Skip to content

Commit

Permalink
Fix Bug 2253677 - Make key wrapping algorithm configurable between AE…
Browse files Browse the repository at this point in the history
…S-KWP and AES-CBC [RHCS 10.6

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.

Revise Bug: Bug 2253677 - Make key wrapping algorithm configurable between AES-KWP and AES-CBC [RHCS 10.6].

 We found an issue with scp01 recovery with said fix. This patch addresses this such that both scp01 and scp03 recovery should now work.
  • Loading branch information
Jack Magne authored and jmagne committed Dec 18, 2023
1 parent 1fa4721 commit 28d46fb
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ private void processServerSideKeyGen(HttpServletRequest req,
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);

Expand Down Expand Up @@ -227,6 +231,10 @@ private void processServerSideKeyGen(HttpServletRequest req,
thisreq.setExtData(Request.NETKEY_ATTR_KEY_SIZE, rKeysize);
thisreq.setExtData(Request.NETKEY_ATTR_KEY_TYPE, rKeytype);
thisreq.setExtData(Request.NETKEY_ATTR_KEY_EC_CURVE, rKeycurve);

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

queue.processRequest(thisreq);
Integer result = thisreq.getExtDataInInteger(Request.RESULT);
Expand Down
40 changes: 35 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 @@ -174,6 +174,11 @@ public boolean serviceRequest(Request 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 = "";
try {
SecureRandom random = jssSubsystem.getRandomNumberGenerator();
Expand All @@ -185,6 +190,7 @@ public boolean serviceRequest(Request request)

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

KRAEngineConfig configStore = engine.getConfig();
boolean allowEncDecrypt_archival = configStore.getBoolean("kra.allowEncDecrypt.archival", false);
Expand Down Expand Up @@ -228,6 +234,16 @@ public boolean serviceRequest(Request request)
String rWrappedDesKeyString = request.getExtDataInString(Request.NETKEY_ATTR_DRMTRANS_DES_KEY);
String rWrappedAesKeyString = request.getExtDataInString(Request.NETKEY_ATTR_DRMTRANS_AES_KEY);

String aesKeyWrapAlg = request.getExtDataInString(Request.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG);

logger.debug(method + " Request.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG: " + Request.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;

if(rWrappedAesKeyString != null && rWrappedAesKeyString.length() > 0) {
Expand Down Expand Up @@ -408,13 +424,27 @@ public boolean serviceRequest(Request 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;
iv_s = org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(iv);
logger.debug(method + " attemptedAesKeyWrap = false ");
}

Expand Down Expand Up @@ -467,7 +497,7 @@ public boolean serviceRequest(Request request)
null,
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);

} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ public synchronized boolean serviceRequest(Request request) throws EBaseExceptio
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 @@ -243,6 +249,13 @@ public synchronized boolean serviceRequest(Request request) throws EBaseExceptio
String rUserid = request.getExtDataInString(Request.NETKEY_ATTR_USERID);
String rWrappedDesKeyString = request.getExtDataInString(Request.NETKEY_ATTR_DRMTRANS_DES_KEY);
String rWrappedAesKeyString = request.getExtDataInString(Request.NETKEY_ATTR_DRMTRANS_AES_KEY);
String aesKeyWrapAlg = request.getExtDataInString(Request.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
Expand Down Expand Up @@ -292,10 +305,12 @@ public synchronized boolean serviceRequest(Request request) throws EBaseExceptio
(wrapped_des_key.length > 0)) {

try {
logger.debug("TokenKeyRecoveryService: received DRM-trans-wrapped des key: length: " + wrapped_des_key.length);

sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_des_key, wrapParams);
logger.debug("TokenKeyRecoveryService: received des key");
} catch (Exception e) {
logger.debug("TokenKeyRecoveryService: no des key");
logger.debug("TokenKeyRecoveryService: no des key: " + e);
if(!useAesTransWrapped) {
request.setExtData(Request.RESULT, Integer.valueOf(4));
return false;
Expand Down Expand Up @@ -399,7 +414,9 @@ public synchronized boolean serviceRequest(Request request) throws EBaseExceptio
*/
token = mStorageUnit.getToken();
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 @@ -576,14 +593,27 @@ public synchronized boolean serviceRequest(Request request) throws EBaseExceptio
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 ");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ public class Request {
public static final String NETKEY_ATTR_DRMTRANS_DES_KEY = "drm_trans_desKey";
public static final String NETKEY_ATTR_ARCHIVE_FLAG = "archive";
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 static final String NETKEY_ATTR_SERVERSIDE_MUSCLE_FLAG = "serverSideMuscle";
public static final String NETKEY_ATTR_ENC_PRIVKEY_FLAG = "encryptPrivKey";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public interface IRemoteRequest {

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
13 changes: 7 additions & 6 deletions base/tps/src/main/java/org/dogtagpki/server/tps/TPSEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,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 TPSEngine() {
super("TPS");
Expand Down Expand Up @@ -534,17 +535,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 @@ -581,7 +582,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 @@ -621,7 +622,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 @@ -645,7 +646,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 @@ -68,14 +68,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";
}

TPSEngine engine = TPSEngine.getInstance();
TPSSubsystem subsystem = (TPSSubsystem) engine.getSubsystem(TPSSubsystem.ID);
HttpConnector conn =
Expand Down Expand Up @@ -111,7 +119,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 @@ -133,7 +143,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 @@ -260,6 +274,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";
}

TPSEngine engine = TPSEngine.getInstance();
TPSSubsystem subsystem = (TPSSubsystem) engine.getSubsystem(TPSSubsystem.ID);
logger.debug("KRARemoteRequestHandler: getting conn id: " + connid);
Expand All @@ -273,8 +294,8 @@ public KRARecoverKeyResponse recoverKey(

String sendMsg = null;
try {
String desPart = " ";
String aesPart = " ";
String desPart = "";
String aesPart = "";

if(sDesKey != null) {
desPart = "&" + IRemoteRequest.KRA_Trans_DesKey + "=" + sDesKey;
Expand All @@ -289,17 +310,21 @@ 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);
sendMsg = IRemoteRequest.TOKEN_CUID + "=" +
cuid +
"&" + IRemoteRequest.KRA_UserId + "=" +
userid +
"&" + IRemoteRequest.KRA_RECOVERY_KEYID + "=" +
keyid.toString() + desPart + aesPart;
keyid.toString() + desPart + aesPart +
"&" + IRemoteRequest.KRA_Aes_Wrap_Alg + "=" +
aesWrapAlg;
}
//logger.debug("KRARemoteRequestHandler: recoverKey(): outgoing: " + sendMsg);
} catch (Exception e) {
logger.debug("KRARemoteRequestHandler: recoverKey(): uriEncode failed: " + e);
throw new EBaseException("KRARemoteRequestHandler: recoverKey(): uriEncode failed: " + e);
Expand Down
Loading

0 comments on commit 28d46fb

Please sign in to comment.