p7decode.c (66916B)
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 /* 6 * PKCS7 decoding, verification. 7 */ 8 9 #include "p7local.h" 10 11 #include "cert.h" 12 /* XXX do not want to have to include */ 13 #include "certdb.h" /* certdb.h -- the trust stuff needed by */ 14 /* the add certificate code needs to get */ 15 /* rewritten/abstracted and then this */ 16 /* include should be removed! */ 17 /*#include "cdbhdl.h" */ 18 #include "cryptohi.h" 19 #include "keyhi.h" 20 #include "secasn1.h" 21 #include "secitem.h" 22 #include "secoid.h" 23 #include "pk11func.h" 24 #include "prtime.h" 25 #include "secerr.h" 26 #include "sechash.h" /* for HASH_GetHashObject() */ 27 #include "secder.h" 28 #include "secpkcs5.h" 29 30 struct sec_pkcs7_decoder_worker { 31 int depth; 32 int digcnt; 33 void **digcxs; 34 const SECHashObject **digobjs; 35 sec_PKCS7CipherObject *decryptobj; 36 PRBool saw_contents; 37 }; 38 39 struct SEC_PKCS7DecoderContextStr { 40 SEC_ASN1DecoderContext *dcx; 41 SEC_PKCS7ContentInfo *cinfo; 42 SEC_PKCS7DecoderContentCallback cb; 43 void *cb_arg; 44 SECKEYGetPasswordKey pwfn; 45 void *pwfn_arg; 46 struct sec_pkcs7_decoder_worker worker; 47 PLArenaPool *tmp_poolp; 48 int error; 49 SEC_PKCS7GetDecryptKeyCallback dkcb; 50 void *dkcb_arg; 51 SEC_PKCS7DecryptionAllowedCallback decrypt_allowed_cb; 52 }; 53 54 /* 55 * Handle one worker, decrypting and digesting the data as necessary. 56 * 57 * XXX If/when we support nested contents, this probably needs to be 58 * revised somewhat to get passed the content-info (which unfortunately 59 * can be two different types depending on whether it is encrypted or not) 60 * corresponding to the given worker. 61 */ 62 static void 63 sec_pkcs7_decoder_work_data(SEC_PKCS7DecoderContext *p7dcx, 64 struct sec_pkcs7_decoder_worker *worker, 65 const unsigned char *data, unsigned long len, 66 PRBool final) 67 { 68 unsigned char *buf = NULL; 69 PRBool freeBuf = PR_FALSE; 70 SECStatus rv; 71 int i; 72 73 /* 74 * We should really have data to process, or we should be trying 75 * to finish/flush the last block. (This is an overly paranoid 76 * check since all callers are in this file and simple inspection 77 * proves they do it right. But it could find a bug in future 78 * modifications/development, that is why it is here.) 79 */ 80 PORT_Assert((data != NULL && len) || final); 81 82 /* 83 * Decrypt this chunk. 84 * 85 * XXX If we get an error, we do not want to do the digest or callback, 86 * but we want to keep decoding. Or maybe we want to stop decoding 87 * altogether if there is a callback, because obviously we are not 88 * sending the data back and they want to know that. 89 */ 90 if (worker->decryptobj != NULL) { 91 /* XXX the following lengths should all be longs? */ 92 unsigned int inlen; /* length of data being decrypted */ 93 unsigned int outlen; /* length of decrypted data */ 94 unsigned int buflen; /* length available for decrypted data */ 95 SECItem *plain; 96 97 inlen = len; 98 buflen = sec_PKCS7DecryptLength(worker->decryptobj, inlen, final); 99 if (buflen == 0) { 100 if (inlen == 0) /* no input and no output */ 101 return; 102 /* 103 * No output is expected, but the input data may be buffered 104 * so we still have to call Decrypt. 105 */ 106 rv = sec_PKCS7Decrypt(worker->decryptobj, NULL, NULL, 0, 107 data, inlen, final); 108 if (rv != SECSuccess) { 109 p7dcx->error = PORT_GetError(); 110 return; /* XXX indicate error? */ 111 } 112 return; 113 } 114 115 if (p7dcx->cb != NULL) { 116 buf = (unsigned char *)PORT_Alloc(buflen); 117 freeBuf = PR_TRUE; 118 plain = NULL; 119 } else { 120 unsigned long oldlen; 121 122 /* 123 * XXX This assumes one level of content only. 124 * See comment above about nested content types. 125 * XXX Also, it should work for signedAndEnvelopedData, too! 126 */ 127 plain = &(p7dcx->cinfo->content.envelopedData->encContentInfo.plainContent); 128 129 oldlen = plain->len; 130 if (oldlen == 0) { 131 buf = (unsigned char *)PORT_ArenaAlloc(p7dcx->cinfo->poolp, 132 buflen); 133 } else { 134 buf = (unsigned char *)PORT_ArenaGrow(p7dcx->cinfo->poolp, 135 plain->data, 136 oldlen, oldlen + buflen); 137 if (buf != NULL) 138 buf += oldlen; 139 } 140 plain->data = buf; 141 } 142 if (buf == NULL) { 143 p7dcx->error = SEC_ERROR_NO_MEMORY; 144 return; /* XXX indicate error? */ 145 } 146 rv = sec_PKCS7Decrypt(worker->decryptobj, buf, &outlen, buflen, 147 data, inlen, final); 148 if (rv != SECSuccess) { 149 p7dcx->error = PORT_GetError(); 150 goto cleanup; /* XXX indicate error? */ 151 } 152 if (plain != NULL) { 153 PORT_Assert(final || outlen == buflen); 154 plain->len += outlen; 155 } 156 data = buf; 157 len = outlen; 158 } 159 160 /* 161 * Update the running digests. 162 */ 163 if (len) { 164 for (i = 0; i < worker->digcnt; i++) { 165 (*worker->digobjs[i]->update)(worker->digcxs[i], data, len); 166 } 167 } 168 169 /* 170 * Pass back the contents bytes, and free the temporary buffer. 171 */ 172 if (p7dcx->cb != NULL) { 173 if (len) 174 (*p7dcx->cb)(p7dcx->cb_arg, (const char *)data, len); 175 } 176 177 cleanup: 178 if (freeBuf && buf != NULL) { 179 PORT_Free(buf); 180 } 181 } 182 183 static void 184 sec_pkcs7_decoder_filter(void *arg, const char *data, unsigned long len, 185 int depth, SEC_ASN1EncodingPart data_kind) 186 { 187 SEC_PKCS7DecoderContext *p7dcx; 188 struct sec_pkcs7_decoder_worker *worker; 189 190 /* 191 * Since we do not handle any nested contents, the only bytes we 192 * are really interested in are the actual contents bytes (not 193 * the identifier, length, or end-of-contents bytes). If we were 194 * handling nested types we would probably need to do something 195 * smarter based on depth and data_kind. 196 */ 197 if (data_kind != SEC_ASN1_Contents) 198 return; 199 200 /* 201 * The ASN.1 decoder should not even call us with a length of 0. 202 * Just being paranoid. 203 */ 204 PORT_Assert(len); 205 if (len == 0) 206 return; 207 208 p7dcx = (SEC_PKCS7DecoderContext *)arg; 209 210 /* 211 * Handling nested contents would mean that there is a chain 212 * of workers -- one per each level of content. The following 213 * would start with the first worker and loop over them. 214 */ 215 worker = &(p7dcx->worker); 216 217 worker->saw_contents = PR_TRUE; 218 219 sec_pkcs7_decoder_work_data(p7dcx, worker, 220 (const unsigned char *)data, len, PR_FALSE); 221 } 222 223 /* 224 * Create digest contexts for each algorithm in "digestalgs". 225 * No algorithms is not an error, we just do not do anything. 226 * An error (like trouble allocating memory), marks the error 227 * in "p7dcx" and returns SECFailure, which means that our caller 228 * should just give up altogether. 229 */ 230 static SECStatus 231 sec_pkcs7_decoder_start_digests(SEC_PKCS7DecoderContext *p7dcx, int depth, 232 SECAlgorithmID **digestalgs) 233 { 234 int i, digcnt; 235 236 p7dcx->worker.digcnt = 0; 237 238 if (digestalgs == NULL) 239 return SECSuccess; 240 241 /* 242 * Count the algorithms. 243 */ 244 digcnt = 0; 245 while (digestalgs[digcnt] != NULL) 246 digcnt++; 247 248 /* 249 * No algorithms means no work to do. 250 * Just act as if there were no algorithms specified. 251 */ 252 if (digcnt == 0) 253 return SECSuccess; 254 255 p7dcx->worker.digcxs = (void **)PORT_ArenaAlloc(p7dcx->tmp_poolp, 256 digcnt * sizeof(void *)); 257 p7dcx->worker.digobjs = (const SECHashObject **)PORT_ArenaAlloc(p7dcx->tmp_poolp, 258 digcnt * sizeof(SECHashObject *)); 259 if (p7dcx->worker.digcxs == NULL || p7dcx->worker.digobjs == NULL) { 260 p7dcx->error = SEC_ERROR_NO_MEMORY; 261 return SECFailure; 262 } 263 264 p7dcx->worker.depth = depth; 265 266 /* 267 * Create a digest context for each algorithm. 268 */ 269 for (i = 0; i < digcnt; i++) { 270 SECAlgorithmID *algid = digestalgs[i]; 271 SECOidTag oidTag = SECOID_FindOIDTag(&(algid->algorithm)); 272 const SECHashObject *digobj = HASH_GetHashObjectByOidTag(oidTag); 273 void *digcx; 274 275 /* 276 * Skip any algorithm we do not even recognize; obviously, 277 * this could be a problem, but if it is critical then the 278 * result will just be that the signature does not verify. 279 * We do not necessarily want to error out here, because 280 * the particular algorithm may not actually be important, 281 * but we cannot know that until later. 282 */ 283 if (digobj == NULL) { 284 continue; 285 } 286 287 digcx = (*digobj->create)(); 288 if (digcx != NULL) { 289 (*digobj->begin)(digcx); 290 p7dcx->worker.digobjs[p7dcx->worker.digcnt] = digobj; 291 p7dcx->worker.digcxs[p7dcx->worker.digcnt] = digcx; 292 p7dcx->worker.digcnt++; 293 } 294 } 295 296 if (p7dcx->worker.digcnt != 0) 297 SEC_ASN1DecoderSetFilterProc(p7dcx->dcx, 298 sec_pkcs7_decoder_filter, 299 p7dcx, 300 (PRBool)(p7dcx->cb != NULL)); 301 return SECSuccess; 302 } 303 304 /* destroy any active digest contexts without harvesting results */ 305 static void 306 sec_pkcs7_decoder_abort_digests(struct sec_pkcs7_decoder_worker *worker) 307 { 308 int i; 309 310 if (!worker || worker->digcnt <= 0 || !worker->digcxs || !worker->digobjs) { 311 worker->digcnt = 0; 312 return; 313 } 314 315 for (i = 0; i < worker->digcnt; i++) { 316 if (worker->digcxs[i] && worker->digobjs[i]) { 317 (*worker->digobjs[i]->destroy)(worker->digcxs[i], PR_TRUE); 318 } 319 worker->digcxs[i] = NULL; 320 } 321 322 worker->digcnt = 0; 323 } 324 325 /* 326 * Close out all of the digest contexts, storing the results in "digestsp". 327 */ 328 static SECStatus 329 sec_pkcs7_decoder_finish_digests(SEC_PKCS7DecoderContext *p7dcx, 330 PLArenaPool *poolp, 331 SECItem ***digestsp) 332 { 333 /* 334 * XXX Handling nested contents would mean that there is a chain 335 * of workers -- one per each level of content. The following 336 * would want to find the last worker in the chain. 337 */ 338 struct sec_pkcs7_decoder_worker *worker = &(p7dcx->worker); 339 340 /* 341 * If no digests, then we have nothing to do. 342 */ 343 if (worker->digcnt == 0) { 344 return SECSuccess; 345 } 346 347 /* 348 * No matter what happens after this, we want to stop filtering. 349 * XXX If we handle nested contents, we only want to stop filtering 350 * if we are finishing off the *last* worker. 351 */ 352 SEC_ASN1DecoderClearFilterProc(p7dcx->dcx); 353 354 /* 355 * If we ended up with no contents, just destroy each 356 * digest context -- they are meaningless and potentially 357 * confusing, because their presence would imply some content 358 * was digested. 359 */ 360 if (!worker->saw_contents) { 361 sec_pkcs7_decoder_abort_digests(worker); 362 return SECSuccess; 363 } 364 365 void *mark = PORT_ArenaMark(poolp); 366 367 /* 368 * Close out each digest context, saving digest away. 369 */ 370 SECItem **digests = 371 (SECItem **)PORT_ArenaZAlloc(poolp, (worker->digcnt + 1) * sizeof(SECItem *)); 372 if (digests == NULL) { 373 p7dcx->error = PORT_GetError(); 374 sec_pkcs7_decoder_abort_digests(worker); 375 PORT_ArenaRelease(poolp, mark); 376 return SECFailure; 377 } 378 379 for (int i = 0; i < worker->digcnt; i++) { 380 const SECHashObject *digobj = worker->digobjs[i]; 381 digests[i] = SECITEM_AllocItem(poolp, NULL, digobj->length); 382 if (!digests[i]) { 383 p7dcx->error = PORT_GetError(); 384 sec_pkcs7_decoder_abort_digests(worker); 385 PORT_ArenaRelease(poolp, mark); 386 return SECFailure; 387 } 388 } 389 390 for (int i = 0; i < worker->digcnt; i++) { 391 void *digcx = worker->digcxs[i]; 392 const SECHashObject *digobj = worker->digobjs[i]; 393 394 (*digobj->end)(digcx, digests[i]->data, &(digests[i]->len), digests[i]->len); 395 (*digobj->destroy)(digcx, PR_TRUE); 396 worker->digcxs[i] = NULL; 397 } 398 worker->digcnt = 0; 399 *digestsp = digests; 400 401 PORT_ArenaUnmark(poolp, mark); 402 return SECSuccess; 403 } 404 405 /* 406 * XXX Need comment explaining following helper function (which is used 407 * by sec_pkcs7_decoder_start_decrypt). 408 */ 409 410 static PK11SymKey * 411 sec_pkcs7_decoder_get_recipient_key(SEC_PKCS7DecoderContext *p7dcx, 412 SEC_PKCS7RecipientInfo **recipientinfos, 413 SEC_PKCS7EncryptedContentInfo *enccinfo) 414 { 415 SEC_PKCS7RecipientInfo *ri; 416 CERTCertificate *cert = NULL; 417 SECKEYPrivateKey *privkey = NULL; 418 PK11SymKey *bulkkey = NULL; 419 SECOidTag keyalgtag, bulkalgtag, encalgtag; 420 PK11SlotInfo *slot = NULL; 421 422 if (recipientinfos == NULL || recipientinfos[0] == NULL) { 423 p7dcx->error = SEC_ERROR_NOT_A_RECIPIENT; 424 goto no_key_found; 425 } 426 427 cert = PK11_FindCertAndKeyByRecipientList(&slot, recipientinfos, &ri, 428 &privkey, p7dcx->pwfn_arg); 429 if (cert == NULL) { 430 p7dcx->error = SEC_ERROR_NOT_A_RECIPIENT; 431 goto no_key_found; 432 } 433 434 ri->cert = cert; /* so we can find it later */ 435 PORT_Assert(privkey != NULL); 436 437 keyalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm)); 438 encalgtag = SECOID_GetAlgorithmTag(&(ri->keyEncAlg)); 439 if (keyalgtag != encalgtag) { 440 p7dcx->error = SEC_ERROR_PKCS7_KEYALG_MISMATCH; 441 goto no_key_found; 442 } 443 bulkalgtag = SECOID_GetAlgorithmTag(&(enccinfo->contentEncAlg)); 444 445 switch (encalgtag) { 446 case SEC_OID_PKCS1_RSA_ENCRYPTION: 447 bulkkey = PK11_PubUnwrapSymKey(privkey, &ri->encKey, 448 PK11_AlgtagToMechanism(bulkalgtag), 449 CKA_DECRYPT, 0); 450 if (bulkkey == NULL) { 451 p7dcx->error = PORT_GetError(); 452 PORT_SetError(0); 453 goto no_key_found; 454 } 455 break; 456 default: 457 p7dcx->error = SEC_ERROR_UNSUPPORTED_KEYALG; 458 break; 459 } 460 461 no_key_found: 462 if (privkey != NULL) 463 SECKEY_DestroyPrivateKey(privkey); 464 if (slot != NULL) 465 PK11_FreeSlot(slot); 466 467 return bulkkey; 468 } 469 470 /* 471 * XXX The following comment is old -- the function used to only handle 472 * EnvelopedData or SignedAndEnvelopedData but now handles EncryptedData 473 * as well (and it had all of the code of the helper function above 474 * built into it), though the comment was left as is. Fix it... 475 * 476 * We are just about to decode the content of an EnvelopedData. 477 * Set up a decryption context so we can decrypt as we go. 478 * Presumably we are one of the recipients listed in "recipientinfos". 479 * (XXX And if we are not, or if we have trouble, what should we do? 480 * It would be nice to let the decoding still work. Maybe it should 481 * be an error if there is a content callback, but not an error otherwise?) 482 * The encryption key and related information can be found in "enccinfo". 483 */ 484 static SECStatus 485 sec_pkcs7_decoder_start_decrypt(SEC_PKCS7DecoderContext *p7dcx, int depth, 486 SEC_PKCS7RecipientInfo **recipientinfos, 487 SEC_PKCS7EncryptedContentInfo *enccinfo, 488 PK11SymKey **copy_key_for_signature) 489 { 490 PK11SymKey *bulkkey = NULL; 491 sec_PKCS7CipherObject *decryptobj; 492 493 /* 494 * If a callback is supplied to retrieve the encryption key, 495 * for instance, for Encrypted Content infos, then retrieve 496 * the bulkkey from the callback. Otherwise, assume that 497 * we are processing Enveloped or SignedAndEnveloped data 498 * content infos. 499 * 500 * XXX Put an assert here? 501 */ 502 if (SEC_PKCS7ContentType(p7dcx->cinfo) == SEC_OID_PKCS7_ENCRYPTED_DATA) { 503 if (p7dcx->dkcb != NULL) { 504 bulkkey = (*p7dcx->dkcb)(p7dcx->dkcb_arg, 505 &(enccinfo->contentEncAlg)); 506 } 507 enccinfo->keysize = 0; 508 } else { 509 bulkkey = sec_pkcs7_decoder_get_recipient_key(p7dcx, recipientinfos, 510 enccinfo); 511 if (bulkkey == NULL) 512 goto no_decryption; 513 enccinfo->keysize = PK11_GetKeyStrength(bulkkey, 514 &(enccinfo->contentEncAlg)); 515 } 516 517 /* 518 * XXX I think following should set error in p7dcx and clear set error 519 * (as used to be done here, or as is done in get_receipient_key above. 520 */ 521 if (bulkkey == NULL) { 522 goto no_decryption; 523 } 524 525 /* 526 * We want to make sure decryption is allowed. This is done via 527 * a callback specified in SEC_PKCS7DecoderStart(). 528 */ 529 if (p7dcx->decrypt_allowed_cb) { 530 if ((*p7dcx->decrypt_allowed_cb)(&(enccinfo->contentEncAlg), 531 bulkkey) == PR_FALSE) { 532 p7dcx->error = SEC_ERROR_DECRYPTION_DISALLOWED; 533 goto no_decryption; 534 } 535 } else { 536 p7dcx->error = SEC_ERROR_DECRYPTION_DISALLOWED; 537 goto no_decryption; 538 } 539 540 /* 541 * When decrypting a signedAndEnvelopedData, the signature also has 542 * to be decrypted with the bulk encryption key; to avoid having to 543 * get it all over again later (and do another potentially expensive 544 * RSA operation), copy it for later signature verification to use. 545 */ 546 if (copy_key_for_signature != NULL) 547 *copy_key_for_signature = PK11_ReferenceSymKey(bulkkey); 548 549 /* 550 * Now we have the bulk encryption key (in bulkkey) and the 551 * the algorithm (in enccinfo->contentEncAlg). Using those, 552 * create a decryption context. 553 */ 554 decryptobj = sec_PKCS7CreateDecryptObject(bulkkey, 555 &(enccinfo->contentEncAlg)); 556 557 /* 558 * We are done with (this) bulkkey now. 559 */ 560 PK11_FreeSymKey(bulkkey); 561 bulkkey = NULL; 562 563 if (decryptobj == NULL) { 564 p7dcx->error = PORT_GetError(); 565 PORT_SetError(0); 566 goto no_decryption; 567 } 568 569 SEC_ASN1DecoderSetFilterProc(p7dcx->dcx, 570 sec_pkcs7_decoder_filter, 571 p7dcx, 572 (PRBool)(p7dcx->cb != NULL)); 573 574 p7dcx->worker.depth = depth; 575 p7dcx->worker.decryptobj = decryptobj; 576 577 return SECSuccess; 578 579 no_decryption: 580 PK11_FreeSymKey(bulkkey); 581 /* 582 * For some reason (error set already, if appropriate), we cannot 583 * decrypt the content. I am not sure what exactly is the right 584 * thing to do here; in some cases we want to just stop, and in 585 * others we want to let the decoding finish even though we cannot 586 * decrypt the content. My current thinking is that if the caller 587 * set up a content callback, then they are really interested in 588 * getting (decrypted) content, and if they cannot they will want 589 * to know about it. However, if no callback was specified, then 590 * maybe it is not important that the decryption failed. 591 */ 592 if (p7dcx->cb != NULL) 593 return SECFailure; 594 else 595 return SECSuccess; /* Let the decoding continue. */ 596 } 597 598 static SECStatus 599 sec_pkcs7_decoder_finish_decrypt(SEC_PKCS7DecoderContext *p7dcx, 600 PLArenaPool *poolp, 601 SEC_PKCS7EncryptedContentInfo *enccinfo) 602 { 603 struct sec_pkcs7_decoder_worker *worker; 604 605 /* 606 * XXX Handling nested contents would mean that there is a chain 607 * of workers -- one per each level of content. The following 608 * would want to find the last worker in the chain. 609 */ 610 worker = &(p7dcx->worker); 611 612 /* 613 * If no decryption context, then we have nothing to do. 614 */ 615 if (worker->decryptobj == NULL) 616 return SECSuccess; 617 618 /* 619 * No matter what happens after this, we want to stop filtering. 620 * XXX If we handle nested contents, we only want to stop filtering 621 * if we are finishing off the *last* worker. 622 */ 623 SEC_ASN1DecoderClearFilterProc(p7dcx->dcx); 624 625 /* 626 * Handle the last block. 627 */ 628 sec_pkcs7_decoder_work_data(p7dcx, worker, NULL, 0, PR_TRUE); 629 630 /* 631 * The callback invoked from work_data may have aborted and already 632 * torn down the decrypt context, so only destroy if it is still set. 633 */ 634 if (worker->decryptobj) { 635 sec_PKCS7DestroyDecryptObject(worker->decryptobj); 636 worker->decryptobj = NULL; 637 } 638 639 return SECSuccess; 640 } 641 642 static void 643 sec_pkcs7_decoder_notify(void *arg, PRBool before, void *dest, int depth) 644 { 645 SEC_PKCS7DecoderContext *p7dcx; 646 SEC_PKCS7ContentInfo *cinfo; 647 SEC_PKCS7SignedData *sigd; 648 SEC_PKCS7EnvelopedData *envd; 649 SEC_PKCS7SignedAndEnvelopedData *saed; 650 SEC_PKCS7EncryptedData *encd; 651 SEC_PKCS7DigestedData *digd; 652 PRBool after; 653 SECStatus rv; 654 655 /* 656 * Just to make the code easier to read, create an "after" variable 657 * that is equivalent to "not before". 658 * (This used to be just the statement "after = !before", but that 659 * causes a warning on the mac; to avoid that, we do it the long way.) 660 */ 661 if (before) 662 after = PR_FALSE; 663 else 664 after = PR_TRUE; 665 666 p7dcx = (SEC_PKCS7DecoderContext *)arg; 667 if (!p7dcx) { 668 return; 669 } 670 671 cinfo = p7dcx->cinfo; 672 673 if (!cinfo) { 674 return; 675 } 676 677 if (cinfo->contentTypeTag == NULL) { 678 if (after && dest == &(cinfo->contentType)) 679 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); 680 return; 681 } 682 683 switch (cinfo->contentTypeTag->offset) { 684 case SEC_OID_PKCS7_SIGNED_DATA: 685 sigd = cinfo->content.signedData; 686 if (sigd == NULL) 687 break; 688 689 if (sigd->contentInfo.contentTypeTag == NULL) { 690 if (after && dest == &(sigd->contentInfo.contentType)) 691 sigd->contentInfo.contentTypeTag = 692 SECOID_FindOID(&(sigd->contentInfo.contentType)); 693 break; 694 } 695 696 /* 697 * We only set up a filtering digest if the content is 698 * plain DATA; anything else needs more work because a 699 * second pass is required to produce a DER encoding from 700 * an input that can be BER encoded. (This is a requirement 701 * of PKCS7 that is unfortunate, but there you have it.) 702 * 703 * XXX Also, since we stop here if this is not DATA, the 704 * inner content is not getting processed at all. Someday 705 * we may want to fix that. 706 */ 707 if (sigd->contentInfo.contentTypeTag->offset != SEC_OID_PKCS7_DATA) { 708 /* XXX Set an error in p7dcx->error */ 709 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 710 break; 711 } 712 713 /* 714 * Just before the content, we want to set up a digest context 715 * for each digest algorithm listed, and start a filter which 716 * will run all of the contents bytes through that digest. 717 */ 718 if (before && dest == &(sigd->contentInfo.content)) { 719 rv = sec_pkcs7_decoder_start_digests(p7dcx, depth, 720 sigd->digestAlgorithms); 721 if (rv != SECSuccess) 722 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 723 724 break; 725 } 726 727 /* 728 * XXX To handle nested types, here is where we would want 729 * to check for inner boundaries that need handling. 730 */ 731 732 /* 733 * Are we done? 734 */ 735 if (after && dest == &(sigd->contentInfo.content)) { 736 /* 737 * Close out the digest contexts. We ignore any error 738 * because we are stopping anyway; the error status left 739 * behind in p7dcx will be seen by outer functions. 740 */ 741 (void)sec_pkcs7_decoder_finish_digests(p7dcx, cinfo->poolp, 742 &(sigd->digests)); 743 744 /* 745 * XXX To handle nested contents, we would need to remove 746 * the worker from the chain (and free it). 747 */ 748 749 /* 750 * Stop notify. 751 */ 752 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 753 } 754 break; 755 756 case SEC_OID_PKCS7_ENVELOPED_DATA: 757 envd = cinfo->content.envelopedData; 758 if (envd == NULL) 759 break; 760 761 if (envd->encContentInfo.contentTypeTag == NULL) { 762 if (after && dest == &(envd->encContentInfo.contentType)) 763 envd->encContentInfo.contentTypeTag = 764 SECOID_FindOID(&(envd->encContentInfo.contentType)); 765 break; 766 } 767 768 /* 769 * Just before the content, we want to set up a decryption 770 * context, and start a filter which will run all of the 771 * contents bytes through it to determine the plain content. 772 */ 773 if (before && dest == &(envd->encContentInfo.encContent)) { 774 rv = sec_pkcs7_decoder_start_decrypt(p7dcx, depth, 775 envd->recipientInfos, 776 &(envd->encContentInfo), 777 NULL); 778 if (rv != SECSuccess) 779 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 780 781 break; 782 } 783 784 /* 785 * Are we done? 786 */ 787 if (after && dest == &(envd->encContentInfo.encContent)) { 788 /* 789 * Close out the decryption context. We ignore any error 790 * because we are stopping anyway; the error status left 791 * behind in p7dcx will be seen by outer functions. 792 */ 793 (void)sec_pkcs7_decoder_finish_decrypt(p7dcx, cinfo->poolp, 794 &(envd->encContentInfo)); 795 796 /* 797 * XXX To handle nested contents, we would need to remove 798 * the worker from the chain (and free it). 799 */ 800 801 /* 802 * Stop notify. 803 */ 804 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 805 } 806 break; 807 808 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: 809 saed = cinfo->content.signedAndEnvelopedData; 810 if (saed == NULL) 811 break; 812 813 if (saed->encContentInfo.contentTypeTag == NULL) { 814 if (after && dest == &(saed->encContentInfo.contentType)) 815 saed->encContentInfo.contentTypeTag = 816 SECOID_FindOID(&(saed->encContentInfo.contentType)); 817 break; 818 } 819 820 /* 821 * Just before the content, we want to set up a decryption 822 * context *and* digest contexts, and start a filter which 823 * will run all of the contents bytes through both. 824 */ 825 if (before && dest == &(saed->encContentInfo.encContent)) { 826 rv = sec_pkcs7_decoder_start_decrypt(p7dcx, depth, 827 saed->recipientInfos, 828 &(saed->encContentInfo), 829 &(saed->sigKey)); 830 if (rv == SECSuccess) 831 rv = sec_pkcs7_decoder_start_digests(p7dcx, depth, 832 saed->digestAlgorithms); 833 if (rv != SECSuccess) 834 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 835 836 break; 837 } 838 839 /* 840 * Are we done? 841 */ 842 if (after && dest == &(saed->encContentInfo.encContent)) { 843 /* 844 * Close out the decryption and digests contexts. 845 * We ignore any errors because we are stopping anyway; 846 * the error status left behind in p7dcx will be seen by 847 * outer functions. 848 * 849 * Note that the decrypt stuff must be called first; 850 * it may have a last buffer to do which in turn has 851 * to be added to the digest. 852 */ 853 (void)sec_pkcs7_decoder_finish_decrypt(p7dcx, cinfo->poolp, 854 &(saed->encContentInfo)); 855 (void)sec_pkcs7_decoder_finish_digests(p7dcx, cinfo->poolp, 856 &(saed->digests)); 857 858 /* 859 * XXX To handle nested contents, we would need to remove 860 * the worker from the chain (and free it). 861 */ 862 863 /* 864 * Stop notify. 865 */ 866 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 867 } 868 break; 869 870 case SEC_OID_PKCS7_DIGESTED_DATA: 871 digd = cinfo->content.digestedData; 872 if (digd == NULL) 873 break; 874 875 /* 876 * XXX Want to do the digest or not? Maybe future enhancement... 877 */ 878 if (before && dest == &(digd->contentInfo.content.data)) { 879 SEC_ASN1DecoderSetFilterProc(p7dcx->dcx, sec_pkcs7_decoder_filter, 880 p7dcx, 881 (PRBool)(p7dcx->cb != NULL)); 882 break; 883 } 884 885 /* 886 * Are we done? 887 */ 888 if (after && dest == &(digd->contentInfo.content.data)) { 889 SEC_ASN1DecoderClearFilterProc(p7dcx->dcx); 890 } 891 break; 892 893 case SEC_OID_PKCS7_ENCRYPTED_DATA: 894 encd = cinfo->content.encryptedData; 895 896 if (!encd) { 897 break; 898 } 899 900 /* 901 * XXX If the decryption key callback is set, we want to start 902 * the decryption. If the callback is not set, we will treat the 903 * content as plain data, since we do not have the key. 904 * 905 * Is this the proper thing to do? 906 */ 907 if (before && dest == &(encd->encContentInfo.encContent)) { 908 /* 909 * Start the encryption process if the decryption key callback 910 * is present. Otherwise, treat the content like plain data. 911 */ 912 rv = SECSuccess; 913 if (p7dcx->dkcb != NULL) { 914 rv = sec_pkcs7_decoder_start_decrypt(p7dcx, depth, NULL, 915 &(encd->encContentInfo), 916 NULL); 917 } 918 919 if (rv != SECSuccess) 920 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 921 922 break; 923 } 924 925 /* 926 * Are we done? 927 */ 928 if (after && dest == &(encd->encContentInfo.encContent)) { 929 /* 930 * Close out the decryption context. We ignore any error 931 * because we are stopping anyway; the error status left 932 * behind in p7dcx will be seen by outer functions. 933 */ 934 (void)sec_pkcs7_decoder_finish_decrypt(p7dcx, cinfo->poolp, 935 &(encd->encContentInfo)); 936 937 /* 938 * Stop notify. 939 */ 940 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 941 } 942 break; 943 944 case SEC_OID_PKCS7_DATA: 945 /* 946 * If a output callback has been specified, we want to set the filter 947 * to call the callback. This is taken care of in 948 * sec_pkcs7_decoder_start_decrypt() or 949 * sec_pkcs7_decoder_start_digests() for the other content types. 950 */ 951 952 if (before && dest == &(cinfo->content.data)) { 953 954 /* 955 * Set the filter proc up. 956 */ 957 SEC_ASN1DecoderSetFilterProc(p7dcx->dcx, 958 sec_pkcs7_decoder_filter, 959 p7dcx, 960 (PRBool)(p7dcx->cb != NULL)); 961 break; 962 } 963 964 if (after && dest == &(cinfo->content.data)) { 965 /* 966 * Time to clean up after ourself, stop the Notify and Filter 967 * procedures. 968 */ 969 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 970 SEC_ASN1DecoderClearFilterProc(p7dcx->dcx); 971 } 972 break; 973 974 default: 975 SEC_ASN1DecoderClearNotifyProc(p7dcx->dcx); 976 break; 977 } 978 } 979 980 SEC_PKCS7DecoderContext * 981 SEC_PKCS7DecoderStart(SEC_PKCS7DecoderContentCallback cb, void *cb_arg, 982 SECKEYGetPasswordKey pwfn, void *pwfn_arg, 983 SEC_PKCS7GetDecryptKeyCallback decrypt_key_cb, 984 void *decrypt_key_cb_arg, 985 SEC_PKCS7DecryptionAllowedCallback decrypt_allowed_cb) 986 { 987 SEC_PKCS7DecoderContext *p7dcx; 988 SEC_ASN1DecoderContext *dcx; 989 SEC_PKCS7ContentInfo *cinfo; 990 PLArenaPool *poolp; 991 992 poolp = PORT_NewArena(1024); /* XXX what is right value? */ 993 if (poolp == NULL) 994 return NULL; 995 996 cinfo = (SEC_PKCS7ContentInfo *)PORT_ArenaZAlloc(poolp, sizeof(*cinfo)); 997 if (cinfo == NULL) { 998 PORT_FreeArena(poolp, PR_FALSE); 999 return NULL; 1000 } 1001 1002 cinfo->poolp = poolp; 1003 cinfo->pwfn = pwfn; 1004 cinfo->pwfn_arg = pwfn_arg; 1005 cinfo->created = PR_FALSE; 1006 cinfo->refCount = 1; 1007 1008 p7dcx = 1009 (SEC_PKCS7DecoderContext *)PORT_ZAlloc(sizeof(SEC_PKCS7DecoderContext)); 1010 if (p7dcx == NULL) { 1011 PORT_FreeArena(poolp, PR_FALSE); 1012 return NULL; 1013 } 1014 1015 p7dcx->tmp_poolp = PORT_NewArena(1024); /* XXX what is right value? */ 1016 if (p7dcx->tmp_poolp == NULL) { 1017 PORT_Free(p7dcx); 1018 PORT_FreeArena(poolp, PR_FALSE); 1019 return NULL; 1020 } 1021 1022 dcx = SEC_ASN1DecoderStart(poolp, cinfo, sec_PKCS7ContentInfoTemplate); 1023 if (dcx == NULL) { 1024 PORT_FreeArena(p7dcx->tmp_poolp, PR_FALSE); 1025 PORT_Free(p7dcx); 1026 PORT_FreeArena(poolp, PR_FALSE); 1027 return NULL; 1028 } 1029 1030 SEC_ASN1DecoderSetNotifyProc(dcx, sec_pkcs7_decoder_notify, p7dcx); 1031 1032 p7dcx->dcx = dcx; 1033 p7dcx->cinfo = cinfo; 1034 p7dcx->cb = cb; 1035 p7dcx->cb_arg = cb_arg; 1036 p7dcx->pwfn = pwfn; 1037 p7dcx->pwfn_arg = pwfn_arg; 1038 p7dcx->dkcb = decrypt_key_cb; 1039 p7dcx->dkcb_arg = decrypt_key_cb_arg; 1040 p7dcx->decrypt_allowed_cb = decrypt_allowed_cb; 1041 1042 return p7dcx; 1043 } 1044 1045 /* 1046 * Do the next chunk of PKCS7 decoding. If there is a problem, set 1047 * an error and return a failure status. Note that in the case of 1048 * an error, this routine is still prepared to be called again and 1049 * again in case that is the easiest route for our caller to take. 1050 * We simply detect it and do not do anything except keep setting 1051 * that error in case our caller has not noticed it yet... 1052 */ 1053 SECStatus 1054 SEC_PKCS7DecoderUpdate(SEC_PKCS7DecoderContext *p7dcx, 1055 const char *buf, unsigned long len) 1056 { 1057 if (!p7dcx) { 1058 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1059 return SECFailure; 1060 } 1061 1062 if (p7dcx->cinfo != NULL && p7dcx->dcx != NULL) { 1063 PORT_Assert(p7dcx->error == 0); 1064 if (p7dcx->error == 0) { 1065 if (SEC_ASN1DecoderUpdate(p7dcx->dcx, buf, len) != SECSuccess) { 1066 p7dcx->error = PORT_GetError(); 1067 PORT_Assert(p7dcx->error); 1068 if (p7dcx->error == 0) 1069 p7dcx->error = -1; 1070 } 1071 } 1072 } 1073 1074 if (p7dcx->error) { 1075 sec_pkcs7_decoder_abort_digests(&p7dcx->worker); 1076 if (p7dcx->worker.decryptobj) { 1077 sec_PKCS7DestroyDecryptObject(p7dcx->worker.decryptobj); 1078 p7dcx->worker.decryptobj = NULL; 1079 } 1080 if (p7dcx->dcx != NULL) { 1081 (void)SEC_ASN1DecoderFinish(p7dcx->dcx); 1082 p7dcx->dcx = NULL; 1083 } 1084 if (p7dcx->cinfo != NULL) { 1085 SEC_PKCS7DestroyContentInfo(p7dcx->cinfo); 1086 p7dcx->cinfo = NULL; 1087 } 1088 PORT_SetError(p7dcx->error); 1089 return SECFailure; 1090 } 1091 1092 return SECSuccess; 1093 } 1094 1095 SEC_PKCS7ContentInfo * 1096 SEC_PKCS7DecoderFinish(SEC_PKCS7DecoderContext *p7dcx) 1097 { 1098 SEC_PKCS7ContentInfo *cinfo; 1099 1100 sec_pkcs7_decoder_abort_digests(&p7dcx->worker); 1101 cinfo = p7dcx->cinfo; 1102 if (p7dcx->dcx != NULL) { 1103 if (SEC_ASN1DecoderFinish(p7dcx->dcx) != SECSuccess) { 1104 SEC_PKCS7DestroyContentInfo(cinfo); 1105 cinfo = NULL; 1106 } 1107 } 1108 /* free any NSS data structures */ 1109 if (p7dcx->worker.decryptobj) { 1110 sec_PKCS7DestroyDecryptObject(p7dcx->worker.decryptobj); 1111 p7dcx->worker.decryptobj = NULL; 1112 } 1113 1114 PORT_FreeArena(p7dcx->tmp_poolp, PR_FALSE); 1115 PORT_Free(p7dcx); 1116 return cinfo; 1117 } 1118 1119 SEC_PKCS7ContentInfo * 1120 SEC_PKCS7DecodeItem(SECItem *p7item, 1121 SEC_PKCS7DecoderContentCallback cb, void *cb_arg, 1122 SECKEYGetPasswordKey pwfn, void *pwfn_arg, 1123 SEC_PKCS7GetDecryptKeyCallback decrypt_key_cb, 1124 void *decrypt_key_cb_arg, 1125 SEC_PKCS7DecryptionAllowedCallback decrypt_allowed_cb) 1126 { 1127 SEC_PKCS7DecoderContext *p7dcx; 1128 1129 p7dcx = SEC_PKCS7DecoderStart(cb, cb_arg, pwfn, pwfn_arg, decrypt_key_cb, 1130 decrypt_key_cb_arg, decrypt_allowed_cb); 1131 if (!p7dcx) { 1132 /* error code is set */ 1133 return NULL; 1134 } 1135 (void)SEC_PKCS7DecoderUpdate(p7dcx, (char *)p7item->data, p7item->len); 1136 return SEC_PKCS7DecoderFinish(p7dcx); 1137 } 1138 1139 /* 1140 * Abort the ASN.1 stream. Used by pkcs 12 1141 */ 1142 void 1143 SEC_PKCS7DecoderAbort(SEC_PKCS7DecoderContext *p7dcx, int error) 1144 { 1145 PORT_Assert(p7dcx); 1146 if (!p7dcx) { 1147 return; 1148 } 1149 1150 /* ensure any streaming helpers are torn down */ 1151 sec_pkcs7_decoder_abort_digests(&p7dcx->worker); 1152 if (p7dcx->worker.decryptobj) { 1153 sec_PKCS7DestroyDecryptObject(p7dcx->worker.decryptobj); 1154 p7dcx->worker.decryptobj = NULL; 1155 } 1156 1157 SEC_ASN1DecoderAbort(p7dcx->dcx, error); 1158 } 1159 1160 /* 1161 * If the thing contains any certs or crls return true; false otherwise. 1162 */ 1163 PRBool 1164 SEC_PKCS7ContainsCertsOrCrls(SEC_PKCS7ContentInfo *cinfo) 1165 { 1166 SECOidTag kind; 1167 SECItem **certs; 1168 CERTSignedCrl **crls; 1169 1170 kind = SEC_PKCS7ContentType(cinfo); 1171 switch (kind) { 1172 default: 1173 case SEC_OID_PKCS7_DATA: 1174 case SEC_OID_PKCS7_DIGESTED_DATA: 1175 case SEC_OID_PKCS7_ENVELOPED_DATA: 1176 case SEC_OID_PKCS7_ENCRYPTED_DATA: 1177 return PR_FALSE; 1178 case SEC_OID_PKCS7_SIGNED_DATA: 1179 certs = cinfo->content.signedData->rawCerts; 1180 crls = cinfo->content.signedData->crls; 1181 break; 1182 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: 1183 certs = cinfo->content.signedAndEnvelopedData->rawCerts; 1184 crls = cinfo->content.signedAndEnvelopedData->crls; 1185 break; 1186 } 1187 1188 /* 1189 * I know this could be collapsed, but I was in a mood to be explicit. 1190 */ 1191 if (certs != NULL && certs[0] != NULL) 1192 return PR_TRUE; 1193 else if (crls != NULL && crls[0] != NULL) 1194 return PR_TRUE; 1195 else 1196 return PR_FALSE; 1197 } 1198 1199 /* return the content length...could use GetContent, however we 1200 * need the encrypted content length 1201 */ 1202 PRBool 1203 SEC_PKCS7IsContentEmpty(SEC_PKCS7ContentInfo *cinfo, unsigned int minLen) 1204 { 1205 SECItem *item = NULL; 1206 1207 if (cinfo == NULL) { 1208 return PR_TRUE; 1209 } 1210 1211 switch (SEC_PKCS7ContentType(cinfo)) { 1212 case SEC_OID_PKCS7_DATA: 1213 item = cinfo->content.data; 1214 break; 1215 case SEC_OID_PKCS7_ENCRYPTED_DATA: 1216 item = &cinfo->content.encryptedData->encContentInfo.encContent; 1217 break; 1218 default: 1219 /* add other types */ 1220 return PR_FALSE; 1221 } 1222 1223 if (!item) { 1224 return PR_TRUE; 1225 } else if (item->len <= minLen) { 1226 return PR_TRUE; 1227 } 1228 1229 return PR_FALSE; 1230 } 1231 1232 PRBool 1233 SEC_PKCS7ContentIsEncrypted(SEC_PKCS7ContentInfo *cinfo) 1234 { 1235 SECOidTag kind; 1236 1237 kind = SEC_PKCS7ContentType(cinfo); 1238 switch (kind) { 1239 default: 1240 case SEC_OID_PKCS7_DATA: 1241 case SEC_OID_PKCS7_DIGESTED_DATA: 1242 case SEC_OID_PKCS7_SIGNED_DATA: 1243 return PR_FALSE; 1244 case SEC_OID_PKCS7_ENCRYPTED_DATA: 1245 case SEC_OID_PKCS7_ENVELOPED_DATA: 1246 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: 1247 return PR_TRUE; 1248 } 1249 } 1250 1251 /* 1252 * If the PKCS7 content has a signature (not just *could* have a signature) 1253 * return true; false otherwise. This can/should be called before calling 1254 * VerifySignature, which will always indicate failure if no signature is 1255 * present, but that does not mean there even was a signature! 1256 * Note that the content itself can be empty (detached content was sent 1257 * another way); it is the presence of the signature that matters. 1258 */ 1259 PRBool 1260 SEC_PKCS7ContentIsSigned(SEC_PKCS7ContentInfo *cinfo) 1261 { 1262 SECOidTag kind; 1263 SEC_PKCS7SignerInfo **signerinfos; 1264 1265 kind = SEC_PKCS7ContentType(cinfo); 1266 switch (kind) { 1267 default: 1268 case SEC_OID_PKCS7_DATA: 1269 case SEC_OID_PKCS7_DIGESTED_DATA: 1270 case SEC_OID_PKCS7_ENVELOPED_DATA: 1271 case SEC_OID_PKCS7_ENCRYPTED_DATA: 1272 return PR_FALSE; 1273 case SEC_OID_PKCS7_SIGNED_DATA: 1274 signerinfos = cinfo->content.signedData->signerInfos; 1275 break; 1276 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: 1277 signerinfos = cinfo->content.signedAndEnvelopedData->signerInfos; 1278 break; 1279 } 1280 1281 /* 1282 * I know this could be collapsed; but I kind of think it will get 1283 * more complicated before I am finished, so... 1284 */ 1285 if (signerinfos != NULL && signerinfos[0] != NULL) 1286 return PR_TRUE; 1287 else 1288 return PR_FALSE; 1289 } 1290 1291 /* 1292 * sec_pkcs7_verify_signature 1293 * 1294 * Look at a PKCS7 contentInfo and check if the signature is good. 1295 * The digest was either calculated earlier (and is stored in the 1296 * contentInfo itself) or is passed in via "detached_digest". 1297 * 1298 * The verification checks that the signing cert is valid and trusted 1299 * for the purpose specified by "certusage" at 1300 * - "*atTime" if "atTime" is not null, or 1301 * - the signing time if the signing time is available in "cinfo", or 1302 * - the current time (as returned by PR_Now). 1303 * 1304 * In addition, if "keepcerts" is true, add any new certificates found 1305 * into our local database. 1306 * 1307 * XXX Each place which returns PR_FALSE should be sure to have a good 1308 * error set for inspection by the caller. Alternatively, we could create 1309 * an enumeration of success and each type of failure and return that 1310 * instead of a boolean. For now, the default in a bad situation is to 1311 * set the error to SEC_ERROR_PKCS7_BAD_SIGNATURE. But this should be 1312 * reviewed; better (more specific) errors should be possible (to distinguish 1313 * a signature failure from a badly-formed pkcs7 signedData, for example). 1314 * Some of the errors should probably just be SEC_ERROR_BAD_SIGNATURE, 1315 * but that has a less helpful error string associated with it right now; 1316 * if/when that changes, review and change these as needed. 1317 * 1318 * XXX This is broken wrt signedAndEnvelopedData. In that case, the 1319 * message digest is doubly encrypted -- first encrypted with the signer 1320 * private key but then again encrypted with the bulk encryption key used 1321 * to encrypt the content. So before we can pass the digest to VerifyDigest, 1322 * we need to decrypt it with the bulk encryption key. Also, in this case, 1323 * there should be NO authenticatedAttributes (signerinfo->authAttr should 1324 * be NULL). 1325 */ 1326 static PRBool 1327 sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, 1328 SECCertUsage certusage, 1329 const SECItem *detached_digest, 1330 HASH_HashType digest_type, 1331 PRBool keepcerts, 1332 const PRTime *atTime) 1333 { 1334 SECAlgorithmID **digestalgs, *bulkid; 1335 const SECItem *digest; 1336 SECItem **digests; 1337 SECItem **rawcerts; 1338 SEC_PKCS7SignerInfo **signerinfos, *signerinfo; 1339 CERTCertificate *cert, **certs; 1340 PRBool goodsig; 1341 CERTCertDBHandle *certdb, *defaultdb; 1342 SECOidTag encTag, digestTag; 1343 HASH_HashType found_type; 1344 int i, certcount; 1345 SECKEYPublicKey *publickey; 1346 SECItem *content_type; 1347 PK11SymKey *sigkey; 1348 SECItem *encoded_stime; 1349 PRTime stime; 1350 PRTime verificationTime; 1351 SECStatus rv; 1352 1353 /* 1354 * Everything needed in order to "goto done" safely. 1355 */ 1356 goodsig = PR_FALSE; 1357 certcount = 0; 1358 cert = NULL; 1359 certs = NULL; 1360 certdb = NULL; 1361 defaultdb = CERT_GetDefaultCertDB(); 1362 publickey = NULL; 1363 1364 if (!SEC_PKCS7ContentIsSigned(cinfo)) { 1365 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1366 goto done; 1367 } 1368 1369 PORT_Assert(cinfo->contentTypeTag != NULL); 1370 1371 switch (cinfo->contentTypeTag->offset) { 1372 default: 1373 case SEC_OID_PKCS7_DATA: 1374 case SEC_OID_PKCS7_DIGESTED_DATA: 1375 case SEC_OID_PKCS7_ENVELOPED_DATA: 1376 case SEC_OID_PKCS7_ENCRYPTED_DATA: 1377 /* Could only get here if SEC_PKCS7ContentIsSigned is broken. */ 1378 PORT_Assert(0); 1379 case SEC_OID_PKCS7_SIGNED_DATA: { 1380 SEC_PKCS7SignedData *sdp; 1381 1382 sdp = cinfo->content.signedData; 1383 digestalgs = sdp->digestAlgorithms; 1384 digests = sdp->digests; 1385 rawcerts = sdp->rawCerts; 1386 signerinfos = sdp->signerInfos; 1387 content_type = &(sdp->contentInfo.contentType); 1388 sigkey = NULL; 1389 bulkid = NULL; 1390 } break; 1391 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: { 1392 SEC_PKCS7SignedAndEnvelopedData *saedp; 1393 1394 saedp = cinfo->content.signedAndEnvelopedData; 1395 digestalgs = saedp->digestAlgorithms; 1396 digests = saedp->digests; 1397 rawcerts = saedp->rawCerts; 1398 signerinfos = saedp->signerInfos; 1399 content_type = &(saedp->encContentInfo.contentType); 1400 sigkey = saedp->sigKey; 1401 bulkid = &(saedp->encContentInfo.contentEncAlg); 1402 } break; 1403 } 1404 1405 if ((signerinfos == NULL) || (signerinfos[0] == NULL)) { 1406 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1407 goto done; 1408 } 1409 1410 /* 1411 * XXX Need to handle multiple signatures; checking them is easy, 1412 * but what should be the semantics here (like, return value)? 1413 */ 1414 if (signerinfos[1] != NULL) { 1415 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1416 goto done; 1417 } 1418 1419 signerinfo = signerinfos[0]; 1420 1421 /* 1422 * XXX I would like to just pass the issuerAndSN, along with the rawcerts 1423 * and crls, to some function that did all of this certificate stuff 1424 * (open/close the database if necessary, verifying the certs, etc.) 1425 * and gave me back a cert pointer if all was good. 1426 */ 1427 certdb = defaultdb; 1428 if (certdb == NULL) { 1429 goto done; 1430 } 1431 1432 certcount = 0; 1433 if (rawcerts != NULL) { 1434 for (; rawcerts[certcount] != NULL; certcount++) { 1435 /* just counting */ 1436 } 1437 } 1438 1439 /* 1440 * Note that the result of this is that each cert in "certs" 1441 * needs to be destroyed. 1442 */ 1443 rv = CERT_ImportCerts(certdb, certusage, certcount, rawcerts, &certs, 1444 keepcerts, PR_FALSE, NULL); 1445 if (rv != SECSuccess) { 1446 goto done; 1447 } 1448 1449 /* 1450 * This cert will also need to be freed, but since we save it 1451 * in signerinfo for later, we do not want to destroy it when 1452 * we leave this function -- we let the clean-up of the entire 1453 * cinfo structure later do the destroy of this cert. 1454 */ 1455 cert = CERT_FindCertByIssuerAndSN(certdb, signerinfo->issuerAndSN); 1456 if (cert == NULL) { 1457 goto done; 1458 } 1459 1460 signerinfo->cert = cert; 1461 1462 /* 1463 * Get and convert the signing time; if available, it will be used 1464 * both on the cert verification and for importing the sender 1465 * email profile. 1466 */ 1467 encoded_stime = SEC_PKCS7GetSigningTime(cinfo); 1468 if (encoded_stime != NULL) { 1469 if (DER_DecodeTimeChoice(&stime, encoded_stime) != SECSuccess) 1470 encoded_stime = NULL; /* conversion failed, so pretend none */ 1471 } 1472 1473 /* 1474 * XXX This uses the signing time, if available. Additionally, we 1475 * might want to, if there is no signing time, get the message time 1476 * from the mail header itself, and use that. That would require 1477 * a change to our interface though, and for S/MIME callers to pass 1478 * in a time (and for non-S/MIME callers to pass in nothing, or 1479 * maybe make them pass in the current time, always?). 1480 */ 1481 if (atTime) { 1482 verificationTime = *atTime; 1483 } else if (encoded_stime != NULL) { 1484 verificationTime = stime; 1485 } else { 1486 verificationTime = PR_Now(); 1487 } 1488 if (CERT_VerifyCert(certdb, cert, PR_TRUE, certusage, verificationTime, 1489 cinfo->pwfn_arg, NULL) != SECSuccess) { 1490 /* 1491 * XXX Give the user an option to check the signature anyway? 1492 * If we want to do this, need to give a way to leave and display 1493 * some dialog and get the answer and come back through (or do 1494 * the rest of what we do below elsewhere, maybe by putting it 1495 * in a function that we call below and could call from a dialog 1496 * finish handler). 1497 */ 1498 goto savecert; 1499 } 1500 1501 publickey = CERT_ExtractPublicKey(cert); 1502 if (publickey == NULL) 1503 goto done; 1504 1505 /* 1506 * XXX No! If digests is empty, see if we can create it now by 1507 * digesting the contents. This is necessary if we want to allow 1508 * somebody to do a simple decode (without filtering, etc.) and 1509 * then later call us here to do the verification. 1510 * OR, we can just specify that the interface to this routine 1511 * *requires* that the digest(s) be done before calling and either 1512 * stashed in the struct itself or passed in explicitly (as would 1513 * be done for detached contents). 1514 */ 1515 if ((digests == NULL || digests[0] == NULL) && (detached_digest == NULL || detached_digest->data == NULL)) 1516 goto done; 1517 1518 /* 1519 * Find and confirm digest algorithm. 1520 */ 1521 digestTag = SECOID_FindOIDTag(&(signerinfo->digestAlg.algorithm)); 1522 1523 /* make sure we understand the digest type first */ 1524 found_type = HASH_GetHashTypeByOidTag(digestTag); 1525 if ((digestTag == SEC_OID_UNKNOWN) || (found_type == HASH_AlgNULL)) { 1526 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1527 goto done; 1528 } 1529 1530 if (detached_digest != NULL) { 1531 unsigned int hashLen = HASH_ResultLen(found_type); 1532 1533 if (digest_type != found_type || 1534 detached_digest->len != hashLen) { 1535 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1536 goto done; 1537 } 1538 digest = detached_digest; 1539 } else { 1540 PORT_Assert(digestalgs != NULL && digestalgs[0] != NULL); 1541 if (digestalgs == NULL || digestalgs[0] == NULL) { 1542 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1543 goto done; 1544 } 1545 1546 /* 1547 * pick digest matching signerinfo->digestAlg from digests 1548 */ 1549 for (i = 0; digestalgs[i] != NULL; i++) { 1550 if (SECOID_FindOIDTag(&(digestalgs[i]->algorithm)) == digestTag) 1551 break; 1552 } 1553 if (digestalgs[i] == NULL) { 1554 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1555 goto done; 1556 } 1557 1558 digest = digests[i]; 1559 } 1560 1561 encTag = SECOID_FindOIDTag(&(signerinfo->digestEncAlg.algorithm)); 1562 if (encTag == SEC_OID_UNKNOWN) { 1563 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1564 goto done; 1565 } 1566 1567 if (signerinfo->authAttr != NULL) { 1568 SEC_PKCS7Attribute *attr; 1569 SECItem *value; 1570 SECItem encoded_attrs; 1571 1572 /* 1573 * We have a sigkey only for signedAndEnvelopedData, which is 1574 * not supposed to have any authenticated attributes. 1575 */ 1576 if (sigkey != NULL) { 1577 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1578 goto done; 1579 } 1580 1581 /* 1582 * PKCS #7 says that if there are any authenticated attributes, 1583 * then there must be one for content type which matches the 1584 * content type of the content being signed, and there must 1585 * be one for message digest which matches our message digest. 1586 * So check these things first. 1587 * XXX Might be nice to have a compare-attribute-value function 1588 * which could collapse the following nicely. 1589 */ 1590 attr = sec_PKCS7FindAttribute(signerinfo->authAttr, 1591 SEC_OID_PKCS9_CONTENT_TYPE, PR_TRUE); 1592 value = sec_PKCS7AttributeValue(attr); 1593 if (value == NULL || value->len != content_type->len) { 1594 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1595 goto done; 1596 } 1597 if (PORT_Memcmp(value->data, content_type->data, value->len) != 0) { 1598 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1599 goto done; 1600 } 1601 1602 attr = sec_PKCS7FindAttribute(signerinfo->authAttr, 1603 SEC_OID_PKCS9_MESSAGE_DIGEST, PR_TRUE); 1604 value = sec_PKCS7AttributeValue(attr); 1605 if (value == NULL || value->len != digest->len) { 1606 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1607 goto done; 1608 } 1609 if (PORT_Memcmp(value->data, digest->data, value->len) != 0) { 1610 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1611 goto done; 1612 } 1613 1614 /* 1615 * Okay, we met the constraints of the basic attributes. 1616 * Now check the signature, which is based on a digest of 1617 * the DER-encoded authenticated attributes. So, first we 1618 * encode and then we digest/verify. 1619 */ 1620 encoded_attrs.data = NULL; 1621 encoded_attrs.len = 0; 1622 if (sec_PKCS7EncodeAttributes(NULL, &encoded_attrs, 1623 &(signerinfo->authAttr)) == NULL) 1624 goto done; 1625 1626 if (encoded_attrs.data == NULL || encoded_attrs.len == 0) { 1627 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1628 goto done; 1629 } 1630 1631 goodsig = (PRBool)(VFY_VerifyDataDirect(encoded_attrs.data, 1632 encoded_attrs.len, 1633 publickey, &(signerinfo->encDigest), 1634 encTag, digestTag, NULL, 1635 cinfo->pwfn_arg) == SECSuccess); 1636 PORT_Free(encoded_attrs.data); 1637 } else { 1638 SECItem *sig; 1639 SECItem holder; 1640 1641 /* 1642 * No authenticated attributes. 1643 * The signature is based on the plain message digest. 1644 */ 1645 1646 sig = &(signerinfo->encDigest); 1647 if (sig->len == 0) { /* bad signature */ 1648 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1649 goto done; 1650 } 1651 1652 if (sigkey != NULL) { 1653 sec_PKCS7CipherObject *decryptobj; 1654 unsigned int buflen; 1655 1656 /* 1657 * For signedAndEnvelopedData, we first must decrypt the encrypted 1658 * digest with the bulk encryption key. The result is the normal 1659 * encrypted digest (aka the signature). 1660 */ 1661 decryptobj = sec_PKCS7CreateDecryptObject(sigkey, bulkid); 1662 if (decryptobj == NULL) 1663 goto done; 1664 1665 buflen = sec_PKCS7DecryptLength(decryptobj, sig->len, PR_TRUE); 1666 PORT_Assert(buflen); 1667 if (buflen == 0) { /* something is wrong */ 1668 sec_PKCS7DestroyDecryptObject(decryptobj); 1669 goto done; 1670 } 1671 1672 holder.data = (unsigned char *)PORT_Alloc(buflen); 1673 if (holder.data == NULL) { 1674 sec_PKCS7DestroyDecryptObject(decryptobj); 1675 goto done; 1676 } 1677 1678 rv = sec_PKCS7Decrypt(decryptobj, holder.data, &holder.len, buflen, 1679 sig->data, sig->len, PR_TRUE); 1680 sec_PKCS7DestroyDecryptObject(decryptobj); 1681 if (rv != SECSuccess) { 1682 goto done; 1683 } 1684 1685 sig = &holder; 1686 } 1687 1688 goodsig = (PRBool)(VFY_VerifyDigestDirect(digest, publickey, sig, 1689 encTag, digestTag, cinfo->pwfn_arg) == SECSuccess); 1690 1691 if (sigkey != NULL) { 1692 PORT_Assert(sig == &holder); 1693 PORT_ZFree(holder.data, holder.len); 1694 } 1695 } 1696 1697 if (!goodsig) { 1698 /* 1699 * XXX Change the generic error into our specific one, because 1700 * in that case we get a better explanation out of the Security 1701 * Advisor. This is really a bug in our error strings (the 1702 * "generic" error has a lousy/wrong message associated with it 1703 * which assumes the signature verification was done for the 1704 * purposes of checking the issuer signature on a certificate) 1705 * but this is at least an easy workaround and/or in the 1706 * Security Advisor, which specifically checks for the error 1707 * SEC_ERROR_PKCS7_BAD_SIGNATURE and gives more explanation 1708 * in that case but does not similarly check for 1709 * SEC_ERROR_BAD_SIGNATURE. It probably should, but then would 1710 * probably say the wrong thing in the case that it *was* the 1711 * certificate signature check that failed during the cert 1712 * verification done above. Our error handling is really a mess. 1713 */ 1714 if (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE) 1715 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); 1716 } 1717 1718 savecert: 1719 /* 1720 * Only save the smime profile if we are checking an email message and 1721 * the cert has an email address in it. 1722 */ 1723 if (cert->emailAddr && cert->emailAddr[0] && 1724 ((certusage == certUsageEmailSigner) || 1725 (certusage == certUsageEmailRecipient))) { 1726 SECItem *profile = NULL; 1727 int save_error; 1728 1729 /* 1730 * Remember the current error set because we do not care about 1731 * anything set by the functions we are about to call. 1732 */ 1733 save_error = PORT_GetError(); 1734 1735 if (goodsig && (signerinfo->authAttr != NULL)) { 1736 /* 1737 * If the signature is good, then we can save the S/MIME profile, 1738 * if we have one. 1739 */ 1740 SEC_PKCS7Attribute *attr; 1741 1742 attr = sec_PKCS7FindAttribute(signerinfo->authAttr, 1743 SEC_OID_PKCS9_SMIME_CAPABILITIES, 1744 PR_TRUE); 1745 profile = sec_PKCS7AttributeValue(attr); 1746 } 1747 1748 rv = CERT_SaveSMimeProfile(cert, profile, encoded_stime); 1749 1750 /* 1751 * Restore the saved error in case the calls above set a new 1752 * one that we do not actually care about. 1753 */ 1754 PORT_SetError(save_error); 1755 1756 /* 1757 * XXX Failure is not indicated anywhere -- the signature 1758 * verification itself is unaffected by whether or not the 1759 * profile was successfully saved. 1760 */ 1761 } 1762 1763 done: 1764 1765 /* 1766 * See comment above about why we do not want to destroy cert 1767 * itself here. 1768 */ 1769 1770 if (certs != NULL) 1771 CERT_DestroyCertArray(certs, certcount); 1772 1773 if (publickey != NULL) 1774 SECKEY_DestroyPublicKey(publickey); 1775 1776 return goodsig; 1777 } 1778 1779 /* 1780 * SEC_PKCS7VerifySignature 1781 * Look at a PKCS7 contentInfo and check if the signature is good. 1782 * The verification checks that the signing cert is valid and trusted 1783 * for the purpose specified by "certusage". 1784 * 1785 * In addition, if "keepcerts" is true, add any new certificates found 1786 * into our local database. 1787 */ 1788 PRBool 1789 SEC_PKCS7VerifySignature(SEC_PKCS7ContentInfo *cinfo, 1790 SECCertUsage certusage, 1791 PRBool keepcerts) 1792 { 1793 return sec_pkcs7_verify_signature(cinfo, certusage, 1794 NULL, HASH_AlgNULL, keepcerts, NULL); 1795 } 1796 1797 /* 1798 * SEC_PKCS7VerifyDetachedSignature 1799 * Look at a PKCS7 contentInfo and check if the signature matches 1800 * a passed-in digest (calculated, supposedly, from detached contents). 1801 * The verification checks that the signing cert is valid and trusted 1802 * for the purpose specified by "certusage". 1803 * 1804 * In addition, if "keepcerts" is true, add any new certificates found 1805 * into our local database. 1806 */ 1807 PRBool 1808 SEC_PKCS7VerifyDetachedSignature(SEC_PKCS7ContentInfo *cinfo, 1809 SECCertUsage certusage, 1810 const SECItem *detached_digest, 1811 HASH_HashType digest_type, 1812 PRBool keepcerts) 1813 { 1814 return sec_pkcs7_verify_signature(cinfo, certusage, 1815 detached_digest, digest_type, 1816 keepcerts, NULL); 1817 } 1818 1819 /* 1820 * SEC_PKCS7VerifyDetachedSignatureAtTime 1821 * Look at a PKCS7 contentInfo and check if the signature matches 1822 * a passed-in digest (calculated, supposedly, from detached contents). 1823 * The verification checks that the signing cert is valid and trusted 1824 * for the purpose specified by "certusage" at time "atTime". 1825 * 1826 * In addition, if "keepcerts" is true, add any new certificates found 1827 * into our local database. 1828 */ 1829 PRBool 1830 SEC_PKCS7VerifyDetachedSignatureAtTime(SEC_PKCS7ContentInfo *cinfo, 1831 SECCertUsage certusage, 1832 const SECItem *detached_digest, 1833 HASH_HashType digest_type, 1834 PRBool keepcerts, 1835 PRTime atTime) 1836 { 1837 return sec_pkcs7_verify_signature(cinfo, certusage, 1838 detached_digest, digest_type, 1839 keepcerts, &atTime); 1840 } 1841 1842 /* 1843 * Return the asked-for portion of the name of the signer of a PKCS7 1844 * signed object. 1845 * 1846 * Returns a pointer to allocated memory, which must be freed. 1847 * A NULL return value is an error. 1848 */ 1849 1850 #define sec_common_name 1 1851 #define sec_email_address 2 1852 1853 static char * 1854 sec_pkcs7_get_signer_cert_info(SEC_PKCS7ContentInfo *cinfo, int selector) 1855 { 1856 SECOidTag kind; 1857 SEC_PKCS7SignerInfo **signerinfos; 1858 CERTCertificate *signercert; 1859 char *container; 1860 1861 kind = SEC_PKCS7ContentType(cinfo); 1862 switch (kind) { 1863 default: 1864 case SEC_OID_PKCS7_DATA: 1865 case SEC_OID_PKCS7_DIGESTED_DATA: 1866 case SEC_OID_PKCS7_ENVELOPED_DATA: 1867 case SEC_OID_PKCS7_ENCRYPTED_DATA: 1868 PORT_Assert(0); 1869 return NULL; 1870 case SEC_OID_PKCS7_SIGNED_DATA: { 1871 SEC_PKCS7SignedData *sdp; 1872 1873 sdp = cinfo->content.signedData; 1874 signerinfos = sdp->signerInfos; 1875 } break; 1876 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: { 1877 SEC_PKCS7SignedAndEnvelopedData *saedp; 1878 1879 saedp = cinfo->content.signedAndEnvelopedData; 1880 signerinfos = saedp->signerInfos; 1881 } break; 1882 } 1883 1884 if (signerinfos == NULL || signerinfos[0] == NULL) 1885 return NULL; 1886 1887 signercert = signerinfos[0]->cert; 1888 1889 /* 1890 * No cert there; see if we can find one by calling verify ourselves. 1891 */ 1892 if (signercert == NULL) { 1893 /* 1894 * The cert usage does not matter in this case, because we do not 1895 * actually care about the verification itself, but we have to pick 1896 * some valid usage to pass in. 1897 */ 1898 (void)sec_pkcs7_verify_signature(cinfo, certUsageEmailSigner, 1899 NULL, HASH_AlgNULL, PR_FALSE, NULL); 1900 signercert = signerinfos[0]->cert; 1901 if (signercert == NULL) 1902 return NULL; 1903 } 1904 1905 switch (selector) { 1906 case sec_common_name: 1907 container = CERT_GetCommonName(&signercert->subject); 1908 break; 1909 case sec_email_address: 1910 if (signercert->emailAddr && signercert->emailAddr[0]) { 1911 container = PORT_Strdup(signercert->emailAddr); 1912 } else { 1913 container = NULL; 1914 } 1915 break; 1916 default: 1917 PORT_Assert(0); 1918 container = NULL; 1919 break; 1920 } 1921 1922 return container; 1923 } 1924 1925 char * 1926 SEC_PKCS7GetSignerCommonName(SEC_PKCS7ContentInfo *cinfo) 1927 { 1928 return sec_pkcs7_get_signer_cert_info(cinfo, sec_common_name); 1929 } 1930 1931 char * 1932 SEC_PKCS7GetSignerEmailAddress(SEC_PKCS7ContentInfo *cinfo) 1933 { 1934 return sec_pkcs7_get_signer_cert_info(cinfo, sec_email_address); 1935 } 1936 1937 /* 1938 * Return the signing time, in UTCTime format, of a PKCS7 contentInfo. 1939 */ 1940 SECItem * 1941 SEC_PKCS7GetSigningTime(SEC_PKCS7ContentInfo *cinfo) 1942 { 1943 SEC_PKCS7SignerInfo **signerinfos; 1944 SEC_PKCS7Attribute *attr; 1945 1946 if (SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_SIGNED_DATA) 1947 return NULL; 1948 1949 signerinfos = cinfo->content.signedData->signerInfos; 1950 1951 /* 1952 * No signature, or more than one, means no deal. 1953 */ 1954 if (signerinfos == NULL || signerinfos[0] == NULL || signerinfos[1] != NULL) 1955 return NULL; 1956 1957 attr = sec_PKCS7FindAttribute(signerinfos[0]->authAttr, 1958 SEC_OID_PKCS9_SIGNING_TIME, PR_TRUE); 1959 return sec_PKCS7AttributeValue(attr); 1960 }