p12exp.c (43563B)
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 #include "secitem.h" 7 #include "secoid.h" 8 #include "seccomon.h" 9 #include "secport.h" 10 #include "cert.h" 11 #include "pkcs12.h" 12 #include "p12local.h" 13 #include "secpkcs7.h" 14 #include "secasn1.h" 15 #include "secerr.h" 16 #include "p12plcy.h" 17 18 /* release the memory taken up by the list of nicknames */ 19 static void 20 sec_pkcs12_destroy_nickname_list(SECItem **nicknames) 21 { 22 int i = 0; 23 24 if (nicknames == NULL) { 25 return; 26 } 27 28 while (nicknames[i] != NULL) { 29 SECITEM_FreeItem(nicknames[i], PR_FALSE); 30 i++; 31 } 32 33 PORT_Free(nicknames); 34 } 35 36 /* release the memory taken up by the list of certificates */ 37 static void 38 sec_pkcs12_destroy_certificate_list(CERTCertificate **ref_certs) 39 { 40 int i = 0; 41 42 if (ref_certs == NULL) { 43 return; 44 } 45 46 while (ref_certs[i] != NULL) { 47 CERT_DestroyCertificate(ref_certs[i]); 48 i++; 49 } 50 } 51 52 static void 53 sec_pkcs12_destroy_cinfos_for_cert_bags(SEC_PKCS12CertAndCRLBag *certBag) 54 { 55 int j = 0; 56 j = 0; 57 while (certBag->certAndCRLs[j] != NULL) { 58 SECOidTag certType = SECOID_FindOIDTag(&certBag->certAndCRLs[j]->BagID); 59 if (certType == SEC_OID_PKCS12_X509_CERT_CRL_BAG) { 60 SEC_PKCS12X509CertCRL *x509; 61 x509 = certBag->certAndCRLs[j]->value.x509; 62 SEC_PKCS7DestroyContentInfo(&x509->certOrCRL); 63 } 64 j++; 65 } 66 } 67 68 /* destroy all content infos since they were not allocated in common 69 * pool 70 */ 71 static void 72 sec_pkcs12_destroy_cert_content_infos(SEC_PKCS12SafeContents *safe, 73 SEC_PKCS12Baggage *baggage) 74 { 75 int i, j; 76 77 if ((safe != NULL) && (safe->contents != NULL)) { 78 i = 0; 79 while (safe->contents[i] != NULL) { 80 SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType); 81 if (bagType == SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID) { 82 SEC_PKCS12CertAndCRLBag *certBag; 83 certBag = safe->contents[i]->safeContent.certAndCRLBag; 84 sec_pkcs12_destroy_cinfos_for_cert_bags(certBag); 85 } 86 i++; 87 } 88 } 89 90 if ((baggage != NULL) && (baggage->bags != NULL)) { 91 i = 0; 92 while (baggage->bags[i] != NULL) { 93 if (baggage->bags[i]->unencSecrets != NULL) { 94 j = 0; 95 while (baggage->bags[i]->unencSecrets[j] != NULL) { 96 SECOidTag bagType; 97 bagType = SECOID_FindOIDTag(&baggage->bags[i]->unencSecrets[j]->safeBagType); 98 if (bagType == SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID) { 99 SEC_PKCS12CertAndCRLBag *certBag; 100 certBag = baggage->bags[i]->unencSecrets[j]->safeContent.certAndCRLBag; 101 sec_pkcs12_destroy_cinfos_for_cert_bags(certBag); 102 } 103 j++; 104 } 105 } 106 i++; 107 } 108 } 109 } 110 111 /* convert the nickname list from a NULL termincated Char list 112 * to a NULL terminated SECItem list 113 */ 114 static SECItem ** 115 sec_pkcs12_convert_nickname_list(char **nicknames) 116 { 117 SECItem **nicks; 118 int i, j; 119 PRBool error = PR_FALSE; 120 121 if (nicknames == NULL) { 122 return NULL; 123 } 124 125 i = j = 0; 126 while (nicknames[i] != NULL) { 127 i++; 128 } 129 130 /* allocate the space and copy the data */ 131 nicks = (SECItem **)PORT_ZAlloc(sizeof(SECItem *) * (i + 1)); 132 if (nicks != NULL) { 133 for (j = 0; ((j < i) && (error == PR_FALSE)); j++) { 134 nicks[j] = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 135 if (nicks[j] != NULL) { 136 nicks[j]->data = 137 (unsigned char *)PORT_ZAlloc(PORT_Strlen(nicknames[j]) + 1); 138 if (nicks[j]->data != NULL) { 139 nicks[j]->len = PORT_Strlen(nicknames[j]); 140 PORT_Memcpy(nicks[j]->data, nicknames[j], nicks[j]->len); 141 nicks[j]->data[nicks[j]->len] = 0; 142 } else { 143 error = PR_TRUE; 144 } 145 } else { 146 error = PR_TRUE; 147 } 148 } 149 } 150 151 if (error == PR_TRUE) { 152 for (i = 0; i < j; i++) { 153 SECITEM_FreeItem(nicks[i], PR_TRUE); 154 } 155 PORT_Free(nicks); 156 nicks = NULL; 157 } 158 159 return nicks; 160 } 161 162 /* package the certificate add_cert into PKCS12 structures, 163 * retrieve the certificate chain for the cert and return 164 * the packaged contents. 165 * poolp -- common memory pool; 166 * add_cert -- certificate to package up 167 * nickname for the certificate 168 * a return of NULL indicates an error 169 */ 170 static SEC_PKCS12CertAndCRL * 171 sec_pkcs12_get_cert(PLArenaPool *poolp, 172 CERTCertificate *add_cert, 173 SECItem *nickname) 174 { 175 SEC_PKCS12CertAndCRL *cert; 176 SEC_PKCS7ContentInfo *cinfo; 177 SGNDigestInfo *t_di; 178 void *mark; 179 SECStatus rv; 180 181 if ((poolp == NULL) || (add_cert == NULL) || (nickname == NULL)) { 182 return NULL; 183 } 184 mark = PORT_ArenaMark(poolp); 185 186 cert = sec_pkcs12_new_cert_crl(poolp, SEC_OID_PKCS12_X509_CERT_CRL_BAG); 187 if (cert != NULL) { 188 189 /* copy the nickname */ 190 rv = SECITEM_CopyItem(poolp, &cert->nickname, nickname); 191 if (rv != SECSuccess) { 192 PORT_SetError(SEC_ERROR_NO_MEMORY); 193 cert = NULL; 194 } else { 195 196 /* package the certificate and cert chain into a NULL signer 197 * PKCS 7 SignedData content Info and prepare it for encoding 198 * since we cannot use DER_ANY_TEMPLATE 199 */ 200 cinfo = SEC_PKCS7CreateCertsOnly(add_cert, PR_TRUE, NULL); 201 rv = SEC_PKCS7PrepareForEncode(cinfo, NULL, NULL, NULL); 202 203 /* thumbprint the certificate */ 204 if ((cinfo != NULL) && (rv == SECSuccess)) { 205 PORT_Memcpy(&cert->value.x509->certOrCRL, cinfo, sizeof(*cinfo)); 206 t_di = sec_pkcs12_compute_thumbprint(&add_cert->derCert); 207 if (t_di != NULL) { 208 /* test */ 209 rv = SGN_CopyDigestInfo(poolp, &cert->value.x509->thumbprint, 210 t_di); 211 if (rv != SECSuccess) { 212 cert = NULL; 213 PORT_SetError(SEC_ERROR_NO_MEMORY); 214 } 215 SGN_DestroyDigestInfo(t_di); 216 } else 217 cert = NULL; 218 } 219 } 220 } 221 222 if (cert == NULL) { 223 PORT_ArenaRelease(poolp, mark); 224 } else { 225 PORT_ArenaUnmark(poolp, mark); 226 } 227 228 return cert; 229 } 230 231 /* package the private key associated with the certificate and 232 * return the appropriate PKCS 12 structure 233 * poolp common memory pool 234 * nickname key nickname 235 * cert -- cert to look up 236 * wincx -- window handle 237 * an error is indicated by a return of NULL 238 */ 239 static SEC_PKCS12PrivateKey * 240 sec_pkcs12_get_private_key(PLArenaPool *poolp, 241 SECItem *nickname, 242 CERTCertificate *cert, 243 void *wincx) 244 { 245 SECKEYPrivateKeyInfo *pki; 246 SEC_PKCS12PrivateKey *pk; 247 SECStatus rv; 248 void *mark; 249 250 if ((poolp == NULL) || (nickname == NULL)) { 251 return NULL; 252 } 253 254 mark = PORT_ArenaMark(poolp); 255 256 /* retrieve key from the data base */ 257 pki = PK11_ExportPrivateKeyInfo(nickname, cert, wincx); 258 if (pki == NULL) { 259 PORT_ArenaRelease(poolp, mark); 260 PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); 261 return NULL; 262 } 263 264 pk = (SEC_PKCS12PrivateKey *)PORT_ArenaZAlloc(poolp, 265 sizeof(SEC_PKCS12PrivateKey)); 266 if (pk != NULL) { 267 rv = sec_pkcs12_init_pvk_data(poolp, &pk->pvkData); 268 269 if (rv == SECSuccess) { 270 /* copy the key into poolp memory space */ 271 rv = SECKEY_CopyPrivateKeyInfo(poolp, &pk->pkcs8data, pki); 272 if (rv == SECSuccess) { 273 rv = SECITEM_CopyItem(poolp, &pk->pvkData.nickname, nickname); 274 } 275 } 276 277 if (rv != SECSuccess) { 278 PORT_SetError(SEC_ERROR_NO_MEMORY); 279 pk = NULL; 280 } 281 } else { 282 PORT_SetError(SEC_ERROR_NO_MEMORY); 283 } 284 285 /* destroy private key, zeroing out data */ 286 SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE); 287 if (pk == NULL) { 288 PORT_ArenaRelease(poolp, mark); 289 } else { 290 PORT_ArenaUnmark(poolp, mark); 291 } 292 293 return pk; 294 } 295 296 /* get a shrouded key item associated with a certificate 297 * return the appropriate PKCS 12 structure 298 * poolp common memory pool 299 * nickname key nickname 300 * cert -- cert to look up 301 * wincx -- window handle 302 * an error is indicated by a return of NULL 303 */ 304 static SEC_PKCS12ESPVKItem * 305 sec_pkcs12_get_shrouded_key(PLArenaPool *poolp, 306 SECItem *nickname, 307 CERTCertificate *cert, 308 SECOidTag algorithm, 309 SECItem *pwitem, 310 PKCS12UnicodeConvertFunction unicodeFn, 311 void *wincx) 312 { 313 SECKEYEncryptedPrivateKeyInfo *epki; 314 SEC_PKCS12ESPVKItem *pk; 315 void *mark; 316 SECStatus rv; 317 PK11SlotInfo *slot = NULL; 318 PRBool swapUnicodeBytes = PR_FALSE; 319 320 #ifdef IS_LITTLE_ENDIAN 321 swapUnicodeBytes = PR_TRUE; 322 #endif 323 324 if ((poolp == NULL) || (nickname == NULL)) 325 return NULL; 326 327 mark = PORT_ArenaMark(poolp); 328 329 /* use internal key slot */ 330 slot = PK11_GetInternalKeySlot(); 331 332 /* retrieve encrypted prviate key */ 333 epki = PK11_ExportEncryptedPrivateKeyInfo(slot, algorithm, pwitem, 334 nickname, cert, 1, 0, NULL); 335 PK11_FreeSlot(slot); 336 if (epki == NULL) { 337 PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); 338 PORT_ArenaRelease(poolp, mark); 339 return NULL; 340 } 341 342 /* create a private key and store the data into the poolp memory space */ 343 pk = sec_pkcs12_create_espvk(poolp, SEC_OID_PKCS12_PKCS8_KEY_SHROUDING); 344 if (pk != NULL) { 345 rv = sec_pkcs12_init_pvk_data(poolp, &pk->espvkData); 346 rv = SECITEM_CopyItem(poolp, &pk->espvkData.nickname, nickname); 347 pk->espvkCipherText.pkcs8KeyShroud = 348 (SECKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp, 349 sizeof(SECKEYEncryptedPrivateKeyInfo)); 350 if ((pk->espvkCipherText.pkcs8KeyShroud != NULL) && (rv == SECSuccess)) { 351 rv = SECKEY_CopyEncryptedPrivateKeyInfo(poolp, 352 pk->espvkCipherText.pkcs8KeyShroud, epki); 353 if (rv == SECSuccess) { 354 rv = (*unicodeFn)(poolp, &pk->espvkData.uniNickName, nickname, 355 PR_TRUE, swapUnicodeBytes); 356 } 357 } 358 359 if (rv != SECSuccess) { 360 PORT_SetError(SEC_ERROR_NO_MEMORY); 361 pk = NULL; 362 } 363 } 364 365 SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE); 366 if (pk == NULL) { 367 PORT_ArenaRelease(poolp, mark); 368 } else { 369 PORT_ArenaUnmark(poolp, mark); 370 } 371 372 return pk; 373 } 374 375 /* add a thumbprint to a private key associated certs list 376 * pvk is the area where the list is stored 377 * thumb is the thumbprint to copy 378 * a return of SECFailure indicates an error 379 */ 380 static SECStatus 381 sec_pkcs12_add_thumbprint(SEC_PKCS12PVKSupportingData *pvk, 382 SGNDigestInfo *thumb) 383 { 384 SGNDigestInfo **thumb_list = NULL; 385 int nthumbs, size; 386 void *mark, *dummy; 387 SECStatus rv = SECFailure; 388 389 if ((pvk == NULL) || (thumb == NULL)) { 390 return SECFailure; 391 } 392 393 mark = PORT_ArenaMark(pvk->poolp); 394 395 thumb_list = pvk->assocCerts; 396 nthumbs = pvk->nThumbs; 397 398 /* allocate list space needed -- either growing or allocating 399 * list must be NULL terminated 400 */ 401 size = sizeof(SGNDigestInfo *); 402 dummy = PORT_ArenaGrow(pvk->poolp, thumb_list, (size * (nthumbs + 1)), 403 (size * (nthumbs + 2))); 404 thumb_list = dummy; 405 if (dummy != NULL) { 406 thumb_list[nthumbs] = (SGNDigestInfo *)PORT_ArenaZAlloc(pvk->poolp, 407 sizeof(SGNDigestInfo)); 408 if (thumb_list[nthumbs] != NULL) { 409 SGN_CopyDigestInfo(pvk->poolp, thumb_list[nthumbs], thumb); 410 nthumbs += 1; 411 thumb_list[nthumbs] = 0; 412 } else { 413 dummy = NULL; 414 } 415 } 416 417 if (dummy == NULL) { 418 PORT_ArenaRelease(pvk->poolp, mark); 419 return SECFailure; 420 } 421 422 pvk->assocCerts = thumb_list; 423 pvk->nThumbs = nthumbs; 424 425 PORT_ArenaUnmark(pvk->poolp, mark); 426 return SECSuccess; 427 } 428 429 /* search the list of shrouded keys in the baggage for the desired 430 * name. return a pointer to the item. a return of NULL indicates 431 * that no match was present or that an error occurred. 432 */ 433 static SEC_PKCS12ESPVKItem * 434 sec_pkcs12_get_espvk_by_name(SEC_PKCS12Baggage *luggage, 435 SECItem *name) 436 { 437 PRBool found = PR_FALSE; 438 SEC_PKCS12ESPVKItem *espvk = NULL; 439 int i, j; 440 SECComparison rv = SECEqual; 441 SECItem *t_name; 442 SEC_PKCS12BaggageItem *bag; 443 444 if ((luggage == NULL) || (name == NULL)) { 445 return NULL; 446 } 447 448 i = 0; 449 while ((found == PR_FALSE) && (i < luggage->luggage_size)) { 450 j = 0; 451 bag = luggage->bags[i]; 452 while ((found == PR_FALSE) && (j < bag->nEspvks)) { 453 espvk = bag->espvks[j]; 454 if (espvk->poolp == NULL) { 455 espvk->poolp = luggage->poolp; 456 } 457 t_name = SECITEM_DupItem(&espvk->espvkData.nickname); 458 if (t_name != NULL) { 459 rv = SECITEM_CompareItem(name, t_name); 460 if (rv == SECEqual) { 461 found = PR_TRUE; 462 } 463 SECITEM_FreeItem(t_name, PR_TRUE); 464 } else { 465 PORT_SetError(SEC_ERROR_NO_MEMORY); 466 return NULL; 467 } 468 j++; 469 } 470 i++; 471 } 472 473 if (found != PR_TRUE) { 474 PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME); 475 return NULL; 476 } 477 478 return espvk; 479 } 480 481 /* locates a certificate and copies the thumbprint to the 482 * appropriate private key 483 */ 484 static SECStatus 485 sec_pkcs12_propagate_thumbprints(SECItem **nicknames, 486 CERTCertificate **ref_certs, 487 SEC_PKCS12SafeContents *safe, 488 SEC_PKCS12Baggage *baggage) 489 { 490 SEC_PKCS12CertAndCRL *cert; 491 SEC_PKCS12PrivateKey *key; 492 SEC_PKCS12ESPVKItem *espvk; 493 int i; 494 PRBool error = PR_FALSE; 495 SECStatus rv = SECFailure; 496 497 if ((nicknames == NULL) || (safe == NULL)) { 498 return SECFailure; 499 } 500 501 i = 0; 502 while ((nicknames[i] != NULL) && (error == PR_FALSE)) { 503 /* process all certs */ 504 cert = (SEC_PKCS12CertAndCRL *)sec_pkcs12_find_object(safe, baggage, 505 SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID, 506 nicknames[i], NULL); 507 if (cert != NULL) { 508 /* locate key and copy thumbprint */ 509 key = (SEC_PKCS12PrivateKey *)sec_pkcs12_find_object(safe, baggage, 510 SEC_OID_PKCS12_KEY_BAG_ID, 511 nicknames[i], NULL); 512 if (key != NULL) { 513 key->pvkData.poolp = key->poolp; 514 rv = sec_pkcs12_add_thumbprint(&key->pvkData, 515 &cert->value.x509->thumbprint); 516 if (rv == SECFailure) 517 error = PR_TRUE; /* XXX Set error? */ 518 } 519 520 /* look in the baggage as well...*/ 521 if ((baggage != NULL) && (error == PR_FALSE)) { 522 espvk = sec_pkcs12_get_espvk_by_name(baggage, nicknames[i]); 523 if (espvk != NULL) { 524 espvk->espvkData.poolp = espvk->poolp; 525 rv = sec_pkcs12_add_thumbprint(&espvk->espvkData, 526 &cert->value.x509->thumbprint); 527 if (rv == SECFailure) 528 error = PR_TRUE; /* XXX Set error? */ 529 } 530 } 531 } 532 i++; 533 } 534 535 if (error == PR_TRUE) { 536 return SECFailure; 537 } 538 539 return SECSuccess; 540 } 541 542 /* append a safe bag to the end of the safe contents list */ 543 SECStatus 544 sec_pkcs12_append_safe_bag(SEC_PKCS12SafeContents *safe, 545 SEC_PKCS12SafeBag *bag) 546 { 547 int size; 548 void *mark = NULL, *dummy = NULL; 549 550 if ((bag == NULL) || (safe == NULL)) 551 return SECFailure; 552 553 mark = PORT_ArenaMark(safe->poolp); 554 555 size = (safe->safe_size * sizeof(SEC_PKCS12SafeBag *)); 556 557 if (safe->safe_size > 0) { 558 dummy = (SEC_PKCS12SafeBag **)PORT_ArenaGrow(safe->poolp, 559 safe->contents, 560 size, 561 (size + sizeof(SEC_PKCS12SafeBag *))); 562 safe->contents = dummy; 563 } else { 564 safe->contents = (SEC_PKCS12SafeBag **)PORT_ArenaZAlloc(safe->poolp, 565 (2 * sizeof(SEC_PKCS12SafeBag *))); 566 dummy = safe->contents; 567 } 568 569 if (dummy == NULL) { 570 PORT_SetError(SEC_ERROR_NO_MEMORY); 571 goto loser; 572 } 573 574 safe->contents[safe->safe_size] = bag; 575 safe->safe_size++; 576 safe->contents[safe->safe_size] = NULL; 577 578 PORT_ArenaUnmark(safe->poolp, mark); 579 return SECSuccess; 580 581 loser: 582 PORT_ArenaRelease(safe->poolp, mark); 583 return SECFailure; 584 } 585 586 /* append a certificate onto the end of a cert bag */ 587 static SECStatus 588 sec_pkcs12_append_cert_to_bag(PLArenaPool *arena, 589 SEC_PKCS12SafeBag *safebag, 590 CERTCertificate *cert, 591 SECItem *nickname) 592 { 593 int size; 594 void *dummy = NULL, *mark = NULL; 595 SEC_PKCS12CertAndCRL *p12cert; 596 SEC_PKCS12CertAndCRLBag *bag; 597 598 if ((arena == NULL) || (safebag == NULL) || 599 (cert == NULL) || (nickname == NULL)) { 600 return SECFailure; 601 } 602 603 bag = safebag->safeContent.certAndCRLBag; 604 if (bag == NULL) { 605 return SECFailure; 606 } 607 608 mark = PORT_ArenaMark(arena); 609 610 p12cert = sec_pkcs12_get_cert(arena, cert, nickname); 611 if (p12cert == NULL) { 612 PORT_ArenaRelease(bag->poolp, mark); 613 return SECFailure; 614 } 615 616 size = bag->bag_size * sizeof(SEC_PKCS12CertAndCRL *); 617 if (bag->bag_size > 0) { 618 dummy = (SEC_PKCS12CertAndCRL **)PORT_ArenaGrow(bag->poolp, 619 bag->certAndCRLs, 620 size, 621 size + sizeof(SEC_PKCS12CertAndCRL *)); 622 bag->certAndCRLs = dummy; 623 } else { 624 bag->certAndCRLs = (SEC_PKCS12CertAndCRL **)PORT_ArenaZAlloc(bag->poolp, 625 (2 * sizeof(SEC_PKCS12CertAndCRL *))); 626 dummy = bag->certAndCRLs; 627 } 628 629 if (dummy == NULL) { 630 PORT_SetError(SEC_ERROR_NO_MEMORY); 631 goto loser; 632 } 633 634 bag->certAndCRLs[bag->bag_size] = p12cert; 635 bag->bag_size++; 636 bag->certAndCRLs[bag->bag_size] = NULL; 637 638 PORT_ArenaUnmark(bag->poolp, mark); 639 return SECSuccess; 640 641 loser: 642 PORT_ArenaRelease(bag->poolp, mark); 643 return SECFailure; 644 } 645 646 /* append a key onto the end of a list of keys in a key bag */ 647 SECStatus 648 sec_pkcs12_append_key_to_bag(SEC_PKCS12SafeBag *safebag, 649 SEC_PKCS12PrivateKey *pk) 650 { 651 void *mark, *dummy; 652 SEC_PKCS12PrivateKeyBag *bag; 653 int size; 654 655 if ((safebag == NULL) || (pk == NULL)) 656 return SECFailure; 657 658 bag = safebag->safeContent.keyBag; 659 if (bag == NULL) { 660 return SECFailure; 661 } 662 663 mark = PORT_ArenaMark(bag->poolp); 664 665 size = (bag->bag_size * sizeof(SEC_PKCS12PrivateKey *)); 666 667 if (bag->bag_size > 0) { 668 dummy = (SEC_PKCS12PrivateKey **)PORT_ArenaGrow(bag->poolp, 669 bag->privateKeys, 670 size, 671 size + sizeof(SEC_PKCS12PrivateKey *)); 672 bag->privateKeys = dummy; 673 } else { 674 bag->privateKeys = (SEC_PKCS12PrivateKey **)PORT_ArenaZAlloc(bag->poolp, 675 (2 * sizeof(SEC_PKCS12PrivateKey *))); 676 dummy = bag->privateKeys; 677 } 678 679 if (dummy == NULL) { 680 PORT_SetError(SEC_ERROR_NO_MEMORY); 681 goto loser; 682 } 683 684 bag->privateKeys[bag->bag_size] = pk; 685 bag->bag_size++; 686 bag->privateKeys[bag->bag_size] = NULL; 687 688 PORT_ArenaUnmark(bag->poolp, mark); 689 return SECSuccess; 690 691 loser: 692 /* XXX Free memory? */ 693 PORT_ArenaRelease(bag->poolp, mark); 694 return SECFailure; 695 } 696 697 /* append a safe bag to the baggage area */ 698 static SECStatus 699 sec_pkcs12_append_unshrouded_bag(SEC_PKCS12BaggageItem *bag, 700 SEC_PKCS12SafeBag *u_bag) 701 { 702 int size; 703 void *mark = NULL, *dummy = NULL; 704 705 if ((bag == NULL) || (u_bag == NULL)) 706 return SECFailure; 707 708 mark = PORT_ArenaMark(bag->poolp); 709 710 /* dump things into the first bag */ 711 size = (bag->nSecrets + 1) * sizeof(SEC_PKCS12SafeBag *); 712 dummy = PORT_ArenaGrow(bag->poolp, 713 bag->unencSecrets, size, 714 size + sizeof(SEC_PKCS12SafeBag *)); 715 bag->unencSecrets = dummy; 716 if (dummy == NULL) { 717 PORT_SetError(SEC_ERROR_NO_MEMORY); 718 goto loser; 719 } 720 721 bag->unencSecrets[bag->nSecrets] = u_bag; 722 bag->nSecrets++; 723 bag->unencSecrets[bag->nSecrets] = NULL; 724 725 PORT_ArenaUnmark(bag->poolp, mark); 726 return SECSuccess; 727 728 loser: 729 PORT_ArenaRelease(bag->poolp, mark); 730 return SECFailure; 731 } 732 733 /* gather up all certificates and keys and package them up 734 * in the safe, baggage, or both. 735 * nicknames is the list of nicknames and corresponding certs in ref_certs 736 * ref_certs a null terminated list of certificates 737 * rSafe, rBaggage -- return areas for safe and baggage 738 * shroud_keys -- store keys externally 739 * pwitem -- password for computing integrity mac and encrypting contents 740 * wincx -- window handle 741 * 742 * if a failure occurs, an error is set and SECFailure returned. 743 */ 744 static SECStatus 745 sec_pkcs12_package_certs_and_keys(SECItem **nicknames, 746 CERTCertificate **ref_certs, 747 PRBool unencryptedCerts, 748 SEC_PKCS12SafeContents **rSafe, 749 SEC_PKCS12Baggage **rBaggage, 750 PRBool shroud_keys, 751 SECOidTag shroud_alg, 752 SECItem *pwitem, 753 PKCS12UnicodeConvertFunction unicodeFn, 754 void *wincx) 755 { 756 PLArenaPool *permArena; 757 SEC_PKCS12SafeContents *safe = NULL; 758 SEC_PKCS12Baggage *baggage = NULL; 759 760 SECStatus rv = SECFailure; 761 PRBool problem = PR_FALSE; 762 763 SEC_PKCS12ESPVKItem *espvk = NULL; 764 SEC_PKCS12PrivateKey *pk = NULL; 765 CERTCertificate *add_cert = NULL; 766 SEC_PKCS12SafeBag *certbag = NULL, *keybag = NULL; 767 SEC_PKCS12BaggageItem *external_bag = NULL; 768 int ncerts = 0, nkeys = 0; 769 int i; 770 771 if ((nicknames == NULL) || (rSafe == NULL) || (rBaggage == NULL)) { 772 return SECFailure; 773 } 774 775 *rBaggage = baggage; 776 *rSafe = safe; 777 778 permArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 779 if (permArena == NULL) { 780 PORT_SetError(SEC_ERROR_NO_MEMORY); 781 return SECFailure; 782 } 783 784 /* allocate structures */ 785 safe = sec_pkcs12_create_safe_contents(permArena); 786 if (safe == NULL) { 787 PORT_SetError(SEC_ERROR_NO_MEMORY); 788 rv = SECFailure; 789 goto loser; 790 } 791 792 certbag = sec_pkcs12_create_safe_bag(permArena, 793 SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID); 794 if (certbag == NULL) { 795 rv = SECFailure; 796 goto loser; 797 } 798 799 if (shroud_keys != PR_TRUE) { 800 keybag = sec_pkcs12_create_safe_bag(permArena, 801 SEC_OID_PKCS12_KEY_BAG_ID); 802 if (keybag == NULL) { 803 rv = SECFailure; 804 goto loser; 805 } 806 } 807 808 if ((shroud_keys == PR_TRUE) || (unencryptedCerts == PR_TRUE)) { 809 baggage = sec_pkcs12_create_baggage(permArena); 810 if (baggage == NULL) { 811 rv = SECFailure; 812 goto loser; 813 } 814 external_bag = sec_pkcs12_create_external_bag(baggage); 815 } 816 817 /* package keys and certs */ 818 i = 0; 819 while ((nicknames[i] != NULL) && (problem == PR_FALSE)) { 820 if (ref_certs[i] != NULL) { 821 /* append cert to bag o certs */ 822 rv = sec_pkcs12_append_cert_to_bag(permArena, certbag, 823 ref_certs[i], 824 nicknames[i]); 825 if (rv == SECFailure) { 826 problem = PR_FALSE; 827 } else { 828 ncerts++; 829 } 830 831 if (rv == SECSuccess) { 832 /* package up them keys */ 833 if (shroud_keys == PR_TRUE) { 834 espvk = sec_pkcs12_get_shrouded_key(permArena, 835 nicknames[i], 836 ref_certs[i], 837 shroud_alg, 838 pwitem, unicodeFn, 839 wincx); 840 if (espvk != NULL) { 841 rv = sec_pkcs12_append_shrouded_key(external_bag, espvk); 842 SECITEM_CopyItem(permArena, &espvk->derCert, 843 &ref_certs[i]->derCert); 844 } else { 845 rv = SECFailure; 846 } 847 } else { 848 pk = sec_pkcs12_get_private_key(permArena, nicknames[i], 849 ref_certs[i], wincx); 850 if (pk != NULL) { 851 rv = sec_pkcs12_append_key_to_bag(keybag, pk); 852 SECITEM_CopyItem(permArena, &espvk->derCert, 853 &ref_certs[i]->derCert); 854 } else { 855 rv = SECFailure; 856 } 857 } 858 859 if (rv == SECFailure) { 860 problem = PR_TRUE; 861 } else { 862 nkeys++; 863 } 864 } 865 } else { 866 /* handle only keys here ? */ 867 problem = PR_TRUE; 868 } 869 i++; 870 } 871 872 /* let success fall through */ 873 loser: 874 if (problem == PR_FALSE) { 875 /* if we have certs, we want to append the cert bag to the 876 * appropriate area 877 */ 878 if (ncerts > 0) { 879 if (unencryptedCerts != PR_TRUE) { 880 rv = sec_pkcs12_append_safe_bag(safe, certbag); 881 } else { 882 rv = sec_pkcs12_append_unshrouded_bag(external_bag, certbag); 883 } 884 } else { 885 rv = SECSuccess; 886 } 887 888 /* append key bag, if they are stored in safe contents */ 889 if ((rv == SECSuccess) && (shroud_keys == PR_FALSE) && (nkeys > 0)) { 890 rv = sec_pkcs12_append_safe_bag(safe, keybag); 891 } 892 } else { 893 rv = SECFailure; 894 } 895 896 /* if baggage not used, NULLify it */ 897 if ((shroud_keys == PR_TRUE) || (unencryptedCerts == PR_TRUE)) { 898 if (((unencryptedCerts == PR_TRUE) && (ncerts == 0)) && 899 ((shroud_keys == PR_TRUE) && (nkeys == 0))) 900 baggage = NULL; 901 } else { 902 baggage = NULL; 903 } 904 905 if ((problem == PR_TRUE) || (rv == SECFailure)) { 906 PORT_FreeArena(permArena, PR_TRUE); 907 rv = SECFailure; 908 baggage = NULL; 909 safe = NULL; 910 } 911 912 *rBaggage = baggage; 913 *rSafe = safe; 914 915 return rv; 916 } 917 918 /* DER encode the safe contents and return a SECItem. if an error 919 * occurs, NULL is returned. 920 */ 921 static SECItem * 922 sec_pkcs12_encode_safe_contents(SEC_PKCS12SafeContents *safe) 923 { 924 SECItem *dsafe = NULL, *tsafe; 925 void *dummy = NULL; 926 PLArenaPool *arena; 927 928 if (safe == NULL) { 929 return NULL; 930 } 931 932 /* rv = sec_pkcs12_prepare_for_der_code_safe(safe, PR_TRUE); 933 if(rv != SECSuccess) { 934 PORT_SetError(SEC_ERROR_NO_MEMORY); 935 return NULL; 936 }*/ 937 938 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 939 if (arena == NULL) { 940 PORT_SetError(SEC_ERROR_NO_MEMORY); 941 return NULL; 942 } 943 944 tsafe = (SECItem *)PORT_ArenaZAlloc(arena, sizeof(SECItem)); 945 if (tsafe != NULL) { 946 dummy = SEC_ASN1EncodeItem(arena, tsafe, safe, 947 SEC_PKCS12SafeContentsTemplate); 948 if (dummy != NULL) { 949 dsafe = SECITEM_DupItem(tsafe); 950 } else { 951 PORT_SetError(SEC_ERROR_NO_MEMORY); 952 } 953 } else { 954 PORT_SetError(SEC_ERROR_NO_MEMORY); 955 } 956 957 PORT_FreeArena(arena, PR_TRUE); 958 959 return dsafe; 960 } 961 962 /* prepare the authenicated safe for encoding and encode it. 963 * baggage is copied to the appropriate area, safe is encoded and 964 * encrypted. the version and transport mode are set on the asafe. 965 * the whole ball of wax is then der encoded and packaged up into 966 * data content info 967 * safe -- container of certs and keys, is encrypted. 968 * baggage -- container of certs and keys, keys assumed to be encrypted by 969 * another method, certs are in the clear 970 * algorithm -- algorithm by which to encrypt safe 971 * pwitem -- password for encryption 972 * wincx - window handle 973 * 974 * return of NULL is an error condition. 975 */ 976 static SEC_PKCS7ContentInfo * 977 sec_pkcs12_get_auth_safe(SEC_PKCS12SafeContents *safe, 978 SEC_PKCS12Baggage *baggage, 979 SECOidTag algorithm, 980 SECItem *pwitem, 981 PKCS12UnicodeConvertFunction unicodeFn, 982 void *wincx) 983 { 984 SECItem *src = NULL, *dest = NULL, *psalt = NULL; 985 PLArenaPool *poolp; 986 SEC_PKCS12AuthenticatedSafe *asafe; 987 SEC_PKCS7ContentInfo *safe_cinfo = NULL; 988 SEC_PKCS7ContentInfo *asafe_cinfo = NULL; 989 void *dummy; 990 SECStatus rv = SECSuccess; 991 PRBool swapUnicodeBytes = PR_FALSE; 992 993 #ifdef IS_LITTLE_ENDIAN 994 swapUnicodeBytes = PR_TRUE; 995 #endif 996 997 if (((safe != NULL) && (pwitem == NULL)) && (baggage == NULL)) 998 return NULL; 999 1000 poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1001 if (poolp == NULL) { 1002 PORT_SetError(SEC_ERROR_NO_MEMORY); 1003 return NULL; 1004 } 1005 1006 /* prepare authenticated safe for encode */ 1007 asafe = sec_pkcs12_new_asafe(poolp); 1008 if (asafe != NULL) { 1009 1010 /* set version */ 1011 dummy = SEC_ASN1EncodeInteger(asafe->poolp, &asafe->version, 1012 SEC_PKCS12_PFX_VERSION); 1013 if (dummy == NULL) { 1014 PORT_SetError(SEC_ERROR_NO_MEMORY); 1015 rv = SECFailure; 1016 goto loser; 1017 } 1018 1019 /* generate the privacy salt used to create virtual pwd */ 1020 psalt = sec_pkcs12_generate_salt(); 1021 if (psalt != NULL) { 1022 rv = SECITEM_CopyItem(asafe->poolp, &asafe->privacySalt, 1023 psalt); 1024 if (rv == SECSuccess) { 1025 asafe->privacySalt.len *= 8; 1026 } else { 1027 SECITEM_ZfreeItem(psalt, PR_TRUE); 1028 PORT_SetError(SEC_ERROR_NO_MEMORY); 1029 goto loser; 1030 } 1031 } 1032 1033 if ((psalt == NULL) || (rv == SECFailure)) { 1034 PORT_SetError(SEC_ERROR_NO_MEMORY); 1035 rv = SECFailure; 1036 goto loser; 1037 } 1038 1039 /* package up safe contents */ 1040 if (safe != NULL) { 1041 safe_cinfo = SEC_PKCS7CreateEncryptedData(algorithm, NULL, wincx); 1042 if ((safe_cinfo != NULL) && (safe->safe_size > 0)) { 1043 /* encode the safe and encrypt the contents of the 1044 * content info 1045 */ 1046 src = sec_pkcs12_encode_safe_contents(safe); 1047 1048 if (src != NULL) { 1049 rv = SEC_PKCS7SetContent(safe_cinfo, (char *)src->data, src->len); 1050 SECITEM_ZfreeItem(src, PR_TRUE); 1051 if (rv == SECSuccess) { 1052 SECItem *vpwd; 1053 vpwd = sec_pkcs12_create_virtual_password(pwitem, psalt, 1054 unicodeFn, swapUnicodeBytes); 1055 if (vpwd != NULL) { 1056 rv = SEC_PKCS7EncryptContents(NULL, safe_cinfo, 1057 vpwd, wincx); 1058 SECITEM_ZfreeItem(vpwd, PR_TRUE); 1059 } else { 1060 rv = SECFailure; 1061 PORT_SetError(SEC_ERROR_NO_MEMORY); 1062 } 1063 } else { 1064 PORT_SetError(SEC_ERROR_NO_MEMORY); 1065 } 1066 } else { 1067 rv = SECFailure; 1068 } 1069 } else if (safe->safe_size > 0) { 1070 PORT_SetError(SEC_ERROR_NO_MEMORY); 1071 goto loser; 1072 } else { 1073 /* case where there is NULL content in the safe contents */ 1074 rv = SEC_PKCS7SetContent(safe_cinfo, NULL, 0); 1075 if (rv != SECFailure) { 1076 PORT_SetError(SEC_ERROR_NO_MEMORY); 1077 } 1078 } 1079 1080 if (rv != SECSuccess) { 1081 SEC_PKCS7DestroyContentInfo(safe_cinfo); 1082 safe_cinfo = NULL; 1083 goto loser; 1084 } 1085 1086 asafe->safe = safe_cinfo; 1087 /* 1088 PORT_Memcpy(&asafe->safe, safe_cinfo, sizeof(*safe_cinfo)); 1089 */ 1090 } 1091 1092 /* copy the baggage to the authenticated safe baggage if present */ 1093 if (baggage != NULL) { 1094 PORT_Memcpy(&asafe->baggage, baggage, sizeof(*baggage)); 1095 } 1096 1097 /* encode authenticated safe and store it in a Data content info */ 1098 dest = (SECItem *)PORT_ArenaZAlloc(poolp, sizeof(SECItem)); 1099 if (dest != NULL) { 1100 dummy = SEC_ASN1EncodeItem(poolp, dest, asafe, 1101 SEC_PKCS12AuthenticatedSafeTemplate); 1102 if (dummy != NULL) { 1103 asafe_cinfo = SEC_PKCS7CreateData(); 1104 if (asafe_cinfo != NULL) { 1105 rv = SEC_PKCS7SetContent(asafe_cinfo, 1106 (char *)dest->data, 1107 dest->len); 1108 if (rv != SECSuccess) { 1109 PORT_SetError(SEC_ERROR_NO_MEMORY); 1110 SEC_PKCS7DestroyContentInfo(asafe_cinfo); 1111 asafe_cinfo = NULL; 1112 } 1113 } 1114 } else { 1115 PORT_SetError(SEC_ERROR_NO_MEMORY); 1116 rv = SECFailure; 1117 } 1118 } 1119 } 1120 1121 loser: 1122 PORT_FreeArena(poolp, PR_TRUE); 1123 if (safe_cinfo != NULL) { 1124 SEC_PKCS7DestroyContentInfo(safe_cinfo); 1125 } 1126 if (psalt != NULL) { 1127 SECITEM_ZfreeItem(psalt, PR_TRUE); 1128 } 1129 1130 if (rv == SECFailure) { 1131 return NULL; 1132 } 1133 1134 return asafe_cinfo; 1135 } 1136 1137 /* generates the PFX and computes the mac on the authenticated safe 1138 * NULL implies an error 1139 */ 1140 static SEC_PKCS12PFXItem * 1141 sec_pkcs12_get_pfx(SEC_PKCS7ContentInfo *cinfo, 1142 PRBool do_mac, 1143 SECItem *pwitem, PKCS12UnicodeConvertFunction unicodeFn) 1144 { 1145 SECItem *dest = NULL, *mac = NULL, *salt = NULL, *key = NULL; 1146 SEC_PKCS12PFXItem *pfx; 1147 SECStatus rv = SECFailure; 1148 SGNDigestInfo *di; 1149 SECItem *vpwd; 1150 PRBool swapUnicodeBytes = PR_FALSE; 1151 1152 #ifdef IS_LITTLE_ENDIAN 1153 swapUnicodeBytes = PR_TRUE; 1154 #endif 1155 1156 if ((cinfo == NULL) || ((do_mac == PR_TRUE) && (pwitem == NULL))) { 1157 return NULL; 1158 } 1159 1160 /* allocate new pfx structure */ 1161 pfx = sec_pkcs12_new_pfx(); 1162 if (pfx == NULL) { 1163 PORT_SetError(SEC_ERROR_NO_MEMORY); 1164 return NULL; 1165 } 1166 1167 PORT_Memcpy(&pfx->authSafe, cinfo, sizeof(*cinfo)); 1168 if (do_mac == PR_TRUE) { 1169 1170 /* salt for computing mac */ 1171 salt = sec_pkcs12_generate_salt(); 1172 if (salt != NULL) { 1173 rv = SECITEM_CopyItem(pfx->poolp, &pfx->macData.macSalt, salt); 1174 pfx->macData.macSalt.len *= 8; 1175 1176 vpwd = sec_pkcs12_create_virtual_password(pwitem, salt, 1177 unicodeFn, swapUnicodeBytes); 1178 if (vpwd == NULL) { 1179 rv = SECFailure; 1180 key = NULL; 1181 } else { 1182 key = sec_pkcs12_generate_key_from_password(SEC_OID_SHA1, 1183 salt, vpwd); 1184 SECITEM_ZfreeItem(vpwd, PR_TRUE); 1185 } 1186 1187 if ((key != NULL) && (rv == SECSuccess)) { 1188 dest = SEC_PKCS7GetContent(cinfo); 1189 if (dest != NULL) { 1190 1191 /* compute mac on data -- for password integrity mode */ 1192 mac = sec_pkcs12_generate_mac(key, dest, PR_FALSE); 1193 if (mac != NULL) { 1194 di = SGN_CreateDigestInfo(SEC_OID_SHA1, 1195 mac->data, mac->len); 1196 if (di != NULL) { 1197 rv = SGN_CopyDigestInfo(pfx->poolp, 1198 &pfx->macData.safeMac, di); 1199 SGN_DestroyDigestInfo(di); 1200 } else { 1201 PORT_SetError(SEC_ERROR_NO_MEMORY); 1202 } 1203 SECITEM_ZfreeItem(mac, PR_TRUE); 1204 } 1205 } else { 1206 rv = SECFailure; 1207 } 1208 } else { 1209 PORT_SetError(SEC_ERROR_NO_MEMORY); 1210 rv = SECFailure; 1211 } 1212 1213 if (key != NULL) { 1214 SECITEM_ZfreeItem(key, PR_TRUE); 1215 } 1216 SECITEM_ZfreeItem(salt, PR_TRUE); 1217 } 1218 } 1219 1220 if (rv == SECFailure) { 1221 SEC_PKCS12DestroyPFX(pfx); 1222 pfx = NULL; 1223 } 1224 1225 return pfx; 1226 } 1227 1228 /* der encode the pfx */ 1229 static SECItem * 1230 sec_pkcs12_encode_pfx(SEC_PKCS12PFXItem *pfx) 1231 { 1232 SECItem *dest; 1233 void *dummy; 1234 1235 if (pfx == NULL) { 1236 return NULL; 1237 } 1238 1239 dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1240 if (dest == NULL) { 1241 PORT_SetError(SEC_ERROR_NO_MEMORY); 1242 return NULL; 1243 } 1244 1245 dummy = SEC_ASN1EncodeItem(NULL, dest, pfx, SEC_PKCS12PFXItemTemplate); 1246 if (dummy == NULL) { 1247 PORT_SetError(SEC_ERROR_NO_MEMORY); 1248 SECITEM_ZfreeItem(dest, PR_TRUE); 1249 dest = NULL; 1250 } 1251 1252 return dest; 1253 } 1254 1255 SECItem * 1256 SEC_PKCS12GetPFX(char **nicknames, 1257 CERTCertificate **ref_certs, 1258 PRBool shroud_keys, 1259 SEC_PKCS5GetPBEPassword pbef, 1260 void *pbearg, 1261 PKCS12UnicodeConvertFunction unicodeFn, 1262 void *wincx) 1263 { 1264 SECItem **nicks = NULL; 1265 SEC_PKCS12PFXItem *pfx = NULL; 1266 SEC_PKCS12Baggage *baggage = NULL; 1267 SEC_PKCS12SafeContents *safe = NULL; 1268 SEC_PKCS7ContentInfo *cinfo = NULL; 1269 SECStatus rv = SECFailure; 1270 SECItem *dest = NULL, *pwitem = NULL; 1271 PRBool problem = PR_FALSE; 1272 PRBool unencryptedCerts; 1273 SECOidTag shroud_alg, safe_alg; 1274 1275 /* how should we encrypt certs ? */ 1276 unencryptedCerts = !SEC_PKCS12IsEncryptionAllowed(); 1277 if (!unencryptedCerts) { 1278 safe_alg = SEC_PKCS12GetPreferredEncryptionAlgorithm(); 1279 if (safe_alg == SEC_OID_UNKNOWN) { 1280 safe_alg = SEC_PKCS12GetStrongestAllowedAlgorithm(); 1281 } 1282 if (safe_alg == SEC_OID_UNKNOWN) { 1283 unencryptedCerts = PR_TRUE; 1284 /* for export where no encryption is allowed, we still need 1285 * to encrypt the NULL contents per the spec. encrypted info 1286 * is known plaintext, so it shouldn't be a problem. 1287 */ 1288 safe_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; 1289 } 1290 } else { 1291 /* for export where no encryption is allowed, we still need 1292 * to encrypt the NULL contents per the spec. encrypted info 1293 * is known plaintext, so it shouldn't be a problem. 1294 */ 1295 safe_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; 1296 } 1297 1298 /* keys are always stored with triple DES */ 1299 shroud_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC; 1300 1301 /* check for FIPS, if so, do not encrypt certs */ 1302 if (PK11_IsFIPS() && !unencryptedCerts) { 1303 unencryptedCerts = PR_TRUE; 1304 } 1305 1306 if ((nicknames == NULL) || (pbef == NULL) || (ref_certs == NULL)) { 1307 problem = PR_TRUE; 1308 goto loser; 1309 } 1310 1311 /* get password */ 1312 pwitem = (*pbef)(pbearg); 1313 if (pwitem == NULL) { 1314 problem = PR_TRUE; 1315 goto loser; 1316 } 1317 nicks = sec_pkcs12_convert_nickname_list(nicknames); 1318 1319 /* get safe and baggage */ 1320 rv = sec_pkcs12_package_certs_and_keys(nicks, ref_certs, unencryptedCerts, 1321 &safe, &baggage, shroud_keys, 1322 shroud_alg, pwitem, unicodeFn, wincx); 1323 if (rv == SECFailure) { 1324 problem = PR_TRUE; 1325 } 1326 1327 if ((safe != NULL) && (problem == PR_FALSE)) { 1328 /* copy thumbprints */ 1329 rv = sec_pkcs12_propagate_thumbprints(nicks, ref_certs, safe, baggage); 1330 1331 /* package everything up into AuthenticatedSafe */ 1332 cinfo = sec_pkcs12_get_auth_safe(safe, baggage, 1333 safe_alg, pwitem, unicodeFn, wincx); 1334 1335 sec_pkcs12_destroy_cert_content_infos(safe, baggage); 1336 1337 /* get the pfx and mac it */ 1338 if (cinfo != NULL) { 1339 pfx = sec_pkcs12_get_pfx(cinfo, PR_TRUE, pwitem, unicodeFn); 1340 if (pfx != NULL) { 1341 dest = sec_pkcs12_encode_pfx(pfx); 1342 SEC_PKCS12DestroyPFX(pfx); 1343 } 1344 SEC_PKCS7DestroyContentInfo(cinfo); 1345 } 1346 1347 if (safe != NULL) { 1348 PORT_FreeArena(safe->poolp, PR_TRUE); 1349 } 1350 } else { 1351 if (safe != NULL) { 1352 PORT_FreeArena(safe->poolp, PR_TRUE); 1353 } 1354 } 1355 1356 loser: 1357 if (nicks != NULL) { 1358 sec_pkcs12_destroy_nickname_list(nicks); 1359 } 1360 1361 if (ref_certs != NULL) { 1362 sec_pkcs12_destroy_certificate_list(ref_certs); 1363 } 1364 1365 if (pwitem != NULL) { 1366 SECITEM_ZfreeItem(pwitem, PR_TRUE); 1367 } 1368 1369 if (problem == PR_TRUE) { 1370 dest = NULL; 1371 } 1372 1373 return dest; 1374 }