From: Dr. Stephen Henson Date: Sat, 15 Mar 2008 23:21:33 +0000 (+0000) Subject: Initial support for enveloped data decrypt. Extent runex.pl to cover these X-Git-Tag: OpenSSL_0_9_8k^2~526 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=4f1aa191b33f0bbda29c3289d50fee2991b77df0 Initial support for enveloped data decrypt. Extent runex.pl to cover these examples. All RFC4134 examples can not be processed. --- diff --git a/apps/cms.c b/apps/cms.c index 29e43999e2..b757908070 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -814,7 +814,7 @@ int MAIN(int argc, char **argv) ret = 4; if (operation == SMIME_DECRYPT) { - if (!CMS_decrypt(cms, key, recip, out, flags)) + if (!CMS_decrypt(cms, key, recip, indata, out, flags)) { BIO_printf(bio_err, "Error decrypting CMS structure\n"); goto end; diff --git a/crypto/cms/cms.h b/crypto/cms/cms.h index c9801cf293..41f0e8687d 100644 --- a/crypto/cms/cms.h +++ b/crypto/cms/cms.h @@ -70,6 +70,7 @@ typedef struct CMS_ContentInfo_st CMS_ContentInfo; typedef struct CMS_SignerInfo_st CMS_SignerInfo; typedef struct CMS_CertificateChoices CMS_CertificateChoices; typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice; +typedef struct CMS_RecipientInfo_st CMS_RecipientInfo; DECLARE_STACK_OF(CMS_SignerInfo) DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo) @@ -78,6 +79,12 @@ DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo) #define CMS_SIGNERINFO_ISSUER_SERIAL 0 #define CMS_SIGNERINFO_KEYIDENTIFIER 1 +#define CMS_RECIPINFO_TRANS 0 +#define CMS_RECIPINFO_AGREE 1 +#define CMS_RECIPINFO_KEK 2 +#define CMS_RECIPINFO_PASS 3 +#define CMS_RECIPINFO_OTHER 4 + /* S/MIME related flags */ #define CMS_TEXT 0x1 @@ -157,9 +164,23 @@ STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms); CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, unsigned int flags); -int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert, BIO *data, +int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert, + BIO *data, BIO *dcont, unsigned int flags); +STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms); +int CMS_RecipientInfo_type(CMS_RecipientInfo *ri); +int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert); +int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, + EVP_PKEY **pk, X509 **recip, + X509_ALGOR **palg); +int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno); + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, + EVP_PKEY *pkey); + int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, unsigned int flags); CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags); @@ -249,6 +270,7 @@ void ERR_load_CMS_strings(void); /* Error codes for the CMS functions. */ /* Function codes. */ +#define CMS_F_CHECK_CONTENT 151 #define CMS_F_CMS_ADD1_RECIPIENT_CERT 99 #define CMS_F_CMS_ADD1_SIGNER 100 #define CMS_F_CMS_ADD1_SIGNINGTIME 101 @@ -262,6 +284,7 @@ void ERR_load_CMS_strings(void); #define CMS_F_CMS_DATA 107 #define CMS_F_CMS_DATAFINAL 108 #define CMS_F_CMS_DATAINIT 109 +#define CMS_F_CMS_DECRYPT 152 #define CMS_F_CMS_DECRYPTEDCONTENT_DECRYPT_BIO 145 #define CMS_F_CMS_DECRYPTEDCONTENT_ENCRYPT_BIO 143 #define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 110 @@ -285,6 +308,7 @@ void ERR_load_CMS_strings(void); #define CMS_F_CMS_GET0_ENVELOPED 119 #define CMS_F_CMS_GET0_REVOCATION_CHOICES 120 #define CMS_F_CMS_GET0_SIGNED 121 +#define CMS_F_CMS_RECIPIENTINFO_DECRYPT 150 #define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 122 #define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 123 #define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 124 @@ -307,6 +331,7 @@ void ERR_load_CMS_strings(void); #define CMS_R_CIPHER_INITIALISATION_ERROR 138 #define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR 139 #define CMS_R_CMS_DATAFINAL_ERROR 101 +#define CMS_R_CMS_LIB 145 #define CMS_R_CONTENT_NOT_FOUND 102 #define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA 103 #define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA 104 @@ -328,6 +353,7 @@ void ERR_load_CMS_strings(void); #define CMS_R_NO_DEFAULT_DIGEST 117 #define CMS_R_NO_DIGEST_SET 118 #define CMS_R_NO_MATCHING_DIGEST 119 +#define CMS_R_NO_MATCHING_RECIPIENT 147 #define CMS_R_NO_PRIVATE_KEY 120 #define CMS_R_NO_PUBLIC_KEY 121 #define CMS_R_NO_SIGNERS 122 @@ -340,6 +366,7 @@ void ERR_load_CMS_strings(void); #define CMS_R_TYPE_NOT_DATA 129 #define CMS_R_TYPE_NOT_DIGESTED_DATA 130 #define CMS_R_TYPE_NOT_ENCRYPTED_DATA 142 +#define CMS_R_TYPE_NOT_ENVELOPED_DATA 146 #define CMS_R_UNABLE_TO_FINALIZE_CONTEXT 131 #define CMS_R_UNKNOWN_CIPHER 141 #define CMS_R_UNKNOWN_DIGEST_ALGORIHM 132 diff --git a/crypto/cms/cms_dd.c b/crypto/cms/cms_dd.c index ec7689d001..a927caad8e 100644 --- a/crypto/cms/cms_dd.c +++ b/crypto/cms/cms_dd.c @@ -98,8 +98,6 @@ CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md) BIO *cms_DigestedData_init_bio(CMS_ContentInfo *cms) { CMS_DigestedData *dd; - if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_digest) - return NULL; dd = cms->d.digestedData; return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm); } diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c index fbf87b6735..a99ce1b5f2 100644 --- a/crypto/cms/cms_enc.c +++ b/crypto/cms/cms_enc.c @@ -227,13 +227,8 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms) { - CMS_EncryptedContentInfo *ec; - if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) - { - CMSerr(CMS_F_CMS_ENCRYPTEDDATA_INIT_BIO, - CMS_R_NOT_ENCRYPTED_DATA); - return NULL; - } - ec = cms->d.encryptedData->encryptedContentInfo; - return cms_EncryptedContent_init_bio(ec); + CMS_EncryptedData *enc = cms->d.encryptedData; + if (enc->unprotectedAttrs) + enc->version = 2; + return cms_EncryptedContent_init_bio(enc->encryptedContentInfo); } diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index 3a5991e016..39ebe5a0f1 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -101,6 +101,20 @@ static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms) return cms_get0_enveloped(cms); } +STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms) + { + CMS_EnvelopedData *env; + env = cms_enveloped_data_init(cms); + if (!env) + return NULL; + return env->recipientInfos; + } + +int CMS_RecipientInfo_type(CMS_RecipientInfo *ri) + { + return ri->type; + } + /* Add a recipient certificate. For now only handle key transport. * If we ever handle key agreement will need updating. */ @@ -229,6 +243,7 @@ int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, CMS_R_NOT_KEY_TRANSPORT); return 0; } + ktri = ri->d.ktri; return cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer, sno); @@ -236,13 +251,86 @@ int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert) { - CMS_KeyTransRecipientInfo *ktri; if (ri->type != CMS_RECIPINFO_TRANS) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP, CMS_R_NOT_KEY_TRANSPORT); + return -2; + } + + return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert); + } + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, + EVP_PKEY *pkey) + { + CMS_KeyTransRecipientInfo *ktri; + EVP_PKEY_CTX *pctx = NULL; + unsigned char *ek = NULL; + size_t eklen; + + int ret = 0; + + if (ri->type != CMS_RECIPINFO_TRANS) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, + CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + ktri = ri->d.ktri; + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pctx) return 0; + + if (EVP_PKEY_decrypt_init(pctx) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, + EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, CMS_R_CTRL_ERROR); + goto err; } - return cms_SignerIdentifier_cert_cmp(ktri->rid, cert); + if (EVP_PKEY_decrypt(pctx, NULL, &eklen, + ktri->encryptedKey->data, + ktri->encryptedKey->length) <= 0) + goto err; + + ek = OPENSSL_malloc(eklen); + + if (ek == NULL) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_decrypt(pctx, ek, &eklen, + ktri->encryptedKey->data, + ktri->encryptedKey->length) <= 0) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, CMS_R_CMS_LIB); + goto err; + } + + ret = 1; + + cms->d.envelopedData->encryptedContentInfo->key = ek; + cms->d.envelopedData->encryptedContentInfo->keylen = eklen; + + err: + if (pctx) + EVP_PKEY_CTX_free(pctx); + if (!ret && ek) + OPENSSL_free(ek); + + return ret; + } + +BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) + { + CMS_EncryptedContentInfo *ec; + ec = cms->d.envelopedData->encryptedContentInfo; + return cms_EncryptedContent_init_bio(ec); } diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index 0d142681b4..3baa40e525 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -70,6 +70,7 @@ static ERR_STRING_DATA CMS_str_functs[]= { +{ERR_FUNC(CMS_F_CHECK_CONTENT), "CHECK_CONTENT"}, {ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT), "CMS_ADD1_RECIPIENT_CERT"}, {ERR_FUNC(CMS_F_CMS_ADD1_SIGNER), "CMS_add1_signer"}, {ERR_FUNC(CMS_F_CMS_ADD1_SIGNINGTIME), "CMS_ADD1_SIGNINGTIME"}, @@ -83,6 +84,7 @@ static ERR_STRING_DATA CMS_str_functs[]= {ERR_FUNC(CMS_F_CMS_DATA), "CMS_data"}, {ERR_FUNC(CMS_F_CMS_DATAFINAL), "CMS_dataFinal"}, {ERR_FUNC(CMS_F_CMS_DATAINIT), "CMS_dataInit"}, +{ERR_FUNC(CMS_F_CMS_DECRYPT), "CMS_decrypt"}, {ERR_FUNC(CMS_F_CMS_DECRYPTEDCONTENT_DECRYPT_BIO), "CMS_DECRYPTEDCONTENT_DECRYPT_BIO"}, {ERR_FUNC(CMS_F_CMS_DECRYPTEDCONTENT_ENCRYPT_BIO), "CMS_DECRYPTEDCONTENT_ENCRYPT_BIO"}, {ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX), "CMS_DIGESTALGORITHM_FIND_CTX"}, @@ -106,9 +108,10 @@ static ERR_STRING_DATA CMS_str_functs[]= {ERR_FUNC(CMS_F_CMS_GET0_ENVELOPED), "CMS_GET0_ENVELOPED"}, {ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES), "CMS_GET0_REVOCATION_CHOICES"}, {ERR_FUNC(CMS_F_CMS_GET0_SIGNED), "CMS_GET0_SIGNED"}, -{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP), "CMS_RECIPIENTINFO_KTRI_CERT_CMP"}, -{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS), "CMS_RECIPIENTINFO_KTRI_GET0_ALGS"}, -{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID), "CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_DECRYPT), "CMS_RecipientInfo_decrypt"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP), "CMS_RecipientInfo_ktri_cert_cmp"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS), "CMS_RecipientInfo_ktri_get0_algs"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID), "CMS_RecipientInfo_ktri_get0_signer_id"}, {ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER), "CMS_SET1_SIGNERIDENTIFIER"}, {ERR_FUNC(CMS_F_CMS_SET_DETACHED), "CMS_set_detached"}, {ERR_FUNC(CMS_F_CMS_SIGN), "CMS_sign"}, @@ -131,6 +134,7 @@ static ERR_STRING_DATA CMS_str_reasons[]= {ERR_REASON(CMS_R_CIPHER_INITIALISATION_ERROR),"cipher initialisation error"}, {ERR_REASON(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR),"cipher parameter initialisation error"}, {ERR_REASON(CMS_R_CMS_DATAFINAL_ERROR) ,"cms datafinal error"}, +{ERR_REASON(CMS_R_CMS_LIB) ,"cms lib"}, {ERR_REASON(CMS_R_CONTENT_NOT_FOUND) ,"content not found"}, {ERR_REASON(CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA),"content type not compressed data"}, {ERR_REASON(CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA),"content type not enveloped data"}, @@ -152,6 +156,7 @@ static ERR_STRING_DATA CMS_str_reasons[]= {ERR_REASON(CMS_R_NO_DEFAULT_DIGEST) ,"no default digest"}, {ERR_REASON(CMS_R_NO_DIGEST_SET) ,"no digest set"}, {ERR_REASON(CMS_R_NO_MATCHING_DIGEST) ,"no matching digest"}, +{ERR_REASON(CMS_R_NO_MATCHING_RECIPIENT) ,"no matching recipient"}, {ERR_REASON(CMS_R_NO_PRIVATE_KEY) ,"no private key"}, {ERR_REASON(CMS_R_NO_PUBLIC_KEY) ,"no public key"}, {ERR_REASON(CMS_R_NO_SIGNERS) ,"no signers"}, @@ -164,6 +169,7 @@ static ERR_STRING_DATA CMS_str_reasons[]= {ERR_REASON(CMS_R_TYPE_NOT_DATA) ,"type not data"}, {ERR_REASON(CMS_R_TYPE_NOT_DIGESTED_DATA),"type not digested data"}, {ERR_REASON(CMS_R_TYPE_NOT_ENCRYPTED_DATA),"type not encrypted data"}, +{ERR_REASON(CMS_R_TYPE_NOT_ENVELOPED_DATA),"type not enveloped data"}, {ERR_REASON(CMS_R_UNABLE_TO_FINALIZE_CONTEXT),"unable to finalize context"}, {ERR_REASON(CMS_R_UNKNOWN_CIPHER) ,"unknown cipher"}, {ERR_REASON(CMS_R_UNKNOWN_DIGEST_ALGORIHM),"unknown digest algorihm"}, diff --git a/crypto/cms/cms_lcl.h b/crypto/cms/cms_lcl.h index 06eeea7eeb..774ec103f7 100644 --- a/crypto/cms/cms_lcl.h +++ b/crypto/cms/cms_lcl.h @@ -91,7 +91,6 @@ typedef struct CMS_KEKIdentifier_st CMS_KEKIdentifier; typedef struct CMS_KEKRecipientInfo_st CMS_KEKRecipientInfo; typedef struct CMS_PasswordRecipientInfo_st CMS_PasswordRecipientInfo; typedef struct CMS_OtherRecipientInfo_st CMS_OtherRecipientInfo; -typedef struct CMS_RecipientInfo_st CMS_RecipientInfo; struct CMS_ContentInfo_st { @@ -187,12 +186,6 @@ struct CMS_RecipientInfo_st } d; }; -#define CMS_RECIPINFO_TRANS 0 -#define CMS_RECIPINFO_AGREE 1 -#define CMS_RECIPINFO_KEK 2 -#define CMS_RECIPINFO_PASS 3 -#define CMS_RECIPINFO_OTHER 4 - typedef CMS_SignerIdentifier CMS_RecipientIdentifier; struct CMS_KeyTransRecipientInfo_st @@ -416,9 +409,10 @@ BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm); int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, X509_ALGOR *mdalg); -BIO *cms_EncryptedContent_encrypt_bio(CMS_EncryptedContentInfo *ec); -BIO *cms_EncryptedContent_decrypt_bio(CMS_EncryptedContentInfo *ec); +BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec); BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms); + +BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms); #ifdef __cplusplus } diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c index e691ca3a7c..7b118b8d98 100644 --- a/crypto/cms/cms_lib.c +++ b/crypto/cms/cms_lib.c @@ -137,6 +137,10 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) cmsbio = cms_EncryptedData_init_bio(cms); break; + case NID_pkcs7_enveloped: + cmsbio = cms_EnvelopedData_init_bio(cms); + break; + default: CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE); return NULL; diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index 52860975f6..dc8e896e71 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -798,9 +798,9 @@ BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms) CMS_SignedData *sd; BIO *chain = NULL; sd = cms_get0_signed(cms); - cms_sd_set_version(sd); if (!sd) return NULL; + cms_sd_set_version(sd); for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { X509_ALGOR *digestAlgorithm; diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index d1a16808e9..7a2498d735 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -113,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; @@ -156,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) @@ -209,16 +213,8 @@ 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; @@ -304,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 */ @@ -470,7 +459,7 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, return NULL; } -/* Placeholders for now... */ +/* Placeholder for now... */ CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, unsigned int flags) @@ -478,10 +467,50 @@ CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in, 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; + STACK_OF(CMS_RecipientInfo) *ris; + CMS_RecipientInfo *ri; + 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; + 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 (cert) + { + if (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0) + { + if (CMS_RecipientInfo_decrypt(cms, ri, pk) <=0) + return 0; + else + break; + } + } + } + + 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) @@ -528,15 +557,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) diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h index 898aafffae..94a166630c 100644 --- a/crypto/rsa/rsa.h +++ b/crypto/rsa/rsa.h @@ -481,6 +481,7 @@ void ERR_load_RSA_strings(void); #define RSA_R_NULL_BEFORE_BLOCK_MISSING 113 #define RSA_R_N_DOES_NOT_EQUAL_P_Q 127 #define RSA_R_OAEP_DECODING_ERROR 121 +#define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148 #define RSA_R_PADDING_CHECK_FAILED 114 #define RSA_R_P_NOT_PRIME 128 #define RSA_R_Q_NOT_PRIME 129 diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 39fa9ec104..e705f16cb9 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -267,38 +267,29 @@ static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) { + X509_ALGOR *alg = NULL; switch (op) { case ASN1_PKEY_CTRL_PKCS7_SIGN: if (arg1 == 0) - { - X509_ALGOR *alg; PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, NULL, &alg); - X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), - V_ASN1_NULL, 0); - } - return 1; + break; case ASN1_PKEY_CTRL_PKCS7_ENCRYPT: if (arg1 == 0) - { - X509_ALGOR *alg; PKCS7_RECIP_INFO_get0_alg(arg2, &alg); - X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), - V_ASN1_NULL, 0); - } - return 1; + break; #ifndef OPENSSL_NO_CMS case ASN1_PKEY_CTRL_CMS_SIGN: if (arg1 == 0) - { - X509_ALGOR *alg; CMS_SignerInfo_get0_algs(arg2, NULL, NULL, NULL, &alg); - X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), - V_ASN1_NULL, 0); - } - return 1; + break; + + case ASN1_PKEY_CTRL_CMS_ENVELOPE: + if (arg1 == 0) + CMS_RecipientInfo_ktri_get0_algs(arg2, NULL, NULL, &alg); + break; #endif case ASN1_PKEY_CTRL_DEFAULT_MD_NID: @@ -310,6 +301,12 @@ static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) } + if (alg) + X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), + V_ASN1_NULL, 0); + + return 1; + } diff --git a/crypto/rsa/rsa_err.c b/crypto/rsa/rsa_err.c index b7ac4d2c21..0577fbb1ea 100644 --- a/crypto/rsa/rsa_err.c +++ b/crypto/rsa/rsa_err.c @@ -1,6 +1,6 @@ /* crypto/rsa/rsa_err.c */ /* ==================================================================== - * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2007 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 @@ -159,6 +159,7 @@ static ERR_STRING_DATA RSA_str_reasons[]= {ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING),"null before block missing"}, {ERR_REASON(RSA_R_N_DOES_NOT_EQUAL_P_Q) ,"n does not equal p q"}, {ERR_REASON(RSA_R_OAEP_DECODING_ERROR) ,"oaep decoding error"}, +{ERR_REASON(RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE),"operation not supported for this keytype"}, {ERR_REASON(RSA_R_PADDING_CHECK_FAILED) ,"padding check failed"}, {ERR_REASON(RSA_R_P_NOT_PRIME) ,"p not prime"}, {ERR_REASON(RSA_R_Q_NOT_PRIME) ,"q not prime"}, diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c index 0580bac9c9..7d6fef822a 100644 --- a/crypto/rsa/rsa_pmeth.c +++ b/crypto/rsa/rsa_pmeth.c @@ -443,7 +443,7 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return 1; case EVP_PKEY_CTRL_PEER_KEY: RSAerr(RSA_F_PKEY_RSA_CTRL, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return -2; default: