pk7_doit.c revision 280268
1/* crypto/pkcs7/pk7_doit.c */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59#include <stdio.h> 60#include "cryptlib.h" 61#include <openssl/rand.h> 62#include <openssl/objects.h> 63#include <openssl/x509.h> 64#include <openssl/x509v3.h> 65#include <openssl/err.h> 66 67static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 68 void *value); 69static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid); 70 71static int PKCS7_type_is_other(PKCS7* p7) 72 { 73 int isOther=1; 74 75 int nid=OBJ_obj2nid(p7->type); 76 77 switch( nid ) 78 { 79 case NID_pkcs7_data: 80 case NID_pkcs7_signed: 81 case NID_pkcs7_enveloped: 82 case NID_pkcs7_signedAndEnveloped: 83 case NID_pkcs7_digest: 84 case NID_pkcs7_encrypted: 85 isOther=0; 86 break; 87 default: 88 isOther=1; 89 } 90 91 return isOther; 92 93 } 94 95static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) 96 { 97 if ( PKCS7_type_is_data(p7)) 98 return p7->d.data; 99 if ( PKCS7_type_is_other(p7) && p7->d.other 100 && (p7->d.other->type == V_ASN1_OCTET_STRING)) 101 return p7->d.other->value.octet_string; 102 return NULL; 103 } 104 105static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) 106 { 107 BIO *btmp; 108 const EVP_MD *md; 109 if ((btmp=BIO_new(BIO_f_md())) == NULL) 110 { 111 PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB); 112 goto err; 113 } 114 115 md=EVP_get_digestbyobj(alg->algorithm); 116 if (md == NULL) 117 { 118 PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE); 119 goto err; 120 } 121 122 BIO_set_md(btmp,md); 123 if (*pbio == NULL) 124 *pbio=btmp; 125 else if (!BIO_push(*pbio,btmp)) 126 { 127 PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB); 128 goto err; 129 } 130 btmp=NULL; 131 132 return 1; 133 134 err: 135 if (btmp) 136 BIO_free(btmp); 137 return 0; 138 139 } 140 141static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, 142 unsigned char *key, int keylen) 143 { 144 EVP_PKEY_CTX *pctx = NULL; 145 EVP_PKEY *pkey = NULL; 146 unsigned char *ek = NULL; 147 int ret = 0; 148 size_t eklen; 149 150 pkey = X509_get_pubkey(ri->cert); 151 152 if (!pkey) 153 return 0; 154 155 pctx = EVP_PKEY_CTX_new(pkey, NULL); 156 if (!pctx) 157 return 0; 158 159 if (EVP_PKEY_encrypt_init(pctx) <= 0) 160 goto err; 161 162 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, 163 EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0) 164 { 165 PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, PKCS7_R_CTRL_ERROR); 166 goto err; 167 } 168 169 if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0) 170 goto err; 171 172 ek = OPENSSL_malloc(eklen); 173 174 if (ek == NULL) 175 { 176 PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, ERR_R_MALLOC_FAILURE); 177 goto err; 178 } 179 180 if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0) 181 goto err; 182 183 ASN1_STRING_set0(ri->enc_key, ek, eklen); 184 ek = NULL; 185 186 ret = 1; 187 188 err: 189 if (pkey) 190 EVP_PKEY_free(pkey); 191 if (pctx) 192 EVP_PKEY_CTX_free(pctx); 193 if (ek) 194 OPENSSL_free(ek); 195 return ret; 196 197 } 198 199 200static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, 201 PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) 202 { 203 EVP_PKEY_CTX *pctx = NULL; 204 unsigned char *ek = NULL; 205 size_t eklen; 206 207 int ret = -1; 208 209 pctx = EVP_PKEY_CTX_new(pkey, NULL); 210 if (!pctx) 211 return -1; 212 213 if (EVP_PKEY_decrypt_init(pctx) <= 0) 214 goto err; 215 216 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, 217 EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) 218 { 219 PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR); 220 goto err; 221 } 222 223 if (EVP_PKEY_decrypt(pctx, NULL, &eklen, 224 ri->enc_key->data, ri->enc_key->length) <= 0) 225 goto err; 226 227 ek = OPENSSL_malloc(eklen); 228 229 if (ek == NULL) 230 { 231 PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE); 232 goto err; 233 } 234 235 if (EVP_PKEY_decrypt(pctx, ek, &eklen, 236 ri->enc_key->data, ri->enc_key->length) <= 0) 237 { 238 ret = 0; 239 PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); 240 goto err; 241 } 242 243 ret = 1; 244 245 if (*pek) 246 { 247 OPENSSL_cleanse(*pek, *peklen); 248 OPENSSL_free(*pek); 249 } 250 251 *pek = ek; 252 *peklen = eklen; 253 254 err: 255 if (pctx) 256 EVP_PKEY_CTX_free(pctx); 257 if (!ret && ek) 258 OPENSSL_free(ek); 259 260 return ret; 261 } 262 263BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) 264 { 265 int i; 266 BIO *out=NULL,*btmp=NULL; 267 X509_ALGOR *xa = NULL; 268 const EVP_CIPHER *evp_cipher=NULL; 269 STACK_OF(X509_ALGOR) *md_sk=NULL; 270 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; 271 X509_ALGOR *xalg=NULL; 272 PKCS7_RECIP_INFO *ri=NULL; 273 ASN1_OCTET_STRING *os=NULL; 274 275 if (p7 == NULL) { 276 PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); 277 return NULL; 278 } 279 /* 280 * The content field in the PKCS7 ContentInfo is optional, but that really 281 * only applies to inner content (precisely, detached signatures). 282 * 283 * When reading content, missing outer content is therefore treated as an 284 * error. 285 * 286 * When creating content, PKCS7_content_new() must be called before 287 * calling this method, so a NULL p7->d is always an error. 288 */ 289 if (p7->d.ptr == NULL) { 290 PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT); 291 return NULL; 292 } 293 294 i=OBJ_obj2nid(p7->type); 295 p7->state=PKCS7_S_HEADER; 296 297 switch (i) 298 { 299 case NID_pkcs7_signed: 300 md_sk=p7->d.sign->md_algs; 301 os = PKCS7_get_octet_string(p7->d.sign->contents); 302 break; 303 case NID_pkcs7_signedAndEnveloped: 304 rsk=p7->d.signed_and_enveloped->recipientinfo; 305 md_sk=p7->d.signed_and_enveloped->md_algs; 306 xalg=p7->d.signed_and_enveloped->enc_data->algorithm; 307 evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher; 308 if (evp_cipher == NULL) 309 { 310 PKCS7err(PKCS7_F_PKCS7_DATAINIT, 311 PKCS7_R_CIPHER_NOT_INITIALIZED); 312 goto err; 313 } 314 break; 315 case NID_pkcs7_enveloped: 316 rsk=p7->d.enveloped->recipientinfo; 317 xalg=p7->d.enveloped->enc_data->algorithm; 318 evp_cipher=p7->d.enveloped->enc_data->cipher; 319 if (evp_cipher == NULL) 320 { 321 PKCS7err(PKCS7_F_PKCS7_DATAINIT, 322 PKCS7_R_CIPHER_NOT_INITIALIZED); 323 goto err; 324 } 325 break; 326 case NID_pkcs7_digest: 327 xa = p7->d.digest->md; 328 os = PKCS7_get_octet_string(p7->d.digest->contents); 329 break; 330 case NID_pkcs7_data: 331 break; 332 default: 333 PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 334 goto err; 335 } 336 337 for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) 338 if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) 339 goto err; 340 341 if (xa && !PKCS7_bio_add_digest(&out, xa)) 342 goto err; 343 344 if (evp_cipher != NULL) 345 { 346 unsigned char key[EVP_MAX_KEY_LENGTH]; 347 unsigned char iv[EVP_MAX_IV_LENGTH]; 348 int keylen,ivlen; 349 EVP_CIPHER_CTX *ctx; 350 351 if ((btmp=BIO_new(BIO_f_cipher())) == NULL) 352 { 353 PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); 354 goto err; 355 } 356 BIO_get_cipher_ctx(btmp, &ctx); 357 keylen=EVP_CIPHER_key_length(evp_cipher); 358 ivlen=EVP_CIPHER_iv_length(evp_cipher); 359 xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); 360 if (ivlen > 0) 361 if (RAND_pseudo_bytes(iv,ivlen) <= 0) 362 goto err; 363 if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0) 364 goto err; 365 if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) 366 goto err; 367 if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) 368 goto err; 369 370 if (ivlen > 0) { 371 if (xalg->parameter == NULL) { 372 xalg->parameter = ASN1_TYPE_new(); 373 if (xalg->parameter == NULL) 374 goto err; 375 } 376 if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) 377 goto err; 378 } 379 380 /* Lets do the pub key stuff :-) */ 381 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) 382 { 383 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 384 if (pkcs7_encode_rinfo(ri, key, keylen) <= 0) 385 goto err; 386 } 387 OPENSSL_cleanse(key, keylen); 388 389 if (out == NULL) 390 out=btmp; 391 else 392 BIO_push(out,btmp); 393 btmp=NULL; 394 } 395 396 if (bio == NULL) 397 { 398 if (PKCS7_is_detached(p7)) 399 bio=BIO_new(BIO_s_null()); 400 else if (os && os->length > 0) 401 bio = BIO_new_mem_buf(os->data, os->length); 402 if(bio == NULL) 403 { 404 bio=BIO_new(BIO_s_mem()); 405 if (bio == NULL) 406 goto err; 407 BIO_set_mem_eof_return(bio,0); 408 } 409 } 410 if (out) 411 BIO_push(out,bio); 412 else 413 out = bio; 414 bio=NULL; 415 if (0) 416 { 417err: 418 if (out != NULL) 419 BIO_free_all(out); 420 if (btmp != NULL) 421 BIO_free_all(btmp); 422 out=NULL; 423 } 424 return(out); 425 } 426 427static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert) 428 { 429 int ret; 430 ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, 431 pcert->cert_info->issuer); 432 if (ret) 433 return ret; 434 return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, 435 ri->issuer_and_serial->serial); 436 } 437 438/* int */ 439BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) 440 { 441 int i,j; 442 BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL; 443 X509_ALGOR *xa; 444 ASN1_OCTET_STRING *data_body=NULL; 445 const EVP_MD *evp_md; 446 const EVP_CIPHER *evp_cipher=NULL; 447 EVP_CIPHER_CTX *evp_ctx=NULL; 448 X509_ALGOR *enc_alg=NULL; 449 STACK_OF(X509_ALGOR) *md_sk=NULL; 450 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; 451 PKCS7_RECIP_INFO *ri=NULL; 452 unsigned char *ek = NULL, *tkey = NULL; 453 int eklen = 0, tkeylen = 0; 454 455 if (p7 == NULL) { 456 PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); 457 return NULL; 458 } 459 460 if (p7->d.ptr == NULL) { 461 PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); 462 return NULL; 463 } 464 465 i=OBJ_obj2nid(p7->type); 466 p7->state=PKCS7_S_HEADER; 467 468 switch (i) 469 { 470 case NID_pkcs7_signed: 471 data_body=PKCS7_get_octet_string(p7->d.sign->contents); 472 if (!PKCS7_is_detached(p7) && data_body == NULL) 473 { 474 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_INVALID_SIGNED_DATA_TYPE); 475 goto err; 476 } 477 md_sk=p7->d.sign->md_algs; 478 break; 479 case NID_pkcs7_signedAndEnveloped: 480 rsk=p7->d.signed_and_enveloped->recipientinfo; 481 md_sk=p7->d.signed_and_enveloped->md_algs; 482 data_body=p7->d.signed_and_enveloped->enc_data->enc_data; 483 enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm; 484 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); 485 if (evp_cipher == NULL) 486 { 487 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 488 goto err; 489 } 490 break; 491 case NID_pkcs7_enveloped: 492 rsk=p7->d.enveloped->recipientinfo; 493 enc_alg=p7->d.enveloped->enc_data->algorithm; 494 data_body=p7->d.enveloped->enc_data->enc_data; 495 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); 496 if (evp_cipher == NULL) 497 { 498 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 499 goto err; 500 } 501 break; 502 default: 503 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 504 goto err; 505 } 506 507 /* We will be checking the signature */ 508 if (md_sk != NULL) 509 { 510 for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) 511 { 512 xa=sk_X509_ALGOR_value(md_sk,i); 513 if ((btmp=BIO_new(BIO_f_md())) == NULL) 514 { 515 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); 516 goto err; 517 } 518 519 j=OBJ_obj2nid(xa->algorithm); 520 evp_md=EVP_get_digestbynid(j); 521 if (evp_md == NULL) 522 { 523 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE); 524 goto err; 525 } 526 527 BIO_set_md(btmp,evp_md); 528 if (out == NULL) 529 out=btmp; 530 else 531 BIO_push(out,btmp); 532 btmp=NULL; 533 } 534 } 535 536 if (evp_cipher != NULL) 537 { 538#if 0 539 unsigned char key[EVP_MAX_KEY_LENGTH]; 540 unsigned char iv[EVP_MAX_IV_LENGTH]; 541 unsigned char *p; 542 int keylen,ivlen; 543 int max; 544 X509_OBJECT ret; 545#endif 546 547 if ((etmp=BIO_new(BIO_f_cipher())) == NULL) 548 { 549 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); 550 goto err; 551 } 552 553 /* It was encrypted, we need to decrypt the secret key 554 * with the private key */ 555 556 /* Find the recipientInfo which matches the passed certificate 557 * (if any) 558 */ 559 560 if (pcert) 561 { 562 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) 563 { 564 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 565 if (!pkcs7_cmp_ri(ri, pcert)) 566 break; 567 ri=NULL; 568 } 569 if (ri == NULL) 570 { 571 PKCS7err(PKCS7_F_PKCS7_DATADECODE, 572 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); 573 goto err; 574 } 575 } 576 577 /* If we haven't got a certificate try each ri in turn */ 578 if (pcert == NULL) 579 { 580 /* Always attempt to decrypt all rinfo even 581 * after sucess as a defence against MMA timing 582 * attacks. 583 */ 584 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) 585 { 586 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 587 588 if (pkcs7_decrypt_rinfo(&ek, &eklen, 589 ri, pkey) < 0) 590 goto err; 591 ERR_clear_error(); 592 } 593 } 594 else 595 { 596 /* Only exit on fatal errors, not decrypt failure */ 597 if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) 598 goto err; 599 ERR_clear_error(); 600 } 601 602 evp_ctx=NULL; 603 BIO_get_cipher_ctx(etmp,&evp_ctx); 604 if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0) 605 goto err; 606 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) 607 goto err; 608 /* Generate random key as MMA defence */ 609 tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); 610 tkey = OPENSSL_malloc(tkeylen); 611 if (!tkey) 612 goto err; 613 if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) 614 goto err; 615 if (ek == NULL) 616 { 617 ek = tkey; 618 eklen = tkeylen; 619 tkey = NULL; 620 } 621 622 if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) { 623 /* Some S/MIME clients don't use the same key 624 * and effective key length. The key length is 625 * determined by the size of the decrypted RSA key. 626 */ 627 if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) 628 { 629 /* Use random key as MMA defence */ 630 OPENSSL_cleanse(ek, eklen); 631 OPENSSL_free(ek); 632 ek = tkey; 633 eklen = tkeylen; 634 tkey = NULL; 635 } 636 } 637 /* Clear errors so we don't leak information useful in MMA */ 638 ERR_clear_error(); 639 if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,ek,NULL,0) <= 0) 640 goto err; 641 642 if (ek) 643 { 644 OPENSSL_cleanse(ek,eklen); 645 OPENSSL_free(ek); 646 ek = NULL; 647 } 648 if (tkey) 649 { 650 OPENSSL_cleanse(tkey,tkeylen); 651 OPENSSL_free(tkey); 652 tkey = NULL; 653 } 654 655 if (out == NULL) 656 out=etmp; 657 else 658 BIO_push(out,etmp); 659 etmp=NULL; 660 } 661 662#if 1 663 if (PKCS7_is_detached(p7) || (in_bio != NULL)) 664 { 665 bio=in_bio; 666 } 667 else 668 { 669#if 0 670 bio=BIO_new(BIO_s_mem()); 671 /* We need to set this so that when we have read all 672 * the data, the encrypt BIO, if present, will read 673 * EOF and encode the last few bytes */ 674 BIO_set_mem_eof_return(bio,0); 675 676 if (data_body->length > 0) 677 BIO_write(bio,(char *)data_body->data,data_body->length); 678#else 679 if (data_body->length > 0) 680 bio = BIO_new_mem_buf(data_body->data,data_body->length); 681 else { 682 bio=BIO_new(BIO_s_mem()); 683 BIO_set_mem_eof_return(bio,0); 684 } 685 if (bio == NULL) 686 goto err; 687#endif 688 } 689 BIO_push(out,bio); 690 bio=NULL; 691#endif 692 if (0) 693 { 694err: 695 if (ek) 696 { 697 OPENSSL_cleanse(ek,eklen); 698 OPENSSL_free(ek); 699 } 700 if (tkey) 701 { 702 OPENSSL_cleanse(tkey,tkeylen); 703 OPENSSL_free(tkey); 704 } 705 if (out != NULL) BIO_free_all(out); 706 if (btmp != NULL) BIO_free_all(btmp); 707 if (etmp != NULL) BIO_free_all(etmp); 708 if (bio != NULL) BIO_free_all(bio); 709 out=NULL; 710 } 711 return(out); 712 } 713 714static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) 715 { 716 for (;;) 717 { 718 bio=BIO_find_type(bio,BIO_TYPE_MD); 719 if (bio == NULL) 720 { 721 PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 722 return NULL; 723 } 724 BIO_get_md_ctx(bio,pmd); 725 if (*pmd == NULL) 726 { 727 PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR); 728 return NULL; 729 } 730 if (EVP_MD_CTX_type(*pmd) == nid) 731 return bio; 732 bio=BIO_next(bio); 733 } 734 return NULL; 735 } 736 737static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) 738 { 739 unsigned char md_data[EVP_MAX_MD_SIZE]; 740 unsigned int md_len; 741 742 /* Add signing time if not already present */ 743 if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) 744 { 745 if (!PKCS7_add0_attrib_signing_time(si, NULL)) 746 { 747 PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, 748 ERR_R_MALLOC_FAILURE); 749 return 0; 750 } 751 } 752 753 /* Add digest */ 754 if (!EVP_DigestFinal_ex(mctx, md_data,&md_len)) 755 { 756 PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB); 757 return 0; 758 } 759 if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) 760 { 761 PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); 762 return 0; 763 } 764 765 /* Now sign the attributes */ 766 if (!PKCS7_SIGNER_INFO_sign(si)) 767 return 0; 768 769 return 1; 770 } 771 772 773int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) 774 { 775 int ret=0; 776 int i,j; 777 BIO *btmp; 778 PKCS7_SIGNER_INFO *si; 779 EVP_MD_CTX *mdc,ctx_tmp; 780 STACK_OF(X509_ATTRIBUTE) *sk; 781 STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; 782 ASN1_OCTET_STRING *os=NULL; 783 784 if (p7 == NULL) { 785 PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); 786 return 0; 787 } 788 789 if (p7->d.ptr == NULL) { 790 PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); 791 return 0; 792 } 793 794 EVP_MD_CTX_init(&ctx_tmp); 795 i=OBJ_obj2nid(p7->type); 796 p7->state=PKCS7_S_HEADER; 797 798 switch (i) 799 { 800 case NID_pkcs7_data: 801 os = p7->d.data; 802 break; 803 case NID_pkcs7_signedAndEnveloped: 804 /* XXXXXXXXXXXXXXXX */ 805 si_sk=p7->d.signed_and_enveloped->signer_info; 806 os = p7->d.signed_and_enveloped->enc_data->enc_data; 807 if (!os) 808 { 809 os=M_ASN1_OCTET_STRING_new(); 810 if (!os) 811 { 812 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE); 813 goto err; 814 } 815 p7->d.signed_and_enveloped->enc_data->enc_data=os; 816 } 817 break; 818 case NID_pkcs7_enveloped: 819 /* XXXXXXXXXXXXXXXX */ 820 os = p7->d.enveloped->enc_data->enc_data; 821 if (!os) 822 { 823 os=M_ASN1_OCTET_STRING_new(); 824 if (!os) 825 { 826 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE); 827 goto err; 828 } 829 p7->d.enveloped->enc_data->enc_data=os; 830 } 831 break; 832 case NID_pkcs7_signed: 833 si_sk=p7->d.sign->signer_info; 834 os=PKCS7_get_octet_string(p7->d.sign->contents); 835 /* If detached data then the content is excluded */ 836 if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { 837 M_ASN1_OCTET_STRING_free(os); 838 os = NULL; 839 p7->d.sign->contents->d.data = NULL; 840 } 841 break; 842 843 case NID_pkcs7_digest: 844 os=PKCS7_get_octet_string(p7->d.digest->contents); 845 /* If detached data then the content is excluded */ 846 if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) 847 { 848 M_ASN1_OCTET_STRING_free(os); 849 os = NULL; 850 p7->d.digest->contents->d.data = NULL; 851 } 852 break; 853 854 default: 855 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 856 goto err; 857 } 858 859 if (si_sk != NULL) 860 { 861 for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++) 862 { 863 si=sk_PKCS7_SIGNER_INFO_value(si_sk,i); 864 if (si->pkey == NULL) 865 continue; 866 867 j = OBJ_obj2nid(si->digest_alg->algorithm); 868 869 btmp=bio; 870 871 btmp = PKCS7_find_digest(&mdc, btmp, j); 872 873 if (btmp == NULL) 874 goto err; 875 876 /* We now have the EVP_MD_CTX, lets do the 877 * signing. */ 878 if (!EVP_MD_CTX_copy_ex(&ctx_tmp,mdc)) 879 goto err; 880 881 sk=si->auth_attr; 882 883 /* If there are attributes, we add the digest 884 * attribute and only sign the attributes */ 885 if (sk_X509_ATTRIBUTE_num(sk) > 0) 886 { 887 if (!do_pkcs7_signed_attrib(si, &ctx_tmp)) 888 goto err; 889 } 890 else 891 { 892 unsigned char *abuf = NULL; 893 unsigned int abuflen; 894 abuflen = EVP_PKEY_size(si->pkey); 895 abuf = OPENSSL_malloc(abuflen); 896 if (!abuf) 897 goto err; 898 899 if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen, 900 si->pkey)) 901 { 902 PKCS7err(PKCS7_F_PKCS7_DATAFINAL, 903 ERR_R_EVP_LIB); 904 goto err; 905 } 906 ASN1_STRING_set0(si->enc_digest, abuf, abuflen); 907 } 908 } 909 } 910 else if (i == NID_pkcs7_digest) { 911 unsigned char md_data[EVP_MAX_MD_SIZE]; 912 unsigned int md_len; 913 if (!PKCS7_find_digest(&mdc, bio, 914 OBJ_obj2nid(p7->d.digest->md->algorithm))) 915 goto err; 916 if (!EVP_DigestFinal_ex(mdc,md_data,&md_len)) 917 goto err; 918 M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); 919 } 920 921 if (!PKCS7_is_detached(p7)) { 922 /* 923 * NOTE(emilia): I think we only reach os == NULL here because detached 924 * digested data support is broken. 925 */ 926 if (os == NULL) 927 goto err; 928 if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { 929 char *cont; 930 long contlen; 931 btmp = BIO_find_type(bio, BIO_TYPE_MEM); 932 if (btmp == NULL) { 933 PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); 934 goto err; 935 } 936 contlen = BIO_get_mem_data(btmp, &cont); 937 /* 938 * Mark the BIO read only then we can use its copy of the data 939 * instead of making an extra copy. 940 */ 941 BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); 942 BIO_set_mem_eof_return(btmp, 0); 943 ASN1_STRING_set0(os, (unsigned char *)cont, contlen); 944 } 945 } 946 ret=1; 947err: 948 EVP_MD_CTX_cleanup(&ctx_tmp); 949 return(ret); 950 } 951 952int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) 953 { 954 EVP_MD_CTX mctx; 955 EVP_PKEY_CTX *pctx; 956 unsigned char *abuf = NULL; 957 int alen; 958 size_t siglen; 959 const EVP_MD *md = NULL; 960 961 md = EVP_get_digestbyobj(si->digest_alg->algorithm); 962 if (md == NULL) 963 return 0; 964 965 EVP_MD_CTX_init(&mctx); 966 if (EVP_DigestSignInit(&mctx, &pctx, md,NULL, si->pkey) <= 0) 967 goto err; 968 969 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 970 EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) 971 { 972 PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 973 goto err; 974 } 975 976 alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr,&abuf, 977 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); 978 if(!abuf) 979 goto err; 980 if (EVP_DigestSignUpdate(&mctx,abuf,alen) <= 0) 981 goto err; 982 OPENSSL_free(abuf); 983 abuf = NULL; 984 if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) 985 goto err; 986 abuf = OPENSSL_malloc(siglen); 987 if(!abuf) 988 goto err; 989 if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) 990 goto err; 991 992 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 993 EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) 994 { 995 PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 996 goto err; 997 } 998 999 EVP_MD_CTX_cleanup(&mctx); 1000 1001 ASN1_STRING_set0(si->enc_digest, abuf, siglen); 1002 1003 return 1; 1004 1005 err: 1006 if (abuf) 1007 OPENSSL_free(abuf); 1008 EVP_MD_CTX_cleanup(&mctx); 1009 return 0; 1010 1011 } 1012 1013int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, 1014 PKCS7 *p7, PKCS7_SIGNER_INFO *si) 1015 { 1016 PKCS7_ISSUER_AND_SERIAL *ias; 1017 int ret=0,i; 1018 STACK_OF(X509) *cert; 1019 X509 *x509; 1020 1021 if (p7 == NULL) { 1022 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); 1023 return 0; 1024 } 1025 1026 if (p7->d.ptr == NULL) { 1027 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); 1028 return 0; 1029 } 1030 1031 if (PKCS7_type_is_signed(p7)) 1032 { 1033 cert=p7->d.sign->cert; 1034 } 1035 else if (PKCS7_type_is_signedAndEnveloped(p7)) 1036 { 1037 cert=p7->d.signed_and_enveloped->cert; 1038 } 1039 else 1040 { 1041 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE); 1042 goto err; 1043 } 1044 /* XXXXXXXXXXXXXXXXXXXXXXX */ 1045 ias=si->issuer_and_serial; 1046 1047 x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial); 1048 1049 /* were we able to find the cert in passed to us */ 1050 if (x509 == NULL) 1051 { 1052 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); 1053 goto err; 1054 } 1055 1056 /* Lets verify */ 1057 if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert)) 1058 { 1059 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); 1060 goto err; 1061 } 1062 X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); 1063 i=X509_verify_cert(ctx); 1064 if (i <= 0) 1065 { 1066 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); 1067 X509_STORE_CTX_cleanup(ctx); 1068 goto err; 1069 } 1070 X509_STORE_CTX_cleanup(ctx); 1071 1072 return PKCS7_signatureVerify(bio, p7, si, x509); 1073 err: 1074 return ret; 1075 } 1076 1077int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, 1078 X509 *x509) 1079 { 1080 ASN1_OCTET_STRING *os; 1081 EVP_MD_CTX mdc_tmp,*mdc; 1082 int ret=0,i; 1083 int md_type; 1084 STACK_OF(X509_ATTRIBUTE) *sk; 1085 BIO *btmp; 1086 EVP_PKEY *pkey; 1087 1088 EVP_MD_CTX_init(&mdc_tmp); 1089 1090 if (!PKCS7_type_is_signed(p7) && 1091 !PKCS7_type_is_signedAndEnveloped(p7)) { 1092 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1093 PKCS7_R_WRONG_PKCS7_TYPE); 1094 goto err; 1095 } 1096 1097 md_type=OBJ_obj2nid(si->digest_alg->algorithm); 1098 1099 btmp=bio; 1100 for (;;) 1101 { 1102 if ((btmp == NULL) || 1103 ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL)) 1104 { 1105 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1106 PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1107 goto err; 1108 } 1109 BIO_get_md_ctx(btmp,&mdc); 1110 if (mdc == NULL) 1111 { 1112 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1113 ERR_R_INTERNAL_ERROR); 1114 goto err; 1115 } 1116 if (EVP_MD_CTX_type(mdc) == md_type) 1117 break; 1118 /* Workaround for some broken clients that put the signature 1119 * OID instead of the digest OID in digest_alg->algorithm 1120 */ 1121 if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) 1122 break; 1123 btmp=BIO_next(btmp); 1124 } 1125 1126 /* mdc is the digest ctx that we want, unless there are attributes, 1127 * in which case the digest is the signed attributes */ 1128 if (!EVP_MD_CTX_copy_ex(&mdc_tmp,mdc)) 1129 goto err; 1130 1131 sk=si->auth_attr; 1132 if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) 1133 { 1134 unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; 1135 unsigned int md_len; 1136 int alen; 1137 ASN1_OCTET_STRING *message_digest; 1138 1139 if (!EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len)) 1140 goto err; 1141 message_digest=PKCS7_digest_from_attributes(sk); 1142 if (!message_digest) 1143 { 1144 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1145 PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1146 goto err; 1147 } 1148 if ((message_digest->length != (int)md_len) || 1149 (memcmp(message_digest->data,md_dat,md_len))) 1150 { 1151#if 0 1152{ 1153int ii; 1154for (ii=0; ii<message_digest->length; ii++) 1155 printf("%02X",message_digest->data[ii]); printf(" sent\n"); 1156for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); 1157} 1158#endif 1159 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1160 PKCS7_R_DIGEST_FAILURE); 1161 ret= -1; 1162 goto err; 1163 } 1164 1165 if (!EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL)) 1166 goto err; 1167 1168 alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, 1169 ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); 1170 if (alen <= 0) 1171 { 1172 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,ERR_R_ASN1_LIB); 1173 ret = -1; 1174 goto err; 1175 } 1176 if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) 1177 goto err; 1178 1179 OPENSSL_free(abuf); 1180 } 1181 1182 os=si->enc_digest; 1183 pkey = X509_get_pubkey(x509); 1184 if (!pkey) 1185 { 1186 ret = -1; 1187 goto err; 1188 } 1189 1190 i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey); 1191 EVP_PKEY_free(pkey); 1192 if (i <= 0) 1193 { 1194 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1195 PKCS7_R_SIGNATURE_FAILURE); 1196 ret= -1; 1197 goto err; 1198 } 1199 else 1200 ret=1; 1201err: 1202 EVP_MD_CTX_cleanup(&mdc_tmp); 1203 return(ret); 1204 } 1205 1206PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) 1207 { 1208 STACK_OF(PKCS7_RECIP_INFO) *rsk; 1209 PKCS7_RECIP_INFO *ri; 1210 int i; 1211 1212 i=OBJ_obj2nid(p7->type); 1213 if (i != NID_pkcs7_signedAndEnveloped) 1214 return NULL; 1215 if (p7->d.signed_and_enveloped == NULL) 1216 return NULL; 1217 rsk=p7->d.signed_and_enveloped->recipientinfo; 1218 if (rsk == NULL) 1219 return NULL; 1220 ri=sk_PKCS7_RECIP_INFO_value(rsk,0); 1221 if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL); 1222 ri=sk_PKCS7_RECIP_INFO_value(rsk,idx); 1223 return(ri->issuer_and_serial); 1224 } 1225 1226ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid) 1227 { 1228 return(get_attribute(si->auth_attr,nid)); 1229 } 1230 1231ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid) 1232 { 1233 return(get_attribute(si->unauth_attr,nid)); 1234 } 1235 1236static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid) 1237 { 1238 int i; 1239 X509_ATTRIBUTE *xa; 1240 ASN1_OBJECT *o; 1241 1242 o=OBJ_nid2obj(nid); 1243 if (!o || !sk) return(NULL); 1244 for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) 1245 { 1246 xa=sk_X509_ATTRIBUTE_value(sk,i); 1247 if (OBJ_cmp(xa->object,o) == 0) 1248 { 1249 if (!xa->single && sk_ASN1_TYPE_num(xa->value.set)) 1250 return(sk_ASN1_TYPE_value(xa->value.set,0)); 1251 else 1252 return(NULL); 1253 } 1254 } 1255 return(NULL); 1256 } 1257 1258ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) 1259{ 1260 ASN1_TYPE *astype; 1261 if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL; 1262 return astype->value.octet_string; 1263} 1264 1265int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, 1266 STACK_OF(X509_ATTRIBUTE) *sk) 1267 { 1268 int i; 1269 1270 if (p7si->auth_attr != NULL) 1271 sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free); 1272 p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk); 1273 if (p7si->auth_attr == NULL) 1274 return 0; 1275 for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) 1276 { 1277 if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i, 1278 X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i)))) 1279 == NULL) 1280 return(0); 1281 } 1282 return(1); 1283 } 1284 1285int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk) 1286 { 1287 int i; 1288 1289 if (p7si->unauth_attr != NULL) 1290 sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, 1291 X509_ATTRIBUTE_free); 1292 p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk); 1293 if (p7si->unauth_attr == NULL) 1294 return 0; 1295 for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) 1296 { 1297 if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i, 1298 X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i)))) 1299 == NULL) 1300 return(0); 1301 } 1302 return(1); 1303 } 1304 1305int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1306 void *value) 1307 { 1308 return(add_attribute(&(p7si->auth_attr),nid,atrtype,value)); 1309 } 1310 1311int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1312 void *value) 1313 { 1314 return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value)); 1315 } 1316 1317static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 1318 void *value) 1319 { 1320 X509_ATTRIBUTE *attr=NULL; 1321 1322 if (*sk == NULL) 1323 { 1324 *sk = sk_X509_ATTRIBUTE_new_null(); 1325 if (*sk == NULL) 1326 return 0; 1327new_attrib: 1328 if (!(attr=X509_ATTRIBUTE_create(nid,atrtype,value))) 1329 return 0; 1330 if (!sk_X509_ATTRIBUTE_push(*sk,attr)) 1331 { 1332 X509_ATTRIBUTE_free(attr); 1333 return 0; 1334 } 1335 } 1336 else 1337 { 1338 int i; 1339 1340 for (i=0; i<sk_X509_ATTRIBUTE_num(*sk); i++) 1341 { 1342 attr=sk_X509_ATTRIBUTE_value(*sk,i); 1343 if (OBJ_obj2nid(attr->object) == nid) 1344 { 1345 X509_ATTRIBUTE_free(attr); 1346 attr=X509_ATTRIBUTE_create(nid,atrtype,value); 1347 if (attr == NULL) 1348 return 0; 1349 if (!sk_X509_ATTRIBUTE_set(*sk,i,attr)) 1350 { 1351 X509_ATTRIBUTE_free(attr); 1352 return 0; 1353 } 1354 goto end; 1355 } 1356 } 1357 goto new_attrib; 1358 } 1359end: 1360 return(1); 1361 } 1362 1363