summaryrefslogtreecommitdiffstats
path: root/base/symkey
diff options
context:
space:
mode:
authorJack Magne <jmagne@redhat.com>2014-10-13 13:40:59 -0700
committerJack Magne <jmagne@redhat.com>2015-02-27 18:44:07 -0800
commitf39e3387f8a671ef97a08d1c0c3e4b2b6fd65ad3 (patch)
tree256bd8cca169f87c99c8ef6874b173bed3f1db4e /base/symkey
parent7b1d897ba4cf9de1459d2aad37e969ce9a93a05a (diff)
downloadpki-f39e3387f8a671ef97a08d1c0c3e4b2b6fd65ad3.tar.gz
pki-f39e3387f8a671ef97a08d1c0c3e4b2b6fd65ad3.tar.xz
pki-f39e3387f8a671ef97a08d1c0c3e4b2b6fd65ad3.zip
Ticket: TPS Rewrite: Implement Secure Channel Protocol 02 (#883).
First cut of gp211 and scp protocol 02 for tokens. Allow token operations using a GP211 token over secure channel protocol 02. This patch supports the following: 1. Token operations with a GP211 card and SCP02 protocol, implementation 15. 2. Token still supports GP201 cards with SCP01. 3. SCP02 tested with SC650 gp211/scp02 card. Things still to do: 1. Right now the SCP02 support has been tested with the current gp201 applet and enrollment and formatting works just fine. We need to modify and compile the applet against the GP211 spec and retest to see if any further changes are needed. 2. The nistSP800 key derivation stuff is not completed for the SCP02 protocol. Some of the routines are self contained vs similar SCP01 ones. We have another ticket to complete the nistSP800 support from end to end. This work will be done for that ticket. 3. One of the new scp02 deriviation functions can make use of a new NSS derive mechanism. As of now this work is done by simple encryption, this can be done later. 4. The security APDU level of "RMAC" is not supported because the card does not support it. It could have been done to the spec, but it having the card to test is more convenient and there were more crucial issues to this point.
Diffstat (limited to 'base/symkey')
-rw-r--r--base/symkey/src/com/netscape/symkey/Buffer.cpp6
-rw-r--r--base/symkey/src/com/netscape/symkey/EncryptData.cpp5
-rw-r--r--base/symkey/src/com/netscape/symkey/SessionKey.cpp604
-rw-r--r--base/symkey/src/com/netscape/symkey/SessionKey.java17
-rw-r--r--base/symkey/src/com/netscape/symkey/SymKey.cpp446
-rw-r--r--base/symkey/src/com/netscape/symkey/SymKey.h5
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, &param);
+ 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, &paramsItem, 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, &paramsItem, 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, &paramsItem, 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, &paramsItem, CKA_ENCRYPT, CKA_DERIVE, 16);
+ macKey16 = PK11_Derive(new_mac_key, CKM_EXTRACT_KEY_FROM_KEY, &paramsItem, 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);