Coverage Report

Created: 2018-09-25 14:53

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