Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: mozilla/security/nss/lib/softoken/pkcs11c.c

Issue 10961060: Update NSS to NSS 3.14 Beta 1. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Add the NSS snapshot timestamp to README.chromium and nss-checkout.sh Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mozilla/security/nss/lib/softoken/pkcs11.c ('k') | mozilla/security/nss/lib/softoken/pkcs11i.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mozilla/security/nss/lib/softoken/pkcs11c.c
===================================================================
--- mozilla/security/nss/lib/softoken/pkcs11c.c (revision 158129)
+++ mozilla/security/nss/lib/softoken/pkcs11c.c (working copy)
@@ -24,7 +24,6 @@
#include "pkcs11.h"
#include "pkcs11i.h"
#include "lowkeyi.h"
-#include "sechash.h"
#include "secder.h"
#include "secdig.h"
#include "lowpbe.h" /* We do PBE below */
@@ -2057,7 +2056,7 @@
context->update = (SFTKCipher) nsc_DSA_Sign_Stub;
context->destroy = (privKey == key->objectInfo) ?
(SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey;
- context->maxLen = DSA_SIGNATURE_LEN;
+ context->maxLen = DSA_MAX_SIGNATURE_LEN;
break;
@@ -2905,14 +2904,36 @@
return CKR_OK;
}
+
+/*
+ * this is coded for "full" support. These selections will be limitted to
+ * the official subset by freebl.
+ */
+static unsigned int
+sftk_GetSubPrimeFromPrime(unsigned int primeBits)
+{
+ if (primeBits <= 1024) {
+ return 160;
+ } else if (primeBits <= 2048) {
+ return 224;
+ } else if (primeBits <= 3072) {
+ return 256;
+ } else if (primeBits <= 7680) {
+ return 384;
+ } else {
+ return 512;
+ }
+}
+
static CK_RV
nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
{
SFTKAttribute *attribute;
CK_ULONG counter;
unsigned int seedBits = 0;
+ unsigned int subprimeBits = 0;
unsigned int primeBits;
- unsigned int j;
+ unsigned int j = 8; /* default to 1024 bits */
CK_RV crv = CKR_OK;
PQGParams *params = NULL;
PQGVerify *vfy = NULL;
@@ -2924,9 +2945,11 @@
}
primeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
sftk_FreeAttribute(attribute);
- j = PQG_PBITS_TO_INDEX(primeBits);
- if (j == (unsigned int)-1) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
+ if (primeBits < 1024) {
+ j = PQG_PBITS_TO_INDEX(primeBits);
+ if (j == (unsigned int)-1) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
}
attribute = sftk_FindAttribute(key, CKA_NETSCAPE_PQG_SEED_BITS);
@@ -2935,15 +2958,35 @@
sftk_FreeAttribute(attribute);
}
+ attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS);
+ if (attribute != NULL) {
+ subprimeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
+ sftk_FreeAttribute(attribute);
+ }
+
sftk_DeleteAttributeType(key,CKA_PRIME_BITS);
+ sftk_DeleteAttributeType(key,CKA_SUBPRIME_BITS);
sftk_DeleteAttributeType(key,CKA_NETSCAPE_PQG_SEED_BITS);
- if (seedBits == 0) {
- rv = PQG_ParamGen(j, &params, &vfy);
+ /* use the old PQG interface if we have old input data */
+ if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) {
+ if (seedBits == 0) {
+ rv = PQG_ParamGen(j, &params, &vfy);
+ } else {
+ rv = PQG_ParamGenSeedLen(j,seedBits/8, &params, &vfy);
+ }
} else {
- rv = PQG_ParamGenSeedLen(j,seedBits/8, &params, &vfy);
+ if (subprimeBits == 0) {
+ subprimeBits = sftk_GetSubPrimeFromPrime(primeBits);
+ }
+ if (seedBits == 0) {
+ seedBits = primeBits;
+ }
+ rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits/8, &params, &vfy);
}
+
+
if (rv != SECSuccess) {
if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
sftk_fatalError = PR_TRUE;
@@ -3459,6 +3502,7 @@
CK_MECHANISM mech = {0, NULL, 0};
CK_ULONG modulusLen;
+ CK_ULONG subPrimeLen;
PRBool isEncryptable = PR_FALSE;
PRBool canSignVerify = PR_FALSE;
PRBool isDerivable = PR_FALSE;
@@ -3472,10 +3516,12 @@
unsigned char *text_compared;
CK_ULONG bytes_encrypted;
CK_ULONG bytes_compared;
+ CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH;
/* Variables used for Signature/Verification functions. */
- /* always uses SHA-1 digest */
- unsigned char *known_digest = (unsigned char *)"Mozilla Rules World!";
+ /* Must be at least 256 bits for DSA2 digest */
+ unsigned char *known_digest = (unsigned char *)
+ "Mozilla Rules the World through NSS!";
unsigned char *signature;
CK_ULONG signature_length;
@@ -3492,6 +3538,19 @@
modulusLen--;
}
sftk_FreeAttribute(attribute);
+ } else if (keyType == CKK_DSA) {
+ SFTKAttribute *attribute;
+
+ /* Get subprime length of private key. */
+ attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME);
+ if (attribute == NULL) {
+ return CKR_DEVICE_ERROR;
+ }
+ subPrimeLen = attribute->attrib.ulValueLen;
+ if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) {
+ subPrimeLen--;
+ }
+ sftk_FreeAttribute(attribute);
}
/**************************************************/
@@ -3617,7 +3676,8 @@
mech.mechanism = CKM_RSA_PKCS;
break;
case CKK_DSA:
- signature_length = DSA_SIGNATURE_LEN;
+ signature_length = DSA_MAX_SIGNATURE_LEN;
+ pairwise_digest_length = subPrimeLen;
mech.mechanism = CKM_DSA;
break;
#ifdef NSS_ENABLE_ECC
@@ -3645,7 +3705,7 @@
crv = NSC_Sign(hSession,
known_digest,
- PAIRWISE_DIGEST_LENGTH,
+ pairwise_digest_length,
signature,
&signature_length);
if (crv != CKR_OK) {
@@ -3662,7 +3722,7 @@
crv = NSC_Verify(hSession,
known_digest,
- PAIRWISE_DIGEST_LENGTH,
+ pairwise_digest_length,
signature,
signature_length);
@@ -3945,9 +4005,12 @@
break;
}
+ /*
+ * these are checked by DSA_NewKey
+ */
bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
pqgParam.subPrime.len);
- if (bitSize != DSA_Q_BITS) {
+ if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) {
crv = CKR_TEMPLATE_INCOMPLETE;
PORT_Free(pqgParam.prime.data);
PORT_Free(pqgParam.subPrime.data);
@@ -3963,7 +4026,7 @@
break;
}
bitSize = sftk_GetLengthInBits(pqgParam.base.data,pqgParam.base.len);
- if ((bitSize < 1) || (bitSize > DSA_MAX_P_BITS)) {
+ if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) {
crv = CKR_TEMPLATE_INCOMPLETE;
PORT_Free(pqgParam.prime.data);
PORT_Free(pqgParam.subPrime.data);
@@ -5065,6 +5128,113 @@
return 0;
}
+/* Inputs:
+ * key_len: Length of derived key to be generated.
+ * SharedSecret: a shared secret that is the output of a key agreement primitive.
+ * SharedInfo: (Optional) some data shared by the entities computing the secret key.
+ * SharedInfoLen: the length in octets of SharedInfo
+ * Hash: The hash function to be used in the KDF
+ * HashLen: the length in octets of the output of Hash
+ * Output:
+ * key: Pointer to a buffer containing derived key, if return value is SECSuccess.
+ */
+static CK_RV sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret,
+ CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
+ SECStatus Hash(unsigned char *, const unsigned char *, uint32),
+ CK_ULONG HashLen)
+{
+ unsigned char *buffer = NULL, *output_buffer = NULL;
+ uint32 buffer_len, max_counter, i;
+ SECStatus rv;
+
+ /* Check that key_len isn't too long. The maximum key length could be
+ * greatly increased if the code below did not limit the 4-byte counter
+ * to a maximum value of 255. */
+ if (key_len > 254 * HashLen)
+ return SEC_ERROR_INVALID_ARGS;
+
+ if (SharedInfo == NULL)
+ SharedInfoLen = 0;
+
+ buffer_len = SharedSecret->len + 4 + SharedInfoLen;
+ buffer = (CK_BYTE *)PORT_Alloc(buffer_len);
+ if (buffer == NULL) {
+ rv = SEC_ERROR_NO_MEMORY;
+ goto loser;
+ }
+
+ max_counter = key_len/HashLen;
+ if (key_len > max_counter * HashLen)
+ max_counter++;
+
+ output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen);
+ if (output_buffer == NULL) {
+ rv = SEC_ERROR_NO_MEMORY;
+ goto loser;
+ }
+
+ /* Populate buffer with SharedSecret || Counter || [SharedInfo]
+ * where Counter is 0x00000001 */
+ PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len);
+ buffer[SharedSecret->len] = 0;
+ buffer[SharedSecret->len + 1] = 0;
+ buffer[SharedSecret->len + 2] = 0;
+ buffer[SharedSecret->len + 3] = 1;
+ if (SharedInfo) {
+ PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen);
+ }
+
+ for(i=0; i < max_counter; i++) {
+ rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len);
+ if (rv != SECSuccess)
+ goto loser;
+
+ /* Increment counter (assumes max_counter < 255) */
+ buffer[SharedSecret->len + 3]++;
+ }
+
+ PORT_ZFree(buffer, buffer_len);
+ if (key_len < max_counter * HashLen) {
+ PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len);
+ }
+ *key = output_buffer;
+
+ return SECSuccess;
+
+ loser:
+ if (buffer) {
+ PORT_ZFree(buffer, buffer_len);
+ }
+ if (output_buffer) {
+ PORT_ZFree(output_buffer, max_counter * HashLen);
+ }
+ return rv;
+}
+
+static CK_RV sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len,
+ SECItem *SharedSecret,
+ CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
+ CK_EC_KDF_TYPE kdf)
+{
+ if (kdf == CKD_SHA1_KDF)
+ return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
+ SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH);
+ else if (kdf == CKD_SHA224_KDF)
+ return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
+ SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH);
+ else if (kdf == CKD_SHA256_KDF)
+ return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
+ SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH);
+ else if (kdf == CKD_SHA384_KDF)
+ return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
+ SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH);
+ else if (kdf == CKD_SHA512_KDF)
+ return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
+ SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
+ else
+ return SEC_ERROR_INVALID_ALGORITHM;
+}
+
/*
* SSL Key generation given pre master secret
*/
@@ -5893,17 +6063,8 @@
crv = CKR_TEMPLATE_INCONSISTENT;
break;
}
- /* now allocate the hash contexts */
- md5 = MD5_NewContext();
- if (md5 == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- MD5_Begin(md5);
- MD5_Update(md5,(const unsigned char*)att->attrib.pValue,
+ MD5_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
att->attrib.ulValueLen);
- MD5_End(md5,key_block,&outLen,MD5_LENGTH);
- MD5_DestroyContext(md5, PR_TRUE);
crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize);
break;
@@ -5913,21 +6074,60 @@
crv = CKR_TEMPLATE_INCONSISTENT;
break;
}
- /* now allocate the hash contexts */
- sha = SHA1_NewContext();
- if (sha == NULL) {
- crv = CKR_HOST_MEMORY;
+ SHA1_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
+ att->attrib.ulValueLen);
+
+ crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
+ break;
+
+ case CKM_SHA224_KEY_DERIVATION:
+ if (keySize == 0) keySize = SHA224_LENGTH;
+ if (keySize > SHA224_LENGTH) {
+ crv = CKR_TEMPLATE_INCONSISTENT;
break;
}
- SHA1_Begin(sha);
- SHA1_Update(sha,(const unsigned char*)att->attrib.pValue,
+ SHA224_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
att->attrib.ulValueLen);
- SHA1_End(sha,key_block,&outLen,SHA1_LENGTH);
- SHA1_DestroyContext(sha, PR_TRUE);
crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
break;
+ case CKM_SHA256_KEY_DERIVATION:
+ if (keySize == 0) keySize = SHA256_LENGTH;
+ if (keySize > SHA256_LENGTH) {
+ crv = CKR_TEMPLATE_INCONSISTENT;
+ break;
+ }
+ SHA256_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
+ att->attrib.ulValueLen);
+
+ crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
+ break;
+
+ case CKM_SHA384_KEY_DERIVATION:
+ if (keySize == 0) keySize = SHA384_LENGTH;
+ if (keySize > SHA384_LENGTH) {
+ crv = CKR_TEMPLATE_INCONSISTENT;
+ break;
+ }
+ SHA384_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
+ att->attrib.ulValueLen);
+
+ crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
+ break;
+
+ case CKM_SHA512_KEY_DERIVATION:
+ if (keySize == 0) keySize = SHA512_LENGTH;
+ if (keySize > SHA512_LENGTH) {
+ crv = CKR_TEMPLATE_INCONSISTENT;
+ break;
+ }
+ SHA512_HashBuf(key_block,(const unsigned char*)att->attrib.pValue,
+ att->attrib.ulValueLen);
+
+ crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize);
+ break;
+
case CKM_DH_PKCS_DERIVE:
{
SECItem derived, dhPublic;
@@ -5967,7 +6167,6 @@
SECItem ecScalar, ecPoint;
SECItem tmp;
PRBool withCofactor = PR_FALSE;
- unsigned char secret_hash[20];
unsigned char *secret;
unsigned char *keyData = NULL;
int secretlen, curveLen, pubKeyLen;
@@ -6053,28 +6252,30 @@
break;
}
- /*
- * tmp is the raw data created by ECDH_Derive,
- * secret and secretlen are the values we will eventually pass as our
- * generated key.
- */
- secret = tmp.data;
- secretlen = tmp.len;
/*
* apply the kdf function.
*/
- if (mechParams->kdf == CKD_SHA1_KDF) {
- /* Compute SHA1 hash */
- PORT_Memset(secret_hash, 0, 20);
- rv = SHA1_HashBuf(secret_hash, tmp.data, tmp.len);
+ if (mechParams->kdf == CKD_NULL) {
+ /*
+ * tmp is the raw data created by ECDH_Derive,
+ * secret and secretlen are the values we will
+ * eventually pass as our generated key.
+ */
+ secret = tmp.data;
+ secretlen = tmp.len;
+ } else {
+ secretlen = keySize;
+ rv = sftk_ANSI_X9_63_kdf(&secret, keySize,
+ &tmp, mechParams->pSharedData,
+ mechParams->ulSharedDataLen, mechParams->kdf);
+ PORT_ZFree(tmp.data, tmp.len);
if (rv != SECSuccess) {
- PORT_ZFree(tmp.data, tmp.len);
crv = CKR_HOST_MEMORY;
break;
- }
- secret = secret_hash;
- secretlen = 20;
+ }
+ tmp.data = secret;
+ tmp.len = secretlen;
}
/*
@@ -6105,8 +6306,6 @@
if (keyData) {
PORT_ZFree(keyData, keySize);
}
- PORT_Memset(secret_hash, 0, 20);
-
break;
ec_loser:
« no previous file with comments | « mozilla/security/nss/lib/softoken/pkcs11.c ('k') | mozilla/security/nss/lib/softoken/pkcs11i.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698