mirror of
https://abf.rosa.ru/djam/libressl.git
synced 2025-02-23 16:12:53 +00:00
278 lines
10 KiB
Diff
278 lines
10 KiB
Diff
![]() |
From 4f8119d9168bfe32b03d31673425423d466f365c Mon Sep 17 00:00:00 2001
|
||
|
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
||
|
Date: Thu, 9 Apr 2020 03:04:33 +0300
|
||
|
Subject: [PATCH 63/87] cms: support specifying originator certificate and key
|
||
|
during encryption
|
||
|
|
||
|
LibreSSL supports using ephemeral public key as Originator. Add support
|
||
|
for using other Originator types.
|
||
|
|
||
|
Sponsored by ROSA Linux
|
||
|
|
||
|
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
||
|
---
|
||
|
src/lib/libcrypto/cms/cms.h | 6 +++-
|
||
|
src/lib/libcrypto/cms/cms_env.c | 6 ++--
|
||
|
src/lib/libcrypto/cms/cms_kari.c | 45 +++++++++++++++++++++++--
|
||
|
src/lib/libcrypto/cms/cms_lcl.h | 3 +-
|
||
|
src/lib/libcrypto/cms/cms_smime.c | 3 +-
|
||
|
src/lib/libcrypto/ec/ec_ameth.c | 5 ++-
|
||
|
src/regress/lib/libcrypto/cms/cmstest.c | 2 +-
|
||
|
src/usr.bin/openssl/cms.c | 25 ++++++++++++--
|
||
|
8 files changed, 83 insertions(+), 12 deletions(-)
|
||
|
|
||
|
diff --git a/src/lib/libcrypto/cms/cms.h b/src/lib/libcrypto/cms/cms.h
|
||
|
index 0c62536ec..4084fd7da 100644
|
||
|
--- a/src/lib/libcrypto/cms/cms.h
|
||
|
+++ b/src/lib/libcrypto/cms/cms.h
|
||
|
@@ -125,6 +125,7 @@ int CMS_ContentInfo_print_ctx(BIO *out, CMS_ContentInfo *x, int indent, const AS
|
||
|
#define CMS_DEBUG_DECRYPT 0x20000
|
||
|
#define CMS_KEY_PARAM 0x40000
|
||
|
#define CMS_ASCIICRLF 0x80000
|
||
|
+#define CMS_USE_ORIGINATOR_KEYID 0x100000
|
||
|
|
||
|
const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms);
|
||
|
|
||
|
@@ -188,7 +189,9 @@ int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
|
||
|
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);
|
||
|
+ const EVP_CIPHER *cipher,
|
||
|
+ EVP_PKEY *originator_pkey, X509 *originator,
|
||
|
+ unsigned int flags);
|
||
|
|
||
|
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
|
||
|
BIO *dcont, BIO *out, unsigned int flags);
|
||
|
@@ -205,6 +208,7 @@ int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
|
||
|
EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri);
|
||
|
CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
|
||
|
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip,
|
||
|
+ EVP_PKEY *originator_pkey, X509 *originator,
|
||
|
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);
|
||
|
diff --git a/src/lib/libcrypto/cms/cms_env.c b/src/lib/libcrypto/cms/cms_env.c
|
||
|
index 17778a4fe..b51baf702 100644
|
||
|
--- a/src/lib/libcrypto/cms/cms_env.c
|
||
|
+++ b/src/lib/libcrypto/cms/cms_env.c
|
||
|
@@ -238,7 +238,9 @@ cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *pk,
|
||
|
*/
|
||
|
|
||
|
CMS_RecipientInfo *
|
||
|
-CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags)
|
||
|
+CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip,
|
||
|
+ EVP_PKEY *originator_pkey, X509 *originator,
|
||
|
+ unsigned int flags)
|
||
|
{
|
||
|
CMS_RecipientInfo *ri = NULL;
|
||
|
CMS_EnvelopedData *env;
|
||
|
@@ -267,7 +269,7 @@ CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags)
|
||
|
break;
|
||
|
|
||
|
case CMS_RECIPINFO_AGREE:
|
||
|
- if (!cms_RecipientInfo_kari_init(ri, recip, pk, flags))
|
||
|
+ if (!cms_RecipientInfo_kari_init(ri, recip, pk, originator, originator_pkey, flags))
|
||
|
goto err;
|
||
|
break;
|
||
|
|
||
|
diff --git a/src/lib/libcrypto/cms/cms_kari.c b/src/lib/libcrypto/cms/cms_kari.c
|
||
|
index 145cc48dd..5a6e4b820 100644
|
||
|
--- a/src/lib/libcrypto/cms/cms_kari.c
|
||
|
+++ b/src/lib/libcrypto/cms/cms_kari.c
|
||
|
@@ -362,10 +362,33 @@ cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari, EVP_PKEY *pk)
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
+/* Set the key from originator */
|
||
|
+static int
|
||
|
+cms_kari_set_originator_priv_key(CMS_KeyAgreeRecipientInfo *kari, EVP_PKEY *pk)
|
||
|
+{
|
||
|
+ EVP_PKEY_CTX *pctx = NULL;
|
||
|
+ int rv = 0;
|
||
|
+
|
||
|
+ pctx = EVP_PKEY_CTX_new(pk, NULL);
|
||
|
+ if (!pctx)
|
||
|
+ goto err;
|
||
|
+ if (EVP_PKEY_derive_init(pctx) <= 0)
|
||
|
+ goto err;
|
||
|
+ kari->pctx = pctx;
|
||
|
+ rv = 1;
|
||
|
+
|
||
|
+ err:
|
||
|
+ if (!rv)
|
||
|
+ EVP_PKEY_CTX_free(pctx);
|
||
|
+
|
||
|
+ return rv;
|
||
|
+}
|
||
|
+
|
||
|
/* Initialise a kari based on passed certificate and key */
|
||
|
|
||
|
int
|
||
|
cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *pk,
|
||
|
+ X509 *originator, EVP_PKEY *originator_pkey,
|
||
|
unsigned int flags)
|
||
|
{
|
||
|
CMS_KeyAgreeRecipientInfo *kari;
|
||
|
@@ -401,9 +424,25 @@ cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *pk,
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
- /* Create ephemeral key */
|
||
|
- if (!cms_kari_create_ephemeral_key(kari, pk))
|
||
|
- return 0;
|
||
|
+ if (originator_pkey == NULL && originator == NULL) {
|
||
|
+ /* Create ephemeral key */
|
||
|
+ if (!cms_kari_create_ephemeral_key(kari, pk))
|
||
|
+ return 0;
|
||
|
+ } else {
|
||
|
+ CMS_OriginatorIdentifierOrKey *oik = ri->d.kari->originator;
|
||
|
+
|
||
|
+ if (flags & CMS_USE_ORIGINATOR_KEYID) {
|
||
|
+ oik->type = CMS_OIK_KEYIDENTIFIER;
|
||
|
+ if (!cms_set1_keyid(&oik->d.subjectKeyIdentifier, originator))
|
||
|
+ return 0;
|
||
|
+ } else {
|
||
|
+ oik->type = CMS_OIK_ISSUER_SERIAL;
|
||
|
+ if (!cms_set1_ias(&oik->d.issuerAndSerialNumber, originator))
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ if (!cms_kari_set_originator_priv_key(kari, originator_pkey))
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
|
||
|
EVP_PKEY_up_ref(pk);
|
||
|
rek->pkey = pk;
|
||
|
diff --git a/src/lib/libcrypto/cms/cms_lcl.h b/src/lib/libcrypto/cms/cms_lcl.h
|
||
|
index fa6c7660c..e70c27e71 100644
|
||
|
--- a/src/lib/libcrypto/cms/cms_lcl.h
|
||
|
+++ b/src/lib/libcrypto/cms/cms_lcl.h
|
||
|
@@ -465,7 +465,8 @@ 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);
|
||
|
+ EVP_PKEY *pk, X509 *originator, EVP_PKEY *originator_pkey,
|
||
|
+ unsigned int flags);
|
||
|
int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
|
||
|
|
||
|
/* PWRI routines */
|
||
|
diff --git a/src/lib/libcrypto/cms/cms_smime.c b/src/lib/libcrypto/cms/cms_smime.c
|
||
|
index 1a067c149..dd1eb787b 100644
|
||
|
--- a/src/lib/libcrypto/cms/cms_smime.c
|
||
|
+++ b/src/lib/libcrypto/cms/cms_smime.c
|
||
|
@@ -612,6 +612,7 @@ CMS_sign_receipt(CMS_SignerInfo *si, X509 *signcert, EVP_PKEY *pkey,
|
||
|
|
||
|
CMS_ContentInfo *
|
||
|
CMS_encrypt(STACK_OF(X509) *certs, BIO *data, const EVP_CIPHER *cipher,
|
||
|
+ EVP_PKEY *originator_pkey, X509 *originator,
|
||
|
unsigned int flags)
|
||
|
{
|
||
|
CMS_ContentInfo *cms;
|
||
|
@@ -623,7 +624,7 @@ CMS_encrypt(STACK_OF(X509) *certs, BIO *data, const EVP_CIPHER *cipher,
|
||
|
goto merr;
|
||
|
for (i = 0; i < sk_X509_num(certs); i++) {
|
||
|
recip = sk_X509_value(certs, i);
|
||
|
- if (!CMS_add1_recipient_cert(cms, recip, flags)) {
|
||
|
+ if (!CMS_add1_recipient_cert(cms, recip, originator_pkey, originator, flags)) {
|
||
|
CMSerror(CMS_R_RECIPIENT_ERROR);
|
||
|
goto err;
|
||
|
}
|
||
|
diff --git a/src/lib/libcrypto/ec/ec_ameth.c b/src/lib/libcrypto/ec/ec_ameth.c
|
||
|
index 2e73bdd2f..a93a924bb 100644
|
||
|
--- a/src/lib/libcrypto/ec/ec_ameth.c
|
||
|
+++ b/src/lib/libcrypto/ec/ec_ameth.c
|
||
|
@@ -832,7 +832,10 @@ ecdh_cms_encrypt(CMS_RecipientInfo *ri)
|
||
|
if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
|
||
|
NULL, NULL, NULL))
|
||
|
goto err;
|
||
|
- X509_ALGOR_get0(&aoid, NULL, NULL, talg);
|
||
|
+ if (talg == NULL)
|
||
|
+ aoid = NULL;
|
||
|
+ else
|
||
|
+ X509_ALGOR_get0(&aoid, NULL, NULL, talg);
|
||
|
|
||
|
/* Is everything uninitialised? */
|
||
|
if (aoid == OBJ_nid2obj(NID_undef)) {
|
||
|
diff --git a/src/regress/lib/libcrypto/cms/cmstest.c b/src/regress/lib/libcrypto/cms/cmstest.c
|
||
|
index 466583ecb..ca2619fc8 100644
|
||
|
--- a/src/regress/lib/libcrypto/cms/cmstest.c
|
||
|
+++ b/src/regress/lib/libcrypto/cms/cmstest.c
|
||
|
@@ -143,7 +143,7 @@ test_cms_encrypt_decrypt()
|
||
|
if ((bio_mem = BIO_new_mem_buf(cms_msg, -1)) == NULL)
|
||
|
errx(1, "failed to create BIO for message");
|
||
|
|
||
|
- if ((ci = CMS_encrypt(certs, bio_mem, EVP_aes_256_cbc(), 0)) == NULL) {
|
||
|
+ if ((ci = CMS_encrypt(certs, bio_mem, EVP_aes_256_cbc(), NULL, NULL, 0)) == NULL) {
|
||
|
fprintf(stderr, "FAIL: CMS_encrypt returned NULL\n");
|
||
|
ERR_print_errors_fp(stderr);
|
||
|
goto failure;
|
||
|
diff --git a/src/usr.bin/openssl/cms.c b/src/usr.bin/openssl/cms.c
|
||
|
index ada4c7746..a16987e93 100644
|
||
|
--- a/src/usr.bin/openssl/cms.c
|
||
|
+++ b/src/usr.bin/openssl/cms.c
|
||
|
@@ -246,6 +246,8 @@ cms_main(int argc, char **argv)
|
||
|
flags |= CMS_BINARY;
|
||
|
else if (!strcmp(*args, "-keyid"))
|
||
|
flags |= CMS_USE_KEYID;
|
||
|
+ else if (!strcmp(*args, "-origkeyid"))
|
||
|
+ flags |= CMS_USE_ORIGINATOR_KEYID;
|
||
|
else if (!strcmp(*args, "-nosigs"))
|
||
|
flags |= CMS_NOSIGS;
|
||
|
else if (!strcmp(*args, "-no_content_verify"))
|
||
|
@@ -590,6 +592,7 @@ cms_main(int argc, char **argv)
|
||
|
BIO_printf(bio_err, "-signer file signer certificate file\n");
|
||
|
BIO_printf(bio_err, "-recip file recipient certificate file for decryption\n");
|
||
|
BIO_printf(bio_err, "-keyid use subject key identifier\n");
|
||
|
+ BIO_printf(bio_err, "-origkeyid use originator's key identifier\n");
|
||
|
BIO_printf(bio_err, "-in file input file\n");
|
||
|
BIO_printf(bio_err, "-inform arg input format SMIME (default), PEM or DER\n");
|
||
|
BIO_printf(bio_err, "-inkey file input private key (if not signer or recipient)\n");
|
||
|
@@ -686,6 +689,9 @@ cms_main(int argc, char **argv)
|
||
|
if (operation == SMIME_DECRYPT) {
|
||
|
if (!keyfile)
|
||
|
keyfile = recipfile;
|
||
|
+ } else if (operation == SMIME_ENCRYPT) {
|
||
|
+ if (!keyfile)
|
||
|
+ keyfile = certfile;
|
||
|
} else if ((operation == SMIME_SIGN) ||
|
||
|
(operation == SMIME_SIGN_RECEIPT)) {
|
||
|
if (!keyfile)
|
||
|
@@ -797,8 +803,23 @@ cms_main(int argc, char **argv)
|
||
|
cms = CMS_compress(in, -1, flags);
|
||
|
} else if (operation == SMIME_ENCRYPT) {
|
||
|
int i;
|
||
|
+ X509 *orig = NULL;
|
||
|
+ if (other) {
|
||
|
+ if (!key) {
|
||
|
+ BIO_puts(bio_err,"Must specify CMS originator private key\n");
|
||
|
+ goto end;
|
||
|
+ }
|
||
|
+ if (sk_X509_num(other) != 1) {
|
||
|
+ BIO_puts(bio_err,"Must specify only CMS originator certificate\n");
|
||
|
+ goto end;
|
||
|
+ }
|
||
|
+ orig = sk_X509_value(other, 0);
|
||
|
+ } else if (key) {
|
||
|
+ BIO_puts(bio_err,"Must specify only CMS originator certificate (-certfile)\n");
|
||
|
+ goto end;
|
||
|
+ }
|
||
|
flags |= CMS_PARTIAL;
|
||
|
- cms = CMS_encrypt(NULL, in, cipher, flags);
|
||
|
+ cms = CMS_encrypt(NULL, in, cipher, key, orig, flags);
|
||
|
if (cms == NULL)
|
||
|
goto end;
|
||
|
for (i = 0; i < sk_X509_num(encerts); i++) {
|
||
|
@@ -812,7 +833,7 @@ cms_main(int argc, char **argv)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
- ri = CMS_add1_recipient_cert(cms, x, tflags);
|
||
|
+ ri = CMS_add1_recipient_cert(cms, x, key, orig, tflags);
|
||
|
if (ri == NULL)
|
||
|
goto end;
|
||
|
if (kparam != NULL) {
|
||
|
--
|
||
|
2.17.1
|
||
|
|