mirror of
https://abf.rosa.ru/djam/libressl.git
synced 2025-02-23 16:12:53 +00:00
224 lines
8 KiB
Diff
224 lines
8 KiB
Diff
From c07aac0a0dced669f5291aad98c453f3d47eab10 Mon Sep 17 00:00:00 2001
|
|
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
|
Date: Tue, 7 Apr 2020 16:36:32 +0300
|
|
Subject: [PATCH 54/87] cms: add support for using AEAD ciphers in CMS files
|
|
|
|
Russian standards body has added definition for special unprotected
|
|
attribute (id-cms-mac-attr) used together with AEAD ciphers (primarily
|
|
CTR-ACKM-OMAC) to store MAC value together with encrypted data.
|
|
|
|
Sponsored by ROSA Linux
|
|
|
|
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
|
---
|
|
src/lib/libcrypto/cms/cms_enc.c | 66 ++++++++++++++++++++++++++-
|
|
src/lib/libcrypto/cms/cms_env.c | 15 +++++-
|
|
src/lib/libcrypto/cms/cms_lcl.h | 7 ++-
|
|
src/lib/libcrypto/cms/cms_lib.c | 8 +++-
|
|
src/lib/libcrypto/objects/obj_mac.num | 1 +
|
|
src/lib/libcrypto/objects/objects.txt | 1 +
|
|
6 files changed, 92 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/lib/libcrypto/cms/cms_enc.c b/src/lib/libcrypto/cms/cms_enc.c
|
|
index fd2df99c6..2b8f9c5b8 100644
|
|
--- a/src/lib/libcrypto/cms/cms_enc.c
|
|
+++ b/src/lib/libcrypto/cms/cms_enc.c
|
|
@@ -68,7 +68,8 @@
|
|
/* Return BIO based on EncryptedContentInfo and key */
|
|
|
|
BIO *
|
|
-cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
|
|
+cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
|
|
+ STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs)
|
|
{
|
|
BIO *b;
|
|
EVP_CIPHER_CTX *ctx;
|
|
@@ -189,6 +190,23 @@ cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
|
|
ASN1_TYPE_free(calg->parameter);
|
|
calg->parameter = NULL;
|
|
}
|
|
+ } else if (ciph->flags & EVP_CIPH_FLAG_AEAD_CIPHER) {
|
|
+ int idx = X509at_get_attr_by_NID(unprotectedAttrs, NID_id_cms_mac_attr, -1);
|
|
+ X509_ATTRIBUTE *attr;
|
|
+ ASN1_TYPE *type;
|
|
+
|
|
+ if (idx == -1 ||
|
|
+ (attr = X509at_get_attr(unprotectedAttrs, idx)) == NULL ||
|
|
+ attr->single != 0 ||
|
|
+ sk_ASN1_TYPE_num(attr->value.set) != 1 ||
|
|
+ (type = sk_ASN1_TYPE_value(attr->value.set, 0)) == NULL ||
|
|
+ type->type != V_ASN1_OCTET_STRING ||
|
|
+ !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG,
|
|
+ type->value.octet_string->length,
|
|
+ type->value.octet_string->data)) {
|
|
+ CMSerror(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
|
|
+ goto err;
|
|
+ }
|
|
}
|
|
ok = 1;
|
|
|
|
@@ -204,6 +222,43 @@ cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
|
|
return NULL;
|
|
}
|
|
|
|
+int cms_EncryptedContent_final(CMS_EncryptedContentInfo *ec,
|
|
+ BIO *chain, STACK_OF(X509_ATTRIBUTE) **unprotectedAttrs)
|
|
+{
|
|
+ EVP_CIPHER_CTX *ctx = NULL;
|
|
+ BIO *mbio = BIO_find_type(chain, BIO_TYPE_CIPHER);
|
|
+
|
|
+ if (mbio == NULL) {
|
|
+ CMSerror(CMS_R_CONTENT_NOT_FOUND);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ BIO_get_cipher_ctx(mbio, &ctx);
|
|
+ if (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) {
|
|
+ unsigned char tag[EVP_MAX_MD_SIZE];
|
|
+ int taglen;
|
|
+ int nid = EVP_CIPHER_CTX_nid(ctx);
|
|
+
|
|
+ /* Most of the AEAD ciphers have 16-bit tags except Magma ciphers */
|
|
+ if (nid == NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac ||
|
|
+ nid == NID_id_tc26_cipher_gostr3412_2015_magma_mgm)
|
|
+ taglen = 8;
|
|
+ else
|
|
+ taglen = 16;
|
|
+
|
|
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG,
|
|
+ taglen, tag) <= 0) {
|
|
+ CMSerror(CMS_R_CTRL_FAILURE);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (!X509at_add1_attr_by_NID(unprotectedAttrs, NID_id_cms_mac_attr, V_ASN1_OCTET_STRING, tag, taglen))
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
int
|
|
cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
|
|
const EVP_CIPHER *cipher, const unsigned char *key, size_t keylen)
|
|
@@ -258,5 +313,12 @@ cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
|
|
if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
|
|
enc->version = 2;
|
|
|
|
- return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
|
|
+ return cms_EncryptedContent_init_bio(enc->encryptedContentInfo, enc->unprotectedAttrs);
|
|
+}
|
|
+
|
|
+int cms_EncryptedData_final(CMS_ContentInfo *cms, BIO *chain)
|
|
+{
|
|
+ CMS_EncryptedData *enc = cms->d.encryptedData;
|
|
+
|
|
+ return cms_EncryptedContent_final(enc->encryptedContentInfo, chain, &enc->unprotectedAttrs);
|
|
}
|
|
diff --git a/src/lib/libcrypto/cms/cms_env.c b/src/lib/libcrypto/cms/cms_env.c
|
|
index 911f7a8a2..f5e9280d4 100644
|
|
--- a/src/lib/libcrypto/cms/cms_env.c
|
|
+++ b/src/lib/libcrypto/cms/cms_env.c
|
|
@@ -927,7 +927,7 @@ cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
|
|
/* Get BIO first to set up key */
|
|
|
|
ec = cms->d.envelopedData->encryptedContentInfo;
|
|
- ret = cms_EncryptedContent_init_bio(ec);
|
|
+ ret = cms_EncryptedContent_init_bio(ec, cms->d.envelopedData->unprotectedAttrs);
|
|
|
|
/* If error or no cipher end of processing */
|
|
|
|
@@ -960,6 +960,19 @@ cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
|
|
return NULL;
|
|
}
|
|
|
|
+int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain)
|
|
+{
|
|
+ CMS_EnvelopedData *env = NULL;
|
|
+
|
|
+ env = cms_get0_enveloped(cms);
|
|
+ if (env == NULL) {
|
|
+ CMSerror(CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return cms_EncryptedContent_final(env->encryptedContentInfo, chain, &env->unprotectedAttrs);
|
|
+}
|
|
+
|
|
/*
|
|
* Get RecipientInfo type (if any) supported by a key (public or private). To
|
|
* retain compatibility with previous behaviour if the ctrl value isn't
|
|
diff --git a/src/lib/libcrypto/cms/cms_lcl.h b/src/lib/libcrypto/cms/cms_lcl.h
|
|
index 8083e5537..fdfd12160 100644
|
|
--- a/src/lib/libcrypto/cms/cms_lcl.h
|
|
+++ b/src/lib/libcrypto/cms/cms_lcl.h
|
|
@@ -442,16 +442,21 @@ int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert);
|
|
int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert);
|
|
int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert);
|
|
|
|
-BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec);
|
|
+BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
|
|
+ STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs);
|
|
BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms);
|
|
+int cms_EncryptedData_final(CMS_ContentInfo *cms, BIO *chain);
|
|
int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
|
|
const EVP_CIPHER *cipher, const unsigned char *key, size_t keylen);
|
|
+int cms_EncryptedContent_final(CMS_EncryptedContentInfo *ec,
|
|
+ BIO *chain, STACK_OF(X509_ATTRIBUTE) **unprotectedAttrs);
|
|
|
|
int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms);
|
|
int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src);
|
|
ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si);
|
|
|
|
BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
|
|
+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);
|
|
diff --git a/src/lib/libcrypto/cms/cms_lib.c b/src/lib/libcrypto/cms/cms_lib.c
|
|
index b6580dd6f..787a8f99e 100644
|
|
--- a/src/lib/libcrypto/cms/cms_lib.c
|
|
+++ b/src/lib/libcrypto/cms/cms_lib.c
|
|
@@ -215,12 +215,16 @@ CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
|
|
switch (OBJ_obj2nid(cms->contentType)) {
|
|
|
|
case NID_pkcs7_data:
|
|
- case NID_pkcs7_enveloped:
|
|
- case NID_pkcs7_encrypted:
|
|
case NID_id_smime_ct_compressedData:
|
|
/* Nothing to do */
|
|
return 1;
|
|
|
|
+ case NID_pkcs7_enveloped:
|
|
+ return cms_EnvelopedData_final(cms, cmsbio);
|
|
+
|
|
+ case NID_pkcs7_encrypted:
|
|
+ return cms_EncryptedData_final(cms, cmsbio);
|
|
+
|
|
case NID_pkcs7_signed:
|
|
return cms_SignedData_final(cms, cmsbio);
|
|
|
|
diff --git a/src/lib/libcrypto/objects/obj_mac.num b/src/lib/libcrypto/objects/obj_mac.num
|
|
index 188349d71..6e494cb92 100644
|
|
--- a/src/lib/libcrypto/objects/obj_mac.num
|
|
+++ b/src/lib/libcrypto/objects/obj_mac.num
|
|
@@ -1020,3 +1020,4 @@ id_tc26_agreement_gost_3410_12_256 1019
|
|
id_tc26_agreement_gost_3410_12_512 1020
|
|
id_tc26_wrap_gostr3412_2015_magma_kexp15 1021
|
|
id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1022
|
|
+id_cms_mac_attr 1023
|
|
diff --git a/src/lib/libcrypto/objects/objects.txt b/src/lib/libcrypto/objects/objects.txt
|
|
index 0d2af66ac..3f810dcf8 100644
|
|
--- a/src/lib/libcrypto/objects/objects.txt
|
|
+++ b/src/lib/libcrypto/objects/objects.txt
|
|
@@ -1368,6 +1368,7 @@ brainpool 1 14 : brainpoolP512t1
|
|
: gost89-cbc
|
|
|
|
member-body 643 7 1 : tc26
|
|
+tc26 0 6 1 1 : id-cms-mac-attr
|
|
!Cname id-tc26-gost3411-2012-256
|
|
tc26 1 2 2 : streebog256 : GOST R 34.11-2012 (256 bit)
|
|
!Cname id-tc26-gost3411-2012-512
|
|
--
|
|
2.17.1
|
|
|