diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c --- a/lib/softoken/pkcs11.c +++ b/lib/softoken/pkcs11.c @@ -388,16 +388,17 @@ static const struct mechanismList mechan {CKM_SHA256_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, {CKM_SHA384, {0, 0, CKF_DIGEST}, PR_FALSE}, {CKM_SHA384_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, {CKM_SHA384_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, {CKM_SHA512, {0, 0, CKF_DIGEST}, PR_FALSE}, {CKM_SHA512_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE}, {CKM_SHA512_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE}, {CKM_TLS_PRF_GENERAL, {0, 512, CKF_SN_VR}, PR_FALSE}, + {CKM_TLS12_MAC, {0, 512, CKF_SN_VR}, PR_FALSE}, {CKM_NSS_TLS_PRF_GENERAL_SHA256, {0, 512, CKF_SN_VR}, PR_FALSE}, /* ------------------------- HKDF Operations -------------------------- */ {CKM_NSS_HKDF_SHA1, {1, 128, CKF_DERIVE}, PR_TRUE}, {CKM_NSS_HKDF_SHA256, {1, 128, CKF_DERIVE}, PR_TRUE}, {CKM_NSS_HKDF_SHA384, {1, 128, CKF_DERIVE}, PR_TRUE}, {CKM_NSS_HKDF_SHA512, {1, 128, CKF_DERIVE}, PR_TRUE}, /* ------------------------- CAST Operations --------------------------- */ @@ -468,22 +469,25 @@ static const struct mechanismList mechan {CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE}, {CKM_MD2_KEY_DERIVATION, { 0, 16, CKF_DERIVE}, PR_FALSE}, {CKM_SHA1_KEY_DERIVATION, { 0, 20, CKF_DERIVE}, PR_FALSE}, {CKM_SHA224_KEY_DERIVATION, { 0, 28, CKF_DERIVE}, PR_FALSE}, {CKM_SHA256_KEY_DERIVATION, { 0, 32, CKF_DERIVE}, PR_FALSE}, {CKM_SHA384_KEY_DERIVATION, { 0, 48, CKF_DERIVE}, PR_FALSE}, {CKM_SHA512_KEY_DERIVATION, { 0, 64, CKF_DERIVE}, PR_FALSE}, {CKM_TLS_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, + {CKM_TLS12_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, {CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256, {48, 48, CKF_DERIVE}, PR_FALSE}, {CKM_TLS_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE}, + {CKM_TLS12_MASTER_KEY_DERIVE_DH, {8, 128, CKF_DERIVE}, PR_FALSE}, {CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256, {8, 128, CKF_DERIVE}, PR_FALSE}, {CKM_TLS_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, + {CKM_TLS12_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE}, PR_FALSE}, {CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256, {48, 48, CKF_DERIVE}, PR_FALSE}, /* ---------------------- PBE Key Derivations ------------------------ */ {CKM_PBE_MD2_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, {CKM_PBE_MD5_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, /* ------------------ NETSCAPE PBE Key Derivations ------------------- */ {CKM_NETSCAPE_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE}, PR_TRUE}, {CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c --- a/lib/softoken/pkcs11c.c +++ b/lib/softoken/pkcs11c.c @@ -2512,20 +2527,62 @@ finish_rsa: crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_SSL3_SHA1_MAC: crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_TLS_PRF_GENERAL: - crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL); + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); break; + case CKM_TLS12_MAC: { + CK_TLS12_MAC_PARAMS *tls12_mac_params; + HASH_HashType tlsPrfHash; + const char *label; + + if (pMechanism->ulParameterLen != sizeof(CK_TLS12_MAC_PARAMS)) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + tls12_mac_params = (CK_TLS12_MAC_PARAMS *)pMechanism->pParameter; + if (tls12_mac_params->prfMechanism == CKM_TLS_PRF) { + /* The TLS 1.0 and 1.1 PRF */ + tlsPrfHash = HASH_AlgNULL; + if (tls12_mac_params->ulMacLength != 12) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + } else { + /* The hash function for the TLS 1.2 PRF */ + tlsPrfHash = + GetHashTypeFromMechanism(tls12_mac_params->prfMechanism); + if (tlsPrfHash == HASH_AlgNULL || + tls12_mac_params->ulMacLength < 12) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + } + if (tls12_mac_params->ulServerOrClient == 1) { + label = "server finished"; + } else if (tls12_mac_params->ulServerOrClient == 2) { + label = "client finished"; + } else { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash, + tls12_mac_params->ulMacLength); + if (crv == CKR_OK) { + context->hashUpdate(context->hashInfo, label, 15); + } + break; + } case CKM_NSS_TLS_PRF_GENERAL_SHA256: - crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256); + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); break; case CKM_NSS_HMAC_CONSTANT_TIME: { sftk_MACConstantTimeCtx *ctx = sftk_HMACConstantTime_New(pMechanism,key); CK_ULONG *intpointer; if (ctx == NULL) { @@ -3109,20 +3166,20 @@ finish_rsa: crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_SSL3_SHA1_MAC: crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_TLS_PRF_GENERAL: - crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL); + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); break; case CKM_NSS_TLS_PRF_GENERAL_SHA256: - crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256); + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); break; default: crv = CKR_MECHANISM_INVALID; break; } if (crv != CKR_OK) { @@ -5916,22 +5973,23 @@ CK_ULONG tmpKeySize; CK_ULONG IVSize; CK_ULONG keySize = 0; CK_RV crv = CKR_OK; CK_BBOOL cktrue = CK_TRUE; CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; CK_OBJECT_CLASS classType = CKO_SECRET_KEY; CK_KEY_DERIVATION_STRING_DATA *stringPtr; + CK_MECHANISM_TYPE mechanism = pMechanism->mechanism; CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr; void *cipherInfo; PRBool isTLS = PR_FALSE; - PRBool isSHA256 = PR_FALSE; PRBool isDH = PR_FALSE; + HASH_HashType tlsPrfHash = HASH_AlgNULL; SECStatus rv; int i; unsigned int outLen; unsigned char sha_out[SHA1_LENGTH]; unsigned char key_block[NUM_MIXERS * MD5_LENGTH]; unsigned char key_block2[MD5_LENGTH]; unsigned char des3key[24]; PRBool isFIPS; @@ -5969,17 +6027,17 @@ } } if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } if (keySize == 0) { keySize = sftk_MapKeySize(keyType); } - switch (pMechanism->mechanism) { + switch (mechanism) { case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */ case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */ case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */ case CKM_NSS_JPAKE_ROUND2_SHA512: extractValue = PR_FALSE; classType = CKO_PRIVATE_KEY; break; case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ @@ -6017,39 +6075,57 @@ att = sftk_FindAttribute(sourceKey,CKA_VALUE); if (att == NULL) { sftk_FreeObject(key); sftk_FreeObject(sourceKey); return CKR_KEY_HANDLE_INVALID; } } - switch (pMechanism->mechanism) { + switch (mechanism) { /* * generate the master secret */ + case CKM_TLS12_MASTER_KEY_DERIVE: + case CKM_TLS12_MASTER_KEY_DERIVE_DH: case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: - isSHA256 = PR_TRUE; - /* fall thru */ case CKM_TLS_MASTER_KEY_DERIVE: case CKM_TLS_MASTER_KEY_DERIVE_DH: - isTLS = PR_TRUE; - /* fall thru */ case CKM_SSL3_MASTER_KEY_DERIVE: case CKM_SSL3_MASTER_KEY_DERIVE_DH: { CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; SSL3RSAPreMasterSecret * rsa_pms; unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; - if ((pMechanism->mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || - (pMechanism->mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || - (pMechanism->mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) - isDH = PR_TRUE; + if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) || + (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { + CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master = + (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *) pMechanism->pParameter; + tlsPrfHash = GetHashTypeFromMechanism(tls12_master->prfHashMechanism); + if (tlsPrfHash == HASH_AlgNULL) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) || + (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) { + tlsPrfHash = HASH_AlgSHA256; + } + + if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) && + (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) { + isTLS = PR_TRUE; + } + if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || + (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || + (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) || + (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { + isDH = PR_TRUE; + } /* first do the consistancy checks */ if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { crv = CKR_KEY_TYPE_INCONSISTENT; break; } att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != @@ -6106,18 +6182,18 @@ crsr.data = crsrdata; crsr.len = sizeof crsrdata; master.data = key_block; master.len = SSL3_MASTER_SECRET_LENGTH; pms.data = (unsigned char*)att->attrib.pValue; pms.len = att->attrib.ulValueLen; - if (isSHA256) { - status = TLS_P_hash(HASH_AlgSHA256, &pms, "master secret", + if (tlsPrfHash != HASH_AlgNULL) { + status = TLS_P_hash(tlsPrfHash, &pms, "master secret", &crsr, &master, isFIPS); } else { status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); } if (status != SECSuccess) { crv = CKR_FUNCTION_FAILED; break; } @@ -6170,31 +6246,44 @@ if (crv != CKR_OK) break; /* While we're here, we might as well force this, too. */ crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL)); if (crv != CKR_OK) break; } break; } + case CKM_TLS12_KEY_AND_MAC_DERIVE: case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: - isSHA256 = PR_TRUE; - /* fall thru */ case CKM_TLS_KEY_AND_MAC_DERIVE: - isTLS = PR_TRUE; - /* fall thru */ case CKM_SSL3_KEY_AND_MAC_DERIVE: { CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; CK_SSL3_KEY_MAT_OUT * ssl3_keys_out; CK_ULONG effKeySize; unsigned int block_needed; unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; + if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) { + CK_TLS12_KEY_MAT_PARAMS *tls12_keys = + (CK_TLS12_KEY_MAT_PARAMS *) pMechanism->pParameter; + tlsPrfHash = GetHashTypeFromMechanism(tls12_keys->prfHashMechanism); + if (tlsPrfHash == HASH_AlgNULL) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) { + tlsPrfHash = HASH_AlgSHA256; + } + + if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) { + isTLS = PR_TRUE; + } + crv = sftk_DeriveSensitiveCheck(sourceKey,key); if (crv != CKR_OK) break; if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) { crv = CKR_KEY_FUNCTION_NOT_PERMITTED; break; } att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); @@ -6264,18 +6353,18 @@ srcr.data = srcrdata; srcr.len = sizeof srcrdata; keyblk.data = key_block; keyblk.len = block_needed; master.data = (unsigned char*)att->attrib.pValue; master.len = att->attrib.ulValueLen; - if (isSHA256) { - status = TLS_P_hash(HASH_AlgSHA256, &master, "key expansion", + if (tlsPrfHash != HASH_AlgNULL) { + status = TLS_P_hash(tlsPrfHash, &master, "key expansion", &srcr, &keyblk, isFIPS); } else { status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, isFIPS); } if (status != SECSuccess) { goto key_and_mac_derive_fail; } @@ -7011,17 +7100,17 @@ SEC_ASN1_GET(SEC_OctetStringTemplate), &ecPoint); if (rv != SECSuccess) { goto ec_loser; } ecPoint = newPoint; } - if (pMechanism->mechanism == CKM_ECDH1_COFACTOR_DERIVE) { + if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) { withCofactor = PR_TRUE; } else { /* When not using cofactor derivation, one should * validate the public key to avoid small subgroup * attacks. */ if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint) != SECSuccess) { diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h --- a/lib/softoken/pkcs11i.h +++ b/lib/softoken/pkcs11i.h @@ -25,6 +25,11 @@ * the expense of space. */ + +/* Was present in older nss-util, is missing in newer. Definition required to build. */ +#define CKM_TLS12_MAC 0x000003E5 + + /* * The attribute allocation strategy is static allocation: * Attributes are pre-allocated as part of the session object and used from @@ -733,13 +733,14 @@ void sftk_MACConstantTime_DestroyContext /**************************************** * implement TLS Pseudo Random Function (PRF) */ extern CK_RV sftk_TLSPRFInit(SFTKSessionContext *context, SFTKObject * key, CK_KEY_TYPE key_type, - HASH_HashType hash_alg); + HASH_HashType hash_alg, + unsigned int out_len); SEC_END_PROTOS #endif /* _PKCS11I_H_ */ diff --git a/lib/softoken/tlsprf.c b/lib/softoken/tlsprf.c --- a/lib/softoken/tlsprf.c +++ b/lib/softoken/tlsprf.c @@ -1,16 +1,17 @@ /* tlsprf.c - TLS Pseudo Random Function (PRF) implementation * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "pkcs11i.h" #include "blapi.h" +#include "secerr.h" #define SFTK_OFFSETOF(str, memb) ((PRPtrdiff)(&(((str *)0)->memb))) static void sftk_TLSPRFNull(void *data, PRBool freeit) { return; } @@ -18,16 +19,17 @@ typedef struct { PRUint32 cxSize; /* size of allocated block, in bytes. */ PRUint32 cxBufSize; /* sizeof buffer at cxBufPtr. */ unsigned char *cxBufPtr; /* points to real buffer, may be cxBuf. */ PRUint32 cxKeyLen; /* bytes of cxBufPtr containing key. */ PRUint32 cxDataLen; /* bytes of cxBufPtr containing data. */ SECStatus cxRv; /* records failure of void functions. */ PRBool cxIsFIPS; /* true if conforming to FIPS 198. */ HASH_HashType cxHashAlg; /* hash algorithm to use for TLS 1.2+ */ + unsigned int cxOutLen; /* bytes of output if nonzero */ unsigned char cxBuf[512]; /* actual size may be larger than 512. */ } TLSPRFContext; static void sftk_TLSPRFHashUpdate(TLSPRFContext *cx, const unsigned char *data, unsigned int data_len) { PRUint32 bytesUsed = cx->cxKeyLen + cx->cxDataLen; @@ -82,17 +84,24 @@ sftk_TLSPRFUpdate(TLSPRFContext *cx, secretItem.data = cx->cxBufPtr; secretItem.len = cx->cxKeyLen; seedItem.data = cx->cxBufPtr + cx->cxKeyLen; seedItem.len = cx->cxDataLen; sigItem.data = sig; - sigItem.len = maxLen; + if (cx->cxOutLen == 0) { + sigItem.len = maxLen; + } else if (cx->cxOutLen <= maxLen) { + sigItem.len = cx->cxOutLen; + } else { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + return SECFailure; + } if (cx->cxHashAlg != HASH_AlgNULL) { rv = TLS_P_hash(cx->cxHashAlg, &secretItem, NULL, &seedItem, &sigItem, cx->cxIsFIPS); } else { rv = TLS_PRF(&secretItem, NULL, &seedItem, &sigItem, cx->cxIsFIPS); } if (rv == SECSuccess && sigLen != NULL) @@ -137,17 +146,18 @@ sftk_TLSPRFHashDestroy(TLSPRFContext *cx PORT_ZFree(cx, cx->cxSize); } } CK_RV sftk_TLSPRFInit(SFTKSessionContext *context, SFTKObject * key, CK_KEY_TYPE key_type, - HASH_HashType hash_alg) + HASH_HashType hash_alg, + unsigned int out_len) { SFTKAttribute * keyVal; TLSPRFContext * prf_cx; CK_RV crv = CKR_HOST_MEMORY; PRUint32 keySize; PRUint32 blockSize; if (key_type != CKK_GENERIC_SECRET) @@ -164,16 +174,17 @@ sftk_TLSPRFInit(SFTKSessionContext *cont prf_cx->cxSize = blockSize; prf_cx->cxKeyLen = keySize; prf_cx->cxDataLen = 0; prf_cx->cxBufSize = blockSize - SFTK_OFFSETOF(TLSPRFContext, cxBuf); prf_cx->cxRv = SECSuccess; prf_cx->cxIsFIPS = (key->slot->slotID == FIPS_SLOT_ID); prf_cx->cxBufPtr = prf_cx->cxBuf; prf_cx->cxHashAlg = hash_alg; + prf_cx->cxOutLen = out_len; if (keySize) PORT_Memcpy(prf_cx->cxBufPtr, keyVal->attrib.pValue, keySize); context->hashInfo = (void *) prf_cx; context->cipherInfo = (void *) prf_cx; context->hashUpdate = (SFTKHash) sftk_TLSPRFHashUpdate; context->end = (SFTKEnd) sftk_TLSPRFEnd; context->update = (SFTKCipher) sftk_TLSPRFUpdate;