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