libressl/0062-cms-specify-originator-key-for-KeyAgreement-decoding.patch

203 lines
6.4 KiB
Diff
Raw Normal View History

From 01486becb95b03f8e62ecdadd268d48ceb452fcc Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
Date: Wed, 8 Apr 2020 21:28:10 +0300
Subject: [PATCH 62/87] cms: specify originator key for KeyAgreement decoding
Some CMS files with KeyAgreement will specify Originator using
IssuerAndSerialNumber or using SubjectKeyIdentifier. To decrypt these
files one needs originator certificate. Allow specifying it via
-certfile command line option.
Sponsored by ROSA Linux
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
src/lib/libcrypto/Symbols.list | 1 +
src/lib/libcrypto/cms/cms.h | 2 ++
src/lib/libcrypto/cms/cms_asn1.c | 2 ++
src/lib/libcrypto/cms/cms_err.c | 1 +
src/lib/libcrypto/cms/cms_kari.c | 3 ++
src/lib/libcrypto/cms/cms_lcl.h | 2 ++
src/lib/libcrypto/cms/cms_smime.c | 53 +++++++++++++++++++++++++++++++
src/usr.bin/openssl/cms.c | 13 ++++++++
8 files changed, 77 insertions(+)
diff --git a/src/lib/libcrypto/Symbols.list b/src/lib/libcrypto/Symbols.list
index e5e7c435e..ec3506131 100644
--- a/src/lib/libcrypto/Symbols.list
+++ b/src/lib/libcrypto/Symbols.list
@@ -627,6 +627,7 @@ CMS_dataInit
CMS_data_create
CMS_decrypt
CMS_decrypt_set1_key
+CMS_decrypt_set1_originator
CMS_decrypt_set1_password
CMS_decrypt_set1_pkey
CMS_digest_create
diff --git a/src/lib/libcrypto/cms/cms.h b/src/lib/libcrypto/cms/cms.h
index fd2a5013a..0c62536ec 100644
--- a/src/lib/libcrypto/cms/cms.h
+++ b/src/lib/libcrypto/cms/cms.h
@@ -198,6 +198,7 @@ int CMS_decrypt_set1_key(CMS_ContentInfo *cms, unsigned char *key,
size_t keylen, const unsigned char *id, size_t idlen);
int CMS_decrypt_set1_password(CMS_ContentInfo *cms, unsigned char *pass,
ssize_t passlen);
+int CMS_decrypt_set1_originator(CMS_ContentInfo *cms, X509 *cert);
STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
@@ -525,6 +526,7 @@ int ERR_load_CMS_strings(void);
#define CMS_R_UNWRAP_FAILURE 180
#define CMS_R_VERIFICATION_FAILURE 158
#define CMS_R_WRAP_ERROR 159
+#define CMS_R_NO_MATCHING_ORIGINATOR 160
#ifdef __cplusplus
}
diff --git a/src/lib/libcrypto/cms/cms_asn1.c b/src/lib/libcrypto/cms/cms_asn1.c
index ac53fec15..b3c02c07f 100644
--- a/src/lib/libcrypto/cms/cms_asn1.c
+++ b/src/lib/libcrypto/cms/cms_asn1.c
@@ -713,9 +713,11 @@ cms_kari_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
return 0;
EVP_CIPHER_CTX_set_flags(kari->ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
kari->pctx = NULL;
+ kari->originator_pkey = NULL;
} else if (operation == ASN1_OP_FREE_POST) {
EVP_PKEY_CTX_free(kari->pctx);
EVP_CIPHER_CTX_free(kari->ctx);
+ EVP_PKEY_free(kari->originator_pkey);
}
return 1;
}
diff --git a/src/lib/libcrypto/cms/cms_err.c b/src/lib/libcrypto/cms/cms_err.c
index 9b2abaa03..6b6112d46 100644
--- a/src/lib/libcrypto/cms/cms_err.c
+++ b/src/lib/libcrypto/cms/cms_err.c
@@ -278,6 +278,7 @@ static ERR_STRING_DATA CMS_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_VERIFICATION_FAILURE),
"verification failure"},
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_WRAP_ERROR), "wrap error"},
+ {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_MATCHING_ORIGINATOR), "no matching originator"},
{0, NULL}
};
diff --git a/src/lib/libcrypto/cms/cms_kari.c b/src/lib/libcrypto/cms/cms_kari.c
index 0082a7525..145cc48dd 100644
--- a/src/lib/libcrypto/cms/cms_kari.c
+++ b/src/lib/libcrypto/cms/cms_kari.c
@@ -231,6 +231,9 @@ CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
pctx = EVP_PKEY_CTX_new(pk, NULL);
if (!pctx || !EVP_PKEY_derive_init(pctx))
goto err;
+ if (kari->originator_pkey)
+ if (EVP_PKEY_derive_set_peer(pctx, kari->originator_pkey) <= 0)
+ goto err;
kari->pctx = pctx;
return 1;
diff --git a/src/lib/libcrypto/cms/cms_lcl.h b/src/lib/libcrypto/cms/cms_lcl.h
index d400f5028..fa6c7660c 100644
--- a/src/lib/libcrypto/cms/cms_lcl.h
+++ b/src/lib/libcrypto/cms/cms_lcl.h
@@ -209,6 +209,8 @@ struct CMS_KeyAgreeRecipientInfo_st {
EVP_PKEY_CTX *pctx;
/* Cipher context for CEK wrapping */
EVP_CIPHER_CTX *ctx;
+ /* Originator's public key */
+ EVP_PKEY *originator_pkey;
};
struct CMS_OriginatorIdentifierOrKey_st {
diff --git a/src/lib/libcrypto/cms/cms_smime.c b/src/lib/libcrypto/cms/cms_smime.c
index d02ec5db1..1a067c149 100644
--- a/src/lib/libcrypto/cms/cms_smime.c
+++ b/src/lib/libcrypto/cms/cms_smime.c
@@ -672,6 +672,59 @@ cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, EVP_PKEY *pk,
return 0;
}
+static int
+cms_kari_set1_peer(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
+ X509 *cert)
+{
+ EVP_PKEY *pk = X509_get0_pubkey(cert);
+ if (!pk) {
+ CMSerror(CMS_R_ERROR_GETTING_PUBLIC_KEY);
+ return -1;
+ }
+
+ EVP_PKEY_up_ref(pk);
+ ri->d.kari->originator_pkey = pk;
+
+ return 1;
+}
+
+int
+CMS_decrypt_set1_originator(CMS_ContentInfo *cms, X509 *cert)
+{
+ STACK_OF(CMS_RecipientInfo) *ris;
+ CMS_RecipientInfo *ri;
+ int i, r, rv = 0;
+ int debug = 0;
+
+ ris = CMS_get0_RecipientInfos(cms);
+ if (ris)
+ debug = cms->d.envelopedData->encryptedContentInfo->debug;
+
+ for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
+ int ri_type;
+
+ ri = sk_CMS_RecipientInfo_value(ris, i);
+ ri_type = CMS_RecipientInfo_type(ri);
+ if (ri_type == CMS_RECIPINFO_AGREE && !CMS_RecipientInfo_kari_orig_id_cmp(ri, cert)) {
+ r = cms_kari_set1_peer(cms, ri, cert);
+ if (r > 0)
+ rv = 1;
+ if (r < 0)
+ return 0;
+ }
+ }
+ /* If not debugging always return success */
+ if (!debug) {
+ ERR_clear_error();
+ return 1;
+ }
+
+ if (!rv)
+ CMSerror(CMS_R_NO_MATCHING_ORIGINATOR);
+
+ return rv;
+}
+
int
CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
{
diff --git a/src/usr.bin/openssl/cms.c b/src/usr.bin/openssl/cms.c
index cad855673..ada4c7746 100644
--- a/src/usr.bin/openssl/cms.c
+++ b/src/usr.bin/openssl/cms.c
@@ -947,6 +947,19 @@ cms_main(int argc, char **argv)
if (flags & CMS_DEBUG_DECRYPT)
CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags);
+ if (other) {
+ int i;
+ X509 *x;
+
+ for (i = 0; i < sk_X509_num(other); i++) {
+ x = sk_X509_value(other, i);
+ if (!CMS_decrypt_set1_originator(cms, x)) {
+ BIO_puts(bio_err,"Error setting CMS originator certificate\n");
+ goto end;
+ }
+ }
+ }
+
if (secret_key) {
if (!CMS_decrypt_set1_key(cms, secret_key,
secret_keylen, secret_keyid, secret_keyidlen)) {
--
2.17.1