Skip to content

Commit

Permalink
Fix: Bug 2123071 - add AES support for TMS server-side keygen on late…
Browse files Browse the repository at this point in the history
…st HSM / FIPS environment [RHCS 10.4].

This fix allows the latest HSM / FIPS environment to successfully complete a token enrollment including server side
keygen functionality.

This is accomplished with TMS code and applet code that allows SCP03 tokens alone the ability to inject a private key onto the token
using the AEK_KEYWRAP_KWP algorithm. This fix includes a new applet that must be used for scp03 tokens.

base/tps/shared/applets/1.5.64260792.ijc

The CS.cfg must be configured to use this applet as follows:

op.enroll.userKey.update.applet.requiredVersion.prot.3=1.5.64260792  for enrollment and,
op.format.userKey.update.applet.requiredVersion.prot.3=1.5.64260792 for format.

Note any other profiles including external registration must be configured to use this applet if put into play.

Note: The following must be configured in the TPS's server.xml to extend the timeout from the client
as per this example:

connectionTimeout="-1" for each connector SSL or non SSL. This is required since the KWP implementation
takes a bit longer to unwrap the keys(s) onto the token than previously.

Tested with a full FIPS / latest HSM box using PSS and OAEP for all subsystems. OAEP should be required
with PSS optional.

Tested with the g&d 7.0 smart cafe SCP03 using a max of 3072 bit keys due to the limitations of the token itself.

Addressed review comments.

Addressed final review comment.
  • Loading branch information
jmagne committed Jul 12, 2023
1 parent 022687f commit 79fca19
Show file tree
Hide file tree
Showing 23 changed files with 803 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ public interface IRequest extends Serializable {
public final static String NETKEY_ATTR_CUID = "CUID";
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 final static String NETKEY_ATTR_ARCHIVE_FLAG = "archive";
public final static String NETKEY_ATTR_SERVERSIDE_MUSCLE_FLAG = "serverSideMuscle";
public final static String NETKEY_ATTR_ENC_PRIVKEY_FLAG = "encryptPrivKey";
Expand Down
22 changes: 22 additions & 0 deletions base/common/src/main/java/org/dogtagpki/tps/main/TPSBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,28 @@ public String toHexStringPlain() {
return result.toString();
}

/*
* Convenience routine to put apdu's in format to import into java cmd line programs if so desired
*/
public String toHexStringJavaByteArray() {
final String HEX_DIGITS = "0123456789ABCDEF";

StringBuffer result = new StringBuffer(buf.length * 2);
result.append("{ ");
for (int i = 0; i < buf.length; i++)
{
char c = (char) buf[i];
result.append("(byte) 0x");
result.append(HEX_DIGITS.charAt((c & 0xF0) >> 4));
result.append(HEX_DIGITS.charAt(c & 0x0F));
if(i < buf.length - 1)
result.append(",");
}
result.append("}");
return result.toString();
}


public int getIntFrom1Byte(int offset) {

if (offset < 0 || offset >= (this.size())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,12 +528,6 @@ public static TPSMessage createMessage(String message) throws IOException {
}
}

int debug = 1;

if (debug == 1) {
logger.debug("TPSMessage.createMessage: message: " + message);
}

TPSMessage new_msg = new TPSMessage(message);

return new_msg.createMessage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ 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);

//Get trans wrapped aes session key if provided.
String raesKeyString = req.getParameter(IRemoteRequest.KRA_Trans_AesKey);
if ((rCUID == null) || (rCUID.equals(""))) {
logger.warn("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: CUID");
missingParam = true;
Expand Down Expand Up @@ -185,12 +186,23 @@ private void processServerSideKeyGen(HttpServletRequest req,
}
}

boolean wrappedAesPresent = true;
boolean wrappedDesPresent = true;
if ((rdesKeyString == null) ||
(rdesKeyString.equals(""))) {
logger.warn("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: DRM-transportKey-wrapped DES key");
missingParam = true;
logger.warn("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: DRM-transportKey-wrapped DES key, possibly AES key sent instead.");
wrappedDesPresent = false;
}

if((raesKeyString == null) || (raesKeyString.equals(""))) {
wrappedAesPresent = false;
logger.warn("GenerateKeyPairServlet: processServerSideKeygen(): missing DRM-wrapped AES Key, possibly DES key sent instead.");
}

if(wrappedAesPresent == false && wrappedDesPresent == false) {
missingParam = true;
}

if ((rArchive == null) || (rArchive.equals(""))) {
logger.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing key archival flag 'archive' ,default to true");
rArchive = "true";
Expand All @@ -202,7 +214,15 @@ private void processServerSideKeyGen(HttpServletRequest req,
thisreq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_NETKEY_RA);
thisreq.setExtData(IRequest.NETKEY_ATTR_CUID, rCUID);
thisreq.setExtData(IRequest.NETKEY_ATTR_USERID, rUserid);
thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString);

if(wrappedDesPresent == true) {
thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString);
}

if(wrappedAesPresent == true) {
thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_AES_KEY, raesKeyString);
}

thisreq.setExtData(IRequest.NETKEY_ATTR_ARCHIVE_FLAG, rArchive);
thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_SIZE, rKeysize);
thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_TYPE, rKeytype);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ private void processTokenKeyRecovery(HttpServletRequest req,

// IConfigStore sconfig = CMS.getConfigStore();
boolean missingParam = false;
boolean missingTransAes = false;
boolean missingTransDes = false;
String status = "0";

logger.debug("processTokenKeyRecovery begins:");
Expand All @@ -168,6 +170,8 @@ private void processTokenKeyRecovery(HttpServletRequest req,
String rdesKeyString = req.getParameter(IRemoteRequest.KRA_Trans_DesKey);
String rCert = req.getParameter(IRemoteRequest.KRA_RECOVERY_CERT);

String raesKeyString = req.getParameter(IRemoteRequest.KRA_Trans_AesKey);

if ((rCUID == null) || (rCUID.equals(""))) {
logger.warn("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: CUID");
missingParam = true;
Expand All @@ -178,9 +182,17 @@ private void processTokenKeyRecovery(HttpServletRequest req,
missingParam = true;
}

if ((raesKeyString == null) || (raesKeyString.equals(""))) {
logger.warn("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: DRM-transportKey-wrapped aes key");
missingTransAes = true;
}
if ((rdesKeyString == null) ||
(rdesKeyString.equals(""))) {
logger.warn("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: DRM-transportKey-wrapped des key");
missingTransDes = true;
}
//We expect either a trans wrapped aes or des key.
if(missingTransAes == true && missingTransDes == true) {
missingParam = true;
}

Expand All @@ -196,7 +208,14 @@ private void processTokenKeyRecovery(HttpServletRequest req,
thisreq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_NETKEY_RA);
thisreq.setExtData(IRequest.NETKEY_ATTR_CUID, rCUID);
thisreq.setExtData(IRequest.NETKEY_ATTR_USERID, rUserid);
thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString);

if(!missingTransDes) {
thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString);
}
if(!missingTransAes) {
thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_AES_KEY, raesKeyString);
}

if ((rCert != null) && (!rCert.equals(""))) {
thisreq.setExtData(IRequest.NETKEY_ATTR_USER_CERT, rCert);
logger.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): received request parameter: cert");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.dogtagpki.server.kra.KRAEngine;
import org.dogtagpki.server.kra.KRAEngineConfig;
import org.mozilla.jss.NoSuchTokenException;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.KeyPairAlgorithm;
import org.mozilla.jss.crypto.KeyPairGenerator;
Expand Down Expand Up @@ -1823,14 +1824,15 @@ public KeyPair generateKeyPair(
InvalidParameterException, PQGParamGenException {
return generateKeyPair(kpAlg, keySize, keyCurve, pqg, usageList, true);
}

public KeyPair generateKeyPair(
KeyPairAlgorithm kpAlg, int keySize, String keyCurve, PQGParams pqg,
KeyPairGeneratorSpi.Usage[] usageList, boolean temp)
throws NoSuchAlgorithmException, TokenException, InvalidAlgorithmParameterException,
InvalidParameterException, PQGParamGenException {

KRAEngine engine = KRAEngine.getInstance();
CryptoToken token = getKeygenToken();
CryptoToken token = getKeygenToken();

logger.debug("NetkeyKeygenService: key pair is to be generated on slot: " + token.getName());

Expand Down
Loading

0 comments on commit 79fca19

Please sign in to comment.