summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Engert <kaie@kuix.de>2020-01-11 10:59:54 +0100
committerKai Engert <kaie@kuix.de>2020-01-11 10:59:54 +0100
commit863027c91e4eec94e568274f61822ccaab7a8b9c (patch)
tree82952f63ab3e87ef276b0149ae14746d94a3e154
parent33bac5d8e52188c3a12b31e9fae1c1881b53fdfe (diff)
downloadnss-hg-863027c91e4eec94e568274f61822ccaab7a8b9c.tar.gz
Bug 1606992 - Cache the most recent PBKDF2 password hash, to speed up repeated SDR operations. r=jcj
-rw-r--r--lib/softoken/lowpbe.c76
-rw-r--r--lib/softoken/pkcs11.c7
2 files changed, 82 insertions, 1 deletions
diff --git a/lib/softoken/lowpbe.c b/lib/softoken/lowpbe.c
index 4a101c68c..a79eaca7c 100644
--- a/lib/softoken/lowpbe.c
+++ b/lib/softoken/lowpbe.c
@@ -553,6 +553,52 @@ loser:
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
*/
@@ -596,7 +642,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/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c
index 7f3a01746..6c535cf77 100644
--- a/lib/softoken/pkcs11.c
+++ b/lib/softoken/pkcs11.c
@@ -3097,6 +3097,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)
@@ -3113,6 +3116,8 @@ nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
ENABLE_FORK_CHECK();
+ sftk_PBELockInit();
+
rv = SECOID_Init();
if (rv != SECSuccess) {
crv = CKR_DEVICE_ERROR;
@@ -3293,6 +3298,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);