diff options
Diffstat (limited to 'base/symkey')
-rw-r--r-- | base/symkey/src/com/netscape/symkey/Buffer.cpp | 6 | ||||
-rw-r--r-- | base/symkey/src/com/netscape/symkey/EncryptData.cpp | 5 | ||||
-rw-r--r-- | base/symkey/src/com/netscape/symkey/SessionKey.cpp | 604 | ||||
-rw-r--r-- | base/symkey/src/com/netscape/symkey/SessionKey.java | 17 | ||||
-rw-r--r-- | base/symkey/src/com/netscape/symkey/SymKey.cpp | 446 | ||||
-rw-r--r-- | base/symkey/src/com/netscape/symkey/SymKey.h | 5 |
6 files changed, 937 insertions, 146 deletions
diff --git a/base/symkey/src/com/netscape/symkey/Buffer.cpp b/base/symkey/src/com/netscape/symkey/Buffer.cpp index 5c687c5f5..6241534a5 100644 --- a/base/symkey/src/com/netscape/symkey/Buffer.cpp +++ b/base/symkey/src/com/netscape/symkey/Buffer.cpp @@ -171,10 +171,10 @@ Buffer::dump() const unsigned int i; for( i=0; i < len; ++i ) { - printf("%02x ", buf[i]); - if( i % 16 == 15 ) printf("\n"); + PR_fprintf(PR_STDOUT,"%02x ", buf[i]); + if( i % 16 == 15 ) PR_fprintf(PR_STDOUT,"\n"); } - printf("\n"); + PR_fprintf(PR_STDOUT,"\n"); } static const char hextbl[] = { diff --git a/base/symkey/src/com/netscape/symkey/EncryptData.cpp b/base/symkey/src/com/netscape/symkey/EncryptData.cpp index 3963b5026..cebc0bb25 100644 --- a/base/symkey/src/com/netscape/symkey/EncryptData.cpp +++ b/base/symkey/src/com/netscape/symkey/EncryptData.cpp @@ -219,7 +219,6 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr if (masterKey != NULL) { - // --------------------------------- // AC KDF SPEC CHANGE: Determine which KDF to use. // @@ -279,11 +278,9 @@ Java_com_netscape_symkey_SessionKey_EncryptData(JNIEnv * env, jclass this2, jstr GetDiversificationData(kddValue,kekData,kek); // AC: Derives the Kek key for the token. - kekKey = ComputeCardKeyOnToken(masterKey,kekData); + kekKey = ComputeCardKeyOnToken(masterKey,kekData,1); } // endif use original KDF - // --------------------------------- - if (kekKey != NULL) { diff --git a/base/symkey/src/com/netscape/symkey/SessionKey.cpp b/base/symkey/src/com/netscape/symkey/SessionKey.cpp index 2c146730f..610928099 100644 --- a/base/symkey/src/com/netscape/symkey/SessionKey.cpp +++ b/base/symkey/src/com/netscape/symkey/SessionKey.cpp @@ -349,6 +349,101 @@ JSS_PK11_getSymKeyPtr(JNIEnv *env, jobject symKeyObject, PK11SymKey **ptr) SYM_KEY_PROXY_SIG, (void**)ptr); } #endif //STEAL_JSS + + +/* ToDo: fully support nistSP800 in next ticket +*/ +PK11SymKey *DeriveKeySCP02(PK11SymKey *cardKey, const Buffer& sequenceCounter, const Buffer& derivationConstant) +{ + + PK11SymKey *key = NULL; + PK11SymKey *master = NULL; + unsigned char message[KEYLENGTH] = {0}; + unsigned char derivationData[DES3_LENGTH] = {0}; + + PRBool invalid_mechanism = PR_TRUE; + SECStatus s = SECFailure; + int len = 0; + int i = 0; + + SECItem *secParam = NULL; + + PK11SlotInfo *slot = PK11_GetInternalKeySlot(); + PK11Context *context = NULL; + SECItem param = { siBuffer, NULL, 0 }; + + unsigned char icv[EIGHT_BYTES] = { 0 }; + + if( sequenceCounter == NULL || derivationConstant == NULL || + sequenceCounter.size() != 2 || derivationConstant.size() != 2 || + cardKey == NULL) { + PR_fprintf(PR_STDERR,"In DeriveKeySCP02! Error invalid input data!\n"); + goto done; + } + + PR_fprintf(PR_STDOUT,"In DeriveKeySCP02! \n"); + PR_fprintf(PR_STDOUT,"In DeriveKeySCP02! seqCounter[0] : %d sequenceCounter [1] : %d \n", sequenceCounter[0], sequenceCounter[1]); + PR_fprintf(PR_STDOUT,"In DeriveKeySCP02! derivationConstant[0] : %x derivationConstant[1] : %x \n", derivationConstant[0], derivationConstant[1]); + + master = cardKey; + + message[0] = (unsigned char) derivationConstant[0]; + message[1] = (unsigned char) derivationConstant[1]; + message[2] = (unsigned char) sequenceCounter[0]; + message[3] = (unsigned char) sequenceCounter[1]; + + + //ToDo use the new NSS provided derive mechanisms for this operation + if(invalid_mechanism == PR_FALSE) { + // Use derive mechanisms + } else { + + //Use encryption method + param.data = (unsigned char *) &icv; + param.len = 8; + secParam = PK11_ParamFromIV(CKM_DES3_CBC_PAD, ¶m); + context = PK11_CreateContextBySymKey(CKM_DES3_CBC_PAD, CKA_ENCRYPT, master, secParam); + if(context == NULL) { + goto done; + } + s = PK11_CipherOp(context,&derivationData[0] , &len, EIGHT_BYTES, &message[0], EIGHT_BYTES); + + if (s != SECSuccess) { goto done; } + + s = PK11_CipherOp(context, &derivationData[EIGHT_BYTES], &len, EIGHT_BYTES, &message[EIGHT_BYTES], EIGHT_BYTES); + if (s != SECSuccess) { goto done; } + + for(i = 0;i < EIGHT_BYTES ;i++) + { + derivationData[i+KEYLENGTH] = derivationData[i]; + } + + key = CreateUnWrappedSymKeyOnToken( slot, master, &derivationData[0] , DES3_LENGTH, PR_FALSE ); + + PR_fprintf(PR_STDOUT,"In DeriveKeySCP02! calculated key: %p \n", key); + } + + done: + + memset(derivationData, 0, sizeof derivationData); + if ( context != NULL) { + PK11_DestroyContext(context, PR_TRUE); + context = NULL; + } + + if (slot) { + PK11_FreeSlot(slot); + slot = NULL; + } + + if (secParam) { + SECITEM_FreeItem(secParam, PR_TRUE); + secParam = NULL; + } + + return key; +} + // 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) @@ -567,6 +662,369 @@ finish: } +//ToDo: Fix this to conform the nistSP800 +//================================================================================= +#ifdef __cplusplus +extern "C" +{ +#endif +/* + * Class: com_netscape_cms_servlet_tks_RASessionKey + * Method: ComputeSessionKeySCP02 + * Signature: ([B[B[B[B)[B + */ + JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_ComputeSessionKeySCP02 + (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_ComputeSessionKeySCP02(JNIEnv * env, jclass this2, jstring tokenName, jstring keyName, jbyteArray keyInfo, jbyteArray CUID, jbyteArray devKeyArray, jbyteArray sequenceCounter, jbyteArray derivationConstant, jstring useSoftToken_s, jstring keySet, jstring sharedSecretKeyName) +{ + /* hardcode permanent dev key */ + jbyte *dev_key = NULL; + if (devKeyArray != NULL) { + dev_key = (jbyte*)(env)->GetByteArrayElements(devKeyArray, NULL); + } else { + return NULL; + } + + 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 *devSymKey = NULL; + PK11SymKey *symkey16 = NULL; + PK11SymKey *devKey = NULL; + + + BYTE devData[KEYLENGTH]; + char keyname[KEYNAMELENGTH]; + + const char *devKeyName = NULL; + + const char *macName = "mac"; + const char *encName = "enc"; + const char *kekName = "kek"; + + keyType kType = mac; + + /* 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 *sc = NULL; + int sc_len = 0; + + int dc_len = 0; + jbyte *dc = NULL; + + jbyte * keyVersion = NULL; + int keyVersion_len = 0; + + Buffer devBuff( ( BYTE *) dev_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( sequenceCounter != NULL) { + sc = (jbyte*)(env)->GetByteArrayElements( sequenceCounter, NULL); + sc_len = (env)->GetArrayLength(sequenceCounter); + } + + if( sc == NULL || sc_len != 2) { + goto done; + } + + if( derivationConstant != NULL) { + dc = (jbyte*)(env)->GetByteArrayElements( derivationConstant, NULL); + dc_len = (env)->GetArrayLength( derivationConstant); + } + + if( dc == NULL || dc_len != 2) { + 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(tokenName) + { + tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL); + slot = ReturnSlot(tokenNameChars); + (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); + } + + if(keyName) + { + keyNameChars = (char *)(env)->GetStringUTFChars(keyName, NULL); + strncpy(keyname,keyNameChars,KEYNAMELENGTH); + (env)->ReleaseStringUTFChars(keyName, (const char *)keyNameChars); + }else + GetKeyName(keyVersion,keyname); + + //Get key type from derivation constant + switch((unsigned char) dc[1]) { + case 0x1 : + kType = mac; + devKeyName = macName; + break; + + case 0x82: + kType = enc; + devKeyName = encName; + break; + + case 0x81: + kType = kek; + devKeyName = kekName; + break; + + default: + kType = mac; + devKeyName = macName; + break; + } + + GetDiversificationData(cuidValue,devData,kType); + + PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKeySCP02! keyName %s keyVersion[0] %d keyVersion[1] %d \n",keyname,(int) keyVersion[0],(int) keyVersion[1]); + + if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 ) || + (keyVersion[0] == -1 && keyVersion[1] == 0x1)) + + { + /* default manufacturers key */ + + devSymKey = ReturnDeveloperSymKey(slot, (char *) devKeyName , keySetString, devBuff); + + if( devSymKey == NULL ) { + goto done; + } + + PR_fprintf(PR_STDOUT,"SessionKey.ComputeSessionKeySCP02! sc[0] : %d sc[1] : %d \n", sc[0], sc[1]); + symkey = DeriveKeySCP02( //Util::DeriveKey( + devSymKey, Buffer((BYTE*)sc, sc_len), Buffer((BYTE*)dc, dc_len)); + + if(symkey == NULL) + { + goto done; + } + + //In the enc key case create the auth as well, we may need it later. + + if(kType == enc) { + + PK11SymKey *authKey = NULL; + + authKey = ReturnDeveloperSymKey(slot, (char *) "auth" , keySetString, devBuff); + + if(authKey == NULL) + { + goto done; + } + + PK11_FreeSymKey(authKey); + authKey = NULL; + + } + + }else + { + PR_fprintf(PR_STDOUT,"SessionKey.ComputeSessionKeySCP02! Attempting with master key. \n"); + masterKey = ReturnSymKey( slot,keyname); + if(masterKey == NULL) + { + goto done; + } + + devKey =ComputeCardKeyOnToken(masterKey,devData,2); + if(devKey == NULL) + { + goto done; + } + + symkey = DeriveKeySCP02(devKey, Buffer((BYTE*)sc, sc_len), Buffer((BYTE*)dc, dc_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; + } + + 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, 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 ( symkey16 ) { + PK11_FreeSymKey( symkey16 ); + symkey16 = NULL; + } + + if( masterKey ) { + PK11_FreeSymKey( masterKey); + masterKey = NULL; + } + + if( devKey ) { + PK11_FreeSymKey( devKey); + devKey = NULL; + } + + if( devSymKey ) { + PK11_FreeSymKey( devSymKey ); + devSymKey = NULL; + } + + if( keySetStringChars ) { + (env)->ReleaseStringUTFChars(keySet, (const char *)keySetStringChars); + keySetStringChars = NULL; + } + + if( sharedSecretKeyNameChars ) { + (env)->ReleaseStringUTFChars(sharedSecretKeyName, (const char *)sharedSecretKeyNameChars); + sharedSecretKeyNameChars = NULL; + } + + if ( handleBytes != NULL) { + (env)->ReleaseByteArrayElements( handleBA, handleBytes, 0); + } + + if ( sc != NULL) { + (env)->ReleaseByteArrayElements(sequenceCounter, sc, JNI_ABORT); + } + + if ( dc != NULL) { + (env)->ReleaseByteArrayElements(derivationConstant, dc, JNI_ABORT); + } + + if( keyVersion != NULL) { + (env)->ReleaseByteArrayElements(keyInfo, keyVersion, JNI_ABORT); + } + + if ( cuidValue != NULL) { + (env)->ReleaseByteArrayElements(CUID, cuidValue, JNI_ABORT); + } + + if( dev_key != NULL) { + (env)->ReleaseByteArrayElements(devKeyArray, dev_key, JNI_ABORT); + } + + if (wrapStatus != SECFailure ){ + return handleBA; + }else{ + return NULL; + } + +} + + + //================================================================================= #ifdef __cplusplus extern "C" @@ -595,7 +1053,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp return NULL; } - char input[KEYLENGTH]; + unsigned char input[KEYLENGTH] = {0}; int i = 0; SECItem wrappedKeyItem = { siBuffer, NULL , 0}; @@ -762,7 +1220,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp }else GetKeyName(keyVersion,keyname); - PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKey! \n"); + PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKey! keyName %s keyVersion[0] %d keyVersion[1] %d \n",keyname,(int) keyVersion[0],(int) keyVersion[1]); if ( (keyVersion[0] == 0x1 && keyVersion[1]== 0x1 && strcmp( keyname, "#01#01") == 0) || (keyVersion[0] == -1 && strstr(keyname, "#FF"))) @@ -781,13 +1239,13 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp }else { + PR_fprintf(PR_STDOUT,"In SessionKey.ComputeSessionKey! Upgraded keyset mode. \n"); masterKey = ReturnSymKey( slot,keyname); if(masterKey == NULL) { goto done; } - // --------------------------------- // AC KDF SPEC CHANGE: Determine which KDF to use. // @@ -847,17 +1305,12 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp GetDiversificationData(kddValue,macData,mac);//keytype is mac // AC: Derives the mac key for the token. - macKey =ComputeCardKeyOnToken(masterKey,macData); + macKey =ComputeCardKeyOnToken(masterKey,macData,1); } // endif use original KDF // --------------------------------- - if(macKey == NULL) - { - goto done; - } - // AC: This computes the GP session key using the card-specific MAC key we previously derived. symkey = DeriveKey(macKey, Buffer((BYTE*)hc, hc_len), Buffer((BYTE*)cc, cc_len)); @@ -1030,7 +1483,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp return NULL; } - char input[KEYLENGTH]; + unsigned char input[KEYLENGTH] = {0}; int i = 0; SECItem wrappedKeyItem = { siBuffer, NULL , 0}; @@ -1205,7 +1658,6 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp goto done; } - // --------------------------------- // AC KDF SPEC CHANGE: Determine which KDF to use. // @@ -1265,12 +1717,11 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp GetDiversificationData(kddValue,encData,enc); // AC: Derives the enc key for the token. - encKey =ComputeCardKeyOnToken(masterKey,encData); + encKey =ComputeCardKeyOnToken(masterKey,encData,1); } // endif use original KDF // --------------------------------- - if(encKey == NULL) { goto done; } @@ -1446,7 +1897,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_Compute keySetString = (char *) DEFKEYSET_NAME; } - char input[KEYLENGTH]; + unsigned char input[KEYLENGTH] = {0}; int i; jobject keyObj = NULL; @@ -1575,7 +2026,6 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_Compute goto done; } - // --------------------------------- // AC KDF SPEC CHANGE: Determine which KDF to use. // @@ -1635,12 +2085,11 @@ extern "C" JNIEXPORT jobject JNICALL Java_com_netscape_symkey_SessionKey_Compute GetDiversificationData(kddValue,kekData,kek);//keytype is kek // AC: Derives the mac key for the token. - kekKey =ComputeCardKeyOnToken(masterKey,kekData); + kekKey =ComputeCardKeyOnToken(masterKey,kekData,1); } // endif use original KDF // --------------------------------- - } if(kekKey == NULL) { @@ -2049,7 +2498,6 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp goto done; } - // --------------------------------- // AC KDF SPEC CHANGE: Determine which KDF to use. // @@ -2109,12 +2557,11 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Comp GetDiversificationData(kddValue,authData,enc); // AC: Derives the mac key for the token. - authKey = ComputeCardKeyOnToken(masterKey,authData); + authKey = ComputeCardKeyOnToken(masterKey,authData,1); } // endif use original KDF // --------------------------------- - if (authKey == NULL) { goto done; @@ -2297,14 +2744,24 @@ Java_com_netscape_symkey_SessionKey_ECBencrypt goto finish; } + PR_fprintf(PR_STDOUT,"In SessionKey: ECBencrypt! 16 byte key derived.... \n"); + //Wrap the new 16 bit key with the input symkey. wrappedKeyItem.data = (unsigned char *) handleBytes; wrappedKeyItem.len = dlen; + + PR_fprintf(PR_STDOUT,"In SessionKey: ECBencrypt! About to wrap des key with sym key.\n"); 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); + + PR_fprintf(PR_STDOUT," ECBencrypt wrapped data: \n"); + Buffer wrappedDataBuf(wrappedKeyItem.data,wrappedKeyItem.len); + wrappedDataBuf.dump(); + + } else { PR_fprintf(PR_STDERR, "ECBecrypt wrap failed! Error %d \n", PR_GetError()); } @@ -2328,6 +2785,105 @@ extern "C" { #endif /* + * Class: com_netscape_cms_servlet_tks_DeriveDESKeyFrom3DesKey + * Method: DeriveDESKeyFrom3DesKey + * Signature: ([B[B[B[B)[B + */ + JNIEXPORT jobject JNICALL + Java_com_netscape_symkey_SessionKey_DeriveDESKeyFrom3DesKey + (JNIEnv*, jclass,jstring ,jobject,jlong); +#ifdef __cplusplus +} +#endif +extern "C" JNIEXPORT jobject JNICALL +Java_com_netscape_symkey_SessionKey_DeriveDESKeyFrom3DesKey +(JNIEnv* env, jclass this2, jstring tokenName, jobject des3Key,jlong alg) +{ + PK11SymKey * des3 = NULL; + PK11SymKey * des = NULL; + PK11SymKey * desFinal = NULL; + PRStatus r = PR_FAILURE; + CK_ULONG bitPosition = 0; + SECItem paramsItem = { siBuffer, NULL, 0 }; + jobject keyObj = NULL; + char *tokenNameChars = NULL; + PK11SlotInfo *slot = NULL; + + if( des3Key == NULL) { + goto loser; + } + + if(alg != CKM_DES_CBC && alg != CKM_DES_ECB) { + PR_fprintf(PR_STDOUT,"SessionKey.DeriveDESKeyFrom3DesKey invalid alg!.. \n"); + goto loser; + } + + if (tokenName) + { + tokenNameChars = (char *)(env)->GetStringUTFChars(tokenName, NULL); + if ( tokenNameChars && !strcmp(tokenNameChars, "internal")) { + slot = PK11_GetInternalSlot(); + } else { + slot = ReturnSlot(tokenNameChars); + } + + (env)->ReleaseStringUTFChars(tokenName, (const char *)tokenNameChars); + } else { + slot = PK11_GetInternalKeySlot(); + } + + if(slot == NULL) { + goto loser; + } + + r = JSS_PK11_getSymKeyPtr(env, des3Key, &des3); + + if (r != PR_SUCCESS) { + PR_fprintf(PR_STDOUT,"SessionKey: DeriveDESKeyFrom3DesKey Unable to get input session 3des sym key! \n"); + goto loser; + } + + /* Now create a DES key with the first 8 bytes of the input 3des key */ + + // Extract first eight bytes from generated key into another key. + bitPosition = 0; + paramsItem.data = (CK_BYTE *) &bitPosition; + paramsItem.len = sizeof bitPosition; + + + des = PK11_Derive(des3, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, alg , CKA_DERIVE, 8); + if (des == NULL ) { + goto loser; + } + + //Make sure we move this to the orig token, in case it got moved by NSS + //during the derive phase. + + desFinal = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, des); + + + /* wrap the sesssion in java object. */ + keyObj = JSS_PK11_wrapSymKey(env, &desFinal, NULL); + +loser: + + if ( slot != NULL ) { + PK11_FreeSlot( slot); + slot = NULL; + } + + if ( des != NULL) { + PK11_FreeSymKey(des); + des = NULL; + } + return keyObj; +} + +#ifdef __cplusplus +extern "C" +{ +#endif +/* * Class: com_netscape_cms_servlet_tks_UnwrapSessionKeyWithSharedSecret * Method: UnwrapSessionKeyWithSharedSecret * Signature: ([B[B[B[B)[B @@ -2396,6 +2952,7 @@ Java_com_netscape_symkey_SessionKey_UnwrapSessionKeyWithSharedSecret wrappedItem.data = (unsigned char *) sessionKeyBytes; wrappedItem.len = sessionKeyLen; + sessionKey = PK11_UnwrapSymKey(sharedSecret, CKM_DES3_ECB,SecParam, &wrappedItem, CKM_DES3_ECB, @@ -2437,6 +2994,12 @@ loser: sessionKey = NULL; } + if (SecParam) { + SECITEM_FreeItem(SecParam, PR_TRUE); + SecParam = NULL; + } + + // Don't free finalKey ptr because wrapping routine takes that out of our hands. return keyObj; @@ -2467,7 +3030,6 @@ Java_com_netscape_symkey_SessionKey_GetSymKeyByName char *tokenNameChars = NULL; char *keyNameChars = NULL; PK11SlotInfo *slot = NULL; - CK_OBJECT_HANDLE keyhandle = 0; PR_fprintf(PR_STDOUT,"In SessionKey GetSymKeyByName!\n"); diff --git a/base/symkey/src/com/netscape/symkey/SessionKey.java b/base/symkey/src/com/netscape/symkey/SessionKey.java index d44cc5479..7a32de60c 100644 --- a/base/symkey/src/com/netscape/symkey/SessionKey.java +++ b/base/symkey/src/com/netscape/symkey/SessionKey.java @@ -74,6 +74,19 @@ public class SessionKey { // external calls from RA public static native byte[] ComputeKeyCheck(PK11SymKey desKey); /* byte data[] ); */ + //SCP02/GP211 methods + + public static native byte[] ComputeSessionKeySCP02(String tokenName, + String keyName, + byte[] keyInfo, + byte[] CUID, + byte[] devKeyArray, + byte[] sequenceCounter, + byte[] derivationConstant, + String useSoftToken, + String keySet, + String sharedSecretKeyName); + public static native byte[] ComputeSessionKey(String tokenName, String keyName, byte[] card_challenge, @@ -173,7 +186,7 @@ public class SessionKey { byte[] CUIDValue, byte[] KDD, // AC: KDF SPEC CHANGE byte[] kekKeyArray, - String useSoftToken, String keySet); + String useSoftToken, String keySet,byte protocol); // internal calls from config TKS keys tab public static native String GenMasterKey(String token, @@ -197,4 +210,6 @@ public class SessionKey { // with functionality only available now in NSS. This is all to preserve exact functional parity with the current TKS. public static native PK11SymKey UnwrapSessionKeyWithSharedSecret(String tokenName, PK11SymKey sharedSecret, byte[] sessionKeyArray); + + public static native PK11SymKey DeriveDESKeyFrom3DesKey(String tokenName, PK11SymKey key3Des,long alg); } diff --git a/base/symkey/src/com/netscape/symkey/SymKey.cpp b/base/symkey/src/com/netscape/symkey/SymKey.cpp index 6e206db54..8890ac3b5 100644 --- a/base/symkey/src/com/netscape/symkey/SymKey.cpp +++ b/base/symkey/src/com/netscape/symkey/SymKey.cpp @@ -91,6 +91,8 @@ char masterKeyNickName[KEYNAMELENGTH]; char masterNewKeyNickName[KEYNAMELENGTH]; char sharedSecretSymKeyName[KEYNAMELENGTH] = { 0 }; +static int checkForDeveloperKeySet(char * keyInfo); + //================================================================================= #ifdef __cplusplus extern "C" @@ -509,10 +511,10 @@ static secuPWData pwdata = { secuPWData::PW_NONE, 0 }; * Internal token is required when we are doing key diversification * where raw key material needs to be accessed */ -PK11SymKey *ComputeCardKeyOnSoftToken(PK11SymKey *masterKey, unsigned char *data) +PK11SymKey *ComputeCardKeyOnSoftToken(PK11SymKey *masterKey, unsigned char *data, int protocol) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); - PK11SymKey *key = ComputeCardKey(masterKey, data, slot); + PK11SymKey *key = ComputeCardKey(masterKey, data, slot,protocol); if( slot != NULL) { PK11_FreeSlot(slot); slot = NULL; @@ -521,7 +523,7 @@ PK11SymKey *ComputeCardKeyOnSoftToken(PK11SymKey *masterKey, unsigned char *data return key; } -PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot) +PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot,int protocol) { PK11SymKey *key = NULL; PK11Context *context = NULL; @@ -533,9 +535,12 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI static SECItem noParams = { siBuffer, NULL, 0 }; unsigned char *in = data; PK11SymKey *tmpkey = NULL; + unsigned char icv[EIGHT_BYTES] = { 0 }; unsigned char wrappedkey[DES3_LENGTH]; SECItem wrappeditem = { siBuffer, NULL, 0 }; + PR_fprintf(PR_STDOUT,"ComputeCardKey: protocol %d.\n",protocol); + keyData = (unsigned char*)malloc(keysize); for (i = 0;i < keysize; i++) @@ -550,7 +555,7 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, masterKey, - &noParams); + &noParams); if (context == NULL) { PR_fprintf(PR_STDERR,"ComputeCardKey: failed to create context.\n"); @@ -591,7 +596,7 @@ PK11SymKey *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotI PR_fprintf(PR_STDERR,"ComputeCardKey: failed to keygen. \n"); goto done; } - + context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, tmpkey, &noParams); @@ -635,10 +640,10 @@ done: return key; } -PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data) +PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data, int protocol) { PK11SlotInfo *slot = PK11_GetSlotFromKey(masterKey); - PK11SymKey *key = ComputeCardKey(masterKey, data, slot); + PK11SymKey *key = ComputeCardKey(masterKey, data, slot,protocol); if( slot) { PK11_FreeSlot(slot); @@ -787,13 +792,14 @@ PRStatus ComputeKeyCheckWithSymKey(PK11SymKey * newKey, 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 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,int protocol, Buffer &output) { PRStatus rv = PR_FAILURE; static SECItem noParams = { siBuffer, NULL, 0 }; PK11SymKey *transportKey = NULL; PK11SymKey *wrappingKey = NULL; BYTE masterKeyData[DES3_LENGTH]; + BYTE alg = 0x81; /* Wrapping vars */ SECItem wrappedKeyItem = { siBuffer, NULL , 0 }; @@ -819,34 +825,69 @@ PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek Buffer kc_kek_key(3); Buffer result; - PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys!\n"); + //Buffer *dumpBuffer = NULL; + //int showDerivedKeys = 0; + + PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys! Protocol: %d \n",protocol); if ( new_auth_key == NULL || new_mac_key == NULL || new_kek_key == NULL) { return rv; } 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; + + if(protocol == 1) { + if ( old_kek_key2_sym == NULL ) { /* perm key mode */ + /* Find transport key, shared secret */ + transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL)); + if ( transportKey == NULL ) { + goto done; + } + + /* convert 16-byte to 24-byte triple-DES key */ + memcpy(masterKeyData, old_kek_key2, KEYLENGTH); + memcpy(masterKeyData+16, old_kek_key2, EIGHT_BYTES); + + wrappingKey = CreateUnWrappedSymKeyOnToken( slot, transportKey, masterKeyData, sizeof(masterKeyData), PR_FALSE); + + } else { /* card key mode */ + PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys: SCP01 card key mode.\n"); + wrappingKey = old_kek_key2_sym; } - /* convert 16-byte to 24-byte triple-DES key */ - memcpy(masterKeyData, old_kek_key2, KEYLENGTH); - memcpy(masterKeyData+16, old_kek_key2, EIGHT_BYTES); + } else if(protocol == 2) { - wrappingKey = CreateUnWrappedSymKeyOnToken( slot, transportKey, masterKeyData, sizeof(masterKeyData), PR_FALSE); + PR_fprintf(PR_STDOUT,"In CreateKeySetDataWithSymKeys: Using dekKey from SCP02 for wrapping key.\n"); - } else { /* card key mode */ - wrappingKey = old_kek_key2_sym; - } + + // Use the unwapped SCP02 DEK sym key pointer. + wrappingKey = old_kek_key2_sym; + + } else { + PR_fprintf(PR_STDERR,"Invalid protocol %d . \n",protocol); + goto done; + + } //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); + /* + + if(showDerivedKeys == 1) { + SECItem *keyData = NULL; + PK11_ExtractKeyValue( authKey16 ); + keyData = PK11_GetKeyData(authKey16); + dumpBuffer = new Buffer(keyData->data,keyData->len ); + PR_fprintf(PR_STDERR,"Debug authKey16 data: \n"); + dumpBuffer->dump(); + delete dumpBuffer; + dumpBuffer = NULL; + } + + */ + if ( authKey16 == NULL ) { PR_fprintf(PR_STDERR,"Error deriving authKey16. Error %d \n", PR_GetError()); goto done; @@ -860,13 +901,28 @@ PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek goto done; } - macKey16 = PK11_Derive(new_mac_key, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT, CKA_DERIVE, 16); + macKey16 = PK11_Derive(new_mac_key, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT, CKA_DERIVE, 16); if ( macKey16 == NULL ) { PR_fprintf(PR_STDERR,"Error deriving macKey16. Error %d \n", PR_GetError()); goto done; } + /* + + if(showDerivedKeys == 1) { + SECItem *keyData = NULL; + PK11_ExtractKeyValue( macKey16 ); + keyData = PK11_GetKeyData(macKey16); + dumpBuffer = new Buffer(keyData->data,keyData->len ); + PR_fprintf(PR_STDERR,"Debug macKey16 data: \n"); + dumpBuffer->dump(); + delete dumpBuffer; + dumpBuffer = NULL; + } + + */ + wrappedKeyItem.data = (unsigned char *) encrypted_mac_key; wrappedKeyItem.len = encrypted_mac_key.size(); wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, macKey16, &wrappedKeyItem); @@ -883,6 +939,21 @@ PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek PR_fprintf(PR_STDERR,"Error deriving kekKey16. Error %d \n", PR_GetError()); } + /* + + if(showDerivedKeys == 1) { + SECItem *keyData = NULL; + PK11_ExtractKeyValue( kekKey16 ); + keyData = PK11_GetKeyData(kekKey16); + dumpBuffer = new Buffer(keyData->data,keyData->len ); + PR_fprintf(PR_STDERR,"Debug kekKey16 data: \n"); + dumpBuffer->dump(); + delete dumpBuffer; + dumpBuffer = NULL; + } + + */ + wrappedKeyItem.data = (unsigned char *) encrypted_kek_key; wrappedKeyItem.len = encrypted_mac_key.size(); wrapStatus = PK11_WrapSymKey(CKM_DES3_ECB,&noParams, wrappingKey, kekKey16, &wrappedKeyItem); @@ -897,18 +968,22 @@ PRStatus CreateKeySetDataWithSymKeys( Buffer &newMasterVer,const Buffer &old_kek ComputeKeyCheckWithSymKey(new_kek_key, kc_kek_key); + if(protocol == 2) { + alg = 0x80; + } //default at top is 0x81 + result = newMasterVer + - Buffer(1, (BYTE)0x81) + + Buffer(1, (BYTE)alg) + Buffer(1, (BYTE)0x10) + encrypted_auth_key + Buffer(1, (BYTE)0x03) + kc_auth_key + - Buffer(1, (BYTE)0x81) + + Buffer(1, (BYTE)alg) + Buffer(1, (BYTE)0x10) + encrypted_mac_key + Buffer(1, (BYTE)0x03) + kc_mac_key + - Buffer(1, (BYTE)0x81) + + Buffer(1, (BYTE)alg) + Buffer(1, (BYTE)0x10) + encrypted_kek_key + Buffer(1, (BYTE)0x03) + @@ -1042,13 +1117,13 @@ void getFullName(char * fullMasterKeyName, char * masterKeyNameChars ) // AC: KDF SPEC CHANGE: function signature change - added jstring oldKeyInfo, jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, and jbyteArray KDD // AC: BUGFIX for key versions higher than 09: We need to specialDecode keyInfo parameters before sending them into symkey! This means the parameters must be jbyteArray's // -- Changed parameter "jstring keyInfo" to "jbyteArray newKeyInfo" -extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey -(JNIEnv *, jclass, jstring, jstring, jstring, jstring, jbyteArray, jbyteArray, jbyte, jboolean, jbyteArray, jbyteArray, jbyteArray, jstring, jstring); +//extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey +//(JNIEnv *, jclass, jstring, jstring, jstring, jstring, jbyteArray, jbyteArray, jbyte, jboolean, jbyteArray, jbyteArray, jbyteArray, jstring, jstring); // AC: KDF SPEC CHANGE: function signature change - added jstring oldKeyInfo, jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, and jbyteArray KDD // AC: BUGFIX for key versions higher than 09: We need to specialDecode keyInfo parameters before sending them into symkey! This means the parameters must be jbyteArray's // -- Changed parameter "jstring keyInfo" to "jbyteArray newKeyInfo" -extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey( JNIEnv * env, jclass this2, jstring tokenName,jstring newTokenName, jstring oldMasterKeyName, jstring newMasterKeyName, jbyteArray oldKeyInfo, jbyteArray newKeyInfo, jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, jbyteArray CUIDValue, jbyteArray KDD, jbyteArray kekKeyArray, jstring useSoftToken_s, jstring keySet) +extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_DiversifyKey( JNIEnv * env, jclass this2, jstring tokenName,jstring newTokenName, jstring oldMasterKeyName, jstring newMasterKeyName, jbyteArray oldKeyInfo, jbyteArray newKeyInfo, jbyte nistSP800_108KdfOnKeyVersion, jboolean nistSP800_108KdfUseCuidAsKdd, jbyteArray CUIDValue, jbyteArray KDD, jbyteArray kekKeyArray, jstring useSoftToken_s, jstring keySet,jbyte protocol) { PK11SymKey *encKey = NULL; PK11SymKey *macKey = NULL; @@ -1069,6 +1144,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive PK11SymKey* old_mac_sym_key = NULL; PK11SymKey* old_enc_sym_key = NULL; PK11SymKey* old_kek_sym_key = NULL; + BYTE scp02DekKeyData[DES3_LENGTH]; char *keySetStringChars = NULL; if ( keySet != NULL ) { @@ -1106,10 +1182,10 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive Buffer output; PK11SlotInfo *newSlot =NULL; char * newTokenNameChars = NULL; - char *keyInfoChars = NULL; + //char *keyInfoChars = NULL; // AC: KDF SPEC CHANGE: Need to retrieve old key info from JNI. - char* oldKeyInfoChars = NULL; + //char* oldKeyInfoChars = NULL; // AC: KDF SPEC CHANGE: Convert new setting value to BYTE (unsigned). BYTE nistSP800_108KdfOnKeyVersion_byte = static_cast<BYTE>(nistSP800_108KdfOnKeyVersion); @@ -1125,6 +1201,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive PK11SymKey * masterKey = NULL; PK11SymKey * oldMasterKey = NULL; + PK11SymKey * transportKey = NULL; BYTE KDCenc[KEYLENGTH]; BYTE KDCmac[KEYLENGTH]; @@ -1170,7 +1247,7 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive goto done; } - PR_fprintf(PR_STDOUT,"In SessionKey.DiversifyKey! \n"); + PR_fprintf(PR_STDOUT,"In SessionKey.DiversifyKey! Protocol: %d \n", protocol); // AC: KDF SPEC CHANGE: // Changed from "cuidValue" to "kddValue". @@ -1274,106 +1351,106 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive 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, KEYLENGTH); + if(protocol == 1) { + if( checkForDeveloperKeySet(oldMasterKeyNameChars )) + { + old_kek_key_buff = Buffer((BYTE*)old_kek_key, KEYLENGTH); + } + else + { + oldMasterKey = ReturnSymKey(slot,fullMasterKeyName); - // AC: BUGFIX: Remove garbage code. - // I believe that this code is a no-op as long as the system is working correctly - // (with the developer keyset data populated in the config file & copied to HSM). - // - // Notes: - // "old_kek_key_buff" appears to only be used if unable to read/load the developer keys into HSM. - // "old_kek_key_buff" is populated with incorrect data (not appropriate key-length) - // "output" is overwritten when "CreateKeySetDataWithSymKeys" is called - // - // As a result, only when there is some failure (i.e. we execute a "goto" and skip assignment - // to "output") do we return a keyset data that is 16 bytes in length (the default KEK). - // This is unlikely to work and even if it does, is a horrible idea as the caller has no way - // of knowing that we've now essentially inserted a "backdoor" on the token. So, instead of - // this, we treat #00#00 just like any other "normal" case. - // - //}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, KEYLENGTH); + // AC: BUGFIX: Check for nonexistent master key instead of (potentially) crashing. + if (oldMasterKey == NULL){ + goto done; + } - } - else - { - oldMasterKey = ReturnSymKey(slot,fullMasterKeyName); + // --------------------------------- + // AC KDF SPEC CHANGE: Determine which KDF to use. + // + // if old key version meets setting value, use NIST SP800-108 KDF for deriving old keys + if (NistSP800_108KDF::useNistSP800_108KDF(nistSP800_108KdfOnKeyVersion_byte, oldKeyVersion) == true){ + + PR_fprintf(PR_STDOUT,"DiversifyKey old key NistSP800_108KDF code: Using NIST SP800-108 KDF for old keyset.\n"); + + // react to "UseCUIDAsKDD" setting value + jbyte* context_jbyte = NULL; + jsize context_len_jsize = 0; + if (nistSP800_108KdfUseCuidAsKdd == JNI_TRUE){ + context_jbyte = cuidValue; + context_len_jsize = cuidValue_len; + }else{ + context_jbyte = kddValue; + context_len_jsize = kddValue_len; + } + // Converting this way is safe since jbyte is guaranteed to be 8 bits + // Of course, this assumes that "char" is 8 bits (not guaranteed, but typical), + // but it looks like this assumption is also made in GetDiversificationData + const BYTE* const context = reinterpret_cast<const BYTE*>(context_jbyte); - // AC: BUGFIX: Check for nonexistent master key instead of (potentially) crashing. - if (oldMasterKey == NULL){ - goto done; - } + // Convert jsize to size_t + const size_t context_len = static_cast<size_t>(context_len_jsize); + if (context_len > 0x000000FF){ // sanity check (CUID should never be larger than 255 bytes) + PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Error; context_len larger than 255 bytes.\n"); + goto done; + } + // call NIST SP800-108 KDF routine + try{ + NistSP800_108KDF::ComputeCardKeys(oldMasterKey, context, context_len, &old_enc_sym_key, &old_mac_sym_key, &old_kek_sym_key); + }catch(std::runtime_error& ex){ + PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Exception invoking NistSP800_108KDF::ComputeCardKeys: "); + PR_fprintf(PR_STDERR, "%s\n", ex.what() == NULL ? "null" : ex.what()); + goto done; + }catch(...){ + PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Unknown exception invoking NistSP800_108KDF::ComputeCardKeys.\n"); + goto done; + } - // --------------------------------- - // AC KDF SPEC CHANGE: Determine which KDF to use. - // - // if old key version meets setting value, use NIST SP800-108 KDF for deriving old keys - if (NistSP800_108KDF::useNistSP800_108KDF(nistSP800_108KdfOnKeyVersion_byte, oldKeyVersion) == true){ + // if not a key version where we use the NIST SP800-108 KDF, use the original KDF + }else{ - PR_fprintf(PR_STDOUT,"DiversifyKey old key NistSP800_108KDF code: Using NIST SP800-108 KDF for old keyset.\n"); + PR_fprintf(PR_STDOUT,"DiversifyKey old key NistSP800_108KDF code: Using original KDF for old keyset.\n"); - // react to "UseCUIDAsKDD" setting value - jbyte* context_jbyte = NULL; - jsize context_len_jsize = 0; - if (nistSP800_108KdfUseCuidAsKdd == JNI_TRUE){ - context_jbyte = cuidValue; - context_len_jsize = cuidValue_len; - }else{ - context_jbyte = kddValue; - context_len_jsize = kddValue_len; - } + // AC: Derives the kek key for the token. + old_kek_sym_key = ComputeCardKeyOnToken(oldMasterKey,KDCkek,1); - // Converting this way is safe since jbyte is guaranteed to be 8 bits - // Of course, this assumes that "char" is 8 bits (not guaranteed, but typical), - // but it looks like this assumption is also made in GetDiversificationData - const BYTE* const context = reinterpret_cast<const BYTE*>(context_jbyte); + } // endif use original KDF + } - // Convert jsize to size_t - const size_t context_len = static_cast<size_t>(context_len_jsize); - if (context_len > 0x000000FF){ // sanity check (CUID should never be larger than 255 bytes) - PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Error; context_len larger than 255 bytes.\n"); - goto done; - } + } else if(protocol == 2) { - // call NIST SP800-108 KDF routine - try{ - NistSP800_108KDF::ComputeCardKeys(oldMasterKey, context, context_len, &old_enc_sym_key, &old_mac_sym_key, &old_kek_sym_key); - }catch(std::runtime_error& ex){ - PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Exception invoking NistSP800_108KDF::ComputeCardKeys: "); - PR_fprintf(PR_STDERR, "%s\n", ex.what() == NULL ? "null" : ex.what()); - goto done; - }catch(...){ - PR_fprintf(PR_STDERR, "DiversifyKey old key NistSP800_108KDF code: Unknown exception invoking NistSP800_108KDF::ComputeCardKeys.\n"); - goto done; - } + Buffer dek_key_buf = Buffer((BYTE*)old_kek_key, 16); - // if not a key version where we use the NIST SP800-108 KDF, use the original KDF - }else{ + PR_fprintf(PR_STDOUT,"DiversifyKey: protocol is 2 import wrapped dek key. \n"); + dek_key_buf.dump(); + transportKey = ReturnSymKey( slot, GetSharedSecretKeyName(NULL)); - PR_fprintf(PR_STDOUT,"DiversifyKey old key NistSP800_108KDF code: Using original KDF for old keyset.\n"); + if(transportKey == NULL) + goto done; - // AC: Derives the kek key for the token. - old_kek_sym_key = ComputeCardKeyOnToken(oldMasterKey,KDCkek); + /* convert 16-byte to 24-byte triple-DES key */ + memcpy(scp02DekKeyData, old_kek_key, 16); - } // endif use original KDF - // --------------------------------- + old_kek_sym_key = UnwrapWrappedSymKeyOnToken( slot, transportKey,DES2_LENGTH, scp02DekKeyData, PR_FALSE); + if(old_kek_sym_key == NULL) { + PR_fprintf(PR_STDERR,"DiversifyKey: Can't unwrap dek key for protocol 2! \n"); + goto done; + } + } else { + PR_fprintf(PR_STDERR,"DiversifyKey: invalid protocol! \n"); + goto done; + } // AC KDF SPEC CHANGE: Moved this code down so we don't skip it during "goto done". //if (oldMasterKey) { // PK11_FreeSymKey( oldMasterKey ); // oldMasterKey = NULL; //} - } // AC KDF SPEC CHANGE: Moved this code down so we don't skip it during "goto done". //if(oldMasterKeyNameChars) { @@ -1406,7 +1483,6 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive } else { PR_fprintf(PR_STDOUT,"DiversifyKey: Compute card key on token case ! \n"); - // --------------------------------- // AC KDF SPEC CHANGE: Determine which KDF to use. // @@ -1457,14 +1533,13 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive // AC: Derives the kek key for the token. /* compute card key */ - encKey = ComputeCardKeyOnSoftToken(masterKey, KDCenc); - macKey = ComputeCardKeyOnSoftToken(masterKey, KDCmac); - kekKey = ComputeCardKeyOnSoftToken(masterKey, KDCkek); + encKey = ComputeCardKeyOnSoftToken(masterKey, KDCenc,protocol); + macKey = ComputeCardKeyOnSoftToken(masterKey, KDCmac,protocol); + kekKey = ComputeCardKeyOnSoftToken(masterKey, KDCkek,protocol); } // endif use original KDF // --------------------------------- - /* Fixes Bugscape Bug #55855: TKS crashes if specified key * is not present -- for each portion of the key, check if * the PK11SymKey is NULL before sending it to PK11_GetKeyData()! @@ -1487,19 +1562,23 @@ extern "C" JNIEXPORT jbyteArray JNICALL Java_com_netscape_symkey_SessionKey_Dive } if (old_kek_sym_key != NULL) { + CreateKeySetDataWithSymKeys(newMasterKeyBuffer, Buffer(), old_kek_sym_key, encKey, macKey, kekKey, + protocol, 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, + protocol, output); } @@ -1638,13 +1717,14 @@ PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWra PK11Context * EncContext = NULL; SECItem unWrappedKeyItem = { siBuffer, NULL, 0}; PK11SymKey *unwrapper = NULL; + PK11SymKey *unwrapped24Key = NULL; PR_fprintf( PR_STDOUT, "Creating UnWrappedSymKey on token. \n"); if ( (slot == NULL) || (unWrappingKey == NULL) || (keyToBeUnWrapped == NULL) || - (sizeOfKeyToBeUnWrapped != DES3_LENGTH) + ((sizeOfKeyToBeUnWrapped != DES3_LENGTH) && (sizeOfKeyToBeUnWrapped != DES2_LENGTH)) ) { return NULL; } @@ -1675,7 +1755,11 @@ PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWra goto done; } - if ( final_len != DES3_LENGTH ) { + PR_fprintf( PR_STDOUT, + "Creating UnWrappedSymKey on token. final len %d \n", final_len); + + + if ( final_len != DES3_LENGTH && final_len != DES2_LENGTH) { goto done; } @@ -1689,6 +1773,22 @@ PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWra CKM_DES3_ECB, CKA_UNWRAP, sizeOfKeyToBeUnWrapped, 0, isPerm ); + + if(sizeOfKeyToBeUnWrapped == DES2_LENGTH) { + unwrapped24Key = CreateDesKey24Byte(slot, unWrappedSymKey); + if(unwrapped24Key == NULL) { + PR_fprintf( PR_STDERR, + "UnwrapWrappedSymKeyOnToken . Unable to unwrap 24 byte key onto token!. \n"); + + } + } + + + if(unwrapped24Key != NULL) { + PK11_FreeSymKey( unWrappedSymKey); + unWrappedSymKey = unwrapped24Key; + } + done: @@ -1710,7 +1810,7 @@ done: if( unwrapKeySlot != NULL) { PK11_FreeSlot( unwrapKeySlot); unwrapKeySlot = NULL; - } + } PR_fprintf( PR_STDOUT, "UnWrappedSymKey on token result: %p \n",unWrappedSymKey); @@ -1735,6 +1835,8 @@ PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySe snprintf(devKeyName,maxKeyNameSize,"%s-%sKey", keySet, keyType); + PR_fprintf(PR_STDOUT,"ReturnDeveloperSymKey! trying to find key %s. \n",devKeyName); + devSymKey = ReturnSymKey( slot, devKeyName ); // Try to create the key once and leave it there. @@ -1767,7 +1869,10 @@ PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySe PR_fprintf(PR_STDERR, "Can't set the nickname of just written devKey! \n"); } } + } else { + PR_fprintf(PR_STDOUT,"ReturnDeveloperSymKey! input key size %d. \n",inputKey.size()); } + } done: @@ -1806,3 +1911,114 @@ JNICALL Java_com_netscape_symkey_SessionKey_SetDefaultPrefix(JNIEnv * env, jclas return; } + +int checkForDeveloperKeySet(char * keyInfo) +{ + + if(keyInfo == NULL) + return 1; + + //SCP01 or SCP02 + if(strcmp( keyInfo, "#01#01") == 0 || strcmp( keyInfo, "#FF#01") == 0) + return 1; + + //SCP02 + if(strcmp( keyInfo, "#01#02") == 0 || strcmp( keyInfo, "#FF#02") == 0) + return 1; + + return 0; +} + +// Unwrap previously wrapped sym key. Assume the final output is 24 bytes DES3, this function assumes the key is wrapped already. + +PK11SymKey *UnwrapWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey,int sizeOfWrappedKey, unsigned char * wrappedKeyData, PRBool isPerm) { + + PK11SymKey * unWrappedSymKey = NULL; + int final_len = DES3_LENGTH; + SECItem unWrappedKeyItem = { siBuffer, NULL, 0}; + PK11SymKey *unwrapper = NULL; + PK11SymKey *unwrapped24Key = NULL; + + + PR_fprintf( PR_STDOUT, + "Creating UnWrappedSymKey on token. UnwrapWrappedSymKeyOnToken. \n"); + + if ( (slot == NULL) || (unWrappingKey == NULL) || (wrappedKeyData == NULL)) + { + return NULL; + } + + if(sizeOfWrappedKey == DES2_LENGTH) { + PR_fprintf( PR_STDOUT, + "UnwrapWrappedSymKeyOnToken . Given 16 byte encrypted key will have to derive a 24 byte on later. \n"); + } + + 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; + } + + if ( final_len != DES3_LENGTH ) { + goto done; + } + + unWrappedKeyItem.data = wrappedKeyData; + unWrappedKeyItem.len = sizeOfWrappedKey; + + /* 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, + sizeOfWrappedKey, 0, isPerm ); + + if(unWrappedSymKey == NULL) { + PR_fprintf( PR_STDERR, + "UnwrapWrappedSymKeyOnToken . Unable to unwrap key onto token!. \n"); + goto done; + } + + if(sizeOfWrappedKey == DES2_LENGTH) { + unwrapped24Key = CreateDesKey24Byte(slot, unWrappedSymKey); + if(unwrapped24Key == NULL) { + PR_fprintf( PR_STDERR, + "UnwrapWrappedSymKeyOnToken . Unable to unwrap 24 byte key onto token!. \n"); + + } + } + +done: + + if( SecParam != NULL ) { + SECITEM_FreeItem(SecParam, PR_TRUE); + SecParam = NULL; + } + + if( unwrapper != NULL ) { + PK11_FreeSymKey( unwrapper ); + unwrapper = NULL; + } + + if( unwrapKeySlot != NULL) { + PK11_FreeSlot( unwrapKeySlot); + unwrapKeySlot = NULL; + } + + if( unwrapped24Key != NULL) { + PK11_FreeSymKey( unWrappedSymKey); + unWrappedSymKey = unwrapped24Key; + } + + PR_fprintf( PR_STDOUT, + "UnwrapWrappedSymKey on token result: %p \n",unWrappedSymKey); + + + return unWrappedSymKey; + +} diff --git a/base/symkey/src/com/netscape/symkey/SymKey.h b/base/symkey/src/com/netscape/symkey/SymKey.h index efe187075..4f1bbe7ef 100644 --- a/base/symkey/src/com/netscape/symkey/SymKey.h +++ b/base/symkey/src/com/netscape/symkey/SymKey.h @@ -41,13 +41,14 @@ 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); +PK11SymKey * ComputeCardKeyOnToken(PK11SymKey *masterKey, BYTE* data,int protocol); 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 *ComputeCardKey(PK11SymKey *masterKey, unsigned char *data, PK11SlotInfo *slot,int protocol); PK11SymKey *CreateUnWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey, BYTE *keyToBeUnWrapped, int sizeOfKeyToBeUnWrapped, PRBool isPerm); PK11SymKey *ReturnDeveloperSymKey(PK11SlotInfo *slot, char *keyType, char *keySet, Buffer &inputKey); PK11SymKey *CreateDesKey24Byte(PK11SlotInfo *slot, PK11SymKey *origKey); +PK11SymKey *UnwrapWrappedSymKeyOnToken( PK11SlotInfo *slot, PK11SymKey * unWrappingKey,int sizeOfWrappedKey, unsigned char * wrappedKeyData, PRBool isPerm); char *GetSharedSecretKeyName(char *newKeyName); |