Coverage Report

Created: 2024-11-21 07:03

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