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