p7local.c (44906B)
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 * Support routines for PKCS7 implementation, none of which are exported. 7 * This file should only contain things that are needed by both the 8 * encoding/creation side *and* the decoding/decryption side. Anything 9 * else should be static routines in the appropriate file. 10 */ 11 12 #include "p7local.h" 13 14 #include "cryptohi.h" 15 #include "secasn1.h" 16 #include "secoid.h" 17 #include "secitem.h" 18 #include "pk11func.h" 19 #include "secpkcs5.h" 20 #include "secerr.h" 21 22 #include <limits.h> 23 24 /* 25 * ------------------------------------------------------------------- 26 * Cipher stuff. 27 */ 28 29 typedef SECStatus (*sec_pkcs7_cipher_function)(void *, 30 unsigned char *, 31 unsigned *, 32 unsigned int, 33 const unsigned char *, 34 unsigned int); 35 typedef SECStatus (*sec_pkcs7_cipher_destroy)(void *, PRBool); 36 37 static SECStatus 38 SECPKCS7Cipher_PK11_CipherOp(void *vctx, unsigned char *output, 39 unsigned int *outputLen, unsigned int maxOutputLen, 40 const unsigned char *input, unsigned int inputLen) 41 { 42 PK11Context *ctx = vctx; 43 PORT_Assert(maxOutputLen <= INT_MAX); 44 int signedOutputLen = maxOutputLen; 45 SECStatus rv = PK11_CipherOp(ctx, output, &signedOutputLen, maxOutputLen, input, inputLen); 46 PORT_Assert(signedOutputLen >= 0); 47 *outputLen = signedOutputLen; 48 return rv; 49 } 50 static SECStatus 51 SECPKCS7Cipher_PK11_DestroyContext(void *vctx, PRBool freeit) 52 { 53 PK11Context *ctx = vctx; 54 PK11_DestroyContext(ctx, freeit); 55 return SECSuccess; 56 } 57 58 #define BLOCK_SIZE 4096 59 60 struct sec_pkcs7_cipher_object { 61 void *cx; 62 sec_pkcs7_cipher_function doit; 63 sec_pkcs7_cipher_destroy destroy; 64 PRBool encrypt; 65 int block_size; 66 int pad_size; 67 int pending_count; 68 unsigned char pending_buf[BLOCK_SIZE]; 69 }; 70 71 SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate) 72 SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate) 73 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 74 SEC_ASN1_MKSUB(SEC_OctetStringTemplate) 75 SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate) 76 77 /* 78 * Create a cipher object to do decryption, based on the given bulk 79 * encryption key and algorithm identifier (which may include an iv). 80 * 81 * XXX This interface, or one similar, would be really nice available 82 * in general... I tried to keep the pkcs7-specific stuff (mostly 83 * having to do with padding) out of here. 84 * 85 * XXX Once both are working, it might be nice to combine this and the 86 * function below (for starting up encryption) into one routine, and just 87 * have two simple cover functions which call it. 88 */ 89 sec_PKCS7CipherObject * 90 sec_PKCS7CreateDecryptObject(PK11SymKey *key, SECAlgorithmID *algid) 91 { 92 sec_PKCS7CipherObject *result; 93 SECOidTag algtag; 94 void *ciphercx; 95 CK_MECHANISM_TYPE cryptoMechType; 96 PK11SlotInfo *slot; 97 SECItem *param = NULL; 98 99 result = (struct sec_pkcs7_cipher_object *) 100 PORT_ZAlloc(sizeof(struct sec_pkcs7_cipher_object)); 101 if (result == NULL) 102 return NULL; 103 104 ciphercx = NULL; 105 algtag = SECOID_GetAlgorithmTag(algid); 106 107 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { 108 SECItem *pwitem; 109 110 pwitem = (SECItem *)PK11_GetSymKeyUserData(key); 111 if (!pwitem) { 112 PORT_Free(result); 113 return NULL; 114 } 115 116 cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); 117 if (cryptoMechType == CKM_INVALID_MECHANISM) { 118 PORT_Free(result); 119 SECITEM_FreeItem(param, PR_TRUE); 120 return NULL; 121 } 122 } else { 123 cryptoMechType = PK11_AlgtagToMechanism(algtag); 124 param = PK11_ParamFromAlgid(algid); 125 if (param == NULL) { 126 PORT_Free(result); 127 return NULL; 128 } 129 } 130 131 result->pad_size = PK11_GetBlockSize(cryptoMechType, param); 132 slot = PK11_GetSlotFromKey(key); 133 result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; 134 PK11_FreeSlot(slot); 135 ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT, 136 key, param); 137 SECITEM_FreeItem(param, PR_TRUE); 138 if (ciphercx == NULL) { 139 PORT_Free(result); 140 return NULL; 141 } 142 143 result->cx = ciphercx; 144 result->doit = SECPKCS7Cipher_PK11_CipherOp; 145 result->destroy = SECPKCS7Cipher_PK11_DestroyContext; 146 result->encrypt = PR_FALSE; 147 result->pending_count = 0; 148 149 return result; 150 } 151 152 /* 153 * Create a cipher object to do encryption, based on the given bulk 154 * encryption key and algorithm tag. Fill in the algorithm identifier 155 * (which may include an iv) appropriately. 156 * 157 * XXX This interface, or one similar, would be really nice available 158 * in general... I tried to keep the pkcs7-specific stuff (mostly 159 * having to do with padding) out of here. 160 * 161 * XXX Once both are working, it might be nice to combine this and the 162 * function above (for starting up decryption) into one routine, and just 163 * have two simple cover functions which call it. 164 */ 165 sec_PKCS7CipherObject * 166 sec_PKCS7CreateEncryptObject(PLArenaPool *poolp, PK11SymKey *key, 167 SECOidTag algtag, SECAlgorithmID *algid) 168 { 169 sec_PKCS7CipherObject *result; 170 void *ciphercx; 171 SECStatus rv; 172 CK_MECHANISM_TYPE cryptoMechType; 173 PK11SlotInfo *slot; 174 SECItem *param = NULL; 175 PRBool needToEncodeAlgid = PR_FALSE; 176 177 result = (struct sec_pkcs7_cipher_object *) 178 PORT_ZAlloc(sizeof(struct sec_pkcs7_cipher_object)); 179 if (result == NULL) 180 return NULL; 181 182 ciphercx = NULL; 183 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { 184 SECItem *pwitem; 185 186 pwitem = (SECItem *)PK11_GetSymKeyUserData(key); 187 if (!pwitem) { 188 PORT_Free(result); 189 return NULL; 190 } 191 192 cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); 193 if (cryptoMechType == CKM_INVALID_MECHANISM) { 194 PORT_Free(result); 195 SECITEM_FreeItem(param, PR_TRUE); 196 return NULL; 197 } 198 } else { 199 cryptoMechType = PK11_AlgtagToMechanism(algtag); 200 param = PK11_GenerateNewParam(cryptoMechType, key); 201 if (param == NULL) { 202 PORT_Free(result); 203 return NULL; 204 } 205 needToEncodeAlgid = PR_TRUE; 206 } 207 208 result->pad_size = PK11_GetBlockSize(cryptoMechType, param); 209 slot = PK11_GetSlotFromKey(key); 210 result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; 211 PK11_FreeSlot(slot); 212 ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT, 213 key, param); 214 if (ciphercx == NULL) { 215 PORT_Free(result); 216 SECITEM_FreeItem(param, PR_TRUE); 217 return NULL; 218 } 219 220 /* 221 * These are placed after the CreateContextBySymKey() because some 222 * mechanisms have to generate their IVs from their card (i.e. FORTEZZA). 223 * Don't move it from here. 224 */ 225 if (needToEncodeAlgid) { 226 rv = PK11_ParamToAlgid(algtag, param, poolp, algid); 227 if (rv != SECSuccess) { 228 PORT_Free(result); 229 SECITEM_FreeItem(param, PR_TRUE); 230 PK11_DestroyContext(ciphercx, PR_TRUE); 231 return NULL; 232 } 233 } 234 SECITEM_FreeItem(param, PR_TRUE); 235 236 result->cx = ciphercx; 237 result->doit = SECPKCS7Cipher_PK11_CipherOp; 238 result->destroy = SECPKCS7Cipher_PK11_DestroyContext; 239 result->encrypt = PR_TRUE; 240 result->pending_count = 0; 241 242 return result; 243 } 244 245 /* 246 * Destroy the cipher object. 247 */ 248 static void 249 sec_pkcs7_destroy_cipher(sec_PKCS7CipherObject *obj) 250 { 251 (*obj->destroy)(obj->cx, PR_TRUE); 252 PORT_Free(obj); 253 } 254 255 void 256 sec_PKCS7DestroyDecryptObject(sec_PKCS7CipherObject *obj) 257 { 258 PORT_Assert(obj != NULL); 259 if (obj == NULL) 260 return; 261 PORT_Assert(!obj->encrypt); 262 sec_pkcs7_destroy_cipher(obj); 263 } 264 265 void 266 sec_PKCS7DestroyEncryptObject(sec_PKCS7CipherObject *obj) 267 { 268 PORT_Assert(obj != NULL); 269 if (obj == NULL) 270 return; 271 PORT_Assert(obj->encrypt); 272 sec_pkcs7_destroy_cipher(obj); 273 } 274 275 /* 276 * XXX I think all of the following lengths should be longs instead 277 * of ints, but our current crypto interface uses ints, so I did too. 278 */ 279 280 /* 281 * What will be the output length of the next call to decrypt? 282 * Result can be used to perform memory allocations. Note that the amount 283 * is exactly accurate only when not doing a block cipher or when final 284 * is false, otherwise it is an upper bound on the amount because until 285 * we see the data we do not know how many padding bytes there are 286 * (always between 1 and bsize). 287 * 288 * Note that this can return zero, which does not mean that the decrypt 289 * operation can be skipped! (It simply means that there are not enough 290 * bytes to make up an entire block; the bytes will be reserved until 291 * there are enough to encrypt/decrypt at least one block.) However, 292 * if zero is returned it *does* mean that no output buffer need be 293 * passed in to the subsequent decrypt operation, as no output bytes 294 * will be stored. 295 */ 296 unsigned int 297 sec_PKCS7DecryptLength(sec_PKCS7CipherObject *obj, unsigned int input_len, 298 PRBool final) 299 { 300 int blocks, block_size; 301 302 PORT_Assert(!obj->encrypt); 303 304 block_size = obj->block_size; 305 306 /* 307 * If this is not a block cipher, then we always have the same 308 * number of output bytes as we had input bytes. 309 */ 310 if (block_size == 0) 311 return input_len; 312 313 /* 314 * On the final call, we will always use up all of the pending 315 * bytes plus all of the input bytes, *but*, there will be padding 316 * at the end and we cannot predict how many bytes of padding we 317 * will end up removing. The amount given here is actually known 318 * to be at least 1 byte too long (because we know we will have 319 * at least 1 byte of padding), but seemed clearer/better to me. 320 */ 321 if (final) 322 return obj->pending_count + input_len; 323 324 /* 325 * Okay, this amount is exactly what we will output on the 326 * next cipher operation. We will always hang onto the last 327 * 1 - block_size bytes for non-final operations. That is, 328 * we will do as many complete blocks as we can *except* the 329 * last block (complete or partial). (This is because until 330 * we know we are at the end, we cannot know when to interpret 331 * and removing the padding byte(s), which are guaranteed to 332 * be there.) 333 */ 334 blocks = (obj->pending_count + input_len - 1) / block_size; 335 return blocks * block_size; 336 } 337 338 /* 339 * What will be the output length of the next call to encrypt? 340 * Result can be used to perform memory allocations. 341 * 342 * Note that this can return zero, which does not mean that the encrypt 343 * operation can be skipped! (It simply means that there are not enough 344 * bytes to make up an entire block; the bytes will be reserved until 345 * there are enough to encrypt/decrypt at least one block.) However, 346 * if zero is returned it *does* mean that no output buffer need be 347 * passed in to the subsequent encrypt operation, as no output bytes 348 * will be stored. 349 */ 350 unsigned int 351 sec_PKCS7EncryptLength(sec_PKCS7CipherObject *obj, unsigned int input_len, 352 PRBool final) 353 { 354 int blocks, block_size; 355 int pad_size; 356 357 PORT_Assert(obj->encrypt); 358 359 block_size = obj->block_size; 360 pad_size = obj->pad_size; 361 362 /* 363 * If this is not a block cipher, then we always have the same 364 * number of output bytes as we had input bytes. 365 */ 366 if (block_size == 0) 367 return input_len; 368 369 /* 370 * On the final call, we only send out what we need for 371 * remaining bytes plus the padding. (There is always padding, 372 * so even if we have an exact number of blocks as input, we 373 * will add another full block that is just padding.) 374 */ 375 if (final) { 376 if (pad_size == 0) { 377 return obj->pending_count + input_len; 378 } else { 379 blocks = (obj->pending_count + input_len) / pad_size; 380 blocks++; 381 return blocks * pad_size; 382 } 383 } 384 385 /* 386 * Now, count the number of complete blocks of data we have. 387 */ 388 blocks = (obj->pending_count + input_len) / block_size; 389 390 return blocks * block_size; 391 } 392 393 /* 394 * Decrypt a given length of input buffer (starting at "input" and 395 * containing "input_len" bytes), placing the decrypted bytes in 396 * "output" and storing the output length in "*output_len_p". 397 * "obj" is the return value from sec_PKCS7CreateDecryptObject. 398 * When "final" is true, this is the last of the data to be decrypted. 399 * 400 * This is much more complicated than it sounds when the cipher is 401 * a block-type, meaning that the decryption function will only 402 * operate on whole blocks. But our caller is operating stream-wise, 403 * and can pass in any number of bytes. So we need to keep track 404 * of block boundaries. We save excess bytes between calls in "obj". 405 * We also need to determine which bytes are padding, and remove 406 * them from the output. We can only do this step when we know we 407 * have the final block of data. PKCS #7 specifies that the padding 408 * used for a block cipher is a string of bytes, each of whose value is 409 * the same as the length of the padding, and that all data is padded. 410 * (Even data that starts out with an exact multiple of blocks gets 411 * added to it another block, all of which is padding.) 412 */ 413 SECStatus 414 sec_PKCS7Decrypt(sec_PKCS7CipherObject *obj, unsigned char *output, 415 unsigned int *output_len_p, unsigned int max_output_len, 416 const unsigned char *input, unsigned int input_len, 417 PRBool final) 418 { 419 unsigned int blocks, bsize, pcount, padsize; 420 unsigned int max_needed, ifraglen, ofraglen, output_len; 421 unsigned char *pbuf; 422 SECStatus rv; 423 424 PORT_Assert(!obj->encrypt); 425 426 /* 427 * Check that we have enough room for the output. Our caller should 428 * already handle this; failure is really an internal error (i.e. bug). 429 */ 430 max_needed = sec_PKCS7DecryptLength(obj, input_len, final); 431 PORT_Assert(max_output_len >= max_needed); 432 if (max_output_len < max_needed) { 433 /* PORT_SetError (XXX); */ 434 return SECFailure; 435 } 436 437 /* 438 * hardware encryption does not like small decryption sizes here, so we 439 * allow both blocking and padding. 440 */ 441 bsize = obj->block_size; 442 padsize = obj->pad_size; 443 444 /* 445 * When no blocking or padding work to do, we can simply call the 446 * cipher function and we are done. 447 */ 448 if (bsize == 0) { 449 return (*obj->doit)(obj->cx, output, output_len_p, max_output_len, 450 input, input_len); 451 } 452 453 pcount = obj->pending_count; 454 pbuf = obj->pending_buf; 455 456 output_len = 0; 457 458 if (pcount) { 459 /* 460 * Try to fill in an entire block, starting with the bytes 461 * we already have saved away. 462 */ 463 while (input_len && pcount < bsize) { 464 pbuf[pcount++] = *input++; 465 input_len--; 466 } 467 /* 468 * If we have at most a whole block and this is not our last call, 469 * then we are done for now. (We do not try to decrypt a lone 470 * single block because we cannot interpret the padding bytes 471 * until we know we are handling the very last block of all input.) 472 */ 473 if (input_len == 0 && !final) { 474 obj->pending_count = pcount; 475 if (output_len_p) 476 *output_len_p = 0; 477 return SECSuccess; 478 } 479 /* 480 * Given the logic above, we expect to have a full block by now. 481 * If we do not, there is something wrong, either with our own 482 * logic or with (length of) the data given to us. 483 */ 484 if ((padsize != 0) && (pcount % padsize) != 0) { 485 PORT_Assert(final); 486 PORT_SetError(SEC_ERROR_BAD_DATA); 487 return SECFailure; 488 } 489 /* 490 * Decrypt the block. 491 */ 492 rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len, 493 pbuf, pcount); 494 if (rv != SECSuccess) 495 return rv; 496 497 /* 498 * For now anyway, all of our ciphers have the same number of 499 * bytes of output as they do input. If this ever becomes untrue, 500 * then sec_PKCS7DecryptLength needs to be made smarter! 501 */ 502 PORT_Assert(ofraglen == pcount); 503 504 /* 505 * Account for the bytes now in output. 506 */ 507 max_output_len -= ofraglen; 508 output_len += ofraglen; 509 output += ofraglen; 510 } 511 512 /* 513 * If this is our last call, we expect to have an exact number of 514 * blocks left to be decrypted; we will decrypt them all. 515 * 516 * If not our last call, we always save between 1 and bsize bytes 517 * until next time. (We must do this because we cannot be sure 518 * that none of the decrypted bytes are padding bytes until we 519 * have at least another whole block of data. You cannot tell by 520 * looking -- the data could be anything -- you can only tell by 521 * context, knowing you are looking at the last block.) We could 522 * decrypt a whole block now but it is easier if we just treat it 523 * the same way we treat partial block bytes. 524 */ 525 if (final) { 526 if (padsize) { 527 blocks = input_len / padsize; 528 ifraglen = blocks * padsize; 529 } else 530 ifraglen = input_len; 531 PORT_Assert(ifraglen == input_len); 532 533 if (ifraglen != input_len) { 534 PORT_SetError(SEC_ERROR_BAD_DATA); 535 return SECFailure; 536 } 537 } else { 538 blocks = (input_len - 1) / bsize; 539 ifraglen = blocks * bsize; 540 PORT_Assert(ifraglen < input_len); 541 542 pcount = input_len - ifraglen; 543 PORT_Memcpy(pbuf, input + ifraglen, pcount); 544 obj->pending_count = pcount; 545 } 546 547 if (ifraglen) { 548 rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len, 549 input, ifraglen); 550 if (rv != SECSuccess) 551 return rv; 552 553 /* 554 * For now anyway, all of our ciphers have the same number of 555 * bytes of output as they do input. If this ever becomes untrue, 556 * then sec_PKCS7DecryptLength needs to be made smarter! 557 */ 558 PORT_Assert(ifraglen == ofraglen); 559 if (ifraglen != ofraglen) { 560 PORT_SetError(SEC_ERROR_BAD_DATA); 561 return SECFailure; 562 } 563 564 output_len += ofraglen; 565 } else { 566 ofraglen = 0; 567 } 568 569 /* 570 * If we just did our very last block, "remove" the padding by 571 * adjusting the output length. 572 */ 573 if (final && (padsize != 0)) { 574 unsigned int padlen = *(output + ofraglen - 1); 575 if (padlen == 0 || padlen > padsize) { 576 PORT_SetError(SEC_ERROR_BAD_DATA); 577 return SECFailure; 578 } 579 output_len -= padlen; 580 } 581 582 PORT_Assert(output_len_p != NULL || output_len == 0); 583 if (output_len_p != NULL) 584 *output_len_p = output_len; 585 586 return SECSuccess; 587 } 588 589 /* 590 * Encrypt a given length of input buffer (starting at "input" and 591 * containing "input_len" bytes), placing the encrypted bytes in 592 * "output" and storing the output length in "*output_len_p". 593 * "obj" is the return value from sec_PKCS7CreateEncryptObject. 594 * When "final" is true, this is the last of the data to be encrypted. 595 * 596 * This is much more complicated than it sounds when the cipher is 597 * a block-type, meaning that the encryption function will only 598 * operate on whole blocks. But our caller is operating stream-wise, 599 * and can pass in any number of bytes. So we need to keep track 600 * of block boundaries. We save excess bytes between calls in "obj". 601 * We also need to add padding bytes at the end. PKCS #7 specifies 602 * that the padding used for a block cipher is a string of bytes, 603 * each of whose value is the same as the length of the padding, 604 * and that all data is padded. (Even data that starts out with 605 * an exact multiple of blocks gets added to it another block, 606 * all of which is padding.) 607 * 608 * XXX I would kind of like to combine this with the function above 609 * which does decryption, since they have a lot in common. But the 610 * tricky parts about padding and filling blocks would be much 611 * harder to read that way, so I left them separate. At least for 612 * now until it is clear that they are right. 613 */ 614 SECStatus 615 sec_PKCS7Encrypt(sec_PKCS7CipherObject *obj, unsigned char *output, 616 unsigned int *output_len_p, unsigned int max_output_len, 617 const unsigned char *input, unsigned int input_len, 618 PRBool final) 619 { 620 int blocks, bsize, padlen, pcount, padsize; 621 unsigned int max_needed, ifraglen, ofraglen, output_len; 622 unsigned char *pbuf; 623 SECStatus rv; 624 625 PORT_Assert(obj->encrypt); 626 627 /* 628 * Check that we have enough room for the output. Our caller should 629 * already handle this; failure is really an internal error (i.e. bug). 630 */ 631 max_needed = sec_PKCS7EncryptLength(obj, input_len, final); 632 PORT_Assert(max_output_len >= max_needed); 633 if (max_output_len < max_needed) { 634 /* PORT_SetError (XXX); */ 635 return SECFailure; 636 } 637 638 bsize = obj->block_size; 639 padsize = obj->pad_size; 640 641 /* 642 * When no blocking and padding work to do, we can simply call the 643 * cipher function and we are done. 644 */ 645 if (bsize == 0) { 646 return (*obj->doit)(obj->cx, output, output_len_p, max_output_len, 647 input, input_len); 648 } 649 650 pcount = obj->pending_count; 651 pbuf = obj->pending_buf; 652 653 output_len = 0; 654 655 if (pcount) { 656 /* 657 * Try to fill in an entire block, starting with the bytes 658 * we already have saved away. 659 */ 660 while (input_len && pcount < bsize) { 661 pbuf[pcount++] = *input++; 662 input_len--; 663 } 664 /* 665 * If we do not have a full block and we know we will be 666 * called again, then we are done for now. 667 */ 668 if (pcount < bsize && !final) { 669 obj->pending_count = pcount; 670 if (output_len_p != NULL) 671 *output_len_p = 0; 672 return SECSuccess; 673 } 674 /* 675 * If we have a whole block available, encrypt it. 676 */ 677 if ((padsize == 0) || (pcount % padsize) == 0) { 678 rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len, 679 pbuf, pcount); 680 if (rv != SECSuccess) 681 return rv; 682 683 /* 684 * For now anyway, all of our ciphers have the same number of 685 * bytes of output as they do input. If this ever becomes untrue, 686 * then sec_PKCS7EncryptLength needs to be made smarter! 687 */ 688 PORT_Assert(ofraglen == pcount); 689 690 /* 691 * Account for the bytes now in output. 692 */ 693 max_output_len -= ofraglen; 694 output_len += ofraglen; 695 output += ofraglen; 696 697 pcount = 0; 698 } 699 } 700 701 if (input_len) { 702 PORT_Assert(pcount == 0); 703 704 blocks = input_len / bsize; 705 ifraglen = blocks * bsize; 706 707 if (ifraglen) { 708 rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len, 709 input, ifraglen); 710 if (rv != SECSuccess) 711 return rv; 712 713 /* 714 * For now anyway, all of our ciphers have the same number of 715 * bytes of output as they do input. If this ever becomes untrue, 716 * then sec_PKCS7EncryptLength needs to be made smarter! 717 */ 718 PORT_Assert(ifraglen == ofraglen); 719 720 max_output_len -= ofraglen; 721 output_len += ofraglen; 722 output += ofraglen; 723 } 724 725 pcount = input_len - ifraglen; 726 PORT_Assert(pcount < bsize); 727 if (pcount) 728 PORT_Memcpy(pbuf, input + ifraglen, pcount); 729 } 730 731 if (final) { 732 if (padsize) { 733 padlen = padsize - (pcount % padsize); 734 PORT_Memset(pbuf + pcount, padlen, padlen); 735 } else { 736 padlen = 0; 737 } 738 rv = (*obj->doit)(obj->cx, output, &ofraglen, max_output_len, 739 pbuf, pcount + padlen); 740 if (rv != SECSuccess) 741 return rv; 742 743 /* 744 * For now anyway, all of our ciphers have the same number of 745 * bytes of output as they do input. If this ever becomes untrue, 746 * then sec_PKCS7EncryptLength needs to be made smarter! 747 */ 748 PORT_Assert(ofraglen == (pcount + padlen)); 749 output_len += ofraglen; 750 } else { 751 obj->pending_count = pcount; 752 } 753 754 PORT_Assert(output_len_p != NULL || output_len == 0); 755 if (output_len_p != NULL) 756 *output_len_p = output_len; 757 758 return SECSuccess; 759 } 760 761 /* 762 * End of cipher stuff. 763 * ------------------------------------------------------------------- 764 */ 765 766 /* 767 * ------------------------------------------------------------------- 768 * XXX The following Attribute stuff really belongs elsewhere. 769 * The Attribute type is *not* part of pkcs7 but rather X.501. 770 * But for now, since PKCS7 is the only customer of attributes, 771 * we define them here. Once there is a use outside of PKCS7, 772 * then change the attribute types and functions from internal 773 * to external naming convention, and move them elsewhere! 774 */ 775 776 /* 777 * Look through a set of attributes and find one that matches the 778 * specified object ID. If "only" is true, then make sure that 779 * there is not more than one attribute of the same type. Otherwise, 780 * just return the first one found. (XXX Does anybody really want 781 * that first-found behavior? It was like that when I found it...) 782 */ 783 SEC_PKCS7Attribute * 784 sec_PKCS7FindAttribute(SEC_PKCS7Attribute **attrs, SECOidTag oidtag, 785 PRBool only) 786 { 787 SECOidData *oid; 788 SEC_PKCS7Attribute *attr1, *attr2; 789 790 if (attrs == NULL) 791 return NULL; 792 793 oid = SECOID_FindOIDByTag(oidtag); 794 if (oid == NULL) 795 return NULL; 796 797 while ((attr1 = *attrs++) != NULL) { 798 if (attr1->type.len == oid->oid.len && PORT_Memcmp(attr1->type.data, oid->oid.data, oid->oid.len) == 0) 799 break; 800 } 801 802 if (attr1 == NULL) 803 return NULL; 804 805 if (!only) 806 return attr1; 807 808 while ((attr2 = *attrs++) != NULL) { 809 if (attr2->type.len == oid->oid.len && PORT_Memcmp(attr2->type.data, oid->oid.data, oid->oid.len) == 0) 810 break; 811 } 812 813 if (attr2 != NULL) 814 return NULL; 815 816 return attr1; 817 } 818 819 /* 820 * Return the single attribute value, doing some sanity checking first: 821 * - Multiple values are *not* expected. 822 * - Empty values are *not* expected. 823 */ 824 SECItem * 825 sec_PKCS7AttributeValue(SEC_PKCS7Attribute *attr) 826 { 827 SECItem *value; 828 829 if (attr == NULL) 830 return NULL; 831 832 value = attr->values[0]; 833 834 if (value == NULL || value->data == NULL || value->len == 0) 835 return NULL; 836 837 if (attr->values[1] != NULL) 838 return NULL; 839 840 return value; 841 } 842 843 static const SEC_ASN1Template * 844 sec_attr_choose_attr_value_template(void *src_or_dest, PRBool encoding) 845 { 846 const SEC_ASN1Template *theTemplate; 847 848 SEC_PKCS7Attribute *attribute; 849 SECOidData *oiddata; 850 PRBool encoded; 851 852 PORT_Assert(src_or_dest != NULL); 853 if (src_or_dest == NULL) 854 return NULL; 855 856 attribute = (SEC_PKCS7Attribute *)src_or_dest; 857 858 if (encoding && attribute->encoded) 859 return SEC_ASN1_GET(SEC_AnyTemplate); 860 861 oiddata = attribute->typeTag; 862 if (oiddata == NULL) { 863 oiddata = SECOID_FindOID(&attribute->type); 864 attribute->typeTag = oiddata; 865 } 866 867 if (oiddata == NULL) { 868 encoded = PR_TRUE; 869 theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); 870 } else { 871 switch (oiddata->offset) { 872 default: 873 encoded = PR_TRUE; 874 theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); 875 break; 876 case SEC_OID_PKCS9_EMAIL_ADDRESS: 877 case SEC_OID_RFC1274_MAIL: 878 case SEC_OID_PKCS9_UNSTRUCTURED_NAME: 879 encoded = PR_FALSE; 880 theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate); 881 break; 882 case SEC_OID_PKCS9_CONTENT_TYPE: 883 encoded = PR_FALSE; 884 theTemplate = SEC_ASN1_GET(SEC_ObjectIDTemplate); 885 break; 886 case SEC_OID_PKCS9_MESSAGE_DIGEST: 887 encoded = PR_FALSE; 888 theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate); 889 break; 890 case SEC_OID_PKCS9_SIGNING_TIME: 891 encoded = PR_FALSE; 892 theTemplate = SEC_ASN1_GET(CERT_TimeChoiceTemplate); 893 break; 894 /* XXX Want other types here, too */ 895 } 896 } 897 898 if (encoding) { 899 /* 900 * If we are encoding and we think we have an already-encoded value, 901 * then the code which initialized this attribute should have set 902 * the "encoded" property to true (and we would have returned early, 903 * up above). No devastating error, but that code should be fixed. 904 * (It could indicate that the resulting encoded bytes are wrong.) 905 */ 906 PORT_Assert(!encoded); 907 } else { 908 /* 909 * We are decoding; record whether the resulting value is 910 * still encoded or not. 911 */ 912 attribute->encoded = encoded; 913 } 914 return theTemplate; 915 } 916 917 static const SEC_ASN1TemplateChooserPtr sec_attr_chooser = sec_attr_choose_attr_value_template; 918 919 static const SEC_ASN1Template sec_pkcs7_attribute_template[] = { 920 { SEC_ASN1_SEQUENCE, 921 0, NULL, sizeof(SEC_PKCS7Attribute) }, 922 { SEC_ASN1_OBJECT_ID, 923 offsetof(SEC_PKCS7Attribute, type) }, 924 { SEC_ASN1_DYNAMIC | SEC_ASN1_SET_OF, 925 offsetof(SEC_PKCS7Attribute, values), 926 &sec_attr_chooser }, 927 { 0 } 928 }; 929 930 static const SEC_ASN1Template sec_pkcs7_set_of_attribute_template[] = { 931 { SEC_ASN1_SET_OF, 0, sec_pkcs7_attribute_template }, 932 }; 933 934 /* 935 * If you are wondering why this routine does not reorder the attributes 936 * first, and might be tempted to make it do so, see the comment by the 937 * call to ReorderAttributes in p7encode.c. (Or, see who else calls this 938 * and think long and hard about the implications of making it always 939 * do the reordering.) 940 */ 941 SECItem * 942 sec_PKCS7EncodeAttributes(PLArenaPool *poolp, SECItem *dest, void *src) 943 { 944 return SEC_ASN1EncodeItem(poolp, dest, src, 945 sec_pkcs7_set_of_attribute_template); 946 } 947 948 /* 949 * Make sure that the order of the attributes guarantees valid DER 950 * (which must be in lexigraphically ascending order for a SET OF); 951 * if reordering is necessary it will be done in place (in attrs). 952 */ 953 SECStatus 954 sec_PKCS7ReorderAttributes(SEC_PKCS7Attribute **attrs) 955 { 956 PLArenaPool *poolp; 957 int num_attrs, i, pass, besti; 958 unsigned int j; 959 SECItem **enc_attrs; 960 SEC_PKCS7Attribute **new_attrs; 961 962 /* 963 * I think we should not be called with NULL. But if we are, 964 * call it a success anyway, because the order *is* okay. 965 */ 966 PORT_Assert(attrs != NULL); 967 if (attrs == NULL) 968 return SECSuccess; 969 970 /* 971 * Count how many attributes we are dealing with here. 972 */ 973 num_attrs = 0; 974 while (attrs[num_attrs] != NULL) 975 num_attrs++; 976 977 /* 978 * Again, I think we should have some attributes here. 979 * But if we do not, or if there is only one, then call it 980 * a success because it also already has a fine order. 981 */ 982 PORT_Assert(num_attrs); 983 if (num_attrs == 0 || num_attrs == 1) 984 return SECSuccess; 985 986 /* 987 * Allocate an arena for us to work with, so it is easy to 988 * clean up all of the memory (fairly small pieces, really). 989 */ 990 poolp = PORT_NewArena(1024); /* XXX what is right value? */ 991 if (poolp == NULL) 992 return SECFailure; /* no memory; nothing we can do... */ 993 994 /* 995 * Allocate arrays to hold the individual encodings which we will use 996 * for comparisons and the reordered attributes as they are sorted. 997 */ 998 enc_attrs = (SECItem **)PORT_ArenaZAlloc(poolp, num_attrs * sizeof(SECItem *)); 999 new_attrs = (SEC_PKCS7Attribute **)PORT_ArenaZAlloc(poolp, 1000 num_attrs * sizeof(SEC_PKCS7Attribute *)); 1001 if (enc_attrs == NULL || new_attrs == NULL) { 1002 PORT_FreeArena(poolp, PR_FALSE); 1003 return SECFailure; 1004 } 1005 1006 /* 1007 * DER encode each individual attribute. 1008 */ 1009 for (i = 0; i < num_attrs; i++) { 1010 enc_attrs[i] = SEC_ASN1EncodeItem(poolp, NULL, attrs[i], 1011 sec_pkcs7_attribute_template); 1012 if (enc_attrs[i] == NULL) { 1013 PORT_FreeArena(poolp, PR_FALSE); 1014 return SECFailure; 1015 } 1016 } 1017 1018 /* 1019 * Now compare and sort them; this is not the most efficient sorting 1020 * method, but it is just fine for the problem at hand, because the 1021 * number of attributes is (always) going to be small. 1022 */ 1023 for (pass = 0; pass < num_attrs; pass++) { 1024 /* 1025 * Find the first not-yet-accepted attribute. (Once one is 1026 * sorted into the other array, it is cleared from enc_attrs.) 1027 */ 1028 for (i = 0; i < num_attrs; i++) { 1029 if (enc_attrs[i] != NULL) 1030 break; 1031 } 1032 PORT_Assert(i < num_attrs); 1033 besti = i; 1034 1035 /* 1036 * Find the lowest (lexigraphically) encoding. One that is 1037 * shorter than all the rest is known to be "less" because each 1038 * attribute is of the same type (a SEQUENCE) and so thus the 1039 * first octet of each is the same, and the second octet is 1040 * the length (or the length of the length with the high bit 1041 * set, followed by the length, which also works out to always 1042 * order the shorter first). Two (or more) that have the 1043 * same length need to be compared byte by byte until a mismatch 1044 * is found. 1045 */ 1046 for (i = besti + 1; i < num_attrs; i++) { 1047 if (enc_attrs[i] == NULL) /* slot already handled */ 1048 continue; 1049 1050 if (enc_attrs[i]->len != enc_attrs[besti]->len) { 1051 if (enc_attrs[i]->len < enc_attrs[besti]->len) 1052 besti = i; 1053 continue; 1054 } 1055 1056 for (j = 0; j < enc_attrs[i]->len; j++) { 1057 if (enc_attrs[i]->data[j] < enc_attrs[besti]->data[j]) { 1058 besti = i; 1059 break; 1060 } 1061 } 1062 1063 /* 1064 * For this not to be true, we would have to have encountered 1065 * two *identical* attributes, which I think we should not see. 1066 * So assert if it happens, but even if it does, let it go 1067 * through; the ordering of the two does not matter. 1068 */ 1069 PORT_Assert(j < enc_attrs[i]->len); 1070 } 1071 1072 /* 1073 * Now we have found the next-lowest one; copy it over and 1074 * remove it from enc_attrs. 1075 */ 1076 new_attrs[pass] = attrs[besti]; 1077 enc_attrs[besti] = NULL; 1078 } 1079 1080 /* 1081 * Now new_attrs has the attributes in the order we want; 1082 * copy them back into the attrs array we started with. 1083 */ 1084 for (i = 0; i < num_attrs; i++) 1085 attrs[i] = new_attrs[i]; 1086 1087 PORT_FreeArena(poolp, PR_FALSE); 1088 return SECSuccess; 1089 } 1090 1091 /* 1092 * End of attribute stuff. 1093 * ------------------------------------------------------------------- 1094 */ 1095 1096 /* 1097 * Templates and stuff. Keep these at the end of the file. 1098 */ 1099 1100 /* forward declaration */ 1101 static const SEC_ASN1Template * 1102 sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding); 1103 1104 static const SEC_ASN1TemplateChooserPtr sec_pkcs7_chooser = sec_pkcs7_choose_content_template; 1105 1106 const SEC_ASN1Template sec_PKCS7ContentInfoTemplate[] = { 1107 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, 1108 0, NULL, sizeof(SEC_PKCS7ContentInfo) }, 1109 { SEC_ASN1_OBJECT_ID, 1110 offsetof(SEC_PKCS7ContentInfo, contentType) }, 1111 { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1112 offsetof(SEC_PKCS7ContentInfo, content), 1113 &sec_pkcs7_chooser }, 1114 { 0 } 1115 }; 1116 1117 /* XXX These names should change from external to internal convention. */ 1118 1119 static const SEC_ASN1Template SEC_PKCS7SignerInfoTemplate[] = { 1120 { SEC_ASN1_SEQUENCE, 1121 0, NULL, sizeof(SEC_PKCS7SignerInfo) }, 1122 { SEC_ASN1_INTEGER, 1123 offsetof(SEC_PKCS7SignerInfo, version) }, 1124 { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 1125 offsetof(SEC_PKCS7SignerInfo, issuerAndSN), 1126 SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) }, 1127 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1128 offsetof(SEC_PKCS7SignerInfo, digestAlg), 1129 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1130 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1131 offsetof(SEC_PKCS7SignerInfo, authAttr), 1132 sec_pkcs7_set_of_attribute_template }, 1133 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1134 offsetof(SEC_PKCS7SignerInfo, digestEncAlg), 1135 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1136 { SEC_ASN1_OCTET_STRING, 1137 offsetof(SEC_PKCS7SignerInfo, encDigest) }, 1138 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1139 offsetof(SEC_PKCS7SignerInfo, unAuthAttr), 1140 sec_pkcs7_set_of_attribute_template }, 1141 { 0 } 1142 }; 1143 1144 static const SEC_ASN1Template SEC_PKCS7SignedDataTemplate[] = { 1145 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, 1146 0, NULL, sizeof(SEC_PKCS7SignedData) }, 1147 { SEC_ASN1_INTEGER, 1148 offsetof(SEC_PKCS7SignedData, version) }, 1149 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, 1150 offsetof(SEC_PKCS7SignedData, digestAlgorithms), 1151 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1152 { SEC_ASN1_INLINE, 1153 offsetof(SEC_PKCS7SignedData, contentInfo), 1154 sec_PKCS7ContentInfoTemplate }, 1155 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1156 SEC_ASN1_XTRN | 0, 1157 offsetof(SEC_PKCS7SignedData, rawCerts), 1158 SEC_ASN1_SUB(SEC_SetOfAnyTemplate) }, 1159 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1160 SEC_ASN1_XTRN | 1, 1161 offsetof(SEC_PKCS7SignedData, crls), 1162 SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) }, 1163 { SEC_ASN1_SET_OF, 1164 offsetof(SEC_PKCS7SignedData, signerInfos), 1165 SEC_PKCS7SignerInfoTemplate }, 1166 { 0 } 1167 }; 1168 1169 static const SEC_ASN1Template SEC_PointerToPKCS7SignedDataTemplate[] = { 1170 { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedDataTemplate } 1171 }; 1172 1173 static const SEC_ASN1Template SEC_PKCS7RecipientInfoTemplate[] = { 1174 { SEC_ASN1_SEQUENCE, 1175 0, NULL, sizeof(SEC_PKCS7RecipientInfo) }, 1176 { SEC_ASN1_INTEGER, 1177 offsetof(SEC_PKCS7RecipientInfo, version) }, 1178 { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 1179 offsetof(SEC_PKCS7RecipientInfo, issuerAndSN), 1180 SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) }, 1181 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1182 offsetof(SEC_PKCS7RecipientInfo, keyEncAlg), 1183 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1184 { SEC_ASN1_OCTET_STRING, 1185 offsetof(SEC_PKCS7RecipientInfo, encKey) }, 1186 { 0 } 1187 }; 1188 1189 static const SEC_ASN1Template SEC_PKCS7EncryptedContentInfoTemplate[] = { 1190 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, 1191 0, NULL, sizeof(SEC_PKCS7EncryptedContentInfo) }, 1192 { SEC_ASN1_OBJECT_ID, 1193 offsetof(SEC_PKCS7EncryptedContentInfo, contentType) }, 1194 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1195 offsetof(SEC_PKCS7EncryptedContentInfo, contentEncAlg), 1196 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1197 { SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_CONTEXT_SPECIFIC | 1198 SEC_ASN1_XTRN | 0, 1199 offsetof(SEC_PKCS7EncryptedContentInfo, encContent), 1200 SEC_ASN1_SUB(SEC_OctetStringTemplate) }, 1201 { 0 } 1202 }; 1203 1204 static const SEC_ASN1Template SEC_PKCS7EnvelopedDataTemplate[] = { 1205 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, 1206 0, NULL, sizeof(SEC_PKCS7EnvelopedData) }, 1207 { SEC_ASN1_INTEGER, 1208 offsetof(SEC_PKCS7EnvelopedData, version) }, 1209 { SEC_ASN1_SET_OF, 1210 offsetof(SEC_PKCS7EnvelopedData, recipientInfos), 1211 SEC_PKCS7RecipientInfoTemplate }, 1212 { SEC_ASN1_INLINE, 1213 offsetof(SEC_PKCS7EnvelopedData, encContentInfo), 1214 SEC_PKCS7EncryptedContentInfoTemplate }, 1215 { 0 } 1216 }; 1217 1218 static const SEC_ASN1Template SEC_PointerToPKCS7EnvelopedDataTemplate[] = { 1219 { SEC_ASN1_POINTER, 0, SEC_PKCS7EnvelopedDataTemplate } 1220 }; 1221 1222 static const SEC_ASN1Template SEC_PKCS7SignedAndEnvelopedDataTemplate[] = { 1223 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, 1224 0, NULL, sizeof(SEC_PKCS7SignedAndEnvelopedData) }, 1225 { SEC_ASN1_INTEGER, 1226 offsetof(SEC_PKCS7SignedAndEnvelopedData, version) }, 1227 { SEC_ASN1_SET_OF, 1228 offsetof(SEC_PKCS7SignedAndEnvelopedData, recipientInfos), 1229 SEC_PKCS7RecipientInfoTemplate }, 1230 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, 1231 offsetof(SEC_PKCS7SignedAndEnvelopedData, digestAlgorithms), 1232 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1233 { SEC_ASN1_INLINE, 1234 offsetof(SEC_PKCS7SignedAndEnvelopedData, encContentInfo), 1235 SEC_PKCS7EncryptedContentInfoTemplate }, 1236 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1237 SEC_ASN1_XTRN | 0, 1238 offsetof(SEC_PKCS7SignedAndEnvelopedData, rawCerts), 1239 SEC_ASN1_SUB(SEC_SetOfAnyTemplate) }, 1240 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1241 SEC_ASN1_XTRN | 1, 1242 offsetof(SEC_PKCS7SignedAndEnvelopedData, crls), 1243 SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) }, 1244 { SEC_ASN1_SET_OF, 1245 offsetof(SEC_PKCS7SignedAndEnvelopedData, signerInfos), 1246 SEC_PKCS7SignerInfoTemplate }, 1247 { 0 } 1248 }; 1249 1250 static const SEC_ASN1Template 1251 SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate[] = { 1252 { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedAndEnvelopedDataTemplate } 1253 }; 1254 1255 static const SEC_ASN1Template SEC_PKCS7DigestedDataTemplate[] = { 1256 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, 1257 0, NULL, sizeof(SEC_PKCS7DigestedData) }, 1258 { SEC_ASN1_INTEGER, 1259 offsetof(SEC_PKCS7DigestedData, version) }, 1260 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1261 offsetof(SEC_PKCS7DigestedData, digestAlg), 1262 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1263 { SEC_ASN1_INLINE, 1264 offsetof(SEC_PKCS7DigestedData, contentInfo), 1265 sec_PKCS7ContentInfoTemplate }, 1266 { SEC_ASN1_OCTET_STRING, 1267 offsetof(SEC_PKCS7DigestedData, digest) }, 1268 { 0 } 1269 }; 1270 1271 static const SEC_ASN1Template SEC_PointerToPKCS7DigestedDataTemplate[] = { 1272 { SEC_ASN1_POINTER, 0, SEC_PKCS7DigestedDataTemplate } 1273 }; 1274 1275 static const SEC_ASN1Template SEC_PKCS7EncryptedDataTemplate[] = { 1276 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, 1277 0, NULL, sizeof(SEC_PKCS7EncryptedData) }, 1278 { SEC_ASN1_INTEGER, 1279 offsetof(SEC_PKCS7EncryptedData, version) }, 1280 { SEC_ASN1_INLINE, 1281 offsetof(SEC_PKCS7EncryptedData, encContentInfo), 1282 SEC_PKCS7EncryptedContentInfoTemplate }, 1283 { 0 } 1284 }; 1285 1286 static const SEC_ASN1Template SEC_PointerToPKCS7EncryptedDataTemplate[] = { 1287 { SEC_ASN1_POINTER, 0, SEC_PKCS7EncryptedDataTemplate } 1288 }; 1289 1290 static const SEC_ASN1Template * 1291 sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding) 1292 { 1293 const SEC_ASN1Template *theTemplate; 1294 SEC_PKCS7ContentInfo *cinfo; 1295 SECOidTag kind; 1296 1297 if (src_or_dest == NULL) 1298 return NULL; 1299 1300 cinfo = (SEC_PKCS7ContentInfo *)src_or_dest; 1301 kind = SEC_PKCS7ContentType(cinfo); 1302 switch (kind) { 1303 default: 1304 theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); 1305 break; 1306 case SEC_OID_PKCS7_DATA: 1307 theTemplate = SEC_ASN1_GET(SEC_PointerToOctetStringTemplate); 1308 break; 1309 case SEC_OID_PKCS7_SIGNED_DATA: 1310 theTemplate = SEC_PointerToPKCS7SignedDataTemplate; 1311 break; 1312 case SEC_OID_PKCS7_ENVELOPED_DATA: 1313 theTemplate = SEC_PointerToPKCS7EnvelopedDataTemplate; 1314 break; 1315 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: 1316 theTemplate = SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate; 1317 break; 1318 case SEC_OID_PKCS7_DIGESTED_DATA: 1319 theTemplate = SEC_PointerToPKCS7DigestedDataTemplate; 1320 break; 1321 case SEC_OID_PKCS7_ENCRYPTED_DATA: 1322 theTemplate = SEC_PointerToPKCS7EncryptedDataTemplate; 1323 break; 1324 } 1325 return theTemplate; 1326 } 1327 1328 /* 1329 * End of templates. Do not add stuff after this; put new code 1330 * up above the start of the template definitions. 1331 */