From a93a2217ebca9eb7b6190a142e71bbc2a7a0db97 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 8 Apr 2020 18:00:40 +0300 Subject: [PATCH 56/87] cms: allow keys support different RI types GOST keys support both KeyTransport and KeyAgreement. Instead of checking that RI type matches one of EVP_PKEY, check if EVP_PKEY supports this RI type. Signed-off-by: Dmitry Baryshkov --- src/lib/libcrypto/cms/cms_env.c | 20 ++++++++++++++++++++ src/lib/libcrypto/cms/cms_lcl.h | 1 + src/lib/libcrypto/cms/cms_smime.c | 14 ++++++-------- src/lib/libcrypto/evp/evp.h | 1 + 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/lib/libcrypto/cms/cms_env.c b/src/lib/libcrypto/cms/cms_env.c index f5e9280d4..17778a4fe 100644 --- a/src/lib/libcrypto/cms/cms_env.c +++ b/src/lib/libcrypto/cms/cms_env.c @@ -989,3 +989,23 @@ cms_pkey_get_ri_type(EVP_PKEY *pk) } return CMS_RECIPINFO_TRANS; } + +/* Some PKEYs (GOST) support different RecipientInfo types */ +int cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type) +{ + int supportedRiType; + + if (pk->ameth != NULL && pk->ameth->pkey_ctrl != NULL) { + int i, r; + + i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED, ri_type, &r); + if (i > 0) + return r; + } + + supportedRiType = cms_pkey_get_ri_type(pk); + if (supportedRiType < 0) + return 0; + + return (supportedRiType == ri_type); +} diff --git a/src/lib/libcrypto/cms/cms_lcl.h b/src/lib/libcrypto/cms/cms_lcl.h index fdfd12160..d400f5028 100644 --- a/src/lib/libcrypto/cms/cms_lcl.h +++ b/src/lib/libcrypto/cms/cms_lcl.h @@ -460,6 +460,7 @@ int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain); CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms); int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd); int cms_pkey_get_ri_type(EVP_PKEY *pk); +int cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type); /* KARI routines */ int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *pk, unsigned int flags); diff --git a/src/lib/libcrypto/cms/cms_smime.c b/src/lib/libcrypto/cms/cms_smime.c index 367810f40..d02ec5db1 100644 --- a/src/lib/libcrypto/cms/cms_smime.c +++ b/src/lib/libcrypto/cms/cms_smime.c @@ -677,21 +677,19 @@ CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert) { STACK_OF(CMS_RecipientInfo) *ris; CMS_RecipientInfo *ri; - int i, r, ri_type; + int i, r; int debug = 0, match_ri = 0; ris = CMS_get0_RecipientInfos(cms); if (ris) debug = cms->d.envelopedData->encryptedContentInfo->debug; - ri_type = cms_pkey_get_ri_type(pk); - if (ri_type == CMS_RECIPINFO_NONE) { - CMSerror(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); - return 0; - } for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) { + int ri_type; + ri = sk_CMS_RecipientInfo_value(ris, i); - if (CMS_RecipientInfo_type(ri) != ri_type) + ri_type = CMS_RecipientInfo_type(ri); + if (!cms_pkey_is_ri_type_supported(pk, ri_type)) continue; match_ri = 1; if (ri_type == CMS_RECIPINFO_AGREE) { @@ -734,7 +732,7 @@ CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert) } } /* If no cert, key transport and not debugging always return success */ - if (cert == NULL && ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) { + if (cert == NULL && cms_pkey_get_ri_type(pk) == CMS_RECIPINFO_TRANS && match_ri && !debug) { ERR_clear_error(); return 1; } diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h index 981351d76..48c7e7360 100644 --- a/src/lib/libcrypto/evp/evp.h +++ b/src/lib/libcrypto/evp/evp.h @@ -1036,6 +1036,7 @@ void EVP_PBE_cleanup(void); #define ASN1_PKEY_CTRL_CMS_SIGN 0x5 #define ASN1_PKEY_CTRL_CMS_ENVELOPE 0x7 #define ASN1_PKEY_CTRL_CMS_RI_TYPE 0x8 +#define ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED 0x9 int EVP_PKEY_asn1_get_count(void); const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx); -- 2.17.1