diff options
Diffstat (limited to 'pki/base/tps/src/engine/RA.cpp')
-rw-r--r-- | pki/base/tps/src/engine/RA.cpp | 241 |
1 files changed, 220 insertions, 21 deletions
diff --git a/pki/base/tps/src/engine/RA.cpp b/pki/base/tps/src/engine/RA.cpp index 0491b6db4..19c445f9d 100644 --- a/pki/base/tps/src/engine/RA.cpp +++ b/pki/base/tps/src/engine/RA.cpp @@ -61,6 +61,19 @@ extern "C" #include "main/RollingLogFile.h" #include "selftests/SelfTest.h" +typedef struct +{ + enum + { + PW_NONE = 0, + PW_FROMFILE = 1, + PW_PLAINTEXT = 2, + PW_EXTERNAL = 3 + } source; + char *data; +} secuPWData; + + static ConfigStore *m_cfg = NULL; static LogFile* m_debug_log = (LogFile *)NULL; static LogFile* m_error_log = (LogFile *)NULL; @@ -1501,6 +1514,10 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, const char *connId) { PK11SymKey *symKey = NULL; + PK11SymKey *symKey24 = NULL; + PK11SymKey *encSymKey24 = NULL; + PK11SymKey *transportKey = NULL; + PK11SymKey *encSymKey16 = NULL; char body[MAX_BODY_LEN]; char configname[256]; char * cardc = NULL; @@ -1511,6 +1528,8 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, PSHttpResponse *response = NULL; HttpConnection *tksConn = NULL; RA_pblock *ra_pb = NULL; + SECItem *SecParam = PK11_ParamFromIV(CKM_DES3_ECB, NULL); + char* transportKeyName = NULL; RA::Debug(LL_PER_PDU, "Start ComputeSessionKey", ""); tksConn = RA::GetTKSConn(connId); @@ -1621,6 +1640,21 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, } } + // Now unwrap the session keys with shared secret transport key + + PR_snprintf((char *)configname, 256, "conn.%s.tksSharedSymKeyName", connId); + + transportKeyName = (char *) m_cfg->GetConfigAsString(configname, TRANSPORT_KEY_NAME); + + RA::Debug(LL_PER_PDU,"RA:ComputeSessionKey","Shared Secret key name: %s.", transportKeyName); + + transportKey = FindSymKeyByName( slot, transportKeyName); + + if ( transportKey == NULL ) { + RA::Debug(LL_PER_PDU,"RA::ComputeSessionKey","fail getting transport key"); + goto loser; + } + sessionKey_s = ra_pb->find_val_s(TKS_RESPONSE_SessionKey); if (sessionKey_s == NULL) { RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "fail no sessionKey_b"); @@ -1632,21 +1666,24 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "decodekey len=%d",decodeKey->size()); - BYTE masterKeyData[24]; - SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData)}; BYTE *keyData = (BYTE *)*decodeKey; - memcpy(masterKeyData, (char*)keyData, 16); - memcpy(masterKeyData+16, (char*)keyData, 8); + SECItem wrappeditem = {siBuffer , keyData, 16 }; - symKey = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem, - CKF_ENCRYPT, PR_FALSE, 0); + symKey = PK11_UnwrapSymKey(transportKey, + CKM_DES3_ECB,SecParam, &wrappeditem, + CKM_DES3_ECB, + CKA_UNWRAP, + 16); + + if ( symKey ) { + symKey24 = CreateDesKey24Byte(slot, symKey); + } if( decodeKey != NULL ) { delete decodeKey; decodeKey = NULL; } - if (symKey == NULL) + if (symKey24 == NULL) RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "MAC Session key is NULL"); @@ -1662,27 +1699,30 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "decodeEnckey len=%d",decodeEncKey->size()); - BYTE masterEncKeyData[24]; - SECItem masterEncKeyItem = - {siBuffer, masterEncKeyData, sizeof(masterEncKeyData)}; BYTE *EnckeyData = (BYTE *)*decodeEncKey; - memcpy(masterEncKeyData, (char*)EnckeyData, 16); - memcpy(masterEncKeyData+16, (char*)EnckeyData, 8); + wrappeditem.data = (unsigned char *) EnckeyData; + wrappeditem.len = 16; + + encSymKey16 = PK11_UnwrapSymKey(transportKey, + CKM_DES3_ECB,SecParam, &wrappeditem, + CKM_DES3_ECB, + CKA_UNWRAP, + 16); + + if ( encSymKey16 ) { + encSymKey24 = CreateDesKey24Byte(slot, encSymKey16); + } - *encSymKey = - PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, - PK11_OriginGenerated, CKA_ENCRYPT, &masterEncKeyItem, - CKF_ENCRYPT, PR_FALSE, 0); + *encSymKey = encSymKey24; if( decodeEncKey != NULL ) { delete decodeEncKey; decodeEncKey = NULL; } - if (encSymKey == NULL) + if (encSymKey24 == NULL) RA::Debug(LL_PER_PDU, "RA:ComputeSessionKey", "encSessionKey is NULL"); - if (serverKeygen) { char * tmp= NULL; tmp = ra_pb->find_val_s(TKS_RESPONSE_DRM_Trans_DesKey); @@ -1761,13 +1801,28 @@ PK11SymKey *RA::ComputeSessionKey(RA_Session *session, response = NULL; } + if ( SecParam != NULL ) { + SECITEM_FreeItem(SecParam, PR_TRUE); + SecParam = NULL; + } + if (ra_pb != NULL) { delete ra_pb; } + + if ( symKey != NULL ) { + PK11_FreeSymKey( symKey ); + symKey = NULL; + } + + if ( encSymKey16 != NULL ) { + PK11_FreeSymKey( encSymKey16 ); + encSymKey16 = NULL; + } + // in production, if TKS is unreachable, symKey will be NULL, // and this will signal error to the caller. - return symKey; - + return symKey24; } Buffer *RA::ComputeHostCryptogram(Buffer &card_challenge, @@ -3420,3 +3475,147 @@ TPS_PUBLIC bool RA::verifySystemCerts() { return rv; } + +PK11SymKey *RA::FindSymKeyByName( PK11SlotInfo *slot, char *keyname) { +char *name = NULL; + PK11SymKey *foundSymKey= NULL; + PK11SymKey *firstSymKey= NULL; + PK11SymKey *sk = NULL; + PK11SymKey *nextSymKey = NULL; + secuPWData pwdata; + + pwdata.source = secuPWData::PW_NONE; + pwdata.data = (char *) NULL; + if (keyname == NULL) + { + goto cleanup; + } + if (slot== NULL) + { + goto cleanup; + } + /* Initialize the symmetric key list. */ + firstSymKey = PK11_ListFixedKeysInSlot( slot , NULL, ( void *) &pwdata ); + /* scan through the symmetric key list for a key matching our nickname */ + sk = firstSymKey; + while( sk != NULL ) + { + /* get the nickname of this symkey */ + name = PK11_GetSymKeyNickname( sk ); + + /* if the name matches, make a 'copy' of it */ + if ( name != NULL && !strcmp( keyname, name )) + { + if (foundSymKey == NULL) + { + foundSymKey = PK11_ReferenceSymKey(sk); + } + PORT_Free(name); + } + + sk = PK11_GetNextSymKey( sk ); + } + + /* We're done with the list now, let's free all the keys in it + It's okay to free our key, because we made a copy of it */ + + sk = firstSymKey; + while( sk != NULL ) + { + nextSymKey = PK11_GetNextSymKey(sk); + PK11_FreeSymKey(sk); + sk = nextSymKey; + } + + cleanup: + return foundSymKey; +} + +PK11SymKey *RA::CreateDesKey24Byte(PK11SlotInfo *slot, PK11SymKey *origKey) +{ + PK11SymKey *newKey = NULL; + PK11SymKey *firstEight = NULL; + PK11SymKey *concatKey = NULL; + PK11SymKey *internalOrigKey = NULL; + CK_ULONG bitPosition = 0; + SECItem paramsItem = { siBuffer, NULL, 0 }; + CK_OBJECT_HANDLE keyhandle = 0; + RA::Debug("RA_Enroll_Processor::CreateDesKey24Byte", + "entering."); + + PK11SlotInfo *internal = PK11_GetInternalSlot(); + if ( slot == NULL || origKey == NULL || internal == NULL) + goto loser; + + if( internal != slot ) { //Make sure we do this on the NSS Generic Crypto services because concatanation + // only works there. + internalOrigKey = PK11_MoveSymKey( internal, CKA_ENCRYPT, 0, PR_FALSE, origKey ); + } + // Extract first eight bytes from generated key into another key. + bitPosition = 0; + paramsItem.data = (CK_BYTE *) &bitPosition; + paramsItem.len = sizeof bitPosition; + + if ( internalOrigKey) + firstEight = PK11_Derive(internalOrigKey, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT , CKA_DERIVE, 8); + else + firstEight = PK11_Derive(origKey, CKM_EXTRACT_KEY_FROM_KEY, ¶msItem, CKA_ENCRYPT , CKA_DERIVE, 8); + + if (firstEight == NULL ) { + RA::Debug("RA_Enroll_Processor::CreateDesKey24Byte", + "error deriving 8 byte portion of key."); + goto loser; + } + + //Concatenate 8 byte key to the end of the original key, giving new 24 byte key + keyhandle = PK11_GetSymKeyHandle(firstEight); + + paramsItem.data=(unsigned char *) &keyhandle; + paramsItem.len=sizeof(keyhandle); + + if ( internalOrigKey ) { + concatKey = PK11_Derive ( internalOrigKey , CKM_CONCATENATE_BASE_AND_KEY , ¶msItem ,CKM_DES3_ECB , CKA_DERIVE , 0); + } else { + concatKey = PK11_Derive ( origKey , CKM_CONCATENATE_BASE_AND_KEY , ¶msItem ,CKM_DES3_ECB , CKA_DERIVE , 0); + } + + if ( concatKey == NULL ) { + RA::Debug("RA_Enroll_Processor::CreateDesKey24Byte", + "error concatenating 8 bytes on end of key."); + goto loser; + } + + //Make sure we move this to the proper token, in case it got moved by NSS + //during the derive phase. + + newKey = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, concatKey); + + if ( newKey == NULL ) { + RA::Debug("RA_Enroll_Processor::CreateDesKey24Byte", + "error moving key to original slot."); + } + +loser: + + if ( concatKey != NULL ) { + PK11_FreeSymKey( concatKey ); + concatKey = NULL; + } + + if ( firstEight != NULL ) { + PK11_FreeSymKey ( firstEight ); + firstEight = NULL; + } + + if ( internalOrigKey != NULL ) { + PK11_FreeSymKey ( internalOrigKey ); + internalOrigKey = NULL; + } + + if ( internal != NULL ) { + PK11_FreeSlot( internal); + internal = NULL; + } + + return newKey; +} |