Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/pkcs12/p12local.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 "nssrenam.h"
6
#include "pkcs12.h"
7
#include "secpkcs7.h"
8
#include "secasn1.h"
9
#include "seccomon.h"
10
#include "secoid.h"
11
#include "sechash.h"
12
#include "secitem.h"
13
#include "secerr.h"
14
#include "pk11func.h"
15
#include "p12local.h"
16
#include "p12.h"
17
18
0
#define SALT_LENGTH 16
19
20
SEC_ASN1_MKSUB(SECKEY_PrivateKeyInfoTemplate)
21
SEC_ASN1_MKSUB(sgn_DigestInfoTemplate)
22
23
CK_MECHANISM_TYPE
24
sec_pkcs12_algtag_to_mech(SECOidTag algtag)
25
0
{
26
0
    switch (algtag) {
27
0
        case SEC_OID_MD2:
28
0
            return CKM_MD2_HMAC;
29
0
        case SEC_OID_MD5:
30
0
            return CKM_MD5_HMAC;
31
0
        case SEC_OID_SHA1:
32
0
            return CKM_SHA_1_HMAC;
33
0
        case SEC_OID_SHA224:
34
0
            return CKM_SHA224_HMAC;
35
0
        case SEC_OID_SHA256:
36
0
            return CKM_SHA256_HMAC;
37
0
        case SEC_OID_SHA384:
38
0
            return CKM_SHA384_HMAC;
39
0
        case SEC_OID_SHA512:
40
0
            return CKM_SHA512_HMAC;
41
0
        default:
42
0
            break;
43
0
    }
44
0
    return CKM_INVALID_MECHANISM;
45
0
}
46
47
/* helper functions */
48
/* returns proper bag type template based upon object type tag */
49
const SEC_ASN1Template *
50
sec_pkcs12_choose_bag_type_old(void *src_or_dest, PRBool encoding)
51
0
{
52
0
    const SEC_ASN1Template *theTemplate;
53
0
    SEC_PKCS12SafeBag *safebag;
54
0
    SECOidData *oiddata;
55
0
56
0
    if (src_or_dest == NULL) {
57
0
        return NULL;
58
0
    }
59
0
60
0
    safebag = (SEC_PKCS12SafeBag *)src_or_dest;
61
0
62
0
    oiddata = safebag->safeBagTypeTag;
63
0
    if (oiddata == NULL) {
64
0
        oiddata = SECOID_FindOID(&safebag->safeBagType);
65
0
        safebag->safeBagTypeTag = oiddata;
66
0
    }
67
0
68
0
    switch (oiddata->offset) {
69
0
        default:
70
0
            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
71
0
            break;
72
0
        case SEC_OID_PKCS12_KEY_BAG_ID:
73
0
            theTemplate = SEC_PointerToPKCS12KeyBagTemplate;
74
0
            break;
75
0
        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
76
0
            theTemplate = SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD;
77
0
            break;
78
0
        case SEC_OID_PKCS12_SECRET_BAG_ID:
79
0
            theTemplate = SEC_PointerToPKCS12SecretBagTemplate;
80
0
            break;
81
0
    }
82
0
    return theTemplate;
83
0
}
84
85
const SEC_ASN1Template *
86
sec_pkcs12_choose_bag_type(void *src_or_dest, PRBool encoding)
87
0
{
88
0
    const SEC_ASN1Template *theTemplate;
89
0
    SEC_PKCS12SafeBag *safebag;
90
0
    SECOidData *oiddata;
91
0
92
0
    if (src_or_dest == NULL) {
93
0
        return NULL;
94
0
    }
95
0
96
0
    safebag = (SEC_PKCS12SafeBag *)src_or_dest;
97
0
98
0
    oiddata = safebag->safeBagTypeTag;
99
0
    if (oiddata == NULL) {
100
0
        oiddata = SECOID_FindOID(&safebag->safeBagType);
101
0
        safebag->safeBagTypeTag = oiddata;
102
0
    }
103
0
104
0
    switch (oiddata->offset) {
105
0
        default:
106
0
            theTemplate = SEC_ASN1_GET(SEC_AnyTemplate);
107
0
            break;
108
0
        case SEC_OID_PKCS12_KEY_BAG_ID:
109
0
            theTemplate = SEC_PKCS12PrivateKeyBagTemplate;
110
0
            break;
111
0
        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
112
0
            theTemplate = SEC_PKCS12CertAndCRLBagTemplate;
113
0
            break;
114
0
        case SEC_OID_PKCS12_SECRET_BAG_ID:
115
0
            theTemplate = SEC_PKCS12SecretBagTemplate;
116
0
            break;
117
0
    }
118
0
    return theTemplate;
119
0
}
120
121
/* returns proper cert crl template based upon type tag */
122
const SEC_ASN1Template *
123
sec_pkcs12_choose_cert_crl_type_old(void *src_or_dest, PRBool encoding)
124
0
{
125
0
    const SEC_ASN1Template *theTemplate;
126
0
    SEC_PKCS12CertAndCRL *certbag;
127
0
    SECOidData *oiddata;
128
0
129
0
    if (src_or_dest == NULL) {
130
0
        return NULL;
131
0
    }
132
0
133
0
    certbag = (SEC_PKCS12CertAndCRL *)src_or_dest;
134
0
    oiddata = certbag->BagTypeTag;
135
0
    if (oiddata == NULL) {
136
0
        oiddata = SECOID_FindOID(&certbag->BagID);
137
0
        certbag->BagTypeTag = oiddata;
138
0
    }
139
0
140
0
    switch (oiddata->offset) {
141
0
        default:
142
0
            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
143
0
            break;
144
0
        case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
145
0
            theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate_OLD;
146
0
            break;
147
0
        case SEC_OID_PKCS12_SDSI_CERT_BAG:
148
0
            theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
149
0
            break;
150
0
    }
151
0
    return theTemplate;
152
0
}
153
154
const SEC_ASN1Template *
155
sec_pkcs12_choose_cert_crl_type(void *src_or_dest, PRBool encoding)
156
0
{
157
0
    const SEC_ASN1Template *theTemplate;
158
0
    SEC_PKCS12CertAndCRL *certbag;
159
0
    SECOidData *oiddata;
160
0
161
0
    if (src_or_dest == NULL) {
162
0
        return NULL;
163
0
    }
164
0
165
0
    certbag = (SEC_PKCS12CertAndCRL *)src_or_dest;
166
0
    oiddata = certbag->BagTypeTag;
167
0
    if (oiddata == NULL) {
168
0
        oiddata = SECOID_FindOID(&certbag->BagID);
169
0
        certbag->BagTypeTag = oiddata;
170
0
    }
171
0
172
0
    switch (oiddata->offset) {
173
0
        default:
174
0
            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
175
0
            break;
176
0
        case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
177
0
            theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate;
178
0
            break;
179
0
        case SEC_OID_PKCS12_SDSI_CERT_BAG:
180
0
            theTemplate = SEC_PointerToPKCS12SDSICertTemplate;
181
0
            break;
182
0
    }
183
0
    return theTemplate;
184
0
}
185
186
/* returns appropriate shroud template based on object type tag */
187
const SEC_ASN1Template *
188
sec_pkcs12_choose_shroud_type(void *src_or_dest, PRBool encoding)
189
0
{
190
0
    const SEC_ASN1Template *theTemplate;
191
0
    SEC_PKCS12ESPVKItem *espvk;
192
0
    SECOidData *oiddata;
193
0
194
0
    if (src_or_dest == NULL) {
195
0
        return NULL;
196
0
    }
197
0
198
0
    espvk = (SEC_PKCS12ESPVKItem *)src_or_dest;
199
0
    oiddata = espvk->espvkTag;
200
0
    if (oiddata == NULL) {
201
0
        oiddata = SECOID_FindOID(&espvk->espvkOID);
202
0
        espvk->espvkTag = oiddata;
203
0
    }
204
0
205
0
    switch (oiddata->offset) {
206
0
        default:
207
0
            theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
208
0
            break;
209
0
        case SEC_OID_PKCS12_PKCS8_KEY_SHROUDING:
210
0
            theTemplate =
211
0
                SEC_ASN1_GET(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate);
212
0
            break;
213
0
    }
214
0
    return theTemplate;
215
0
}
216
217
/* generate SALT  placing it into the character array passed in.
218
 * it is assumed that salt_dest is an array of appropriate size
219
 * XXX We might want to generate our own random context
220
 */
221
SECItem *
222
sec_pkcs12_generate_salt(void)
223
0
{
224
0
    SECItem *salt;
225
0
226
0
    salt = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
227
0
    if (salt == NULL) {
228
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
229
0
        return NULL;
230
0
    }
231
0
    salt->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
232
0
                                              SALT_LENGTH);
233
0
    salt->len = SALT_LENGTH;
234
0
    if (salt->data == NULL) {
235
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
236
0
        SECITEM_ZfreeItem(salt, PR_TRUE);
237
0
        return NULL;
238
0
    }
239
0
240
0
    PK11_GenerateRandom(salt->data, salt->len);
241
0
242
0
    return salt;
243
0
}
244
245
/* generate KEYS -- as per PKCS12 section 7.
246
 * only used for MAC
247
 */
248
SECItem *
249
sec_pkcs12_generate_key_from_password(SECOidTag algorithm,
250
                                      SECItem *salt,
251
                                      SECItem *password)
252
0
{
253
0
    unsigned char *pre_hash = NULL;
254
0
    unsigned char *hash_dest = NULL;
255
0
    SECStatus res;
256
0
    PLArenaPool *poolp;
257
0
    SECItem *key = NULL;
258
0
    int key_len = 0;
259
0
260
0
    if ((salt == NULL) || (password == NULL)) {
261
0
        return NULL;
262
0
    }
263
0
264
0
    poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
265
0
    if (poolp == NULL) {
266
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
267
0
        return NULL;
268
0
    }
269
0
270
0
    pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) * (salt->len + password->len));
271
0
    if (pre_hash == NULL) {
272
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
273
0
        goto loser;
274
0
    }
275
0
276
0
    hash_dest = (unsigned char *)PORT_ArenaZAlloc(poolp,
277
0
                                                  sizeof(unsigned char) * SHA1_LENGTH);
278
0
    if (hash_dest == NULL) {
279
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
280
0
        goto loser;
281
0
    }
282
0
283
0
    PORT_Memcpy(pre_hash, salt->data, salt->len);
284
0
    /* handle password of 0 length case */
285
0
    if (password->len > 0) {
286
0
        PORT_Memcpy(&(pre_hash[salt->len]), password->data, password->len);
287
0
    }
288
0
289
0
    res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, pre_hash,
290
0
                       (salt->len + password->len));
291
0
    if (res == SECFailure) {
292
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
293
0
        goto loser;
294
0
    }
295
0
296
0
    switch (algorithm) {
297
0
        case SEC_OID_SHA1:
298
0
            if (key_len == 0)
299
0
                key_len = 16;
300
0
            key = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
301
0
            if (key == NULL) {
302
0
                PORT_SetError(SEC_ERROR_NO_MEMORY);
303
0
                goto loser;
304
0
            }
305
0
            key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * key_len);
306
0
            if (key->data == NULL) {
307
0
                PORT_SetError(SEC_ERROR_NO_MEMORY);
308
0
                goto loser;
309
0
            }
310
0
            key->len = key_len;
311
0
            PORT_Memcpy(key->data, &hash_dest[SHA1_LENGTH - key->len], key->len);
312
0
            break;
313
0
        default:
314
0
            goto loser;
315
0
            break;
316
0
    }
317
0
318
0
    PORT_FreeArena(poolp, PR_TRUE);
319
0
    return key;
320
0
321
0
loser:
322
0
    PORT_FreeArena(poolp, PR_TRUE);
323
0
    if (key != NULL) {
324
0
        SECITEM_ZfreeItem(key, PR_TRUE);
325
0
    }
326
0
    return NULL;
327
0
}
328
329
/* MAC is generated per PKCS 12 section 6.  It is expected that key, msg
330
 * and mac_dest are pre allocated, non-NULL arrays.  msg_len is passed in
331
 * because it is not known how long the message actually is.  String
332
 * manipulation routines will not necessarily work because msg may have
333
 * imbedded NULLs
334
 */
335
static SECItem *
336
sec_pkcs12_generate_old_mac(SECItem *key,
337
                            SECItem *msg)
338
0
{
339
0
    SECStatus res;
340
0
    PLArenaPool *temparena = NULL;
341
0
    unsigned char *hash_dest = NULL, *hash_src1 = NULL, *hash_src2 = NULL;
342
0
    int i;
343
0
    SECItem *mac = NULL;
344
0
345
0
    if ((key == NULL) || (msg == NULL))
346
0
        goto loser;
347
0
348
0
    /* allocate return item */
349
0
    mac = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
350
0
    if (mac == NULL)
351
0
        return NULL;
352
0
    mac->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * SHA1_LENGTH);
353
0
    mac->len = SHA1_LENGTH;
354
0
    if (mac->data == NULL)
355
0
        goto loser;
356
0
357
0
    /* allocate temporary items */
358
0
    temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
359
0
    if (temparena == NULL)
360
0
        goto loser;
361
0
362
0
    hash_src1 = (unsigned char *)PORT_ArenaZAlloc(temparena,
363
0
                                                  sizeof(unsigned char) * (16 + msg->len));
364
0
    if (hash_src1 == NULL)
365
0
        goto loser;
366
0
367
0
    hash_src2 = (unsigned char *)PORT_ArenaZAlloc(temparena,
368
0
                                                  sizeof(unsigned char) * (SHA1_LENGTH + 16));
369
0
    if (hash_src2 == NULL)
370
0
        goto loser;
371
0
372
0
    hash_dest = (unsigned char *)PORT_ArenaZAlloc(temparena,
373
0
                                                  sizeof(unsigned char) * SHA1_LENGTH);
374
0
    if (hash_dest == NULL)
375
0
        goto loser;
376
0
377
0
    /* perform mac'ing as per PKCS 12 */
378
0
379
0
    /* first round of hashing */
380
0
    for (i = 0; i < 16; i++)
381
0
        hash_src1[i] = key->data[i] ^ 0x36;
382
0
    PORT_Memcpy(&(hash_src1[16]), msg->data, msg->len);
383
0
    res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, hash_src1, (16 + msg->len));
384
0
    if (res == SECFailure)
385
0
        goto loser;
386
0
387
0
    /* second round of hashing */
388
0
    for (i = 0; i < 16; i++)
389
0
        hash_src2[i] = key->data[i] ^ 0x5c;
390
0
    PORT_Memcpy(&(hash_src2[16]), hash_dest, SHA1_LENGTH);
391
0
    res = PK11_HashBuf(SEC_OID_SHA1, mac->data, hash_src2, SHA1_LENGTH + 16);
392
0
    if (res == SECFailure)
393
0
        goto loser;
394
0
395
0
    PORT_FreeArena(temparena, PR_TRUE);
396
0
    return mac;
397
0
398
0
loser:
399
0
    if (temparena != NULL)
400
0
        PORT_FreeArena(temparena, PR_TRUE);
401
0
    if (mac != NULL)
402
0
        SECITEM_ZfreeItem(mac, PR_TRUE);
403
0
    return NULL;
404
0
}
405
406
/* MAC is generated per PKCS 12 section 6.  It is expected that key, msg
407
 * and mac_dest are pre allocated, non-NULL arrays.  msg_len is passed in
408
 * because it is not known how long the message actually is.  String
409
 * manipulation routines will not necessarily work because msg may have
410
 * imbedded NULLs
411
 */
412
SECItem *
413
sec_pkcs12_generate_mac(SECItem *key,
414
                        SECItem *msg,
415
                        PRBool old_method)
416
0
{
417
0
    SECStatus res = SECFailure;
418
0
    SECItem *mac = NULL;
419
0
    PK11Context *pk11cx = NULL;
420
0
    SECItem ignore = { 0 };
421
0
422
0
    if ((key == NULL) || (msg == NULL)) {
423
0
        return NULL;
424
0
    }
425
0
426
0
    if (old_method == PR_TRUE) {
427
0
        return sec_pkcs12_generate_old_mac(key, msg);
428
0
    }
429
0
430
0
    /* allocate return item */
431
0
    mac = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH);
432
0
    if (mac == NULL) {
433
0
        return NULL;
434
0
    }
435
0
436
0
    pk11cx = PK11_CreateContextByRawKey(NULL, CKM_SHA_1_HMAC, PK11_OriginDerive,
437
0
                                        CKA_SIGN, key, &ignore, NULL);
438
0
    if (pk11cx == NULL) {
439
0
        goto loser;
440
0
    }
441
0
442
0
    res = PK11_DigestBegin(pk11cx);
443
0
    if (res == SECFailure) {
444
0
        goto loser;
445
0
    }
446
0
447
0
    res = PK11_DigestOp(pk11cx, msg->data, msg->len);
448
0
    if (res == SECFailure) {
449
0
        goto loser;
450
0
    }
451
0
452
0
    res = PK11_DigestFinal(pk11cx, mac->data, &mac->len, SHA1_LENGTH);
453
0
    if (res == SECFailure) {
454
0
        goto loser;
455
0
    }
456
0
457
0
    PK11_DestroyContext(pk11cx, PR_TRUE);
458
0
    pk11cx = NULL;
459
0
460
0
loser:
461
0
462
0
    if (res != SECSuccess) {
463
0
        SECITEM_ZfreeItem(mac, PR_TRUE);
464
0
        mac = NULL;
465
0
        if (pk11cx) {
466
0
            PK11_DestroyContext(pk11cx, PR_TRUE);
467
0
        }
468
0
    }
469
0
470
0
    return mac;
471
0
}
472
473
/* compute the thumbprint of the DER cert and create a digest info
474
 * to store it in and return the digest info.
475
 * a return of NULL indicates an error.
476
 */
477
SGNDigestInfo *
478
sec_pkcs12_compute_thumbprint(SECItem *der_cert)
479
0
{
480
0
    SGNDigestInfo *thumb = NULL;
481
0
    SECItem digest;
482
0
    PLArenaPool *temparena = NULL;
483
0
    SECStatus rv = SECFailure;
484
0
485
0
    if (der_cert == NULL)
486
0
        return NULL;
487
0
488
0
    temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
489
0
    if (temparena == NULL) {
490
0
        return NULL;
491
0
    }
492
0
493
0
    digest.data = (unsigned char *)PORT_ArenaZAlloc(temparena,
494
0
                                                    sizeof(unsigned char) *
495
0
                                                        SHA1_LENGTH);
496
0
    /* digest data and create digest info */
497
0
    if (digest.data != NULL) {
498
0
        digest.len = SHA1_LENGTH;
499
0
        rv = PK11_HashBuf(SEC_OID_SHA1, digest.data, der_cert->data,
500
0
                          der_cert->len);
501
0
        if (rv == SECSuccess) {
502
0
            thumb = SGN_CreateDigestInfo(SEC_OID_SHA1,
503
0
                                         digest.data,
504
0
                                         digest.len);
505
0
        } else {
506
0
            PORT_SetError(SEC_ERROR_NO_MEMORY);
507
0
        }
508
0
    } else {
509
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
510
0
    }
511
0
512
0
    PORT_FreeArena(temparena, PR_TRUE);
513
0
514
0
    return thumb;
515
0
}
516
517
/* create a virtual password per PKCS 12, the password is converted
518
 * to unicode, the salt is prepended to it, and then the whole thing
519
 * is returned */
520
SECItem *
521
sec_pkcs12_create_virtual_password(SECItem *password, SECItem *salt,
522
                                   PRBool swap)
523
0
{
524
0
    SECItem uniPwd = { siBuffer, NULL, 0 }, *retPwd = NULL;
525
0
526
0
    if ((password == NULL) || (salt == NULL)) {
527
0
        return NULL;
528
0
    }
529
0
530
0
    if (password->len == 0) {
531
0
        uniPwd.data = (unsigned char *)PORT_ZAlloc(2);
532
0
        uniPwd.len = 2;
533
0
        if (!uniPwd.data) {
534
0
            return NULL;
535
0
        }
536
0
    } else {
537
0
        uniPwd.data = (unsigned char *)PORT_ZAlloc(password->len * 3);
538
0
        uniPwd.len = password->len * 3;
539
0
        if (!PORT_UCS2_ASCIIConversion(PR_TRUE, password->data, password->len,
540
0
                                       uniPwd.data, uniPwd.len, &uniPwd.len, swap)) {
541
0
            SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
542
0
            return NULL;
543
0
        }
544
0
    }
545
0
546
0
    retPwd = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
547
0
    if (retPwd == NULL) {
548
0
        goto loser;
549
0
    }
550
0
551
0
    /* allocate space and copy proper data */
552
0
    retPwd->len = uniPwd.len + salt->len;
553
0
    retPwd->data = (unsigned char *)PORT_Alloc(retPwd->len);
554
0
    if (retPwd->data == NULL) {
555
0
        PORT_Free(retPwd);
556
0
        goto loser;
557
0
    }
558
0
559
0
    PORT_Memcpy(retPwd->data, salt->data, salt->len);
560
0
    PORT_Memcpy((retPwd->data + salt->len), uniPwd.data, uniPwd.len);
561
0
562
0
    SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
563
0
564
0
    return retPwd;
565
0
566
0
loser:
567
0
    PORT_SetError(SEC_ERROR_NO_MEMORY);
568
0
    SECITEM_ZfreeItem(&uniPwd, PR_FALSE);
569
0
    return NULL;
570
0
}
571
572
/* appends a shrouded key to a key bag.  this is used for exporting
573
 * to store externally wrapped keys.  it is used when importing to convert
574
 * old items to new
575
 */
576
SECStatus
577
sec_pkcs12_append_shrouded_key(SEC_PKCS12BaggageItem *bag,
578
                               SEC_PKCS12ESPVKItem *espvk)
579
0
{
580
0
    int size;
581
0
    void *mark = NULL, *dummy = NULL;
582
0
583
0
    if ((bag == NULL) || (espvk == NULL))
584
0
        return SECFailure;
585
0
586
0
    mark = PORT_ArenaMark(bag->poolp);
587
0
588
0
    /* grow the list */
589
0
    size = (bag->nEspvks + 1) * sizeof(SEC_PKCS12ESPVKItem *);
590
0
    dummy = (SEC_PKCS12ESPVKItem **)PORT_ArenaGrow(bag->poolp,
591
0
                                                   bag->espvks, size,
592
0
                                                   size + sizeof(SEC_PKCS12ESPVKItem *));
593
0
    bag->espvks = (SEC_PKCS12ESPVKItem **)dummy;
594
0
    if (dummy == NULL) {
595
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
596
0
        goto loser;
597
0
    }
598
0
599
0
    bag->espvks[bag->nEspvks] = espvk;
600
0
    bag->nEspvks++;
601
0
    bag->espvks[bag->nEspvks] = NULL;
602
0
603
0
    PORT_ArenaUnmark(bag->poolp, mark);
604
0
    return SECSuccess;
605
0
606
0
loser:
607
0
    PORT_ArenaRelease(bag->poolp, mark);
608
0
    return SECFailure;
609
0
}
610
611
/* search a certificate list for a nickname, a thumbprint, or both
612
 * within a certificate bag.  if the certificate could not be
613
 * found or an error occurs, NULL is returned;
614
 */
615
static SEC_PKCS12CertAndCRL *
616
sec_pkcs12_find_cert_in_certbag(SEC_PKCS12CertAndCRLBag *certbag,
617
                                SECItem *nickname, SGNDigestInfo *thumbprint)
618
0
{
619
0
    PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
620
0
    int i, j;
621
0
622
0
    if ((certbag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
623
0
        return NULL;
624
0
    }
625
0
626
0
    if (thumbprint && nickname) {
627
0
        search_both = PR_TRUE;
628
0
    }
629
0
630
0
    if (nickname) {
631
0
        search_nickname = PR_TRUE;
632
0
    }
633
0
634
0
search_again:
635
0
    i = 0;
636
0
    while (certbag->certAndCRLs[i] != NULL) {
637
0
        SEC_PKCS12CertAndCRL *cert = certbag->certAndCRLs[i];
638
0
639
0
        if (SECOID_FindOIDTag(&cert->BagID) == SEC_OID_PKCS12_X509_CERT_CRL_BAG) {
640
0
641
0
            /* check nicknames */
642
0
            if (search_nickname) {
643
0
                if (SECITEM_CompareItem(nickname, &cert->nickname) == SECEqual) {
644
0
                    return cert;
645
0
                }
646
0
            } else {
647
0
                /* check thumbprints */
648
0
                SECItem **derCertList;
649
0
650
0
                /* get pointer to certificate list, does not need to
651
0
                 * be freed since it is within the arena which will
652
0
                 * be freed later.
653
0
                 */
654
0
                derCertList = SEC_PKCS7GetCertificateList(&cert->value.x509->certOrCRL);
655
0
                j = 0;
656
0
                if (derCertList != NULL) {
657
0
                    while (derCertList[j] != NULL) {
658
0
                        SECComparison eq;
659
0
                        SGNDigestInfo *di;
660
0
                        di = sec_pkcs12_compute_thumbprint(derCertList[j]);
661
0
                        if (di) {
662
0
                            eq = SGN_CompareDigestInfo(thumbprint, di);
663
0
                            SGN_DestroyDigestInfo(di);
664
0
                            if (eq == SECEqual) {
665
0
                                /* copy the derCert for later reference */
666
0
                                cert->value.x509->derLeafCert = derCertList[j];
667
0
                                return cert;
668
0
                            }
669
0
                        } else {
670
0
                            /* an error occurred */
671
0
                            return NULL;
672
0
                        }
673
0
                        j++;
674
0
                    }
675
0
                }
676
0
            }
677
0
        }
678
0
679
0
        i++;
680
0
    }
681
0
682
0
    if (search_both) {
683
0
        search_both = PR_FALSE;
684
0
        search_nickname = PR_FALSE;
685
0
        goto search_again;
686
0
    }
687
0
688
0
    return NULL;
689
0
}
690
691
/* search a key list for a nickname, a thumbprint, or both
692
 * within a key bag.  if the key could not be
693
 * found or an error occurs, NULL is returned;
694
 */
695
static SEC_PKCS12PrivateKey *
696
sec_pkcs12_find_key_in_keybag(SEC_PKCS12PrivateKeyBag *keybag,
697
                              SECItem *nickname, SGNDigestInfo *thumbprint)
698
0
{
699
0
    PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
700
0
    int i, j;
701
0
702
0
    if ((keybag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
703
0
        return NULL;
704
0
    }
705
0
706
0
    if (keybag->privateKeys == NULL) {
707
0
        return NULL;
708
0
    }
709
0
710
0
    if (thumbprint && nickname) {
711
0
        search_both = PR_TRUE;
712
0
    }
713
0
714
0
    if (nickname) {
715
0
        search_nickname = PR_TRUE;
716
0
    }
717
0
718
0
search_again:
719
0
    i = 0;
720
0
    while (keybag->privateKeys[i] != NULL) {
721
0
        SEC_PKCS12PrivateKey *key = keybag->privateKeys[i];
722
0
723
0
        /* check nicknames */
724
0
        if (search_nickname) {
725
0
            if (SECITEM_CompareItem(nickname, &key->pvkData.nickname) == SECEqual) {
726
0
                return key;
727
0
            }
728
0
        } else {
729
0
            /* check digests */
730
0
            SGNDigestInfo **assocCerts = key->pvkData.assocCerts;
731
0
            if ((assocCerts == NULL) || (assocCerts[0] == NULL)) {
732
0
                return NULL;
733
0
            }
734
0
735
0
            j = 0;
736
0
            while (assocCerts[j] != NULL) {
737
0
                SECComparison eq;
738
0
                eq = SGN_CompareDigestInfo(thumbprint, assocCerts[j]);
739
0
                if (eq == SECEqual) {
740
0
                    return key;
741
0
                }
742
0
                j++;
743
0
            }
744
0
        }
745
0
        i++;
746
0
    }
747
0
748
0
    if (search_both) {
749
0
        search_both = PR_FALSE;
750
0
        search_nickname = PR_FALSE;
751
0
        goto search_again;
752
0
    }
753
0
754
0
    return NULL;
755
0
}
756
757
/* seach the safe first then try the baggage bag
758
 *  safe and bag contain certs and keys to search
759
 *  objType is the object type to look for
760
 *  bagType is the type of bag that was found by sec_pkcs12_find_object
761
 *  index is the entity in safe->safeContents or bag->unencSecrets which
762
 *    is being searched
763
 *  nickname and thumbprint are the search criteria
764
 *
765
 * a return of null indicates no match
766
 */
767
static void *
768
sec_pkcs12_try_find(SEC_PKCS12SafeContents *safe,
769
                    SEC_PKCS12BaggageItem *bag,
770
                    SECOidTag objType, SECOidTag bagType, int index,
771
                    SECItem *nickname, SGNDigestInfo *thumbprint)
772
0
{
773
0
    PRBool searchSafe;
774
0
    int i = index;
775
0
776
0
    if ((safe == NULL) && (bag == NULL)) {
777
0
        return NULL;
778
0
    }
779
0
780
0
    searchSafe = (safe == NULL ? PR_FALSE : PR_TRUE);
781
0
    switch (objType) {
782
0
        case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
783
0
            if (objType == bagType) {
784
0
                SEC_PKCS12CertAndCRLBag *certBag;
785
0
786
0
                if (searchSafe) {
787
0
                    certBag = safe->contents[i]->safeContent.certAndCRLBag;
788
0
                } else {
789
0
                    certBag = bag->unencSecrets[i]->safeContent.certAndCRLBag;
790
0
                }
791
0
                return sec_pkcs12_find_cert_in_certbag(certBag, nickname,
792
0
                                                       thumbprint);
793
0
            }
794
0
            break;
795
0
        case SEC_OID_PKCS12_KEY_BAG_ID:
796
0
            if (objType == bagType) {
797
0
                SEC_PKCS12PrivateKeyBag *keyBag;
798
0
799
0
                if (searchSafe) {
800
0
                    keyBag = safe->contents[i]->safeContent.keyBag;
801
0
                } else {
802
0
                    keyBag = bag->unencSecrets[i]->safeContent.keyBag;
803
0
                }
804
0
                return sec_pkcs12_find_key_in_keybag(keyBag, nickname,
805
0
                                                     thumbprint);
806
0
            }
807
0
            break;
808
0
        default:
809
0
            break;
810
0
    }
811
0
812
0
    return NULL;
813
0
}
814
815
/* searches both the baggage and the safe areas looking for
816
 * object of specified type matching either the nickname or the
817
 * thumbprint specified.
818
 *
819
 * safe and baggage store certs and keys
820
 * objType is the OID for the bag type to be searched:
821
 *   SEC_OID_PKCS12_KEY_BAG_ID, or
822
 *   SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID
823
 * nickname and thumbprint are the search criteria
824
 *
825
 * if no match found, NULL returned and error set
826
 */
827
void *
828
sec_pkcs12_find_object(SEC_PKCS12SafeContents *safe,
829
                       SEC_PKCS12Baggage *baggage,
830
                       SECOidTag objType,
831
                       SECItem *nickname,
832
                       SGNDigestInfo *thumbprint)
833
0
{
834
0
    int i, j;
835
0
    void *retItem;
836
0
837
0
    if (((safe == NULL) && (thumbprint == NULL)) ||
838
0
        ((nickname == NULL) && (thumbprint == NULL))) {
839
0
        return NULL;
840
0
    }
841
0
842
0
    i = 0;
843
0
    if ((safe != NULL) && (safe->contents != NULL)) {
844
0
        while (safe->contents[i] != NULL) {
845
0
            SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType);
846
0
            retItem = sec_pkcs12_try_find(safe, NULL, objType, bagType, i,
847
0
                                          nickname, thumbprint);
848
0
            if (retItem != NULL) {
849
0
                return retItem;
850
0
            }
851
0
            i++;
852
0
        }
853
0
    }
854
0
855
0
    if ((baggage != NULL) && (baggage->bags != NULL)) {
856
0
        i = 0;
857
0
        while (baggage->bags[i] != NULL) {
858
0
            SEC_PKCS12BaggageItem *xbag = baggage->bags[i];
859
0
            j = 0;
860
0
            if (xbag->unencSecrets != NULL) {
861
0
                while (xbag->unencSecrets[j] != NULL) {
862
0
                    SECOidTag bagType;
863
0
                    bagType = SECOID_FindOIDTag(&xbag->unencSecrets[j]->safeBagType);
864
0
                    retItem = sec_pkcs12_try_find(NULL, xbag, objType, bagType,
865
0
                                                  j, nickname, thumbprint);
866
0
                    if (retItem != NULL) {
867
0
                        return retItem;
868
0
                    }
869
0
                    j++;
870
0
                }
871
0
            }
872
0
            i++;
873
0
        }
874
0
    }
875
0
876
0
    PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME);
877
0
    return NULL;
878
0
}
879
880
/* this function converts a password to unicode and encures that the
881
 * required double 0 byte be placed at the end of the string
882
 */
883
PRBool
884
sec_pkcs12_convert_item_to_unicode(PLArenaPool *arena, SECItem *dest,
885
                                   SECItem *src, PRBool zeroTerm,
886
                                   PRBool asciiConvert, PRBool toUnicode)
887
0
{
888
0
    PRBool success = PR_FALSE;
889
0
    if (!src || !dest) {
890
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
891
0
        return PR_FALSE;
892
0
    }
893
0
894
0
    dest->len = src->len * 3 + 2;
895
0
    if (arena) {
896
0
        dest->data = (unsigned char *)PORT_ArenaZAlloc(arena, dest->len);
897
0
    } else {
898
0
        dest->data = (unsigned char *)PORT_ZAlloc(dest->len);
899
0
    }
900
0
901
0
    if (!dest->data) {
902
0
        dest->len = 0;
903
0
        return PR_FALSE;
904
0
    }
905
0
906
0
    if (!asciiConvert) {
907
0
        success = PORT_UCS2_UTF8Conversion(toUnicode, src->data, src->len, dest->data,
908
0
                                           dest->len, &dest->len);
909
0
    } else {
910
#ifndef IS_LITTLE_ENDIAN
911
        PRBool swapUnicode = PR_FALSE;
912
#else
913
0
        PRBool swapUnicode = PR_TRUE;
914
0
#endif
915
0
        success = PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len, dest->data,
916
0
                                            dest->len, &dest->len, swapUnicode);
917
0
    }
918
0
919
0
    if (!success) {
920
0
        if (!arena) {
921
0
            PORT_Free(dest->data);
922
0
            dest->data = NULL;
923
0
            dest->len = 0;
924
0
        }
925
0
        return PR_FALSE;
926
0
    }
927
0
928
0
    if ((dest->len >= 2) &&
929
0
        (dest->data[dest->len - 1] || dest->data[dest->len - 2]) && zeroTerm) {
930
0
        if (dest->len + 2 > 3 * src->len) {
931
0
            if (arena) {
932
0
                dest->data = (unsigned char *)PORT_ArenaGrow(arena,
933
0
                                                             dest->data, dest->len,
934
0
                                                             dest->len + 2);
935
0
            } else {
936
0
                dest->data = (unsigned char *)PORT_Realloc(dest->data,
937
0
                                                           dest->len + 2);
938
0
            }
939
0
940
0
            if (!dest->data) {
941
0
                return PR_FALSE;
942
0
            }
943
0
        }
944
0
        dest->len += 2;
945
0
        dest->data[dest->len - 1] = dest->data[dest->len - 2] = 0;
946
0
    }
947
0
948
0
    return PR_TRUE;
949
0
}
950
951
PRBool
952
sec_pkcs12_is_pkcs12_pbe_algorithm(SECOidTag algorithm)
953
0
{
954
0
    switch (algorithm) {
955
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
956
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
957
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
958
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
959
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
960
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
961
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
962
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
963
0
        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
964
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
965
0
        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
966
0
        /* those are actually PKCS #5 v1.5 PBEs, but we
967
0
         * historically treat them in the same way as PKCS #12
968
0
         * PBEs */
969
0
        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
970
0
        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
971
0
        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
972
0
            return PR_TRUE;
973
0
        default:
974
0
            return PR_FALSE;
975
0
    }
976
0
}
977
978
/* this function decodes a password from Unicode if necessary,
979
 * according to the PBE algorithm.
980
 *
981
 * we assume that the pwitem is already encoded in Unicode by the
982
 * caller.  if the encryption scheme is not the one defined in PKCS
983
 * #12, decode the pwitem back into UTF-8. */
984
PRBool
985
sec_pkcs12_decode_password(PLArenaPool *arena,
986
                           SECItem *result,
987
                           SECOidTag algorithm,
988
                           const SECItem *pwitem)
989
0
{
990
0
    if (!sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm))
991
0
        return sec_pkcs12_convert_item_to_unicode(arena, result,
992
0
                                                  (SECItem *)pwitem,
993
0
                                                  PR_TRUE, PR_FALSE, PR_FALSE);
994
0
995
0
    return SECITEM_CopyItem(arena, result, pwitem) == SECSuccess;
996
0
}
997
998
/* this function encodes a password into Unicode if necessary,
999
 * according to the PBE algorithm.
1000
 *
1001
 * we assume that the pwitem holds a raw password.  if the encryption
1002
 * scheme is the one defined in PKCS #12, encode the password into
1003
 * BMPString. */
1004
PRBool
1005
sec_pkcs12_encode_password(PLArenaPool *arena,
1006
                           SECItem *result,
1007
                           SECOidTag algorithm,
1008
                           const SECItem *pwitem)
1009
0
{
1010
0
    if (sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm))
1011
0
        return sec_pkcs12_convert_item_to_unicode(arena, result,
1012
0
                                                  (SECItem *)pwitem,
1013
0
                                                  PR_TRUE, PR_TRUE, PR_TRUE);
1014
0
1015
0
    return SECITEM_CopyItem(arena, result, pwitem) == SECSuccess;
1016
0
}
1017
1018
/* pkcs 12 templates */
1019
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser =
1020
    sec_pkcs12_choose_shroud_type;
1021
1022
const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[] =
1023
    {
1024
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
1025
      { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
1026
      { SEC_ASN1_ANY, offsetof(SEC_PKCS12SafeBag, derSafeContent) },
1027
      { 0 }
1028
    };
1029
1030
const SEC_ASN1Template SEC_PKCS12CodedCertBagTemplate[] =
1031
    {
1032
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
1033
      { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
1034
      { SEC_ASN1_ANY, offsetof(SEC_PKCS12CertAndCRL, derValue) },
1035
      { 0 }
1036
    };
1037
1038
const SEC_ASN1Template SEC_PKCS12CodedCertAndCRLBagTemplate[] =
1039
    {
1040
      { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
1041
        SEC_PKCS12CodedCertBagTemplate },
1042
    };
1043
1044
const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate_OLD[] =
1045
    {
1046
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
1047
      { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
1048
      { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
1049
        SEC_PKCS12PVKSupportingDataTemplate_OLD },
1050
      { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1051
            SEC_ASN1_DYNAMIC | 0,
1052
        offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
1053
        &sec_pkcs12_shroud_chooser },
1054
      { 0 }
1055
    };
1056
1057
const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate[] =
1058
    {
1059
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) },
1060
      { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) },
1061
      { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData),
1062
        SEC_PKCS12PVKSupportingDataTemplate },
1063
      { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
1064
            SEC_ASN1_DYNAMIC | 0,
1065
        offsetof(SEC_PKCS12ESPVKItem, espvkCipherText),
1066
        &sec_pkcs12_shroud_chooser },
1067
      { 0 }
1068
    };
1069
1070
const SEC_ASN1Template SEC_PKCS12PVKAdditionalDataTemplate[] =
1071
    {
1072
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKAdditionalData) },
1073
      { SEC_ASN1_OBJECT_ID,
1074
        offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalType) },
1075
      { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
1076
        offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalContent) },
1077
      { 0 }
1078
    };
1079
1080
const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate_OLD[] =
1081
    {
1082
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
1083
      { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
1084
        offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
1085
        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
1086
      { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,
1087
        offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
1088
      { SEC_ASN1_PRINTABLE_STRING,
1089
        offsetof(SEC_PKCS12PVKSupportingData, nickname) },
1090
      { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
1091
        offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
1092
      { 0 }
1093
    };
1094
1095
const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate[] =
1096
    {
1097
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) },
1098
      { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
1099
        offsetof(SEC_PKCS12PVKSupportingData, assocCerts),
1100
        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
1101
      { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,
1102
        offsetof(SEC_PKCS12PVKSupportingData, regenerable) },
1103
      { SEC_ASN1_BMP_STRING,
1104
        offsetof(SEC_PKCS12PVKSupportingData, uniNickName) },
1105
      { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
1106
        offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) },
1107
      { 0 }
1108
    };
1109
1110
const SEC_ASN1Template SEC_PKCS12BaggageItemTemplate[] =
1111
    {
1112
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12BaggageItem) },
1113
      { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, espvks),
1114
        SEC_PKCS12ESPVKItemTemplate },
1115
      { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
1116
        SEC_PKCS12SafeBagTemplate },
1117
      /*{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets),
1118
        SEC_PKCS12CodedSafeBagTemplate }, */
1119
      { 0 }
1120
    };
1121
1122
const SEC_ASN1Template SEC_PKCS12BaggageTemplate[] =
1123
    {
1124
      { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage, bags),
1125
        SEC_PKCS12BaggageItemTemplate },
1126
    };
1127
1128
const SEC_ASN1Template SEC_PKCS12BaggageTemplate_OLD[] =
1129
    {
1130
      { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage_OLD, espvks),
1131
        SEC_PKCS12ESPVKItemTemplate_OLD },
1132
    };
1133
1134
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser =
1135
    sec_pkcs12_choose_bag_type;
1136
1137
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser_old =
1138
    sec_pkcs12_choose_bag_type_old;
1139
1140
const SEC_ASN1Template SEC_PKCS12SafeBagTemplate_OLD[] =
1141
    {
1142
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
1143
      { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
1144
      { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
1145
            SEC_ASN1_CONTEXT_SPECIFIC | 0,
1146
        offsetof(SEC_PKCS12SafeBag, safeContent),
1147
        &sec_pkcs12_bag_chooser_old },
1148
      { 0 }
1149
    };
1150
1151
const SEC_ASN1Template SEC_PKCS12SafeBagTemplate[] =
1152
    {
1153
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
1154
      { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
1155
      { SEC_ASN1_DYNAMIC | SEC_ASN1_POINTER,
1156
        offsetof(SEC_PKCS12SafeBag, safeContent),
1157
        &sec_pkcs12_bag_chooser },
1158
      { SEC_ASN1_OPTIONAL | SEC_ASN1_BMP_STRING,
1159
        offsetof(SEC_PKCS12SafeBag, uniSafeBagName) },
1160
      { 0 }
1161
    };
1162
1163
const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate_OLD[] =
1164
    {
1165
      { SEC_ASN1_SET_OF,
1166
        offsetof(SEC_PKCS12SafeContents, contents),
1167
        SEC_PKCS12SafeBagTemplate_OLD }
1168
    };
1169
1170
const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate[] =
1171
    {
1172
      { SEC_ASN1_SET_OF,
1173
        offsetof(SEC_PKCS12SafeContents, contents),
1174
        SEC_PKCS12SafeBagTemplate } /* here */
1175
    };
1176
1177
const SEC_ASN1Template SEC_PKCS12PrivateKeyTemplate[] =
1178
    {
1179
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKey) },
1180
      { SEC_ASN1_INLINE, offsetof(SEC_PKCS12PrivateKey, pvkData),
1181
        SEC_PKCS12PVKSupportingDataTemplate },
1182
      { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1183
        offsetof(SEC_PKCS12PrivateKey, pkcs8data),
1184
        SEC_ASN1_SUB(SECKEY_PrivateKeyInfoTemplate) },
1185
      { 0 }
1186
    };
1187
1188
const SEC_ASN1Template SEC_PKCS12PrivateKeyBagTemplate[] =
1189
    {
1190
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKeyBag) },
1191
      { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12PrivateKeyBag, privateKeys),
1192
        SEC_PKCS12PrivateKeyTemplate },
1193
      { 0 }
1194
    };
1195
1196
const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate_OLD[] =
1197
    {
1198
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
1199
      { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
1200
        sec_PKCS7ContentInfoTemplate },
1201
      { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
1202
        offsetof(SEC_PKCS12X509CertCRL, thumbprint),
1203
        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
1204
      { 0 }
1205
    };
1206
1207
const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate[] =
1208
    {
1209
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
1210
      { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL),
1211
        sec_PKCS7ContentInfoTemplate },
1212
      { 0 }
1213
    };
1214
1215
const SEC_ASN1Template SEC_PKCS12SDSICertTemplate[] =
1216
    {
1217
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) },
1218
      { SEC_ASN1_IA5_STRING, offsetof(SEC_PKCS12SDSICert, value) },
1219
      { 0 }
1220
    };
1221
1222
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser_old =
1223
    sec_pkcs12_choose_cert_crl_type_old;
1224
1225
static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser =
1226
    sec_pkcs12_choose_cert_crl_type;
1227
1228
const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate_OLD[] =
1229
    {
1230
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
1231
      { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
1232
      { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT |
1233
            SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | 0,
1234
        offsetof(SEC_PKCS12CertAndCRL, value),
1235
        &sec_pkcs12_cert_crl_chooser_old },
1236
      { 0 }
1237
    };
1238
1239
const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate[] =
1240
    {
1241
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) },
1242
      { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) },
1243
      { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
1244
            SEC_ASN1_CONTEXT_SPECIFIC | 0,
1245
        offsetof(SEC_PKCS12CertAndCRL, value),
1246
        &sec_pkcs12_cert_crl_chooser },
1247
      { 0 }
1248
    };
1249
1250
const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate[] =
1251
    {
1252
      { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
1253
        SEC_PKCS12CertAndCRLTemplate },
1254
    };
1255
1256
const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate_OLD[] =
1257
    {
1258
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRLBag) },
1259
      { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs),
1260
        SEC_PKCS12CertAndCRLTemplate_OLD },
1261
      { 0 }
1262
    };
1263
1264
const SEC_ASN1Template SEC_PKCS12SecretAdditionalTemplate[] =
1265
    {
1266
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SecretAdditional) },
1267
      { SEC_ASN1_OBJECT_ID,
1268
        offsetof(SEC_PKCS12SecretAdditional, secretAdditionalType) },
1269
      { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT,
1270
        offsetof(SEC_PKCS12SecretAdditional, secretAdditionalContent) },
1271
      { 0 }
1272
    };
1273
1274
const SEC_ASN1Template SEC_PKCS12SecretTemplate[] =
1275
    {
1276
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
1277
      { SEC_ASN1_BMP_STRING, offsetof(SEC_PKCS12Secret, uniSecretName) },
1278
      { SEC_ASN1_ANY, offsetof(SEC_PKCS12Secret, value) },
1279
      { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
1280
        offsetof(SEC_PKCS12Secret, secretAdditional),
1281
        SEC_PKCS12SecretAdditionalTemplate },
1282
      { 0 }
1283
    };
1284
1285
const SEC_ASN1Template SEC_PKCS12SecretItemTemplate[] =
1286
    {
1287
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) },
1288
      { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 0,
1289
        offsetof(SEC_PKCS12SecretItem, secret), SEC_PKCS12SecretTemplate },
1290
      { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 1,
1291
        offsetof(SEC_PKCS12SecretItem, subFolder), SEC_PKCS12SafeBagTemplate },
1292
      { 0 }
1293
    };
1294
1295
const SEC_ASN1Template SEC_PKCS12SecretBagTemplate[] =
1296
    {
1297
      { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12SecretBag, secrets),
1298
        SEC_PKCS12SecretItemTemplate },
1299
    };
1300
1301
const SEC_ASN1Template SEC_PKCS12MacDataTemplate[] =
1302
    {
1303
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
1304
      { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SEC_PKCS12MacData, safeMac),
1305
        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
1306
      { SEC_ASN1_BIT_STRING, offsetof(SEC_PKCS12MacData, macSalt) },
1307
      { 0 }
1308
    };
1309
1310
const SEC_ASN1Template SEC_PKCS12PFXItemTemplate[] =
1311
    {
1312
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
1313
      { SEC_ASN1_OPTIONAL |
1314
            SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
1315
        offsetof(SEC_PKCS12PFXItem, macData), SEC_PKCS12MacDataTemplate },
1316
      { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
1317
        offsetof(SEC_PKCS12PFXItem, authSafe),
1318
        sec_PKCS7ContentInfoTemplate },
1319
      { 0 }
1320
    };
1321
1322
const SEC_ASN1Template SEC_PKCS12PFXItemTemplate_OLD[] =
1323
    {
1324
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) },
1325
      { SEC_ASN1_OPTIONAL |
1326
            SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
1327
        offsetof(SEC_PKCS12PFXItem, old_safeMac),
1328
        SEC_ASN1_SUB(sgn_DigestInfoTemplate) },
1329
      { SEC_ASN1_OPTIONAL | SEC_ASN1_BIT_STRING,
1330
        offsetof(SEC_PKCS12PFXItem, old_macSalt) },
1331
      { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
1332
        offsetof(SEC_PKCS12PFXItem, authSafe),
1333
        sec_PKCS7ContentInfoTemplate },
1334
      { 0 }
1335
    };
1336
1337
const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate[] =
1338
    {
1339
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
1340
      { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
1341
        offsetof(SEC_PKCS12AuthenticatedSafe, version) },
1342
      { SEC_ASN1_OPTIONAL | SEC_ASN1_OBJECT_ID,
1343
        offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
1344
      { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL,
1345
        offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
1346
      { SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF,
1347
        offsetof(SEC_PKCS12AuthenticatedSafe, baggage.bags),
1348
        SEC_PKCS12BaggageItemTemplate },
1349
      { SEC_ASN1_POINTER,
1350
        offsetof(SEC_PKCS12AuthenticatedSafe, safe),
1351
        sec_PKCS7ContentInfoTemplate },
1352
      { 0 }
1353
    };
1354
1355
const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate_OLD[] =
1356
    {
1357
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) },
1358
      { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
1359
        offsetof(SEC_PKCS12AuthenticatedSafe, version) },
1360
      { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
1361
        offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) },
1362
      { SEC_ASN1_BIT_STRING,
1363
        offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) },
1364
      { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
1365
            SEC_ASN1_CONTEXT_SPECIFIC | 0,
1366
        offsetof(SEC_PKCS12AuthenticatedSafe, old_baggage),
1367
        SEC_PKCS12BaggageTemplate_OLD },
1368
      { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
1369
        offsetof(SEC_PKCS12AuthenticatedSafe, old_safe),
1370
        sec_PKCS7ContentInfoTemplate },
1371
      { 0 }
1372
    };
1373
1374
const SEC_ASN1Template SEC_PointerToPKCS12KeyBagTemplate[] =
1375
    {
1376
      { SEC_ASN1_POINTER, 0, SEC_PKCS12PrivateKeyBagTemplate }
1377
    };
1378
1379
const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD[] =
1380
    {
1381
      { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate_OLD }
1382
    };
1383
1384
const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate[] =
1385
    {
1386
      { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate }
1387
    };
1388
1389
const SEC_ASN1Template SEC_PointerToPKCS12SecretBagTemplate[] =
1390
    {
1391
      { SEC_ASN1_POINTER, 0, SEC_PKCS12SecretBagTemplate }
1392
    };
1393
1394
const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate_OLD[] =
1395
    {
1396
      { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate_OLD }
1397
    };
1398
1399
const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate[] =
1400
    {
1401
      { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate }
1402
    };
1403
1404
const SEC_ASN1Template SEC_PointerToPKCS12SDSICertTemplate[] =
1405
    {
1406
      { SEC_ASN1_POINTER, 0, SEC_PKCS12SDSICertTemplate }
1407
    };