diff options
Diffstat (limited to 'security/nss')
-rw-r--r-- | security/nss/lib/cryptohi/seckey.c | 5 | ||||
-rw-r--r-- | security/nss/lib/freebl/dh.c | 3 | ||||
-rw-r--r-- | security/nss/lib/freebl/ec.c | 14 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/ecp_25519.c | 3 | ||||
-rw-r--r-- | security/nss/lib/nss/nss.h | 4 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11akey.c | 20 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11cert.c | 4 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11pk12.c | 13 | ||||
-rw-r--r-- | security/nss/lib/softoken/legacydb/keydb.c | 33 | ||||
-rw-r--r-- | security/nss/lib/softoken/legacydb/lgattr.c | 6 | ||||
-rw-r--r-- | security/nss/lib/softoken/lgglue.c | 12 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11.c | 4 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11c.c | 2 | ||||
-rw-r--r-- | security/nss/lib/softoken/sftkdb.c | 4 | ||||
-rw-r--r-- | security/nss/lib/softoken/sftkdb.h | 1 | ||||
-rw-r--r-- | security/nss/lib/softoken/sftkdbti.h | 7 | ||||
-rw-r--r-- | security/nss/lib/softoken/sftkpwd.c | 193 | ||||
-rw-r--r-- | security/nss/lib/softoken/softkver.h | 4 | ||||
-rw-r--r-- | security/nss/lib/ssl/ssl3con.c | 20 | ||||
-rw-r--r-- | security/nss/lib/util/nssutil.h | 4 | ||||
-rw-r--r-- | security/nss/lib/util/quickder.c | 7 |
21 files changed, 289 insertions, 74 deletions
diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c index 080909772..173096050 100644 --- a/security/nss/lib/cryptohi/seckey.c +++ b/security/nss/lib/cryptohi/seckey.c @@ -639,6 +639,11 @@ seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki) return pubk; break; case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + /* A basic sanity check on inputs. */ + if (spki->algorithm.parameters.len == 0 || newOs.len == 0) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + break; + } pubk->keyType = ecKey; pubk->u.ec.size = 0; diff --git a/security/nss/lib/freebl/dh.c b/security/nss/lib/freebl/dh.c index 6f2bafda2..b2d6d7430 100644 --- a/security/nss/lib/freebl/dh.c +++ b/security/nss/lib/freebl/dh.c @@ -210,7 +210,8 @@ DH_Derive(SECItem *publicValue, unsigned int len = 0; unsigned int nb; unsigned char *secret = NULL; - if (!publicValue || !prime || !privateValue || !derivedSecret) { + if (!publicValue || !publicValue->len || !prime || !prime->len || + !privateValue || !privateValue->len || !derivedSecret) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } diff --git a/security/nss/lib/freebl/ec.c b/security/nss/lib/freebl/ec.c index 6468a10d6..ddbcc2340 100644 --- a/security/nss/lib/freebl/ec.c +++ b/security/nss/lib/freebl/ec.c @@ -202,8 +202,8 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, #endif MP_DIGITS(&k) = 0; - if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0) || - !ecParams->name) { + if (!ecParams || ecParams->name == ECCurve_noName || + !privKey || !privKeyBytes || privKeyLen <= 0) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -391,7 +391,7 @@ EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey) int len; unsigned char *privKeyBytes = NULL; - if (!ecParams) { + if (!ecParams || ecParams->name == ECCurve_noName || !privKey) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -430,7 +430,8 @@ EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue) mp_err err = MP_OKAY; int len; - if (!ecParams || !publicValue || !ecParams->name) { + if (!ecParams || ecParams->name == ECCurve_noName || + !publicValue || !publicValue->len) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -536,8 +537,9 @@ ECDH_Derive(SECItem *publicValue, int i; #endif - if (!publicValue || !ecParams || !privateValue || !derivedSecret || - !ecParams->name) { + if (!publicValue || !publicValue->len || + !ecParams || ecParams->name == ECCurve_noName || + !privateValue || !privateValue->len || !derivedSecret) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } diff --git a/security/nss/lib/freebl/ecl/ecp_25519.c b/security/nss/lib/freebl/ecl/ecp_25519.c index 38bd34c50..7b331b28f 100644 --- a/security/nss/lib/freebl/ecl/ecp_25519.c +++ b/security/nss/lib/freebl/ecl/ecp_25519.c @@ -114,6 +114,9 @@ ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P) } px = P->data; } + if (k->len != 32) { + return SECFailure; + } SECStatus rv = ec_Curve25519_mul(X->data, k->data, px); if (NSS_SecureMemcmpZero(X->data, X->len) == 0) { diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 49c545ecc..ea54ce0cd 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -22,10 +22,10 @@ * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]" */ -#define NSS_VERSION "3.41" _NSS_CUSTOMIZED +#define NSS_VERSION "3.41.2" _NSS_CUSTOMIZED #define NSS_VMAJOR 3 #define NSS_VMINOR 41 -#define NSS_VPATCH 0 +#define NSS_VPATCH 2 #define NSS_VBUILD 0 #define NSS_BETA PR_FALSE diff --git a/security/nss/lib/pk11wrap/pk11akey.c b/security/nss/lib/pk11wrap/pk11akey.c index c6070e264..9a914272d 100644 --- a/security/nss/lib/pk11wrap/pk11akey.c +++ b/security/nss/lib/pk11wrap/pk11akey.c @@ -190,7 +190,6 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, attrs++; PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); attrs++; - signedattr = attrs; PK11_SETATTRS(attrs, CKA_EC_PARAMS, pubKey->u.ec.DEREncodedParams.data, pubKey->u.ec.DEREncodedParams.len); @@ -224,10 +223,13 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, } templateCount = attrs - theTemplate; - signedcount = attrs - signedattr; PORT_Assert(templateCount <= (sizeof(theTemplate) / sizeof(CK_ATTRIBUTE))); - for (attrs = signedattr; signedcount; attrs++, signedcount--) { - pk11_SignedToUnsigned(attrs); + if (pubKey->keyType != ecKey) { + PORT_Assert(signedattr); + signedcount = attrs - signedattr; + for (attrs = signedattr; signedcount; attrs++, signedcount--) { + pk11_SignedToUnsigned(attrs); + } } rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate, templateCount, isToken, &objectID); @@ -1074,9 +1076,13 @@ pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot, SECKEYPrivateKey *privKey, &cktrue, &ckfalse); /* Not everyone can handle zero padded key values, give - * them the raw data as unsigned */ - for (ap = attrs; extra_count; ap++, extra_count--) { - pk11_SignedToUnsigned(ap); + * them the raw data as unsigned. The exception is EC, + * where the values are encoded or zero-preserving + * per-RFC5915 */ + if (privKey->keyType != ecKey) { + for (ap = attrs; extra_count; ap++, extra_count--) { + pk11_SignedToUnsigned(ap); + } } /* now Store the puppies */ diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index 819769643..a880b1ab8 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -184,7 +184,9 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, SECKEY_DestroyPublicKey(pubKey); return PR_FALSE; } - pk11_SignedToUnsigned(&theTemplate); + if (pubKey->keyType != ecKey) { + pk11_SignedToUnsigned(&theTemplate); + } if (pk11_FindObjectByTemplate(slot, &theTemplate, 1) != CK_INVALID_HANDLE) { SECKEY_DestroyPublicKey(pubKey); return PR_TRUE; diff --git a/security/nss/lib/pk11wrap/pk11pk12.c b/security/nss/lib/pk11wrap/pk11pk12.c index 47b6702c6..9888ace69 100644 --- a/security/nss/lib/pk11wrap/pk11pk12.c +++ b/security/nss/lib/pk11wrap/pk11pk12.c @@ -505,7 +505,7 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, } PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len); attrs++; - signedattr = attrs; + /* No signed attrs for EC */ /* curveOID always is a copy of AlgorithmID.parameters. */ PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data, lpk->u.ec.curveOID.len); @@ -523,11 +523,12 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, } templateCount = attrs - theTemplate; PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE)); - PORT_Assert(signedattr != NULL); - signedcount = attrs - signedattr; - - for (ap = signedattr; signedcount; ap++, signedcount--) { - pk11_SignedToUnsigned(ap); + if (lpk->keyType != ecKey) { + PORT_Assert(signedattr); + signedcount = attrs - signedattr; + for (ap = signedattr; signedcount; ap++, signedcount--) { + pk11_SignedToUnsigned(ap); + } } rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, diff --git a/security/nss/lib/softoken/legacydb/keydb.c b/security/nss/lib/softoken/legacydb/keydb.c index b4aa7754b..c8c4d07ba 100644 --- a/security/nss/lib/softoken/legacydb/keydb.c +++ b/security/nss/lib/softoken/legacydb/keydb.c @@ -1213,6 +1213,8 @@ nsslowkey_EncodePW(SECOidTag alg, const SECItem *salt, SECItem *data) unsigned char one = 1; SECItem *epw = NULL; SECItem *encParam; + int iterLen = 0; + int saltLen; SECStatus rv; param.salt = *salt; @@ -1221,6 +1223,17 @@ nsslowkey_EncodePW(SECOidTag alg, const SECItem *salt, SECItem *data) param.iter.len = 1; edi.encryptedData = *data; + iterLen = salt->len > 1 ? salt->data[salt->len - 1] : 2; + saltLen = (salt->len - iterLen) - 1; + /* if the resulting saltLen is a sha hash length, then assume that + * the iteration count is tacked on the end of the buffer */ + if ((saltLen == SHA1_LENGTH) || (saltLen == SHA256_LENGTH) || (saltLen == SHA384_LENGTH) || (saltLen == SHA224_LENGTH) || + (saltLen == SHA512_LENGTH)) { + param.iter.data = &salt->data[saltLen]; + param.iter.len = iterLen; + param.salt.len = saltLen; + } + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { return NULL; @@ -1270,9 +1283,23 @@ nsslowkey_DecodePW(const SECItem *derData, SECOidTag *alg, SECItem *salt) if (rv != SECSuccess) { goto loser; } - rv = SECITEM_CopyItem(NULL, salt, ¶m.salt); - if (rv != SECSuccess) { - goto loser; + /* if the iteration count isn't one, tack it at the end of the salt */ + if (!((param.iter.len == 1) && (param.iter.data[0] == 1))) { + int total_len = param.salt.len + param.iter.len + 1; + salt->data = PORT_Alloc(total_len); + if (salt->data == NULL) { + goto loser; + } + PORT_Memcpy(salt->data, param.salt.data, param.salt.len); + PORT_Memcpy(&salt->data[param.salt.len], param.iter.data, + param.iter.len); + salt->data[total_len - 1] = param.iter.len; + salt->len = total_len; + } else { + rv = SECITEM_CopyItem(NULL, salt, ¶m.salt); + if (rv != SECSuccess) { + goto loser; + } } pwe = SECITEM_DupItem(&edi.encryptedData); diff --git a/security/nss/lib/softoken/legacydb/lgattr.c b/security/nss/lib/softoken/legacydb/lgattr.c index 542b0c968..3d77bd056 100644 --- a/security/nss/lib/softoken/legacydb/lgattr.c +++ b/security/nss/lib/softoken/legacydb/lgattr.c @@ -950,9 +950,9 @@ lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, case CKA_UNWRAP: return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); case CKA_VALUE: - return lg_CopyPrivAttrSigned(attribute, type, - key->u.ec.privateValue.data, - key->u.ec.privateValue.len, sdbpw); + return lg_CopyPrivAttribute(attribute, type, + key->u.ec.privateValue.data, + key->u.ec.privateValue.len, sdbpw); case CKA_EC_PARAMS: return lg_CopyAttributeSigned(attribute, type, key->u.ec.ecParams.DEREncoding.data, diff --git a/security/nss/lib/softoken/lgglue.c b/security/nss/lib/softoken/lgglue.c index 94f054129..67f17943b 100644 --- a/security/nss/lib/softoken/lgglue.c +++ b/security/nss/lib/softoken/lgglue.c @@ -171,6 +171,8 @@ sftkdb_encrypt_stub(PLArenaPool *arena, SDB *sdb, SECItem *plainText, { SFTKDBHandle *handle = sdb->app_private; SECStatus rv; + SECItem *key; + int iterationCount; if (handle == NULL) { return SECFailure; @@ -192,9 +194,15 @@ sftkdb_encrypt_stub(PLArenaPool *arena, SDB *sdb, SECItem *plainText, /* PORT_SetError */ return SECFailure; } + if (handle->newKey) { + key = handle->newKey; + iterationCount = handle->newDefaultIterationCount; + } else { + key = &handle->passwordKey; + iterationCount = handle->defaultIterationCount; + } - rv = sftkdb_EncryptAttribute(arena, - handle->newKey ? handle->newKey : &handle->passwordKey, + rv = sftkdb_EncryptAttribute(arena, key, iterationCount, plainText, cipherText); PZ_Unlock(handle->passwordLock); diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 34f25a9d0..7dd4f7ee9 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -617,7 +617,7 @@ sftk_hasNullPassword(SFTKSlot *slot, SFTKDBHandle *keydb) pwenabled = PR_FALSE; if (sftkdb_HasPasswordSet(keydb) == SECSuccess) { PRBool tokenRemoved = PR_FALSE; - SECStatus rv = sftkdb_CheckPassword(keydb, "", &tokenRemoved); + SECStatus rv = sftkdb_CheckPasswordNull(keydb, &tokenRemoved); if (tokenRemoved) { sftk_CloseAllSessions(slot, PR_FALSE); } @@ -3812,7 +3812,7 @@ NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, PZ_Unlock(slot->slotLock); tokenRemoved = PR_FALSE; - rv = sftkdb_CheckPassword(handle, "", &tokenRemoved); + rv = sftkdb_CheckPasswordNull(handle, &tokenRemoved); if (tokenRemoved) { sftk_CloseAllSessions(slot, PR_FALSE); } diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index 7eec3d7ee..884702cc1 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -7568,7 +7568,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession, rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, withCofactor, &tmp); - PORT_Free(ecScalar.data); + PORT_ZFree(ecScalar.data, ecScalar.len); ecScalar.data = NULL; if (privKey != sourceKey->objectInfo) { nsslowkey_DestroyPrivateKey(privKey); diff --git a/security/nss/lib/softoken/sftkdb.c b/security/nss/lib/softoken/sftkdb.c index 409c910f4..21796bbbb 100644 --- a/security/nss/lib/softoken/sftkdb.c +++ b/security/nss/lib/softoken/sftkdb.c @@ -530,6 +530,7 @@ sftk_signTemplate(PLArenaPool *arena, SFTKDBHandle *handle, goto loser; } rv = sftkdb_SignAttribute(arena, &keyHandle->passwordKey, + keyHandle->defaultIterationCount, objectID, template[i].type, &plainText, &signText); PZ_Unlock(keyHandle->passwordLock); @@ -663,6 +664,7 @@ sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object, break; } rv = sftkdb_EncryptAttribute(arena, &handle->passwordKey, + handle->defaultIterationCount, &plainText, &cipherText); PZ_Unlock(handle->passwordLock); if (rv == SECSuccess) { @@ -2759,7 +2761,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix, (sftkdb_HasPasswordSet(*keyDB) == SECSuccess) ? PR_TRUE : PR_FALSE; /* if the password on the key db is NULL, kick off our update * chain of events */ - sftkdb_CheckPassword((*keyDB), "", &tokenRemoved); + sftkdb_CheckPasswordNull((*keyDB), &tokenRemoved); } else { /* we don't have a key DB, update the certificate DB now */ sftkdb_Update(*certDB, NULL); diff --git a/security/nss/lib/softoken/sftkdb.h b/security/nss/lib/softoken/sftkdb.h index a47c89670..e30f3a237 100644 --- a/security/nss/lib/softoken/sftkdb.h +++ b/security/nss/lib/softoken/sftkdb.h @@ -25,6 +25,7 @@ CK_RV sftkdb_closeDB(SFTKDBHandle *handle); SECStatus sftkdb_PWIsInitialized(SFTKDBHandle *keydb); SECStatus sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved); +SECStatus sftkdb_CheckPasswordNull(SFTKDBHandle *keydb, PRBool *tokenRemoved); SECStatus sftkdb_PWCached(SFTKDBHandle *keydb); SECStatus sftkdb_HasPasswordSet(SFTKDBHandle *keydb); SECStatus sftkdb_ResetKeyDB(SFTKDBHandle *keydb); diff --git a/security/nss/lib/softoken/sftkdbti.h b/security/nss/lib/softoken/sftkdbti.h index 7b1db4560..22655de56 100644 --- a/security/nss/lib/softoken/sftkdbti.h +++ b/security/nss/lib/softoken/sftkdbti.h @@ -13,7 +13,9 @@ struct SFTKDBHandleStr { PRInt32 ref; CK_OBJECT_HANDLE type; SECItem passwordKey; + int defaultIterationCount; SECItem *newKey; + int newDefaultIterationCount; SECItem *oldKey; SECItem *updatePasswordKey; PZLock *passwordLock; @@ -39,9 +41,10 @@ struct SFTKDBHandleStr { SECStatus sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText, SECItem **plainText); SECStatus sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey, - SECItem *plainText, SECItem **cipherText); + int iterationCount, SECItem *plainText, + SECItem **cipherText); SECStatus sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey, - CK_OBJECT_HANDLE objectID, + int iterationCount, CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE attrType, SECItem *plainText, SECItem **sigText); SECStatus sftkdb_VerifyAttribute(SECItem *passKey, diff --git a/security/nss/lib/softoken/sftkpwd.c b/security/nss/lib/softoken/sftkpwd.c index 9834d3ba0..b6d098a07 100644 --- a/security/nss/lib/softoken/sftkpwd.c +++ b/security/nss/lib/softoken/sftkpwd.c @@ -34,6 +34,14 @@ #include "secerr.h" #include "softoken.h" +const int NSS_DEFAULT_ITERATION_COUNT = +#ifdef DEBUG + 25 +#else + 500 +#endif + ; + /****************************************************************** * * Key DB password handling functions @@ -132,7 +140,7 @@ const SEC_ASN1Template sftkdb_EncryptedDataInfoTemplate[] = { * to data in cipherText, if cipherText is freed, cipherValue will be invalid. */ static SECStatus -sftkdb_decodeCipherText(SECItem *cipherText, sftkCipherValue *cipherValue) +sftkdb_decodeCipherText(const SECItem *cipherText, sftkCipherValue *cipherValue) { PLArenaPool *arena = NULL; SFTKDBEncryptedDataInfo edi; @@ -225,7 +233,8 @@ loser: * with SECITEM_FreeItem by the caller. */ SECStatus -sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText, SECItem **plain) +sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText, + SECItem **plain) { SECStatus rv; sftkCipherValue cipherValue; @@ -261,7 +270,8 @@ loser: */ SECStatus sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey, - SECItem *plainText, SECItem **cipherText) + int iterationCount, SECItem *plainText, + SECItem **cipherText) { SECStatus rv; sftkCipherValue cipherValue; @@ -275,7 +285,7 @@ sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey, RNG_GenerateGlobalRandomBytes(saltData, cipherValue.salt.len); param = nsspkcs5_NewParam(cipherValue.alg, HASH_AlgSHA1, &cipherValue.salt, - 1); + iterationCount); if (param == NULL) { rv = SECFailure; goto loser; @@ -413,7 +423,8 @@ loser: */ SECStatus sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey, - CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE attrType, + int iterationCount, CK_OBJECT_HANDLE objectID, + CK_ATTRIBUTE_TYPE attrType, SECItem *plainText, SECItem **signature) { SECStatus rv; @@ -446,7 +457,8 @@ sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey, RNG_GenerateGlobalRandomBytes(saltData, prfLength); /* initialize our pkcs5 parameter */ - param = nsspkcs5_NewParam(signValue.alg, HASH_AlgSHA1, &signValue.salt, 1); + param = nsspkcs5_NewParam(signValue.alg, HASH_AlgSHA1, &signValue.salt, + iterationCount); if (param == NULL) { rv = SECFailure; goto loser; @@ -491,7 +503,7 @@ loser: * and sftkdb_DecryptAttribute calls. */ static void -sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey) +sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey, int iterationCount) { unsigned char *data; int len; @@ -507,6 +519,7 @@ sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey) len = keydb->passwordKey.len; keydb->passwordKey.data = passKey->data; keydb->passwordKey.len = passKey->len; + keydb->defaultIterationCount = iterationCount; passKey->data = data; passKey->len = len; SKIP_AFTER_FORK(PZ_Unlock(keydb->passwordLock)); @@ -660,6 +673,90 @@ sftkdb_HasPasswordSet(SFTKDBHandle *keydb) return (crv == CKR_OK) ? SECSuccess : SECFailure; } +/* pull out the common final part of checking a password */ +SECStatus +sftkdb_finishPasswordCheck(SFTKDBHandle *keydb, SECItem *key, + const char *pw, SECItem *value, + PRBool *tokenRemoved); + +/* + * check to see if we have the NULL password set. + * We special case the NULL password so that if you have no password set, you + * don't do thousands of hash rounds. This allows us to startup and get + * webpages without slowdown in normal mode. + */ +SECStatus +sftkdb_CheckPasswordNull(SFTKDBHandle *keydb, PRBool *tokenRemoved) +{ + /* just like sftkdb_CheckPassowd, we get the salt and value, and + * create a dbkey */ + SECStatus rv; + SECItem salt, value; + unsigned char saltData[SDB_MAX_META_DATA_LEN]; + unsigned char valueData[SDB_MAX_META_DATA_LEN]; + SECItem key; + SDB *db; + CK_RV crv; + sftkCipherValue cipherValue; + + cipherValue.param = NULL; + cipherValue.arena = NULL; + + if (keydb == NULL) { + return SECFailure; + } + + db = sftk_getPWSDB(keydb); + if (db == NULL) { + return SECFailure; + } + + key.data = NULL; + key.len = 0; + + /* get the entry from the database */ + salt.data = saltData; + salt.len = sizeof(saltData); + value.data = valueData; + value.len = sizeof(valueData); + crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value); + if (crv != CKR_OK) { + rv = SECFailure; + goto done; + } + + /* get our intermediate key based on the entry salt value */ + rv = sftkdb_passwordToKey(keydb, &salt, "", &key); + if (rv != SECSuccess) { + goto done; + } + + /* First get the cipher type */ + rv = sftkdb_decodeCipherText(&value, &cipherValue); + if (rv != SECSuccess) { + goto done; + } + + if (cipherValue.param->iter != 1) { + rv = SECFailure; + goto done; + } + + rv = sftkdb_finishPasswordCheck(keydb, &key, "", &value, tokenRemoved); + +done: + if (key.data) { + PORT_ZFree(key.data, key.len); + } + if (cipherValue.param) { + nsspkcs5_DestroyPBEParameter(cipherValue.param); + } + if (cipherValue.arena) { + PORT_FreeArena(cipherValue.arena, PR_FALSE); + } + return rv; +} + #define SFTK_PW_CHECK_STRING "password-check" #define SFTK_PW_CHECK_LEN 14 @@ -674,7 +771,6 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved) unsigned char saltData[SDB_MAX_META_DATA_LEN]; unsigned char valueData[SDB_MAX_META_DATA_LEN]; SECItem key; - SECItem *result = NULL; SDB *db; CK_RV crv; @@ -710,8 +806,30 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved) goto done; } + rv = sftkdb_finishPasswordCheck(keydb, &key, pw, &value, tokenRemoved); + +done: + if (key.data) { + PORT_ZFree(key.data, key.len); + } + return rv; +} + +/* we need to pass iterationCount in case we are updating a new database + * and from an old one. */ +SECStatus +sftkdb_finishPasswordCheck(SFTKDBHandle *keydb, SECItem *key, const char *pw, + SECItem *value, PRBool *tokenRemoved) +{ + SECItem *result = NULL; + SECStatus rv; + int iterationCount = NSS_DEFAULT_ITERATION_COUNT; + + if (*pw == 0) { + iterationCount = 1; + } /* decrypt the entry value */ - rv = sftkdb_DecryptAttribute(&key, &value, &result); + rv = sftkdb_DecryptAttribute(key, value, &result); if (rv != SECSuccess) { goto done; } @@ -752,7 +870,7 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved) * as well as changing which database is returned from * SFTK_GET_PW_DB (thus effecting both sftkdb_CheckPassword() * and sftkdb_HasPasswordSet()) */ - keydb->updatePasswordKey = SECITEM_DupItem(&key); + keydb->updatePasswordKey = SECITEM_DupItem(key); PZ_Unlock(keydb->passwordLock); if (keydb->updatePasswordKey == NULL) { /* PORT_Error set by SECITEM_DupItem */ @@ -787,7 +905,7 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved) * are good to go */ goto done; } - sftkdb_CheckPassword(keydb, "", tokenRemoved); + sftkdb_CheckPasswordNull(keydb, tokenRemoved); /* * Important 'NULL' code here. At this point either we @@ -821,15 +939,15 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved) PZ_Unlock(keydb->passwordLock); } /* load the keys, so the keydb can parse it's key set */ - sftkdb_switchKeys(keydb, &key); + sftkdb_switchKeys(keydb, key, iterationCount); /* we need to update, do it now */ if (((keydb->db->sdb_flags & SDB_RDONLY) == 0) && keydb->update) { /* update the peer certdb if it exists */ if (keydb->peerDB) { - sftkdb_Update(keydb->peerDB, &key); + sftkdb_Update(keydb->peerDB, key); } - sftkdb_Update(keydb, &key); + sftkdb_Update(keydb, key); } } else { rv = SECFailure; @@ -837,9 +955,6 @@ sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved) } done: - if (key.data) { - PORT_ZFree(key.data, key.len); - } if (result) { SECITEM_FreeItem(result, PR_TRUE); } @@ -857,7 +972,7 @@ sftkdb_PWCached(SFTKDBHandle *keydb) static CK_RV sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle, - CK_OBJECT_HANDLE id, SECItem *newKey) + CK_OBJECT_HANDLE id, SECItem *newKey, int iterationCount) { CK_ATTRIBUTE authAttrs[] = { { CKA_MODULUS, NULL, 0 }, @@ -937,7 +1052,7 @@ sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle, plainText.data = authAttrs[i].pValue; plainText.len = authAttrs[i].ulValueLen; - rv = sftkdb_SignAttribute(arena, newKey, id, + rv = sftkdb_SignAttribute(arena, newKey, iterationCount, id, authAttrs[i].type, &plainText, &signText); if (rv != SECSuccess) { return CKR_GENERAL_ERROR; @@ -954,7 +1069,7 @@ sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle, static CK_RV sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb, - CK_OBJECT_HANDLE id, SECItem *newKey) + CK_OBJECT_HANDLE id, SECItem *newKey, int iterationCount) { CK_RV crv = CKR_OK; CK_RV crv2; @@ -1041,7 +1156,8 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb, plainText.data = first[i].pValue; plainText.len = first[i].ulValueLen; - rv = sftkdb_EncryptAttribute(arena, newKey, &plainText, &result); + rv = sftkdb_EncryptAttribute(arena, newKey, iterationCount, + &plainText, &result); if (rv != SECSuccess) { return CKR_GENERAL_ERROR; } @@ -1056,6 +1172,7 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb, */ id &= SFTK_OBJ_ID_MASK; keydb->newKey = newKey; + keydb->newDefaultIterationCount = iterationCount; crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, id, first, count); keydb->newKey = NULL; @@ -1063,8 +1180,8 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb, } static CK_RV -sftk_convertAttributes(SFTKDBHandle *handle, - CK_OBJECT_HANDLE id, SECItem *newKey) +sftk_convertAttributes(SFTKDBHandle *handle, CK_OBJECT_HANDLE id, + SECItem *newKey, int iterationCount) { CK_RV crv = CKR_OK; PLArenaPool *arena = NULL; @@ -1078,13 +1195,14 @@ sftk_convertAttributes(SFTKDBHandle *handle, /* * first handle the MACS */ - crv = sftk_updateMacs(arena, handle, id, newKey); + crv = sftk_updateMacs(arena, handle, id, newKey, iterationCount); if (crv != CKR_OK) { goto loser; } if (handle->type == SFTK_KEYDB_TYPE) { - crv = sftk_updateEncrypted(arena, handle, id, newKey); + crv = sftk_updateEncrypted(arena, handle, id, newKey, + iterationCount); if (crv != CKR_OK) { goto loser; } @@ -1106,7 +1224,7 @@ loser: */ CK_RV sftkdb_convertObjects(SFTKDBHandle *handle, CK_ATTRIBUTE *template, - CK_ULONG count, SECItem *newKey) + CK_ULONG count, SECItem *newKey, int iterationCount) { SDBFind *find = NULL; CK_ULONG idCount = SFTK_MAX_IDS; @@ -1122,7 +1240,8 @@ sftkdb_convertObjects(SFTKDBHandle *handle, CK_ATTRIBUTE *template, while ((crv == CKR_OK) && (idCount == SFTK_MAX_IDS)) { crv = sftkdb_FindObjects(handle, find, ids, SFTK_MAX_IDS, &idCount); for (i = 0; (crv == CKR_OK) && (i < idCount); i++) { - crv = sftk_convertAttributes(handle, ids[i], newKey); + crv = sftk_convertAttributes(handle, ids[i], newKey, + iterationCount); } } crv2 = sftkdb_FindObjectsFinal(handle, find); @@ -1147,6 +1266,7 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb, SFTKDBHandle *certdb; unsigned char saltData[SDB_MAX_META_DATA_LEN]; unsigned char valueData[SDB_MAX_META_DATA_LEN]; + int iterationCount = NSS_DEFAULT_ITERATION_COUNT; CK_RV crv; SDB *db; @@ -1182,6 +1302,10 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb, RNG_GenerateGlobalRandomBytes(salt.data, salt.len); } + if (newPin && *newPin == 0) { + iterationCount = 1; + } + rv = sftkdb_passwordToKey(keydb, &salt, newPin, &newKey); if (rv != SECSuccess) { goto loser; @@ -1190,7 +1314,7 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb, /* * convert encrypted entries here. */ - crv = sftkdb_convertObjects(keydb, NULL, 0, &newKey); + crv = sftkdb_convertObjects(keydb, NULL, 0, &newKey, iterationCount); if (crv != CKR_OK) { rv = SECFailure; goto loser; @@ -1202,13 +1326,15 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb, CK_OBJECT_CLASS myClass = CKO_NETSCAPE_TRUST; objectType.pValue = &myClass; - crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey); + crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey, + iterationCount); if (crv != CKR_OK) { rv = SECFailure; goto loser; } myClass = CKO_PUBLIC_KEY; - crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey); + crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey, + iterationCount); if (crv != CKR_OK) { rv = SECFailure; goto loser; @@ -1218,7 +1344,8 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb, plainText.data = (unsigned char *)SFTK_PW_CHECK_STRING; plainText.len = SFTK_PW_CHECK_LEN; - rv = sftkdb_EncryptAttribute(NULL, &newKey, &plainText, &result); + rv = sftkdb_EncryptAttribute(NULL, &newKey, iterationCount, + &plainText, &result); if (rv != SECSuccess) { goto loser; } @@ -1237,7 +1364,7 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb, keydb->newKey = NULL; - sftkdb_switchKeys(keydb, &newKey); + sftkdb_switchKeys(keydb, &newKey, iterationCount); loser: if (newKey.data) { @@ -1262,7 +1389,7 @@ sftkdb_ClearPassword(SFTKDBHandle *keydb) SECItem oldKey; oldKey.data = NULL; oldKey.len = 0; - sftkdb_switchKeys(keydb, &oldKey); + sftkdb_switchKeys(keydb, &oldKey, 1); if (oldKey.data) { PORT_ZFree(oldKey.data, oldKey.len); } diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h index c1f63d769..73a38b010 100644 --- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -17,10 +17,10 @@ * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]" */ -#define SOFTOKEN_VERSION "3.41" SOFTOKEN_ECC_STRING +#define SOFTOKEN_VERSION "3.41.2" SOFTOKEN_ECC_STRING #define SOFTOKEN_VMAJOR 3 #define SOFTOKEN_VMINOR 41 -#define SOFTOKEN_VPATCH 0 +#define SOFTOKEN_VPATCH 2 #define SOFTOKEN_VBUILD 0 #define SOFTOKEN_BETA PR_FALSE diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 3b5c69b11..d98521a52 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -64,6 +64,7 @@ static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags); static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType); static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash); PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme); +PRBool ssl_IsRsaPkcs1SignatureScheme(SSLSignatureScheme scheme); const PRUint8 ssl_hello_retry_random[] = { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, @@ -4060,6 +4061,9 @@ ssl_SignatureSchemeValid(SSLSignatureScheme scheme, SECOidTag spkiOid, if (ssl_SignatureSchemeToHashType(scheme) == ssl_hash_sha1) { return PR_FALSE; } + if (ssl_IsRsaPkcs1SignatureScheme(scheme)) { + return PR_FALSE; + } /* With TLS 1.3, EC keys should have been selected based on calling * ssl_SignatureSchemeFromSpki(), reject them otherwise. */ return spkiOid != SEC_OID_ANSIX962_EC_PUBLIC_KEY; @@ -4309,6 +4313,22 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme) return PR_FALSE; } +PRBool +ssl_IsRsaPkcs1SignatureScheme(SSLSignatureScheme scheme) +{ + switch (scheme) { + case ssl_sig_rsa_pkcs1_sha256: + case ssl_sig_rsa_pkcs1_sha384: + case ssl_sig_rsa_pkcs1_sha512: + case ssl_sig_rsa_pkcs1_sha1: + return PR_TRUE; + + default: + return PR_FALSE; + } + return PR_FALSE; +} + SSLAuthType ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme) { diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h index 62511eafe..a2be260b0 100644 --- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -19,10 +19,10 @@ * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]" */ -#define NSSUTIL_VERSION "3.41" +#define NSSUTIL_VERSION "3.41.2" #define NSSUTIL_VMAJOR 3 #define NSSUTIL_VMINOR 41 -#define NSSUTIL_VPATCH 0 +#define NSSUTIL_VPATCH 2 #define NSSUTIL_VBUILD 0 #define NSSUTIL_BETA PR_FALSE diff --git a/security/nss/lib/util/quickder.c b/security/nss/lib/util/quickder.c index 7a6ac1c53..70ae42b27 100644 --- a/security/nss/lib/util/quickder.c +++ b/security/nss/lib/util/quickder.c @@ -757,6 +757,13 @@ DecodeItem(void* dest, } case SEC_ASN1_BIT_STRING: { + /* Can't be 8 or more spare bits, or any spare bits + * if there are no octets. */ + if (temp.data[0] >= 8 || (temp.data[0] > 0 && temp.len == 1)) { + PORT_SetError(SEC_ERROR_BAD_DER); + rv = SECFailure; + break; + } /* change the length in the SECItem to be the number of bits */ temp.len = (temp.len - 1) * 8 - (temp.data[0] & 0x7); |