X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fcms%2Fcms_smime.c;h=c9be5a03e561bf39ef23f724754d2a645fa3264f;hp=a1ee0f24e2ec7232ec8787f7948b61a27a107ba6;hb=e4f0e40eac4ee00d8447741c76c9862a36b0e734;hpb=b820455c6e0aa38e7bdf121ec971f72e0eb097d0 diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index a1ee0f24e2..c9be5a03e5 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -77,12 +77,20 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) else tmpout = out; - /* Read all content through chain to determine content digests */ + /* Read all content through chain to process digest, decrypt etc */ for (;;) { i=BIO_read(in,buf,sizeof(buf)); if (i <= 0) + { + if (BIO_method_type(in) == BIO_TYPE_CIPHER) + { + if (!BIO_get_cipher_status(in)) + goto err; + } break; + } + if (tmpout) BIO_write(tmpout, buf, i); } @@ -105,6 +113,17 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) } +static int check_content(CMS_ContentInfo *cms) + { + ASN1_OCTET_STRING **pos = CMS_get0_content(cms); + if (!pos || !*pos) + { + CMSerr(CMS_F_CHECK_CONTENT, CMS_R_NO_CONTENT); + return 0; + } + return 1; + } + int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags) { BIO *cont; @@ -148,15 +167,8 @@ int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, return 0; } - if (!dcont) - { - ASN1_OCTET_STRING **pos = CMS_get0_content(cms); - if (!pos || !*pos) - { - CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_NO_CONTENT); - return 0; - } - } + if (!dcont && !check_content(cms)) + return 0; cont = CMS_dataInit(cms, dcont); if (!cont) @@ -201,27 +213,45 @@ int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, return 0; } - if (!dcont) - { - ASN1_OCTET_STRING **pos = CMS_get0_content(cms); - if (!pos || !*pos) - { - CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT, - CMS_R_NO_CONTENT); - return 0; - } - } + if (!dcont && !check_content(cms)) + return 0; + if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0) + return 0; cont = CMS_dataInit(cms, dcont); if (!cont) return 0; - r = CMS_EncryptedData_set1_key(cont, cms, key, keylen); - if (r) - r = cms_copy_content(out, cont, flags); + r = cms_copy_content(out, cont, flags); BIO_free_all(cont); return r; } +CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen, + unsigned int flags) + { + CMS_ContentInfo *cms; + if (!cipher) + { + CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER); + return NULL; + } + cms = CMS_ContentInfo_new(); + if (!cms) + return NULL; + if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen)) + return NULL; + + if(!(flags & CMS_DETACHED)) + CMS_set_detached(cms, 0); + + if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, in, flags)) + return cms; + + CMS_ContentInfo_free(cms); + return NULL; + } + static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, X509_STORE *store, STACK_OF(X509) *certs, @@ -270,15 +300,8 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, int i, scount = 0, ret = 0; BIO *cmsbio = NULL, *tmpin = NULL; - if (!dcont) - { - ASN1_OCTET_STRING **pos = CMS_get0_content(cms); - if (!pos || !*pos) - { - CMSerr(CMS_F_CMS_VERIFY, CMS_R_NO_CONTENT); - return 0; - } - } + if (!dcont && !check_content(cms)) + return 0; /* Attempt to find all signer certificates */ @@ -424,8 +447,8 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, data, flags)) return cms; - - return cms; + else + goto err; merr: CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE); @@ -436,18 +459,93 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, return NULL; } -/* Placeholders for now... */ - -CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in, +CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data, const EVP_CIPHER *cipher, unsigned int flags) { + CMS_ContentInfo *cms; + int i; + X509 *recip; + cms = CMS_EnvelopedData_create(cipher); + if (!cms) + goto merr; + for (i = 0; i < sk_X509_num(certs); i++) + { + recip = sk_X509_value(certs, i); + if (!CMS_add1_recipient_cert(cms, recip, flags)) + { + CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR); + goto err; + } + } + + if(!(flags & CMS_DETACHED)) + CMS_set_detached(cms, 0); + + if ((flags & (CMS_STREAM|CMS_PARTIAL)) || CMS_final(cms, data, flags)) + return cms; + else + goto err; + + merr: + CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE); + err: + if (cms) + CMS_ContentInfo_free(cms); return NULL; } -int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert, BIO *data, +int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, + BIO *dcont, BIO *out, unsigned int flags) { - return 0; + int i, r; + BIO *cont; + if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) + { + CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA); + return 0; + } + if (!dcont && !check_content(cms)) + return 0; + if (pk) + { + STACK_OF(CMS_RecipientInfo) *ris; + CMS_RecipientInfo *ri; + ris = CMS_get0_RecipientInfos(cms); + for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) + { + ri = sk_CMS_RecipientInfo_value(ris, i); + if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_TRANS) + continue; + /* If we have a cert try matching RecipientInfo + * otherwise try them all. + */ + if (!cert || + (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0)) + { + CMS_RecipientInfo_set0_pkey(ri, pk); + r = CMS_RecipientInfo_decrypt(cms, ri); + CMS_RecipientInfo_set0_pkey(ri, NULL); + if (r > 0) + break; + if (cert) + return 0; + ERR_clear_error(); + } + } + + if (i == sk_CMS_RecipientInfo_num(ris)) + { + CMSerr(CMS_F_CMS_DECRYPT, CMS_R_NO_MATCHING_RECIPIENT); + return 0; + } + } + cont = CMS_dataInit(cms, dcont); + if (!cont) + return 0; + r = cms_copy_content(out, cont, flags); + BIO_free_all(cont); + return r; } int CMS_final(CMS_ContentInfo *cms, BIO *data, int flags) @@ -494,15 +592,8 @@ int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, return 0; } - if (!dcont) - { - ASN1_OCTET_STRING **pos = CMS_get0_content(cms); - if (!pos || !*pos) - { - CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_NO_CONTENT); - return 0; - } - } + if (!dcont && !check_content(cms)) + return 0; cont = CMS_dataInit(cms, dcont); if (!cont)