Blame SOURCES/nss-softokn-3.16-tls12-mechanisms.patch

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