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;