summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/pkcs7/pk7_doit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/pkcs7/pk7_doit.c')
-rw-r--r--src/lib/libcrypto/pkcs7/pk7_doit.c121
1 files changed, 79 insertions, 42 deletions
diff --git a/src/lib/libcrypto/pkcs7/pk7_doit.c b/src/lib/libcrypto/pkcs7/pk7_doit.c
index dee81b547a..80ac5e34b4 100644
--- a/src/lib/libcrypto/pkcs7/pk7_doit.c
+++ b/src/lib/libcrypto/pkcs7/pk7_doit.c
@@ -61,6 +61,7 @@
61#include <openssl/rand.h> 61#include <openssl/rand.h>
62#include <openssl/objects.h> 62#include <openssl/objects.h>
63#include <openssl/x509.h> 63#include <openssl/x509.h>
64#include <openssl/x509v3.h>
64 65
65static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, 66static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
66 void *value); 67 void *value);
@@ -160,9 +161,10 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
160 BIO_get_cipher_ctx(btmp, &ctx); 161 BIO_get_cipher_ctx(btmp, &ctx);
161 keylen=EVP_CIPHER_key_length(evp_cipher); 162 keylen=EVP_CIPHER_key_length(evp_cipher);
162 ivlen=EVP_CIPHER_iv_length(evp_cipher); 163 ivlen=EVP_CIPHER_iv_length(evp_cipher);
163 RAND_bytes(key,keylen); 164 if (RAND_bytes(key,keylen) <= 0)
165 goto err;
164 xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); 166 xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
165 if (ivlen > 0) RAND_bytes(iv,ivlen); 167 if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen);
166 EVP_CipherInit(ctx, evp_cipher, key, iv, 1); 168 EVP_CipherInit(ctx, evp_cipher, key, iv, 1);
167 169
168 if (ivlen > 0) { 170 if (ivlen > 0) {
@@ -204,7 +206,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
204 Free(tmp); 206 Free(tmp);
205 goto err; 207 goto err;
206 } 208 }
207 ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj); 209 M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj);
208 } 210 }
209 Free(tmp); 211 Free(tmp);
210 memset(key, 0, keylen); 212 memset(key, 0, keylen);
@@ -216,30 +218,23 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
216 btmp=NULL; 218 btmp=NULL;
217 } 219 }
218 220
219 if (bio == NULL) /* ??????????? */ 221 if (bio == NULL) {
220 {
221 if (p7->detached) 222 if (p7->detached)
222 bio=BIO_new(BIO_s_null()); 223 bio=BIO_new(BIO_s_null());
223 else 224 else {
224 {
225 bio=BIO_new(BIO_s_mem());
226 /* We need to set this so that when we have read all
227 * the data, the encrypt BIO, if present, will read
228 * EOF and encode the last few bytes */
229 BIO_set_mem_eof_return(bio,0);
230
231 if (PKCS7_type_is_signed(p7) && 225 if (PKCS7_type_is_signed(p7) &&
232 PKCS7_type_is_data(p7->d.sign->contents)) 226 PKCS7_type_is_data(p7->d.sign->contents)) {
233 {
234 ASN1_OCTET_STRING *os; 227 ASN1_OCTET_STRING *os;
235
236 os=p7->d.sign->contents->d.data; 228 os=p7->d.sign->contents->d.data;
237 if (os->length > 0) 229 if (os->length > 0) bio =
238 BIO_write(bio,(char *)os->data, 230 BIO_new_mem_buf(os->data, os->length);
239 os->length); 231 }
240 } 232 if(bio == NULL) {
233 bio=BIO_new(BIO_s_mem());
234 BIO_set_mem_eof_return(bio,0);
241 } 235 }
242 } 236 }
237 }
243 BIO_push(out,bio); 238 BIO_push(out,bio);
244 bio=NULL; 239 bio=NULL;
245 if (0) 240 if (0)
@@ -259,7 +254,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
259 { 254 {
260 int i,j; 255 int i,j;
261 BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL; 256 BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
262 char *tmp=NULL; 257 unsigned char *tmp=NULL;
263 X509_ALGOR *xa; 258 X509_ALGOR *xa;
264 ASN1_OCTET_STRING *data_body=NULL; 259 ASN1_OCTET_STRING *data_body=NULL;
265 const EVP_MD *evp_md; 260 const EVP_MD *evp_md;
@@ -270,6 +265,9 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
270 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; 265 STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
271 X509_ALGOR *xalg=NULL; 266 X509_ALGOR *xalg=NULL;
272 PKCS7_RECIP_INFO *ri=NULL; 267 PKCS7_RECIP_INFO *ri=NULL;
268#ifndef NO_RC2
269 char is_rc2 = 0;
270#endif
273/* EVP_PKEY *pkey; */ 271/* EVP_PKEY *pkey; */
274#if 0 272#if 0
275 X509_STORE_CTX s_ctx; 273 X509_STORE_CTX s_ctx;
@@ -314,6 +312,16 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
314 goto err; 312 goto err;
315 } 313 }
316 314
315 if(EVP_CIPHER_nid(evp_cipher) == NID_rc2_cbc)
316 {
317#ifndef NO_RC2
318 is_rc2 = 1;
319#else
320 PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
321 goto err;
322#endif
323 }
324
317 /* We will be checking the signature */ 325 /* We will be checking the signature */
318 if (md_sk != NULL) 326 if (md_sk != NULL)
319 { 327 {
@@ -372,7 +380,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
372 ri=sk_PKCS7_RECIP_INFO_value(rsk,i); 380 ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
373 if(!X509_NAME_cmp(ri->issuer_and_serial->issuer, 381 if(!X509_NAME_cmp(ri->issuer_and_serial->issuer,
374 pcert->cert_info->issuer) && 382 pcert->cert_info->issuer) &&
375 !ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, 383 !M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
376 ri->issuer_and_serial->serial)) break; 384 ri->issuer_and_serial->serial)) break;
377 ri=NULL; 385 ri=NULL;
378 } 386 }
@@ -383,17 +391,15 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
383 } 391 }
384 392
385 jj=EVP_PKEY_size(pkey); 393 jj=EVP_PKEY_size(pkey);
386 tmp=Malloc(jj+10); 394 tmp=(unsigned char *)Malloc(jj+10);
387 if (tmp == NULL) 395 if (tmp == NULL)
388 { 396 {
389 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE); 397 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE);
390 goto err; 398 goto err;
391 } 399 }
392 400
393 jj=EVP_PKEY_decrypt((unsigned char *)tmp, 401 jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key),
394 ASN1_STRING_data(ri->enc_key), 402 M_ASN1_STRING_length(ri->enc_key), pkey);
395 ASN1_STRING_length(ri->enc_key),
396 pkey);
397 if (jj <= 0) 403 if (jj <= 0)
398 { 404 {
399 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB); 405 PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB);
@@ -406,13 +412,25 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
406 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) 412 if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
407 return(NULL); 413 return(NULL);
408 414
409 if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) 415 if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
410 { 416 /* HACK: some S/MIME clients don't use the same key
411 PKCS7err(PKCS7_F_PKCS7_DATADECODE, 417 * and effective key length. The key length is
418 * determined by the size of the decrypted RSA key.
419 * So we hack things to manually set the RC2 key
420 * because we currently can't do this with the EVP
421 * interface.
422 */
423#ifndef NO_RC2
424 if(is_rc2) RC2_set_key(&(evp_ctx->c.rc2_ks),jj, tmp,
425 EVP_CIPHER_CTX_key_length(evp_ctx)*8);
426 else
427#endif
428 {
429 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
412 PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); 430 PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
413 goto err; 431 goto err;
414 } 432 }
415 EVP_CipherInit(evp_ctx,NULL,(unsigned char *)tmp,NULL,0); 433 } else EVP_CipherInit(evp_ctx,NULL,tmp,NULL,0);
416 434
417 memset(tmp,0,jj); 435 memset(tmp,0,jj);
418 436
@@ -430,6 +448,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
430 } 448 }
431 else 449 else
432 { 450 {
451#if 0
433 bio=BIO_new(BIO_s_mem()); 452 bio=BIO_new(BIO_s_mem());
434 /* We need to set this so that when we have read all 453 /* We need to set this so that when we have read all
435 * the data, the encrypt BIO, if present, will read 454 * the data, the encrypt BIO, if present, will read
@@ -438,6 +457,14 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
438 457
439 if (data_body->length > 0) 458 if (data_body->length > 0)
440 BIO_write(bio,(char *)data_body->data,data_body->length); 459 BIO_write(bio,(char *)data_body->data,data_body->length);
460#else
461 if (data_body->length > 0)
462 bio = BIO_new_mem_buf(data_body->data,data_body->length);
463 else {
464 bio=BIO_new(BIO_s_mem());
465 BIO_set_mem_eof_return(bio,0);
466 }
467#endif
441 } 468 }
442 BIO_push(out,bio); 469 BIO_push(out,bio);
443 bio=NULL; 470 bio=NULL;
@@ -479,12 +506,12 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
479 case NID_pkcs7_signedAndEnveloped: 506 case NID_pkcs7_signedAndEnveloped:
480 /* XXXXXXXXXXXXXXXX */ 507 /* XXXXXXXXXXXXXXXX */
481 si_sk=p7->d.signed_and_enveloped->signer_info; 508 si_sk=p7->d.signed_and_enveloped->signer_info;
482 os=ASN1_OCTET_STRING_new(); 509 os=M_ASN1_OCTET_STRING_new();
483 p7->d.signed_and_enveloped->enc_data->enc_data=os; 510 p7->d.signed_and_enveloped->enc_data->enc_data=os;
484 break; 511 break;
485 case NID_pkcs7_enveloped: 512 case NID_pkcs7_enveloped:
486 /* XXXXXXXXXXXXXXXX */ 513 /* XXXXXXXXXXXXXXXX */
487 os=ASN1_OCTET_STRING_new(); 514 os=M_ASN1_OCTET_STRING_new();
488 p7->d.enveloped->enc_data->enc_data=os; 515 p7->d.enveloped->enc_data->enc_data=os;
489 break; 516 break;
490 case NID_pkcs7_signed: 517 case NID_pkcs7_signed:
@@ -492,7 +519,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
492 os=p7->d.sign->contents->d.data; 519 os=p7->d.sign->contents->d.data;
493 /* If detached data then the content is excluded */ 520 /* If detached data then the content is excluded */
494 if(p7->detached) { 521 if(p7->detached) {
495 ASN1_OCTET_STRING_free(os); 522 M_ASN1_OCTET_STRING_free(os);
496 p7->d.sign->contents->d.data = NULL; 523 p7->d.sign->contents->d.data = NULL;
497 } 524 }
498 break; 525 break;
@@ -527,7 +554,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
527 PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_INTERNAL_ERROR); 554 PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_INTERNAL_ERROR);
528 goto err; 555 goto err;
529 } 556 }
530 if (EVP_MD_type(EVP_MD_CTX_type(mdc)) == j) 557 if (EVP_MD_CTX_type(mdc) == j)
531 break; 558 break;
532 else 559 else
533 btmp=btmp->next_bio; 560 btmp=btmp->next_bio;
@@ -561,10 +588,10 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
561 V_ASN1_UTCTIME,sign_time); 588 V_ASN1_UTCTIME,sign_time);
562 589
563 /* Add digest */ 590 /* Add digest */
564 md_tmp=EVP_MD_CTX_type(&ctx_tmp); 591 md_tmp=EVP_MD_CTX_md(&ctx_tmp);
565 EVP_DigestFinal(&ctx_tmp,md_data,&md_len); 592 EVP_DigestFinal(&ctx_tmp,md_data,&md_len);
566 digest=ASN1_OCTET_STRING_new(); 593 digest=M_ASN1_OCTET_STRING_new();
567 ASN1_OCTET_STRING_set(digest,md_data,md_len); 594 M_ASN1_OCTET_STRING_set(digest,md_data,md_len);
568 PKCS7_add_signed_attribute(si, 595 PKCS7_add_signed_attribute(si,
569 NID_pkcs9_messageDigest, 596 NID_pkcs9_messageDigest,
570 V_ASN1_OCTET_STRING,digest); 597 V_ASN1_OCTET_STRING,digest);
@@ -611,8 +638,17 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
611 goto err; 638 goto err;
612 } 639 }
613 BIO_get_mem_ptr(btmp,&buf_mem); 640 BIO_get_mem_ptr(btmp,&buf_mem);
614 ASN1_OCTET_STRING_set(os, 641 /* Mark the BIO read only then we can use its copy of the data
642 * instead of making an extra copy.
643 */
644 BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
645 BIO_set_mem_eof_return(btmp, 0);
646 os->data = (unsigned char *)buf_mem->data;
647 os->length = buf_mem->length;
648#if 0
649 M_ASN1_OCTET_STRING_set(os,
615 (unsigned char *)buf_mem->data,buf_mem->length); 650 (unsigned char *)buf_mem->data,buf_mem->length);
651#endif
616 } 652 }
617 if (pp != NULL) Free(pp); 653 if (pp != NULL) Free(pp);
618 pp=NULL; 654 pp=NULL;
@@ -658,6 +694,7 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
658 694
659 /* Lets verify */ 695 /* Lets verify */
660 X509_STORE_CTX_init(ctx,cert_store,x509,cert); 696 X509_STORE_CTX_init(ctx,cert_store,x509,cert);
697 X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
661 i=X509_verify_cert(ctx); 698 i=X509_verify_cert(ctx);
662 if (i <= 0) 699 if (i <= 0)
663 { 700 {
@@ -709,7 +746,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
709 PKCS7_R_INTERNAL_ERROR); 746 PKCS7_R_INTERNAL_ERROR);
710 goto err; 747 goto err;
711 } 748 }
712 if (EVP_MD_type(EVP_MD_CTX_type(mdc)) == md_type) 749 if (EVP_MD_CTX_type(mdc) == md_type)
713 break; 750 break;
714 btmp=btmp->next_bio; 751 btmp=btmp->next_bio;
715 } 752 }