From f232790c48747fa5be3a75fbdfafa7f1a48d50ac Mon Sep 17 00:00:00 2001 From: jmagne Date: Fri, 16 Sep 2011 02:34:02 +0000 Subject: Fix bugzilla #730162 - TPS/TKS token enrollment failure in FIPS mode (hsm+NSS) . git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/trunk@2205 c9f7a03b-bd48-0410-a16d-cbbf54688b0b --- .../cms/selftests/tks/TKSKnownSessionKey.java | 19 +- .../cms/servlet/csadmin/CertRequestPanel.java | 4 +- .../com/netscape/cms/servlet/tks/TokenServlet.java | 59 +- .../symkey/src/com/netscape/symkey/EncryptData.cpp | 244 +-- .../symkey/src/com/netscape/symkey/SessionKey.cpp | 1624 ++++++++++++-------- .../symkey/src/com/netscape/symkey/SessionKey.java | 27 +- pki/base/symkey/src/com/netscape/symkey/SymKey.cpp | 828 ++++++---- pki/base/symkey/src/com/netscape/symkey/SymKey.h | 12 +- pki/base/tks/shared/conf/CS.cfg.in | 2 + pki/base/tps/doc/CS.cfg.in | 5 +- pki/base/tps/src/engine/RA.cpp | 241 ++- pki/base/tps/src/include/engine/RA.h | 5 + 12 files changed, 1914 insertions(+), 1156 deletions(-) (limited to 'pki/base') diff --git a/pki/base/common/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java b/pki/base/common/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java index 05337bd96..b030759f7 100644 --- a/pki/base/common/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java +++ b/pki/base/common/src/com/netscape/cms/selftests/tks/TKSKnownSessionKey.java @@ -34,6 +34,8 @@ import com.netscape.certsrv.selftests.*; import com.netscape.cms.selftests.*; import java.util.*; import com.netscape.symkey.*; +import org.mozilla.jss.crypto.*; + ////////////////////// @@ -132,7 +134,7 @@ extends ASelfTest if (mSessionKey == null) { mSessionKey = SessionKey.ComputeSessionKey (mToken, mKeyName, mCardChallenge, mHostChallenge, - mKeyInfo, mCUID, mMacKey, mUseSoftToken); + mKeyInfo, mCUID, mMacKey, mUseSoftToken, null, null); if (mSessionKey == null || mSessionKey.length != 16) { mSelfTestSubsystem.log (mSelfTestSubsystem.getSelfTestLogger(), CMS.getLogMessage("SELFTESTS_MISSING_VALUES", @@ -295,23 +297,21 @@ extends ASelfTest throws ESelfTestException { String logMessage = null; + String keySet = "defKeySet"; byte[] sessionKey = SessionKey.ComputeSessionKey (mToken, mKeyName, mCardChallenge, mHostChallenge, - mKeyInfo, mCUID, mMacKey, mUseSoftToken); + mKeyInfo, mCUID, mMacKey, mUseSoftToken, keySet, null); + + // Now we just see if we can successfully generate a session key. + // For FIPS compliance, the routine now returns a wrapped key, which can't be extracted and compared. if (sessionKey == null) { CMS.debug("TKSKnownSessionKey: generated no session key"); CMS.debug("TKSKnownSessionKey self test FAILED"); logMessage = CMS.getLogMessage ("SELFTESTS_TKS_FAILED", getSelfTestName(), getSelfTestName()); mSelfTestSubsystem.log (logger, logMessage); throw new ESelfTestException( logMessage ); - } else if (!Arrays.equals(mSessionKey, sessionKey)) { - CMS.debug("TKSKnownSessionKey: generated invalid session key"); - CMS.debug("TKSKnownSessionKey self test FAILED"); - logMessage = CMS.getLogMessage ("SELFTESTS_TKS_FAILED", getSelfTestName(), getSelfTestName()); - mSelfTestSubsystem.log (logger, logMessage); - throw new ESelfTestException( logMessage ); - } else { + } else { logMessage = CMS.getLogMessage ("SELFTESTS_TKS_SUCCEEDED", getSelfTestName(), getSelfTestName()); mSelfTestSubsystem.log (logger, logMessage); CMS.debug("TKSKnownSessionKey self test SUCCEEDED"); @@ -320,4 +320,3 @@ extends ASelfTest return; } } - diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java index 842f87b5f..1a67cf129 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java @@ -623,8 +623,8 @@ public class CertRequestPanel extends WizardPanelBase { } if (/*(certchains.length <= 1) &&*/ - (b64chain != null)) { - CMS.debug("CertRequestPanel: cert might not have contained chain...calling importCertificateChain"); + (b64chain != null && b64chain.length() != 0)) { + CMS.debug("CertRequestPanel: cert might not have contained chain...calling importCertificateChain: " + b64chain); try { CryptoUtil.importCertificateChain( CryptoUtil.normalizeCertAndReq(b64chain)); diff --git a/pki/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.java b/pki/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.java index 9e0901a2c..4cc2654b7 100644 --- a/pki/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.java +++ b/pki/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.java @@ -61,7 +61,7 @@ import com.netscape.symkey.*; */ public class TokenServlet extends CMSServlet { protected static final String PROP_ENABLED = "enabled"; - + protected static final String TRANSPORT_KEY_NAME ="sharedSecret"; private final static String INFO = "TokenServlet"; public static int ERROR = 1; private ITKSAuthority mTKS = null; @@ -251,6 +251,7 @@ public class TokenServlet extends CMSServlet { String auditMessage = null; String errorMsg = ""; String badParams = ""; + String transportKeyName = ""; String rCUID = req.getParameter("CUID"); String keySet = req.getParameter("keySet"); @@ -261,7 +262,7 @@ public class TokenServlet extends CMSServlet { boolean serversideKeygen = false; byte[] drm_trans_wrapped_desKey = null; - SymmetricKey desKey = null; + PK11SymKey desKey = null; // PK11SymKey kek_session_key; PK11SymKey kek_key; @@ -311,6 +312,14 @@ public class TokenServlet extends CMSServlet { } catch (EBaseException eee) { } + try { + transportKeyName = sconfig.getString("tks.tksSharedSymKeyName",TRANSPORT_KEY_NAME); + } catch (EBaseException e) { + } + + CMS.debug("TokenServlet: ComputeSessionKey(): tksSharedSymKeyName: " + transportKeyName); + + String rcard_challenge = req.getParameter("card_challenge"); String rhost_challenge = req.getParameter("host_challenge"); String rKeyInfo = req.getParameter("KeyInfo"); @@ -407,7 +416,7 @@ public class TokenServlet extends CMSServlet { CMS.debug("TokenServlet about to try ComputeSessionKey selectedToken=" + selectedToken + " keyNickName=" + keyNickName); session_key = SessionKey.ComputeSessionKey( selectedToken,keyNickName,card_challenge, - host_challenge,keyInfo,CUID, macKeyArray, useSoftToken_s); + host_challenge,keyInfo,CUID, macKeyArray, useSoftToken_s, keySet, transportKeyName ); if(session_key == null) { @@ -419,7 +428,7 @@ public class TokenServlet extends CMSServlet { byte encKeyArray[] = com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".auth_key")); enc_session_key = SessionKey.ComputeEncSessionKey( selectedToken,keyNickName,card_challenge, - host_challenge,keyInfo,CUID, encKeyArray, useSoftToken_s); + host_challenge,keyInfo,CUID, encKeyArray, useSoftToken_s, keySet); if(enc_session_key == null) { @@ -440,9 +449,13 @@ public class TokenServlet extends CMSServlet { CMS.debug("TokenServlet: calling ComputeKekKey"); byte kekKeyArray[] = com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key")); + + kek_key = SessionKey.ComputeKekKey( selectedToken,keyNickName,card_challenge, - host_challenge,keyInfo,CUID, kekKeyArray, useSoftToken_s); + host_challenge,keyInfo,CUID, kekKeyArray, useSoftToken_s,keySet); + + CMS.debug("TokenServlet: called ComputeKekKey"); if(kek_key == null) @@ -470,14 +483,14 @@ public class TokenServlet extends CMSServlet { */ /*generate it on whichever token the master key is at*/ if (useSoftToken_s.equals("true")) { - CMS.debug("TokenServlet: key encryption key generated on internal"); + CMS.debug("TokenServlet: key encryption key generated on internal"); //cfu audit here? sym key gen - desKey = SessionKey.GenerateSymkey("internal"); + desKey = SessionKey.GenerateSymkey("internal"); //cfu audit here? sym key gen done - } else { - CMS.debug("TokenServlet: key encryption key generated on " + selectedToken); - desKey = SessionKey.GenerateSymkey(selectedToken); - } + } else { + CMS.debug("TokenServlet: key encryption key generated on " + selectedToken); + desKey = SessionKey.GenerateSymkey(selectedToken); + } if (desKey != null) CMS.debug("TokenServlet: key encryption key generated for "+rCUID); else { @@ -492,7 +505,7 @@ public class TokenServlet extends CMSServlet { */ byte[] encDesKey = SessionKey.ECBencrypt( kek_key, - desKey.getKeyData()); + desKey); /* CMS.debug("computeSessionKey:encrypted desKey size = "+encDesKey.length); CMS.debug(encDesKey); @@ -503,7 +516,7 @@ public class TokenServlet extends CMSServlet { // get keycheck byte[] keycheck = - SessionKey.ComputeKeyCheck(desKey.getKeyData()); + SessionKey.ComputeKeyCheck(desKey); /* CMS.debug("computeSessionKey:keycheck size = "+keycheck.length); CMS.debug(keycheck); @@ -525,11 +538,12 @@ public class TokenServlet extends CMSServlet { drmTransCert = CryptoManager.getInstance().findCertByNickname(drmTransNickname); // wrap kek session key with DRM transport public key CryptoToken token = null; - if (useSoftToken_s.equals("true")) { - token = CryptoManager.getInstance().getTokenByName("Internal Key Storage Token"); - } else { - token = CryptoManager.getInstance().getTokenByName(selectedToken); - } + if (useSoftToken_s.equals("true")) { + //token = CryptoManager.getInstance().getTokenByName(selectedToken); + token = CryptoManager.getInstance().getInternalCryptoToken(); + } else { + token = CryptoManager.getInstance().getTokenByName(selectedToken); + } PublicKey pubKey = drmTransCert.getPublicKey(); String pubKeyAlgo = pubKey.getAlgorithm(); CMS.debug("Transport Cert Key Algorithm: " + pubKeyAlgo); @@ -542,6 +556,7 @@ public class TokenServlet extends CMSServlet { keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.RSA); keyWrapper.initWrap(pubKey, null); } + CMS.debug("desKey token " + desKey.getOwningToken().getName() + " token: " + token.getName() ); drm_trans_wrapped_desKey = keyWrapper.wrap(desKey); CMS.debug("computeSessionKey:desKey wrapped with drm transportation key."); @@ -550,7 +565,7 @@ public class TokenServlet extends CMSServlet { byte authKeyArray[] = com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".auth_key")); host_cryptogram = SessionKey.ComputeCryptogram( selectedToken,keyNickName,card_challenge, - host_challenge,keyInfo,CUID,0, authKeyArray, useSoftToken_s); + host_challenge,keyInfo,CUID,0, authKeyArray, useSoftToken_s, keySet); if(host_cryptogram == null) { @@ -560,7 +575,7 @@ public class TokenServlet extends CMSServlet { } card_crypto = SessionKey.ComputeCryptogram( selectedToken,keyNickName,card_challenge, - host_challenge,keyInfo,CUID,1, authKeyArray, useSoftToken_s); + host_challenge,keyInfo,CUID,1, authKeyArray, useSoftToken_s, keySet); if(card_crypto == null) { @@ -880,7 +895,7 @@ public class TokenServlet extends CMSServlet { byte kekKeyArray[] = com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key")); KeySetData = SessionKey.DiversifyKey(oldSelectedToken, newSelectedToken, oldKeyNickName, - newKeyNickName,rnewKeyInfo,CUID, kekKeyArray, useSoftToken_s); + newKeyNickName,rnewKeyInfo,CUID, kekKeyArray, useSoftToken_s, keySet); if (KeySetData == null || KeySetData.length<=1) { CMS.getLogger().log(ILogger.EV_AUDIT, @@ -1084,7 +1099,7 @@ public class TokenServlet extends CMSServlet { byte kekKeyArray[] = com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key")); encryptedData = SessionKey.EncryptData( - selectedToken,keyNickName,data,keyInfo,CUID, kekKeyArray, useSoftToken_s); + selectedToken,keyNickName,data,keyInfo,CUID, kekKeyArray, useSoftToken_s, keySet); CMS.getLogger().log(ILogger.EV_AUDIT, ILogger.S_TKS, diff --git a/pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp b/pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp index ff9e91df0..ccb817f7c 100644 --- a/pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp +++ b/pki/base/symkey/src/com/netscape/symkey/EncryptData.cpp @@ -41,94 +41,25 @@ extern "C" PRFileDesc *d = NULL; -/** - * Encrypt 'cc_len' bytes of data in 'input' with key kek_key. - * Result goes into buffer 'output' - * Returns PR_FAILURE if there was an error - */ -PRStatus EncryptData(const Buffer &kek_key, jbyte * input,int cc_len, Buffer &output) +void GetKeyName(jbyte *keyVersion, char *keyname) { - PRStatus rv = PR_FAILURE; - - PK11SymKey *master = NULL; - PK11SlotInfo *slot = PK11_GetInternalKeySlot(); - PK11Context *context = NULL; - int i; - SECStatus s = SECFailure; - int len; - static SECItem noParams = { siBuffer, 0, 0 }; -#ifdef DES2_WORKAROUND - unsigned char masterKeyData[24]; -#else - unsigned char masterKeyData[16]; -#endif - SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) }; - unsigned char result[8]; - -// convert 16-byte to 24-byte triple-DES key - memcpy(masterKeyData, kek_key, 16); -#ifdef DES2_WORKAROUND - memcpy(masterKeyData+16, kek_key, 8); -#endif - - master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem, - CKF_ENCRYPT, PR_FALSE, 0); - if (master == NULL) - { - goto done; - } - - context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master, - &noParams); - if (context == NULL) - { - goto done; - } - - for(i = 0;i < (int)cc_len;i += 8) - { - s = PK11_CipherOp(context, result, &len, 8, - (unsigned char *)(input+i), 8); - - if (s != SECSuccess) - { - goto done; - } - output.replace(i, result, 8); - } - - rv = PR_SUCCESS; + int index=0; -done: - /* memset(masterKeyData, 0, sizeof masterKeyData); */ - if (context != NULL) - { - PK11_DestroyContext(context, PR_TRUE); - context = NULL; - } - if (slot != NULL) - { - PK11_FreeSlot(slot); - slot = NULL; - } - if (master != NULL) - { - PK11_FreeSymKey(master); - master = NULL; + if( !keyname || !keyVersion || + (strlen(keyname) < KEYNAMELENGTH)) { + return; } - return rv; -} - -void GetKeyName(jbyte *keyVersion, char *keyname) -{ - int index=0; if(strlen(masterKeyPrefix)!=0) { index= strlen(masterKeyPrefix); strcpy(keyname,masterKeyPrefix); } + + if( (index + 3) >= KEYNAMELENGTH) { + return; + } + keyname[index+0]='#'; sprintf(keyname+index+1,"%.2d", keyVersion[0]); keyname[index+3]='#'; @@ -137,55 +68,112 @@ void GetKeyName(jbyte *keyVersion, char *keyname) extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_EncryptData -(JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring); +(JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring); extern "C" JNIEXPORT jbyteArray JNICALL -Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstring j_tokenName, jstring j_keyName, jbyteArray j_in, jbyteArray keyInfo, jbyteArray CUID, jbyteArray kekKeyArray, jstring useSoftToken_s) +Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstring j_tokenName, jstring j_keyName, jbyteArray j_in, jbyteArray keyInfo, jbyteArray CUID, jbyteArray kekKeyArray, jstring useSoftToken_s,jstring keySet) { - int status = PR_FAILURE; - jbyte * kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL); - jbyte * keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); - jbyte * cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); - jbyte *cc = (jbyte*)(env)->GetByteArrayElements( j_in, NULL); - int cc_len = (env)->GetArrayLength(j_in); + jbyte * kek_key = NULL; - Buffer kek_buffer = Buffer((BYTE*)kek_key, 16); - Buffer out = Buffer(16, (BYTE)0); + PK11SymKey *masterKey = NULL; + PK11SymKey *kekKey = NULL; - /* generate kek key */ - /* identify the masterKey by KeyInfo in TKS */ + Buffer out = Buffer(KEYLENGTH, (BYTE)0); BYTE kekData[KEYLENGTH]; char keyname[KEYNAMELENGTH]; - GetDiversificationData(cuidValue,kekData,kek); + + int status = PR_FAILURE; + + jbyte *cc = NULL; + int cc_len = 0; + jbyte * cuidValue = NULL; + + if( kekKeyArray != NULL) { + kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL); + } else { + return NULL; + } PK11SlotInfo *slot = NULL; - if(j_tokenName != NULL) - { + PK11SlotInfo *internal = PK11_GetInternalKeySlot(); + + Buffer kek_buffer = Buffer((BYTE*)kek_key, KEYLENGTH); + char *keySetStringChars = NULL; + if( keySet != NULL) { + keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL); + } + + char *keySetString = keySetStringChars; + + if ( keySetString == NULL ) { + keySetString = (char *) DEFKEYSET_NAME; + } + + jbyte * keyVersion = NULL; + int keyVersion_len = 0; + if( keyInfo != NULL) { + keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); + if( keyVersion) { + keyVersion_len = (env)->GetArrayLength(keyInfo); + } + } + + if( !keyVersion || (keyVersion_len < 2) ) { + goto done; + } + + if( CUID != NULL) { + cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + } + + if( cuidValue == NULL) { + goto done; + } + + if( j_in != NULL) { + cc = (jbyte*)(env)->GetByteArrayElements( j_in, NULL); + cc_len = (env)->GetArrayLength(j_in); + } + + if( cc == NULL) { + goto done; + } + + GetDiversificationData(cuidValue,kekData,kek); + + PR_fprintf(PR_STDOUT,"In SessionKey: EncryptData! \n"); + + if(j_tokenName != NULL) { char *tokenNameChars = (char *)(env)->GetStringUTFChars(j_tokenName, NULL); slot = ReturnSlot(tokenNameChars); (env)->ReleaseStringUTFChars(j_tokenName, (const char *)tokenNameChars); tokenNameChars = NULL; } - if(j_keyName != NULL) - { + if(j_keyName != NULL) { char *keyNameChars= (char *)(env)->GetStringUTFChars(j_keyName, NULL); strcpy(keyname,keyNameChars); env->ReleaseStringUTFChars(j_keyName, (const char *)keyNameChars); keyNameChars = NULL; } - else - { + else { GetKeyName(keyVersion,keyname); } - PK11SymKey *masterKey = NULL; - - if (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 || + if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 && strcmp( keyname, "#01#01") == 0) || (keyVersion[0] == -1 && strstr(keyname, "#FF") )) { /* default development keyset */ - status = EncryptData(kek_buffer, cc, cc_len, out); + Buffer devInput = Buffer((BYTE*)cc, cc_len); + Buffer empty = Buffer(); + + kekKey = ReturnDeveloperSymKey( internal, (char *) "kek", keySetString, empty); + + if ( kekKey ) { + status = EncryptData(Buffer(),kekKey,devInput, out); + } else { + status = EncryptData(kek_buffer, NULL, devInput, out); + } } else { @@ -198,37 +186,45 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr */ if (masterKey != NULL) { - PK11SymKey *kekKey = ComputeCardKeyOnToken(masterKey,kekData); + kekKey = ComputeCardKeyOnToken(masterKey,kekData); if (kekKey != NULL) { Buffer input = Buffer((BYTE*)cc, cc_len); - status = EncryptDataWithCardKey(kekKey, input, out); - - if (kekKey != NULL) - { - PK11_FreeSymKey( kekKey); - kekKey = NULL; - } + status = EncryptData(Buffer(), kekKey, input, out); } } } } - if (masterKey != NULL) - { +done: + + if (masterKey != NULL) { PK11_FreeSymKey( masterKey); masterKey = NULL; } - if( slot!= NULL ) - { - PK11_FreeSlot( slot ); + if( slot != NULL ) { + PK11_FreeSlot( slot); slot = NULL; } + if( internal != NULL) { + PK11_FreeSlot( internal); + internal = NULL; + } + + if ( kekKey != NULL) { + PK11_FreeSymKey( kekKey); + kekKey = NULL; + } + + if( keySetStringChars ) { + (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars); + keySetStringChars = NULL; + } + jbyteArray handleBA=NULL; - if (status != PR_FAILURE && (out.size()>0) ) - { + if (status != PR_FAILURE && (out.size()>0) ) { jbyte *handleBytes=NULL; handleBA = (env)->NewByteArray( out.size()); handleBytes = (env)->GetByteArrayElements(handleBA, NULL); @@ -238,9 +234,17 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr handleBytes=NULL; } - env->ReleaseByteArrayElements(j_in, cc, JNI_ABORT); - env->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); - env->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); + if( cc != NULL) { + env->ReleaseByteArrayElements(j_in, cc, JNI_ABORT); + } + + if( keyVersion != NULL) { + env->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); + } + + if( cuidValue != NULL) { + env->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); + } return handleBA; } diff --git a/pki/base/symkey/src/com/netscape/symkey/SessionKey.cpp b/pki/base/symkey/src/com/netscape/symkey/SessionKey.cpp index 735d904c6..eb412f01a 100644 --- a/pki/base/symkey/src/com/netscape/symkey/SessionKey.cpp +++ b/pki/base/symkey/src/com/netscape/symkey/SessionKey.cpp @@ -1,4 +1,4 @@ -// --- BEGIN COPYRIGHT BLOCK --- + // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. @@ -27,6 +27,7 @@ extern "C" #include #include #include +#include "secerr.h" /* #include @@ -66,6 +67,7 @@ extern "C" #define SYM_KEY_PROXY_FIELD "keyProxy" #define SYM_KEY_PROXY_SIG "Lorg/mozilla/jss/pkcs11/SymKeyProxy;" + /*********************************************************************** ** ** J S S _ p t r T o B y t e A r r a y @@ -298,8 +300,8 @@ JSS_getPtrFromProxy(JNIEnv *env, jobject nativeProxy, void **ptr) ** } */ PRStatus -JSS_getPtrFromProxyOwner(JNIEnv *env, jobject proxyOwner, const char *proxyFieldName, -const char *proxyFieldSig, void **ptr) +JSS_getPtrFromProxyOwner(JNIEnv *env, jobject proxyOwner, char* proxyFieldName, +char *proxyFieldSig, void **ptr) { jclass ownerClass; jfieldID proxyField; @@ -343,23 +345,36 @@ JSS_PK11_getSymKeyPtr(JNIEnv *env, jobject symKeyObject, PK11SymKey **ptr) SYM_KEY_PROXY_SIG, (void**)ptr); } #endif //STEAL_JSS - -PK11SymKey *DeriveKeyWithCardKey(PK11SymKey *cardkey, const Buffer& hostChallenge, const Buffer& cardChallenge) +// Function takes wither a symkey OR a keybuffer (for the default keyset case) +// To derive a new key. +PK11SymKey *DeriveKey(PK11SymKey *cardKey, const Buffer& hostChallenge, const Buffer& cardChallenge) { PK11SymKey *key = NULL, *master = NULL; PK11SlotInfo *slot = PK11_GetInternalKeySlot(); PK11Context *context = NULL; - unsigned char derivationData[16]; + unsigned char derivationData[KEYLENGTH]; #ifdef DES2_WORKAROUND - unsigned char keyData[24]; + unsigned char keyData[DES3_LENGTH]; #else - unsigned char keyData[16]; + unsigned char keyData[KEYLENGTH]; #endif - int i; - SECStatus s; - int len; - SECItem keyItem = { siBuffer, keyData, sizeof keyData }; - static SECItem noParams = { siBuffer, 0, 0 }; + int i = 0; + SECStatus s = SECSuccess; + int len = 0;; + static SECItem noParams = { siBuffer, NULL, 0 }; + + /* vars for PK11_Derive section */ + SECItem param = { siBuffer, NULL, 0 }; + CK_KEY_DERIVATION_STRING_DATA string; + PK11SymKey *tmp1 = NULL; + PK11SymKey *tmp2 = NULL; + PRBool invalid_mechanism = PR_FALSE; + CK_OBJECT_HANDLE keyhandle = 0; + + PR_fprintf(PR_STDOUT,"In DeriveKey! \n"); + master = cardKey; + + if( ! master ) goto done; for(i = 0;i < 4;i++) { @@ -368,102 +383,101 @@ PK11SymKey *DeriveKeyWithCardKey(PK11SymKey *cardkey, const Buffer& hostChalleng derivationData[i+8] = cardChallenge[i]; derivationData[i+12] = hostChallenge[i+4]; } - context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, cardkey, - &noParams); - if (!context) goto done; - /* Part 1 */ - s = PK11_CipherOp(context, &keyData[0], &len, 8, &derivationData[0], 8); - if (s != SECSuccess) goto done; + string.pData = &derivationData[0]; + string.ulLen = EIGHT_BYTES; + param.data = (unsigned char*)&string; + param.len = sizeof(string); - /* Part 2 */ - s = PK11_CipherOp(context, &keyData[8], &len, 8, &derivationData[8], 8); - if (s != SECSuccess) goto done; + invalid_mechanism = PR_FALSE; -#ifdef DES2_WORKAROUND - /* Part 3 */ - for(i = 0;i < 8;i++) - { - keyData[i+16] = keyData[i]; + tmp1 = PK11_Derive( master , CKM_DES_ECB_ENCRYPT_DATA , ¶m , CKM_CONCATENATE_BASE_AND_KEY , CKA_DERIVE, 0); + + if ( tmp1 == NULL) { + if ( PR_GetError() == SEC_ERROR_NO_TOKEN) + invalid_mechanism = PR_TRUE; + + PR_fprintf(PR_STDERR,"DeriveKey: Can't create key, using encrypt and derive method ! error %d \n", PR_GetError()); + } else { + PR_fprintf(PR_STDOUT,"DeriveKey: Successfully created key using encrypt and derive method! \n"); } -#endif - key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, PK11_OriginGenerated, - CKA_ENCRYPT, &keyItem, CKF_SIGN | CKF_ENCRYPT, PR_FALSE, 0); + if ( invalid_mechanism == PR_FALSE) { - done: - memset(keyData, 0, sizeof keyData); - if (context) PK11_DestroyContext(context, PR_TRUE); - if (slot) PK11_FreeSlot(slot); - if (master) PK11_FreeSymKey(master); + string.pData = &derivationData[EIGHT_BYTES]; + string.ulLen = EIGHT_BYTES; - return key; -} + tmp2 = PK11_Derive( master , CKM_DES_ECB_ENCRYPT_DATA , ¶m , CKM_CONCATENATE_BASE_AND_KEY , CKA_DERIVE , 0); + if ( tmp2 == NULL) { + PR_fprintf(PR_STDERR,"DeriveKey: Can't derive key using CONCATENATE method! \n"); + goto done; + } else { + PR_fprintf(PR_STDOUT,"DeriveKey: Successfully created key using CONCATENATE method! \n"); + } -PK11SymKey *DeriveKey(const Buffer& permKey, const Buffer& hostChallenge, const Buffer& cardChallenge) -{ - PK11SymKey *key = NULL, *master = NULL; - PK11SlotInfo *slot = PK11_GetInternalKeySlot(); - PK11Context *context = NULL; - unsigned char derivationData[16]; -#ifdef DES2_WORKAROUND - unsigned char keyData[24]; -#else - unsigned char keyData[16]; -#endif - int i; - SECStatus s; - int len; - SECItem keyItem = { siBuffer, keyData, sizeof keyData }; - static SECItem noParams = { siBuffer, 0, 0 }; - BYTE masterKeyData[24]; - SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) }; + keyhandle = PK11_GetSymKeyHandle(tmp2); - /* convert 16-byte to 24-byte triple-DES key */ - memcpy(masterKeyData, permKey, 16); - memcpy(masterKeyData+16, permKey, 8); + param.data=(unsigned char *) &keyhandle; + param.len=sizeof(keyhandle); - master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem, - CKF_ENCRYPT, PR_FALSE, 0); - if( ! master ) goto done; + key = PK11_Derive ( tmp1 , CKM_CONCATENATE_BASE_AND_KEY , ¶m ,CKM_DES3_ECB , CKA_DERIVE , 16); - for(i = 0;i < 4;i++) - { - derivationData[i] = cardChallenge[i+4]; - derivationData[i+4] = hostChallenge[i]; - derivationData[i+8] = cardChallenge[i]; - derivationData[i+12] = hostChallenge[i+4]; - } - context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master, - &noParams); - if (!context) goto done; + if ( key == NULL) { + PR_fprintf(PR_STDERR,"DeriveKey: Can't create final derived key! \n"); + goto done; + } else { + PR_fprintf(PR_STDOUT,"DeriveKey: Successfully created final derived key! \n"); + } - /* Part 1 */ - s = PK11_CipherOp(context, &keyData[0], &len, 8, &derivationData[0], 8); - if (s != SECSuccess) goto done; + } else { /* We don't have access to the proper derive mechanism, use primitive mechanisms now */ - /* Part 2 */ - s = PK11_CipherOp(context, &keyData[8], &len, 8, &derivationData[8], 8); - if (s != SECSuccess) goto done; + context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master, + &noParams); -#ifdef DES2_WORKAROUND - /* Part 3 */ - for(i = 0;i < 8;i++) - { - keyData[i+16] = keyData[i]; - } -#endif + if (!context) goto done; + + s = PK11_CipherOp(context, &keyData[0], &len, EIGHT_BYTES, &derivationData[0], EIGHT_BYTES); + if (s != SECSuccess) goto done; + + s = PK11_CipherOp(context, &keyData[EIGHT_BYTES], &len, 8, &derivationData[EIGHT_BYTES], EIGHT_BYTES); + if (s != SECSuccess) goto done; + + for(i = 0;i < EIGHT_BYTES ;i++) + { + keyData[i+KEYLENGTH] = keyData[i]; + } + + key = CreateUnWrappedSymKeyOnToken( slot, master, &keyData[0] , DES3_LENGTH, PR_FALSE ); - key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, PK11_OriginGenerated, - CKA_ENCRYPT, &keyItem, CKF_SIGN | CKF_ENCRYPT, PR_FALSE, 0); + if ( key == NULL ) { + PR_fprintf(PR_STDERR,"DeriveKey: CreateUnWrappedSymKey failed! %d \n", PR_GetError()); + } else { + PR_fprintf(PR_STDOUT,"DeriveKey: CreateUnWrappedSymKey succeeded! \n"); + } + } done: memset(keyData, 0, sizeof keyData); - if (context) PK11_DestroyContext(context, PR_TRUE); - if (slot) PK11_FreeSlot(slot); - if (master) PK11_FreeSymKey(master); + if ( context != NULL) { + PK11_DestroyContext(context, PR_TRUE); + context = NULL; + } + + if (slot) { + PK11_FreeSlot(slot); + slot = NULL; + } + + if (tmp1) { + PK11_FreeSymKey(tmp1); + tmp1 = NULL; + } + + if (tmp2) { + PK11_FreeSymKey(tmp2); + tmp2 = NULL; + } return key; } @@ -473,84 +487,75 @@ extern "C" { #endif JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeKeyCheck - (JNIEnv *, jclass, jbyteArray); + (JNIEnv *, jclass, jobject deskeyObj); #ifdef __cplusplus } #endif extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeKeyCheck -(JNIEnv* env, jclass this2, jbyteArray data) +(JNIEnv* env, jclass this2, jobject deskeyObj) { jbyteArray handleBA=NULL; - jint len; - jbyte *bytes=NULL; jbyte *handleBytes=NULL; PK11SymKey *key = NULL; - PK11SlotInfo *slot = PK11_GetInternalKeySlot(); +// PK11SlotInfo *slot = PK11_GetInternalKeySlot(); PK11Context *context = NULL; SECStatus s = SECFailure; - int lenx; - static SECItem noParams = { siBuffer, 0, 0 }; -#ifdef DES2_WORKAROUND - unsigned char keyData[24]; -#else - unsigned char keyData[16]; -#endif - SECItem keyItem = {siBuffer, keyData, sizeof(keyData) }; - unsigned char value[8]; + PRStatus r = PR_FAILURE; + int lenx = 0; + static SECItem noParams = { siBuffer, NULL, 0 }; - len = (env)->GetArrayLength(data); - bytes = (env)->GetByteArrayElements(data, NULL); - if( bytes == NULL ) - { - goto finish; - } + unsigned char value[EIGHT_BYTES]; -/* convert 16-byte to 24-byte triple-DES key */ - memcpy(keyData, bytes, 16); -#ifdef DES2_WORKAROUND - memcpy(keyData+16, bytes, 8); -#endif memset(value, 0, sizeof value); - key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &keyItem, - CKF_ENCRYPT, PR_FALSE, 0); - if( ! key ) - { + r = JSS_PK11_getSymKeyPtr(env, deskeyObj, &key); + + if (r != PR_SUCCESS) { + goto finish; + } + + if ( ! key ) { goto finish; } context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key, &noParams); - if (!context) - { + if (!context) { goto finish; } - s = PK11_CipherOp(context, &value[0], &lenx, 8, &value[0], 8); + + s = PK11_CipherOp(context, &value[0], &lenx, EIGHT_BYTES, &value[0], EIGHT_BYTES); if (s != SECSuccess) { goto finish; } handleBA = (env)->NewByteArray(3); - if(handleBA == NULL ) - { + if(handleBA == NULL ) { goto finish; } handleBytes = (env)->GetByteArrayElements(handleBA, NULL); - if(handleBytes==NULL) - { + if(handleBytes==NULL) { goto finish; } memcpy(handleBytes, value, 3); - (env)->ReleaseByteArrayElements(handleBA, handleBytes, 0); + if( handleBytes != NULL) { + (env)->ReleaseByteArrayElements(handleBA, handleBytes, 0); + } + +finish: + + if ( context != NULL) { + PK11_DestroyContext(context, PR_TRUE); + context = NULL; + } - finish: - if (context) PK11_DestroyContext(context, PR_TRUE); - if (slot) PK11_FreeSlot(slot); - if (key) PK11_FreeSymKey(key); +// if ( slot != NULL) { +// PK11_FreeSlot(slot); +// slot = NULL; +// } return handleBA; } @@ -567,28 +572,132 @@ extern "C" * Signature: ([B[B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeSessionKey - (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring); + (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring, jstring); #ifdef __cplusplus } #endif #define KEYLENGTH 16 -extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeSessionKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray macKeyArray, jstring useSoftToken_s) +extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeSessionKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray macKeyArray, jstring useSoftToken_s, jstring keySet, jstring sharedSecretKeyName) { -/* hardcore permanent mac key */ - jbyte *mac_key = (jbyte*)(env)->GetByteArrayElements(macKeyArray, NULL); - char input[16]; - int i; + /* hardcore permanent mac key */ + jbyte *mac_key = NULL; + if (macKeyArray != NULL) { + mac_key = (jbyte*)(env)->GetByteArrayElements(macKeyArray, NULL); + } else { + return NULL; + } + + char input[KEYLENGTH]; + int i = 0; + + SECItem wrappedKeyItem = { siBuffer, NULL , 0}; + SECItem noParams = { siBuffer, NULL, 0 }; + SECStatus wrapStatus = SECFailure; + + + char *keyNameChars=NULL; + char *tokenNameChars=NULL; + PK11SlotInfo *slot = NULL; + PK11SlotInfo *internal = PK11_GetInternalKeySlot(); + + PK11SymKey *symkey = NULL; + PK11SymKey *transportKey = NULL; + PK11SymKey *masterKey = NULL; + + PK11SymKey *macSymKey = NULL; + PK11SymKey *symkey16 = NULL; + PK11SymKey *macKey = NULL; + + + BYTE macData[KEYLENGTH]; + char keyname[KEYNAMELENGTH]; + + + /* Derive vars */ + + CK_ULONG bitPosition = 0; + SECItem paramsItem = { siBuffer, NULL, 0 }; + + /* Java object return vars */ + + jbyteArray handleBA=NULL; + jbyte *handleBytes=NULL; + + jbyte * cuidValue = NULL; + + jbyte *cc = NULL; + int cc_len = 0; + + int hc_len = 0; + jbyte *hc = NULL; + + jbyte * keyVersion = NULL; + int keyVersion_len = 0; + + Buffer macBuff( ( BYTE *) mac_key , KEYLENGTH ); + + char *keySetStringChars = NULL; + if( keySet != NULL ) { + keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL); + } + + char *keySetString = keySetStringChars; + + if ( keySetString == NULL ) { + keySetString = (char *) DEFKEYSET_NAME; + } + + char *sharedSecretKeyNameChars = NULL; + + if( sharedSecretKeyName != NULL ) { + sharedSecretKeyNameChars = (char *) (env)->GetStringUTFChars( sharedSecretKeyName, NULL); + } + + char *sharedSecretKeyNameString = sharedSecretKeyNameChars; + + if ( sharedSecretKeyNameString == NULL ) { + sharedSecretKeyNameString = (char *) TRANSPORT_KEY_NAME; + } + + GetSharedSecretKeyName(sharedSecretKeyNameString); + + if( card_challenge != NULL) { + cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); + cc_len = (env)->GetArrayLength(card_challenge); + } + + if( cc == NULL) { + goto done; + } + + if( host_challenge != NULL) { + hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); + hc_len = (env)->GetArrayLength( host_challenge); + } + + if( hc == NULL) { + goto done; + } + + if( keyInfo != NULL) { + keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); + + if( keyVersion) { + keyVersion_len = (env)->GetArrayLength(keyInfo); + } + } -//char icv[8]; - jbyte *cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); - int cc_len = (env)->GetArrayLength(card_challenge); + if( !keyVersion || (keyVersion_len < 2) ){ + goto done; + } - jbyte *hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); - // .size(); - int hc_len = (env)->GetArrayLength( host_challenge); + if ( CUID != NULL ) { + cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + } - jbyte * keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); - jbyte * cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + if( cuidValue == NULL) { + goto done; + } /* copy card and host challenge into input buffer */ for (i = 0; i < 8; i++) @@ -599,15 +708,9 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp { input[8+i] = hc[i]; } - PK11SymKey *symkey = NULL; - - BYTE macData[KEYLENGTH]; - char keyname[KEYNAMELENGTH]; GetDiversificationData(cuidValue,macData,mac);//keytype is mac - char *tokenNameChars; - PK11SlotInfo *slot = NULL; if(tokenName) { tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL); @@ -615,102 +718,158 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); } - char *keyNameChars=NULL; - if(keyName) { keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL); - strcpy(keyname,keyNameChars); + strncpy(keyname,keyNameChars,KEYNAMELENGTH); (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars); }else GetKeyName(keyVersion,keyname); + PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKey! \n"); - - if (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 && strcmp( keyname, "#01#01") == 0 || + if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 && strcmp( keyname, "#01#01") == 0) || (keyVersion[0] == -1 && strstr(keyname, "#FF"))) { - /* default manufacturers key */ - symkey = DeriveKey( //Util::DeriveKey( - Buffer((BYTE*)mac_key, KEYLENGTH), Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); - if( slot ) - PK11_FreeSlot( slot ); + macSymKey = ReturnDeveloperSymKey(slot, (char *) "mac" , keySetString, macBuff); + + if( macSymKey == NULL ) { + goto done; + } + + symkey = DeriveKey( //Util::DeriveKey( + macSymKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); }else { - PK11SymKey * masterKey = ReturnSymKey( slot,keyname); - - /* We need to use internal so that the key - * can be exported by using PK11_GetKeyData() - */ + masterKey = ReturnSymKey( slot,keyname); if(masterKey == NULL) { - - if(slot) - PK11_FreeSlot(slot); - return NULL; + goto done; } - PK11SymKey *macKey =ComputeCardKeyOnToken(masterKey,macData); - + macKey =ComputeCardKeyOnToken(masterKey,macData); if(macKey == NULL) { - - if(slot) - PK11_FreeSlot(slot); - - PK11_FreeSymKey(masterKey); - return NULL; + goto done; } - - symkey = DeriveKeyWithCardKey(macKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); + + symkey = DeriveKey(macKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); if(symkey == NULL) { + goto done; + } + } + //Now wrap the key for the trip back to TPS with shared secret transport key + + symkey16 = NULL; + transportKey = ReturnSymKey( internal, GetSharedSecretKeyName(NULL)); + if ( transportKey == NULL ) { + PR_fprintf(PR_STDERR, "Can't find shared secret transport key! \n"); + goto done; + } - if(slot) - PK11_FreeSlot(slot); + handleBA = (env)->NewByteArray( KEYLENGTH); + handleBytes = (env)->GetByteArrayElements(handleBA, NULL); - PK11_FreeSymKey( masterKey); - PK11_FreeSymKey( macKey); + paramsItem.data = (CK_BYTE *) &bitPosition; + paramsItem.len = sizeof bitPosition; - return NULL; - } + symkey16 = PK11_Derive(symkey, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT, + CKA_DERIVE, 16); + if ( !symkey16 ) { + PR_fprintf(PR_STDERR,"Can't derive 16 byte key from 24 byte symkey! \n"); + goto done; + } + + wrappedKeyItem.data = (unsigned char *) handleBytes; + wrappedKeyItem.len = KEYLENGTH; + wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, transportKey, symkey16, &wrappedKeyItem); + + if(wrapStatus == SECFailure ) + { + PR_fprintf(PR_STDERR, "Can't wrap session key! Error: %d \n", PR_GetError()); + } + +done: + + if( slot) { + PK11_FreeSlot(slot); + slot = NULL; + } + + if( internal ) { + PK11_FreeSlot(internal); + internal = NULL; + } + + if ( symkey ) { + PK11_FreeSymKey( symkey); + symkey = NULL; + } + + if ( transportKey ) { + PK11_FreeSymKey( transportKey ); + transportKey = NULL; + } - if( slot ) - PK11_FreeSlot( slot ); + if ( symkey16 ) { + PK11_FreeSymKey( symkey16 ); + symkey16 = NULL; + } + if( masterKey ) { PK11_FreeSymKey( masterKey); + masterKey = NULL; + } + + if( macKey ) { PK11_FreeSymKey( macKey); + macKey = NULL; + } + if( macSymKey ) { + PK11_FreeSymKey( macSymKey ); + macSymKey = NULL; } - /* status = EncryptData(kek_key, Buffer(cc,cc_len),out); */ - jbyte * session_key = (jbyte *) (PK11_GetKeyData(symkey)->data); + if( keySetStringChars ) { + (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars); + keySetStringChars = NULL; + } - if(session_key == NULL) - { - PK11_FreeSymKey(symkey); - return NULL; + if( sharedSecretKeyNameChars ) { + (env)->ReleaseStringUTFChars(sharedSecretKeyName, (const char *)sharedSecretKeyNameChars); + sharedSecretKeyNameChars = NULL; } - jbyteArray handleBA=NULL; - jbyte *handleBytes=NULL; - handleBA = (env)->NewByteArray( KEYLENGTH); - handleBytes = (env)->GetByteArrayElements(handleBA, NULL); - memcpy(handleBytes, session_key,KEYLENGTH); - PK11_FreeSymKey( symkey); + if ( handleBA != NULL) { + (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); + } + + if ( cc != NULL) { + (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT); + } + + if ( hc != NULL) { + (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT); + } - (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); + if( keyVersion != NULL) { + (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); + } - (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT); - (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT); + if ( cuidValue != NULL) { + (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); + } - (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); - (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); + if( mac_key != NULL) { + (env)->ReleaseByteArrayElements(macKeyArray, mac_key, JNI_ABORT); + } return handleBA; } @@ -726,177 +885,115 @@ extern "C" * Signature: ([B[B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeEncSessionKey - (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring); + (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring); #ifdef __cplusplus } #endif #define KEYLENGTH 16 -extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeEncSessionKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray encKeyArray, jstring useSoftToken_s) +extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeEncSessionKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray encKeyArray, jstring useSoftToken_s, jstring keySet) { /* hardcoded permanent enc key */ - jbyte *enc_key = (jbyte*)(env)->GetByteArrayElements(encKeyArray, NULL); - char input[16]; - int i; -//char icv[8]; + jbyte *enc_key = NULL; + if(encKeyArray != NULL ) { + enc_key = (jbyte*)(env)->GetByteArrayElements(encKeyArray, NULL); + } else { + return NULL; + } - jbyte *cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); - int cc_len = (env)->GetArrayLength(card_challenge); + char input[KEYLENGTH]; + int i = 0; - jbyte *hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); - // .size(); - int hc_len = (env)->GetArrayLength( host_challenge); + SECItem wrappedKeyItem = { siBuffer, NULL , 0}; + SECItem noParams = { siBuffer, NULL, 0 }; + SECStatus wrapStatus = SECFailure; - jbyte * keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); - jbyte * cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + char *keyNameChars = NULL; + char *tokenNameChars = NULL; + PK11SlotInfo *slot = NULL; + PK11SlotInfo *internal = PK11_GetInternalKeySlot(); - /* copy card and host challenge into input buffer */ - for (i = 0; i < 8; i++) - { - input[i] = cc[i]; - } - for (i = 0; i < 8; i++) - { - input[8+i] = hc[i]; - } PK11SymKey *symkey = NULL; + PK11SymKey * transportKey = NULL; + PK11SymKey *masterKey = NULL; + + PK11SymKey *encSymKey = NULL; + PK11SymKey *encKey = NULL; + PK11SymKey *symkey16 = NULL; BYTE encData[KEYLENGTH]; char keyname[KEYNAMELENGTH]; - GetDiversificationData(cuidValue,encData,enc); - char *tokenNameChars; - PK11SlotInfo *slot = NULL; - if(tokenName) - { - tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL); - slot = ReturnSlot(tokenNameChars); - (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); + + /* Derive vars */ + CK_ULONG bitPosition = 0; + SECItem paramsItem = { siBuffer, NULL, 0 }; + + /* Java object return vars */ + + jbyteArray handleBA=NULL; + jbyte *handleBytes=NULL; + + jbyte * cuidValue = NULL; + + jbyte *cc = NULL; + int cc_len = 0; + + int hc_len = 0; + jbyte *hc = NULL; + + jbyte * keyVersion = NULL; + int keyVersion_len = 0; + + Buffer encBuff( ( BYTE *) enc_key , KEYLENGTH ); + + char *keySetStringChars = NULL; + + if( keySet != NULL ) { + keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL); } - char *keyNameChars=NULL; - if(keyName) - { - keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL); - strcpy(keyname,keyNameChars); - (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars); + char *keySetString = keySetStringChars; + + if ( keySetString == NULL ) { + keySetString = (char *) DEFKEYSET_NAME; } - else - { - GetKeyName(keyVersion,keyname); + + if( card_challenge != NULL) { + cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); + cc_len = (env)->GetArrayLength(card_challenge); } - if (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 || - (keyVersion[0] == -1 && strstr(keyname, "#FF"))) - { - /* default manufacturers key */ - symkey = DeriveKey( //Util::DeriveKey( - Buffer((BYTE*)enc_key, KEYLENGTH), Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); - - if( slot ) - PK11_FreeSlot( slot ); - }else - { - PK11SymKey * masterKey = ReturnSymKey( slot,keyname); - - /* We need to use internal so that the key - * can be exported by using PK11_GetKeyData() - */ - if(masterKey == NULL) - { - if(slot) - PK11_FreeSlot(slot); - return NULL; + if( cc == NULL) { + goto done; + } - } + if( host_challenge != NULL) { + hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); + hc_len = (env)->GetArrayLength( host_challenge); + } - PK11SymKey *encKey =ComputeCardKeyOnToken(masterKey,encData); - if(encKey == NULL) - { - if(slot) - PK11_FreeSlot(slot); + if( hc == NULL) { + goto done; + } - PK11_FreeSymKey(masterKey); + if( keyInfo != NULL) { + keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); - return NULL; + if( keyVersion) { + keyVersion_len = (env)->GetArrayLength(keyInfo); } - - symkey = DeriveKeyWithCardKey(encKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); - - PK11_FreeSymKey( masterKey); - PK11_FreeSymKey( encKey); - - if(slot) - PK11_FreeSlot(slot); - } - /* status = EncryptData(kek_key, Buffer(cc,cc_len),out); */ - if(symkey == NULL) - { - return NULL; + if( !keyVersion || (keyVersion_len < 2) ){ + goto done; } - jbyte * session_key = (jbyte *) (PK11_GetKeyData(symkey)->data); - - jbyteArray handleBA=NULL; - jbyte *handleBytes=NULL; - handleBA = (env)->NewByteArray( KEYLENGTH); - handleBytes = (env)->GetByteArrayElements(handleBA, NULL); - memcpy(handleBytes, session_key,KEYLENGTH); - PK11_FreeSymKey( symkey); - - (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); - - (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT); - (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT); - - (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); - (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); - - return handleBA; -} - - -#ifdef __cplusplus -extern "C" -{ -#endif -/* - * Class: com_netscape_cms_servlet_tks_RASessionKey - * Method: ComputeKekSessionKey - * Signature: ([B[B[B[B)[B - */ - JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_ComputeKekSessionKey - (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring); -#ifdef __cplusplus -} -#endif -#define KEYLENGTH 16 -extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_ComputeKekSessionKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray kekKeyArray, jstring useSoftToken_s) -{ - /* hardcoded permanent kek key */ - jbyte *kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL); - char input[16]; - int i; -//char icv[8]; - - PRFileDesc *debug_fd = NULL; - -#ifdef DRM_SUPPORT_DEBUG - debug_fd = PR_Open("/tmp/debug1.cfu", - PR_RDWR | PR_CREATE_FILE | PR_APPEND, - 400 | 200); - PR_fprintf(debug_fd,"ComputeKekSessionKey\n"); -#endif // DRM_SUPPORT_DEBUG - - jbyte *cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); - int cc_len = (env)->GetArrayLength(card_challenge); - - jbyte *hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); - // .size(); - int hc_len = (env)->GetArrayLength( host_challenge); + if( CUID != NULL) { + cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + } - jbyte * keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); - jbyte * cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + if( cuidValue == NULL) { + goto done; + } /* copy card and host challenge into input buffer */ for (i = 0; i < 8; i++) @@ -907,91 +1004,162 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_Compute { input[8+i] = hc[i]; } - PK11SymKey *symkey = NULL; - BYTE kekData[KEYLENGTH]; - char keyname[KEYNAMELENGTH]; - GetDiversificationData(cuidValue,kekData,kek);//keytype is kek - char *tokenNameChars; - PK11SlotInfo *slot = NULL; - if (tokenName) + GetDiversificationData(cuidValue,encData,enc); + + if(tokenName) { tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL); slot = ReturnSlot(tokenNameChars); (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); } - char *keyNameChars=NULL; - if (keyName) + + if(keyName) { keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL); - strcpy(keyname,keyNameChars); + strncpy(keyname,keyNameChars,KEYNAMELENGTH); (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars); - } else { + } + else { GetKeyName(keyVersion,keyname); } - if (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 || + if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0) || (keyVersion[0] == -1 && strstr(keyname, "#FF"))) { /* default manufacturers key */ + + encSymKey = ReturnDeveloperSymKey(slot, (char *) "auth" , keySetString, encBuff); + + if( encSymKey == NULL ) { + goto done; + } + symkey = DeriveKey( //Util::DeriveKey( - Buffer((BYTE*)kek_key, KEYLENGTH), Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); - } else { - PK11SymKey * masterKey = ReturnSymKey( slot,keyname); + encSymKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); + + }else + { + masterKey = ReturnSymKey( slot,keyname); /* We need to use internal so that the key * can be exported by using PK11_GetKeyData() */ - if(masterKey == NULL) - { - if(slot) - PK11_FreeSlot(slot); - return NULL; + if(masterKey == NULL) { + goto done; } - PK11SymKey *kekKey =ComputeCardKeyOnToken(masterKey,kekData); - if (kekKey == NULL) - { - if(slot) - PK11_FreeSlot(slot); - - PK11_FreeSymKey(masterKey); - return NULL; + encKey =ComputeCardKeyOnToken(masterKey,encData); + if(encKey == NULL) { + goto done; } + symkey = DeriveKey(encKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); + } - symkey = DeriveKeyWithCardKey(kekKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); + if(symkey == NULL) { + goto done; + } + //Now wrap the key for the trip back to TPS with shared secret transport key + transportKey = ReturnSymKey( internal, GetSharedSecretKeyName(NULL)); + if ( transportKey == NULL ) { + goto done; + } + + handleBA = (env)->NewByteArray( KEYLENGTH); + handleBytes = (env)->GetByteArrayElements(handleBA, NULL); + + paramsItem.data = (CK_BYTE *) &bitPosition; + paramsItem.len = sizeof bitPosition; + + symkey16 = PK11_Derive(symkey, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT, + CKA_DERIVE, KEYLENGTH); + + if ( !symkey16 ) { + PR_fprintf(PR_STDERR,"SessionKey: ComputeEncSessionKey - Can't derive 16 byte key from 24 byte symkey! \n"); + goto done; + } + + wrappedKeyItem.data = (unsigned char *) handleBytes; + wrappedKeyItem.len = KEYLENGTH; + wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, transportKey, symkey16, &wrappedKeyItem); + + if ( wrapStatus == SECFailure ) { + PR_fprintf(PR_STDERR,"SessionKey: ComputeEncSessionKey - Can't wrap encSessionKey ! Error: %d \n", PR_GetError()); + } + +done: + + if ( slot ) { + PK11_FreeSlot ( slot ); + slot = NULL; + } + + if ( internal) { + PK11_FreeSlot( internal); + internal = NULL; + } + + if( symkey) { + PK11_FreeSymKey( symkey); + symkey = NULL; + } + + if( transportKey) { + PK11_FreeSymKey( transportKey ); + transportKey = NULL; + } + + if( masterKey) { PK11_FreeSymKey( masterKey); - PK11_FreeSymKey( kekKey); + masterKey = NULL; + } - if(slot) - PK11_FreeSlot(slot); + if( symkey16) { + PK11_FreeSymKey( symkey16); + symkey16 = NULL; + } + if ( encSymKey ) { + PK11_FreeSymKey( encSymKey); + encSymKey = NULL; + } + + if( encKey) { + PK11_FreeSymKey( encKey); + encKey = NULL; } - /* status = EncryptData(kek_key, Buffer(cc,cc_len),out); */ - if(symkey == NULL) - { - return NULL; + if( keySetStringChars ) { + (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars); + keySetStringChars = NULL; } - if (debug_fd) - PR_fprintf(debug_fd,"ComputeKekSessionKey: got kek session key\n"); + if ( handleBytes != NULL ) { + (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); + } - jobject keyObj = JSS_PK11_wrapSymKey(env, &symkey, debug_fd); - if (keyObj == NULL) - { - if (debug_fd) - PR_fprintf(debug_fd,"ComputeKekSessionKey called wrapSymKey, key NULL\n"); + if( cc != NULL ) { + (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT); } - else - { - if (debug_fd) - PR_fprintf(debug_fd,"ComputeKekSessionKey called wrapSymKey, key not NULL\n"); + + if( hc != NULL ) { + (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT); + } + if(keyVersion != NULL ) { + (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); + } + + if(cuidValue != NULL) { + (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); } - return keyObj; -} + if( enc_key != NULL) { + (env)->ReleaseByteArrayElements(encKeyArray, enc_key, JNI_ABORT); + } + + return handleBA; +} #ifdef __cplusplus extern "C" @@ -1003,33 +1171,89 @@ extern "C" * Signature: ([B[B[B[B)[B */ JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_ComputeKekKey - (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring); + (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jstring, jstring); #ifdef __cplusplus } #endif #define KEYLENGTH 16 -extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_ComputeKekKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray kekKeyArray, jstring useSoftToken_s) + +extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_ComputeKekKey(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, jbyteArray kekKeyArray, jstring useSoftToken_s, jstring keySet) { /* hardcoded permanent kek key */ - jbyte *kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL); - char input[16]; + jbyte *kek_key = NULL; + if( kekKeyArray != NULL) { + kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL); + } else { + return NULL; + } + + Buffer kekBuff( ( BYTE *) kek_key , KEYLENGTH ); + + char *keySetStringChars = NULL; + if( keySet != NULL ) { + keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL); + } + + char *keySetString = keySetStringChars; + + if ( keySetString == NULL ) { + keySetString = (char *) DEFKEYSET_NAME; + } + + char input[KEYLENGTH]; int i; -//char icv[8]; jobject keyObj = NULL; - PRFileDesc *debug_fd = NULL; + jbyte *cc = NULL; + jbyte *hc = NULL; + jbyte * keyVersion = NULL; + int keyVersion_len = 0; + jbyte * cuidValue = NULL; -#ifdef DRM_SUPPORT_DEBUG - debug_fd = PR_Open("/tmp/debug1.cfu", - PR_RDWR | PR_CREATE_FILE | PR_APPEND, - 400 | 200); - PR_fprintf(debug_fd,"ComputeKekKey\n"); -#endif // DRM_SUPPORT_DEBUG + char *keyNameChars=NULL; + char *tokenNameChars = NULL; + PK11SlotInfo *slot = NULL; + + PK11SymKey *kekKey = NULL; + PK11SymKey *masterKey = NULL; + + BYTE kekData[KEYLENGTH]; + char keyname[KEYNAMELENGTH]; + + if( card_challenge != NULL) { + cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); + } + + if( cc == NULL) { + goto done; + } + + if( host_challenge != NULL) { + hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); + } + + if( hc == NULL) { + goto done; + } + + if( keyInfo != NULL) { + keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); + if( keyVersion) { + keyVersion_len = (env)->GetArrayLength(keyInfo); + } + } - jbyte *cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); - jbyte *hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); - jbyte * keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); - jbyte * cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + if( !keyVersion || (keyVersion_len < 2) ){ + goto done; + } + + if( CUID != NULL) { + cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + } + + if( cuidValue == NULL) { + goto done; + } /* copy card and host challenge into input buffer */ for (i = 0; i < 8; i++) @@ -1041,21 +1265,15 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_Compute input[8+i] = hc[i]; } - PK11SlotInfo *internalSlot = NULL; - PK11SymKey *masterKey = NULL; - PK11SymKey *kekKey = NULL; - BYTE kekData[KEYLENGTH]; - char keyname[KEYNAMELENGTH]; GetDiversificationData(cuidValue,kekData,kek);//keytype is kek - char *tokenNameChars; - PK11SlotInfo *slot = NULL; + if (tokenName) { tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL); slot = ReturnSlot(tokenNameChars); (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); } - char *keyNameChars=NULL; + if (keyName) { keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL); @@ -1064,84 +1282,74 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_Compute }else GetKeyName(keyVersion,keyname); - if (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 || + PR_fprintf(PR_STDOUT,"In SessionKey.ComputeKekKey! \n"); + + if (( keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 ) || (keyVersion[0] == -1 && strcmp(keyname, "#FF"))) { /* default manufacturers key */ - if (debug_fd) - PR_fprintf(debug_fd,"ComputeKekKey shouldn't get here\n"); - - BYTE masterKeyData[24]; - SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData)}; - memcpy(masterKeyData, (char*)kek_key, 16); - memcpy(masterKeyData+16, (char*)kek_key, 8); - if (debug_fd) - PR_fprintf(debug_fd, "ComputeKekKey DRMproto before import\n"); - kekKey = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginUnwrap, CKA_ENCRYPT, &masterKeyItem, - ALL_SYMKEY_OPS /*CKF_ENCRYPT*/, PR_FALSE, 0); - - if( slot ) - PK11_FreeSlot( slot ); + kekKey = ReturnDeveloperSymKey(slot, (char *) "kek" , keySetString, kekBuff); } else { masterKey = ReturnSymKey( slot,keyname); - /* We need to use internal so that the key - * can be exported by using PK11_GetKeyData() - */ + if(masterKey == NULL) { - if(slot) - PK11_FreeSlot(slot); - return NULL; + goto done; } kekKey =ComputeCardKeyOnToken(masterKey,kekData); } - if(kekKey == NULL) - { - if(slot) - PK11_FreeSlot(slot); + if(kekKey == NULL) { + goto done; + } - if(masterKey) - PK11_FreeSymKey(masterKey); + keyObj = JSS_PK11_wrapSymKey(env, &kekKey, NULL); - return NULL; - } - if (debug_fd) - PR_fprintf(debug_fd,"ComputeKekKey: got kek key\n"); +done: - keyObj = JSS_PK11_wrapSymKey(env, &kekKey, debug_fd); - if (keyObj == NULL) - { - if (debug_fd) - PR_fprintf(debug_fd,"ComputeKekKey: keyObj is NULL\n"); - } - else - { - if (debug_fd) - PR_fprintf(debug_fd,"ComputeKekKey: keyObj is not NULL\n"); + if( keySetStringChars ) { + (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars); + keySetStringChars = NULL; } - if(masterKey) + if(masterKey) { PK11_FreeSymKey( masterKey); + masterKey = NULL; + } - if(kekKey) + if(kekKey) { PK11_FreeSymKey( kekKey); + kekKey = NULL; + } - if(slot) + if(slot) { PK11_FreeSlot(slot); + slot = NULL; + } - if(internalSlot) - PK11_FreeSlot(internalSlot); + if (cc != NULL) { + (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT); + } + + if (hc != NULL) { + (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT); + } + + if( keyVersion != NULL ) { + (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); + } + + if (cuidValue != NULL ) { + (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); + } return keyObj; } - PRStatus ComputeMAC(PK11SymKey *key, Buffer &x_input, const Buffer &icv, Buffer &output) { @@ -1156,7 +1364,7 @@ const Buffer &icv, Buffer &output) CK_ULONG macLen = sizeof result; SECItem params = { siBuffer, (unsigned char *)&macLen, sizeof macLen }; #endif - static SECItem noParams = { siBuffer, 0, 0 }; + static SECItem noParams = { siBuffer, NULL, 0 }; static unsigned char macPad[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -1289,66 +1497,136 @@ extern "C" * Signature: ([B[B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeCryptogram - (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, int, jbyteArray, jstring); + (JNIEnv *, jclass, jstring, jstring, jbyteArray, jbyteArray, jbyteArray, jbyteArray, int, jbyteArray, jstring, jstring); #ifdef __cplusplus } #endif #define KEYLENGTH 16 -extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeCryptogram(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, int type, jbyteArray authKeyArray, jstring useSoftToken_s) +extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeCryptogram(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray card_challenge, jbyteArray host_challenge, jbyteArray keyInfo, jbyteArray CUID, int type, jbyteArray authKeyArray, jstring useSoftToken_s, jstring keySet) { /* hardcore permanent mac key */ - jbyte *auth_key = (jbyte*)(env)->GetByteArrayElements(authKeyArray, NULL); - char input[16]; + jbyte *auth_key = NULL; + if( authKeyArray != NULL) { + auth_key = (jbyte*)(env)->GetByteArrayElements(authKeyArray, NULL); + } else { + return NULL; + } + + Buffer authBuff( ( BYTE *) auth_key , KEYLENGTH ); + Buffer icv = Buffer(EIGHT_BYTES, (BYTE)0); + Buffer output = Buffer(EIGHT_BYTES, (BYTE)0); + + char *keySetStringChars = NULL; + if( keySet != NULL ) { + keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL); + } + + char *keySetString = keySetStringChars; + + if ( keySetString == NULL ) { + keySetString = (char *) DEFKEYSET_NAME; + } + + char input[KEYLENGTH]; int i; -//char icv[8]; - jbyte *cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); - int cc_len = (env)->GetArrayLength(card_challenge); - jbyte *hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); - // .size(); - int hc_len = (env)->GetArrayLength( host_challenge); + PR_fprintf(PR_STDOUT,"In SessionKey: ComputeCryptogram! \n"); + jbyteArray handleBA=NULL; + jbyte *handleBytes=NULL; + + jbyte *cc = NULL; + jbyte *hc = NULL; + int cc_len = 0; + int hc_len = 0; + jbyte * keyVersion = NULL; + int keyVersion_len = 0; + jbyte * cuidValue = NULL; - jbyte * keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); - jbyte * cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + char *tokenNameChars = NULL; + char *keyNameChars=NULL; + PK11SlotInfo *slot = NULL; + + jbyte * session_key = NULL; + PK11SymKey *symkey = NULL; + PK11SymKey *masterKey = NULL; + PK11SymKey *authKey = NULL; + PK11SymKey *authSymKey = NULL; + + BYTE authData[KEYLENGTH]; + char keyname[KEYNAMELENGTH]; + Buffer input_x = Buffer(KEYLENGTH); + + if( card_challenge != NULL ) { + cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); + cc_len = (env)->GetArrayLength(card_challenge); + } + + if( cc == NULL) { + goto done; + } + + if( host_challenge != NULL ) { + hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); + hc_len = (env)->GetArrayLength( host_challenge); + } + + if( hc == NULL) { + goto done; + } + + if( keyInfo != NULL) { + keyVersion = (jbyte*)(env)->GetByteArrayElements( keyInfo, NULL); + if( keyVersion) { + keyVersion_len = (env)->GetArrayLength(keyInfo); + } + } + + if( !keyVersion || (keyVersion_len < 2) ){ + goto done; + } + + if( CUID != NULL) { + cuidValue = (jbyte*)(env)->GetByteArrayElements( CUID, NULL); + } + + if( cuidValue == NULL) { + goto done; + } if (type == 0) // compute host cryptogram { /* copy card and host challenge into input buffer */ - for (i = 0; i < 8; i++) + for (i = 0; i < EIGHT_BYTES; i++) { input[i] = cc[i]; } - for (i = 0; i < 8; i++) + for (i = 0; i < EIGHT_BYTES; i++) { - input[8+i] = hc[i]; + input[EIGHT_BYTES +i] = hc[i]; } } // compute card cryptogram else if (type == 1) { - for (i = 0; i < 8; i++) + for (i = 0; i < EIGHT_BYTES; i++) { input[i] = hc[i]; } - for (i = 0; i < 8; i++) + for (i = 0; i < EIGHT_BYTES; i++) { - input[8+i] = cc[i]; + input[EIGHT_BYTES+i] = cc[i]; } } - PK11SymKey *symkey = NULL; + input_x.replace(0, (BYTE*) input, KEYLENGTH); - BYTE authData[KEYLENGTH]; - char keyname[KEYNAMELENGTH]; GetDiversificationData(cuidValue,authData,enc); - char *tokenNameChars; - PK11SlotInfo *slot = NULL; + if (tokenName) { tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL); slot = ReturnSlot(tokenNameChars); (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); } - char *keyNameChars=NULL; if (keyName) { @@ -1358,141 +1636,106 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp }else GetKeyName(keyVersion,keyname); - if (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 || + if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 &&strcmp( keyname, "#01#01") == 0 ) || (keyVersion[0] == -1 && strstr(keyname, "#FF"))) { + /* default manufacturers key */ - symkey = DeriveKey( //Util::DeriveKey( - Buffer((BYTE*)auth_key, KEYLENGTH), Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); - if( slot ) - PK11_FreeSlot( slot ); + authSymKey = ReturnDeveloperSymKey(slot, (char *) "auth" , keySetString, authBuff); + if( authSymKey == NULL ) { + goto done; + } + + symkey = DeriveKey( + authSymKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); } else { - PK11SymKey * masterKey = ReturnSymKey( slot,keyname); + masterKey = ReturnSymKey( slot,keyname); if (masterKey == NULL) { - if(slot) - PK11_FreeSlot(slot); - - return NULL; + goto done; } - PK11SymKey *authKey = ComputeCardKeyOnToken(masterKey,authData); + authKey = ComputeCardKeyOnToken(masterKey,authData); if (authKey == NULL) { - if(slot) - PK11_FreeSlot(slot); - - PK11_FreeSymKey( masterKey); - return NULL; + goto done; } - if(slot) - PK11_FreeSlot(slot); - - symkey = DeriveKeyWithCardKey(authKey, + symkey = DeriveKey(authKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); - PK11_FreeSymKey( masterKey); - PK11_FreeSymKey( authKey); - } - - if(symkey == NULL) - { - return NULL; } - Buffer icv = Buffer(8, (BYTE)0); - Buffer output = Buffer(8, (BYTE)0); - Buffer input_x = Buffer((BYTE*)input, 16); ComputeMAC(symkey, input_x, icv, output); - jbyte * session_key = (jbyte *) (BYTE*)output; + session_key = (jbyte *) (BYTE*)output; - jbyteArray handleBA=NULL; - jbyte *handleBytes=NULL; - handleBA = (env)->NewByteArray( 8); + handleBA = (env)->NewByteArray( EIGHT_BYTES); handleBytes = (env)->GetByteArrayElements(handleBA, NULL); - memcpy(handleBytes, session_key,8); - PK11_FreeSymKey( symkey); - (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); - (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT); - (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT); - (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); - (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); - - return handleBA; -} + if( handleBytes ) { + memcpy(handleBytes, session_key, EIGHT_BYTES); + } +done: -//================================================================================= -#ifdef __cplusplus -extern "C" -{ -#endif -/* - * Class: com_netscape_cms_servlet_tks_RASessionKey - * Method: ComputeCardCryptogram - * Signature: ([B[B[B[B)[B - */ - JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeCardCryptogram - (JNIEnv *, jclass, jbyteArray, jbyteArray, jbyteArray); -#ifdef __cplusplus -} -#endif -#define KEYLENGTH 16 -extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeCardCryptogram(JNIEnv * env, jclass this2, jbyteArray auth_key, jbyteArray card_challenge, jbyteArray host_challenge) -{ - char input[16]; - int i; + if( slot ) { + PK11_FreeSlot( slot ); + slot = NULL; + } - jbyte *ak = (jbyte*)(env)->GetByteArrayElements( auth_key, NULL); - int ak_len = (env)->GetArrayLength(auth_key); + if( symkey ) { + PK11_FreeSymKey( symkey ); + symkey = NULL; + } - jbyte *cc = (jbyte*)(env)->GetByteArrayElements( card_challenge, NULL); - int cc_len = (env)->GetArrayLength(card_challenge); + if( authSymKey ) { + PK11_FreeSymKey( authSymKey ); + authSymKey = NULL; + } + + if( authKey) { + PK11_FreeSymKey( authKey); + authKey = NULL; + } - jbyte *hc = (jbyte*)(env)->GetByteArrayElements( host_challenge, NULL); - // .size(); - int hc_len = (env)->GetArrayLength( host_challenge); + if( masterKey) { + PK11_FreeSymKey( masterKey); + masterKey = NULL; + } - for (i = 0; i < 8; i++) - { - input[i] = hc[i]; + if( keySetStringChars ) { + (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars); + keySetStringChars = NULL; } - for (i = 0; i < 8; i++) - { - input[8+i] = cc[i]; + + if( handleBytes != NULL) { + (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); } - PK11SymKey *symkey = NULL; + if( cc != NULL) { + (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT); + } - /* default manufacturers key */ - symkey = DeriveKey( //Util::DeriveKey( - Buffer((BYTE*)ak, ak_len), Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); + if( hc != NULL) { + (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT); + } - Buffer icv = Buffer(8, (BYTE)0); - Buffer output = Buffer(8, (BYTE)0); - Buffer input_x = Buffer((BYTE*)input, 16); - ComputeMAC(symkey, input_x, icv, output); - jbyte * session_key = (jbyte *) (BYTE*)output; + if( keyVersion != NULL) { + (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); + } - jbyteArray handleBA=NULL; - jbyte *handleBytes=NULL; - handleBA = (env)->NewByteArray( 8); - handleBytes = (env)->GetByteArrayElements(handleBA, NULL); - memcpy(handleBytes, session_key,8); - PK11_FreeSymKey( symkey); - (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); - (env)->ReleaseByteArrayElements(auth_key, ak, JNI_ABORT); - (env)->ReleaseByteArrayElements(card_challenge, cc, JNI_ABORT); - (env)->ReleaseByteArrayElements(host_challenge, hc, JNI_ABORT); + if( cuidValue != NULL) { + (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); + } return handleBA; } +//================================================================================= + #ifdef __cplusplus extern "C" { @@ -1504,62 +1747,61 @@ extern "C" */ JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ECBencrypt - (JNIEnv*, jclass, jobject, jbyteArray); + (JNIEnv*, jclass, jobject, jobject); #ifdef __cplusplus } #endif extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ECBencrypt -(JNIEnv* env, jclass this2, jobject symkeyObj, jbyteArray data) +(JNIEnv* env, jclass this2, jobject symkeyObj, jobject deskeyObj ) { jbyteArray handleBA=NULL; - jint datalen, i; - jint dlen=16; // applet only supports 16 bytes - jbyte *databytes=NULL; + jint dlen=KEYLENGTH; // applet only supports 16 bytes jbyte *handleBytes=NULL; PK11SymKey *symkey = NULL; - PK11Context *context = NULL; + PK11SymKey *deskey = NULL; + PK11SymKey *newdeskey = NULL; PRStatus r = PR_FAILURE; - SECStatus s = SECFailure; - int lenx; - static SECItem noParams = { siBuffer, 0, 0 }; + static SECItem noParams = { siBuffer, NULL, 0 }; + SECItem wrappedKeyItem = { siBuffer, NULL, 0 }; + SECStatus wrapStatus = SECFailure; - unsigned char result[8]; -/* - PRFileDesc *debug_fd = PR_Open("/tmp/debug.cfu", - PR_RDWR | PR_CREATE_FILE | PR_APPEND, - 400 | 200); + /* PK11_Derive vars. */ - PR_fprintf(debug_fd,"ECBencrypt\n"); -*/ - r = JSS_PK11_getSymKeyPtr(env, symkeyObj, &symkey); - if (r != PR_SUCCESS) - { - goto finish; + SECItem paramsItem = { siBuffer, NULL, 0 }; + CK_ULONG bitPosition = 0; + + PR_fprintf(PR_STDOUT,"In SessionKey: ECBencrypt! \n"); + + if( !symkeyObj || !deskeyObj) { + goto finish; } - datalen = (jint)(env)->GetArrayLength(data); - databytes = (jbyte*)(env)->GetByteArrayElements(data, NULL); - if( databytes == NULL ) - { + r = JSS_PK11_getSymKeyPtr(env, symkeyObj, &symkey); + if (r != PR_SUCCESS) { goto finish; } - if( ! symkey ) - { + r = JSS_PK11_getSymKeyPtr(env, deskeyObj, &deskey); + if (r != PR_SUCCESS) { goto finish; } + // Instead of playing with raw keys, let's derive the 16 byte des2 key from + // the 24 byte des2 key. - context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, symkey, - &noParams); - if (!context) - { + bitPosition = 0; + paramsItem.data = (CK_BYTE *) &bitPosition; + paramsItem.len = sizeof bitPosition; + + newdeskey = PK11_Derive(deskey, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT, + CKA_DERIVE, 16); + + if ( ! newdeskey ) { goto finish; } - if (datalen > 16) - dlen = 16; // applet suports only 16 bytes + dlen = KEYLENGTH; // applet suports only 16 bytes handleBA = (env)->NewByteArray(dlen); if(handleBA == NULL ) @@ -1573,20 +1815,28 @@ Java_com_netscape_symkey_SessionKey_ECBencrypt goto finish; } - for (i=0; i< dlen; i+=8) - { - s = PK11_CipherOp(context, result, &lenx, 8, (unsigned char *)&databytes[i], 8); - if (s != SECSuccess) - { - goto finish; - } - memcpy(handleBytes+i, result, 8); + //Wrap the new 16 bit key with the input symkey. + + wrappedKeyItem.data = (unsigned char *) handleBytes; + wrappedKeyItem.len = dlen; + wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, symkey, newdeskey, &wrappedKeyItem); + + if( wrapStatus == SECSuccess) { + PR_fprintf(PR_STDERR, "ECBencrypt wrapStatus %d wrappedKeySize %d \n", wrapStatus, wrappedKeyItem.len); + } else { + PR_fprintf(PR_STDERR, "ECBecrypt wrap failed! Error %d \n", PR_GetError()); } - (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); +finish: + + if( handleBytes != NULL) { + (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); + } - finish: - if (context) PK11_DestroyContext(context, PR_TRUE); + if ( newdeskey ) { + PK11_FreeSymKey( newdeskey ); + newdeskey = NULL; + } return handleBA; } @@ -1611,77 +1861,96 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_GenerateSymkey (JNIEnv* env, jclass this2, jstring tokenName) { - jint keylen=24; jobject keyObj = NULL; - PK11SymKey *okey = NULL; - PK11SymKey *key = NULL; - char *tokenNameChars; + PK11SymKey *okeyFirstEight = NULL; + PK11SymKey *concatKey = NULL; + PK11SymKey *finalKey = NULL; + char *tokenNameChars = NULL; PK11SlotInfo *slot = NULL; - SECStatus s = SECFailure; + CK_ULONG bitPosition = 0; + SECItem paramsItem = { siBuffer, NULL, 0 }; + CK_OBJECT_HANDLE keyhandle = 0; - SECItem* okeyItem = NULL; - unsigned char keyData[24]; - SECItem keyItem = {siBuffer, keyData, sizeof(keyData) }; -/* -PRFileDesc *debug_fd = PR_Open("/tmp/debug.cfu", - PR_RDWR | PR_CREATE_FILE | PR_APPEND, - 400 | 200); - -PR_fprintf(debug_fd,"GenerateSymkey\n"); -*/ + PR_fprintf(PR_STDOUT,"In SessionKey GenerateSymkey!\n"); if (tokenName) { tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL); - slot = ReturnSlot(tokenNameChars); + if ( tokenNameChars && !strcmp(tokenNameChars, "internal")) { + slot = PK11_GetInternalSlot(); + } else { + slot = ReturnSlot(tokenNameChars); + } + + PR_fprintf(PR_STDOUT,"SessinKey: GenerateSymkey slot %p name %s tokenName %s \n",slot, PK11_GetSlotName(slot), PK11_GetTokenName(slot)); (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); } + //Generate original 16 byte DES2 key okey = PK11_TokenKeyGen(slot, CKM_DES2_KEY_GEN,0, 0, 0, PR_FALSE, NULL); - if (okey == NULL) + + if (okey == NULL) { goto finish; + } - s= PK11_ExtractKeyValue(okey); + // Extract first eight bytes from generated key into another key. + bitPosition = 0; + paramsItem.data = (CK_BYTE *) &bitPosition; + paramsItem.len = sizeof bitPosition; - if (s != SECSuccess) - goto finish; + okeyFirstEight = PK11_Derive(okey, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT , CKA_DERIVE, 8); + if (okeyFirstEight == NULL ) { + goto finish; + } - okeyItem = PK11_GetKeyData( okey); + //Concatenate 8 byte key to the end of the original key, giving new 24 byte key + keyhandle = PK11_GetSymKeyHandle(okeyFirstEight); + paramsItem.data=(unsigned char *) &keyhandle; + paramsItem.len=sizeof(keyhandle); - if (okeyItem == NULL) - goto finish; + concatKey = PK11_Derive ( okey , CKM_CONCATENATE_BASE_AND_KEY , ¶msItem ,CKM_DES3_ECB , CKA_DERIVE , 0); + if ( concatKey == NULL ) { + goto finish; + } - memcpy(keyData, okeyItem->data, 16); + //Make sure we move this to the orig token, in case it got moved by NSS + //during the derive phase. -// make the 3rd 8 bytes the same as the 1st - if (keylen == 24) - { - memcpy(keyData+16, okeyItem->data, 8); + finalKey = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, concatKey); + + /* wrap the symkey in java object. This sets symkey to NULL. */ + keyObj = JSS_PK11_wrapSymKey(env, &finalKey, NULL); + +finish: + if ( slot != NULL) { + PK11_FreeSlot(slot); + slot = NULL; + } - keyItem.len = keylen; + if ( okey != NULL) { + PK11_FreeSymKey(okey); + okey = NULL; } - key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &keyItem, - CKF_ENCRYPT, PR_FALSE, 0); - if( ! key ) - { - goto finish; + if ( okeyFirstEight != NULL) { + PK11_FreeSymKey(okeyFirstEight); + okeyFirstEight = NULL; } - /* wrap the symkey in java object. This sets symkey to NULL. */ - keyObj = JSS_PK11_wrapSymKey(env, &key, NULL); + if ( concatKey != NULL) { + PK11_FreeSymKey(concatKey); + concatKey = NULL; + } -finish: - if (slot) PK11_FreeSlot(slot); - if (okey) PK11_FreeSymKey(okey); - if (key) PK11_FreeSymKey(key); + if ( finalKey != NULL) { + PK11_FreeSymKey(finalKey); + finalKey = NULL; + } return keyObj; } - // begin DRM proto #ifdef __cplusplus @@ -1716,7 +1985,10 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_bytes2P memcpy(masterKeyData, (char*)symKeyBytes, 16); memcpy(masterKeyData+16, (char*)symKeyBytes, 8); - PR_fprintf(debug_fd, "DRMproto before import\n"); + + // ToDo: possibly get rid of whole function, not used + // For now , no need to get rid of PK11_ImportSymKeyWithFlags call. + symKey = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, PK11_OriginUnwrap, CKA_ENCRYPT, &masterKeyItem, ALL_SYMKEY_OPS /*CKF_ENCRYPT*/, PR_FALSE, 0); diff --git a/pki/base/symkey/src/com/netscape/symkey/SessionKey.java b/pki/base/symkey/src/com/netscape/symkey/SessionKey.java index 11460105d..a535a9fba 100644 --- a/pki/base/symkey/src/com/netscape/symkey/SessionKey.java +++ b/pki/base/symkey/src/com/netscape/symkey/SessionKey.java @@ -77,12 +77,9 @@ public class SessionKey } } - // external calls from RA - public static native byte[] ComputeKeyCheck( byte data[] ); - public static native byte[] ComputeCardCryptogram( byte[] raw_auth_key, - byte[] card_challenge, - byte[] host_challenge ); + // external calls from RA + public static native byte[] ComputeKeyCheck(PK11SymKey desKey ); /* byte data[] ); */ public static native byte[] ComputeSessionKey( String tokenName, String keyName, @@ -91,7 +88,9 @@ public class SessionKey byte[] keyInfo, byte[] CUID, byte[] macKeyArray, - String useSoftToken ); + String useSoftToken, + String keySet, + String sharedSecretKeyName ); public static native byte[] ComputeEncSessionKey( String tokenName, String keyName, @@ -100,7 +99,8 @@ public class SessionKey byte[] keyInfo, byte[] CUID, byte[] encKeyArray, - String useSoftToken ); + String useSoftToken, + String keySet ); public static native PK11SymKey ComputeKekSessionKey( String tokenName, String keyName, @@ -109,7 +109,8 @@ public class SessionKey byte[] keyInfo, byte[] CUID, byte[] kekKeyArray, - String useSoftToken ); + String useSoftToken, + String keySet ); public static native PK11SymKey ComputeKekKey( String tokenName, String keyName, @@ -118,10 +119,10 @@ public class SessionKey byte[] keyInfo, byte[] CUID, byte[] kekKeyArray, - String useSoftToken ); + String useSoftToken, String keySet ); public static native byte[] ECBencrypt( PK11SymKey key, - byte[] data ); + PK11SymKey desKey ); //byte[] data ); public static native PK11SymKey GenerateSymkey( String tokenName ); @@ -139,7 +140,7 @@ public class SessionKey byte[] CUID, int type, byte[] authKeyArray, - String useSoftToken ); + String useSoftToken, String keySet ); public static native byte[] EncryptData( String tokenName, String keyName, @@ -147,7 +148,7 @@ public class SessionKey byte[] keyInfo, byte[] CUID, byte[] kekKeyArray, - String useSoftToken ); + String useSoftToken, String keySet ); public static native byte[] DiversifyKey( String tokenName, String newTokenName, @@ -156,7 +157,7 @@ public class SessionKey String keyInfo, byte[] CUIDValue, byte[] kekKeyArray, - String useSoftToken ); + String useSoftToken, String keySet ); // internal calls from config TKS keys tab public static native String GenMasterKey( String token, diff --git a/pki/base/symkey/src/com/netscape/symkey/SymKey.cpp b/pki/base/symkey/src/com/netscape/symkey/SymKey.cpp index 70a3dfbc6..c300d1ada 100644 --- a/pki/base/symkey/src/com/netscape/symkey/SymKey.cpp +++ b/pki/base/symkey/src/com/netscape/symkey/SymKey.cpp @@ -52,7 +52,6 @@ extern "C" #include "certdb.h" #include "nss.h" -#include "seccomon.h" #include "nspr.h" #ifdef __cplusplus #include @@ -87,6 +86,7 @@ typedef struct char masterKeyPrefix[PREFIXLENGHT]; char masterKeyNickName[KEYNAMELENGTH]; char masterNewKeyNickName[KEYNAMELENGTH]; +char sharedSecretSymKeyName[KEYNAMELENGTH] = { 0 }; //================================================================================= #ifdef __cplusplus @@ -113,7 +113,7 @@ PK11SlotInfo *ReturnSlot(char *tokenNameChars) } PK11SlotInfo *slot=NULL; - if(!strcmp( tokenNameChars, "internal" ) ) + if(!strcmp( tokenNameChars, "internal" ) || !strcmp( tokenNameChars, "Internal Key Storage Token")) { slot = PK11_GetInternalKeySlot(); } @@ -140,7 +140,7 @@ PK11SymKey * ReturnSymKey( PK11SlotInfo *slot, char *keyname) pwdata.source = secuPWData::PW_NONE; pwdata.data = (char *) NULL; - + PR_fprintf(PR_STDOUT,"In ReturnSymKey name %s \n",keyname); if (keyname == NULL) { goto cleanup; @@ -151,7 +151,6 @@ PK11SymKey * ReturnSymKey( PK11SlotInfo *slot, char *keyname) } /* Initialize the symmetric key list. */ firstSymKey = PK11_ListFixedKeysInSlot( slot , NULL, ( void *) &pwdata ); - /* scan through the symmetric key list for a key matching our nickname */ sk = firstSymKey; while( sk != NULL ) @@ -414,7 +413,11 @@ PK11SymKey *ComputeCardKeyOnSoftToken(PK11SymKey *masterKey, unsigned char *data { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); PK11SymKey *key = ComputeCardKey(masterKey, data, slot); - PK11_FreeSlot(slot); + if( slot != NULL) { + PK11_FreeSlot(slot); + slot = NULL; + } + return key; } @@ -422,16 +425,16 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI { PK11SymKey *key = NULL; PK11Context *context = NULL; - int keysize; - keysize = 24; + int keysize = DES3_LENGTH; unsigned char *keyData = NULL; - SECStatus s; + SECStatus s = SECSuccess; int i = 0; - int len=0; - static SECItem noParams = { siBuffer, 0, 0 }; + int len = 0; + static SECItem noParams = { siBuffer, NULL, 0 }; unsigned char *in = data; PK11SymKey *tmpkey = NULL; - unsigned char wrappedkey[24]; + unsigned char wrappedkey[DES3_LENGTH]; + SECItem wrappeditem = { siBuffer, NULL, 0 }; keyData = (unsigned char*)malloc(keysize); @@ -440,9 +443,8 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI keyData[i] = 0x0; } - if (masterKey == NULL) - { - printf("ComputeCardKey: master key is null\n"); + if (masterKey == NULL) { + PR_fprintf(PR_STDERR,"ComputeCardKey: master key is null.\n"); goto done; } @@ -450,34 +452,31 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI masterKey, &noParams); - if (context == NULL) - { - printf("failed to create context\n"); + if (context == NULL) { + PR_fprintf(PR_STDERR,"ComputeCardKey: failed to create context.\n"); goto done; } /* Part 1 */ s = PK11_CipherOp(context, &keyData[0], &len, 8, in, 8); - if (s != SECSuccess) - { - printf("failed to encryp #1\n"); + if (s != SECSuccess) { + PR_fprintf(PR_STDERR,"ComputeCardKey: failed to encrypt #1\n"); goto done; } - pk11_FormatDESKey(&keyData[0], 8); /* set parity */ + pk11_FormatDESKey(&keyData[0], EIGHT_BYTES); /* set parity */ /* Part 2 */ - s = PK11_CipherOp(context, &keyData[8], &len, 8, in+8, 8); - if (s != SECSuccess) - { - printf("failed to encryp #2\n"); + s = PK11_CipherOp(context, &keyData[EIGHT_BYTES], &len, EIGHT_BYTES, in+EIGHT_BYTES, EIGHT_BYTES); + if (s != SECSuccess) { + PR_fprintf(PR_STDERR,"ComputeCardKey: failed to encryp #2.\n"); goto done; } - pk11_FormatDESKey(&keyData[8], 8); + pk11_FormatDESKey(&keyData[EIGHT_BYTES], EIGHT_BYTES); /* Part 3 */ - for(i = 0;i < 8;i++) + for(i = 0;i < EIGHT_BYTES;i++) { - keyData[i+16] = keyData[i]; + keyData[i+KEYLENGTH] = keyData[i]; } #define CKF_KEY_OPERATION_FLAGS 0x000e7b00UL @@ -489,7 +488,7 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI PR_FALSE, &pwdata); if (tmpkey == NULL) { - printf("failed to keygen \n"); + PR_fprintf(PR_STDERR,"ComputeCardKey: failed to keygen. \n"); goto done; } @@ -498,7 +497,7 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI &noParams); if (context == NULL) { - printf("failed to set context \n"); + PR_fprintf(PR_STDERR,"ComputeCardKey: failed to set context. \n"); goto done; } @@ -506,11 +505,10 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI s = PK11_CipherOp(context, wrappedkey, &len, 24, keyData, 24); if (s != SECSuccess) { - printf("failed to encryp #3\n"); + PR_fprintf(PR_STDERR,"ComputeCardKey: failed to encrypt #3.\n"); goto done; } - SECItem wrappeditem; wrappeditem.data = wrappedkey; wrappeditem.len = len; @@ -533,123 +531,82 @@ done: PK11_FreeSymKey(tmpkey); tmpkey = NULL; } + return key; } - PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data) { PK11SlotInfo *slot = PK11_GetSlotFromKey(masterKey); PK11SymKey *key = ComputeCardKey(masterKey, data, slot); - PK11_FreeSlot(slot); - return key; -} - - -PRStatus EncryptDataWithCardKey(PK11SymKey *card_key, Buffer &input, Buffer &output) -{ - PRStatus rv = PR_FAILURE; - - PK11Context *context = NULL; - int i; - SECStatus s = SECFailure; - int len; - static SECItem noParams = { siBuffer, 0, 0 }; - unsigned char result[8]; - - if (card_key == NULL) { - printf("EncryptDataWithCardKey: card_key is null\n"); - goto done; - } - - context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, card_key, - &noParams); - if (context == NULL) - { - goto done; - } - - for(i = 0;i < (int)input.size();i += 8) - { - s = PK11_CipherOp(context, result, &len, 8, - (unsigned char *)(((BYTE*)input)+i), 8); - if (s != SECSuccess) - { - goto done; - } - output.replace(i, result, 8); + if( slot) { + PK11_FreeSlot(slot); + slot = NULL; } - rv = PR_SUCCESS; - -done: - if (context) - { - PK11_DestroyContext(context, PR_TRUE); - context = NULL; - } - return rv; + return key; } - -PRStatus EncryptData(Buffer &kek_key, Buffer &input, Buffer &output) +// Either encrypt data with a provided SymKey OR a key buffer array (for the Default keyset case). +PRStatus EncryptData(const Buffer &kek_key,PK11SymKey *cardKey, Buffer &input, Buffer &output) { PRStatus rv = PR_FAILURE; PK11SymKey *master = NULL; + PK11SymKey *transportKey = NULL; PK11SlotInfo *slot = NULL; PK11Context *context = NULL; - int i; + int i = 0; SECStatus s = SECFailure; - int len; - static SECItem noParams = { siBuffer, 0, 0 }; + int len = 0; + static SECItem noParams = { siBuffer, NULL, 0 }; #ifdef DES2_WORKAROUND - unsigned char masterKeyData[24]; + unsigned char masterKeyData[DES3_LENGTH]; #else - unsigned char masterKeyData[16]; -#endif - SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) }; - unsigned char result[8]; - - /* convert 16-byte to 24-byte triple-DES key */ - memcpy(masterKeyData, (BYTE*)kek_key, 16); -#ifdef DES2_WORKAROUND - memcpy(masterKeyData+16, (BYTE*)kek_key, 8); + unsigned char masterKeyData[KEYLENGTH]; #endif + unsigned char result[EIGHT_BYTES]; slot = PK11_GetInternalKeySlot(); - if (slot == NULL) - { + + if (slot == NULL) { goto done; } - master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem, - CKF_ENCRYPT, PR_FALSE, 0); - if( master == NULL) - { - printf("EncryptData: master is null\n"); + if ( cardKey == NULL ) { /* Developer key set mode.*/ + transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL)); + + /* convert 16-byte to 24-byte triple-DES key */ + memcpy(masterKeyData, kek_key, 16); + memcpy(masterKeyData+16, kek_key, 8); + + master = CreateUnWrappedSymKeyOnToken( slot, transportKey, masterKeyData, sizeof(masterKeyData), PR_FALSE); + + } else { + master = cardKey; + } + + if( master == NULL) { goto done; } context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master, &noParams); - if (context == NULL) - { + + if (context == NULL) { goto done; } - for(i = 0;i < (int)input.size();i += 8) + for(i = 0;i < (int)input.size();i += EIGHT_BYTES) { - s = PK11_CipherOp(context, result, &len, 8, - (unsigned char *)(((BYTE*)input)+i), 8); + s = PK11_CipherOp(context, result, &len, EIGHT_BYTES, + (unsigned char *)(((BYTE*)input)+i), EIGHT_BYTES); - if (s != SECSuccess) - { + if (s != SECSuccess) { goto done; } - output.replace(i, result, 8); + output.replace(i, result, EIGHT_BYTES); } rv = PR_SUCCESS; @@ -667,7 +624,7 @@ done: PK11_FreeSlot(slot); slot = NULL; } - if (master) + if (master && cardKey == NULL) { PK11_FreeSymKey(master); master = NULL; @@ -676,37 +633,27 @@ done: return rv; } - -PRStatus ComputeKeyCheck(const Buffer& newKey, Buffer& output) +PRStatus ComputeKeyCheckWithSymKey(PK11SymKey * newKey, Buffer& output) { PK11SymKey *key = NULL; PRStatus status = PR_FAILURE ; PK11SlotInfo *slot = NULL; PK11Context *context = NULL; SECStatus s = SECFailure; - int len; - static SECItem noParams = { siBuffer, 0, 0 }; -#ifdef DES2_WORKAROUND - unsigned char keyData[24]; -#else - unsigned char keyData[16]; -#endif - SECItem keyItem = {siBuffer, keyData, sizeof(keyData) }; - unsigned char value[8]; - /* convert 16-byte to 24-byte triple-DES key */ - memcpy(keyData, newKey, 16); -#ifdef DES2_WORKAROUND - memcpy(keyData+16, newKey, 8); -#endif + int len = 0; + static SECItem noParams = { siBuffer, NULL, 0 }; + unsigned char value[EIGHT_BYTES]; + + if ( newKey == NULL ) { + return status; + } memset(value, 0, sizeof value); slot = PK11_GetInternalKeySlot(); if (slot != NULL) { - key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &keyItem, - CKF_ENCRYPT, PR_FALSE, 0); + key = newKey ; if( key != NULL ) { context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key, @@ -723,94 +670,130 @@ PRStatus ComputeKeyCheck(const Buffer& newKey, Buffer& output) } PK11_DestroyContext(context, PR_TRUE); context = NULL; - memset(keyData, 0, sizeof keyData); } - PK11_FreeSymKey(key); - key = NULL; + //PK11_FreeSymKey(key); + //key = NULL; } - PK11_FreeSlot(slot); + if( slot != NULL) { + PK11_FreeSlot(slot); + slot = NULL; + } } return status; } - -PRStatus CreateKeySetDataWithKey( Buffer &newMasterVer, PK11SymKey *old_kek_key, Buffer &new_auth_key, Buffer &new_mac_key, Buffer &new_kek_key, Buffer &output) +// Create key set data with the help of either a provided old_keyk_ke2_sym key or key buffer (for the Default keyset case). +PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek_key2, PK11SymKey *old_kek_key2_sym, PK11SymKey *new_auth_key, PK11SymKey *new_mac_key, PK11SymKey *new_kek_key, Buffer &output) { PRStatus rv = PR_FAILURE; + static SECItem noParams = { siBuffer, NULL, 0 }; + PK11SymKey *transportKey = NULL; + PK11SymKey *wrappingKey = NULL; + BYTE masterKeyData[DES3_LENGTH]; + + /* Wrapping vars */ + SECItem wrappedKeyItem = { siBuffer, NULL , 0 }; + SECStatus wrapStatus = SECFailure; + PK11SlotInfo *slot = NULL; + /* Extracting vars */ + + CK_ULONG bitPosition = 0; + SECItem paramsItem = { siBuffer, NULL, 0 }; + paramsItem.data = (CK_BYTE *) &bitPosition; + paramsItem.len = sizeof bitPosition; + + PK11SymKey *macKey16 = NULL; + PK11SymKey *authKey16 = NULL; + PK11SymKey *kekKey16 = NULL; + + Buffer encrypted_auth_key(KEYLENGTH); + Buffer encrypted_mac_key(KEYLENGTH); + Buffer encrypted_kek_key(KEYLENGTH); + Buffer kc_auth_key(3); + Buffer kc_mac_key(3); + Buffer kc_kek_key(3); Buffer result; - if (old_kek_key == NULL) - { - result = new_auth_key + new_mac_key + new_kek_key + output ; + + PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys!\n"); + + if ( new_auth_key == NULL || new_mac_key == NULL || new_kek_key == NULL) { + return rv; } - else - { - Buffer encrypted_auth_key(16); - EncryptDataWithCardKey(old_kek_key, new_auth_key, encrypted_auth_key); - Buffer kc_auth_key(3); - ComputeKeyCheck(new_auth_key, kc_auth_key); + slot = PK11_GetSlotFromKey(new_auth_key); + if ( old_kek_key2_sym == NULL ) { /* perm key mode */ + /* Find transport key, shared secret */ + transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL)); + if ( transportKey == NULL ) { + goto done; + } - Buffer encrypted_mac_key(16); - EncryptDataWithCardKey(old_kek_key, new_mac_key, encrypted_mac_key); - Buffer kc_mac_key(3); - ComputeKeyCheck(new_mac_key, kc_mac_key); + /* convert 16-byte to 24-byte triple-DES key */ + memcpy(masterKeyData, old_kek_key2, KEYLENGTH); + memcpy(masterKeyData+16, old_kek_key2, EIGHT_BYTES); - Buffer encrypted_kek_key(16); - EncryptDataWithCardKey(old_kek_key, new_kek_key, encrypted_kek_key); - Buffer kc_kek_key(3); - ComputeKeyCheck(new_kek_key, kc_kek_key); + wrappingKey = CreateUnWrappedSymKeyOnToken( slot, transportKey, masterKeyData, sizeof(masterKeyData), PR_FALSE); - result = newMasterVer + - Buffer(1, (BYTE)0x81) + - Buffer(1, (BYTE)0x10) + - encrypted_auth_key + - Buffer(1, (BYTE)0x03) + - kc_auth_key + - Buffer(1, (BYTE)0x81) + - Buffer(1, (BYTE)0x10) + - encrypted_mac_key + - Buffer(1, (BYTE)0x03) + - kc_mac_key + - Buffer(1, (BYTE)0x81) + - Buffer(1, (BYTE)0x10) + - encrypted_kek_key + - Buffer(1, (BYTE)0x03) + - kc_kek_key; + } else { /* card key mode */ + wrappingKey = old_kek_key2_sym; } - output = result; - rv = PR_SUCCESS; - return rv; + //Now derive 16 byte versions of the provided symkeys + authKey16 = PK11_Derive(new_auth_key, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT, + CKA_DERIVE, 16); -} /* CreateKeySetDataWithKey */ + if ( authKey16 == NULL ) { + PR_fprintf(PR_STDERR,"Error deriving authKey16. Error %d \n", PR_GetError()); + goto done; + } + wrappedKeyItem.data = (unsigned char *) encrypted_auth_key; + wrappedKeyItem.len = encrypted_auth_key.size(); + wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, authKey16, &wrappedKeyItem); + if ( wrapStatus == SECFailure ) { + PR_fprintf(PR_STDERR,"Error wrapping authKey16. Error %d \n", PR_GetError()); + goto done; + } -PRStatus CreateKeySetData( Buffer &newMasterVer, Buffer &old_kek_key2, Buffer &new_auth_key, Buffer &new_mac_key, Buffer &new_kek_key, Buffer &output) -{ - PRStatus rv = PR_FAILURE; + macKey16 = PK11_Derive(new_mac_key, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT, CKA_DERIVE, 16); - Buffer result; - if(old_kek_key2 == Buffer((BYTE*)"#00#00", 6)) - { - result = new_auth_key + new_mac_key + new_kek_key + output ; - } else { - Buffer encrypted_auth_key(16); - EncryptData(old_kek_key2, new_auth_key, encrypted_auth_key); - Buffer kc_auth_key(3); - ComputeKeyCheck(new_auth_key, kc_auth_key); + if ( macKey16 == NULL ) { + PR_fprintf(PR_STDERR,"Error deriving macKey16. Error %d \n", PR_GetError()); + goto done; + } + + wrappedKeyItem.data = (unsigned char *) encrypted_mac_key; + wrappedKeyItem.len = encrypted_mac_key.size(); + wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, macKey16, &wrappedKeyItem); + if ( wrapStatus == SECFailure) { + PR_fprintf(PR_STDERR,"Error wrapping macKey16. Error %d \n", PR_GetError()); + goto done; + } + + kekKey16 = PK11_Derive(new_kek_key, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT, + CKA_DERIVE, 16); + + if ( kekKey16 == NULL ) { + goto done; + PR_fprintf(PR_STDERR,"Error deriving kekKey16. Error %d \n", PR_GetError()); + } - Buffer encrypted_mac_key(16); - EncryptData(old_kek_key2, new_mac_key, encrypted_mac_key); - Buffer kc_mac_key(3); - ComputeKeyCheck(new_mac_key, kc_mac_key); + wrappedKeyItem.data = (unsigned char *) encrypted_kek_key; + wrappedKeyItem.len = encrypted_mac_key.size(); + wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, kekKey16, &wrappedKeyItem); + if ( wrapStatus == SECFailure) { + PR_fprintf(PR_STDERR,"Error wrapping kekKey16. Error %d \n", PR_GetError()); + goto done; + } + + ComputeKeyCheckWithSymKey(new_auth_key, kc_auth_key); - Buffer encrypted_kek_key(16); - EncryptData(old_kek_key2, new_kek_key, encrypted_kek_key); - Buffer kc_kek_key(3); - ComputeKeyCheck(new_kek_key, kc_kek_key); + ComputeKeyCheckWithSymKey(new_mac_key, kc_mac_key); + + ComputeKeyCheckWithSymKey(new_kek_key, kc_kek_key); result = newMasterVer + Buffer(1, (BYTE)0x81) + @@ -828,16 +811,46 @@ PRStatus CreateKeySetData( Buffer &newMasterVer, Buffer &old_kek_key2, Buffer &n encrypted_kek_key + Buffer(1, (BYTE)0x03) + kc_kek_key; - } output = result; rv = PR_SUCCESS; + +done: + + if ( kekKey16 != NULL) { + PK11_FreeSymKey( kekKey16); + kekKey16 = NULL; + } + + if ( authKey16 != NULL) { + PK11_FreeSymKey( authKey16); + authKey16 = NULL; + } + + if ( macKey16 != NULL) { + PK11_FreeSymKey( macKey16); + macKey16 = NULL; + } + + if ( slot != NULL ) { + PK11_FreeSlot( slot); + slot = NULL; + } + + if ( transportKey != NULL ) { + PK11_FreeSymKey( transportKey); + transportKey = NULL; + } + return rv; } - void GetDiversificationData(jbyte *cuidValue,BYTE *KDC,keyType keytype) { + if( ( cuidValue == NULL) || ( KDC == NULL)) { + return; + } + BYTE *lastTwoBytesOfAID = (BYTE *)cuidValue; // BYTE *ICFabricationDate = (BYTE *)cuidValue + 2; BYTE *ICSerialNumber = (BYTE *)cuidValue + 4; @@ -881,6 +894,10 @@ void GetDiversificationData(jbyte *cuidValue,BYTE *KDC,keyType keytype) static int getMasterKeyVersion(char *newMasterKeyNameChars) { + if( newMasterKeyNameChars == NULL || + strlen( newMasterKeyNameChars) < 3) { + return 0; + } char masterKeyVersionNumber[3]; masterKeyVersionNumber[0]=newMasterKeyNameChars[1]; @@ -890,12 +907,25 @@ static int getMasterKeyVersion(char *newMasterKeyNameChars) return newMasterKeyVesion; } +char *GetSharedSecretKeyName(char *newKeyName) { + if ( newKeyName && strlen( newKeyName ) > 0 ) { + if( strlen( sharedSecretSymKeyName) == 0) { + strncpy( sharedSecretSymKeyName, newKeyName, KEYNAMELENGTH); + } + } + + return (char *) sharedSecretSymKeyName ; +} void getFullName(char * fullMasterKeyName, char * masterKeyNameChars ) { + if( fullMasterKeyName == NULL || masterKeyNameChars == NULL + || ( strlen(fullMasterKeyName) + strlen(masterKeyNameChars)) > KEYNAMELENGTH) { + return; + } fullMasterKeyName[0]='\0'; if(strlen(masterKeyPrefix)>0) - strcpy(fullMasterKeyName,masterKeyPrefix); + strncpy(fullMasterKeyName,masterKeyPrefix, KEYNAMELENGTH); strcat(fullMasterKeyName,masterKeyNameChars); } @@ -906,9 +936,9 @@ void getFullName(char * fullMasterKeyName, char * masterKeyNameChars ) * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[B)[B */ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey -(JNIEnv *, jclass, jstring, jstring, jstring, jstring, jstring, jbyteArray, jbyteArray, jstring); +(JNIEnv *, jclass, jstring, jstring, jstring, jstring, jstring, jbyteArray, jbyteArray, jstring, jstring); -extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey( JNIEnv * env, jclass this2, jstring tokenName,jstring newTokenName, jstring oldMasterKeyName, jstring newMasterKeyName, jstring keyInfo, jbyteArray CUIDValue, jbyteArray kekKeyArray, jstring useSoftToken_s) +extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey( JNIEnv * env, jclass this2, jstring tokenName,jstring newTokenName, jstring oldMasterKeyName, jstring newMasterKeyName, jstring keyInfo, jbyteArray CUIDValue, jbyteArray kekKeyArray, jstring useSoftToken_s, jstring keySet) { PK11SymKey *encKey = NULL; PK11SymKey *macKey = NULL; @@ -923,22 +953,17 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive char fullNewMasterKeyName[KEYNAMELENGTH]; PRBool specified_key_is_present = PR_TRUE; PK11SymKey *old_kek_sym_key = NULL; - SECStatus s; - jbyte * cuidValue = (jbyte*)(env)->GetByteArrayElements( CUIDValue, NULL); - - BYTE *encKeyData = NULL; - BYTE *macKeyData = NULL; - BYTE *kekKeyData = NULL; - - BYTE KDCenc[KEYLENGTH]; - BYTE KDCmac[KEYLENGTH]; - BYTE KDCkek[KEYLENGTH]; - jbyte * old_kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL); + char *keySetStringChars = NULL; + if ( keySet != NULL ) { + keySetStringChars = (char *) (env)->GetStringUTFChars( keySet, NULL); + } - GetDiversificationData(cuidValue,KDCenc,enc); - GetDiversificationData(cuidValue,KDCmac,mac); - GetDiversificationData(cuidValue,KDCkek,kek); + char *keySetString = keySetStringChars; + + if ( keySetString == NULL ) { + keySetString = (char *) DEFKEYSET_NAME; + } jbyteArray handleBA=NULL; jbyte *handleBytes=NULL; @@ -946,44 +971,87 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive /* find slot */ char *tokenNameChars = NULL; + char * newMasterKeyNameChars = NULL; PK11SlotInfo *slot = NULL; + PK11SlotInfo *internal = PK11_GetInternalKeySlot(); + + Buffer output; + PK11SlotInfo *newSlot =NULL; + char * newTokenNameChars = NULL; + char *keyInfoChars = NULL; + + jbyte * cuidValue = NULL; + jbyte * old_kek_key = NULL; + + PK11SymKey * masterKey = NULL; + PK11SymKey * oldMasterKey = NULL; + + BYTE KDCenc[KEYLENGTH]; + BYTE KDCmac[KEYLENGTH]; + BYTE KDCkek[KEYLENGTH]; + + if( CUIDValue != NULL) { + cuidValue = (jbyte*)(env)->GetByteArrayElements( CUIDValue, NULL); + } + + if( cuidValue == NULL) { + goto done; + } + + if( kekKeyArray != NULL) { + old_kek_key = (jbyte*)(env)->GetByteArrayElements(kekKeyArray, NULL); + } + + if( old_kek_key == NULL) { + goto done; + } + + PR_fprintf(PR_STDOUT,"In SessionKey.DiversifyKey! \n"); + + GetDiversificationData(cuidValue,KDCenc,enc); + GetDiversificationData(cuidValue,KDCmac,mac); + GetDiversificationData(cuidValue,KDCkek,kek); if(tokenName) { tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL); slot = ReturnSlot(tokenNameChars); - (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); + PR_fprintf(PR_STDOUT,"DiversifyKey: tokenNameChars %s slot %p \n", tokenNameChars,slot); + if( tokenNameChars != NULL) { + (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); + } } - /* find masterkey */ - char * newMasterKeyNameChars = NULL; if(newMasterKeyName) { /* newMasterKeyNameChars #02#01 */ newMasterKeyNameChars= (char *)(env)->GetStringUTFChars(newMasterKeyName, NULL); } - /* fullNewMasterKeyName - no prefix #02#01 */ getFullName(fullNewMasterKeyName,newMasterKeyNameChars); - Buffer output; - PK11SlotInfo *newSlot =NULL; - char * newTokenNameChars = NULL; + PR_fprintf(PR_STDOUT,"DiversifyKey: fullNewMasterKeyName %s . \n", fullNewMasterKeyName); + if(newTokenName) { newTokenNameChars = (char *)(env)->GetStringUTFChars(newTokenName, NULL); newSlot = ReturnSlot(newTokenNameChars); - (env)->ReleaseStringUTFChars(newTokenName, (const char *)newTokenNameChars); + PR_fprintf(PR_STDOUT,"DiversifyKey: newTokenNameChars %s newSlot %p . \n", newTokenNameChars,newSlot); + if( newTokenNameChars != NULL) { + (env)->ReleaseStringUTFChars(newTokenName, (const char *)newTokenNameChars); + } } - PK11SymKey * masterKey = ReturnSymKey(newSlot,fullNewMasterKeyName); - if(newMasterKeyNameChars) - { + masterKey = ReturnSymKey(newSlot,fullNewMasterKeyName); + + if(newMasterKeyNameChars) { (env)->ReleaseStringUTFChars(newMasterKeyName, (const char *)newMasterKeyNameChars); } /* packing return */ - char *keyInfoChars; - keyInfoChars = (char *)(env)->GetStringUTFChars(keyInfo, NULL); + if( keyInfo != NULL) { + keyInfoChars = (char *)(env)->GetStringUTFChars(keyInfo, NULL); + } + newMasterKeyVesion = getMasterKeyVersion(keyInfoChars); if(keyInfoChars) @@ -996,40 +1064,60 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive if(oldMasterKeyName) { oldMasterKeyNameChars = (char *)(env)->GetStringUTFChars(oldMasterKeyName, NULL); + PR_fprintf(PR_STDOUT,"DiversifyKey oldMasterKeyNameChars %s \n", oldMasterKeyNameChars); } getFullName(fullMasterKeyName,oldMasterKeyNameChars); - - if(newSlot == NULL) - { + PR_fprintf(PR_STDOUT,"DiversifyKey fullMasterKeyName %s \n", fullMasterKeyName); + if(newSlot == NULL) { newSlot = slot; } if(strcmp( oldMasterKeyNameChars, "#01#01") == 0 || strcmp( oldMasterKeyNameChars, "#FF#01") == 0) { - old_kek_key_buff = Buffer((BYTE*)old_kek_key, 16); + old_kek_key_buff = Buffer((BYTE*)old_kek_key, KEYLENGTH); }else if(strcmp( oldMasterKeyNameChars, "#00#00") == 0) { - /* print Debug message - do not create real keysetdata */ old_kek_key_buff = Buffer((BYTE*)"#00#00", 6); - output = Buffer((BYTE*)old_kek_key, 16); + output = Buffer((BYTE*)old_kek_key, KEYLENGTH); } else { - PK11SymKey * oldMasterKey = ReturnSymKey(slot,fullMasterKeyName); + oldMasterKey = ReturnSymKey(slot,fullMasterKeyName); old_kek_sym_key = ComputeCardKeyOnToken(oldMasterKey,KDCkek); - if (oldMasterKey) + if (oldMasterKey) { PK11_FreeSymKey( oldMasterKey ); + oldMasterKey = NULL; + } } - if(oldMasterKeyNameChars) + if(oldMasterKeyNameChars) { (env)->ReleaseStringUTFChars(oldMasterKeyName, (const char *)oldMasterKeyNameChars); + } /* special case #01#01 */ if (fullNewMasterKeyName != NULL && strcmp(fullNewMasterKeyName, "#01#01") == 0) { - encKeyData = (BYTE*)old_kek_key; - macKeyData = (BYTE*)old_kek_key; - kekKeyData = (BYTE*)old_kek_key; + Buffer empty = Buffer(); + + encKey = ReturnDeveloperSymKey(internal,(char *) "auth", keySetString, empty); + + if ( encKey == NULL ) { + goto done; + } + PR_fprintf(PR_STDOUT, "Special case dev key set for DiversifyKey!\n"); + + macKey = ReturnDeveloperSymKey(internal, (char *) "mac", keySetString, empty); + if ( macKey == NULL ) { + goto done; + } + + kekKey = ReturnDeveloperSymKey(internal, (char *) "kek", keySetString, empty); + + if ( kekKey == NULL ) { + goto done; + } + } else { + PR_fprintf(PR_STDOUT,"DiversifyKey: Compute card key on token case ! \n"); /* compute card key */ encKey = ComputeCardKeyOnSoftToken(masterKey, KDCenc); macKey = ComputeCardKeyOnSoftToken(masterKey, KDCmac); @@ -1039,73 +1127,65 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive * is not present -- for each portion of the key, check if * the PK11SymKey is NULL before sending it to PK11_GetKeyData()! */ - if( encKey != NULL) - { - s = PK11_ExtractKeyValue(encKey); - encKeyData = (BYTE*)(PK11_GetKeyData(encKey)->data); - } - else - { + if( encKey == NULL) { + PR_fprintf(PR_STDERR,"Can't create encKey in DiversifyKey! \n"); specified_key_is_present = PR_FALSE; goto done; } - if( macKey != NULL) - { - s = PK11_ExtractKeyValue(macKey); - macKeyData = (BYTE*)(PK11_GetKeyData(macKey)->data); - } - else - { + if( macKey == NULL) { + PR_fprintf(PR_STDERR,"Can't create macKey in DiversifyKey! \n"); specified_key_is_present = PR_FALSE; goto done; } - if( kekKey != NULL) - { - s = PK11_ExtractKeyValue(kekKey); - kekKeyData = (BYTE*)(PK11_GetKeyData(kekKey)->data); - } - else - { + if( kekKey == NULL) { + PR_fprintf(PR_STDERR,"Can't create kekKey in DiversifyKey! \n"); specified_key_is_present = PR_FALSE; goto done; } - } - encKeyBuff = Buffer(encKeyData, 16); - macKeyBuff = Buffer(macKeyData, 16); - kekKeyBuff = Buffer(kekKeyData, 16); - - /* decide to whether to create the new key set by using a sym key or - a buffered key */ - if (old_kek_sym_key != NULL) - { - CreateKeySetDataWithKey(newMasterKeyBuffer, + if (old_kek_sym_key != NULL) { + CreateKeySetDataWithSymKeys(newMasterKeyBuffer, Buffer(), old_kek_sym_key, - encKeyBuff, - macKeyBuff, - kekKeyBuff, - output); - } - else - { - CreateKeySetData(newMasterKeyBuffer, - old_kek_key_buff, - encKeyBuff, - macKeyBuff, - kekKeyBuff, + encKey, + macKey, + kekKey, + output); } + else { + old_kek_sym_key = ReturnDeveloperSymKey(slot, (char *) "kek", keySetString, old_kek_key_buff); + CreateKeySetDataWithSymKeys(newMasterKeyBuffer, Buffer(), + old_kek_sym_key, + encKey, + macKey, + kekKey, output); } done: - if (masterKey != NULL) + if (masterKey != NULL) { PK11_FreeSymKey( masterKey); - if (encKey != NULL) + masterKey = NULL; + } + + if (encKey != NULL) { PK11_FreeSymKey( encKey ); - if (macKey != NULL) + encKey = NULL; + } + + if (macKey != NULL) { PK11_FreeSymKey( macKey ); - if (kekKey != NULL) + macKey = NULL; + } + + if (kekKey != NULL) { PK11_FreeSymKey( kekKey ); + kekKey = NULL; + } + + if( keySetStringChars ) { + (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars); + keySetStringChars = NULL; + } if( specified_key_is_present ) { @@ -1116,20 +1196,188 @@ done: handleBytes = (env)->GetByteArrayElements(handleBA, NULL); memcpy(handleBytes, (BYTE*)output,output.size()); - (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); + if( handleBytes != NULL) { + (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); + } + } + + if( cuidValue != NULL) { + (env)->ReleaseByteArrayElements(CUIDValue, cuidValue, JNI_ABORT); + } + + if( kekKeyArray != NULL) { + (env)->ReleaseByteArrayElements(kekKeyArray, old_kek_key, JNI_ABORT); } - (env)->ReleaseByteArrayElements(CUIDValue, cuidValue, JNI_ABORT); + if((newSlot != slot) && newSlot) { + PK11_FreeSlot( newSlot); + newSlot = NULL; + } - if((newSlot != slot)&& newSlot) - PK11_FreeSlot( newSlot ); - if( slot ) - PK11_FreeSlot( slot ); + if( slot ) { + PK11_FreeSlot( slot); + slot = NULL; + } + + if( internal) { + PK11_FreeSlot( internal); + internal = NULL; + } return handleBA; +} + +PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey, BYTE *keyToBeUnWrapped, int sizeOfKeyToBeUnWrapped, PRBool isPerm) +{ + PK11SymKey * unWrappedSymKey = NULL; + int bufSize = 48; + unsigned char outbuf[bufSize]; + int final_len = 0; + SECStatus s = SECSuccess; + PK11Context * EncContext = NULL; + SECItem unWrappedKeyItem = { siBuffer, NULL, 0}; + PK11SymKey *unwrapper = NULL; + + PR_fprintf( PR_STDOUT, + "Creating UnWrappedSymKey on token. \n"); + + if ( (slot == NULL) || (unWrappingKey == NULL) || + (keyToBeUnWrapped == NULL) || + (sizeOfKeyToBeUnWrapped != DES3_LENGTH) + ) { + return NULL; + } + + PK11SlotInfo *unwrapKeySlot = PK11_GetSlotFromKey( unWrappingKey ); + + if ( unwrapKeySlot != slot ) { + unwrapper = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, unWrappingKey); + } + + SECItem *SecParam = PK11_ParamFromIV(CKM_DES3_ECB, NULL); + if ( SecParam == NULL) { + goto done; + } + + EncContext = PK11_CreateContextBySymKey(CKM_DES3_ECB, + CKA_ENCRYPT, + unWrappingKey, SecParam); + + if ( EncContext == NULL) { + goto done; + } + + s = PK11_CipherOp(EncContext, outbuf, &final_len, sizeof( outbuf), keyToBeUnWrapped, + sizeOfKeyToBeUnWrapped); + + if ( s != SECSuccess) { + goto done; + } + + if ( final_len != DES3_LENGTH ) { + goto done; + } + + unWrappedKeyItem.data = outbuf; + unWrappedKeyItem.len = final_len; + + + /* Now try to unwrap our key into the token */ + unWrappedSymKey = PK11_UnwrapSymKeyWithFlagsPerm(unwrapper ? unwrapper : unWrappingKey, + CKM_DES3_ECB,SecParam, &unWrappedKeyItem, + CKM_DES3_ECB, + CKA_UNWRAP, + sizeOfKeyToBeUnWrapped, 0, isPerm ); + +done: + + if( SecParam != NULL ) { + SECITEM_FreeItem(SecParam, PR_TRUE); + SecParam = NULL; + } + if( EncContext != NULL ) { + PK11_DestroyContext(EncContext, PR_TRUE); + EncContext = NULL; + } + + if( unwrapper != NULL ) { + PK11_FreeSymKey( unwrapper ); + unwrapper = NULL; + } + + if( unwrapKeySlot != NULL) { + PK11_FreeSlot( unwrapKeySlot); + unwrapKeySlot = NULL; + } + + PR_fprintf( PR_STDOUT, + "UnWrappedSymKey on token result: %p \n",unWrappedSymKey); + + return unWrappedSymKey; } +//Return default keyset developer key. Either auth, mac, or kek +PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySet, Buffer &inputKey) +{ + const int maxKeyNameSize = 56; + PK11SymKey *devSymKey = NULL; + PK11SymKey *transportKey = NULL; + char devKeyName[maxKeyNameSize]; + + SECStatus rv = SECSuccess; + + BYTE sessionKey[DES3_LENGTH]; + if( slot == NULL || keyType == NULL || keySet == NULL) { + return NULL; + } + + snprintf(devKeyName,maxKeyNameSize,"%s-%sKey", keySet, keyType); + + devSymKey = ReturnSymKey( slot, devKeyName ); + + // Try to create the key once and leave it there. + if( devSymKey == NULL ) { + PR_fprintf(PR_STDOUT, "Can't find devSymKey, try to create it on token. \n"); + if ( inputKey.size() == DES2_LENGTH ) { //Any other size ignored + transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL)); + + if( transportKey == NULL) { + PR_fprintf(PR_STDERR,"Can't get transport key in ReturnDeveloperSymKey! \n"); + goto done; + } + + /* convert 16-byte to 24-byte triple-DES key */ + memcpy(sessionKey, inputKey, DES2_LENGTH); + memcpy(sessionKey+ DES2_LENGTH, inputKey, EIGHT_BYTES); + + //Unwrap this thing on there as permanent, so we don't have to create it again for a given keySet. + if( transportKey) { + devSymKey = CreateUnWrappedSymKeyOnToken( slot, transportKey, sessionKey, sizeof(sessionKey), PR_TRUE); + } + + PR_fprintf(PR_STDERR,"Tried to create devSymKey %p \n",devSymKey); + + rv = SECSuccess; + if( devSymKey ) { + rv = PK11_SetSymKeyNickname( devSymKey, devKeyName ); + + if ( rv != SECSuccess ) { + PR_fprintf(PR_STDERR, "Can't set the nickname of just written devKey! \n"); + } + } + } + } + +done: + if( transportKey ) { + PK11_FreeSymKey( transportKey ); + transportKey = NULL; + } + + // Dont' free slot , let the caller. + return devSymKey; +} /* * Class: com_netscape_cms_servlet_tks_RASessionKey diff --git a/pki/base/symkey/src/com/netscape/symkey/SymKey.h b/pki/base/symkey/src/com/netscape/symkey/SymKey.h index 2f98d0444..5a53d48c9 100644 --- a/pki/base/symkey/src/com/netscape/symkey/SymKey.h +++ b/pki/base/symkey/src/com/netscape/symkey/SymKey.h @@ -28,17 +28,27 @@ typedef enum { } keyType; #define KEYLENGTH 16 #define PREFIXLENGHT 128 +#define DES2_LENGTH 16 +#define DES3_LENGTH 24 +#define EIGHT_BYTES 8 #define KEYNAMELENGTH PREFIXLENGHT+7 +#define TRANSPORT_KEY_NAME "sharedSecret" +#define DEFKEYSET_NAME "defKeySet" extern char masterKeyPrefix[PREFIXLENGHT]; +extern char sharedSecretSymKeyName[KEYNAMELENGTH]; void GetDiversificationData(jbyte *cuidValue,BYTE *KDC,keyType keytype); PK11SymKey * ReturnSymKey( PK11SlotInfo *slot, char *keyname); void GetKeyName(jbyte *keyVersion,char *keyname); PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data); -PRStatus EncryptDataWithCardKey(PK11SymKey *card_key, Buffer &input, Buffer &output); +PRStatus EncryptData(const Buffer &kek_key, PK11SymKey *card_key, Buffer &input, Buffer &output); PK11SlotInfo *ReturnSlot(char *tokenNameChars); PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot); +PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey, BYTE *keyToBeUnWrapped, int sizeOfKeyToBeUnWrapped, PRBool isPerm); +PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySet, Buffer &inputKey); + +char *GetSharedSecretKeyName(char *newKeyName); #define DES2_WORKAROUND #endif /* _TKSSYMKEY_H_ */ diff --git a/pki/base/tks/shared/conf/CS.cfg.in b/pki/base/tks/shared/conf/CS.cfg.in index fbe2d24c0..f06b2c5d0 100644 --- a/pki/base/tks/shared/conf/CS.cfg.in +++ b/pki/base/tks/shared/conf/CS.cfg.in @@ -313,10 +313,12 @@ tks._000=## tks._001=## TKS tks._002=## tks._003=## +tks._004=## tks.debug=false tks.defaultSlot=Internal Key Storage Token tks.drm_transport_cert_nickname= tks.master_key_prefix= +tks.tksSharedSymKeyName=sharedSecret tks.useDefaultSlot=true usrgrp._000=## usrgrp._001=## User/Group diff --git a/pki/base/tps/doc/CS.cfg.in b/pki/base/tps/doc/CS.cfg.in index 7ec1e2876..5fecf3540 100644 --- a/pki/base/tps/doc/CS.cfg.in +++ b/pki/base/tps/doc/CS.cfg.in @@ -177,7 +177,9 @@ conn.tks1._022=# - enable keep alive or not conn.tks1._023=# conn.tks1._024=# where conn.tks1._025=# - TKS connection ID -conn.tks1._026=######################################### +conn.tks1._026=# conn.tks.tksSharedSymKeyName: +conn.tks1._027=# - set shared secret key name +conn.tks1._028=######################################### conn.tks1.hostport=[TKS_HOST]:[TKS_PORT] conn.tks1.clientNickname=[HSM_LABEL][NICKNAME] conn.tks1.servlet.computeSessionKey=/tks/agent/tks/computeSessionKey @@ -191,6 +193,7 @@ conn.tks1.SSLOn=true conn.tks1.keepAlive=false conn.tks1.keySet=defKeySet conn.tks1.serverKeygen=[SERVER_KEYGEN] +conn.tks1.tksSharedSymKeyName=sharedSecret conn.drm1._000=######################################### conn.drm1._001=# DRM connection conn.drm1._002=# diff --git a/pki/base/tps/src/engine/RA.cpp b/pki/base/tps/src/engine/RA.cpp index 0491b6db4..19c445f9d 100644 --- a/pki/base/tps/src/engine/RA.cpp +++ b/pki/base/tps/src/engine/RA.cpp @@ -61,6 +61,19 @@ extern "C" #include "main/RollingLogFile.h" #include "selftests/SelfTest.h" +typedef struct +{ + enum + { + PW_NONE = 0, + PW_FROMFILE = 1, + PW_PLAINTEXT = 2, + PW_EXTERNAL = 3 + } source; + char *data; +} secuPWData; + + static ConfigStore *m_cfg = NULL; static LogFile* m_debug_log = (LogFile *)NULL; static LogFile* m_error_log = (LogFile *)NULL; @@ -1501,6 +1514,10 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, const char *connId) { PK11SymKey *symKey = NULL; + PK11SymKey *symKey24 = NULL; + PK11SymKey *encSymKey24 = NULL; + PK11SymKey *transportKey = NULL; + PK11SymKey *encSymKey16 = NULL; char body[MAX_BODY_LEN]; char configname[256]; char * cardc = NULL; @@ -1511,6 +1528,8 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, PSHttpResponse *response = NULL; HttpConnection *tksConn = NULL; RA_pblock *ra_pb = NULL; + SECItem *SecParam = PK11_ParamFromIV(CKM_DES3_ECB, NULL); + char* transportKeyName = NULL; RA::Debug(LL_PER_PDU, "Start ComputeSessionKey", ""); tksConn = RA::GetTKSConn(connId); @@ -1621,6 +1640,21 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, } } + // Now unwrap the session keys with shared secret transport key + + PR_snprintf((char *)configname, 256, "conn.%s.tksSharedSymKeyName", connId); + + transportKeyName = (char *) m_cfg->GetConfigAsString(configname, TRANSPORT_KEY_NAME); + + RA::Debug(LL_PER_PDU,"RA:ComputeSessionKey","Shared Secret key name: %s.", transportKeyName); + + transportKey = FindSymKeyByName( slot, transportKeyName); + + if ( transportKey == NULL ) { + RA::Debug(LL_PER_PDU,"RA::ComputeSessionKey","fail getting transport key"); + goto loser; + } + sessionKey_s = ra_pb->find_val_s(TKS_RESPONSE_SessionKey); if (sessionKey_s == NULL) { RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "fail no sessionKey_b"); @@ -1632,21 +1666,24 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "decodekey len=%d",decodeKey->size()); - BYTE masterKeyData[24]; - SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData)}; BYTE *keyData = (BYTE *)*decodeKey; - memcpy(masterKeyData, (char*)keyData, 16); - memcpy(masterKeyData+16, (char*)keyData, 8); + SECItem wrappeditem = {siBuffer , keyData, 16 }; - symKey = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem, - CKF_ENCRYPT, PR_FALSE, 0); + symKey = PK11_UnwrapSymKey(transportKey, + CKM_DES3_ECB,SecParam, &wrappeditem, + CKM_DES3_ECB, + CKA_UNWRAP, + 16); + + if ( symKey ) { + symKey24 = CreateDesKey24Byte(slot, symKey); + } if( decodeKey != NULL ) { delete decodeKey; decodeKey = NULL; } - if (symKey == NULL) + if (symKey24 == NULL) RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "MAC Session key is NULL"); @@ -1662,27 +1699,30 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "decodeEnckey len=%d",decodeEncKey->size()); - BYTE masterEncKeyData[24]; - SECItem masterEncKeyItem = - {siBuffer, masterEncKeyData, sizeof(masterEncKeyData)}; BYTE *EnckeyData = (BYTE *)*decodeEncKey; - memcpy(masterEncKeyData, (char*)EnckeyData, 16); - memcpy(masterEncKeyData+16, (char*)EnckeyData, 8); + wrappeditem.data = (unsigned char *) EnckeyData; + wrappeditem.len = 16; + + encSymKey16 = PK11_UnwrapSymKey(transportKey, + CKM_DES3_ECB,SecParam, &wrappeditem, + CKM_DES3_ECB, + CKA_UNWRAP, + 16); + + if ( encSymKey16 ) { + encSymKey24 = CreateDesKey24Byte(slot, encSymKey16); + } - *encSymKey = - PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &masterEncKeyItem, - CKF_ENCRYPT, PR_FALSE, 0); + *encSymKey = encSymKey24; if( decodeEncKey != NULL ) { delete decodeEncKey; decodeEncKey = NULL; } - if (encSymKey == NULL) + if (encSymKey24 == NULL) RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "encSessionKey is NULL"); - if (serverKeygen) { char * tmp= NULL; tmp = ra_pb->find_val_s(TKS_RESPONSE_DRM_Trans_DesKey); @@ -1761,13 +1801,28 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, response = NULL; } + if ( SecParam != NULL ) { + SECITEM_FreeItem(SecParam, PR_TRUE); + SecParam = NULL; + } + if (ra_pb != NULL) { delete ra_pb; } + + if ( symKey != NULL ) { + PK11_FreeSymKey( symKey ); + symKey = NULL; + } + + if ( encSymKey16 != NULL ) { + PK11_FreeSymKey( encSymKey16 ); + encSymKey16 = NULL; + } + // in production, if TKS is unreachable, symKey will be NULL, // and this will signal error to the caller. - return symKey; - + return symKey24; } Buffer *RA::ComputeHostCryptogram(Buffer &card_challenge, @@ -3420,3 +3475,147 @@ TPS_PUBLIC bool RA::verifySystemCerts() { return rv; } + +PK11SymKey *RA::FindSymKeyByName( PK11SlotInfo *slot, char *keyname) { +char *name = NULL; + PK11SymKey *foundSymKey= NULL; + PK11SymKey *firstSymKey= NULL; + PK11SymKey *sk = NULL; + PK11SymKey *nextSymKey = NULL; + secuPWData pwdata; + + pwdata.source = secuPWData::PW_NONE; + pwdata.data = (char *) NULL; + if (keyname == NULL) + { + goto cleanup; + } + if (slot== NULL) + { + goto cleanup; + } + /* Initialize the symmetric key list. */ + firstSymKey = PK11_ListFixedKeysInSlot( slot , NULL, ( void *) &pwdata ); + /* scan through the symmetric key list for a key matching our nickname */ + sk = firstSymKey; + while( sk != NULL ) + { + /* get the nickname of this symkey */ + name = PK11_GetSymKeyNickname( sk ); + + /* if the name matches, make a 'copy' of it */ + if ( name != NULL && !strcmp( keyname, name )) + { + if (foundSymKey == NULL) + { + foundSymKey = PK11_ReferenceSymKey(sk); + } + PORT_Free(name); + } + + sk = PK11_GetNextSymKey( sk ); + } + + /* We're done with the list now, let's free all the keys in it + It's okay to free our key, because we made a copy of it */ + + sk = firstSymKey; + while( sk != NULL ) + { + nextSymKey = PK11_GetNextSymKey(sk); + PK11_FreeSymKey(sk); + sk = nextSymKey; + } + + cleanup: + return foundSymKey; +} + +PK11SymKey *RA::CreateDesKey24Byte(PK11SlotInfo *slot, PK11SymKey *origKey) +{ + PK11SymKey *newKey = NULL; + PK11SymKey *firstEight = NULL; + PK11SymKey *concatKey = NULL; + PK11SymKey *internalOrigKey = NULL; + CK_ULONG bitPosition = 0; + SECItem paramsItem = { siBuffer, NULL, 0 }; + CK_OBJECT_HANDLE keyhandle = 0; + RA::Debug("RA_Enroll_Processor::CreateDesKey24Byte", + "entering."); + + PK11SlotInfo *internal = PK11_GetInternalSlot(); + if ( slot == NULL || origKey == NULL || internal == NULL) + goto loser; + + if( internal != slot ) { //Make sure we do this on the NSS Generic Crypto services because concatanation + // only works there. + internalOrigKey = PK11_MoveSymKey( internal, CKA_ENCRYPT, 0, PR_FALSE, origKey ); + } + // Extract first eight bytes from generated key into another key. + bitPosition = 0; + paramsItem.data = (CK_BYTE *) &bitPosition; + paramsItem.len = sizeof bitPosition; + + if ( internalOrigKey) + firstEight = PK11_Derive(internalOrigKey, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT , CKA_DERIVE, 8); + else + firstEight = PK11_Derive(origKey, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT , CKA_DERIVE, 8); + + if (firstEight == NULL ) { + RA::Debug("RA_Enroll_Processor::CreateDesKey24Byte", + "error deriving 8 byte portion of key."); + goto loser; + } + + //Concatenate 8 byte key to the end of the original key, giving new 24 byte key + keyhandle = PK11_GetSymKeyHandle(firstEight); + + paramsItem.data=(unsigned char *) &keyhandle; + paramsItem.len=sizeof(keyhandle); + + if ( internalOrigKey ) { + concatKey = PK11_Derive ( internalOrigKey , CKM_CONCATENATE_BASE_AND_KEY , ¶msItem ,CKM_DES3_ECB , CKA_DERIVE , 0); + } else { + concatKey = PK11_Derive ( origKey , CKM_CONCATENATE_BASE_AND_KEY , ¶msItem ,CKM_DES3_ECB , CKA_DERIVE , 0); + } + + if ( concatKey == NULL ) { + RA::Debug("RA_Enroll_Processor::CreateDesKey24Byte", + "error concatenating 8 bytes on end of key."); + goto loser; + } + + //Make sure we move this to the proper token, in case it got moved by NSS + //during the derive phase. + + newKey = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, concatKey); + + if ( newKey == NULL ) { + RA::Debug("RA_Enroll_Processor::CreateDesKey24Byte", + "error moving key to original slot."); + } + +loser: + + if ( concatKey != NULL ) { + PK11_FreeSymKey( concatKey ); + concatKey = NULL; + } + + if ( firstEight != NULL ) { + PK11_FreeSymKey ( firstEight ); + firstEight = NULL; + } + + if ( internalOrigKey != NULL ) { + PK11_FreeSymKey ( internalOrigKey ); + internalOrigKey = NULL; + } + + if ( internal != NULL ) { + PK11_FreeSlot( internal); + internal = NULL; + } + + return newKey; +} diff --git a/pki/base/tps/src/include/engine/RA.h b/pki/base/tps/src/include/engine/RA.h index 8e8601601..9e7db9857 100644 --- a/pki/base/tps/src/include/engine/RA.h +++ b/pki/base/tps/src/include/engine/RA.h @@ -91,6 +91,8 @@ enum RA_Log_Level { /* status of RA::Initialize( char *cfg_path, RA_Context *ctx ). */ #define RA_INITIALIZATION_SUCCESS 1 +#define TRANSPORT_KEY_NAME "sharedSecret" + typedef char NSSUTF8; class RA @@ -135,6 +137,9 @@ class RA char **wrappedPrivateKey_s, const char *connId, char **ivParam_s); static Buffer *ComputeHostCryptogram(Buffer &card_challenge, Buffer &host_challenge); + + static PK11SymKey *FindSymKeyByName( PK11SlotInfo *slot, char *keyname); + static PK11SymKey *CreateDesKey24Byte(PK11SlotInfo *slot, PK11SymKey *origKey); public: TPS_PUBLIC static ConfigStore *GetConfigStore(); TPS_PUBLIC static bool match_comma_list(const char* item, char *list); -- cgit