Coverage Report

Created: 2025-06-24 06:49

/src/nss/lib/softoken/lowpbe.c
Line
Count
Source (jump to first uncovered line)
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
0
#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
0
{
86
0
    void *ctx;
87
0
    unsigned int retLen;
88
89
0
    ctx = hashObj->create();
90
0
    if (ctx == NULL) {
91
0
        return SECFailure;
92
0
    }
93
0
    hashObj->begin(ctx);
94
0
    hashObj->update(ctx, src, len);
95
0
    hashObj->end(ctx, dest, &retLen, hashObj->length);
96
0
    hashObj->destroy(ctx, PR_TRUE);
97
0
    return SECSuccess;
98
0
}
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
0
{
106
0
    SECItem *hash = NULL, *pre_hash = NULL;
107
0
    SECStatus rv = SECFailure;
108
109
0
    if ((salt == NULL) || (pwd == NULL) || (iter < 0)) {
110
0
        return NULL;
111
0
    }
112
113
0
    hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
114
0
    pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
115
116
0
    if ((hash != NULL) && (pre_hash != NULL)) {
117
0
        int i, ph_len;
118
119
0
        ph_len = hashObj->length;
120
0
        if ((salt->len + pwd->len) > hashObj->length) {
121
0
            ph_len = salt->len + pwd->len;
122
0
        }
123
124
0
        rv = SECFailure;
125
126
        /* allocate buffers */
127
0
        hash->len = hashObj->length;
128
0
        hash->data = (unsigned char *)PORT_ZAlloc(hash->len);
129
0
        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
0
        if (faulty3DES) {
136
0
            pre_hash->len = ph_len;
137
0
        } else {
138
0
            pre_hash->len = salt->len + pwd->len;
139
0
        }
140
141
        /* preform hash */
142
0
        if ((hash->data != NULL) && (pre_hash->data != NULL)) {
143
0
            rv = SECSuccess;
144
            /* check for 0 length password */
145
0
            if (pwd->len > 0) {
146
0
                PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
147
0
            }
148
0
            if (salt->len > 0) {
149
0
                PORT_Memcpy((pre_hash->data + pwd->len), salt->data, salt->len);
150
0
            }
151
0
            for (i = 0; ((i < iter) && (rv == SECSuccess)); i++) {
152
0
                rv = nsspkcs5_HashBuf(hashObj, hash->data,
153
0
                                      pre_hash->data, pre_hash->len);
154
0
                if (rv != SECFailure) {
155
0
                    pre_hash->len = hashObj->length;
156
0
                    PORT_Memcpy(pre_hash->data, hash->data, hashObj->length);
157
0
                }
158
0
            }
159
0
        }
160
0
    }
161
162
0
    if (pre_hash != NULL) {
163
0
        SECITEM_ZfreeItem(pre_hash, PR_TRUE);
164
0
    }
165
166
0
    if ((rv != SECSuccess) && (hash != NULL)) {
167
0
        SECITEM_ZfreeItem(hash, PR_TRUE);
168
0
        hash = NULL;
169
0
    }
170
171
0
    return hash;
172
0
}
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
0
{
185
0
    SECItem *ret_bits = NULL;
186
0
    int hash_size = 0;
187
0
    unsigned int i;
188
0
    unsigned int hash_iter;
189
0
    unsigned int dig_len;
190
0
    SECStatus rv = SECFailure;
191
0
    unsigned char *state = NULL;
192
0
    unsigned int state_len;
193
0
    HMACContext *cx = NULL;
194
195
0
    hash_size = hashObj->length;
196
0
    hash_iter = (bytes_needed + (unsigned int)hash_size - 1) / hash_size;
197
198
    /* allocate return buffer */
199
0
    ret_bits = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
200
0
    if (ret_bits == NULL)
201
0
        return NULL;
202
0
    ret_bits->data = (unsigned char *)PORT_ZAlloc((hash_iter * hash_size) + 1);
203
0
    ret_bits->len = (hash_iter * hash_size);
204
0
    if (ret_bits->data == NULL) {
205
0
        PORT_Free(ret_bits);
206
0
        return NULL;
207
0
    }
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
0
    if ((unsigned int)hash_size > pbe_param->salt.len) {
214
0
        state_len = hash_size;
215
0
    } else {
216
0
        state_len = pbe_param->salt.len;
217
0
    }
218
0
    state = (unsigned char *)PORT_ZAlloc(state_len);
219
0
    if (state == NULL) {
220
0
        rv = SECFailure;
221
0
        goto loser;
222
0
    }
223
0
    if (pbe_param->salt.len > 0) {
224
0
        PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len);
225
0
    }
226
227
0
    cx = HMAC_Create(hashObj, init_hash->data, init_hash->len, PR_TRUE);
228
0
    if (cx == NULL) {
229
0
        rv = SECFailure;
230
0
        goto loser;
231
0
    }
232
233
0
    for (i = 0; i < hash_iter; i++) {
234
235
        /* generate output bits */
236
0
        HMAC_Begin(cx);
237
0
        HMAC_Update(cx, state, state_len);
238
0
        HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len);
239
0
        rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size),
240
0
                         &dig_len, hash_size);
241
0
        if (rv != SECSuccess)
242
0
            goto loser;
243
0
        PORT_Assert((unsigned int)hash_size == dig_len);
244
245
        /* generate new state */
246
0
        HMAC_Begin(cx);
247
0
        HMAC_Update(cx, state, state_len);
248
0
        rv = HMAC_Finish(cx, state, &state_len, state_len);
249
0
        if (rv != SECSuccess)
250
0
            goto loser;
251
0
        PORT_Assert(state_len == dig_len);
252
0
    }
253
254
0
loser:
255
0
    if (state != NULL)
256
0
        PORT_ZFree(state, state_len);
257
0
    HMAC_Destroy(cx, PR_TRUE);
258
259
0
    if (rv != SECSuccess) {
260
0
        SECITEM_ZfreeItem(ret_bits, PR_TRUE);
261
0
        ret_bits = NULL;
262
0
    }
263
264
0
    return ret_bits;
265
0
}
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
0
{
275
0
    SECItem *hash = NULL;
276
0
    SECItem *newHash = NULL;
277
0
    int bytes_needed;
278
0
    int bytes_available;
279
280
0
    bytes_needed = pbe_param->ivLen + pbe_param->keyLen;
281
0
    bytes_available = hashObj->length;
282
283
0
    hash = nsspkcs5_PBKDF1(hashObj, &pbe_param->salt, pwitem,
284
0
                           pbe_param->iter, faulty3DES);
285
286
0
    if (hash == NULL) {
287
0
        return NULL;
288
0
    }
289
290
0
    if (bytes_needed <= bytes_available) {
291
0
        return hash;
292
0
    }
293
294
0
    newHash = nsspkcs5_PFXPBE(hashObj, pbe_param, hash, bytes_needed);
295
0
    if (hash != newHash)
296
0
        SECITEM_ZfreeItem(hash, PR_TRUE);
297
0
    return newHash;
298
0
}
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
0
{
306
    /* use byt xor, not all platforms are happy about inaligned
307
     * integer fetches */
308
0
    while (len--) {
309
0
        *dest = *dest ^ *src;
310
0
        dest++;
311
0
        src++;
312
0
    }
313
0
}
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
0
{
319
0
    int j;
320
0
    HMACContext *cx = NULL;
321
0
    unsigned int hLen = hashobj->length;
322
0
    SECStatus rv = SECFailure;
323
0
    unsigned char *last = NULL;
324
0
    unsigned int lastLength = salt->len + 4;
325
0
    unsigned int lastBufLength;
326
327
0
    cx = HMAC_Create(hashobj, pwitem->data, pwitem->len, PR_FALSE);
328
0
    if (cx == NULL) {
329
0
        goto loser;
330
0
    }
331
0
    PORT_Memset(T, 0, hLen);
332
0
    lastBufLength = PR_MAX(lastLength, hLen);
333
0
    last = PORT_Alloc(lastBufLength);
334
0
    if (last == NULL) {
335
0
        goto loser;
336
0
    }
337
0
    PORT_Memcpy(last, salt->data, salt->len);
338
0
    last[salt->len] = (i >> 24) & 0xff;
339
0
    last[salt->len + 1] = (i >> 16) & 0xff;
340
0
    last[salt->len + 2] = (i >> 8) & 0xff;
341
0
    last[salt->len + 3] = i & 0xff;
342
343
    /* NOTE: we need at least one iteration to return success! */
344
0
    for (j = 0; j < iterations; j++) {
345
0
        HMAC_Begin(cx);
346
0
        HMAC_Update(cx, last, lastLength);
347
0
        rv = HMAC_Finish(cx, last, &lastLength, hLen);
348
0
        if (rv != SECSuccess) {
349
0
            break;
350
0
        }
351
0
        do_xor(T, last, hLen);
352
0
    }
353
0
loser:
354
0
    if (cx) {
355
0
        HMAC_Destroy(cx, PR_TRUE);
356
0
    }
357
0
    if (last) {
358
0
        PORT_ZFree(last, lastBufLength);
359
0
    }
360
0
    return rv;
361
0
}
362
363
static SECItem *
364
nsspkcs5_PBKDF2(const SECHashObject *hashobj, NSSPKCS5PBEParameter *pbe_param,
365
                SECItem *pwitem)
366
0
{
367
0
    int iterations = pbe_param->iter;
368
0
    int bytesNeeded = pbe_param->keyLen;
369
0
    unsigned int dkLen = bytesNeeded;
370
0
    unsigned int hLen = hashobj->length;
371
0
    unsigned int nblocks = (dkLen + hLen - 1) / hLen;
372
0
    unsigned int i;
373
0
    unsigned char *rp;
374
0
    unsigned char *T = NULL;
375
0
    SECItem *result = NULL;
376
0
    SECItem *salt = &pbe_param->salt;
377
0
    SECStatus rv = SECFailure;
378
379
0
    result = SECITEM_AllocItem(NULL, NULL, nblocks * hLen);
380
0
    if (result == NULL) {
381
0
        return NULL;
382
0
    }
383
384
0
    T = PORT_Alloc(hLen);
385
0
    if (T == NULL) {
386
0
        goto loser;
387
0
    }
388
389
0
    for (i = 1, rp = result->data; i <= nblocks; i++, rp += hLen) {
390
0
        rv = nsspkcs5_PBKDF2_F(hashobj, pwitem, salt, iterations, i, T);
391
0
        if (rv != SECSuccess) {
392
0
            break;
393
0
        }
394
0
        PORT_Memcpy(rp, T, hLen);
395
0
    }
396
397
0
loser:
398
0
    if (T) {
399
0
        PORT_ZFree(T, hLen);
400
0
    }
401
0
    if (rv != SECSuccess) {
402
0
        SECITEM_ZfreeItem(result, PR_TRUE);
403
0
        result = NULL;
404
0
    } else {
405
0
        result->len = dkLen;
406
0
    }
407
408
0
    return result;
409
0
}
410
411
0
#define NSSPBE_ROUNDUP(x, y) ((((x) + ((y)-1)) / (y)) * (y))
412
0
#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
0
{
421
0
    PLArenaPool *arena = NULL;
422
0
    unsigned int SLen, PLen;
423
0
    unsigned int hashLength = hashObject->length;
424
0
    unsigned char *S, *P;
425
0
    SECItem *A = NULL, B, D, I;
426
0
    SECItem *salt = &pbe_param->salt;
427
0
    unsigned int c, i = 0;
428
0
    unsigned int hashLen;
429
0
    int iter;
430
0
    unsigned char *iterBuf;
431
0
    void *hash = NULL;
432
0
    unsigned int bufferLength;
433
434
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
435
0
    if (!arena) {
436
0
        return NULL;
437
0
    }
438
439
    /* how many hash object lengths are needed */
440
0
    c = (bytesNeeded + (hashLength - 1)) / hashLength;
441
442
    /* 64 if 0 < hashLength <= 32, 128 if 32 < hashLength <= 64 */
443
0
    bufferLength = NSSPBE_ROUNDUP(hashLength * 2, 64);
444
445
    /* initialize our buffers */
446
0
    D.len = bufferLength;
447
    /* B and D are the same length, use one alloc go get both */
448
0
    D.data = (unsigned char *)PORT_ArenaZAlloc(arena, D.len * 2);
449
0
    B.len = D.len;
450
0
    B.data = D.data + D.len;
451
452
    /* if all goes well, A will be returned, so don't use our temp arena */
453
0
    A = SECITEM_AllocItem(NULL, NULL, c * hashLength);
454
0
    if (A == NULL) {
455
0
        goto loser;
456
0
    }
457
458
0
    SLen = NSSPBE_ROUNDUP(salt->len, bufferLength);
459
0
    PLen = NSSPBE_ROUNDUP(pwitem->len, bufferLength);
460
0
    I.len = SLen + PLen;
461
0
    I.data = (unsigned char *)PORT_ArenaZAlloc(arena, I.len);
462
0
    if (I.data == NULL) {
463
0
        goto loser;
464
0
    }
465
466
    /* S & P are only used to initialize I */
467
0
    S = I.data;
468
0
    P = S + SLen;
469
470
0
    PORT_Memset(D.data, (char)bitGenPurpose, D.len);
471
0
    if (SLen) {
472
0
        for (i = 0; i < SLen; i += salt->len) {
473
0
            PORT_Memcpy(S + i, salt->data, NSSPBE_MIN(SLen - i, salt->len));
474
0
        }
475
0
    }
476
0
    if (PLen) {
477
0
        for (i = 0; i < PLen; i += pwitem->len) {
478
0
            PORT_Memcpy(P + i, pwitem->data, NSSPBE_MIN(PLen - i, pwitem->len));
479
0
        }
480
0
    }
481
482
0
    iterBuf = (unsigned char *)PORT_ArenaZAlloc(arena, hashLength);
483
0
    if (iterBuf == NULL) {
484
0
        goto loser;
485
0
    }
486
487
0
    hash = hashObject->create();
488
0
    if (!hash) {
489
0
        goto loser;
490
0
    }
491
    /* calculate the PBE now */
492
0
    for (i = 0; i < c; i++) {
493
0
        int Bidx; /* must be signed or the for loop won't terminate */
494
0
        unsigned int k, j;
495
0
        unsigned char *Ai = A->data + i * hashLength;
496
497
0
        for (iter = 0; iter < pbe_param->iter; iter++) {
498
0
            hashObject->begin(hash);
499
500
0
            if (iter) {
501
0
                hashObject->update(hash, iterBuf, hashLen);
502
0
            } else {
503
0
                hashObject->update(hash, D.data, D.len);
504
0
                hashObject->update(hash, I.data, I.len);
505
0
            }
506
507
0
            hashObject->end(hash, iterBuf, &hashLen, hashObject->length);
508
0
            if (hashLen != hashObject->length) {
509
0
                break;
510
0
            }
511
0
        }
512
513
0
        PORT_Memcpy(Ai, iterBuf, hashLength);
514
0
        for (Bidx = 0; Bidx < (int)B.len; Bidx += hashLength) {
515
0
            PORT_Memcpy(B.data + Bidx, iterBuf, NSSPBE_MIN(B.len - Bidx, hashLength));
516
0
        }
517
518
0
        k = I.len / B.len;
519
0
        for (j = 0; j < k; j++) {
520
0
            unsigned int q, carryBit;
521
0
            unsigned char *Ij = I.data + j * B.len;
522
523
            /* (Ij = Ij+B+1) */
524
0
            for (Bidx = (B.len - 1), q = 1, carryBit = 0; Bidx >= 0; Bidx--, q = 0) {
525
0
                q += (unsigned int)Ij[Bidx];
526
0
                q += (unsigned int)B.data[Bidx];
527
0
                q += carryBit;
528
529
0
                carryBit = (q > 0xff);
530
0
                Ij[Bidx] = (unsigned char)(q & 0xff);
531
0
            }
532
0
        }
533
0
    }
534
0
loser:
535
0
    if (hash) {
536
0
        hashObject->destroy(hash, PR_TRUE);
537
0
    }
538
0
    if (arena) {
539
0
        PORT_FreeArena(arena, PR_TRUE);
540
0
    }
541
542
0
    if (A) {
543
        /* if i != c, then we didn't complete the loop above and must of failed
544
         * somwhere along the way */
545
0
        if (i != c) {
546
0
            SECITEM_ZfreeItem(A, PR_TRUE);
547
0
            A = NULL;
548
0
        } else {
549
0
            A->len = bytesNeeded;
550
0
        }
551
0
    }
552
553
0
    return A;
554
0
}
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
1.66k
#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
11
{
586
11
    if (!PBECache.lock) {
587
11
        PBECache.lock = PZ_NewLock(nssIPBECacheLock);
588
11
    }
589
11
}
590
591
static void
592
sftk_clearPBECommonCacheItemsLocked(KDFCacheItem *item)
593
1.66k
{
594
1.66k
    if (item->hash) {
595
0
        SECITEM_ZfreeItem(item->hash, PR_TRUE);
596
0
        item->hash = NULL;
597
0
    }
598
1.66k
    if (item->salt) {
599
0
        SECITEM_ZfreeItem(item->salt, PR_TRUE);
600
0
        item->salt = NULL;
601
0
    }
602
1.66k
    if (item->pwItem) {
603
0
        SECITEM_ZfreeItem(item->pwItem, PR_TRUE);
604
0
        item->pwItem = NULL;
605
0
    }
606
1.66k
}
607
608
static void
609
sftk_setPBECommonCacheItemsKDFLocked(KDFCacheItem *cacheItem,
610
                                     const SECItem *hash,
611
                                     const NSSPKCS5PBEParameter *pbe_param,
612
                                     const SECItem *pwItem)
613
0
{
614
0
    cacheItem->hash = SECITEM_DupItem(hash);
615
0
    cacheItem->hashType = pbe_param->hashType;
616
0
    cacheItem->iterations = pbe_param->iter;
617
0
    cacheItem->keyLen = pbe_param->keyLen;
618
0
    cacheItem->salt = SECITEM_DupItem(&pbe_param->salt);
619
0
    cacheItem->pwItem = SECITEM_DupItem(pwItem);
620
0
}
621
622
static void
623
sftk_setPBECacheKDF2(const SECItem *hash,
624
                     const NSSPKCS5PBEParameter *pbe_param,
625
                     const SECItem *pwItem)
626
0
{
627
0
    PZ_Lock(PBECache.lock);
628
0
    KDFCacheItem *next = &PBECache.cacheKDF2.common[PBECache.cacheKDF2.next];
629
630
0
    sftk_clearPBECommonCacheItemsLocked(next);
631
632
0
    sftk_setPBECommonCacheItemsKDFLocked(next, hash, pbe_param, pwItem);
633
0
    PBECache.cacheKDF2.next++;
634
0
    if (PBECache.cacheKDF2.next >= KDF2_CACHE_COUNT) {
635
0
        PBECache.cacheKDF2.next = 0;
636
0
    }
637
638
0
    PZ_Unlock(PBECache.lock);
639
0
}
640
641
static void
642
sftk_setPBECacheKDF1(const SECItem *hash,
643
                     const NSSPKCS5PBEParameter *pbe_param,
644
                     const SECItem *pwItem,
645
                     PRBool faulty3DES)
646
0
{
647
0
    PZ_Lock(PBECache.lock);
648
649
0
    sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF1.common);
650
651
0
    sftk_setPBECommonCacheItemsKDFLocked(&PBECache.cacheKDF1.common,
652
0
                                         hash, pbe_param, pwItem);
653
0
    PBECache.cacheKDF1.faulty3DES = faulty3DES;
654
0
    PBECache.cacheKDF1.ivLen = pbe_param->ivLen;
655
656
0
    PZ_Unlock(PBECache.lock);
657
0
}
658
659
static PRBool
660
sftk_comparePBECommonCacheItemLocked(const KDFCacheItem *cacheItem,
661
                                     const NSSPKCS5PBEParameter *pbe_param,
662
                                     const SECItem *pwItem)
663
0
{
664
0
    return (cacheItem->hash &&
665
0
            cacheItem->salt &&
666
0
            cacheItem->pwItem &&
667
0
            pbe_param->hashType == cacheItem->hashType &&
668
0
            pbe_param->iter == cacheItem->iterations &&
669
0
            pbe_param->keyLen == cacheItem->keyLen &&
670
0
            SECITEM_ItemsAreEqual(&pbe_param->salt, cacheItem->salt) &&
671
0
            SECITEM_ItemsAreEqual(pwItem, cacheItem->pwItem));
672
0
}
673
674
static SECItem *
675
sftk_getPBECacheKDF2(const NSSPKCS5PBEParameter *pbe_param,
676
                     const SECItem *pwItem)
677
0
{
678
0
    SECItem *result = NULL;
679
0
    int i;
680
681
0
    PZ_Lock(PBECache.lock);
682
0
    for (i = 0; i < KDF2_CACHE_COUNT; i++) {
683
0
        const KDFCacheItem *cacheItem = &PBECache.cacheKDF2.common[i];
684
0
        if (sftk_comparePBECommonCacheItemLocked(cacheItem,
685
0
                                                 pbe_param, pwItem)) {
686
0
            result = SECITEM_DupItem(cacheItem->hash);
687
0
            break;
688
0
        }
689
0
    }
690
0
    PZ_Unlock(PBECache.lock);
691
692
0
    return result;
693
0
}
694
695
static SECItem *
696
sftk_getPBECacheKDF1(const NSSPKCS5PBEParameter *pbe_param,
697
                     const SECItem *pwItem,
698
                     PRBool faulty3DES)
699
0
{
700
0
    SECItem *result = NULL;
701
0
    const KDFCacheItem *cacheItem = &PBECache.cacheKDF1.common;
702
703
0
    PZ_Lock(PBECache.lock);
704
0
    if (sftk_comparePBECommonCacheItemLocked(cacheItem, pbe_param, pwItem) &&
705
0
        PBECache.cacheKDF1.faulty3DES == faulty3DES &&
706
0
        PBECache.cacheKDF1.ivLen == pbe_param->ivLen) {
707
0
        result = SECITEM_DupItem(cacheItem->hash);
708
0
    }
709
0
    PZ_Unlock(PBECache.lock);
710
711
0
    return result;
712
0
}
713
714
void
715
sftk_PBELockShutdown(void)
716
11
{
717
11
    int i;
718
11
    if (PBECache.lock) {
719
11
        PZ_DestroyLock(PBECache.lock);
720
11
        PBECache.lock = 0;
721
11
    }
722
11
    sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF1.common);
723
1.66k
    for (i = 0; i < KDF2_CACHE_COUNT; i++) {
724
1.65k
        sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF2.common[i]);
725
1.65k
    }
726
11
    PBECache.cacheKDF2.next = 0;
727
11
}
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
0
{
736
0
    SECItem *hash = NULL, *key = NULL;
737
0
    const SECHashObject *hashObj;
738
0
    PRBool getIV = PR_FALSE;
739
740
0
    if ((pbe_param == NULL) || (pwitem == NULL)) {
741
0
        return NULL;
742
0
    }
743
744
0
    key = SECITEM_AllocItem(NULL, NULL, pbe_param->keyLen);
745
0
    if (key == NULL) {
746
0
        return NULL;
747
0
    }
748
749
0
    if (iv && (pbe_param->ivLen) && (iv->data == NULL)) {
750
0
        getIV = PR_TRUE;
751
0
        iv->data = (unsigned char *)PORT_Alloc(pbe_param->ivLen);
752
0
        if (iv->data == NULL) {
753
0
            goto loser;
754
0
        }
755
0
        iv->len = pbe_param->ivLen;
756
0
    }
757
758
0
    hashObj = HASH_GetRawHashObject(pbe_param->hashType);
759
0
    switch (pbe_param->pbeType) {
760
0
        case NSSPKCS5_PBKDF1:
761
0
            hash = sftk_getPBECacheKDF1(pbe_param, pwitem, faulty3DES);
762
0
            if (!hash) {
763
0
                hash = nsspkcs5_PBKDF1Extended(hashObj, pbe_param, pwitem, faulty3DES);
764
0
                sftk_setPBECacheKDF1(hash, pbe_param, pwitem, faulty3DES);
765
0
            }
766
0
            if (hash == NULL) {
767
0
                goto loser;
768
0
            }
769
0
            PORT_Assert(hash->len >= key->len + (getIV ? iv->len : 0));
770
0
            if (getIV) {
771
0
                PORT_Memcpy(iv->data, hash->data + (hash->len - iv->len), iv->len);
772
0
            }
773
774
0
            break;
775
0
        case NSSPKCS5_PBKDF2:
776
0
            hash = sftk_getPBECacheKDF2(pbe_param, pwitem);
777
0
            if (!hash) {
778
0
                hash = nsspkcs5_PBKDF2(hashObj, pbe_param, pwitem);
779
0
                sftk_setPBECacheKDF2(hash, pbe_param, pwitem);
780
0
            }
781
0
            if (getIV) {
782
0
                PORT_Memcpy(iv->data, pbe_param->ivData, iv->len);
783
0
            }
784
0
            break;
785
0
        case NSSPKCS5_PKCS12_V2:
786
0
            if (getIV) {
787
0
                hash = nsspkcs5_PKCS12PBE(hashObj, pbe_param, pwitem,
788
0
                                          pbeBitGenCipherIV, iv->len);
789
0
                if (hash == NULL) {
790
0
                    goto loser;
791
0
                }
792
0
                PORT_Memcpy(iv->data, hash->data, iv->len);
793
0
                SECITEM_ZfreeItem(hash, PR_TRUE);
794
0
                hash = NULL;
795
0
            }
796
0
            hash = nsspkcs5_PKCS12PBE(hashObj, pbe_param, pwitem,
797
0
                                      pbe_param->keyID, key->len);
798
0
        default:
799
0
            break;
800
0
    }
801
802
0
    if (hash == NULL) {
803
0
        goto loser;
804
0
    }
805
806
0
    PORT_Memcpy(key->data, hash->data, key->len);
807
808
0
    SECITEM_ZfreeItem(hash, PR_TRUE);
809
0
    return key;
810
811
0
loser:
812
0
    if (getIV && iv->data) {
813
0
        PORT_ZFree(iv->data, iv->len);
814
0
        iv->data = NULL;
815
0
    }
816
817
0
    SECITEM_ZfreeItem(key, PR_TRUE);
818
0
    return NULL;
819
0
}
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
0
{
826
0
    SECStatus rv;
827
0
    SECItem derIV;
828
0
    SECItem iv;
829
0
    SECItem *dummy = NULL;
830
0
    unsigned char ivData[MAX_IV_LENGTH];
831
832
0
    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
0
    rv = RNG_GenerateGlobalRandomBytes(ivData, ivLen - 2);
840
0
    if (rv != SECSuccess) {
841
0
        return SECFailure;
842
0
    }
843
0
    derIV.data = NULL;
844
0
    derIV.len = 0;
845
0
    iv.data = ivData;
846
0
    iv.len = ivLen - 2;
847
0
    dummy = SEC_ASN1EncodeItem(pbe_param->poolp, &derIV, &iv,
848
0
                               SEC_ASN1_GET(SEC_OctetStringTemplate));
849
0
    if (dummy == NULL) {
850
0
        return SECFailure;
851
0
    }
852
0
    pbe_param->ivData = derIV.data;
853
0
    pbe_param->ivLen = derIV.len;
854
0
    PORT_Assert(pbe_param->ivLen == ivLen);
855
0
    return SECSuccess;
856
0
}
857
858
static SECStatus
859
nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
860
                     NSSPKCS5PBEParameter *pbe_param)
861
0
{
862
0
    PRBool skipType = PR_FALSE;
863
0
    SECStatus rv;
864
865
0
    pbe_param->keyLen = 5;
866
0
    pbe_param->ivLen = 8;
867
0
    pbe_param->hashType = hashType;
868
0
    pbe_param->pbeType = NSSPKCS5_PBKDF1;
869
0
    pbe_param->encAlg = SEC_OID_RC2_CBC;
870
0
    pbe_param->is2KeyDES = PR_FALSE;
871
0
    switch (algorithm) {
872
        /* DES3 Algorithms */
873
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
874
0
            pbe_param->is2KeyDES = PR_TRUE;
875
0
            pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
876
0
            pbe_param->keyLen = 16;
877
0
            pbe_param->encAlg = SEC_OID_DES_EDE3_CBC;
878
0
            break;
879
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
880
0
            pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
881
0
            pbe_param->keyLen = 24;
882
0
            pbe_param->encAlg = SEC_OID_DES_EDE3_CBC;
883
0
            break;
884
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
885
0
            pbe_param->keyLen = 24;
886
0
            pbe_param->encAlg = SEC_OID_DES_EDE3_CBC;
887
0
            break;
888
889
        /* DES Algorithms */
890
0
        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
891
0
            pbe_param->hashType = HASH_AlgMD2;
892
0
            goto finish_des;
893
0
        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
894
0
            pbe_param->hashType = HASH_AlgMD5;
895
        /* fall through */
896
0
        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
897
0
        finish_des:
898
0
            pbe_param->keyLen = 8;
899
0
            pbe_param->encAlg = SEC_OID_DES_CBC;
900
0
            break;
901
902
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
903
        /* RC2 Algorithms */
904
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
905
0
            pbe_param->keyLen = 16;
906
        /* fall through */
907
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
908
0
            pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
909
0
            break;
910
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
911
0
            pbe_param->keyLen = 16;
912
        /* fall through */
913
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
914
0
            break;
915
0
#endif
916
917
        /* RC4 algorithms */
918
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
919
0
            skipType = PR_TRUE;
920
        /* fall through */
921
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
922
0
            pbe_param->keyLen = 16;
923
        /* fall through */
924
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
925
0
            if (!skipType) {
926
0
                pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
927
0
            }
928
        /* fall through */
929
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
930
0
            pbe_param->ivLen = 0;
931
0
            pbe_param->encAlg = SEC_OID_RC4;
932
0
            break;
933
934
0
        case SEC_OID_PKCS5_PBKDF2:
935
0
        case SEC_OID_PKCS5_PBES2:
936
0
        case SEC_OID_PKCS5_PBMAC1:
937
            /* everything else will be filled in by the template */
938
0
            pbe_param->ivLen = 0;
939
0
            pbe_param->pbeType = NSSPKCS5_PBKDF2;
940
0
            pbe_param->encAlg = SEC_OID_PKCS5_PBKDF2;
941
0
            pbe_param->keyLen = 0; /* needs to be set by caller after return */
942
0
            break;
943
        /* AES uses PBKDF2 */
944
0
        case SEC_OID_AES_128_CBC:
945
0
            rv = nsspkcs5_SetIVParam(pbe_param, 16);
946
0
            if (rv != SECSuccess) {
947
0
                return rv;
948
0
            }
949
0
            pbe_param->ivLen = 16;
950
0
            pbe_param->pbeType = NSSPKCS5_PBKDF2;
951
0
            pbe_param->encAlg = algorithm;
952
0
            pbe_param->keyLen = 128 / 8;
953
0
            break;
954
0
        case SEC_OID_AES_192_CBC:
955
0
            rv = nsspkcs5_SetIVParam(pbe_param, 16);
956
0
            if (rv != SECSuccess) {
957
0
                return rv;
958
0
            }
959
0
            pbe_param->pbeType = NSSPKCS5_PBKDF2;
960
0
            pbe_param->encAlg = algorithm;
961
0
            pbe_param->keyLen = 192 / 8;
962
0
            break;
963
0
        case SEC_OID_AES_256_CBC:
964
0
            rv = nsspkcs5_SetIVParam(pbe_param, 16);
965
0
            if (rv != SECSuccess) {
966
0
                return rv;
967
0
            }
968
0
            pbe_param->pbeType = NSSPKCS5_PBKDF2;
969
0
            pbe_param->encAlg = algorithm;
970
0
            pbe_param->keyLen = 256 / 8;
971
0
            break;
972
0
        case SEC_OID_AES_128_KEY_WRAP:
973
0
            pbe_param->ivLen = 0;
974
0
            pbe_param->pbeType = NSSPKCS5_PBKDF2;
975
0
            pbe_param->encAlg = algorithm;
976
0
            pbe_param->keyLen = 128 / 8;
977
0
            break;
978
0
        case SEC_OID_AES_192_KEY_WRAP:
979
0
            pbe_param->ivLen = 0;
980
0
            pbe_param->pbeType = NSSPKCS5_PBKDF2;
981
0
            pbe_param->encAlg = algorithm;
982
0
            pbe_param->keyLen = 192 / 8;
983
0
            break;
984
0
        case SEC_OID_AES_256_KEY_WRAP:
985
0
            pbe_param->ivLen = 0;
986
0
            pbe_param->pbeType = NSSPKCS5_PBKDF2;
987
0
            pbe_param->encAlg = algorithm;
988
0
            pbe_param->keyLen = 256 / 8;
989
0
            break;
990
991
0
        default:
992
0
            return SECFailure;
993
0
    }
994
0
    if (pbe_param->pbeType == NSSPKCS5_PBKDF2) {
995
0
        SECOidTag prfAlg = HASH_HMACOidFromHash(pbe_param->hashType);
996
0
        if (prfAlg == SEC_OID_UNKNOWN) {
997
0
            return SECFailure;
998
0
        }
999
0
        rv = SECOID_SetAlgorithmID(pbe_param->poolp, &pbe_param->prfAlg,
1000
0
                                   prfAlg, NULL);
1001
0
        if (rv != SECSuccess) {
1002
0
            return rv;
1003
0
        }
1004
0
    }
1005
0
    return SECSuccess;
1006
0
}
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
0
{
1014
0
    PLArenaPool *arena = NULL;
1015
0
    NSSPKCS5PBEParameter *pbe_param = NULL;
1016
0
    SECStatus rv = SECFailure;
1017
1018
0
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
1019
0
    if (arena == NULL)
1020
0
        return NULL;
1021
1022
    /* allocate memory for the parameter */
1023
0
    pbe_param = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena,
1024
0
                                                         sizeof(NSSPKCS5PBEParameter));
1025
1026
0
    if (pbe_param == NULL) {
1027
0
        goto loser;
1028
0
    }
1029
1030
0
    pbe_param->poolp = arena;
1031
1032
0
    rv = nsspkcs5_FillInParam(alg, hashType, pbe_param);
1033
0
    if (rv != SECSuccess) {
1034
0
        goto loser;
1035
0
    }
1036
1037
0
    pbe_param->iter = iterationCount;
1038
0
    if (salt) {
1039
0
        rv = SECITEM_CopyItem(arena, &pbe_param->salt, salt);
1040
0
    }
1041
1042
    /* default key gen */
1043
0
    pbe_param->keyID = pbeBitGenCipherKey;
1044
1045
0
loser:
1046
0
    if (rv != SECSuccess) {
1047
0
        PORT_FreeArena(arena, PR_TRUE);
1048
0
        pbe_param = NULL;
1049
0
    }
1050
1051
0
    return pbe_param;
1052
0
}
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
0
{
1061
0
    switch (hmac) {
1062
0
        case SEC_OID_HMAC_SHA1:
1063
0
            return HASH_AlgSHA1;
1064
0
        case SEC_OID_HMAC_SHA256:
1065
0
            return HASH_AlgSHA256;
1066
0
        case SEC_OID_HMAC_SHA384:
1067
0
            return HASH_AlgSHA384;
1068
0
        case SEC_OID_HMAC_SHA512:
1069
0
            return HASH_AlgSHA512;
1070
0
        case SEC_OID_HMAC_SHA224:
1071
0
        default:
1072
0
            break;
1073
0
    }
1074
0
    return HASH_AlgNULL;
1075
0
}
1076
1077
SECOidTag
1078
HASH_HMACOidFromHash(HASH_HashType hashType)
1079
0
{
1080
0
    switch (hashType) {
1081
0
        case HASH_AlgSHA1:
1082
0
            return SEC_OID_HMAC_SHA1;
1083
0
        case HASH_AlgSHA256:
1084
0
            return SEC_OID_HMAC_SHA256;
1085
0
        case HASH_AlgSHA384:
1086
0
            return SEC_OID_HMAC_SHA384;
1087
0
        case HASH_AlgSHA512:
1088
0
            return SEC_OID_HMAC_SHA512;
1089
0
        case HASH_AlgSHA224:
1090
0
            return SEC_OID_HMAC_SHA224;
1091
0
        case HASH_AlgMD2:
1092
0
        case HASH_AlgMD5:
1093
0
        case HASH_AlgTOTAL:
1094
0
        default:
1095
0
            break;
1096
0
    }
1097
0
    return SEC_OID_UNKNOWN;
1098
0
}
1099
1100
/* decode the algid and generate a PKCS 5 parameter from it
1101
 */
1102
NSSPKCS5PBEParameter *
1103
nsspkcs5_AlgidToParam(SECAlgorithmID *algid)
1104
0
{
1105
0
    NSSPKCS5PBEParameter *pbe_param = NULL;
1106
0
    nsspkcs5V2PBEParameter pbev2_param;
1107
0
    SECOidTag algorithm;
1108
0
    SECStatus rv = SECFailure;
1109
1110
0
    if (algid == NULL) {
1111
0
        return NULL;
1112
0
    }
1113
1114
0
    algorithm = SECOID_GetAlgorithmTag(algid);
1115
0
    if (algorithm == SEC_OID_UNKNOWN) {
1116
0
        goto loser;
1117
0
    }
1118
1119
0
    pbe_param = nsspkcs5_NewParam(algorithm, HASH_AlgSHA1, NULL, 1);
1120
0
    if (pbe_param == NULL) {
1121
0
        goto loser;
1122
0
    }
1123
1124
    /* decode parameter */
1125
0
    rv = SECFailure;
1126
0
    switch (pbe_param->pbeType) {
1127
0
        case NSSPKCS5_PBKDF1:
1128
0
            rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
1129
0
                                    NSSPKCS5PBEParameterTemplate, &algid->parameters);
1130
0
            break;
1131
0
        case NSSPKCS5_PKCS12_V2:
1132
0
            rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
1133
0
                                    NSSPKCS5PKCS12V2PBEParameterTemplate, &algid->parameters);
1134
0
            break;
1135
0
        case NSSPKCS5_PBKDF2:
1136
0
            PORT_Memset(&pbev2_param, 0, sizeof(pbev2_param));
1137
            /* just the PBE */
1138
0
            if (algorithm == SEC_OID_PKCS5_PBKDF2) {
1139
0
                rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
1140
0
                                        NSSPKCS5V2PBEParameterTemplate, &algid->parameters);
1141
0
            } else {
1142
                /* PBE data an others */
1143
0
                rv = SEC_ASN1DecodeItem(pbe_param->poolp, &pbev2_param,
1144
0
                                        NSSPKCS5V2PBES2ParameterTemplate, &algid->parameters);
1145
0
                if (rv != SECSuccess) {
1146
0
                    break;
1147
0
                }
1148
0
                pbe_param->encAlg = SECOID_GetAlgorithmTag(&pbev2_param.algParams);
1149
0
                rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
1150
0
                                        NSSPKCS5V2PBEParameterTemplate,
1151
0
                                        &pbev2_param.keyParams.parameters);
1152
0
                if (rv != SECSuccess) {
1153
0
                    break;
1154
0
                }
1155
0
                pbe_param->keyLen = DER_GetInteger(&pbe_param->keyLength);
1156
0
            }
1157
            /* we we are encrypting, save any iv's */
1158
0
            if (algorithm == SEC_OID_PKCS5_PBES2) {
1159
0
                pbe_param->ivLen = pbev2_param.algParams.parameters.len;
1160
0
                pbe_param->ivData = pbev2_param.algParams.parameters.data;
1161
0
            }
1162
0
            pbe_param->hashType =
1163
0
                HASH_FromHMACOid(SECOID_GetAlgorithmTag(&pbe_param->prfAlg));
1164
0
            if (pbe_param->hashType == HASH_AlgNULL) {
1165
0
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1166
0
                rv = SECFailure;
1167
0
            }
1168
0
            break;
1169
0
    }
1170
1171
0
loser:
1172
0
    PORT_Memset(&pbev2_param, 0, sizeof(pbev2_param));
1173
0
    if (rv == SECSuccess) {
1174
0
        pbe_param->iter = DER_GetInteger(&pbe_param->iteration);
1175
0
    } else {
1176
0
        nsspkcs5_DestroyPBEParameter(pbe_param);
1177
0
        pbe_param = NULL;
1178
0
    }
1179
1180
0
    return pbe_param;
1181
0
}
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
0
{
1190
0
    if (pbe_param != NULL) {
1191
0
        PORT_FreeArena(pbe_param->poolp, PR_TRUE);
1192
0
    }
1193
0
}
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
0
{
1203
0
    SECItem *dest;
1204
0
    SECItem *dup_src;
1205
0
    CK_RV crv = CKR_DEVICE_ERROR;
1206
0
    int error;
1207
0
    SECStatus rv = SECFailure;
1208
0
    DESContext *ctxt;
1209
0
    unsigned int pad;
1210
1211
0
    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
1212
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1213
0
        return NULL;
1214
0
    }
1215
1216
0
    dup_src = SECITEM_DupItem(src);
1217
0
    if (dup_src == NULL) {
1218
0
        return NULL;
1219
0
    }
1220
1221
0
    if (encrypt != PR_FALSE) {
1222
0
        void *dummy;
1223
1224
0
        dummy = CBC_PadBuffer(NULL, dup_src->data,
1225
0
                              dup_src->len, &dup_src->len, DES_BLOCK_SIZE);
1226
0
        if (dummy == NULL) {
1227
0
            SECITEM_ZfreeItem(dup_src, PR_TRUE);
1228
0
            return NULL;
1229
0
        }
1230
0
        dup_src->data = (unsigned char *)dummy;
1231
0
    }
1232
1233
0
    dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
1234
0
    if (dest == NULL) {
1235
0
        goto loser;
1236
0
    }
1237
0
    ctxt = DES_CreateContext(key->data, iv->data,
1238
0
                             (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC),
1239
0
                             encrypt);
1240
0
    if (ctxt == NULL) {
1241
0
        goto loser;
1242
0
    }
1243
0
    rv = (encrypt ? DES_Encrypt : DES_Decrypt)(
1244
0
        ctxt, dest->data, &dest->len,
1245
0
        dest->len, dup_src->data, dup_src->len);
1246
1247
0
    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
1248
0
    error = PORT_GetError();
1249
1250
    /* remove padding */
1251
0
    if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
1252
0
        crv = sftk_CheckCBCPadding(dest->data, dest->len, DES_BLOCK_SIZE, &pad);
1253
0
        dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
1254
0
        PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
1255
0
    }
1256
0
    DES_DestroyContext(ctxt, PR_TRUE);
1257
1258
0
loser:
1259
0
    if (crv != CKR_OK) {
1260
0
        if (dest != NULL) {
1261
0
            SECITEM_ZfreeItem(dest, PR_TRUE);
1262
0
        }
1263
0
        dest = NULL;
1264
0
    }
1265
1266
0
    if (dup_src != NULL) {
1267
0
        SECITEM_ZfreeItem(dup_src, PR_TRUE);
1268
0
    }
1269
1270
0
    return dest;
1271
0
}
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
0
{
1279
0
    SECItem *dest;
1280
0
    SECItem *dup_src;
1281
0
    CK_RV crv = CKR_DEVICE_ERROR;
1282
0
    int error;
1283
0
    SECStatus rv = SECFailure;
1284
0
    AESContext *ctxt;
1285
0
    unsigned int pad;
1286
1287
0
    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
1288
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1289
0
        return NULL;
1290
0
    }
1291
1292
0
    dup_src = SECITEM_DupItem(src);
1293
0
    if (dup_src == NULL) {
1294
0
        return NULL;
1295
0
    }
1296
1297
0
    if (encrypt != PR_FALSE) {
1298
0
        void *dummy;
1299
1300
0
        dummy = CBC_PadBuffer(NULL, dup_src->data,
1301
0
                              dup_src->len, &dup_src->len, AES_BLOCK_SIZE);
1302
0
        if (dummy == NULL) {
1303
0
            SECITEM_ZfreeItem(dup_src, PR_TRUE);
1304
0
            return NULL;
1305
0
        }
1306
0
        dup_src->data = (unsigned char *)dummy;
1307
0
    }
1308
1309
0
    dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
1310
0
    if (dest == NULL) {
1311
0
        goto loser;
1312
0
    }
1313
0
    ctxt = AES_CreateContext(key->data, iv->data, NSS_AES_CBC,
1314
0
                             encrypt, key->len, AES_BLOCK_SIZE);
1315
0
    if (ctxt == NULL) {
1316
0
        goto loser;
1317
0
    }
1318
0
    rv = (encrypt ? AES_Encrypt : AES_Decrypt)(
1319
0
        ctxt, dest->data, &dest->len,
1320
0
        dest->len, dup_src->data, dup_src->len);
1321
1322
0
    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
1323
0
    error = PORT_GetError();
1324
1325
    /* remove padding */
1326
0
    if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
1327
0
        crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE, &pad);
1328
0
        dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
1329
0
        PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
1330
0
    }
1331
0
    AES_DestroyContext(ctxt, PR_TRUE);
1332
1333
0
loser:
1334
0
    if (crv != CKR_OK) {
1335
0
        if (dest != NULL) {
1336
0
            SECITEM_ZfreeItem(dest, PR_TRUE);
1337
0
        }
1338
0
        dest = NULL;
1339
0
    }
1340
1341
0
    if (dup_src != NULL) {
1342
0
        SECITEM_ZfreeItem(dup_src, PR_TRUE);
1343
0
    }
1344
1345
0
    return dest;
1346
0
}
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
0
{
1354
0
    SECItem *dest;
1355
0
    SECItem *dup_src;
1356
0
    CK_RV crv = CKR_DEVICE_ERROR;
1357
0
    int error;
1358
0
    SECStatus rv = SECFailure;
1359
0
    AESKeyWrapContext *ctxt;
1360
0
    unsigned int pad;
1361
1362
0
    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
1363
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1364
0
        return NULL;
1365
0
    }
1366
1367
0
    dup_src = SECITEM_DupItem(src);
1368
0
    if (dup_src == NULL) {
1369
0
        return NULL;
1370
0
    }
1371
1372
0
    if (encrypt != PR_FALSE) {
1373
0
        void *dummy;
1374
1375
0
        dummy = CBC_PadBuffer(NULL, dup_src->data,
1376
0
                              dup_src->len, &dup_src->len, AES_BLOCK_SIZE);
1377
0
        if (dummy == NULL) {
1378
0
            SECITEM_ZfreeItem(dup_src, PR_TRUE);
1379
0
            return NULL;
1380
0
        }
1381
0
        dup_src->data = (unsigned char *)dummy;
1382
0
    }
1383
1384
0
    dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
1385
0
    if (dest == NULL) {
1386
0
        goto loser;
1387
0
    }
1388
0
    ctxt = AESKeyWrap_CreateContext(key->data, iv->data, encrypt,
1389
0
                                    key->len);
1390
1391
0
    if (ctxt == NULL) {
1392
0
        goto loser;
1393
0
    }
1394
0
    rv = (encrypt ? AESKeyWrap_Encrypt : AESKeyWrap_Decrypt)(
1395
0
        ctxt, dest->data, &dest->len,
1396
0
        dest->len, dup_src->data, dup_src->len);
1397
1398
0
    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
1399
0
    error = PORT_GetError();
1400
1401
    /* remove padding */
1402
0
    if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
1403
0
        crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE, &pad);
1404
0
        dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
1405
0
        PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
1406
0
    }
1407
0
    AESKeyWrap_DestroyContext(ctxt, PR_TRUE);
1408
1409
0
loser:
1410
0
    if (crv != CKR_OK) {
1411
0
        if (dest != NULL) {
1412
0
            SECITEM_ZfreeItem(dest, PR_TRUE);
1413
0
        }
1414
0
        dest = NULL;
1415
0
    }
1416
1417
0
    if (dup_src != NULL) {
1418
0
        SECITEM_ZfreeItem(dup_src, PR_TRUE);
1419
0
    }
1420
1421
0
    return dest;
1422
0
}
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
0
{
1431
0
    SECItem *dest;
1432
0
    SECItem *dup_src;
1433
0
    SECStatus rv = SECFailure;
1434
0
    int pad;
1435
1436
0
    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
1437
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1438
0
        return NULL;
1439
0
    }
1440
1441
0
    dup_src = SECITEM_DupItem(src);
1442
0
    if (dup_src == NULL) {
1443
0
        return NULL;
1444
0
    }
1445
1446
0
    if (encrypt != PR_FALSE) {
1447
0
        void *v;
1448
1449
0
        v = CBC_PadBuffer(NULL, dup_src->data,
1450
0
                          dup_src->len, &dup_src->len, 8 /* RC2_BLOCK_SIZE */);
1451
0
        if (v == NULL) {
1452
0
            SECITEM_ZfreeItem(dup_src, PR_TRUE);
1453
0
            return NULL;
1454
0
        }
1455
0
        dup_src->data = (unsigned char *)v;
1456
0
    }
1457
1458
0
    dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
1459
0
    if (dest != NULL) {
1460
0
        dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
1461
0
        if (dest->data != NULL) {
1462
0
            RC2Context *ctxt;
1463
1464
0
            ctxt = RC2_CreateContext(key->data, key->len, iv->data,
1465
0
                                     NSS_RC2_CBC, key->len);
1466
1467
0
            if (ctxt != NULL) {
1468
0
                rv = (encrypt ? RC2_Encrypt : RC2_Decrypt)(
1469
0
                    ctxt, dest->data, &dest->len,
1470
0
                    dup_src->len + 64, dup_src->data, dup_src->len);
1471
1472
                /* assumes 8 byte blocks  -- remove padding */
1473
0
                if ((rv == SECSuccess) && (encrypt != PR_TRUE)) {
1474
0
                    pad = dest->data[dest->len - 1];
1475
0
                    if ((pad > 0) && (pad <= 8)) {
1476
0
                        if (dest->data[dest->len - pad] != pad) {
1477
0
                            PORT_SetError(SEC_ERROR_BAD_PASSWORD);
1478
0
                            rv = SECFailure;
1479
0
                        } else {
1480
0
                            dest->len -= pad;
1481
0
                        }
1482
0
                    } else {
1483
0
                        PORT_SetError(SEC_ERROR_BAD_PASSWORD);
1484
0
                        rv = SECFailure;
1485
0
                    }
1486
0
                }
1487
0
            }
1488
0
        }
1489
0
    }
1490
1491
0
    if ((rv != SECSuccess) && (dest != NULL)) {
1492
0
        SECITEM_ZfreeItem(dest, PR_TRUE);
1493
0
        dest = NULL;
1494
0
    }
1495
1496
0
    if (dup_src != NULL) {
1497
0
        SECITEM_ZfreeItem(dup_src, PR_TRUE);
1498
0
    }
1499
1500
0
    return dest;
1501
0
}
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
0
{
1509
0
    SECItem *dest;
1510
0
    SECStatus rv = SECFailure;
1511
1512
0
    if ((src == NULL) || (key == NULL) || (iv == NULL)) {
1513
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1514
0
        return NULL;
1515
0
    }
1516
1517
0
    dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
1518
0
    if (dest != NULL) {
1519
0
        dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
1520
0
                                                  (src->len + 64));
1521
0
        if (dest->data != NULL) {
1522
0
            RC4Context *ctxt;
1523
1524
0
            ctxt = RC4_CreateContext(key->data, key->len);
1525
0
            if (ctxt) {
1526
0
                rv = (encrypt ? RC4_Encrypt : RC4_Decrypt)(
1527
0
                    ctxt, dest->data, &dest->len,
1528
0
                    src->len + 64, src->data, src->len);
1529
0
                RC4_DestroyContext(ctxt, PR_TRUE);
1530
0
            }
1531
0
        }
1532
0
    }
1533
1534
0
    if ((rv != SECSuccess) && (dest)) {
1535
0
        SECITEM_ZfreeItem(dest, PR_TRUE);
1536
0
        dest = NULL;
1537
0
    }
1538
1539
0
    return dest;
1540
0
}
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
0
{
1556
0
    SECItem *key = NULL, iv;
1557
0
    SECItem *dest = NULL;
1558
0
    PRBool tripleDES = PR_TRUE;
1559
0
    pkcs5_crypto_func cryptof;
1560
1561
0
    iv.data = NULL;
1562
1563
0
    if (update) {
1564
0
        *update = PR_FALSE;
1565
0
    }
1566
1567
0
    if ((pwitem == NULL) || (src == NULL)) {
1568
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1569
0
        return NULL;
1570
0
    }
1571
1572
    /* get key, and iv */
1573
0
    key = nsspkcs5_ComputeKeyAndIV(pbe_param, pwitem, &iv, PR_FALSE);
1574
0
    if (key == NULL) {
1575
0
        return NULL;
1576
0
    }
1577
1578
0
    switch (pbe_param->encAlg) {
1579
        /* PKCS 5 v2 only */
1580
0
        case SEC_OID_AES_128_KEY_WRAP:
1581
0
        case SEC_OID_AES_192_KEY_WRAP:
1582
0
        case SEC_OID_AES_256_KEY_WRAP:
1583
0
            cryptof = sec_pkcs5_aes_key_wrap;
1584
0
            break;
1585
0
        case SEC_OID_AES_128_CBC:
1586
0
        case SEC_OID_AES_192_CBC:
1587
0
        case SEC_OID_AES_256_CBC:
1588
0
            cryptof = sec_pkcs5_aes;
1589
0
            break;
1590
0
        case SEC_OID_DES_EDE3_CBC:
1591
0
            cryptof = sec_pkcs5_des;
1592
0
            tripleDES = PR_TRUE;
1593
0
            break;
1594
0
        case SEC_OID_DES_CBC:
1595
0
            cryptof = sec_pkcs5_des;
1596
0
            tripleDES = PR_FALSE;
1597
0
            break;
1598
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
1599
0
        case SEC_OID_RC2_CBC:
1600
0
            cryptof = sec_pkcs5_rc2;
1601
0
            break;
1602
0
#endif
1603
0
        case SEC_OID_RC4:
1604
0
            cryptof = sec_pkcs5_rc4;
1605
0
            break;
1606
0
        default:
1607
0
            cryptof = NULL;
1608
0
            break;
1609
0
    }
1610
1611
0
    if (cryptof == NULL) {
1612
0
        goto loser;
1613
0
    }
1614
1615
0
    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
0
    if ((pbe_param->encAlg == SEC_OID_DES_EDE3_CBC) &&
1625
0
        (dest == NULL) && (encrypt == PR_FALSE)) {
1626
0
        dest = (*cryptof)(key, &iv, src, PR_FALSE, encrypt);
1627
0
        if (update && (dest != NULL))
1628
0
            *update = PR_TRUE;
1629
0
    }
1630
1631
0
loser:
1632
0
    if (key != NULL) {
1633
0
        SECITEM_ZfreeItem(key, PR_TRUE);
1634
0
    }
1635
0
    if (iv.data != NULL) {
1636
0
        SECITEM_ZfreeItem(&iv, PR_FALSE);
1637
0
    }
1638
1639
0
    return dest;
1640
0
}
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
0
{
1654
0
    SECAlgorithmID *algid, *ret_algid = NULL;
1655
0
    SECItem der_param;
1656
0
    nsspkcs5V2PBEParameter pkcs5v2_param;
1657
1658
0
    SECStatus rv = SECFailure;
1659
0
    void *dummy = NULL;
1660
1661
0
    if (arena == NULL) {
1662
0
        return NULL;
1663
0
    }
1664
1665
0
    der_param.data = NULL;
1666
0
    der_param.len = 0;
1667
1668
    /* generate the algorithm id */
1669
0
    algid = (SECAlgorithmID *)PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID));
1670
0
    if (algid == NULL) {
1671
0
        goto loser;
1672
0
    }
1673
1674
0
    if (pbe_param->iteration.data == NULL) {
1675
0
        dummy = SEC_ASN1EncodeInteger(pbe_param->poolp, &pbe_param->iteration,
1676
0
                                      pbe_param->iter);
1677
0
        if (dummy == NULL) {
1678
0
            goto loser;
1679
0
        }
1680
0
    }
1681
0
    switch (pbe_param->pbeType) {
1682
0
        case NSSPKCS5_PBKDF1:
1683
0
            dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
1684
0
                                       NSSPKCS5PBEParameterTemplate);
1685
0
            break;
1686
0
        case NSSPKCS5_PKCS12_V2:
1687
0
            dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
1688
0
                                       NSSPKCS5PKCS12V2PBEParameterTemplate);
1689
0
            break;
1690
0
        case NSSPKCS5_PBKDF2:
1691
0
            if (pbe_param->keyLength.data == NULL) {
1692
0
                dummy = SEC_ASN1EncodeInteger(pbe_param->poolp,
1693
0
                                              &pbe_param->keyLength, pbe_param->keyLen);
1694
0
                if (dummy == NULL) {
1695
0
                    goto loser;
1696
0
                }
1697
0
            }
1698
0
            PORT_Memset(&pkcs5v2_param, 0, sizeof(pkcs5v2_param));
1699
0
            dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
1700
0
                                       NSSPKCS5V2PBEParameterTemplate);
1701
0
            if (dummy == NULL) {
1702
0
                break;
1703
0
            }
1704
0
            dummy = NULL;
1705
0
            rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.keyParams,
1706
0
                                       SEC_OID_PKCS5_PBKDF2, &der_param);
1707
0
            if (rv != SECSuccess) {
1708
0
                break;
1709
0
            }
1710
0
            der_param.data = pbe_param->ivData;
1711
0
            der_param.len = pbe_param->ivLen;
1712
0
            rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.algParams,
1713
0
                                       pbe_param->encAlg, pbe_param->ivLen ? &der_param : NULL);
1714
0
            if (rv != SECSuccess) {
1715
0
                dummy = NULL;
1716
0
                break;
1717
0
            }
1718
0
            der_param.data = NULL;
1719
0
            der_param.len = 0;
1720
0
            dummy = SEC_ASN1EncodeItem(arena, &der_param, &pkcs5v2_param,
1721
0
                                       NSSPKCS5V2PBES2ParameterTemplate);
1722
            /* If the algorithm was set to some encryption oid, set it
1723
             * to PBES2 */
1724
0
            if ((algorithm != SEC_OID_PKCS5_PBKDF2) &&
1725
0
                (algorithm != SEC_OID_PKCS5_PBMAC1)) {
1726
0
                algorithm = SEC_OID_PKCS5_PBES2;
1727
0
            }
1728
0
            break;
1729
0
        default:
1730
0
            break;
1731
0
    }
1732
1733
0
    if (dummy == NULL) {
1734
0
        goto loser;
1735
0
    }
1736
1737
0
    rv = SECOID_SetAlgorithmID(arena, algid, algorithm, &der_param);
1738
0
    if (rv != SECSuccess) {
1739
0
        goto loser;
1740
0
    }
1741
1742
0
    ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
1743
0
    if (ret_algid == NULL) {
1744
0
        goto loser;
1745
0
    }
1746
1747
0
    rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
1748
0
    if (rv != SECSuccess) {
1749
0
        SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
1750
0
        ret_algid = NULL;
1751
0
    }
1752
1753
0
loser:
1754
1755
0
    return ret_algid;
1756
0
}
1757
1758
0
#define TEST_KEY "pbkdf test key"
1759
SECStatus
1760
sftk_fips_pbkdf_PowerUpSelfTests(void)
1761
0
{
1762
0
    SECItem *result;
1763
0
    SECItem inKey;
1764
0
    NSSPKCS5PBEParameter pbe_params;
1765
0
    unsigned char iteration_count = 5;
1766
0
    unsigned char keyLen = 64;
1767
0
    char *inKeyData = TEST_KEY;
1768
0
    static const unsigned char saltData[] = {
1769
0
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1770
0
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
1771
0
    };
1772
1773
0
    static const unsigned char pbkdf_known_answer[] = {
1774
0
        0x73, 0x8c, 0xfa, 0x02, 0xe8, 0xdb, 0x43, 0xe4,
1775
0
        0x99, 0xc5, 0xfd, 0xd9, 0x4d, 0x8e, 0x3e, 0x7b,
1776
0
        0xc4, 0xda, 0x22, 0x1b, 0xe1, 0xae, 0x23, 0x7a,
1777
0
        0x21, 0x27, 0xbd, 0xcc, 0x78, 0xc4, 0xe6, 0xc5,
1778
0
        0x33, 0x38, 0x35, 0xe0, 0x68, 0x1a, 0x1e, 0x06,
1779
0
        0xad, 0xaf, 0x7f, 0xd7, 0x3f, 0x0e, 0xc0, 0x90,
1780
0
        0x17, 0x97, 0x73, 0x75, 0x7b, 0x88, 0x49, 0xd8,
1781
0
        0x6f, 0x78, 0x5a, 0xde, 0x50, 0x20, 0x55, 0x33
1782
0
    };
1783
1784
0
    sftk_PBELockInit();
1785
1786
0
    inKey.data = (unsigned char *)inKeyData;
1787
0
    inKey.len = sizeof(TEST_KEY) - 1;
1788
1789
0
    pbe_params.salt.data = (unsigned char *)saltData;
1790
0
    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
0
    pbe_params.iteration.data = &iteration_count;
1795
0
    pbe_params.iteration.len = 1;
1796
0
    pbe_params.keyLength.data = &keyLen;
1797
0
    pbe_params.keyLength.len = 1;
1798
    /* pkcs5v2 stores the key in the AlgorithmID, so we don't need to
1799
     * generate it here */
1800
0
    pbe_params.ivLen = 0;
1801
0
    pbe_params.ivData = NULL;
1802
    /* keyID is only used by pkcs12 extensions to pkcs5v1 */
1803
0
    pbe_params.keyID = pbeBitGenCipherKey;
1804
    /* Algorithm is used by the decryption code after get get our key */
1805
0
    pbe_params.encAlg = SEC_OID_AES_256_CBC;
1806
    /* these are the fields actually used in nsspkcs5_ComputeKeyAndIV
1807
     * for NSSPKCS5_PBKDF2 */
1808
0
    pbe_params.iter = iteration_count;
1809
0
    pbe_params.keyLen = keyLen;
1810
0
    pbe_params.hashType = HASH_AlgSHA256;
1811
0
    pbe_params.pbeType = NSSPKCS5_PBKDF2;
1812
0
    pbe_params.is2KeyDES = PR_FALSE;
1813
1814
0
    result = nsspkcs5_ComputeKeyAndIV(&pbe_params, &inKey, NULL, PR_FALSE);
1815
0
    if ((result == NULL) || (result->len != sizeof(pbkdf_known_answer)) ||
1816
0
        (PORT_Memcmp(result->data, pbkdf_known_answer, sizeof(pbkdf_known_answer)) != 0)) {
1817
0
        SECITEM_FreeItem(result, PR_TRUE);
1818
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1819
0
        return SECFailure;
1820
0
    }
1821
0
    SECITEM_FreeItem(result, PR_TRUE);
1822
0
    return SECSuccess;
1823
0
}