pk7_doit.c revision 284295
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 /* Detached content must be supplied via in_bio instead. */ 508 if (data_body == NULL && in_bio == NULL) { 509 PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); 510 goto err; 511 } 512 513 /* We will be checking the signature */ 514 if (md_sk != NULL) 515 { 516 for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) 517 { 518 xa=sk_X509_ALGOR_value(md_sk,i); 519 if ((btmp=BIO_new(BIO_f_md())) == NULL) 520 { 521 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); 522 goto err; 523 } 524 525 j=OBJ_obj2nid(xa->algorithm); 526 evp_md=EVP_get_digestbynid(j); 527 if (evp_md == NULL) 528 { 529 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE); 530 goto err; 531 } 532 533 BIO_set_md(btmp,evp_md); 534 if (out == NULL) 535 out=btmp; 536 else 537 BIO_push(out,btmp); 538 btmp=NULL; 539 } 540 } 541 542 if (evp_cipher != NULL) 543 { 544#if 0 545 unsigned char key[EVP_MAX_KEY_LENGTH]; 546 unsigned char iv[EVP_MAX_IV_LENGTH]; 547 unsigned char *p; 548 int keylen,ivlen; 549 int max; 550 X509_OBJECT ret; 551#endif 552 553 if ((etmp=BIO_new(BIO_f_cipher())) == NULL) 554 { 555 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); 556 goto err; 557 } 558 559 /* It was encrypted, we need to decrypt the secret key 560 * with the private key */ 561 562 /* Find the recipientInfo which matches the passed certificate 563 * (if any) 564 */ 565 566 if (pcert) 567 { 568 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) 569 { 570 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 571 if (!pkcs7_cmp_ri(ri, pcert)) 572 break; 573 ri=NULL; 574 } 575 if (ri == NULL) 576 { 577 PKCS7err(PKCS7_F_PKCS7_DATADECODE, 578 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); 579 goto err; 580 } 581 } 582 583 /* If we haven't got a certificate try each ri in turn */ 584 if (pcert == NULL) 585 { 586 /* Always attempt to decrypt all rinfo even 587 * after sucess as a defence against MMA timing 588 * attacks. 589 */ 590 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) 591 { 592 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 593 594 if (pkcs7_decrypt_rinfo(&ek, &eklen, 595 ri, pkey) < 0) 596 goto err; 597 ERR_clear_error(); 598 } 599 } 600 else 601 { 602 /* Only exit on fatal errors, not decrypt failure */ 603 if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) 604 goto err; 605 ERR_clear_error(); 606 } 607 608 evp_ctx=NULL; 609 BIO_get_cipher_ctx(etmp,&evp_ctx); 610 if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0) 611 goto err; 612 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) 613 goto err; 614 /* Generate random key as MMA defence */ 615 tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); 616 tkey = OPENSSL_malloc(tkeylen); 617 if (!tkey) 618 goto err; 619 if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) 620 goto err; 621 if (ek == NULL) 622 { 623 ek = tkey; 624 eklen = tkeylen; 625 tkey = NULL; 626 } 627 628 if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) { 629 /* Some S/MIME clients don't use the same key 630 * and effective key length. The key length is 631 * determined by the size of the decrypted RSA key. 632 */ 633 if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) 634 { 635 /* Use random key as MMA defence */ 636 OPENSSL_cleanse(ek, eklen); 637 OPENSSL_free(ek); 638 ek = tkey; 639 eklen = tkeylen; 640 tkey = NULL; 641 } 642 } 643 /* Clear errors so we don't leak information useful in MMA */ 644 ERR_clear_error(); 645 if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,ek,NULL,0) <= 0) 646 goto err; 647 648 if (ek) 649 { 650 OPENSSL_cleanse(ek,eklen); 651 OPENSSL_free(ek); 652 ek = NULL; 653 } 654 if (tkey) 655 { 656 OPENSSL_cleanse(tkey,tkeylen); 657 OPENSSL_free(tkey); 658 tkey = NULL; 659 } 660 661 if (out == NULL) 662 out=etmp; 663 else 664 BIO_push(out,etmp); 665 etmp=NULL; 666 } 667 668#if 1 669 if (in_bio != NULL) 670 { 671 bio=in_bio; 672 } 673 else 674 { 675#if 0 676 bio=BIO_new(BIO_s_mem()); 677 /* We need to set this so that when we have read all 678 * the data, the encrypt BIO, if present, will read 679 * EOF and encode the last few bytes */ 680 BIO_set_mem_eof_return(bio,0); 681 682 if (data_body->length > 0) 683 BIO_write(bio,(char *)data_body->data,data_body->length); 684#else 685 if (data_body->length > 0) 686 bio = BIO_new_mem_buf(data_body->data,data_body->length); 687 else { 688 bio=BIO_new(BIO_s_mem()); 689 BIO_set_mem_eof_return(bio,0); 690 } 691 if (bio == NULL) 692 goto err; 693#endif 694 } 695 BIO_push(out,bio); 696 bio=NULL; 697#endif 698 if (0) 699 { 700err: 701 if (ek) 702 { 703 OPENSSL_cleanse(ek,eklen); 704 OPENSSL_free(ek); 705 } 706 if (tkey) 707 { 708 OPENSSL_cleanse(tkey,tkeylen); 709 OPENSSL_free(tkey); 710 } 711 if (out != NULL) BIO_free_all(out); 712 if (btmp != NULL) BIO_free_all(btmp); 713 if (etmp != NULL) BIO_free_all(etmp); 714 if (bio != NULL) BIO_free_all(bio); 715 out=NULL; 716 } 717 return(out); 718 } 719 720static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) 721 { 722 for (;;) 723 { 724 bio=BIO_find_type(bio,BIO_TYPE_MD); 725 if (bio == NULL) 726 { 727 PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 728 return NULL; 729 } 730 BIO_get_md_ctx(bio,pmd); 731 if (*pmd == NULL) 732 { 733 PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR); 734 return NULL; 735 } 736 if (EVP_MD_CTX_type(*pmd) == nid) 737 return bio; 738 bio=BIO_next(bio); 739 } 740 return NULL; 741 } 742 743static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) 744 { 745 unsigned char md_data[EVP_MAX_MD_SIZE]; 746 unsigned int md_len; 747 748 /* Add signing time if not already present */ 749 if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) 750 { 751 if (!PKCS7_add0_attrib_signing_time(si, NULL)) 752 { 753 PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, 754 ERR_R_MALLOC_FAILURE); 755 return 0; 756 } 757 } 758 759 /* Add digest */ 760 if (!EVP_DigestFinal_ex(mctx, md_data,&md_len)) 761 { 762 PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB); 763 return 0; 764 } 765 if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) 766 { 767 PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); 768 return 0; 769 } 770 771 /* Now sign the attributes */ 772 if (!PKCS7_SIGNER_INFO_sign(si)) 773 return 0; 774 775 return 1; 776 } 777 778 779int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) 780 { 781 int ret=0; 782 int i,j; 783 BIO *btmp; 784 PKCS7_SIGNER_INFO *si; 785 EVP_MD_CTX *mdc,ctx_tmp; 786 STACK_OF(X509_ATTRIBUTE) *sk; 787 STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; 788 ASN1_OCTET_STRING *os=NULL; 789 790 if (p7 == NULL) { 791 PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); 792 return 0; 793 } 794 795 if (p7->d.ptr == NULL) { 796 PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); 797 return 0; 798 } 799 800 EVP_MD_CTX_init(&ctx_tmp); 801 i=OBJ_obj2nid(p7->type); 802 p7->state=PKCS7_S_HEADER; 803 804 switch (i) 805 { 806 case NID_pkcs7_data: 807 os = p7->d.data; 808 break; 809 case NID_pkcs7_signedAndEnveloped: 810 /* XXXXXXXXXXXXXXXX */ 811 si_sk=p7->d.signed_and_enveloped->signer_info; 812 os = p7->d.signed_and_enveloped->enc_data->enc_data; 813 if (!os) 814 { 815 os=M_ASN1_OCTET_STRING_new(); 816 if (!os) 817 { 818 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE); 819 goto err; 820 } 821 p7->d.signed_and_enveloped->enc_data->enc_data=os; 822 } 823 break; 824 case NID_pkcs7_enveloped: 825 /* XXXXXXXXXXXXXXXX */ 826 os = p7->d.enveloped->enc_data->enc_data; 827 if (!os) 828 { 829 os=M_ASN1_OCTET_STRING_new(); 830 if (!os) 831 { 832 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE); 833 goto err; 834 } 835 p7->d.enveloped->enc_data->enc_data=os; 836 } 837 break; 838 case NID_pkcs7_signed: 839 si_sk=p7->d.sign->signer_info; 840 os=PKCS7_get_octet_string(p7->d.sign->contents); 841 /* If detached data then the content is excluded */ 842 if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { 843 M_ASN1_OCTET_STRING_free(os); 844 os = NULL; 845 p7->d.sign->contents->d.data = NULL; 846 } 847 break; 848 849 case NID_pkcs7_digest: 850 os=PKCS7_get_octet_string(p7->d.digest->contents); 851 /* If detached data then the content is excluded */ 852 if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) 853 { 854 M_ASN1_OCTET_STRING_free(os); 855 os = NULL; 856 p7->d.digest->contents->d.data = NULL; 857 } 858 break; 859 860 default: 861 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 862 goto err; 863 } 864 865 if (si_sk != NULL) 866 { 867 for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++) 868 { 869 si=sk_PKCS7_SIGNER_INFO_value(si_sk,i); 870 if (si->pkey == NULL) 871 continue; 872 873 j = OBJ_obj2nid(si->digest_alg->algorithm); 874 875 btmp=bio; 876 877 btmp = PKCS7_find_digest(&mdc, btmp, j); 878 879 if (btmp == NULL) 880 goto err; 881 882 /* We now have the EVP_MD_CTX, lets do the 883 * signing. */ 884 if (!EVP_MD_CTX_copy_ex(&ctx_tmp,mdc)) 885 goto err; 886 887 sk=si->auth_attr; 888 889 /* If there are attributes, we add the digest 890 * attribute and only sign the attributes */ 891 if (sk_X509_ATTRIBUTE_num(sk) > 0) 892 { 893 if (!do_pkcs7_signed_attrib(si, &ctx_tmp)) 894 goto err; 895 } 896 else 897 { 898 unsigned char *abuf = NULL; 899 unsigned int abuflen; 900 abuflen = EVP_PKEY_size(si->pkey); 901 abuf = OPENSSL_malloc(abuflen); 902 if (!abuf) 903 goto err; 904 905 if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen, 906 si->pkey)) 907 { 908 PKCS7err(PKCS7_F_PKCS7_DATAFINAL, 909 ERR_R_EVP_LIB); 910 goto err; 911 } 912 ASN1_STRING_set0(si->enc_digest, abuf, abuflen); 913 } 914 } 915 } 916 else if (i == NID_pkcs7_digest) { 917 unsigned char md_data[EVP_MAX_MD_SIZE]; 918 unsigned int md_len; 919 if (!PKCS7_find_digest(&mdc, bio, 920 OBJ_obj2nid(p7->d.digest->md->algorithm))) 921 goto err; 922 if (!EVP_DigestFinal_ex(mdc,md_data,&md_len)) 923 goto err; 924 M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); 925 } 926 927 if (!PKCS7_is_detached(p7)) { 928 /* 929 * NOTE(emilia): I think we only reach os == NULL here because detached 930 * digested data support is broken. 931 */ 932 if (os == NULL) 933 goto err; 934 if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { 935 char *cont; 936 long contlen; 937 btmp = BIO_find_type(bio, BIO_TYPE_MEM); 938 if (btmp == NULL) { 939 PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); 940 goto err; 941 } 942 contlen = BIO_get_mem_data(btmp, &cont); 943 /* 944 * Mark the BIO read only then we can use its copy of the data 945 * instead of making an extra copy. 946 */ 947 BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); 948 BIO_set_mem_eof_return(btmp, 0); 949 ASN1_STRING_set0(os, (unsigned char *)cont, contlen); 950 } 951 } 952 ret=1; 953err: 954 EVP_MD_CTX_cleanup(&ctx_tmp); 955 return(ret); 956 } 957 958int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) 959 { 960 EVP_MD_CTX mctx; 961 EVP_PKEY_CTX *pctx; 962 unsigned char *abuf = NULL; 963 int alen; 964 size_t siglen; 965 const EVP_MD *md = NULL; 966 967 md = EVP_get_digestbyobj(si->digest_alg->algorithm); 968 if (md == NULL) 969 return 0; 970 971 EVP_MD_CTX_init(&mctx); 972 if (EVP_DigestSignInit(&mctx, &pctx, md,NULL, si->pkey) <= 0) 973 goto err; 974 975 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 976 EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) 977 { 978 PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 979 goto err; 980 } 981 982 alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr,&abuf, 983 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); 984 if(!abuf) 985 goto err; 986 if (EVP_DigestSignUpdate(&mctx,abuf,alen) <= 0) 987 goto err; 988 OPENSSL_free(abuf); 989 abuf = NULL; 990 if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) 991 goto err; 992 abuf = OPENSSL_malloc(siglen); 993 if(!abuf) 994 goto err; 995 if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) 996 goto err; 997 998 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 999 EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) 1000 { 1001 PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); 1002 goto err; 1003 } 1004 1005 EVP_MD_CTX_cleanup(&mctx); 1006 1007 ASN1_STRING_set0(si->enc_digest, abuf, siglen); 1008 1009 return 1; 1010 1011 err: 1012 if (abuf) 1013 OPENSSL_free(abuf); 1014 EVP_MD_CTX_cleanup(&mctx); 1015 return 0; 1016 1017 } 1018 1019int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, 1020 PKCS7 *p7, PKCS7_SIGNER_INFO *si) 1021 { 1022 PKCS7_ISSUER_AND_SERIAL *ias; 1023 int ret=0,i; 1024 STACK_OF(X509) *cert; 1025 X509 *x509; 1026 1027 if (p7 == NULL) { 1028 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_INVALID_NULL_POINTER); 1029 return 0; 1030 } 1031 1032 if (p7->d.ptr == NULL) { 1033 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY, PKCS7_R_NO_CONTENT); 1034 return 0; 1035 } 1036 1037 if (PKCS7_type_is_signed(p7)) 1038 { 1039 cert=p7->d.sign->cert; 1040 } 1041 else if (PKCS7_type_is_signedAndEnveloped(p7)) 1042 { 1043 cert=p7->d.signed_and_enveloped->cert; 1044 } 1045 else 1046 { 1047 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE); 1048 goto err; 1049 } 1050 /* XXXXXXXXXXXXXXXXXXXXXXX */ 1051 ias=si->issuer_and_serial; 1052 1053 x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial); 1054 1055 /* were we able to find the cert in passed to us */ 1056 if (x509 == NULL) 1057 { 1058 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); 1059 goto err; 1060 } 1061 1062 /* Lets verify */ 1063 if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert)) 1064 { 1065 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); 1066 goto err; 1067 } 1068 X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); 1069 i=X509_verify_cert(ctx); 1070 if (i <= 0) 1071 { 1072 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); 1073 X509_STORE_CTX_cleanup(ctx); 1074 goto err; 1075 } 1076 X509_STORE_CTX_cleanup(ctx); 1077 1078 return PKCS7_signatureVerify(bio, p7, si, x509); 1079 err: 1080 return ret; 1081 } 1082 1083int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, 1084 X509 *x509) 1085 { 1086 ASN1_OCTET_STRING *os; 1087 EVP_MD_CTX mdc_tmp,*mdc; 1088 int ret=0,i; 1089 int md_type; 1090 STACK_OF(X509_ATTRIBUTE) *sk; 1091 BIO *btmp; 1092 EVP_PKEY *pkey; 1093 1094 EVP_MD_CTX_init(&mdc_tmp); 1095 1096 if (!PKCS7_type_is_signed(p7) && 1097 !PKCS7_type_is_signedAndEnveloped(p7)) { 1098 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1099 PKCS7_R_WRONG_PKCS7_TYPE); 1100 goto err; 1101 } 1102 1103 md_type=OBJ_obj2nid(si->digest_alg->algorithm); 1104 1105 btmp=bio; 1106 for (;;) 1107 { 1108 if ((btmp == NULL) || 1109 ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL)) 1110 { 1111 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1112 PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1113 goto err; 1114 } 1115 BIO_get_md_ctx(btmp,&mdc); 1116 if (mdc == NULL) 1117 { 1118 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1119 ERR_R_INTERNAL_ERROR); 1120 goto err; 1121 } 1122 if (EVP_MD_CTX_type(mdc) == md_type) 1123 break; 1124 /* Workaround for some broken clients that put the signature 1125 * OID instead of the digest OID in digest_alg->algorithm 1126 */ 1127 if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) 1128 break; 1129 btmp=BIO_next(btmp); 1130 } 1131 1132 /* mdc is the digest ctx that we want, unless there are attributes, 1133 * in which case the digest is the signed attributes */ 1134 if (!EVP_MD_CTX_copy_ex(&mdc_tmp,mdc)) 1135 goto err; 1136 1137 sk=si->auth_attr; 1138 if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) 1139 { 1140 unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; 1141 unsigned int md_len; 1142 int alen; 1143 ASN1_OCTET_STRING *message_digest; 1144 1145 if (!EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len)) 1146 goto err; 1147 message_digest=PKCS7_digest_from_attributes(sk); 1148 if (!message_digest) 1149 { 1150 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1151 PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 1152 goto err; 1153 } 1154 if ((message_digest->length != (int)md_len) || 1155 (memcmp(message_digest->data,md_dat,md_len))) 1156 { 1157#if 0 1158{ 1159int ii; 1160for (ii=0; ii<message_digest->length; ii++) 1161 printf("%02X",message_digest->data[ii]); printf(" sent\n"); 1162for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); 1163} 1164#endif 1165 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1166 PKCS7_R_DIGEST_FAILURE); 1167 ret= -1; 1168 goto err; 1169 } 1170 1171 if (!EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL)) 1172 goto err; 1173 1174 alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, 1175 ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); 1176 if (alen <= 0) 1177 { 1178 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,ERR_R_ASN1_LIB); 1179 ret = -1; 1180 goto err; 1181 } 1182 if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) 1183 goto err; 1184 1185 OPENSSL_free(abuf); 1186 } 1187 1188 os=si->enc_digest; 1189 pkey = X509_get_pubkey(x509); 1190 if (!pkey) 1191 { 1192 ret = -1; 1193 goto err; 1194 } 1195 1196 i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey); 1197 EVP_PKEY_free(pkey); 1198 if (i <= 0) 1199 { 1200 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 1201 PKCS7_R_SIGNATURE_FAILURE); 1202 ret= -1; 1203 goto err; 1204 } 1205 else 1206 ret=1; 1207err: 1208 EVP_MD_CTX_cleanup(&mdc_tmp); 1209 return(ret); 1210 } 1211 1212PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) 1213 { 1214 STACK_OF(PKCS7_RECIP_INFO) *rsk; 1215 PKCS7_RECIP_INFO *ri; 1216 int i; 1217 1218 i=OBJ_obj2nid(p7->type); 1219 if (i != NID_pkcs7_signedAndEnveloped) 1220 return NULL; 1221 if (p7->d.signed_and_enveloped == NULL) 1222 return NULL; 1223 rsk=p7->d.signed_and_enveloped->recipientinfo; 1224 if (rsk == NULL) 1225 return NULL; 1226 ri=sk_PKCS7_RECIP_INFO_value(rsk,0); 1227 if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL); 1228 ri=sk_PKCS7_RECIP_INFO_value(rsk,idx); 1229 return(ri->issuer_and_serial); 1230 } 1231 1232ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid) 1233 { 1234 return(get_attribute(si->auth_attr,nid)); 1235 } 1236 1237ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid) 1238 { 1239 return(get_attribute(si->unauth_attr,nid)); 1240 } 1241 1242static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid) 1243 { 1244 int i; 1245 X509_ATTRIBUTE *xa; 1246 ASN1_OBJECT *o; 1247 1248 o=OBJ_nid2obj(nid); 1249 if (!o || !sk) return(NULL); 1250 for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) 1251 { 1252 xa=sk_X509_ATTRIBUTE_value(sk,i); 1253 if (OBJ_cmp(xa->object,o) == 0) 1254 { 1255 if (!xa->single && sk_ASN1_TYPE_num(xa->value.set)) 1256 return(sk_ASN1_TYPE_value(xa->value.set,0)); 1257 else 1258 return(NULL); 1259 } 1260 } 1261 return(NULL); 1262 } 1263 1264ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) 1265{ 1266 ASN1_TYPE *astype; 1267 if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL; 1268 return astype->value.octet_string; 1269} 1270 1271int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, 1272 STACK_OF(X509_ATTRIBUTE) *sk) 1273 { 1274 int i; 1275 1276 if (p7si->auth_attr != NULL) 1277 sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free); 1278 p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk); 1279 if (p7si->auth_attr == NULL) 1280 return 0; 1281 for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) 1282 { 1283 if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i, 1284 X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i)))) 1285 == NULL) 1286 return(0); 1287 } 1288 return(1); 1289 } 1290 1291int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk) 1292 { 1293 int i; 1294 1295 if (p7si->unauth_attr != NULL) 1296 sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, 1297 X509_ATTRIBUTE_free); 1298 p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk); 1299 if (p7si->unauth_attr == NULL) 1300 return 0; 1301 for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) 1302 { 1303 if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i, 1304 X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i)))) 1305 == NULL) 1306 return(0); 1307 } 1308 return(1); 1309 } 1310 1311int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1312 void *value) 1313 { 1314 return(add_attribute(&(p7si->auth_attr),nid,atrtype,value)); 1315 } 1316 1317int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 1318 void *value) 1319 { 1320 return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value)); 1321 } 1322 1323static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 1324 void *value) 1325 { 1326 X509_ATTRIBUTE *attr=NULL; 1327 1328 if (*sk == NULL) 1329 { 1330 *sk = sk_X509_ATTRIBUTE_new_null(); 1331 if (*sk == NULL) 1332 return 0; 1333new_attrib: 1334 if (!(attr=X509_ATTRIBUTE_create(nid,atrtype,value))) 1335 return 0; 1336 if (!sk_X509_ATTRIBUTE_push(*sk,attr)) 1337 { 1338 X509_ATTRIBUTE_free(attr); 1339 return 0; 1340 } 1341 } 1342 else 1343 { 1344 int i; 1345 1346 for (i=0; i<sk_X509_ATTRIBUTE_num(*sk); i++) 1347 { 1348 attr=sk_X509_ATTRIBUTE_value(*sk,i); 1349 if (OBJ_obj2nid(attr->object) == nid) 1350 { 1351 X509_ATTRIBUTE_free(attr); 1352 attr=X509_ATTRIBUTE_create(nid,atrtype,value); 1353 if (attr == NULL) 1354 return 0; 1355 if (!sk_X509_ATTRIBUTE_set(*sk,i,attr)) 1356 { 1357 X509_ATTRIBUTE_free(attr); 1358 return 0; 1359 } 1360 goto end; 1361 } 1362 } 1363 goto new_attrib; 1364 } 1365end: 1366 return(1); 1367 } 1368 1369