p12d.c (113926B)
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 "nss.h" 7 #include "p12t.h" 8 #include "p12.h" 9 #include "plarena.h" 10 #include "secitem.h" 11 #include "secoid.h" 12 #include "seccomon.h" 13 #include "secport.h" 14 #include "cert.h" 15 #include "secpkcs7.h" 16 #include "secasn1.h" 17 #include "secerr.h" 18 #include "pk11func.h" 19 #include "p12plcy.h" 20 #include "p12local.h" 21 #include "secder.h" 22 #include "secport.h" 23 24 #include "certdb.h" 25 26 #include "prcpucfg.h" 27 28 /* This belongs in secport.h */ 29 #define PORT_ArenaGrowArray(poolp, oldptr, type, oldnum, newnum) \ 30 (type *)PORT_ArenaGrow((poolp), (oldptr), \ 31 (oldnum) * sizeof(type), (newnum) * sizeof(type)) 32 33 typedef struct sec_PKCS12SafeContentsContextStr sec_PKCS12SafeContentsContext; 34 35 /* Opaque structure for decoding SafeContents. These are used 36 * for each authenticated safe as well as any nested safe contents. 37 */ 38 struct sec_PKCS12SafeContentsContextStr { 39 /* the parent decoder context */ 40 SEC_PKCS12DecoderContext *p12dcx; 41 42 /* memory arena to allocate space from */ 43 PLArenaPool *arena; 44 45 /* decoder context and destination for decoding safe contents */ 46 SEC_ASN1DecoderContext *safeContentsA1Dcx; 47 sec_PKCS12SafeContents safeContents; 48 49 /* information for decoding safe bags within the safe contents. 50 * these variables are updated for each safe bag decoded. 51 */ 52 SEC_ASN1DecoderContext *currentSafeBagA1Dcx; 53 sec_PKCS12SafeBag *currentSafeBag; 54 PRBool skipCurrentSafeBag; 55 56 /* if the safe contents is nested, the parent is pointed to here. */ 57 sec_PKCS12SafeContentsContext *nestedSafeContentsCtx; 58 }; 59 60 /* opaque decoder context structure. information for decoding a pkcs 12 61 * PDU are stored here as well as decoding pointers for intermediary 62 * structures which are part of the PKCS 12 PDU. Upon a successful 63 * decode, the safe bags containing certificates and keys encountered. 64 */ 65 struct SEC_PKCS12DecoderContextStr { 66 PLArenaPool *arena; 67 PK11SlotInfo *slot; 68 void *wincx; 69 PRBool error; 70 int errorValue; 71 72 /* password */ 73 SECItem *pwitem; 74 75 /* used for decoding the PFX structure */ 76 SEC_ASN1DecoderContext *pfxA1Dcx; 77 sec_PKCS12PFXItem pfx; 78 79 /* safe bags found during decoding */ 80 sec_PKCS12SafeBag **safeBags; 81 unsigned int safeBagCount; 82 83 /* state variables for decoding authenticated safes. */ 84 SEC_PKCS7DecoderContext *currentASafeP7Dcx; 85 SEC_ASN1DecoderContext *aSafeA1Dcx; 86 SEC_PKCS7DecoderContext *aSafeP7Dcx; 87 SEC_PKCS7ContentInfo *aSafeCinfo; 88 sec_PKCS12AuthenticatedSafe authSafe; 89 sec_PKCS12SafeContents safeContents; 90 91 /* safe contents info */ 92 unsigned int safeContentsCnt; 93 sec_PKCS12SafeContentsContext **safeContentsList; 94 95 /* HMAC info */ 96 sec_PKCS12MacData macData; 97 98 /* routines for reading back the data to be hmac'd */ 99 /* They are called as follows. 100 * 101 * Stage 1: decode the aSafes cinfo into a buffer in dArg, 102 * which p12d.c sometimes refers to as the "temp file". 103 * This occurs during SEC_PKCS12DecoderUpdate calls. 104 * 105 * dOpen(dArg, PR_FALSE) 106 * dWrite(dArg, buf, len) 107 * ... 108 * dWrite(dArg, buf, len) 109 * dClose(dArg, PR_FALSE) 110 * 111 * Stage 2: verify MAC 112 * This occurs SEC_PKCS12DecoderVerify. 113 * 114 * dOpen(dArg, PR_TRUE) 115 * dRead(dArg, buf, IN_BUF_LEN) 116 * ... 117 * dRead(dArg, buf, IN_BUF_LEN) 118 * dClose(dArg, PR_TRUE) 119 */ 120 digestOpenFn dOpen; 121 digestCloseFn dClose; 122 digestIOFn dRead, dWrite; 123 void *dArg; 124 PRBool dIsOpen; /* is the temp file created? */ 125 126 /* helper functions */ 127 SECKEYGetPasswordKey pwfn; 128 void *pwfnarg; 129 PRBool swapUnicodeBytes; 130 PRBool forceUnicode; 131 132 /* import information */ 133 PRBool bagsVerified; 134 135 /* buffer management for the default callbacks implementation */ 136 void *buffer; /* storage area */ 137 PRInt32 filesize; /* actual data size */ 138 PRInt32 allocated; /* total buffer size allocated */ 139 PRInt32 currentpos; /* position counter */ 140 SECPKCS12TargetTokenCAs tokenCAs; 141 sec_PKCS12SafeBag **keyList; /* used by ...IterateNext() */ 142 unsigned int iteration; 143 SEC_PKCS12DecoderItem decitem; 144 }; 145 146 /* forward declarations of functions that are used when decoding 147 * safeContents bags which are nested and when decoding the 148 * authenticatedSafes. 149 */ 150 static SECStatus 151 sec_pkcs12_decoder_begin_nested_safe_contents(sec_PKCS12SafeContentsContext 152 *safeContentsCtx); 153 static SECStatus 154 sec_pkcs12_decoder_finish_nested_safe_contents(sec_PKCS12SafeContentsContext 155 *safeContentsCtx); 156 157 /* make sure that the PFX version being decoded is a version 158 * which we support. 159 */ 160 static PRBool 161 sec_pkcs12_proper_version(sec_PKCS12PFXItem *pfx) 162 { 163 /* if no version, assume it is not supported */ 164 if (pfx->version.len == 0) { 165 return PR_FALSE; 166 } 167 168 if (DER_GetInteger(&pfx->version) > SEC_PKCS12_VERSION) { 169 return PR_FALSE; 170 } 171 172 return PR_TRUE; 173 } 174 175 /* retrieve the key for decrypting the safe contents */ 176 static PK11SymKey * 177 sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid) 178 { 179 SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg; 180 PK11SlotInfo *slot; 181 PK11SymKey *bulkKey; 182 SECItem pwitem = { 0 }; 183 SECOidTag algorithm; 184 185 if (!p12dcx) { 186 return NULL; 187 } 188 189 /* if no slot specified, use the internal key slot */ 190 if (p12dcx->slot) { 191 slot = PK11_ReferenceSlot(p12dcx->slot); 192 } else { 193 slot = PK11_GetInternalKeySlot(); 194 } 195 196 algorithm = SECOID_GetAlgorithmTag(algid); 197 198 if (p12dcx->forceUnicode) { 199 if (SECITEM_CopyItem(NULL, &pwitem, p12dcx->pwitem) != SECSuccess) { 200 PK11_FreeSlot(slot); 201 return NULL; 202 } 203 } else { 204 if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm, p12dcx->pwitem)) { 205 PK11_FreeSlot(slot); 206 return NULL; 207 } 208 } 209 210 bulkKey = PK11_PBEKeyGen(slot, algid, &pwitem, PR_FALSE, p12dcx->wincx); 211 /* some tokens can't generate PBE keys on their own, generate the 212 * key in the internal slot, and let the Import code deal with it, 213 * (if the slot can't generate PBEs, then we need to use the internal 214 * slot anyway to unwrap). */ 215 if (!bulkKey && !PK11_IsInternal(slot)) { 216 PK11_FreeSlot(slot); 217 slot = PK11_GetInternalKeySlot(); 218 bulkKey = PK11_PBEKeyGen(slot, algid, &pwitem, PR_FALSE, p12dcx->wincx); 219 } 220 PK11_FreeSlot(slot); 221 222 /* set the password data on the key */ 223 if (bulkKey) { 224 PK11_SetSymKeyUserData(bulkKey, p12dcx->pwitem, NULL); 225 } 226 227 if (pwitem.data) { 228 SECITEM_ZfreeItem(&pwitem, PR_FALSE); 229 } 230 231 return bulkKey; 232 } 233 234 /* XXX this needs to be modified to handle enveloped data. most 235 * likely, it should mirror the routines for SMIME in that regard. 236 */ 237 static PRBool 238 sec_pkcs12_decoder_decryption_allowed(SECAlgorithmID *algid, 239 PK11SymKey *bulkkey) 240 { 241 PRBool decryptionAllowed = SEC_PKCS12DecryptionAllowed(algid); 242 243 if (!decryptionAllowed) { 244 PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM); 245 return PR_FALSE; 246 } 247 248 return PR_TRUE; 249 } 250 251 /* when we encounter a new safe bag during the decoding, we need 252 * to allocate space for the bag to be decoded to and set the 253 * state variables appropriately. all of the safe bags are allocated 254 * in a buffer in the outer SEC_PKCS12DecoderContext, however, 255 * a pointer to the safeBag is also used in the sec_PKCS12SafeContentsContext 256 * for the current bag. 257 */ 258 static SECStatus 259 sec_pkcs12_decoder_init_new_safe_bag(sec_PKCS12SafeContentsContext 260 *safeContentsCtx) 261 { 262 void *mark = NULL; 263 SEC_PKCS12DecoderContext *p12dcx; 264 265 /* make sure that the structures are defined, and there has 266 * not been an error in the decoding 267 */ 268 if (!safeContentsCtx || !safeContentsCtx->p12dcx || safeContentsCtx->p12dcx->error) { 269 return SECFailure; 270 } 271 272 p12dcx = safeContentsCtx->p12dcx; 273 mark = PORT_ArenaMark(p12dcx->arena); 274 275 /* allocate a new safe bag, if bags already exist, grow the 276 * list of bags, otherwise allocate a new list. the list is 277 * NULL terminated. 278 */ 279 p12dcx->safeBags = (!p12dcx->safeBagCount) 280 ? PORT_ArenaZNewArray(p12dcx->arena, sec_PKCS12SafeBag *, 2) 281 : PORT_ArenaGrowArray(p12dcx->arena, p12dcx->safeBags, 282 sec_PKCS12SafeBag *, p12dcx->safeBagCount + 1, 283 p12dcx->safeBagCount + 2); 284 285 if (!p12dcx->safeBags) { 286 p12dcx->errorValue = PORT_GetError(); 287 goto loser; 288 } 289 290 /* append the bag to the end of the list and update the reference 291 * in the safeContentsCtx. 292 */ 293 p12dcx->safeBags[p12dcx->safeBagCount] = 294 safeContentsCtx->currentSafeBag = 295 PORT_ArenaZNew(p12dcx->arena, sec_PKCS12SafeBag); 296 if (!safeContentsCtx->currentSafeBag) { 297 p12dcx->errorValue = PORT_GetError(); 298 goto loser; 299 } 300 p12dcx->safeBags[++p12dcx->safeBagCount] = NULL; 301 302 safeContentsCtx->currentSafeBag->slot = safeContentsCtx->p12dcx->slot; 303 safeContentsCtx->currentSafeBag->pwitem = safeContentsCtx->p12dcx->pwitem; 304 safeContentsCtx->currentSafeBag->swapUnicodeBytes = 305 safeContentsCtx->p12dcx->swapUnicodeBytes; 306 safeContentsCtx->currentSafeBag->arena = safeContentsCtx->p12dcx->arena; 307 safeContentsCtx->currentSafeBag->tokenCAs = 308 safeContentsCtx->p12dcx->tokenCAs; 309 310 PORT_ArenaUnmark(p12dcx->arena, mark); 311 return SECSuccess; 312 313 loser: 314 315 /* if an error occurred, release the memory and set the error flag 316 * the only possible errors triggered by this function are memory 317 * related. 318 */ 319 if (mark) { 320 PORT_ArenaRelease(p12dcx->arena, mark); 321 } 322 323 p12dcx->error = PR_TRUE; 324 return SECFailure; 325 } 326 327 /* A wrapper for updating the ASN1 context in which a safeBag is 328 * being decoded. This function is called as a callback from 329 * secasn1d when decoding SafeContents structures. 330 */ 331 static void 332 sec_pkcs12_decoder_safe_bag_update(void *arg, const char *data, 333 unsigned long len, int depth, 334 SEC_ASN1EncodingPart data_kind) 335 { 336 sec_PKCS12SafeContentsContext *safeContentsCtx = 337 (sec_PKCS12SafeContentsContext *)arg; 338 SEC_PKCS12DecoderContext *p12dcx; 339 SECStatus rv; 340 341 if (!safeContentsCtx || !safeContentsCtx->p12dcx || !safeContentsCtx->currentSafeBagA1Dcx) { 342 return; 343 } 344 p12dcx = safeContentsCtx->p12dcx; 345 346 /* make sure that there are no errors and we are not skipping the current safeBag */ 347 if (p12dcx->error || safeContentsCtx->skipCurrentSafeBag) { 348 goto loser; 349 } 350 351 rv = SEC_ASN1DecoderUpdate(safeContentsCtx->currentSafeBagA1Dcx, data, len); 352 if (rv != SECSuccess) { 353 p12dcx->errorValue = PORT_GetError(); 354 p12dcx->error = PR_TRUE; 355 goto loser; 356 } 357 358 /* The update may have set safeContentsCtx->skipCurrentSafeBag, and we 359 * may not get another opportunity to clean up the decoder context. 360 */ 361 if (safeContentsCtx->skipCurrentSafeBag) { 362 goto loser; 363 } 364 365 return; 366 367 loser: 368 /* Finish the decoder context. Because there 369 * is not a way of returning an error message, it may be worth 370 * while to do a check higher up and finish any decoding contexts 371 * that are still open. 372 */ 373 SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagA1Dcx); 374 safeContentsCtx->currentSafeBagA1Dcx = NULL; 375 return; 376 } 377 378 /* notify function for decoding safeBags. This function is 379 * used to filter safeBag types which are not supported, 380 * initiate the decoding of nested safe contents, and decode 381 * safeBags in general. this function is set when the decoder 382 * context for the safeBag is first created. 383 */ 384 static void 385 sec_pkcs12_decoder_safe_bag_notify(void *arg, PRBool before, 386 void *dest, int real_depth) 387 { 388 sec_PKCS12SafeContentsContext *safeContentsCtx = 389 (sec_PKCS12SafeContentsContext *)arg; 390 SEC_PKCS12DecoderContext *p12dcx; 391 sec_PKCS12SafeBag *bag; 392 PRBool after; 393 394 /* if an error is encountered, return */ 395 if (!safeContentsCtx || !safeContentsCtx->p12dcx || 396 safeContentsCtx->p12dcx->error) { 397 return; 398 } 399 p12dcx = safeContentsCtx->p12dcx; 400 401 /* to make things more readable */ 402 if (before) 403 after = PR_FALSE; 404 else 405 after = PR_TRUE; 406 407 /* have we determined the safeBagType yet? */ 408 bag = safeContentsCtx->currentSafeBag; 409 if (bag->bagTypeTag == NULL) { 410 if (after && (dest == &(bag->safeBagType))) { 411 bag->bagTypeTag = SECOID_FindOID(&(bag->safeBagType)); 412 if (bag->bagTypeTag == NULL) { 413 p12dcx->error = PR_TRUE; 414 p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; 415 } 416 } 417 return; 418 } 419 420 /* process the safeBag depending on it's type. those 421 * which we do not support, are ignored. we start a decoding 422 * context for a nested safeContents. 423 */ 424 switch (bag->bagTypeTag->offset) { 425 case SEC_OID_PKCS12_V1_KEY_BAG_ID: 426 case SEC_OID_PKCS12_V1_CERT_BAG_ID: 427 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: 428 break; 429 case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID: 430 /* if we are just starting to decode the safeContents, initialize 431 * a new safeContentsCtx to process it. 432 */ 433 if (before && (dest == &(bag->safeBagContent))) { 434 sec_pkcs12_decoder_begin_nested_safe_contents(safeContentsCtx); 435 } else if (after && (dest == &(bag->safeBagContent))) { 436 /* clean up the nested decoding */ 437 sec_pkcs12_decoder_finish_nested_safe_contents(safeContentsCtx); 438 } 439 break; 440 case SEC_OID_PKCS12_V1_CRL_BAG_ID: 441 case SEC_OID_PKCS12_V1_SECRET_BAG_ID: 442 default: 443 /* skip any safe bag types we don't understand or handle */ 444 safeContentsCtx->skipCurrentSafeBag = PR_TRUE; 445 break; 446 } 447 448 return; 449 } 450 451 /* notify function for decoding safe contents. each entry in the 452 * safe contents is a safeBag which needs to be allocated and 453 * the decoding context initialized at the beginning and then 454 * the context needs to be closed and finished at the end. 455 * 456 * this function is set when the safeContents decode context is 457 * initialized. 458 */ 459 static void 460 sec_pkcs12_decoder_safe_contents_notify(void *arg, PRBool before, 461 void *dest, int real_depth) 462 { 463 sec_PKCS12SafeContentsContext *safeContentsCtx = 464 (sec_PKCS12SafeContentsContext *)arg; 465 SEC_PKCS12DecoderContext *p12dcx; 466 SECStatus rv; 467 468 /* if there is an error we don't want to continue processing, 469 * just return and keep going. 470 */ 471 if (!safeContentsCtx || !safeContentsCtx->p12dcx || 472 safeContentsCtx->p12dcx->error) { 473 return; 474 } 475 p12dcx = safeContentsCtx->p12dcx; 476 477 /* if we are done with the current safeBag, then we need to 478 * finish the context and set the state variables appropriately. 479 */ 480 if (!before) { 481 SEC_ASN1DecoderClearFilterProc(safeContentsCtx->safeContentsA1Dcx); 482 SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagA1Dcx); 483 safeContentsCtx->currentSafeBagA1Dcx = NULL; 484 safeContentsCtx->skipCurrentSafeBag = PR_FALSE; 485 } else { 486 /* we are starting a new safe bag. we need to allocate space 487 * for the bag and initialize the decoding context. 488 */ 489 rv = sec_pkcs12_decoder_init_new_safe_bag(safeContentsCtx); 490 if (rv != SECSuccess) { 491 goto loser; 492 } 493 494 /* set up the decoder context */ 495 safeContentsCtx->currentSafeBagA1Dcx = 496 SEC_ASN1DecoderStart(p12dcx->arena, 497 safeContentsCtx->currentSafeBag, 498 sec_PKCS12SafeBagTemplate); 499 if (!safeContentsCtx->currentSafeBagA1Dcx) { 500 p12dcx->errorValue = PORT_GetError(); 501 goto loser; 502 } 503 504 /* set the notify and filter procs so that the safe bag 505 * data gets sent to the proper location when decoding. 506 */ 507 SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->currentSafeBagA1Dcx, 508 sec_pkcs12_decoder_safe_bag_notify, 509 safeContentsCtx); 510 SEC_ASN1DecoderSetFilterProc(safeContentsCtx->safeContentsA1Dcx, 511 sec_pkcs12_decoder_safe_bag_update, 512 safeContentsCtx, PR_TRUE); 513 } 514 515 return; 516 517 loser: 518 /* in the event of an error, we want to close the decoding 519 * context and clear the filter and notify procedures. 520 */ 521 p12dcx->error = PR_TRUE; 522 523 if (safeContentsCtx->currentSafeBagA1Dcx) { 524 SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagA1Dcx); 525 safeContentsCtx->currentSafeBagA1Dcx = NULL; 526 } 527 528 SEC_ASN1DecoderClearNotifyProc(safeContentsCtx->safeContentsA1Dcx); 529 SEC_ASN1DecoderClearFilterProc(safeContentsCtx->safeContentsA1Dcx); 530 531 return; 532 } 533 534 /* initialize the safeContents for decoding. this routine 535 * is used for authenticatedSafes as well as nested safeContents. 536 */ 537 static sec_PKCS12SafeContentsContext * 538 sec_pkcs12_decoder_safe_contents_init_decode(SEC_PKCS12DecoderContext *p12dcx, 539 PRBool nestedSafe) 540 { 541 sec_PKCS12SafeContentsContext *safeContentsCtx = NULL; 542 const SEC_ASN1Template *theTemplate; 543 544 if (!p12dcx || p12dcx->error) { 545 return NULL; 546 } 547 548 /* allocate a new safeContents list or grow the existing list and 549 * append the new safeContents onto the end. 550 */ 551 p12dcx->safeContentsList = (!p12dcx->safeContentsCnt) 552 ? PORT_ArenaZNewArray(p12dcx->arena, sec_PKCS12SafeContentsContext *, 2) 553 : PORT_ArenaGrowArray(p12dcx->arena, p12dcx->safeContentsList, 554 sec_PKCS12SafeContentsContext *, 555 1 + p12dcx->safeContentsCnt, 556 2 + p12dcx->safeContentsCnt); 557 558 if (!p12dcx->safeContentsList) { 559 p12dcx->errorValue = PORT_GetError(); 560 goto loser; 561 } 562 563 p12dcx->safeContentsList[p12dcx->safeContentsCnt] = safeContentsCtx = 564 PORT_ArenaZNew(p12dcx->arena, sec_PKCS12SafeContentsContext); 565 if (!p12dcx->safeContentsList[p12dcx->safeContentsCnt]) { 566 p12dcx->errorValue = PORT_GetError(); 567 goto loser; 568 } 569 p12dcx->safeContentsList[++p12dcx->safeContentsCnt] = NULL; 570 571 /* set up the state variables */ 572 safeContentsCtx->p12dcx = p12dcx; 573 safeContentsCtx->arena = p12dcx->arena; 574 575 /* begin the decoding -- the template is based on whether we are 576 * decoding a nested safeContents or not. 577 */ 578 if (nestedSafe == PR_TRUE) { 579 theTemplate = sec_PKCS12NestedSafeContentsDecodeTemplate; 580 } else { 581 theTemplate = sec_PKCS12SafeContentsDecodeTemplate; 582 } 583 584 /* start the decoder context */ 585 safeContentsCtx->safeContentsA1Dcx = SEC_ASN1DecoderStart(p12dcx->arena, 586 &safeContentsCtx->safeContents, 587 theTemplate); 588 589 if (!safeContentsCtx->safeContentsA1Dcx) { 590 p12dcx->errorValue = PORT_GetError(); 591 goto loser; 592 } 593 594 /* set the safeContents notify procedure to look for 595 * and start the decode of safeBags. 596 */ 597 SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->safeContentsA1Dcx, 598 sec_pkcs12_decoder_safe_contents_notify, 599 safeContentsCtx); 600 601 return safeContentsCtx; 602 603 loser: 604 /* in the case of an error, we want to finish the decoder 605 * context and set the error flag. 606 */ 607 if (safeContentsCtx && safeContentsCtx->safeContentsA1Dcx) { 608 SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsA1Dcx); 609 safeContentsCtx->safeContentsA1Dcx = NULL; 610 } 611 612 p12dcx->error = PR_TRUE; 613 614 return NULL; 615 } 616 617 /* wrapper for updating safeContents. this is set as the filter of 618 * safeBag when there is a nested safeContents. 619 */ 620 static void 621 sec_pkcs12_decoder_nested_safe_contents_update(void *arg, const char *buf, 622 unsigned long len, int depth, 623 SEC_ASN1EncodingPart data_kind) 624 { 625 sec_PKCS12SafeContentsContext *safeContentsCtx = 626 (sec_PKCS12SafeContentsContext *)arg; 627 SEC_PKCS12DecoderContext *p12dcx; 628 SECStatus rv; 629 630 /* check for an error */ 631 if (!safeContentsCtx || !safeContentsCtx->p12dcx || 632 safeContentsCtx->p12dcx->error || !safeContentsCtx->safeContentsA1Dcx) { 633 return; 634 } 635 636 /* no need to update if no data sent in */ 637 if (!len || !buf) { 638 return; 639 } 640 641 /* update the decoding context */ 642 p12dcx = safeContentsCtx->p12dcx; 643 rv = SEC_ASN1DecoderUpdate(safeContentsCtx->safeContentsA1Dcx, buf, len); 644 if (rv != SECSuccess) { 645 p12dcx->errorValue = PORT_GetError(); 646 goto loser; 647 } 648 649 return; 650 651 loser: 652 /* handle any errors. If a decoding context is open, close it. */ 653 p12dcx->error = PR_TRUE; 654 if (safeContentsCtx->safeContentsA1Dcx) { 655 SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsA1Dcx); 656 safeContentsCtx->safeContentsA1Dcx = NULL; 657 } 658 } 659 660 /* whenever a new safeContentsSafeBag is encountered, we need 661 * to init a safeContentsContext. 662 */ 663 static SECStatus 664 sec_pkcs12_decoder_begin_nested_safe_contents(sec_PKCS12SafeContentsContext 665 *safeContentsCtx) 666 { 667 /* check for an error */ 668 if (!safeContentsCtx || !safeContentsCtx->p12dcx || 669 safeContentsCtx->p12dcx->error) { 670 return SECFailure; 671 } 672 673 safeContentsCtx->nestedSafeContentsCtx = 674 sec_pkcs12_decoder_safe_contents_init_decode(safeContentsCtx->p12dcx, 675 PR_TRUE); 676 if (!safeContentsCtx->nestedSafeContentsCtx) { 677 return SECFailure; 678 } 679 680 /* set up new filter proc */ 681 SEC_ASN1DecoderSetNotifyProc( 682 safeContentsCtx->nestedSafeContentsCtx->safeContentsA1Dcx, 683 sec_pkcs12_decoder_safe_contents_notify, 684 safeContentsCtx->nestedSafeContentsCtx); 685 686 SEC_ASN1DecoderSetFilterProc(safeContentsCtx->currentSafeBagA1Dcx, 687 sec_pkcs12_decoder_nested_safe_contents_update, 688 safeContentsCtx->nestedSafeContentsCtx, 689 PR_TRUE); 690 691 return SECSuccess; 692 } 693 694 /* when the safeContents is done decoding, we need to reset the 695 * proper filter and notify procs and close the decoding context 696 */ 697 static SECStatus 698 sec_pkcs12_decoder_finish_nested_safe_contents(sec_PKCS12SafeContentsContext 699 *safeContentsCtx) 700 { 701 /* check for error */ 702 if (!safeContentsCtx || !safeContentsCtx->p12dcx || 703 safeContentsCtx->p12dcx->error) { 704 return SECFailure; 705 } 706 707 /* clean up */ 708 SEC_ASN1DecoderClearFilterProc(safeContentsCtx->currentSafeBagA1Dcx); 709 SEC_ASN1DecoderClearNotifyProc( 710 safeContentsCtx->nestedSafeContentsCtx->safeContentsA1Dcx); 711 SEC_ASN1DecoderFinish( 712 safeContentsCtx->nestedSafeContentsCtx->safeContentsA1Dcx); 713 safeContentsCtx->nestedSafeContentsCtx->safeContentsA1Dcx = NULL; 714 safeContentsCtx->nestedSafeContentsCtx = NULL; 715 716 return SECSuccess; 717 } 718 719 /* wrapper for updating safeContents. This is used when decoding 720 * the nested safeContents and any authenticatedSafes. 721 */ 722 static void 723 sec_pkcs12_decoder_safe_contents_callback(void *arg, const char *buf, 724 unsigned long len) 725 { 726 SECStatus rv; 727 sec_PKCS12SafeContentsContext *safeContentsCtx = 728 (sec_PKCS12SafeContentsContext *)arg; 729 SEC_PKCS12DecoderContext *p12dcx; 730 731 /* check for error */ 732 if (!safeContentsCtx || !safeContentsCtx->p12dcx || 733 safeContentsCtx->p12dcx->error || !safeContentsCtx->safeContentsA1Dcx) { 734 return; 735 } 736 p12dcx = safeContentsCtx->p12dcx; 737 738 /* update the decoder */ 739 rv = SEC_ASN1DecoderUpdate(safeContentsCtx->safeContentsA1Dcx, buf, len); 740 if (rv != SECSuccess) { 741 /* if we fail while trying to decode a 'safe', it's probably because 742 * we didn't have the correct password. */ 743 PORT_SetError(SEC_ERROR_BAD_PASSWORD); 744 p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; 745 SEC_PKCS7DecoderAbort(p12dcx->currentASafeP7Dcx, SEC_ERROR_BAD_PASSWORD); 746 goto loser; 747 } 748 749 return; 750 751 loser: 752 /* set the error and finish the context */ 753 p12dcx->error = PR_TRUE; 754 if (safeContentsCtx->safeContentsA1Dcx) { 755 SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsA1Dcx); 756 safeContentsCtx->safeContentsA1Dcx = NULL; 757 } 758 759 return; 760 } 761 762 /* this is a wrapper for the ASN1 decoder to call SEC_PKCS7DecoderUpdate 763 */ 764 static void 765 sec_pkcs12_decoder_wrap_p7_update(void *arg, const char *data, 766 unsigned long len, int depth, 767 SEC_ASN1EncodingPart data_kind) 768 { 769 SEC_PKCS7DecoderContext *p7dcx = (SEC_PKCS7DecoderContext *)arg; 770 771 SEC_PKCS7DecoderUpdate(p7dcx, data, len); 772 } 773 774 /* notify function for decoding aSafes. at the beginning, 775 * of an authenticatedSafe, we start a decode of a safeContents. 776 * at the end, we clean up the safeContents decoder context and 777 * reset state variables 778 */ 779 static void 780 sec_pkcs12_decoder_asafes_notify(void *arg, PRBool before, void *dest, 781 int real_depth) 782 { 783 SEC_PKCS12DecoderContext *p12dcx; 784 sec_PKCS12SafeContentsContext *safeContentsCtx; 785 786 /* make sure no error occurred. */ 787 p12dcx = (SEC_PKCS12DecoderContext *)arg; 788 if (!p12dcx || p12dcx->error) { 789 return; 790 } 791 792 if (before) { 793 794 /* init a new safeContentsContext */ 795 safeContentsCtx = sec_pkcs12_decoder_safe_contents_init_decode(p12dcx, 796 PR_FALSE); 797 if (!safeContentsCtx) { 798 goto loser; 799 } 800 801 /* initiate the PKCS7ContentInfo decode */ 802 p12dcx->currentASafeP7Dcx = SEC_PKCS7DecoderStart( 803 sec_pkcs12_decoder_safe_contents_callback, 804 safeContentsCtx, 805 p12dcx->pwfn, p12dcx->pwfnarg, 806 sec_pkcs12_decoder_get_decrypt_key, p12dcx, 807 sec_pkcs12_decoder_decryption_allowed); 808 if (!p12dcx->currentASafeP7Dcx) { 809 p12dcx->errorValue = PORT_GetError(); 810 goto loser; 811 } 812 SEC_ASN1DecoderSetFilterProc(p12dcx->aSafeA1Dcx, 813 sec_pkcs12_decoder_wrap_p7_update, 814 p12dcx->currentASafeP7Dcx, PR_TRUE); 815 } 816 817 if (!before) { 818 /* if one is being decoded, finish the decode */ 819 if (p12dcx->currentASafeP7Dcx != NULL) { 820 SEC_PKCS7ContentInfo *cinfo; 821 unsigned int cnt = p12dcx->safeContentsCnt - 1; 822 safeContentsCtx = p12dcx->safeContentsList[cnt]; 823 if (safeContentsCtx->safeContentsA1Dcx) { 824 SEC_ASN1DecoderClearFilterProc(p12dcx->aSafeA1Dcx); 825 SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsA1Dcx); 826 safeContentsCtx->safeContentsA1Dcx = NULL; 827 } 828 cinfo = SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx); 829 SEC_ASN1DecoderClearFilterProc(p12dcx->aSafeA1Dcx); 830 p12dcx->currentASafeP7Dcx = NULL; 831 if (!cinfo) { 832 p12dcx->errorValue = PORT_GetError(); 833 goto loser; 834 } 835 SEC_PKCS7DestroyContentInfo(cinfo); /* don't leak it */ 836 } 837 } 838 839 return; 840 841 loser: 842 /* set the error flag */ 843 p12dcx->error = PR_TRUE; 844 return; 845 } 846 847 /* wrapper for updating asafes decoding context. this function 848 * writes data being decoded to disk, so that a mac can be computed 849 * later. 850 */ 851 static void 852 sec_pkcs12_decoder_asafes_callback(void *arg, const char *buf, 853 unsigned long len) 854 { 855 SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg; 856 SECStatus rv; 857 858 if (!p12dcx || p12dcx->error) { 859 return; 860 } 861 862 /* update the context */ 863 rv = SEC_ASN1DecoderUpdate(p12dcx->aSafeA1Dcx, buf, len); 864 if (rv != SECSuccess) { 865 p12dcx->errorValue = PORT_GetError(); 866 p12dcx->error = PR_TRUE; 867 goto loser; 868 } 869 870 /* if we are writing to a file, write out the new information */ 871 if (p12dcx->dWrite) { 872 unsigned long writeLen = (*p12dcx->dWrite)(p12dcx->dArg, 873 (unsigned char *)buf, len); 874 if (writeLen != len) { 875 p12dcx->errorValue = PORT_GetError(); 876 goto loser; 877 } 878 } 879 880 return; 881 882 loser: 883 /* set the error flag */ 884 p12dcx->error = PR_TRUE; 885 SEC_ASN1DecoderFinish(p12dcx->aSafeA1Dcx); 886 p12dcx->aSafeA1Dcx = NULL; 887 888 return; 889 } 890 891 /* start the decode of an authenticatedSafe contentInfo. 892 */ 893 static SECStatus 894 sec_pkcs12_decode_start_asafes_cinfo(SEC_PKCS12DecoderContext *p12dcx) 895 { 896 if (!p12dcx || p12dcx->error) { 897 return SECFailure; 898 } 899 900 /* start the decode context */ 901 p12dcx->aSafeA1Dcx = SEC_ASN1DecoderStart(p12dcx->arena, 902 &p12dcx->authSafe, 903 sec_PKCS12AuthenticatedSafeTemplate); 904 if (!p12dcx->aSafeA1Dcx) { 905 p12dcx->errorValue = PORT_GetError(); 906 goto loser; 907 } 908 909 /* set the notify function */ 910 SEC_ASN1DecoderSetNotifyProc(p12dcx->aSafeA1Dcx, 911 sec_pkcs12_decoder_asafes_notify, p12dcx); 912 913 /* begin the authSafe decoder context */ 914 p12dcx->aSafeP7Dcx = SEC_PKCS7DecoderStart( 915 sec_pkcs12_decoder_asafes_callback, p12dcx, 916 p12dcx->pwfn, p12dcx->pwfnarg, NULL, NULL, NULL); 917 if (!p12dcx->aSafeP7Dcx) { 918 p12dcx->errorValue = PORT_GetError(); 919 goto loser; 920 } 921 922 /* open the temp file for writing, if the digest functions were set */ 923 if (p12dcx->dOpen && (*p12dcx->dOpen)(p12dcx->dArg, PR_FALSE) != SECSuccess) { 924 p12dcx->errorValue = PORT_GetError(); 925 goto loser; 926 } 927 /* dOpen(dArg, PR_FALSE) creates the temp file */ 928 p12dcx->dIsOpen = PR_TRUE; 929 930 return SECSuccess; 931 932 loser: 933 p12dcx->error = PR_TRUE; 934 935 if (p12dcx->aSafeA1Dcx) { 936 SEC_ASN1DecoderFinish(p12dcx->aSafeA1Dcx); 937 p12dcx->aSafeA1Dcx = NULL; 938 } 939 940 if (p12dcx->aSafeP7Dcx) { 941 SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx); 942 p12dcx->aSafeP7Dcx = NULL; 943 } 944 945 return SECFailure; 946 } 947 948 /* wrapper for updating the safeContents. this function is used as 949 * a filter for the pfx when decoding the authenticated safes 950 */ 951 static void 952 sec_pkcs12_decode_asafes_cinfo_update(void *arg, const char *buf, 953 unsigned long len, int depth, 954 SEC_ASN1EncodingPart data_kind) 955 { 956 SEC_PKCS12DecoderContext *p12dcx; 957 SECStatus rv; 958 959 p12dcx = (SEC_PKCS12DecoderContext *)arg; 960 if (!p12dcx || p12dcx->error) { 961 return; 962 } 963 964 /* update the safeContents decoder */ 965 rv = SEC_PKCS7DecoderUpdate(p12dcx->aSafeP7Dcx, buf, len); 966 if (rv != SECSuccess) { 967 p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; 968 goto loser; 969 } 970 971 return; 972 973 loser: 974 975 /* did we find an error? if so, close the context and set the 976 * error flag. 977 */ 978 SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx); 979 p12dcx->aSafeP7Dcx = NULL; 980 p12dcx->error = PR_TRUE; 981 } 982 983 /* notify procedure used while decoding the pfx. When we encounter 984 * the authSafes, we want to trigger the decoding of authSafes as well 985 * as when we encounter the macData, trigger the decoding of it. we do 986 * this because we we are streaming the decoder and not decoding in place. 987 * the pfx which is the destination, only has the version decoded into it. 988 */ 989 static void 990 sec_pkcs12_decoder_pfx_notify_proc(void *arg, PRBool before, void *dest, 991 int real_depth) 992 { 993 SECStatus rv; 994 SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg; 995 996 /* if an error occurs, clear the notifyProc and the filterProc 997 * and continue. 998 */ 999 if (p12dcx->error) { 1000 SEC_ASN1DecoderClearNotifyProc(p12dcx->pfxA1Dcx); 1001 SEC_ASN1DecoderClearFilterProc(p12dcx->pfxA1Dcx); 1002 return; 1003 } 1004 1005 if (before && (dest == &p12dcx->pfx.encodedAuthSafe)) { 1006 1007 /* we want to make sure this is a version we support */ 1008 if (!sec_pkcs12_proper_version(&p12dcx->pfx)) { 1009 p12dcx->errorValue = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION; 1010 goto loser; 1011 } 1012 1013 /* start the decode of the aSafes cinfo... */ 1014 rv = sec_pkcs12_decode_start_asafes_cinfo(p12dcx); 1015 if (rv != SECSuccess) { 1016 goto loser; 1017 } 1018 1019 /* set the filter proc to update the authenticated safes. */ 1020 SEC_ASN1DecoderSetFilterProc(p12dcx->pfxA1Dcx, 1021 sec_pkcs12_decode_asafes_cinfo_update, 1022 p12dcx, PR_TRUE); 1023 } 1024 1025 if (!before && (dest == &p12dcx->pfx.encodedAuthSafe)) { 1026 1027 /* we are done decoding the authenticatedSafes, so we need to 1028 * finish the decoderContext and clear the filter proc 1029 * and close the hmac callback, if present 1030 */ 1031 p12dcx->aSafeCinfo = SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx); 1032 p12dcx->aSafeP7Dcx = NULL; 1033 if (!p12dcx->aSafeCinfo) { 1034 p12dcx->errorValue = PORT_GetError(); 1035 goto loser; 1036 } 1037 SEC_ASN1DecoderClearFilterProc(p12dcx->pfxA1Dcx); 1038 if (p12dcx->dClose && ((*p12dcx->dClose)(p12dcx->dArg, PR_FALSE) != SECSuccess)) { 1039 p12dcx->errorValue = PORT_GetError(); 1040 goto loser; 1041 } 1042 } 1043 1044 return; 1045 1046 loser: 1047 p12dcx->error = PR_TRUE; 1048 } 1049 1050 /* default implementations of the open/close/read/write functions for 1051 SEC_PKCS12DecoderStart 1052 */ 1053 1054 #define DEFAULT_TEMP_SIZE 4096 1055 1056 static SECStatus 1057 p12u_DigestOpen(void *arg, PRBool readData) 1058 { 1059 SEC_PKCS12DecoderContext *p12cxt = arg; 1060 1061 p12cxt->currentpos = 0; 1062 1063 if (PR_FALSE == readData) { 1064 /* allocate an initial buffer */ 1065 p12cxt->filesize = 0; 1066 p12cxt->allocated = DEFAULT_TEMP_SIZE; 1067 p12cxt->buffer = PORT_Alloc(DEFAULT_TEMP_SIZE); 1068 PR_ASSERT(p12cxt->buffer); 1069 } else { 1070 PR_ASSERT(p12cxt->buffer); 1071 if (!p12cxt->buffer) { 1072 return SECFailure; /* no data to read */ 1073 } 1074 } 1075 1076 return SECSuccess; 1077 } 1078 1079 static SECStatus 1080 p12u_DigestClose(void *arg, PRBool removeFile) 1081 { 1082 SEC_PKCS12DecoderContext *p12cxt = arg; 1083 1084 PR_ASSERT(p12cxt); 1085 if (!p12cxt) { 1086 return SECFailure; 1087 } 1088 p12cxt->currentpos = 0; 1089 1090 if (PR_TRUE == removeFile) { 1091 PR_ASSERT(p12cxt->buffer); 1092 if (!p12cxt->buffer) { 1093 return SECFailure; 1094 } 1095 if (p12cxt->buffer) { 1096 PORT_Free(p12cxt->buffer); 1097 p12cxt->buffer = NULL; 1098 p12cxt->allocated = 0; 1099 p12cxt->filesize = 0; 1100 } 1101 } 1102 1103 return SECSuccess; 1104 } 1105 1106 static int 1107 p12u_DigestRead(void *arg, unsigned char *buf, unsigned long len) 1108 { 1109 int toread = len; 1110 SEC_PKCS12DecoderContext *p12cxt = arg; 1111 1112 if (!buf || len == 0 || !p12cxt->buffer) { 1113 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1114 return -1; 1115 } 1116 1117 if ((p12cxt->filesize - p12cxt->currentpos) < (long)len) { 1118 /* trying to read past the end of the buffer */ 1119 toread = p12cxt->filesize - p12cxt->currentpos; 1120 } 1121 memcpy(buf, (char *)p12cxt->buffer + p12cxt->currentpos, toread); 1122 p12cxt->currentpos += toread; 1123 return toread; 1124 } 1125 1126 static int 1127 p12u_DigestWrite(void *arg, unsigned char *buf, unsigned long len) 1128 { 1129 SEC_PKCS12DecoderContext *p12cxt = arg; 1130 1131 if (!buf || len == 0) { 1132 return -1; 1133 } 1134 1135 if (p12cxt->currentpos + (long)len > p12cxt->filesize) { 1136 p12cxt->filesize = p12cxt->currentpos + len; 1137 } else { 1138 p12cxt->filesize += len; 1139 } 1140 if (p12cxt->filesize > p12cxt->allocated) { 1141 void *newbuffer; 1142 size_t newsize = p12cxt->filesize + DEFAULT_TEMP_SIZE; 1143 newbuffer = PORT_Realloc(p12cxt->buffer, newsize); 1144 if (NULL == newbuffer) { 1145 return -1; /* can't extend the buffer */ 1146 } 1147 p12cxt->buffer = newbuffer; 1148 p12cxt->allocated = newsize; 1149 } 1150 PR_ASSERT(p12cxt->buffer); 1151 memcpy((char *)p12cxt->buffer + p12cxt->currentpos, buf, len); 1152 p12cxt->currentpos += len; 1153 return len; 1154 } 1155 1156 /* SEC_PKCS12DecoderStart 1157 * Creates a decoder context for decoding a PKCS 12 PDU objct. 1158 * This function sets up the initial decoding context for the 1159 * PFX and sets the needed state variables. 1160 * 1161 * pwitem - the password for the hMac and any encoded safes. 1162 * this should be changed to take a callback which retrieves 1163 * the password. it may be possible for different safes to 1164 * have different passwords. also, the password is already 1165 * in unicode. it should probably be converted down below via 1166 * a unicode conversion callback. 1167 * slot - the slot to import the dataa into should multiple slots 1168 * be supported based on key type and cert type? 1169 * dOpen, dClose, dRead, dWrite - digest routines for writing data 1170 * to a file so it could be read back and the hmac recomputed 1171 * and verified. doesn't seem to be a way for both encoding 1172 * and decoding to be single pass, thus the need for these 1173 * routines. 1174 * dArg - the argument for dOpen, etc. 1175 * 1176 * if NULL == dOpen == dClose == dRead == dWrite == dArg, then default 1177 * implementations using a memory buffer are used 1178 * 1179 * This function returns the decoder context, if it was successful. 1180 * Otherwise, null is returned. 1181 */ 1182 SEC_PKCS12DecoderContext * 1183 SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx, 1184 digestOpenFn dOpen, digestCloseFn dClose, 1185 digestIOFn dRead, digestIOFn dWrite, void *dArg) 1186 { 1187 SEC_PKCS12DecoderContext *p12dcx; 1188 PLArenaPool *arena; 1189 PRInt32 forceUnicode = PR_FALSE; 1190 SECStatus rv; 1191 1192 arena = PORT_NewArena(2048); /* different size? */ 1193 if (!arena) { 1194 return NULL; /* error is already set */ 1195 } 1196 1197 /* allocate the decoder context and set the state variables */ 1198 p12dcx = PORT_ArenaZNew(arena, SEC_PKCS12DecoderContext); 1199 if (!p12dcx) { 1200 goto loser; /* error is already set */ 1201 } 1202 1203 if (!dOpen && !dClose && !dRead && !dWrite && !dArg) { 1204 /* use default implementations */ 1205 dOpen = p12u_DigestOpen; 1206 dClose = p12u_DigestClose; 1207 dRead = p12u_DigestRead; 1208 dWrite = p12u_DigestWrite; 1209 dArg = (void *)p12dcx; 1210 } 1211 1212 p12dcx->arena = arena; 1213 p12dcx->pwitem = pwitem; 1214 p12dcx->slot = (slot ? PK11_ReferenceSlot(slot) 1215 : PK11_GetInternalKeySlot()); 1216 p12dcx->wincx = wincx; 1217 p12dcx->tokenCAs = SECPKCS12TargetTokenNoCAs; 1218 #ifdef IS_LITTLE_ENDIAN 1219 p12dcx->swapUnicodeBytes = PR_TRUE; 1220 #else 1221 p12dcx->swapUnicodeBytes = PR_FALSE; 1222 #endif 1223 rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode); 1224 if (rv != SECSuccess) { 1225 goto loser; 1226 } 1227 p12dcx->forceUnicode = forceUnicode; 1228 p12dcx->errorValue = 0; 1229 p12dcx->error = PR_FALSE; 1230 1231 /* start the decoding of the PFX and set the notify proc 1232 * for the PFX item. 1233 */ 1234 p12dcx->pfxA1Dcx = SEC_ASN1DecoderStart(p12dcx->arena, &p12dcx->pfx, 1235 sec_PKCS12PFXItemTemplate); 1236 if (!p12dcx->pfxA1Dcx) { 1237 PK11_FreeSlot(p12dcx->slot); 1238 goto loser; 1239 } 1240 1241 SEC_ASN1DecoderSetNotifyProc(p12dcx->pfxA1Dcx, 1242 sec_pkcs12_decoder_pfx_notify_proc, 1243 p12dcx); 1244 1245 /* set up digest functions */ 1246 p12dcx->dOpen = dOpen; 1247 p12dcx->dWrite = dWrite; 1248 p12dcx->dClose = dClose; 1249 p12dcx->dRead = dRead; 1250 p12dcx->dArg = dArg; 1251 p12dcx->dIsOpen = PR_FALSE; 1252 1253 p12dcx->keyList = NULL; 1254 p12dcx->decitem.type = 0; 1255 p12dcx->decitem.der = NULL; 1256 p12dcx->decitem.hasKey = PR_FALSE; 1257 p12dcx->decitem.friendlyName = NULL; 1258 p12dcx->iteration = 0; 1259 1260 return p12dcx; 1261 1262 loser: 1263 PORT_FreeArena(arena, PR_TRUE); 1264 return NULL; 1265 } 1266 1267 SECStatus 1268 SEC_PKCS12DecoderSetTargetTokenCAs(SEC_PKCS12DecoderContext *p12dcx, 1269 SECPKCS12TargetTokenCAs tokenCAs) 1270 { 1271 if (!p12dcx || p12dcx->error) { 1272 return SECFailure; 1273 } 1274 p12dcx->tokenCAs = tokenCAs; 1275 return SECSuccess; 1276 } 1277 1278 /* SEC_PKCS12DecoderUpdate 1279 * Streaming update sending more data to the decoder. If 1280 * an error occurs, SECFailure is returned. 1281 * 1282 * p12dcx - the decoder context 1283 * data, len - the data buffer and length of data to send to 1284 * the update functions. 1285 */ 1286 SECStatus 1287 SEC_PKCS12DecoderUpdate(SEC_PKCS12DecoderContext *p12dcx, 1288 unsigned char *data, unsigned long len) 1289 { 1290 SECStatus rv; 1291 1292 if (!p12dcx || p12dcx->error) { 1293 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1294 return SECFailure; 1295 } 1296 1297 /* update the PFX decoder context */ 1298 rv = SEC_ASN1DecoderUpdate(p12dcx->pfxA1Dcx, (const char *)data, len); 1299 if (rv != SECSuccess) { 1300 p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; 1301 goto loser; 1302 } 1303 1304 return SECSuccess; 1305 1306 loser: 1307 1308 p12dcx->error = PR_TRUE; 1309 return SECFailure; 1310 } 1311 1312 /* This should be a nice sized buffer for reading in data (potentially large 1313 ** amounts) to be MACed. It should be MUCH larger than HASH_LENGTH_MAX. 1314 */ 1315 #define IN_BUF_LEN 1024 1316 #ifdef DEBUG 1317 static const char bufferEnd[] = { "BufferEnd" }; 1318 #endif 1319 #define FUDGE 128 /* must be as large as bufferEnd or more. */ 1320 1321 #ifdef UNSAFE_FUZZER_MODE 1322 static PRBool 1323 fuzzer_parity_check(const unsigned char *buf, size_t len) 1324 { 1325 unsigned char p = 0; 1326 for (size_t i = 0; i < len; i++) 1327 p ^= buf[i]; 1328 return (p & 1) != 0; 1329 } 1330 1331 static SECStatus 1332 sec_pkcs12_decoder_unsafe_parity_outcome(SEC_PKCS12DecoderContext *p12dcx) 1333 { 1334 PRBool allow = PR_TRUE; 1335 if (p12dcx->pfx.encodedMacData.data && p12dcx->pfx.encodedMacData.len) { 1336 allow = fuzzer_parity_check(p12dcx->pfx.encodedMacData.data, p12dcx->pfx.encodedMacData.len); 1337 } 1338 1339 if (p12dcx->dClose) { 1340 (*p12dcx->dClose)(p12dcx->dArg, PR_TRUE); 1341 p12dcx->dIsOpen = PR_FALSE; 1342 } 1343 1344 if (!allow) { 1345 PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC); 1346 return SECFailure; 1347 } 1348 1349 return SECSuccess; 1350 } 1351 #endif /* UNSAFE_FUZZER_MODE */ 1352 1353 /* verify the hmac by reading the data from the temporary file 1354 * using the routines specified when the decodingContext was 1355 * created and return SECSuccess if the hmac matches. 1356 */ 1357 static SECStatus 1358 sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx) 1359 { 1360 PK11Context *pk11cx = NULL; 1361 PK11SymKey *symKey = NULL; 1362 unsigned char *buf; 1363 SECStatus rv = SECFailure; 1364 SECStatus lrv; 1365 unsigned int bufLen; 1366 int bytesRead; 1367 SECItem hmacRes; 1368 SECItem ignore = { 0 }; 1369 CK_MECHANISM_TYPE hmacMech; 1370 1371 if (!p12dcx || p12dcx->error) { 1372 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1373 return SECFailure; 1374 } 1375 #ifdef UNSAFE_FUZZER_MODE 1376 return sec_pkcs12_decoder_unsafe_parity_outcome(p12dcx); 1377 #endif /* UNSAFE_FUZZER_MODE */ 1378 buf = (unsigned char *)PORT_Alloc(IN_BUF_LEN + FUDGE); 1379 if (!buf) 1380 return SECFailure; /* error code has been set. */ 1381 1382 #ifdef DEBUG 1383 memcpy(buf + IN_BUF_LEN, bufferEnd, sizeof bufferEnd); 1384 #endif 1385 1386 /* generate hmac key */ 1387 symKey = sec_pkcs12_integrity_key(p12dcx->slot, &p12dcx->macData, 1388 p12dcx->pwitem, &hmacMech, PR_TRUE, 1389 p12dcx->wincx); 1390 if (symKey == NULL) { 1391 goto loser; 1392 } 1393 1394 /* init hmac */ 1395 pk11cx = PK11_CreateContextBySymKey(hmacMech, CKA_SIGN, symKey, &ignore); 1396 if (!pk11cx) { 1397 goto loser; 1398 } 1399 lrv = PK11_DigestBegin(pk11cx); 1400 if (lrv == SECFailure) { 1401 goto loser; 1402 } 1403 1404 /* try to open the data for readback */ 1405 if (p12dcx->dOpen && ((*p12dcx->dOpen)(p12dcx->dArg, PR_TRUE) != SECSuccess)) { 1406 goto loser; 1407 } 1408 1409 /* read the data back IN_BUF_LEN bytes at a time and recompute 1410 * the hmac. if fewer bytes are read than are requested, it is 1411 * assumed that the end of file has been reached. if bytesRead 1412 * is returned as -1, then an error occurred reading from the 1413 * file. 1414 */ 1415 do { 1416 bytesRead = (*p12dcx->dRead)(p12dcx->dArg, buf, IN_BUF_LEN); 1417 if (bytesRead < 0) { 1418 PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_READ); 1419 goto loser; 1420 } 1421 PORT_Assert(bytesRead <= IN_BUF_LEN); 1422 PORT_Assert(!memcmp(buf + IN_BUF_LEN, bufferEnd, sizeof bufferEnd)); 1423 1424 if (bytesRead > IN_BUF_LEN) { 1425 /* dRead callback overflowed buffer. */ 1426 PORT_SetError(SEC_ERROR_INPUT_LEN); 1427 goto loser; 1428 } 1429 1430 if (bytesRead) { 1431 lrv = PK11_DigestOp(pk11cx, buf, bytesRead); 1432 if (lrv == SECFailure) { 1433 goto loser; 1434 } 1435 } 1436 } while (bytesRead == IN_BUF_LEN); 1437 1438 /* finish the hmac context */ 1439 lrv = PK11_DigestFinal(pk11cx, buf, &bufLen, IN_BUF_LEN); 1440 if (lrv == SECFailure) { 1441 goto loser; 1442 } 1443 1444 hmacRes.data = buf; 1445 hmacRes.len = bufLen; 1446 1447 /* is the hmac computed the same as the hmac which was decoded? */ 1448 rv = SECSuccess; 1449 if (SECITEM_CompareItem(&hmacRes, &p12dcx->macData.safeMac.digest) != SECEqual) { 1450 PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC); 1451 rv = SECFailure; 1452 } 1453 1454 loser: 1455 /* close the file and remove it */ 1456 if (p12dcx->dClose) { 1457 (*p12dcx->dClose)(p12dcx->dArg, PR_TRUE); 1458 p12dcx->dIsOpen = PR_FALSE; 1459 } 1460 1461 if (pk11cx) { 1462 PK11_DestroyContext(pk11cx, PR_TRUE); 1463 } 1464 if (symKey) { 1465 PK11_FreeSymKey(symKey); 1466 } 1467 PORT_ZFree(buf, IN_BUF_LEN + FUDGE); 1468 1469 return rv; 1470 } 1471 1472 /* SEC_PKCS12DecoderVerify 1473 * Verify the macData or the signature of the decoded PKCS 12 PDU. 1474 * If the signature or the macData do not match, SECFailure is 1475 * returned. 1476 * 1477 * p12dcx - the decoder context 1478 */ 1479 SECStatus 1480 SEC_PKCS12DecoderVerify(SEC_PKCS12DecoderContext *p12dcx) 1481 { 1482 SECStatus rv = SECSuccess; 1483 1484 /* make sure that no errors have occurred... */ 1485 if (!p12dcx) { 1486 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1487 return SECFailure; 1488 } 1489 if (p12dcx->error) { 1490 /* error code is already set! PORT_SetError(p12dcx->errorValue); */ 1491 return SECFailure; 1492 } 1493 1494 rv = SEC_ASN1DecoderFinish(p12dcx->pfxA1Dcx); 1495 p12dcx->pfxA1Dcx = NULL; 1496 if (rv != SECSuccess) { 1497 return rv; 1498 } 1499 #ifdef UNSAFE_FUZZER_MODE 1500 return sec_pkcs12_decoder_unsafe_parity_outcome(p12dcx); 1501 #else /* UNSAFE_FUZZER_MODE */ 1502 /* check the signature or the mac depending on the type of 1503 * integrity used. 1504 */ 1505 if (p12dcx->pfx.encodedMacData.len) { 1506 rv = SEC_ASN1DecodeItem(p12dcx->arena, &p12dcx->macData, 1507 sec_PKCS12MacDataTemplate, 1508 &p12dcx->pfx.encodedMacData); 1509 if (rv == SECSuccess) { 1510 return sec_pkcs12_decoder_verify_mac(p12dcx); 1511 } 1512 return rv; 1513 } 1514 if (SEC_PKCS7VerifySignature(p12dcx->aSafeCinfo, certUsageEmailSigner, 1515 PR_FALSE)) { 1516 return SECSuccess; 1517 } 1518 PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC); 1519 return SECFailure; 1520 #endif /* UNSAFE_FUZZER_MODE */ 1521 } 1522 1523 /* SEC_PKCS12DecoderFinish 1524 * Free any open ASN1 or PKCS7 decoder contexts and then 1525 * free the arena pool which everything should be allocated 1526 * from. This function should be called upon completion of 1527 * decoding and installing of a pfx pdu. This should be 1528 * called even if an error occurs. 1529 * 1530 * p12dcx - the decoder context 1531 */ 1532 void 1533 SEC_PKCS12DecoderFinish(SEC_PKCS12DecoderContext *p12dcx) 1534 { 1535 unsigned int i; 1536 1537 if (!p12dcx) { 1538 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1539 return; 1540 } 1541 1542 if (p12dcx->pfxA1Dcx) { 1543 SEC_ASN1DecoderFinish(p12dcx->pfxA1Dcx); 1544 p12dcx->pfxA1Dcx = NULL; 1545 } 1546 1547 if (p12dcx->aSafeA1Dcx) { 1548 SEC_ASN1DecoderFinish(p12dcx->aSafeA1Dcx); 1549 p12dcx->aSafeA1Dcx = NULL; 1550 } 1551 1552 /* cleanup any old ASN1 decoder contexts */ 1553 for (i = 0; i < p12dcx->safeContentsCnt; ++i) { 1554 sec_PKCS12SafeContentsContext *safeContentsCtx, *nested; 1555 safeContentsCtx = p12dcx->safeContentsList[i]; 1556 if (safeContentsCtx) { 1557 nested = safeContentsCtx->nestedSafeContentsCtx; 1558 while (nested) { 1559 if (nested->currentSafeBagA1Dcx) { 1560 SEC_ASN1DecoderFinish(nested->currentSafeBagA1Dcx); 1561 nested->currentSafeBagA1Dcx = NULL; 1562 } 1563 if (nested->safeContentsA1Dcx) { 1564 SEC_ASN1DecoderFinish(nested->safeContentsA1Dcx); 1565 nested->safeContentsA1Dcx = NULL; 1566 } 1567 nested = nested->nestedSafeContentsCtx; 1568 } 1569 if (safeContentsCtx->currentSafeBagA1Dcx) { 1570 SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagA1Dcx); 1571 safeContentsCtx->currentSafeBagA1Dcx = NULL; 1572 } 1573 if (safeContentsCtx->safeContentsA1Dcx) { 1574 SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsA1Dcx); 1575 safeContentsCtx->safeContentsA1Dcx = NULL; 1576 } 1577 } 1578 } 1579 1580 if (p12dcx->currentASafeP7Dcx && 1581 p12dcx->currentASafeP7Dcx != p12dcx->aSafeP7Dcx) { 1582 SEC_PKCS7ContentInfo *cinfo; 1583 cinfo = SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx); 1584 if (cinfo) { 1585 SEC_PKCS7DestroyContentInfo(cinfo); /* don't leak it */ 1586 } 1587 } 1588 p12dcx->currentASafeP7Dcx = NULL; 1589 1590 if (p12dcx->aSafeP7Dcx) { 1591 SEC_PKCS7ContentInfo *cinfo; 1592 cinfo = SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx); 1593 if (cinfo) { 1594 SEC_PKCS7DestroyContentInfo(cinfo); 1595 } 1596 p12dcx->aSafeP7Dcx = NULL; 1597 } 1598 1599 if (p12dcx->aSafeCinfo) { 1600 SEC_PKCS7DestroyContentInfo(p12dcx->aSafeCinfo); 1601 p12dcx->aSafeCinfo = NULL; 1602 } 1603 1604 if (p12dcx->decitem.type != 0 && p12dcx->decitem.der != NULL) { 1605 SECITEM_FreeItem(p12dcx->decitem.der, PR_TRUE); 1606 } 1607 if (p12dcx->decitem.friendlyName != NULL) { 1608 SECITEM_FreeItem(p12dcx->decitem.friendlyName, PR_TRUE); 1609 } 1610 1611 if (p12dcx->slot) { 1612 PK11_FreeSlot(p12dcx->slot); 1613 p12dcx->slot = NULL; 1614 } 1615 1616 if (p12dcx->dIsOpen && p12dcx->dClose) { 1617 (*p12dcx->dClose)(p12dcx->dArg, PR_TRUE); 1618 p12dcx->dIsOpen = PR_FALSE; 1619 } 1620 1621 if (p12dcx->arena) { 1622 PORT_FreeArena(p12dcx->arena, PR_TRUE); 1623 } 1624 } 1625 1626 static SECStatus 1627 sec_pkcs12_decoder_set_attribute_value(sec_PKCS12SafeBag *bag, 1628 SECOidTag attributeType, 1629 SECItem *attrValue) 1630 { 1631 int i = 0; 1632 SECOidData *oid; 1633 1634 if (!bag || !attrValue) { 1635 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1636 return SECFailure; 1637 } 1638 1639 oid = SECOID_FindOIDByTag(attributeType); 1640 if (!oid) { 1641 return SECFailure; 1642 } 1643 1644 if (!bag->attribs) { 1645 bag->attribs = 1646 PORT_ArenaZNewArray(bag->arena, sec_PKCS12Attribute *, 2); 1647 } else { 1648 while (bag->attribs[i]) 1649 i++; 1650 bag->attribs = PORT_ArenaGrowArray(bag->arena, bag->attribs, 1651 sec_PKCS12Attribute *, i + 1, i + 2); 1652 } 1653 1654 if (!bag->attribs) { 1655 return SECFailure; 1656 } 1657 1658 bag->attribs[i] = PORT_ArenaZNew(bag->arena, sec_PKCS12Attribute); 1659 if (!bag->attribs[i]) { 1660 return SECFailure; 1661 } 1662 1663 bag->attribs[i]->attrValue = PORT_ArenaZNewArray(bag->arena, SECItem *, 2); 1664 if (!bag->attribs[i]->attrValue) { 1665 return SECFailure; 1666 } 1667 1668 bag->attribs[i + 1] = NULL; 1669 bag->attribs[i]->attrValue[0] = attrValue; 1670 bag->attribs[i]->attrValue[1] = NULL; 1671 1672 return SECITEM_CopyItem(bag->arena, &bag->attribs[i]->attrType, &oid->oid); 1673 } 1674 1675 static SECItem * 1676 sec_pkcs12_get_attribute_value(sec_PKCS12SafeBag *bag, 1677 SECOidTag attributeType) 1678 { 1679 int i; 1680 1681 if (!bag->attribs) { 1682 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1683 return NULL; 1684 } 1685 1686 for (i = 0; bag->attribs[i] != NULL; i++) { 1687 if (SECOID_FindOIDTag(&bag->attribs[i]->attrType) == attributeType) { 1688 return bag->attribs[i]->attrValue[0]; 1689 } 1690 } 1691 return NULL; 1692 } 1693 1694 /* For now, this function will merely remove any ":" 1695 * in the nickname which the PK11 functions may have 1696 * placed there. This will keep dual certs from appearing 1697 * twice under "Your" certificates when imported onto smart 1698 * cards. Once with the name "Slot:Cert" and another with 1699 * the nickname "Slot:Slot:Cert" 1700 */ 1701 static void 1702 sec_pkcs12_sanitize_nickname(PK11SlotInfo *slot, SECItem *nick) 1703 { 1704 char *nickname; 1705 char *delimit; 1706 int delimitlen; 1707 1708 nickname = (char *)nick->data; 1709 if ((delimit = PORT_Strchr(nickname, ':')) != NULL) { 1710 char *slotName; 1711 int slotNameLen; 1712 1713 slotNameLen = delimit - nickname; 1714 slotName = PORT_NewArray(char, (slotNameLen + 1)); 1715 PORT_Assert(slotName); 1716 if (slotName == NULL) { 1717 /* What else can we do?*/ 1718 return; 1719 } 1720 PORT_Memcpy(slotName, nickname, slotNameLen); 1721 slotName[slotNameLen] = '\0'; 1722 if (PORT_Strcmp(PK11_GetTokenName(slot), slotName) == 0) { 1723 delimitlen = PORT_Strlen(delimit + 1); 1724 PORT_Memmove(nickname, delimit + 1, delimitlen + 1); 1725 nick->len = delimitlen; 1726 } 1727 PORT_Free(slotName); 1728 } 1729 } 1730 1731 static SECItem * 1732 sec_pkcs12_get_nickname(sec_PKCS12SafeBag *bag) 1733 { 1734 SECItem *src, *dest; 1735 1736 if (!bag) { 1737 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1738 return NULL; 1739 } 1740 1741 src = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_FRIENDLY_NAME); 1742 1743 /* The return value src is 16-bit Unicode characters, in big-endian format. 1744 * Check if it is NULL or empty name. 1745 */ 1746 if (!src || !src->data || src->len < 2 || (!src->data[0] && !src->data[1])) { 1747 return NULL; 1748 } 1749 1750 dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 1751 if (!dest) { 1752 goto loser; 1753 } 1754 if (!sec_pkcs12_convert_item_to_unicode(NULL, dest, src, PR_FALSE, 1755 PR_FALSE, PR_FALSE)) { 1756 goto loser; 1757 } 1758 1759 sec_pkcs12_sanitize_nickname(bag->slot, dest); 1760 1761 return dest; 1762 1763 loser: 1764 if (dest) { 1765 SECITEM_ZfreeItem(dest, PR_TRUE); 1766 } 1767 1768 bag->problem = PR_TRUE; 1769 bag->error = PORT_GetError(); 1770 return NULL; 1771 } 1772 1773 static SECStatus 1774 sec_pkcs12_set_nickname(sec_PKCS12SafeBag *bag, SECItem *name) 1775 { 1776 sec_PKCS12Attribute *attr = NULL; 1777 SECOidData *oid = SECOID_FindOIDByTag(SEC_OID_PKCS9_FRIENDLY_NAME); 1778 1779 if (!bag || !bag->arena || !name) { 1780 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1781 return SECFailure; 1782 } 1783 1784 if (!bag->attribs) { 1785 if (!oid) { 1786 goto loser; 1787 } 1788 1789 bag->attribs = 1790 PORT_ArenaZNewArray(bag->arena, sec_PKCS12Attribute *, 2); 1791 if (!bag->attribs) { 1792 goto loser; 1793 } 1794 bag->attribs[0] = PORT_ArenaZNew(bag->arena, sec_PKCS12Attribute); 1795 if (!bag->attribs[0]) { 1796 goto loser; 1797 } 1798 bag->attribs[1] = NULL; 1799 1800 attr = bag->attribs[0]; 1801 if (SECITEM_CopyItem(bag->arena, &attr->attrType, &oid->oid) != SECSuccess) { 1802 goto loser; 1803 } 1804 } else { 1805 int i; 1806 for (i = 0; bag->attribs[i]; i++) { 1807 if (SECOID_FindOIDTag(&bag->attribs[i]->attrType) == SEC_OID_PKCS9_FRIENDLY_NAME) { 1808 attr = bag->attribs[i]; 1809 break; 1810 } 1811 } 1812 if (!attr) { 1813 if (!oid) { 1814 goto loser; 1815 } 1816 bag->attribs = PORT_ArenaGrowArray(bag->arena, bag->attribs, 1817 sec_PKCS12Attribute *, i + 1, i + 2); 1818 if (!bag->attribs) { 1819 goto loser; 1820 } 1821 bag->attribs[i] = PORT_ArenaZNew(bag->arena, sec_PKCS12Attribute); 1822 if (!bag->attribs[i]) { 1823 goto loser; 1824 } 1825 bag->attribs[i + 1] = NULL; 1826 attr = bag->attribs[i]; 1827 if (SECITEM_CopyItem(bag->arena, &attr->attrType, &oid->oid) != SECSuccess) { 1828 goto loser; 1829 } 1830 } 1831 } 1832 1833 PORT_Assert(attr); 1834 if (!attr->attrValue) { 1835 attr->attrValue = PORT_ArenaZNewArray(bag->arena, SECItem *, 2); 1836 if (!attr->attrValue) { 1837 goto loser; 1838 } 1839 attr->attrValue[0] = PORT_ArenaZNew(bag->arena, SECItem); 1840 if (!attr->attrValue[0]) { 1841 goto loser; 1842 } 1843 attr->attrValue[1] = NULL; 1844 } 1845 1846 name->len = PORT_Strlen((char *)name->data); 1847 if (!sec_pkcs12_convert_item_to_unicode(bag->arena, attr->attrValue[0], 1848 name, PR_FALSE, PR_FALSE, PR_TRUE)) { 1849 goto loser; 1850 } 1851 1852 return SECSuccess; 1853 1854 loser: 1855 bag->problem = PR_TRUE; 1856 bag->error = PORT_GetError(); 1857 return SECFailure; 1858 } 1859 1860 static SECStatus 1861 sec_pkcs12_get_key_info(sec_PKCS12SafeBag *key) 1862 { 1863 int i = 0; 1864 SECKEYPrivateKeyInfo *pki = NULL; 1865 1866 if (!key) { 1867 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1868 return SECFailure; 1869 } 1870 1871 /* if the bag does *not* contain an unencrypted PrivateKeyInfo 1872 * then we cannot convert the attributes. We are propagating 1873 * attributes within the PrivateKeyInfo to the SafeBag level. 1874 */ 1875 if (SECOID_FindOIDTag(&(key->safeBagType)) != 1876 SEC_OID_PKCS12_V1_KEY_BAG_ID) { 1877 return SECSuccess; 1878 } 1879 1880 pki = key->safeBagContent.pkcs8KeyBag; 1881 1882 if (!pki || !pki->attributes) { 1883 return SECSuccess; 1884 } 1885 1886 while (pki->attributes[i]) { 1887 SECOidTag tag = SECOID_FindOIDTag(&pki->attributes[i]->attrType); 1888 1889 if (tag == SEC_OID_PKCS9_LOCAL_KEY_ID || 1890 tag == SEC_OID_PKCS9_FRIENDLY_NAME) { 1891 SECItem *attrValue = sec_pkcs12_get_attribute_value(key, tag); 1892 if (!attrValue) { 1893 if (sec_pkcs12_decoder_set_attribute_value(key, tag, 1894 pki->attributes[i]->attrValue[0]) != SECSuccess) { 1895 key->problem = PR_TRUE; 1896 key->error = PORT_GetError(); 1897 return SECFailure; 1898 } 1899 } 1900 } 1901 i++; 1902 } 1903 1904 return SECSuccess; 1905 } 1906 1907 /* retrieve the nickname for the certificate bag. first look 1908 * in the cert bag, otherwise get it from the key. 1909 */ 1910 static SECItem * 1911 sec_pkcs12_get_nickname_for_cert(sec_PKCS12SafeBag *cert, 1912 sec_PKCS12SafeBag *key) 1913 { 1914 SECItem *nickname; 1915 1916 if (!cert) { 1917 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1918 return NULL; 1919 } 1920 1921 nickname = sec_pkcs12_get_nickname(cert); 1922 if (nickname) { 1923 return nickname; 1924 } 1925 1926 if (key) { 1927 nickname = sec_pkcs12_get_nickname(key); 1928 1929 if (nickname && sec_pkcs12_set_nickname(cert, nickname) != SECSuccess) { 1930 SECITEM_ZfreeItem(nickname, PR_TRUE); 1931 return NULL; 1932 } 1933 } 1934 1935 return nickname; 1936 } 1937 1938 /* set the nickname for the certificate */ 1939 static SECStatus 1940 sec_pkcs12_set_nickname_for_cert(sec_PKCS12SafeBag *cert, 1941 sec_PKCS12SafeBag *key, 1942 SECItem *nickname) 1943 { 1944 if (!nickname || !cert) { 1945 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1946 return SECFailure; 1947 } 1948 1949 if (sec_pkcs12_set_nickname(cert, nickname) != SECSuccess) { 1950 return SECFailure; 1951 } 1952 1953 if (key) { 1954 if (sec_pkcs12_set_nickname(key, nickname) != SECSuccess) { 1955 cert->problem = PR_TRUE; 1956 cert->error = key->error; 1957 return SECFailure; 1958 } 1959 } 1960 1961 return SECSuccess; 1962 } 1963 1964 /* retrieve the DER cert from the cert bag */ 1965 static SECItem * 1966 sec_pkcs12_get_der_cert(sec_PKCS12SafeBag *cert) 1967 { 1968 if (!cert || !cert->safeBagContent.certBag) { 1969 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1970 return NULL; 1971 } 1972 1973 if (SECOID_FindOIDTag(&cert->safeBagType) != SEC_OID_PKCS12_V1_CERT_BAG_ID) { 1974 return NULL; 1975 } 1976 1977 /* only support X509 certs not SDSI */ 1978 if (SECOID_FindOIDTag(&cert->safeBagContent.certBag->bagID) != SEC_OID_PKCS9_X509_CERT) { 1979 return NULL; 1980 } 1981 1982 return SECITEM_DupItem(&(cert->safeBagContent.certBag->value.x509Cert)); 1983 } 1984 1985 struct certNickInfo { 1986 PLArenaPool *arena; 1987 unsigned int nNicks; 1988 SECItem **nickList; 1989 unsigned int error; 1990 }; 1991 1992 /* callback for traversing certificates to gather the nicknames 1993 * used in a particular traversal. for instance, when using 1994 * CERT_TraversePermCertsForSubject, gather the nicknames and 1995 * store them in the certNickInfo for a particular DN. 1996 * 1997 * this handles the case where multiple nicknames are allowed 1998 * for the same dn, which is not currently allowed, but may be 1999 * in the future. 2000 */ 2001 static SECStatus 2002 gatherNicknames(CERTCertificate *cert, void *arg) 2003 { 2004 struct certNickInfo *nickArg = (struct certNickInfo *)arg; 2005 SECItem tempNick; 2006 unsigned int i; 2007 2008 if (!cert || !nickArg || nickArg->error) { 2009 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2010 return SECFailure; 2011 } 2012 2013 if (!cert->nickname) { 2014 return SECSuccess; 2015 } 2016 2017 tempNick.data = (unsigned char *)cert->nickname; 2018 tempNick.len = PORT_Strlen(cert->nickname) + 1; 2019 tempNick.type = siAsciiString; 2020 2021 /* do we already have the nickname in the list? */ 2022 if (nickArg->nNicks > 0) { 2023 2024 /* nicknames have been encountered, but there is no list -- bad */ 2025 if (!nickArg->nickList) { 2026 nickArg->error = SEC_ERROR_INVALID_ARGS; 2027 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2028 return SECFailure; 2029 } 2030 2031 for (i = 0; i < nickArg->nNicks; i++) { 2032 if (SECITEM_CompareItem(nickArg->nickList[i], &tempNick) == SECEqual) { 2033 return SECSuccess; 2034 } 2035 } 2036 } 2037 2038 /* add the nickname to the list */ 2039 nickArg->nickList = (nickArg->nNicks == 0) 2040 ? PORT_ArenaZNewArray(nickArg->arena, SECItem *, 2) 2041 : PORT_ArenaGrowArray(nickArg->arena, nickArg->nickList, SECItem *, 2042 nickArg->nNicks + 1, nickArg->nNicks + 2); 2043 2044 if (!nickArg->nickList) { 2045 nickArg->error = SEC_ERROR_NO_MEMORY; 2046 return SECFailure; 2047 } 2048 2049 nickArg->nickList[nickArg->nNicks] = 2050 PORT_ArenaZNew(nickArg->arena, SECItem); 2051 if (!nickArg->nickList[nickArg->nNicks]) { 2052 nickArg->error = PORT_GetError(); 2053 return SECFailure; 2054 } 2055 2056 if (SECITEM_CopyItem(nickArg->arena, nickArg->nickList[nickArg->nNicks], 2057 &tempNick) != SECSuccess) { 2058 nickArg->error = PORT_GetError(); 2059 return SECFailure; 2060 } 2061 2062 nickArg->nNicks++; 2063 2064 return SECSuccess; 2065 } 2066 2067 /* traverses the certs in the data base or in the token for the 2068 * DN to see if any certs currently have a nickname set. 2069 * If so, return it. 2070 */ 2071 static SECItem * 2072 sec_pkcs12_get_existing_nick_for_dn(sec_PKCS12SafeBag *cert) 2073 { 2074 struct certNickInfo *nickArg = NULL; 2075 SECItem *derCert, *returnDn = NULL; 2076 PLArenaPool *arena = NULL; 2077 CERTCertificate *tempCert; 2078 2079 if (!cert) { 2080 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2081 return NULL; 2082 } 2083 2084 derCert = sec_pkcs12_get_der_cert(cert); 2085 if (!derCert) { 2086 return NULL; 2087 } 2088 2089 tempCert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); 2090 if (!tempCert) { 2091 returnDn = NULL; 2092 goto loser; 2093 } 2094 2095 arena = PORT_NewArena(1024); 2096 if (!arena) { 2097 returnDn = NULL; 2098 goto loser; 2099 } 2100 nickArg = PORT_ArenaZNew(arena, struct certNickInfo); 2101 if (!nickArg) { 2102 returnDn = NULL; 2103 goto loser; 2104 } 2105 nickArg->error = 0; 2106 nickArg->nNicks = 0; 2107 nickArg->nickList = NULL; 2108 nickArg->arena = arena; 2109 2110 /* if the token is local, first traverse the cert database 2111 * then traverse the token. 2112 */ 2113 if (PK11_TraverseCertsForSubjectInSlot(tempCert, cert->slot, gatherNicknames, 2114 (void *)nickArg) != SECSuccess) { 2115 returnDn = NULL; 2116 goto loser; 2117 } 2118 2119 if (nickArg->error) { 2120 /* XXX do we want to set the error? */ 2121 returnDn = NULL; 2122 goto loser; 2123 } 2124 2125 if (nickArg->nNicks == 0) { 2126 returnDn = NULL; 2127 goto loser; 2128 } 2129 2130 /* set it to the first name, for now. handle multiple names? */ 2131 returnDn = SECITEM_DupItem(nickArg->nickList[0]); 2132 2133 loser: 2134 if (arena) { 2135 PORT_FreeArena(arena, PR_TRUE); 2136 } 2137 2138 if (tempCert) { 2139 CERT_DestroyCertificate(tempCert); 2140 } 2141 2142 if (derCert) { 2143 SECITEM_FreeItem(derCert, PR_TRUE); 2144 } 2145 2146 return (returnDn); 2147 } 2148 2149 /* counts certificates found for a given traversal function */ 2150 static SECStatus 2151 countCertificate(CERTCertificate *cert, void *arg) 2152 { 2153 unsigned int *nCerts = (unsigned int *)arg; 2154 2155 if (!cert || !arg) { 2156 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2157 return SECFailure; 2158 } 2159 2160 (*nCerts)++; 2161 return SECSuccess; 2162 } 2163 2164 static PRBool 2165 sec_pkcs12_certs_for_nickname_exist(SECItem *nickname, PK11SlotInfo *slot) 2166 { 2167 unsigned int nCerts = 0; 2168 2169 if (!nickname || !slot) { 2170 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2171 return PR_TRUE; 2172 } 2173 2174 /* we want to check the local database first if we are importing to it */ 2175 PK11_TraverseCertsForNicknameInSlot(nickname, slot, countCertificate, 2176 (void *)&nCerts); 2177 return (PRBool)(nCerts != 0); 2178 } 2179 2180 /* validate cert nickname such that there is a one-to-one relation 2181 * between nicknames and dn's. we want to enforce the case that the 2182 * nickname is non-NULL and that there is only one nickname per DN. 2183 * 2184 * if there is a problem with a nickname or the nickname is not present, 2185 * the user will be prompted for it. 2186 */ 2187 static void 2188 sec_pkcs12_validate_cert_nickname(sec_PKCS12SafeBag *cert, 2189 sec_PKCS12SafeBag *key, 2190 SEC_PKCS12NicknameCollisionCallback nicknameCb, 2191 CERTCertificate *leafCert) 2192 { 2193 SECItem *certNickname, *existingDNNick; 2194 PRBool setNickname = PR_FALSE, cancel = PR_FALSE; 2195 SECItem *newNickname = NULL; 2196 2197 if (!cert || !cert->hasKey) { 2198 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2199 return; 2200 } 2201 2202 if (!nicknameCb) { 2203 cert->problem = PR_TRUE; 2204 cert->error = SEC_ERROR_INVALID_ARGS; 2205 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2206 return; 2207 } 2208 2209 if (cert->hasKey && !key) { 2210 cert->problem = PR_TRUE; 2211 cert->error = SEC_ERROR_INVALID_ARGS; 2212 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2213 return; 2214 } 2215 2216 certNickname = sec_pkcs12_get_nickname_for_cert(cert, key); 2217 existingDNNick = sec_pkcs12_get_existing_nick_for_dn(cert); 2218 2219 /* nickname is already used w/ this dn, so it is safe to return */ 2220 if (certNickname && existingDNNick && 2221 SECITEM_CompareItem(certNickname, existingDNNick) == SECEqual) { 2222 goto loser; 2223 } 2224 2225 /* nickname not set in pkcs 12 bags, but a nick is already used for 2226 * this dn. set the nicks in the p12 bags and finish. 2227 */ 2228 if (existingDNNick) { 2229 sec_pkcs12_set_nickname_for_cert(cert, key, existingDNNick); 2230 goto loser; 2231 } 2232 2233 /* at this point, we have a certificate for which the DN is not located 2234 * on the token. the nickname specified may or may not be NULL. if it 2235 * is not null, we need to make sure that there are no other certificates 2236 * with this nickname in the token for it to be valid. this imposes a 2237 * one to one relationship between DN and nickname. 2238 * 2239 * if the nickname is null, we need the user to enter a nickname for 2240 * the certificate. 2241 * 2242 * once we have a nickname, we make sure that the nickname is unique 2243 * for the DN. if it is not, the user is reprompted to enter a new 2244 * nickname. 2245 * 2246 * in order to exit this loop, the nickname entered is either unique 2247 * or the user hits cancel and the certificate is not imported. 2248 */ 2249 setNickname = PR_FALSE; 2250 while (1) { 2251 /* we will use the nickname so long as no other certs have the 2252 * same nickname. and the nickname is not NULL. 2253 */ 2254 if (certNickname && certNickname->data && 2255 !sec_pkcs12_certs_for_nickname_exist(certNickname, cert->slot)) { 2256 if (setNickname) { 2257 sec_pkcs12_set_nickname_for_cert(cert, key, certNickname); 2258 } 2259 break; 2260 } 2261 2262 setNickname = PR_FALSE; 2263 newNickname = (*nicknameCb)(certNickname, &cancel, leafCert); 2264 if (cancel) { 2265 cert->problem = PR_TRUE; 2266 cert->error = SEC_ERROR_USER_CANCELLED; 2267 break; 2268 } 2269 2270 if (!newNickname) { 2271 cert->problem = PR_TRUE; 2272 cert->error = PORT_GetError(); 2273 break; 2274 } 2275 2276 /* at this point we have a new nickname, if we have an existing 2277 * certNickname, we need to free it and assign the new nickname 2278 * to it to avoid a memory leak. happy? 2279 */ 2280 if (certNickname) { 2281 SECITEM_ZfreeItem(certNickname, PR_TRUE); 2282 certNickname = NULL; 2283 } 2284 2285 certNickname = newNickname; 2286 setNickname = PR_TRUE; 2287 /* go back and recheck the new nickname */ 2288 } 2289 2290 loser: 2291 if (certNickname) { 2292 SECITEM_ZfreeItem(certNickname, PR_TRUE); 2293 } 2294 2295 if (existingDNNick) { 2296 SECITEM_ZfreeItem(existingDNNick, PR_TRUE); 2297 } 2298 } 2299 2300 static void 2301 sec_pkcs12_validate_cert(sec_PKCS12SafeBag *cert, 2302 sec_PKCS12SafeBag *key, 2303 SEC_PKCS12NicknameCollisionCallback nicknameCb) 2304 { 2305 CERTCertificate *leafCert; 2306 2307 if (!cert) { 2308 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2309 return; 2310 } 2311 2312 cert->validated = PR_TRUE; 2313 2314 if (!nicknameCb) { 2315 cert->noInstall = PR_TRUE; 2316 cert->problem = PR_TRUE; 2317 cert->error = SEC_ERROR_INVALID_ARGS; 2318 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2319 return; 2320 } 2321 2322 if (!cert->safeBagContent.certBag) { 2323 cert->noInstall = PR_TRUE; 2324 cert->problem = PR_TRUE; 2325 cert->error = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; 2326 return; 2327 } 2328 2329 cert->noInstall = PR_FALSE; 2330 cert->unused = PR_FALSE; 2331 cert->problem = PR_FALSE; 2332 cert->error = 0; 2333 2334 leafCert = CERT_DecodeDERCertificate( 2335 &cert->safeBagContent.certBag->value.x509Cert, PR_FALSE, NULL); 2336 if (!leafCert) { 2337 cert->noInstall = PR_TRUE; 2338 cert->problem = PR_TRUE; 2339 cert->error = PORT_GetError(); 2340 return; 2341 } 2342 2343 sec_pkcs12_validate_cert_nickname(cert, key, nicknameCb, leafCert); 2344 2345 CERT_DestroyCertificate(leafCert); 2346 } 2347 2348 static void 2349 sec_pkcs12_validate_key_by_cert(sec_PKCS12SafeBag *cert, sec_PKCS12SafeBag *key, 2350 void *wincx) 2351 { 2352 CERTCertificate *leafCert; 2353 SECKEYPrivateKey *privk; 2354 2355 if (!key) { 2356 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2357 return; 2358 } 2359 2360 key->validated = PR_TRUE; 2361 2362 if (!cert) { 2363 key->problem = PR_TRUE; 2364 key->noInstall = PR_TRUE; 2365 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; 2366 return; 2367 } 2368 2369 leafCert = CERT_DecodeDERCertificate( 2370 &(cert->safeBagContent.certBag->value.x509Cert), PR_FALSE, NULL); 2371 if (!leafCert) { 2372 key->problem = PR_TRUE; 2373 key->noInstall = PR_TRUE; 2374 key->error = PORT_GetError(); 2375 return; 2376 } 2377 2378 privk = PK11_FindPrivateKeyFromCert(key->slot, leafCert, wincx); 2379 if (!privk) { 2380 privk = PK11_FindKeyByDERCert(key->slot, leafCert, wincx); 2381 } 2382 2383 if (privk) { 2384 SECKEY_DestroyPrivateKey(privk); 2385 key->noInstall = PR_TRUE; 2386 } 2387 2388 CERT_DestroyCertificate(leafCert); 2389 } 2390 2391 static SECStatus 2392 sec_pkcs12_add_cert(sec_PKCS12SafeBag *cert, PRBool keyExists, void *wincx) 2393 { 2394 SECItem *derCert, *nickName; 2395 char *nickData = NULL; 2396 PRBool isIntermediateCA; 2397 SECStatus rv; 2398 2399 if (!cert) { 2400 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2401 return SECFailure; 2402 } 2403 2404 if (cert->problem || cert->noInstall || cert->installed) { 2405 return SECSuccess; 2406 } 2407 2408 derCert = &cert->safeBagContent.certBag->value.x509Cert; 2409 2410 PORT_Assert(!cert->problem && !cert->noInstall); 2411 2412 nickName = sec_pkcs12_get_nickname(cert); 2413 if (nickName) { 2414 nickData = (char *)nickName->data; 2415 } 2416 2417 isIntermediateCA = CERT_IsCADERCert(derCert, NULL) && 2418 !CERT_IsRootDERCert(derCert); 2419 2420 if (keyExists) { 2421 CERTCertificate *newCert; 2422 2423 newCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 2424 derCert, NULL, PR_FALSE, PR_FALSE); 2425 if (!newCert) { 2426 if (nickName) 2427 SECITEM_ZfreeItem(nickName, PR_TRUE); 2428 cert->error = PORT_GetError(); 2429 cert->problem = PR_TRUE; 2430 return SECFailure; 2431 } 2432 2433 rv = PK11_ImportCertForKeyToSlot(cert->slot, newCert, nickData, 2434 PR_TRUE, wincx); 2435 CERT_DestroyCertificate(newCert); 2436 } else if ((cert->tokenCAs == SECPKCS12TargetTokenNoCAs) || 2437 ((cert->tokenCAs == SECPKCS12TargetTokenIntermediateCAs) && 2438 !isIntermediateCA)) { 2439 SECItem *certList[2]; 2440 certList[0] = derCert; 2441 certList[1] = NULL; 2442 2443 rv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageUserCertImport, 2444 1, certList, NULL, PR_TRUE, PR_FALSE, nickData); 2445 } else { 2446 rv = PK11_ImportDERCert(cert->slot, derCert, CK_INVALID_HANDLE, 2447 nickData, PR_FALSE); 2448 } 2449 if (rv) { 2450 cert->problem = 1; 2451 cert->error = PORT_GetError(); 2452 } 2453 cert->installed = PR_TRUE; 2454 if (nickName) 2455 SECITEM_ZfreeItem(nickName, PR_TRUE); 2456 return rv; 2457 } 2458 2459 static const SECItem * 2460 sec_pkcs12_get_public_value_and_type(const SECKEYPublicKey *pubKey, 2461 KeyType *type); 2462 2463 static SECStatus 2464 sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECKEYPublicKey *pubKey, 2465 unsigned int keyUsage, 2466 SECItem *nickName, PRBool forceUnicode, void *wincx) 2467 { 2468 SECStatus rv; 2469 const SECItem *publicValue = NULL; 2470 KeyType keyType; 2471 2472 /* We should always have values for "key" and "pubKey" 2473 so they can be dereferenced later. */ 2474 if (!key || !pubKey) { 2475 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2476 return SECFailure; 2477 } 2478 2479 if (key->problem || key->noInstall) { 2480 return SECSuccess; 2481 } 2482 2483 /* get the value and type from the public key */ 2484 publicValue = sec_pkcs12_get_public_value_and_type(pubKey, &keyType); 2485 if (!publicValue) { 2486 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; 2487 key->problem = PR_TRUE; 2488 return SECFailure; 2489 } 2490 2491 switch (SECOID_FindOIDTag(&key->safeBagType)) { 2492 case SEC_OID_PKCS12_V1_KEY_BAG_ID: 2493 rv = PK11_ImportPrivateKeyInfo(key->slot, 2494 key->safeBagContent.pkcs8KeyBag, 2495 nickName, publicValue, PR_TRUE, PR_TRUE, 2496 keyUsage, wincx); 2497 break; 2498 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: { 2499 SECItem pwitem = { 0 }; 2500 SECAlgorithmID *algid = 2501 &key->safeBagContent.pkcs8ShroudedKeyBag->algorithm; 2502 SECOidTag algorithm = SECOID_GetAlgorithmTag(algid); 2503 2504 if (!SEC_PKCS12DecryptionAllowed(algid)) { 2505 key->error = SEC_ERROR_BAD_EXPORT_ALGORITHM; 2506 key->problem = PR_TRUE; 2507 return SECFailure; 2508 } 2509 2510 if (forceUnicode) { 2511 if (SECITEM_CopyItem(NULL, &pwitem, key->pwitem) != SECSuccess) { 2512 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; 2513 key->problem = PR_TRUE; 2514 return SECFailure; 2515 } 2516 } else { 2517 if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm, 2518 key->pwitem)) { 2519 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; 2520 key->problem = PR_TRUE; 2521 return SECFailure; 2522 } 2523 } 2524 2525 rv = PK11_ImportEncryptedPrivateKeyInfo(key->slot, 2526 key->safeBagContent.pkcs8ShroudedKeyBag, 2527 &pwitem, nickName, publicValue, 2528 PR_TRUE, PR_TRUE, keyType, keyUsage, 2529 wincx); 2530 if (pwitem.data) { 2531 SECITEM_ZfreeItem(&pwitem, PR_FALSE); 2532 } 2533 break; 2534 } 2535 default: 2536 key->error = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION; 2537 key->problem = PR_TRUE; 2538 if (nickName) { 2539 SECITEM_ZfreeItem(nickName, PR_TRUE); 2540 } 2541 return SECFailure; 2542 } 2543 2544 if (rv != SECSuccess) { 2545 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; 2546 key->problem = PR_TRUE; 2547 } else { 2548 /* try to import the public key. Failure to do so is not fatal, 2549 * not all tokens can store the public key */ 2550 if (pubKey) { 2551 PK11_ImportPublicKey(key->slot, pubKey, PR_TRUE); 2552 } 2553 key->installed = PR_TRUE; 2554 } 2555 2556 return rv; 2557 } 2558 2559 /* 2560 * The correctness of the code in this file ABSOLUTELY REQUIRES 2561 * that ALL BAGs share a single common arena. 2562 * 2563 * This function allocates the bag list from the arena of whatever bag 2564 * happens to be passed to it. Each time a new bag is handed to it, 2565 * it grows (resizes) the arena of the bag that was handed to it. 2566 * If the bags have different arenas, it will grow the wrong arena. 2567 * 2568 * Worse, if the bags had separate arenas, then while destroying the bags 2569 * in a bag list, when the bag whose arena contained the bag list was 2570 * destroyed, the baglist itself would be destroyed, making it difficult 2571 * or impossible to continue to destroy the bags in the destroyed list. 2572 */ 2573 static SECStatus 2574 sec_pkcs12_add_item_to_bag_list(sec_PKCS12SafeBag ***bagList, 2575 sec_PKCS12SafeBag *bag) 2576 { 2577 sec_PKCS12SafeBag **newBagList = NULL; 2578 int i = 0; 2579 2580 if (!bagList || !bag) { 2581 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2582 return SECFailure; 2583 } 2584 2585 if (!(*bagList)) { 2586 newBagList = PORT_ArenaZNewArray(bag->arena, sec_PKCS12SafeBag *, 2); 2587 } else { 2588 while ((*bagList)[i]) 2589 i++; 2590 newBagList = PORT_ArenaGrowArray(bag->arena, *bagList, 2591 sec_PKCS12SafeBag *, i + 1, i + 2); 2592 } 2593 2594 if (!newBagList) { 2595 PORT_SetError(SEC_ERROR_NO_MEMORY); 2596 return SECFailure; 2597 } 2598 2599 newBagList[i] = bag; 2600 newBagList[i + 1] = NULL; 2601 *bagList = newBagList; 2602 2603 return SECSuccess; 2604 } 2605 2606 static sec_PKCS12SafeBag ** 2607 sec_pkcs12_find_certs_for_key(sec_PKCS12SafeBag **safeBags, 2608 sec_PKCS12SafeBag *key) 2609 { 2610 sec_PKCS12SafeBag **certList = NULL; 2611 SECItem *keyId; 2612 int i; 2613 2614 if (!safeBags || !safeBags[0]) { 2615 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2616 return NULL; 2617 } 2618 2619 keyId = sec_pkcs12_get_attribute_value(key, SEC_OID_PKCS9_LOCAL_KEY_ID); 2620 if (!keyId) { 2621 return NULL; 2622 } 2623 2624 for (i = 0; safeBags[i]; i++) { 2625 if (SECOID_FindOIDTag(&(safeBags[i]->safeBagType)) == SEC_OID_PKCS12_V1_CERT_BAG_ID) { 2626 SECItem *certKeyId = sec_pkcs12_get_attribute_value(safeBags[i], 2627 SEC_OID_PKCS9_LOCAL_KEY_ID); 2628 2629 if (certKeyId && (SECITEM_CompareItem(certKeyId, keyId) == SECEqual)) { 2630 if (sec_pkcs12_add_item_to_bag_list(&certList, safeBags[i]) != SECSuccess) { 2631 /* This would leak the partial list of safeBags, 2632 * but that list is allocated from the arena of 2633 * one of the safebags, and will be destroyed when 2634 * that arena is destroyed. So this is not a real leak. 2635 */ 2636 return NULL; 2637 } 2638 } 2639 } 2640 } 2641 2642 return certList; 2643 } 2644 2645 CERTCertList * 2646 SEC_PKCS12DecoderGetCerts(SEC_PKCS12DecoderContext *p12dcx) 2647 { 2648 CERTCertList *certList = NULL; 2649 sec_PKCS12SafeBag **safeBags; 2650 int i; 2651 2652 if (!p12dcx || !p12dcx->safeBags || !p12dcx->safeBags[0]) { 2653 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2654 return NULL; 2655 } 2656 2657 safeBags = p12dcx->safeBags; 2658 certList = CERT_NewCertList(); 2659 2660 if (certList == NULL) { 2661 return NULL; 2662 } 2663 2664 for (i = 0; safeBags[i]; i++) { 2665 if (SECOID_FindOIDTag(&(safeBags[i]->safeBagType)) == SEC_OID_PKCS12_V1_CERT_BAG_ID) { 2666 SECItem *derCert = sec_pkcs12_get_der_cert(safeBags[i]); 2667 CERTCertificate *tempCert = NULL; 2668 2669 if (derCert == NULL) 2670 continue; 2671 tempCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 2672 derCert, NULL, 2673 PR_FALSE, PR_TRUE); 2674 2675 if (tempCert) { 2676 CERT_AddCertToListTail(certList, tempCert); 2677 } 2678 SECITEM_FreeItem(derCert, PR_TRUE); 2679 } 2680 /* fixed an infinite loop here, by ensuring that i gets incremented 2681 * if derCert is NULL above. 2682 */ 2683 } 2684 2685 return certList; 2686 } 2687 static sec_PKCS12SafeBag ** 2688 sec_pkcs12_get_key_bags(sec_PKCS12SafeBag **safeBags) 2689 { 2690 int i; 2691 sec_PKCS12SafeBag **keyList = NULL; 2692 SECOidTag bagType; 2693 2694 if (!safeBags || !safeBags[0]) { 2695 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2696 return NULL; 2697 } 2698 2699 for (i = 0; safeBags[i]; i++) { 2700 bagType = SECOID_FindOIDTag(&(safeBags[i]->safeBagType)); 2701 switch (bagType) { 2702 case SEC_OID_PKCS12_V1_KEY_BAG_ID: 2703 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: 2704 if (sec_pkcs12_add_item_to_bag_list(&keyList, safeBags[i]) != SECSuccess) { 2705 /* This would leak, except that keyList is allocated 2706 * from the arena shared by all the safeBags. 2707 */ 2708 return NULL; 2709 } 2710 break; 2711 default: 2712 break; 2713 } 2714 } 2715 2716 return keyList; 2717 } 2718 2719 /* This function takes two passes over the bags, validating them 2720 * The two passes are intended to mirror exactly the two passes in 2721 * sec_pkcs12_install_bags. But they don't. :( 2722 */ 2723 static SECStatus 2724 sec_pkcs12_validate_bags(sec_PKCS12SafeBag **safeBags, 2725 SEC_PKCS12NicknameCollisionCallback nicknameCb, 2726 void *wincx) 2727 { 2728 sec_PKCS12SafeBag **keyList; 2729 int i; 2730 2731 if (!safeBags || !nicknameCb) { 2732 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2733 return SECFailure; 2734 } 2735 2736 if (!safeBags[0]) { 2737 return SECSuccess; 2738 } 2739 2740 /* First pass. Find all the key bags. 2741 * Find the matching cert(s) for each key. 2742 */ 2743 keyList = sec_pkcs12_get_key_bags(safeBags); 2744 if (keyList) { 2745 for (i = 0; keyList[i]; ++i) { 2746 sec_PKCS12SafeBag *key = keyList[i]; 2747 sec_PKCS12SafeBag **certList = 2748 sec_pkcs12_find_certs_for_key(safeBags, key); 2749 2750 if (certList) { 2751 int j; 2752 2753 if (SECOID_FindOIDTag(&(key->safeBagType)) == 2754 SEC_OID_PKCS12_V1_KEY_BAG_ID) { 2755 /* if it is an unencrypted private key then make sure 2756 * the attributes are propageted to the appropriate 2757 * level 2758 */ 2759 if (sec_pkcs12_get_key_info(key) != SECSuccess) { 2760 return SECFailure; 2761 } 2762 } 2763 2764 sec_pkcs12_validate_key_by_cert(certList[0], key, wincx); 2765 for (j = 0; certList[j]; ++j) { 2766 sec_PKCS12SafeBag *cert = certList[j]; 2767 cert->hasKey = PR_TRUE; 2768 if (key->problem) { 2769 cert->problem = PR_TRUE; 2770 cert->error = key->error; 2771 continue; 2772 } 2773 sec_pkcs12_validate_cert(cert, key, nicknameCb); 2774 if (cert->problem) { 2775 key->problem = cert->problem; 2776 key->error = cert->error; 2777 } 2778 } 2779 } 2780 } 2781 } 2782 2783 /* Now take a second pass over the safebags and mark for installation any 2784 * certs that were neither installed nor disqualified by the first pass. 2785 */ 2786 for (i = 0; safeBags[i]; ++i) { 2787 sec_PKCS12SafeBag *bag = safeBags[i]; 2788 2789 if (!bag->validated) { 2790 SECOidTag bagType = SECOID_FindOIDTag(&bag->safeBagType); 2791 2792 switch (bagType) { 2793 case SEC_OID_PKCS12_V1_CERT_BAG_ID: 2794 sec_pkcs12_validate_cert(bag, NULL, nicknameCb); 2795 break; 2796 case SEC_OID_PKCS12_V1_KEY_BAG_ID: 2797 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: 2798 bag->noInstall = PR_TRUE; 2799 bag->problem = PR_TRUE; 2800 bag->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; 2801 break; 2802 default: 2803 bag->noInstall = PR_TRUE; 2804 } 2805 } 2806 } 2807 2808 return SECSuccess; 2809 } 2810 2811 SECStatus 2812 SEC_PKCS12DecoderValidateBags(SEC_PKCS12DecoderContext *p12dcx, 2813 SEC_PKCS12NicknameCollisionCallback nicknameCb) 2814 { 2815 SECStatus rv; 2816 int i, probCnt, errorVal = 0; 2817 if (!p12dcx || p12dcx->error || !p12dcx->safeBags) { 2818 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2819 return SECFailure; 2820 } 2821 2822 rv = sec_pkcs12_validate_bags(p12dcx->safeBags, nicknameCb, p12dcx->wincx); 2823 if (rv == SECSuccess) { 2824 p12dcx->bagsVerified = PR_TRUE; 2825 } 2826 2827 probCnt = 0; 2828 i = 0; 2829 while (p12dcx->safeBags[i]) { 2830 if (p12dcx->safeBags[i]->problem) { 2831 probCnt++; 2832 errorVal = p12dcx->safeBags[i]->error; 2833 } 2834 i++; 2835 } 2836 2837 if (probCnt) { 2838 PORT_SetError(errorVal); 2839 return SECFailure; 2840 } 2841 2842 return rv; 2843 } 2844 2845 SECStatus 2846 SEC_PKCS12DecoderRenameCertNicknames(SEC_PKCS12DecoderContext *p12dcx, 2847 SEC_PKCS12NicknameRenameCallback nicknameCb, 2848 void *arg) 2849 { 2850 int i; 2851 sec_PKCS12SafeBag *safeBag; 2852 CERTCertificate *cert; 2853 SECStatus srv; 2854 2855 if (!p12dcx || p12dcx->error || !p12dcx->safeBags || !nicknameCb) { 2856 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2857 return SECFailure; 2858 } 2859 2860 for (i = 0; (safeBag = p12dcx->safeBags[i]); i++) { 2861 SECItem *newNickname = NULL; 2862 SECItem *defaultNickname = NULL; 2863 SECStatus rename_rv; 2864 2865 if (SECOID_FindOIDTag(&(safeBag->safeBagType)) != 2866 SEC_OID_PKCS12_V1_CERT_BAG_ID) { 2867 continue; 2868 } 2869 2870 cert = CERT_DecodeDERCertificate( 2871 &safeBag->safeBagContent.certBag->value.x509Cert, 2872 PR_FALSE, NULL); 2873 if (!cert) { 2874 return SECFailure; 2875 } 2876 2877 defaultNickname = sec_pkcs12_get_nickname(safeBag); 2878 rename_rv = (*nicknameCb)(cert, defaultNickname, &newNickname, arg); 2879 2880 CERT_DestroyCertificate(cert); 2881 2882 if (defaultNickname) { 2883 SECITEM_ZfreeItem(defaultNickname, PR_TRUE); 2884 defaultNickname = NULL; 2885 } 2886 2887 if (rename_rv != SECSuccess) { 2888 return rename_rv; 2889 } 2890 2891 if (newNickname) { 2892 srv = sec_pkcs12_set_nickname(safeBag, newNickname); 2893 SECITEM_ZfreeItem(newNickname, PR_TRUE); 2894 newNickname = NULL; 2895 if (srv != SECSuccess) { 2896 return SECFailure; 2897 } 2898 } 2899 } 2900 2901 return SECSuccess; 2902 } 2903 2904 static SECKEYPublicKey * 2905 sec_pkcs12_get_public_key_and_usage(sec_PKCS12SafeBag *certBag, 2906 unsigned int *usage) 2907 { 2908 SECKEYPublicKey *pubKey = NULL; 2909 CERTCertificate *cert = NULL; 2910 2911 if (!certBag || !usage) { 2912 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2913 return NULL; 2914 } 2915 2916 *usage = 0; 2917 2918 cert = CERT_DecodeDERCertificate( 2919 &certBag->safeBagContent.certBag->value.x509Cert, PR_FALSE, NULL); 2920 if (!cert) { 2921 return NULL; 2922 } 2923 2924 *usage = cert->keyUsage; 2925 pubKey = CERT_ExtractPublicKey(cert); 2926 CERT_DestroyCertificate(cert); 2927 return pubKey; 2928 } 2929 2930 static const SECItem * 2931 sec_pkcs12_get_public_value_and_type(const SECKEYPublicKey *pubKey, 2932 KeyType *type) 2933 { 2934 2935 if (!type || !pubKey) { 2936 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2937 return NULL; 2938 } 2939 2940 *type = pubKey->keyType; 2941 return PK11_GetPublicValueFromPublicKey(pubKey); 2942 } 2943 2944 /* This function takes two passes over the bags, installing them in the 2945 * desired slot. The two passes are intended to mirror exactly the 2946 * two passes in sec_pkcs12_validate_bags. 2947 */ 2948 static SECStatus 2949 sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, PRBool forceUnicode, 2950 void *wincx) 2951 { 2952 sec_PKCS12SafeBag **keyList; 2953 int i; 2954 int failedKeys = 0; 2955 2956 if (!safeBags) { 2957 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2958 return SECFailure; 2959 } 2960 2961 if (!safeBags[0]) { 2962 return SECSuccess; 2963 } 2964 2965 /* First pass. Find all the key bags. 2966 * Try to install them, and any certs associated with them. 2967 */ 2968 keyList = sec_pkcs12_get_key_bags(safeBags); 2969 if (keyList) { 2970 for (i = 0; keyList[i]; i++) { 2971 SECStatus rv; 2972 SECKEYPublicKey *pubKey = NULL; 2973 SECItem *nickName = NULL; 2974 sec_PKCS12SafeBag *key = keyList[i]; 2975 sec_PKCS12SafeBag **certList; 2976 unsigned int keyUsage; 2977 2978 if (key->problem) { 2979 ++failedKeys; 2980 continue; 2981 } 2982 2983 certList = sec_pkcs12_find_certs_for_key(safeBags, key); 2984 if (certList && certList[0]) { 2985 pubKey = sec_pkcs12_get_public_key_and_usage(certList[0], 2986 &keyUsage); 2987 /* use the cert's nickname, if it has one, else use the 2988 * key's nickname, else fail. 2989 */ 2990 nickName = sec_pkcs12_get_nickname_for_cert(certList[0], key); 2991 } else { 2992 nickName = sec_pkcs12_get_nickname(key); 2993 } 2994 if (!nickName) { 2995 key->error = SEC_ERROR_BAD_NICKNAME; 2996 key->problem = PR_TRUE; 2997 rv = SECFailure; 2998 } else if (!pubKey) { 2999 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; 3000 key->problem = PR_TRUE; 3001 rv = SECFailure; 3002 } else { 3003 rv = sec_pkcs12_add_key(key, pubKey, keyUsage, nickName, 3004 forceUnicode, wincx); 3005 } 3006 if (pubKey) { 3007 SECKEY_DestroyPublicKey(pubKey); 3008 pubKey = NULL; 3009 } 3010 if (nickName) { 3011 SECITEM_FreeItem(nickName, PR_TRUE); 3012 nickName = NULL; 3013 } 3014 if (rv != SECSuccess) { 3015 PORT_SetError(key->error); 3016 ++failedKeys; 3017 } 3018 3019 if (certList) { 3020 int j; 3021 3022 for (j = 0; certList[j]; j++) { 3023 sec_PKCS12SafeBag *cert = certList[j]; 3024 SECStatus certRv; 3025 3026 if (!cert) 3027 continue; 3028 if (rv != SECSuccess) { 3029 cert->problem = key->problem; 3030 cert->error = key->error; 3031 cert->noInstall = PR_TRUE; 3032 continue; 3033 } 3034 3035 certRv = sec_pkcs12_add_cert(cert, cert->hasKey, wincx); 3036 if (certRv != SECSuccess) { 3037 key->problem = cert->problem; 3038 key->error = cert->error; 3039 PORT_SetError(cert->error); 3040 return SECFailure; 3041 } 3042 } 3043 } 3044 } 3045 } 3046 if (failedKeys) 3047 return SECFailure; 3048 3049 /* Now take a second pass over the safebags and install any certs 3050 * that were neither installed nor disqualified by the first pass. 3051 */ 3052 for (i = 0; safeBags[i]; i++) { 3053 sec_PKCS12SafeBag *bag = safeBags[i]; 3054 3055 if (!bag->installed && !bag->problem && !bag->noInstall) { 3056 SECStatus rv; 3057 SECOidTag bagType = SECOID_FindOIDTag(&(bag->safeBagType)); 3058 3059 switch (bagType) { 3060 case SEC_OID_PKCS12_V1_CERT_BAG_ID: 3061 rv = sec_pkcs12_add_cert(bag, bag->hasKey, wincx); 3062 if (rv != SECSuccess) { 3063 PORT_SetError(bag->error); 3064 return SECFailure; 3065 } 3066 break; 3067 case SEC_OID_PKCS12_V1_KEY_BAG_ID: 3068 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: 3069 default: 3070 break; 3071 } 3072 } 3073 } 3074 3075 return SECSuccess; 3076 } 3077 3078 SECStatus 3079 SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx) 3080 { 3081 PRBool forceUnicode = PR_FALSE; 3082 SECStatus rv; 3083 3084 if (!p12dcx || p12dcx->error) { 3085 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3086 return SECFailure; 3087 } 3088 3089 if (!p12dcx->bagsVerified) { 3090 return SECFailure; 3091 } 3092 3093 /* We need to check the option here as well as in 3094 * SEC_PKCS12DecoderStart, because different PBE's could be used 3095 * for PKCS #7 and PKCS #8 */ 3096 rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode); 3097 if (rv != SECSuccess) { 3098 return SECFailure; 3099 } 3100 3101 return sec_pkcs12_install_bags(p12dcx->safeBags, forceUnicode, 3102 p12dcx->wincx); 3103 } 3104 3105 PRBool 3106 sec_pkcs12_bagHasKey(SEC_PKCS12DecoderContext *p12dcx, sec_PKCS12SafeBag *bag) 3107 { 3108 int i; 3109 SECItem *keyId; 3110 SECItem *certKeyId; 3111 3112 certKeyId = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_LOCAL_KEY_ID); 3113 if (certKeyId == NULL) { 3114 return PR_FALSE; 3115 } 3116 3117 for (i = 0; p12dcx->keyList && p12dcx->keyList[i]; i++) { 3118 keyId = sec_pkcs12_get_attribute_value(p12dcx->keyList[i], 3119 SEC_OID_PKCS9_LOCAL_KEY_ID); 3120 if (!keyId) { 3121 continue; 3122 } 3123 if (SECITEM_CompareItem(certKeyId, keyId) == SECEqual) { 3124 return PR_TRUE; 3125 } 3126 } 3127 return PR_FALSE; 3128 } 3129 3130 SECItem * 3131 sec_pkcs12_get_friendlyName(sec_PKCS12SafeBag *bag) 3132 { 3133 SECItem *friendlyName; 3134 SECItem *tempnm; 3135 3136 tempnm = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_FRIENDLY_NAME); 3137 friendlyName = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 3138 if (friendlyName) { 3139 if (!sec_pkcs12_convert_item_to_unicode(NULL, friendlyName, 3140 tempnm, PR_TRUE, PR_FALSE, PR_FALSE)) { 3141 SECITEM_FreeItem(friendlyName, PR_TRUE); 3142 friendlyName = NULL; 3143 } 3144 } 3145 return friendlyName; 3146 } 3147 3148 /* Following two functions provide access to selected portions of the safe bags. 3149 * Iteration is implemented per decoder context and may be accessed after 3150 * SEC_PKCS12DecoderVerify() returns success. 3151 * When ...DecoderIterateNext() returns SUCCESS a decoder item has been returned 3152 * where item.type is always set; item.friendlyName is set if it is non-null; 3153 * item.der, item.hasKey are set only for SEC_OID_PKCS12_V1_CERT_BAG_ID items. 3154 * ...DecoderIterateNext() returns FAILURE when the list is exhausted or when 3155 * arguments are invalid; PORT_GetError() is 0 at end-of-list. 3156 * Caller has read-only access to decoder items. Any SECItems generated are 3157 * owned by the decoder context and are freed by ...DecoderFinish(). 3158 */ 3159 SECStatus 3160 SEC_PKCS12DecoderIterateInit(SEC_PKCS12DecoderContext *p12dcx) 3161 { 3162 if (!p12dcx || p12dcx->error) { 3163 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3164 return SECFailure; 3165 } 3166 3167 p12dcx->iteration = 0; 3168 return SECSuccess; 3169 } 3170 3171 SECStatus 3172 SEC_PKCS12DecoderIterateNext(SEC_PKCS12DecoderContext *p12dcx, 3173 const SEC_PKCS12DecoderItem **ipp) 3174 { 3175 sec_PKCS12SafeBag *bag; 3176 3177 if (!p12dcx || p12dcx->error) { 3178 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3179 return SECFailure; 3180 } 3181 3182 if (p12dcx->decitem.type != 0 && p12dcx->decitem.der != NULL) { 3183 SECITEM_FreeItem(p12dcx->decitem.der, PR_TRUE); 3184 } 3185 if (p12dcx->decitem.shroudAlg != NULL) { 3186 SECOID_DestroyAlgorithmID(p12dcx->decitem.shroudAlg, PR_TRUE); 3187 } 3188 if (p12dcx->decitem.friendlyName != NULL) { 3189 SECITEM_FreeItem(p12dcx->decitem.friendlyName, PR_TRUE); 3190 } 3191 p12dcx->decitem.type = 0; 3192 p12dcx->decitem.der = NULL; 3193 p12dcx->decitem.shroudAlg = NULL; 3194 p12dcx->decitem.friendlyName = NULL; 3195 p12dcx->decitem.hasKey = PR_FALSE; 3196 *ipp = NULL; 3197 if (p12dcx->keyList == NULL) { 3198 p12dcx->keyList = sec_pkcs12_get_key_bags(p12dcx->safeBags); 3199 } 3200 3201 for (; p12dcx->iteration < p12dcx->safeBagCount; p12dcx->iteration++) { 3202 bag = p12dcx->safeBags[p12dcx->iteration]; 3203 if (bag == NULL || bag->problem) { 3204 continue; 3205 } 3206 p12dcx->decitem.type = SECOID_FindOIDTag(&(bag->safeBagType)); 3207 switch (p12dcx->decitem.type) { 3208 case SEC_OID_PKCS12_V1_CERT_BAG_ID: 3209 p12dcx->decitem.der = sec_pkcs12_get_der_cert(bag); 3210 p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag); 3211 p12dcx->decitem.hasKey = sec_pkcs12_bagHasKey(p12dcx, bag); 3212 /* if we don't understand the cert, or it's not parsable, skip it */ 3213 /* as per the comment above, friendlyName may be null legitimately */ 3214 if (!p12dcx->decitem.der) { 3215 p12dcx->decitem.type = 0; /* clear out the type we are ignoring */ 3216 continue; 3217 } 3218 break; 3219 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: 3220 p12dcx->decitem.shroudAlg = PORT_ZNew(SECAlgorithmID); 3221 if (p12dcx->decitem.shroudAlg) { 3222 SECOID_CopyAlgorithmID(NULL, p12dcx->decitem.shroudAlg, 3223 &bag->safeBagContent.pkcs8ShroudedKeyBag->algorithm); 3224 } 3225 /* fall through */ 3226 case SEC_OID_PKCS12_V1_KEY_BAG_ID: 3227 p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag); 3228 break; 3229 default: 3230 /* return these even though we don't expect them */ 3231 break; 3232 case SEC_OID_UNKNOWN: 3233 /* ignore these */ 3234 p12dcx->decitem.type = 0; /* clear out the type we are ignoring */ 3235 continue; 3236 } 3237 *ipp = &p12dcx->decitem; 3238 p12dcx->iteration++; 3239 break; /* end for() */ 3240 } 3241 3242 PORT_SetError(0); /* end-of-list is SECFailure with no PORT error */ 3243 return ((p12dcx->decitem.type == 0) ? SECFailure : SECSuccess); 3244 } 3245 3246 static SECStatus 3247 sec_pkcs12_decoder_append_bag_to_context(SEC_PKCS12DecoderContext *p12dcx, 3248 sec_PKCS12SafeBag *bag) 3249 { 3250 if (!p12dcx || p12dcx->error) { 3251 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3252 return SECFailure; 3253 } 3254 3255 p12dcx->safeBags = !p12dcx->safeBagCount 3256 ? PORT_ArenaZNewArray(p12dcx->arena, sec_PKCS12SafeBag *, 2) 3257 : PORT_ArenaGrowArray(p12dcx->arena, p12dcx->safeBags, 3258 sec_PKCS12SafeBag *, p12dcx->safeBagCount + 1, 3259 p12dcx->safeBagCount + 2); 3260 3261 if (!p12dcx->safeBags) { 3262 PORT_SetError(SEC_ERROR_NO_MEMORY); 3263 return SECFailure; 3264 } 3265 3266 p12dcx->safeBags[p12dcx->safeBagCount] = bag; 3267 p12dcx->safeBags[p12dcx->safeBagCount + 1] = NULL; 3268 p12dcx->safeBagCount++; 3269 3270 return SECSuccess; 3271 } 3272 3273 static sec_PKCS12SafeBag * 3274 sec_pkcs12_decoder_convert_old_key(SEC_PKCS12DecoderContext *p12dcx, 3275 void *key, PRBool isEspvk) 3276 { 3277 sec_PKCS12SafeBag *keyBag; 3278 SECOidData *oid; 3279 SECOidTag keyTag; 3280 SECItem *keyID, *nickName, *newNickName; 3281 3282 if (!p12dcx || p12dcx->error || !key) { 3283 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3284 return NULL; 3285 } 3286 3287 newNickName = PORT_ArenaZNew(p12dcx->arena, SECItem); 3288 keyBag = PORT_ArenaZNew(p12dcx->arena, sec_PKCS12SafeBag); 3289 if (!keyBag || !newNickName) { 3290 return NULL; 3291 } 3292 3293 keyBag->swapUnicodeBytes = p12dcx->swapUnicodeBytes; 3294 keyBag->slot = p12dcx->slot; 3295 keyBag->arena = p12dcx->arena; 3296 keyBag->pwitem = p12dcx->pwitem; 3297 keyBag->tokenCAs = p12dcx->tokenCAs; 3298 keyBag->oldBagType = PR_TRUE; 3299 3300 keyTag = (isEspvk) ? SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID : SEC_OID_PKCS12_V1_KEY_BAG_ID; 3301 oid = SECOID_FindOIDByTag(keyTag); 3302 if (!oid) { 3303 return NULL; 3304 } 3305 3306 if (SECITEM_CopyItem(p12dcx->arena, &keyBag->safeBagType, &oid->oid) != SECSuccess) { 3307 return NULL; 3308 } 3309 3310 if (isEspvk) { 3311 SEC_PKCS12ESPVKItem *espvk = (SEC_PKCS12ESPVKItem *)key; 3312 keyBag->safeBagContent.pkcs8ShroudedKeyBag = 3313 espvk->espvkCipherText.pkcs8KeyShroud; 3314 nickName = &(espvk->espvkData.uniNickName); 3315 if (!espvk->espvkData.assocCerts || !espvk->espvkData.assocCerts[0]) { 3316 PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); 3317 return NULL; 3318 } 3319 keyID = &espvk->espvkData.assocCerts[0]->digest; 3320 } else { 3321 SEC_PKCS12PrivateKey *pk = (SEC_PKCS12PrivateKey *)key; 3322 keyBag->safeBagContent.pkcs8KeyBag = &pk->pkcs8data; 3323 nickName = &(pk->pvkData.uniNickName); 3324 if (!pk->pvkData.assocCerts || !pk->pvkData.assocCerts[0]) { 3325 PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); 3326 return NULL; 3327 } 3328 keyID = &pk->pvkData.assocCerts[0]->digest; 3329 } 3330 3331 if (nickName->len) { 3332 if (nickName->len >= 2) { 3333 if (nickName->data[0] && nickName->data[1]) { 3334 if (!sec_pkcs12_convert_item_to_unicode(p12dcx->arena, newNickName, 3335 nickName, PR_FALSE, PR_FALSE, PR_TRUE)) { 3336 return NULL; 3337 } 3338 nickName = newNickName; 3339 } else if (nickName->data[0] && !nickName->data[1]) { 3340 unsigned int j = 0; 3341 unsigned char t; 3342 for (j = 0; j < nickName->len; j += 2) { 3343 t = nickName->data[j + 1]; 3344 nickName->data[j + 1] = nickName->data[j]; 3345 nickName->data[j] = t; 3346 } 3347 } 3348 } else { 3349 if (!sec_pkcs12_convert_item_to_unicode(p12dcx->arena, newNickName, 3350 nickName, PR_FALSE, PR_FALSE, PR_TRUE)) { 3351 return NULL; 3352 } 3353 nickName = newNickName; 3354 } 3355 } 3356 3357 if (sec_pkcs12_decoder_set_attribute_value(keyBag, 3358 SEC_OID_PKCS9_FRIENDLY_NAME, 3359 nickName) != SECSuccess) { 3360 return NULL; 3361 } 3362 3363 if (sec_pkcs12_decoder_set_attribute_value(keyBag, SEC_OID_PKCS9_LOCAL_KEY_ID, 3364 keyID) != SECSuccess) { 3365 return NULL; 3366 } 3367 3368 return keyBag; 3369 } 3370 3371 static sec_PKCS12SafeBag * 3372 sec_pkcs12_decoder_create_cert(SEC_PKCS12DecoderContext *p12dcx, 3373 SECItem *derCert) 3374 { 3375 sec_PKCS12SafeBag *certBag; 3376 SECOidData *oid; 3377 SGNDigestInfo *digest; 3378 SECItem *keyId; 3379 SECStatus rv; 3380 3381 if (!p12dcx || p12dcx->error || !derCert) { 3382 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3383 return NULL; 3384 } 3385 3386 keyId = PORT_ArenaZNew(p12dcx->arena, SECItem); 3387 if (!keyId) { 3388 return NULL; 3389 } 3390 3391 digest = sec_pkcs12_compute_thumbprint(derCert); 3392 if (!digest) { 3393 return NULL; 3394 } 3395 3396 rv = SECITEM_CopyItem(p12dcx->arena, keyId, &digest->digest); 3397 SGN_DestroyDigestInfo(digest); 3398 if (rv != SECSuccess) { 3399 PORT_SetError(SEC_ERROR_NO_MEMORY); 3400 return NULL; 3401 } 3402 3403 oid = SECOID_FindOIDByTag(SEC_OID_PKCS12_V1_CERT_BAG_ID); 3404 certBag = PORT_ArenaZNew(p12dcx->arena, sec_PKCS12SafeBag); 3405 if (!certBag || !oid || (SECITEM_CopyItem(p12dcx->arena, &certBag->safeBagType, &oid->oid) != SECSuccess)) { 3406 return NULL; 3407 } 3408 3409 certBag->slot = p12dcx->slot; 3410 certBag->pwitem = p12dcx->pwitem; 3411 certBag->swapUnicodeBytes = p12dcx->swapUnicodeBytes; 3412 certBag->arena = p12dcx->arena; 3413 certBag->tokenCAs = p12dcx->tokenCAs; 3414 3415 oid = SECOID_FindOIDByTag(SEC_OID_PKCS9_X509_CERT); 3416 certBag->safeBagContent.certBag = 3417 PORT_ArenaZNew(p12dcx->arena, sec_PKCS12CertBag); 3418 if (!certBag->safeBagContent.certBag || !oid || 3419 (SECITEM_CopyItem(p12dcx->arena, 3420 &certBag->safeBagContent.certBag->bagID, 3421 &oid->oid) != SECSuccess)) { 3422 return NULL; 3423 } 3424 3425 if (SECITEM_CopyItem(p12dcx->arena, 3426 &(certBag->safeBagContent.certBag->value.x509Cert), 3427 derCert) != SECSuccess) { 3428 return NULL; 3429 } 3430 3431 if (sec_pkcs12_decoder_set_attribute_value(certBag, SEC_OID_PKCS9_LOCAL_KEY_ID, 3432 keyId) != SECSuccess) { 3433 return NULL; 3434 } 3435 3436 return certBag; 3437 } 3438 3439 static sec_PKCS12SafeBag ** 3440 sec_pkcs12_decoder_convert_old_cert(SEC_PKCS12DecoderContext *p12dcx, 3441 SEC_PKCS12CertAndCRL *oldCert) 3442 { 3443 sec_PKCS12SafeBag **certList; 3444 SECItem **derCertList; 3445 int i, j; 3446 3447 if (!p12dcx || p12dcx->error || !oldCert) { 3448 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3449 return NULL; 3450 } 3451 3452 derCertList = SEC_PKCS7GetCertificateList(&oldCert->value.x509->certOrCRL); 3453 if (!derCertList) { 3454 return NULL; 3455 } 3456 3457 i = 0; 3458 while (derCertList[i]) 3459 i++; 3460 3461 certList = PORT_ArenaZNewArray(p12dcx->arena, sec_PKCS12SafeBag *, (i + 1)); 3462 if (!certList) { 3463 return NULL; 3464 } 3465 3466 for (j = 0; j < i; j++) { 3467 certList[j] = sec_pkcs12_decoder_create_cert(p12dcx, derCertList[j]); 3468 if (!certList[j]) { 3469 return NULL; 3470 } 3471 } 3472 3473 return certList; 3474 } 3475 3476 static SECStatus 3477 sec_pkcs12_decoder_convert_old_key_and_certs(SEC_PKCS12DecoderContext *p12dcx, 3478 void *oldKey, PRBool isEspvk, 3479 SEC_PKCS12SafeContents *safe, 3480 SEC_PKCS12Baggage *baggage) 3481 { 3482 sec_PKCS12SafeBag *key, **certList; 3483 SEC_PKCS12CertAndCRL *oldCert; 3484 SEC_PKCS12PVKSupportingData *pvkData; 3485 int i; 3486 SECItem *keyName; 3487 3488 if (!p12dcx || !oldKey) { 3489 return SECFailure; 3490 } 3491 3492 if (isEspvk) { 3493 pvkData = &((SEC_PKCS12ESPVKItem *)(oldKey))->espvkData; 3494 } else { 3495 pvkData = &((SEC_PKCS12PrivateKey *)(oldKey))->pvkData; 3496 } 3497 3498 if (!pvkData->assocCerts || !pvkData->assocCerts[0]) { 3499 PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); 3500 return SECFailure; 3501 } 3502 3503 oldCert = (SEC_PKCS12CertAndCRL *)sec_pkcs12_find_object(safe, baggage, 3504 SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID, NULL, 3505 pvkData->assocCerts[0]); 3506 if (!oldCert) { 3507 PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); 3508 return SECFailure; 3509 } 3510 3511 key = sec_pkcs12_decoder_convert_old_key(p12dcx, oldKey, isEspvk); 3512 certList = sec_pkcs12_decoder_convert_old_cert(p12dcx, oldCert); 3513 if (!key || !certList) { 3514 return SECFailure; 3515 } 3516 3517 if (sec_pkcs12_decoder_append_bag_to_context(p12dcx, key) != SECSuccess) { 3518 return SECFailure; 3519 } 3520 3521 keyName = sec_pkcs12_get_nickname(key); 3522 if (!keyName) { 3523 return SECFailure; 3524 } 3525 3526 i = 0; 3527 while (certList[i]) { 3528 if (sec_pkcs12_decoder_append_bag_to_context(p12dcx, certList[i]) != SECSuccess) { 3529 return SECFailure; 3530 } 3531 i++; 3532 } 3533 3534 certList = sec_pkcs12_find_certs_for_key(p12dcx->safeBags, key); 3535 if (!certList) { 3536 return SECFailure; 3537 } 3538 3539 i = 0; 3540 while (certList[i] != 0) { 3541 if (sec_pkcs12_set_nickname(certList[i], keyName) != SECSuccess) { 3542 return SECFailure; 3543 } 3544 i++; 3545 } 3546 3547 return SECSuccess; 3548 } 3549 3550 static SECStatus 3551 sec_pkcs12_decoder_convert_old_safe_to_bags(SEC_PKCS12DecoderContext *p12dcx, 3552 SEC_PKCS12SafeContents *safe, 3553 SEC_PKCS12Baggage *baggage) 3554 { 3555 SECStatus rv; 3556 3557 if (!p12dcx || p12dcx->error) { 3558 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3559 return SECFailure; 3560 } 3561 3562 if (safe && safe->contents) { 3563 int i = 0; 3564 while (safe->contents[i] != NULL) { 3565 if (SECOID_FindOIDTag(&safe->contents[i]->safeBagType) == SEC_OID_PKCS12_KEY_BAG_ID) { 3566 int j = 0; 3567 SEC_PKCS12PrivateKeyBag *privBag = 3568 safe->contents[i]->safeContent.keyBag; 3569 3570 while (privBag->privateKeys[j] != NULL) { 3571 SEC_PKCS12PrivateKey *pk = privBag->privateKeys[j]; 3572 rv = sec_pkcs12_decoder_convert_old_key_and_certs(p12dcx, pk, 3573 PR_FALSE, safe, baggage); 3574 if (rv != SECSuccess) { 3575 goto loser; 3576 } 3577 j++; 3578 } 3579 } 3580 i++; 3581 } 3582 } 3583 3584 if (baggage && baggage->bags) { 3585 int i = 0; 3586 while (baggage->bags[i] != NULL) { 3587 SEC_PKCS12BaggageItem *bag = baggage->bags[i]; 3588 int j = 0; 3589 3590 if (!bag->espvks) { 3591 i++; 3592 continue; 3593 } 3594 3595 while (bag->espvks[j] != NULL) { 3596 SEC_PKCS12ESPVKItem *espvk = bag->espvks[j]; 3597 rv = sec_pkcs12_decoder_convert_old_key_and_certs(p12dcx, espvk, 3598 PR_TRUE, safe, baggage); 3599 if (rv != SECSuccess) { 3600 goto loser; 3601 } 3602 j++; 3603 } 3604 i++; 3605 } 3606 } 3607 3608 return SECSuccess; 3609 3610 loser: 3611 return SECFailure; 3612 } 3613 3614 SEC_PKCS12DecoderContext * 3615 sec_PKCS12ConvertOldSafeToNew(PLArenaPool *arena, PK11SlotInfo *slot, 3616 PRBool swapUnicode, SECItem *pwitem, 3617 void *wincx, SEC_PKCS12SafeContents *safe, 3618 SEC_PKCS12Baggage *baggage) 3619 { 3620 SEC_PKCS12DecoderContext *p12dcx; 3621 3622 if (!arena || !slot || !pwitem) { 3623 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3624 return NULL; 3625 } 3626 3627 if (!safe && !baggage) { 3628 PORT_SetError(SEC_ERROR_INVALID_ARGS); 3629 return NULL; 3630 } 3631 3632 p12dcx = PORT_ArenaZNew(arena, SEC_PKCS12DecoderContext); 3633 if (!p12dcx) { 3634 return NULL; 3635 } 3636 3637 p12dcx->arena = arena; 3638 p12dcx->slot = PK11_ReferenceSlot(slot); 3639 p12dcx->wincx = wincx; 3640 p12dcx->error = PR_FALSE; 3641 p12dcx->swapUnicodeBytes = swapUnicode; 3642 p12dcx->pwitem = pwitem; 3643 p12dcx->tokenCAs = SECPKCS12TargetTokenNoCAs; 3644 3645 if (sec_pkcs12_decoder_convert_old_safe_to_bags(p12dcx, safe, baggage) != SECSuccess) { 3646 p12dcx->error = PR_TRUE; 3647 return NULL; 3648 } 3649 3650 return p12dcx; 3651 }