diff options
Diffstat (limited to 'src/lib/libcrypto/pkcs7/pk7_lib.c')
-rw-r--r-- | src/lib/libcrypto/pkcs7/pk7_lib.c | 192 |
1 files changed, 135 insertions, 57 deletions
diff --git a/src/lib/libcrypto/pkcs7/pk7_lib.c b/src/lib/libcrypto/pkcs7/pk7_lib.c index f2490941a3..3ca0952792 100644 --- a/src/lib/libcrypto/pkcs7/pk7_lib.c +++ b/src/lib/libcrypto/pkcs7/pk7_lib.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include "cryptlib.h" | 60 | #include "cryptlib.h" |
61 | #include <openssl/objects.h> | 61 | #include <openssl/objects.h> |
62 | #include <openssl/x509.h> | 62 | #include <openssl/x509.h> |
63 | #include "asn1_locl.h" | ||
63 | 64 | ||
64 | long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) | 65 | long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) |
65 | { | 66 | { |
@@ -314,7 +315,7 @@ int PKCS7_add_certificate(PKCS7 *p7, X509 *x509) | |||
314 | *sk=sk_X509_new_null(); | 315 | *sk=sk_X509_new_null(); |
315 | if (*sk == NULL) | 316 | if (*sk == NULL) |
316 | { | 317 | { |
317 | PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE,ERR_R_MALLOC_FAILURE); | 318 | PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE, ERR_R_MALLOC_FAILURE); |
318 | return 0; | 319 | return 0; |
319 | } | 320 | } |
320 | CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); | 321 | CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); |
@@ -365,13 +366,8 @@ int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) | |||
365 | int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, | 366 | int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, |
366 | const EVP_MD *dgst) | 367 | const EVP_MD *dgst) |
367 | { | 368 | { |
368 | int nid; | 369 | int ret; |
369 | char is_dsa; | ||
370 | 370 | ||
371 | if (pkey->type == EVP_PKEY_DSA || pkey->type == EVP_PKEY_EC) | ||
372 | is_dsa = 1; | ||
373 | else | ||
374 | is_dsa = 0; | ||
375 | /* We now need to add another PKCS7_SIGNER_INFO entry */ | 371 | /* We now need to add another PKCS7_SIGNER_INFO entry */ |
376 | if (!ASN1_INTEGER_set(p7i->version,1)) | 372 | if (!ASN1_INTEGER_set(p7i->version,1)) |
377 | goto err; | 373 | goto err; |
@@ -391,65 +387,55 @@ int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, | |||
391 | p7i->pkey=pkey; | 387 | p7i->pkey=pkey; |
392 | 388 | ||
393 | /* Set the algorithms */ | 389 | /* Set the algorithms */ |
394 | if (is_dsa) p7i->digest_alg->algorithm=OBJ_nid2obj(NID_sha1); | ||
395 | else | ||
396 | p7i->digest_alg->algorithm=OBJ_nid2obj(EVP_MD_type(dgst)); | ||
397 | 390 | ||
398 | if (p7i->digest_alg->parameter != NULL) | 391 | X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)), |
399 | ASN1_TYPE_free(p7i->digest_alg->parameter); | 392 | V_ASN1_NULL, NULL); |
400 | if ((p7i->digest_alg->parameter=ASN1_TYPE_new()) == NULL) | ||
401 | goto err; | ||
402 | p7i->digest_alg->parameter->type=V_ASN1_NULL; | ||
403 | 393 | ||
404 | if (p7i->digest_enc_alg->parameter != NULL) | 394 | if (pkey->ameth && pkey->ameth->pkey_ctrl) |
405 | ASN1_TYPE_free(p7i->digest_enc_alg->parameter); | ||
406 | nid = EVP_PKEY_type(pkey->type); | ||
407 | if (nid == EVP_PKEY_RSA) | ||
408 | { | 395 | { |
409 | p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_rsaEncryption); | 396 | ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN, |
410 | if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new())) | 397 | 0, p7i); |
411 | goto err; | 398 | if (ret > 0) |
412 | p7i->digest_enc_alg->parameter->type=V_ASN1_NULL; | 399 | return 1; |
413 | } | 400 | if (ret != -2) |
414 | else if (nid == EVP_PKEY_DSA) | 401 | { |
415 | { | 402 | PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET, |
416 | #if 1 | 403 | PKCS7_R_SIGNING_CTRL_FAILURE); |
417 | /* use 'dsaEncryption' OID for compatibility with other software | 404 | return 0; |
418 | * (PKCS #7 v1.5 does specify how to handle DSA) ... */ | 405 | } |
419 | p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_dsa); | ||
420 | #else | ||
421 | /* ... although the 'dsaWithSHA1' OID (as required by RFC 2630 for CMS) | ||
422 | * would make more sense. */ | ||
423 | p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_dsaWithSHA1); | ||
424 | #endif | ||
425 | p7i->digest_enc_alg->parameter = NULL; /* special case for DSA: omit 'parameter'! */ | ||
426 | } | ||
427 | else if (nid == EVP_PKEY_EC) | ||
428 | { | ||
429 | p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_ecdsa_with_SHA1); | ||
430 | if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new())) | ||
431 | goto err; | ||
432 | p7i->digest_enc_alg->parameter->type=V_ASN1_NULL; | ||
433 | } | 406 | } |
434 | else | 407 | PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET, |
435 | return(0); | 408 | PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); |
436 | |||
437 | return(1); | ||
438 | err: | 409 | err: |
439 | return(0); | 410 | return 0; |
440 | } | 411 | } |
441 | 412 | ||
442 | PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, | 413 | PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, |
443 | const EVP_MD *dgst) | 414 | const EVP_MD *dgst) |
444 | { | 415 | { |
445 | PKCS7_SIGNER_INFO *si; | 416 | PKCS7_SIGNER_INFO *si = NULL; |
417 | |||
418 | if (dgst == NULL) | ||
419 | { | ||
420 | int def_nid; | ||
421 | if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) | ||
422 | goto err; | ||
423 | dgst = EVP_get_digestbynid(def_nid); | ||
424 | if (dgst == NULL) | ||
425 | { | ||
426 | PKCS7err(PKCS7_F_PKCS7_ADD_SIGNATURE, | ||
427 | PKCS7_R_NO_DEFAULT_DIGEST); | ||
428 | goto err; | ||
429 | } | ||
430 | } | ||
446 | 431 | ||
447 | if ((si=PKCS7_SIGNER_INFO_new()) == NULL) goto err; | 432 | if ((si=PKCS7_SIGNER_INFO_new()) == NULL) goto err; |
448 | if (!PKCS7_SIGNER_INFO_set(si,x509,pkey,dgst)) goto err; | 433 | if (!PKCS7_SIGNER_INFO_set(si,x509,pkey,dgst)) goto err; |
449 | if (!PKCS7_add_signer(p7,si)) goto err; | 434 | if (!PKCS7_add_signer(p7,si)) goto err; |
450 | return(si); | 435 | return(si); |
451 | err: | 436 | err: |
452 | PKCS7_SIGNER_INFO_free(si); | 437 | if (si) |
438 | PKCS7_SIGNER_INFO_free(si); | ||
453 | return(NULL); | 439 | return(NULL); |
454 | } | 440 | } |
455 | 441 | ||
@@ -485,6 +471,23 @@ STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) | |||
485 | return(NULL); | 471 | return(NULL); |
486 | } | 472 | } |
487 | 473 | ||
474 | void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk, | ||
475 | X509_ALGOR **pdig, X509_ALGOR **psig) | ||
476 | { | ||
477 | if (pk) | ||
478 | *pk = si->pkey; | ||
479 | if (pdig) | ||
480 | *pdig = si->digest_alg; | ||
481 | if (psig) | ||
482 | *psig = si->digest_enc_alg; | ||
483 | } | ||
484 | |||
485 | void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc) | ||
486 | { | ||
487 | if (penc) | ||
488 | *penc = ri->key_enc_algor; | ||
489 | } | ||
490 | |||
488 | PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) | 491 | PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) |
489 | { | 492 | { |
490 | PKCS7_RECIP_INFO *ri; | 493 | PKCS7_RECIP_INFO *ri; |
@@ -492,10 +495,11 @@ PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) | |||
492 | if ((ri=PKCS7_RECIP_INFO_new()) == NULL) goto err; | 495 | if ((ri=PKCS7_RECIP_INFO_new()) == NULL) goto err; |
493 | if (!PKCS7_RECIP_INFO_set(ri,x509)) goto err; | 496 | if (!PKCS7_RECIP_INFO_set(ri,x509)) goto err; |
494 | if (!PKCS7_add_recipient_info(p7,ri)) goto err; | 497 | if (!PKCS7_add_recipient_info(p7,ri)) goto err; |
495 | return(ri); | 498 | return ri; |
496 | err: | 499 | err: |
497 | PKCS7_RECIP_INFO_free(ri); | 500 | if (ri) |
498 | return(NULL); | 501 | PKCS7_RECIP_INFO_free(ri); |
502 | return NULL; | ||
499 | } | 503 | } |
500 | 504 | ||
501 | int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) | 505 | int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) |
@@ -524,6 +528,8 @@ int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) | |||
524 | 528 | ||
525 | int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) | 529 | int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) |
526 | { | 530 | { |
531 | int ret; | ||
532 | EVP_PKEY *pkey = NULL; | ||
527 | if (!ASN1_INTEGER_set(p7i->version,0)) | 533 | if (!ASN1_INTEGER_set(p7i->version,0)) |
528 | return 0; | 534 | return 0; |
529 | if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, | 535 | if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, |
@@ -535,14 +541,41 @@ int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) | |||
535 | M_ASN1_INTEGER_dup(X509_get_serialNumber(x509)))) | 541 | M_ASN1_INTEGER_dup(X509_get_serialNumber(x509)))) |
536 | return 0; | 542 | return 0; |
537 | 543 | ||
538 | X509_ALGOR_free(p7i->key_enc_algor); | 544 | pkey = X509_get_pubkey(x509); |
539 | if (!(p7i->key_enc_algor= X509_ALGOR_dup(x509->cert_info->key->algor))) | 545 | |
540 | return 0; | 546 | if (!pkey || !pkey->ameth || !pkey->ameth->pkey_ctrl) |
547 | { | ||
548 | PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET, | ||
549 | PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | ||
550 | goto err; | ||
551 | } | ||
552 | |||
553 | ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT, | ||
554 | 0, p7i); | ||
555 | if (ret == -2) | ||
556 | { | ||
557 | PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET, | ||
558 | PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); | ||
559 | goto err; | ||
560 | } | ||
561 | if (ret <= 0) | ||
562 | { | ||
563 | PKCS7err(PKCS7_F_PKCS7_RECIP_INFO_SET, | ||
564 | PKCS7_R_ENCRYPTION_CTRL_FAILURE); | ||
565 | goto err; | ||
566 | } | ||
567 | |||
568 | EVP_PKEY_free(pkey); | ||
541 | 569 | ||
542 | CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); | 570 | CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); |
543 | p7i->cert=x509; | 571 | p7i->cert=x509; |
544 | 572 | ||
545 | return(1); | 573 | return 1; |
574 | |||
575 | err: | ||
576 | if (pkey) | ||
577 | EVP_PKEY_free(pkey); | ||
578 | return 0; | ||
546 | } | 579 | } |
547 | 580 | ||
548 | X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) | 581 | X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) |
@@ -587,3 +620,48 @@ int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) | |||
587 | return 1; | 620 | return 1; |
588 | } | 621 | } |
589 | 622 | ||
623 | int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7) | ||
624 | { | ||
625 | ASN1_OCTET_STRING *os = NULL; | ||
626 | |||
627 | switch (OBJ_obj2nid(p7->type)) | ||
628 | { | ||
629 | case NID_pkcs7_data: | ||
630 | os = p7->d.data; | ||
631 | break; | ||
632 | |||
633 | case NID_pkcs7_signedAndEnveloped: | ||
634 | os = p7->d.signed_and_enveloped->enc_data->enc_data; | ||
635 | if (os == NULL) | ||
636 | { | ||
637 | os=M_ASN1_OCTET_STRING_new(); | ||
638 | p7->d.signed_and_enveloped->enc_data->enc_data=os; | ||
639 | } | ||
640 | break; | ||
641 | |||
642 | case NID_pkcs7_enveloped: | ||
643 | os = p7->d.enveloped->enc_data->enc_data; | ||
644 | if (os == NULL) | ||
645 | { | ||
646 | os=M_ASN1_OCTET_STRING_new(); | ||
647 | p7->d.enveloped->enc_data->enc_data=os; | ||
648 | } | ||
649 | break; | ||
650 | |||
651 | case NID_pkcs7_signed: | ||
652 | os=p7->d.sign->contents->d.data; | ||
653 | break; | ||
654 | |||
655 | default: | ||
656 | os = NULL; | ||
657 | break; | ||
658 | } | ||
659 | |||
660 | if (os == NULL) | ||
661 | return 0; | ||
662 | |||
663 | os->flags |= ASN1_STRING_FLAG_NDEF; | ||
664 | *boundary = &os->data; | ||
665 | |||
666 | return 1; | ||
667 | } | ||