Skip to content

Commit

Permalink
Fix Bug 2233158 - Make key wrapping algorithm configurable between AE…
Browse files Browse the repository at this point in the history
…S-KWP and AES-CBC [RHCS 9.7.z]. (dogtagpki#4617)

This fix allows the TPS adminsitrator to configure the aesKeyWrap alg when the KRA wraps a private key to be injected onto the smart card.
    This operation is done in server side keygen and key recovery scenarios. As of the latest code, only the AES_KWP wrap alg is supported.
    Users requested the ability to choose either KWP or AES_CBC_PAD. The caveat here is that CBC_PAD is not assured compatibility between the token and cer

    The choice is very simply configured in the TPS's CS.cfg and can be configured separately for various token profiles. Also the default is KWP if the fo

    ex: op.enroll.userKey.keyGen.aesKeyWrapAlg=CBC

    The two choices here are "KWP" or "CBC".

    Another example for recovery when the original token is marked as temporarilly lost:

    op.enroll.userKeyTemporary.keyGen.aesKeyWrapAlg=CBC

    Once this is set, subsequent calls from the TPS to the KRA for server side keygen will send this choice to the KRA.
    From there the KRA will wrap the private key blob using the required alg and send it back to TPS.

    From there the TPS will send the blob down to the coolkey applet to be unwrapped. A different byte code for KWP (0x88) or CBC (0x89) will be sent to a

    There will be a subsequent addition to this PR to include the new applet which is still being finalized.

    Once the user gets the new rpm's there will be a new applet to choose within the TPS config for ex:

    op.format.userKey.update.applet.requiredVersion.prot.3=1.5.651f3902
    op.enroll.userKey.update.applet.requiredVersion.prot.3=1.5.651f3902

    The applet number here is just an example it will be different when the final applet is approved and checked in.
  • Loading branch information
jmagne authored Nov 20, 2023
1 parent 1512d3f commit 838d690
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ public interface IRequest extends Serializable {
public final static String NETKEY_ATTR_USERID = "USERID";
public final static String NETKEY_ATTR_DRMTRANS_DES_KEY = "drm_trans_desKey";
public static final String NETKEY_ATTR_DRMTRANS_AES_KEY = "drm_trans_aesKey";
public static final String NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG = "drm_aes_wrapAlg";

public final static String NETKEY_ATTR_ARCHIVE_FLAG = "archive";
public final static String NETKEY_ATTR_SERVERSIDE_MUSCLE_FLAG = "serverSideMuscle";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ private void processServerSideKeyGen(HttpServletRequest req,
String rKeysize = req.getParameter(IRemoteRequest.KRA_KEYGEN_KeySize);
String rKeytype = req.getParameter(IRemoteRequest.KRA_KEYGEN_KeyType);
String rKeycurve = req.getParameter(IRemoteRequest.KRA_KEYGEN_EC_KeyCurve);

//Optional AES key wrap alg, default KWP anyway.
String rAesWrapAlg = req.getParameter(IRemoteRequest.KRA_Aes_Wrap_Alg);
logger.debug("GenerateKeyPairServlet: processServerSideKeygen(): rAesWrapAlg: " + rAesWrapAlg);

//Get trans wrapped aes session key if provided.
String raesKeyString = req.getParameter(IRemoteRequest.KRA_Trans_AesKey);
if ((rCUID == null) || (rCUID.equals(""))) {
Expand Down Expand Up @@ -228,6 +233,10 @@ private void processServerSideKeyGen(HttpServletRequest req,
thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_TYPE, rKeytype);
thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_EC_CURVE, rKeycurve);

if((rAesWrapAlg != null) && (rAesWrapAlg.length() >0)) {
thisreq.setExtData(IRequest.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG,rAesWrapAlg);
}

queue.processRequest(thisreq);
Integer result = thisreq.getExtDataInInteger(IRequest.RESULT);
if (result != null) {
Expand Down
38 changes: 33 additions & 5 deletions base/kra/src/main/java/com/netscape/kra/NetkeyKeygenService.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,16 @@ public boolean serviceRequest(IRequest request)
String method = "NetkeyKeygenService: serviceRequest: ";

byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength();

logger.debug(method + " cbc iv len: " + ivLength);

byte iv_cbc[] = new byte[ivLength];
String iv_s = "";

IVParameterSpec algParam = null;
IVParameterSpec desAlgParam = new IVParameterSpec(iv);
IVParameterSpec aesCBCAlgParam = new IVParameterSpec(iv_cbc);

EngineConfig configStore = engine.getConfig();
boolean allowEncDecrypt_archival = configStore.getBoolean("kra.allowEncDecrypt.archival", false);
Expand Down Expand Up @@ -227,6 +233,15 @@ public boolean serviceRequest(IRequest request)

String rWrappedDesKeyString = request.getExtDataInString(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY);
String rWrappedAesKeyString = request.getExtDataInString(IRequest.NETKEY_ATTR_DRMTRANS_AES_KEY);
String aesKeyWrapAlg = request.getExtDataInString(IRequest.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG);

logger.debug(method + " IRequest.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG: " + IRequest.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG);

if(aesKeyWrapAlg != null) {
logger.debug(method + " aesKeyWrapAlg: " + aesKeyWrapAlg);
} else {
logger.debug(method + " no aesKeyWrapAlg provided.");
}

boolean useAesTransWrapped = false;

Expand Down Expand Up @@ -403,10 +418,23 @@ public boolean serviceRequest(IRequest request)

KeyWrapAlgorithm symWrapAlg = KeyWrapAlgorithm.DES3_CBC_PAD;
if(useAesTransWrapped == true) {
//Here we must use AES KWP because it's the only common AES key wrap to be supoprted on hsm, nss, and soon the coolkey applet.
//Should make this configurable at some point.
symWrapAlg = KeyWrapAlgorithm.AES_KEY_WRAP_PAD_KWP;
algParam = null;
//Here we recomment to use AES KWP because it's the only common AES key wrap to be supoprted on hsm, nss, and soon the coolkey applet.
//But now we are going to make it configurable to AES CBC based on interest in doing so. KWP is the one that is assured to work
//with the applet and nss / hsm envorinments. CBC can be chosen at the admin's discretion.

if(aesKeyWrapAlg != null && "CBC".equalsIgnoreCase(aesKeyWrapAlg)) {
// We want CBC
logger.debug(method + " TPS has selected CBC for AES key wrap method.");
symWrapAlg = KeyWrapAlgorithm.AES_CBC_PAD;

algParam = aesCBCAlgParam;
iv_s = org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(iv_cbc);

} else {
symWrapAlg = KeyWrapAlgorithm.AES_KEY_WRAP_PAD_KWP;
algParam = null;
iv_s = org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(iv);
}
logger.debug(method + " attemptedAesKeyWrap = true ");
} else {
algParam = desAlgParam;
Expand Down Expand Up @@ -459,7 +487,7 @@ public boolean serviceRequest(IRequest request)
PubKey));
}

iv_s = org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(iv);
//iv_s = org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(iv);

request.setExtData("iv_s", iv_s);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ public synchronized boolean serviceRequest(IRequest request) throws EBaseExcepti
byte[] wrapped_des_key;

byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };

int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength();
logger.debug(method + " cbc iv len: " + ivLength);

byte iv_cbc[] = new byte[ivLength];

try {
SecureRandom random = jssSubsystem.getRandomNumberGenerator();
random.nextBytes(iv);
Expand Down Expand Up @@ -249,6 +255,14 @@ public synchronized boolean serviceRequest(IRequest request) throws EBaseExcepti
String rWrappedDesKeyString = request.getExtDataInString(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY);

String rWrappedAesKeyString = request.getExtDataInString(IRequest.NETKEY_ATTR_DRMTRANS_AES_KEY);
String aesKeyWrapAlg = request.getExtDataInString(IRequest.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG);

if(aesKeyWrapAlg != null) {
logger.debug(method + " aesKeyWrapAlg: " + aesKeyWrapAlg);
} else {
logger.debug(method + " no aesKeyWrapAlg provided.");
}

// the request record field delayLDAPCommit == "true" will cause
// updateRequest() to delay actual write to ldap
request.setExtData("delayLDAPCommit", "true");
Expand Down Expand Up @@ -406,7 +420,9 @@ public synchronized boolean serviceRequest(IRequest request) throws EBaseExcepti
CryptoManager.getInstance().getInternalKeyStorageToken();
*/
logger.debug("TokenKeyRecoveryService: got token slot:" + token.getName());
IVParameterSpec algParam = new IVParameterSpec(iv);
IVParameterSpec desAlgParam = new IVParameterSpec(iv);
IVParameterSpec algParam = null;
IVParameterSpec aesCBCAlgParam = new IVParameterSpec(iv_cbc);

KeyRecord keyRecord = null;
logger.debug("KRA reading key record");
Expand Down Expand Up @@ -585,17 +601,31 @@ public synchronized boolean serviceRequest(IRequest request) throws EBaseExcepti
logger.debug("TokenKeyRecoveryService: about to wrap...");

KeyWrapAlgorithm symWrapAlg = KeyWrapAlgorithm.DES3_CBC_PAD;
if(attemptAesKeyWrap == true) {
//Here we must use AES KWP because it's the only common AES key wrap to be supoprted on hsm, nss, and soon the coolkey applet.
//Should make this configurable at some point.
symWrapAlg = KeyWrapAlgorithm.AES_KEY_WRAP_PAD_KWP;
algParam = null;
logger.debug(method + " attemptedAesKeyWrap = true ");

if(useAesTransWrapped == true) {
//Here we recomment to use AES KWP because it's the only common AES key wrap to be supoprted on hsm, nss, and soon the coolkey applet.
//But now we are going to make it configurable to AES CBC based on interest in doing so. KWP is the one that is assured to work
//with the applet and nss / hsm envorinments. CBC can be chosen at the admin's discretion.

if(aesKeyWrapAlg != null && "CBC".equalsIgnoreCase(aesKeyWrapAlg)) {
// We want CBC
logger.debug(method + " TPS has selected CBC for AES key wrap method.");
symWrapAlg = KeyWrapAlgorithm.AES_CBC_PAD;

algParam = aesCBCAlgParam;
iv_s = org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(iv_cbc);

} else {
symWrapAlg = KeyWrapAlgorithm.AES_KEY_WRAP_PAD_KWP;
algParam = null;
iv_s = org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(iv);
}
logger.debug(method + " attemptedAesKeyWrap = true ");
} else {
symWrapAlg = KeyWrapAlgorithm.DES3_CBC_PAD;
algParam = desAlgParam;
logger.debug(method + " attemptedAesKeyWrap = false ");
}

wrapped = CryptoUtil.wrapUsingSymmetricKey(
token,
sk,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public interface IRemoteRequest {
public static final String TKS_RESPONSE_KEK_AesKey = "kek_wrapped_aesKey";
public static final String TKS_RESPONSE_DRM_Trans_DesKey = "drm_trans_desKey";
public static final String TKS_RESPONSE_DRM_Trans_AesKey = "drm_trans_aesKey";
public static final String KRA_Aes_Wrap_Alg = "drm_aes_wrapAlg";
public static final String TKS_RESPONSE_KeyCheck = "keycheck";
public static final String TKS_RESPONSE_HostCryptogram = "hostCryptogram";

Expand Down
Binary file added base/tps/shared/applets/1.5.651f3902.ijc
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,22 @@ public KRAServerSideKeyGenResponse serverSideKeyGen(
String userid,
String sDesKey,
String sAesKey,
boolean archive)
boolean archive,
String aesKeyWrapAlg)
throws EBaseException {

logger.debug("KRARemoteRequestHandler: serverSideKeyGen(): begins.");
if (cuid == null || userid == null || sDesKey == null) {
throw new EBaseException("KRARemoteRequestHandler: serverSideKeyGen(): input parameter null.");
}

String aesWrapAlg = aesKeyWrapAlg;

//Just check for unsupported values that are not CBC or KWP and give default.
if(aesWrapAlg == null || aesWrapAlg.length() != 3) {
aesWrapAlg = "KWP";
}

org.dogtagpki.server.tps.TPSEngine engine = org.dogtagpki.server.tps.TPSEngine.getInstance();
TPSSubsystem subsystem = (TPSSubsystem) engine.getSubsystem(TPSSubsystem.ID);
HttpConnector conn =
Expand Down Expand Up @@ -110,7 +118,9 @@ public KRAServerSideKeyGenResponse serverSideKeyGen(
"&" + IRemoteRequest.KRA_Trans_DesKey + "=" +
sDesKey +
"&" + IRemoteRequest.KRA_Trans_AesKey + "=" +
sAesKey;
sAesKey +
"&" + IRemoteRequest.KRA_Aes_Wrap_Alg + "=" +
aesWrapAlg;

//logger.debug("KRARemoteRequestHandler: outgoing request for ECC: " + request);

Expand All @@ -132,7 +142,9 @@ public KRAServerSideKeyGenResponse serverSideKeyGen(
"&" + IRemoteRequest.KRA_Trans_DesKey + "=" +
sDesKey +
"&" + IRemoteRequest.KRA_Trans_AesKey + "=" +
sAesKey;
sAesKey +
"&" + IRemoteRequest.KRA_Aes_Wrap_Alg + "=" +
aesWrapAlg;

logger.debug("KRARemoteRequestHandler: outgoing request for RSA: " + request);

Expand Down Expand Up @@ -238,9 +250,10 @@ public KRARecoverKeyResponse recoverKey(
String userid,
String sDesKey,
String sAesKey,
String b64cert)
String b64cert,
String aesKeyWrapAlg)
throws EBaseException {
return recoverKey(cuid, userid, sDesKey, sAesKey, b64cert, BigInteger.valueOf(0));
return recoverKey(cuid, userid, sDesKey, sAesKey, b64cert, BigInteger.valueOf(0),aesKeyWrapAlg);
}

public KRARecoverKeyResponse recoverKey(
Expand All @@ -249,7 +262,8 @@ public KRARecoverKeyResponse recoverKey(
String sDesKey,
String sAesKey,
String b64cert,
BigInteger keyid)
BigInteger keyid,
String aesKeyWrapAlg)
throws EBaseException {

logger.debug("KRARemoteRequestHandler: recoverKey(): begins. " );
Expand All @@ -261,6 +275,13 @@ public KRARecoverKeyResponse recoverKey(
throw new EBaseException("KRARemoteRequestHandler: recoverKey(): input parameter null.");
}

String aesWrapAlg = aesKeyWrapAlg;

//Just check for unsupported values that are not CBC or KWP and give default.
if(aesWrapAlg == null || aesWrapAlg.length() != 3) {
aesWrapAlg = "KWP";
}

org.dogtagpki.server.tps.TPSEngine engine = org.dogtagpki.server.tps.TPSEngine.getInstance();
TPSSubsystem subsystem = (TPSSubsystem) engine.getSubsystem(TPSSubsystem.ID);
logger.debug("KRARemoteRequestHandler: getting conn id: " + connid);
Expand Down Expand Up @@ -291,7 +312,9 @@ public KRARecoverKeyResponse recoverKey(
"&" + IRemoteRequest.KRA_UserId + "=" +
userid +
"&" + IRemoteRequest.KRA_RECOVERY_CERT + "=" +
b64cert + desPart + aesPart;
b64cert + desPart + aesPart +
"&" + IRemoteRequest.KRA_Aes_Wrap_Alg + "=" +
aesWrapAlg;

} else if (keyid != BigInteger.valueOf(0)) { // recover by keyid ... keyid != BigInteger.valueOf(0)
logger.debug("KRARemoteRequestHandler: recoverKey(): keyid = " + keyid);
Expand All @@ -300,7 +323,9 @@ public KRARecoverKeyResponse recoverKey(
"&" + IRemoteRequest.KRA_UserId + "=" +
userid +
"&" + IRemoteRequest.KRA_RECOVERY_KEYID + "=" +
keyid.toString() + desPart + aesPart;
keyid.toString() + desPart + aesPart +
"&" + IRemoteRequest.KRA_Aes_Wrap_Alg + "=" +
aesWrapAlg;

}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ public enum ENROLL_MODES {
public static final String ENROLL_MODE_RECOVERY = RECOVERY_OP;
public static final String ERNOLL_MODE_RENEWAL = RENEWAL_OP;
public static final String CFG_ALLOW_MULTI_TOKENS_USER = "allowMultiActiveTokensUser";
public static final String CFG_AES_KEY_WRAP_ALG = "aesKeyWrapAlg";

public void init() {
//ToDo
Expand Down Expand Up @@ -526,17 +527,17 @@ public static RA_Algs intToRAAlgs(int alg) {
public KRARecoverKeyResponse recoverKey(String cuid,
String userid,
TPSBuffer drmWrappedDesKey, TPSBuffer drmWrappedAesKey,
String b64cert, String drmConnId) throws TPSException {
String b64cert, String drmConnId, String aesKeyWrapAlg) throws TPSException {

return this.recoverKey(cuid, userid, drmWrappedDesKey, drmWrappedAesKey,
b64cert, drmConnId, BigInteger.valueOf(0));
b64cert, drmConnId, BigInteger.valueOf(0), aesKeyWrapAlg);

}

public KRARecoverKeyResponse recoverKey(String cuid,
String userid,
TPSBuffer drmWrappedDesKey,TPSBuffer drmWrappedAesKey,
String b64cert, String drmConnId,BigInteger keyid) throws TPSException {
String b64cert, String drmConnId,BigInteger keyid, String aesKeyWrapAlg) throws TPSException {
String method = "TPSEngine.recoverKey";
logger.debug("TPSEngine.recoverKey");
if (cuid == null)
Expand Down Expand Up @@ -573,7 +574,7 @@ else if (drmConnId == null)

resp = kra.recoverKey(cuid, userid, encodedDes,
encodedAes,
(b64cert != null) ? Util.uriEncode(b64cert) : b64cert,keyid);
(b64cert != null) ? Util.uriEncode(b64cert) : b64cert,keyid,aesKeyWrapAlg);
} catch (EBaseException e) {
throw new TPSException("TPSEngine.recoverKey: Problem creating or using KRARemoteRequestHandler! "
+ e.toString(), TPSStatus.STATUS_ERROR_RECOVERY_FAILED);
Expand Down Expand Up @@ -613,7 +614,7 @@ else if (drmConnId == null)
public KRAServerSideKeyGenResponse serverSideKeyGen(int keySize, String cuid, String userid, String drmConnId,
TPSBuffer wrappedDesKey, TPSBuffer drmWrappedAesKey,
boolean archive,
boolean isECC) throws TPSException {
boolean isECC, String aesKeyWrapAlg) throws TPSException {

/*
logger.debug("TPSEngine.serverSideKeyGen entering... keySize: " + keySize + " cuid: " + cuid + " userid: "
Expand All @@ -635,7 +636,7 @@ public KRAServerSideKeyGenResponse serverSideKeyGen(int keySize, String cuid, St
resp = kra.serverSideKeyGen(isECC, keySize, cuid, userid,
(wrappedDesKey != null) ? Util.specialURLEncode(wrappedDesKey) : "",
(drmWrappedAesKey != null) ? Util.specialURLEncode(drmWrappedAesKey) : "",
archive);
archive,aesKeyWrapAlg);

} catch (EBaseException e) {
throw new TPSException("TPSEngine.serverSideKeyGen: Problem creating or using KRARemoteRequestHandler! "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class CertEnrollInfo {
private String publisherId;
private String keyType;
private String keyTypePrefix;
private String aesKeyWrapAlg;

private CARetrieveCertResponse recoveredCertData;
private KRARecoverKeyResponse recoveredKeyData;
Expand Down Expand Up @@ -199,6 +200,14 @@ public int getPublicKeyNumber() {
return publicKeyNumber;
}

public void setAesKeyWrapAlg(String alg) {
aesKeyWrapAlg = alg;
}

public String getAesKeyWrapAlg() {
return aesKeyWrapAlg;
}

public void setKeyType(String keyType) {
this.keyType = keyType;
}
Expand Down
Loading

0 comments on commit 838d690

Please sign in to comment.