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 66static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 67 void *value); 68static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid); 69 70static int PKCS7_type_is_other(PKCS7* p7) 71 { 72 int isOther=1; 73 74 int nid=OBJ_obj2nid(p7->type); 75 76 switch( nid ) 77 { 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 104BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) 105 { 106 int i; 107 BIO *out=NULL,*btmp=NULL; 108 X509_ALGOR *xa; 109 const EVP_MD *evp_md; 110 const EVP_CIPHER *evp_cipher=NULL; 111 STACK_OF(X509_ALGOR) *md_sk=NULL; 112 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; 113 X509_ALGOR *xalg=NULL; 114 PKCS7_RECIP_INFO *ri=NULL; 115 EVP_PKEY *pkey; 116 117 i=OBJ_obj2nid(p7->type); 118 p7->state=PKCS7_S_HEADER; 119 120 switch (i) 121 { 122 case NID_pkcs7_signed: 123 md_sk=p7->d.sign->md_algs; 124 break; 125 case NID_pkcs7_signedAndEnveloped: 126 rsk=p7->d.signed_and_enveloped->recipientinfo; 127 md_sk=p7->d.signed_and_enveloped->md_algs; 128 xalg=p7->d.signed_and_enveloped->enc_data->algorithm; 129 evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher; 130 if (evp_cipher == NULL) 131 { 132 PKCS7err(PKCS7_F_PKCS7_DATAINIT, 133 PKCS7_R_CIPHER_NOT_INITIALIZED); 134 goto err; 135 } 136 break; 137 case NID_pkcs7_enveloped: 138 rsk=p7->d.enveloped->recipientinfo; 139 xalg=p7->d.enveloped->enc_data->algorithm; 140 evp_cipher=p7->d.enveloped->enc_data->cipher; 141 if (evp_cipher == NULL) 142 { 143 PKCS7err(PKCS7_F_PKCS7_DATAINIT, 144 PKCS7_R_CIPHER_NOT_INITIALIZED); 145 goto err; 146 } 147 break; 148 default: 149 PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 150 goto err; 151 } 152 153 if (md_sk != NULL) 154 { 155 for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) 156 { 157 xa=sk_X509_ALGOR_value(md_sk,i); 158 if ((btmp=BIO_new(BIO_f_md())) == NULL) 159 { 160 PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); 161 goto err; 162 } 163 164 evp_md=EVP_get_digestbyobj(xa->algorithm); 165 if (evp_md == NULL) 166 { 167 PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNKNOWN_DIGEST_TYPE); 168 goto err; 169 } 170 171 BIO_set_md(btmp,evp_md); 172 if (out == NULL) 173 out=btmp; 174 else 175 BIO_push(out,btmp); 176 btmp=NULL; 177 } 178 } 179 180 if (evp_cipher != NULL) 181 { 182 unsigned char key[EVP_MAX_KEY_LENGTH]; 183 unsigned char iv[EVP_MAX_IV_LENGTH]; 184 int keylen,ivlen; 185 int jj,max; 186 unsigned char *tmp; 187 EVP_CIPHER_CTX *ctx; 188 189 if ((btmp=BIO_new(BIO_f_cipher())) == NULL) 190 { 191 PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); 192 goto err; 193 } 194 BIO_get_cipher_ctx(btmp, &ctx); 195 keylen=EVP_CIPHER_key_length(evp_cipher); 196 ivlen=EVP_CIPHER_iv_length(evp_cipher); 197 if (RAND_bytes(key,keylen) <= 0) 198 goto err; 199 xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); 200 if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen); 201 EVP_CipherInit_ex(ctx, evp_cipher, NULL, key, iv, 1); 202 203 if (ivlen > 0) { 204 if (xalg->parameter == NULL) 205 xalg->parameter=ASN1_TYPE_new(); 206 if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) 207 goto err; 208 } 209 210 /* Lets do the pub key stuff :-) */ 211 max=0; 212 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) 213 { 214 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 215 if (ri->cert == NULL) 216 { 217 PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO); 218 goto err; 219 } 220 pkey=X509_get_pubkey(ri->cert); 221 jj=EVP_PKEY_size(pkey); 222 EVP_PKEY_free(pkey); 223 if (max < jj) max=jj; 224 } 225 if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL) 226 { 227 PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE); 228 goto err; 229 } 230 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) 231 { 232 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 233 pkey=X509_get_pubkey(ri->cert); 234 jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey); 235 EVP_PKEY_free(pkey); 236 if (jj <= 0) 237 { 238 PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB); 239 OPENSSL_free(tmp); 240 goto err; 241 } 242 if (!M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj)) 243 { 244 PKCS7err(PKCS7_F_PKCS7_DATAINIT, 245 ERR_R_MALLOC_FAILURE); 246 OPENSSL_free(tmp); 247 goto err; 248 } 249 } 250 OPENSSL_free(tmp); 251 OPENSSL_cleanse(key, keylen); 252 253 if (out == NULL) 254 out=btmp; 255 else 256 BIO_push(out,btmp); 257 btmp=NULL; 258 } 259 260 if (bio == NULL) 261 { 262 if (PKCS7_is_detached(p7)) 263 bio=BIO_new(BIO_s_null()); 264 else 265 { 266 if (PKCS7_type_is_signed(p7)) 267 { 268 ASN1_OCTET_STRING *os; 269 os = PKCS7_get_octet_string( 270 p7->d.sign->contents); 271 if (os && os->length > 0) 272 bio = BIO_new_mem_buf(os->data, 273 os->length); 274 } 275 if(bio == NULL) 276 { 277 bio=BIO_new(BIO_s_mem()); 278 BIO_set_mem_eof_return(bio,0); 279 } 280 } 281 } 282 BIO_push(out,bio); 283 bio=NULL; 284 if (0) 285 { 286err: 287 if (out != NULL) 288 BIO_free_all(out); 289 if (btmp != NULL) 290 BIO_free_all(btmp); 291 out=NULL; 292 } 293 return(out); 294 } 295 296/* int */ 297BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) 298 { 299 int i,j; 300 BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL; 301 unsigned char *tmp=NULL; 302 X509_ALGOR *xa; 303 ASN1_OCTET_STRING *data_body=NULL; 304 const EVP_MD *evp_md; 305 const EVP_CIPHER *evp_cipher=NULL; 306 EVP_CIPHER_CTX *evp_ctx=NULL; 307 X509_ALGOR *enc_alg=NULL; 308 STACK_OF(X509_ALGOR) *md_sk=NULL; 309 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; 310 X509_ALGOR *xalg=NULL; 311 PKCS7_RECIP_INFO *ri=NULL; 312 313 i=OBJ_obj2nid(p7->type); 314 p7->state=PKCS7_S_HEADER; 315 316 switch (i) 317 { 318 case NID_pkcs7_signed: 319 data_body=PKCS7_get_octet_string(p7->d.sign->contents); 320 md_sk=p7->d.sign->md_algs; 321 break; 322 case NID_pkcs7_signedAndEnveloped: 323 rsk=p7->d.signed_and_enveloped->recipientinfo; 324 md_sk=p7->d.signed_and_enveloped->md_algs; 325 data_body=p7->d.signed_and_enveloped->enc_data->enc_data; 326 enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm; 327 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); 328 if (evp_cipher == NULL) 329 { 330 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 331 goto err; 332 } 333 xalg=p7->d.signed_and_enveloped->enc_data->algorithm; 334 break; 335 case NID_pkcs7_enveloped: 336 rsk=p7->d.enveloped->recipientinfo; 337 enc_alg=p7->d.enveloped->enc_data->algorithm; 338 data_body=p7->d.enveloped->enc_data->enc_data; 339 evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); 340 if (evp_cipher == NULL) 341 { 342 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); 343 goto err; 344 } 345 xalg=p7->d.enveloped->enc_data->algorithm; 346 break; 347 default: 348 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 349 goto err; 350 } 351 352 /* We will be checking the signature */ 353 if (md_sk != NULL) 354 { 355 for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) 356 { 357 xa=sk_X509_ALGOR_value(md_sk,i); 358 if ((btmp=BIO_new(BIO_f_md())) == NULL) 359 { 360 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); 361 goto err; 362 } 363 364 j=OBJ_obj2nid(xa->algorithm); 365 evp_md=EVP_get_digestbynid(j); 366 if (evp_md == NULL) 367 { 368 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE); 369 goto err; 370 } 371 372 BIO_set_md(btmp,evp_md); 373 if (out == NULL) 374 out=btmp; 375 else 376 BIO_push(out,btmp); 377 btmp=NULL; 378 } 379 } 380 381 if (evp_cipher != NULL) 382 { 383#if 0 384 unsigned char key[EVP_MAX_KEY_LENGTH]; 385 unsigned char iv[EVP_MAX_IV_LENGTH]; 386 unsigned char *p; 387 int keylen,ivlen; 388 int max; 389 X509_OBJECT ret; 390#endif 391 int jj; 392 393 if ((etmp=BIO_new(BIO_f_cipher())) == NULL) 394 { 395 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); 396 goto err; 397 } 398 399 /* It was encrypted, we need to decrypt the secret key 400 * with the private key */ 401 402 /* Find the recipientInfo which matches the passed certificate 403 * (if any) 404 */ 405 406 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { 407 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 408 if(!X509_NAME_cmp(ri->issuer_and_serial->issuer, 409 pcert->cert_info->issuer) && 410 !M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, 411 ri->issuer_and_serial->serial)) break; 412 ri=NULL; 413 } 414 if (ri == NULL) { 415 PKCS7err(PKCS7_F_PKCS7_DATADECODE, 416 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); 417 goto err; 418 } 419 420 jj=EVP_PKEY_size(pkey); 421 tmp=(unsigned char *)OPENSSL_malloc(jj+10); 422 if (tmp == NULL) 423 { 424 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE); 425 goto err; 426 } 427 428 jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key), 429 M_ASN1_STRING_length(ri->enc_key), pkey); 430 if (jj <= 0) 431 { 432 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB); 433 goto err; 434 } 435 436 evp_ctx=NULL; 437 BIO_get_cipher_ctx(etmp,&evp_ctx); 438 EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0); 439 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) 440 goto err; 441 442 if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) { 443 /* Some S/MIME clients don't use the same key 444 * and effective key length. The key length is 445 * determined by the size of the decrypted RSA key. 446 */ 447 if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj)) 448 { 449 PKCS7err(PKCS7_F_PKCS7_DATADECODE, 450 PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); 451 goto err; 452 } 453 } 454 EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0); 455 456 OPENSSL_cleanse(tmp,jj); 457 458 if (out == NULL) 459 out=etmp; 460 else 461 BIO_push(out,etmp); 462 etmp=NULL; 463 } 464 465#if 1 466 if (PKCS7_is_detached(p7) || (in_bio != NULL)) 467 { 468 bio=in_bio; 469 } 470 else 471 { 472#if 0 473 bio=BIO_new(BIO_s_mem()); 474 /* We need to set this so that when we have read all 475 * the data, the encrypt BIO, if present, will read 476 * EOF and encode the last few bytes */ 477 BIO_set_mem_eof_return(bio,0); 478 479 if (data_body->length > 0) 480 BIO_write(bio,(char *)data_body->data,data_body->length); 481#else 482 if (data_body->length > 0) 483 bio = BIO_new_mem_buf(data_body->data,data_body->length); 484 else { 485 bio=BIO_new(BIO_s_mem()); 486 BIO_set_mem_eof_return(bio,0); 487 } 488#endif 489 } 490 BIO_push(out,bio); 491 bio=NULL; 492#endif 493 if (0) 494 { 495err: 496 if (out != NULL) BIO_free_all(out); 497 if (btmp != NULL) BIO_free_all(btmp); 498 if (etmp != NULL) BIO_free_all(etmp); 499 if (bio != NULL) BIO_free_all(bio); 500 out=NULL; 501 } 502 if (tmp != NULL) 503 OPENSSL_free(tmp); 504 return(out); 505 } 506 507int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) 508 { 509 int ret=0; 510 int i,j; 511 BIO *btmp; 512 BUF_MEM *buf_mem=NULL; 513 BUF_MEM *buf=NULL; 514 PKCS7_SIGNER_INFO *si; 515 EVP_MD_CTX *mdc,ctx_tmp; 516 STACK_OF(X509_ATTRIBUTE) *sk; 517 STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; 518 ASN1_OCTET_STRING *os=NULL; 519 520 EVP_MD_CTX_init(&ctx_tmp); 521 i=OBJ_obj2nid(p7->type); 522 p7->state=PKCS7_S_HEADER; 523 524 switch (i) 525 { 526 case NID_pkcs7_signedAndEnveloped: 527 /* XXXXXXXXXXXXXXXX */ 528 si_sk=p7->d.signed_and_enveloped->signer_info; 529 if (!(os=M_ASN1_OCTET_STRING_new())) 530 { 531 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_MALLOC_FAILURE); 532 goto err; 533 } 534 p7->d.signed_and_enveloped->enc_data->enc_data=os; 535 break; 536 case NID_pkcs7_enveloped: 537 /* XXXXXXXXXXXXXXXX */ 538 if (!(os=M_ASN1_OCTET_STRING_new())) 539 { 540 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_MALLOC_FAILURE); 541 goto err; 542 } 543 p7->d.enveloped->enc_data->enc_data=os; 544 break; 545 case NID_pkcs7_signed: 546 si_sk=p7->d.sign->signer_info; 547 os=PKCS7_get_octet_string(p7->d.sign->contents); 548 /* If detached data then the content is excluded */ 549 if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { 550 M_ASN1_OCTET_STRING_free(os); 551 p7->d.sign->contents->d.data = NULL; 552 } 553 break; 554 } 555 556 if (si_sk != NULL) 557 { 558 if ((buf=BUF_MEM_new()) == NULL) 559 { 560 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); 561 goto err; 562 } 563 for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++) 564 { 565 si=sk_PKCS7_SIGNER_INFO_value(si_sk,i); 566 if (si->pkey == NULL) continue; 567 568 j=OBJ_obj2nid(si->digest_alg->algorithm); 569 570 btmp=bio; 571 for (;;) 572 { 573 if ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) 574 == NULL) 575 { 576 PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 577 goto err; 578 } 579 BIO_get_md_ctx(btmp,&mdc); 580 if (mdc == NULL) 581 { 582 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_INTERNAL_ERROR); 583 goto err; 584 } 585 if (EVP_MD_CTX_type(mdc) == j) 586 break; 587 else 588 btmp=BIO_next(btmp); 589 } 590 591 /* We now have the EVP_MD_CTX, lets do the 592 * signing. */ 593 EVP_MD_CTX_copy_ex(&ctx_tmp,mdc); 594 if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey))) 595 { 596 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); 597 goto err; 598 } 599 600 sk=si->auth_attr; 601 602 /* If there are attributes, we add the digest 603 * attribute and only sign the attributes */ 604 if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) 605 { 606 unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL; 607 unsigned int md_len, alen; 608 ASN1_OCTET_STRING *digest; 609 ASN1_UTCTIME *sign_time; 610 const EVP_MD *md_tmp; 611 612 /* Add signing time if not already present */ 613 if (!PKCS7_get_signed_attribute(si, 614 NID_pkcs9_signingTime)) 615 { 616 if (!(sign_time=X509_gmtime_adj(NULL,0))) 617 { 618 PKCS7err(PKCS7_F_PKCS7_DATASIGN, 619 ERR_R_MALLOC_FAILURE); 620 goto err; 621 } 622 PKCS7_add_signed_attribute(si, 623 NID_pkcs9_signingTime, 624 V_ASN1_UTCTIME,sign_time); 625 } 626 627 /* Add digest */ 628 md_tmp=EVP_MD_CTX_md(&ctx_tmp); 629 EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len); 630 if (!(digest=M_ASN1_OCTET_STRING_new())) 631 { 632 PKCS7err(PKCS7_F_PKCS7_DATASIGN, 633 ERR_R_MALLOC_FAILURE); 634 goto err; 635 } 636 if (!M_ASN1_OCTET_STRING_set(digest,md_data, 637 md_len)) 638 { 639 PKCS7err(PKCS7_F_PKCS7_DATASIGN, 640 ERR_R_MALLOC_FAILURE); 641 goto err; 642 } 643 PKCS7_add_signed_attribute(si, 644 NID_pkcs9_messageDigest, 645 V_ASN1_OCTET_STRING,digest); 646 647 /* Now sign the attributes */ 648 EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL); 649 alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf, 650 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); 651 if(!abuf) goto err; 652 EVP_SignUpdate(&ctx_tmp,abuf,alen); 653 OPENSSL_free(abuf); 654 } 655 656#ifndef OPENSSL_NO_DSA 657 if (si->pkey->type == EVP_PKEY_DSA) 658 ctx_tmp.digest=EVP_dss1(); 659#endif 660 661 if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data, 662 (unsigned int *)&buf->length,si->pkey)) 663 { 664 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB); 665 goto err; 666 } 667 if (!ASN1_STRING_set(si->enc_digest, 668 (unsigned char *)buf->data,buf->length)) 669 { 670 PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB); 671 goto err; 672 } 673 } 674 } 675 676 if (!PKCS7_is_detached(p7)) 677 { 678 btmp=BIO_find_type(bio,BIO_TYPE_MEM); 679 if (btmp == NULL) 680 { 681 PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO); 682 goto err; 683 } 684 BIO_get_mem_ptr(btmp,&buf_mem); 685 /* Mark the BIO read only then we can use its copy of the data 686 * instead of making an extra copy. 687 */ 688 BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); 689 BIO_set_mem_eof_return(btmp, 0); 690 os->data = (unsigned char *)buf_mem->data; 691 os->length = buf_mem->length; 692#if 0 693 M_ASN1_OCTET_STRING_set(os, 694 (unsigned char *)buf_mem->data,buf_mem->length); 695#endif 696 } 697 ret=1; 698err: 699 EVP_MD_CTX_cleanup(&ctx_tmp); 700 if (buf != NULL) BUF_MEM_free(buf); 701 return(ret); 702 } 703 704int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, 705 PKCS7 *p7, PKCS7_SIGNER_INFO *si) 706 { 707 PKCS7_ISSUER_AND_SERIAL *ias; 708 int ret=0,i; 709 STACK_OF(X509) *cert; 710 X509 *x509; 711 712 if (PKCS7_type_is_signed(p7)) 713 { 714 cert=p7->d.sign->cert; 715 } 716 else if (PKCS7_type_is_signedAndEnveloped(p7)) 717 { 718 cert=p7->d.signed_and_enveloped->cert; 719 } 720 else 721 { 722 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE); 723 goto err; 724 } 725 /* XXXXXXXXXXXXXXXXXXXXXXX */ 726 ias=si->issuer_and_serial; 727 728 x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial); 729 730 /* were we able to find the cert in passed to us */ 731 if (x509 == NULL) 732 { 733 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); 734 goto err; 735 } 736 737 /* Lets verify */ 738 if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert)) 739 { 740 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); 741 goto err; 742 } 743 X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN); 744 i=X509_verify_cert(ctx); 745 if (i <= 0) 746 { 747 PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB); 748 X509_STORE_CTX_cleanup(ctx); 749 goto err; 750 } 751 X509_STORE_CTX_cleanup(ctx); 752 753 return PKCS7_signatureVerify(bio, p7, si, x509); 754 err: 755 return ret; 756 } 757 758int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, 759 X509 *x509) 760 { 761 ASN1_OCTET_STRING *os; 762 EVP_MD_CTX mdc_tmp,*mdc; 763 int ret=0,i; 764 int md_type; 765 STACK_OF(X509_ATTRIBUTE) *sk; 766 BIO *btmp; 767 EVP_PKEY *pkey; 768 769 EVP_MD_CTX_init(&mdc_tmp); 770 771 if (!PKCS7_type_is_signed(p7) && 772 !PKCS7_type_is_signedAndEnveloped(p7)) { 773 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 774 PKCS7_R_WRONG_PKCS7_TYPE); 775 goto err; 776 } 777 778 md_type=OBJ_obj2nid(si->digest_alg->algorithm); 779 780 btmp=bio; 781 for (;;) 782 { 783 if ((btmp == NULL) || 784 ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL)) 785 { 786 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 787 PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 788 goto err; 789 } 790 BIO_get_md_ctx(btmp,&mdc); 791 if (mdc == NULL) 792 { 793 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 794 ERR_R_INTERNAL_ERROR); 795 goto err; 796 } 797 if (EVP_MD_CTX_type(mdc) == md_type) 798 break; 799 /* Workaround for some broken clients that put the signature 800 * OID instead of the digest OID in digest_alg->algorithm 801 */ 802 if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) 803 break; 804 btmp=BIO_next(btmp); 805 } 806 807 /* mdc is the digest ctx that we want, unless there are attributes, 808 * in which case the digest is the signed attributes */ 809 EVP_MD_CTX_copy_ex(&mdc_tmp,mdc); 810 811 sk=si->auth_attr; 812 if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) 813 { 814 unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; 815 unsigned int md_len, alen; 816 ASN1_OCTET_STRING *message_digest; 817 818 EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len); 819 message_digest=PKCS7_digest_from_attributes(sk); 820 if (!message_digest) 821 { 822 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 823 PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); 824 goto err; 825 } 826 if ((message_digest->length != (int)md_len) || 827 (memcmp(message_digest->data,md_dat,md_len))) 828 { 829#if 0 830{ 831int ii; 832for (ii=0; ii<message_digest->length; ii++) 833 printf("%02X",message_digest->data[ii]); printf(" sent\n"); 834for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); 835} 836#endif 837 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 838 PKCS7_R_DIGEST_FAILURE); 839 ret= -1; 840 goto err; 841 } 842 843 EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL); 844 845 alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, 846 ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); 847 EVP_VerifyUpdate(&mdc_tmp, abuf, alen); 848 849 OPENSSL_free(abuf); 850 } 851 852 os=si->enc_digest; 853 pkey = X509_get_pubkey(x509); 854 if (!pkey) 855 { 856 ret = -1; 857 goto err; 858 } 859#ifndef OPENSSL_NO_DSA 860 if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1(); 861#endif 862 863 i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey); 864 EVP_PKEY_free(pkey); 865 if (i <= 0) 866 { 867 PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, 868 PKCS7_R_SIGNATURE_FAILURE); 869 ret= -1; 870 goto err; 871 } 872 else 873 ret=1; 874err: 875 EVP_MD_CTX_cleanup(&mdc_tmp); 876 return(ret); 877 } 878 879PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) 880 { 881 STACK_OF(PKCS7_RECIP_INFO) *rsk; 882 PKCS7_RECIP_INFO *ri; 883 int i; 884 885 i=OBJ_obj2nid(p7->type); 886 if (i != NID_pkcs7_signedAndEnveloped) return(NULL); 887 rsk=p7->d.signed_and_enveloped->recipientinfo; 888 ri=sk_PKCS7_RECIP_INFO_value(rsk,0); 889 if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL); 890 ri=sk_PKCS7_RECIP_INFO_value(rsk,idx); 891 return(ri->issuer_and_serial); 892 } 893 894ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid) 895 { 896 return(get_attribute(si->auth_attr,nid)); 897 } 898 899ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid) 900 { 901 return(get_attribute(si->unauth_attr,nid)); 902 } 903 904static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid) 905 { 906 int i; 907 X509_ATTRIBUTE *xa; 908 ASN1_OBJECT *o; 909 910 o=OBJ_nid2obj(nid); 911 if (!o || !sk) return(NULL); 912 for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) 913 { 914 xa=sk_X509_ATTRIBUTE_value(sk,i); 915 if (OBJ_cmp(xa->object,o) == 0) 916 { 917 if (!xa->single && sk_ASN1_TYPE_num(xa->value.set)) 918 return(sk_ASN1_TYPE_value(xa->value.set,0)); 919 else 920 return(NULL); 921 } 922 } 923 return(NULL); 924 } 925 926ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) 927{ 928 ASN1_TYPE *astype; 929 if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL; 930 return astype->value.octet_string; 931} 932 933int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, 934 STACK_OF(X509_ATTRIBUTE) *sk) 935 { 936 int i; 937 938 if (p7si->auth_attr != NULL) 939 sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free); 940 p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk); 941 for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) 942 { 943 if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i, 944 X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i)))) 945 == NULL) 946 return(0); 947 } 948 return(1); 949 } 950 951int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk) 952 { 953 int i; 954 955 if (p7si->unauth_attr != NULL) 956 sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, 957 X509_ATTRIBUTE_free); 958 p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk); 959 for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) 960 { 961 if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i, 962 X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i)))) 963 == NULL) 964 return(0); 965 } 966 return(1); 967 } 968 969int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 970 void *value) 971 { 972 return(add_attribute(&(p7si->auth_attr),nid,atrtype,value)); 973 } 974 975int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, 976 void *value) 977 { 978 return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value)); 979 } 980 981static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 982 void *value) 983 { 984 X509_ATTRIBUTE *attr=NULL; 985 986 if (*sk == NULL) 987 { 988 *sk = sk_X509_ATTRIBUTE_new_null(); 989new_attrib: 990 attr=X509_ATTRIBUTE_create(nid,atrtype,value); 991 sk_X509_ATTRIBUTE_push(*sk,attr); 992 } 993 else 994 { 995 int i; 996 997 for (i=0; i<sk_X509_ATTRIBUTE_num(*sk); i++) 998 { 999 attr=sk_X509_ATTRIBUTE_value(*sk,i); 1000 if (OBJ_obj2nid(attr->object) == nid) 1001 { 1002 X509_ATTRIBUTE_free(attr); 1003 attr=X509_ATTRIBUTE_create(nid,atrtype,value); 1004 sk_X509_ATTRIBUTE_set(*sk,i,attr); 1005 goto end; 1006 } 1007 } 1008 goto new_attrib; 1009 } 1010end: 1011 return(1); 1012 } 1013 1014