mirror of
https://abf.rosa.ru/djam/libressl.git
synced 2025-02-23 16:12:53 +00:00
349 lines
11 KiB
Diff
349 lines
11 KiB
Diff
From 39697551e90ec5c96552de4d4666ec00b579dcce Mon Sep 17 00:00:00 2001
|
|
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
|
Date: Sun, 5 Apr 2020 22:58:24 +0300
|
|
Subject: [PATCH 53/87] gost: add support for CMS and SMIME enveloped files
|
|
|
|
Add support for CMS and SMIME files using GOST R 34.10-2012 keys and
|
|
GOST R 34.12-2015 (Magma and Kuznyechik) algorithms.
|
|
|
|
Sponsored by ROSA Linux
|
|
|
|
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
|
---
|
|
src/lib/libcrypto/cms/cms_env.c | 2 +-
|
|
src/lib/libcrypto/gost/gost_locl.h | 2 +
|
|
src/lib/libcrypto/gost/gostr341001_ameth.c | 154 +++++++++++++++++++--
|
|
src/lib/libcrypto/gost/gostr341001_pmeth.c | 13 ++
|
|
src/lib/libcrypto/objects/obj_mac.num | 4 +
|
|
src/lib/libcrypto/objects/objects.txt | 6 +
|
|
src/lib/libcrypto/pkcs7/pk7_doit.c | 6 +-
|
|
7 files changed, 168 insertions(+), 19 deletions(-)
|
|
|
|
diff --git a/src/lib/libcrypto/cms/cms_env.c b/src/lib/libcrypto/cms/cms_env.c
|
|
index 74d957eee..911f7a8a2 100644
|
|
--- a/src/lib/libcrypto/cms/cms_env.c
|
|
+++ b/src/lib/libcrypto/cms/cms_env.c
|
|
@@ -386,7 +386,7 @@ cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
|
|
}
|
|
|
|
if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
|
|
- EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) {
|
|
+ EVP_PKEY_CTRL_CMS_ENCRYPT, EVP_CIPHER_type(ec->cipher), ri) <= 0) {
|
|
CMSerror(CMS_R_CTRL_ERROR);
|
|
goto err;
|
|
}
|
|
diff --git a/src/lib/libcrypto/gost/gost_locl.h b/src/lib/libcrypto/gost/gost_locl.h
|
|
index 13e9fd459..1cdc18db9 100644
|
|
--- a/src/lib/libcrypto/gost/gost_locl.h
|
|
+++ b/src/lib/libcrypto/gost/gost_locl.h
|
|
@@ -123,6 +123,8 @@ extern BIGNUM *GOST_le2bn(const unsigned char *buf, size_t len, BIGNUM *bn);
|
|
extern int GOST_bn2le(BIGNUM *bn, unsigned char *buf, int len);
|
|
extern int gost01_VKO_key(EVP_PKEY *pub_key, EVP_PKEY *priv_key, const unsigned char *ukm,
|
|
unsigned int ukm_len, int ukm_be, int out_nid, unsigned char *key);
|
|
+extern int gost01_smime_encrypt(EVP_PKEY_CTX *ctx, X509_ALGOR *alg, int nid);
|
|
+extern int gost01_smime_decrypt(EVP_PKEY_CTX *pctx, X509_ALGOR *alg);
|
|
|
|
/* GOST R 34.10 parameters */
|
|
extern int GostR3410_get_md_digest(int nid);
|
|
diff --git a/src/lib/libcrypto/gost/gostr341001_ameth.c b/src/lib/libcrypto/gost/gostr341001_ameth.c
|
|
index 2efb001fc..965b36237 100644
|
|
--- a/src/lib/libcrypto/gost/gostr341001_ameth.c
|
|
+++ b/src/lib/libcrypto/gost/gostr341001_ameth.c
|
|
@@ -193,6 +193,41 @@ err:
|
|
return params;
|
|
}
|
|
|
|
+static ASN1_STRING *
|
|
+encode_gost01_kexp_params(EVP_PKEY *pkey)
|
|
+{
|
|
+ int digest = GOST_KEY_get_digest(pkey->pkey.gost);
|
|
+ ASN1_STRING *params = ASN1_STRING_new();
|
|
+ X509_ALGOR p;
|
|
+
|
|
+ if (params == NULL) {
|
|
+ GOSTerror(ERR_R_MALLOC_FAILURE);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ switch (digest) {
|
|
+ case NID_id_tc26_gost3411_2012_256:
|
|
+ p.algorithm = OBJ_nid2obj(NID_id_tc26_agreement_gost_3410_12_256);
|
|
+ break;
|
|
+ case NID_id_tc26_gost3411_2012_512:
|
|
+ p.algorithm = OBJ_nid2obj(NID_id_tc26_agreement_gost_3410_12_512);
|
|
+ break;
|
|
+ default:
|
|
+ GOSTerror(ERR_R_INTERNAL_ERROR);
|
|
+ break;
|
|
+ }
|
|
+ p.parameter = NULL;
|
|
+
|
|
+ params->length = i2d_X509_ALGOR(&p, ¶ms->data);
|
|
+ params->type = V_ASN1_SEQUENCE;
|
|
+
|
|
+ return params;
|
|
+err:
|
|
+ ASN1_STRING_free(params);
|
|
+ params = NULL;
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
static int
|
|
pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
|
|
{
|
|
@@ -772,10 +807,110 @@ param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
|
|
return 1;
|
|
}
|
|
|
|
+int gost01_smime_decrypt(EVP_PKEY_CTX *pctx, X509_ALGOR *alg)
|
|
+{
|
|
+ int nid = OBJ_obj2nid(alg->algorithm);
|
|
+ int format;
|
|
+
|
|
+ switch (nid) {
|
|
+ case NID_id_GostR3410_2001:
|
|
+ /* Nothing to do */
|
|
+ return 1;
|
|
+ case NID_id_tc26_wrap_gostr3412_2015_magma_kexp15:
|
|
+ format = GOST_ENC_FORMAT_PSKEY_MAGMA;
|
|
+ break;
|
|
+ case NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15:
|
|
+ format = GOST_ENC_FORMAT_PSKEY_KUZNYECHIK;
|
|
+ break;
|
|
+ default:
|
|
+ GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
|
|
+ return 0;
|
|
+ }
|
|
+ if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
|
|
+ EVP_PKEY_CTRL_GOST_ENC_FORMAT,
|
|
+ format, NULL) <= 0) {
|
|
+ GOSTerror(ERR_R_INTERNAL_ERROR);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+int gost01_smime_encrypt(EVP_PKEY_CTX *ctx, X509_ALGOR *alg, int enc_nid)
|
|
+{
|
|
+ EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
|
|
+ int digest, nid, format;
|
|
+ ASN1_STRING *params;
|
|
+
|
|
+ switch (enc_nid) {
|
|
+ case NID_id_Gost28147_89:
|
|
+ format = GOST_ENC_FORMAT_4490;
|
|
+ nid = NID_id_GostR3410_2001;
|
|
+ break;
|
|
+ case NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm:
|
|
+ case NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac:
|
|
+ format = GOST_ENC_FORMAT_PSKEY_MAGMA;
|
|
+ nid = NID_id_tc26_wrap_gostr3412_2015_magma_kexp15;
|
|
+ break;
|
|
+ case NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm:
|
|
+ case NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac:
|
|
+ format = GOST_ENC_FORMAT_PSKEY_KUZNYECHIK;
|
|
+ nid = NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15;
|
|
+ break;
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_ENCRYPT,
|
|
+ EVP_PKEY_CTRL_GOST_ENC_FORMAT, format,
|
|
+ NULL) != 1)
|
|
+ return 0;
|
|
+
|
|
+ if (EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_ENCRYPT,
|
|
+ EVP_PKEY_CTRL_GOST_GET_DIGEST, 0,
|
|
+ &digest) != 1)
|
|
+ return 0;
|
|
+
|
|
+ switch (digest) {
|
|
+ case NID_id_GostR3411_94_CryptoProParamSet:
|
|
+ if ((params = encode_gost01_algor_params(pkey)) == NULL)
|
|
+ return -1;
|
|
+ break;
|
|
+
|
|
+ case NID_id_tc26_gost3411_2012_256:
|
|
+ case NID_id_tc26_gost3411_2012_512:
|
|
+ if ((params = encode_gost01_kexp_params(pkey)) == NULL)
|
|
+ return -1;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+ return X509_ALGOR_set0(alg, OBJ_nid2obj(nid), V_ASN1_SEQUENCE, params);
|
|
+}
|
|
+
|
|
+#ifndef OPENSSL_NO_CMS
|
|
+static int
|
|
+gost01_cms_decrypt(CMS_RecipientInfo *ri)
|
|
+{
|
|
+ EVP_PKEY_CTX *pkctx;
|
|
+ X509_ALGOR *cmsalg;
|
|
+
|
|
+ pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
|
+ if (pkctx == NULL)
|
|
+ return 0;
|
|
+
|
|
+ if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
|
|
+ return 0;
|
|
+
|
|
+ return gost01_smime_decrypt(pkctx, cmsalg);
|
|
+}
|
|
+#endif
|
|
+
|
|
static int
|
|
pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
|
{
|
|
- X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL;
|
|
+ X509_ALGOR *alg1 = NULL, *alg2 = NULL;
|
|
int digest = GOST_KEY_get_digest(pkey->pkey.gost);
|
|
|
|
switch (op) {
|
|
@@ -786,8 +921,8 @@ pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
|
&alg1, &alg2);
|
|
break;
|
|
case ASN1_PKEY_CTRL_CMS_ENVELOPE:
|
|
- if (arg1 == 0)
|
|
- CMS_RecipientInfo_ktri_get0_algs(arg2, NULL, NULL, &alg3);
|
|
+ if (arg1 == 1)
|
|
+ return gost01_cms_decrypt(arg2);
|
|
break;
|
|
#endif
|
|
case ASN1_PKEY_CTRL_PKCS7_SIGN:
|
|
@@ -795,9 +930,7 @@ pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
|
PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
|
|
break;
|
|
case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
|
|
- if (arg1 == 0)
|
|
- PKCS7_RECIP_INFO_get0_alg(arg2, &alg3);
|
|
- break;
|
|
+ return 1;
|
|
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
|
*(int *)arg2 = GostR3410_get_md_digest(digest);
|
|
return 2;
|
|
@@ -810,15 +943,6 @@ pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
|
X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0);
|
|
if (alg2)
|
|
X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0);
|
|
- if (alg3) {
|
|
- ASN1_STRING *params = encode_gost01_algor_params(pkey);
|
|
- if (params == NULL) {
|
|
- return -1;
|
|
- }
|
|
- X509_ALGOR_set0(alg3,
|
|
- OBJ_nid2obj(GostR3410_get_pk_digest(digest)),
|
|
- V_ASN1_SEQUENCE, params);
|
|
- }
|
|
|
|
return 1;
|
|
}
|
|
diff --git a/src/lib/libcrypto/gost/gostr341001_pmeth.c b/src/lib/libcrypto/gost/gostr341001_pmeth.c
|
|
index ce4658b13..07ca4d3a3 100644
|
|
--- a/src/lib/libcrypto/gost/gostr341001_pmeth.c
|
|
+++ b/src/lib/libcrypto/gost/gostr341001_pmeth.c
|
|
@@ -61,6 +61,9 @@
|
|
#include <openssl/ec.h>
|
|
#include <openssl/ecdsa.h>
|
|
#include <openssl/x509.h>
|
|
+#ifndef OPENSSL_NO_CMS
|
|
+#include <openssl/cms.h>
|
|
+#endif
|
|
|
|
#include "evp_locl.h"
|
|
#include "gost_locl.h"
|
|
@@ -817,6 +820,7 @@ static int
|
|
pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
|
{
|
|
struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
|
|
+ X509_ALGOR *alg;
|
|
|
|
switch (type) {
|
|
case EVP_PKEY_CTRL_MD:
|
|
@@ -828,11 +832,20 @@ pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
|
pctx->md = p2;
|
|
return 1;
|
|
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
|
|
+ PKCS7_RECIP_INFO_get0_alg(p2, &alg);
|
|
+ return gost01_smime_encrypt(ctx, alg, p1);
|
|
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
|
|
+ PKCS7_RECIP_INFO_get0_alg(p2, &alg);
|
|
+ return gost01_smime_decrypt(ctx, alg);
|
|
case EVP_PKEY_CTRL_PKCS7_SIGN:
|
|
case EVP_PKEY_CTRL_DIGESTINIT:
|
|
+ return 1;
|
|
+
|
|
#ifndef OPENSSL_NO_CMS
|
|
case EVP_PKEY_CTRL_CMS_ENCRYPT:
|
|
+ if (CMS_RecipientInfo_ktri_get0_algs(p2, NULL, NULL, &alg) <= 0)
|
|
+ return 0;
|
|
+ return gost01_smime_encrypt(ctx, alg, p1);
|
|
case EVP_PKEY_CTRL_CMS_DECRYPT:
|
|
case EVP_PKEY_CTRL_CMS_SIGN:
|
|
#endif
|
|
diff --git a/src/lib/libcrypto/objects/obj_mac.num b/src/lib/libcrypto/objects/obj_mac.num
|
|
index 2c0d3356f..188349d71 100644
|
|
--- a/src/lib/libcrypto/objects/obj_mac.num
|
|
+++ b/src/lib/libcrypto/objects/obj_mac.num
|
|
@@ -1016,3 +1016,7 @@ id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1015
|
|
id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1016
|
|
id_tc26_cipher_gostr3412_2015_kuznyechik_mgm 1017
|
|
kuznyechik_mac 1018
|
|
+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
|
|
diff --git a/src/lib/libcrypto/objects/objects.txt b/src/lib/libcrypto/objects/objects.txt
|
|
index 4bf75f700..0d2af66ac 100644
|
|
--- a/src/lib/libcrypto/objects/objects.txt
|
|
+++ b/src/lib/libcrypto/objects/objects.txt
|
|
@@ -1416,6 +1416,12 @@ tc26 1 5 2 2 : kuznyechik-ctr-acpkm-omac
|
|
tc26 1 5 2 3 : kuznyechik-mgm
|
|
: kuznyechik-mac
|
|
|
|
+tc26 1 6 1 : id-tc26-agreement-gost-3410-12-256
|
|
+tc26 1 6 2 : id-tc26-agreement-gost-3410-12-512
|
|
+
|
|
+tc26 1 7 1 1 : id-tc26-wrap-gostr3412-2015-magma-kexp15
|
|
+tc26 1 7 2 1 : id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15
|
|
+
|
|
# Curves from draft-ietf-curdle-pkix-02
|
|
1 3 101 110 : X25519
|
|
1 3 101 111 : X448
|
|
diff --git a/src/lib/libcrypto/pkcs7/pk7_doit.c b/src/lib/libcrypto/pkcs7/pk7_doit.c
|
|
index 81a72f681..10cbd348e 100644
|
|
--- a/src/lib/libcrypto/pkcs7/pk7_doit.c
|
|
+++ b/src/lib/libcrypto/pkcs7/pk7_doit.c
|
|
@@ -138,7 +138,7 @@ err:
|
|
}
|
|
|
|
static int
|
|
-pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, unsigned char *key, int keylen)
|
|
+pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, unsigned char *key, int keylen, int enc_type)
|
|
{
|
|
EVP_PKEY_CTX *pctx = NULL;
|
|
EVP_PKEY *pkey = NULL;
|
|
@@ -158,7 +158,7 @@ pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, unsigned char *key, int keylen)
|
|
goto err;
|
|
|
|
if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
|
|
- EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0) {
|
|
+ EVP_PKEY_CTRL_PKCS7_ENCRYPT, enc_type, ri) <= 0) {
|
|
PKCS7error(PKCS7_R_CTRL_ERROR);
|
|
goto err;
|
|
}
|
|
@@ -362,7 +362,7 @@ PKCS7_dataInit(PKCS7 *p7, BIO *bio)
|
|
/* Lets do the pub key stuff :-) */
|
|
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
|
|
ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
|
|
- if (pkcs7_encode_rinfo(ri, key, keylen) <= 0)
|
|
+ if (pkcs7_encode_rinfo(ri, key, keylen, EVP_CIPHER_type(evp_cipher)) <= 0)
|
|
goto err;
|
|
}
|
|
explicit_bzero(key, keylen);
|
|
--
|
|
2.17.1
|
|
|