diff options
Diffstat (limited to 'src/lib/libcrypto/pkcs7/pk7_doit.c')
-rw-r--r-- | src/lib/libcrypto/pkcs7/pk7_doit.c | 121 |
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 | ||
65 | static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, | 66 | static 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 | } |