From 1cbe67b6fb56dcafdc65c2e3d4b3c1a5c57985e9 Mon Sep 17 00:00:00 2001 From: "J.C. Jones" Date: Mon, 13 Jan 2020 17:09:45 +0000 Subject: [PATCH] Bug 1606927 - land NSS a06bd0f6bbe8 UPGRADE_NSS_RELEASE, r=kjacobs 2020-01-11 Kai Engert * lib/softoken/lowpbe.c, lib/softoken/pkcs11.c: Bug 1606992 - Cache the most recent PBKDF2 password hash, to speed up repeated SDR operations. r=jcj [a06bd0f6bbe8] [tip] Differential Revision: https://phabricator.services.mozilla.com/D59741 --HG-- extra : moz-landing-system : lando --- security/nss/TAG-INFO | 2 +- security/nss/coreconf/coreconf.dep | 1 - security/nss/lib/softoken/lowpbe.c | 76 +++++++++++++++++++++++++++++- security/nss/lib/softoken/pkcs11.c | 7 +++ 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index a42cd7bee62af..3a4a17ac30925 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -4921046404f1 \ No newline at end of file +a06bd0f6bbe8 \ No newline at end of file diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 590d1bfaeee3f..5182f75552c81 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,4 +10,3 @@ */ #error "Do not include this header file." - diff --git a/security/nss/lib/softoken/lowpbe.c b/security/nss/lib/softoken/lowpbe.c index 5669e1bd68094..867ad7aea7038 100644 --- a/security/nss/lib/softoken/lowpbe.c +++ b/security/nss/lib/softoken/lowpbe.c @@ -557,6 +557,52 @@ nsspkcs5_PKCS12PBE(const SECHashObject *hashObject, return A; } +/* Bug 1606992 - Cache the hash result for the common case that we're + * asked to repeatedly compute the key for the same password item, + * hash, iterations and salt. */ +static PZLock *PBE_cache_lock = NULL; +static SECItem *cached_PBKDF2_item = NULL; +static HASH_HashType cached_hashType; +static int cached_iterations; +static int cached_keyLen; +static SECItem *cached_salt = NULL; +static SECItem *cached_pwitem = NULL; + +void +sftk_PBELockInit(void) +{ + if (!PBE_cache_lock) { + PBE_cache_lock = PZ_NewLock(nssIPBECacheLock); + } +} + +static void +sftk_clearPBECacheItems(void) +{ + if (cached_PBKDF2_item) { + SECITEM_FreeItem(cached_PBKDF2_item, PR_TRUE); + cached_PBKDF2_item = NULL; + } + if (cached_salt) { + SECITEM_FreeItem(cached_salt, PR_TRUE); + cached_salt = NULL; + } + if (cached_pwitem) { + SECITEM_FreeItem(cached_pwitem, PR_TRUE); + cached_pwitem = NULL; + } +} + +void +sftk_PBELockShutdown(void) +{ + if (PBE_cache_lock) { + PZ_DestroyLock(PBE_cache_lock); + PBE_cache_lock = 0; + } + sftk_clearPBECacheItems(); +} + /* * generate key as per PKCS 5 */ @@ -600,7 +646,35 @@ nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, break; case NSSPKCS5_PBKDF2: - hash = nsspkcs5_PBKDF2(hashObj, pbe_param, pwitem); + PZ_Lock(PBE_cache_lock); + if (cached_PBKDF2_item) { + if (pbe_param->hashType == cached_hashType && + pbe_param->iter == cached_iterations && + pbe_param->keyLen == cached_keyLen && + cached_salt && + SECITEM_ItemsAreEqual(&pbe_param->salt, cached_salt) && + cached_pwitem && + SECITEM_ItemsAreEqual(pwitem, cached_pwitem)) { + hash = SECITEM_DupItem(cached_PBKDF2_item); + } else { + sftk_clearPBECacheItems(); + } + } + PZ_Unlock(PBE_cache_lock); + if (!hash) { + hash = nsspkcs5_PBKDF2(hashObj, pbe_param, pwitem); + PZ_Lock(PBE_cache_lock); + /* ensure no other thread was quicker than us setting the cache */ + if (!cached_PBKDF2_item) { + cached_PBKDF2_item = SECITEM_DupItem(hash); + cached_hashType = pbe_param->hashType; + cached_iterations = pbe_param->iter; + cached_keyLen = pbe_param->keyLen; + cached_salt = SECITEM_DupItem(&pbe_param->salt); + cached_pwitem = SECITEM_DupItem(pwitem); + } + PZ_Unlock(PBE_cache_lock); + } if (getIV) { PORT_Memcpy(iv->data, pbe_param->ivData, iv->len); } diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 94507f280cf60..133c7b9c794a4 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -3104,6 +3104,9 @@ sftk_closePeer(PRBool isFIPS) return; } +extern void sftk_PBELockInit(void); +extern void sftk_PBELockShutdown(void); + /* NSC_Initialize initializes the Cryptoki library. */ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) @@ -3120,6 +3123,8 @@ nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) ENABLE_FORK_CHECK(); + sftk_PBELockInit(); + rv = SECOID_Init(); if (rv != SECSuccess) { crv = CKR_DEVICE_ERROR; @@ -3300,6 +3305,8 @@ nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS) /* clean up the default OID table */ SECOID_Shutdown(); + sftk_PBELockShutdown(); + /* reset fork status in util */ UTIL_SetForkState(PR_FALSE);