X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fpkcs7%2Fpk7_smime.c;h=a577141d3b0a143bbad03c12c8bb804c4581033e;hp=10acec9cde3c51bf58639a7e0c7ddfce156a4c00;hb=d0c36288341ca75328eeb4cc33bce6a7d3f65c51;hpb=60f20632e27d353e76e62b6746879e1d8e292e06 diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c index 10acec9cde..a577141d3b 100644 --- a/crypto/pkcs7/pk7_smime.c +++ b/crypto/pkcs7/pk7_smime.c @@ -1,5 +1,5 @@ /* pk7_smime.c */ -/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ /* ==================================================================== @@ -63,6 +63,8 @@ #include #include +static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si); + PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags) { @@ -96,6 +98,9 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, } } + if(flags & PKCS7_DETACHED) + PKCS7_set_detached(p7, 1); + if (flags & (PKCS7_STREAM|PKCS7_PARTIAL)) return p7; @@ -110,7 +115,7 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, int PKCS7_final(PKCS7 *p7, BIO *data, int flags) { BIO *p7bio; - int ret; + int ret = 0; if (!(p7bio = PKCS7_dataInit(p7, NULL))) { PKCS7err(PKCS7_F_PKCS7_FINAL,ERR_R_MALLOC_FAILURE); @@ -119,8 +124,8 @@ int PKCS7_final(PKCS7 *p7, BIO *data, int flags) SMIME_crlf_copy(data, p7bio, flags); - if(PKCS7_type_is_signed(p7) && (flags & PKCS7_DETACHED)) - PKCS7_set_detached(p7, 1); + (void)BIO_flush(p7bio); + if (!PKCS7_dataFinal(p7,p7bio)) { @@ -146,31 +151,33 @@ static int add_cipher_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) return 1; } +static int add_digest_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) + { + if (EVP_get_digestbynid(nid)) + return PKCS7_simple_smimecap(sk, nid, arg); + return 1; + } + PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, EVP_PKEY *pkey, const EVP_MD *md, int flags) { PKCS7_SIGNER_INFO *si = NULL; - int si_free = 1; STACK_OF(X509_ALGOR) *smcap = NULL; if(!X509_check_private_key(signcert, pkey)) { - PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER, + PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return NULL; } if (!(si = PKCS7_add_signature(p7,signcert,pkey, md))) { - PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER, + PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR); return NULL; } - /* si is now part of p7 so don't free it on error */ - - si_free = 0; - if(!(flags & PKCS7_NOCERTS)) { if (!PKCS7_add_certificate(p7, signcert)) @@ -179,19 +186,23 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, if(!(flags & PKCS7_NOATTR)) { - if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, - V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data))) + if (!PKCS7_add_attrib_content_type(si, NULL)) goto err; /* Add SMIMECapabilities */ if(!(flags & PKCS7_NOSMIMECAP)) { if(!(smcap = sk_X509_ALGOR_new_null())) { - PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER, + PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, ERR_R_MALLOC_FAILURE); goto err; } - if (!add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) + if (!add_cipher_smcap(smcap, NID_aes_256_cbc, -1) + || !add_digest_smcap(smcap, NID_id_GostR3411_94, -1) + || !add_cipher_smcap(smcap, NID_id_Gost28147_89, -1) + || !add_cipher_smcap(smcap, NID_aes_192_cbc, -1) + || !add_cipher_smcap(smcap, NID_aes_128_cbc, -1) + || !add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) || !add_cipher_smcap(smcap, NID_rc2_cbc, 128) || !add_cipher_smcap(smcap, NID_rc2_cbc, 64) || !add_cipher_smcap(smcap, NID_des_cbc, -1) @@ -199,17 +210,59 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, || !PKCS7_add_attrib_smimecap (si, smcap)) goto err; sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); + smcap = NULL; + } + if (flags & PKCS7_REUSE_DIGEST) + { + if (!pkcs7_copy_existing_digest(p7, si)) + goto err; + if (!(flags & PKCS7_PARTIAL) && + !PKCS7_SIGNER_INFO_sign(si)) + goto err; } } return si; err: if (smcap) sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); - if (si && si_free) - PKCS7_SIGNER_INFO_free(si); return NULL; } +/* Search for a digest matching SignerInfo digest type and if found + * copy across. + */ + +static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si) + { + int i; + STACK_OF(PKCS7_SIGNER_INFO) *sinfos; + PKCS7_SIGNER_INFO *sitmp; + ASN1_OCTET_STRING *osdig = NULL; + sinfos = PKCS7_get_signer_info(p7); + for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) + { + sitmp = sk_PKCS7_SIGNER_INFO_value(sinfos, i); + if (si == sitmp) + break; + if (sk_X509_ATTRIBUTE_num(sitmp->auth_attr) <= 0) + continue; + if (!OBJ_cmp(si->digest_alg->algorithm, + sitmp->digest_alg->algorithm)) + { + osdig = PKCS7_digest_from_attributes(sitmp->auth_attr); + break; + } + + } + + if (osdig) + return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length); + + PKCS7err(PKCS7_F_PKCS7_COPY_EXISTING_DIGEST, + PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND); + return 0; + } + int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, BIO *indata, BIO *out, int flags) { @@ -319,13 +372,15 @@ 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()))) { PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE); goto err; } + BIO_set_mem_eof_return(tmpout, 0); } else tmpout = out; /* We now have to 'read' from p7bio to calculate digests etc. */ @@ -424,7 +479,10 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) return 0; } - sk_X509_push(signers, signer); + if (!sk_X509_push(signers, signer)) { + sk_X509_free(signers); + return NULL; + } } return signers; } @@ -444,8 +502,9 @@ 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_cipher(p7, cipher)) { + 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; } @@ -459,12 +518,15 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, } } + if (flags & PKCS7_STREAM) + return p7; + if (PKCS7_final(p7, in, flags)) return p7; err: - BIO_free(p7bio); + BIO_free_all(p7bio); PKCS7_free(p7); return NULL; @@ -502,10 +564,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);