mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-01 21:07:30 +09:00
Issue #1338 - Follow-up: Also cache the most recent PBKDF1 hash
This rewrites the caching mechanism to apply to both PBKDF1 and PBKDF2
This commit is contained in:
parent
25ae10aaec
commit
a8daf97de0
1 changed files with 140 additions and 50 deletions
|
|
@ -554,50 +554,160 @@ loser:
|
||||||
return A;
|
return A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct KDFCacheItemStr {
|
||||||
|
SECItem *hash;
|
||||||
|
SECItem *salt;
|
||||||
|
SECItem *pwItem;
|
||||||
|
HASH_HashType hashType;
|
||||||
|
int iterations;
|
||||||
|
int keyLen;
|
||||||
|
};
|
||||||
|
typedef struct KDFCacheItemStr KDFCacheItem;
|
||||||
|
|
||||||
/* Bug 1606992 - Cache the hash result for the common case that we're
|
/* Bug 1606992 - Cache the hash result for the common case that we're
|
||||||
* asked to repeatedly compute the key for the same password item,
|
* asked to repeatedly compute the key for the same password item,
|
||||||
* hash, iterations and salt. */
|
* hash, iterations and salt. */
|
||||||
static PZLock *PBE_cache_lock = NULL;
|
static struct {
|
||||||
static SECItem *cached_PBKDF2_item = NULL;
|
PZLock *lock;
|
||||||
static HASH_HashType cached_hashType;
|
struct {
|
||||||
static int cached_iterations;
|
KDFCacheItem common;
|
||||||
static int cached_keyLen;
|
int ivLen;
|
||||||
static SECItem *cached_salt = NULL;
|
PRBool faulty3DES;
|
||||||
static SECItem *cached_pwitem = NULL;
|
} cacheKDF1;
|
||||||
|
struct {
|
||||||
|
KDFCacheItem common;
|
||||||
|
} cacheKDF2;
|
||||||
|
} PBECache;
|
||||||
|
|
||||||
void
|
void
|
||||||
sftk_PBELockInit(void)
|
sftk_PBELockInit(void)
|
||||||
{
|
{
|
||||||
if (!PBE_cache_lock) {
|
if (!PBECache.lock) {
|
||||||
PBE_cache_lock = PZ_NewLock(nssIPBECacheLock);
|
PBECache.lock = PZ_NewLock(nssIPBECacheLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sftk_clearPBECacheItems(void)
|
sftk_clearPBECommonCacheItemsLocked(KDFCacheItem *item)
|
||||||
{
|
{
|
||||||
if (cached_PBKDF2_item) {
|
if (item->hash) {
|
||||||
SECITEM_FreeItem(cached_PBKDF2_item, PR_TRUE);
|
SECITEM_ZfreeItem(item->hash, PR_TRUE);
|
||||||
cached_PBKDF2_item = NULL;
|
item->hash = NULL;
|
||||||
}
|
}
|
||||||
if (cached_salt) {
|
if (item->salt) {
|
||||||
SECITEM_FreeItem(cached_salt, PR_TRUE);
|
SECITEM_FreeItem(item->salt, PR_TRUE);
|
||||||
cached_salt = NULL;
|
item->salt = NULL;
|
||||||
}
|
}
|
||||||
if (cached_pwitem) {
|
if (item->pwItem) {
|
||||||
SECITEM_FreeItem(cached_pwitem, PR_TRUE);
|
SECITEM_ZfreeItem(item->pwItem, PR_TRUE);
|
||||||
cached_pwitem = NULL;
|
item->pwItem = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sftk_setPBECommonCacheItemsKDFLocked(KDFCacheItem *cacheItem,
|
||||||
|
const SECItem *hash,
|
||||||
|
const NSSPKCS5PBEParameter *pbe_param,
|
||||||
|
const SECItem *pwItem)
|
||||||
|
{
|
||||||
|
cacheItem->hash = SECITEM_DupItem(hash);
|
||||||
|
cacheItem->hashType = pbe_param->hashType;
|
||||||
|
cacheItem->iterations = pbe_param->iter;
|
||||||
|
cacheItem->keyLen = pbe_param->keyLen;
|
||||||
|
cacheItem->salt = SECITEM_DupItem(&pbe_param->salt);
|
||||||
|
cacheItem->pwItem = SECITEM_DupItem(pwItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sftk_setPBECacheKDF2(const SECItem *hash,
|
||||||
|
const NSSPKCS5PBEParameter *pbe_param,
|
||||||
|
const SECItem *pwItem)
|
||||||
|
{
|
||||||
|
PZ_Lock(PBECache.lock);
|
||||||
|
sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF2.common);
|
||||||
|
sftk_setPBECommonCacheItemsKDFLocked(&PBECache.cacheKDF2.common,
|
||||||
|
hash, pbe_param, pwItem);
|
||||||
|
|
||||||
|
PZ_Unlock(PBECache.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sftk_setPBECacheKDF1(const SECItem *hash,
|
||||||
|
const NSSPKCS5PBEParameter *pbe_param,
|
||||||
|
const SECItem *pwItem,
|
||||||
|
PRBool faulty3DES)
|
||||||
|
{
|
||||||
|
PZ_Lock(PBECache.lock);
|
||||||
|
|
||||||
|
sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF1.common);
|
||||||
|
|
||||||
|
sftk_setPBECommonCacheItemsKDFLocked(&PBECache.cacheKDF1.common,
|
||||||
|
hash, pbe_param, pwItem);
|
||||||
|
PBECache.cacheKDF1.faulty3DES = faulty3DES;
|
||||||
|
PBECache.cacheKDF1.ivLen = pbe_param->ivLen;
|
||||||
|
|
||||||
|
PZ_Unlock(PBECache.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PRBool
|
||||||
|
sftk_comparePBECommonCacheItemLocked(const KDFCacheItem *cacheItem,
|
||||||
|
const NSSPKCS5PBEParameter *pbe_param,
|
||||||
|
const SECItem *pwItem)
|
||||||
|
{
|
||||||
|
return (cacheItem->hash &&
|
||||||
|
cacheItem->salt &&
|
||||||
|
cacheItem->pwItem &&
|
||||||
|
pbe_param->hashType == cacheItem->hashType &&
|
||||||
|
pbe_param->iter == cacheItem->iterations &&
|
||||||
|
pbe_param->keyLen == cacheItem->keyLen &&
|
||||||
|
SECITEM_ItemsAreEqual(&pbe_param->salt, cacheItem->salt) &&
|
||||||
|
SECITEM_ItemsAreEqual(pwItem, cacheItem->pwItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
static SECItem *
|
||||||
|
sftk_getPBECacheKDF2(const NSSPKCS5PBEParameter *pbe_param,
|
||||||
|
const SECItem *pwItem)
|
||||||
|
{
|
||||||
|
SECItem *result = NULL;
|
||||||
|
const KDFCacheItem *cacheItem = &PBECache.cacheKDF2.common;
|
||||||
|
|
||||||
|
PZ_Lock(PBECache.lock);
|
||||||
|
if (sftk_comparePBECommonCacheItemLocked(cacheItem, pbe_param, pwItem)) {
|
||||||
|
result = SECITEM_DupItem(cacheItem->hash);
|
||||||
|
}
|
||||||
|
PZ_Unlock(PBECache.lock);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SECItem *
|
||||||
|
sftk_getPBECacheKDF1(const NSSPKCS5PBEParameter *pbe_param,
|
||||||
|
const SECItem *pwItem,
|
||||||
|
PRBool faulty3DES)
|
||||||
|
{
|
||||||
|
SECItem *result = NULL;
|
||||||
|
const KDFCacheItem *cacheItem = &PBECache.cacheKDF1.common;
|
||||||
|
|
||||||
|
PZ_Lock(PBECache.lock);
|
||||||
|
if (sftk_comparePBECommonCacheItemLocked(cacheItem, pbe_param, pwItem) &&
|
||||||
|
PBECache.cacheKDF1.faulty3DES == faulty3DES &&
|
||||||
|
PBECache.cacheKDF1.ivLen == pbe_param->ivLen) {
|
||||||
|
result = SECITEM_DupItem(cacheItem->hash);
|
||||||
|
}
|
||||||
|
PZ_Unlock(PBECache.lock);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sftk_PBELockShutdown(void)
|
sftk_PBELockShutdown(void)
|
||||||
{
|
{
|
||||||
if (PBE_cache_lock) {
|
if (PBECache.lock) {
|
||||||
PZ_DestroyLock(PBE_cache_lock);
|
PZ_DestroyLock(PBECache.lock);
|
||||||
PBE_cache_lock = 0;
|
PBECache.lock = 0;
|
||||||
}
|
}
|
||||||
sftk_clearPBECacheItems();
|
sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF1.common);
|
||||||
|
sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF2.common);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -632,7 +742,11 @@ nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
|
||||||
hashObj = HASH_GetRawHashObject(pbe_param->hashType);
|
hashObj = HASH_GetRawHashObject(pbe_param->hashType);
|
||||||
switch (pbe_param->pbeType) {
|
switch (pbe_param->pbeType) {
|
||||||
case NSSPKCS5_PBKDF1:
|
case NSSPKCS5_PBKDF1:
|
||||||
hash = nsspkcs5_PBKDF1Extended(hashObj, pbe_param, pwitem, faulty3DES);
|
hash = sftk_getPBECacheKDF1(pbe_param, pwitem, faulty3DES);
|
||||||
|
if (!hash) {
|
||||||
|
hash = nsspkcs5_PBKDF1Extended(hashObj, pbe_param, pwitem, faulty3DES);
|
||||||
|
sftk_setPBECacheKDF1(hash, pbe_param, pwitem, faulty3DES);
|
||||||
|
}
|
||||||
if (hash == NULL) {
|
if (hash == NULL) {
|
||||||
goto loser;
|
goto loser;
|
||||||
}
|
}
|
||||||
|
|
@ -643,34 +757,10 @@ nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case NSSPKCS5_PBKDF2:
|
case NSSPKCS5_PBKDF2:
|
||||||
PZ_Lock(PBE_cache_lock);
|
hash = sftk_getPBECacheKDF2(pbe_param, pwitem);
|
||||||
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) {
|
if (!hash) {
|
||||||
hash = nsspkcs5_PBKDF2(hashObj, pbe_param, pwitem);
|
hash = nsspkcs5_PBKDF2(hashObj, pbe_param, pwitem);
|
||||||
PZ_Lock(PBE_cache_lock);
|
sftk_setPBECacheKDF2(hash, pbe_param, pwitem);
|
||||||
/* 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) {
|
if (getIV) {
|
||||||
PORT_Memcpy(iv->data, pbe_param->ivData, iv->len);
|
PORT_Memcpy(iv->data, pbe_param->ivData, iv->len);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue