mirror of
https://abf.rosa.ru/djam/libressl.git
synced 2025-02-23 16:12:53 +00:00
203 lines
6.4 KiB
Diff
203 lines
6.4 KiB
Diff
![]() |
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
|
||
|
|