diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CVE-2023-4727.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CVE-2023-4727.patch new file mode 100644 index 0000000..8384d93 --- /dev/null +++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CVE-2023-4727.patch @@ -0,0 +1,65 @@ +From 2d152f06a3f3c395015622bce084c887190e07b2 Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Tue, 16 Apr 2024 14:22:18 -0400 +Subject: [PATCH] Subject: [PATCH] CVE-2023-4727 Fix token authentication + bypass vulnerability + +Previously the LDAPSecurityDomainSessionTable.sessionExists() +and getStringValue() were using user-provided session ID as +is in an LDAP filter which could be exploited to bypass token +authentication. + +To fix the problem the code has been modified to escape all +special characters in the session ID before using it in the +LDAP filter. + +Resolves: CVE-2023-4727 +--- + .../session/LDAPSecurityDomainSessionTable.java | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) +--- + .../cmscore/session/LDAPSecurityDomainSessionTable.java | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/base/server/cmscore/src/com/netscape/cmscore/session/LDAPSecurityDomainSessionTable.java b/base/server/cmscore/src/com/netscape/cmscore/session/LDAPSecurityDomainSessionTable.java +index 5fd58d9..a742187 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/session/LDAPSecurityDomainSessionTable.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/session/LDAPSecurityDomainSessionTable.java +@@ -28,6 +28,8 @@ import com.netscape.certsrv.base.ISecurityDomainSessionTable; + import com.netscape.certsrv.base.PKIException; + import com.netscape.certsrv.ldap.ELdapException; + import com.netscape.certsrv.ldap.ILdapConnFactory; ++import com.netscape.cmsutil.ldap.LDAPUtil; ++ + + import netscape.ldap.LDAPAttribute; + import netscape.ldap.LDAPAttributeSet; +@@ -154,7 +156,11 @@ public class LDAPSecurityDomainSessionTable + try { + String basedn = cs.getString("internaldb.basedn"); + String sessionsdn = "ou=sessions,ou=Security Domain," + basedn; +- String filter = "(cn=" + sessionId + ")"; ++ ++ // CVE-2023-4727 ++ // escape session ID in LDAP search filter ++ String filter = "(cn=" + LDAPUtil.escapeFilter(sessionId) + ")"; ++ + String[] attrs = { "cn" }; + + conn = mLdapConnFactory.getConn(); +@@ -229,7 +235,11 @@ public class LDAPSecurityDomainSessionTable + try { + String basedn = cs.getString("internaldb.basedn"); + String sessionsdn = "ou=sessions,ou=Security Domain," + basedn; +- String filter = "(cn=" + sessionId + ")"; ++ ++ // CVE-2023-4727 ++ // escape session ID in LDAP search filter ++ String filter = "(cn=" + LDAPUtil.escapeFilter(sessionId) + ")"; ++ + String[] attrs = { attr }; + + conn = mLdapConnFactory.getConn(); +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.1.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.1.patch new file mode 100644 index 0000000..74ac86f --- /dev/null +++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.1.patch @@ -0,0 +1,173 @@ +From 82fb03158e2f06e4886c7ad254e3b9880fc1ada3 Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Mon, 6 May 2024 18:08:30 -0400 +Subject: [PATCH 1/3] Trivial fix. Remove illegal characters from comments in + TPS CS.cfg file. + +(cherry picked from commit 455fec6347ff4b141936939ac9d4d91afdba0daa) +--- + base/tps/shared/conf/CS.cfg | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/base/tps/shared/conf/CS.cfg b/base/tps/shared/conf/CS.cfg +index 0b4b348..0d2b1ce 100644 +--- a/base/tps/shared/conf/CS.cfg ++++ b/base/tps/shared/conf/CS.cfg +@@ -24,7 +24,7 @@ applet._015=#op.pinReset.userKey.update.applet.requiredVersion.prot.3=1.5.65cbf5 + applet._016=# + applet._017=# The applet above is the latest and supports CBC and KWP key wrapping. + applet._018=# Use existing config for standard protoco1 cards Example: applet._019=#op.format.userKey.update.applet.requiredVersion=1.4.58768072 +-applet._019=# Add “,A000000003000000,A0000001510000” to all instances of *.cardmgr_instance parameters in the CS.cfg file as shown below. Update all format, enroll and pin reset values for every token type in the file. This is to support some newer cards such as the Cosmo Idemia, allowing the code to select the proper AID at run time. ++applet._019=# Add ,A000000003000000,A0000001510000 to all instances of *.cardmgr_instance parameters in the CS.cfg file as shown below. Update all format, enroll and pin reset values for every token type in the file. This is to support some newer cards such as the Cosmo Idemia, allowing the code to select the proper AID at run time. + applet._020=######################################### + applet.aid.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + applet.aid.netkey_file=627601FF0000 +-- +1.8.3.1 + + +From f0101f977d6749f4ecb9069ed331daf9cb98f586 Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Fri, 10 May 2024 15:10:20 -0700 +Subject: [PATCH 2/3] Fix Bug 2253682 - pkidestroy log keeps HSM token password + [RHCS 9.7.z] (#4737) + +This patch addressed the error condiation when pkidestroy fails to delete the tks connector. +Previously the password for the token would be displayed. With this fix, the value is obscured. + +Remove extraneous print statement. +(cherry picked from commit 57cbac9c41a44ecd4d3617b78383a18dd5fdcc63) +--- + base/server/python/pki/server/deployment/pkihelper.py | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py +index 4f4998a..a91e75d 100644 +--- a/base/server/python/pki/server/deployment/pkihelper.py ++++ b/base/server/python/pki/server/deployment/pkihelper.py +@@ -3245,23 +3245,24 @@ class TPSConnector: + "--host", tpshost, + "--port", str(tpsport)] + +- output = subprocess.check_output(command, ++ try: ++ output = subprocess.check_output(command, + stderr=subprocess.STDOUT, + shell=False) +- output = output.decode('utf-8') +- error = re.findall("ClientResponseFailure:(.*?)", output) +- if error: ++ output = output.decode('utf-8') ++ ++ except subprocess.CalledProcessError: + config.pki_log.warning( + log.PKIHELPER_TPSCONNECTOR_UPDATE_FAILURE_2, + str(tpshost), + str(tpsport), + extra=config.PKI_INDENTATION_LEVEL_2) ++ command[12] = "****" + config.pki_log.error( +- log.PKI_SUBPROCESS_ERROR_1, output, ++ log.PKI_SUBPROCESS_ERROR_1, command, + extra=config.PKI_INDENTATION_LEVEL_2) +- if critical_failure: +- raise Exception(log.PKI_SUBPROCESS_ERROR_1 % output) +- ++ if critical_failure: ++ raise Exception(log.PKI_SUBPROCESS_ERROR_1 % output) + + class SecurityDomain: + """PKI Deployment Security Domain Class""" +-- +1.8.3.1 + + +From a53cf5b5e613dfb35262f8b54045e817f30015b3 Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Fri, 17 May 2024 10:10:38 -0700 +Subject: [PATCH 3/3] Fix issue when the AES shared secret can't be imported + automatically during TPS pkispawn operation. (#4747) + +An issue was discovered in the HSM / FIPS case because the code uses the private key of the subsystem cert which can reside on the hsm token. The shared secret right now only supports the internal token. + +Bug 2280722 - Shared token is not generated for TPS and TKS during install despite adding pki_import_shared_secret=True param at install [RHCS 9.7.z]. +Review comments. +(cherry picked from commit ff4b874aa1211989b71b71c5c99e5423511604d0) +--- + .../com/netscape/cmsutil/crypto/CryptoUtil.java | 47 ++++++++++++++++------ + 1 file changed, 35 insertions(+), 12 deletions(-) + +diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +index 29217d1..bb3683f 100644 +--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java ++++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +@@ -3111,20 +3111,34 @@ public class CryptoUtil { + throw new IOException("Shared secret " + sharedSecretNickname + " already exists"); + } + ++ X509Certificate cert = cm.findCertByNickname(subsystemCertNickname); ++ ++ if(cert != null) { ++ logger.debug(method + " subsystemCert: " + cert); ++ } else { ++ logger.debug(method + " can't find subsytem cert."); ++ throw new Exception("Can't find subsystem cert."); ++ } ++ PrivateKey subsystemPrivateKey = cm.findPrivKeyByCert(cert); ++ ++ if(subsystemPrivateKey == null) { ++ throw new InvalidKeyException("Can't find subsytem cert private key"); ++ } ++ ++ CryptoToken subCertToken = subsystemPrivateKey.getOwningToken(); ++ ++ ++ if(subCertToken == null) { ++ throw new TokenException("Invalid owning token for subsystem cert."); ++ } ++ + //Unwrap session key +- +- KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA); ++ KeyWrapper keyWrap = subCertToken.getKeyWrapper(KeyWrapAlgorithm.RSA); + logger.debug(method + " subsytemCertNickname: " + subsystemCertNickname); +- System.out.println(method + " subsytemCertNickname: " + subsystemCertNickname); + +- X509Certificate cert = cm.findCertByNickname(subsystemCertNickname); +- logger.debug(method + " subsystemCert: " + cert); +- PrivateKey subsystemPrivateKey = cm.findPrivKeyByCert(cert); + keyWrap.initUnwrap(subsystemPrivateKey,null); + + SymmetricKey unwrappedSessionKey = null; +- //Since we don't know if aes was used to wrap the key, try with and without. +- + + try { + unwrappedSessionKey = keyWrap.unwrapSymmetric(wrappedSessionKey, SymmetricKey.AES, +@@ -3141,10 +3155,19 @@ public class CryptoUtil { + + IVParameterSpec ivsp = new IVParameterSpec(iv); + +- byte[] unwrappedSharedSecret = decryptUsingSymmetricKey(token, ivsp, wrappedSharedSecret, +- unwrappedSessionKey, encAlg); +- SymmetricKey importedSharedSecret = unwrapAESSKeyFromBytes(token, unwrappedSharedSecret, true); +- importedSharedSecret.setNickName(sharedSecretNickname); ++ byte[] unwrappedSharedSecret = {}; ++ try { ++ unwrappedSharedSecret = decryptUsingSymmetricKey(subCertToken, ivsp, wrappedSharedSecret, ++ unwrappedSessionKey, encAlg); ++ SymmetricKey importedSharedSecret = unwrapAESSKeyFromBytes(token, unwrappedSharedSecret, true); ++ importedSharedSecret.setNickName(sharedSecretNickname); ++ } catch (Exception e) { ++ System.out.println(method + " exception found " + e); ++ throw e; ++ } finally { ++ CryptoUtil.obscureBytes(unwrappedSharedSecret,"random"); ++ } ++ + } + + public static SymmetricKey unwrapAESSKeyFromBytes(CryptoToken token, byte[] inputKeyArray, +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.2.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.2.patch new file mode 100644 index 0000000..a277da6 --- /dev/null +++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.2.patch @@ -0,0 +1,89 @@ +From 066c16616a8c384da4e2a424744aea93e4b4a2d7 Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Thu, 23 May 2024 11:43:15 -0700 +Subject: [PATCH] Fix: Bug 2233158 - Make key wrapping algorithm configurable + between AES-KWP and AES-CBC [RHCS 9.7.z]. (#4753) + +The aes key wrapping alg was not being passed along correctly in TokenKeyRecoveryServlet class. + +Also slightly modify the code that determines the default card manager aid to allow tpsclient, our scp01 virtual tester, to continue to function. The tpsclient only returns 9000 for success instead of the aid in question. +(cherry picked from commit a7f806fbf30aeb4f1c40469b37af1426da2fbf8c) +--- + .../cms/servlet/connector/TokenKeyRecoveryServlet.java | 16 ++++++++++++++++ + .../org/dogtagpki/server/tps/processor/TPSProcessor.java | 11 +++++++++-- + 2 files changed, 25 insertions(+), 2 deletions(-) + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java +index c7a257d..7abe516 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java +@@ -154,6 +154,7 @@ public class TokenKeyRecoveryServlet extends CMSServlet { + boolean missingParam = false; + boolean missingTransAes = false; + boolean missingTransDes = false; ++ boolean missingAesKeyWrapAlg = false; + String status = "0"; + + CMS.debug("processTokenKeyRecovery begins:"); +@@ -163,9 +164,18 @@ public class TokenKeyRecoveryServlet extends CMSServlet { + String rKeyid = req.getParameter(IRemoteRequest.KRA_RECOVERY_KEYID); + String rdesKeyString = req.getParameter(IRemoteRequest.KRA_Trans_DesKey); + String rCert = req.getParameter(IRemoteRequest.KRA_RECOVERY_CERT); ++ //RedHat : make sure the key wrap alg is being processed correctly ++ String aesKeyWrapAlg = req.getParameter(IRemoteRequest.KRA_Aes_Wrap_Alg); + + String raesKeyString = req.getParameter(IRemoteRequest.KRA_Trans_AesKey); + ++ //RedHat : make sure the key wrap alg is being processed correctly ++ if ((aesKeyWrapAlg == null) || (aesKeyWrapAlg.equals(""))) { ++ CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: AES-KeyWrap-alg"); ++ missingAesKeyWrapAlg = true; ++ } ++ ++ + if ((rCUID == null) || (rCUID.equals(""))) { + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: CUID"); + missingParam = true; +@@ -209,6 +219,12 @@ public class TokenKeyRecoveryServlet extends CMSServlet { + thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_AES_KEY, raesKeyString); + } + ++ //RedHat : make sure the key wrap alg is being processed correctly ++ if(!missingAesKeyWrapAlg) { ++ CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): aesKeyWrapAlg: " + aesKeyWrapAlg); ++ thisreq.setExtData(IRequest.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG,aesKeyWrapAlg); ++ } ++ + if ((rCert != null) && (!rCert.equals(""))) { + thisreq.setExtData(IRequest.NETKEY_ATTR_USER_CERT, rCert); + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): received request parameter: cert"); +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +index 48a341d..984ce79 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +@@ -3501,13 +3501,20 @@ public class TPSProcessor { + TPSStatus.STATUS_ERROR_CANNOT_ESTABLISH_COMMUNICATION); + } + } +- ++ + if (defaultAID != null && defaultAID.checkResult()) + { + TPSBuffer aidData = parseAIDResponse(defaultAID.getData()); + + String defAIDStr = aidData.toHexStringPlain(); +- ++ ++ //RedHat : appease tpsclient tester that only returns 90 00 success, using original default AID. ++ if(aidData == null || aidData.size() == 0) { ++ CMS.debug(method + "tpsclient tester probably returned only 90 00, assume old default AID."); ++ defAIDStr = getCardManagerAIDList().get(0); ++ aidData = new TPSBuffer(defAIDStr); ++ } ++ + // Get list of valid AID values from the configuration file + List aidBuf = getCardManagerAIDList(); + +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.3.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.3.patch new file mode 100644 index 0000000..00be2ff --- /dev/null +++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.3.patch @@ -0,0 +1,118 @@ +From dd58b89aebab04c6f3c1516352e8d3496e0e4c45 Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Fri, 31 May 2024 15:31:02 -0700 +Subject: [PATCH] Fix Bug 2265180 - Add Support for Symmetric Key Rollover + [RHCS 9.7.z]. (#4760) + +We found in QE a situation in fips mode with the hsm that the calculation of the scp03 keycheck value +could fail. Simply making that method behave like the scp01 version of the method fixes the issue. + +Also added some trivial code to apease tpsclient. We do so by creating a new secret config value used only +by those testing the product with tpsclient: + +channel.scp01.no.le.byte=true + +This will skip the le zero byte on only the generatekey and readobject apdu's only if scp01 is detected and this value is true. +Otherwise everything will default to current behavior and the le byte of zero will be added as per current behavior. + +Fix case when rollover feature checks config in non external reg mode and caused NPE. +(cherry picked from commit 853327d4c141a825b741535bebf621919d85200c) +--- + .../cms/servlet/tks/SecureChannelProtocol.java | 14 +++++++-- + .../server/tps/channel/SecureChannel.java | 35 +++++++++++++++++++--- + 2 files changed, 42 insertions(+), 7 deletions(-) + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +index b899c28..d39bc01 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +@@ -1189,8 +1189,8 @@ public class SecureChannelProtocol { + throw new EBaseException(method + "No raw array to use to create key!"); + } + +- SymmetricKey transport = getSharedSecretKey(token); +- unwrapped = this.unwrapSymKeyOnToken(token, transport, inputKeyArray, isPerm, SymmetricKey.DES3); ++ //RedHat For DES3 don's use the AES shared secret as wrapping key ++ unwrapped = this.unwrapSymKeyOnToken(token, null, inputKeyArray, isPerm, SymmetricKey.DES3); + + CMS.debug(method + "Returning symkey: length = " + unwrapped.getLength()); + //CMS.debug(method + "Returning symkey: " + unwrapped); +@@ -1630,8 +1630,16 @@ public class SecureChannelProtocol { + byte[] output = null; + byte[] finalOutput = new byte[3]; + ++ // RedHat :Do the same behavior as computeKeyCheck, use the token where the aes key resides. ++ String keysToken = null; ++ try { ++ keysToken = symKey.getOwningToken().getName(); ++ } catch (TokenException e1) { ++ throw new EBaseException(e1 + " Can't get owning token for key/"); ++ } ++ + try { +- output = computeAES_CBCEncryption(symKey, selectedToken, key_check_message, key_check_iv); ++ output = computeAES_CBCEncryption(symKey, keysToken, key_check_message, key_check_iv); + } catch (EBaseException e) { + CMS.debug(method + e); + throw e; +diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java +index bd590a7..6719de9 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java ++++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java +@@ -1160,8 +1160,10 @@ public class SecureChannel { + while (sum < len) { + + read = new ReadObjectAPDU(objectID.toBytesArray(), cur_offset, cur_read); +- // Add a 0x00 Le byte +- read.setTrailer(new TPSBuffer((byte) 0x00)); ++ //RedHat Add a 0x00 Le byte, appease tpsclient if configured ++ if(!skipTrailerLeByteScp01()) { ++ read.setTrailer(new TPSBuffer((byte) 0x00)); ++ } + + //CMS.debug("read encoding: " + read.getEncoding().toHexString()); + computeAPDU(read); +@@ -1452,8 +1454,10 @@ public class SecureChannel { + generate_key_apdu = new GenerateKeyAPDU((byte) pe1, (byte) pe2, (byte) algorithm, keySize, + (byte) option, (byte) 0, wrappedChallenge, keyCheck); + +- // Add a 0x00 Le byte +- generate_key_apdu.setTrailer(new TPSBuffer((byte) 0x00)); ++ // RedHat Add a 0x00 Le byte, appease tpsclient if configured. ++ if(!skipTrailerLeByteScp01()) { ++ generate_key_apdu.setTrailer(new TPSBuffer((byte) 0x00)); ++ } + + computeAPDU(generate_key_apdu); + +@@ -1839,4 +1843,27 @@ public class SecureChannel { + + CMS.debug(method + " Successful delete key data operation completed."); + } ++ ++ // RedHat ++ //Check config param if we want to not add le bytes for certain scp01 apdu's. ++ //default is false. If method returns false the le byte will be added as before. ++ public boolean skipTrailerLeByteScp01() { ++ ++ IConfigStore configStore = CMS.getConfigStore(); ++ ++ String method = "SecureChannel.skipTrailerLeByteScp01: "; ++ boolean skip = false; ++ try { ++ String configName = "channel.scp01.no.le.byte"; ++ ++ if(platProtInfo.isSCP01()) { ++ skip = configStore.getBoolean(configName,false); ++ } ++ } catch (Exception e) { ++ skip = false; ++ } ++ ++ CMS.debug(method + skip); ++ return skip; ++ } + } +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.4.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.4.patch new file mode 100644 index 0000000..a8ae30c --- /dev/null +++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.4.patch @@ -0,0 +1,51 @@ +From fe4788410c0b5e879bdcfe986f50350f2343e531 Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Mon, 3 Jun 2024 16:47:56 -0700 +Subject: [PATCH] Fix Bug 2265180 - Add Support for Symmetric Key Rollover + [RHCS 9.7.z]. (#4765) + +We found in QE a situation in fips mode with the hsm that the calculation of the scp03 keycheck value +could fail. Simply making that method behave like the scp01 version of the method fixes the issue. + +Also added some trivial code to apease tpsclient. We do so by creating a new secret config value used only +by those testing the product with tpsclient: + +channel.scp01.no.le.byte=true + +This will skip the le zero byte on only the generatekey and readobject apdu's only if scp01 is detected and this value is true. +Otherwise everything will default to current behavior and the le byte of zero will be added as per current behavior. + +Fix case when rollover feature checks config in non external reg mode and caused NPE. +Adding one file that didn't make it into the last commit. +(cherry picked from commit acb198939fc215beb44921852425d08c9257db97) +--- + base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +index 984ce79..2aa01a3 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +@@ -2570,7 +2570,8 @@ public class TPSProcessor { + symKeyUpgradeStatus = TPSStatus.STATUS_ERROR_SYMKEY_256_UPGRADE; + } + // Check whether exception is caused by attempting to change 256 OMK to 128 FMK +- else if (getSelectedKeySet().equals(getKeyDowngradeKeySet()) && getSymmetricKeysRequiredVersion() == getKeyDowngradeVersion()) ++ // RedHat : avoid null ptr. For non external reg case. ++ else if (getSelectedKeySet() != null && getSelectedKeySet().equals(getKeyDowngradeKeySet()) && getSymmetricKeysRequiredVersion() == getKeyDowngradeVersion()) + { + // proceed with downgrade if configured to do so + CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: try downgrade key size."); +@@ -3660,7 +3661,8 @@ public class TPSProcessor { + + // ** G&D 256 Key Rollover Support ** + // set the flag to indicate if card needs to roll over to 256 OMK +- boolean keyRollNeeded = (getSelectedKeySet().equals(getKeyRolloverKeySet()) && requiredVersion == getKeyRolloverVersion()); ++ // RedHat : avoid null ptr. For non external reg case. ++ boolean keyRollNeeded = (getSelectedKeySet() != null && getSelectedKeySet().equals(getKeyRolloverKeySet()) && requiredVersion == getKeyRolloverVersion()); + CMS.debug(" keyRollNeeded: " + keyRollNeeded); + // try to make a secure channel with the 'requiredVersion' keys + // If this fails, we know we will have to attempt an upgrade +-- +1.8.3.1 + diff --git a/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.patch b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.patch new file mode 100644 index 0000000..351025d --- /dev/null +++ b/SOURCES/pki-core-rhel-7-9-rhcs-9-7-CY24Q2.patch @@ -0,0 +1,7762 @@ +From b6ff92de03e5d77bc163c0b7531d81ce42a6a89b Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Thu, 24 Aug 2023 20:36:39 -0400 +Subject: [PATCH 01/10] Fix Bug 2180920 - add AES support for TMS server-side + keygen on latest HSM / FIPS environment [RHCS 9.7.z]. + +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. + +(cherry picked from commit 4ffcc64a963ecbb5763416a95e2d765bde1d02d2) +--- + base/common/src/com/netscape/certsrv/apps/CMS.java | 3 +- + .../src/com/netscape/certsrv/request/IRequest.java | 2 + + .../src/org/dogtagpki/tps/main/TPSBuffer.java | 22 ++ + .../src/com/netscape/kra/NetkeyKeygenService.java | 102 ++++++- + .../com/netscape/kra/TokenKeyRecoveryService.java | 87 +++++- + .../servlet/connector/GenerateKeyPairServlet.java | 26 +- + .../servlet/connector/TokenKeyRecoveryServlet.java | 22 +- + .../cms/servlet/csadmin/ConfigurationUtils.java | 2 +- + .../cms/servlet/tks/SecureChannelProtocol.java | 51 +++- + .../dogtagpki/server/connector/IRemoteRequest.java | 3 + + base/tks/shared/conf/CS.cfg | 4 +- + .../server/tks/rest/TPSConnectorService.java | 30 +- + .../dogtagpki/server/tks/servlet/TokenServlet.java | 185 +++++++++++- + base/tps/shared/applets/1.5.64260792.ijc | Bin 0 -> 17671 bytes + base/tps/shared/conf/CS.cfg | 9 +- + .../server/tps/channel/SecureChannel.java | 51 +++- + .../server/tps/cms/KRARemoteRequestHandler.java | 39 ++- + .../tps/cms/TKSComputeSessionKeyResponse.java | 8 + + .../server/tps/cms/TKSRemoteRequestHandler.java | 36 +++ + .../org/dogtagpki/server/tps/engine/TPSEngine.java | 35 ++- + .../server/tps/processor/TPSEnrollProcessor.java | 69 ++++- + .../server/tps/processor/TPSProcessor.java | 15 + + .../com/netscape/cmsutil/crypto/CryptoUtil.java | 336 +++++++++++++++++++++ + 23 files changed, 1046 insertions(+), 91 deletions(-) + create mode 100644 base/tps/shared/applets/1.5.64260792.ijc + +diff --git a/base/common/src/com/netscape/certsrv/apps/CMS.java b/base/common/src/com/netscape/certsrv/apps/CMS.java +index e852043..5d6966c 100644 +--- a/base/common/src/com/netscape/certsrv/apps/CMS.java ++++ b/base/common/src/com/netscape/certsrv/apps/CMS.java +@@ -1573,7 +1573,8 @@ public final class CMS { + name.equalsIgnoreCase("card_challenge") || + name.equalsIgnoreCase("card_cryptogram") || + name.equalsIgnoreCase("drm_trans_desKey") || +- name.equalsIgnoreCase("cert_request")); ++ name.equalsIgnoreCase("cert_request") || ++ name.equalsIgnoreCase("drm_trans_aesKey")); + } + + /** +diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java +index 7193791..cb2f463 100644 +--- a/base/common/src/com/netscape/certsrv/request/IRequest.java ++++ b/base/common/src/com/netscape/certsrv/request/IRequest.java +@@ -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"; +diff --git a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java +index 24c0b49..0d19428 100644 +--- a/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java ++++ b/base/common/src/org/dogtagpki/tps/main/TPSBuffer.java +@@ -315,6 +315,28 @@ public class TPSBuffer { + 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())) { +diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +index 55fd9a0..ea750ce 100644 +--- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java ++++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +@@ -16,7 +16,7 @@ + // All rights reserved. + // --- END COPYRIGHT BLOCK --- + package com.netscape.kra; +- ++import java.util.Arrays; + import java.io.ByteArrayInputStream; + import java.io.ByteArrayOutputStream; + import java.io.FilterOutputStream; +@@ -35,6 +35,7 @@ import org.mozilla.jss.crypto.KeyGenAlgorithm; + import org.mozilla.jss.crypto.KeyWrapAlgorithm; + import org.mozilla.jss.crypto.PrivateKey; + import org.mozilla.jss.crypto.SymmetricKey; ++import org.mozilla.jss.crypto.KeyPairAlgorithm; + import org.mozilla.jss.pkcs11.PK11SymKey; + import org.mozilla.jss.pkix.crmf.PKIArchiveOptions; + import org.mozilla.jss.util.Base64OutputStream; +@@ -71,6 +72,7 @@ import com.netscape.cmsutil.util.Utils; + import netscape.security.provider.RSAPublicKey; + import netscape.security.util.WrappingParams; + ++ + /** + * A class representing keygen/archival request procesor for requests + * from netkey RAs. +@@ -142,6 +144,22 @@ public class NetkeyKeygenService implements IService { + } + } + ++ // AC: KDF SPEC CHANGE - Audit logging helper functions. ++ // Converts a byte array to an ASCII-hex string. ++ // We implemented this ourselves rather than using this.pp.toHexArray() because ++ // the team preferred CUID and KDD strings to be without ":" separators every byte. ++ final char[] bytesToHex_hexArray = "0123456789ABCDEF".toCharArray(); ++ ++ private String bytesToHex(byte[] bytes) { ++ char[] hexChars = new char[bytes.length * 2]; ++ for (int i = 0; i < bytes.length; i++) { ++ int thisChar = bytes[i] & 0x000000FF; ++ hexChars[i * 2] = bytesToHex_hexArray[thisChar >>> 4]; // div 16 ++ hexChars[i * 2 + 1] = bytesToHex_hexArray[thisChar & 0x0F]; ++ } ++ return new String(hexChars); ++ } ++ + /** + * Services an archival request from netkey. + *

+@@ -154,6 +172,8 @@ public class NetkeyKeygenService implements IService { + throws EBaseException { + String auditSubjectID = null; + byte[] wrapped_des_key; ++ byte[] wrapped_aes_key = null; ++ String method = "NetkeyKeygenService: serviceRequest: "; + + byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; + String iv_s = ""; +@@ -166,7 +186,8 @@ public class NetkeyKeygenService implements IService { + throw new EBaseException(e); + } + +- IVParameterSpec algParam = new IVParameterSpec(iv); ++ IVParameterSpec algParam = null; ++ IVParameterSpec desAlgParam = new IVParameterSpec(iv); + + IConfigStore configStore = CMS.getConfigStore(); + boolean allowEncDecrypt_archival = configStore.getBoolean("kra.allowEncDecrypt.archival", false); +@@ -206,6 +227,18 @@ public class NetkeyKeygenService implements IService { + requestId)); + + String rWrappedDesKeyString = request.getExtDataInString(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY); ++ String rWrappedAesKeyString = request.getExtDataInString(IRequest.NETKEY_ATTR_DRMTRANS_AES_KEY); ++ ++ boolean useAesTransWrapped = false; ++ ++ if(rWrappedAesKeyString != null && rWrappedAesKeyString.length() > 0) { ++ useAesTransWrapped = true; ++ //If we are getting an aes trans wrapped key, make that the priority moving forwoard. ++ wrapped_aes_key = org.mozilla.jss.netscape.security.util.Utils.SpecialDecode(rWrappedAesKeyString); ++ CMS.debug(method + "TMS has sent trans wrapped aes key."); ++ request.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_AES_KEY,""); ++ } ++ + // the request reocrd field delayLDAPCommit == "true" will cause + // updateRequest() to delay actual write to ldap + request.setExtData("delayLDAPCommit", "true"); +@@ -239,6 +272,7 @@ public class NetkeyKeygenService implements IService { + + // get the token for generating user keys + CryptoToken keygenToken = mKRA.getKeygenToken(); ++ + if (keygenToken == null) { + CMS.debug("NetkeyKeygenService: failed getting keygenToken"); + request.setExtData(IRequest.RESULT, Integer.valueOf(10)); +@@ -246,14 +280,24 @@ public class NetkeyKeygenService implements IService { + } else + CMS.debug("NetkeyKeygenService: got keygenToken"); + ++ if(wrapped_aes_key != null) { ++ CMS.debug(method + " wrapped aes key size " + wrapped_aes_key.length); ++ } ++ ++ //Create legacy DES and new AES wrapping params, one or the other will be used. + if ((wrapped_des_key != null) && +- (wrapped_des_key.length > 0)) { ++ (wrapped_des_key.length > 0) || useAesTransWrapped == true) { + + WrappingParams wrapParams = new WrappingParams( + SymmetricKey.DES3, KeyGenAlgorithm.DES3, 0, + KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD, + KeyWrapAlgorithm.DES3_CBC_PAD, EncryptionUnit.IV, EncryptionUnit.IV); + ++ WrappingParams aesWrapParams = new WrappingParams( ++ SymmetricKey.AES, KeyGenAlgorithm.AES,0, ++ KeyWrapAlgorithm.RSA, EncryptionAlgorithm.AES_128_CBC_PAD, ++ KeyWrapAlgorithm.AES_KEY_WRAP_PAD,EncryptionUnit.IV, EncryptionUnit.IV); ++ + /* XXX could be done in HSM*/ + KeyPair keypair = null; + +@@ -282,6 +326,7 @@ public class NetkeyKeygenService implements IService { + CMS.debug("NetkeyKeygenService: finished generate key pair for " + rCUID + ":" + rUserid); + + java.security.PrivateKey privKey; ++ + try { + publicKeyData = keypair.getPublic().getEncoded(); + if (publicKeyData == null) { +@@ -311,7 +356,6 @@ public class NetkeyKeygenService implements IService { + + //...extract the private key handle (not privatekeydata) + privKey = keypair.getPrivate(); +- + if (privKey == null) { + request.setExtData(IRequest.RESULT, Integer.valueOf(4)); + CMS.debug("NetkeyKeygenService: failed getting private key"); +@@ -320,28 +364,54 @@ public class NetkeyKeygenService implements IService { + CMS.debug("NetkeyKeygenService: got private key"); + } + +- // unwrap the DES key ++ // unwrap the DES or AES key ++ // If we are given an AES key, use it, otherwise use DES if it's the only one offered. + PK11SymKey sk = null; +- try { +- sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_des_key, wrapParams); +- CMS.debug("NetkeyKeygenService: received DES key"); +- } catch (Exception e) { +- CMS.debug("NetkeyKeygenService: no DES key: " + e); +- request.setExtData(IRequest.RESULT, Integer.valueOf(4)); +- return false; +- } + ++ if(useAesTransWrapped == false) { ++ try { ++ sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_des_key, wrapParams); ++ CMS.debug("NetkeyKeygenService: received DES key"); ++ } catch (Exception e) { ++ CMS.debug("NetkeyKeygenService: no DES key: probably because crypto token no longer supports DES. " + e); ++ request.setExtData(IRequest.RESULT, Integer.valueOf(4)); ++ return false; ++ } ++ } else { ++ //Unwrap the included trans wrapped AES key. ++ CMS.debug(method + "Attempt to unwrap the trans wrapped AES session key."); ++ try { ++ sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_aes_key, aesWrapParams); ++ CMS.debug(method + " received AES session key"); ++ } catch (Exception e) { ++ CMS.debug(method + " no AES session key: or DES kek key. " + e); ++ request.setExtData(IRequest.RESULT, Integer.valueOf(4)); ++ return false; ++ } ++ } + // 3 wrapping should be done in HSM +- // wrap private key with DES ++ // wrap private key with session key + CMS.debug("NetkeyKeygenService: wrapper token=" + keygenToken.getName()); + CMS.debug("NetkeyKeygenService: key transport key is on slot: " + sk.getOwningToken().getName()); + ++ 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; ++ CMS.debug(method + " attemptedAesKeyWrap = true "); ++ } else { ++ algParam = desAlgParam; ++ CMS.debug(method + " attemptedAesKeyWrap = false "); ++ } ++ + byte[] wrapped = CryptoUtil.wrapUsingSymmetricKey( + keygenToken, + sk, + (PrivateKey) privKey, + algParam, +- KeyWrapAlgorithm.DES3_CBC_PAD); ++ symWrapAlg); + + /* + CMS.debug("NetkeyKeygenService: wrap called"); +@@ -383,7 +453,7 @@ public class NetkeyKeygenService implements IService { + PubKey)); + } + +- iv_s = /*base64Encode(iv);*/com.netscape.cmsutil.util.Utils.SpecialEncode(iv); ++ iv_s = org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(iv); + request.setExtData("iv_s", iv_s); + + } catch (Exception e) { +diff --git a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java +index e95945a..62bb37c 100644 +--- a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java ++++ b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java +@@ -190,10 +190,12 @@ public class TokenKeyRecoveryService implements IService { + public synchronized boolean serviceRequest(IRequest request) throws EBaseException { + String auditSubjectID = null; + String iv_s = ""; ++ String method = "TokenKeyRecoveryService.serviceRequest: "; + + CMS.debug("KRA services token key recovery request"); + IConfigStore config = null; + Boolean allowEncDecrypt_recovery = false; ++ CryptoToken token = null; + + try { + config = CMS.getConfigStore(); +@@ -239,12 +241,24 @@ public class TokenKeyRecoveryService implements IService { + String rCUID = request.getExtDataInString(IRequest.NETKEY_ATTR_CUID); + String rUserid = request.getExtDataInString(IRequest.NETKEY_ATTR_USERID); + String rWrappedDesKeyString = request.getExtDataInString(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY); ++ ++ String rWrappedAesKeyString = request.getExtDataInString(IRequest.NETKEY_ATTR_DRMTRANS_AES_KEY); + // the request record field delayLDAPCommit == "true" will cause + // updateRequest() to delay actual write to ldap + request.setExtData("delayLDAPCommit", "true"); + // wrappedDesKey no longer needed. removing. + request.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, ""); + ++ boolean useAesTransWrapped = false; ++ ++ byte[] wrapped_aes_key = null; ++ // Check for AES wrapped key. If present give AES precedence. Otherwise go with DES ++ if((rWrappedAesKeyString != null && rWrappedAesKeyString.length() > 0)) { ++ useAesTransWrapped = true; ++ wrapped_aes_key = org.mozilla.jss.netscape.security.util.Utils.SpecialDecode(rWrappedAesKeyString); ++ CMS.debug(method + "TMS has sent trans wrapped aes key."); ++ } ++ + auditSubjectID = rCUID + ":" + rUserid; + + //CMS.debug("TokenKeyRecoveryService: received DRM-trans-wrapped des key =" + rWrappedDesKeyString); +@@ -252,21 +266,35 @@ public class TokenKeyRecoveryService implements IService { + wrapped_des_key = com.netscape.cmsutil.util.Utils.SpecialDecode(rWrappedDesKeyString); + CMS.debug("TokenKeyRecoveryService: wrapped_des_key specialDecoded"); + ++ ++ KeyWrapAlgorithm wrapAlg = KeyWrapAlgorithm.RSA; ++ //Instantiate both DES3 or AES wrapping params. One or the other will be ultimately used. ++ WrappingParams wrapParams = new WrappingParams( ++ SymmetricKey.DES3, KeyGenAlgorithm.DES3, 0, ++ wrapAlg, EncryptionAlgorithm.DES3_CBC_PAD, ++ KeyWrapAlgorithm.DES3_CBC_PAD, EncryptionUnit.IV, EncryptionUnit.IV); ++ ++ ++ WrappingParams aesWrapParams = new WrappingParams( ++ SymmetricKey.AES, KeyGenAlgorithm.AES,0, ++ wrapAlg, EncryptionAlgorithm.AES_128_CBC_PAD, ++ KeyWrapAlgorithm.AES_KEY_WRAP_PAD,EncryptionUnit.IV, EncryptionUnit.IV); ++ ++ //Attempt legacy DES, if DES key not present or AES key present , drop down to AES processing. ++ + if ((wrapped_des_key != null) && + (wrapped_des_key.length > 0)) { + +- WrappingParams wrapParams = new WrappingParams( +- SymmetricKey.DES3, KeyGenAlgorithm.DES3, 0, +- KeyWrapAlgorithm.RSA, EncryptionAlgorithm.DES3_CBC_PAD, +- KeyWrapAlgorithm.DES3_CBC_PAD, EncryptionUnit.IV, EncryptionUnit.IV); +- + // unwrap the des key + try { + sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_des_key, wrapParams); + CMS.debug("TokenKeyRecoveryService: received des key"); + } catch (Exception e) { + CMS.debug("TokenKeyRecoveryService: no des key"); +- request.setExtData(IRequest.RESULT, Integer.valueOf(4)); ++ if(!useAesTransWrapped) { ++ request.setExtData(IRequest.RESULT, Integer.valueOf(4)); ++ return false; ++ } + } + } else { + CMS.debug("TokenKeyRecoveryService: not receive des key"); +@@ -279,10 +307,38 @@ public class TokenKeyRecoveryService implements IService { + "TokenRecoveryService: Did not receive DES key", + agentId)); + +- return false; ++ //Log the missing des key but we will use the aes key if present ++ if(!useAesTransWrapped) { ++ return false; ++ } ++ CMS.debug("TokenKeyRecoveryService: no des key use aes key for scp03."); ++ ++ } ++ ++ ++ //Now if we failed unwrapping the DES key directly to the token ++ //Use the included trans wrapped AES key to do so. ++ //We will fall back to AES wrapped key if present and DES key not present. ++ ++ boolean attemptAesKeyWrap = false; ++ if(sk == null) { ++ CMS.debug(method + "Attempt to use the AES session key to unwrap session key"); ++ ++ attemptAesKeyWrap = true; ++ try { ++ sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_aes_key, aesWrapParams); ++ CMS.debug(method + " received AES session key"); ++ //Use aes session key to unwrap the DES3 key ++ ++ } catch (Exception e) { ++ CMS.debug(method + " no AES session key: or DES kek key. " + e); ++ request.setExtData(IRequest.RESULT, Integer.valueOf(4)); ++ return false; ++ } + } + + // retrieve based on Certificate ++ token = mStorageUnit.getToken(); + String cert_s = request.getExtDataInString(ATTR_USER_CERT); + String keyid_s = request.getExtDataInString(IRequest.NETKEY_ATTR_KEYID); + KeyId keyId = keyid_s != null ? new KeyId(keyid_s): null; +@@ -340,7 +396,7 @@ public class TokenKeyRecoveryService implements IService { + CryptoToken internalToken = + CryptoManager.getInstance().getInternalKeyStorageToken(); + */ +- CryptoToken token = mStorageUnit.getToken(); ++ //CryptoToken token = mStorageUnit.getToken(); + CMS.debug("TokenKeyRecoveryService: got token slot:" + token.getName()); + IVParameterSpec algParam = new IVParameterSpec(iv); + +@@ -442,6 +498,7 @@ public class TokenKeyRecoveryService implements IService { + + Type keyType = PrivateKey.RSA; + byte wrapped[]; ++ + if (encrypted) { + // Unwrap the archived private key + byte privateKeyData[] = null; +@@ -523,12 +580,24 @@ public class TokenKeyRecoveryService implements IService { + + CMS.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; ++ CMS.debug(method + " attemptedAesKeyWrap = true "); ++ } else { ++ symWrapAlg = KeyWrapAlgorithm.DES3_CBC_PAD; ++ CMS.debug(method + " attemptedAesKeyWrap = false "); ++ } ++ + wrapped = CryptoUtil.wrapUsingSymmetricKey( + token, + sk, + privKey, + algParam, +- KeyWrapAlgorithm.DES3_CBC_PAD); ++ symWrapAlg); + + iv_s = /*base64Encode(iv);*/com.netscape.cmsutil.util.Utils.SpecialEncode(iv); + request.setExtData("iv_s", iv_s); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java +index b88e4c8..f1cf0e5 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java +@@ -143,7 +143,8 @@ public class GenerateKeyPairServlet extends CMSServlet { + 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(""))) { + CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: CUID"); + missingParam = true; +@@ -178,9 +179,20 @@ public class GenerateKeyPairServlet extends CMSServlet { + } + } + ++ boolean wrappedAesPresent = true; ++ boolean wrappedDesPresent = true; + if ((rdesKeyString == null) || + (rdesKeyString.equals(""))) { +- CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: DRM-transportKey-wrapped DES key"); ++ CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: DRM-transportKey-wrapped DES key, possibly AES key sent instead."); ++ wrappedDesPresent = false; ++ } ++ ++ if((raesKeyString == null) || (raesKeyString.equals(""))) { ++ wrappedAesPresent = false; ++ CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing DRM-wrapped AES Key, possibly DES key sent instead."); ++ } ++ ++ if(wrappedAesPresent == false && wrappedDesPresent == false) { + missingParam = true; + } + +@@ -195,7 +207,15 @@ public class GenerateKeyPairServlet extends CMSServlet { + 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); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java +index a4867bd..c7a257d 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java +@@ -152,6 +152,8 @@ public class TokenKeyRecoveryServlet extends CMSServlet { + + // IConfigStore sconfig = CMS.getConfigStore(); + boolean missingParam = false; ++ boolean missingTransAes = false; ++ boolean missingTransDes = false; + String status = "0"; + + CMS.debug("processTokenKeyRecovery begins:"); +@@ -162,6 +164,8 @@ public class TokenKeyRecoveryServlet extends CMSServlet { + 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(""))) { + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: CUID"); + missingParam = true; +@@ -171,11 +175,18 @@ public class TokenKeyRecoveryServlet extends CMSServlet { + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: userid"); + missingParam = true; + } ++ if ((raesKeyString == null) || (raesKeyString.equals(""))) { ++ CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: DRM-transportKey-wrapped aes key"); ++ missingTransAes = true; ++ } + + if ((rdesKeyString == null) || + (rdesKeyString.equals(""))) { + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: DRM-transportKey-wrapped des key"); +- missingParam = true; ++ // We expect either a trans wrapped aes or des key. ++ if(missingTransAes == true && missingTransDes == true) { ++ missingParam = true; ++ } + } + + if (((rCert == null) || (rCert.equals(""))) && +@@ -190,7 +201,14 @@ public class TokenKeyRecoveryServlet extends CMSServlet { + 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); + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): received request parameter: cert"); +diff --git a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +index 2510191..1486a96 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +@@ -3921,7 +3921,7 @@ public class ConfigurationUtils { + byte[] sharedSecretData = Utils.base64decode(keyData.getAdditionalWrappedPrivateData()); + + try { +- CryptoUtil.importSharedSecret(sessionKeyData, sharedSecretData, dbNick, nick); ++ CryptoUtil.importSharedSecretWithAES(sessionKeyData, sharedSecretData, dbNick, nick); + } catch (Exception e) { + CMS.debug("getSharedSecret()): WARNING, Failed to automatically import shared secret. Please follow the manual procedure." + e.toString()); + } +diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +index a7b0718..dc18748 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +@@ -73,6 +73,13 @@ public class SecureChannelProtocol { + static final int AES_192_BITS = 192; + static final int AES_256_BITS = 256; + ++ private static SymmetricKey.Usage session_key_usages[] = { ++ SymmetricKey.Usage.WRAP, ++ SymmetricKey.Usage.UNWRAP, ++ SymmetricKey.Usage.ENCRYPT, ++ SymmetricKey.Usage.DECRYPT ++ }; ++ + private SymmetricKey transportKey = null; + CryptoManager cryptoManager = null; + +@@ -724,6 +731,7 @@ public class SecureChannelProtocol { + + String method = "SecureChannelProtocol.returnDeveloperSymKey:"; + ++ CMS.debug(method + "keyAlg: " + keyAlg); + boolean isAES = false; + String finalAlg = null; + if(keyAlg == null) { +@@ -1000,9 +1008,21 @@ public class SecureChannelProtocol { + } + + try { +- encryptor = token.getCipherContext(EncryptionAlgorithm.DES3_ECB); + +- encryptor.initEncrypt(encUnwrapKey); ++ EncryptionAlgorithm encAlg = EncryptionAlgorithm.DES3_ECB; ++ KeyWrapAlgorithm wrapAlg = KeyWrapAlgorithm.DES3_ECB; ++ ++ IVParameterSpec iv = null; ++ if(encUnwrapKey.getType() == SymmetricKey.Type.AES) { ++ encAlg = EncryptionAlgorithm.AES_128_CBC_PAD; ++ wrapAlg = KeyWrapAlgorithm.AES_CBC_PAD; ++ iv = new IVParameterSpec(new byte[encAlg.getIVLength()]); ++ } ++ ++ encryptor = token.getCipherContext(encAlg); ++ ++ encryptor.initEncrypt(encUnwrapKey,iv); ++ + + if (finalKeyArray != null) { + if(finalKeyType == SymmetricKey.Type.DES3 || finalKeyType == SymmetricKey.Type.DES) +@@ -1020,8 +1040,8 @@ public class SecureChannelProtocol { + + // SecureChannelProtocol.debugByteArray(wrappedKey, " encrypted key"); + +- KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB); +- keyWrap.initUnwrap(encUnwrapKey, null); ++ KeyWrapper keyWrap = token.getKeyWrapper(wrapAlg); ++ keyWrap.initUnwrap(encUnwrapKey, iv); + + if (isPerm == true) { + unwrapped = keyWrap.unwrapSymmetricPerm(wrappedKey, +@@ -2304,4 +2324,27 @@ public class SecureChannelProtocol { + return output; + } + ++ public SymmetricKey generateAESSymKey(String selectedToken, int keySize) throws EBaseException { ++ String method = "SecureChannelProtocol.generateAESSymKey: "; ++ ++ CMS.debug(method + " entering , token: " + selectedToken + " size: " + keySize); ++ SymmetricKey symKey = null; ++ ++ if (selectedToken == null) { ++ throw new EBaseException(method + " Invalid input data!"); ++ } ++ ++ try { ++ CryptoManager cm = this.getCryptoManger(); ++ CryptoToken token = returnTokenByName(selectedToken, cm); ++ symKey = CryptoUtil.generateKey(token, KeyGenAlgorithm.AES, keySize, ++ session_key_usages,true); ++ } catch (Exception e) { ++ CMS.debug(method + " " + e); ++ throw new EBaseException(e); ++ } ++ ++ return symKey; ++ } ++ + } +diff --git a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java +index 0034303..b334b0d 100644 +--- a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java ++++ b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java +@@ -56,7 +56,9 @@ public interface IRemoteRequest { + public static final String TKS_RESPONSE_MacSessionKey = "macSessionKey"; + public static final String TKS_RESPONSE_KekSessionKey = "kekSessionKey"; + public static final String TKS_RESPONSE_KEK_DesKey = "kek_wrapped_desKey"; ++ 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 TKS_RESPONSE_KeyCheck = "keycheck"; + public static final String TKS_RESPONSE_HostCryptogram = "hostCryptogram"; + +@@ -104,6 +106,7 @@ public interface IRemoteRequest { + // KRA request params + public static final String KRA_UserId = "userid"; + public static final String KRA_Trans_DesKey = "drm_trans_desKey"; ++ public static final String KRA_Trans_AesKey = "drm_trans_aesKey"; + public static final String KRA_KEYGEN_Archive = "archive"; + public static final String KRA_KEYGEN_KeyType = "keytype"; + public static final String KRA_KEYGEN_EC_KeyCurve = "eckeycurve"; +diff --git a/base/tks/shared/conf/CS.cfg b/base/tks/shared/conf/CS.cfg +index 9227c27..87819f7 100644 +--- a/base/tks/shared/conf/CS.cfg ++++ b/base/tks/shared/conf/CS.cfg +@@ -300,8 +300,8 @@ selftests.container.logger.maxFileSize=2000 + selftests.container.logger.register=false + selftests.container.logger.rolloverInterval=2592000 + selftests.container.logger.type=transaction +-selftests.container.order.onDemand=TKSKnownSessionKey:critical, SystemCertsVerification:critical +-selftests.container.order.startup=TKSKnownSessionKey:critical, SystemCertsVerification:critical ++selftests.container.order.onDemand=SystemCertsVerification:critical ++selftests.container.order.startup=SystemCertsVerification:critical + selftests.plugin.TKSKnownSessionKey.CUID=#a0#01#92#03#04#05#06#07#08#c9 + selftests.plugin.TKSKnownSessionKey.TksSubId=tks + selftests.plugin.TKSKnownSessionKey.cardChallenge=#bd#6d#19#85#6e#54#0f#cd +diff --git a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java +index 4b62ecf..feeeca1 100644 +--- a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java ++++ b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java +@@ -48,7 +48,8 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + private static final String TPS_LIST = "tps.list"; + + IConfigStore cs = CMS.getConfigStore(); +- ++ ++ public static final int AES_SESS_KEYSIZE = 128; + public IUGSubsystem userGroupManager = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + + @Override +@@ -312,19 +313,26 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + throw new BadRequestException("Shared secret already exists"); + } + +- CryptoUtil.createSharedSecret(nickname); ++// CryptoUtil.createSharedSecret(nickname); ++ CryptoUtil.createSharedSecret(nickname,KeyGenAlgorithm.AES,AES_SESS_KEYSIZE); + + cs.putString("tps." + id + ".nickname", nickname); + cs.commit(true); + +- //Create des3 session sym key to wrap the shared secret. +- SymmetricKey tempKey = createDes3SessionKeyOnInternal(); ++ //Create aes session sym key to wrap the shared secret. ++// SymmetricKey tempKey = createDes3SessionKeyOnInternal(); ++ SymmetricKey tempKey = CryptoUtil.createAESSessionKeyOnInternal(AES_SESS_KEYSIZE); + + if (tempKey == null) { + return createNoContentResponse(); + } + +- List listWrappedKeys = CryptoUtil.exportSharedSecret(nickname, certs[0], tempKey); ++ //List listWrappedKeys = CryptoUtil.exportSharedSecret(nickname, certs[0], tempKey); ++ ++ CMS.debug("TPSConnectorService.createSharedSecret. about to export shared secret : " + nickname + " certs.length " + certs.length); ++ CMS.debug("TPSConnectorService.createSharedSecert cert: " + certs[certs.length -1]); ++ List listWrappedKeys = CryptoUtil.exportSharedSecretWithAES(nickname, certs[certs.length -1], tempKey); ++ CMS.debug("TPSConnectorService.createSharedSecret. done exporting shared secret : " + nickname); + + byte[] wrappedSessionKey = listWrappedKeys.get(0); + byte[] wrappedSharedSecret = listWrappedKeys.get(1); +@@ -384,16 +392,22 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + X509Certificate[] certs = user.getX509Certificates(); + + CryptoUtil.deleteSharedSecret(nickname); +- CryptoUtil.createSharedSecret(nickname); ++ CryptoUtil.createSharedSecret(nickname,KeyGenAlgorithm.AES,AES_SESS_KEYSIZE); ++// CryptoUtil.createSharedSecret(nickname); ++ ++ // Create aes session sym key to wrap the shared secret. ++ SymmetricKey tempKey = CryptoUtil.createAESSessionKeyOnInternal(AES_SESS_KEYSIZE); + + //Create des3 session sym key to wrap the shared secret. +- SymmetricKey tempKey = createDes3SessionKeyOnInternal(); ++ //SymmetricKey tempKey = createDes3SessionKeyOnInternal(); + + if (tempKey == null) { + return createNoContentResponse(); + } + +- List listWrappedKeys = CryptoUtil.exportSharedSecret(nickname,certs[0], tempKey); ++ List listWrappedKeys = CryptoUtil.exportSharedSecretWithAES(nickname, certs[certs.length -1], tempKey); ++ ++ //List listWrappedKeys = CryptoUtil.exportSharedSecret(nickname,certs[0], tempKey); + + byte[] wrappedSessionKey = listWrappedKeys.get(0); + byte[] wrappedSharedSecret = listWrappedKeys.get(1); +diff --git a/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java b/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java +index 24afc50..49ebe60 100644 +--- a/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java ++++ b/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java +@@ -39,6 +39,8 @@ import org.mozilla.jss.crypto.KeyWrapper; + import org.mozilla.jss.crypto.SymmetricKey; + import org.mozilla.jss.crypto.X509Certificate; + import org.mozilla.jss.pkcs11.PK11SymKey; ++import org.mozilla.jss.crypto.IVParameterSpec; ++import org.mozilla.jss.crypto.EncryptionAlgorithm; + + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.authentication.IAuthToken; +@@ -866,7 +868,10 @@ public class TokenServlet extends CMSServlet { + + boolean serversideKeygen = false; + byte[] drm_trans_wrapped_desKey = null; ++ byte[] aes_wrapped_desKey = null; ++ byte[] drm_trans_wrapped_aesKey = null; + SymmetricKey desKey = null; ++ SymmetricKey aesKey = null; + // PK11SymKey kek_session_key; + SymmetricKey kek_key; + +@@ -902,6 +907,7 @@ public class TokenServlet extends CMSServlet { + audit(auditMessage); + + String kek_wrapped_desKeyString = null; ++ String kek_wrapped_aesKeyString = null; + String keycheck_s = null; + + CMS.debug("processComputeSessionKey:"); +@@ -1151,10 +1157,14 @@ public class TokenServlet extends CMSServlet { + //cfu audit here? sym key gen + + desKey = protocol.generateSymKey(CryptoUtil.INTERNAL_TOKEN_NAME); ++ //128 for now until we implement the full > 128 aes funcionality. ++ aesKey = protocol.generateAESSymKey(CryptoUtil.INTERNAL_TOKEN_NAME,128); ++ + //cfu audit here? sym key gen done + } else { + CMS.debug("TokenServlet: key encryption key generated on " + selectedToken); + desKey = protocol.generateSymKey(selectedToken); ++ aesKey = protocol.generateAESSymKey(selectedToken,128); + } + if (desKey != null) { + // AC: KDF SPEC CHANGE - Output using CUID and KDD +@@ -1172,13 +1182,35 @@ public class TokenServlet extends CMSServlet { + throw new Exception("can't generate key encryption key"); + } + ++ if (aesKey != null) { ++ CMS.debug("TokenServlet: aes key encryption key generated for CUID=" + ++ trim(pp.toHexString(xCUID)) /* + ++ ", KDD=" + ++ trim(pp.toHexString(xKDD)) */ ); ++ } else { ++ CMS.debug("TokenServlet: aes key encryption key generation failed for CUID=" + ++ trim(pp.toHexString(xCUID)) /* + ++ ", KDD=" + ++ trim(pp.toHexString(xKDD)) */ ); ++ ++ throw new Exception("can't generate aes key encryption key"); ++ } ++ + /* + * ECBencrypt actually takes the 24 byte DES2 key + * and discard the last 8 bytes before it encrypts. + * This is done so that the applet can digest it + */ + ++ /* Now that ecbEncrypt() can handle AES keys, ++ * in case it's an AES key, it simply ++ * wraps the AES key with KEK and returns ++ * the encrypted byte array ++ */ ++ + byte[] encDesKey = protocol.ecbEncrypt(kek_key, desKey, selectedToken); ++ byte[] encAesKey = protocol.ecbEncrypt(kek_key,aesKey,selectedToken); ++ + + /* + CMS.debug("computeSessionKey:encrypted desKey size = "+encDesKey.length); +@@ -1188,6 +1220,9 @@ public class TokenServlet extends CMSServlet { + kek_wrapped_desKeyString = + com.netscape.cmsutil.util.Utils.SpecialEncode(encDesKey); + ++ kek_wrapped_aesKeyString = ++ org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(encAesKey); ++ + // get keycheck + + byte[] keycheck = protocol.computeKeyCheck(desKey, selectedToken); +@@ -1233,6 +1268,16 @@ public class TokenServlet extends CMSServlet { + drm_trans_wrapped_desKey = keyWrapper.wrap(desKey); + CMS.debug("computeSessionKey:desKey wrapped with drm transportation key."); + ++ drm_trans_wrapped_aesKey = keyWrapper.wrap(aesKey); ++ CMS.debug("computeSessionKey:aesKey wrapped with drm transportation key. size " + drm_trans_wrapped_aesKey.length); ++ ++ //wrap the des key with the aes sym key as well. ++ ++ KeyWrapper aesKeyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC_PAD); ++ aesKeyWrap.initWrap(aesKey,new IVParameterSpec(new byte[EncryptionAlgorithm.AES_128_CBC_PAD.getIVLength()])); ++ aes_wrapped_desKey = aesKeyWrap.wrap(desKey); ++ CMS.debug("computeSessionKey:desKey wrapped with aes session key."); ++ + } // if (serversideKeygen == true) + + byte authKeyArray[] = +@@ -1306,6 +1351,8 @@ public class TokenServlet extends CMSServlet { + String outputString = ""; + String encSessionKeyString = ""; + String drm_trans_wrapped_desKeyString = ""; ++ String aes_wrapped_desKeyString = ""; ++ String drm_trans_wrapped_aesKeyString = ""; + String cryptogram = ""; + String status = "0"; + if (session_key != null && session_key.length > 0) { +@@ -1313,6 +1360,7 @@ public class TokenServlet extends CMSServlet { + com.netscape.cmsutil.util.Utils.SpecialEncode(session_key); + } else { + ++CMS.debug("0"); + status = "1"; + } + +@@ -1320,6 +1368,7 @@ public class TokenServlet extends CMSServlet { + encSessionKeyString = + com.netscape.cmsutil.util.Utils.SpecialEncode(enc_session_key); + } else { ++CMS.debug("1"); + status = "1"; + } + +@@ -1328,8 +1377,29 @@ public class TokenServlet extends CMSServlet { + drm_trans_wrapped_desKeyString = + com.netscape.cmsutil.util.Utils.SpecialEncode(drm_trans_wrapped_desKey); + else { ++CMS.debug("2"); + status = "1"; + } ++ ++ if (drm_trans_wrapped_aesKey != null && drm_trans_wrapped_aesKey.length > 0) { ++ drm_trans_wrapped_aesKeyString = ++ org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(drm_trans_wrapped_aesKey); ++ //CMS.debug("drm_trans_wrapped_aesKeyString: " + drm_trans_wrapped_aesKeyString); ++ ++ } else { ++CMS.debug("3"); ++ status = "1"; ++ } ++ ++ if (aes_wrapped_desKey != null && aes_wrapped_desKey.length > 0) { ++ aes_wrapped_desKeyString = ++ org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(aes_wrapped_desKey); ++ ++ } else { ++CMS.debug("4"); ++ status = "1"; ++ } ++ + } + + if (host_cryptogram != null && host_cryptogram.length > 0) { +@@ -1412,10 +1482,14 @@ public class TokenServlet extends CMSServlet { + sb.append(encSessionKeyString); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_KEK_DesKey + "="); + sb.append(kek_wrapped_desKeyString); ++ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KEK_AesKey + "="); ++ sb.append(kek_wrapped_aesKeyString); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_KeyCheck + "="); + sb.append(keycheck_s); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey + "="); + sb.append(drm_trans_wrapped_desKeyString); ++ sb.append("&" + IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey + "="); ++ sb.append(drm_trans_wrapped_aesKeyString); + value = sb.toString(); + } else { + +@@ -1431,7 +1505,7 @@ public class TokenServlet extends CMSServlet { + } + + } +- //CMS.debug("TokenServlet:outputString.encode " + value); ++ CMS.debug("TokenServlet:outputString.encode " + value); + + try { + resp.setContentLength(value.length()); +@@ -2508,7 +2582,10 @@ public class TokenServlet extends CMSServlet { + audit(auditMessage); + + String kek_wrapped_desKeyString = null; ++ String kek_wrapped_aesKeyString = null; ++ + String keycheck_s = null; ++ String keycheck_aes_s = null; + + String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true"); + if (!useSoftToken_s.equalsIgnoreCase("true")) +@@ -2768,6 +2845,7 @@ public class TokenServlet extends CMSServlet { + String kekSessionKeyString = ""; + + String drm_trans_wrapped_desKeyString = ""; ++ String drm_trans_wrapped_aesKeyString = ""; + String cryptogram = ""; + String status = "0"; + +@@ -2792,11 +2870,40 @@ public class TokenServlet extends CMSServlet { + status = "1"; + } + ++ // 0 : Kek wrapped des key ++ // 1 : keycheck value des ++ // 2 : keycheck value aes ++ // 3 : trans wrapped des key ++ // 4 : trans wrapped aes key ++ // 5 : kek wrapped aes key ++ ++ //Values above returned by routine to calculate server side keygen values. + if (serversideKeygen == true) { +- if (serverSideValues.size() == 3) { +- drm_trans_wrapped_desKeyString = serverSideValues.get(2); ++ CMS.debug(method + " serversideValues.size: " + serverSideValues.size()); ++ //for(int i = 0 ; i < serverSideValues.size(); i++) { ++ // CMS.debug(method + " val:" + i + " : " + serverSideValues.get(i)); ++ //} ++ ++ if (serverSideValues.size() >= 3) { ++ CMS.debug(method + " size >= 3 "); ++ ++ //Get the value produced even for SC03 . ++ drm_trans_wrapped_desKeyString = serverSideValues.get(3); ++ + kek_wrapped_desKeyString = serverSideValues.get(0); + keycheck_s = serverSideValues.get(1); ++ keycheck_aes_s = serverSideValues.get(2); ++ ++ if(serverSideValues.size() >= 5) { ++ CMS.debug(method + " size >= 5"); ++ drm_trans_wrapped_aesKeyString = serverSideValues.get(4); ++ } ++ ++ if(serverSideValues.size() >= 6) { ++ CMS.debug(method + " size >= 6"); ++ kek_wrapped_aesKeyString = serverSideValues.get(5); ++ //CMS.debug(method + "kek_wrapped_aesKeyString: " + kek_wrapped_aesKeyString); ++ } + } + else { + status = "1"; +@@ -2877,10 +2984,15 @@ public class TokenServlet extends CMSServlet { + sb.append(kekSessionKeyString); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_KEK_DesKey + "="); + sb.append(kek_wrapped_desKeyString); ++ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KEK_AesKey + "="); ++ sb.append(kek_wrapped_aesKeyString); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_KeyCheck + "="); +- sb.append(keycheck_s); ++ sb.append(keycheck_aes_s); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey + "="); + sb.append(drm_trans_wrapped_desKeyString); ++ sb.append("&" + IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey + "="); ++ //CMS.debug(method + " drm_trans_wrapped_aesKeyString " + drm_trans_wrapped_aesKeyString); ++ sb.append(drm_trans_wrapped_aesKeyString); + value = sb.toString(); + } else { + StringBuffer sb = new StringBuffer(); +@@ -3011,14 +3123,21 @@ public class TokenServlet extends CMSServlet { + + //returns ArrayList of following values + // 0 : Kek wrapped des key +- // 1 : keycheck value +- // 2 : trans wrapped des key ++ // 1 : keycheck value des ++ // 2 : keycheck value aes ++ // 3 : trans wrapped des key ++ // 4 : trans wrapped aes key ++ // 5 : kek wrapped aes key ++ + private ArrayList calculateServerSideKeygenValues(String useSoftToken, String selectedToken, + SymmetricKey kekSessionKey, SecureChannelProtocol protocol) throws EBaseException { + + SymmetricKey desKey = null; ++ SymmetricKey aesKey = null; + String method = "TokenServlet.calculateSErverSideKeygenValues: "; + ArrayList values = new ArrayList(); ++ int protocolLevel = protocol.getProtocol(); ++ + + /** + * 0. generate des key +@@ -3047,13 +3166,26 @@ public class TokenServlet extends CMSServlet { + if (useSoftToken.equals("true")) { + CMS.debug(method + " key encryption key generated on internal"); + desKey = protocol.generateSymKey("internal"); ++ //128 for now until we implement the full > 128 aes funcionality. ++ if(protocolLevel == 3) { ++ //still do the des key as a backup later ++ aesKey = protocol.generateAESSymKey("internal",128); ++ } ++ + //cfu audit here? sym key gen done + } else { + CMS.debug("TokenServlet: key encryption key generated on " + selectedToken); + desKey = protocol.generateSymKey(selectedToken); ++ if(protocolLevel == 3) { ++ aesKey = protocol.generateAESSymKey(selectedToken,128); ++ } ++ } ++ if (desKey == null && protocolLevel == 1) { ++ throw new EBaseException(method + "can't generate DES key encryption key"); + } +- if (desKey == null) { +- throw new EBaseException(method + "can't generate key encryption key"); ++ ++ if (aesKey == null && protocolLevel == 3) { ++ throw new EBaseException(method + "can't generate AES key encryption key"); + } + + /* +@@ -3062,14 +3194,23 @@ public class TokenServlet extends CMSServlet { + * This is done so that the applet can digest it + */ + ++ /* Now that ecbEncrypt() can handle AES keys, ++ * in case it's an AES key, it simply ++ * wraps the AES key with KEK and returns ++ * the encrypted byte array ++ */ + + // protocol.wrapSessionKey(tokenName, sessionKey, wrappingKey) + + byte[] encDesKey = protocol.ecbEncrypt(kekSessionKey, desKey, selectedToken); ++ byte[] encAesKey = protocol.ecbEncrypt(kekSessionKey,aesKey,selectedToken); + + String kek_wrapped_desKeyString = + com.netscape.cmsutil.util.Utils.SpecialEncode(encDesKey); + ++ String kek_wrapped_aesKeyString = ++ com.netscape.cmsutil.util.Utils.SpecialEncode(encAesKey); ++ + // CMS.debug(method + "kek_wrapped_desKeyString: " + kek_wrapped_desKeyString); + + values.add(kek_wrapped_desKeyString); +@@ -3077,15 +3218,30 @@ public class TokenServlet extends CMSServlet { + // get keycheck + + byte[] keycheck = null; ++ byte[] keycheck_aes = null; + + keycheck = protocol.computeKeyCheck(desKey, selectedToken); ++ if(aesKey != null) { ++ CMS.debug(method + "About to compute keycheck scp03"); ++ keycheck_aes = protocol.computeKeyCheck_SCP03(aesKey, selectedToken); ++ } + +- String keycheck_s = +- com.netscape.cmsutil.util.Utils.SpecialEncode(keycheck); ++ String keycheck_s = ""; ++ String keycheck_aes_s = ""; + +-// CMS.debug(method + "keycheck_s " + keycheck_s); ++ if(keycheck != null) { ++ keycheck_s = com.netscape.cmsutil.util.Utils.SpecialEncode(keycheck); ++ } ++ ++ if(keycheck_aes != null) { ++ keycheck_aes_s = com.netscape.cmsutil.util.Utils.SpecialEncode(keycheck_aes); ++ } ++ ++ ++ // CMS.debug(method + "keycheck_s " + keycheck_s); + + values.add(keycheck_s); ++ values.add(keycheck_aes_s); + + //use DRM transport cert to wrap desKey + String drmTransNickname = CMS.getConfigStore().getString("tks.drm_transport_cert_nickname", ""); +@@ -3130,6 +3286,13 @@ public class TokenServlet extends CMSServlet { + // CMS.debug(method + " drmWrappedDesStr: " + drmWrappedDesStr); + values.add(drmWrappedDesStr); + ++ byte[] drm_trans_wrapped_aesKey = keyWrapper.wrap(aesKey); ++ String drmWrappedAesStr = ++ com.netscape.cmsutil.util.Utils.SpecialEncode(drm_trans_wrapped_aesKey); ++ ++ //CMS.debug(method + " drmWrappedAesStr: " + drmWrappedAesStr); ++ values.add(drmWrappedAesStr); ++ values.add(kek_wrapped_aesKeyString); + } catch (Exception e) { + throw new EBaseException(e); + } +diff --git a/base/tps/shared/applets/1.5.64260792.ijc b/base/tps/shared/applets/1.5.64260792.ijc +new file mode 100644 +index 0000000000000000000000000000000000000000..c92c417226b7f4f38808d8ca4362ef64608e1205 +GIT binary patch +literal 17671 +zcmc(Hdw5*Mm1o_$b>FwUZ@1J}w_EOqWJ&JU!$>W_GQ!}t#M=%KW3a-8$Odf3vT+X{ +zh(?|SSpHpy&e5+;vfHjreJ;5C^*CM0CCGw%7F +zy4{it=KHeW{;_IT*SS@vPF0;cbb|lee11CjWN!0%tLZmN&Pl^ +z=!{F*fHuOIvw`VMWm!#Of|WF;822;Awlam+A!QNbjWVtl5%$2^H|y*n +zHVs0GVuH#pwwFz@{p?<)Q#o6?mhD%2S(`8z>-=~Pf1PJ{9_@Up>nXJ0Xc1?u@J#XC +z;%~cy?#}M+?t$)ex-aX#xqDyto!w7&f1~@^?w@tP3|tks5ypCYdsg+V>)Fur?wU@`EdntbBCk6DxmYoN=jb +zesbD0Kf|tU`ptB#S+Mssk4#6KH?sF+o}RujJIGjeaGF!zc4XRV177D(r@hWs*_B=T +zwBJ=^tgAT9DPQs0bhKcwD^)Kz$es_>11t~+lt4Sc16{kDJus_Iaj&XsU6YiFFjJAO +z&1G*g<46APZgwJ-?VQxFQj10|tCe>z6pnGFv#9ynmQzb~)z|N4|6DYDJQ4IZBM-^X#3`vS-a8q4bR-5rm{pFO*R#c%8MA6Z>+AWYSuT($TgW~ +zC$%erR5s^}Id;x4YP%-I6&UJxon|g87PyY7|Y1w`PkPO|__JbGw_-VoR)1 +zk6tUk%;t90NuY~Mz_xP(WmX_*xuS?S-Br|r_*!;Am*0l`HUsr8EAY&F*}hpj@Pd2U +zL$eO@_dBz05NGd49tj_#vUYejCi6A3p3MLAY#gnDl?Xf!SrZ!l7R@@ +zy1%44Ar?AdkNU=V(l;>6PqX_|*=n=u8+WrG4wD?wXpBYF{Y1(3ZBP=Gy{8ZomFs<5 +zn@9m81wkV5ELvln`$CiLts8aU!iEqxh{|fU=%_`Ph`GKiiFNtzjqyc-ROLwAi0_PB +zf$xZokfB5DAJ+KVLH48BEZ`T{RI>-!|DMfZPbwymf$CzVl(QV~dQ{t?&)>+DJHFBOwBJN>tSM6L!K_tcY +z`g2;B8z_z{HEqZ_YNnt)wu= +zE|LgSP+rC^JLh>fX`-U4llpkIbGt32_u|>kYUdogq>44nC55leu}g=i^ta^n-Bvii +zDKM!hz=xtH=ZD@g_Oxd}rhW4kRv>f0BKU4i7c9>#+Btos=v4gbih`vU?fC*8toRWh +zqnq*_ZGmpm^6k6XdI*H0`ED8IM^c1Sg&1@cBGn>E;*f9bWzV1k!D9IM%#R;wBCKTO +z9)&%`i!rt6`LVt19k4Ve+svBeXEWQ3b(t_AbCrnijyGtBt(3UO_Mj*&hoo;YJ+~OG +zEQeN@Kxr$L#*Zuuvz9OmC<`#6=t1_DLfm(^G$-T9h;Qfa-@H9@Q3U +zCT$;5w!WA^cc}0aIURH|=E)U|CF-!Y9t|WB2(wxFL#hU(+Vg +zfLPaPpcI?^W@0E7MiYA(!30Z-P +z+gOs#eX%v>3m8sI%4b6#VhbE(*OD%RQ*%OU1+uW{WOcohfCX$tNc=xliXrfJGE`fB +zTS?c;7fNYokZzsQ&#tT2(tIA?#6~2D5|mX@%;)Fzjg202UKENq)T5eI&7`%{CW)*D +zr9`=&_AKOE%(UlpUJq=AP&_bmJsHIt>g|1vPqe`s*lEH+I5`1VD=r=<4~)#jP8(#+u*OH15Uz1(&_QsqMEs%gn~US$8iBRhZIYeY +z1{!koP^DNWv1kNLGIYc`GK^DV5EV2q8VAM*?TUpz$ZjB$(ipH>O6SH@MGT!LGf@aX3WBfl +zbgr76V>cdNcs#XYTfH3eq7pN!_Tk;hs_knX+u(MQwYjpa_l%BfYaD-*#@6c^Cr;P6=}j8juWQ_Vy2i;jX$&cnbFM@iq9+|H)<30@ +zl58l6h7HJhPQ$&1s@Ouu$(~A-R0t_C(sPgXz%=En&SO0t+oCcfw?y3%3D&%~2iqO^ +z&r6)kWMx65)yH~<(jrL0e*NiCTC2K`^>hxU^`xMNQ2CpOs}Z!&FG!mnY}*fq7bvA5 +zxwP}4suqU|OId<3!giCV0O%7MX{4GN0zHn25G+Y^gC4uWVhD|D$N&Q_Q +zOIf!p@LZQ#7K<#)yBd~7HU=(s>12acz4suMG<{H)honE768Y*1b-n<5aQ-lPfK!^Z +zz5n;;I$xgb8iIGqp(`MRdo678cogR^g5Tu)MF*~_AXV)}T;U-5vv6hq_%kM?ibPzB +zlpFw@8r9c^Qgp(2^A(l;PpNLvVcDgtqb;l+{4=bc-dMdHpJ>Ml!r%)S{1&xn(orn{ +z$F=f-0?r0TWvH5yfuyadBePqud~@kqnY31a-dHOv6O`^GooIdIrZ_F#O)#l)g~*`_ +zPrXr`h`_lrg~NV0JjDkfoh9PeyNOGJw$l}uyYw9(>UXo-3R+T2-NO+f#C}>%PjhU4 +z{3f>34WZo($BaGXYgAD80i4TchEwE--|mYWtrX@r$KDI#YDp>X>#D+c?Wt5JAo%~d+tUvWdcACCACDuT_k@xENzei2Mt7Modw$CV2hAF%%BGd +zn3^-oFcs5$_|!q1iijxFL3Rf;Xk$YY{aizQq?;MK>1GZGtr2J_U&w$L%~tlrqbJk +zOAA*U<2AHPsE|Yef`)&P0b}>(2|5U2nzSP&5^Lm-LbO^c;CV_BViC!MvdPT!tr +z0$`&cE^}Y1uq?3+1A?0)h9qDEKtL6KpIJFXp*Qrid$f*&J$5F1KC5F}pUkA`7;g)F +z3tRlo1*s+ss$$eN9~!fi$`ebbP5$j0;zy?{Z_@VIb#gn)$P&bK;UonXz!oid`6SY_ +zNyJ!4YU_a;u@MgN5ZvQ*PJ~&g;NcHfolJ*xB0(~p)5`a#Y=?%U4?J`-0Xf=z<Fn2Y65#p6Kb|Z)siR* +zFIL29pX4AmVQ^@TH1rHa*)!=dF3p}v<_Upvim?R?F*XNhpL7-9A>(7D1QytigC{8_ +ziA|y;kDuF?$t=Y8#9zT#^J8QNt6omm|rDtoI$-h-xwFN5htRAkg_0Rt%2vT^LJsh2}%qA3$Kh +zq=1G8dlVknp^2$7hF+vcfd>!Ks&ZK9du5#a0|aNn5Js6IaqkPCpeAwHn=8iamEgqY +z;ehZ^6Nj2k!{jZo_4QIpJT#9vBNkjlL9gxn;lNMF^27M!77yj%kQJROV#48h&*20k +zIzV$D3!i+f+2&!$Oam3OS*Sb}Rn{ae$k7gU95W+;RT1du*uK0P%XMte(8D1%yasc% +z53+k!p;Xqdsx--*uy#OBFq{*zpx`Fq{vS$O?{o-wf6}IEit*6ny;IYc8vK#lOdiY; +zLXZb@>;Lz@s#}#}#E*D7?!KfJLujS57*!$aQSUAa_Ql|3*wROYV2hnm-&@>Z2y}a8 +zgw!H_ywP5Tev5~91qnZnICr94Yyv{lQiP@up_$5o(o6?o**ju}W@D$1HDTFrDvgCIV!0)pxV+OkeVa~?U4#KNs2T{s-Ygjr_esiu6jd#A{&JIG;<5I}mY1)E9|d1Z7x3p1x)__{C3%d5XoQ#9Gn(4Z34NDIwclRmfVn4JK%5PQmh`|dNUky +zbw50%E>OtPwO2T7HGV@Esob;{H)MdWK0URcZ1WPldFh*^wR!1>q>XuKJT&w4$1Jdf +z!Z|o)hm9Ijeas?WfTOrbBmIbb=1@T%FaS`T_kan&>BMCrE&}IqV_Vxe9-YVSCUQN{ +z?pi*jUEvEn!p{uHn}ehL5qVZ7_L0AZqg5VW@Pc>TateQ>e+&)Fs_Lgx&Y?8cs@ngd@nl>H+ecs;XksXsV@DPzhUa%_1Bckh +z*8~~N?h`9p=h!Ewlze6{TZ!nc$yyM3!Ma&5>oq3LNpv5&h~c-6vDMEulk$y{ +z`(ctWjcKjAQWZl}N}D>6xrHrf1}m{Pb~e&lq_-kng>*I2+whLfK$cqL_5l{{Q?o1Z +z3WNlTcn1Q8>Ql45A@IO#Um#HM;Oxpq%^A1>=)$I?<1=~DpB^`5i2dQ*ElPy>wSQqR +z)qcmGt^I-hAB^Db7{NAn4*MEAmwgK(nPltO9yW@1elBKz!7f!)jO+s#*@GC_$8eYW +zBu4i>wuOC;RoHLXpC}Hynf)W)68b0E$0JAC;}SS}lszJW&m3i+kich;vJXk%b4S@h +z2|Rj~-7bM@1>q4~0z6i^S?2SVoicyCvQ_4vue?p>|E2O)ng2!QQkfsCtdsc{D(A@j +zi*&*}4u8hn4Yn9D1f2M->cfgtdR=HT_ +zk5<;oe7-Uy^G7QEGCx`=$o#XFyv(bWK<1ChJH3PKzc0?WJ(y!(hjn>B!#;hiYm1Jz +zcm4-Nvr|IfptmSU751f7L|<;fJhj?1Yp=bRb=MwZsoLW#jrYP*;evg$-p#k_-TV!@ +zxryjbDLCAOQja5XHj@=28%Ij`E(#cDoF#p2()lR8$TU)<7Xqqh6r9vH93{4C>Foly +zvxetQWK;E{h2z5tY%1Cnz2K^oWA^WlvcJYr%i0ahAf+T7I(db-6m0pq-~Kq8!3F9*_H7kL=NfwbWE`ZD4qjs*6M@&O02>nCM859zG^B`ch3`tx +zxo-=VSbk)r7z^MFqu0MJdh)6mTDk*{oF5+%Bb`OuP5bdZQMh_G&Wo67#Tbh#mFIkW +zQhzdh0Y)uG;Dbi1NjQp#0RP=s)T`n}i3OOv&PF*dh!@~g9fq42OU4%7R61juS3Tpf +zXHHnv6vdstliFq{#Wp=@NX8=OvCCHBW15%jlyjgZaBzZih?~BZ6o-9nWDmji7B7i+ +z&gcygIy3)pm|9&_bjREpymc>%`76@Ar}rt}nh*ZK*;`zXy6TOyT?0mSl{0{C&09 +zoRV{u<(rDl6@$Eeyhm`OiGzSgQ>r%tjj+*oszDWA`}Z2ezdzPgJ6hW}mQaq?uE!8t +zx5ZnDUryC;rOqlzQA|`*xI*x&*a<%v$14DshnN8Eq(GoVD~Bur=j7?x`MvK<^1OU` +zP?_xy_<;d3(9e+x@81SnpTTQt{ndUIk!ai~^lQ>X#6}yKQak4d26$;q;TdDMF#5B6 +z=MB|{*8u-))GZR>7@8 +ziQXlvyx?o&XJxYJVq#^MFhK%tM1KZ@Mu>^;jD;hRUR}jN1o^-KHAKx>sG<27h&h!r +zF#G)gvgl~@aHRzl7RQY#$YEFFONxUGF)T4ZfOoetd}n~(Y5Zkvgu0gl?ynq&*~A1g +z8kT0gHZrMr)qeO9DCwM3u?84<=cG1HU5j!G?7N%&>Qg0z(&ZG%B-R_0S`xmwD2(Gj@iFVK-8+i(R% +zKYH~Ly!i2C2;$|l28b{fz_N6BenPDlPnHlD+-G65KgD|vc<@|M{wIulQtPjla0fu0 +zd3rgmQZ(?IE%jH)wtyDB9|30&?)ix-U5bIo&lcVrz||T`5mA~S1U-VZOdT-LQkH~$ +zQJseiIRrisUivwS(;!NsW+^R#4AiKQf%PUr=Q*0Z&+IU))!lghLi`xP+Y$@@YxQgy56Jq)ByPevmNQ!L)Fg +zV0y)G +z?N@l8qVn@8;Z=v`SJ&Ui#RU$`8Vxgbc#k?Yzna?1mpnis2#D=37X|HaD5`6R=rxaD +zOo{dky7Ke^&nUsVyb@$_q`Dj(1i1{EeLy(!rEVWe-LX3Ci`4s+SdIhk!uYcCGU;U+ +z8~PYPmd#yLALNfQw=_(~vr{;0V6a-|g0fTqbPB9LOZCx~B3q1CP%+wMfc1Ns7V%}W +zUi2F32{9=WVBxR(Gjd4-Yz}lqUKD!D;Pe~~aQgG;JbRG+irbuS1o!x4nuU+a?MyiFIqDxr&>nW2B$e$3X_$h#Hb>DgMov%gk`n}3x +z{cZi0uJuImu8qb-v&zK7V`C4)0c09}g76!T9}pmMBozrS9Hx<{1=4b)4x~<`E~FSz +z1SyKtgw%}WA~{GNQXDCPltfyFltIcO<&g478j_A=A{j^)l8sbADk8NZwIg9XX&T20 +zqyVWKsRapRO!pwAkkUv#QY(jhi-b1UA-@hd*8!eEK7)D8U>-B{jKe2>k1*pgeLsG> +zaJ$0vnJ8dSRcE4#y5H7yrk$tmw>Xlbv-}G>6McY9ea2zxj3bZ~eI`O}gfe4;*=^UT +zw<{_Vo?V8VBWa-X7UYUL<0`-!;no#|gkn>N(%(V5k&vg<4)6G_+iTNvMUHWK=F +z9#!!h5F{1&w<$9gQ)UdLW}IFb`o*stux3cQhG*nha|Sy2kqOOdB7b1vo&zN9{^GygTrAMH|Y=#wim +z9Q^YzN8+EykuaXLr89R9G!-Nhd<8FUMVX0#z6HLt@6-vNi75)!S7*vy>VDv|{4e$W +zW(+BU959zGsYMrH@1TLPl=rh-W +z^b*F0Ik%&~_6K#gJd3{2PsfFrs|`K~H&tT1F3?%S)V7dHN&`9H~nlp)+VC5E=<$F2j7Ni)1RZqY}^!^re!^H +zpKE9${L?I#FMrYI+D2o*_^DyMT^ORaBF{TghNTtSFWD34w~83{TvKl>aut+)WLK(L +zTdrklifcuTNSlE#BN{cLO-A^&1Y9fxwARzP#$8S5+=%ixk7+AYm)~PqO?VM5u|m!7 +z$sD%1ZYM;f_Gr@K%XgcWd7jZ~UvT-8dcpWu+>Mw~OT(Sc&OXelM|a(5+>NFT-BV4? +zJp`Oz+csBCu3@$ueVMC;?tq+#3q)v$_O^DGRc&%}3|EBK%QansfkW;zf~-imcwu4l(0jvK+KV-d{&J0fw*3G9>^ +zi8@VKByB^)!^?V_W!VY4y~$}#YEe_Oqh}em8{>|}qdee_7U#O&5@=XgLk#d>gUb2& +zs8Ty11c4doiH>9<+7xqAg(i2E*=uG^bD7ZVpQ7#9!iCIO*8I9nx~_M(AP{Tlwv)8X +zW$4bd4MUG<8N-dPcTKO$IKyy#!!RsAZLVs$C}OpkMbnF?mNnU?@8n~x7T$|Wc&5F~ +zT45Ol-NalC+s-+TW|~pm&3K-vdudz(nY!sF;s(mwB9_@?MP0YU5w@dVYq$1_2u`@k +zW+%{1VT-6}HX;!;&>AvlM0AK7eb=+_;SJxm9yi<;zYrI(cr+ICEXb0BUynr{!^MDX +zZ_seiyBmwTS`rgCF=NZclr((!#$t{W$7|q` +zNV5?bcB_xU^jVnovS`GMx`vfBGp=Q8{br`o&WNU)n(P+4$<@8sGCLY|Z7b@TZjnZb +zakg2luHz+RXDyG|u|zcD1HpAtp6=Qa$3k*!TbH`QvoVKITN;?8>$t6vXe?n{wxJbt+f>D{l>dZz19AdS`Lh#Oy}pPPl5KVYO&6DTyRn#d +z(Zw$QB2Aa1ENg|G^bU^jtVoHSZ2G4W;LQ(F%{}BVc~ZQW}>qVJE_I6Be7Vs +z7I&?9tk-ci;1`%Mtq2%e@F`$yPbdj|PYaHWPYV^9IxP@jy^{AMnoKAP+oc?5WRYPX +z+1>`MDr~9&3k5&EY++Ht!7n}U<-P1M!MdV!0*(<3C4V;Hmo|ws@ +zmdF`vCST0v0l9My7v$L?k;4~J{y;uoR5?j5U`+WPd3zo=$>EDDC&}kaC@0A!Y*J2= +zSJhLChn7tUn+If6UxMDS~y@l_ +zwuir4xjKaPuk%~^7802nw|e=l?5wcdx*l}?ybk{a@V7(Q{ygA!hOn~?@I7_-QNZ|N +zF41wm0Qm1i*q!6gsh5Uu><1{9!dc_7=Ky~uEcfmJytxj)0Qjm9j-Lhi=OLU}hB-

3pD{$?G17O-81iRQKFS*h{na{-S7=72u|xFf`Aeg<%zCrO&u +zcvzl%4?nCVL)ib&V!8hse*%{m_^a`jtAX>45Kgu6ui`pFmZv_-^0{|XpC4kr4!4!~`7_#(jVb$9|WL{H)z04#SK@V^Ln +zuwMQW;44Eoe;)sAqiudGU)xyg{C$9(I?ls@SJmMcmX!Yz+Jd$(#?xlK5zRef1t5m?fq&x#9>zZWbBDL6#td-HyEcSy~ +zhN*O)qZUGux0LS7K&O-NZKeBW(2?TfDBb%o6*(AsWC;3rS`izwYstG#fy@fTIP +zzoDLiyCeL?lBw)-9N+4rfeHmx?fhUaBNWe*O7N0$JB8uZN}8EBkMuuQ{q7P +zzo{N>Lh)DQJxy@mr64FuPcM3x)VR{KssXD?&$)OT>22e8u!B@?DZTTcBL&1(dY{Iu>#NZFJ-|i6ag;vBKaJZl{JBbB +z6!2DpBT64}48QoNG576PSJ#D?;Yb3;$FSlvY+Arf%_z!A*vXmDPR_ti3OtEvQJe1j +zC3D%XBoA@8VT>Kfz +z${m1ZTT@y2L3K^IVwSS<2v#OaIJUC#QH)*Ebd;4(@ROl5xys5P@eW)8>?sKYLAd^{e0nt34GysEqkvy6ij +zFpr~Em+~s06TDltJPrv7d!cV&@ZMUD_al|~+58+luR;4Yd@WxGgLM(_=j-_ud=u(7 +z^SAS@wHj*I^BsIWFn93^-wSiJkG~t=GyD#I7eB}k0Xi%xe}w+e2m0gv)KAzOpd_)-2@z83W}^80a6$EeWrUi7~YeIMgbpuexe_o(r&@o(~PqwKr{Lq|M}A)DTZ`@1x_B~ui>+f|ABWPy~ak79$$yNUv0*mjuIbKOIfQtrR~VyukC1CtMqHfz4vR!^GtbM +zJKn~$(YzRK +z(?>5GRR=wFbgh9x&m6pPhJk3mr=z)gEYC+Rl#hDaj(TJbG-@*^xhc +zhNC9mkCcz>=x-f8wr;IHc&y9^X<)CYBTuO#kE&HgR>WC*s2h_{*+UT*hNS-rpcCi`nKLEIX +Bd{qDd + +literal 0 +HcmV?d00001 + +diff --git a/base/tps/shared/conf/CS.cfg b/base/tps/shared/conf/CS.cfg +index 2e5d499..7a01052 100644 +--- a/base/tps/shared/conf/CS.cfg ++++ b/base/tps/shared/conf/CS.cfg +@@ -11,10 +11,11 @@ applet._002=# SAF Key: + applet._003=# applet.aid.cardmgr_instance=A0000001510000 + applet._004=# Stock RSA,KeyRecover applet : 1.4.58768072.ijc + applet._005=# RSA/KeyRecovery/GP211/SCP02, SCP03 applet : 1.5.558cdcff.ijc +-applet._006=# Use GP211 applet only with SCP02 card +-applet._007=# For protocol > 1 do this ex: proto 3 : op.format.userKey.update.applet.requiredVersion.prot.3=1.5.558cdcff +-applet._008=# Use existing config for standard proto1 cards ex: op.format.userKey.update.applet.requiredVersion=1.4.58768072 +-applet._008=######################################### ++applet._006=# SCP03 AES server side keygen keywrap applet : 1.5.64260792.ijc ++applet._007=# Use GP211 applet only with SCP02 card ++applet._008=# For protocol > 1 do this ex: proto 3 : op.format.userKey.update.applet.requiredVersion.prot.3=1.5.558cdcff, 1.5.64260792.ijc for AES keywrap ++applet._009=# Use existing config for standard proto1 cards ex: op.format.userKey.update.applet.requiredVersion=1.4.58768072 ++applet._010=######################################### + applet.aid.cardmgr_instance=A0000000030000 + applet.aid.netkey_file=627601FF0000 + applet.aid.netkey_instance=627601FF000000 +diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java +index 7369e58..8cebe39 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java ++++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java +@@ -46,6 +46,7 @@ import org.dogtagpki.tps.apdu.ReadObjectAPDU; + import org.dogtagpki.tps.apdu.SetIssuerInfoAPDU; + import org.dogtagpki.tps.apdu.SetPinAPDU; + import org.dogtagpki.tps.apdu.WriteObjectAPDU; ++import org.dogtagpki.tps.apdu.ReadBufferAPDU; + import org.dogtagpki.tps.main.TPSBuffer; + import org.dogtagpki.tps.main.TPSException; + import org.dogtagpki.tps.main.Util; +@@ -73,8 +74,6 @@ public class SecureChannel { + private PK11SymKey cmacSessionKey; + //Used for security level we do not yet suport. + +- +- + private PK11SymKey rmacSessionKey; + private PK11SymKey dekSessionKey; + +@@ -85,8 +84,13 @@ public class SecureChannel { + + private TPSBuffer drmDesKey; + ++ private TPSBuffer drmAesKey; ++ private TPSBuffer aesDesKey; ++ ++ + //SCP01 kek key + private TPSBuffer kekDesKey; ++ private TPSBuffer kekAesKey; + private TPSBuffer keyCheck; + private TPSBuffer keyDiversificationData; + private TPSBuffer cardChallenge; +@@ -1596,6 +1600,22 @@ public class SecureChannel { + this.drmDesKey = drmDesKey; + } + ++ public void setDrmWrappedAesKey(TPSBuffer drmAesKey) { ++ this.drmAesKey = drmAesKey; ++ } ++ ++ public TPSBuffer getDRMWrappedAesKey() { ++ return drmAesKey; ++ } ++ ++ public void setAESWrappedDesKey(TPSBuffer aesDesKey) { ++ this.aesDesKey = aesDesKey; ++ } ++ ++ public TPSBuffer getAESWrappedDesKey() { ++ return aesDesKey; ++ } ++ + public TPSBuffer getKeyCheck() { + return keyCheck; + } +@@ -1626,6 +1646,25 @@ public class SecureChannel { + + } + ++ public TPSBuffer readIOBuffer(int offset, int length) throws IOException, TPSException { ++ String method = "SecureChannel.readIOBuffer"; ++ ++ ReadBufferAPDU readIO = new ReadBufferAPDU (length,offset); ++ computeAPDU(readIO); ++ APDUResponse respApdu= processor.handleAPDURequest(readIO); ++ ++ if (!respApdu.checkResult()) { ++ CMS.debug(method + " problem reading IOBuffer!"); ++ //Keep going since this is not crucial to server operation, debug only,when supported by applet. ++ return null; ++ } ++ TPSBuffer ioBuffData = respApdu.getData(); ++ // use this method only for debugging the applet, by feault this apdu in the applet is not allowed. ++ //CMS.debug(method + " returning: " + ioBuffData.toHexString()); ++ return ioBuffData; ++ ++ } ++ + public TPSBuffer getKekDesKey() { + return kekDesKey; + } +@@ -1634,6 +1673,14 @@ public class SecureChannel { + this.kekDesKey = kekDesKey; + } + ++ public void setKekAesKey(TPSBuffer kekAesKey) { ++ this.kekAesKey = kekAesKey; ++ } ++ ++ public TPSBuffer getKekAesKey() { ++ return kekAesKey; ++ } ++ + public TPSBuffer getSequenceCounter() { + return sequenceCounter; + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java +index 3674526..f8491fa 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java ++++ b/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java +@@ -54,6 +54,7 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + * @param cuid is the token id + * @param userid is the user id + * @param sDesKey is the des key provided by the TKS for key encryption ++ * @param sAesKey is the aes key provided by the TKS to wrap another key + * @param archive true or false + * + * @returns KRAServerSideKeyGenResponse +@@ -64,6 +65,7 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + String cuid, + String userid, + String sDesKey, ++ String sAesKey, + boolean archive) + throws EBaseException { + +@@ -105,7 +107,9 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + "&" + IRemoteRequest.KRA_KEYGEN_EC_KeyCurve + "=" + + eckeycurve + + "&" + IRemoteRequest.KRA_Trans_DesKey + "=" + +- sDesKey; ++ sDesKey + ++ "&" + IRemoteRequest.KRA_Trans_AesKey + "=" + ++ sAesKey; + + //CMS.debug("KRARemoteRequestHandler: outgoing request for ECC: " + request); + +@@ -125,7 +129,9 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + "&" + IRemoteRequest.KRA_KEYGEN_KeySize + "=" + + keysize + + "&" + IRemoteRequest.KRA_Trans_DesKey + "=" + +- sDesKey; ++ sDesKey + ++ "&" + IRemoteRequest.KRA_Trans_AesKey + "=" + ++ sAesKey; ; + + //CMS.debug("KRARemoteRequestHandler: outgoing request for RSA: " + request); + +@@ -220,7 +226,8 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + * + * @param cuid is the token id + * @param userid is the user id +- * @param sDesKey is the des key provided by the TKS for key encryption ++ * @param sDesKey is the des key provided by the TKS for key encryption (SCP01) ++ * @param aAesKey is the aes key provided by the TKS for key encryption (SCP03) + * @param b64cert is the Base64 encoding of a certificate used to recover + * + * @returns KRARecoverKeyResponse +@@ -229,15 +236,17 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + String cuid, + String userid, + String sDesKey, ++ String sAesKey, + String b64cert) + throws EBaseException { +- return recoverKey(cuid, userid, sDesKey, b64cert, BigInteger.valueOf(0)); ++ return recoverKey(cuid, userid, sDesKey,sAesKey, b64cert, BigInteger.valueOf(0)); + } + + public KRARecoverKeyResponse recoverKey( + String cuid, + String userid, + String sDesKey, ++ String sAesKey, + String b64cert, + BigInteger keyid) + throws EBaseException { +@@ -246,7 +255,7 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + if (b64cert == null && keyid == BigInteger.valueOf(0)) { + throw new EBaseException("KRARemoteRequestHandler: recoverKey(): one of b64cert or kid has to be a valid value"); + } +- if (cuid == null || userid == null || sDesKey == null) { ++ if (cuid == null || userid == null) { + throw new EBaseException("KRARemoteRequestHandler: recoverKey(): input parameter null."); + } + +@@ -263,6 +272,16 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + + String sendMsg = null; + try { ++ String desPart = " "; ++ String aesPart = " "; ++ ++ if(sDesKey != null) { ++ desPart = "&" + IRemoteRequest.KRA_Trans_DesKey + "=" + sDesKey; ++ } ++ if(sAesKey != null) { ++ aesPart = "&" + IRemoteRequest.KRA_Trans_AesKey + "=" + sAesKey; ++ } ++ + if (b64cert != null) { // recover by cert + // CMS.debug("KRARemoteRequestHandler: recoverKey(): uriEncoded cert= " + b64cert); + sendMsg = IRemoteRequest.TOKEN_CUID + "=" + +@@ -270,9 +289,8 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + "&" + IRemoteRequest.KRA_UserId + "=" + + userid + + "&" + IRemoteRequest.KRA_RECOVERY_CERT + "=" + +- b64cert + +- "&" + IRemoteRequest.KRA_Trans_DesKey + "=" + +- sDesKey; ++ b64cert + desPart + aesPart; ++ + } else if (keyid != BigInteger.valueOf(0)) { // recover by keyid ... keyid != BigInteger.valueOf(0) + CMS.debug("KRARemoteRequestHandler: recoverKey(): keyid = " + keyid); + sendMsg = IRemoteRequest.TOKEN_CUID + "=" + +@@ -280,9 +298,8 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + "&" + IRemoteRequest.KRA_UserId + "=" + + userid + + "&" + IRemoteRequest.KRA_RECOVERY_KEYID + "=" + +- keyid.toString() + +- "&" + IRemoteRequest.KRA_Trans_DesKey + "=" + +- sDesKey; ++ keyid.toString() + desPart + aesPart; ++ + } + } catch (Exception e) { + CMS.debug("KRARemoteRequestHandler: recoverKey(): uriEncode failed: " + e); +diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java +index 910294e..c30e3f0 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java ++++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java +@@ -51,6 +51,10 @@ public class TKSComputeSessionKeyResponse extends RemoteResponse + return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey); + } + ++ public TPSBuffer getDRM_Trans_AesKey() { ++ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey); ++ } ++ + public TPSBuffer getKeyCheck() { + return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KeyCheck); + } +@@ -63,6 +67,10 @@ public class TKSComputeSessionKeyResponse extends RemoteResponse + return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KEK_DesKey); + } + ++ public TPSBuffer getKekWrappedAesKey() { ++ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KEK_AesKey); ++ } ++ + public TPSBuffer getKekSessionKey() { + return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KekSessionKey); + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java +index 770819d..540f713 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java ++++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java +@@ -205,6 +205,15 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler + response.put(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey, Util.specialDecode(value)); + } + ++ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey); ++ if (value == null) { ++ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " + ++ IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey); ++ } else { ++ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey "); ++ response.put(IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey, Util.specialDecode(value)); ++ } ++ + value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KEK_DesKey); + if (value == null) { + CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " + +@@ -213,6 +222,14 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler + CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_KEK_DesKey"); + response.put(IRemoteRequest.TKS_RESPONSE_KEK_DesKey, Util.specialDecode(value)); + } ++ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KEK_AesKey); ++ if (value == null) { ++ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " + ++ IRemoteRequest.TKS_RESPONSE_KEK_AesKey); ++ } else { ++ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_KEK_AesKey"); ++ response.put(IRemoteRequest.TKS_RESPONSE_KEK_AesKey, Util.specialDecode(value)); ++ } + + value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KeyCheck); + if (value == null) { +@@ -344,6 +361,15 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler + response.put(IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey, Util.specialDecode(value)); + } + ++ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey); ++ if (value == null) { ++ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): response missing name-value pair for: " + ++ IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey); ++ } else { ++ CMS.debug("TKSRemoteRequestHandler: computeSessionKey(): got IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey "); ++ response.put(IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey, Util.specialDecode(value)); ++ } ++ + value = (String) response.get(IRemoteRequest.TKS_RESPONSE_MacSessionKey); + if (value == null) { + CMS.debug(method + "response missing name-value pair for: " + +@@ -373,6 +399,16 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler + response.put(IRemoteRequest.TKS_RESPONSE_KEK_DesKey, Util.specialDecode(value)); + + } ++ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KEK_AesKey); ++ if (value == null) { ++ CMS.debug(method + "response missing name-value pair for: " + ++ IRemoteRequest.TKS_RESPONSE_KEK_AesKey); ++ } else { ++ CMS.debug(method + " got IRemoteRequest.TKS_RESPONSE_KEK_AesKey"); ++ response.put(IRemoteRequest.TKS_RESPONSE_KEK_AesKey, Util.specialDecode(value)); ++ ++ } ++ + + value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KeyCheck); + +diff --git a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java +index cc9b463..be2976d 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java ++++ b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java +@@ -523,16 +523,17 @@ public class TPSEngine { + + public KRARecoverKeyResponse recoverKey(String cuid, + String userid, +- TPSBuffer sDesKey, ++ TPSBuffer drmWrappedDesKey, TPSBuffer drmWrappedAesKey, + String b64cert, String drmConnId) throws TPSException { + +- return this.recoverKey(cuid, userid, sDesKey, b64cert, drmConnId, BigInteger.valueOf(0)); ++ return this.recoverKey(cuid, userid, drmWrappedDesKey, drmWrappedAesKey, ++ b64cert, drmConnId, BigInteger.valueOf(0)); + + } + + public KRARecoverKeyResponse recoverKey(String cuid, + String userid, +- TPSBuffer sDesKey, ++ TPSBuffer drmWrappedDesKey,TPSBuffer drmWrappedAesKey, + String b64cert, String drmConnId,BigInteger keyid) throws TPSException { + String method = "TPSEngine.recoverKey"; + CMS.debug("TPSEngine.recoverKey"); +@@ -540,14 +541,16 @@ public class TPSEngine { + CMS.debug(method + ": cuid null"); + else if (userid == null) + CMS.debug(method + ": userid null"); +- else if (sDesKey == null) +- CMS.debug(method + ": isDesKey null"); ++ else if (drmWrappedDesKey == null) ++ CMS.debug(method + ": drmWrappedDesKey null"); ++ else if (drmWrappedAesKey == null) ++ CMS.debug(method + ": drmWrappedAesKey null"); + else if (b64cert == null) + CMS.debug(method + ": b64cert null"); + else if (drmConnId == null) + CMS.debug(method + ": drmConnId null"); + +- if (cuid == null || userid == null || sDesKey == null || drmConnId == null) { ++ if (cuid == null || userid == null || drmConnId == null) { + throw new TPSException("TPSEngine.recoverKey: invalid input data!", TPSStatus.STATUS_ERROR_RECOVERY_FAILED); + } + +@@ -557,7 +560,17 @@ public class TPSEngine { + try { + kra = new KRARemoteRequestHandler(drmConnId); + +- resp = kra.recoverKey(cuid, userid, Util.specialURLEncode(sDesKey), (b64cert != null) ? Util.uriEncode(b64cert) : b64cert,keyid); ++ String encodedDes = null; ++ String encodedAes = null; ++ ++ if(drmWrappedDesKey != null) ++ encodedDes = Util.specialURLEncode(drmWrappedDesKey); ++ if(drmWrappedAesKey != null) ++ encodedAes = Util.specialURLEncode(drmWrappedAesKey); ++ ++ resp = kra.recoverKey(cuid, userid, encodedDes, ++ encodedAes, ++ (b64cert != null) ? Util.uriEncode(b64cert) : b64cert,keyid); + } catch (EBaseException e) { + throw new TPSException("TPSEngine.recoverKey: Problem creating or using KRARemoteRequestHandler! " + + e.toString(), TPSStatus.STATUS_ERROR_RECOVERY_FAILED); +@@ -595,7 +608,7 @@ public class TPSEngine { + } + + public KRAServerSideKeyGenResponse serverSideKeyGen(int keySize, String cuid, String userid, String drmConnId, +- TPSBuffer wrappedDesKey, ++ TPSBuffer wrappedDesKey, TPSBuffer drmWrappedAesKey, + boolean archive, + boolean isECC) throws TPSException { + +@@ -605,7 +618,7 @@ public class TPSEngine { + + " isECC: " + isECC); + */ + +- if (cuid == null || userid == null || drmConnId == null || wrappedDesKey == null) { ++ if (cuid == null || userid == null || drmConnId == null || ( wrappedDesKey == null && drmWrappedAesKey == null)) { + throw new TPSException("TPSEngine.serverSideKeyGen: Invalid input data!", + TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU); + } +@@ -617,7 +630,9 @@ public class TPSEngine { + kra = new KRARemoteRequestHandler(drmConnId); + + resp = kra.serverSideKeyGen(isECC, keySize, cuid, userid, +- Util.specialURLEncode(wrappedDesKey), archive); ++ (wrappedDesKey != null) ? Util.specialURLEncode(wrappedDesKey) : "", ++ (drmWrappedAesKey != null) ? Util.specialURLEncode(drmWrappedAesKey) : "", ++ archive); + + } catch (EBaseException e) { + throw new TPSException("TPSEngine.serverSideKeyGen: Problem creating or using KRARemoteRequestHandler! " +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +index 2d8c89f..adc8760 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +@@ -1409,10 +1409,12 @@ public class TPSEnrollProcessor extends TPSProcessor { + logMsg = "channel.getDRMWrappedDesKey() not null"; + CMS.debug(method + logMsg); + } ++ TPSBuffer drmDesKey = getDRMDesKeyByProtocol(channel); ++ TPSBuffer drmAesKey = getDRMAesKeyByProtocol(channel); + + keyResp = tps.getEngine().recoverKey(cuid, + userid, +- channel.getDRMWrappedDesKey(), ++ drmDesKey,drmAesKey, + getExternalRegRecoverByKeyID() ? null : b64cert, + kraConn, keyid); + +@@ -1683,9 +1685,14 @@ public class TPSEnrollProcessor extends TPSProcessor { + String b64cert = certResponse.getCertB64(); + CMS.debug("TPSEnrollProcessor.processRecovery: cert blob recovered"); + ++ TPSBuffer drmDesKey = getDRMDesKeyByProtocol(channel); ++ TPSBuffer drmAesKey = getDRMAesKeyByProtocol(channel); ++ + KRARecoverKeyResponse keyResponse = tps.getEngine().recoverKey(toBeRecovered.getId(), + toBeRecovered.getUserID(), +- channel.getDRMWrappedDesKey(), b64cert, getDRMConnectorID(toBeRecovered.getKeyType())); ++ drmDesKey, ++ drmAesKey, ++ b64cert, getDRMConnectorID(toBeRecovered.getKeyType())); + + //Try to write recovered cert to token + +@@ -2027,9 +2034,13 @@ public class TPSEnrollProcessor extends TPSProcessor { + //CMS.debug("TPSEnrollProcessor.processRecovery: recoverd cert blob: " + b64cert); + CMS.debug("TPSEnrollProcessor.processRecovery: cert blob recovered"); + ++ TPSBuffer drmDesKey = getDRMDesKeyByProtocol(channel); ++ TPSBuffer drmAesKey = getDRMAesKeyByProtocol(channel); ++ + KRARecoverKeyResponse keyResponse = tps.getEngine().recoverKey(toBeRecovered.getId(), + toBeRecovered.getUserID(), +- channel.getDRMWrappedDesKey(), b64cert, getDRMConnectorID(certToRecover.getKeyType())); ++ drmDesKey,drmAesKey, ++ b64cert, getDRMConnectorID(certToRecover.getKeyType())); + + CertEnrollInfo cEnrollInfo = new CertEnrollInfo(); + +@@ -2475,9 +2486,12 @@ public class TPSEnrollProcessor extends TPSProcessor { + String publicKeyStr = null; + //Do this for JUST server side keygen + if (isRecovery == false) { ++ TPSBuffer drmDesKey = getDRMDesKeyByProtocol(channel); ++ TPSBuffer drmAesKey = getDRMAesKeyByProtocol(channel); ++ + ssKeyGenResponse = getTPSEngine() + .serverSideKeyGen(cEnrollInfo.getKeySize(), +- aInfo.getCUIDhexStringPlain(), userid, kraConnId, channel.getDRMWrappedDesKey(), ++ aInfo.getCUIDhexStringPlain(), userid, kraConnId, drmDesKey,drmAesKey, + archive, isECC); + + publicKeyStr = ssKeyGenResponse.getPublicKey(); +@@ -3129,8 +3143,12 @@ public class TPSEnrollProcessor extends TPSProcessor { + TPSStatus.STATUS_ERROR_MAC_ENROLL_PDU); + + } +- ++ TPSBuffer kekWrappedAESKey = channel.getKekAesKey(); + TPSBuffer kekWrappedDesKey = channel.getKekDesKey(); ++ TPSBuffer kekWrappedKey = null; ++ if(kekWrappedAESKey != null) { ++ CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8 : kekWrappedAesKey provided."); ++ } + + if (kekWrappedDesKey != null) { + // CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: keyWrappedDesKey: " + kekWrappedDesKey.toHexString()); +@@ -3140,15 +3158,23 @@ public class TPSEnrollProcessor extends TPSProcessor { + + byte alg = (byte) 0x80; + if (kekWrappedDesKey != null && kekWrappedDesKey.size() > 0) { ++ kekWrappedKey = kekWrappedDesKey; + alg = (byte) 0x81; + } + ++ //Give preference to AES kek wrapped key for SCP03, otherwise go with DES for SCP01 ++ if(kekWrappedAESKey != null && kekWrappedAESKey.size() > 0 && channel.isSCP03()) { ++ alg = (byte) 0x88; ++ kekWrappedKey = kekWrappedAESKey; ++ } ++ ++ CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8 : kek wrapped key outgoing: size: " + kekWrappedKey.size()); + TPSBuffer data = new TPSBuffer(); + + data.add(objIdBuff); + data.add(alg); +- data.add((byte) kekWrappedDesKey.size()); +- data.add(kekWrappedDesKey); ++ data.add((byte) kekWrappedKey.size()); ++ data.add(kekWrappedKey); + data.add((byte) keyCheck.size()); + if (keyCheck.size() > 0) { + data.add(keyCheck); +@@ -3919,4 +3945,33 @@ public class TPSEnrollProcessor extends TPSProcessor { + public static void main(String[] args) { + } + ++ private TPSBuffer getDRMDesKeyByProtocol(SecureChannel channel) { ++ ++ String method = "TPSEnrollProcessor.getDRMDesKeyByProtocol: "; ++ int prot = getProtocol(); ++ TPSBuffer drmDesKey = null; ++ ++ CMS.debug(method + " protocol: " + prot); ++ ++ if(prot == 1) ++ drmDesKey = channel.getDRMWrappedDesKey(); ++ ++ return drmDesKey; ++ } ++ ++ private TPSBuffer getDRMAesKeyByProtocol(SecureChannel channel) { ++ ++ String method = "TPSEnrollProcessor.getDRMAesKeyByProtocol: "; ++ ++ int prot = getProtocol(); ++ TPSBuffer drmAesKey = null; ++ ++ CMS.debug(method + " protocol: " + prot); ++ ++ if(prot == 3) ++ drmAesKey = channel.getDRMWrappedAesKey(); ++ ++ return drmAesKey; ++ } ++ + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +index cadab1d..8c4d80e 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +@@ -803,11 +803,17 @@ public class TPSProcessor { + + TPSBuffer drmDesKey = null; + TPSBuffer kekDesKey = null; ++ TPSBuffer kekAesKey = null; + TPSBuffer keyCheck = null; ++ TPSBuffer drmAesKey = null; + + drmDesKey = resp.getDRM_Trans_DesKey(); + keyCheck = resp.getKeyCheck(); + kekDesKey = resp.getKekWrappedDesKey(); ++ kekAesKey = resp.getKekWrappedAesKey(); ++ ++ drmAesKey = resp.getDRM_Trans_AesKey(); ++ //CMS.debug("drmAesKey " + drmAesKey); + + if (checkServerSideKeyGen(connId)) { + CMS.debug("TPSProcessor.generateSecureChannel: true for checkServerSideKeyGen"); +@@ -823,6 +829,10 @@ public class TPSProcessor { + kekDesKey, keyCheck, keyDiversificationData, cardChallenge, + cardCryptogram, hostChallenge, hostCryptogram, keyInfoData, platProtInfo); + ++ //CMS.debug(" drm wrapped aes key: " + drmAesKey.toHexString()); ++ channel.setDrmWrappedAesKey(drmAesKey); ++ channel.setKekAesKey(kekAesKey); ++ + } catch (Exception e) { + CMS.debug(e); + e.printStackTrace(); +@@ -940,6 +950,8 @@ public class TPSProcessor { + + TPSBuffer drmDesKeyBuff = resp.getDRM_Trans_DesKey(); + TPSBuffer kekDesKeyBuff = resp.getKekWrappedDesKey(); ++ TPSBuffer kekAesKeyBuff = resp.getKekWrappedAesKey(); ++ TPSBuffer drmAesKeyBuff = resp.getDRM_Trans_AesKey(); + + // if (encSessionKeyBuff != null) + // CMS.debug(method + " encSessionKeyBuff: " + encSessionKeyBuff.toHexString()); +@@ -984,6 +996,9 @@ public class TPSProcessor { + keyCheckBuff, keyDiversificationData, cardChallenge, + cardCryptogram, hostChallenge, hostCryptogramBuff, keyInfoData, + platProtInfo); ++ ++ channel.setDrmWrappedAesKey(drmAesKeyBuff); ++ channel.setKekAesKey(kekAesKeyBuff); + } + + if (channel == null) { +diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +index a10c6aa..479087f 100644 +--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java ++++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +@@ -191,6 +191,32 @@ public class CryptoUtil { + + public static final int LINE_COUNT = 76; + ++ private static SymmetricKey.Usage sess_key_usages[] = { ++ SymmetricKey.Usage.WRAP, ++ SymmetricKey.Usage.UNWRAP, ++ SymmetricKey.Usage.ENCRYPT, ++ SymmetricKey.Usage.DECRYPT ++ }; ++ ++ //nCipher (v. 12.60+) wrapping/unwrapping keys requirements ++ public final static org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage RSA_KEYPAIR_USAGES[] = { ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.ENCRYPT, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DECRYPT, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.WRAP, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.UNWRAP, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER ++ }; ++ ++ public final static org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage RSA_KEYPAIR_USAGES_MASK[] = { ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.ENCRYPT, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DECRYPT, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.WRAP, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.UNWRAP, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN, ++ org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER ++ }; ++ + static public final Integer[] clientECCiphers = { + /* + SSLSocket.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, +@@ -227,6 +253,44 @@ public class CryptoUtil { + "sect131r1", "sect131r2" + }; + ++ /* DES KEY Parity conversion table. Takes each byte >> 1 as an index, returns ++ * that byte with the proper parity bit set*/ ++ private static final int parityTable[] = ++ { ++ /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */ ++ /* E */0x01, 0x02, 0x04, 0x07, 0x08, 0x0b, 0x0d, 0x0e, ++ /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */ ++ /* O */0x10, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 0x1f, ++ /* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */ ++ /* O */0x20, 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x2f, ++ /* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */ ++ /* E */0x31, 0x32, 0x34, 0x37, 0x38, 0x3b, 0x3d, 0x3e, ++ /* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */ ++ /* O */0x40, 0x43, 0x45, 0x46, 0x49, 0x4a, 0x4c, 0x4f, ++ /* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */ ++ /* E */0x51, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d, 0x5e, ++ /* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */ ++ /* E */0x61, 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x6e, ++ /* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */ ++ /* O */0x70, 0x73, 0x75, 0x76, 0x79, 0x7a, 0x7c, 0x7f, ++ /* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */ ++ /* O */0x80, 0x83, 0x85, 0x86, 0x89, 0x8a, 0x8c, 0x8f, ++ /* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */ ++ /* E */0x91, 0x92, 0x94, 0x97, 0x98, 0x9b, 0x9d, 0x9e, ++ /* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */ ++ /* E */0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xab, 0xad, 0xae, ++ /* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */ ++ /* O */0xb0, 0xb3, 0xb5, 0xb6, 0xb9, 0xba, 0xbc, 0xbf, ++ /* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */ ++ /* E */0xc1, 0xc2, 0xc4, 0xc7, 0xc8, 0xcb, 0xcd, 0xce, ++ /* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */ ++ /* O */0xd0, 0xd3, 0xd5, 0xd6, 0xd9, 0xda, 0xdc, 0xdf, ++ /* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */ ++ /* O */0xe0, 0xe3, 0xe5, 0xe6, 0xe9, 0xea, 0xec, 0xef, ++ /* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */ ++ /* E */0xf1, 0xf2, 0xf4, 0xf7, 0xf8, 0xfb, 0xfd, 0xfe, ++ }; ++ + + private final static HashMap> ecOIDs = new HashMap>(); + static { +@@ -2256,6 +2320,22 @@ public class CryptoUtil { + return kg.generate(); + } + ++ public static SymmetricKey generateKey(CryptoToken token, KeyGenAlgorithm alg, int keySize, ++ SymmetricKey.Usage[] usages, boolean temporary,boolean sensitive) throws Exception { ++ KeyGenerator kg = token.getKeyGenerator(alg); ++ if (usages != null) ++ kg.setKeyUsages(usages); ++ kg.sensitiveKeys(sensitive); ++ kg.temporaryKeys(temporary); ++ if (alg == KeyGenAlgorithm.AES || alg == KeyGenAlgorithm.RC4 ++ || alg == KeyGenAlgorithm.RC2) { ++ kg.initialize(keySize); ++ } ++ ++ return kg.generate(); ++ } ++ ++ + /** + * Compares 2 byte arrays to see if they are the same. + */ +@@ -2890,6 +2970,24 @@ public class CryptoUtil { + km.generateUniqueNamedKey(nickname); + } + ++ public static void createSharedSecret(String nickname, KeyGenAlgorithm alg, int keySize) ++ throws NotInitializedException, TokenException, Exception { ++ ++ logger.debug("CryptoUtil.createSharedSecret with alg and keysize"); ++ CryptoManager cm = CryptoManager.getInstance(); ++ CryptoToken token = cm.getInternalKeyStorageToken(); ++ ++ SymmetricKey sharedSecretKey = CryptoUtil.generateKey( ++ token, ++ alg, ++ keySize, ++ sess_key_usages, ++ false, cm.FIPSEnabled() /* sensitive */); ++ ++ sharedSecretKey.setNickName(nickname); ++ } ++ ++ + public static void deleteSharedSecret(String nickname) throws NotInitializedException, TokenException, + InvalidKeyException { + CryptoManager cm = CryptoManager.getInstance(); +@@ -2898,6 +2996,26 @@ public class CryptoUtil { + km.deleteUniqueNamedKey(nickname); + } + ++ public static SymmetricKey createAESSessionKeyOnInternal(int keySize) throws Exception { ++ ++ String method = "CryptoUtil.createAESSessionKeyOnInternal "; ++ logger.debug(method + "Entering... keySize: " + keySize); ++ ++ CryptoManager cm = CryptoManager.getInstance(); ++ CryptoToken token = cm.getInternalKeyStorageToken(); ++ KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.AES); ++ ++ SymmetricKey sessionKey = CryptoUtil.generateKey( ++ token, ++ KeyGenAlgorithm.AES, ++ keySize, ++ sess_key_usages, ++ true, cm.FIPSEnabled() /* sensitive */); ++ ++ ++ return sessionKey; ++ } ++ + // Return a list of two wrapped keys: + // first element: temp DES3 key wrapped by cert , + // second element: shared secret wrapped by temp DES3 key +@@ -2977,6 +3095,153 @@ public class CryptoUtil { + unwrappedSharedSecret.setNickName(sharedSecretNickname); + } + ++ ++ public static void importSharedSecretWithAES(byte[] wrappedSessionKey,byte[] wrappedSharedSecret,String subsystemCertNickname,String sharedSecretNickname) throws Exception, NotInitializedException, TokenException, ++ NoSuchAlgorithmException, ObjectNotFoundException, InvalidKeyException, InvalidAlgorithmParameterException, ++ IOException { ++ ++ CryptoManager cm = CryptoManager.getInstance(); ++ CryptoToken token = cm.getInternalKeyStorageToken(); ++ ++ String method = "CryptoUtil.importSharedSecretWithAES "; ++ logger.debug(method + " nickname: " + sharedSecretNickname); ++ ++ KeyManager km = new KeyManager(token); ++ if (km.uniqueNamedKeyExists(sharedSecretNickname)) { ++ throw new IOException("Shared secret " + sharedSecretNickname + " already exists"); ++ } ++ ++ //Unwrap session key ++ ++ KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA); ++ logger.debug(method + " subsytemCertNickname: " + subsystemCertNickname); ++ System.out.println(method + " subsytemCertNickname: " + subsystemCertNickname); ++ ++ X509Certificate cert = cm.findCertByNickname(subsystemCertNickname); ++ logger.debug(method + " subsystemCert: " + cert); ++ PrivateKey subsystemPrivateKey = cm.findPrivKeyByCert(cert); ++ keyWrap.initUnwrap(subsystemPrivateKey,null); ++ ++ SymmetricKey unwrappedSessionKey = null; ++ //Since we don't know if aes was used to wrap the key, try with and without. ++ ++ ++ try { ++ unwrappedSessionKey = keyWrap.unwrapSymmetric(wrappedSessionKey, SymmetricKey.AES, ++ 0); ++ } catch(Exception e) { ++ System.out.println(method + " exception found, " + e); ++ throw e; ++ } ++ ++ //Unwrap shared secret permanently with session key ++ EncryptionAlgorithm encAlg = EncryptionAlgorithm.AES_CBC_PAD; ++ int ivLen = encAlg.getIVLength(); ++ byte[] iv = new byte[ivLen]; ++ ++ IVParameterSpec ivsp = new IVParameterSpec(iv); ++ ++ byte[] unwrappedSharedSecret = decryptUsingSymmetricKey(token, ivsp, wrappedSharedSecret, ++ unwrappedSessionKey, encAlg); ++ SymmetricKey importedSharedSecret = unwrapAESSKeyFromBytes(token, unwrappedSharedSecret, true); ++ importedSharedSecret.setNickName(sharedSecretNickname); ++ } ++ ++ public static SymmetricKey unwrapAESSKeyFromBytes(CryptoToken token, byte[] inputKeyArray, ++ boolean isPerm) ++ throws Exception { ++ ++ byte[] finalInputKeyArray = inputKeyArray; ++ String method = "CryptoUtil.unwrapAESKeyFromBytes: "; ++ ++ logger.debug(method + "begins: isPerm: " + isPerm); ++ //for now assume 128 bits aes ++ if(inputKeyArray.length > 16) { ++ throw new Exception(method + "invalid input data size."); ++ } ++ ++ KeyGenerator kg; ++ SymmetricKey finalAESKey; ++ try { ++ kg = token.getKeyGenerator(KeyGenAlgorithm.AES); ++ ++ kg.setKeyUsages(sess_key_usages); ++ kg.temporaryKeys(true); ++ kg.initialize(128); ++ SymmetricKey tempKey = kg.generate(); ++ ++ Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC); ++ ++ int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength(); ++ byte[] iv = null; ++ ++ if (ivLength > 0) { ++ iv = new byte[ivLength]; ++ } ++ ++ encryptor.initEncrypt(tempKey, new IVParameterSpec(iv)); ++ byte[] wrappedKey = encryptor.doFinal(finalInputKeyArray); ++ ++ KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC); ++ keyWrap.initUnwrap(tempKey, new IVParameterSpec(iv)); ++ ++ if(isPerm) ++ finalAESKey = keyWrap.unwrapSymmetricPerm(wrappedKey, SymmetricKey.AES, 16); ++ else ++ finalAESKey = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.AES, 16); ++ ++ } catch (Exception e) { ++ throw new Exception(method + " Can't unwrap key onto token!"); ++ } ++ ++ return finalAESKey; ++ } ++ ++ public static List exportSharedSecretWithAES(String nickname, java.security.cert.X509Certificate wrappingCert, ++ SymmetricKey wrappingKey) throws Exception { ++ ++ CryptoManager cm = CryptoManager.getInstance(); ++ CryptoToken token = cm.getInternalKeyStorageToken(); ++ String method = "CrytoUtil.exportSharedSecret"; ++ List listWrappedKeys = new ArrayList(); ++ ++ logger.debug(method + " nickname: " + nickname); ++ ++ SymmetricKey sharedSecretKey = null; ++ ++ try { ++ sharedSecretKey = getSymKeyByName(token, nickname); ++ } catch (Exception e) { ++ logger.debug(method + " can't find shared secret: " + nickname); ++ throw new IOException("Shared secret " + nickname + " does not exist"); ++ } ++ ++ PublicKey pub = wrappingCert.getPublicKey(); ++ PK11PubKey pubK = PK11PubKey.fromSPKI(pub.getEncoded()); ++ ++ //Wrap the temp AES key with the cert ++ byte[] wrappedKey = wrapUsingPublicKey(token, pubK, wrappingKey, KeyWrapAlgorithm.RSA); ++ ++ listWrappedKeys.add(wrappedKey); ++ //Use the AES key to wrap the shared secret ++ ++ KeyWrapAlgorithm wrapAlg = KeyWrapAlgorithm.AES_CBC_PAD; ++ int ivLen = wrapAlg.getBlockSize(); ++ byte[] iv = new byte[ivLen]; ++ ++ IVParameterSpec ivsp = new IVParameterSpec(iv); ++ ++ byte[] wrappedSharedSecret = wrapUsingSymmetricKey(token, wrappingKey, sharedSecretKey, ivsp, wrapAlg); ++ ++ listWrappedKeys.add(wrappedSharedSecret); ++ ++ if (listWrappedKeys.size() != 2) { ++ throw new IOException("Can't write out shared secret data to export for nickname: " + nickname); ++ } ++ ++ return listWrappedKeys; ++ } ++ + public static SymmetricKey getSymKeyByName(CryptoToken token, String name) throws Exception { + + String method = "CryptoUtil.getSymKeyByName:"; +@@ -3114,6 +3379,56 @@ public class CryptoUtil { + return pk; + } + ++ // Testing only for use in dev / debugging if needed./ ++ public static SymmetricKey unwrapDESKeyFromBytes(CryptoToken token, byte[] inputKeyArray, ++ boolean isPerm) ++ throws Exception { ++ ++ String method = "CryptoUtil.unwrapDESKeyFromBytes: "; ++ ++ logger.debug(method + "begins: isPerm: " + isPerm); ++ if(inputKeyArray.length > 24) { ++ throw new Exception(method + "invalid input data size."); ++ } ++ ++ KeyGenerator kg; ++ SymmetricKey finalDESKey; ++ try { ++ kg = token.getKeyGenerator(KeyGenAlgorithm.AES); ++ ++ kg.setKeyUsages(sess_key_usages); ++ kg.temporaryKeys(true); ++ kg.initialize(128); ++ SymmetricKey tempKey = kg.generate(); ++ ++ Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC_PAD); ++ ++ int ivLength = EncryptionAlgorithm.AES_128_CBC_PAD.getIVLength(); ++ byte[] iv = null; ++ ++ if (ivLength > 0) { ++ iv = new byte[ivLength]; ++ } ++ ++ encryptor.initEncrypt(tempKey, new IVParameterSpec(iv)); ++ byte[] wrappedKey = encryptor.doFinal( getDesParity(inputKeyArray)); ++ ++ KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC_PAD); ++ keyWrap.initUnwrap(tempKey, new IVParameterSpec(iv)); ++ ++ if(isPerm) ++ finalDESKey = keyWrap.unwrapSymmetricPerm(wrappedKey, SymmetricKey.DES3, 24); ++ else ++ finalDESKey = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES3, 24); ++ ++ } catch (Exception e) { ++ throw new Exception(method + " Can't unwrap key onto token!" + e); ++ } ++ ++ return finalDESKey; ++ } ++ ++ + /** + * for CMC encryptedPOP + */ +@@ -3352,6 +3667,27 @@ public class CryptoUtil { + throw new NoSuchAlgorithmException(method + alg); + } + ++ public static byte[] getDesParity(byte[] key) throws Exception { ++ String method = "CryptoUtil.getDesParity"; ++ if (key == null || (key.length != 16 && ++ key.length != 24)) { ++ throw new Exception(method + " Incorrect input key !"); ++ } ++ ++ byte[] desKey = new byte[key.length]; ++ ++ for (int i = 0; i < key.length; i++) { ++ int index = key[i] & 0xff; ++ int finalIndex = index >> 1; ++ ++ byte val = (byte) parityTable[finalIndex]; ++ desKey[i] = val; ++ ++ } ++ ++ return desKey; ++ } ++ + } + + // START ENABLE_ECC +-- +1.8.3.1 + + +From b0e454a5c49633d3536257152ca204c3d0309532 Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Tue, 31 Oct 2023 16:53:29 -0700 +Subject: [PATCH 02/10] Fix Bug 2233158 - Make key wrapping algorithm + configurable between AES-KWP and AES-CBC [RHCS 9.7.z]. (#4593) + +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 certain hsm based setups. The default is to use the currently supported KWP alg. The reason to allow CBC is due to the fact that this alg is supported directly in the token and is much quicker than the hand coded KWP algorithm currently supported. + +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 following setting is not present: + +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 new coolkey applet. The new applet will be able to detect which alg to use and attempt. + +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. + +Review fixes... +(cherry picked from commit 39c9732dd3050db1622ebc93cdf2074046afbca9) +--- + .../src/com/netscape/certsrv/request/IRequest.java | 1 + + .../src/com/netscape/kra/NetkeyKeygenService.java | 38 ++++++++++++-- + .../com/netscape/kra/TokenKeyRecoveryService.java | 44 +++++++++++++--- + .../servlet/connector/GenerateKeyPairServlet.java | 9 ++++ + .../dogtagpki/server/connector/IRemoteRequest.java | 1 + + .../server/tps/cms/KRARemoteRequestHandler.java | 44 +++++++++++++--- + .../org/dogtagpki/server/tps/engine/TPSEngine.java | 13 ++--- + .../server/tps/processor/CertEnrollInfo.java | 9 ++++ + .../server/tps/processor/TPSEnrollProcessor.java | 58 +++++++++++++++++++--- + 9 files changed, 185 insertions(+), 32 deletions(-) + +diff --git a/base/common/src/com/netscape/certsrv/request/IRequest.java b/base/common/src/com/netscape/certsrv/request/IRequest.java +index cb2f463..c0ca40a 100644 +--- a/base/common/src/com/netscape/certsrv/request/IRequest.java ++++ b/base/common/src/com/netscape/certsrv/request/IRequest.java +@@ -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"; +diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +index ea750ce..13c5954 100644 +--- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java ++++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +@@ -176,6 +176,11 @@ public class NetkeyKeygenService implements IService { + String method = "NetkeyKeygenService: serviceRequest: "; + + byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; ++ int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength(); ++ ++ CMS.debug(method + " cbc iv len: " + ivLength); ++ ++ byte iv_cbc[] = new byte[ivLength]; + String iv_s = ""; + try { + JssSubsystem jssSubsystem = (JssSubsystem) CMS.getSubsystem(JssSubsystem.ID); +@@ -188,6 +193,7 @@ public class NetkeyKeygenService implements IService { + + IVParameterSpec algParam = null; + IVParameterSpec desAlgParam = new IVParameterSpec(iv); ++ IVParameterSpec aesCBCAlgParam = new IVParameterSpec(iv_cbc); + + IConfigStore configStore = CMS.getConfigStore(); + boolean allowEncDecrypt_archival = configStore.getBoolean("kra.allowEncDecrypt.archival", false); +@@ -228,6 +234,15 @@ public class NetkeyKeygenService implements IService { + + 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); ++ ++ CMS.debug(method + " IRequest.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG: " + IRequest.NETKEY_ATTR_SSKEYGEN_AES_KEY_WRAP_ALG); ++ ++ if(aesKeyWrapAlg != null) { ++ CMS.debug(method + " aesKeyWrapAlg: " + aesKeyWrapAlg); ++ } else { ++ CMS.debug(method + " no aesKeyWrapAlg provided."); ++ } + + boolean useAesTransWrapped = false; + +@@ -396,10 +411,23 @@ public class NetkeyKeygenService implements IService { + + 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 ++ CMS.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); ++ } + CMS.debug(method + " attemptedAesKeyWrap = true "); + } else { + algParam = desAlgParam; +@@ -453,7 +481,7 @@ public class NetkeyKeygenService implements IService { + 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) { +diff --git a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java +index 62bb37c..05d586a 100644 +--- a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java ++++ b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java +@@ -207,6 +207,12 @@ public class TokenKeyRecoveryService implements IService { + byte[] wrapped_des_key; + + byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; ++ ++ int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength(); ++ CMS.debug(method + " cbc iv len: " + ivLength); ++ ++ byte iv_cbc[] = new byte[ivLength]; ++ + try { + JssSubsystem jssSubsystem = (JssSubsystem) CMS.getSubsystem(JssSubsystem.ID); + SecureRandom random = jssSubsystem.getRandomNumberGenerator(); +@@ -243,6 +249,14 @@ public class TokenKeyRecoveryService implements IService { + 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) { ++ CMS.debug(method + " aesKeyWrapAlg: " + aesKeyWrapAlg); ++ } else { ++ CMS.debug(method + " no aesKeyWrapAlg provided."); ++ } ++ + // the request record field delayLDAPCommit == "true" will cause + // updateRequest() to delay actual write to ldap + request.setExtData("delayLDAPCommit", "true"); +@@ -398,7 +412,9 @@ public class TokenKeyRecoveryService implements IService { + */ + //CryptoToken token = mStorageUnit.getToken(); + CMS.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; + CMS.debug("KRA reading key record"); +@@ -581,14 +597,28 @@ public class TokenKeyRecoveryService implements IService { + CMS.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; ++ ++ 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 ++ CMS.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); ++ } + CMS.debug(method + " attemptedAesKeyWrap = true "); + } else { +- symWrapAlg = KeyWrapAlgorithm.DES3_CBC_PAD; ++ algParam = desAlgParam; + CMS.debug(method + " attemptedAesKeyWrap = false "); + } + +diff --git a/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java b/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java +index f1cf0e5..5a01d80 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java +@@ -143,6 +143,11 @@ public class GenerateKeyPairServlet extends CMSServlet { + 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); ++ CMS.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(""))) { +@@ -221,6 +226,10 @@ public class GenerateKeyPairServlet extends CMSServlet { + 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) { +diff --git a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java +index b334b0d..ae99a84 100644 +--- a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java ++++ b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java +@@ -107,6 +107,7 @@ public interface IRemoteRequest { + public static final String KRA_UserId = "userid"; + public static final String KRA_Trans_DesKey = "drm_trans_desKey"; + public static final String KRA_Trans_AesKey = "drm_trans_aesKey"; ++ public static final String KRA_Aes_Wrap_Alg = "drm_aes_wrapAlg"; + public static final String KRA_KEYGEN_Archive = "archive"; + public static final String KRA_KEYGEN_KeyType = "keytype"; + public static final String KRA_KEYGEN_EC_KeyCurve = "eckeycurve"; +diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java +index f8491fa..be39cd6 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java ++++ b/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java +@@ -66,7 +66,8 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + String userid, + String sDesKey, + String sAesKey, +- boolean archive) ++ boolean archive, ++ String aesKeyWrapAlg) + throws EBaseException { + + CMS.debug("KRARemoteRequestHandler: serverSideKeyGen(): begins."); +@@ -74,6 +75,13 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + 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"; ++ } ++ + TPSSubsystem subsystem = + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + HttpConnector conn = +@@ -109,7 +117,9 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + "&" + IRemoteRequest.KRA_Trans_DesKey + "=" + + sDesKey + + "&" + IRemoteRequest.KRA_Trans_AesKey + "=" + +- sAesKey; ++ sAesKey + ++ "&" + IRemoteRequest.KRA_Aes_Wrap_Alg + "=" + ++ aesWrapAlg; + + //CMS.debug("KRARemoteRequestHandler: outgoing request for ECC: " + request); + +@@ -131,7 +141,10 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + "&" + IRemoteRequest.KRA_Trans_DesKey + "=" + + sDesKey + + "&" + IRemoteRequest.KRA_Trans_AesKey + "=" + +- sAesKey; ; ++ sAesKey + ++ "&" + IRemoteRequest.KRA_Aes_Wrap_Alg + "=" + ++ aesWrapAlg; ++ + + //CMS.debug("KRARemoteRequestHandler: outgoing request for RSA: " + request); + +@@ -237,9 +250,10 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + 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( +@@ -248,7 +262,8 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + String sDesKey, + String sAesKey, + String b64cert, +- BigInteger keyid) ++ BigInteger keyid, ++ String aesKeyWrapAlg) + throws EBaseException { + + CMS.debug("KRARemoteRequestHandler: recoverKey(): begins."); +@@ -259,6 +274,13 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + 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"; ++ } ++ + TPSSubsystem subsystem = + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + CMS.debug("KRARemoteRequestHandler: getting conn id: " + connid); +@@ -289,7 +311,10 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + "&" + 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) + CMS.debug("KRARemoteRequestHandler: recoverKey(): keyid = " + keyid); +@@ -298,7 +323,10 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + "&" + 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) { +diff --git a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java +index be2976d..2f0fa0c 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java ++++ b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java +@@ -202,6 +202,7 @@ public class TPSEngine { + 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 +@@ -524,17 +525,17 @@ public class TPSEngine { + 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"; + CMS.debug("TPSEngine.recoverKey"); + if (cuid == null) +@@ -570,7 +571,7 @@ public class TPSEngine { + + 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); +@@ -610,7 +611,7 @@ public class TPSEngine { + 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 { + + /* + CMS.debug("TPSEngine.serverSideKeyGen entering... keySize: " + keySize + " cuid: " + cuid + " userid: " +@@ -632,7 +633,7 @@ public class TPSEngine { + 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! " +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java b/base/tps/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java +index d6a49a4..d606545 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/CertEnrollInfo.java +@@ -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; +@@ -199,6 +200,14 @@ public class CertEnrollInfo { + return publicKeyNumber; + } + ++ public void setAesKeyWrapAlg(String alg) { ++ aesKeyWrapAlg = alg; ++ } ++ ++ public String getAesKeyWrapAlg() { ++ return aesKeyWrapAlg; ++ } ++ + public void setKeyType(String keyType) { + this.keyType = keyType; + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +index adc8760..ce3f0a2 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +@@ -1311,6 +1311,7 @@ public class TPSEnrollProcessor extends TPSProcessor { + session.getExternalRegAttrs().getCertsToRecoverCount()); + ArrayList erCertsToRecover = session.getExternalRegAttrs().getCertsToRecover(); + ++ String aesKeyWrapAlg = getAESKeyWrapAlgSSKeyGen(); + for (ExternalRegCertToRecover erCert : erCertsToRecover) { + BigInteger keyid = erCert.getKeyid(); + BigInteger serial = erCert.getSerial(); +@@ -1416,7 +1417,7 @@ public class TPSEnrollProcessor extends TPSProcessor { + userid, + drmDesKey,drmAesKey, + getExternalRegRecoverByKeyID() ? null : b64cert, +- kraConn, keyid); ++ kraConn, keyid,aesKeyWrapAlg); + + if (keyResp == null) { + auditInfo = "recovering key not found"; +@@ -1437,6 +1438,8 @@ public class TPSEnrollProcessor extends TPSProcessor { + cEnrollInfo.setTokenToBeRecovered(tokenRecord); + cEnrollInfo.setRecoveredCertData(certResp); + cEnrollInfo.setRecoveredKeyData(keyResp); ++ cEnrollInfo.setAesKeyWrapAlg(aesKeyWrapAlg); ++ + preRecoveredCerts.add(cEnrollInfo); + + } +@@ -1667,6 +1670,8 @@ public class TPSEnrollProcessor extends TPSProcessor { + + boolean recoverOldEncCerts = tokenPolicy.isAllowdRenewSaveOldEncCerts(); + CMS.debug(method + " Recover Old Encryption Certs for Renewed Certs: " + recoverOldEncCerts); ++ ++ String aesKeyWrapAlg = getAESKeyWrapAlgSSKeyGen(); + if (oldEncCertsToRecover.size() > 0 && recoverOldEncCerts == true) { + CMS.debug("About to attempt to recover old encryption certs just renewed."); + +@@ -1692,7 +1697,7 @@ public class TPSEnrollProcessor extends TPSProcessor { + toBeRecovered.getUserID(), + drmDesKey, + drmAesKey, +- b64cert, getDRMConnectorID(toBeRecovered.getKeyType())); ++ b64cert, getDRMConnectorID(toBeRecovered.getKeyType()),aesKeyWrapAlg); + + //Try to write recovered cert to token + +@@ -1701,6 +1706,7 @@ public class TPSEnrollProcessor extends TPSProcessor { + cEnrollInfo.setTokenToBeRecovered(tokenRecord); + cEnrollInfo.setRecoveredCertData(certResponse); + cEnrollInfo.setRecoveredKeyData(keyResponse); ++ cEnrollInfo.setAesKeyWrapAlg(aesKeyWrapAlg); + + PKCS11Obj pkcs11obj = certsInfo.getPKCS11Obj(); + int newCertId = pkcs11obj.getNextFreeCertIdNumber(); +@@ -1955,6 +1961,7 @@ public class TPSEnrollProcessor extends TPSProcessor { + int actualCertIndex = 0; + boolean legalScheme = false; + ++ String aesKeyWrapAlg = getAESKeyWrapAlgSSKeyGen(); + //Go through again and do the recoveries/enrollments + + certsInfo.setNumCertsToEnroll(totalNumCerts); +@@ -1974,6 +1981,7 @@ public class TPSEnrollProcessor extends TPSProcessor { + if (scheme.equals(TPSEngine.RECOVERY_GENERATE_NEW_KEY) || isGenerateAndRecover) { + legalScheme = true; + CertEnrollInfo cEnrollInfo = new CertEnrollInfo(); ++ cEnrollInfo.setAesKeyWrapAlg(aesKeyWrapAlg); + generateCertificate(certsInfo, channel, aInfo, keyTypeValue, TPSEngine.ENROLL_MODES.MODE_ENROLL, + actualCertIndex, cEnrollInfo); + +@@ -2040,13 +2048,14 @@ public class TPSEnrollProcessor extends TPSProcessor { + KRARecoverKeyResponse keyResponse = tps.getEngine().recoverKey(toBeRecovered.getId(), + toBeRecovered.getUserID(), + drmDesKey,drmAesKey, +- b64cert, getDRMConnectorID(certToRecover.getKeyType())); ++ b64cert, getDRMConnectorID(certToRecover.getKeyType()),aesKeyWrapAlg); + + CertEnrollInfo cEnrollInfo = new CertEnrollInfo(); + + cEnrollInfo.setTokenToBeRecovered(toBeRecovered); + cEnrollInfo.setRecoveredCertData(certResponse); + cEnrollInfo.setRecoveredKeyData(keyResponse); ++ cEnrollInfo.setAesKeyWrapAlg(aesKeyWrapAlg); + + generateCertificate(certsInfo, channel, aInfo, keyTypeValue, TPSEngine.ENROLL_MODES.MODE_RECOVERY, + actualCertIndex, cEnrollInfo); +@@ -2451,6 +2460,9 @@ public class TPSEnrollProcessor extends TPSProcessor { + boolean isRecovery = false; + boolean isRenewal = false; + ++ String aesKeyWrapAlg = getAESKeyWrapAlgSSKeyGen(); ++ cEnrollInfo.setAesKeyWrapAlg(aesKeyWrapAlg); ++ + if (mode == ENROLL_MODES.MODE_RECOVERY) { + isRecovery = true; + +@@ -2492,7 +2504,7 @@ public class TPSEnrollProcessor extends TPSProcessor { + ssKeyGenResponse = getTPSEngine() + .serverSideKeyGen(cEnrollInfo.getKeySize(), + aInfo.getCUIDhexStringPlain(), userid, kraConnId, drmDesKey,drmAesKey, +- archive, isECC); ++ archive, isECC, aesKeyWrapAlg); + + publicKeyStr = ssKeyGenResponse.getPublicKey(); + //CMS.debug("TPSEnrollProcessor.enrollOneCertificate: public key string from server: " + publicKeyStr); +@@ -3164,7 +3176,17 @@ public class TPSEnrollProcessor extends TPSProcessor { + + //Give preference to AES kek wrapped key for SCP03, otherwise go with DES for SCP01 + if(kekWrappedAESKey != null && kekWrappedAESKey.size() > 0 && channel.isSCP03()) { +- alg = (byte) 0x88; ++ ++ String aesKeyWrapAlg = cEnrollInfo.getAesKeyWrapAlg(); ++ ++ if(aesKeyWrapAlg != null && "CBC".equalsIgnoreCase(aesKeyWrapAlg)) { //CBC ++ CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: unwrap the priv key with AES CBC "); ++ alg = (byte) 0x89; ++ } else { // KWP ++ CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: unwrap the priv key with AES KWP "); ++ alg = (byte) 0x88; ++ } ++ + kekWrappedKey = kekWrappedAESKey; + } + +@@ -3181,7 +3203,7 @@ public class TPSEnrollProcessor extends TPSProcessor { + } + data.add((byte) ivParamsBuff.size()); + data.add(ivParamsBuff); +-// CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8: key data outgoing: " + data.toHexString()); ++ //CMS.debug("TPSEnrollProcessor.importprivateKeyPKCS8: key data outgoing: " + data.toHexString()); + + int pe1 = (cEnrollInfo.getKeyUser() << 4) + cEnrollInfo.getPrivateKeyNumber(); + int pe2 = (cEnrollInfo.getKeyUsage() << 4) + cEnrollInfo.getPublicKeyNumber(); +@@ -3454,6 +3476,30 @@ public class TPSEnrollProcessor extends TPSProcessor { + return parsedPubKey; + } + ++ public String getAESKeyWrapAlgSSKeyGen() { ++ ++ String aesKeyWrapAlg = "KWP"; ++ ++ IConfigStore configStore = CMS.getConfigStore(); ++ ++ // op.enroll.userKey.keyGen.aesKeyWrapAlg ++ try { ++ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "." + TPSEngine.CFG_KEYGEN + ++ "." + TPSEngine.CFG_AES_KEY_WRAP_ALG; ++ ++ CMS.debug("TPSEnrollProcessor::getAESKeyWrapAlgSSKeyGen: configValue . " + configValue); ++ aesKeyWrapAlg = configStore.getString( ++ configValue, "KWP"); ++ CMS.debug("TPSEnrollProcessor::getAESKeyWrapAlgSSKeyGen: value " + aesKeyWrapAlg); ++ ++ } catch (EBaseException e) { ++ //return default ++ return aesKeyWrapAlg; ++ } ++ ++ return aesKeyWrapAlg; ++ ++ } + private boolean checkForServerSideKeyGen(CertEnrollInfo cInfo) throws TPSException { + + if (cInfo == null) { +-- +1.8.3.1 + + +From 11f0ec5ccf99cb66ab9dda0d35ce9ce116bf763e Mon Sep 17 00:00:00 2001 +From: Marco Fargetta +Date: Mon, 30 Oct 2023 11:52:31 +0100 +Subject: [PATCH 03/10] Remove token password from destroy logs + +In case of failure of the `sslget` command, during `pkidestroy`, the log will contain the full list of option including the token password. +This has been obfuscated before the failure is logged. + +Solve RHCS-4547 + +(cherry picked from commit 3c3eca1db150b4ea58ce0768cb3bdbb5729d63d4) +--- + base/server/python/pki/server/deployment/pkihelper.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py +index 214c9ae..4f4998a 100644 +--- a/base/server/python/pki/server/deployment/pkihelper.py ++++ b/base/server/python/pki/server/deployment/pkihelper.py +@@ -3472,6 +3472,7 @@ class SecurityDomain: + log.PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) ++ exc.cmd[4] = '******' + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure: +-- +1.8.3.1 + + +From 6ad7ca3109dd2e712ef40b1445e5c7f03fc58b7c Mon Sep 17 00:00:00 2001 +From: Jack Magne +Date: Mon, 18 Dec 2023 17:43:34 -0500 +Subject: [PATCH 04/10] Revised fix to: Bug 2233158 - Make key wrapping + algorithm configurable between AES-KWP and AES-CBC [RHCS 9.7.z]. + + We found an issue with scp01 recovery with said fix. This patch addresses this such that both scp01 and scp03 recovery should now work. + +(cherry picked from commit ed61cbd9d66d86273a449d22f5a5f355e896255f) +--- + base/kra/src/com/netscape/kra/NetkeyKeygenService.java | 1 + + base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java | 3 ++- + .../src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java | 5 +++-- + 3 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +index 13c5954..413bb8e 100644 +--- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java ++++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +@@ -431,6 +431,7 @@ public class NetkeyKeygenService implements IService { + CMS.debug(method + " attemptedAesKeyWrap = true "); + } else { + algParam = desAlgParam; ++ iv_s = org.mozilla.jss.netscape.security.util.Utils.SpecialEncode(iv); + CMS.debug(method + " attemptedAesKeyWrap = false "); + } + +diff --git a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java +index 05d586a..12bbf87 100644 +--- a/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java ++++ b/base/kra/src/com/netscape/kra/TokenKeyRecoveryService.java +@@ -301,10 +301,11 @@ public class TokenKeyRecoveryService implements IService { + + // unwrap the des key + try { ++ CMS.debug("TokenKeyRecoveryService: received DRM-trans-wrapped des key: length: " + wrapped_des_key.length); + sk = (PK11SymKey) mTransportUnit.unwrap_sym(wrapped_des_key, wrapParams); + CMS.debug("TokenKeyRecoveryService: received des key"); + } catch (Exception e) { +- CMS.debug("TokenKeyRecoveryService: no des key"); ++ CMS.debug("TokenKeyRecoveryService: no des key: " + e); + if(!useAesTransWrapped) { + request.setExtData(IRequest.RESULT, Integer.valueOf(4)); + return false; +diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java +index be39cd6..6f42855 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java ++++ b/base/tps/src/org/dogtagpki/server/tps/cms/KRARemoteRequestHandler.java +@@ -294,8 +294,8 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + + String sendMsg = null; + try { +- String desPart = " "; +- String aesPart = " "; ++ String desPart = ""; ++ String aesPart = ""; + + if(sDesKey != null) { + desPart = "&" + IRemoteRequest.KRA_Trans_DesKey + "=" + sDesKey; +@@ -329,6 +329,7 @@ public class KRARemoteRequestHandler extends RemoteRequestHandler + + + } ++ //logger.debug("KRARemoteRequestHandler: recoverKey(): outgoing: " + sendMsg); + } catch (Exception e) { + CMS.debug("KRARemoteRequestHandler: recoverKey(): uriEncode failed: " + e); + throw new EBaseException("KRARemoteRequestHandler: recoverKey(): uriEncode failed: " + e); +-- +1.8.3.1 + + +From 002423cfb79f685c6a4dfefded9634262e673dd0 Mon Sep 17 00:00:00 2001 +From: Marco Fargetta +Date: Mon, 5 Feb 2024 18:49:50 +0100 +Subject: [PATCH 05/10] Add AIA and SIA to OIDMap + +The "Authority Info Access" and "Subject Info Access" extensions were not included in the oid +extension map so it was not correctly printed. + +Resolves: RHEL-23935 +(cherry picked from commit 37e366d01076f8b156558a2714bcc07e008b401a) +--- + base/util/src/netscape/security/x509/OIDMap.java | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/base/util/src/netscape/security/x509/OIDMap.java b/base/util/src/netscape/security/x509/OIDMap.java +index 20765c9..4b2ca00 100644 +--- a/base/util/src/netscape/security/x509/OIDMap.java ++++ b/base/util/src/netscape/security/x509/OIDMap.java +@@ -25,6 +25,8 @@ import java.util.Hashtable; + import java.util.Iterator; + import java.util.Properties; + ++import netscape.security.extensions.AuthInfoAccessExtension; ++import netscape.security.extensions.SubjectInfoAccessExtension; + import netscape.security.util.ObjectIdentifier; + + /** +@@ -61,6 +63,10 @@ public class OIDMap { + AuthorityKeyIdentifierExtension.NAME; + private static final String SUB_KEY_IDENTIFIER = ROOT + "." + + SubjectKeyIdentifierExtension.NAME; ++ private static final String AUTHORITY_INFORMATION_ACCESS_IDENTIFIER = ROOT + "." + ++ AuthInfoAccessExtension.NAME; ++ private static final String SUBJECT_INFORMATION_ACCESS_IDENTIFIER = ROOT + "." + ++ SubjectInfoAccessExtension.NAME; + private static final String KEY_USAGE = ROOT + "." + + KeyUsageExtension.NAME; + private static final String PRIVATE_KEY_USAGE = ROOT + "." + +@@ -105,6 +111,8 @@ public class OIDMap { + // Load the default name to oid map (EXTENSIONS_OIDS) + private static void loadNamesDefault(Properties props) { + props.put(SUB_KEY_IDENTIFIER, "2.5.29.14"); ++ props.put(AUTHORITY_INFORMATION_ACCESS_IDENTIFIER, "1.3.6.1.5.5.7.1.1"); ++ props.put(SUBJECT_INFORMATION_ACCESS_IDENTIFIER, "1.3.6.1.5.5.7.1.11"); + props.put(KEY_USAGE, "2.5.29.15"); + props.put(PRIVATE_KEY_USAGE, "2.5.29.16"); + props.put(SUB_ALT_NAME, "2.5.29.17"); +@@ -126,7 +134,11 @@ public class OIDMap { + props.put(AUTH_KEY_IDENTIFIER, + "netscape.security.x509.AuthorityKeyIdentifierExtension"); + props.put(SUB_KEY_IDENTIFIER, +- "netscape.security.x509.SubjectKeyIdentifierExtension"); ++ "org.mozilla.jss.netscape.security.x509.SubjectKeyIdentifierExtension"); ++ props.put(AUTHORITY_INFORMATION_ACCESS_IDENTIFIER, ++ "netscape.security.extensions.AuthInfoAccessExtension"); ++ props.put(SUBJECT_INFORMATION_ACCESS_IDENTIFIER, ++ "netscape.security.extensions.SubjectInfoAccessExtension"); + props.put(KEY_USAGE, + "netscape.security.x509.KeyUsageExtension"); + props.put(PRIVATE_KEY_USAGE, +-- +1.8.3.1 + + +From ab34852d204aa02497ea1f13f3b3a4dc2e435fbe Mon Sep 17 00:00:00 2001 +From: Marco Fargetta +Date: Tue, 7 Feb 2023 15:44:55 +0100 +Subject: [PATCH 06/10] Adopt HTTP 1.1 for http based connections + +Communication between subsystem on separate instance uses HTTP1.0 in +some cases. Since this version of HTTP does not support the Host header, +reverse proxies in the communication flow do not work. + +This commit uprate the `HttpConnection` to use HTTP1.1 for the +communication. Actually, it does not support the full HTTP1.1 protocol +but only what is needed for the current communication options. + +Solve the bugzilla 2130250 + +(cherry picked from commit 7c61a13637b93504733ccb3f9c4e312d62d94066) +--- + .../cmscore/src/com/netscape/cmscore/connector/HttpConnection.java | 4 +++- + base/util/src/com/netscape/cmsutil/http/HttpRequest.java | 5 ++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java +index 649fa80..1e2b756 100644 +--- a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java ++++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java +@@ -91,7 +91,9 @@ public class HttpConnection implements IHttpConnection { + mHttpreq.setHeader("Content-Type", contentType ); + } + +- mHttpreq.setHeader("Connection", "Keep-Alive"); ++ ++ mHttpreq.setHeader("Host", dest.getHost()); ++ logger.debug("HttpConnection: setting Host to " + dest.getHost()); + + connect(); + +diff --git a/base/util/src/com/netscape/cmsutil/http/HttpRequest.java b/base/util/src/com/netscape/cmsutil/http/HttpRequest.java +index 9024dab..c2b194b 100644 +--- a/base/util/src/com/netscape/cmsutil/http/HttpRequest.java ++++ b/base/util/src/com/netscape/cmsutil/http/HttpRequest.java +@@ -73,7 +73,10 @@ public class HttpRequest extends HttpMessage { + throw e; + } + +- mLine = mMethod + " " + mURI + " " + Http.HttpVers; ++ String protocol = (getHeader("host") != null) ? Http.Vers1_1 : Http.Vers1_0; ++ mLine = mMethod + " " + mURI + " " + protocol; ++ ++ + super.write(writer); + } + +-- +1.8.3.1 + + +From 50460cf442b1df50928117efdde0722e2743b29e Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Thu, 22 Feb 2024 16:00:46 -0800 +Subject: [PATCH 07/10] Fix Bug 2121463 - Add Secure Channel Support for + AES-256 Keys [RHCS 9.7.z]. (#4668) + +This 3rd party code contribution for the TMS product, (TPS and TKS), allows secure channels to be created against newer scp03 tokens using 256 bit AES session keys to create secure channels and to upgrade the keyset for such tokens. The operations of creating a simple secure channel to the token and of performing symmetric key changover for a token will not be supported using 256 bit AES session keys and a 256 bit master key. + +The feature is kicked off by configuring the tks to call for 256 bit values for the 3 static keys as follows: + +tks.defKeySet.auth_key=#10#11#12#13#14#15#16#17#18#19#1A#1B#1C#1D#1E#1F#20#21#22#23#24#25#26#27#28#29#2A#2B#2C#2D#2E#2F +tks.defKeySet.kek_key=#10#11#12#13#14#15#16#17#18#19#1A#1B#1C#1D#1E#1F#20#21#22#23#24#25#26#27#28#29#2A#2B#2C#2D#2E#2F +tks.defKeySet.mac_key=#10#11#12#13#14#15#16#17#18#19#1A#1B#1C#1D#1E#1F#20#21#22#23#24#25#26#27#28#29#2A#2B#2C#2D#2E#2F + +The TPS is also configured to support multiple values for the card manager aid instance: + +applet.aid.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + +This allows the code to select the desired AID based on the token. + +Other things provided with this patch: + +1. Support for 256 bit AES shared secret keys common to the TKS and TPS. Installing fresh TKS instance followed by a fresh +TPS instance will result in a 256 bit AES share secret being created in the TKS and automatically imported into the TPS. + +2. Fixed an issue with the Idemia Cosmo card when trying to generate the signing private key on the token. This required an trailing le byte of zero +being sent to the applet command that generates the private key and returns the length of the public key. Without the le, the idemia was returning an incorrect size. + +3. Applet included with TPS with AES support: +1.5.65cbf5a6.ijc + +Review suggestions added. +(cherry picked from commit 49194d77d3b2706c2d575ca35fce72dc05658226) +--- + base/common/src/org/dogtagpki/tps/apdu/APDU.java | 23 +- + .../src/org/dogtagpki/tps/apdu/GetDataAPDU.java | 2 +- + .../dogtagpki/tps/apdu/InitializeUpdateAPDU.java | 2 + + .../dogtagpki/tps/apdu/InstallLoadGP211APDU.java | 6 +- + .../src/org/dogtagpki/tps/apdu/SelectAPDU.java | 12 + + base/common/src/org/dogtagpki/tps/main/Util.java | 18 +- + .../org/dogtagpki/tps/msg/TokenPDURequestMsg.java | 27 ++ + .../cms/src/com/netscape/cms/servlet/tks/KDF.java | 9 +- + .../netscape/cms/servlet/tks/NistSP800_108KDF.java | 30 +- + .../cms/servlet/tks/SecureChannelProtocol.java | 271 ++++++++++---- + base/tks/shared/conf/CS.cfg | 17 +- + .../server/tks/rest/TPSConnectorService.java | 9 +- + .../dogtagpki/server/tks/servlet/TokenServlet.java | 30 +- + base/tps/shared/applets/1.5.65cbf5a6.ijc | Bin 0 -> 17969 bytes + base/tps/shared/conf/CS.cfg | 62 ++-- + .../src/org/dogtagpki/server/tps/TPSSession.java | 13 + + .../server/tps/channel/SecureChannel.java | 64 ++-- + .../server/tps/processor/TPSEnrollProcessor.java | 7 - + .../server/tps/processor/TPSPinResetProcessor.java | 2 - + .../server/tps/processor/TPSProcessor.java | 399 +++++++++++++++++---- + .../com/netscape/cmsutil/crypto/CryptoUtil.java | 4 +- + 21 files changed, 750 insertions(+), 257 deletions(-) + create mode 100644 base/tps/shared/applets/1.5.65cbf5a6.ijc + +diff --git a/base/common/src/org/dogtagpki/tps/apdu/APDU.java b/base/common/src/org/dogtagpki/tps/apdu/APDU.java +index e3d72c7..4dcaf99 100644 +--- a/base/common/src/org/dogtagpki/tps/apdu/APDU.java ++++ b/base/common/src/org/dogtagpki/tps/apdu/APDU.java +@@ -154,6 +154,23 @@ public abstract class APDU { + return encoding; + } + ++ // New method for IDEMIA token processing ++ public TPSBuffer getEncodingWithLength() { ++ ++ TPSBuffer encoding = new TPSBuffer(); ++ ++ encoding.add(cla); ++ encoding.add(ins); ++ encoding.add(p1); ++ encoding.add(p2); ++ ++ if (trailer != null) { ++ encoding.add(trailer); ++ } ++ ++ return encoding; ++ } ++ + public TPSBuffer getDataToMAC() { + TPSBuffer mac = new TPSBuffer(); + +@@ -236,7 +253,6 @@ public abstract class APDU { + padding.setAt(0, (byte) 0x80); + + buffer.add(padding); +- + } + + //Assume the whole buffer is to be incremented +@@ -278,9 +294,7 @@ public abstract class APDU { + TPSBuffer encryptedData = Util.encryptDataAES(data, encKey, encryptedCounter); + + data.set(encryptedData); +- + } +- + } + + public void secureMessageSCP02(PK11SymKey encKey) throws EBaseException { +@@ -290,7 +304,6 @@ public abstract class APDU { + } + + secureMessage(encKey,(byte) 2); +- + } + + public Type getType() { +@@ -338,4 +351,4 @@ public abstract class APDU { + data.dump(); + } + +-}; ++} +diff --git a/base/common/src/org/dogtagpki/tps/apdu/GetDataAPDU.java b/base/common/src/org/dogtagpki/tps/apdu/GetDataAPDU.java +index 6a2e8ed..12e40f2 100644 +--- a/base/common/src/org/dogtagpki/tps/apdu/GetDataAPDU.java ++++ b/base/common/src/org/dogtagpki/tps/apdu/GetDataAPDU.java +@@ -58,7 +58,7 @@ public class GetDataAPDU extends APDU { + encoding.add(ins); + encoding.add(p1); + encoding.add(p2); +- encoding.add((byte) 0x2D); ++ encoding.add((byte) 0x00); + + return encoding; + } /* Encode */ +diff --git a/base/common/src/org/dogtagpki/tps/apdu/InitializeUpdateAPDU.java b/base/common/src/org/dogtagpki/tps/apdu/InitializeUpdateAPDU.java +index 4bc6401..cd5d47e 100644 +--- a/base/common/src/org/dogtagpki/tps/apdu/InitializeUpdateAPDU.java ++++ b/base/common/src/org/dogtagpki/tps/apdu/InitializeUpdateAPDU.java +@@ -56,6 +56,8 @@ public class InitializeUpdateAPDU extends APDU { + theData.add(p2); + theData.add((byte) data.size()); + theData.add(data); ++ // Add Le byte ++ theData.add((byte) 0x00); + + return theData; + } /* Encode */ +diff --git a/base/common/src/org/dogtagpki/tps/apdu/InstallLoadGP211APDU.java b/base/common/src/org/dogtagpki/tps/apdu/InstallLoadGP211APDU.java +index d277fc6..ccb2e82 100644 +--- a/base/common/src/org/dogtagpki/tps/apdu/InstallLoadGP211APDU.java ++++ b/base/common/src/org/dogtagpki/tps/apdu/InstallLoadGP211APDU.java +@@ -13,8 +13,7 @@ public class InstallLoadGP211APDU extends APDU { + setP1((byte) 0x02); + setP2((byte) 0x00); + +- +- CMS.debug("InstlalLoadGP211APDU: packageAID " + packageAID.toHexString() + " aid size: " + packageAID.size() + " fileLen: " + fileLen); ++ CMS.debug("InstallLoadGP211APDU: packageAID " + packageAID.toHexString() + " aid size: " + packageAID.size() + " fileLen: " + fileLen); + + TPSBuffer inputData = new TPSBuffer(); + +@@ -43,9 +42,6 @@ public class InstallLoadGP211APDU extends APDU { + inputData.add((byte) 0x0); + + setData(inputData); +- +- trailer = new TPSBuffer(); +- trailer.add((byte)0x0); + } + + } +diff --git a/base/common/src/org/dogtagpki/tps/apdu/SelectAPDU.java b/base/common/src/org/dogtagpki/tps/apdu/SelectAPDU.java +index d0b4925..e3d2965 100644 +--- a/base/common/src/org/dogtagpki/tps/apdu/SelectAPDU.java ++++ b/base/common/src/org/dogtagpki/tps/apdu/SelectAPDU.java +@@ -30,6 +30,18 @@ public class SelectAPDU extends APDU { + setP1(p1); + setP2(p2); + setData(theData); ++ // Add trailer byte ++ TPSBuffer trailer = new TPSBuffer(1); ++ setTrailer(trailer); ++ } ++ ++ // This constructor is used to make a card mgr request with no data ++ public SelectAPDU(byte p1, byte p2) ++ { ++ setCLA((byte) 0x00); ++ setINS((byte) 0xa4); ++ setP1(p1); ++ setP2(p2); + } + + public Type getType() +diff --git a/base/common/src/org/dogtagpki/tps/main/Util.java b/base/common/src/org/dogtagpki/tps/main/Util.java +index 4f201bf..057aef5 100644 +--- a/base/common/src/org/dogtagpki/tps/main/Util.java ++++ b/base/common/src/org/dogtagpki/tps/main/Util.java +@@ -359,7 +359,12 @@ public class Util { + int outputBits = 8 * 8; + + //output size of cmac PRF +- final int h = 128; ++ int h = 128; ++ // Account for AES-256 ++ if (symKey.getLength() == 32) ++ { ++ h = 256; ++ } + + int remainder = outputBits % h; + +@@ -624,7 +629,8 @@ public class Util { + return tbuf; + } + +- //Encrypt data with aes. Supports 128 for now. ++ // Encrypt data with aes. Supports 128 for now. ++ // Added support for AES 256 + public static TPSBuffer encryptDataAES(TPSBuffer dataToEnc, PK11SymKey encKey,TPSBuffer iv) throws EBaseException { + + TPSBuffer encrypted = null; +@@ -634,12 +640,18 @@ public class Util { + + CryptoToken token = null; + +- + try { + token = CryptoManager.getInstance().getInternalKeyStorageToken(); ++ // Default to AES 128 + Cipher cipher = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC); + AlgorithmParameterSpec algSpec = null; + int len = EncryptionAlgorithm.AES_128_CBC.getIVLength(); ++ // Use 256 bits based on key length ++ if (encKey.getLength() == 32) ++ { ++ cipher = token.getCipherContext(EncryptionAlgorithm.AES_256_CBC); ++ len = 32; ++ } + + byte[] ivEnc = null; + if(iv == null) { //create one +diff --git a/base/common/src/org/dogtagpki/tps/msg/TokenPDURequestMsg.java b/base/common/src/org/dogtagpki/tps/msg/TokenPDURequestMsg.java +index 42fcf25..d8171a4 100644 +--- a/base/common/src/org/dogtagpki/tps/msg/TokenPDURequestMsg.java ++++ b/base/common/src/org/dogtagpki/tps/msg/TokenPDURequestMsg.java +@@ -37,7 +37,34 @@ public class TokenPDURequestMsg extends TPSMessage { + + put(PDU_SIZE_NAME, apduSize); + put(PDU_DATA_NAME, apdu_value); ++ } ++ ++ } ++ ++ // This constructor is used to add a length byte to the apdu ++ public TokenPDURequestMsg(APDU apdu, boolean addLength) { ++ ++ put(MSG_TYPE_NAME, msgTypeToInt(MsgType.MSG_TOKEN_PDU_REQUEST)); ++ ++ TPSBuffer encoding = null; ++ ++ if (apdu != null) { ++ ++ if (addLength) ++ { ++ encoding = apdu.getEncodingWithLength(); ++ } ++ else ++ { ++ encoding = apdu.getEncoding(); ++ } ++ ++ int apduSize = encoding.size(); + ++ String apdu_value = Util.uriEncodeInHex(encoding.toBytesArray()); ++ ++ put(PDU_SIZE_NAME, apduSize); ++ put(PDU_DATA_NAME, apdu_value); + } + + } +diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java b/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java +index e7b183b..ead2f3d 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/tks/KDF.java +@@ -154,11 +154,14 @@ public class KDF { + + static public byte[] getDesParity(byte[] key) throws EBaseException { + String method = "KDF.getDesParity"; ++ ++ // Add AES-256 + if (key == null || (key.length != SecureChannelProtocol.DES2_LENGTH && +- key.length != SecureChannelProtocol.EIGHT_BYTES && key.length != SecureChannelProtocol.DES3_LENGTH)) { ++ key.length != SecureChannelProtocol.EIGHT_BYTES && key.length != SecureChannelProtocol.DES3_LENGTH ++ && key.length != SecureChannelProtocol.DEF_AES_256_KEYLENGTH)) { + throw new EBaseException(method + " Incorrect input key !"); +- } +- ++ } ++ + byte[] desKey = new byte[key.length]; + + for (int i = 0; i < key.length; i++) { +diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java b/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java +index 54d0061..a45907e 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/tks/NistSP800_108KDF.java +@@ -73,7 +73,6 @@ public class NistSP800_108KDF extends KDF { + * Bytes 16 - 31 : mac key + * Bytes 32 - 47 : kek key + We chose this order to conform with the key order used by the PUT KEY command. +- + *******************************************************************************/ + + public Map computeCardKeys(SymmetricKey masterKey, byte[] context, CryptoToken token) +@@ -90,7 +89,7 @@ public class NistSP800_108KDF extends KDF { + byte[] kdf_output = null; + + kdf_output = kdf_CM_SHA256_HMAC_L384(masterKey, context, KDF_LABEL, KDF_OUTPUT_SIZE_BYTES, token); +- ++ + //Now create the 3 keys from only 48 of the 64 bytes... + + byte[] enc = new byte[16]; +@@ -113,7 +112,7 @@ public class NistSP800_108KDF extends KDF { + + SecureChannelProtocol.debugByteArray(mac, " Nist mac before parity: "); + SecureChannelProtocol.debugByteArray(enc, " Nist enc before parity: "); +- SecureChannelProtocol.debugByteArray(kek, " Nist kek before parityl: "); ++ SecureChannelProtocol.debugByteArray(kek, " Nist kek before parity: "); + + + SecureChannelProtocol.debugByteArray(macFinal, " Nist macFinal: "); +@@ -162,7 +161,7 @@ public class NistSP800_108KDF extends KDF { + + //output size of cmac PRF + final int h = 128; +- ++ + int remainder = outputBits % h; + + //calculate counter size +@@ -198,6 +197,10 @@ public class NistSP800_108KDF extends KDF { + for (int i = 1; i <= n; i++) { + + try { ++ // Need to flush and reset buffer before using it ++ input.reset(); ++ input.flush(); ++ + input.write(headerBytes); + input.write((byte) i); + input.write(context); +@@ -253,7 +256,6 @@ public class NistSP800_108KDF extends KDF { + ByteArrayOutputStream cmacOutput = new ByteArrayOutputStream(AES_CMAC_BLOCK_SIZE * iterations); + for(int i = 0; i < iterations; i++) { + byte[] cmacInput = new byte[16]; +- + cmacInput[0] = (byte)(i + 1); // Counter/iteration variable "i" + cmacInput[1] = 0; + cmacInput[2] = 0; +@@ -377,7 +379,7 @@ public class NistSP800_108KDF extends KDF { + // Input an aes key of 128, 192, or 256 bits + // For now calling code only using 128 + // Will move later to common class used by both tks and tps +- ++ + public static byte[] computeAES_CMAC(SymmetricKey aesKey, byte[] input) throws EBaseException { + + String method = "NistSP800_108KDF.computeAES_CMAC:"; +@@ -411,7 +413,17 @@ public class NistSP800_108KDF extends KDF { + Cipher encryptor = null; + + try { +- encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC); ++ // Base size on key length ++ if (aesKey.getLength() == AES_CMAC_BLOCK_SIZE) ++ { ++ //CMS.debug(method + " encryptor context set to AES_128_CBC"); ++ encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC); ++ } ++ else ++ { ++ //CMS.debug(method + " encryptor context set to AES_256_CBC"); ++ encryptor = token.getCipherContext(EncryptionAlgorithm.AES_256_CBC); ++ } + encryptor.initEncrypt(aesKey, new IVParameterSpec(iv)); + k0 = encryptor.doFinal(k0); + +@@ -451,11 +463,11 @@ public class NistSP800_108KDF extends KDF { + index = messageSize - AES_CMAC_BLOCK_SIZE + j; + inb = data[index]; + data[index] = (byte) (inb ^ k1[j]); +- } ++ } + try { + outputStream.write(data); + } catch (IOException e) { +- throw new EBaseException(method + " internal buffer erro!"); ++ throw new EBaseException(method + " internal buffer error!"); + } + finalData = outputStream.toByteArray(); + } +diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +index dc18748..31eb6eb 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +@@ -26,6 +26,7 @@ import org.mozilla.jss.crypto.SymmetricKeyDeriver; + import org.mozilla.jss.crypto.TokenException; + + import com.netscape.certsrv.apps.CMS; ++import com.netscape.certsrv.base.IConfigStore; + import com.netscape.certsrv.base.EBaseException; + import com.netscape.cmscore.security.JssSubsystem; + import com.netscape.cmsutil.crypto.CryptoUtil; +@@ -38,6 +39,7 @@ public class SecureChannelProtocol { + static String masterKeyPrefix = null; + + static final int DEF_AES_KEYLENGTH = 16; ++ static final int DEF_AES_256_KEYLENGTH = 32; + static final int KEYLENGTH = 16; + static final int PREFIXLENGHT = 128; + static final int DES2_LENGTH = 16; +@@ -242,8 +244,9 @@ public class SecureChannelProtocol { + } + + sharedSecretKeyName = SecureChannelProtocol.getSharedSecretKeyName(transportKeyName); ++ + transportKey = getSharedSecretKey(internalToken); +- ++ + //concat host and card challenge: + + byte[] context = null; +@@ -343,7 +346,7 @@ public class SecureChannelProtocol { + divKey = nistKdf.diversifyAESKey(devSymKey, xCUID, constant_gpkmc, token); + } + } else { +- throw new EBaseException(method + " Invalid devolper key type. Does not support diversification: "+ devKeyType); ++ throw new EBaseException(method + " Invalid developer key type. Does not support diversification: "+ devKeyType); + } + } + +@@ -356,7 +359,9 @@ public class SecureChannelProtocol { + sessionKey = divKey; + } + else { +- byte[] finalKeyBytes = nistKdf.kdf_AES_CMAC_SCP03(divKey, context, constant, 16); ++ // Use length of divKey for AES CMAC ++ //CMS.debug(method + "Call to nistKdf.kdf_AES_CMAC_SCP03 divKey length = " + divKey.getLength()); ++ byte[] finalKeyBytes = nistKdf.kdf_AES_CMAC_SCP03(divKey, context, constant, divKey.getLength()); + sessionKey = unwrapAESSymKeyOnToken(token, finalKeyBytes, false); + + JssSubsystem jssSubsystem = (JssSubsystem) CMS.getSubsystem(JssSubsystem.ID); +@@ -414,7 +419,8 @@ public class SecureChannelProtocol { + sessionKey = divKey; + } + else { +- byte[] finalKeyBytes = nistKdf.kdf_AES_CMAC_SCP03(divKey, context, constant, 16); ++ // Use length of divKey for AES CMAC ++ byte[] finalKeyBytes = nistKdf.kdf_AES_CMAC_SCP03(divKey, context, constant, divKey.getLength()); + sessionKey = unwrapAESSymKeyOnToken(token, finalKeyBytes, false); + + JssSubsystem jssSubsystem = (JssSubsystem) CMS.getSubsystem(JssSubsystem.ID); +@@ -423,8 +429,6 @@ public class SecureChannelProtocol { + } + } + +- //SecureChannelProtocol.debugByteArray(sessionKey.getEncoded(), keyType + " : session key"); +- + return sessionKey; + } + +@@ -790,7 +794,8 @@ public class SecureChannelProtocol { + + } else { + +- if(inputLen == DEF_AES_KEYLENGTH) { // support 128 bits for now ++ // Allow 256 bit length ++ if (inputLen == DEF_AES_KEYLENGTH || inputLen == DEF_AES_256_KEYLENGTH) { // support 128 and 256 bits + devKey = unwrapAESSymKeyOnToken(token, inputKeyArray, true); + } + } +@@ -804,6 +809,7 @@ public class SecureChannelProtocol { + + //Takes raw des key 16 bytes, such as developer key and returns an AES key of the same size + //Supports 128 bits for now ++ //07-08-2022, Updated to work with both 128 and 256 bits + public SymmetricKey unwrapAESSymKeyOnToken(CryptoToken token, byte[] inputKeyArray, + boolean isPerm) + throws EBaseException { +@@ -820,10 +826,10 @@ public class SecureChannelProtocol { + } + + byte[] finalInputKeyArray = inputKeyArray; +- if(inputKeyArray.length > 16) { +- finalInputKeyArray = new byte[16]; +- System.arraycopy(inputKeyArray, 0, finalInputKeyArray, 0, 16);; + ++ if(inputKeyArray.length > 32) { ++ finalInputKeyArray = new byte[32]; ++ System.arraycopy(inputKeyArray, 0, finalInputKeyArray, 0, 32); + } + + KeyGenerator kg; +@@ -839,14 +845,23 @@ public class SecureChannelProtocol { + + kg.setKeyUsages(usages); + kg.temporaryKeys(true); +- kg.initialize(128); ++ // Handle 128 and 256 initialization sizes ++ kg.initialize(finalInputKeyArray.length*EIGHT_BYTES); + SymmetricKey tempKey = kg.generate(); + +- //unwrap the test aes keys onto the token +- +- Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC); ++ // Use EncryptionAlgorithm based on key size ++ Cipher encryptor; ++ if (tempKey.getStrength() == AES_128_BITS) ++ { ++ encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC); ++ } ++ else ++ { ++ encryptor = token.getCipherContext(EncryptionAlgorithm.AES_256_CBC); ++ } ++ ++ int ivLength = 16; + +- int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength(); + byte[] iv = null; + + if (ivLength > 0) { +@@ -854,15 +869,18 @@ public class SecureChannelProtocol { + } + + encryptor.initEncrypt(tempKey, new IVParameterSpec(iv)); ++ CMS.debug(method + " Did encryptor.initEncrypt successfully..."); + byte[] wrappedKey = encryptor.doFinal(finalInputKeyArray); + + KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC); + keyWrap.initUnwrap(tempKey, new IVParameterSpec(iv)); + + if(isPerm) +- finalAESKey = keyWrap.unwrapSymmetricPerm(wrappedKey, SymmetricKey.AES, AES_128_BYTES); ++ // Use length of key for finalAESKey ++ finalAESKey = keyWrap.unwrapSymmetricPerm(wrappedKey, SymmetricKey.AES, wrappedKey.length); + else +- finalAESKey = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.AES, AES_128_BYTES); ++ // Use length of key for finalAESKey ++ finalAESKey = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.AES, wrappedKey.length); + + } catch (Exception e) { + throw new EBaseException(method + " Can't unwrap key onto token!"); +@@ -905,7 +923,6 @@ public class SecureChannelProtocol { + kg.initialize(128); + SymmetricKey tempKey = kg.generate(); + +- + int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength(); + byte[] iv = null; + +@@ -929,6 +946,7 @@ public class SecureChannelProtocol { + } + + KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC); ++ + keyWrap.initWrap(tempKey, new IVParameterSpec(iv)); + byte[] wrappedKey = keyWrap.wrap(finalKeyToWrap); + +@@ -942,9 +960,6 @@ public class SecureChannelProtocol { + JssSubsystem jssSubsystem = (JssSubsystem) CMS.getSubsystem(JssSubsystem.ID); + jssSubsystem.obscureBytes(wrappedKey); + +- //byte[] finalKeyBytes = finalAESKey.getKeyData(); +- //displayByteArray(finalKeyBytes, false); +- + } catch (Exception e) { + throw new EBaseException(method + " Can't unwrap key onto token!"); + } +@@ -967,14 +982,25 @@ public class SecureChannelProtocol { + throw new EBaseException(method + "Invalid input!"); + } + +- if (inputKeyArray == null || (inputKeyArray.length != DES3_LENGTH && inputKeyArray.length != DES2_LENGTH)) { ++ // Allow AES-256 ++ if (inputKeyArray == null || (inputKeyArray.length != DES3_LENGTH && inputKeyArray.length != DES2_LENGTH ++ && inputKeyArray.length != DEF_AES_256_KEYLENGTH)) { + throw new EBaseException(method + "No raw array to use to create key!"); + } + + if (unwrappingKey == null) { + try { +- KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); +- ++ // Select algorithm based on key size ++ KeyGenerator kg; ++ if (inputKeyArray.length == DES3_LENGTH || inputKeyArray.length == DES2_LENGTH) ++ { ++ kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); ++ } ++ else ++ { ++ kg = token.getKeyGenerator(KeyGenAlgorithm.AES); ++ } ++ + SymmetricKey.Usage usages[] = new SymmetricKey.Usage[4]; + usages[0] = SymmetricKey.Usage.WRAP; + usages[1] = SymmetricKey.Usage.UNWRAP; +@@ -1008,21 +1034,21 @@ public class SecureChannelProtocol { + } + + try { +- +- EncryptionAlgorithm encAlg = EncryptionAlgorithm.DES3_ECB; +- KeyWrapAlgorithm wrapAlg = KeyWrapAlgorithm.DES3_ECB; +- +- IVParameterSpec iv = null; +- if(encUnwrapKey.getType() == SymmetricKey.Type.AES) { +- encAlg = EncryptionAlgorithm.AES_128_CBC_PAD; +- wrapAlg = KeyWrapAlgorithm.AES_CBC_PAD; +- iv = new IVParameterSpec(new byte[encAlg.getIVLength()]); ++ //Differentiate between DES3, DES and AES ++ if (finalKeyType == SymmetricKey.Type.DES3 || finalKeyType == SymmetricKey.Type.DES) ++ { ++ encryptor = token.getCipherContext(EncryptionAlgorithm.DES3_ECB); ++ } ++ else if (finalKeyType == SymmetricKey.Type.AES && inputKeyArray.length == DEF_AES_KEYLENGTH) ++ { ++ encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC); ++ } ++ else ++ { ++ encryptor = token.getCipherContext(EncryptionAlgorithm.AES_256_CBC); + } + +- encryptor = token.getCipherContext(encAlg); +- +- encryptor.initEncrypt(encUnwrapKey,iv); +- ++ encryptor.initEncrypt(encUnwrapKey); + + if (finalKeyArray != null) { + if(finalKeyType == SymmetricKey.Type.DES3 || finalKeyType == SymmetricKey.Type.DES) +@@ -1036,12 +1062,22 @@ public class SecureChannelProtocol { + wrappedKey = encryptor.doFinal(inputKeyArray); + } + +- CMS.debug(method + " done enrypting data"); ++ CMS.debug(method + " done encrypting data"); + + // SecureChannelProtocol.debugByteArray(wrappedKey, " encrypted key"); + +- KeyWrapper keyWrap = token.getKeyWrapper(wrapAlg); +- keyWrap.initUnwrap(encUnwrapKey, iv); ++ //Differentiate between DES3, DES and AES ++ KeyWrapper keyWrap = null; ++ if(finalKeyType == SymmetricKey.Type.DES3 || finalKeyType == SymmetricKey.Type.DES) ++ { ++ keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.DES3_ECB); ++ } ++ else ++ { ++ keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC); ++ } ++ ++ keyWrap.initUnwrap(encUnwrapKey, null); + + if (isPerm == true) { + unwrapped = keyWrap.unwrapSymmetricPerm(wrappedKey, +@@ -1059,7 +1095,7 @@ public class SecureChannelProtocol { + } + } + +- //CMS.debug(method + "Returning symkey: " + unwrapped); ++ //CMS.debug(method + "Returning symkey: length = " + unwrapped.getLength()); + CMS.debug(method + "Returning symkey..."); + + return unwrapped; +@@ -1084,13 +1120,13 @@ public class SecureChannelProtocol { + } + + if(keyType == SymmetricKey.Type.AES) { +- if(inputKeyArray.length != DEF_AES_KEYLENGTH) +- throw new EBaseException(method + "Invalid length of raw input array."); ++ if(inputKeyArray.length != DEF_AES_KEYLENGTH && inputKeyArray.length != DEF_AES_256_KEYLENGTH) ++ throw new EBaseException(method + "Invalid length of raw AES input array."); + } + else if(keyType == SymmetricKey.Type.DES || + keyType == SymmetricKey.Type.DES3) { + if(inputKeyArray.length != DES3_LENGTH && inputKeyArray.length != DES2_LENGTH) +- throw new EBaseException(method + "Invalid length of raw input array."); ++ throw new EBaseException(method + "Invalid length of raw DES input array."); + } + + try { +@@ -1098,7 +1134,8 @@ public class SecureChannelProtocol { + + if(unwrappingKey.getType() == SymmetricKey.Type.AES) + { +- IVParameterSpec iv = new IVParameterSpec(new byte[EncryptionAlgorithm.AES_128_CBC.getIVLength()]); ++ // Set iv based on key length ++ IVParameterSpec iv = new IVParameterSpec(new byte[unwrappingKey.getLength()]); + keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC); + keyWrap.initUnwrap(unwrappingKey, iv); + } +@@ -1128,7 +1165,7 @@ public class SecureChannelProtocol { + throw new EBaseException(e); + } + +- //CMS.debug(method + "Returning symkey: " + unwrapped); ++ //CMS.debug(method + "Returning symkey: length = " + unwrapped.getLength()); + CMS.debug(method + "Returning symkey..."); + + if (finalUnwrapped != null) +@@ -1145,7 +1182,7 @@ public class SecureChannelProtocol { + SymmetricKey unwrapped = null; + + if (token == null) { +- throw new EBaseException(method + "Invalide crypto token!"); ++ throw new EBaseException(method + "Invalid crypto token!"); + } + + if (inputKeyArray == null || (inputKeyArray.length != DES3_LENGTH && inputKeyArray.length != DES2_LENGTH)) { +@@ -1155,7 +1192,8 @@ public class SecureChannelProtocol { + SymmetricKey transport = getSharedSecretKey(token); + unwrapped = this.unwrapSymKeyOnToken(token, transport, inputKeyArray, isPerm, SymmetricKey.DES3); + +-// CMS.debug(method + "Returning symkey: " + unwrapped); ++ CMS.debug(method + "Returning symkey: length = " + unwrapped.getLength()); ++ //CMS.debug(method + "Returning symkey: " + unwrapped); + + return unwrapped; + } +@@ -1344,7 +1382,7 @@ public class SecureChannelProtocol { + + result = this.wrapSessionKey(selectedToken, des2, devKey); + +- // SecureChannelProtocol.debugByteArray(result, " Wrapped des2 key"); ++ //SecureChannelProtocol.debugByteArray(result, " Wrapped des2 key"); + + return result; + } +@@ -1482,6 +1520,7 @@ public class SecureChannelProtocol { + CryptoToken token = returnTokenByName(tokenName, cm); + + int ivLength = EncryptionAlgorithm.AES_128_CBC.getIVLength(); ++ //CMS.debug(method + " Set iv length to " + ivLength); + byte[] iv = null; + + if (ivLength > 0) { +@@ -1492,14 +1531,12 @@ public class SecureChannelProtocol { + keyWrap.initWrap(wrapper, new IVParameterSpec(iv)); + wrappedSessKeyData = keyWrap.wrap(sessionKey); + +- + } catch (Exception e) { + CMS.debug(method + " " + e); + throw new EBaseException(e); + } + } + +- + //SecureChannelProtocol.debugByteArray(wrappedSessKeyData, "wrappedSessKeyData"); + CMS.debug(method + " returning session key"); + +@@ -1520,20 +1557,21 @@ public class SecureChannelProtocol { + } + + if (iv == null) { +- finalIv = new byte[16]; +- ++ // Set iv based on key length ++ finalIv = new byte[DEF_AES_KEYLENGTH]; + } else { + finalIv = iv; + } + ++ //CMS.debug(method + ": iv length = " + finalIv.length); ++ + try { + CryptoManager cm = this.getCryptoManger(); + CryptoToken token = returnTokenByName(selectedToken, cm); + Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.AES_128_CBC); + encryptor.initEncrypt(symKey, new IVParameterSpec(finalIv)); + output = encryptor.doFinal(input); +- +-// SecureChannelProtocol.debugByteArray(output, "Encrypted data:"); ++ //SecureChannelProtocol.debugByteArray(output, "AES CBC Encrypted data:"); + } catch (Exception e) { + + CMS.debug(method + e); +@@ -1565,15 +1603,14 @@ public class SecureChannelProtocol { + output = encryptor.doFinal(input); + //CMS.debug(method + "done doFinal " + output); + CMS.debug(method + "done doFinal"); +- +- // SecureChannelProtocol.debugByteArray(output, "Encrypted data:"); ++ //SecureChannelProtocol.debugByteArray(output, "Encrypted data:"); + } catch (Exception e) { + + CMS.debug(method + e); + throw new EBaseException(method + e); + } + CMS.debug("returning encrypted output."); +- // SecureChannelProtocol.debugByteArray(output, "Encrypted data before leaving:"); ++ //SecureChannelProtocol.debugByteArray(output, "Encrypted data before leaving:"); + + return output; + } +@@ -1590,7 +1627,6 @@ public class SecureChannelProtocol { + byte[] key_check_message = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; + //zero iv vector + byte[] key_check_iv = new byte[16]; +- + byte[] output = null; + byte[] finalOutput = new byte[3]; + +@@ -1613,7 +1649,7 @@ public class SecureChannelProtocol { + //AES, uses AES_CMAC alg to do the work. + public byte[] computeCryptogram_SCP03(SymmetricKey symKey, String selectedToken, byte[] context, byte cryptoType) + throws EBaseException { +- String method = "SecureChannelProtocol.computeCryptogram_"; ++ String method = "SecureChannelProtocol.computeCryptogram_SCP03"; + + CMS.debug(method + " entering .."); + +@@ -1624,12 +1660,15 @@ public class SecureChannelProtocol { + + NistSP800_108KDF nistKdf = new NistSP800_108KDF(this); + byte[] crypto = nistKdf.kdf_AES_CMAC_SCP03(symKey, context, cryptoType, 8); ++ + //SecureChannelProtocol.debugByteArray(crypto, " calculated cryptogram"); + + byte[] finalCrypto = new byte[8]; + + System.arraycopy(crypto, 0, finalCrypto, 0, 8); + ++ //SecureChannelProtocol.debugByteArray(finalCrypto, " final cryptogram"); ++ + return finalCrypto; + } + +@@ -1787,9 +1826,9 @@ public class SecureChannelProtocol { + CMS.debug(method + " oldMasterKeyName: " + oldMasterKeyName); + CMS.debug(method + " newMasterKeyName: " + newMasterKeyName); + +-// SecureChannelProtocol.debugByteArray(encKeyArray, " Developer enc key array: "); +-// SecureChannelProtocol.debugByteArray(macKeyArray, " Developer mac key array: "); +-// SecureChannelProtocol.debugByteArray(kekKeyArray, " Developer kek key array: "); ++ //SecureChannelProtocol.debugByteArray(encKeyArray, " Developer enc key array: "); ++ //SecureChannelProtocol.debugByteArray(macKeyArray, " Developer mac key array: "); ++ //SecureChannelProtocol.debugByteArray(kekKeyArray, " Developer kek key array: "); + + SymmetricKey masterKey = null; + SymmetricKey oldMasterKey = null; +@@ -1856,8 +1895,8 @@ public class SecureChannelProtocol { + } + } + +-// SecureChannelProtocol.debugByteArray(oldKeyInfo, " oldKeyInfo: "); +-// SecureChannelProtocol.debugByteArray(newKeyInfo, " newKeyInfo: "); ++ //SecureChannelProtocol.debugByteArray(oldKeyInfo, " oldKeyInfo: "); ++ //SecureChannelProtocol.debugByteArray(newKeyInfo, " newKeyInfo: "); + + byte oldKeyVersion = oldKeyInfo[0]; + byte newKeyVersion = newKeyInfo[0]; +@@ -2016,16 +2055,16 @@ public class SecureChannelProtocol { + + } + +- boolean showKeysForDebug = false; ++ boolean showKeysForDebug = checkAllowDebugKeyRollover(); + + if (showKeysForDebug == true) { +- try { +- SecureChannelProtocol.debugByteArray(encKey.getKeyData(), "DiversifyKey: new encKey: "); +- SecureChannelProtocol.debugByteArray(macKey.getKeyData(), "DiversifyKey: new macKey:"); +- SecureChannelProtocol.debugByteArray(kekKey.getKeyData(), "DiversifyKey: new kekKey"); +- } catch (NotExtractableException e) { +- CMS.debug(method + " Can not display debugging info for key"); +- } ++ byte[] enc = debugAESKeyToBytes(token,encKey); ++ byte[] mac = debugAESKeyToBytes(token,macKey); ++ byte[] kek = debugAESKeyToBytes(token,kekKey); ++ ++ SecureChannelProtocol.debugByteArray(enc, "DiversifyKey: new encKey: "); ++ SecureChannelProtocol.debugByteArray(mac, "DiversifyKey: new macKey:"); ++ SecureChannelProtocol.debugByteArray(kek, "DiversifyKey: new kekKey"); + } + + if (old_kek_sym_key != null) { +@@ -2108,7 +2147,7 @@ public class SecureChannelProtocol { + byte[] keycheck_enc_key = null; + byte[] keycheck_mac_key = null; + byte[] keycheck_kek_key = null; +- ++ + if (protocol == PROTOCOL_ONE) { + if (old_kek_sym_key == null) { + CMS.debug(method + " Using old kek key array."); +@@ -2170,10 +2209,20 @@ public class SecureChannelProtocol { + byte[] b1 = null; + byte[] b2 = null; + +- if (protocol == PROTOCOL_THREE) { ++ if (protocol == PROTOCOL_THREE) ++ { + //Will be different if the key is bigger than AES 128 + // Support 128 for now +- b1 = new byte[] { alg, 0x11, (byte) encrypted_enc_key.length }; ++ // Added support for AES 256 keys ++ //CMS.debug(method + " encrypted_enc_key length = " + encrypted_enc_key.length); ++ if (encrypted_enc_key.length == DEF_AES_256_KEYLENGTH) ++ { ++ b1 = new byte[] { alg, 0x21, (byte) encrypted_enc_key.length }; ++ } ++ else ++ { ++ b1 = new byte[] { alg, 0x11, (byte) encrypted_enc_key.length }; ++ } + } else { + b1 = new byte[] { alg, 0x10 }; + } +@@ -2205,7 +2254,7 @@ public class SecureChannelProtocol { + throw new EBaseException(method + " Can't compose final output byte array!"); + } + +-// SecureChannelProtocol.debugByteArray(output, " Final output to createKeySetData: "); ++ //SecureChannelProtocol.debugByteArray(output, " Final output to createKeySetData: "); + CMS.debug(method + " returning output"); + + return output; +@@ -2286,7 +2335,7 @@ public class SecureChannelProtocol { + byte[] output = null; + output = computeAES_CBCEncryption(kekKey, selectedToken, data, null); + +-// debugByteArray(output, method + " encryptData: Output: "); ++ //debugByteArray(output, method + " encryptData: Output: "); + + return output; + } +@@ -2319,7 +2368,7 @@ public class SecureChannelProtocol { + + byte[] output = computeDes3EcbEncryption(kekKey, selectedToken, data); + +- // debugByteArray(output, " encryptData: Output: "); ++ //debugByteArray(output, " encryptData: Output: "); + + return output; + } +@@ -2346,5 +2395,69 @@ public class SecureChannelProtocol { + + return symKey; + } ++ private static byte[] debugAESKeyToBytes(CryptoToken token,SymmetricKey aesKey) { ++ KeyGenerator kg; ++ SymmetricKey sessionKey; ++ byte[] result = null; ++ ++ if(token == null || aesKey == null) { ++ return result; ++ } ++ ++ try { ++ kg = token.getKeyGenerator(KeyGenAlgorithm.AES); ++ ++ SymmetricKey.Usage usages[] = new SymmetricKey.Usage[4]; ++ usages[0] = SymmetricKey.Usage.WRAP; ++ usages[1] = SymmetricKey.Usage.UNWRAP; ++ usages[2] = SymmetricKey.Usage.ENCRYPT; ++ usages[3] = SymmetricKey.Usage.DECRYPT; ++ ++ kg.setKeyUsages(usages); ++ kg.temporaryKeys(true); ++ // Handle 128 and 256 initialization sizes ++ kg.initialize(256); ++ SymmetricKey tempKey = kg.generate(); ++ ++ // Now wrap and unwrap with AES CBC PAD ++ ++ KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC_PAD); ++ int ivLen = KeyWrapAlgorithm.AES_CBC_PAD.getBlockSize(); ++ byte[] iv = new byte[ivLen]; ++ ++ IVParameterSpec ivsp = new IVParameterSpec(iv); ++ keyWrap.initWrap(tempKey, ivsp); ++ byte [] wrapped = keyWrap.wrap(aesKey); ++ ++ Cipher decryptor = token.getCipherContext(EncryptionAlgorithm.AES_256_CBC_PAD); ++ decryptor.initDecrypt(tempKey,ivsp); ++ result = decryptor.doFinal(wrapped); ++ ++ } catch (Exception e) { ++ return result; ++ } ++ ++ return result; ++ } ++ ++ private boolean checkAllowDebugKeyRollover() { ++ boolean allow = false; ++ ++ String method = "SecureChannelProtocol.checkAllowDebugKeyRollover: "; ++ IConfigStore cs = CMS.getConfigStore(); ++ ++ String allowDebugKeyRollover = "tks.debugKeyRollover"; ++ ++ //CMS.debug(method + " trying config: " + allowDebugKeyRollover); ++ ++ try { ++ allow = cs.getBoolean("tks.useNewSharedSecretNames", false); ++ } catch (EBaseException e) { ++ allow = false; ++ } ++ ++ //CMS.debug(method + "returning allow: " + allow); ++ return allow; ++ } + + } +diff --git a/base/tks/shared/conf/CS.cfg b/base/tks/shared/conf/CS.cfg +index 87819f7..f5e990c 100644 +--- a/base/tks/shared/conf/CS.cfg ++++ b/base/tks/shared/conf/CS.cfg +@@ -349,19 +349,30 @@ tks.defKeySet._007=## diversVer1 = emv,visa2, or none. This is for developer or + tks.defKeySet._008=## devKeyType = DES3or AES. This is for the key type of developer or version one keys. + tks.defKeySet._009=## masterKeyType = DES3 or AES. This is for the type of key for the master key. + tks.defKeySet._010=## +-tks.defKeySet._011=## Only supports two tokens now: G&D Smart Cafe 6 and Smart Cafe 7, use these exact settings ++tks.defKeySet._011=## Major supported tokens now: G&D Smart Cafe 6 and Smart Cafe 7, Cosmo Idemia use these exact settings + tks.defKeySet._013=## Smart Cafe 6 settings: + tks.defKeySet._014=## tks.defKeySet.prot3.divers=emv + tks.defKeySet._015=## tks.defKeySet.prot3.diversVer1Keys=emv + tks.defKeySet._016=## tks.defKeySet.prot3.devKeyType=DES3 + tks.defKeySet._017=## tks.defKeySet.prot3.masterKeyType=DES3 + tks.defKeySet._018=##Smart Cafe 7 settings: +-tks.defKeySet._019=## tks.defKeySet.prot3.divers=none ++tks.defKeySet._019=## tks.defKeySet.prot3.divers=gpkmc + tks.defKeySet._020=## tks.defKeySet.prot3.diversVer1Keys=none + tks.defKeySet._021=## tks.defKeySet.prot3.devKeyType=AES + tks.defKeySet._022=## tks.defKeySet.prot3.masterKeyType=AES + tks.defKeySet._023=## +-tks.defKeySet._024=## ++tks.defKeySet._024=##Cosmo Idemia settings: ++tks.defKeySet._025=## tks.defKeySet.prot3.divers=gpkmc ++tks.defKeySet._026=## tks.defKeySet.prot3.diversVer1Keys=gpkmc ++tks.defKeySet._027=## tks.defKeySet.prot3.defKeyType=AES ++tks.defKeySet._028=## tks.defKeySet.prot3.masterKeyType=AES ++tks.defKeySet._029=## Static keyset for AES 256 bit secure channel support for SP03 tokens, Cosmo Idemia or g&d 7.0 with static keys rolled over to 256 bits: ++tks.defKeySet._030=## tks.defKeySet.auth_key=#10#11#12#13#14#15#16#17#18#19#1A#1B#1C#1D#1E#1F#20#21#22#23#24#25#26#27#28#29#2A#2B#2C#2D#2E#2F ++tks.defKeySet._031=## tks.defKeySet.kek_key=#10#11#12#13#14#15#16#17#18#19#1A#1B#1C#1D#1E#1F#20#21#22#23#24#25#26#27#28#29#2A#2B#2C#2D#2E#2F ++tks.defKeySet._032=## tks.defKeySet.mac_key=#10#11#12#13#14#15#16#17#18#19#1A#1B#1C#1D#1E#1F#20#21#22#23#24#25#26#27#28#29#2A#2B#2C#2D#2E#2F ++tks.defKeySet._033=## ++tks.defKeySet._034=## The following represents the default 128 bit static keys for legacy tokens or the g&d 7.0 in 128 bit mode. ++tks.defKeySet._035=## Set them to the above 256 bit (32 bytes) values if using 256 bit AES secure channel. + tks.defKeySet.auth_key=#40#41#42#43#44#45#46#47#48#49#4a#4b#4c#4d#4e#4f + tks.defKeySet.mac_key=#40#41#42#43#44#45#46#47#48#49#4a#4b#4c#4d#4e#4f + tks.defKeySet.kek_key=#40#41#42#43#44#45#46#47#48#49#4a#4b#4c#4d#4e#4f +diff --git a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java +index feeeca1..f77d873 100644 +--- a/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java ++++ b/base/tks/src/org/dogtagpki/server/tks/rest/TPSConnectorService.java +@@ -50,6 +50,7 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + IConfigStore cs = CMS.getConfigStore(); + + public static final int AES_SESS_KEYSIZE = 128; ++ public static final int AES_SESS_KEYSIZE_256 = 256; + public IUGSubsystem userGroupManager = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + + @Override +@@ -314,14 +315,14 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + } + + // CryptoUtil.createSharedSecret(nickname); +- CryptoUtil.createSharedSecret(nickname,KeyGenAlgorithm.AES,AES_SESS_KEYSIZE); ++ CryptoUtil.createSharedSecret(nickname,KeyGenAlgorithm.AES,AES_SESS_KEYSIZE_256); + + cs.putString("tps." + id + ".nickname", nickname); + cs.commit(true); + + //Create aes session sym key to wrap the shared secret. + // SymmetricKey tempKey = createDes3SessionKeyOnInternal(); +- SymmetricKey tempKey = CryptoUtil.createAESSessionKeyOnInternal(AES_SESS_KEYSIZE); ++ SymmetricKey tempKey = CryptoUtil.createAESSessionKeyOnInternal(AES_SESS_KEYSIZE_256); + + if (tempKey == null) { + return createNoContentResponse(); +@@ -392,11 +393,11 @@ public class TPSConnectorService extends PKIService implements TPSConnectorResou + X509Certificate[] certs = user.getX509Certificates(); + + CryptoUtil.deleteSharedSecret(nickname); +- CryptoUtil.createSharedSecret(nickname,KeyGenAlgorithm.AES,AES_SESS_KEYSIZE); ++ CryptoUtil.createSharedSecret(nickname,KeyGenAlgorithm.AES,AES_SESS_KEYSIZE_256); + // CryptoUtil.createSharedSecret(nickname); + + // Create aes session sym key to wrap the shared secret. +- SymmetricKey tempKey = CryptoUtil.createAESSessionKeyOnInternal(AES_SESS_KEYSIZE); ++ SymmetricKey tempKey = CryptoUtil.createAESSessionKeyOnInternal(AES_SESS_KEYSIZE_256); + + //Create des3 session sym key to wrap the shared secret. + //SymmetricKey tempKey = createDes3SessionKeyOnInternal(); +diff --git a/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java b/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java +index 49ebe60..f5dd932 100644 +--- a/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java ++++ b/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java +@@ -1226,10 +1226,9 @@ public class TokenServlet extends CMSServlet { + // get keycheck + + byte[] keycheck = protocol.computeKeyCheck(desKey, selectedToken); +- /* +- CMS.debug("computeSessionKey:keycheck size = "+keycheck.length); +- CMS.debug(keycheck); +- */ ++ //CMS.debug("computeSessionKey:keycheck size = "+keycheck.length); ++ //CMS.debug(keycheck); ++ + keycheck_s = + com.netscape.cmsutil.util.Utils.SpecialEncode(keycheck); + +@@ -2227,7 +2226,7 @@ CMS.debug("4"); + + } + +-// SecureChannelProtocol.debugByteArray(encryptedData, "New Encrypt Data: "); ++ //SecureChannelProtocol.debugByteArray(encryptedData, "New Encrypt Data: "); + + // AC: KDF SPEC CHANGE - Log both CUID and KDD + +@@ -2533,6 +2532,7 @@ CMS.debug("4"); + String errorMsg = ""; + String badParams = ""; + String transportKeyName = ""; ++ + String rCUID = req.getParameter(IRemoteRequest.TOKEN_CUID); + + String rKDD = req.getParameter("KDD"); +@@ -2739,6 +2739,11 @@ CMS.debug("4"); + CMS.debug("TokenServlet about to try ComputeSessionKey selectedToken=" + + selectedToken + " keyNickName=" + keyNickName); + ++ //SecureChannelProtocol.debugByteArray(macKeyArray, method + " macKeyArray: " + macKeyArray.length); ++ //SecureChannelProtocol.debugByteArray(xKDD, method + " xKDD: " + xKDD.length); ++ //SecureChannelProtocol.debugByteArray(xhost_challenge, method + " xhost_challenge: " + xhost_challenge.length); ++ //SecureChannelProtocol.debugByteArray(xcard_challenge, method + " xcard_challenge: " + xcard_challenge.length); ++ + SecureChannelProtocol protocol = new SecureChannelProtocol(SecureChannelProtocol.PROTOCOL_THREE); + + macSessionKey = protocol.computeSessionKey_SCP03(selectedToken, keyNickName,xkeyInfo, +@@ -2780,7 +2785,6 @@ CMS.debug("4"); + + kek_session_key = protocol.wrapSessionKey(selectedToken, kekSessionKey, null); + +- + //Offload some of the tedious params gathering to another method + //ToDo, create a method that reads all this stuff at once for all major methods + if (serversideKeygen) { +@@ -2789,7 +2793,7 @@ CMS.debug("4"); + kekSessionKey, protocol); + } catch (EBaseException e) { + +- CMS.debug(method + " Can't calcualte server side keygen required values..."); ++ CMS.debug(method + " Can't calculate server side keygen required values..."); + + } + } +@@ -2808,8 +2812,8 @@ CMS.debug("4"); + } + + host_cryptogram = protocol.computeCryptogram_SCP03(macSessionKey, selectedToken, contextStream.toByteArray(),NistSP800_108KDF.HOST_CRYPTO_KDF_CONSTANT); +-// SecureChannelProtocol.debugByteArray(host_cryptogram, method + " calculated host crypto: " + host_cryptogram.length); +- ++ //CMS.debug("TokenServlet: NistSP800_108KDF.HOST_CRYPTO_KDF_CONSTANT = " + NistSP800_108KDF.HOST_CRYPTO_KDF_CONSTANT); ++ //SecureChannelProtocol.debugByteArray(host_cryptogram, method + " calculated host crypto: " + host_cryptogram.length); + + if( isCryptoValidate) { + if (rcard_cryptogram == null) { +@@ -2818,9 +2822,10 @@ CMS.debug("4"); + } + input_card_crypto = + com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_cryptogram); ++ + card_crypto = protocol.computeCryptogram_SCP03(macSessionKey, selectedToken, contextStream.toByteArray(),NistSP800_108KDF.CARD_CRYPTO_KDF_CONSTANT); +-// SecureChannelProtocol.debugByteArray(card_crypto, method + " calculated card crypto: "); +-// SecureChannelProtocol.debugByteArray(input_card_crypto, method + " original card crypto: "); ++ //SecureChannelProtocol.debugByteArray(card_crypto, method + " calculated card crypto: "); ++ //SecureChannelProtocol.debugByteArray(input_card_crypto, method + " original card crypto: "); + + if(!cryptoGramsAreEqual(input_card_crypto, card_crypto)) { + throw new Exception(method + "Card cryptogram mismatch!"); +@@ -3004,6 +3009,7 @@ CMS.debug("4"); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_EncSessionKey + "="); + sb.append(encSessionKeyString); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_KekSessionKey + "="); ++ sb.append(kekSessionKeyString); + value = sb.toString(); + } + +@@ -3283,7 +3289,7 @@ CMS.debug("4"); + String drmWrappedDesStr = + com.netscape.cmsutil.util.Utils.SpecialEncode(drm_trans_wrapped_desKey); + +-// CMS.debug(method + " drmWrappedDesStr: " + drmWrappedDesStr); ++ //CMS.debug(method + " drmWrappedDesStr: " + drmWrappedDesStr); + values.add(drmWrappedDesStr); + + byte[] drm_trans_wrapped_aesKey = keyWrapper.wrap(aesKey); +diff --git a/base/tps/shared/applets/1.5.65cbf5a6.ijc b/base/tps/shared/applets/1.5.65cbf5a6.ijc +new file mode 100644 +index 0000000000000000000000000000000000000000..ac27c4646fc503e58f0841b16c49a97d3799eb2e +GIT binary patch +literal 17969 +zcmc(He|%g=b?@Anxxer3-d*ip-CcQiC0UYpEyyh4TX^1jP>{JMj-J +z|JafQ#D-U71yGFbI3x`v#gvpEiQBN2Tl}Df^2(z;%CFb*Uef|?N_iNhjy&M<=sR?syjSw&}>`8Z>27t{0>q%A|doyRq%8NkzSK~+~XqZU~2 +z*9`V?HU~nQW`W8*>^?Tnjv(H&9vgDb(Pokz}m= +znYHWJK0oLVhJ*RRzQN(aD+YHD9vXbd;JLv+9Q^X&w+5dDt^jU~v7zG7+M$g@TZU>w +z$A?}XP7i-{_}uW1)@kc@14q|1&0}ocQ|msx?%8$c*Y~ZzcK!DC3+qp=|H%5r`fr*e +zn_cVdoMnBMZA;6!L^{Lf(znjV(|57C{F%AS^DnS%g$;AN3!h-D@QFE2ac_Li?d@XQ +z25z162lgPIoeKs>2^Rj#FHEVJ=?!8QUiO@HqSHP#k5UJgSBIQ63ul3HG4{QRjX` +z=mWD9$tV(twiFA8tmLV0o?tIz3;nakt)gre3wrh7Qsxxb`pbHt@4PU_5P@-moiCe# +zkz{k*rYDg0-?fdhtYRUsmM8?4ez;W?v;%9(YVHmK)3>&YY=MZQ%57z{_8j^Zn3pw# +zCMsP +z-Mip~e)xX&@dX$0L+*kXCfP%XV^K1$N?)^(Q1KNDzKZ|jLK3xsl?r_yQ3oo04{9Kr3G43U`SI2sQPP+ZN-@V#B%zk1wE7~JFt)oiNt}0uF#JuU{&bH6_5`lp**=z +zKsPX{U~btGWjl~}>8G`IffdNZ0Qw;YvRWMtB*hck%Q8ZUDf|`|YhE0SJx5p=q@u;X +zgE$X)$=YS2?258S#Js>$#0COy +zcXF8^6}bvG7P!-P7`Sp9gy|&v-sV6*&i>~@5%525ZWNERe_H6q3hqJZg}|*w=!01H +zBMbmuQ^!qTA1K^n?i()+JU*EMh0v9YO3ymUPdZ{$JlFkrbBS!nlLGz +zKhCaAp5n`;io!8=okFNXi7g2+*mXY+R^yxU{YCv4`p4A53Qr`Ip2g#2iCo;MEe7a;kzqWvVE)U6pe|pTMHVc +zk}b;4Vi^fLc`88f>Vc~-(aqR_bAsInfpGP}t0MnYmT(#ngT7L%v6dupEHLk8UqS>XNKuF$#gDU_OUc07na(6LvA{HDbiF1p +zLATU$7v#|J^lIQ8W3R7a>e57D&XDP4cG3tTFwuC;hEKz`tg@$H#B2-3erx95I_QBffV89e1urkX<|F_iS1}L?VDBKx~81SSjX6{C&NN(XE3&_@M6_xD +zy`|=rIy0Te*c;I-^3YO{02R)UvD-1gRFI)jHC3lVRS=}8m0v|GLN%vSK7?h8FkOY2 +zaYX>damV;nf(N!f1Lc@FTCQ~liIv070_hmrE@tIbO2i`Rf?;wu?8^4~>13VJ`l{~#NEgAnc|mCf+G^3rWvxa+ +z7P2)F@g22t1iYCxs+~WsIXWX>490W--4y^ +z$_#9-q&!Qe7@>!O2^L@8=nnM2IL4-@G4Sbll*CN$q>iJ}Hd!kw3D6{jYZo-=25_-L +z{Gt9^%l+RK!)|lXqJ3r$XsF&pm13Uc@+M%>mbbKF0QV%jcQa5?RQE9RS_$OX5}r$V?yKVEii^E1(piBHY_IEkr=&KeH@lSbUV@cyO-VkbzY-XCiyo{7 +z8+!3^_Jrta|FKVoc^GWi+TQ}pa(@XN*V~g0azw&zkeM}DCu37T9L2f|oAm9ARd!ybvhj13-3$7GP5u}A +z0Y$K)A8HDzA2aCa%Ax!5i&cgyzi8#y&sFv>Ryp}9mF=IaoVr-$j#sJd{9NVq#VTiB +zr81;Qjky+Yi=Hy5*hpO`CD~RI?LDCAyKVCts$wUdD~D=vQX!2+K{K0-#T*r?EzN4vXULWm(Ir?qUV3tm3(=I4t*0<9pl0s=+&~DMzh(F)R(n+JOv#@`3Myd^#GFIW%+al%mTuzV@ +zxnn#lu>y1O{&#;n9W!LsH;QL +zeRbL0D2c@~_Jb?O$pWnFYVZBOKi387WY-qF3l3c&ZMfU9Cr`(5{v!BQ&R=xkdS{qz +z48y^2oZT1A>@R=DgjA7;E0IzifKej?eJo2Sj8~sgW&c!KJ34lDW$Nflvj_VOvuCtt +zugGV5F@xCfB{uv{QMTx)7J}n?^=KJq1G6^P=vE%3yHG~kZpjX;m2+j$T>WZ$t}snd +zx^+6y2Iiq8P2C}EscMGEpo&htah!<2xhna^o*A$6QAlTn`1LO0lBDHyGsdoL2Z;I! +zcBG_d^z4HiZc41D)s#BM?oS?K`@IM{$Z*U!OtwZ1Wsl%o{_gQC8RG8=h3c6i(%;- +z$Z^m{gw|Q2Jq@-<)xtblfPjgjRmD~@&&Mz9#D$1(HyvjS(4g%FP4tUx@lj@GWTsn1 +z9JD5&p#rHqU)Y9s!atWl?b<5JBx$8gJ6!BN+CyqdS@+}^nbnM{%0D^{pkOA}HVXPqwJ`kt?KU@+K%7Y_` +z{7uWbIAhuUd_SGF?Eb)+=>Xs$BdOv*sjvdE4IP4+BgYir0Dxx|cAr%{Nv=1vb8xbS +zgEe*uY(Beh&#;Qr)-l}^1~!)X14~j(7*xclX+Ab(Yqig=7&h6rzu-T*PMROyJOtPfd{&?I%{2t0r&}=_za5F7G~Z=kdB-P +zBL5{^K4hC(z~0$`lAUo;k!9&8$~f(l93*B;4y}=co`ER)79GabwrA1y1dloS*un#l +z1IlfFR3t)k +zu$FNUd?6RukSd&Rx52~c`aW=#4+8mm)%ROP@Jo`Q!fW^ft>suIrpg1C7NRJ}gLqW4 +z8whlM#V!Uz`F-e1qofB=_Q&8Du*jj|V?T-x?9jwim_RGaqCmojx2hUt27VRi{t(WY +z$c0fQPu%e+1vQDo-idOuRR~VpF&+{gN|I31Ic#|=_IhJpZJ2&~0@GB?phM(DcxHUc +zdg(s)pimiDgOt&vgc!rO0a}oS34H>t!z;%rN74d9EXKmT?~$*|&cFkZ?}K#SlCh~M +zFzFi}jag%F+ast>KRF+ax3E|wmZziQ;tZB)5lNq-K$&l}Si!ZG=Zvrjs?n+ABpg+s +zP=w1KEFLSuAS=5K_=KbLp34b_cYww|6{P~q*&XAMnKmj$vs8E?sw&CYkfZ%#8Y3fs +zHQ?yz+q=4vDE95mQ{p6h&1Q_%InExs6uGMW(pra#32PtZ1l@T-Wt6-O%>Vai?6M{y+;&WKXDSU5I8q8kxib@B(FMt9(RK!%L6Vj`En2vy!=S_X7@J2I +zXU2TL3>TaTLRbd42ZHm+g$}(*HdZxsU0n;obBhF_G)h4Tfgi68tEAfX8f0go##X)2 +z)sVD25U)h0N@|?43iUZPosPOu^Ma1HqQR{Q*;P<9WR2Od#^BEOu)RiJ^Xtj5A`AE~ +zWGXWZ9?X?yn0JB63~ZIL(k_Dt*2^yWGihVZ63{O{#=auTIdI`)?7`)MV=f<<+1SW8 +zbZkJkgpE8Qo7KQICzc@;{Tiy~9)lrvsux^6&FYN;sw{D=u#6l*C{kFeLZq-RRza1laH);bxsw|B^|7LyaiVhp&YJSf>N9=S?J(3}tQisq +z2KYv{*Lg*qQz38B>eaDEKS)*y89BtZx<1;r9*ejSY;U8u63o$cDD4b6Mk{yOROoSyvg69lw|Cq`)V +zUxBx%jGvsos0^K)xd@etYQAyC2203agkyYEsXf#)Ht_-+#Z4V4VBBa&8u+LQfE>w3 +zEdXvmZX{80utI23MvPp`~xz3pgkV_hCs_0`L8x%Iu+|?z;TIv=fz1T&7Z@-m1oL +z--e1#zV8@2wb;AUQ&g3()&*4*mxXycZSkZS$-{||Cfq$HWnPnq&t#SSc>{Y@3em45I?v55HQGez77s((v-6peF||t)(af_dNw#V8nGwzg@p7 +zEF5PahT9IN#@;moK67&$d7UwzumJNg2!LC?w6>|FN13%DLX8Z@u-`)FP3&fm?}!98rTPB@6WSb_Di +zwQPtDnX}d`nvZPI=-WWwT8F1u^>*cB*yk{edA+e-$g#TCBS!Q0venFF71qNxA#6c- +zJ;JRBZ$P+%^~liz)yDM(w#iQ{l0c-Kv0=wTQ7KS6>LksKha^VDfVqtx|WCT|X +zYp^Kkd`@Qi>1j*(@PE5_uNGrL^JVtK=1sImETBzdR +zRhNdx*;kjx+Y7VkYuH^Lf<6AinKe5Nyc7C5M6+K(-=Jq2qzZ>~0`8rAF;2ZX$9kLZ +zW^0=tXW8aimcvW5Y&2p2t<}t*wwn1fG;@gP)-{}-BB{rjyO1x)iER@Ve3vCQXB<`o +zeb)UAdNMUprWXf|k&>I;gR{yWJ-1il`q%XRnL@U8c5wsj0=Ji)no;t^?3DA<)9i~l +z%h?Bk8D_PNOGmp1m%Liv1icdWwv$sr^A|quKc9;G4Lk)|f;(5hWLLLwvMm_KZz7XedXzP? +z$8U^0>{~N-BTJt3r?Y#UjND^nOf|Fc>Kt$cENAPw{fdbs11>u6(sTxPMm`+q6Nd?Q +zcKR7SucJ3EQ{`8Mb!Fof?kIx`8H +zyk)i%XKAfu;CY(|F{7amX3a&Pcd|^lHQsa8CIL+@A*S +zEbmtDB(;UnkRPp(h443ILyYc$v607%ywS#}fUg~QCZoDCQL)l1b36eqcKnx|3&#G1k^bx!!fPWg^XnC|!Lm6CK +zkJFHmCBVszPUAtEYT1ApanO`y +zy@q>}3cZ%A{cWI6Z_F3a#LT(^VS)tgn9)2s4JR7kpNM*(%*vXHrE*kNM9D^!(0ELE +z)v9^e9ispWXy}gdS|=zh_Zve{-L559WQTcTSZc9?*J*jaKSb-)|EfMg&8rTN)Skz_ +zjRE9!OwEn@#H{8wMq$Vxr+-$AASzV*XZ2}nT2`}Q-wF2J@w({HM=%lKelFsErIrxr7{2FBDf)v-$)IXsj@8s>j&h +z$`+Ney4a!+ieq(s8h5WM(e9Y)GSynbQi&yL+W=|1B+M?TxGt)V4S7F4fpfvLq+<$g +zTU3sqRUht|znhIfJg;kmaKr(uDvRs;RBQRXya86EA4hM0fR`Ld_#P<#J$gQ?k2E&m +zmV+AejcQJizjJD5>#^KU(4rS0utsq{c%iW&BJv!GuOg1iL*&9|ws;BX5v1o^fQgza +zCu)nzd|WxgwF3v*^CV7}ASYg(HEy9E`~&S}bQ~d)Xcl)2SuwhJ31Ret +zX;C-9_+r#cS)2t-y{pu|%OO7D;w48n;wkenHj4>a+{j5q;dSbU#f?;#Bqa+0rZiEA +z(qOCNAQC^s476lMSHm{Ib~Qb)*kp1M7vwHsOs!{-S3~i;A`sm5hUW`Y!=xrv%{Jl(* +z_%iKY^w9PNIV)3O;lGUJ)s%)<9B7KnIJA_<@jV{m`03Mu`Z)WsoaIU19LewU72>qa +z&rWI0+Dj0TYQAtNmfz(RcA04FfT-t{S~wJ6!P=MV78_N+nh^N)gJG|I@3rs!UorgR +zK(NF}&xmd4gK@kj(wR&PCZCv^dIA8J+f17`nSp+5m?wj=DU1g*%nTiA#F%>qI*e5n3p|BzYIR1Ecsf4b%Y4t +zH<*7O;RC?`A=D8Z3AMW87=7+&6&d +zBV307THS9#|1j>=+YmAc51}oz)A#!ruLE94#Nhor#y<~U&tu-^O$6|M-atV4ylc$S +z*nEts{3v4JR`9!}3dUbP0vNm=G7L8S6~L%hNg@zV0>L(DZdk?9Amaub{AajB5U)D{ +zI@A_qXdZGik3Oz{#b6`2<-3{p?2^*bP4oSR6%>+*9vL?bX;~)z@NHTSeOx2q;9lIa +zY}{e+0 +z*nwGafhN9cJ{k0$k1nw8b~L&OKck+>G-iPw4BiH$7s;iP1&`N@pSS0A)&>k6~Wx%#Hh871>WNiSx_Z5>xw`-d^CLBsRnNiUu? +z4PRKgcM>@N+i|$CxQ^j+v}Ii;4Hx8Otk37>S`>{tJQl7(?YObki+6hQVg9<|jLow) +zzXqIvOVl73PpKhJRexXIm4*Xy_q@Q%yDP|KFh=Ah-> +zb916Oz@65g8JFfR(=Kz}x6zwn3*SAS@akm3ArEiV-Yhe%Bwv%#tJKS_ek6XGE-)K5sg1a`4^N_oGk{d>6sAF&O2-x3 +zovtAn!>Kouc0b +zk{NeR4;^y+4W^6My+qv8GZ?sq5!)VytUE}0IwnKMdh&-%V43+uEM?f9Ir2wa?yE#1~b&%f3ONUvJ +zNVskikKbdlv>BRCSAfn8+Zgq#c+8J`rk%0!p6%!(R=!=&jCXf*IGs*M%J37boOs-G +z?6_}vW$GpRIgsdz`I$sYxcJ__px+?V?|d#WGg6lPkEZx=MB;=!iM7&`Yf8 +zAZBIb)@nCqm-r#;srOI6Rs1NRy?)J@lt6K6LvyC7p83dM8it; +z_h3PFnocZ{Nb5<@P9}z2cLu*k#a;_nrVT>_yYG1|h3`4Z5%D=G5Q#Yn*Y6bH1V1;S +zXzU*CMMhgRHcWP38x~ODZCGmTsOV*J!ojazALAAFFu{hV4FgUPY--vSfL9Z2Y1*BD +z2MJaiC>vqdHOZ^UB}F`nB>mQw%%}mfrZnCQg9rxH5ZQM^dl_a?PHI0Pt4!xOB$06z +zkX>eS+|QDkh8tS4(gHHl9Ios%mlw#~^SDEnUyK`M5F(IGnBbC3L|^-NvIdhpP6lC$ +zOR@<&xFnM?%_Uil87|3447eowtrN!yL?M@C>1DYj<1WV~*>_#q`BjWeJefz7=cxjs +z0#6kY6?v)~Q8!QZAnM_%UR3Cv6J$TGo)dkD`sVN~16J&uBqMfUPLdtFW=@bLj^D4nA%cx>^LO%{BsooPZ|3i08>4*t9?*Gb3w{~!pGL6rMZj-~V0Res +zgDv>;fbm;pqT_xU@Y50Oo#NjU*GF*TdE_e@ZSuqq0snTC?|%UB8(Z*sz_&(l^0k0} +z5W%Toj8O?&lc%mg{`*?_UjzKQ2<`|0f2{?7AF$JciRN~+tTlOhE8uCs9PlFGz6dA% +z7l2zl$~Pg6|;cXMfk<*0C%_G8NlThO#FcuQCr170NmSx{{}E5Q04y{ +zV72I)yt@Q=LzLhBCcw9};IsT}yKeW>{D$^i_qc%F2&X3md}#~5WkvoDC=FW0=tEDP +zAHh{w1U~{;DHG(MSpk2Q?`X?p&rAHnxKqNJrpbG6#8MF({MeVLGgMO(6Z$tig3w{XvZ^?h(?_<0#QogD6pB8J`Zi1yYkO00- +zu%!*;_@nsYB0jb@P~qQZuV7wG&0bT1;(8b5JKCC0@qg96fj&FR3Wl!gK)_K>LSI#& +zRoRj95r|}~Yvo4)cT-hOD}RQcVQ(XtYirjd|1$&&ZSC{WscIUfHs}IJv0T>%ph^DU%ev7{&s+-gXpB3q-Z`cQRpy#-i +zRi{@v`0k($h0d|Wfx&+kUAVTzr^$y5+{q}R(6pfc+R)lIEVQAGZCGkUTY#?w +zU)P3eVsj*1hBkDZKgjMPnx;1Nve*)F)zXI3_|4vN%D1)QkAjX87DpRChf%j?VfZV6 +z)uM5=;UDp*aFvITr>)Zf?;<#c|L_1D!+(fCeO`Bum~06$!;uAyPhiI9*__1Ag=0Bw +zo%7MwIghPVA|>Z!b8g)U2$NcPnzrsKY+0?buKP6LwM1KJ>z)OUYF}#W&Lh7<`MS2g +z4-%mku%WHLR_I_ZKBl&QJ787U($+7CYoi&nwe=@4GjYOkwDliB-xW<)Ti+0NBu$>S +z{+pcctMO^_^{+rWlyEosNPwAClEQwXy{P`qYcFeU_-ER`a|pEhGhqJ5TX2fE{{r6r +z%khG$|1<4p*sBNlS}cSYfj@+_)Xwt}s*9Xls~xna(v@bDZ$cR3ui;zx)yTaTHLm41 +z@U7UuUe7o2+flk5VF$mH?`t+udOJVFZwKaE`P=wAust2&_v8BkevCiJALfq&`kE)41$|%l +zd*Hu{rM3esq^}@)vfOXJT1EQY5jY^r*Kw73R>)O{oLdh +z&DYOOY%w;?$E`~S=9xTKmFFsalp`87D?m2R-7qQ6Z80~1kh!m0_zu3#RgsNwZbF`$ +z6qCNS&wuJFUZJQeCcEWik1>gA8+;#ZlUuCu$#awLzV1!)93|Z&2;H%LBVCi{uG(U3I9C-DU*H?4Tj#~ZSuydrwPE0X +zEdhkj5r#PD8`D+~LNB^DDJQRzlT~99ot+jvV#5}BZUV#TK5y*ve~V9u$r0n+BuM&l +Va#Y;VtxulYg5bN;)&QIL{}0O1kp=(& + +literal 0 +HcmV?d00001 + +diff --git a/base/tps/shared/conf/CS.cfg b/base/tps/shared/conf/CS.cfg +index 7a01052..0b4b348 100644 +--- a/base/tps/shared/conf/CS.cfg ++++ b/base/tps/shared/conf/CS.cfg +@@ -11,12 +11,22 @@ applet._002=# SAF Key: + applet._003=# applet.aid.cardmgr_instance=A0000001510000 + applet._004=# Stock RSA,KeyRecover applet : 1.4.58768072.ijc + applet._005=# RSA/KeyRecovery/GP211/SCP02, SCP03 applet : 1.5.558cdcff.ijc +-applet._006=# SCP03 AES server side keygen keywrap applet : 1.5.64260792.ijc +-applet._007=# Use GP211 applet only with SCP02 card +-applet._008=# For protocol > 1 do this ex: proto 3 : op.format.userKey.update.applet.requiredVersion.prot.3=1.5.558cdcff, 1.5.64260792.ijc for AES keywrap +-applet._009=# Use existing config for standard proto1 cards ex: op.format.userKey.update.applet.requiredVersion=1.4.58768072 +-applet._010=######################################### +-applet.aid.cardmgr_instance=A0000000030000 ++applet._006=# SCP03 AES server side keygen keywrap applet :1.5.65cbf5a6.ijc ++applet._007=# Use GP211 applet only with SCP03 card ++applet._008=# Set the applet for scp03 tokens as follows: ++applet._009=# Examples: ++applet._010=#Format: ++applet._011=#op.format.userKey.update.applet.requiredVersion.prot.3=1.5.65cbf5a6.ijc ++applet._012=# Enrollment: ++applet._013=#op.enroll.userKey.update.applet.requiredVersion.prot.3=1.5.65cbf5a6.ijc ++applet._014=# Pin Reset: ++applet._015=#op.pinReset.userKey.update.applet.requiredVersion.prot.3=1.5.65cbf5a6.ijc ++applet._016=# ++applet._017=# The applet above is the latest and supports CBC and KWP key wrapping. ++applet._018=# Use existing config for standard protoco1 cards Example: applet._019=#op.format.userKey.update.applet.requiredVersion=1.4.58768072 ++applet._019=# Add “,A000000003000000,A0000001510000” to all instances of *.cardmgr_instance parameters in the CS.cfg file as shown below. Update all format, enroll and pin reset values for every token type in the file. This is to support some newer cards such as the Cosmo Idemia, allowing the code to select the proper AID at run time. ++applet._020=######################################### ++applet.aid.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + applet.aid.netkey_file=627601FF0000 + applet.aid.netkey_instance=627601FF000000 + applet.aid.netkey_old_file=A000000001 +@@ -318,7 +328,7 @@ op.enroll.delegateIEtoken.maximumGPKeyVersion=FF + op.enroll.delegateIEtoken.rollbackKeyVersionOnPutKeyFailure=false + op.enroll.delegateIEtoken.validateCardKeyInfoAgainstTokenDB=true + op.enroll.delegateIEtoken.auth.id=ldap1 +-op.enroll.delegateIEtoken.cardmgr_instance=A0000000030000 ++op.enroll.delegateIEtoken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.enroll.delegateIEtoken.issuerinfo.enable=true + op.enroll.delegateIEtoken.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.enroll.delegateIEtoken.keyGen.authentication.SANpattern=$auth.exec-edipi$.$auth.exec-pcc$@EXAMPLE.com +@@ -474,7 +484,7 @@ op.format.delegateIEtoken.rollbackKeyVersionOnPutKeyFailure=false + op.format.delegateIEtoken.validateCardKeyInfoAgainstTokenDB=true + op.format.delegateIEtoken.auth.id=ldap1 + op.format.delegateIEtoken.ca.conn=ca1 +-op.format.delegateIEtoken.cardmgr_instance=A0000000030000 ++op.format.delegateIEtoken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.delegateIEtoken.issuerinfo.enable=true + op.format.delegateIEtoken.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.format.delegateIEtoken.loginRequest.enable=true +@@ -501,7 +511,7 @@ op.enroll.delegateISEtoken.maximumGPKeyVersion=FF + op.enroll.delegateISEtoken.rollbackKeyVersionOnPutKeyFailure=false + op.enroll.delegateISEtoken.validateCardKeyInfoAgainstTokenDB=true + op.enroll.delegateISEtoken.auth.id=ldap1 +-op.enroll.delegateISEtoken.cardmgr_instance=A0000000030000 ++op.enroll.delegateISEtoken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.enroll.delegateISEtoken.issuerinfo.enable=true + op.enroll.delegateISEtoken.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.enroll.delegateISEtoken.keyGen.authentication.SANpattern=$auth.exec-edipi$.$auth.exec-pcc$@EXAMPLE.com +@@ -772,7 +782,7 @@ op.format.delegateISEtoken.rollbackKeyVersionOnPutKeyFailure=false + op.format.delegateISEtoken.validateCardKeyInfoAgainstTokenDB=true + op.format.delegateISEtoken.auth.id=ldap1 + op.format.delegateISEtoken.ca.conn=ca1 +-op.format.delegateISEtoken.cardmgr_instance=A0000000030000 ++op.format.delegateISEtoken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.delegateISEtoken.issuerinfo.enable=true + op.format.delegateISEtoken.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.format.delegateISEtoken.loginRequest.enable=true +@@ -796,7 +806,7 @@ op.enroll.externalRegAddToToken.maximumGPKeyVersion=FF + op.enroll.externalRegAddToToken.rollbackKeyVersionOnPutKeyFailure=false + op.enroll.externalRegAddToToken.validateCardKeyInfoAgainstTokenDB=true + op.enroll.externalRegAddToToken.auth.id=ldap1 +-op.enroll.externalRegAddToToken.cardmgr_instance=A0000000030000 ++op.enroll.externalRegAddToToken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.enroll.externalRegAddToToken.issuerinfo.enable=true + op.enroll.externalRegAddToToken.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.enroll.externalRegAddToToken.keyGen.encryption.ca.conn=ca1 +@@ -868,7 +878,7 @@ op.format.externalRegAddToToken.rollbackKeyVersionOnPutKeyFailure=false + op.format.externalRegAddToToken.validateCardKeyInfoAgainstTokenDB=true + op.format.externalRegAddToToken.auth.id=ldap1 + op.format.externalRegAddToToken.ca.conn=ca1 +-op.format.externalRegAddToToken.cardmgr_instance=A0000000030000 ++op.format.externalRegAddToToken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.externalRegAddToToken.issuerinfo.enable=true + op.format.externalRegAddToToken.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.format.externalRegAddToToken.loginRequest.enable=true +@@ -884,7 +894,7 @@ op.format.externalRegAddToToken.update.symmetricKeys.requiredVersion=1 + op.format.externalRegISEtoken.auth.enable=true + op.format.externalRegISEtoken.auth.id=ldap1 + op.format.externalRegISEtoken.ca.conn=ca1 +-op.format.externalRegISEtoken.cardmgr_instance=A0000000030000 ++op.format.externalRegISEtoken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.externalRegISEtoken.cuidMustMatchKDD=false + op.format.externalRegISEtoken.enableBoundedGPKeyVersion=true + op.format.externalRegISEtoken.issuerinfo.enable=true +@@ -910,7 +920,7 @@ op.enroll.externalRegISEtoken._003=# controlled by registration user record + op.enroll.externalRegISEtoken._004=######################################### + op.enroll.externalRegISEtoken.auth.enable=true + op.enroll.externalRegISEtoken.auth.id=ldap1 +-op.enroll.externalRegISEtoken.cardmgr_instance=A0000000030000 ++op.enroll.externalRegISEtoken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.enroll.externalRegISEtoken.cuidMustMatchKDD=false + op.enroll.externalRegISEtoken.enableBoundedGPKeyVersion=true + op.enroll.externalRegISEtoken.issuerinfo.enable=true +@@ -1192,7 +1202,7 @@ op.enroll.soKey.rollbackKeyVersionOnPutKeyFailure=false + op.enroll.soKey.validateCardKeyInfoAgainstTokenDB=true + op.enroll.soKey.auth.enable=true + op.enroll.soKey.auth.id=ldap1 +-op.enroll.soKey.cardmgr_instance=A0000000030000 ++op.enroll.soKey.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.enroll.soKey.issuerinfo.enable=true + op.enroll.soKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.enroll.soKey.keyGen.encryption.ca.conn=ca1 +@@ -1345,7 +1355,7 @@ op.enroll.soKeyTemporary.rollbackKeyVersionOnPutKeyFailure=false + op.enroll.soKeyTemporary.validateCardKeyInfoAgainstTokenDB=true + op.enroll.soKeyTemporary.auth.enable=true + op.enroll.soKeyTemporary.auth.id=ldap1 +-op.enroll.soKeyTemporary.cardmgr_instance=A0000000030000 ++op.enroll.soKeyTemporary.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.enroll.soKeyTemporary.keyGen.auth.ca.conn=ca1 + op.enroll.soKeyTemporary.keyGen.auth.ca.profileId=caTempTokenDeviceKeyEnrollment + op.enroll.soKeyTemporary.keyGen.auth.certAttrId=c0 +@@ -1516,7 +1526,7 @@ op.enroll.userKey.rollbackKeyVersionOnPutKeyFailure=false + op.enroll.userKey.validateCardKeyInfoAgainstTokenDB=true + op.enroll.userKey.auth.enable=true + op.enroll.userKey.auth.id=ldap1 +-op.enroll.userKey.cardmgr_instance=A0000000030000 ++op.enroll.userKey.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.enroll.userKey.issuerinfo.enable=true + op.enroll.userKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.enroll.userKey.keyGen.encryption.ca.conn=ca1 +@@ -1682,7 +1692,7 @@ op.enroll.userKey.renewal.signing.gracePeriod.before=30 + op.enroll.userKey.renewal.signing.gracePeriod.enable=false + op.enroll.userKeyTemporary.auth.enable=true + op.enroll.userKeyTemporary.auth.id=ldap1 +-op.enroll.userKeyTemporary.cardmgr_instance=A0000000030000 ++op.enroll.userKeyTemporary.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.enroll.userKeyTemporary.keyGen.auth.ca.conn=ca1 + op.enroll.userKeyTemporary.keyGen.auth.ca.profileId=caTempTokenDeviceKeyEnrollment + op.enroll.userKeyTemporary.keyGen.auth.certAttrId=c0 +@@ -1861,7 +1871,7 @@ op.format.cleanToken.validateCardKeyInfoAgainstTokenDB=true + op.format.cleanToken.auth.enable=false + op.format.cleanToken.auth.id=ldap1 + op.format.cleanToken.ca.conn=ca1 +-op.format.cleanToken.cardmgr_instance=A0000000030000 ++op.format.cleanToken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.cleanToken.issuerinfo.enable=true + op.format.cleanToken.issuerinfo.value= + op.format.cleanToken.loginRequest.enable=true +@@ -1883,7 +1893,7 @@ op.format.soCleanSOToken.validateCardKeyInfoAgainstTokenDB=true + op.format.soCleanSOToken.auth.enable=false + op.format.soCleanSOToken.auth.id=ldap1 + op.format.soCleanSOToken.ca.conn=ca1 +-op.format.soCleanSOToken.cardmgr_instance=A0000000030000 ++op.format.soCleanSOToken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.soCleanSOToken.issuerinfo.enable=true + op.format.soCleanSOToken.issuerinfo.value= + op.format.soCleanSOToken.loginRequest.enable=false +@@ -1905,7 +1915,7 @@ op.format.soCleanUserToken.validateCardKeyInfoAgainstTokenDB=true + op.format.soCleanUserToken.auth.enable=false + op.format.soCleanUserToken.auth.id=ldap1 + op.format.soCleanUserToken.ca.conn=ca1 +-op.format.soCleanUserToken.cardmgr_instance=A0000000030000 ++op.format.soCleanUserToken.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.soCleanUserToken.issuerinfo.enable=true + op.format.soCleanUserToken.issuerinfo.value= + op.format.soCleanUserToken.loginRequest.enable=false +@@ -1927,7 +1937,7 @@ op.format.soKey.validateCardKeyInfoAgainstTokenDB=true + op.format.soKey.auth.enable=true + op.format.soKey.auth.id=ldap1 + op.format.soKey.ca.conn=ca1 +-op.format.soKey.cardmgr_instance=A0000000030000 ++op.format.soKey.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.soKey.issuerinfo.enable=true + op.format.soKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.format.soKey.loginRequest.enable=true +@@ -1949,7 +1959,7 @@ op.format.soUserKey.validateCardKeyInfoAgainstTokenDB=true + op.format.soUserKey.auth.enable=false + op.format.soUserKey.auth.id=ldap1 + op.format.soUserKey.ca.conn=ca1 +-op.format.soUserKey.cardmgr_instance=A0000000030000 ++op.format.soUserKey.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.soUserKey.issuerinfo.enable=true + op.format.soUserKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.format.soUserKey.loginRequest.enable=false +@@ -1971,7 +1981,7 @@ op.format.tokenKey.validateCardKeyInfoAgainstTokenDB=true + op.format.tokenKey.auth.enable=true + op.format.tokenKey.auth.id=ldap1 + op.format.tokenKey.ca.conn=ca1 +-op.format.tokenKey.cardmgr_instance=A0000000030000 ++op.format.tokenKey.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.tokenKey.issuerinfo.enable=true + op.format.tokenKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.format.tokenKey.loginRequest.enable=true +@@ -1993,7 +2003,7 @@ op.format.userKey.validateCardKeyInfoAgainstTokenDB=true + op.format.userKey.auth.enable=true + op.format.userKey.auth.id=ldap1 + op.format.userKey.ca.conn=ca1 +-op.format.userKey.cardmgr_instance=A0000000030000 ++op.format.userKey.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.format.userKey.issuerinfo.enable=true + op.format.userKey.issuerinfo.value=http://[PKI_HOSTNAME]:[PKI_UNSECURE_PORT]/tps/phoneHome + op.format.userKey.loginRequest.enable=true +@@ -2015,7 +2025,7 @@ op.pinReset.userKey.rollbackKeyVersionOnPutKeyFailure=false + op.pinReset.userKey.validateCardKeyInfoAgainstTokenDB=true + op.pinReset.userKey.auth.enable=true + op.pinReset.userKey.auth.id=ldap1 +-op.pinReset.userKey.cardmgr_instance=A0000000030000 ++op.pinReset.userKey.cardmgr_instance=A0000000030000,A000000003000000,A0000001510000 + op.pinReset.userKey.loginRequest.enable=true + op.pinReset.userKey.pinReset.pin.maxLen=10 + op.pinReset.userKey.pinReset.pin.minLen=4 +diff --git a/base/tps/src/org/dogtagpki/server/tps/TPSSession.java b/base/tps/src/org/dogtagpki/server/tps/TPSSession.java +index f7fca84..31c30e2 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/TPSSession.java ++++ b/base/tps/src/org/dogtagpki/server/tps/TPSSession.java +@@ -32,6 +32,8 @@ import org.dogtagpki.tps.msg.TPSMessage; + + import com.netscape.certsrv.apps.CMS; + ++import org.dogtagpki.tps.main.TPSBuffer; ++ + public class TPSSession { + + private TPSConnection connection; +@@ -40,6 +42,9 @@ public class TPSSession { + + private ExternalRegAttrs extRegAttrs; + ++ // Store card mgr in session so we only have to query it once per session ++ private TPSBuffer selectedCardMgr; ++ + public TPSSession(TPSConnection conn, String ip) { + + if (conn == null) { +@@ -182,4 +187,12 @@ public class TPSSession { + public ExternalRegAttrs getExternalRegAttrs() { + return extRegAttrs; + } ++ ++ public TPSBuffer getSelectedCardMgr() { ++ return selectedCardMgr; ++ } ++ ++ public void setSelectedCardMgr(TPSBuffer cardMgrBuffer) { ++ this.selectedCardMgr = cardMgrBuffer; ++ } + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java +index 8cebe39..65e6285 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java ++++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java +@@ -59,6 +59,8 @@ import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.base.EBaseException; + import com.netscape.certsrv.base.IConfigStore; + ++import java.util.Arrays; ++ + public class SecureChannel { + + // Have not written all code to use all of these as of yet. +@@ -152,8 +154,8 @@ public class SecureChannel { + + CMS.debug("SecureChannel.SecureChannel: For SCP03. : "); + +-// if (keyCheck != null) +-// CMS.debug("keyCheck: " + keyCheck.toHexString()); ++ //if (keyCheck != null) ++ // CMS.debug("keyCheck: " + keyCheck.toHexString()); + + this.platProtInfo = platformInfo; + this.processor = processor; +@@ -425,11 +427,11 @@ public class SecureChannel { + throw new TPSException(method + "Failed to calculate card cryptogram!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL); + } + +-// if(cardCryptogram != null) +-// CMS.debug(method + " actual card cryptogram " + cardCryptogram.toHexString()); ++ //if(cardCryptogram != null) ++ // CMS.debug(method + " actual card cryptogram " + cardCryptogram.toHexString()); + +-// if(calculatedCardCryptogram != null) +-// CMS.debug(method + " calculated card cryptogram " + calculatedCardCryptogram.toHexString()); ++ //if(calculatedCardCryptogram != null) ++ // CMS.debug(method + " calculated card cryptogram " + calculatedCardCryptogram.toHexString()); + + ExternalAuthenticateAPDUGP211 externalAuth = new ExternalAuthenticateAPDUGP211(hostCryptogram, + /* secLevel */secLevelGP211); +@@ -454,12 +456,12 @@ public class SecureChannel { + + if (false == cardCryptogram.equals(calculatedCardCryptogram)) { + +- CMS.debug("SecureChannel.eternalAuthenticate. Failed to match calculated to returned card cryptogram!. cardCryptogram: " ++ CMS.debug("SecureChannel.externalAuthenticate. Failed to match calculated to returned card cryptogram!. cardCryptogram: " + + cardCryptogram.toHexString() +- + " calculatedCardCrytpogram: " ++ + " calculatedCardCryptogram: " + + calculatedCardCryptogram.toHexString()); + throw new TPSException( +- "SecureChannel.eternalAuthenticate. Failed to match calculated to returned card cryptogram!.", ++ "SecureChannel.externalAuthenticate. Failed to match calculated to returned card cryptogram!.", + TPSStatus.STATUS_ERROR_SECURE_CHANNEL); + + } +@@ -530,9 +532,7 @@ public class SecureChannel { + + if (secLevel == SecurityLevel.SECURE_MSG_MAC_ENC) { + try { +- //CMS.debug("SecureChannel.computeAPDU: Before encryption data value: " + apdu.getData().toHexString()); + apdu.secureMessage(encSessionKey, (byte) 1); +- //CMS.debug("SecureChannel.computeAPDU: After encryption data value: " + apdu.getData().toHexString()); + } catch (EBaseException e) { + throw new TPSException("SecureChannel.computeAPDU: Can't encrypt outgoing data! " + e, + TPSStatus.STATUS_ERROR_SECURE_CHANNEL); +@@ -553,14 +553,9 @@ public class SecureChannel { + + if (secLevelGP211 == ExternalAuthenticateAPDUGP211.SecurityLevel.CDEC_CMAC) { + try { +- //CMS.debug("SecureChannel.computeAPDU_SCP03: Before encryption data value: " +- // + apdu.getData().toHexString()); + this.incrementBuffer(encryptionCounter); + TPSBuffer currentEncryptionCounter = new TPSBuffer(encryptionCounter); + apdu.secureMessageSCP03(encSessionKey,currentEncryptionCounter); +- ; +- //CMS.debug("SecureChannel.computeAPDU_SCP03: After encryption data value: " +- // + apdu.getData().toHexString()); + } catch (EBaseException e) { + throw new TPSException("SecureChannel.computeAPDU_SCP03: Can't encrypt outgoing data! " + e, + TPSStatus.STATUS_ERROR_SECURE_CHANNEL); +@@ -609,11 +604,7 @@ public class SecureChannel { + + if (secLevelGP211 == ExternalAuthenticateAPDUGP211.SecurityLevel.CDEC_CMAC) { + try { +- //CMS.debug("SecureChannel.computeAPDU_SCP02: Before encryption data value: " +- // + apdu.getData().toHexString()); + apdu.secureMessageSCP02(encSessionKey); +- //CMS.debug("SecureChannel.computeAPDU_SCP02: After encryption data value: " +- // + apdu.getData().toHexString()); + } catch (EBaseException e) { + throw new TPSException("SecureChannel.computeAPDU_SCP02: Can't encrypt outgoing data! " + e, + TPSStatus.STATUS_ERROR_SECURE_CHANNEL); +@@ -635,20 +626,11 @@ public class SecureChannel { + + data = apdu.getDataToMAC(); + +- //CMS.debug("SecureChannel.computeAPDUMacSCP03: data To MAC: " + data.toHexString() + " incoming icv: " +- // + icv.toHexString()); +- + try { +- +- CMS.debug("SecureChannel.computeAPDUMacSCP03: No ecnrypton of ICV."); +- + TPSBuffer dataToMac = new TPSBuffer(icv); + /// Prepend the chaining value to the data to be maced. + dataToMac.add(data); + +- //CMS.debug("SecureChannel.computeAPDUMacSCP03: final data To MAC: " + dataToMac.toHexString() + " incoming icv: " +- // + icv.toHexString()); +- + newMac = Util.computeAES_CMAC(macSessionKey, dataToMac); + + +@@ -658,12 +640,11 @@ public class SecureChannel { + TPSStatus.STATUS_ERROR_SECURE_CHANNEL); + } + +- CMS.debug("SecureChannel.computeAPDUMacSCP03: computed MAC: " /* + newMac.toHexString() */); ++ //CMS.debug("SecureChannel.computeAPDUMacSCP03: computed MAC: " /* + newMac.toHexString() */); + + apdu.setMAC(newMac.substr(0,8)); +- ++ + icv.set(newMac); +- + } + + private void computeAPDUMacSCP02(APDU apdu) throws TPSException { +@@ -785,7 +766,18 @@ public class SecureChannel { + TPSBuffer emptySDAID = new TPSBuffer(); + + if (isGP211()) { ++ CMS.debug("SecureChannel.installLoad: isGP211 is true"); + TPSBuffer cardMgrGP211AIDBuff = new TPSBuffer(TPSEngine.CFG_DEF_CARDMGR_211_INSTANCE_AID); ++ ++ TPSBuffer aidSubStrBuffer = new TPSBuffer(cardMgrGP211AIDBuff.substr(0,sdAID.size())); ++ byte[] defaultAIDtoChk = aidSubStrBuffer.toBytesArray(); ++ ++ // Use default AID unless another AID was already selected ++ if (!Arrays.equals(sdAID.toBytesArray(),defaultAIDtoChk)) ++ { ++ cardMgrGP211AIDBuff = new TPSBuffer(sdAID); ++ } ++ + installLoadGP211(packageAID, cardMgrGP211AIDBuff, fileLength); + return; + } +@@ -1140,6 +1132,7 @@ public class SecureChannel { + public TPSBuffer readObject(TPSBuffer objectID, int offset, int len) throws TPSException, IOException { + + CMS.debug("SecureChannel.readObject: entering ..."); ++ CMS.debug("offset: " + offset + " len: " + len + " objectID: " + objectID.toHexString()); + + if (objectID == null || len == 0) { + throw new TPSException("SecureChannel.readObject: invalid input data.", +@@ -1166,6 +1159,10 @@ public class SecureChannel { + while (sum < len) { + + read = new ReadObjectAPDU(objectID.toBytesArray(), cur_offset, cur_read); ++ // Add a 0x00 Le byte ++ read.setTrailer(new TPSBuffer((byte) 0x00)); ++ ++ //CMS.debug("read encoding: " + read.getEncoding().toHexString()); + computeAPDU(read); + + APDUResponse response = processor.handleAPDURequest(read); +@@ -1454,6 +1451,9 @@ public class SecureChannel { + generate_key_apdu = new GenerateKeyAPDU((byte) pe1, (byte) pe2, (byte) algorithm, keySize, + (byte) option, (byte) 0, wrappedChallenge, keyCheck); + ++ // Add a 0x00 Le byte ++ generate_key_apdu.setTrailer(new TPSBuffer((byte) 0x00)); ++ + computeAPDU(generate_key_apdu); + + response = processor.handleAPDURequest(generate_key_apdu); +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +index ce3f0a2..06304ed 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +@@ -120,8 +120,6 @@ public class TPSEnrollProcessor extends TPSProcessor { + + throw e; + } +- appletInfo.setAid(getCardManagerAID()); +- + CMS.debug(method + " token cuid: " + appletInfo.getCUIDhexStringPlain()); + boolean isTokenPresent = false; + +@@ -1021,11 +1019,6 @@ public class TPSEnrollProcessor extends TPSProcessor { + + TPSBuffer obj = channel.readObject(objectID, 0, (int) objectLenVal); + +- if (obj != null) { +- //CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: obj: " + obj.toHexString()); +- CMS.debug("PKCS11Obj.getCurrentObjectsOnToken: obj exists"); +- } +- + if ((char) objectID.at(0) == (byte) 'z' && objectID.at(1) == (byte) '0') { + lastFormatVersion = obj.getIntFrom2Bytes(0); + lastObjectVersion = obj.getIntFrom2Bytes(2); +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java +index 2ee9186..fed5164 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java +@@ -103,8 +103,6 @@ public class TPSPinResetProcessor extends TPSProcessor { + + throw e; + } +- appletInfo.setAid(getCardManagerAID()); +- + CMS.debug(method + " token cuid: " + appletInfo.getCUIDhexStringPlain()); + + tokenRecord = isTokenRecordPresent(appletInfo); +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +index 8c4d80e..625832c 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +@@ -176,6 +176,16 @@ public class TPSProcessor { + return session.getTokenRecord(); + } + ++ protected TPSBuffer getSelectedCardMgr() { ++ TPSSession session = getSession(); ++ return session.getSelectedCardMgr(); ++ } ++ ++ protected void setSelectedCardMgr(TPSBuffer cardMgr) { ++ TPSSession session = getSession(); ++ session.setSelectedCardMgr(cardMgr); ++ } ++ + protected void setBeginMessage(BeginOpMsg msg) { + beginMsg = msg; + } +@@ -295,6 +305,20 @@ public class TPSProcessor { + + } + ++ protected APDUResponse selectDefaultApplet(byte p1, byte p2, TPSBuffer len) throws IOException, TPSException { ++ ++ CMS.debug("In TPS_Processor.SelectDefaultApplet."); ++ ++ SelectAPDU select_apdu = new SelectAPDU(p1, p2); ++ ++ //return the Response because the caller can ++ //decide what to do, not every failure is fatal. ++ //For instance the coolkey applet may not yet exist. ++ //return handleAPDURequest(select_apdu); ++ return handleAPDURequestWithLength(select_apdu, len); ++ ++ } ++ + protected TPSBuffer getStatus() throws IOException, TPSException { + + CMS.debug("In TPS_Processor.GetStatus."); +@@ -311,6 +335,7 @@ public class TPSProcessor { + } + + TokenPDURequestMsg request_msg = new TokenPDURequestMsg(apdu); ++ CMS.debug("TPS_Processor.HandleAPDURequest: request_msg=" + request_msg.toString()); + + try { + session.write(request_msg); +@@ -333,6 +358,38 @@ public class TPSProcessor { + return response_msg.getResponseAPDU(); + } + ++ public APDUResponse handleAPDURequestWithLength(APDU apdu, TPSBuffer trailer) throws IOException, TPSException { ++ ++ if (apdu == null) { ++ throw new TPSException("TPSProcessor.handleAPDURequestWithLength: invalid incoming apdu!"); ++ } ++ ++ apdu.setTrailer(trailer); ++ ++ TokenPDURequestMsg request_msg = new TokenPDURequestMsg(apdu,true); ++ CMS.debug("TPSProcessor.handleAPDURequestWithLength: request_msg=" + request_msg.toString()); ++ ++ try { ++ session.write(request_msg); ++ } catch (IOException e) { ++ CMS.debug("TPSProcessor.handleAPDURequestWithLength: failed WriteMsg: " + e.toString()); ++ throw e; ++ ++ } ++ ++ TokenPDUResponseMsg response_msg = null; ++ ++ try { ++ response_msg = (TokenPDUResponseMsg) session.read(); ++ } catch (IOException e) { ++ CMS.debug("TPSProcessor.handleAPDURequestWithLength: failed ReadMsg: " + e.toString()); ++ throw e; ++ ++ } ++ ++ return response_msg.getResponseAPDU(); ++ } ++ + protected TPSBuffer getCplcData() throws IOException, TPSException { + CMS.debug("In TPS_Processor. getCplcData"); + +@@ -341,7 +398,18 @@ public class TPSProcessor { + APDUResponse respApdu = handleAPDURequest(get_data_apdu); + + if (!respApdu.checkResult()) { +- throw new TPSException("TPSProcessor.getCplcData: Can't get data!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL); ++ // If card needs length of data, resend request with length ++ if (respApdu.getSW1() == (byte) 0x6C) ++ { ++ TPSBuffer trailer = new TPSBuffer(respApdu.getSW2()); ++ // Request cplc data again from the token with correct length ++ CMS.debug("TPSProcessor.getCplcData: Request for cplc data failed, retrying with correct length..."); ++ respApdu = handleAPDURequestWithLength(get_data_apdu, trailer); ++ } ++ ++ if (!respApdu.checkResult()) { ++ throw new TPSException("TPSProcessor.getCplcData: Can't get data!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL); ++ } + } + TPSBuffer cplcData = respApdu.getData(); + +@@ -363,8 +431,21 @@ public class TPSProcessor { + + APDUResponse respApdu = handleAPDURequest(get_data_apdu); + +- if (!respApdu.checkResult()) { +- throw new TPSException("TPSProcessor.getData: Can't get data!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL); ++ if (!respApdu.checkResult()) ++ { ++ // If card needs length of data, resend request with length ++ if (respApdu.getSW1() == (byte) 0x6C) ++ { ++ TPSBuffer trailer = new TPSBuffer(respApdu.getSW2()); ++ // Get data again from the token with correct length ++ CMS.debug("TPSProcessor.getData: Request for card data failed, retrying with correct length..."); ++ respApdu = handleAPDURequestWithLength(get_data_apdu,trailer); ++ } ++ ++ if (!respApdu.checkResult()) ++ { ++ throw new TPSException("TPSProcessor.getData: Can't get data!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL); ++ } + } + + return respApdu.getData(); +@@ -498,6 +579,7 @@ public class TPSProcessor { + String method = "TPSProcessor.initializeUpdate:"; + + CMS.debug(method + " Entering..."); ++ + InitializeUpdateAPDU initUpdate = new InitializeUpdateAPDU(keyVersion, keyIndex, randomData); + + int done = 0; +@@ -571,12 +653,12 @@ public class TPSProcessor { + + TPSBuffer initUpdateResp = initializeUpdate(keyVersion, keyIndex, randomData); + +-// CMS.debug("TPSProcessor.setupSecureChanne: initUpdateResponse: " + initUpdateResp.toHexString()); ++ CMS.debug("TPSProcessor.setupSecureChannel: initUpdateResponse: " + initUpdateResp.toHexString()); + + TPSBuffer key_diversification_data = initUpdateResp.substr(0, DIVERSIFICATION_DATA_SIZE); + appletInfo.setKDD(key_diversification_data); + +-// CMS.debug("TPSProcessor.setupSecureChannel: diversification data: " + key_diversification_data.toHexString()); ++ CMS.debug("TPSProcessor.setupSecureChannel: diversification data: " + key_diversification_data.toHexString()); + + TPSBuffer key_info_data = null; + +@@ -608,14 +690,15 @@ public class TPSProcessor { + .substr(CARD_CHALLENGE_OFFSET_GP211_SC02, CARD_CHALLENGE_SIZE_GP211_SC02); + card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET, CARD_CRYPTOGRAM_SIZE); //new TPSBuffer(canned_card_challenge); + +- /* ++ /* + CMS.debug("TPSProcessor.setupSecureChannel 02: card cryptogram: " + card_cryptogram.toHexString()); + CMS.debug("TPSProcessor.setupSecureChannel 02: card challenge: " + card_challenge.toHexString()); + CMS.debug("TPSProcessor.setupSecureChannel 02: host challenge: " + randomData.toHexString()); + */ ++ + CMS.debug("TPSProcessor.setupSecureChannel 02: card cryptogram: extracted"); + CMS.debug("TPSProcessor.setupSecureChannel 02: card challenge: extracted"); +- ++ + } + + //Set the second byte of the keyInfo data to 0x1, this only gives us the secure protocol version 0x2 here. +@@ -628,9 +711,9 @@ public class TPSProcessor { + card_challenge = initUpdateResp.substr(CARD_CHALLENGE_OFFSET_GP211_SC03,CARD_CHALLENGE_SIZE); + card_cryptogram = initUpdateResp.substr(CARD_CRYPTOGRAM_OFFSET_GP211_SC03, CARD_CRYPTOGRAM_SIZE); + +-// CMS.debug("TPSProcessor.setupSecureChannel 03: card cryptogram: " + card_cryptogram.toHexString()); +-// CMS.debug("TPSProcessor.setupSecureChannel 03: card challenge: " + card_challenge.toHexString()); +-// CMS.debug("TPSProcessor.setupSecureChannel 03: host challenge: " + randomData.toHexString()); ++ CMS.debug("TPSProcessor.setupSecureChannel 03: card cryptogram: " + card_cryptogram.toHexString()); ++ CMS.debug("TPSProcessor.setupSecureChannel 03: card challenge: " + card_challenge.toHexString()); ++ CMS.debug("TPSProcessor.setupSecureChannel 03: host challenge: " + randomData.toHexString()); + } else { + + card_challenge = initUpdateResp.substr(CARD_CHALLENGE_OFFSET, CARD_CHALLENGE_SIZE); +@@ -953,26 +1036,26 @@ public class TPSProcessor { + TPSBuffer kekAesKeyBuff = resp.getKekWrappedAesKey(); + TPSBuffer drmAesKeyBuff = resp.getDRM_Trans_AesKey(); + +-// if (encSessionKeyBuff != null) +-// CMS.debug(method + " encSessionKeyBuff: " + encSessionKeyBuff.toHexString()); ++ //if (encSessionKeyBuff != null) ++ // CMS.debug(method + " encSessionKeyBuff: " + encSessionKeyBuff.toHexString()); + +-// if (kekSessionKeyBuff != null) +-// CMS.debug(method + " kekSessionKeyBuff: " + kekSessionKeyBuff.toHexString()); ++ //if (kekSessionKeyBuff != null) ++ // CMS.debug(method + " kekSessionKeyBuff: " + kekSessionKeyBuff.toHexString()); + +-// if (macSessionKeyBuff != null) +-// CMS.debug(method + " macSessionKeyBuff: " + macSessionKeyBuff.toHexString()); ++ //if (macSessionKeyBuff != null) ++ // CMS.debug(method + " macSessionKeyBuff: " + macSessionKeyBuff.toHexString()); + +-// if (hostCryptogramBuff != null) +-// CMS.debug(method + " hostCryptogramBuff: " + hostCryptogramBuff.toHexString()); ++ //if (hostCryptogramBuff != null) ++ /// CMS.debug(method + " hostCryptogramBuff: " + hostCryptogramBuff.toHexString()); + +-// if (keyCheckBuff != null) +-// CMS.debug(method + " keyCheckBuff: " + keyCheckBuff.toHexString()); ++ //if (keyCheckBuff != null) ++ // CMS.debug(method + " keyCheckBuff: " + keyCheckBuff.toHexString()); + +-// if (drmDesKeyBuff != null) +-// CMS.debug(method + " drmDessKeyBuff: " + drmDesKeyBuff.toHexString()); ++ //if (drmDesKeyBuff != null) ++ // CMS.debug(method + " drmDessKeyBuff: " + drmDesKeyBuff.toHexString()); + +-// if (kekDesKeyBuff != null) +-// CMS.debug(method + " kekDesKeyBuff: " + kekDesKeyBuff.toHexString()); ++ //if (kekDesKeyBuff != null) ++ // CMS.debug(method + " kekDesKeyBuff: " + kekDesKeyBuff.toHexString()); + + + if (encSessionKeyBuff != null) +@@ -987,9 +1070,9 @@ public class TPSProcessor { + kekSessionKeySCP03 = (PK11SymKey) protocol.unwrapWrappedSymKeyOnToken(token, sharedSecret, + kekSessionKeyBuff.toBytesArray(), false, SymmetricKey.AES); + +-// CMS.debug(" encSessionKeySCP03 " + encSessionKeySCP03); +-// CMS.debug(" macSessionKeySCP03 " + macSessionKeySCP03); +-// CMS.debug(" kekSessionKeySCP03 " + kekSessionKeySCP03); ++ //CMS.debug(" encSessionKeySCP03 " + encSessionKeySCP03.getEncoded()); ++ //CMS.debug(" macSessionKeySCP03 " + macSessionKeySCP03.getEncoded()); ++ //CMS.debug(" kekSessionKeySCP03 " + kekSessionKeySCP03.getEncoded()); + + channel = new SecureChannel(this, encSessionKeySCP03, macSessionKeySCP03, kekSessionKeySCP03, + drmDesKeyBuff, kekDesKeyBuff, +@@ -1067,10 +1150,17 @@ public class TPSProcessor { + if (upgraded == 0) { + CMS.debug("TPSProcessor.checkAndUpgradeApplet: applet already at correct version or upgrade disabled."); + +- // We didn't need to upgrade the applet but create new channel for now. +- selectCardManager(); +- setupSecureChannel(appletInfo); ++ TPSBuffer selectedCardMgr = getSelectedCardMgr(); ++ ++ if (selectedCardMgr == null || selectedCardMgr.size() == 0) ++ { ++ selectDefaultCardManager(); ++ } ++ ++ appletInfo.setAid(getSelectedCardMgr()); ++ CMS.debug("TPSProcessor.checkAndUpgradeApplet: Selected Card Mgr from session: " + appletInfo.getAid()); + ++ setupSecureChannel(appletInfo); + } + + return upgraded; +@@ -1081,12 +1171,10 @@ public class TPSProcessor { + TPSException { + + TPSBuffer netkeyAIDBuff = null; +- TPSBuffer cardMgrAIDBuff = null; + TPSBuffer netkeyPAIDBuff = null; + + netkeyAIDBuff = getNetkeyAID(); + netkeyPAIDBuff = getNetkeyPAID(); +- cardMgrAIDBuff = getCardManagerAID(); + + int channelBlockSize = getChannelBlockSize(); + int channelInstanceSize = getChannelInstanceSize(); +@@ -1106,19 +1194,22 @@ public class TPSProcessor { + + String appletFilePath = directory + "/" + new_version + "." + appletFileExt; + +- CMS.debug("TPSProcessor.upgradeApplet: targe applet file name: " + appletFilePath); ++ CMS.debug("TPSProcessor.upgradeApplet: target applet file name: " + appletFilePath); + + appletData = getAppletFileData(appletFilePath); + +- APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, cardMgrAIDBuff); + +- if (!select.checkResult()) { +- String logMsg = "Can't selelect the card manager!"; +- auditAppletUpgrade(appletInfo, "failure", null /*unavailable*/, new_version, logMsg); +- throw new TPSException("TPSProcessor.upgradeApplet:" + logMsg, +- TPSStatus.STATUS_ERROR_UPGRADE_APPLET); ++ // Get card mgr from session or select default ++ TPSBuffer selectedCardMgr = getSelectedCardMgr(); ++ ++ if (selectedCardMgr == null || selectedCardMgr.size() == 0) ++ { ++ selectDefaultCardManager(); + } + ++ appletInfo.setAid(getSelectedCardMgr()); ++ CMS.debug("TPSProcessor.upgradeApplet: After session.getSelectedCardMgr(), appletInfo.getAid() = " + appletInfo.getAid().toHexStringPlain()); ++ + SecureChannel channel = setupSecureChannel((byte) defKeyVersion, (byte) defKeyIndex, connId, appletInfo); + + channel.externalAuthenticate(); +@@ -1128,7 +1219,7 @@ public class TPSProcessor { + + // Next step will be to load the applet file to token. + +- channel.installLoad(netkeyPAIDBuff, cardMgrAIDBuff, appletData.length); ++ channel.installLoad(netkeyPAIDBuff, appletInfo.getAid(), appletData.length); + + TPSBuffer appletDataBuff = new TPSBuffer(appletData); + +@@ -1138,7 +1229,7 @@ public class TPSProcessor { + + //Now select our new applet + +- select = selectApplet((byte) 0x04, (byte) 0x00, netkeyAIDBuff); ++ APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, netkeyAIDBuff); + + if (!select.checkResult()) { + String logMsg = "Cannot select newly created applet!"; +@@ -2100,8 +2191,6 @@ public class TPSProcessor { + + throw e; + } +- appletInfo.setAid(getCardManagerAID()); +- + CMS.debug("TPSProcessor.format: token cuid: " + appletInfo.getCUIDhexStringPlain()); + boolean isTokenPresent = false; + +@@ -2130,7 +2219,8 @@ public class TPSProcessor { + byte app_minor_version = appletInfo.getAppMinorVersion(); + + CMS.debug("TPSProcessor.format: major_version " + major_version + " minor_version: " + minor_version +- + " app_major_version: " + app_major_version + " app_minor_version: " + app_minor_version); ++ + " app_major_version: " + app_major_version + " app_minor_version: " + app_minor_version ++ + " cardMgrAID: " + appletInfo.getAid().toHexStringPlain()); + + String tokenType = "tokenType"; + +@@ -2943,6 +3033,33 @@ public class TPSProcessor { + return ret; + } + ++ protected List getCardManagerAIDList() throws TPSException { ++ ++ String cardMgrAID = null; ++ List cardMgrAidList = null; ++ TPSEngine engine = getTPSEngine(); ++ IConfigStore configStore = CMS.getConfigStore(); ++ CMS.debug("TPSProcessor.getCardManagerAIDList: getting config: " + TPSEngine.CFG_APPLET_CARDMGR_INSTANCE_AID); ++ try ++ { ++ cardMgrAID = configStore.getString(TPSEngine.CFG_APPLET_CARDMGR_INSTANCE_AID, ++ TPSEngine.CFG_DEF_CARDMGR_INSTANCE_AID); ++ ++ if(cardMgrAID.length() > 0) ++ cardMgrAidList = Arrays.asList(cardMgrAID.split(",")); ++ ++ if(cardMgrAidList == null) ++ cardMgrAidList = Arrays.asList(engine.CFG_DEF_CARDMGR_INSTANCE_AID); ++ } ++ catch (EBaseException e1) ++ { ++ CMS.debug("TPS_Processor.getCardManagerAIDList: Internal Error obtaining mandatory config values. Error: " + e1); ++ throw new TPSException("TPS error getting config values from config store.", TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ ++ return cardMgrAidList; ++ } ++ + protected String getAppletExtension() throws TPSException { + IConfigStore configStore = CMS.getConfigStore(); + String extension = null; +@@ -3197,13 +3314,29 @@ public class TPSProcessor { + + CMS.debug("TPSProcessor.getAppletInfo, entering ..."); + +- selectCardManager(); +- +- TPSBuffer cplc_data = getCplcData(); +- CMS.debug("cplc_data: " + cplc_data.toHexString()); +- +- TPSBuffer token_cuid = extractTokenCUID(cplc_data); +- TPSBuffer token_msn = extractTokenMSN(cplc_data); ++ TPSBuffer cplc_data = null; ++ TPSBuffer token_cuid = null; ++ TPSBuffer token_msn = null; ++ ++ // Get default card manager ++ selectDefaultCardManager(); ++ ++ // Get the selected card manager ++ TPSBuffer selectedCardMgr = getSelectedCardMgr(); ++ CMS.debug("TPSProcessor.getAppletInfo: selectedCardMgr = " + selectedCardMgr.toHexStringPlain()); ++ ++ cplc_data = getCplcData(); ++ CMS.debug("TPSProcessor.getAppletInfo, cplc_data: " + cplc_data.toHexString()); ++ ++ if (cplc_data != null) ++ { ++ token_cuid = extractTokenCUID(cplc_data); ++ token_msn = extractTokenMSN(cplc_data); ++ } ++ else ++ { ++ throw new TPSException("TPSProcessor.getAppletInfo: Can't get cplc data!", TPSStatus.STATUS_ERROR_SECURE_CHANNEL); ++ } + + /** + * Checks if the netkey has the required applet version. +@@ -3246,11 +3379,12 @@ public class TPSProcessor { + result.setMSN(token_msn); + result.setTotalMem(total_mem); + result.setFreeMem(free_mem); ++ result.setAid(selectedCardMgr); + + CMS.debug("TPSProcessor.getAppletInfo: cuid: " + result.getCUIDhexString() + " msn: " + result.getMSNString() + + " major version: " + result.getMajorVersion() + " minor version: " + result.getMinorVersion() + + " App major version: " + result.getAppMajorVersion() + " App minor version: " +- + result.getAppMinorVersion()); ++ + result.getAppMinorVersion() + " cardManagerAID: " + selectedCardMgr.toHexStringPlain()); + + String currentAppletVersion = formatCurrentAppletVersion(result); + if (currentAppletVersion != null) { +@@ -3261,19 +3395,97 @@ public class TPSProcessor { + return result; + } + +- protected void selectCardManager() throws TPSException, IOException { +- CMS.debug("TPSProcessor.selectCardManager: entering.."); +- TPSBuffer aidBuf = getCardManagerAID(); +- +- APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, aidBuf); ++ // Method to get default card manager AID ++ protected void selectDefaultCardManager() throws TPSException, IOException { ++ String method = "TPSProcessor.selectDefaultCardManager: "; ++ CMS.debug(method + "entering.."); + +- if (!select.checkResult()) { +- throw new TPSException("TPSProcessor.selectCardManager: Can't selelect the card manager applet!", ++ TPSEngine engine = getTPSEngine(); ++ ++ // Request default AID from the token ++ TPSBuffer trailer = new TPSBuffer((byte) 0x00); ++ APDUResponse defaultAID = selectDefaultApplet((byte) 0x04, (byte) 0x00, trailer); ++ ++ if (defaultAID == null || !defaultAID.checkResult()) ++ { ++ // If card needs length of data, resend request with length ++ if (defaultAID.getSW1() == (byte) 0x6C) ++ { ++ trailer = new TPSBuffer(defaultAID.getSW2()); ++ // Request default AID again from the token with correct length ++ CMS.debug(method + "Request for card manager failed, retrying with correct length..."); ++ defaultAID = selectDefaultApplet((byte) 0x04, (byte) 0x00, trailer); ++ } ++ else ++ { ++ throw new TPSException("TPSProcessor.selectDefaultCardManager: Can't select the card manager applet!", + TPSStatus.STATUS_ERROR_CANNOT_ESTABLISH_COMMUNICATION); ++ } ++ } ++ ++ if (defaultAID != null && defaultAID.checkResult()) ++ { ++ TPSBuffer aidData = parseAIDResponse(defaultAID.getData()); ++ ++ String defAIDStr = aidData.toHexStringPlain(); ++ ++ // Get list of valid AID values from the configuration file ++ List aidBuf = getCardManagerAIDList(); ++ ++ // Check AID matches one in the list ++ for (String aid:aidBuf) ++ { ++ // Found valid AID ++ if (defAIDStr.equals(aid)) ++ { ++ CMS.debug(method + "Found cardManagerAID in list of valid values: " + defAIDStr + ", select it to be sure"); ++ ++ // Confirm AID is valid by selecting it ++ APDUResponse confirmedAID = selectApplet((byte) 0x04, (byte) 0x00, aidData); ++ ++ if (confirmedAID != null && confirmedAID.checkResult()) ++ { ++ CMS.debug(method + "Confirmed cardManagerAID: " + defAIDStr); ++ ++ // Set this card manager in the session ++ setSelectedCardMgr(aidData); ++ break; ++ } ++ else ++ { ++ CMS.debug(method + "Card Manager Selection Failed for cardMgrAID " + defAIDStr + "!"); ++ } ++ } ++ } ++ //Need to check for null or get a null ptr exception. ++ TPSBuffer selectedCardMgr = getSelectedCardMgr(); ++ if (selectedCardMgr == null || selectedCardMgr.size() == 0) ++ { ++ throw new TPSException("TPSProcessor.selectDefaultCardManager: Can't select the card manager applet!", ++ TPSStatus.STATUS_ERROR_CANNOT_ESTABLISH_COMMUNICATION); ++ } ++ } ++ else ++ { ++ throw new TPSException("TPSProcessor.selectDefaultCardManager: Can't select the card manager applet!", ++ TPSStatus.STATUS_ERROR_CANNOT_ESTABLISH_COMMUNICATION); + } + } + ++ protected void selectCardMgr(TPSBuffer aidBuffer) throws TPSException, IOException { ++ CMS.debug("TPSProcessor.selectCardMgr: entering.."); ++ ++ CMS.debug("TPSProcessor.selectCardMgr: cardManagerAID value = " + aidBuffer.toHexStringPlain()); ++ ++ APDUResponse select = selectApplet((byte) 0x04, (byte) 0x00, aidBuffer); ++ ++ CMS.debug("TPSProcessor.selectCardMgr: select result = " + select.checkResult()); + ++ if (select == null || !select.checkResult()) { ++ throw new TPSException("TPSProcessor.selectCardMgr: Can't select the card manager applet!", ++ TPSStatus.STATUS_ERROR_CANNOT_ESTABLISH_COMMUNICATION); ++ } ++ } + + protected boolean checkSymmetricKeysEnabled() throws TPSException { + boolean result = true; +@@ -3379,7 +3591,20 @@ public class TPSProcessor { + //If we failed we need to upgrade the keys + if (failed == true) { + +- selectCardManager(); ++ // Make sure correct card manager is selected ++ TPSBuffer selectedCardMgr = getSelectedCardMgr(); ++ if (selectedCardMgr == null || selectedCardMgr.size() == 0) ++ { ++ selectDefaultCardManager(); ++ } ++ else ++ { ++ selectCardMgr(getSelectedCardMgr()); ++ } ++ ++ appletInfo.setAid(getSelectedCardMgr()); ++ ++ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: Selected card manager from session: " + appletInfo.getAid().toHexStringPlain()); + + channel = setupSecureChannel(appletInfo); + +@@ -3865,17 +4090,28 @@ public class TPSProcessor { + TPSBuffer data = null; + TPSBuffer keyData = null; + +- selectCardManager(); +- try { ++ // If card manager is not selected, select it ++ TPSBuffer selectedCardMgr = getSelectedCardMgr(); + ++ if (selectedCardMgr == null || getSelectedCardMgr().size() == 0) ++ { ++ selectDefaultCardManager(); ++ } ++ // If it was selected already, make sure it is the one used here ++ else ++ { ++ selectCardMgr(getSelectedCardMgr()); ++ } ++ ++ try { + data = getData(SecureChannel.GP211_GET_DATA_CARD_DATA); ++ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: data.size() = " + data.size()); + keyData = getData(SecureChannel.GP211_GET_DATA_KEY_INFO); + + } catch (TPSException e) { + CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: Card can't understand GP211! " + e); + + throw e; +- + } + + if (data.size() < 5) { +@@ -3883,8 +4119,9 @@ public class TPSProcessor { + TPSStatus.STATUS_ERROR_SECURE_CHANNEL); + } + +- //CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: returned data: " + data.toHexString()); + CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: card data returned"); ++ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: returned data: " + data.toHexString()); ++ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: returned key data: " + keyData.toHexString()); + + // Now process the GP211 data returned by the card. + +@@ -3893,14 +4130,20 @@ public class TPSProcessor { + int length = 0; + + if (data.at(offset) == (byte) 0x66) { ++ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: data.at(" + offset + ") = 0x66"); + offset++; ++ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: offset = " + offset); + + totalLength = data.getIntFrom1Byte(offset++); + offset++; ++ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: offset = " + offset); + + } else { ++ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: data.at(" + offset + ") = " + data.at(offset)); + offset++; ++ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: offset = " + offset); + totalLength = data.getIntFrom1Byte(offset++); ++ CMS.debug("TPSProcessor.gp211GetSecureChannelProtocolDetails: offset = " + offset); + + } + +@@ -4601,6 +4844,34 @@ public class TPSProcessor { + audit(auditMessage); + } + ++ protected TPSBuffer parseAIDResponse(TPSBuffer response) ++ { ++ TPSBuffer aid = new TPSBuffer(); ++ ++ // Response starts with 0x6F ++ if (response.at(0) == (byte) 0x6F) ++ { ++ for(int i = 1; i < response.size(); i++) ++ { ++ // Find 0x84, AID follows that ++ if (response.at(i) == (byte) 0x84) ++ { ++ // Next byte is length of AID ++ int len = response.at(i+1); ++ ++ // Grab the AID bytes ++ aid = response.substr(i+2,len); ++ break; ++ } ++ } ++ } ++ else ++ { ++ CMS.debug("TPSProcessor.parseAIDResponse: select AID response missing mandatory data, cannot parse response!"); ++ } ++ return aid; ++ } ++ + /** + * Signed Audit Log + * +diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +index 479087f..29217d1 100644 +--- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java ++++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +@@ -3155,8 +3155,8 @@ public class CryptoUtil { + String method = "CryptoUtil.unwrapAESKeyFromBytes: "; + + logger.debug(method + "begins: isPerm: " + isPerm); +- //for now assume 128 bits aes +- if(inputKeyArray.length > 16) { ++ //support 128 or 256 bits aes ++ if(inputKeyArray.length > 32) { + throw new Exception(method + "invalid input data size."); + } + +-- +1.8.3.1 + + +From 6fe53787eb0caacc64798870b0f10030a4972f03 Mon Sep 17 00:00:00 2001 +From: Marco Fargetta +Date: Fri, 1 Mar 2024 15:17:36 +0100 +Subject: [PATCH 08/10] [RHEL-26881] Fix additional OID mappings + +Pretty print some additional OID: + +OCSP No Check - id-pkix-ocsp-nocheck { 1.3.6.1.5.5.7.48.1.5} +Inhibit Any Policy {2.5.29.54} +Extended Key Usage: + - serverAuth {1 3 6 1 5 5 7 3 1} + - clientAuth {1 3 6 1 5 5 7 3 2} + - codeSigning {1 3 6 1 5 5 7 3 3} + - emailProtection {1 3 6 1 5 5 7 3 4} + +(cherry picked from commit e227e0c7541d1f8cff71191adbbc654bfaf8ae9b) +--- + base/java-tools/man/man1/PrettyPrintCert.1 | 17 +++++++---------- + .../extensions/ExtendedKeyUsageExtension.java | 18 ++++++++++++++++++ + .../src/netscape/security/util/ExtPrettyPrint.java | 20 ++++++++++++++++++-- + base/util/src/netscape/security/x509/OIDMap.java | 13 +++++++++++-- + 4 files changed, 54 insertions(+), 14 deletions(-) + +diff --git a/base/java-tools/man/man1/PrettyPrintCert.1 b/base/java-tools/man/man1/PrettyPrintCert.1 +index 3cfb2f9..62054de 100644 +--- a/base/java-tools/man/man1/PrettyPrintCert.1 ++++ b/base/java-tools/man/man1/PrettyPrintCert.1 +@@ -117,14 +117,11 @@ The certificate in pretty-print format in the \fBcert.out\fP file looks like the + Key Identifier: + BB:36:98:5D:65:CB:88:E0:87:23:37:6F:5B:F7:AF:8B: + 8A:EB:BA:B5 +- Identifier: 1.3.6.1.5.5.7.1.1 +- Critical: no +- Value: +- 30:40:30:3E:06:08:2B:06:01:05:05:07:30:01:86:32: +- 68:74:74:70:3A:2F:2F:70:6B:69:2D:64:65:73:6B:74: +- 6F:70:2E:75:73:65:72:73:79:73:2E:72:65:64:68:61: +- 74:2E:63:6F:6D:3A:38:30:38:30:2F:63:61:2F:6F:63: +- 73:70 ++ Identifier: Authority Info Access: - 1.3.6.1.5.5.7.1.1 ++ Critical: no ++ Access Description: ++ Method #0: ocsp ++ Location #0: URIName: http://pki-desktop.usersys.redhat.com:8080/ca/ocsp + Identifier: Key Usage: - 2.5.29.15 + Critical: yes + Key Usage: +@@ -134,8 +131,8 @@ The certificate in pretty-print format in the \fBcert.out\fP file looks like the + Identifier: Extended Key Usage: - 2.5.29.37 + Critical: no + Extended Key Usage: +- 1.3.6.1.5.5.7.3.2 +- 1.3.6.1.5.5.7.3.4 ++ clientAuth ++ emailProtection + Signature: + Algorithm: SHA256withRSA - 1.2.840.113549.1.1.11 + Signature: +diff --git a/base/util/src/netscape/security/extensions/ExtendedKeyUsageExtension.java b/base/util/src/netscape/security/extensions/ExtendedKeyUsageExtension.java +index c9c8acf..7522095 100644 +--- a/base/util/src/netscape/security/extensions/ExtendedKeyUsageExtension.java ++++ b/base/util/src/netscape/security/extensions/ExtendedKeyUsageExtension.java +@@ -43,18 +43,36 @@ public class ExtendedKeyUsageExtension extends Extension implements CertAttrSet + public static final String OID = "2.5.29.37"; + public static final String NAME = OIDMap.EXT_KEY_USAGE_NAME; + public static final String OID_OCSPSigning = "1.3.6.1.5.5.7.3.9"; ++ public static final String OID_EMailProtection = "1.3.6.1.5.5.7.3.4"; + public static final String OID_CODESigning = "1.3.6.1.5.5.7.3.3"; ++ public static final String OID_ClientAuth = "1.3.6.1.5.5.7.3.2"; ++ public static final String OID_ServerAuth = "1.3.6.1.5.5.7.3.1"; + + public static final int OID_OCSP_SIGNING_STR[] = + { 1, 3, 6, 1, 5, 5, 7, 3, 9 }; + public static final ObjectIdentifier OID_OCSP_SIGNING = new + ObjectIdentifier(OID_OCSP_SIGNING_STR); + ++ public static final int OID_EMAIL_PROTECTION_STR[] = ++ { 1, 3, 6, 1, 5, 5, 7, 3, 4 }; ++ public static final ObjectIdentifier OID_EMAIL_PROTECTION = new ++ ObjectIdentifier(OID_EMAIL_PROTECTION_STR); ++ + public static final int OID_CODE_SIGNING_STR[] = + { 1, 3, 6, 1, 5, 5, 7, 3, 3 }; + public static final ObjectIdentifier OID_CODE_SIGNING = new + ObjectIdentifier(OID_OCSP_SIGNING_STR); + ++ public static final int OID_CLIENT_AUTH_STR[] = ++ { 1, 3, 6, 1, 5, 5, 7, 3, 2 }; ++ public static final ObjectIdentifier OID_CLIENT_AUTH = new ++ ObjectIdentifier(OID_CLIENT_AUTH_STR); ++ ++ public static final int OID_SERVER_AUTH_STR[] = ++ { 1, 3, 6, 1, 5, 5, 7, 3, 1 }; ++ public static final ObjectIdentifier OID_SERVER_AUTH = new ++ ObjectIdentifier(OID_SERVER_AUTH_STR); ++ + private Vector oidSet = null; + private byte mCached[] = null; + +diff --git a/base/util/src/netscape/security/util/ExtPrettyPrint.java b/base/util/src/netscape/security/util/ExtPrettyPrint.java +index 0788e19..1846eca 100644 +--- a/base/util/src/netscape/security/util/ExtPrettyPrint.java ++++ b/base/util/src/netscape/security/util/ExtPrettyPrint.java +@@ -478,9 +478,25 @@ public class ExtPrettyPrint { + + if (oid.equals(ExtendedKeyUsageExtension.OID_OCSP_SIGNING)) { + sb.append(pp.indent(mIndentSize + 8) + "OCSPSigning" + "\n"); +- } else { +- sb.append(pp.indent(mIndentSize + 8) + oid.toString() + "\n"); ++ continue; ++ } ++ if (oid.equals(ExtendedKeyUsageExtension.OID_EMAIL_PROTECTION)) { ++ sb.append(pp.indent(mIndentSize + 8) + "emailProtection" + "\n"); ++ continue; ++ } ++ if (oid.equals(ExtendedKeyUsageExtension.OID_CODE_SIGNING)) { ++ sb.append(pp.indent(mIndentSize + 8) + "codeSigning" + "\n"); ++ continue; ++ } ++ if (oid.equals(ExtendedKeyUsageExtension.OID_CLIENT_AUTH)) { ++ sb.append(pp.indent(mIndentSize + 8) + "clientAuth" + "\n"); ++ continue; ++ } ++ if (oid.equals(ExtendedKeyUsageExtension.OID_SERVER_AUTH)) { ++ sb.append(pp.indent(mIndentSize + 8) + "serverAuth" + "\n"); ++ continue; + } ++ sb.append(pp.indent(mIndentSize + 8) + oid.toString() + "\n"); + } + } + return sb.toString(); +diff --git a/base/util/src/netscape/security/x509/OIDMap.java b/base/util/src/netscape/security/x509/OIDMap.java +index 4b2ca00..6b9b661 100644 +--- a/base/util/src/netscape/security/x509/OIDMap.java ++++ b/base/util/src/netscape/security/x509/OIDMap.java +@@ -26,6 +26,8 @@ import java.util.Iterator; + import java.util.Properties; + + import netscape.security.extensions.AuthInfoAccessExtension; ++import netscape.security.extensions.InhibitAnyPolicyExtension; ++import netscape.security.extensions.OCSPNoCheckExtension; + import netscape.security.extensions.SubjectInfoAccessExtension; + import netscape.security.util.ObjectIdentifier; + +@@ -89,9 +91,10 @@ public class OIDMap { + SubjectDirAttributesExtension.NAME; + public static final String EXT_KEY_USAGE_NAME = "ExtendedKeyUsageExtension"; + public static final String EXT_INHIBIT_ANY_POLICY_NAME = "InhibitAnyPolicyExtension"; ++ private static final String EXT_INHIBIT_ANY_POLICY = ROOT + "." + InhibitAnyPolicyExtension.NAME; + private static final String EXT_KEY_USAGE = //ROOT + "." + + EXT_KEY_USAGE_NAME; +- ++ private static final String OCSP_NO_CHECK = ROOT + "." + OCSPNoCheckExtension.NAME; + private static final String CRL_NUMBER = ROOT + "." + + CRLNumberExtension.NAME; + private static final String CRL_REASON = ROOT + "." + +@@ -127,6 +130,8 @@ public class OIDMap { + props.put(AUTH_KEY_IDENTIFIER, "2.5.29.35"); + props.put(SUBJ_DIR_ATTR, "2.5.29.9"); + props.put(EXT_KEY_USAGE, "2.5.29.37"); ++ props.put(EXT_INHIBIT_ANY_POLICY, "2.5.29.54"); ++ props.put(OCSP_NO_CHECK, "1.3.6.1.5.5.7.48.1.5"); + } + + // Load the default name to class map (EXTENSIONS_CLASSES) +@@ -134,7 +139,7 @@ public class OIDMap { + props.put(AUTH_KEY_IDENTIFIER, + "netscape.security.x509.AuthorityKeyIdentifierExtension"); + props.put(SUB_KEY_IDENTIFIER, +- "org.mozilla.jss.netscape.security.x509.SubjectKeyIdentifierExtension"); ++ "netscape.security.x509.SubjectKeyIdentifierExtension"); + props.put(AUTHORITY_INFORMATION_ACCESS_IDENTIFIER, + "netscape.security.extensions.AuthInfoAccessExtension"); + props.put(SUBJECT_INFORMATION_ACCESS_IDENTIFIER, +@@ -161,6 +166,10 @@ public class OIDMap { + "netscape.security.x509.SubjectDirAttributesExtension"); + props.put(EXT_KEY_USAGE, + "netscape.security.extensions.ExtendedKeyUsageExtension"); ++ props.put(EXT_INHIBIT_ANY_POLICY, ++ "netscape.security.extensions.InhibitAnyPolicyExtension"); ++ props.put(OCSP_NO_CHECK, ++ "netscape.security.extensions.OCSPNoCheckExtension"); + props.put(CRL_NUMBER, "netscape.security.x509.CRLNumberExtension"); + props.put(CRL_REASON, "netscape.security.x509.CRLReasonExtension"); + } +-- +1.8.3.1 + + +From cc2b81514a74a513b0e3b6ea57b5fb7c7693a613 Mon Sep 17 00:00:00 2001 +From: Marco Fargetta +Date: Wed, 13 Mar 2024 11:47:29 +0100 +Subject: [PATCH 09/10] [RHEL-26881] Fix additional OID mappings - extra + +Pretty print some additional OID: + +Extended Key Usage: +- id-kp-ipsecIKE {1 3 6 1 5 5 7 3 17} +- iKEIntermediate {1 3 6 1 5 5 8 2 2} + +(cherry picked from commit 085fdba55d5abad2d2064c052a32c25e81e2d481) +--- + .../security/extensions/ExtendedKeyUsageExtension.java | 14 +++++++++++++- + base/util/src/netscape/security/util/ExtPrettyPrint.java | 8 ++++++++ + 2 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/base/util/src/netscape/security/extensions/ExtendedKeyUsageExtension.java b/base/util/src/netscape/security/extensions/ExtendedKeyUsageExtension.java +index 7522095..583f124 100644 +--- a/base/util/src/netscape/security/extensions/ExtendedKeyUsageExtension.java ++++ b/base/util/src/netscape/security/extensions/ExtendedKeyUsageExtension.java +@@ -42,12 +42,24 @@ public class ExtendedKeyUsageExtension extends Extension implements CertAttrSet + private static final long serialVersionUID = 765403075764697489L; + public static final String OID = "2.5.29.37"; + public static final String NAME = OIDMap.EXT_KEY_USAGE_NAME; ++ public static final String OID_IKEIntermediate = "1.3.6.1.5.5.8.2.2"; ++ public static final String OID_IpsecIKE = "1.3.6.1.5.5.7.3.17"; + public static final String OID_OCSPSigning = "1.3.6.1.5.5.7.3.9"; + public static final String OID_EMailProtection = "1.3.6.1.5.5.7.3.4"; + public static final String OID_CODESigning = "1.3.6.1.5.5.7.3.3"; + public static final String OID_ClientAuth = "1.3.6.1.5.5.7.3.2"; + public static final String OID_ServerAuth = "1.3.6.1.5.5.7.3.1"; + ++ public static final int OID_IKE_INTERMEDIATE_STR[] = ++ { 1, 3, 6, 1, 5, 5, 8, 2, 2 }; ++ public static final ObjectIdentifier OID_IKE_INTERMEDIATE = new ++ ObjectIdentifier(OID_IKE_INTERMEDIATE_STR); ++ ++ public static final int OID_ID_KP_IPSEC_IKE_STR[] = ++ { 1, 3, 6, 1, 5, 5, 7, 3, 17 }; ++ public static final ObjectIdentifier OID_ID_KP_IPSEC_IKE = new ++ ObjectIdentifier(OID_ID_KP_IPSEC_IKE_STR); ++ + public static final int OID_OCSP_SIGNING_STR[] = + { 1, 3, 6, 1, 5, 5, 7, 3, 9 }; + public static final ObjectIdentifier OID_OCSP_SIGNING = new +@@ -61,7 +73,7 @@ public class ExtendedKeyUsageExtension extends Extension implements CertAttrSet + public static final int OID_CODE_SIGNING_STR[] = + { 1, 3, 6, 1, 5, 5, 7, 3, 3 }; + public static final ObjectIdentifier OID_CODE_SIGNING = new +- ObjectIdentifier(OID_OCSP_SIGNING_STR); ++ ObjectIdentifier(OID_CODE_SIGNING_STR); + + public static final int OID_CLIENT_AUTH_STR[] = + { 1, 3, 6, 1, 5, 5, 7, 3, 2 }; +diff --git a/base/util/src/netscape/security/util/ExtPrettyPrint.java b/base/util/src/netscape/security/util/ExtPrettyPrint.java +index 1846eca..ecabb84 100644 +--- a/base/util/src/netscape/security/util/ExtPrettyPrint.java ++++ b/base/util/src/netscape/security/util/ExtPrettyPrint.java +@@ -476,6 +476,14 @@ public class ExtPrettyPrint { + while (e.hasMoreElements()) { + ObjectIdentifier oid = e.nextElement(); + ++ if (oid.equals(ExtendedKeyUsageExtension.OID_IKE_INTERMEDIATE)) { ++ sb.append(pp.indent(mIndentSize + 8) + "ipsec Intermediate System Usage" + "\n"); ++ continue; ++ } ++ if (oid.equals(ExtendedKeyUsageExtension.OID_ID_KP_IPSEC_IKE)) { ++ sb.append(pp.indent(mIndentSize + 8) + "ipsec Internet Key Exchange" + "\n"); ++ continue; ++ } + if (oid.equals(ExtendedKeyUsageExtension.OID_OCSP_SIGNING)) { + sb.append(pp.indent(mIndentSize + 8) + "OCSPSigning" + "\n"); + continue; +-- +1.8.3.1 + + +From cc0e275920fd776c85b80751a342bea6b34e5971 Mon Sep 17 00:00:00 2001 +From: jmagne +Date: Mon, 15 Apr 2024 16:41:21 -0700 +Subject: [PATCH 10/10] Fix Bug 2265180 - Add Support for Symmetric Key + Rollover [RHCS 9.7.z]. (#4719) + +The purpose of this fix is two fold, based on external code contributions. + +1. Implement the feature that allows certain 128 bit AES tokens to be upgraded to be 256 bit AES tokens. +2. Implement the feature that allows certain legacy scp03 tokens to have private keys injected with the legacy DES based unrapping algorithm. + +Feature 1 works ONLY for external registration based enrollments. This requires the use of new key mappings that allow us to map the incoming token to a given keyset. +Examples of this configuration will be provided in the bug testing instructions, which consists of keyset mapping entries in the TPS config, which then map to actual keyset config entries in the TKS. + +Feature 2 was originally designed to work only for external reg. Redhat has added some minor mods to allow this to be configured in the non external reg case if desired, +using the existing config variable per token profile. The key mapping resolver configurations for this feature has been upgraded to handle the desired wrapping algorithm and desired applet file version. +Note once again this keyset mapping resolver feature is only available for external registration enrollment. + +Rollover feature tested in dev for the g&d 7.0, while the legacy wrapping feature has been dev tested for the safenet sc650 scp03 token with both external reg and non external reg. +Address typos. Alter debug msg to show less data. Adress another comment typo. Address further review comments. +(cherry picked from commit cd6c62fe834c3301010f205c1f53ba1496e9fa6e) +--- + base/common/src/org/dogtagpki/tps/apdu/APDU.java | 3 +- + .../src/org/dogtagpki/tps/apdu/DeleteKeysAPDU.java | 35 + + .../common/src/org/dogtagpki/tps/msg/EndOpMsg.java | 6 +- + .../src/com/netscape/kra/NetkeyKeygenService.java | 1 + + .../cms/servlet/tks/SecureChannelProtocol.java | 19 +- + .../dogtagpki/server/connector/IRemoteRequest.java | 2 + + .../dogtagpki/server/tks/servlet/TokenServlet.java | 24 +- + .../server/tps/channel/SecureChannel.java | 36 + + .../tps/cms/TKSComputeSessionKeyResponse.java | 5 + + .../server/tps/cms/TKSRemoteRequestHandler.java | 27 +- + .../org/dogtagpki/server/tps/engine/TPSEngine.java | 10 +- + .../server/tps/mapping/BaseMappingResolver.java | 5 +- + .../server/tps/mapping/FilterMappingResolver.java | 39 +- + .../server/tps/processor/TPSEnrollProcessor.java | 129 +++- + .../server/tps/processor/TPSPinResetProcessor.java | 8 +- + .../server/tps/processor/TPSProcessor.java | 725 +++++++++++++++++++-- + 16 files changed, 969 insertions(+), 105 deletions(-) + create mode 100644 base/common/src/org/dogtagpki/tps/apdu/DeleteKeysAPDU.java + +diff --git a/base/common/src/org/dogtagpki/tps/apdu/APDU.java b/base/common/src/org/dogtagpki/tps/apdu/APDU.java +index 4dcaf99..bb0f9a3 100644 +--- a/base/common/src/org/dogtagpki/tps/apdu/APDU.java ++++ b/base/common/src/org/dogtagpki/tps/apdu/APDU.java +@@ -58,7 +58,8 @@ public abstract class APDU { + APDU_GET_ISSUERINFO, + APDU_GENERATE_KEY_ECC, + APDU_GET_LIFECYCLE, +- APDU_CLEAR_KEY_SLOTS ++ APDU_CLEAR_KEY_SLOTS, ++ APDU_DELETE_KEYS // ** G&D 256 Key Rollover Support ** + } + + protected byte cla; +diff --git a/base/common/src/org/dogtagpki/tps/apdu/DeleteKeysAPDU.java b/base/common/src/org/dogtagpki/tps/apdu/DeleteKeysAPDU.java +new file mode 100644 +index 0000000..91158bb +--- /dev/null ++++ b/base/common/src/org/dogtagpki/tps/apdu/DeleteKeysAPDU.java +@@ -0,0 +1,35 @@ ++package org.dogtagpki.tps.apdu; ++ ++/** ++ * ** G&D 256 Key Rollover Support ** ++ */ ++ ++import org.dogtagpki.tps.main.TPSBuffer; ++import com.netscape.certsrv.apps.CMS; ++ ++public class DeleteKeysAPDU extends APDU { ++ ++ public DeleteKeysAPDU(TPSBuffer keyVersion) { ++ setCLA((byte) 0x84); ++ setINS((byte) 0xE4); ++ setP1((byte) 0x00); ++ setP2((byte) 0x00); ++ ++ TPSBuffer keyData = new TPSBuffer(); ++ ++ keyData.add((byte) 0xD2); // tag for deleting key version ++ keyData.add((byte) keyVersion.size()); // length of key version ++ keyData.add(keyVersion); // key version ++ ++ //CMS.debug("DeleteKeysAPDU: keyData = " + keyData.toHexString()); ++ ++ setData(keyData); ++ ++ } ++ ++ @Override ++ public APDU.Type getType() { ++ return APDU.Type.APDU_DELETE_KEYS; ++ ++ } ++} +diff --git a/base/common/src/org/dogtagpki/tps/msg/EndOpMsg.java b/base/common/src/org/dogtagpki/tps/msg/EndOpMsg.java +index f770bbd..ccf61f6 100644 +--- a/base/common/src/org/dogtagpki/tps/msg/EndOpMsg.java ++++ b/base/common/src/org/dogtagpki/tps/msg/EndOpMsg.java +@@ -68,7 +68,8 @@ public class EndOpMsg extends TPSMessage { + STATUS_ERROR_NOT_TOKEN_OWNER, + STATUS_RENEWAL_IS_PROCESSED, + STATUS_ERROR_RENEWAL_FAILED, +- STATUS_ERROR_CANNOT_ESTABLISH_COMMUNICATION ++ STATUS_ERROR_CANNOT_ESTABLISH_COMMUNICATION, ++ STATUS_ERROR_SYMKEY_256_UPGRADE // ** G&D 256 Key Rollover Support ** + }; + + +@@ -227,6 +228,9 @@ public class EndOpMsg extends TPSMessage { + case STATUS_ERROR_CANNOT_ESTABLISH_COMMUNICATION: + result = 45; + break; ++ case STATUS_ERROR_SYMKEY_256_UPGRADE: // ** G&D 256 Key Rollover Support ** ++ result = 46; ++ break; + default: + break; + } +diff --git a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +index 413bb8e..210f0db 100644 +--- a/base/kra/src/com/netscape/kra/NetkeyKeygenService.java ++++ b/base/kra/src/com/netscape/kra/NetkeyKeygenService.java +@@ -27,6 +27,7 @@ import java.security.InvalidKeyException; + import java.security.KeyPair; + import java.security.SecureRandom; + ++import org.dogtagpki.tps.main.TPSBuffer; + import org.mozilla.jss.asn1.ASN1Util; + import org.mozilla.jss.crypto.CryptoToken; + import org.mozilla.jss.crypto.EncryptionAlgorithm; +diff --git a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +index 31eb6eb..b899c28 100644 +--- a/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java ++++ b/base/server/cms/src/com/netscape/cms/servlet/tks/SecureChannelProtocol.java +@@ -1818,14 +1818,15 @@ public class SecureChannelProtocol { + byte[] CUIDValue, + byte[] KDD, + byte[] kekKeyArray, byte[] encKeyArray, byte[] macKeyArray, +- String useSoftToken, String keySet, byte protocol, GPParams params) throws EBaseException { ++ String useSoftToken, String keySet, byte protocol, GPParams params, ++ GPParams oldParams) throws EBaseException { // ** G&D 256 Key Rollover Support ** add oldParams parameter + + String method = "SecureChannelProtocol.diversifyKey:"; + + CMS.debug(method + " Entering ... newTokenName: " + newTokenName + " protocol: " + protocol); + CMS.debug(method + " oldMasterKeyName: " + oldMasterKeyName); + CMS.debug(method + " newMasterKeyName: " + newMasterKeyName); +- ++ + //SecureChannelProtocol.debugByteArray(encKeyArray, " Developer enc key array: "); + //SecureChannelProtocol.debugByteArray(macKeyArray, " Developer mac key array: "); + //SecureChannelProtocol.debugByteArray(kekKeyArray, " Developer kek key array: "); +@@ -1965,11 +1966,12 @@ public class SecureChannelProtocol { + } + + } else { // Protocol 3 +- ++ // ** G&D 256 Key Rollover Support ** ++ // use the oldParams to compute the old_kek_sym_key + old_kek_sym_key = this.computeSessionKey_SCP03(tokenName, oldMasterKeyName, +- oldKeyInfo, SecureChannelProtocol.kekType, kekKeyArray, keySet, +- CUIDValue, KDD, null, null, transportKeyName, params); +- ++ oldKeyInfo, SecureChannelProtocol.kekType, kekKeyArray, keySet, ++ CUIDValue, KDD, null, null, transportKeyName, oldParams); ++ + CMS.debug(method + " Moving back to the developer key set case, protocol 3"); + } + } +@@ -2042,10 +2044,11 @@ public class SecureChannelProtocol { + + // Generate an old kek key to do the encrypting of the new static keys + ++ // ** G&D 256 Key Rollover Support ** ++ // use the oldParams to compute the old_kek_sym_key + old_kek_sym_key = this.computeSessionKey_SCP03(tokenName, oldMasterKeyName, oldKeyInfo, + SecureChannelProtocol.kekType, kekKeyArray, +- keySet, CUIDValue, KDD, null, null, transportKeyName, params); +- ++ keySet, CUIDValue, KDD, null, null, transportKeyName, oldParams); + } + + if (encKey == null || macKey == null || kekKey == null) { +diff --git a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java +index ae99a84..fc3bffc 100644 +--- a/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java ++++ b/base/server/cms/src/org/dogtagpki/server/connector/IRemoteRequest.java +@@ -48,6 +48,7 @@ public interface IRemoteRequest { + public static final String TOKEN_NEW_KEYINFO = "newKeyInfo"; + public static final String TOKEN_DATA = "data"; + public static final String WRAPPED_DEK_SESSION_KEY = "wrappedDekKey"; ++ public static final String TOKEN_OLD_KEYSET = "oldKeySet"; // ** G&D 256 Key Rollover Support ** + + // TKS response params + /* computeSessionKey responses */ +@@ -60,6 +61,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 TKS_RESPONSE_KeyCheck = "keycheck"; ++ public static final String TKS_RESPONSE_KeyCheck_Des = "keycheck_des"; // Applet and Alg Selection by Token Range Support + public static final String TKS_RESPONSE_HostCryptogram = "hostCryptogram"; + + /* createKeySetData response */ +diff --git a/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java b/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java +index f5dd932..0fde529 100644 +--- a/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java ++++ b/base/tks/src/org/dogtagpki/server/tks/servlet/TokenServlet.java +@@ -37,6 +37,7 @@ import org.mozilla.jss.crypto.CryptoToken; + import org.mozilla.jss.crypto.KeyWrapAlgorithm; + import org.mozilla.jss.crypto.KeyWrapper; + import org.mozilla.jss.crypto.SymmetricKey; ++import org.mozilla.jss.crypto.TokenException; + import org.mozilla.jss.crypto.X509Certificate; + import org.mozilla.jss.pkcs11.PK11SymKey; + import org.mozilla.jss.crypto.IVParameterSpec; +@@ -1664,6 +1665,11 @@ CMS.debug("4"); + keySet = "defKeySet"; + } + CMS.debug("keySet selected: " + keySet); ++ ++ // ** G&D 256 Key Rollover Support ** ++ String oldKeySet = req.getParameter(IRemoteRequest.TOKEN_OLD_KEYSET); ++ CMS.debug("oldKeySet: " + oldKeySet); ++ + + SessionContext sContext = SessionContext.getContext(); + +@@ -1817,6 +1823,11 @@ CMS.debug("4"); + // Get the first 6 characters, since scp03 gives us extra characters. + tokKeyInfo = tokKeyInfo.substring(0,6); + String oldKeyInfoMap = "tks." + keySet + ".mk_mappings." + tokKeyInfo; //#xx#xx ++ ++ // ** G&D 256 Key Rollover Support ** ++ if (oldKeySet != null) ++ oldKeyInfoMap = "tks." + oldKeySet + ".mk_mappings." + tokKeyInfo; //#xx#xx ++ + CMS.debug(method + " oldKeyInfoMap: " + oldKeyInfoMap); + String oldMappingValue = CMS.getConfigStore().getString(oldKeyInfoMap, null); + String oldSelectedToken = null; +@@ -1858,6 +1869,13 @@ CMS.debug("4"); + // passed down to the SecureChannelProtocol functions that deal with SCP03 + + GPParams gp3Params = readGPSettings(keySet); ++ ++ // ** G&D 256 Key Rollover Support ** ++ // need to use setting associated with the oldKeySet if provided ++ GPParams oldGp3Params = gp3Params; ++ if (oldKeySet != null) { ++ oldGp3Params = readGPSettings(oldKeySet); ++ } + + SecureChannelProtocol secProtocol = new SecureChannelProtocol(protocol); + // AC: KDF SPEC CHANGE - check for error reading settings +@@ -1872,7 +1890,8 @@ CMS.debug("4"); + nistSP800_108KdfUseCuidAsKdd, // AC: KDF SPEC CHANGE - pass in configuration file value + xCUID, // AC: KDF SPEC CHANGE - removed duplicative 'CUID' variable and replaced with 'xCUID' + xKDD, // AC: KDF SPEC CHANGE - pass in KDD so symkey can make decision about which value (KDD,CUID) to use +- kekKeyArray,encKeyArray,macKeyArray, useSoftToken_s, keySet, (byte) protocol,gp3Params); ++ kekKeyArray,encKeyArray,macKeyArray, useSoftToken_s, keySet, (byte) protocol,gp3Params, ++ oldGp3Params); // ** G&D 256 Key Rollover Support ** add oldGp3Params parameter to the method call + + } else if (protocol == 2) { + KeySetData = SessionKey.DiversifyKey(oldSelectedToken, newSelectedToken, oldKeyNickName, +@@ -1908,7 +1927,6 @@ CMS.debug("4"); + if (KeySetData != null && KeySetData.length > 1) { + value = IRemoteRequest.RESPONSE_STATUS + "=0&" + IRemoteRequest.TKS_RESPONSE_KeySetData + "=" + + com.netscape.cmsutil.util.Utils.SpecialEncode(KeySetData); +- //CMS.debug("TokenServlet:process DiversifyKey.encode " + value); + CMS.debug("TokenServlet:process DiversifyKey.encode returning KeySetData"); + // AC: KDF SPEC CHANGE - check for settings file issue (flag) + } else if (missingSetting_exception != null) { +@@ -2993,6 +3011,8 @@ CMS.debug("4"); + sb.append(kek_wrapped_aesKeyString); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_KeyCheck + "="); + sb.append(keycheck_aes_s); ++ sb.append("&" + IRemoteRequest.TKS_RESPONSE_KeyCheck_Des + "="); // Applet and Alg Selection by Token Range Support ++ sb.append(keycheck_s); // Applet and Alg Selection by Token Range Support + sb.append("&" + IRemoteRequest.TKS_RESPONSE_DRM_Trans_DesKey + "="); + sb.append(drm_trans_wrapped_desKeyString); + sb.append("&" + IRemoteRequest.TKS_RESPONSE_DRM_Trans_AesKey + "="); +diff --git a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java +index 65e6285..bd590a7 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java ++++ b/base/tps/src/org/dogtagpki/server/tps/channel/SecureChannel.java +@@ -28,6 +28,7 @@ import org.dogtagpki.tps.apdu.CreateObjectAPDU; + import org.dogtagpki.tps.apdu.CreatePinAPDU; + import org.dogtagpki.tps.apdu.DeleteFileAPDU; + import org.dogtagpki.tps.apdu.DeleteFileGP211APDU; ++import org.dogtagpki.tps.apdu.DeleteKeysAPDU; + import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU; + import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDU.SecurityLevel; + import org.dogtagpki.tps.apdu.ExternalAuthenticateAPDUGP211; +@@ -1803,4 +1804,39 @@ public class SecureChannel { + this.rmacSessionKey = rmacSessionKey; + } + ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method constructs the APDU for key deletion and sends the request to the card to ++ * delete keys with the given version. ++ * ++ * @param keyVersion the key version to be deleted ++ * @throws TPSException ++ * @throws IOException ++ * ++ */ ++ public void deleteKeys(byte keyVersion) throws TPSException, IOException { ++ String method = "SecureChannel.deleteKeys: keyVersion: " + keyVersion + ": "; ++ ++ CMS.debug(method + " entering ..."); ++ ++ APDUResponse response; ++ try { ++ TPSBuffer data = new TPSBuffer(keyVersion); ++ DeleteKeysAPDU deleteKeyApdu = new DeleteKeysAPDU(data); ++ computeAPDU(deleteKeyApdu); ++ response = processor.handleAPDURequest(deleteKeyApdu); ++ } catch (TPSException | IOException e) { ++ CMS.debug(method + " bad apdu return!"); ++ CMS.debug(e); ++ throw e; ++ } ++ ++ if (!response.checkResult()) { ++ CMS.debug(method + " response with unsuccess result"); ++ throw new TPSException(method + " failed to delete key set!", ++ TPSStatus.STATUS_ERROR_KEY_CHANGE_OVER); ++ } ++ ++ CMS.debug(method + " Successful delete key data operation completed."); ++ } + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java +index c30e3f0..d92879f 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java ++++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSComputeSessionKeyResponse.java +@@ -59,6 +59,11 @@ public class TKSComputeSessionKeyResponse extends RemoteResponse + return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KeyCheck); + } + ++ // Applet and Alg Selection by Token Range Support ++ public TPSBuffer getKeyCheckDes() { ++ return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_KeyCheck_Des); ++ } ++ + public TPSBuffer getHostCryptogram() { + return (TPSBuffer) nameValTable.get(IRemoteRequest.TKS_RESPONSE_HostCryptogram); + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java +index 540f713..a8bb3c5 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java ++++ b/base/tps/src/org/dogtagpki/server/tps/cms/TKSRemoteRequestHandler.java +@@ -315,6 +315,9 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler + + Util.specialURLEncode(card_cryptogram.toBytesArray()) + + "&" + IRemoteRequest.TOKEN_KEYSET + "=" + keySet; + ++ //CMS.debug(method + " request to TKS: " + requestString); ++ CMS.debug(method + " sending request to TKS..."); ++ + HttpResponse resp = + conn.send("computeSessionKey", + requestString +@@ -420,6 +423,19 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler + CMS.debug(method + " got IRemoteRequest.TKS_RESPONSE_KeyCheck"); + response.put(IRemoteRequest.TKS_RESPONSE_KeyCheck, Util.specialDecode(value)); + } ++ ++ // Applet and Alg Selection by Token Range Support - begin ++ value = (String) response.get(IRemoteRequest.TKS_RESPONSE_KeyCheck_Des); ++ ++ if (value == null) { ++ CMS.debug(method + "response missing name-value pair for: " + ++ IRemoteRequest.TKS_RESPONSE_KeyCheck_Des); ++ ++ } else { ++ CMS.debug(method + " got IRemoteRequest.TKS_RESPONSE_KeyCheck_Des"); ++ response.put(IRemoteRequest.TKS_RESPONSE_KeyCheck_Des, Util.specialDecode(value)); ++ } ++ // Applet and Alg Selection by Token Range Support - end + + value = (String) response.get(IRemoteRequest.TKS_RESPONSE_HostCryptogram); + if ( value == null ) { +@@ -618,7 +634,7 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler + public TKSCreateKeySetDataResponse createKeySetData ( + TPSBuffer NewMasterVer, + TPSBuffer version, +- TPSBuffer cuid, TPSBuffer kdd, int protocol, TPSBuffer wrappedDekSessionKey) ++ TPSBuffer cuid, TPSBuffer kdd, int protocol, TPSBuffer wrappedDekSessionKey, String oldKeySet) // ** G&D 256 Key Rollover Support ** add oldKeySet parameter + throws EBaseException { + CMS.debug("TKSRemoteRequestHandler: createKeySetData(): begins."); + if (cuid == null || NewMasterVer == null || version == null) { +@@ -645,7 +661,14 @@ public class TKSRemoteRequestHandler extends RemoteRequestHandler + if (wrappedDekSessionKey != null) { // We have secure channel protocol 02 trying to upgrade the key set. + command += "&" + IRemoteRequest.WRAPPED_DEK_SESSION_KEY + "=" + Util.specialURLEncode(wrappedDekSessionKey); + } +- ++ ++ // ** G&D 256 Key Rollover Support ** ++ // include oldKeySet name in the request TKS if provided ++ if (oldKeySet != null) { ++ command += "&" + IRemoteRequest.TOKEN_OLD_KEYSET + "=" + oldKeySet; ++ } ++ CMS.debug("TKSRemoteRequestHandler: createKeySetData(): request to TKS: " + command); ++ + HttpResponse resp = + conn.send("createKeySetData", + command); +diff --git a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java +index 2f0fa0c..0ffe83d 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java ++++ b/base/tps/src/org/dogtagpki/server/tps/engine/TPSEngine.java +@@ -429,7 +429,9 @@ public class TPSEngine { + + } + +- public TPSBuffer createKeySetData(TPSBuffer newMasterVersion, TPSBuffer oldVersion, int protocol, TPSBuffer cuid, TPSBuffer kdd, TPSBuffer wrappedDekSessionKey, String connId, String inKeyset) ++ // ** G&D 256 Key Rollover Support ** ++ // Add oldKeySet parameter ++ public TPSBuffer createKeySetData(TPSBuffer newMasterVersion, TPSBuffer oldVersion, int protocol, TPSBuffer cuid, TPSBuffer kdd, TPSBuffer wrappedDekSessionKey, String connId, String inKeyset, String oldKeySet) + throws TPSException { + + String method = "TPSEngine.createKeySetData:"; +@@ -440,13 +442,17 @@ public class TPSEngine { + TPSStatus.STATUS_ERROR_UPGRADE_APPLET); + } + ++ CMS.debug(method + " cuid: " + cuid.toHexStringPlain() + " newMasterVersion: " + newMasterVersion.toHexString() ++ + " oldVersion: " + oldVersion.toHexString() + " protocol: " + protocol + " inKeyset: " + inKeyset ++ + " oldKeySet: " + oldKeySet); ++ + TKSRemoteRequestHandler tks = null; + + TKSCreateKeySetDataResponse resp = null; + + try { + tks = new TKSRemoteRequestHandler(connId, inKeyset); +- resp = tks.createKeySetData(newMasterVersion, oldVersion, cuid, kdd, protocol,wrappedDekSessionKey); ++ resp = tks.createKeySetData(newMasterVersion, oldVersion, cuid, kdd, protocol,wrappedDekSessionKey, oldKeySet); // ** G&D 256 Key Rollover Support ** pass oldKeySet to TKS + } catch (EBaseException e) { + + throw new TPSException(method + " failure to get key set data from TKS", +diff --git a/base/tps/src/org/dogtagpki/server/tps/mapping/BaseMappingResolver.java b/base/tps/src/org/dogtagpki/server/tps/mapping/BaseMappingResolver.java +index e5c03cc..fe6bcd5 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/mapping/BaseMappingResolver.java ++++ b/base/tps/src/org/dogtagpki/server/tps/mapping/BaseMappingResolver.java +@@ -38,5 +38,8 @@ public abstract class BaseMappingResolver { + + public abstract String getResolvedMapping(FilterMappingParams mappingParams, String nameToMap) + throws TPSException; +- ++ ++ // ** G&D 256 Key Rollover Support ** ++ public abstract String getResolvedMapping(FilterMappingParams mappingParams, String nameToMap, Integer symKeySize) ++ throws TPSException; + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingResolver.java b/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingResolver.java +index 45cd203..d824a57 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingResolver.java ++++ b/base/tps/src/org/dogtagpki/server/tps/mapping/FilterMappingResolver.java +@@ -28,6 +28,15 @@ public class FilterMappingResolver extends BaseMappingResolver { + // from TPS: RA_Processor::ProcessMappingFilter + public String getResolvedMapping(FilterMappingParams mappingParams, String nameToMap) + throws TPSException { ++ // ** G&D 256 Key Rollover Support ** ++ // call the overloaded method, passing null for symKeySize ++ return getResolvedMapping(mappingParams, nameToMap, null); ++ } ++ ++ // ** G&D 256 Key Rollover Support ** ++ // Overload the method with the symKeySize parameter ++ public String getResolvedMapping(FilterMappingParams mappingParams, String nameToMap, Integer symKeySize) ++ throws TPSException { + String method = "FilterMappingResolver.getResolvedMapping for "+ nameToMap + ": "; + String tokenType = null; + String keySet = null; +@@ -311,7 +320,34 @@ public class FilterMappingResolver extends BaseMappingResolver { + continue; + } + } +- ++ ++ // ** G&D 256 Key Rollover Support ** ++ // G&D SPC03 tokens have same token range but different AES key sizes (128 and 256) ++ // If symKeySize is passed in, and if ...filter.symKeySize is configured, check ++ // whether the two values match. ++ // Skip symKeySize comparison if the parameter is not passed in ++ if (symKeySize != null) { ++ mappingConfigName = prefix + ".mapping." + mappingId + ".filter.symKeySize"; ++ CMS.debug(method + " mappingConfigName: " + mappingConfigName); ++ String configSymKeySize = null; ++ try { ++ configSymKeySize = configStore.getString(mappingConfigName, null); ++ } catch (EBaseException e) { ++ throw new TPSException( ++ method + " Internal error obtaining config value. Config: " ++ + mappingConfigName, ++ TPSStatus.STATUS_ERROR_MAPPING_RESOLVER_FAILED); ++ } ++ ++ // skip symKeySize comparison if not configured ++ if (configSymKeySize != null && configSymKeySize.length() > 0) { ++ CMS.debug(method + " cuid: " + cuid + ": comparing symKeySize: configured: " + configSymKeySize + " expected: " + symKeySize); ++ if (Integer.parseInt(configSymKeySize) != symKeySize.intValue()) { ++ continue; ++ } ++ } ++ } ++ + //if we make it this far, we have a mapped name + selectedMappedName = targetMappedName; + CMS.debug(method + " Selected mapped name: " + selectedMappedName); +@@ -327,5 +363,4 @@ public class FilterMappingResolver extends BaseMappingResolver { + return selectedMappedName; + + } +- + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +index 06304ed..061fea7 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSEnrollProcessor.java +@@ -262,9 +262,33 @@ public class TPSEnrollProcessor extends TPSProcessor { + TPSSubsystem subsystem = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + BaseMappingResolver resolverInst = subsystem.getMappingResolverManager() + .getResolverInstance(resolverInstName); +- String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet"); ++ ++ // ** G&D 256 Key Rollover Support ** ++ // Get the key size on card and pass it in to getResolvedMapping ++ Integer symKeySize = getCardSymKeyLength(appletInfo.getCUIDhexStringPlain()); ++ CMS.debug(method + " symKeySize on card: " + symKeySize); ++ ++ String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet", symKeySize); + setSelectedKeySet(keySet); + CMS.debug(method + " resolved keySet: " + keySet); ++ ++ // ** Applet and Alg Selection by Token Range Support begin ** ++ try { ++ String keyWrapAlg = resolverInst.getResolvedMapping(mappingParams, "keyWrapAlg", symKeySize); ++ setSelectedKeyWrapAlg(keyWrapAlg); ++ CMS.debug(method + " resolved keyWrapAlg: " + keyWrapAlg); ++ } catch (TPSException e) { ++ CMS.debug(method + " OK not to have keyWrapAlg target in token range mapping"); ++ } ++ ++ try { ++ String appletVer = resolverInst.getResolvedMapping(mappingParams, "appletVer", symKeySize); ++ setSelectedAppletVer(appletVer); ++ CMS.debug(method + " resolved appletVer: " + appletVer); ++ } catch (TPSException e) { ++ CMS.debug(method + " OK not to have appletVer target in token range mapping"); ++ } ++ // ** Applet and Alg Selection by Token Range Support end ** + } + } catch (TPSException e) { + logMsg = e.toString(); +@@ -274,7 +298,6 @@ public class TPSEnrollProcessor extends TPSProcessor { + throw new TPSException(logMsg, TPSStatus.STATUS_ERROR_MISCONFIGURATION); + } + } else { +- CMS.debug(method + " isExternalReg: OFF"); + /* + * Note: op.enroll.mappingResolver=none indicates no resolver + * plugin used (tokenType resolved perhaps via authentication) +@@ -302,6 +325,14 @@ public class TPSEnrollProcessor extends TPSProcessor { + } + } + ++ //RedHat do this to check the fact that DES has been configured for the non external Reg legacy key wrapping. ++ if(!isExternalReg) { ++ //RedHat method name change ++ String aesKeyWrapAlg = establishSymKeyWrapAlgSSKeyGen(); ++ //We don't care about the answer here, we just want to set the fact that des is configured. ++ CMS.debug(method + " non external reg: aesKeyWrapAlg: " + aesKeyWrapAlg); ++ } ++ + checkProfileStateOK(); + + boolean do_force_format = false; +@@ -1304,7 +1335,8 @@ public class TPSEnrollProcessor extends TPSProcessor { + session.getExternalRegAttrs().getCertsToRecoverCount()); + ArrayList erCertsToRecover = session.getExternalRegAttrs().getCertsToRecover(); + +- String aesKeyWrapAlg = getAESKeyWrapAlgSSKeyGen(); ++ //RedHat method name change ++ String aesKeyWrapAlg = establishSymKeyWrapAlgSSKeyGen(); + for (ExternalRegCertToRecover erCert : erCertsToRecover) { + BigInteger keyid = erCert.getKeyid(); + BigInteger serial = erCert.getSerial(); +@@ -1664,7 +1696,8 @@ public class TPSEnrollProcessor extends TPSProcessor { + boolean recoverOldEncCerts = tokenPolicy.isAllowdRenewSaveOldEncCerts(); + CMS.debug(method + " Recover Old Encryption Certs for Renewed Certs: " + recoverOldEncCerts); + +- String aesKeyWrapAlg = getAESKeyWrapAlgSSKeyGen(); ++ //RedHat method name change ++ String aesKeyWrapAlg = establishSymKeyWrapAlgSSKeyGen(); + if (oldEncCertsToRecover.size() > 0 && recoverOldEncCerts == true) { + CMS.debug("About to attempt to recover old encryption certs just renewed."); + +@@ -1954,7 +1987,8 @@ public class TPSEnrollProcessor extends TPSProcessor { + int actualCertIndex = 0; + boolean legalScheme = false; + +- String aesKeyWrapAlg = getAESKeyWrapAlgSSKeyGen(); ++ //RedHat method name change. ++ String aesKeyWrapAlg = establishSymKeyWrapAlgSSKeyGen(); + //Go through again and do the recoveries/enrollments + + certsInfo.setNumCertsToEnroll(totalNumCerts); +@@ -2453,7 +2487,8 @@ public class TPSEnrollProcessor extends TPSProcessor { + boolean isRecovery = false; + boolean isRenewal = false; + +- String aesKeyWrapAlg = getAESKeyWrapAlgSSKeyGen(); ++ //Method name change ++ String aesKeyWrapAlg = establishSymKeyWrapAlgSSKeyGen(); + cEnrollInfo.setAesKeyWrapAlg(aesKeyWrapAlg); + + if (mode == ENROLL_MODES.MODE_RECOVERY) { +@@ -3159,17 +3194,20 @@ public class TPSEnrollProcessor extends TPSProcessor { + // CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: keyWrappedDesKey: " + kekWrappedDesKey.toHexString()); + CMS.debug("TPSEnrollProcessor.importPrivateKeyPKCS8: got keyWrappedDesKey"); + } else +- CMS.debug("TPSEnrollProcessor.iportPrivateKeyPKC8: null kekWrappedDesKey!"); ++ CMS.debug("TPSEnrollProcessor.importPrivateKeyPKC8: null kekWrappedDesKey!"); + + byte alg = (byte) 0x80; + if (kekWrappedDesKey != null && kekWrappedDesKey.size() > 0) { ++ CMS.debug("TPSEnrollProcessor.importPrivateKeyPKC8: setting alg to 0x81 for DES wrapping!"); + kekWrappedKey = kekWrappedDesKey; + alg = (byte) 0x81; + } + +- //Give preference to AES kek wrapped key for SCP03, otherwise go with DES for SCP01 +- if(kekWrappedAESKey != null && kekWrappedAESKey.size() > 0 && channel.isSCP03()) { +- ++ //RedHat modify to allow for the non external reg key wrap alg to be set to DES for legacy tokens. ++ //Give preference to AES kek wrapped key for SCP03, otherwise go with DES for SCP01 or even SCP03 if so configured. ++ //This allows the feature of legacy DES wrapping for SCP03 legacy tokens when not using externalReg. ++ if(kekWrappedAESKey != null && kekWrappedAESKey.size() > 0 && channel.isSCP03() && !isDesConfigured())// ** Applet and Alg Selection by Token Range Support: check if DES is configured) ++ { + String aesKeyWrapAlg = cEnrollInfo.getAesKeyWrapAlg(); + + if(aesKeyWrapAlg != null && "CBC".equalsIgnoreCase(aesKeyWrapAlg)) { //CBC +@@ -3469,30 +3507,46 @@ public class TPSEnrollProcessor extends TPSProcessor { + return parsedPubKey; + } + +- public String getAESKeyWrapAlgSSKeyGen() { ++ //Redhat change name of method since it's multi purpose. ++ public String establishSymKeyWrapAlgSSKeyGen() { + + String aesKeyWrapAlg = "KWP"; +- +- IConfigStore configStore = CMS.getConfigStore(); +- +- // op.enroll.userKey.keyGen.aesKeyWrapAlg +- try { +- String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "." + TPSEngine.CFG_KEYGEN + +- "." + TPSEngine.CFG_AES_KEY_WRAP_ALG; +- +- CMS.debug("TPSEnrollProcessor::getAESKeyWrapAlgSSKeyGen: configValue . " + configValue); +- aesKeyWrapAlg = configStore.getString( +- configValue, "KWP"); +- CMS.debug("TPSEnrollProcessor::getAESKeyWrapAlgSSKeyGen: value " + aesKeyWrapAlg); +- +- } catch (EBaseException e) { +- //return default +- return aesKeyWrapAlg; ++ ++ String method = "TPSEnrollProcessor::establishSymKeyWrapAlgSSKeyGen: "; ++ // Applet and Alg Selection by Token Range Support - check keyWrapAlg target configuration in token range first ++ String selectedAlg = getSelectedKeyWrapAlg(); ++ if (selectedAlg == null) { // Applet and Alg Selection by Token Range Support - use aesKeyWrapAlg configured by tokenType ++ IConfigStore configStore = CMS.getConfigStore(); ++ ++ // op.enroll.userKey.keyGen.aesKeyWrapAlg ++ try { ++ String configValue = TPSEngine.OP_ENROLL_PREFIX + "." + selectedTokenType + "." + TPSEngine.CFG_KEYGEN + ++ "." + TPSEngine.CFG_AES_KEY_WRAP_ALG; ++ ++ CMS.debug(method + " configValue . " + configValue); ++ aesKeyWrapAlg = configStore.getString( ++ configValue, "KWP"); ++ CMS.debug(method + " value " + aesKeyWrapAlg); ++ // Red Hat call into the new method to set DES to allow it to work for the non external reg case. ++ if(aesKeyWrapAlg.equalsIgnoreCase("DES")) { ++ CMS.debug(method + " DES configured per original token based value."); ++ setSelectedKeyWrapAlg(aesKeyWrapAlg); ++ } ++ ++ } catch (EBaseException e) { ++ //return default ++ return aesKeyWrapAlg; ++ } ++ } else { ++ aesKeyWrapAlg = selectedAlg; ++ CMS.debug(method + " using keyWrapAlg configured by token range or token type: " + aesKeyWrapAlg); + } +- ++ ++ CMS.debug(method + " returning: " + aesKeyWrapAlg); + return aesKeyWrapAlg; + + } ++ + private boolean checkForServerSideKeyGen(CertEnrollInfo cInfo) throws TPSException { + + if (cInfo == null) { +@@ -3981,36 +4035,41 @@ public class TPSEnrollProcessor extends TPSProcessor { + return allow; + } + +- public static void main(String[] args) { +- } + ++ // RH update for AES Key Wrap Alg + private TPSBuffer getDRMDesKeyByProtocol(SecureChannel channel) { + + String method = "TPSEnrollProcessor.getDRMDesKeyByProtocol: "; + int prot = getProtocol(); + TPSBuffer drmDesKey = null; ++ ++ CMS.debug(method + " protocol: " + prot); + +- CMS.debug(method + " protocol: " + prot); +- +- if(prot == 1) ++ if(prot == 1 || isDesConfigured()) { // ** Applet and Alg Selection by Token Range Support: case of SafeNet SCP03 still using DES + drmDesKey = channel.getDRMWrappedDesKey(); ++ } + + return drmDesKey; + } + ++ // RH update for AES Key Wrap Alg + private TPSBuffer getDRMAesKeyByProtocol(SecureChannel channel) { + +- String method = "TPSEnrollProcessor.getDRMAesKeyByProtocol: "; ++ String method = "TPSEnrollProcessor.getDRMAesKeyByProtocol: "; + + int prot = getProtocol(); + TPSBuffer drmAesKey = null; + + CMS.debug(method + " protocol: " + prot); + +- if(prot == 3) ++ if(prot == 3 && !isDesConfigured()) { // ** Applet and Alg Selection by Token Range Support: case of SafeNet SCP03 still using DES + drmAesKey = channel.getDRMWrappedAesKey(); ++ } + + return drmAesKey; + } + ++ public static void main(String[] args) { ++ } ++ + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java +index fed5164..8beeb22 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSPinResetProcessor.java +@@ -244,7 +244,13 @@ public class TPSPinResetProcessor extends TPSProcessor { + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + BaseMappingResolver resolverInst = + subsystem.getMappingResolverManager().getResolverInstance(resolverInstName); +- String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet"); ++ ++ // ** G&D 256 Key Rollover Support ** ++ // Get the key size on card and pass it in to getResolvedMapping ++ Integer symKeySize = getCardSymKeyLength(appletInfo.getCUIDhexStringPlain()); ++ CMS.debug(method + " symKeySize on card: " + symKeySize); ++ ++ String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet", symKeySize); + setSelectedKeySet(keySet); + CMS.debug(method + " resolved keySet: " + keySet); + } +diff --git a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +index 625832c..48a341d 100644 +--- a/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java ++++ b/base/tps/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +@@ -141,6 +141,8 @@ public class TPSProcessor { + //protected TokenRecord tokenRecord; + protected String selectedTokenType; + protected String selectedKeySet; ++ protected String selectedKeyWrapAlg; // ** Applet and Alg Selection by Token Range Support ** ++ protected String selectedAppletVer; // ** Applet and Alg Selection by Token Range Support ** + IAuthToken authToken; + List ldapStringAttrs; + +@@ -1030,6 +1032,11 @@ public class TPSProcessor { + TPSBuffer macSessionKeyBuff = resp.getMacSessionKey(); + TPSBuffer hostCryptogramBuff = resp.getHostCryptogram(); + TPSBuffer keyCheckBuff = resp.getKeyCheck(); ++ // Applet and Alg Selection by Token Range Support ++ if (isDesConfigured()) { ++ CMS.debug(method + " Getting keyCheckDes."); ++ keyCheckBuff = resp.getKeyCheckDes(); ++ } + + TPSBuffer drmDesKeyBuff = resp.getDRM_Trans_DesKey(); + TPSBuffer kekDesKeyBuff = resp.getKekWrappedDesKey(); +@@ -1049,7 +1056,7 @@ public class TPSProcessor { + /// CMS.debug(method + " hostCryptogramBuff: " + hostCryptogramBuff.toHexString()); + + //if (keyCheckBuff != null) +- // CMS.debug(method + " keyCheckBuff: " + keyCheckBuff.toHexString()); ++ /// CMS.debug(method + " keyCheckBuff: " + keyCheckBuff.toHexString()); + + //if (drmDesKeyBuff != null) + // CMS.debug(method + " drmDessKeyBuff: " + drmDesKeyBuff.toHexString()); +@@ -2355,9 +2362,33 @@ public class TPSProcessor { + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + BaseMappingResolver resolverInst = + subsystem.getMappingResolverManager().getResolverInstance(resolverInstName); +- String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet"); ++ ++ // ** G&D 256 Key Rollover Support ** ++ // Get the key size on card and pass it in to getResolvedMapping ++ Integer symKeySize = getCardSymKeyLength(appletInfo.getCUIDhexStringPlain()); ++ CMS.debug("TPSProcessor.format: symKeySize on card: " + symKeySize); ++ ++ String keySet = resolverInst.getResolvedMapping(mappingParams, "keySet", symKeySize); + setSelectedKeySet(keySet); + CMS.debug("In TPSProcessor.format: resolved keySet: " + keySet); ++ ++ // ** Applet and Alg Selection by Token Range Support begin ** ++ try { ++ String keyWrapAlg = resolverInst.getResolvedMapping(mappingParams, "keyWrapAlg", symKeySize); ++ setSelectedKeyWrapAlg(keyWrapAlg); ++ CMS.debug("In TPSProcessor.format: resolved keyWrapAlg: " + keyWrapAlg); ++ } catch (TPSException e) { ++ CMS.debug("TPSProcessor.format: OK not to have keyWrapAlg target in token range mapping"); ++ } ++ ++ try { ++ String appletVer = resolverInst.getResolvedMapping(mappingParams, "appletVer", symKeySize); ++ setSelectedAppletVer(appletVer); ++ CMS.debug("In TPSProcessor.format: resolved appletVer: " + appletVer); ++ } catch (TPSException e) { ++ CMS.debug("TPSProcessor.format: OK not to have appletVer target in token range mapping"); ++ } ++ // ** Applet and Alg Selection by Token Range Support end ** + } + } catch (TPSException e) { + logMsg = e.toString(); +@@ -2520,20 +2551,52 @@ public class TPSProcessor { + statusUpdate(100, "PROGRESS_DONE"); + } + ++ // ** G&D 256 Key Rollover Support ** ++ // initialize status for key rollover ++ TPSStatus symKeyUpgradeStatus = TPSStatus.STATUS_NO_ERROR; ++ + // Upgrade Symm Keys if needed +- +- SecureChannel channel; ++ ++ SecureChannel channel = null; + try { + channel = checkAndUpgradeSymKeys(appletInfo, tokenRecord); + } catch (TPSException te) { +- auditKeyChangeover(appletInfo, "failure", null /* TODO */, ++ // ** G&D 256 Key Rollover Support ** ++ // Check whether the exception is thrown by 256 key rollover ++ if (te.getStatus() == TPSStatus.STATUS_ERROR_SYMKEY_256_UPGRADE) ++ { ++ // will update the token record in the DS before throwing the exception ++ // because it might be the case that 128 FMK was successfully rolled to 128 OMK ++ symKeyUpgradeStatus = TPSStatus.STATUS_ERROR_SYMKEY_256_UPGRADE; ++ } ++ // Check whether exception is caused by attempting to change 256 OMK to 128 FMK ++ else if (getSelectedKeySet().equals(getKeyDowngradeKeySet()) && getSymmetricKeysRequiredVersion() == getKeyDowngradeVersion()) ++ { ++ // proceed with downgrade if configured to do so ++ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: try downgrade key size."); ++ try { ++ channel = downgradeSymKeySize(appletInfo, tokenRecord, getSymmetricKeysRequiredVersion(), getChannelDefKeyIndex(), getTKSConnectorID()); ++ } catch (TPSException e) { ++ auditKeyChangeover(appletInfo, "failure", null /* TODO */, ++ getSymmetricKeysRequiredVersionHexString(), e.toString()); ++ throw e; ++ } ++ } ++ // throw the exception if none of above ++ else { ++ auditKeyChangeover(appletInfo, "failure", null /* TODO */, + getSymmetricKeysRequiredVersionHexString(), te.toString()); +- throw te; ++ throw te; ++ } ++ } ++ ++ // ** G&D 256 Key Rollover Support ** ++ // check 256 key rollover status before using the channel ++ if (symKeyUpgradeStatus == TPSStatus.STATUS_NO_ERROR) { ++ channel.externalAuthenticate(); ++ ++ auditFormatSuccess(userid, appletInfo, channel.getKeyInfoData().toHexStringPlain()); + } +- channel.externalAuthenticate(); +- +- auditFormatSuccess(userid, appletInfo, channel.getKeyInfoData().toHexStringPlain()); +- + if (isTokenPresent && revokeCertsAtFormat()) { + // Revoke certificates on token, if so configured + RevocationReason reason = getRevocationReasonAtFormat(); +@@ -2574,6 +2637,13 @@ public class TPSProcessor { + // Update Token DB + tokenRecord.setTokenStatus(TokenStatus.FORMATTED); + logMsg = "token format operation"; ++ ++ // ** G&D 256 Key Rollover Support ** ++ // changing the logMsg if exception occurred in 256 key rollover ++ if (symKeyUpgradeStatus == TPSStatus.STATUS_ERROR_SYMKEY_256_UPGRADE) { ++ logMsg = "token format operation without symkey 256 upgrade"; ++ } ++ + try { + tps.tdb.tdbUpdateTokenEntry(tokenRecord); + tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), logMsg, "success"); +@@ -2585,6 +2655,12 @@ public class TPSProcessor { + throw new TPSException(logMsg, TPSStatus.STATUS_ERROR_UPDATE_TOKENDB_FAILED); + } + ++ // ** G&D 256 Key Rollover Support ** ++ // if exception was caused by 256 key rollover, throw the exception after token record updated in the DS ++ if (symKeyUpgradeStatus == TPSStatus.STATUS_ERROR_SYMKEY_256_UPGRADE) { ++ throw new TPSException("Failed to upgrade symmetric key size to 256"); ++ } ++ + CMS.debug("TPSProcessor.format:: ends"); + + } +@@ -2897,34 +2973,37 @@ public class TPSProcessor { + IConfigStore configStore = CMS.getConfigStore(); + + acquireChannelPlatformAndProtocolInfo(); ++ ++ requiredVersion = getSelectedAppletVer(); // ** Applet and Alg Selection by Token Range Support: use appletVer target if it's defined in token range ++ if (requiredVersion == null) { // otherwise, get the requiredVersion configured by token type + +- int prot = getProtocol(); +- +- CMS.debug("TPSProcessor.checkForAppletUpgrad: protocol: " + prot); +- +- String protString = ""; +- +- // Let the existing config param handle protocol 1 by default +- if(prot > 1) { +- protString = ".prot."+ prot; +- } +- +- String appletRequiredConfig = operation + "." + selectedTokenType + "." +- + TPSEngine.CFG_APPLET_UPDATE_REQUIRED_VERSION + protString; +- CMS.debug("TPSProcessor.checkForAppletUpgrade: getting config: " + appletRequiredConfig); +- try { +- requiredVersion = configStore.getString(appletRequiredConfig, null); +- } catch (EBaseException e) { +- throw new TPSException( +- "TPSProcessor.checkForAppletUpgrade: Can't find applet required Version. Internal error obtaining version.", +- TPSStatus.STATUS_ERROR_MISCONFIGURATION); +- } +- +- if (requiredVersion == null) { +- throw new TPSException("TPSProcessor.checkForAppletUpgrade: Can't find applet required Version.", +- TPSStatus.STATUS_ERROR_MISCONFIGURATION); +- } +- ++ int prot = getProtocol(); ++ ++ CMS.debug("TPSProcessor.checkForAppletUpgrad: protocol: " + prot); ++ ++ String protString = ""; ++ ++ // Let the existing config param handle protocol 1 by default ++ if(prot > 1) { ++ protString = ".prot."+ prot; ++ } ++ ++ String appletRequiredConfig = operation + "." + selectedTokenType + "." ++ + TPSEngine.CFG_APPLET_UPDATE_REQUIRED_VERSION + protString; ++ CMS.debug("TPSProcessor.checkForAppletUpgrade: getting config: " + appletRequiredConfig); ++ try { ++ requiredVersion = configStore.getString(appletRequiredConfig, null); ++ } catch (EBaseException e) { ++ throw new TPSException( ++ "TPSProcessor.checkForAppletUpgrade: Can't find applet required Version. Internal error obtaining version.", ++ TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ ++ if (requiredVersion == null) { ++ throw new TPSException("TPSProcessor.checkForAppletUpgrade: Can't find applet required Version.", ++ TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ } + CMS.debug("TPSProcessor.checkForAppletUpgrade: returning: " + requiredVersion); + + return requiredVersion; +@@ -3566,19 +3645,23 @@ public class TPSProcessor { + + int defKeyVersion = 0; + int defKeyIndex = getChannelDefKeyIndex(); +- ++ + if (checkSymmetricKeysEnabled()) { + + CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: Symm key upgrade enabled."); + int requiredVersion = getSymmetricKeysRequiredVersion(); +- ++ ++ // ** G&D 256 Key Rollover Support ** ++ // set the flag to indicate if card needs to roll over to 256 OMK ++ boolean keyRollNeeded = (getSelectedKeySet().equals(getKeyRolloverKeySet()) && requiredVersion == getKeyRolloverVersion()); ++ CMS.debug(" keyRollNeeded: " + keyRollNeeded); + // try to make a secure channel with the 'requiredVersion' keys + // If this fails, we know we will have to attempt an upgrade + // of the keys + + boolean failed = false; + try { +- ++ + channel = setupSecureChannel((byte) requiredVersion, (byte) defKeyIndex, + getTKSConnectorID(),appletInfo); + +@@ -3587,7 +3670,7 @@ public class TPSProcessor { + CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: failed to create secure channel with required version, we need to upgrade the keys."); + failed = true; + } +- ++ + //If we failed we need to upgrade the keys + if (failed == true) { + +@@ -3667,9 +3750,8 @@ public class TPSProcessor { + } + + TPSBuffer keySetData = engine.createKeySetData(newVersion, curKeyInfo, protocol, +- appletInfo.getCUID(),channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId, getSelectedKeySet()); ++ appletInfo.getCUID(),channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId, getSelectedKeySet(), null); + +- //CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: new keySetData from TKS: " + keySetData.toHexString()); + CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: received new keySetData from TKS"); + + byte curVersion = curKeyInfo.at(0); +@@ -3680,11 +3762,11 @@ public class TPSProcessor { + throw new TPSException("TPSProcessor.checkAndUpgradeSymKeys: end of progress."); + + try { +- channel.putKeys(curVersion, curIndex, keySetData); ++ channel.putKeys(curVersion, curIndex, keySetData); + tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), + "Sent new GP Key Set to token", "success"); + } catch (TPSException e) { +- ++ + CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: failed to put key, checking to see if this a SCP02 with 0xFF default key set."); + + if (protocol == 2 && curVersion == (byte) 0xff) { +@@ -3692,7 +3774,7 @@ public class TPSProcessor { + + byte[] nv_dev = { (byte) 0x1, (byte) 0x1 }; + TPSBuffer devKeySetData = engine.createKeySetData(new TPSBuffer(nv_dev), curKeyInfo, protocol, +- appletInfo.getCUID(), channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId, getSelectedKeySet()); ++ appletInfo.getCUID(), channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId, getSelectedKeySet(), null); + + CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: about to get rid of keyset 0xFF and replace it with keyset 0x1 with developer key set"); + channel.putKeys((byte) 0x0, (byte) 0x1, devKeySetData); +@@ -3718,17 +3800,35 @@ public class TPSProcessor { + + CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: curVersionStr: " + curVersionStr + " newVersionStr: " + + newVersionStr); +- selectCoolKeyApplet(); ++ ++ // ** G&D 256 Key Rollover Support ** ++ // Create the secure channel if no further key rollover is needed ++ if (!keyRollNeeded) { ++ selectCoolKeyApplet(); + +- channel = setupSecureChannel((byte) requiredVersion, (byte) defKeyIndex, ++ channel = setupSecureChannel((byte) requiredVersion, (byte) defKeyIndex, + getTKSConnectorID(), appletInfo); +- auditKeyChangeover(appletInfo, "success", curVersionStr, newVersionStr, null); ++ auditKeyChangeover(appletInfo, "success", curVersionStr, newVersionStr, null); ++ } + +- } else { ++ } else if (!keyRollNeeded) { // ** G&D 256 Key Rollover Support ** message only applicable if no further rollover is needed + CMS.debug("TPSProcessor.checkAndUpgradeSymeKeys: We are already at the desired key set, returning secure channel."); + } + + // tokenRecord.setKeyInfo(channel.getKeyInfoData().toHexStringPlain()); ++ ++ // ** G&D 256 Key Rollover Support ** ++ // Continue to upgrade keys to 256 bit ++ if (keyRollNeeded) ++ { ++ try { ++ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: we need to do 256 key rollover for " + getSelectedKeySet()); ++ channel = upgradeSymKeySize(appletInfo, tokenRecord, requiredVersion, defKeyIndex, getTKSConnectorID()); ++ } catch (TPSException | IOException e) { ++ CMS.debug("TPSProcessor.checkAndUpgradeSymKeys: Failed to roll symmetric key size to 256"); ++ throw new TPSException("Failed to upgrade symmetric key size to 256", TPSStatus.STATUS_ERROR_SYMKEY_256_UPGRADE); ++ } ++ } + + } else { + //Create a standard secure channel with current key set. +@@ -4888,6 +4988,531 @@ public class TPSProcessor { + signedAuditLogger.log(event); + } + ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method returns the configured keySet name for the purpose of ++ * downgrading the 256 OMK to 128 FMK. If such a configuration is not found, ++ * an empty string will be returned and the downgrade is disallowed. ++ * ++ * @return the keySet name ++ * @throws TPSException ++ */ ++ protected String getKeyDowngradeKeySet() throws TPSException { ++ String method = "TPSProcessor.getKeyDowngradeKeySet: "; ++ IConfigStore configStore = CMS.getConfigStore(); ++ String config = "symKey.downgrade.keySet"; ++ String keySet; ++ try { ++ keySet = configStore.getString(config, ""); ++ } catch (EBaseException e) { ++ throw new TPSException(method + "Internal error finding config value:" + config, ++ TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ CMS.debug(method + " returning " + keySet); ++ return keySet; ++ } ++ ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method returns the configured key version to downgrade to for the ++ * purpose of downgrading the 256 OMK to 128 FMK. If such a configuration ++ * is not found, key version 3 will be returned as the default FMK version. ++ * ++ * @return the key version to downgrade to ++ * @throws TPSException ++ */ ++ protected int getKeyDowngradeVersion() throws TPSException { ++ String method = "TPSProcessor.getKeyDowngradeVersion: "; ++ IConfigStore configStore = CMS.getConfigStore(); ++ int ver; ++ String config = "symKey.downgrade.keyVer"; ++ try { ++ ver = configStore.getInteger(config, 0x03); ++ } catch (EBaseException e) { ++ throw new TPSException(method + "Internal error finding config value:" + config, ++ TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ CMS.debug(method + " returning " + ver); ++ return ver; ++ } ++ ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method returns the configured temporary key slot/version used in the key ++ * downgrade process for the purpose of downgrading the 256 OMK to 128 FMK. ++ * If such a configuration is not found, key slot/version 5 will be returned. ++ * ++ * @return ++ * @throws TPSException ++ */ ++ protected int getKeyDowngradeTempSlot() throws TPSException { ++ String method = "TPSProcessor.getKeyDowngradeTempSlot: "; ++ IConfigStore configStore = CMS.getConfigStore(); ++ int slot; ++ String config = "symKey.downgrade.temp.slot"; ++ try { ++ slot = configStore.getInteger(config, 0x5); ++ } catch (EBaseException e) { ++ throw new TPSException(method + "Internal error finding config value:" + config, ++ TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ CMS.debug(method + " returning " + slot); ++ return slot; ++ } ++ ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method returns the configured keySet name for the purpose of rolling ++ * over symmetric key size from 128 to 256. If such a configuration is not ++ * found, an empty string will be returned and the key upgrade is disallowed. ++ * ++ * @return the keySet name ++ * @throws TPSException ++ */ ++ protected String getKeyRolloverKeySet() throws TPSException { ++ String method = "TPSProcessor.getKeyRolloverKeySet: "; ++ IConfigStore configStore = CMS.getConfigStore(); ++ String config = "symKey.rollover.keySet"; ++ String keySet; ++ try { ++ keySet = configStore.getString(config, ""); ++ } catch (EBaseException e) { ++ throw new TPSException(method + "Internal error finding config value:" + config, ++ TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ CMS.debug(method + " returning " + keySet); ++ return keySet; ++ } ++ ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method returns the configured key version to upgrade to for the ++ * purpose of rolling over symmetric key size from 128 to 256. If such a ++ * configuration is not found, key version 0x21 will be returned as the ++ * default OMK version. ++ * ++ * @return the key version to roll over to ++ * @throws TPSException ++ */ ++ protected int getKeyRolloverVersion() throws TPSException { ++ String method = "TPSProcessor.getKeyRolloverVersion: "; ++ IConfigStore configStore = CMS.getConfigStore(); ++ int ver; ++ String config = "symKey.rollover.keyVer"; ++ try { ++ ver = configStore.getInteger(config, 0x21); ++ } catch (EBaseException e) { ++ throw new TPSException(method + "Internal error finding config value:" + config, ++ TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ CMS.debug(method + " returning " + ver); ++ return ver; ++ } ++ ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method returns the configured temporary key slot/version used in the key ++ * upgrade process for the purpose of rolling over symmetric key size from 128 to 256. ++ * If such a configuration is not found, key slot/version 3 will be returned. ++ * ++ * @return ++ * @throws TPSException ++ */ ++ protected int getKeyRolloverTempSlot() throws TPSException { ++ String method = "TPSProcessor.getKeyRolloverTempSlot: "; ++ IConfigStore configStore = CMS.getConfigStore(); ++ int slot; ++ String config = "symKey.rollover.temp.slot"; ++ try { ++ slot = configStore.getInteger(config, 0x3); ++ } catch (EBaseException e) { ++ throw new TPSException(method + "Internal error finding config value:" + config, ++ TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ CMS.debug(method + " returning " + slot); ++ return slot; ++ } ++ ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method gets the key info template on the card and returns it. ++ * ++ * @return the TPSBuffer that contains the key info template ++ * @throws TPSException ++ * @throws IOException ++ */ ++ protected TPSBuffer getKeyInfoTemplate() throws TPSException, IOException { ++ // If card manager is not selected, select it ++ if (getSelectedCardMgr().size() == 0) { ++ selectDefaultCardManager(); ++ } ++ // If it was selected already, make sure it is the one used here ++ else { ++ selectCardMgr(getSelectedCardMgr()); ++ } ++ return getData(SecureChannel.GP211_GET_DATA_KEY_INFO); ++ } ++ ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method returns the symmetric key size (e.g. 128 or 256 bits) on the card. ++ * The key size is calculated by extracting the octet length from the key info ++ * template on card and multiplying it by 8. ++ * ++ * @param cuid the token CUID (for debug logging) ++ * @return the symmetric key length on the card (e.g. 128 or 256) ++ * @throws TPSException ++ * @throws IOException ++ */ ++ protected Integer getCardSymKeyLength(String cuid) throws TPSException, IOException { ++ String method = "TPSProcessor.getCardSymKeyLength: CUID: " + cuid + ": "; ++ ++ TPSBuffer keyData; ++ if (platProtInfo != null) { ++ keyData = platProtInfo.getKeysetInfoData(); ++ CMS.debug(method + " key info template from platProtInfo: " + keyData.toHexString()); ++ } ++ else { ++ keyData = getKeyInfoTemplate(); ++ CMS.debug(method + " key info template from getData: " + keyData.toHexString()); ++ } ++ ++ Integer symKeyLen = null; ++ ++ // example for key info template: ++ // E0%12%C0%04%01%21%88%20%C0%04%02%21%88%20%C0%04%03%21%88%20%90%00% ++ // Byte 7 is the key octet length (0x20 in the example above) ++ int keyLenOffset = 7; ++ if (keyData.size() > keyLenOffset) { ++ int keyOctetLen = keyData.getIntFrom1Byte(keyLenOffset); ++ CMS.debug(method + " key octet length: " + keyOctetLen); ++ symKeyLen = keyOctetLen * 8; ++ } ++ return symKeyLen; ++ } ++ ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method downgrades the symmetric key size for the purpose of rolling the 256 OMK back to ++ * 128 FMK. ++ * ++ * @param appletInfo ++ * @param tokenRecord ++ * @param requiredVersion ++ * @param defKeyIndex ++ * @param connId ++ * @return the SecureChannel set up with the 128 FMK ++ * @throws TPSException ++ * @throws IOException ++ */ ++ protected SecureChannel downgradeSymKeySize(AppletInfo appletInfo, TokenRecord tokenRecord, int requiredVersion, int defKeyIndex, String connId) throws TPSException, IOException { ++ String method = "TPSProcessor.downgradeSymKeySize: CUID: " + tokenRecord.getId() + ": "; ++ SecureChannel channel = null; ++ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); ++ String oldKeySet = getSelectedKeySet(); ++ String newKeySet = oldKeySet; ++ try { ++ // find keySet name for the 128-bit sym key ++ String resolverInstName = getKeySetResolverInstanceName(); ++ if (!resolverInstName.equals("none")) { ++ FilterMappingParams mappingParams = createFilterMappingParams(resolverInstName, ++ appletInfo.getCUIDhexStringPlain(), appletInfo.getMSNString(), ++ appletInfo.getMajorVersion(), appletInfo.getMinorVersion()); ++ TPSSubsystem subsystem = ++ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); ++ BaseMappingResolver resolverInst = ++ subsystem.getMappingResolverManager().getResolverInstance(resolverInstName); ++ ++ newKeySet = resolverInst.getResolvedMapping(mappingParams, "keySet", 128); ++ CMS.debug(method + " resolved keySet: " + newKeySet); ++ } else { ++ throw new TPSException("Invalid keySet resolver instance name: " + resolverInstName, TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ } catch (TPSException e) { ++ tps.tdb.tdbActivity(ActivityDatabase.OP_FORMAT, tokenRecord, session.getIpAddress(), e.toString(), ++ "failure"); ++ throw new TPSException(e.toString(), TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ ++ // Make sure correct card manager is selected ++ if (getSelectedCardMgr().size() == 0) { ++ selectDefaultCardManager(); ++ } ++ else { ++ selectCardMgr(getSelectedCardMgr()); ++ } ++ appletInfo.setAid(getSelectedCardMgr()); ++ ++ channel = setupSecureChannel(appletInfo); ++ auditKeyChangeoverRequired(appletInfo, channel.getKeyInfoData().toHexStringPlain(), getSymmetricKeysRequiredVersionHexString(), null); ++ ++ // get the temporary slot (key version) where keys will be added to ++ byte tmpVer = (byte)getKeyDowngradeTempSlot(); ++ ++ TPSEngine engine = getTPSEngine(); ++ int protocol = 3; ++ TPSBuffer curKeyInfo = channel.getKeyInfoData(); ++ CMS.debug(method + " curKeyInfo: " + curKeyInfo.toHexString()); ++ ++ byte[] nv = new byte[] { (byte)requiredVersion, curKeyInfo.at(1), curKeyInfo.at(2) }; ++ TPSBuffer newVersion = new TPSBuffer(nv); ++ CMS.debug(method + " newVersion: " + newVersion.toHexString()); ++ ++ // get key data from TKS ++ TPSBuffer keySetData = engine.createKeySetData(newVersion, curKeyInfo, protocol, ++ appletInfo.getCUID(),channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId, newKeySet, oldKeySet); ++ CMS.debug(method + " new keySetData from TKS: " + keySetData.substr(0, 4).toHexString() + "..."); ++ ++ // change the 1st byte of keySetData to the configured temporary key version (slot where keys to be added to) ++ TPSBuffer modKeySetData = new TPSBuffer(keySetData); ++ modKeySetData.setAt(0, (byte)tmpVer); ++ CMS.debug(method + " modified keySetData from TKS before add key: " + modKeySetData.substr(0, 4).toHexString() + "..."); ++ ++ try { ++ // step 1: add the new keys (note: 1st param 0x0 is for add, 2nd param is not used in putKeys) ++ channel.putKeys((byte)0x0, curKeyInfo.at(1), modKeySetData); ++ CMS.debug(method + " successfully added keys to slot " + tmpVer); ++ } catch (TPSException | IOException e) { ++ CMS.debug(method + " failed to add key to slot " + tmpVer + ": " + e.getMessage()); ++ tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), ++ "Failed to send new GP Key Set to token", "failure"); ++ throw e; ++ } ++ ++ try { ++ // step 2: delete keys at the current version ++ channel.deleteKeys(curKeyInfo.at(0)); ++ CMS.debug(method + " successfully deleted keys in slot " + curKeyInfo.at(0)); ++ } catch (TPSException | IOException e) { ++ CMS.debug(method + " failed to delete keys in slot " + curKeyInfo.at(0) + ": " + e.getMessage()); ++ tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), ++ "Failed to delete GP Key Set from token", "failure"); ++ throw e; ++ } ++ ++ try { ++ // step 3: replace the current version/slot with the new key added in step 1 ++ channel.putKeys(tmpVer, curKeyInfo.at(1), keySetData); ++ CMS.debug(method + " successfully replaced key in slot " + tmpVer + " with key in " + keySetData.at(0)); ++ } catch (TPSException | IOException e) { ++ CMS.debug(method + " failed to replace keys in slot " + tmpVer + " with key in " + keySetData.at(0) + ": " + e.getMessage()); ++ tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), ++ "Failed to send new GP Key Set to token", "failure"); ++ throw e; ++ } ++ ++ // log key changeover event ++ tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), ++ "Sent new GP Key Set to token", "success"); ++ ++ CMS.debug(method + " key info template: " + getKeyInfoTemplate().toHexString()); ++ ++ CMS.debug(method + " changing token db keyInfo to: " + newVersion.toHexStringPlain()); ++ tokenRecord.setKeyInfo(newVersion.toHexStringPlain()); ++ ++ // change the selected keySet name to the new keySet name before calling setupSecureChannel ++ setSelectedKeySet(newKeySet); ++ ++ selectCoolKeyApplet(); ++ ++ channel = setupSecureChannel(newVersion.at(0), (byte)defKeyIndex, connId, appletInfo); ++ ++ CMS.debug(method + " done setupSecureChannel with version " + newVersion.at(0)); ++ ++ auditKeyChangeover(appletInfo, "success", curKeyInfo.toHexString(), newVersion.toHexString(), null); ++ ++ return channel; ++ } ++ ++ ++ /** ++ * ** G&D 256 Key Rollover Support ** ++ * This method upgrade the symmetric key size for the purpose of rolling the 128 OMK to 256 OMK. ++ * The steps include adding the 256-bit keys to a temporary slot (e.g. v3), deleting the current ++ * version 128-bit key, and replacing current version with the 256-bit keys. ++ * ++ * @param appletInfo ++ * @param tokenRecord ++ * @param requiredVersion ++ * @param defKeyIndex ++ * @param connId ++ * @return the SecureChannel set up with new 256-bit key ++ * @throws TPSException ++ * @throws IOException ++ * ++ */ ++ protected SecureChannel upgradeSymKeySize(AppletInfo appletInfo, TokenRecord tokenRecord, int requiredVersion, int defKeyIndex, String connId) throws TPSException, IOException { ++ String method = "TPSProcessor.upgradeSymKeySize: CUID: " + tokenRecord.getId() + ": "; ++ SecureChannel channel = null; ++ TPSSubsystem tps = (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); ++ String oldKeySet = getSelectedKeySet(); ++ String newKeySet = oldKeySet; ++ try { ++ // find keySet name for the 256-bit sym key ++ String resolverInstName = getKeySetResolverInstanceName(); ++ if (resolverInstName != null && !resolverInstName.equals("none")) { ++ FilterMappingParams mappingParams = createFilterMappingParams(resolverInstName, ++ appletInfo.getCUIDhexStringPlain(), appletInfo.getMSNString(), ++ appletInfo.getMajorVersion(), appletInfo.getMinorVersion()); ++ TPSSubsystem subsystem = ++ (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); ++ BaseMappingResolver resolverInst = ++ subsystem.getMappingResolverManager().getResolverInstance(resolverInstName); ++ ++ newKeySet = resolverInst.getResolvedMapping(mappingParams, "keySet", 256); ++ CMS.debug(method + " resolved keySet: " + newKeySet); ++ } else { ++ throw new TPSException("Invalid keySet resolver instance name: " + resolverInstName, TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ } catch (TPSException e) { ++ tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), e.toString(), ++ "failure"); ++ throw new TPSException(e.toString(), TPSStatus.STATUS_ERROR_MISCONFIGURATION); ++ } ++ ++ // Make sure correct card manager is selected ++ if (getSelectedCardMgr().size() == 0) { ++ selectDefaultCardManager(); ++ } ++ else { ++ selectCardMgr(getSelectedCardMgr()); ++ } ++ appletInfo.setAid(getSelectedCardMgr()); ++ ++ channel = setupSecureChannel(appletInfo); ++ auditKeyChangeoverRequired(appletInfo, channel.getKeyInfoData().toHexStringPlain(), getSymmetricKeysRequiredVersionHexString(), null); ++ ++ // get the temporary slot (key version) where keys will be added to ++ byte tmpVer = (byte)getKeyRolloverTempSlot(); ++ ++ TPSEngine engine = getTPSEngine(); ++ int protocol = 3; ++ TPSBuffer curKeyInfo = channel.getKeyInfoData(); ++ CMS.debug(method + " curKeyInfo: " + curKeyInfo.toHexString()); ++ ++ byte[] nv = new byte[] { (byte)requiredVersion, curKeyInfo.at(1), curKeyInfo.at(2) }; ++ TPSBuffer newVersion = new TPSBuffer(nv); ++ CMS.debug(method + " newVersion: " + newVersion.toHexString()); ++ ++ // get key data from TKS ++ TPSBuffer keySetData = engine.createKeySetData(newVersion, curKeyInfo, protocol, ++ appletInfo.getCUID(),channel.getKeyDiversificationData(), channel.getDekSessionKeyWrapped(), connId, newKeySet, oldKeySet); ++ CMS.debug(method + " new keySetData from TKS: " + keySetData.substr(0, 4).toHexString() + "..."); ++ ++ // change the 1st byte of keySetData to the configured temporary key version (slot where keys to be added to) ++ TPSBuffer modKeySetData = new TPSBuffer(keySetData); ++ modKeySetData.setAt(0, (byte)tmpVer); ++ CMS.debug(method + " modified keySetData from TKS before add key: " + modKeySetData.substr(0, 4).toHexString() + "..."); ++ ++ try { ++ // step 1: add new 256 OMK to temp slot or 3 (note: 1st param 0x0 is for add, 2nd param is not used in putKeys) ++ channel.putKeys((byte)0x0, curKeyInfo.at(1), modKeySetData); ++ CMS.debug(method + " successfully added keys to slot " + tmpVer); ++ } catch (TPSException | IOException e) { ++ CMS.debug(method + " failed to add key to slot " + tmpVer + ": " + e.getMessage()); ++ ++ // Attempt to recover from previous upgrade failure: ++ // Check whether the exception is caused by the previous failure during deleteKeys. ++ // The previous deleteKeys failure can be determined by the number of keys in ++ // the key info template. There are 3 keys in each set of keys. If 2 sets of keys (6 keys) ++ // are in the key info template, then we can proceed with deleteKeys. ++ boolean errorOutNow = true; ++ if (platProtInfo != null) { ++ TPSBuffer keyTemplateOnCard = platProtInfo.getKeysetInfoData(); ++ CMS.debug(method + " key template on card: " + keyTemplateOnCard.toHexString()); ++ ++ // The 2nd byte in the key info template tells the total number of bytes of all the keys. ++ // Each key is made up of 6 bytes in the template. ++ byte dataLength = keyTemplateOnCard.at(1); ++ CMS.debug(method + " data length: " + String.format("%02X", dataLength)); ++ ++ // if 2 sets of keys on card (0x24 = 36; 36/6 = 6 keys), ++ // try to recover from previous failure by continuing to delete keys ++ if (dataLength == (byte) 0x24) ++ { ++ CMS.debug(method + " Found 2 sets of keys on card. Try to delete keys"); ++ errorOutNow = false; ++ } ++ } ++ // If exception is not caused by previous deleteKeys failure, throw the exception ++ if (errorOutNow) ++ { ++ tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), ++ "Failed to send new GP Key Set to token", "failure"); ++ throw e; ++ } ++ } ++ ++ try { ++ // Step 2: delete the 128 OMK in current slot (S21) ++ channel.deleteKeys(curKeyInfo.at(0)); ++ CMS.debug(method + " successfully deleted keys in slot " + curKeyInfo.at(0)); ++ } catch (TPSException | IOException e) { ++ CMS.debug(method + " failed to delete keys in slot " + curKeyInfo.at(0) + ": " + e.getMessage()); ++ tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), ++ "Failed to delete GP Key Set from token", "failure"); ++ throw e; ++ } ++ ++ try { ++ // Step 3: replace key: move the 256 OMK from temp slot (S3) to the current slot (S21) ++ channel.putKeys(tmpVer, curKeyInfo.at(1), keySetData); ++ CMS.debug(method + " successfully replaced keys in slot " + tmpVer + " with keys in " + keySetData.at(0)); ++ } catch (TPSException | IOException e) { ++ CMS.debug(method + " failed to replace keys in slot " + tmpVer + " with key in " + keySetData.at(0) + ": " + e.getMessage()); ++ tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), ++ "Failed to send new GP Key Set to token", "failure"); ++ throw e; ++ } ++ ++ // log key changeover event ++ tps.tdb.tdbActivity(ActivityDatabase.OP_KEY_CHANGEOVER, tokenRecord, session.getIpAddress(), ++ "Sent new GP Key Set to token", "success"); ++ ++ CMS.debug(method + " key info template: " + getKeyInfoTemplate().toHexString()); ++ ++ CMS.debug(method + " changing token db keyInfo to: " + newVersion.toHexStringPlain()); ++ tokenRecord.setKeyInfo(newVersion.toHexStringPlain()); ++ ++ // change the selected keySet name to the new 256 keySet name before calling setupSecureChannel ++ setSelectedKeySet(newKeySet); ++ ++ // this is needed for using the secure channel to set the PIN on token ++ selectCoolKeyApplet(); ++ ++ // create the secure channel with S21:256 OMK ++ channel = setupSecureChannel(newVersion.at(0), (byte)defKeyIndex, connId, appletInfo); ++ ++ CMS.debug(method + " done setupSecureChannel with version " + newVersion.at(0)); ++ ++ auditKeyChangeover(appletInfo, "success", curKeyInfo.toHexString(), newVersion.toHexString(), null); ++ ++ return channel; ++ } ++ ++ // ** Applet and Alg Selection by Token Range Support ** ++ protected void setSelectedKeyWrapAlg(String theKeyWrapAlg) { ++ selectedKeyWrapAlg = theKeyWrapAlg; ++ } ++ ++ public String getSelectedKeyWrapAlg() { ++ return selectedKeyWrapAlg; ++ } ++ ++ protected void setSelectedAppletVer(String theAppletVer) { ++ selectedAppletVer = theAppletVer; ++ } ++ ++ public String getSelectedAppletVer() { ++ return selectedAppletVer; ++ } ++ ++ public boolean isDesConfigured() { ++ boolean configured = (selectedKeyWrapAlg != null && selectedKeyWrapAlg.equalsIgnoreCase("DES")); ++ CMS.debug("TPSProcessor.isDesConfigured: returning " + configured); ++ return configured; ++ } ++ + public static void main(String[] args) { + } + +-- +1.8.3.1 + diff --git a/SPECS/pki-core.spec b/SPECS/pki-core.spec index f78ddfa..bd0ff1d 100644 --- a/SPECS/pki-core.spec +++ b/SPECS/pki-core.spec @@ -65,13 +65,13 @@ Name: pki-core %if 0%{?rhel} Version: 10.5.18 -%define redhat_release 27 +%define redhat_release 32 %define redhat_stage 0 #%define default_release %{redhat_release}.%{redhat_stage} %define default_release %{redhat_release} %else Version: 10.5.18 -%define fedora_release 27 +%define fedora_release 32 %define fedora_stage 0 #%define default_release %{fedora_release}.%{fedora_stage} %define default_release %{fedora_release} @@ -92,6 +92,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: cmake >= 2.8.9-1 BuildRequires: gcc-c++ +BuildRequires: git BuildRequires: zip BuildRequires: java-1.8.0-openjdk-devel BuildRequires: redhat-rpm-config @@ -105,8 +106,8 @@ BuildRequires: slf4j %if 0%{?fedora} || 0%{?rhel} > 7 BuildRequires: slf4j-jdk14 %endif -BuildRequires: nspr-devel -BuildRequires: nss-devel >= 3.28.3 +BuildRequires: nspr-devel >= 4.35.0-1 +BuildRequires: nss-devel >= 3.90.0-2 %if 0%{?rhel} && 0%{?rhel} <= 7 BuildRequires: nuxwdog-client-java >= 1.0.5-1 @@ -165,7 +166,7 @@ BuildRequires: policycoreutils-python-utils BuildRequires: python-ldap BuildRequires: junit BuildRequires: jpackage-utils >= 0:1.7.5-10 -BuildRequires: jss >= 4.4.9-3 +BuildRequires: jss >= 4.4.9-4 %if 0%{?rhel} && 0%{?rhel} <= 7 BuildRequires: tomcatjss >= 7.2.5-1 %else @@ -231,6 +232,12 @@ Patch22: pki-core-rhel-7-9-rhcs-9-7-bu-19.patch Patch23: pki-core-rhel-7-9-rhcs-9-7-bu-21.patch #Patch24: pki-core-rhel-7-9-rhcs-9-7-bu-22.patch Patch25: pki-core-rhel-7-9-rhcs-9-7-bu-23.patch +Patch26: pki-core-rhel-7-9-rhcs-9-7-CY24Q2.patch +Patch27: pki-core-rhel-7-9-rhcs-9-7-CVE-2023-4727.patch +Patch28: pki-core-rhel-7-9-rhcs-9-7-CY24Q2.1.patch +Patch29: pki-core-rhel-7-9-rhcs-9-7-CY24Q2.2.patch +Patch30: pki-core-rhel-7-9-rhcs-9-7-CY24Q2.3.patch +Patch31: pki-core-rhel-7-9-rhcs-9-7-CY24Q2.4.patch # Obtain version phase number (e. g. - used by "alpha", "beta", etc.) # @@ -330,8 +337,8 @@ Group: System Environment/Libraries Requires: java-1.8.0-openjdk-headless Requires: jpackage-utils >= 0:1.7.5-10 -Requires: jss >= 4.4.9-3 -Requires: nss >= 3.28.3 +Requires: jss >= 4.4.9-4 +Requires: nss >= 3.90.0-2 Provides: symkey = %{version}-%{release} @@ -378,7 +385,7 @@ Obsoletes: pki-util < %{version}-%{release} Conflicts: freeipa-server < 3.0.0 -Requires: nss >= 3.28.3 +Requires: nss >= 3.90.0-2 Requires: python2-cryptography Requires: python-nss Requires: python-requests >= 2.6.0 @@ -409,7 +416,7 @@ Requires: slf4j-jdk14 %endif Requires: javassist Requires: jpackage-utils >= 0:1.7.5-10 -Requires: jss >= 4.4.9-3 +Requires: jss >= 4.4.9-4 Requires: ldapjdk >= 4.19-5 Requires: pki-base = %{version}-%{release} @@ -480,7 +487,7 @@ Obsoletes: pki-native-tools < %{version}-%{release} Obsoletes: pki-java-tools < %{version}-%{release} Requires: openldap-clients -Requires: nss-tools >= 3.28.3 +Requires: nss-tools >= 3.90.0-2 Requires: java-1.8.0-openjdk-headless Requires: pki-base = %{version}-%{release} Requires: pki-base-java = %{version}-%{release} @@ -771,7 +778,7 @@ Requires(postun): systemd-units # additional runtime requirements needed to run native 'tpsclient' # REMINDER: Revisit these once 'tpsclient' is rewritten as a Java app -Requires: nss-tools >= 3.28.3 +Requires: nss-tools >= 3.90.0-2 Requires: openldap-clients %if 0%{?package_fedora_packages} || 0%{?package_rhel_packages} Requires: pki-symkey = %{version}-%{release} @@ -826,36 +833,14 @@ This package is a part of the PKI Core used by the Certificate System. %endif # %{with server} - +# Replace "%setup -q -n %{name}-%{version}%{?prerel}" with "%autosetup -S git" +# in order to use "git apply " since "%patch0 -p1" doesn't +# support binary patches! %prep -%setup -q -n %{name}-%{version}%{?prerel} - -%patch0 -p1 -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 -%patch16 -p1 -%patch17 -p1 -#%patch18 -p1 -%patch19 -p1 -#%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -#%patch24 -p1 -%patch25 -p1 + + +%autosetup -S git + %clean %{__rm} -rf %{buildroot} @@ -1392,6 +1377,177 @@ fi %endif # %{with server} %changelog +* Mon Jun 3 2024 Dogtag Team 10.5.18-32 +- ########################################################################## +- # RHEL 7.9 (Async Security Update CY24Q2.4): +- ########################################################################## +- Updated nspr-devel and nss-devel build requirements as well as nss and + nss-tools runtime requirements (mharmsen) +- Updated jss dependencies (mharmsen) +- Added git build dependency (mharmsen) +- Additional trivial fix (jmagne) +- RHEL-9917 - EMBARGOED CVE-2023-4727 pki-core: dogtag ca: + token authentication bypass vulnerability [rhel-7.9.z] (jmagne) +- RHEL-24339 - pki-core - PrettyPrintCert does not properly + translate AIA information into a readable format [RHEL 7.9.z] (mfargett) +- RHEL-26881 - Fix additional OID mappings [RHEL 7.9.z] (mfargett) +- ########################################################################## +- # RHCS 9.7 (Async Security Update CY24Q2.4): +- ########################################################################## +- Bug 2047831 - Coolkey Hardcoded RSA Max Key Size + [RHCS 9.7.z] (jmagne) +- Bug 2121463 - Add Secure Channel Support for AES-256 Keys + [RHCS 9.7.z] (jmagne) +- Bug 2177785 - TPS missing Host header field in HTTP/1.1 request + message [RHCS 9.7.z] (mfargett) +- Bug 2180920 - add AES support for TMS server-side keygen on latest + HSM / FIPS environment [RHCS 9.7.z] (jmagne) +- Bug 2233158 - Make key wrapping algorithm configurable + between AES-KWP and AES-CBC [RHCS 9.7.z] (jmagne) +- Bug 2253682 - pkidestroy log keeps HSM token password + [RHCS 9.7.z] (mfargett, jmagne) +- Bug 2265180 - Add Support for Symmetric Key Rollover + [RHCS 9.7.z] (jmagne) +- Bug 2280722 - Shared token is not generated for TPS and TKS + during install despite adding pki_import_shared_secret=True param + at install [RHCS 9.7.z] (jmagne) + +* Fri May 31 2024 Dogtag Team 10.5.18-31 +- ########################################################################## +- # RHEL 7.9 (Async Security Update CY24Q2.3): +- ########################################################################## +- Updated nspr-devel and nss-devel build requirements as well as nss and + nss-tools runtime requirements (mharmsen) +- Updated jss dependencies (mharmsen) +- Added git build dependency (mharmsen) +- Additional trivial fix (jmagne) +- RHEL-9917 - EMBARGOED CVE-2023-4727 pki-core: dogtag ca: + token authentication bypass vulnerability [rhel-7.9.z] (jmagne) +- RHEL-24339 - pki-core - PrettyPrintCert does not properly + translate AIA information into a readable format [RHEL 7.9.z] (mfargett) +- RHEL-26881 - Fix additional OID mappings [RHEL 7.9.z] (mfargett) +- ########################################################################## +- # RHCS 9.7 (Async Security Update CY24Q2.3): +- ########################################################################## +- Bug 2047831 - Coolkey Hardcoded RSA Max Key Size + [RHCS 9.7.z] (jmagne) +- Bug 2121463 - Add Secure Channel Support for AES-256 Keys + [RHCS 9.7.z] (jmagne) +- Bug 2177785 - TPS missing Host header field in HTTP/1.1 request + message [RHCS 9.7.z] (mfargett) +- Bug 2180920 - add AES support for TMS server-side keygen on latest + HSM / FIPS environment [RHCS 9.7.z] (jmagne) +- Bug 2233158 - Make key wrapping algorithm configurable + between AES-KWP and AES-CBC [RHCS 9.7.z] (jmagne) +- Bug 2253682 - pkidestroy log keeps HSM token password + [RHCS 9.7.z] (mfargett, jmagne) +- Bug 2265180 - Add Support for Symmetric Key Rollover + [RHCS 9.7.z] (jmagne) +- Bug 2280722 - Shared token is not generated for TPS and TKS + during install despite adding pki_import_shared_secret=True param + at install [RHCS 9.7.z] (jmagne) + +* Thu May 23 2024 Dogtag Team 10.5.18-30 +- ########################################################################## +- # RHEL 7.9 (Async Security Update CY24Q2.2): +- ########################################################################## +- Updated nspr-devel and nss-devel build requirements as well as nss and + nss-tools runtime requirements (mharmsen) +- Updated jss dependencies (mharmsen) +- Added git build dependency (mharmsen) +- Additional trivial fix (jmagne) +- RHEL-9917 - EMBARGOED CVE-2023-4727 pki-core: dogtag ca: + token authentication bypass vulnerability [rhel-7.9.z] (jmagne) +- RHEL-24339 - pki-core - PrettyPrintCert does not properly + translate AIA information into a readable format [RHEL 7.9.z] (mfargett) +- RHEL-26881 - Fix additional OID mappings [RHEL 7.9.z] (mfargett) +- ########################################################################## +- # RHCS 9.7 (Async Security Update CY24Q2.2): +- ########################################################################## +- Bug 2047831 - Coolkey Hardcoded RSA Max Key Size + [RHCS 9.7.z] (jmagne) +- Bug 2121463 - Add Secure Channel Support for AES-256 Keys + [RHCS 9.7.z] (jmagne) +- Bug 2177785 - TPS missing Host header field in HTTP/1.1 request + message [RHCS 9.7.z] (mfargett) +- Bug 2180920 - add AES support for TMS server-side keygen on latest + HSM / FIPS environment [RHCS 9.7.z] (jmagne) +- Bug 2233158 - Make key wrapping algorithm configurable + between AES-KWP and AES-CBC [RHCS 9.7.z] (jmagne) +- Bug 2253682 - pkidestroy log keeps HSM token password + [RHCS 9.7.z] (mfargett, jmagne) +- Bug 2265180 - Add Support for Symmetric Key Rollover + [RHCS 9.7.z] (jmagne) +- Bug 2280722 - Shared token is not generated for TPS and TKS + during install despite adding pki_import_shared_secret=True param + at install [RHCS 9.7.z] (jmagne) + +* Fri May 17 2024 Dogtag Team 10.5.18-29 +- ########################################################################## +- # RHEL 7.9 (Async Security Update CY24Q2.1): +- ########################################################################## +- Updated nspr-devel and nss-devel build requirements as well as nss and + nss-tools runtime requirements (mharmsen) +- Updated jss dependencies (mharmsen) +- Added git build dependency (mharmsen) +- Additional trivial fix (jmagne) +- RHEL-9917 - EMBARGOED CVE-2023-4727 pki-core: dogtag ca: + token authentication bypass vulnerability [rhel-7.9.z] (jmagne) +- RHEL-24339 - pki-core - PrettyPrintCert does not properly + translate AIA information into a readable format [RHEL 7.9.z] (mfargett) +- RHEL-26881 - Fix additional OID mappings [RHEL 7.9.z] (mfargett) +- ########################################################################## +- # RHCS 9.7 (Async Security Update CY24Q2.1): +- ########################################################################## +- Bug 2047831 - Coolkey Hardcoded RSA Max Key Size + [RHCS 9.7.z] (jmagne) +- Bug 2121463 - Add Secure Channel Support for AES-256 Keys + [RHCS 9.7.z] (jmagne) +- Bug 2177785 - TPS missing Host header field in HTTP/1.1 request + message [RHCS 9.7.z] (mfargett) +- Bug 2180920 - add AES support for TMS server-side keygen on latest + HSM / FIPS environment [RHCS 9.7.z] (jmagne) +- Bug 2233158 - Make key wrapping algorithm configurable + between AES-KWP and AES-CBC [RHCS 9.7.z] (jmagne) +- Bug 2253682 - pkidestroy log keeps HSM token password + [RHCS 9.7.z] (mfargett, jmagne) +- Bug 2265180 - Add Support for Symmetric Key Rollover + [RHCS 9.7.z] (jmagne) +- Bug 2280722 - Shared token is not generated for TPS and TKS + during install despite adding pki_import_shared_secret=True param + at install [RHCS 9.7.z] (jmagne) + +* Thu Apr 18 2024 Dogtag Team 10.5.18-28 +- ########################################################################## +- # RHEL 7.9 (Async Security Update CY24Q2): +- ########################################################################## +- Updated nspr-devel and nss-devel build requirements as well as nss and + nss-tools runtime requirements (mharmsen) +- Updated jss dependencies (mharmsen) +- Added git build dependency (mharmsen) +- RHEL-9917 - EMBARGOED CVE-2023-4727 pki-core: dogtag ca: + token authentication bypass vulnerability [rhel-7.9.z] (jmagne) +- RHEL-24339 - pki-core - PrettyPrintCert does not properly + translate AIA information into a readable format [RHEL 7.9.z] (mfargett) +- RHEL-26881 - Fix additional OID mappings [RHEL 7.9.z] (mfargett) +- ########################################################################## +- # RHCS 9.7 (Async Security Update CY24Q2): +- ########################################################################## +- Bug 2047831 - Coolkey Hardcoded RSA Max Key Size + [RHCS 9.7.z] (jmagne) +- Bug 2121463 - Add Secure Channel Support for AES-256 Keys + [RHCS 9.7.z] (jmagne) +- Bug 2177785 - TPS missing Host header field in HTTP/1.1 request + message [RHCS 9.7.z] (mfargett) +- Bug 2180920 - add AES support for TMS server-side keygen on latest + HSM / FIPS environment [RHCS 9.7.z] (jmagne) +- Bug 2233158 - Make key wrapping algorithm configurable + between AES-KWP and AES-CBC [RHCS 9.7.z] (jmagne) +- Bug 2253682 - pkidestroy log keeps HSM token password + [RHCS 9.7.z] (mfargett) +- Bug 2265180 - Add Support for Symmetric Key Rollover + [RHCS 9.7.z] (jmagne) + * Mon May 1 2023 Dogtag Team 10.5.18-27 - ########################################################################## - # RHEL 7.9 (Batch Update 23):