Coverage Report

Created: 2026-10-06 06:17

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