Coverage Report

Created: 2024-05-20 06:23

/src/nss/lib/pk11wrap/pk11pbe.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 "blapit.h"
8
#include "seccomon.h"
9
#include "secitem.h"
10
#include "secport.h"
11
#include "hasht.h"
12
#include "pkcs11t.h"
13
#include "sechash.h"
14
#include "secasn1.h"
15
#include "secder.h"
16
#include "secoid.h"
17
#include "secerr.h"
18
#include "secmod.h"
19
#include "pk11func.h"
20
#include "secpkcs5.h"
21
#include "secmodi.h"
22
#include "secmodti.h"
23
#include "pkcs11.h"
24
#include "pk11func.h"
25
#include "secitem.h"
26
#include "keyhi.h"
27
28
typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter;
29
struct SEC_PKCS5PBEParameterStr {
30
    PLArenaPool *poolp;
31
    SECItem salt;              /* octet string */
32
    SECItem iteration;         /* integer */
33
    SECItem keyLength;         /* PKCS5v2 only */
34
    SECAlgorithmID *pPrfAlgId; /* PKCS5v2 only */
35
    SECAlgorithmID prfAlgId;   /* PKCS5v2 only */
36
};
37
38
/* PKCS5 V2 has an algorithm ID for the encryption and for
39
 * the key generation. This is valid for SEC_OID_PKCS5_PBES2
40
 * and SEC_OID_PKCS5_PBMAC1
41
 */
42
struct sec_pkcs5V2ParameterStr {
43
    PLArenaPool *poolp;
44
    SECAlgorithmID pbeAlgId;    /* real pbe algorithms */
45
    SECAlgorithmID cipherAlgId; /* encryption/mac */
46
};
47
48
typedef struct sec_pkcs5V2ParameterStr sec_pkcs5V2Parameter;
49
50
/* template for PKCS 5 PBE Parameter.  This template has been expanded
51
 * based upon the additions in PKCS 12.  This should eventually be moved
52
 * if RSA updates PKCS 5.
53
 */
54
const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] = {
55
    { SEC_ASN1_SEQUENCE,
56
      0, NULL, sizeof(SEC_PKCS5PBEParameter) },
57
    { SEC_ASN1_OCTET_STRING,
58
      offsetof(SEC_PKCS5PBEParameter, salt) },
59
    { SEC_ASN1_INTEGER,
60
      offsetof(SEC_PKCS5PBEParameter, iteration) },
61
    { 0 }
62
};
63
64
const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] = {
65
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
66
    { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
67
    { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
68
    { 0 }
69
};
70
71
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
72
73
/* SECOID_PKCS5_PBKDF2 */
74
const SEC_ASN1Template SEC_PKCS5V2PBEParameterTemplate[] = {
75
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
76
    /* This is really a choice, but since we only understand this
77
     * choice, just inline it */
78
    { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
79
    { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
80
    { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL,
81
      offsetof(SEC_PKCS5PBEParameter, keyLength) },
82
    { SEC_ASN1_POINTER | SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL,
83
      offsetof(SEC_PKCS5PBEParameter, pPrfAlgId),
84
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
85
    { 0 }
86
};
87
88
/* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
89
const SEC_ASN1Template SEC_PKCS5V2ParameterTemplate[] = {
90
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
91
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(sec_pkcs5V2Parameter, pbeAlgId),
92
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
93
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
94
      offsetof(sec_pkcs5V2Parameter, cipherAlgId),
95
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
96
    { 0 }
97
};
98
99
/*
100
 * maps a PBE algorithm to a crypto algorithm. for PKCS12 and PKCS5v1
101
 * for PKCS5v2 it returns SEC_OID_PKCS5_PBKDF2.
102
 */
103
SECOidTag
104
sec_pkcs5GetCryptoFromAlgTag(SECOidTag algorithm)
105
0
{
106
0
    switch (algorithm) {
107
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
108
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
109
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
110
0
            return SEC_OID_DES_EDE3_CBC;
111
0
        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
112
0
        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
113
0
        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
114
0
            return SEC_OID_DES_CBC;
115
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
116
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
117
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
118
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
119
0
            return SEC_OID_RC2_CBC;
120
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
121
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
122
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
123
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
124
0
            return SEC_OID_RC4;
125
0
        case SEC_OID_PKCS5_PBKDF2:
126
0
        case SEC_OID_PKCS5_PBES2:
127
0
        case SEC_OID_PKCS5_PBMAC1:
128
0
            return SEC_OID_PKCS5_PBKDF2;
129
0
        default:
130
0
            break;
131
0
    }
132
133
0
    return SEC_OID_UNKNOWN;
134
0
}
135
136
/*
137
 * get a new PKCS5 V2 Parameter from the algorithm id.
138
 *  if arena is passed in, use it, otherwise create a new arena.
139
 */
140
sec_pkcs5V2Parameter *
141
sec_pkcs5_v2_get_v2_param(PLArenaPool *arena, SECAlgorithmID *algid)
142
0
{
143
0
    PLArenaPool *localArena = NULL;
144
0
    sec_pkcs5V2Parameter *pbeV2_param;
145
0
    SECStatus rv;
146
147
0
    if (arena == NULL) {
148
0
        localArena = arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
149
0
        if (arena == NULL) {
150
0
            return NULL;
151
0
        }
152
0
    }
153
0
    pbeV2_param = PORT_ArenaZNew(arena, sec_pkcs5V2Parameter);
154
0
    if (pbeV2_param == NULL) {
155
0
        goto loser;
156
0
    }
157
158
0
    rv = SEC_ASN1DecodeItem(arena, pbeV2_param,
159
0
                            SEC_PKCS5V2ParameterTemplate, &algid->parameters);
160
0
    if (rv == SECFailure) {
161
0
        goto loser;
162
0
    }
163
164
0
    pbeV2_param->poolp = arena;
165
0
    return pbeV2_param;
166
0
loser:
167
0
    if (localArena) {
168
0
        PORT_FreeArena(arena, PR_FALSE);
169
0
    }
170
0
    return NULL;
171
0
}
172
173
void
174
sec_pkcs5_v2_destroy_v2_param(sec_pkcs5V2Parameter *param)
175
0
{
176
0
    if (param && param->poolp) {
177
0
        PORT_FreeArena(param->poolp, PR_TRUE);
178
0
    }
179
0
}
180
181
/* maps crypto algorithm from PBE algorithm.
182
 */
183
SECOidTag
184
SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid)
185
0
{
186
187
0
    SECOidTag pbeAlg;
188
0
    SECOidTag cipherAlg;
189
190
0
    if (algid == NULL)
191
0
        return SEC_OID_UNKNOWN;
192
193
0
    pbeAlg = SECOID_GetAlgorithmTag(algid);
194
0
    cipherAlg = sec_pkcs5GetCryptoFromAlgTag(pbeAlg);
195
0
    if ((cipherAlg == SEC_OID_PKCS5_PBKDF2) &&
196
0
        (pbeAlg != SEC_OID_PKCS5_PBKDF2)) {
197
0
        sec_pkcs5V2Parameter *pbeV2_param;
198
0
        cipherAlg = SEC_OID_UNKNOWN;
199
200
0
        pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
201
0
        if (pbeV2_param != NULL) {
202
0
            cipherAlg = SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId);
203
0
            sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
204
0
        }
205
0
    }
206
207
0
    return cipherAlg;
208
0
}
209
210
/* check to see if an oid is a pbe algorithm
211
 */
212
PRBool
213
SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid)
214
0
{
215
0
    return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN);
216
0
}
217
218
PRBool
219
SEC_PKCS5IsAlgorithmPBEAlgTag(SECOidTag algtag)
220
0
{
221
0
    return (PRBool)(sec_pkcs5GetCryptoFromAlgTag(algtag) != SEC_OID_UNKNOWN);
222
0
}
223
224
/*
225
 * find the most appropriate PKCS5v2 overall oid tag from a regular
226
 * cipher/hash algorithm tag.
227
 */
228
static SECOidTag
229
sec_pkcs5v2_get_pbe(SECOidTag algTag)
230
0
{
231
    /* if it's a valid hash oid... */
232
0
    if (HASH_GetHashOidTagByHMACOidTag(algTag) != SEC_OID_UNKNOWN) {
233
        /* use the MAC tag */
234
0
        return SEC_OID_PKCS5_PBMAC1;
235
0
    }
236
0
    if (HASH_GetHashTypeByOidTag(algTag) != HASH_AlgNULL) {
237
        /* eliminate Hash algorithms */
238
0
        return SEC_OID_UNKNOWN;
239
0
    }
240
0
    if (PK11_AlgtagToMechanism(algTag) != CKM_INVALID_MECHANISM) {
241
        /* it's not a hash, if it has a PKCS #11 mechanism associated
242
         * with it, assume it's a cipher. (NOTE this will generate
243
         * some false positives). */
244
0
        return SEC_OID_PKCS5_PBES2;
245
0
    }
246
0
    return SEC_OID_UNKNOWN;
247
0
}
248
249
/*
250
 * maps PBE algorithm from crypto algorithm, assumes SHA1 hashing.
251
 *  input keyLen in bits.
252
 */
253
SECOidTag
254
SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen)
255
0
{
256
0
    switch (algTag) {
257
0
        case SEC_OID_DES_EDE3_CBC:
258
0
            switch (keyLen) {
259
0
                case 168:
260
0
                case 192:
261
0
                case 0:
262
0
                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
263
0
                case 128:
264
0
                case 92:
265
0
                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
266
0
                default:
267
0
                    break;
268
0
            }
269
0
            break;
270
0
        case SEC_OID_DES_CBC:
271
0
            return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
272
0
        case SEC_OID_RC2_CBC:
273
0
            switch (keyLen) {
274
0
                case 40:
275
0
                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
276
0
                case 128:
277
0
                case 0:
278
0
                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
279
0
                default:
280
0
                    break;
281
0
            }
282
0
            break;
283
0
        case SEC_OID_RC4:
284
0
            switch (keyLen) {
285
0
                case 40:
286
0
                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
287
0
                case 128:
288
0
                case 0:
289
0
                    return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
290
0
                default:
291
0
                    break;
292
0
            }
293
0
            break;
294
0
        default:
295
0
            return sec_pkcs5v2_get_pbe(algTag);
296
0
    }
297
298
0
    return SEC_OID_UNKNOWN;
299
0
}
300
301
/*
302
 * Some oids encode the key size in the oid, while the actual PKCS
303
 * PKCS #11 mechanism does not. In those cases we can't use
304
 * the PKCS #11 automated key length code to select the key size.
305
 */
306
static int
307
sec_pkcs5v2_key_length_by_oid(SECOidTag algorithm)
308
0
{
309
0
    switch (algorithm) {
310
0
        case SEC_OID_AES_128_CBC:
311
0
        case SEC_OID_CAMELLIA_128_CBC:
312
0
            return AES_128_KEY_LENGTH;
313
0
        case SEC_OID_AES_192_CBC:
314
0
        case SEC_OID_CAMELLIA_192_CBC:
315
0
            return AES_192_KEY_LENGTH;
316
0
        case SEC_OID_AES_256_CBC:
317
0
        case SEC_OID_CAMELLIA_256_CBC:
318
0
            return AES_256_KEY_LENGTH;
319
0
        default:
320
0
            break;
321
0
    }
322
0
    return -1;
323
0
}
324
325
/* find the keylength from the algorithm id */
326
static int
327
sec_pkcs5v2_default_key_length(SECOidTag algorithm)
328
0
{
329
0
    CK_MECHANISM_TYPE cryptoMech;
330
0
    int key_length = sec_pkcs5v2_key_length_by_oid(algorithm);
331
0
    if (key_length != -1) {
332
0
        return key_length;
333
0
    }
334
0
    cryptoMech = PK11_AlgtagToMechanism(algorithm);
335
0
    if (cryptoMech == CKM_INVALID_MECHANISM) {
336
0
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
337
0
        return -1;
338
0
    }
339
0
    return PK11_GetMaxKeyLength(cryptoMech);
340
0
}
341
342
/*
343
 * get the key length in bytes from a PKCS5 PBE
344
 */
345
static int
346
sec_pkcs5v2_key_length(SECAlgorithmID *algid, SECAlgorithmID *cipherAlgId)
347
0
{
348
0
    SECOidTag algorithm;
349
0
    PLArenaPool *arena = NULL;
350
0
    SEC_PKCS5PBEParameter p5_param;
351
0
    SECStatus rv;
352
0
    int length = -1;
353
0
    SECOidTag cipherAlg = SEC_OID_UNKNOWN;
354
355
0
    algorithm = SECOID_GetAlgorithmTag(algid);
356
    /* sanity check, they should all be PBKDF2 here */
357
0
    if (algorithm != SEC_OID_PKCS5_PBKDF2) {
358
0
        return -1;
359
0
    }
360
361
0
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
362
0
    if (arena == NULL) {
363
0
        goto loser;
364
0
    }
365
0
    PORT_Memset(&p5_param, 0, sizeof(p5_param));
366
0
    rv = SEC_ASN1DecodeItem(arena, &p5_param,
367
0
                            SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
368
0
    if (rv != SECSuccess) {
369
0
        goto loser;
370
0
    }
371
372
0
    if (cipherAlgId)
373
0
        cipherAlg = SECOID_GetAlgorithmTag(cipherAlgId);
374
375
0
    if (p5_param.keyLength.data != NULL) {
376
        /* if the length is given, accept that length. This
377
         * will allow us to decode old NSS encrypted data
378
         * where we used the MAX keysize for the algorithm,
379
         * but put an incorrect header for a different keysize.
380
         */
381
0
        length = DER_GetInteger(&p5_param.keyLength);
382
0
    } else {
383
        /* if the keylength was not specified, figure it
384
         * out from the oid */
385
0
        length = sec_pkcs5v2_default_key_length(cipherAlg);
386
0
    }
387
388
0
loser:
389
0
    if (arena) {
390
0
        PORT_FreeArena(arena, PR_FALSE);
391
0
    }
392
0
    return length;
393
0
}
394
395
/*
396
 *  get the key length in bytes needed for the PBE algorithm
397
 */
398
int
399
SEC_PKCS5GetKeyLength(SECAlgorithmID *algid)
400
0
{
401
402
0
    SECOidTag algorithm;
403
404
0
    if (algid == NULL)
405
0
        return SEC_OID_UNKNOWN;
406
407
0
    algorithm = SECOID_GetAlgorithmTag(algid);
408
409
0
    switch (algorithm) {
410
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
411
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
412
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
413
0
            return 24;
414
0
        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
415
0
        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
416
0
        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
417
0
            return 8;
418
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
419
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
420
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
421
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
422
0
            return 5;
423
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
424
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
425
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
426
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
427
0
            return 16;
428
0
        case SEC_OID_PKCS5_PBKDF2:
429
0
            return sec_pkcs5v2_key_length(algid, NULL);
430
0
        case SEC_OID_PKCS5_PBES2:
431
0
        case SEC_OID_PKCS5_PBMAC1: {
432
0
            sec_pkcs5V2Parameter *pbeV2_param;
433
0
            int length = -1;
434
0
            pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
435
0
            if (pbeV2_param != NULL) {
436
0
                length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId,
437
0
                                                &pbeV2_param->cipherAlgId);
438
0
                sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
439
0
            }
440
0
            return length;
441
0
        }
442
443
0
        default:
444
0
            break;
445
0
    }
446
0
    return -1;
447
0
}
448
449
/* the PKCS12 V2 algorithms only encode the salt, there is no iteration
450
 * count so we need a check for V2 algorithm parameters.
451
 */
452
static PRBool
453
sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm)
454
0
{
455
0
    switch (algorithm) {
456
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
457
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
458
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
459
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
460
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
461
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
462
0
            return PR_TRUE;
463
0
        default:
464
0
            break;
465
0
    }
466
467
0
    return PR_FALSE;
468
0
}
469
470
static PRBool
471
sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(SECOidTag algorithm)
472
0
{
473
0
    switch (algorithm) {
474
0
        case SEC_OID_PKCS5_PBES2:
475
0
        case SEC_OID_PKCS5_PBMAC1:
476
0
        case SEC_OID_PKCS5_PBKDF2:
477
0
            return PR_TRUE;
478
0
        default:
479
0
            break;
480
0
    }
481
482
0
    return PR_FALSE;
483
0
}
484
485
/* destroy a pbe parameter.  it assumes that the parameter was
486
 * generated using the appropriate create function and therefor
487
 * contains an arena pool.
488
 */
489
static void
490
sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param)
491
0
{
492
0
    if (pbe_param != NULL)
493
0
        PORT_FreeArena(pbe_param->poolp, PR_TRUE);
494
0
}
495
496
/* creates a PBE parameter based on the PBE algorithm.  the only required
497
 * parameters are algorithm and interation.  the return is a PBE parameter
498
 * which conforms to PKCS 5 parameter unless an extended parameter is needed.
499
 * this is primarily if keyLength and a variable key length algorithm are
500
 * specified.
501
 *   salt -  if null, a salt will be generated from random bytes.
502
 *   iteration - number of iterations to perform hashing.
503
 *   keyLength - only used in variable key length algorithms. if specified,
504
 *            should be in bytes.
505
 * once a parameter is allocated, it should be destroyed calling
506
 * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter.
507
 */
508
0
#define DEFAULT_SALT_LENGTH 16
509
static SEC_PKCS5PBEParameter *
510
sec_pkcs5_create_pbe_parameter(SECOidTag algorithm,
511
                               SECItem *salt,
512
                               int iteration,
513
                               int keyLength,
514
                               SECOidTag prfAlg)
515
0
{
516
0
    PLArenaPool *poolp = NULL;
517
0
    SEC_PKCS5PBEParameter *pbe_param = NULL;
518
0
    SECStatus rv = SECSuccess;
519
0
    void *dummy = NULL;
520
521
0
    if (iteration < 0) {
522
0
        return NULL;
523
0
    }
524
525
0
    poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
526
0
    if (poolp == NULL)
527
0
        return NULL;
528
529
0
    pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp,
530
0
                                                          sizeof(SEC_PKCS5PBEParameter));
531
0
    if (!pbe_param) {
532
0
        PORT_FreeArena(poolp, PR_TRUE);
533
0
        return NULL;
534
0
    }
535
536
0
    pbe_param->poolp = poolp;
537
538
0
    rv = SECFailure;
539
0
    if (salt && salt->data) {
540
0
        rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt);
541
0
    } else {
542
        /* sigh, the old interface generated salt on the fly, so we have to
543
         * preserve the semantics */
544
0
        pbe_param->salt.len = DEFAULT_SALT_LENGTH;
545
0
        pbe_param->salt.data = PORT_ArenaZAlloc(poolp, DEFAULT_SALT_LENGTH);
546
0
        if (pbe_param->salt.data) {
547
0
            rv = PK11_GenerateRandom(pbe_param->salt.data, DEFAULT_SALT_LENGTH);
548
0
        }
549
0
    }
550
551
0
    if (rv != SECSuccess) {
552
0
        PORT_FreeArena(poolp, PR_TRUE);
553
0
        return NULL;
554
0
    }
555
556
    /* encode the integer */
557
0
    dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration,
558
0
                                  iteration);
559
0
    rv = (dummy) ? SECSuccess : SECFailure;
560
561
0
    if (rv != SECSuccess) {
562
0
        PORT_FreeArena(poolp, PR_FALSE);
563
0
        return NULL;
564
0
    }
565
566
    /*
567
     * for PKCS5 v2 Add the keylength and the prf
568
     */
569
0
    if (algorithm == SEC_OID_PKCS5_PBKDF2) {
570
0
        dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->keyLength,
571
0
                                      keyLength);
572
0
        rv = (dummy) ? SECSuccess : SECFailure;
573
0
        if (rv != SECSuccess) {
574
0
            PORT_FreeArena(poolp, PR_FALSE);
575
0
            return NULL;
576
0
        }
577
0
        rv = SECOID_SetAlgorithmID(poolp, &pbe_param->prfAlgId, prfAlg, NULL);
578
0
        if (rv != SECSuccess) {
579
0
            PORT_FreeArena(poolp, PR_FALSE);
580
0
            return NULL;
581
0
        }
582
0
        pbe_param->pPrfAlgId = &pbe_param->prfAlgId;
583
0
    }
584
585
0
    return pbe_param;
586
0
}
587
588
/* creates a algorithm ID containing the PBE algorithm and appropriate
589
 * parameters.  the required parameter is the algorithm.  if salt is
590
 * not specified, it is generated randomly.
591
 *
592
 * the returned SECAlgorithmID should be destroyed using
593
 * SECOID_DestroyAlgorithmID
594
 */
595
SECAlgorithmID *
596
sec_pkcs5CreateAlgorithmID(SECOidTag algorithm,
597
                           SECOidTag cipherAlgorithm,
598
                           SECOidTag prfAlg,
599
                           SECOidTag *pPbeAlgorithm,
600
                           int keyLength,
601
                           SECItem *salt,
602
                           int iteration)
603
0
{
604
0
    PLArenaPool *poolp = NULL;
605
0
    SECAlgorithmID *algid, *ret_algid = NULL;
606
0
    SECOidTag pbeAlgorithm = algorithm;
607
0
    SECItem der_param;
608
0
    void *dummy;
609
0
    SECStatus rv = SECFailure;
610
0
    SEC_PKCS5PBEParameter *pbe_param = NULL;
611
0
    sec_pkcs5V2Parameter pbeV2_param;
612
613
0
    if (iteration <= 0) {
614
0
        return NULL;
615
0
    }
616
617
0
    poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
618
0
    if (!poolp) {
619
0
        goto loser;
620
0
    }
621
622
0
    if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm) ||
623
0
        sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
624
        /* use PKCS 5 v2 */
625
0
        SECItem *cipherParams;
626
627
        /*
628
         * if we ask for pkcs5 Algorithms directly, then the
629
         * application needs to supply the cipher algorithm,
630
         * otherwise we are implicitly using pkcs5 v2 and the
631
         * passed in algorithm is the encryption algorithm.
632
         */
633
0
        if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
634
0
            if (cipherAlgorithm == SEC_OID_UNKNOWN) {
635
0
                goto loser;
636
0
            }
637
0
        } else {
638
0
            cipherAlgorithm = algorithm;
639
            /* force algorithm to be chosen below */
640
0
            algorithm = SEC_OID_PKCS5_PBKDF2;
641
0
        }
642
643
0
        pbeAlgorithm = SEC_OID_PKCS5_PBKDF2;
644
        /*
645
         * 'algorithm' is the overall algorithm oid tag used to wrap the
646
         * entire algorithm ID block. For PKCS5v1 and PKCS12, this
647
         * algorithm OID has encoded in it both the PBE KDF function
648
         * and the encryption algorithm. For PKCS 5v2, PBE KDF and
649
         * encryption/macing oids are encoded as parameters in
650
         * the algorithm ID block.
651
         *
652
         * Thus in PKCS5 v1 and PKCS12, this algorithm maps to a pkcs #11
653
         * mechanism, where as in PKCS 5v2, this algorithm tag does not map
654
         * directly to a PKCS #11 mechanim, instead the 2 oids in the
655
         * algorithm ID block map the the actual PKCS #11 mechanism.
656
         * algorithm is). We use choose this algorithm oid based on the
657
         * cipherAlgorithm to determine what this should be (MAC1 or PBES2).
658
         */
659
0
        if (algorithm == SEC_OID_PKCS5_PBKDF2) {
660
            /* choose mac or pbes */
661
0
            algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm);
662
0
        }
663
664
        /* set the PKCS5v2 specific parameters */
665
0
        if (keyLength == 0) {
666
0
            SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
667
0
            if (hashAlg != SEC_OID_UNKNOWN) {
668
0
                keyLength = HASH_ResultLenByOidTag(hashAlg);
669
0
            } else {
670
0
                keyLength = sec_pkcs5v2_default_key_length(cipherAlgorithm);
671
0
            }
672
0
            if (keyLength <= 0) {
673
0
                goto loser;
674
0
            }
675
0
        }
676
        /* currently SEC_OID_HMAC_SHA1 is the default */
677
0
        if (prfAlg == SEC_OID_UNKNOWN) {
678
0
            prfAlg = SEC_OID_HMAC_SHA1;
679
0
        }
680
681
        /* build the PKCS5v2 cipher algorithm id */
682
0
        cipherParams = pk11_GenerateNewParamWithKeyLen(
683
0
            PK11_AlgtagToMechanism(cipherAlgorithm), keyLength);
684
0
        if (!cipherParams) {
685
0
            goto loser;
686
0
        }
687
688
0
        PORT_Memset(&pbeV2_param, 0, sizeof(pbeV2_param));
689
690
0
        rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams,
691
0
                               poolp, &pbeV2_param.cipherAlgId);
692
0
        SECITEM_FreeItem(cipherParams, PR_TRUE);
693
0
        if (rv != SECSuccess) {
694
0
            goto loser;
695
0
        }
696
0
    }
697
698
    /* generate the parameter */
699
0
    pbe_param = sec_pkcs5_create_pbe_parameter(pbeAlgorithm, salt, iteration,
700
0
                                               keyLength, prfAlg);
701
0
    if (!pbe_param) {
702
0
        goto loser;
703
0
    }
704
705
    /* generate the algorithm id */
706
0
    algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
707
0
    if (algid == NULL) {
708
0
        goto loser;
709
0
    }
710
711
0
    der_param.data = NULL;
712
0
    der_param.len = 0;
713
0
    if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
714
        /* first encode the PBE algorithm ID */
715
0
        dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
716
0
                                   SEC_PKCS5V2PBEParameterTemplate);
717
0
        if (dummy == NULL) {
718
0
            goto loser;
719
0
        }
720
0
        rv = SECOID_SetAlgorithmID(poolp, &pbeV2_param.pbeAlgId,
721
0
                                   pbeAlgorithm, &der_param);
722
0
        if (rv != SECSuccess) {
723
0
            goto loser;
724
0
        }
725
726
        /* now encode the Full PKCS 5 parameter */
727
0
        der_param.data = NULL;
728
0
        der_param.len = 0;
729
0
        dummy = SEC_ASN1EncodeItem(poolp, &der_param, &pbeV2_param,
730
0
                                   SEC_PKCS5V2ParameterTemplate);
731
0
    } else if (!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
732
0
        dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
733
0
                                   SEC_PKCS5PBEParameterTemplate);
734
0
    } else {
735
0
        dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
736
0
                                   SEC_V2PKCS12PBEParameterTemplate);
737
0
    }
738
0
    if (dummy == NULL) {
739
0
        goto loser;
740
0
    }
741
742
0
    rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param);
743
0
    if (rv != SECSuccess) {
744
0
        goto loser;
745
0
    }
746
747
0
    ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
748
0
    if (ret_algid == NULL) {
749
0
        goto loser;
750
0
    }
751
752
0
    rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
753
0
    if (rv != SECSuccess) {
754
0
        SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
755
0
        ret_algid = NULL;
756
0
    } else if (pPbeAlgorithm) {
757
0
        *pPbeAlgorithm = pbeAlgorithm;
758
0
    }
759
760
0
loser:
761
0
    if (poolp != NULL) {
762
0
        PORT_FreeArena(poolp, PR_TRUE);
763
0
        algid = NULL;
764
0
    }
765
766
0
    if (pbe_param) {
767
0
        sec_pkcs5_destroy_pbe_param(pbe_param);
768
0
    }
769
770
0
    return ret_algid;
771
0
}
772
773
SECStatus
774
pbe_PK11AlgidToParam(SECAlgorithmID *algid, SECItem *mech)
775
0
{
776
0
    SEC_PKCS5PBEParameter p5_param;
777
0
    SECItem *salt = NULL;
778
0
    SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
779
0
    PLArenaPool *arena = NULL;
780
0
    SECStatus rv = SECFailure;
781
0
    unsigned char *paramData = NULL;
782
0
    unsigned char *pSalt = NULL;
783
0
    CK_ULONG iterations;
784
0
    int paramLen = 0;
785
0
    int iv_len;
786
787
0
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
788
0
    if (arena == NULL) {
789
0
        goto loser;
790
0
    }
791
792
    /*
793
     * decode the algid based on the pbe type
794
     */
795
0
    PORT_Memset(&p5_param, 0, sizeof(p5_param));
796
0
    if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
797
0
        iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
798
0
        rv = SEC_ASN1DecodeItem(arena, &p5_param,
799
0
                                SEC_V2PKCS12PBEParameterTemplate, &algid->parameters);
800
0
    } else if (algorithm == SEC_OID_PKCS5_PBKDF2) {
801
0
        iv_len = 0;
802
0
        rv = SEC_ASN1DecodeItem(arena, &p5_param,
803
0
                                SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
804
0
    } else {
805
0
        iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
806
0
        rv = SEC_ASN1DecodeItem(arena, &p5_param, SEC_PKCS5PBEParameterTemplate,
807
0
                                &algid->parameters);
808
0
    }
809
810
0
    if (iv_len < 0) {
811
0
        goto loser;
812
0
    }
813
814
0
    if (rv != SECSuccess) {
815
0
        goto loser;
816
0
    }
817
818
    /* get salt */
819
0
    salt = &p5_param.salt;
820
0
    iterations = (CK_ULONG)DER_GetInteger(&p5_param.iteration);
821
822
    /* allocate and fill in the PKCS #11 parameters
823
     * based on the algorithm. */
824
0
    if (algorithm == SEC_OID_PKCS5_PBKDF2) {
825
0
        SECOidTag prfAlgTag;
826
0
        CK_PKCS5_PBKD2_PARAMS *pbeV2_params =
827
0
            (CK_PKCS5_PBKD2_PARAMS *)PORT_ZAlloc(
828
0
                sizeof(CK_PKCS5_PBKD2_PARAMS) + salt->len);
829
830
0
        if (pbeV2_params == NULL) {
831
0
            goto loser;
832
0
        }
833
0
        paramData = (unsigned char *)pbeV2_params;
834
0
        paramLen = sizeof(CK_PKCS5_PBKD2_PARAMS);
835
836
        /* set the prf */
837
0
        prfAlgTag = SEC_OID_HMAC_SHA1;
838
0
        if (p5_param.pPrfAlgId &&
839
0
            p5_param.pPrfAlgId->algorithm.data != 0) {
840
0
            prfAlgTag = SECOID_GetAlgorithmTag(p5_param.pPrfAlgId);
841
0
        }
842
0
        switch (prfAlgTag) {
843
0
            case SEC_OID_HMAC_SHA1:
844
0
                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
845
0
                break;
846
0
            case SEC_OID_HMAC_SHA224:
847
0
                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA224;
848
0
                break;
849
0
            case SEC_OID_HMAC_SHA256:
850
0
                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA256;
851
0
                break;
852
0
            case SEC_OID_HMAC_SHA384:
853
0
                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA384;
854
0
                break;
855
0
            case SEC_OID_HMAC_SHA512:
856
0
                pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA512;
857
0
                break;
858
0
            default:
859
0
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
860
0
                goto loser;
861
0
        }
862
863
        /* probably should fetch these from the prfAlgid */
864
0
        pbeV2_params->pPrfData = NULL;
865
0
        pbeV2_params->ulPrfDataLen = 0;
866
0
        pbeV2_params->saltSource = CKZ_SALT_SPECIFIED;
867
0
        pSalt = ((CK_CHAR_PTR)pbeV2_params) + sizeof(CK_PKCS5_PBKD2_PARAMS);
868
0
        if (salt->data) {
869
0
            PORT_Memcpy(pSalt, salt->data, salt->len);
870
0
        }
871
0
        pbeV2_params->pSaltSourceData = pSalt;
872
0
        pbeV2_params->ulSaltSourceDataLen = salt->len;
873
0
        pbeV2_params->iterations = iterations;
874
0
    } else {
875
0
        CK_PBE_PARAMS *pbe_params = NULL;
876
0
        pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS) +
877
0
                                                  salt->len + iv_len);
878
0
        if (pbe_params == NULL) {
879
0
            goto loser;
880
0
        }
881
0
        paramData = (unsigned char *)pbe_params;
882
0
        paramLen = sizeof(CK_PBE_PARAMS);
883
884
0
        pSalt = ((CK_CHAR_PTR)pbe_params) + sizeof(CK_PBE_PARAMS);
885
0
        pbe_params->pSalt = pSalt;
886
0
        if (salt->data) {
887
0
            PORT_Memcpy(pSalt, salt->data, salt->len);
888
0
        }
889
0
        pbe_params->ulSaltLen = salt->len;
890
0
        if (iv_len) {
891
0
            pbe_params->pInitVector =
892
0
                ((CK_CHAR_PTR)pbe_params) + sizeof(CK_PBE_PARAMS) + salt->len;
893
0
        }
894
0
        pbe_params->ulIteration = iterations;
895
0
    }
896
897
    /* copy into the mechanism sec item */
898
0
    mech->data = paramData;
899
0
    mech->len = paramLen;
900
0
    if (arena) {
901
0
        PORT_FreeArena(arena, PR_TRUE);
902
0
    }
903
0
    return SECSuccess;
904
905
0
loser:
906
0
    if (paramData) {
907
0
        PORT_Free(paramData);
908
0
    }
909
0
    if (arena) {
910
0
        PORT_FreeArena(arena, PR_TRUE);
911
0
    }
912
0
    return SECFailure;
913
0
}
914
915
/*
916
 * public, deprecated, not valid for pkcs5 v2
917
 *
918
 * use PK11_CreatePBEV2AlgorithmID or PK11_CreatePBEAlgorithmID to create
919
 * PBE algorithmID's directly.
920
 */
921
SECStatus
922
PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PLArenaPool *arena,
923
                     SECAlgorithmID *algId)
924
0
{
925
0
    CK_PBE_PARAMS *pbe_param;
926
0
    SECItem pbeSalt;
927
0
    SECAlgorithmID *pbeAlgID = NULL;
928
0
    SECStatus rv;
929
930
0
    if (!param || !algId) {
931
0
        return SECFailure;
932
0
    }
933
934
0
    pbe_param = (CK_PBE_PARAMS *)param->data;
935
0
    pbeSalt.data = (unsigned char *)pbe_param->pSalt;
936
0
    pbeSalt.len = pbe_param->ulSaltLen;
937
0
    pbeAlgID = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN,
938
0
                                          SEC_OID_UNKNOWN, NULL, 0,
939
0
                                          &pbeSalt, (int)pbe_param->ulIteration);
940
0
    if (!pbeAlgID) {
941
0
        return SECFailure;
942
0
    }
943
944
0
    rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID);
945
0
    SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE);
946
0
    return rv;
947
0
}
948
949
/*
950
 * public, Deprecated, This function is only for binary compatibility with
951
 * older applications. Does not support PKCS5v2.
952
 *
953
 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
954
 * iv values rather than generating PBE bits directly.
955
 */
956
PBEBitGenContext *
957
PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
958
                  SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
959
                  unsigned int iterations)
960
0
{
961
0
    SECItem *context = NULL;
962
0
    SECItem mechItem;
963
0
    CK_PBE_PARAMS pbe_params;
964
0
    CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
965
0
    PK11SlotInfo *slot;
966
0
    PK11SymKey *symKey = NULL;
967
0
    unsigned char ivData[8];
968
969
    /* use the purpose to select the low level keygen algorithm */
970
0
    switch (bitGenPurpose) {
971
0
        case pbeBitGenIntegrityKey:
972
0
            switch (hashAlgorithm) {
973
0
                case SEC_OID_SHA1:
974
0
                    mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC;
975
0
                    break;
976
0
                case SEC_OID_MD2:
977
0
                    mechanism = CKM_NSS_PBE_MD2_HMAC_KEY_GEN;
978
0
                    break;
979
0
                case SEC_OID_MD5:
980
0
                    mechanism = CKM_NSS_PBE_MD5_HMAC_KEY_GEN;
981
0
                    break;
982
0
                default:
983
0
                    break;
984
0
            }
985
0
            break;
986
0
        case pbeBitGenCipherIV:
987
0
            if (bitsNeeded > 64) {
988
0
                break;
989
0
            }
990
0
            if (hashAlgorithm != SEC_OID_SHA1) {
991
0
                break;
992
0
            }
993
0
            mechanism = CKM_PBE_SHA1_DES3_EDE_CBC;
994
0
            break;
995
0
        case pbeBitGenCipherKey:
996
0
            if (hashAlgorithm != SEC_OID_SHA1) {
997
0
                break;
998
0
            }
999
0
            switch (bitsNeeded) {
1000
0
                case 40:
1001
0
                    mechanism = CKM_PBE_SHA1_RC4_40;
1002
0
                    break;
1003
0
                case 128:
1004
0
                    mechanism = CKM_PBE_SHA1_RC4_128;
1005
0
                    break;
1006
0
                default:
1007
0
                    break;
1008
0
            }
1009
0
        case pbeBitGenIDNull:
1010
0
            break;
1011
0
    }
1012
1013
0
    if (mechanism == CKM_INVALID_MECHANISM) {
1014
        /* we should set an error, but this is a deprecated function, and
1015
         * we are keeping bug for bug compatibility;)... */
1016
0
        return NULL;
1017
0
    }
1018
1019
0
    pbe_params.pInitVector = ivData;
1020
0
    pbe_params.pPassword = pwitem->data;
1021
0
    pbe_params.ulPasswordLen = pwitem->len;
1022
0
    pbe_params.pSalt = salt->data;
1023
0
    pbe_params.ulSaltLen = salt->len;
1024
0
    pbe_params.ulIteration = iterations;
1025
0
    mechItem.data = (unsigned char *)&pbe_params;
1026
0
    mechItem.len = sizeof(pbe_params);
1027
1028
0
    slot = PK11_GetInternalSlot();
1029
0
    symKey = PK11_RawPBEKeyGen(slot, mechanism,
1030
0
                               &mechItem, pwitem, PR_FALSE, NULL);
1031
0
    PK11_FreeSlot(slot);
1032
0
    if (symKey != NULL) {
1033
0
        if (bitGenPurpose == pbeBitGenCipherIV) {
1034
            /* NOTE: this assumes that bitsNeeded is a multiple of 8! */
1035
0
            SECItem ivItem;
1036
1037
0
            ivItem.data = ivData;
1038
0
            ivItem.len = bitsNeeded / 8;
1039
0
            context = SECITEM_DupItem(&ivItem);
1040
0
        } else {
1041
0
            SECItem *keyData;
1042
0
            PK11_ExtractKeyValue(symKey);
1043
0
            keyData = PK11_GetKeyData(symKey);
1044
1045
            /* assert bitsNeeded with length? */
1046
0
            if (keyData) {
1047
0
                context = SECITEM_DupItem(keyData);
1048
0
            }
1049
0
        }
1050
0
        PK11_FreeSymKey(symKey);
1051
0
    }
1052
1053
0
    return (PBEBitGenContext *)context;
1054
0
}
1055
1056
/*
1057
 * public, Deprecated, This function is only for binary compatibility with
1058
 * older applications. Does not support PKCS5v2.
1059
 *
1060
 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetIV() for
1061
 * iv values rather than generating PBE bits directly.
1062
 */
1063
SECItem *
1064
PBE_GenerateBits(PBEBitGenContext *context)
1065
0
{
1066
0
    return (SECItem *)context;
1067
0
}
1068
1069
/*
1070
 * public, Deprecated, This function is only for binary compatibility with
1071
 * older applications. Does not support PKCS5v2.
1072
 *
1073
 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
1074
 * iv values rather than generating PBE bits directly.
1075
 */
1076
void
1077
PBE_DestroyContext(PBEBitGenContext *context)
1078
0
{
1079
0
    SECITEM_FreeItem((SECItem *)context, PR_TRUE);
1080
0
}
1081
1082
/*
1083
 * public, deprecated. Replaced with PK11_GetPBEIV().
1084
 */
1085
SECItem *
1086
SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
1087
0
{
1088
    /* pbe stuff */
1089
0
    CK_MECHANISM_TYPE type;
1090
0
    SECItem *param = NULL;
1091
0
    SECItem *iv = NULL;
1092
0
    SECItem src;
1093
0
    int iv_len = 0;
1094
0
    PK11SymKey *symKey;
1095
0
    PK11SlotInfo *slot;
1096
0
    CK_PBE_PARAMS_PTR pPBEparams;
1097
0
    SECOidTag pbeAlg;
1098
1099
0
    pbeAlg = SECOID_GetAlgorithmTag(algid);
1100
0
    if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
1101
0
        unsigned char *ivData;
1102
0
        sec_pkcs5V2Parameter *pbeV2_param = NULL;
1103
1104
        /* can only return the IV if the crypto Algorithm exists */
1105
0
        if (pbeAlg == SEC_OID_PKCS5_PBKDF2) {
1106
0
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1107
0
            goto loser;
1108
0
        }
1109
0
        pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
1110
0
        if (pbeV2_param == NULL) {
1111
0
            goto loser;
1112
0
        }
1113
        /* extract the IV from the cipher algid portion of our pkcs 5 v2
1114
         * algorithm id */
1115
0
        type = PK11_AlgtagToMechanism(
1116
0
            SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
1117
0
        param = PK11_ParamFromAlgid(&pbeV2_param->cipherAlgId);
1118
0
        sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
1119
0
        if (!param) {
1120
0
            goto loser;
1121
0
        }
1122
        /* NOTE: NULL is a permissible return here */
1123
0
        ivData = PK11_IVFromParam(type, param, &iv_len);
1124
0
        src.data = ivData;
1125
0
        src.len = iv_len;
1126
0
        goto done;
1127
0
    }
1128
1129
0
    type = PK11_AlgtagToMechanism(pbeAlg);
1130
0
    param = PK11_ParamFromAlgid(algid);
1131
0
    if (param == NULL) {
1132
0
        goto done;
1133
0
    }
1134
0
    slot = PK11_GetInternalSlot();
1135
0
    symKey = PK11_RawPBEKeyGen(slot, type, param, pwitem, faulty3DES, NULL);
1136
0
    PK11_FreeSlot(slot);
1137
0
    if (symKey == NULL) {
1138
0
        goto loser;
1139
0
    }
1140
0
    PK11_FreeSymKey(symKey);
1141
0
    pPBEparams = (CK_PBE_PARAMS_PTR)param->data;
1142
0
    iv_len = PK11_GetIVLength(type);
1143
1144
0
    src.data = (unsigned char *)pPBEparams->pInitVector;
1145
0
    src.len = iv_len;
1146
1147
0
done:
1148
0
    iv = SECITEM_DupItem(&src);
1149
1150
0
loser:
1151
0
    if (param) {
1152
0
        SECITEM_ZfreeItem(param, PR_TRUE);
1153
0
    }
1154
0
    return iv;
1155
0
}
1156
1157
/*
1158
 * Subs from nss 3.x that are deprecated
1159
 */
1160
PBEBitGenContext *
1161
__PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
1162
                    SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
1163
                    unsigned int iterations)
1164
0
{
1165
0
    PORT_Assert("__PBE_CreateContext is Deprecated" == NULL);
1166
0
    return NULL;
1167
0
}
1168
1169
SECItem *
1170
__PBE_GenerateBits(PBEBitGenContext *context)
1171
0
{
1172
0
    PORT_Assert("__PBE_GenerateBits is Deprecated" == NULL);
1173
0
    return NULL;
1174
0
}
1175
1176
void
1177
__PBE_DestroyContext(PBEBitGenContext *context)
1178
0
{
1179
0
    PORT_Assert("__PBE_DestroyContext is Deprecated" == NULL);
1180
0
}
1181
1182
SECStatus
1183
RSA_FormatBlock(SECItem *result, unsigned modulusLen,
1184
                int blockType, SECItem *data)
1185
0
{
1186
0
    PORT_Assert("RSA_FormatBlock is Deprecated" == NULL);
1187
0
    return SECFailure;
1188
0
}
1189
1190
/****************************************************************************
1191
 *
1192
 * Now Do The PBE Functions Here...
1193
 *
1194
 ****************************************************************************/
1195
1196
static void
1197
pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params)
1198
0
{
1199
0
    if (pbe_params) {
1200
0
        if (pbe_params->pPassword)
1201
0
            PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen);
1202
0
        if (pbe_params->pSalt)
1203
0
            PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen);
1204
0
        PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS));
1205
0
    }
1206
0
}
1207
1208
/*
1209
 * public, deprecated.  use PK11_CreatePBEAlgorithmID or
1210
 * PK11_CreatePBEV2AlgorithmID instead. If you needthe pkcs #11 parameters,
1211
 * use PK11_ParamFromAlgid from the algorithm id you created using
1212
 * PK11_CreatePBEAlgorithmID or PK11_CreatePBEV2AlgorithmID.
1213
 */
1214
SECItem *
1215
PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations)
1216
0
{
1217
0
    CK_PBE_PARAMS *pbe_params = NULL;
1218
0
    SECItem *paramRV = NULL;
1219
1220
0
    paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS));
1221
0
    if (!paramRV) {
1222
0
        goto loser;
1223
0
    }
1224
    /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */
1225
0
    PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS));
1226
1227
0
    pbe_params = (CK_PBE_PARAMS *)paramRV->data;
1228
0
    pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len);
1229
0
    if (!pbe_params->pPassword) {
1230
0
        goto loser;
1231
0
    }
1232
0
    if (pwd->data) {
1233
0
        PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len);
1234
0
    }
1235
0
    pbe_params->ulPasswordLen = pwd->len;
1236
1237
0
    pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len);
1238
0
    if (!pbe_params->pSalt) {
1239
0
        goto loser;
1240
0
    }
1241
0
    PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len);
1242
0
    pbe_params->ulSaltLen = salt->len;
1243
1244
0
    pbe_params->ulIteration = (CK_ULONG)iterations;
1245
0
    return paramRV;
1246
1247
0
loser:
1248
0
    if (pbe_params)
1249
0
        pk11_destroy_ck_pbe_params(pbe_params);
1250
0
    if (paramRV)
1251
0
        PORT_ZFree(paramRV, sizeof(SECItem));
1252
0
    return NULL;
1253
0
}
1254
1255
/*
1256
 * public, deprecated.
1257
 */
1258
void
1259
PK11_DestroyPBEParams(SECItem *pItem)
1260
0
{
1261
0
    if (pItem) {
1262
0
        CK_PBE_PARAMS *params = (CK_PBE_PARAMS *)(pItem->data);
1263
0
        if (params)
1264
0
            pk11_destroy_ck_pbe_params(params);
1265
0
        PORT_ZFree(pItem, sizeof(SECItem));
1266
0
    }
1267
0
}
1268
1269
/*
1270
 * public, Partially supports PKCS5 V2 (some parameters are not controllable
1271
 * through this interface). Use PK11_CreatePBEV2AlgorithmID() if you need
1272
 * finer control these.
1273
 */
1274
SECAlgorithmID *
1275
PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt)
1276
0
{
1277
0
    SECAlgorithmID *algid = NULL;
1278
0
    algid = sec_pkcs5CreateAlgorithmID(algorithm,
1279
0
                                       SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, NULL,
1280
0
                                       0, salt, iteration);
1281
0
    return algid;
1282
0
}
1283
1284
/*
1285
 * public, fully support pkcs5v2.
1286
 */
1287
SECAlgorithmID *
1288
PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag,
1289
                            SECOidTag prfAlgTag, int keyLength, int iteration,
1290
                            SECItem *salt)
1291
0
{
1292
0
    SECAlgorithmID *algid = NULL;
1293
0
    algid = sec_pkcs5CreateAlgorithmID(pbeAlgTag, cipherAlgTag, prfAlgTag,
1294
0
                                       NULL, keyLength, salt, iteration);
1295
0
    return algid;
1296
0
}
1297
1298
/*
1299
 * private.
1300
 */
1301
PK11SymKey *
1302
pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
1303
                             SECItem *params, CK_KEY_TYPE keyType, int keyLen,
1304
                             SECItem *pwitem, void *wincx)
1305
0
{
1306
0
    CK_ULONG pwLen;
1307
    /* do some sanity checks */
1308
0
    if ((params == NULL) || (params->data == NULL)) {
1309
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1310
0
        return NULL;
1311
0
    }
1312
1313
0
    if (type == CKM_INVALID_MECHANISM) {
1314
0
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1315
0
        return NULL;
1316
0
    }
1317
1318
    /* set the password pointer in the parameters... */
1319
0
    if (type == CKM_PKCS5_PBKD2) {
1320
0
        CK_PKCS5_PBKD2_PARAMS *pbev2_params;
1321
0
        if (params->len < sizeof(CK_PKCS5_PBKD2_PARAMS)) {
1322
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
1323
0
            return NULL;
1324
0
        }
1325
0
        pbev2_params = (CK_PKCS5_PBKD2_PARAMS *)params->data;
1326
0
        pbev2_params->pPassword = pwitem->data;
1327
0
        pwLen = pwitem->len;
1328
0
        pbev2_params->ulPasswordLen = &pwLen;
1329
0
    } else {
1330
0
        CK_PBE_PARAMS *pbe_params;
1331
0
        if (params->len < sizeof(CK_PBE_PARAMS)) {
1332
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
1333
0
            return NULL;
1334
0
        }
1335
0
        pbe_params = (CK_PBE_PARAMS *)params->data;
1336
0
        pbe_params->pPassword = pwitem->data;
1337
0
        pbe_params->ulPasswordLen = pwitem->len;
1338
0
    }
1339
1340
    /* generate the key (and sometimes the IV as a side effect...) */
1341
0
    return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType,
1342
0
                                               keyLen, NULL,
1343
0
                                               CKF_SIGN | CKF_ENCRYPT | CKF_DECRYPT | CKF_UNWRAP | CKF_WRAP,
1344
0
                                               0, wincx);
1345
0
}
1346
1347
/*
1348
 * public, deprecated. use PK11_PBEKeyGen instead.
1349
 */
1350
PK11SymKey *
1351
PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech,
1352
                  SECItem *pwitem, PRBool faulty3DES, void *wincx)
1353
0
{
1354
0
    if (faulty3DES && (type == CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC)) {
1355
0
        type = CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC;
1356
0
    }
1357
0
    return pk11_RawPBEKeyGenWithKeyType(slot, type, mech, -1, 0, pwitem, wincx);
1358
0
}
1359
1360
/*
1361
 * pubic, supports pkcs5 v2.
1362
 *
1363
 * Create symkey from a PBE key. The algid can be created with
1364
 *  PK11_CreatePBEV2AlgorithmID and PK11_CreatePBEAlgorithmID, or by
1365
 *  extraction of der data.
1366
 */
1367
PK11SymKey *
1368
PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem,
1369
               PRBool faulty3DES, void *wincx)
1370
0
{
1371
0
    CK_MECHANISM_TYPE type;
1372
0
    SECItem *param = NULL;
1373
0
    PK11SymKey *symKey = NULL;
1374
0
    SECOidTag pbeAlg;
1375
0
    CK_KEY_TYPE keyType = -1;
1376
0
    int keyLen = 0;
1377
1378
0
    pbeAlg = SECOID_GetAlgorithmTag(algid);
1379
    /* if we're using PKCS5v2, extract the additional information we need
1380
     * (key length, key type, and pbeAlg). */
1381
0
    if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
1382
0
        CK_MECHANISM_TYPE cipherMech;
1383
0
        sec_pkcs5V2Parameter *pbeV2_param;
1384
1385
0
        pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
1386
0
        if (pbeV2_param == NULL) {
1387
0
            return NULL;
1388
0
        }
1389
0
        cipherMech = PK11_AlgtagToMechanism(
1390
0
            SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
1391
0
        pbeAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId);
1392
0
        param = PK11_ParamFromAlgid(&pbeV2_param->pbeAlgId);
1393
0
        sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
1394
0
        keyLen = SEC_PKCS5GetKeyLength(algid);
1395
0
        if (keyLen == -1) {
1396
0
            keyLen = 0;
1397
0
        }
1398
0
        keyType = PK11_GetKeyType(cipherMech, keyLen);
1399
0
    } else {
1400
0
        param = PK11_ParamFromAlgid(algid);
1401
0
    }
1402
1403
0
    if (param == NULL) {
1404
0
        goto loser;
1405
0
    }
1406
1407
0
    type = PK11_AlgtagToMechanism(pbeAlg);
1408
0
    if (type == CKM_INVALID_MECHANISM) {
1409
0
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1410
0
        goto loser;
1411
0
    }
1412
0
    if (faulty3DES && (type == CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC)) {
1413
0
        type = CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC;
1414
0
    }
1415
0
    symKey = pk11_RawPBEKeyGenWithKeyType(slot, type, param, keyType, keyLen,
1416
0
                                          pwitem, wincx);
1417
1418
0
loser:
1419
0
    if (param) {
1420
0
        SECITEM_ZfreeItem(param, PR_TRUE);
1421
0
    }
1422
0
    return symKey;
1423
0
}
1424
1425
/*
1426
 * public, supports pkcs5v2
1427
 */
1428
SECItem *
1429
PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem)
1430
0
{
1431
0
    return SEC_PKCS5GetIV(algid, pwitem, PR_FALSE);
1432
0
}
1433
1434
CK_MECHANISM_TYPE
1435
pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param,
1436
                           SECItem *pbe_pwd, PRBool faulty3DES)
1437
0
{
1438
0
    int keyLen = 0;
1439
0
    SECOidTag algTag = SEC_PKCS5GetCryptoAlgorithm(algid);
1440
0
    CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(algTag);
1441
0
    CK_MECHANISM_TYPE returnedMechanism = CKM_INVALID_MECHANISM;
1442
0
    SECItem *iv = NULL;
1443
1444
0
    if (mech == CKM_INVALID_MECHANISM) {
1445
0
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1446
0
        goto loser;
1447
0
    }
1448
0
    if (PK11_GetIVLength(mech)) {
1449
0
        iv = SEC_PKCS5GetIV(algid, pbe_pwd, faulty3DES);
1450
0
        if (iv == NULL) {
1451
0
            goto loser;
1452
0
        }
1453
0
    }
1454
1455
0
    keyLen = SEC_PKCS5GetKeyLength(algid);
1456
1457
0
    *param = pk11_ParamFromIVWithLen(mech, iv, keyLen);
1458
0
    if (*param == NULL) {
1459
0
        goto loser;
1460
0
    }
1461
0
    returnedMechanism = mech;
1462
1463
0
loser:
1464
0
    if (iv) {
1465
0
        SECITEM_FreeItem(iv, PR_TRUE);
1466
0
    }
1467
0
    return returnedMechanism;
1468
0
}
1469
1470
/*
1471
 * Public, supports pkcs5 v2
1472
 *
1473
 * Get the crypto mechanism directly from the pbe algorithmid.
1474
 *
1475
 * It's important to go directly from the algorithm id so that we can
1476
 * handle both the PKCS #5 v1, PKCS #12, and PKCS #5 v2 cases.
1477
 *
1478
 * This function returns both the mechanism and the parameter for the mechanism.
1479
 * The caller is responsible for freeing the parameter.
1480
 */
1481
CK_MECHANISM_TYPE
1482
PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param,
1483
                           SECItem *pbe_pwd)
1484
0
{
1485
0
    return pk11_GetPBECryptoMechanism(algid, param, pbe_pwd, PR_FALSE);
1486
0
}