diff options
author | Damien Miller <djm@cvs.openbsd.org> | 2008-09-06 12:17:55 +0000 |
---|---|---|
committer | Damien Miller <djm@cvs.openbsd.org> | 2008-09-06 12:17:55 +0000 |
commit | 96de7a4399a8c71cbb70d6252fa77acfd76b3f09 (patch) | |
tree | e6f6e4aad1952944ccd27e9eb47ea48b9a78dde7 /lib/libcrypto/pkcs7 | |
parent | ec7710fe8f10fb624fbc33c0bbad2474e0c26979 (diff) |
resolve conflicts
Diffstat (limited to 'lib/libcrypto/pkcs7')
-rw-r--r-- | lib/libcrypto/pkcs7/bio_ber.c | 2 | ||||
-rw-r--r-- | lib/libcrypto/pkcs7/example.c | 8 | ||||
-rw-r--r-- | lib/libcrypto/pkcs7/pk7_asn1.c | 41 | ||||
-rw-r--r-- | lib/libcrypto/pkcs7/pk7_attr.c | 3 | ||||
-rw-r--r-- | lib/libcrypto/pkcs7/pk7_doit.c | 354 | ||||
-rw-r--r-- | lib/libcrypto/pkcs7/pk7_lib.c | 117 | ||||
-rw-r--r-- | lib/libcrypto/pkcs7/pk7_mime.c | 104 | ||||
-rw-r--r-- | lib/libcrypto/pkcs7/pk7_smime.c | 109 | ||||
-rw-r--r-- | lib/libcrypto/pkcs7/pkcs7.h | 15 | ||||
-rw-r--r-- | lib/libcrypto/pkcs7/pkcs7err.c | 15 |
10 files changed, 514 insertions, 254 deletions
diff --git a/lib/libcrypto/pkcs7/bio_ber.c b/lib/libcrypto/pkcs7/bio_ber.c index 895a91177be..31973fcd1fc 100644 --- a/lib/libcrypto/pkcs7/bio_ber.c +++ b/lib/libcrypto/pkcs7/bio_ber.c @@ -204,7 +204,7 @@ int bio_ber_get_header(BIO *bio, BIO_BER_CTX *ctx) if ((ctx->buf_len < BER_BUF_SIZE) && (ERR_GET_REASON(ERR_peek_error()) == ASN1_R_TOO_LONG)) { - ERR_get_error(); /* clear the error */ + ERR_clear_error(); /* clear the error */ BIO_set_retry_read(b); } return(-1); diff --git a/lib/libcrypto/pkcs7/example.c b/lib/libcrypto/pkcs7/example.c index c993947cc37..2953d04b5c9 100644 --- a/lib/libcrypto/pkcs7/example.c +++ b/lib/libcrypto/pkcs7/example.c @@ -123,7 +123,7 @@ int get_signed_seq2string(PKCS7_SIGNER_INFO *si, char **str1, char **str2) so=PKCS7_get_signed_attribute(si,signed_seq2string_nid); if (so && (so->type == V_ASN1_SEQUENCE)) { - ASN1_CTX c; + ASN1_const_CTX c; ASN1_STRING *s; long length; ASN1_OCTET_STRING *os1,*os2; @@ -144,7 +144,7 @@ int get_signed_seq2string(PKCS7_SIGNER_INFO *si, char **str1, char **str2) goto err; c.slen-=(c.p-c.q); - if (!asn1_Finish(&c)) goto err; + if (!asn1_const_Finish(&c)) goto err; *str1=malloc(os1->length+1); *str2=malloc(os2->length+1); memcpy(*str1,os1->data,os1->length); @@ -290,7 +290,7 @@ int sk_get_seq2string(STACK_OF(X509_ATTRIBUTE) *sk, char **str1, char **str2) so=PKCS7_get_signed_attribute(&si,signed_seq2string_nid); if (so->type == V_ASN1_SEQUENCE) { - ASN1_CTX c; + ASN1_const_CTX c; ASN1_STRING *s; long length; ASN1_OCTET_STRING *os1,*os2; @@ -311,7 +311,7 @@ int sk_get_seq2string(STACK_OF(X509_ATTRIBUTE) *sk, char **str1, char **str2) goto err; c.slen-=(c.p-c.q); - if (!asn1_Finish(&c)) goto err; + if (!asn1_const_Finish(&c)) goto err; *str1=malloc(os1->length+1); *str2=malloc(os2->length+1); memcpy(*str1,os1->data,os1->length); diff --git a/lib/libcrypto/pkcs7/pk7_asn1.c b/lib/libcrypto/pkcs7/pk7_asn1.c index 46f0fc9375b..77931feeb41 100644 --- a/lib/libcrypto/pkcs7/pk7_asn1.c +++ b/lib/libcrypto/pkcs7/pk7_asn1.c @@ -69,30 +69,31 @@ ASN1_ADB_TEMPLATE(p7default) = ASN1_EXP_OPT(PKCS7, d.other, ASN1_ANY, 0); ASN1_ADB(PKCS7) = { - ADB_ENTRY(NID_pkcs7_data, ASN1_EXP_OPT(PKCS7, d.data, ASN1_OCTET_STRING, 0)), - ADB_ENTRY(NID_pkcs7_signed, ASN1_EXP_OPT(PKCS7, d.sign, PKCS7_SIGNED, 0)), - ADB_ENTRY(NID_pkcs7_enveloped, ASN1_EXP_OPT(PKCS7, d.enveloped, PKCS7_ENVELOPE, 0)), - ADB_ENTRY(NID_pkcs7_signedAndEnveloped, ASN1_EXP_OPT(PKCS7, d.signed_and_enveloped, PKCS7_SIGN_ENVELOPE, 0)), - ADB_ENTRY(NID_pkcs7_digest, ASN1_EXP_OPT(PKCS7, d.digest, PKCS7_DIGEST, 0)), - ADB_ENTRY(NID_pkcs7_encrypted, ASN1_EXP_OPT(PKCS7, d.encrypted, PKCS7_ENCRYPT, 0)) + ADB_ENTRY(NID_pkcs7_data, ASN1_NDEF_EXP_OPT(PKCS7, d.data, ASN1_OCTET_STRING_NDEF, 0)), + ADB_ENTRY(NID_pkcs7_signed, ASN1_NDEF_EXP_OPT(PKCS7, d.sign, PKCS7_SIGNED, 0)), + ADB_ENTRY(NID_pkcs7_enveloped, ASN1_NDEF_EXP_OPT(PKCS7, d.enveloped, PKCS7_ENVELOPE, 0)), + ADB_ENTRY(NID_pkcs7_signedAndEnveloped, ASN1_NDEF_EXP_OPT(PKCS7, d.signed_and_enveloped, PKCS7_SIGN_ENVELOPE, 0)), + ADB_ENTRY(NID_pkcs7_digest, ASN1_NDEF_EXP_OPT(PKCS7, d.digest, PKCS7_DIGEST, 0)), + ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP_OPT(PKCS7, d.encrypted, PKCS7_ENCRYPT, 0)) } ASN1_ADB_END(PKCS7, 0, type, 0, &p7default_tt, NULL); -ASN1_SEQUENCE(PKCS7) = { +ASN1_NDEF_SEQUENCE(PKCS7) = { ASN1_SIMPLE(PKCS7, type, ASN1_OBJECT), ASN1_ADB_OBJECT(PKCS7) -}ASN1_SEQUENCE_END(PKCS7) +}ASN1_NDEF_SEQUENCE_END(PKCS7) IMPLEMENT_ASN1_FUNCTIONS(PKCS7) +IMPLEMENT_ASN1_NDEF_FUNCTION(PKCS7) IMPLEMENT_ASN1_DUP_FUNCTION(PKCS7) -ASN1_SEQUENCE(PKCS7_SIGNED) = { +ASN1_NDEF_SEQUENCE(PKCS7_SIGNED) = { ASN1_SIMPLE(PKCS7_SIGNED, version, ASN1_INTEGER), ASN1_SET_OF(PKCS7_SIGNED, md_algs, X509_ALGOR), ASN1_SIMPLE(PKCS7_SIGNED, contents, PKCS7), ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNED, cert, X509, 0), ASN1_IMP_SET_OF_OPT(PKCS7_SIGNED, crl, X509_CRL, 1), ASN1_SET_OF(PKCS7_SIGNED, signer_info, PKCS7_SIGNER_INFO) -} ASN1_SEQUENCE_END(PKCS7_SIGNED) +} ASN1_NDEF_SEQUENCE_END(PKCS7_SIGNED) IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGNED) @@ -130,11 +131,11 @@ ASN1_SEQUENCE(PKCS7_ISSUER_AND_SERIAL) = { IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL) -ASN1_SEQUENCE(PKCS7_ENVELOPE) = { +ASN1_NDEF_SEQUENCE(PKCS7_ENVELOPE) = { ASN1_SIMPLE(PKCS7_ENVELOPE, version, ASN1_INTEGER), ASN1_SET_OF(PKCS7_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO), ASN1_SIMPLE(PKCS7_ENVELOPE, enc_data, PKCS7_ENC_CONTENT) -} ASN1_SEQUENCE_END(PKCS7_ENVELOPE) +} ASN1_NDEF_SEQUENCE_END(PKCS7_ENVELOPE) IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENVELOPE) @@ -157,15 +158,15 @@ ASN1_SEQUENCE_cb(PKCS7_RECIP_INFO, ri_cb) = { IMPLEMENT_ASN1_FUNCTIONS(PKCS7_RECIP_INFO) -ASN1_SEQUENCE(PKCS7_ENC_CONTENT) = { +ASN1_NDEF_SEQUENCE(PKCS7_ENC_CONTENT) = { ASN1_SIMPLE(PKCS7_ENC_CONTENT, content_type, ASN1_OBJECT), ASN1_SIMPLE(PKCS7_ENC_CONTENT, algorithm, X509_ALGOR), ASN1_IMP_OPT(PKCS7_ENC_CONTENT, enc_data, ASN1_OCTET_STRING, 0) -} ASN1_SEQUENCE_END(PKCS7_ENC_CONTENT) +} ASN1_NDEF_SEQUENCE_END(PKCS7_ENC_CONTENT) IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT) -ASN1_SEQUENCE(PKCS7_SIGN_ENVELOPE) = { +ASN1_NDEF_SEQUENCE(PKCS7_SIGN_ENVELOPE) = { ASN1_SIMPLE(PKCS7_SIGN_ENVELOPE, version, ASN1_INTEGER), ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, recipientinfo, PKCS7_RECIP_INFO), ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, md_algs, X509_ALGOR), @@ -173,23 +174,23 @@ ASN1_SEQUENCE(PKCS7_SIGN_ENVELOPE) = { ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, cert, X509, 0), ASN1_IMP_SET_OF_OPT(PKCS7_SIGN_ENVELOPE, crl, X509_CRL, 1), ASN1_SET_OF(PKCS7_SIGN_ENVELOPE, signer_info, PKCS7_SIGNER_INFO) -} ASN1_SEQUENCE_END(PKCS7_SIGN_ENVELOPE) +} ASN1_NDEF_SEQUENCE_END(PKCS7_SIGN_ENVELOPE) IMPLEMENT_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE) -ASN1_SEQUENCE(PKCS7_ENCRYPT) = { +ASN1_NDEF_SEQUENCE(PKCS7_ENCRYPT) = { ASN1_SIMPLE(PKCS7_ENCRYPT, version, ASN1_INTEGER), ASN1_SIMPLE(PKCS7_ENCRYPT, enc_data, PKCS7_ENC_CONTENT) -} ASN1_SEQUENCE_END(PKCS7_ENCRYPT) +} ASN1_NDEF_SEQUENCE_END(PKCS7_ENCRYPT) IMPLEMENT_ASN1_FUNCTIONS(PKCS7_ENCRYPT) -ASN1_SEQUENCE(PKCS7_DIGEST) = { +ASN1_NDEF_SEQUENCE(PKCS7_DIGEST) = { ASN1_SIMPLE(PKCS7_DIGEST, version, ASN1_INTEGER), ASN1_SIMPLE(PKCS7_DIGEST, md, X509_ALGOR), ASN1_SIMPLE(PKCS7_DIGEST, contents, PKCS7), ASN1_SIMPLE(PKCS7_DIGEST, digest, ASN1_OCTET_STRING) -} ASN1_SEQUENCE_END(PKCS7_DIGEST) +} ASN1_NDEF_SEQUENCE_END(PKCS7_DIGEST) IMPLEMENT_ASN1_FUNCTIONS(PKCS7_DIGEST) diff --git a/lib/libcrypto/pkcs7/pk7_attr.c b/lib/libcrypto/pkcs7/pk7_attr.c index 039141027a6..735c8800e10 100644 --- a/lib/libcrypto/pkcs7/pk7_attr.c +++ b/lib/libcrypto/pkcs7/pk7_attr.c @@ -96,7 +96,8 @@ int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, STACK_OF(X509_ALGOR) *cap) STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si) { ASN1_TYPE *cap; - unsigned char *p; + const unsigned char *p; + cap = PKCS7_get_signed_attribute(si, NID_SMIMECapabilities); if (!cap || (cap->type != V_ASN1_SEQUENCE)) return NULL; diff --git a/lib/libcrypto/pkcs7/pk7_doit.c b/lib/libcrypto/pkcs7/pk7_doit.c index 4ac29ae14d6..a03d7ebedf1 100644 --- a/lib/libcrypto/pkcs7/pk7_doit.c +++ b/lib/libcrypto/pkcs7/pk7_doit.c @@ -62,6 +62,7 @@ #include <openssl/objects.h> #include <openssl/x509.h> #include <openssl/x509v3.h> +#include <openssl/err.h> static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, void *value); @@ -101,18 +102,54 @@ static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) return NULL; } +static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) + { + BIO *btmp; + const EVP_MD *md; + if ((btmp=BIO_new(BIO_f_md())) == NULL) + { + PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB); + goto err; + } + + md=EVP_get_digestbyobj(alg->algorithm); + if (md == NULL) + { + PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE); + goto err; + } + + BIO_set_md(btmp,md); + if (*pbio == NULL) + *pbio=btmp; + else if (!BIO_push(*pbio,btmp)) + { + PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB); + goto err; + } + btmp=NULL; + + return 1; + + err: + if (btmp) + BIO_free(btmp); + return 0; + + } + BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) { int i; BIO *out=NULL,*btmp=NULL; - X509_ALGOR *xa; - const EVP_MD *evp_md; + X509_ALGOR *xa = NULL; const EVP_CIPHER *evp_cipher=NULL; STACK_OF(X509_ALGOR) *md_sk=NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; X509_ALGOR *xalg=NULL; PKCS7_RECIP_INFO *ri=NULL; EVP_PKEY *pkey; + ASN1_OCTET_STRING *os=NULL; i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; @@ -121,6 +158,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) { case NID_pkcs7_signed: md_sk=p7->d.sign->md_algs; + os = PKCS7_get_octet_string(p7->d.sign->contents); break; case NID_pkcs7_signedAndEnveloped: rsk=p7->d.signed_and_enveloped->recipientinfo; @@ -145,37 +183,21 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) goto err; } break; + case NID_pkcs7_digest: + xa = p7->d.digest->md; + os = PKCS7_get_octet_string(p7->d.digest->contents); + break; default: PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } - if (md_sk != NULL) - { - for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) - { - xa=sk_X509_ALGOR_value(md_sk,i); - if ((btmp=BIO_new(BIO_f_md())) == NULL) - { - PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); - goto err; - } - - evp_md=EVP_get_digestbyobj(xa->algorithm); - if (evp_md == NULL) - { - PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNKNOWN_DIGEST_TYPE); - goto err; - } + for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) + if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) + goto err; - BIO_set_md(btmp,evp_md); - if (out == NULL) - out=btmp; - else - BIO_push(out,btmp); - btmp=NULL; - } - } + if (xa && !PKCS7_bio_add_digest(&out, xa)) + goto err; if (evp_cipher != NULL) { @@ -194,17 +216,25 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) BIO_get_cipher_ctx(btmp, &ctx); keylen=EVP_CIPHER_key_length(evp_cipher); ivlen=EVP_CIPHER_iv_length(evp_cipher); - if (RAND_bytes(key,keylen) <= 0) - goto err; xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); - if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen); - EVP_CipherInit_ex(ctx, evp_cipher, NULL, key, iv, 1); + if (ivlen > 0) + if (RAND_pseudo_bytes(iv,ivlen) <= 0) + goto err; + if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0) + goto err; + if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) + goto err; + if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) + goto err; if (ivlen > 0) { - if (xalg->parameter == NULL) - xalg->parameter=ASN1_TYPE_new(); + if (xalg->parameter == NULL) { + xalg->parameter = ASN1_TYPE_new(); + if (xalg->parameter == NULL) + goto err; + } if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) - goto err; + goto err; } /* Lets do the pub key stuff :-) */ @@ -217,7 +247,8 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO); goto err; } - pkey=X509_get_pubkey(ri->cert); + if ((pkey=X509_get_pubkey(ri->cert)) == NULL) + goto err; jj=EVP_PKEY_size(pkey); EVP_PKEY_free(pkey); if (max < jj) max=jj; @@ -230,7 +261,8 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); - pkey=X509_get_pubkey(ri->cert); + if ((pkey=X509_get_pubkey(ri->cert)) == NULL) + goto err; jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey); EVP_PKEY_free(pkey); if (jj <= 0) @@ -261,24 +293,16 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) { if (PKCS7_is_detached(p7)) bio=BIO_new(BIO_s_null()); - else + else if (os && os->length > 0) + bio = BIO_new_mem_buf(os->data, os->length); + if(bio == NULL) { - if (PKCS7_type_is_signed(p7)) - { - ASN1_OCTET_STRING *os; - os = PKCS7_get_octet_string( - p7->d.sign->contents); - if (os && os->length > 0) - bio = BIO_new_mem_buf(os->data, - os->length); - } - if(bio == NULL) - { - bio=BIO_new(BIO_s_mem()); - BIO_set_mem_eof_return(bio,0); - } + bio=BIO_new(BIO_s_mem()); + if (bio == NULL) + goto err; + BIO_set_mem_eof_return(bio,0); } - } + } BIO_push(out,bio); bio=NULL; if (0) @@ -293,6 +317,17 @@ err: return(out); } +static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert) + { + int ret; + ret = X509_NAME_cmp(ri->issuer_and_serial->issuer, + pcert->cert_info->issuer); + if (ret) + return ret; + return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, + ri->issuer_and_serial->serial); + } + /* int */ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) { @@ -403,18 +438,18 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) * (if any) */ - for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { - ri=sk_PKCS7_RECIP_INFO_value(rsk,i); - if(!X509_NAME_cmp(ri->issuer_and_serial->issuer, - pcert->cert_info->issuer) && - !M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, - ri->issuer_and_serial->serial)) break; - ri=NULL; - } - if (ri == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATADECODE, - PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); - goto err; + if (pcert) { + for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { + ri=sk_PKCS7_RECIP_INFO_value(rsk,i); + if (!pkcs7_cmp_ri(ri, pcert)) + break; + ri=NULL; + } + if (ri == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); + goto err; + } } jj=EVP_PKEY_size(pkey); @@ -425,17 +460,46 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) goto err; } - jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key), - M_ASN1_STRING_length(ri->enc_key), pkey); - if (jj <= 0) + /* If we haven't got a certificate try each ri in turn */ + + if (pcert == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB); - goto err; + for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) + { + ri=sk_PKCS7_RECIP_INFO_value(rsk,i); + jj=EVP_PKEY_decrypt(tmp, + M_ASN1_STRING_data(ri->enc_key), + M_ASN1_STRING_length(ri->enc_key), + pkey); + if (jj > 0) + break; + ERR_clear_error(); + ri = NULL; + } + if (ri == NULL) + { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_NO_RECIPIENT_MATCHES_KEY); + goto err; + } + } + else + { + jj=EVP_PKEY_decrypt(tmp, + M_ASN1_STRING_data(ri->enc_key), + M_ASN1_STRING_length(ri->enc_key), pkey); + if (jj <= 0) + { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + ERR_R_EVP_LIB); + goto err; + } } evp_ctx=NULL; BIO_get_cipher_ctx(etmp,&evp_ctx); - EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0); + if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0) + goto err; if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) goto err; @@ -451,7 +515,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) goto err; } } - EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0); + if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0) + goto err; OPENSSL_cleanse(tmp,jj); @@ -485,6 +550,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) bio=BIO_new(BIO_s_mem()); BIO_set_mem_eof_return(bio,0); } + if (bio == NULL) + goto err; #endif } BIO_push(out,bio); @@ -504,6 +571,29 @@ err: return(out); } +static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) + { + for (;;) + { + bio=BIO_find_type(bio,BIO_TYPE_MD); + if (bio == NULL) + { + PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); + return NULL; + } + BIO_get_md_ctx(bio,pmd); + if (*pmd == NULL) + { + PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR); + return NULL; + } + if (EVP_MD_CTX_type(*pmd) == nid) + return bio; + bio=BIO_next(bio); + } + return NULL; + } + int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) { int ret=0; @@ -528,7 +618,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) si_sk=p7->d.signed_and_enveloped->signer_info; if (!(os=M_ASN1_OCTET_STRING_new())) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_MALLOC_FAILURE); + PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE); goto err; } p7->d.signed_and_enveloped->enc_data->enc_data=os; @@ -537,7 +627,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) /* XXXXXXXXXXXXXXXX */ if (!(os=M_ASN1_OCTET_STRING_new())) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_MALLOC_FAILURE); + PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE); goto err; } p7->d.enveloped->enc_data->enc_data=os; @@ -551,13 +641,24 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) p7->d.sign->contents->d.data = NULL; } break; + + case NID_pkcs7_digest: + os=PKCS7_get_octet_string(p7->d.digest->contents); + /* If detached data then the content is excluded */ + if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) + { + M_ASN1_OCTET_STRING_free(os); + p7->d.digest->contents->d.data = NULL; + } + break; + } if (si_sk != NULL) { if ((buf=BUF_MEM_new()) == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); + PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB); goto err; } for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++) @@ -568,32 +669,18 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) j=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; - for (;;) - { - if ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) - == NULL) - { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); - goto err; - } - BIO_get_md_ctx(btmp,&mdc); - if (mdc == NULL) - { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_INTERNAL_ERROR); - goto err; - } - if (EVP_MD_CTX_type(mdc) == j) - break; - else - btmp=BIO_next(btmp); - } - + + btmp = PKCS7_find_digest(&mdc, btmp, j); + + if (btmp == NULL) + goto err; + /* We now have the EVP_MD_CTX, lets do the * signing. */ EVP_MD_CTX_copy_ex(&ctx_tmp,mdc); if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey))) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); + PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB); goto err; } @@ -615,13 +702,17 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) { if (!(sign_time=X509_gmtime_adj(NULL,0))) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN, + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); goto err; } - PKCS7_add_signed_attribute(si, + if (!PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime, - V_ASN1_UTCTIME,sign_time); + V_ASN1_UTCTIME,sign_time)) + { + M_ASN1_UTCTIME_free(sign_time); + goto err; + } } /* Add digest */ @@ -629,20 +720,25 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len); if (!(digest=M_ASN1_OCTET_STRING_new())) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN, + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); goto err; } if (!M_ASN1_OCTET_STRING_set(digest,md_data, md_len)) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN, + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); + M_ASN1_OCTET_STRING_free(digest); goto err; } - PKCS7_add_signed_attribute(si, + if (!PKCS7_add_signed_attribute(si, NID_pkcs9_messageDigest, - V_ASN1_OCTET_STRING,digest); + V_ASN1_OCTET_STRING,digest)) + { + M_ASN1_OCTET_STRING_free(digest); + goto err; + } /* Now sign the attributes */ EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL); @@ -657,28 +753,42 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) if (si->pkey->type == EVP_PKEY_DSA) ctx_tmp.digest=EVP_dss1(); #endif +#ifndef OPENSSL_NO_ECDSA + if (si->pkey->type == EVP_PKEY_EC) + ctx_tmp.digest=EVP_ecdsa(); +#endif if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data, (unsigned int *)&buf->length,si->pkey)) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB); + PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB); goto err; } if (!ASN1_STRING_set(si->enc_digest, (unsigned char *)buf->data,buf->length)) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB); + PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB); goto err; } } } + else if (i == NID_pkcs7_digest) + { + unsigned char md_data[EVP_MAX_MD_SIZE]; + unsigned int md_len; + if (!PKCS7_find_digest(&mdc, bio, + OBJ_obj2nid(p7->d.digest->md->algorithm))) + goto err; + EVP_DigestFinal_ex(mdc,md_data,&md_len); + M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); + } if (!PKCS7_is_detached(p7)) { btmp=BIO_find_type(bio,BIO_TYPE_MEM); if (btmp == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO); + PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO); goto err; } BIO_get_mem_ptr(btmp,&buf_mem); @@ -859,6 +969,9 @@ for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); #ifndef OPENSSL_NO_DSA if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1(); #endif +#ifndef OPENSSL_NO_ECDSA + if (pkey->type == EVP_PKEY_EC) mdc_tmp.digest=EVP_ecdsa(); +#endif i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey); EVP_PKEY_free(pkey); @@ -883,8 +996,13 @@ PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx) int i; i=OBJ_obj2nid(p7->type); - if (i != NID_pkcs7_signedAndEnveloped) return(NULL); + if (i != NID_pkcs7_signedAndEnveloped) + return NULL; + if (p7->d.signed_and_enveloped == NULL) + return NULL; rsk=p7->d.signed_and_enveloped->recipientinfo; + if (rsk == NULL) + return NULL; ri=sk_PKCS7_RECIP_INFO_value(rsk,0); if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL); ri=sk_PKCS7_RECIP_INFO_value(rsk,idx); @@ -938,6 +1056,8 @@ int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, if (p7si->auth_attr != NULL) sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free); p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk); + if (p7si->auth_attr == NULL) + return 0; for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) { if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i, @@ -956,6 +1076,8 @@ int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk) sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free); p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk); + if (p7si->unauth_attr == NULL) + return 0; for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) { if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i, @@ -985,10 +1107,16 @@ static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, if (*sk == NULL) { - *sk = sk_X509_ATTRIBUTE_new_null(); + if (!(*sk = sk_X509_ATTRIBUTE_new_null())) + return 0; new_attrib: - attr=X509_ATTRIBUTE_create(nid,atrtype,value); - sk_X509_ATTRIBUTE_push(*sk,attr); + if (!(attr=X509_ATTRIBUTE_create(nid,atrtype,value))) + return 0; + if (!sk_X509_ATTRIBUTE_push(*sk,attr)) + { + X509_ATTRIBUTE_free(attr); + return 0; + } } else { @@ -1001,7 +1129,13 @@ new_attrib: { X509_ATTRIBUTE_free(attr); attr=X509_ATTRIBUTE_create(nid,atrtype,value); - sk_X509_ATTRIBUTE_set(*sk,i,attr); + if (attr == NULL) + return 0; + if (!sk_X509_ATTRIBUTE_set(*sk,i,attr)) + { + X509_ATTRIBUTE_free(attr); + return 0; + } goto end; } } diff --git a/lib/libcrypto/pkcs7/pk7_lib.c b/lib/libcrypto/pkcs7/pk7_lib.c index ee1817c7af9..f2490941a34 100644 --- a/lib/libcrypto/pkcs7/pk7_lib.c +++ b/lib/libcrypto/pkcs7/pk7_lib.c @@ -138,6 +138,10 @@ int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data) p7->d.sign->contents=p7_data; break; case NID_pkcs7_digest: + if (p7->d.digest->contents != NULL) + PKCS7_free(p7->d.digest->contents); + p7->d.digest->contents=p7_data; + break; case NID_pkcs7_data: case NID_pkcs7_enveloped: case NID_pkcs7_signedAndEnveloped: @@ -206,6 +210,12 @@ int PKCS7_set_type(PKCS7 *p7, int type) break; case NID_pkcs7_digest: + p7->type=obj; + if ((p7->d.digest=PKCS7_DIGEST_new()) + == NULL) goto err; + if (!ASN1_INTEGER_set(p7->d.digest->version,0)) + goto err; + break; default: PKCS7err(PKCS7_F_PKCS7_SET_TYPE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; @@ -215,6 +225,13 @@ err: return(0); } +int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other) + { + p7->type = OBJ_nid2obj(type); + p7->d.other = other; + return 1; + } + int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) { int i,j,nid; @@ -254,16 +271,23 @@ int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) if (!j) /* we need to add another algorithm */ { if(!(alg=X509_ALGOR_new()) - || !(alg->parameter = ASN1_TYPE_new())) { + || !(alg->parameter = ASN1_TYPE_new())) + { + X509_ALGOR_free(alg); PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,ERR_R_MALLOC_FAILURE); return(0); - } + } alg->algorithm=OBJ_nid2obj(nid); alg->parameter->type = V_ASN1_NULL; - sk_X509_ALGOR_push(md_sk,alg); + if (!sk_X509_ALGOR_push(md_sk,alg)) + { + X509_ALGOR_free(alg); + return 0; + } } - sk_PKCS7_SIGNER_INFO_push(signer_sk,psi); + if (!sk_PKCS7_SIGNER_INFO_push(signer_sk,psi)) + return 0; return(1); } @@ -288,8 +312,17 @@ int PKCS7_add_certificate(PKCS7 *p7, X509 *x509) if (*sk == NULL) *sk=sk_X509_new_null(); + if (*sk == NULL) + { + PKCS7err(PKCS7_F_PKCS7_ADD_CERTIFICATE,ERR_R_MALLOC_FAILURE); + return 0; + } CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509); - sk_X509_push(*sk,x509); + if (!sk_X509_push(*sk,x509)) + { + X509_free(x509); + return 0; + } return(1); } @@ -314,18 +347,31 @@ int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) if (*sk == NULL) *sk=sk_X509_CRL_new_null(); + if (*sk == NULL) + { + PKCS7err(PKCS7_F_PKCS7_ADD_CRL,ERR_R_MALLOC_FAILURE); + return 0; + } CRYPTO_add(&crl->references,1,CRYPTO_LOCK_X509_CRL); - sk_X509_CRL_push(*sk,crl); + if (!sk_X509_CRL_push(*sk,crl)) + { + X509_CRL_free(crl); + return 0; + } return(1); } int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, const EVP_MD *dgst) { + int nid; char is_dsa; - if (pkey->type == EVP_PKEY_DSA) is_dsa = 1; - else is_dsa = 0; + + if (pkey->type == EVP_PKEY_DSA || pkey->type == EVP_PKEY_EC) + is_dsa = 1; + else + is_dsa = 0; /* We now need to add another PKCS7_SIGNER_INFO entry */ if (!ASN1_INTEGER_set(p7i->version,1)) goto err; @@ -355,16 +401,38 @@ int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, goto err; p7i->digest_alg->parameter->type=V_ASN1_NULL; - p7i->digest_enc_alg->algorithm=OBJ_nid2obj(EVP_PKEY_type(pkey->type)); - if (p7i->digest_enc_alg->parameter != NULL) ASN1_TYPE_free(p7i->digest_enc_alg->parameter); - if(is_dsa) p7i->digest_enc_alg->parameter = NULL; - else { + nid = EVP_PKEY_type(pkey->type); + if (nid == EVP_PKEY_RSA) + { + p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_rsaEncryption); if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new())) goto err; p7i->digest_enc_alg->parameter->type=V_ASN1_NULL; - } + } + else if (nid == EVP_PKEY_DSA) + { +#if 1 + /* use 'dsaEncryption' OID for compatibility with other software + * (PKCS #7 v1.5 does specify how to handle DSA) ... */ + p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_dsa); +#else + /* ... although the 'dsaWithSHA1' OID (as required by RFC 2630 for CMS) + * would make more sense. */ + p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_dsaWithSHA1); +#endif + p7i->digest_enc_alg->parameter = NULL; /* special case for DSA: omit 'parameter'! */ + } + else if (nid == EVP_PKEY_EC) + { + p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_ecdsa_with_SHA1); + if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new())) + goto err; + p7i->digest_enc_alg->parameter->type=V_ASN1_NULL; + } + else + return(0); return(1); err: @@ -381,9 +449,28 @@ PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, if (!PKCS7_add_signer(p7,si)) goto err; return(si); err: + PKCS7_SIGNER_INFO_free(si); return(NULL); } +int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) + { + if (PKCS7_type_is_digest(p7)) + { + if(!(p7->d.digest->md->parameter = ASN1_TYPE_new())) + { + PKCS7err(PKCS7_F_PKCS7_SET_DIGEST,ERR_R_MALLOC_FAILURE); + return 0; + } + p7->d.digest->md->parameter->type = V_ASN1_NULL; + p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md)); + return 1; + } + + PKCS7err(PKCS7_F_PKCS7_SET_DIGEST,PKCS7_R_WRONG_CONTENT_TYPE); + return 1; + } + STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7) { if (PKCS7_type_is_signed(p7)) @@ -407,6 +494,7 @@ PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) if (!PKCS7_add_recipient_info(p7,ri)) goto err; return(ri); err: + PKCS7_RECIP_INFO_free(ri); return(NULL); } @@ -429,7 +517,8 @@ int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) return(0); } - sk_PKCS7_RECIP_INFO_push(sk,ri); + if (!sk_PKCS7_RECIP_INFO_push(sk,ri)) + return 0; return(1); } diff --git a/lib/libcrypto/pkcs7/pk7_mime.c b/lib/libcrypto/pkcs7/pk7_mime.c index 927b88c3e75..17b68992f7d 100644 --- a/lib/libcrypto/pkcs7/pk7_mime.c +++ b/lib/libcrypto/pkcs7/pk7_mime.c @@ -1,6 +1,6 @@ /* pk7_mime.c */ /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL - * project 1999. + * project. */ /* ==================================================================== * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. @@ -86,6 +86,7 @@ STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */ DECLARE_STACK_OF(MIME_HEADER) IMPLEMENT_STACK_OF(MIME_HEADER) +static int pkcs7_output_data(BIO *bio, BIO *data, PKCS7 *p7, int flags); static int B64_write_PKCS7(BIO *bio, PKCS7 *p7); static PKCS7 *B64_read_PKCS7(BIO *bio); static char * strip_ends(char *name); @@ -109,9 +110,6 @@ static void mime_hdr_free(MIME_HEADER *hdr); #define MAX_SMLEN 1024 #define mime_debug(x) /* x */ - -typedef void (*stkfree)(); - /* Base 64 read and write of PKCS#7 structure */ static int B64_write_PKCS7(BIO *bio, PKCS7 *p7) @@ -123,7 +121,7 @@ static int B64_write_PKCS7(BIO *bio, PKCS7 *p7) } bio = BIO_push(b64, bio); i2d_PKCS7_bio(bio, p7); - BIO_flush(bio); + (void)BIO_flush(bio); bio = BIO_pop(bio); BIO_free(b64); return 1; @@ -140,7 +138,7 @@ static PKCS7 *B64_read_PKCS7(BIO *bio) bio = BIO_push(b64, bio); if(!(p7 = d2i_PKCS7_bio(bio, NULL))) PKCS7err(PKCS7_F_B64_READ_PKCS7,PKCS7_R_DECODE_ERROR); - BIO_flush(bio); + (void)BIO_flush(bio); bio = BIO_pop(bio); BIO_free(b64); return p7; @@ -182,7 +180,7 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) mime_eol, mime_eol); /* Now write out the first part */ BIO_printf(bio, "------%s%s", bound, mime_eol); - SMIME_crlf_copy(data, bio, flags); + pkcs7_output_data(bio, data, p7, flags); BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol); /* Headers for signature */ @@ -196,7 +194,7 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) mime_eol, mime_eol); B64_write_PKCS7(bio, p7); BIO_printf(bio,"%s------%s--%s%s", mime_eol, bound, - mime_eol, mime_eol); + mime_eol, mime_eol); return 1; } @@ -231,6 +229,46 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) return 1; } +/* Handle output of PKCS#7 data */ + + +static int pkcs7_output_data(BIO *out, BIO *data, PKCS7 *p7, int flags) + { + BIO *tmpbio, *p7bio; + + if (!(flags & PKCS7_STREAM)) + { + SMIME_crlf_copy(data, out, flags); + return 1; + } + + /* Partial sign operation */ + + /* Initialize sign operation */ + p7bio = PKCS7_dataInit(p7, out); + + /* Copy data across, computing digests etc */ + SMIME_crlf_copy(data, p7bio, flags); + + /* Must be detached */ + PKCS7_set_detached(p7, 1); + + /* Finalize signatures */ + PKCS7_dataFinal(p7, p7bio); + + /* Now remove any digests prepended to the BIO */ + + while (p7bio != out) + { + tmpbio = BIO_pop(p7bio); + BIO_free(p7bio); + p7bio = tmpbio; + } + + return 1; + + } + /* SMIME reader: handle multipart/signed and opaque signing. * in multipart case the content is placed in a memory BIO * pointed to by "bcont". In opaque this is set to NULL @@ -339,56 +377,6 @@ PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont) } -/* Copy text from one BIO to another making the output CRLF at EOL */ -int SMIME_crlf_copy(BIO *in, BIO *out, int flags) -{ - char eol; - int len; - char linebuf[MAX_SMLEN]; - if(flags & PKCS7_BINARY) { - while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0) - BIO_write(out, linebuf, len); - return 1; - } - if(flags & PKCS7_TEXT) BIO_printf(out, "Content-Type: text/plain\r\n\r\n"); - while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) { - eol = strip_eol(linebuf, &len); - if (len) - BIO_write(out, linebuf, len); - if(eol) BIO_write(out, "\r\n", 2); - } - return 1; -} - -/* Strip off headers if they are text/plain */ -int SMIME_text(BIO *in, BIO *out) -{ - char iobuf[4096]; - int len; - STACK_OF(MIME_HEADER) *headers; - MIME_HEADER *hdr; - - if (!(headers = mime_parse_hdr(in))) { - PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_PARSE_ERROR); - return 0; - } - if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { - PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_NO_CONTENT_TYPE); - sk_MIME_HEADER_pop_free(headers, mime_hdr_free); - return 0; - } - if (strcmp (hdr->value, "text/plain")) { - PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_INVALID_MIME_TYPE); - ERR_add_error_data(2, "type: ", hdr->value); - sk_MIME_HEADER_pop_free(headers, mime_hdr_free); - return 0; - } - sk_MIME_HEADER_pop_free(headers, mime_hdr_free); - while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0) - BIO_write(out, iobuf, len); - return 1; -} - /* Split a multipart/XXX message body into component parts: result is * canonical parts in a STACK of bios */ diff --git a/lib/libcrypto/pkcs7/pk7_smime.c b/lib/libcrypto/pkcs7/pk7_smime.c index 99a0d63f38f..5c6b0fe24bc 100644 --- a/lib/libcrypto/pkcs7/pk7_smime.c +++ b/lib/libcrypto/pkcs7/pk7_smime.c @@ -1,9 +1,9 @@ /* pk7_smime.c */ /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL - * project 1999. + * project. */ /* ==================================================================== - * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -66,10 +66,10 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags) { - PKCS7 *p7; + PKCS7 *p7 = NULL; PKCS7_SIGNER_INFO *si; - BIO *p7bio; - STACK_OF(X509_ALGOR) *smcap; + BIO *p7bio = NULL; + STACK_OF(X509_ALGOR) *smcap = NULL; int i; if(!X509_check_private_key(signcert, pkey)) { @@ -82,66 +82,87 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, return NULL; } - PKCS7_set_type(p7, NID_pkcs7_signed); + if (!PKCS7_set_type(p7, NID_pkcs7_signed)) + goto err; - PKCS7_content_new(p7, NID_pkcs7_data); + if (!PKCS7_content_new(p7, NID_pkcs7_data)) + goto err; - if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) { + if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) { PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR); - return NULL; + goto err; } if(!(flags & PKCS7_NOCERTS)) { - PKCS7_add_certificate(p7, signcert); + if (!PKCS7_add_certificate(p7, signcert)) + goto err; if(certs) for(i = 0; i < sk_X509_num(certs); i++) - PKCS7_add_certificate(p7, sk_X509_value(certs, i)); - } - - if(!(p7bio = PKCS7_dataInit(p7, NULL))) { - PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); - return NULL; + if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i))) + goto err; } - - SMIME_crlf_copy(data, p7bio, flags); - if(!(flags & PKCS7_NOATTR)) { - PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, - V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)); + if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, + V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data))) + goto err; /* Add SMIMECapabilities */ if(!(flags & PKCS7_NOSMIMECAP)) { if(!(smcap = sk_X509_ALGOR_new_null())) { PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); - return NULL; + goto err; } #ifndef OPENSSL_NO_DES - PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1); + if (!PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1)) + goto err; #endif #ifndef OPENSSL_NO_RC2 - PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128); - PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64); + if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128)) + goto err; + if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64)) + goto err; #endif #ifndef OPENSSL_NO_DES - PKCS7_simple_smimecap (smcap, NID_des_cbc, -1); + if (!PKCS7_simple_smimecap (smcap, NID_des_cbc, -1)) + goto err; #endif #ifndef OPENSSL_NO_RC2 - PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40); + if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40)) + goto err; #endif - PKCS7_add_attrib_smimecap (si, smcap); + if (!PKCS7_add_attrib_smimecap (si, smcap)) + goto err; sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + smcap = NULL; } } if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1); - if (!PKCS7_dataFinal(p7,p7bio)) { + if (flags & PKCS7_STREAM) + return p7; + + + if (!(p7bio = PKCS7_dataInit(p7, NULL))) { + PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE); + goto err; + } + + SMIME_crlf_copy(data, p7bio, flags); + + + if (!PKCS7_dataFinal(p7,p7bio)) { PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_DATASIGN); - return NULL; + goto err; } - BIO_free_all(p7bio); + BIO_free_all(p7bio); return p7; +err: + sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + BIO_free_all(p7bio); + PKCS7_free(p7); + return NULL; } int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, @@ -215,6 +236,8 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, sk_X509_free(signers); return 0; } + if (!(flags & PKCS7_NOCRL)) + X509_STORE_CTX_set0_crls(&cert_ctx, p7->d.sign->crl); i = X509_verify_cert(&cert_ctx); if (i <= 0) j = X509_STORE_CTX_get_error(&cert_ctx); X509_STORE_CTX_cleanup(&cert_ctx); @@ -251,7 +274,8 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, tmpin = indata; - p7bio=PKCS7_dataInit(p7,tmpin); + if (!(p7bio=PKCS7_dataInit(p7,tmpin))) + goto err; if(flags & PKCS7_TEXT) { if(!(tmpout = BIO_new(BIO_s_mem()))) { @@ -330,7 +354,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) if(sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) { PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_NO_SIGNERS); - return 0; + return NULL; } if(!(signers = sk_X509_new_null())) { @@ -353,10 +377,13 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) if (!signer) { PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND); sk_X509_free(signers); - return 0; + return NULL; } - sk_X509_push(signers, signer); + if (!sk_X509_push(signers, signer)) { + sk_X509_free(signers); + return NULL; + } } return signers; } @@ -376,7 +403,8 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, return NULL; } - PKCS7_set_type(p7, NID_pkcs7_enveloped); + if (!PKCS7_set_type(p7, NID_pkcs7_enveloped)) + goto err; if(!PKCS7_set_cipher(p7, cipher)) { PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_ERROR_SETTING_CIPHER); goto err; @@ -398,7 +426,7 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, SMIME_crlf_copy(in, p7bio, flags); - BIO_flush(p7bio); + (void)BIO_flush(p7bio); if (!PKCS7_dataFinal(p7,p7bio)) { PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_PKCS7_DATAFINAL_ERROR); @@ -410,7 +438,7 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, err: - BIO_free(p7bio); + BIO_free_all(p7bio); PKCS7_free(p7); return NULL; @@ -432,7 +460,7 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) return 0; } - if(!X509_check_private_key(cert, pkey)) { + if(cert && !X509_check_private_key(cert, pkey)) { PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return 0; @@ -448,10 +476,13 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) /* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */ if(!(tmpbuf = BIO_new(BIO_f_buffer()))) { PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE); + BIO_free_all(tmpmem); return 0; } if(!(bread = BIO_push(tmpbuf, tmpmem))) { PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE); + BIO_free_all(tmpbuf); + BIO_free_all(tmpmem); return 0; } ret = SMIME_text(bread, data); diff --git a/lib/libcrypto/pkcs7/pkcs7.h b/lib/libcrypto/pkcs7/pkcs7.h index 15372e18f8c..cc092d262dc 100644 --- a/lib/libcrypto/pkcs7/pkcs7.h +++ b/lib/libcrypto/pkcs7/pkcs7.h @@ -233,6 +233,8 @@ DECLARE_PKCS12_STACK_OF(PKCS7) (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped) #define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data) +#define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest) + #define PKCS7_set_detached(p,v) \ PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL) #define PKCS7_get_detached(p) \ @@ -262,6 +264,8 @@ DECLARE_PKCS12_STACK_OF(PKCS7) #define PKCS7_NOSMIMECAP 0x200 #define PKCS7_NOOLDMIMETYPE 0x400 #define PKCS7_CRLFEOL 0x800 +#define PKCS7_STREAM 0x1000 +#define PKCS7_NOCRL 0x2000 /* Flags: for compatibility with older code */ @@ -302,10 +306,12 @@ DECLARE_ASN1_FUNCTIONS(PKCS7) DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN) DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY) +DECLARE_ASN1_NDEF_FUNCTION(PKCS7) long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg); int PKCS7_set_type(PKCS7 *p7, int type); +int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other); int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data); int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, const EVP_MD *dgst); @@ -326,6 +332,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert); PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, const EVP_MD *dgst); X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md); STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7); PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509); @@ -381,16 +388,20 @@ void ERR_load_PKCS7_strings(void); #define PKCS7_F_PKCS7_ADD_CRL 101 #define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102 #define PKCS7_F_PKCS7_ADD_SIGNER 103 +#define PKCS7_F_PKCS7_BIO_ADD_DIGEST 125 #define PKCS7_F_PKCS7_CTRL 104 #define PKCS7_F_PKCS7_DATADECODE 112 +#define PKCS7_F_PKCS7_DATAFINAL 128 #define PKCS7_F_PKCS7_DATAINIT 105 #define PKCS7_F_PKCS7_DATASIGN 106 #define PKCS7_F_PKCS7_DATAVERIFY 107 #define PKCS7_F_PKCS7_DECRYPT 114 #define PKCS7_F_PKCS7_ENCRYPT 115 +#define PKCS7_F_PKCS7_FIND_DIGEST 127 #define PKCS7_F_PKCS7_GET0_SIGNERS 124 #define PKCS7_F_PKCS7_SET_CIPHER 108 #define PKCS7_F_PKCS7_SET_CONTENT 109 +#define PKCS7_F_PKCS7_SET_DIGEST 126 #define PKCS7_F_PKCS7_SET_TYPE 110 #define PKCS7_F_PKCS7_SIGN 116 #define PKCS7_F_PKCS7_SIGNATUREVERIFY 113 @@ -421,13 +432,15 @@ void ERR_load_PKCS7_strings(void); #define PKCS7_R_NO_MULTIPART_BODY_FAILURE 136 #define PKCS7_R_NO_MULTIPART_BOUNDARY 137 #define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE 115 +#define PKCS7_R_NO_RECIPIENT_MATCHES_KEY 146 #define PKCS7_R_NO_SIGNATURES_ON_DATA 123 #define PKCS7_R_NO_SIGNERS 142 #define PKCS7_R_NO_SIG_CONTENT_TYPE 138 #define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 104 #define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR 124 +#define PKCS7_R_PKCS7_DATAFINAL 126 #define PKCS7_R_PKCS7_DATAFINAL_ERROR 125 -#define PKCS7_R_PKCS7_DATASIGN 126 +#define PKCS7_R_PKCS7_DATASIGN 145 #define PKCS7_R_PKCS7_PARSE_ERROR 139 #define PKCS7_R_PKCS7_SIG_PARSE_ERROR 140 #define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 127 diff --git a/lib/libcrypto/pkcs7/pkcs7err.c b/lib/libcrypto/pkcs7/pkcs7err.c index 19894c80a45..c0e3d4cd333 100644 --- a/lib/libcrypto/pkcs7/pkcs7err.c +++ b/lib/libcrypto/pkcs7/pkcs7err.c @@ -77,16 +77,20 @@ static ERR_STRING_DATA PKCS7_str_functs[]= {ERR_FUNC(PKCS7_F_PKCS7_ADD_CRL), "PKCS7_add_crl"}, {ERR_FUNC(PKCS7_F_PKCS7_ADD_RECIPIENT_INFO), "PKCS7_add_recipient_info"}, {ERR_FUNC(PKCS7_F_PKCS7_ADD_SIGNER), "PKCS7_add_signer"}, +{ERR_FUNC(PKCS7_F_PKCS7_BIO_ADD_DIGEST), "PKCS7_BIO_ADD_DIGEST"}, {ERR_FUNC(PKCS7_F_PKCS7_CTRL), "PKCS7_ctrl"}, {ERR_FUNC(PKCS7_F_PKCS7_DATADECODE), "PKCS7_dataDecode"}, +{ERR_FUNC(PKCS7_F_PKCS7_DATAFINAL), "PKCS7_dataFinal"}, {ERR_FUNC(PKCS7_F_PKCS7_DATAINIT), "PKCS7_dataInit"}, {ERR_FUNC(PKCS7_F_PKCS7_DATASIGN), "PKCS7_DATASIGN"}, {ERR_FUNC(PKCS7_F_PKCS7_DATAVERIFY), "PKCS7_dataVerify"}, {ERR_FUNC(PKCS7_F_PKCS7_DECRYPT), "PKCS7_decrypt"}, {ERR_FUNC(PKCS7_F_PKCS7_ENCRYPT), "PKCS7_encrypt"}, +{ERR_FUNC(PKCS7_F_PKCS7_FIND_DIGEST), "PKCS7_FIND_DIGEST"}, {ERR_FUNC(PKCS7_F_PKCS7_GET0_SIGNERS), "PKCS7_get0_signers"}, {ERR_FUNC(PKCS7_F_PKCS7_SET_CIPHER), "PKCS7_set_cipher"}, {ERR_FUNC(PKCS7_F_PKCS7_SET_CONTENT), "PKCS7_set_content"}, +{ERR_FUNC(PKCS7_F_PKCS7_SET_DIGEST), "PKCS7_set_digest"}, {ERR_FUNC(PKCS7_F_PKCS7_SET_TYPE), "PKCS7_set_type"}, {ERR_FUNC(PKCS7_F_PKCS7_SIGN), "PKCS7_sign"}, {ERR_FUNC(PKCS7_F_PKCS7_SIGNATUREVERIFY), "PKCS7_signatureVerify"}, @@ -120,11 +124,13 @@ static ERR_STRING_DATA PKCS7_str_reasons[]= {ERR_REASON(PKCS7_R_NO_MULTIPART_BODY_FAILURE),"no multipart body failure"}, {ERR_REASON(PKCS7_R_NO_MULTIPART_BOUNDARY),"no multipart boundary"}, {ERR_REASON(PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE),"no recipient matches certificate"}, +{ERR_REASON(PKCS7_R_NO_RECIPIENT_MATCHES_KEY),"no recipient matches key"}, {ERR_REASON(PKCS7_R_NO_SIGNATURES_ON_DATA),"no signatures on data"}, {ERR_REASON(PKCS7_R_NO_SIGNERS) ,"no signers"}, {ERR_REASON(PKCS7_R_NO_SIG_CONTENT_TYPE) ,"no sig content type"}, {ERR_REASON(PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE),"operation not supported on this type"}, {ERR_REASON(PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR),"pkcs7 add signature error"}, +{ERR_REASON(PKCS7_R_PKCS7_DATAFINAL) ,"pkcs7 datafinal"}, {ERR_REASON(PKCS7_R_PKCS7_DATAFINAL_ERROR),"pkcs7 datafinal error"}, {ERR_REASON(PKCS7_R_PKCS7_DATASIGN) ,"pkcs7 datasign"}, {ERR_REASON(PKCS7_R_PKCS7_PARSE_ERROR) ,"pkcs7 parse error"}, @@ -150,15 +156,12 @@ static ERR_STRING_DATA PKCS7_str_reasons[]= void ERR_load_PKCS7_strings(void) { - static int init=1; +#ifndef OPENSSL_NO_ERR - if (init) + if (ERR_func_error_string(PKCS7_str_functs[0].error) == NULL) { - init=0; -#ifndef OPENSSL_NO_ERR ERR_load_strings(0,PKCS7_str_functs); ERR_load_strings(0,PKCS7_str_reasons); -#endif - } +#endif } |