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