libressl/0063-cms-support-specifying-originator-certificate-and-ke.patch
Mikhail Novosyolov faac7d3eaa Add gost-new patches sponsored by ROSA Linux
TODO: add tests
2020-08-05 12:58:06 +03:00

277 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