summaryrefslogtreecommitdiffstats
path: root/security/nss
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss')
-rw-r--r--security/nss/lib/cryptohi/seckey.c5
-rw-r--r--security/nss/lib/freebl/dh.c3
-rw-r--r--security/nss/lib/freebl/ec.c14
-rw-r--r--security/nss/lib/freebl/ecl/ecp_25519.c3
-rw-r--r--security/nss/lib/nss/nss.h4
-rw-r--r--security/nss/lib/pk11wrap/pk11akey.c20
-rw-r--r--security/nss/lib/pk11wrap/pk11cert.c4
-rw-r--r--security/nss/lib/pk11wrap/pk11pk12.c13
-rw-r--r--security/nss/lib/softoken/legacydb/keydb.c33
-rw-r--r--security/nss/lib/softoken/legacydb/lgattr.c6
-rw-r--r--security/nss/lib/softoken/lgglue.c12
-rw-r--r--security/nss/lib/softoken/pkcs11.c4
-rw-r--r--security/nss/lib/softoken/pkcs11c.c2
-rw-r--r--security/nss/lib/softoken/sftkdb.c4
-rw-r--r--security/nss/lib/softoken/sftkdb.h1
-rw-r--r--security/nss/lib/softoken/sftkdbti.h7
-rw-r--r--security/nss/lib/softoken/sftkpwd.c193
-rw-r--r--security/nss/lib/softoken/softkver.h4
-rw-r--r--security/nss/lib/ssl/ssl3con.c20
-rw-r--r--security/nss/lib/util/nssutil.h4
-rw-r--r--security/nss/lib/util/quickder.c7
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, &param.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, &param.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);