tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

lowpbe.c (55518B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "plarena.h"
      6 
      7 #include "seccomon.h"
      8 #include "secitem.h"
      9 #include "secport.h"
     10 #include "hasht.h"
     11 #include "pkcs11t.h"
     12 #include "blapi.h"
     13 #include "hasht.h"
     14 #include "secasn1.h"
     15 #include "secder.h"
     16 #include "lowpbe.h"
     17 #include "secoid.h"
     18 #include "alghmac.h"
     19 #include "softoken.h"
     20 #include "secerr.h"
     21 #include "pkcs11i.h"
     22 
     23 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
     24 
     25 /* how much a crypto encrypt/decryption may expand a buffer */
     26 #define MAX_CRYPTO_EXPANSION 64
     27 
     28 /* template for PKCS 5 PBE Parameter.  This template has been expanded
     29 * based upon the additions in PKCS 12.  This should eventually be moved
     30 * if RSA updates PKCS 5.
     31 */
     32 static const SEC_ASN1Template NSSPKCS5PBEParameterTemplate[] = {
     33    { SEC_ASN1_SEQUENCE,
     34      0, NULL, sizeof(NSSPKCS5PBEParameter) },
     35    { SEC_ASN1_OCTET_STRING,
     36      offsetof(NSSPKCS5PBEParameter, salt) },
     37    { SEC_ASN1_INTEGER,
     38      offsetof(NSSPKCS5PBEParameter, iteration) },
     39    { 0 }
     40 };
     41 
     42 static const SEC_ASN1Template NSSPKCS5PKCS12V2PBEParameterTemplate[] = {
     43    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) },
     44    { SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) },
     45    { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) },
     46    { 0 }
     47 };
     48 
     49 /* PKCS5 v2 */
     50 
     51 struct nsspkcs5V2PBEParameterStr {
     52    SECAlgorithmID keyParams; /* parameters of the key generation */
     53    SECAlgorithmID algParams; /* parameters for the encryption or mac op */
     54 };
     55 
     56 typedef struct nsspkcs5V2PBEParameterStr nsspkcs5V2PBEParameter;
     57 
     58 static const SEC_ASN1Template NSSPKCS5V2PBES2ParameterTemplate[] = {
     59    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(nsspkcs5V2PBEParameter) },
     60    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
     61      offsetof(nsspkcs5V2PBEParameter, keyParams),
     62      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     63    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
     64      offsetof(nsspkcs5V2PBEParameter, algParams),
     65      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     66    { 0 }
     67 };
     68 
     69 static const SEC_ASN1Template NSSPKCS5V2PBEParameterTemplate[] = {
     70    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) },
     71    /* this is really a choice, but since we don't understand any other
     72     * choice, just inline it. */
     73    { SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) },
     74    { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) },
     75    { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, keyLength) },
     76    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
     77      offsetof(NSSPKCS5PBEParameter, prfAlg),
     78      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     79    { 0 }
     80 };
     81 
     82 SECStatus
     83 nsspkcs5_HashBuf(const SECHashObject *hashObj, unsigned char *dest,
     84                 unsigned char *src, int len)
     85 {
     86    void *ctx;
     87    unsigned int retLen;
     88 
     89    ctx = hashObj->create();
     90    if (ctx == NULL) {
     91        return SECFailure;
     92    }
     93    hashObj->begin(ctx);
     94    hashObj->update(ctx, src, len);
     95    hashObj->end(ctx, dest, &retLen, hashObj->length);
     96    hashObj->destroy(ctx, PR_TRUE);
     97    return SECSuccess;
     98 }
     99 
    100 /* generate bits using any hash
    101 */
    102 static SECItem *
    103 nsspkcs5_PBKDF1(const SECHashObject *hashObj, SECItem *salt, SECItem *pwd,
    104                int iter, PRBool faulty3DES)
    105 {
    106    SECItem *hash = NULL, *pre_hash = NULL;
    107    SECStatus rv = SECFailure;
    108 
    109    if ((salt == NULL) || (pwd == NULL) || (iter < 0)) {
    110        return NULL;
    111    }
    112 
    113    hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    114    pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    115 
    116    if ((hash != NULL) && (pre_hash != NULL)) {
    117        int i, ph_len;
    118 
    119        ph_len = hashObj->length;
    120        if ((salt->len + pwd->len) > hashObj->length) {
    121            ph_len = salt->len + pwd->len;
    122        }
    123 
    124        rv = SECFailure;
    125 
    126        /* allocate buffers */
    127        hash->len = hashObj->length;
    128        hash->data = (unsigned char *)PORT_ZAlloc(hash->len);
    129        pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len);
    130 
    131        /* in pbeSHA1TripleDESCBC there was an allocation error that made
    132         * it into the caller.  We do not want to propagate those errors
    133         * further, so we are doing it correctly, but reading the old method.
    134         */
    135        if (faulty3DES) {
    136            pre_hash->len = ph_len;
    137        } else {
    138            pre_hash->len = salt->len + pwd->len;
    139        }
    140 
    141        /* preform hash */
    142        if ((hash->data != NULL) && (pre_hash->data != NULL)) {
    143            rv = SECSuccess;
    144            /* check for 0 length password */
    145            if (pwd->len > 0) {
    146                PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
    147            }
    148            if (salt->len > 0) {
    149                PORT_Memcpy((pre_hash->data + pwd->len), salt->data, salt->len);
    150            }
    151            for (i = 0; ((i < iter) && (rv == SECSuccess)); i++) {
    152                rv = nsspkcs5_HashBuf(hashObj, hash->data,
    153                                      pre_hash->data, pre_hash->len);
    154                if (rv != SECFailure) {
    155                    pre_hash->len = hashObj->length;
    156                    PORT_Memcpy(pre_hash->data, hash->data, hashObj->length);
    157                }
    158            }
    159        }
    160    }
    161 
    162    if (pre_hash != NULL) {
    163        SECITEM_ZfreeItem(pre_hash, PR_TRUE);
    164    }
    165 
    166    if ((rv != SECSuccess) && (hash != NULL)) {
    167        SECITEM_ZfreeItem(hash, PR_TRUE);
    168        hash = NULL;
    169    }
    170 
    171    return hash;
    172 }
    173 
    174 /* this bit generation routine is described in PKCS 12 and the proposed
    175 * extensions to PKCS 5.  an initial hash is generated following the
    176 * instructions laid out in PKCS 5.  If the number of bits generated is
    177 * insufficient, then the method discussed in the proposed extensions to
    178 * PKCS 5 in PKCS 12 are used.  This extension makes use of the HMAC
    179 * function.  And the P_Hash function from the TLS standard.
    180 */
    181 static SECItem *
    182 nsspkcs5_PFXPBE(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param,
    183                SECItem *init_hash, unsigned int bytes_needed)
    184 {
    185    SECItem *ret_bits = NULL;
    186    int hash_size = 0;
    187    unsigned int i;
    188    unsigned int hash_iter;
    189    unsigned int dig_len;
    190    SECStatus rv = SECFailure;
    191    unsigned char *state = NULL;
    192    unsigned int state_len;
    193    HMACContext *cx = NULL;
    194 
    195    hash_size = hashObj->length;
    196    hash_iter = (bytes_needed + (unsigned int)hash_size - 1) / hash_size;
    197 
    198    /* allocate return buffer */
    199    ret_bits = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
    200    if (ret_bits == NULL)
    201        return NULL;
    202    ret_bits->data = (unsigned char *)PORT_ZAlloc((hash_iter * hash_size) + 1);
    203    ret_bits->len = (hash_iter * hash_size);
    204    if (ret_bits->data == NULL) {
    205        PORT_Free(ret_bits);
    206        return NULL;
    207    }
    208 
    209    /* allocate intermediate hash buffer.  8 is for the 8 bytes of
    210     * data which are added based on iteration number
    211     */
    212 
    213    if ((unsigned int)hash_size > pbe_param->salt.len) {
    214        state_len = hash_size;
    215    } else {
    216        state_len = pbe_param->salt.len;
    217    }
    218    state = (unsigned char *)PORT_ZAlloc(state_len);
    219    if (state == NULL) {
    220        rv = SECFailure;
    221        goto loser;
    222    }
    223    if (pbe_param->salt.len > 0) {
    224        PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len);
    225    }
    226 
    227    cx = HMAC_Create(hashObj, init_hash->data, init_hash->len, PR_TRUE);
    228    if (cx == NULL) {
    229        rv = SECFailure;
    230        goto loser;
    231    }
    232 
    233    for (i = 0; i < hash_iter; i++) {
    234 
    235        /* generate output bits */
    236        HMAC_Begin(cx);
    237        HMAC_Update(cx, state, state_len);
    238        HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len);
    239        rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size),
    240                         &dig_len, hash_size);
    241        if (rv != SECSuccess)
    242            goto loser;
    243        PORT_Assert((unsigned int)hash_size == dig_len);
    244 
    245        /* generate new state */
    246        HMAC_Begin(cx);
    247        HMAC_Update(cx, state, state_len);
    248        rv = HMAC_Finish(cx, state, &state_len, state_len);
    249        if (rv != SECSuccess)
    250            goto loser;
    251        PORT_Assert(state_len == dig_len);
    252    }
    253 
    254 loser:
    255    if (state != NULL)
    256        PORT_ZFree(state, state_len);
    257    HMAC_Destroy(cx, PR_TRUE);
    258 
    259    if (rv != SECSuccess) {
    260        SECITEM_ZfreeItem(ret_bits, PR_TRUE);
    261        ret_bits = NULL;
    262    }
    263 
    264    return ret_bits;
    265 }
    266 
    267 /* generate bits for the key and iv determination.  if enough bits
    268 * are not generated using PKCS 5, then we need to generate more bits
    269 * based on the extension proposed in PKCS 12
    270 */
    271 static SECItem *
    272 nsspkcs5_PBKDF1Extended(const SECHashObject *hashObj,
    273                        NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, PRBool faulty3DES)
    274 {
    275    SECItem *hash = NULL;
    276    SECItem *newHash = NULL;
    277    int bytes_needed;
    278    int bytes_available;
    279 
    280    bytes_needed = pbe_param->ivLen + pbe_param->keyLen;
    281    bytes_available = hashObj->length;
    282 
    283    hash = nsspkcs5_PBKDF1(hashObj, &pbe_param->salt, pwitem,
    284                           pbe_param->iter, faulty3DES);
    285 
    286    if (hash == NULL) {
    287        return NULL;
    288    }
    289 
    290    if (bytes_needed <= bytes_available) {
    291        return hash;
    292    }
    293 
    294    newHash = nsspkcs5_PFXPBE(hashObj, pbe_param, hash, bytes_needed);
    295    if (hash != newHash)
    296        SECITEM_ZfreeItem(hash, PR_TRUE);
    297    return newHash;
    298 }
    299 
    300 /*
    301 * PBDKDF2 is PKCS #5 v2.0 it's currently not used by NSS
    302 */
    303 static void
    304 do_xor(unsigned char *dest, unsigned char *src, int len)
    305 {
    306    /* use byt xor, not all platforms are happy about inaligned
    307     * integer fetches */
    308    while (len--) {
    309        *dest = *dest ^ *src;
    310        dest++;
    311        src++;
    312    }
    313 }
    314 
    315 static SECStatus
    316 nsspkcs5_PBKDF2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt,
    317                  int iterations, unsigned int i, unsigned char *T)
    318 {
    319    int j;
    320    HMACContext *cx = NULL;
    321    unsigned int hLen = hashobj->length;
    322    SECStatus rv = SECFailure;
    323    unsigned char *last = NULL;
    324    unsigned int lastLength = salt->len + 4;
    325    unsigned int lastBufLength;
    326 
    327    cx = HMAC_Create(hashobj, pwitem->data, pwitem->len, PR_FALSE);
    328    if (cx == NULL) {
    329        goto loser;
    330    }
    331    PORT_Memset(T, 0, hLen);
    332    lastBufLength = PR_MAX(lastLength, hLen);
    333    last = PORT_Alloc(lastBufLength);
    334    if (last == NULL) {
    335        goto loser;
    336    }
    337    PORT_Memcpy(last, salt->data, salt->len);
    338    last[salt->len] = (i >> 24) & 0xff;
    339    last[salt->len + 1] = (i >> 16) & 0xff;
    340    last[salt->len + 2] = (i >> 8) & 0xff;
    341    last[salt->len + 3] = i & 0xff;
    342 
    343    /* NOTE: we need at least one iteration to return success! */
    344    for (j = 0; j < iterations; j++) {
    345        HMAC_Begin(cx);
    346        HMAC_Update(cx, last, lastLength);
    347        rv = HMAC_Finish(cx, last, &lastLength, hLen);
    348        if (rv != SECSuccess) {
    349            break;
    350        }
    351        do_xor(T, last, hLen);
    352    }
    353 loser:
    354    if (cx) {
    355        HMAC_Destroy(cx, PR_TRUE);
    356    }
    357    if (last) {
    358        PORT_ZFree(last, lastBufLength);
    359    }
    360    return rv;
    361 }
    362 
    363 static SECItem *
    364 nsspkcs5_PBKDF2(const SECHashObject *hashobj, NSSPKCS5PBEParameter *pbe_param,
    365                SECItem *pwitem)
    366 {
    367    int iterations = pbe_param->iter;
    368    int bytesNeeded = pbe_param->keyLen;
    369    unsigned int dkLen = bytesNeeded;
    370    unsigned int hLen = hashobj->length;
    371    unsigned int nblocks = (dkLen + hLen - 1) / hLen;
    372    unsigned int i;
    373    unsigned char *rp;
    374    unsigned char *T = NULL;
    375    SECItem *result = NULL;
    376    SECItem *salt = &pbe_param->salt;
    377    SECStatus rv = SECFailure;
    378 
    379    result = SECITEM_AllocItem(NULL, NULL, nblocks * hLen);
    380    if (result == NULL) {
    381        return NULL;
    382    }
    383 
    384    T = PORT_Alloc(hLen);
    385    if (T == NULL) {
    386        goto loser;
    387    }
    388 
    389    for (i = 1, rp = result->data; i <= nblocks; i++, rp += hLen) {
    390        rv = nsspkcs5_PBKDF2_F(hashobj, pwitem, salt, iterations, i, T);
    391        if (rv != SECSuccess) {
    392            break;
    393        }
    394        PORT_Memcpy(rp, T, hLen);
    395    }
    396 
    397 loser:
    398    if (T) {
    399        PORT_ZFree(T, hLen);
    400    }
    401    if (rv != SECSuccess) {
    402        SECITEM_ZfreeItem(result, PR_TRUE);
    403        result = NULL;
    404    } else {
    405        result->len = dkLen;
    406    }
    407 
    408    return result;
    409 }
    410 
    411 #define NSSPBE_ROUNDUP(x, y) ((((x) + ((y)-1)) / (y)) * (y))
    412 #define NSSPBE_MIN(x, y) ((x) < (y) ? (x) : (y))
    413 /*
    414 * This is the extended PBE function defined by the final PKCS #12 spec.
    415 */
    416 static SECItem *
    417 nsspkcs5_PKCS12PBE(const SECHashObject *hashObject,
    418                   NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
    419                   PBEBitGenID bitGenPurpose, unsigned int bytesNeeded)
    420 {
    421    PLArenaPool *arena = NULL;
    422    unsigned int SLen, PLen;
    423    unsigned int hashLength = hashObject->length;
    424    unsigned char *S, *P;
    425    SECItem *A = NULL, B, D, I;
    426    SECItem *salt = &pbe_param->salt;
    427    unsigned int c, i = 0;
    428    unsigned int hashLen;
    429    int iter;
    430    unsigned char *iterBuf;
    431    void *hash = NULL;
    432    unsigned int bufferLength;
    433 
    434    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    435    if (!arena) {
    436        return NULL;
    437    }
    438 
    439    /* how many hash object lengths are needed */
    440    c = (bytesNeeded + (hashLength - 1)) / hashLength;
    441 
    442    /* 64 if 0 < hashLength <= 32, 128 if 32 < hashLength <= 64 */
    443    bufferLength = NSSPBE_ROUNDUP(hashLength * 2, 64);
    444 
    445    /* initialize our buffers */
    446    D.len = bufferLength;
    447    /* B and D are the same length, use one alloc go get both */
    448    D.data = (unsigned char *)PORT_ArenaZAlloc(arena, D.len * 2);
    449    B.len = D.len;
    450    B.data = D.data + D.len;
    451 
    452    /* if all goes well, A will be returned, so don't use our temp arena */
    453    A = SECITEM_AllocItem(NULL, NULL, c * hashLength);
    454    if (A == NULL) {
    455        goto loser;
    456    }
    457 
    458    SLen = NSSPBE_ROUNDUP(salt->len, bufferLength);
    459    PLen = NSSPBE_ROUNDUP(pwitem->len, bufferLength);
    460    I.len = SLen + PLen;
    461    I.data = (unsigned char *)PORT_ArenaZAlloc(arena, I.len);
    462    if (I.data == NULL) {
    463        goto loser;
    464    }
    465 
    466    /* S & P are only used to initialize I */
    467    S = I.data;
    468    P = S + SLen;
    469 
    470    PORT_Memset(D.data, (char)bitGenPurpose, D.len);
    471    if (SLen) {
    472        for (i = 0; i < SLen; i += salt->len) {
    473            PORT_Memcpy(S + i, salt->data, NSSPBE_MIN(SLen - i, salt->len));
    474        }
    475    }
    476    if (PLen) {
    477        for (i = 0; i < PLen; i += pwitem->len) {
    478            PORT_Memcpy(P + i, pwitem->data, NSSPBE_MIN(PLen - i, pwitem->len));
    479        }
    480    }
    481 
    482    iterBuf = (unsigned char *)PORT_ArenaZAlloc(arena, hashLength);
    483    if (iterBuf == NULL) {
    484        goto loser;
    485    }
    486 
    487    hash = hashObject->create();
    488    if (!hash) {
    489        goto loser;
    490    }
    491    /* calculate the PBE now */
    492    for (i = 0; i < c; i++) {
    493        int Bidx; /* must be signed or the for loop won't terminate */
    494        unsigned int k, j;
    495        unsigned char *Ai = A->data + i * hashLength;
    496 
    497        for (iter = 0; iter < pbe_param->iter; iter++) {
    498            hashObject->begin(hash);
    499 
    500            if (iter) {
    501                hashObject->update(hash, iterBuf, hashLen);
    502            } else {
    503                hashObject->update(hash, D.data, D.len);
    504                hashObject->update(hash, I.data, I.len);
    505            }
    506 
    507            hashObject->end(hash, iterBuf, &hashLen, hashObject->length);
    508            if (hashLen != hashObject->length) {
    509                break;
    510            }
    511        }
    512 
    513        PORT_Memcpy(Ai, iterBuf, hashLength);
    514        for (Bidx = 0; Bidx < (int)B.len; Bidx += hashLength) {
    515            PORT_Memcpy(B.data + Bidx, iterBuf, NSSPBE_MIN(B.len - Bidx, hashLength));
    516        }
    517 
    518        k = I.len / B.len;
    519        for (j = 0; j < k; j++) {
    520            unsigned int q, carryBit;
    521            unsigned char *Ij = I.data + j * B.len;
    522 
    523            /* (Ij = Ij+B+1) */
    524            for (Bidx = (B.len - 1), q = 1, carryBit = 0; Bidx >= 0; Bidx--, q = 0) {
    525                q += (unsigned int)Ij[Bidx];
    526                q += (unsigned int)B.data[Bidx];
    527                q += carryBit;
    528 
    529                carryBit = (q > 0xff);
    530                Ij[Bidx] = (unsigned char)(q & 0xff);
    531            }
    532        }
    533    }
    534 loser:
    535    if (hash) {
    536        hashObject->destroy(hash, PR_TRUE);
    537    }
    538    if (arena) {
    539        PORT_FreeArena(arena, PR_TRUE);
    540    }
    541 
    542    if (A) {
    543        /* if i != c, then we didn't complete the loop above and must of failed
    544         * somwhere along the way */
    545        if (i != c) {
    546            SECITEM_ZfreeItem(A, PR_TRUE);
    547            A = NULL;
    548        } else {
    549            A->len = bytesNeeded;
    550        }
    551    }
    552 
    553    return A;
    554 }
    555 
    556 struct KDFCacheItemStr {
    557    SECItem *hash;
    558    SECItem *salt;
    559    SECItem *pwItem;
    560    HASH_HashType hashType;
    561    int iterations;
    562    int keyLen;
    563 };
    564 typedef struct KDFCacheItemStr KDFCacheItem;
    565 
    566 /* Bug 1606992 - Cache the hash result for the common case that we're
    567 * asked to repeatedly compute the key for the same password item,
    568 * hash, iterations and salt. */
    569 #define KDF2_CACHE_COUNT 150
    570 static struct {
    571    PZLock *lock;
    572    struct {
    573        KDFCacheItem common;
    574        int ivLen;
    575        PRBool faulty3DES;
    576    } cacheKDF1;
    577    struct {
    578        KDFCacheItem common[KDF2_CACHE_COUNT];
    579        int next;
    580    } cacheKDF2;
    581 } PBECache;
    582 
    583 void
    584 sftk_PBELockInit(void)
    585 {
    586    if (!PBECache.lock) {
    587        PBECache.lock = PZ_NewLock(nssIPBECacheLock);
    588    }
    589 }
    590 
    591 static void
    592 sftk_clearPBECommonCacheItemsLocked(KDFCacheItem *item)
    593 {
    594    if (item->hash) {
    595        SECITEM_ZfreeItem(item->hash, PR_TRUE);
    596        item->hash = NULL;
    597    }
    598    if (item->salt) {
    599        SECITEM_ZfreeItem(item->salt, PR_TRUE);
    600        item->salt = NULL;
    601    }
    602    if (item->pwItem) {
    603        SECITEM_ZfreeItem(item->pwItem, PR_TRUE);
    604        item->pwItem = NULL;
    605    }
    606 }
    607 
    608 static void
    609 sftk_setPBECommonCacheItemsKDFLocked(KDFCacheItem *cacheItem,
    610                                     const SECItem *hash,
    611                                     const NSSPKCS5PBEParameter *pbe_param,
    612                                     const SECItem *pwItem)
    613 {
    614    cacheItem->hash = SECITEM_DupItem(hash);
    615    cacheItem->hashType = pbe_param->hashType;
    616    cacheItem->iterations = pbe_param->iter;
    617    cacheItem->keyLen = pbe_param->keyLen;
    618    cacheItem->salt = SECITEM_DupItem(&pbe_param->salt);
    619    cacheItem->pwItem = SECITEM_DupItem(pwItem);
    620 }
    621 
    622 static void
    623 sftk_setPBECacheKDF2(const SECItem *hash,
    624                     const NSSPKCS5PBEParameter *pbe_param,
    625                     const SECItem *pwItem)
    626 {
    627    PZ_Lock(PBECache.lock);
    628    KDFCacheItem *next = &PBECache.cacheKDF2.common[PBECache.cacheKDF2.next];
    629 
    630    sftk_clearPBECommonCacheItemsLocked(next);
    631 
    632    sftk_setPBECommonCacheItemsKDFLocked(next, hash, pbe_param, pwItem);
    633    PBECache.cacheKDF2.next++;
    634    if (PBECache.cacheKDF2.next >= KDF2_CACHE_COUNT) {
    635        PBECache.cacheKDF2.next = 0;
    636    }
    637 
    638    PZ_Unlock(PBECache.lock);
    639 }
    640 
    641 static void
    642 sftk_setPBECacheKDF1(const SECItem *hash,
    643                     const NSSPKCS5PBEParameter *pbe_param,
    644                     const SECItem *pwItem,
    645                     PRBool faulty3DES)
    646 {
    647    PZ_Lock(PBECache.lock);
    648 
    649    sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF1.common);
    650 
    651    sftk_setPBECommonCacheItemsKDFLocked(&PBECache.cacheKDF1.common,
    652                                         hash, pbe_param, pwItem);
    653    PBECache.cacheKDF1.faulty3DES = faulty3DES;
    654    PBECache.cacheKDF1.ivLen = pbe_param->ivLen;
    655 
    656    PZ_Unlock(PBECache.lock);
    657 }
    658 
    659 static PRBool
    660 sftk_comparePBECommonCacheItemLocked(const KDFCacheItem *cacheItem,
    661                                     const NSSPKCS5PBEParameter *pbe_param,
    662                                     const SECItem *pwItem)
    663 {
    664    return (cacheItem->hash &&
    665            cacheItem->salt &&
    666            cacheItem->pwItem &&
    667            pbe_param->hashType == cacheItem->hashType &&
    668            pbe_param->iter == cacheItem->iterations &&
    669            pbe_param->keyLen == cacheItem->keyLen &&
    670            SECITEM_ItemsAreEqual(&pbe_param->salt, cacheItem->salt) &&
    671            SECITEM_ItemsAreEqual(pwItem, cacheItem->pwItem));
    672 }
    673 
    674 static SECItem *
    675 sftk_getPBECacheKDF2(const NSSPKCS5PBEParameter *pbe_param,
    676                     const SECItem *pwItem)
    677 {
    678    SECItem *result = NULL;
    679    int i;
    680 
    681    PZ_Lock(PBECache.lock);
    682    for (i = 0; i < KDF2_CACHE_COUNT; i++) {
    683        const KDFCacheItem *cacheItem = &PBECache.cacheKDF2.common[i];
    684        if (sftk_comparePBECommonCacheItemLocked(cacheItem,
    685                                                 pbe_param, pwItem)) {
    686            result = SECITEM_DupItem(cacheItem->hash);
    687            break;
    688        }
    689    }
    690    PZ_Unlock(PBECache.lock);
    691 
    692    return result;
    693 }
    694 
    695 static SECItem *
    696 sftk_getPBECacheKDF1(const NSSPKCS5PBEParameter *pbe_param,
    697                     const SECItem *pwItem,
    698                     PRBool faulty3DES)
    699 {
    700    SECItem *result = NULL;
    701    const KDFCacheItem *cacheItem = &PBECache.cacheKDF1.common;
    702 
    703    PZ_Lock(PBECache.lock);
    704    if (sftk_comparePBECommonCacheItemLocked(cacheItem, pbe_param, pwItem) &&
    705        PBECache.cacheKDF1.faulty3DES == faulty3DES &&
    706        PBECache.cacheKDF1.ivLen == pbe_param->ivLen) {
    707        result = SECITEM_DupItem(cacheItem->hash);
    708    }
    709    PZ_Unlock(PBECache.lock);
    710 
    711    return result;
    712 }
    713 
    714 void
    715 sftk_PBELockShutdown(void)
    716 {
    717    int i;
    718    if (PBECache.lock) {
    719        PZ_DestroyLock(PBECache.lock);
    720        PBECache.lock = 0;
    721    }
    722    sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF1.common);
    723    for (i = 0; i < KDF2_CACHE_COUNT; i++) {
    724        sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF2.common[i]);
    725    }
    726    PBECache.cacheKDF2.next = 0;
    727 }
    728 
    729 /*
    730 * generate key as per PKCS 5
    731 */
    732 SECItem *
    733 nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
    734                         SECItem *iv, PRBool faulty3DES)
    735 {
    736    SECItem *hash = NULL, *key = NULL;
    737    const SECHashObject *hashObj;
    738    PRBool getIV = PR_FALSE;
    739 
    740    if ((pbe_param == NULL) || (pwitem == NULL)) {
    741        return NULL;
    742    }
    743 
    744    key = SECITEM_AllocItem(NULL, NULL, pbe_param->keyLen);
    745    if (key == NULL) {
    746        return NULL;
    747    }
    748 
    749    if (iv && (pbe_param->ivLen) && (iv->data == NULL)) {
    750        getIV = PR_TRUE;
    751        iv->data = (unsigned char *)PORT_Alloc(pbe_param->ivLen);
    752        if (iv->data == NULL) {
    753            goto loser;
    754        }
    755        iv->len = pbe_param->ivLen;
    756    }
    757 
    758    hashObj = HASH_GetRawHashObject(pbe_param->hashType);
    759    switch (pbe_param->pbeType) {
    760        case NSSPKCS5_PBKDF1:
    761            hash = sftk_getPBECacheKDF1(pbe_param, pwitem, faulty3DES);
    762            if (!hash) {
    763                hash = nsspkcs5_PBKDF1Extended(hashObj, pbe_param, pwitem, faulty3DES);
    764                sftk_setPBECacheKDF1(hash, pbe_param, pwitem, faulty3DES);
    765            }
    766            if (hash == NULL) {
    767                goto loser;
    768            }
    769            PORT_Assert(hash->len >= key->len + (getIV ? iv->len : 0));
    770            if (getIV) {
    771                PORT_Memcpy(iv->data, hash->data + (hash->len - iv->len), iv->len);
    772            }
    773 
    774            break;
    775        case NSSPKCS5_PBKDF2:
    776            hash = sftk_getPBECacheKDF2(pbe_param, pwitem);
    777            if (!hash) {
    778                hash = nsspkcs5_PBKDF2(hashObj, pbe_param, pwitem);
    779                sftk_setPBECacheKDF2(hash, pbe_param, pwitem);
    780            }
    781            if (getIV) {
    782                PORT_Memcpy(iv->data, pbe_param->ivData, iv->len);
    783            }
    784            break;
    785        case NSSPKCS5_PKCS12_V2:
    786            if (getIV) {
    787                hash = nsspkcs5_PKCS12PBE(hashObj, pbe_param, pwitem,
    788                                          pbeBitGenCipherIV, iv->len);
    789                if (hash == NULL) {
    790                    goto loser;
    791                }
    792                PORT_Memcpy(iv->data, hash->data, iv->len);
    793                SECITEM_ZfreeItem(hash, PR_TRUE);
    794                hash = NULL;
    795            }
    796            hash = nsspkcs5_PKCS12PBE(hashObj, pbe_param, pwitem,
    797                                      pbe_param->keyID, key->len);
    798        default:
    799            break;
    800    }
    801 
    802    if (hash == NULL) {
    803        goto loser;
    804    }
    805 
    806    PORT_Memcpy(key->data, hash->data, key->len);
    807 
    808    SECITEM_ZfreeItem(hash, PR_TRUE);
    809    return key;
    810 
    811 loser:
    812    if (getIV && iv->data) {
    813        PORT_ZFree(iv->data, iv->len);
    814        iv->data = NULL;
    815    }
    816 
    817    SECITEM_ZfreeItem(key, PR_TRUE);
    818    return NULL;
    819 }
    820 
    821 #define MAX_IV_LENGTH 64
    822 /* get a random IV into the parameters */
    823 static SECStatus
    824 nsspkcs5_SetIVParam(NSSPKCS5PBEParameter *pbe_param, int ivLen)
    825 {
    826    SECStatus rv;
    827    SECItem derIV;
    828    SECItem iv;
    829    SECItem *dummy = NULL;
    830    unsigned char ivData[MAX_IV_LENGTH];
    831 
    832    PORT_Assert(ivLen <= MAX_IV_LENGTH);
    833 
    834    /* Because of a bug in the decode section, the IV's not are expected
    835     * to be der encoded, but still need to parse as if they were der data.
    836     * because we want to be compatible with existing versions of nss that
    837     * have that bug, create an IV that looks like der data. That still
    838     * leaves 14 bytes of entropy in the IV  */
    839    rv = RNG_GenerateGlobalRandomBytes(ivData, ivLen - 2);
    840    if (rv != SECSuccess) {
    841        return SECFailure;
    842    }
    843    derIV.data = NULL;
    844    derIV.len = 0;
    845    iv.data = ivData;
    846    iv.len = ivLen - 2;
    847    dummy = SEC_ASN1EncodeItem(pbe_param->poolp, &derIV, &iv,
    848                               SEC_ASN1_GET(SEC_OctetStringTemplate));
    849    if (dummy == NULL) {
    850        return SECFailure;
    851    }
    852    pbe_param->ivData = derIV.data;
    853    pbe_param->ivLen = derIV.len;
    854    PORT_Assert(pbe_param->ivLen == ivLen);
    855    return SECSuccess;
    856 }
    857 
    858 static SECStatus
    859 nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
    860                     NSSPKCS5PBEParameter *pbe_param)
    861 {
    862    PRBool skipType = PR_FALSE;
    863    SECStatus rv;
    864 
    865    pbe_param->keyLen = 5;
    866    pbe_param->ivLen = 8;
    867    pbe_param->hashType = hashType;
    868    pbe_param->pbeType = NSSPKCS5_PBKDF1;
    869    pbe_param->encAlg = SEC_OID_RC2_CBC;
    870    pbe_param->is2KeyDES = PR_FALSE;
    871    switch (algorithm) {
    872        /* DES3 Algorithms */
    873        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
    874            pbe_param->is2KeyDES = PR_TRUE;
    875            pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
    876            pbe_param->keyLen = 16;
    877            pbe_param->encAlg = SEC_OID_DES_EDE3_CBC;
    878            break;
    879        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
    880            pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
    881            pbe_param->keyLen = 24;
    882            pbe_param->encAlg = SEC_OID_DES_EDE3_CBC;
    883            break;
    884        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
    885            pbe_param->keyLen = 24;
    886            pbe_param->encAlg = SEC_OID_DES_EDE3_CBC;
    887            break;
    888 
    889        /* DES Algorithms */
    890        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
    891            pbe_param->hashType = HASH_AlgMD2;
    892            goto finish_des;
    893        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
    894            pbe_param->hashType = HASH_AlgMD5;
    895        /* fall through */
    896        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
    897        finish_des:
    898            pbe_param->keyLen = 8;
    899            pbe_param->encAlg = SEC_OID_DES_CBC;
    900            break;
    901 
    902 #ifndef NSS_DISABLE_DEPRECATED_RC2
    903        /* RC2 Algorithms */
    904        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
    905            pbe_param->keyLen = 16;
    906        /* fall through */
    907        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
    908            pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
    909            break;
    910        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
    911            pbe_param->keyLen = 16;
    912        /* fall through */
    913        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
    914            break;
    915 #endif
    916 
    917        /* RC4 algorithms */
    918        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
    919            skipType = PR_TRUE;
    920        /* fall through */
    921        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
    922            pbe_param->keyLen = 16;
    923        /* fall through */
    924        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
    925            if (!skipType) {
    926                pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
    927            }
    928        /* fall through */
    929        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
    930            pbe_param->ivLen = 0;
    931            pbe_param->encAlg = SEC_OID_RC4;
    932            break;
    933 
    934        case SEC_OID_PKCS5_PBKDF2:
    935        case SEC_OID_PKCS5_PBES2:
    936        case SEC_OID_PKCS5_PBMAC1:
    937            /* everything else will be filled in by the template */
    938            pbe_param->ivLen = 0;
    939            pbe_param->pbeType = NSSPKCS5_PBKDF2;
    940            pbe_param->encAlg = SEC_OID_PKCS5_PBKDF2;
    941            pbe_param->keyLen = 0; /* needs to be set by caller after return */
    942            break;
    943        /* AES uses PBKDF2 */
    944        case SEC_OID_AES_128_CBC:
    945            rv = nsspkcs5_SetIVParam(pbe_param, 16);
    946            if (rv != SECSuccess) {
    947                return rv;
    948            }
    949            pbe_param->ivLen = 16;
    950            pbe_param->pbeType = NSSPKCS5_PBKDF2;
    951            pbe_param->encAlg = algorithm;
    952            pbe_param->keyLen = 128 / 8;
    953            break;
    954        case SEC_OID_AES_192_CBC:
    955            rv = nsspkcs5_SetIVParam(pbe_param, 16);
    956            if (rv != SECSuccess) {
    957                return rv;
    958            }
    959            pbe_param->pbeType = NSSPKCS5_PBKDF2;
    960            pbe_param->encAlg = algorithm;
    961            pbe_param->keyLen = 192 / 8;
    962            break;
    963        case SEC_OID_AES_256_CBC:
    964            rv = nsspkcs5_SetIVParam(pbe_param, 16);
    965            if (rv != SECSuccess) {
    966                return rv;
    967            }
    968            pbe_param->pbeType = NSSPKCS5_PBKDF2;
    969            pbe_param->encAlg = algorithm;
    970            pbe_param->keyLen = 256 / 8;
    971            break;
    972        case SEC_OID_AES_128_KEY_WRAP:
    973            pbe_param->ivLen = 0;
    974            pbe_param->pbeType = NSSPKCS5_PBKDF2;
    975            pbe_param->encAlg = algorithm;
    976            pbe_param->keyLen = 128 / 8;
    977            break;
    978        case SEC_OID_AES_192_KEY_WRAP:
    979            pbe_param->ivLen = 0;
    980            pbe_param->pbeType = NSSPKCS5_PBKDF2;
    981            pbe_param->encAlg = algorithm;
    982            pbe_param->keyLen = 192 / 8;
    983            break;
    984        case SEC_OID_AES_256_KEY_WRAP:
    985            pbe_param->ivLen = 0;
    986            pbe_param->pbeType = NSSPKCS5_PBKDF2;
    987            pbe_param->encAlg = algorithm;
    988            pbe_param->keyLen = 256 / 8;
    989            break;
    990 
    991        default:
    992            return SECFailure;
    993    }
    994    if (pbe_param->pbeType == NSSPKCS5_PBKDF2) {
    995        SECOidTag prfAlg = HASH_HMACOidFromHash(pbe_param->hashType);
    996        if (prfAlg == SEC_OID_UNKNOWN) {
    997            return SECFailure;
    998        }
    999        rv = SECOID_SetAlgorithmID(pbe_param->poolp, &pbe_param->prfAlg,
   1000                                   prfAlg, NULL);
   1001        if (rv != SECSuccess) {
   1002            return rv;
   1003        }
   1004    }
   1005    return SECSuccess;
   1006 }
   1007 
   1008 /* decode the algid and generate a PKCS 5 parameter from it
   1009 */
   1010 NSSPKCS5PBEParameter *
   1011 nsspkcs5_NewParam(SECOidTag alg, HASH_HashType hashType, SECItem *salt,
   1012                  int iterationCount)
   1013 {
   1014    PLArenaPool *arena = NULL;
   1015    NSSPKCS5PBEParameter *pbe_param = NULL;
   1016    SECStatus rv = SECFailure;
   1017 
   1018    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   1019    if (arena == NULL)
   1020        return NULL;
   1021 
   1022    /* allocate memory for the parameter */
   1023    pbe_param = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena,
   1024                                                         sizeof(NSSPKCS5PBEParameter));
   1025 
   1026    if (pbe_param == NULL) {
   1027        goto loser;
   1028    }
   1029 
   1030    pbe_param->poolp = arena;
   1031 
   1032    rv = nsspkcs5_FillInParam(alg, hashType, pbe_param);
   1033    if (rv != SECSuccess) {
   1034        goto loser;
   1035    }
   1036 
   1037    pbe_param->iter = iterationCount;
   1038    if (salt) {
   1039        rv = SECITEM_CopyItem(arena, &pbe_param->salt, salt);
   1040    }
   1041 
   1042    /* default key gen */
   1043    pbe_param->keyID = pbeBitGenCipherKey;
   1044 
   1045 loser:
   1046    if (rv != SECSuccess) {
   1047        PORT_FreeArena(arena, PR_TRUE);
   1048        pbe_param = NULL;
   1049    }
   1050 
   1051    return pbe_param;
   1052 }
   1053 
   1054 /*
   1055 * find the hash type needed to implement a specific HMAC.
   1056 * OID definitions are from pkcs 5 v2.0 and 2.1
   1057 */
   1058 HASH_HashType
   1059 HASH_FromHMACOid(SECOidTag hmac)
   1060 {
   1061    switch (hmac) {
   1062        case SEC_OID_HMAC_SHA1:
   1063            return HASH_AlgSHA1;
   1064        case SEC_OID_HMAC_SHA256:
   1065            return HASH_AlgSHA256;
   1066        case SEC_OID_HMAC_SHA384:
   1067            return HASH_AlgSHA384;
   1068        case SEC_OID_HMAC_SHA512:
   1069            return HASH_AlgSHA512;
   1070        case SEC_OID_HMAC_SHA224:
   1071        default:
   1072            break;
   1073    }
   1074    return HASH_AlgNULL;
   1075 }
   1076 
   1077 SECOidTag
   1078 HASH_HMACOidFromHash(HASH_HashType hashType)
   1079 {
   1080    switch (hashType) {
   1081        case HASH_AlgSHA1:
   1082            return SEC_OID_HMAC_SHA1;
   1083        case HASH_AlgSHA256:
   1084            return SEC_OID_HMAC_SHA256;
   1085        case HASH_AlgSHA384:
   1086            return SEC_OID_HMAC_SHA384;
   1087        case HASH_AlgSHA512:
   1088            return SEC_OID_HMAC_SHA512;
   1089        case HASH_AlgSHA224:
   1090            return SEC_OID_HMAC_SHA224;
   1091        case HASH_AlgMD2:
   1092        case HASH_AlgMD5:
   1093        case HASH_AlgTOTAL:
   1094        default:
   1095            break;
   1096    }
   1097    return SEC_OID_UNKNOWN;
   1098 }
   1099 
   1100 /* decode the algid and generate a PKCS 5 parameter from it
   1101 */
   1102 NSSPKCS5PBEParameter *
   1103 nsspkcs5_AlgidToParam(SECAlgorithmID *algid)
   1104 {
   1105    NSSPKCS5PBEParameter *pbe_param = NULL;
   1106    nsspkcs5V2PBEParameter pbev2_param;
   1107    SECOidTag algorithm;
   1108    SECStatus rv = SECFailure;
   1109 
   1110    if (algid == NULL) {
   1111        return NULL;
   1112    }
   1113 
   1114    algorithm = SECOID_GetAlgorithmTag(algid);
   1115    if (algorithm == SEC_OID_UNKNOWN) {
   1116        goto loser;
   1117    }
   1118 
   1119    pbe_param = nsspkcs5_NewParam(algorithm, HASH_AlgSHA1, NULL, 1);
   1120    if (pbe_param == NULL) {
   1121        goto loser;
   1122    }
   1123 
   1124    /* decode parameter */
   1125    rv = SECFailure;
   1126    switch (pbe_param->pbeType) {
   1127        case NSSPKCS5_PBKDF1:
   1128            rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
   1129                                    NSSPKCS5PBEParameterTemplate, &algid->parameters);
   1130            break;
   1131        case NSSPKCS5_PKCS12_V2:
   1132            rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
   1133                                    NSSPKCS5PKCS12V2PBEParameterTemplate, &algid->parameters);
   1134            break;
   1135        case NSSPKCS5_PBKDF2:
   1136            PORT_Memset(&pbev2_param, 0, sizeof(pbev2_param));
   1137            /* just the PBE */
   1138            if (algorithm == SEC_OID_PKCS5_PBKDF2) {
   1139                rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
   1140                                        NSSPKCS5V2PBEParameterTemplate, &algid->parameters);
   1141            } else {
   1142                /* PBE data an others */
   1143                rv = SEC_ASN1DecodeItem(pbe_param->poolp, &pbev2_param,
   1144                                        NSSPKCS5V2PBES2ParameterTemplate, &algid->parameters);
   1145                if (rv != SECSuccess) {
   1146                    break;
   1147                }
   1148                pbe_param->encAlg = SECOID_GetAlgorithmTag(&pbev2_param.algParams);
   1149                rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
   1150                                        NSSPKCS5V2PBEParameterTemplate,
   1151                                        &pbev2_param.keyParams.parameters);
   1152                if (rv != SECSuccess) {
   1153                    break;
   1154                }
   1155                pbe_param->keyLen = DER_GetInteger(&pbe_param->keyLength);
   1156            }
   1157            /* we we are encrypting, save any iv's */
   1158            if (algorithm == SEC_OID_PKCS5_PBES2) {
   1159                pbe_param->ivLen = pbev2_param.algParams.parameters.len;
   1160                pbe_param->ivData = pbev2_param.algParams.parameters.data;
   1161            }
   1162            pbe_param->hashType =
   1163                HASH_FromHMACOid(SECOID_GetAlgorithmTag(&pbe_param->prfAlg));
   1164            if (pbe_param->hashType == HASH_AlgNULL) {
   1165                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   1166                rv = SECFailure;
   1167            }
   1168            break;
   1169    }
   1170 
   1171 loser:
   1172    PORT_Memset(&pbev2_param, 0, sizeof(pbev2_param));
   1173    if (rv == SECSuccess) {
   1174        pbe_param->iter = DER_GetInteger(&pbe_param->iteration);
   1175    } else {
   1176        nsspkcs5_DestroyPBEParameter(pbe_param);
   1177        pbe_param = NULL;
   1178    }
   1179 
   1180    return pbe_param;
   1181 }
   1182 
   1183 /* destroy a pbe parameter.  it assumes that the parameter was
   1184 * generated using the appropriate create function and therefor
   1185 * contains an arena pool.
   1186 */
   1187 void
   1188 nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param)
   1189 {
   1190    if (pbe_param != NULL) {
   1191        PORT_FreeArena(pbe_param->poolp, PR_TRUE);
   1192    }
   1193 }
   1194 
   1195 /* crypto routines */
   1196 /* perform DES encryption and decryption.  these routines are called
   1197 * by nsspkcs5_CipherData.  In the case of an error, NULL is returned.
   1198 */
   1199 static SECItem *
   1200 sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
   1201              PRBool encrypt)
   1202 {
   1203    SECItem *dest;
   1204    SECItem *dup_src;
   1205    CK_RV crv = CKR_DEVICE_ERROR;
   1206    int error;
   1207    SECStatus rv = SECFailure;
   1208    DESContext *ctxt;
   1209    unsigned int pad;
   1210 
   1211    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
   1212        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1213        return NULL;
   1214    }
   1215 
   1216    dup_src = SECITEM_DupItem(src);
   1217    if (dup_src == NULL) {
   1218        return NULL;
   1219    }
   1220 
   1221    if (encrypt != PR_FALSE) {
   1222        void *dummy;
   1223 
   1224        dummy = CBC_PadBuffer(NULL, dup_src->data,
   1225                              dup_src->len, &dup_src->len, DES_BLOCK_SIZE);
   1226        if (dummy == NULL) {
   1227            SECITEM_ZfreeItem(dup_src, PR_TRUE);
   1228            return NULL;
   1229        }
   1230        dup_src->data = (unsigned char *)dummy;
   1231    }
   1232 
   1233    dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
   1234    if (dest == NULL) {
   1235        goto loser;
   1236    }
   1237    ctxt = DES_CreateContext(key->data, iv->data,
   1238                             (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC),
   1239                             encrypt);
   1240    if (ctxt == NULL) {
   1241        goto loser;
   1242    }
   1243    rv = (encrypt ? DES_Encrypt : DES_Decrypt)(
   1244        ctxt, dest->data, &dest->len,
   1245        dest->len, dup_src->data, dup_src->len);
   1246 
   1247    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
   1248    error = PORT_GetError();
   1249 
   1250    /* remove padding */
   1251    if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
   1252        crv = sftk_CheckCBCPadding(dest->data, dest->len, DES_BLOCK_SIZE, &pad);
   1253        dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
   1254        PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
   1255    }
   1256    DES_DestroyContext(ctxt, PR_TRUE);
   1257 
   1258 loser:
   1259    if (crv != CKR_OK) {
   1260        if (dest != NULL) {
   1261            SECITEM_ZfreeItem(dest, PR_TRUE);
   1262        }
   1263        dest = NULL;
   1264    }
   1265 
   1266    if (dup_src != NULL) {
   1267        SECITEM_ZfreeItem(dup_src, PR_TRUE);
   1268    }
   1269 
   1270    return dest;
   1271 }
   1272 
   1273 /* perform aes encryption/decryption if an error occurs, NULL is returned
   1274 */
   1275 static SECItem *
   1276 sec_pkcs5_aes(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
   1277              PRBool encrypt)
   1278 {
   1279    SECItem *dest;
   1280    SECItem *dup_src;
   1281    CK_RV crv = CKR_DEVICE_ERROR;
   1282    int error;
   1283    SECStatus rv = SECFailure;
   1284    AESContext *ctxt;
   1285    unsigned int pad;
   1286 
   1287    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
   1288        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1289        return NULL;
   1290    }
   1291 
   1292    dup_src = SECITEM_DupItem(src);
   1293    if (dup_src == NULL) {
   1294        return NULL;
   1295    }
   1296 
   1297    if (encrypt != PR_FALSE) {
   1298        void *dummy;
   1299 
   1300        dummy = CBC_PadBuffer(NULL, dup_src->data,
   1301                              dup_src->len, &dup_src->len, AES_BLOCK_SIZE);
   1302        if (dummy == NULL) {
   1303            SECITEM_ZfreeItem(dup_src, PR_TRUE);
   1304            return NULL;
   1305        }
   1306        dup_src->data = (unsigned char *)dummy;
   1307    }
   1308 
   1309    dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
   1310    if (dest == NULL) {
   1311        goto loser;
   1312    }
   1313    ctxt = AES_CreateContext(key->data, iv->data, NSS_AES_CBC,
   1314                             encrypt, key->len, AES_BLOCK_SIZE);
   1315    if (ctxt == NULL) {
   1316        goto loser;
   1317    }
   1318    rv = (encrypt ? AES_Encrypt : AES_Decrypt)(
   1319        ctxt, dest->data, &dest->len,
   1320        dest->len, dup_src->data, dup_src->len);
   1321 
   1322    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
   1323    error = PORT_GetError();
   1324 
   1325    /* remove padding */
   1326    if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
   1327        crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE, &pad);
   1328        dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
   1329        PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
   1330    }
   1331    AES_DestroyContext(ctxt, PR_TRUE);
   1332 
   1333 loser:
   1334    if (crv != CKR_OK) {
   1335        if (dest != NULL) {
   1336            SECITEM_ZfreeItem(dest, PR_TRUE);
   1337        }
   1338        dest = NULL;
   1339    }
   1340 
   1341    if (dup_src != NULL) {
   1342        SECITEM_ZfreeItem(dup_src, PR_TRUE);
   1343    }
   1344 
   1345    return dest;
   1346 }
   1347 
   1348 /* perform aes encryption/decryption if an error occurs, NULL is returned
   1349 */
   1350 static SECItem *
   1351 sec_pkcs5_aes_key_wrap(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
   1352                       PRBool encrypt)
   1353 {
   1354    SECItem *dest;
   1355    SECItem *dup_src;
   1356    CK_RV crv = CKR_DEVICE_ERROR;
   1357    int error;
   1358    SECStatus rv = SECFailure;
   1359    AESKeyWrapContext *ctxt;
   1360    unsigned int pad;
   1361 
   1362    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
   1363        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1364        return NULL;
   1365    }
   1366 
   1367    dup_src = SECITEM_DupItem(src);
   1368    if (dup_src == NULL) {
   1369        return NULL;
   1370    }
   1371 
   1372    if (encrypt != PR_FALSE) {
   1373        void *dummy;
   1374 
   1375        dummy = CBC_PadBuffer(NULL, dup_src->data,
   1376                              dup_src->len, &dup_src->len, AES_BLOCK_SIZE);
   1377        if (dummy == NULL) {
   1378            SECITEM_ZfreeItem(dup_src, PR_TRUE);
   1379            return NULL;
   1380        }
   1381        dup_src->data = (unsigned char *)dummy;
   1382    }
   1383 
   1384    dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
   1385    if (dest == NULL) {
   1386        goto loser;
   1387    }
   1388    ctxt = AESKeyWrap_CreateContext(key->data, iv->data, encrypt,
   1389                                    key->len);
   1390 
   1391    if (ctxt == NULL) {
   1392        goto loser;
   1393    }
   1394    rv = (encrypt ? AESKeyWrap_Encrypt : AESKeyWrap_Decrypt)(
   1395        ctxt, dest->data, &dest->len,
   1396        dest->len, dup_src->data, dup_src->len);
   1397 
   1398    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
   1399    error = PORT_GetError();
   1400 
   1401    /* remove padding */
   1402    if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
   1403        crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE, &pad);
   1404        dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
   1405        PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
   1406    }
   1407    AESKeyWrap_DestroyContext(ctxt, PR_TRUE);
   1408 
   1409 loser:
   1410    if (crv != CKR_OK) {
   1411        if (dest != NULL) {
   1412            SECITEM_ZfreeItem(dest, PR_TRUE);
   1413        }
   1414        dest = NULL;
   1415    }
   1416 
   1417    if (dup_src != NULL) {
   1418        SECITEM_ZfreeItem(dup_src, PR_TRUE);
   1419    }
   1420 
   1421    return dest;
   1422 }
   1423 
   1424 #ifndef NSS_DISABLE_DEPRECATED_RC2
   1425 /* perform rc2 encryption/decryption if an error occurs, NULL is returned
   1426 */
   1427 static SECItem *
   1428 sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy,
   1429              PRBool encrypt)
   1430 {
   1431    SECItem *dest;
   1432    SECItem *dup_src;
   1433    SECStatus rv = SECFailure;
   1434    int pad;
   1435 
   1436    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
   1437        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1438        return NULL;
   1439    }
   1440 
   1441    dup_src = SECITEM_DupItem(src);
   1442    if (dup_src == NULL) {
   1443        return NULL;
   1444    }
   1445 
   1446    if (encrypt != PR_FALSE) {
   1447        void *v;
   1448 
   1449        v = CBC_PadBuffer(NULL, dup_src->data,
   1450                          dup_src->len, &dup_src->len, 8 /* RC2_BLOCK_SIZE */);
   1451        if (v == NULL) {
   1452            SECITEM_ZfreeItem(dup_src, PR_TRUE);
   1453            return NULL;
   1454        }
   1455        dup_src->data = (unsigned char *)v;
   1456    }
   1457 
   1458    dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
   1459    if (dest != NULL) {
   1460        dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
   1461        if (dest->data != NULL) {
   1462            RC2Context *ctxt;
   1463 
   1464            ctxt = RC2_CreateContext(key->data, key->len, iv->data,
   1465                                     NSS_RC2_CBC, key->len);
   1466 
   1467            if (ctxt != NULL) {
   1468                rv = (encrypt ? RC2_Encrypt : RC2_Decrypt)(
   1469                    ctxt, dest->data, &dest->len,
   1470                    dup_src->len + 64, dup_src->data, dup_src->len);
   1471 
   1472                /* assumes 8 byte blocks  -- remove padding */
   1473                if ((rv == SECSuccess) && (encrypt != PR_TRUE)) {
   1474                    pad = dest->data[dest->len - 1];
   1475                    if ((pad > 0) && (pad <= 8)) {
   1476                        if (dest->data[dest->len - pad] != pad) {
   1477                            PORT_SetError(SEC_ERROR_BAD_PASSWORD);
   1478                            rv = SECFailure;
   1479                        } else {
   1480                            dest->len -= pad;
   1481                        }
   1482                    } else {
   1483                        PORT_SetError(SEC_ERROR_BAD_PASSWORD);
   1484                        rv = SECFailure;
   1485                    }
   1486                }
   1487            }
   1488        }
   1489    }
   1490 
   1491    if ((rv != SECSuccess) && (dest != NULL)) {
   1492        SECITEM_ZfreeItem(dest, PR_TRUE);
   1493        dest = NULL;
   1494    }
   1495 
   1496    if (dup_src != NULL) {
   1497        SECITEM_ZfreeItem(dup_src, PR_TRUE);
   1498    }
   1499 
   1500    return dest;
   1501 }
   1502 #endif /* NSS_DISABLE_DEPRECATED_RC2 */
   1503 
   1504 /* perform rc4 encryption and decryption */
   1505 static SECItem *
   1506 sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op,
   1507              PRBool encrypt)
   1508 {
   1509    SECItem *dest;
   1510    SECStatus rv = SECFailure;
   1511 
   1512    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
   1513        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1514        return NULL;
   1515    }
   1516 
   1517    dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
   1518    if (dest != NULL) {
   1519        dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
   1520                                                  (src->len + 64));
   1521        if (dest->data != NULL) {
   1522            RC4Context *ctxt;
   1523 
   1524            ctxt = RC4_CreateContext(key->data, key->len);
   1525            if (ctxt) {
   1526                rv = (encrypt ? RC4_Encrypt : RC4_Decrypt)(
   1527                    ctxt, dest->data, &dest->len,
   1528                    src->len + 64, src->data, src->len);
   1529                RC4_DestroyContext(ctxt, PR_TRUE);
   1530            }
   1531        }
   1532    }
   1533 
   1534    if ((rv != SECSuccess) && (dest)) {
   1535        SECITEM_ZfreeItem(dest, PR_TRUE);
   1536        dest = NULL;
   1537    }
   1538 
   1539    return dest;
   1540 }
   1541 /* function pointer template for crypto functions */
   1542 typedef SECItem *(*pkcs5_crypto_func)(SECItem *key, SECItem *iv,
   1543                                      SECItem *src, PRBool op1, PRBool op2);
   1544 
   1545 /* performs the cipher operation on the src and returns the result.
   1546 * if an error occurs, NULL is returned.
   1547 *
   1548 * a null length password is allowed.  this corresponds to encrypting
   1549 * the data with ust the salt.
   1550 */
   1551 /* change this to use PKCS 11? */
   1552 SECItem *
   1553 nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
   1554                    SECItem *src, PRBool encrypt, PRBool *update)
   1555 {
   1556    SECItem *key = NULL, iv;
   1557    SECItem *dest = NULL;
   1558    PRBool tripleDES = PR_TRUE;
   1559    pkcs5_crypto_func cryptof;
   1560 
   1561    iv.data = NULL;
   1562 
   1563    if (update) {
   1564        *update = PR_FALSE;
   1565    }
   1566 
   1567    if ((pwitem == NULL) || (src == NULL)) {
   1568        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1569        return NULL;
   1570    }
   1571 
   1572    /* get key, and iv */
   1573    key = nsspkcs5_ComputeKeyAndIV(pbe_param, pwitem, &iv, PR_FALSE);
   1574    if (key == NULL) {
   1575        return NULL;
   1576    }
   1577 
   1578    switch (pbe_param->encAlg) {
   1579        /* PKCS 5 v2 only */
   1580        case SEC_OID_AES_128_KEY_WRAP:
   1581        case SEC_OID_AES_192_KEY_WRAP:
   1582        case SEC_OID_AES_256_KEY_WRAP:
   1583            cryptof = sec_pkcs5_aes_key_wrap;
   1584            break;
   1585        case SEC_OID_AES_128_CBC:
   1586        case SEC_OID_AES_192_CBC:
   1587        case SEC_OID_AES_256_CBC:
   1588            cryptof = sec_pkcs5_aes;
   1589            break;
   1590        case SEC_OID_DES_EDE3_CBC:
   1591            cryptof = sec_pkcs5_des;
   1592            tripleDES = PR_TRUE;
   1593            break;
   1594        case SEC_OID_DES_CBC:
   1595            cryptof = sec_pkcs5_des;
   1596            tripleDES = PR_FALSE;
   1597            break;
   1598 #ifndef NSS_DISABLE_DEPRECATED_RC2
   1599        case SEC_OID_RC2_CBC:
   1600            cryptof = sec_pkcs5_rc2;
   1601            break;
   1602 #endif
   1603        case SEC_OID_RC4:
   1604            cryptof = sec_pkcs5_rc4;
   1605            break;
   1606        default:
   1607            cryptof = NULL;
   1608            break;
   1609    }
   1610 
   1611    if (cryptof == NULL) {
   1612        goto loser;
   1613    }
   1614 
   1615    dest = (*cryptof)(key, &iv, src, tripleDES, encrypt);
   1616    /*
   1617     * it's possible for some keys and keydb's to claim to
   1618     * be triple des when they're really des. In this case
   1619     * we simply try des. If des works we set the update flag
   1620     * so the key db knows it needs to update all it's entries.
   1621     *  The case can only happen on decrypted of a
   1622     *  SEC_OID_DES_EDE3_CBD.
   1623     */
   1624    if ((pbe_param->encAlg == SEC_OID_DES_EDE3_CBC) &&
   1625        (dest == NULL) && (encrypt == PR_FALSE)) {
   1626        dest = (*cryptof)(key, &iv, src, PR_FALSE, encrypt);
   1627        if (update && (dest != NULL))
   1628            *update = PR_TRUE;
   1629    }
   1630 
   1631 loser:
   1632    if (key != NULL) {
   1633        SECITEM_ZfreeItem(key, PR_TRUE);
   1634    }
   1635    if (iv.data != NULL) {
   1636        SECITEM_ZfreeItem(&iv, PR_FALSE);
   1637    }
   1638 
   1639    return dest;
   1640 }
   1641 
   1642 /* creates a algorithm ID containing the PBE algorithm and appropriate
   1643 * parameters.  the required parameter is the algorithm.  if salt is
   1644 * not specified, it is generated randomly.  if IV is specified, it overrides
   1645 * the PKCS 5 generation of the IV.
   1646 *
   1647 * the returned SECAlgorithmID should be destroyed using
   1648 * SECOID_DestroyAlgorithmID
   1649 */
   1650 SECAlgorithmID *
   1651 nsspkcs5_CreateAlgorithmID(PLArenaPool *arena, SECOidTag algorithm,
   1652                           NSSPKCS5PBEParameter *pbe_param)
   1653 {
   1654    SECAlgorithmID *algid, *ret_algid = NULL;
   1655    SECItem der_param;
   1656    nsspkcs5V2PBEParameter pkcs5v2_param;
   1657 
   1658    SECStatus rv = SECFailure;
   1659    void *dummy = NULL;
   1660 
   1661    if (arena == NULL) {
   1662        return NULL;
   1663    }
   1664 
   1665    der_param.data = NULL;
   1666    der_param.len = 0;
   1667 
   1668    /* generate the algorithm id */
   1669    algid = (SECAlgorithmID *)PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID));
   1670    if (algid == NULL) {
   1671        goto loser;
   1672    }
   1673 
   1674    if (pbe_param->iteration.data == NULL) {
   1675        dummy = SEC_ASN1EncodeInteger(pbe_param->poolp, &pbe_param->iteration,
   1676                                      pbe_param->iter);
   1677        if (dummy == NULL) {
   1678            goto loser;
   1679        }
   1680    }
   1681    switch (pbe_param->pbeType) {
   1682        case NSSPKCS5_PBKDF1:
   1683            dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
   1684                                       NSSPKCS5PBEParameterTemplate);
   1685            break;
   1686        case NSSPKCS5_PKCS12_V2:
   1687            dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
   1688                                       NSSPKCS5PKCS12V2PBEParameterTemplate);
   1689            break;
   1690        case NSSPKCS5_PBKDF2:
   1691            if (pbe_param->keyLength.data == NULL) {
   1692                dummy = SEC_ASN1EncodeInteger(pbe_param->poolp,
   1693                                              &pbe_param->keyLength, pbe_param->keyLen);
   1694                if (dummy == NULL) {
   1695                    goto loser;
   1696                }
   1697            }
   1698            PORT_Memset(&pkcs5v2_param, 0, sizeof(pkcs5v2_param));
   1699            dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
   1700                                       NSSPKCS5V2PBEParameterTemplate);
   1701            if (dummy == NULL) {
   1702                break;
   1703            }
   1704            dummy = NULL;
   1705            rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.keyParams,
   1706                                       SEC_OID_PKCS5_PBKDF2, &der_param);
   1707            if (rv != SECSuccess) {
   1708                break;
   1709            }
   1710            der_param.data = pbe_param->ivData;
   1711            der_param.len = pbe_param->ivLen;
   1712            rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.algParams,
   1713                                       pbe_param->encAlg, pbe_param->ivLen ? &der_param : NULL);
   1714            if (rv != SECSuccess) {
   1715                dummy = NULL;
   1716                break;
   1717            }
   1718            der_param.data = NULL;
   1719            der_param.len = 0;
   1720            dummy = SEC_ASN1EncodeItem(arena, &der_param, &pkcs5v2_param,
   1721                                       NSSPKCS5V2PBES2ParameterTemplate);
   1722            /* If the algorithm was set to some encryption oid, set it
   1723             * to PBES2 */
   1724            if ((algorithm != SEC_OID_PKCS5_PBKDF2) &&
   1725                (algorithm != SEC_OID_PKCS5_PBMAC1)) {
   1726                algorithm = SEC_OID_PKCS5_PBES2;
   1727            }
   1728            break;
   1729        default:
   1730            break;
   1731    }
   1732 
   1733    if (dummy == NULL) {
   1734        goto loser;
   1735    }
   1736 
   1737    rv = SECOID_SetAlgorithmID(arena, algid, algorithm, &der_param);
   1738    if (rv != SECSuccess) {
   1739        goto loser;
   1740    }
   1741 
   1742    ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
   1743    if (ret_algid == NULL) {
   1744        goto loser;
   1745    }
   1746 
   1747    rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
   1748    if (rv != SECSuccess) {
   1749        SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
   1750        ret_algid = NULL;
   1751    }
   1752 
   1753 loser:
   1754 
   1755    return ret_algid;
   1756 }
   1757 
   1758 #define TEST_KEY "pbkdf test key"
   1759 SECStatus
   1760 sftk_fips_pbkdf_PowerUpSelfTests(void)
   1761 {
   1762    SECItem *result;
   1763    SECItem inKey;
   1764    NSSPKCS5PBEParameter pbe_params;
   1765    unsigned char iteration_count = 5;
   1766    unsigned char keyLen = 64;
   1767    char *inKeyData = TEST_KEY;
   1768    static const unsigned char saltData[] = {
   1769        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   1770        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
   1771    };
   1772 
   1773    static const unsigned char pbkdf_known_answer[] = {
   1774        0x73, 0x8c, 0xfa, 0x02, 0xe8, 0xdb, 0x43, 0xe4,
   1775        0x99, 0xc5, 0xfd, 0xd9, 0x4d, 0x8e, 0x3e, 0x7b,
   1776        0xc4, 0xda, 0x22, 0x1b, 0xe1, 0xae, 0x23, 0x7a,
   1777        0x21, 0x27, 0xbd, 0xcc, 0x78, 0xc4, 0xe6, 0xc5,
   1778        0x33, 0x38, 0x35, 0xe0, 0x68, 0x1a, 0x1e, 0x06,
   1779        0xad, 0xaf, 0x7f, 0xd7, 0x3f, 0x0e, 0xc0, 0x90,
   1780        0x17, 0x97, 0x73, 0x75, 0x7b, 0x88, 0x49, 0xd8,
   1781        0x6f, 0x78, 0x5a, 0xde, 0x50, 0x20, 0x55, 0x33
   1782    };
   1783 
   1784    sftk_PBELockInit();
   1785 
   1786    inKey.data = (unsigned char *)inKeyData;
   1787    inKey.len = sizeof(TEST_KEY) - 1;
   1788 
   1789    pbe_params.salt.data = (unsigned char *)saltData;
   1790    pbe_params.salt.len = sizeof(saltData);
   1791    /* the interation and keyLength are used as intermediate
   1792     * values when decoding the Algorithm ID, set them for completeness,
   1793     * but they are not used */
   1794    pbe_params.iteration.data = &iteration_count;
   1795    pbe_params.iteration.len = 1;
   1796    pbe_params.keyLength.data = &keyLen;
   1797    pbe_params.keyLength.len = 1;
   1798    /* pkcs5v2 stores the key in the AlgorithmID, so we don't need to
   1799     * generate it here */
   1800    pbe_params.ivLen = 0;
   1801    pbe_params.ivData = NULL;
   1802    /* keyID is only used by pkcs12 extensions to pkcs5v1 */
   1803    pbe_params.keyID = pbeBitGenCipherKey;
   1804    /* Algorithm is used by the decryption code after get get our key */
   1805    pbe_params.encAlg = SEC_OID_AES_256_CBC;
   1806    /* these are the fields actually used in nsspkcs5_ComputeKeyAndIV
   1807     * for NSSPKCS5_PBKDF2 */
   1808    pbe_params.iter = iteration_count;
   1809    pbe_params.keyLen = keyLen;
   1810    pbe_params.hashType = HASH_AlgSHA256;
   1811    pbe_params.pbeType = NSSPKCS5_PBKDF2;
   1812    pbe_params.is2KeyDES = PR_FALSE;
   1813 
   1814    result = nsspkcs5_ComputeKeyAndIV(&pbe_params, &inKey, NULL, PR_FALSE);
   1815    if ((result == NULL) || (result->len != sizeof(pbkdf_known_answer)) ||
   1816        (PORT_Memcmp(result->data, pbkdf_known_answer, sizeof(pbkdf_known_answer)) != 0)) {
   1817        SECITEM_FreeItem(result, PR_TRUE);
   1818        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1819        return SECFailure;
   1820    }
   1821    SECITEM_FreeItem(result, PR_TRUE);
   1822    return SECSuccess;
   1823 }