diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2008-03-18 01:00:38 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2008-03-18 01:00:38 +0000 |
commit | 6e3bc4f0730a3cb7d2d263153cb234da51637b38 (patch) | |
tree | 4014d7cad18d13c1483b6f5fd580c2deda17ccee /crypto | |
parent | c36e936b60abcc426b74135b9ce4fd2950725c68 (diff) |
More support for KEK RecipientInfo.
Generalise RecipientInfo and enveloped data handling so applications can
add their own key lookup routines as well as using the standard ones.
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/aes/Makefile | 4 | ||||
-rw-r--r-- | crypto/aes/aes.h | 7 | ||||
-rw-r--r-- | crypto/aes/aes_wrap.c | 8 | ||||
-rw-r--r-- | crypto/cms/cms.h | 14 | ||||
-rw-r--r-- | crypto/cms/cms_env.c | 269 | ||||
-rw-r--r-- | crypto/cms/cms_err.c | 10 | ||||
-rw-r--r-- | crypto/cms/cms_smime.c | 47 |
7 files changed, 295 insertions, 64 deletions
diff --git a/crypto/aes/Makefile b/crypto/aes/Makefile index 632fdb55bd..80dcc3251c 100644 --- a/crypto/aes/Makefile +++ b/crypto/aes/Makefile @@ -24,8 +24,8 @@ APPS= LIB=$(TOP)/libcrypto.a LIBSRC=aes_core.c aes_misc.c aes_ecb.c aes_cbc.c aes_cfb.c aes_ofb.c \ - aes_ctr.c aes_ige.c -LIBOBJ=aes_misc.o aes_ecb.o aes_cfb.o aes_ofb.o aes_ctr.o aes_ige.o \ + aes_ctr.c aes_ige.c aes_wrap.c +LIBOBJ=aes_misc.o aes_ecb.o aes_cfb.o aes_ofb.o aes_ctr.o aes_ige.o aes_wrap.o \ $(AES_ENC) SRC= $(LIBSRC) diff --git a/crypto/aes/aes.h b/crypto/aes/aes.h index 949a754a0f..51f91e6079 100644 --- a/crypto/aes/aes.h +++ b/crypto/aes/aes.h @@ -128,6 +128,13 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key2, const unsigned char *ivec, const int enc); +int AES_wrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); +int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); + #ifdef __cplusplus } diff --git a/crypto/aes/aes_wrap.c b/crypto/aes/aes_wrap.c index ba62b55a9f..9feacd65d8 100644 --- a/crypto/aes/aes_wrap.c +++ b/crypto/aes/aes_wrap.c @@ -55,6 +55,10 @@ #include <openssl/aes.h> #include <openssl/bio.h> +static const unsigned char default_iv[] = { + 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, +}; + int AES_wrap_key(AES_KEY *key, const unsigned char *iv, unsigned char *out, const unsigned char *in, unsigned int inlen) @@ -195,10 +199,6 @@ static const unsigned char key[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; -static const unsigned char default_iv[] = { - 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, -}; - static const unsigned char e1[] = { 0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47, 0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82, diff --git a/crypto/cms/cms.h b/crypto/cms/cms.h index b6c9792305..6061b8885e 100644 --- a/crypto/cms/cms.h +++ b/crypto/cms/cms.h @@ -172,6 +172,7 @@ int CMS_RecipientInfo_type(CMS_RecipientInfo *ri); CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher); CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags); +int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey); 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, @@ -180,8 +181,7 @@ 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_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, unsigned int flags); @@ -315,11 +315,16 @@ void ERR_load_CMS_strings(void); #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_KEKRI_DECRYPT 161 +#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 162 #define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 158 #define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 122 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 160 #define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 155 #define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 123 #define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 124 +#define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 163 +#define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 159 #define CMS_F_CMS_SET1_SIGNERIDENTIFIER 125 #define CMS_F_CMS_SET_DETACHED 126 #define CMS_F_CMS_SIGN 127 @@ -349,7 +354,9 @@ void ERR_load_CMS_strings(void); #define CMS_R_CTRL_FAILURE 108 #define CMS_R_ERROR_GETTING_PUBLIC_KEY 109 #define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 110 +#define CMS_R_ERROR_SETTING_KEY 155 #define CMS_R_ERROR_SETTING_RECIPIENTINFO 150 +#define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 156 #define CMS_R_INVALID_KEY_LENGTH 140 #define CMS_R_MD_BIO_INIT_ERROR 111 #define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 112 @@ -387,8 +394,11 @@ void ERR_load_CMS_strings(void); #define CMS_R_UNSUPPORTED_CONTENT_TYPE 135 #define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153 #define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 151 +#define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE 154 #define CMS_R_UNSUPPORTED_TYPE 136 +#define CMS_R_UNWRAP_ERROR 157 #define CMS_R_VERIFICATION_FAILURE 137 +#define CMS_R_WRAP_ERROR 158 #ifdef __cplusplus } diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index 5ac3e125dc..008524932d 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -58,6 +58,7 @@ #include <openssl/err.h> #include <openssl/cms.h> #include <openssl/rand.h> +#include <openssl/aes.h> #include "cms_lcl.h" #include "asn1_locl.h" @@ -266,6 +267,26 @@ int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, return 1; } +/* For now hard code AES key wrap info */ + +static int aes_wrap_keylen(int nid) + { + switch (nid) + { + case NID_id_aes128_wrap: + return 16; + + case NID_id_aes192_wrap: + return 24; + + case NID_id_aes256_wrap: + return 32; + + default: + return 0; + } + } + CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, unsigned char *key, size_t keylen, @@ -282,31 +303,18 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, if (!env) goto err; - /* For now hard code checks on nids */ - switch (nid) - { - case NID_id_aes128_wrap: - exp_keylen = 16; - break; + exp_keylen = aes_wrap_keylen(nid); - case NID_id_aes192_wrap: - exp_keylen = 24; - break; - - case NID_id_aes256_wrap: - exp_keylen = 32; - break; - - default: + if (!exp_keylen) + { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_UNSUPPORTED_KEK_ALGORITHM); goto err; } - if (exp_keylen && (keylen != exp_keylen)) + if (keylen != exp_keylen) { - CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, - CMS_R_INVALID_KEY_LENGTH); + CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH); goto err; } @@ -408,10 +416,43 @@ int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert) CMS_R_NOT_KEY_TRANSPORT); return -2; } - return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert); } +int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey) + { + if (ri->type != CMS_RECIPINFO_TRANS) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY, + CMS_R_NOT_KEY_TRANSPORT); + return 0; + } + ri->d.ktri->pkey = pkey; + return 1; + } + +int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, + unsigned char *key, size_t keylen) + { + CMS_KEKRecipientInfo *kekri; + int wrap_nid; + if (ri->type != CMS_RECIPINFO_KEK) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK); + return 0; + } + wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm); + if (aes_wrap_keylen(wrap_nid) != keylen) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, + CMS_R_INVALID_KEY_LENGTH); + return 0; + } + kekri->key = key; + kekri->keylen = keylen; + return 1; + } + /* Encrypt content key in key transport recipient info */ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, @@ -477,25 +518,23 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, } -int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, - EVP_PKEY *pkey) +static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) { - CMS_KeyTransRecipientInfo *ktri; + CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; EVP_PKEY_CTX *pctx = NULL; unsigned char *ek = NULL; size_t eklen; + int ret; - int ret = 0; - - if (ri->type != CMS_RECIPINFO_TRANS) + if (ktri->pkey == NULL) { - CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, - CMS_R_NOT_KEY_TRANSPORT); + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, + CMS_R_NO_PRIVATE_KEY); return 0; } - ktri = ri->d.ktri; - pctx = EVP_PKEY_CTX_new(pkey, NULL); + pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); if (!pctx) return 0; @@ -505,7 +544,7 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, 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); + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR); goto err; } @@ -518,7 +557,8 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, if (ek == NULL) { - CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, ERR_R_MALLOC_FAILURE); + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, + ERR_R_MALLOC_FAILURE); goto err; } @@ -526,7 +566,7 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, ktri->encryptedKey->data, ktri->encryptedKey->length) <= 0) { - CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, CMS_R_CMS_LIB); + CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); goto err; } @@ -544,6 +584,155 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, return ret; } + +/* Encrypt content key in KEK recipient info */ + +static int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) + { + CMS_EncryptedContentInfo *ec; + CMS_KEKRecipientInfo *kekri; + AES_KEY actx; + unsigned char *wkey = NULL; + int wkeylen; + int r = 0; + + ec = cms->d.envelopedData->encryptedContentInfo; + + kekri = ri->d.kekri; + + if (!kekri->key) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY); + return 0; + } + + if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, + CMS_R_ERROR_SETTING_KEY); + goto err; + } + + wkey = OPENSSL_malloc(ec->keylen + 8); + + if (!wkey) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, + ERR_R_MALLOC_FAILURE); + goto err; + } + + wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen); + + if (wkeylen <= 0) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR); + goto err; + } + + ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen); + + r = 1; + + err: + + if (!r && wkey) + OPENSSL_free(wkey); + OPENSSL_cleanse(&actx, sizeof(actx)); + + return r; + + } + +static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri) + { + CMS_EncryptedContentInfo *ec; + CMS_KEKRecipientInfo *kekri; + AES_KEY actx; + unsigned char *ukey = NULL; + int ukeylen; + int r = 0; + + ec = cms->d.envelopedData->encryptedContentInfo; + + kekri = ri->d.kekri; + + if (!kekri->key) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY); + return 0; + } + + /* If encrypted key length is invalid don't bother */ + + if (kekri->encryptedKey->length < 16) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_INVALID_ENCRYPTED_KEY_LENGTH); + goto err; + } + + if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_ERROR_SETTING_KEY); + goto err; + } + + ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8); + + if (!ukey) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + ERR_R_MALLOC_FAILURE); + goto err; + } + + ukeylen = AES_unwrap_key(&actx, NULL, ukey, + kekri->encryptedKey->data, + kekri->encryptedKey->length); + + if (ukeylen <= 0) + { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, + CMS_R_UNWRAP_ERROR); + goto err; + } + + ec->key = ukey; + ec->keylen = ukeylen; + + r = 1; + + err: + + if (!r && ukey) + OPENSSL_free(ukey); + OPENSSL_cleanse(&actx, sizeof(actx)); + + return r; + + } + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) + { + switch(ri->type) + { + case CMS_RECIPINFO_TRANS: + return cms_RecipientInfo_ktri_decrypt(cms, ri); + + case CMS_RECIPINFO_KEK: + return cms_RecipientInfo_kekri_decrypt(cms, ri); + + default: + CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT, + CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE); + return 0; + } + } + BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) { CMS_EncryptedContentInfo *ec; @@ -562,20 +751,28 @@ BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms) if (!ret || !ec->cipher) return ret; - rinfos = cms->d.envelopedData->recipientInfos; for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) { ri = sk_CMS_RecipientInfo_value(rinfos, i); - if (ri->type == CMS_RECIPINFO_TRANS) - r = cms_RecipientInfo_ktri_encrypt(cms, ri); - else + + switch (ri->type) { + case CMS_RECIPINFO_TRANS: + r = cms_RecipientInfo_ktri_encrypt(cms, ri); + break; + + case CMS_RECIPINFO_KEK: + r = cms_RecipientInfo_kekri_encrypt(cms, ri); + break; + + default: CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, CMS_R_UNSUPPORTED_RECIPIENT_TYPE); goto err; } + if (r <= 0) { CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO, diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index acc756adf1..f7df77ba90 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -113,11 +113,16 @@ static ERR_STRING_DATA CMS_str_functs[]= {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_DECRYPT), "CMS_RecipientInfo_decrypt"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT), "CMS_RECIPIENTINFO_KEKRI_DECRYPT"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT), "CMS_RECIPIENTINFO_KEKRI_ENCRYPT"}, {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID), "CMS_RECIPIENTINFO_KEKRI_GET0_ID"}, {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP), "CMS_RecipientInfo_ktri_cert_cmp"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT), "CMS_RECIPIENTINFO_KTRI_DECRYPT"}, {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT), "CMS_RECIPIENTINFO_KTRI_ENCRYPT"}, {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_SET0_KEY), "CMS_RECIPIENTINFO_SET0_KEY"}, +{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY), "CMS_RecipientInfo_set0_pkey"}, {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"}, @@ -150,7 +155,9 @@ static ERR_STRING_DATA CMS_str_reasons[]= {ERR_REASON(CMS_R_CTRL_FAILURE) ,"ctrl failure"}, {ERR_REASON(CMS_R_ERROR_GETTING_PUBLIC_KEY),"error getting public key"}, {ERR_REASON(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),"error reading messagedigest attribute"}, +{ERR_REASON(CMS_R_ERROR_SETTING_KEY) ,"error setting key"}, {ERR_REASON(CMS_R_ERROR_SETTING_RECIPIENTINFO),"error setting recipientinfo"}, +{ERR_REASON(CMS_R_INVALID_ENCRYPTED_KEY_LENGTH),"invalid encrypted key length"}, {ERR_REASON(CMS_R_INVALID_KEY_LENGTH) ,"invalid key length"}, {ERR_REASON(CMS_R_MD_BIO_INIT_ERROR) ,"md bio init error"}, {ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),"messagedigest attribute wrong length"}, @@ -188,8 +195,11 @@ static ERR_STRING_DATA CMS_str_reasons[]= {ERR_REASON(CMS_R_UNSUPPORTED_CONTENT_TYPE),"unsupported content type"}, {ERR_REASON(CMS_R_UNSUPPORTED_KEK_ALGORITHM),"unsupported kek algorithm"}, {ERR_REASON(CMS_R_UNSUPPORTED_RECIPIENT_TYPE),"unsupported recipient type"}, +{ERR_REASON(CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE),"unsupported recpientinfo type"}, {ERR_REASON(CMS_R_UNSUPPORTED_TYPE) ,"unsupported type"}, +{ERR_REASON(CMS_R_UNWRAP_ERROR) ,"unwrap error"}, {ERR_REASON(CMS_R_VERIFICATION_FAILURE) ,"verification failure"}, +{ERR_REASON(CMS_R_WRAP_ERROR) ,"wrap error"}, {0,NULL} }; diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index 3a813de246..dcc0e6ba10 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -498,8 +498,6 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, BIO *dcont, BIO *out, unsigned int flags) { - STACK_OF(CMS_RecipientInfo) *ris; - CMS_RecipientInfo *ri; int i, r; BIO *cont; if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) @@ -509,28 +507,37 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, } if (!dcont && !check_content(cms)) return 0; - ris = CMS_get0_RecipientInfos(cms); - for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) + if (pk) { - 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)) + STACK_OF(CMS_RecipientInfo) *ris; + CMS_RecipientInfo *ri; + ris = CMS_get0_RecipientInfos(cms); + for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) { - if (CMS_RecipientInfo_decrypt(cms, ri, pk) > 0) - break; - else if (cert) - return 0; + 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; + } } - } - if (i == sk_CMS_RecipientInfo_num(ris)) - { - CMSerr(CMS_F_CMS_DECRYPT, CMS_R_NO_MATCHING_RECIPIENT); - return 0; + 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) |