From cd0eec15fae54c7ca1b11109f85503b3cfb02217 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 8 Apr 2020 21:27:04 +0300 Subject: [PATCH 59/87] gost: support specifying old or new (KEG) derivation format Signed-off-by: Dmitry Baryshkov --- src/lib/libcrypto/gost/gost.h | 4 ++ src/lib/libcrypto/gost/gostr341001_pmeth.c | 68 +++++++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/lib/libcrypto/gost/gost.h b/src/lib/libcrypto/gost/gost.h index 6a2b60670..694906b76 100644 --- a/src/lib/libcrypto/gost/gost.h +++ b/src/lib/libcrypto/gost/gost.h @@ -229,6 +229,7 @@ size_t GOST_KEY_get_size(const GOST_KEY * r); #define EVP_PKEY_CTRL_GOST_SET_DIGEST (EVP_PKEY_ALG_CTRL+3) #define EVP_PKEY_CTRL_GOST_GET_DIGEST (EVP_PKEY_ALG_CTRL+4) #define EVP_PKEY_CTRL_GOST_ENC_FORMAT (EVP_PKEY_ALG_CTRL+5) +#define EVP_PKEY_CTRL_GOST_DERIVE_FORMAT (EVP_PKEY_ALG_CTRL+6) #define GOST_SIG_FORMAT_SR_BE 0 #define GOST_SIG_FORMAT_RS_LE 1 @@ -237,6 +238,9 @@ size_t GOST_KEY_get_size(const GOST_KEY * r); #define GOST_ENC_FORMAT_PSKEY_MAGMA 1 /* CMS, TLS CTR-OMAC, Magma-encoded */ #define GOST_ENC_FORMAT_PSKEY_KUZNYECHIK 2 /* CMS, TLS CTR-OMAC, Kuznyechik-encoded */ +#define GOST_DERIVE_FORMAT_4490 0 /* RFC 4490, TLS CNT-IMIT */ +#define GOST_DERIVE_FORMAT_KEG 1 /* CMS, TLS CTR-OMAC */ + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. diff --git a/src/lib/libcrypto/gost/gostr341001_pmeth.c b/src/lib/libcrypto/gost/gostr341001_pmeth.c index 07ca4d3a3..e21101ddc 100644 --- a/src/lib/libcrypto/gost/gostr341001_pmeth.c +++ b/src/lib/libcrypto/gost/gostr341001_pmeth.c @@ -137,6 +137,7 @@ struct gost_pmeth_data { int peer_key_used; int sig_format; int enc_format; + int derive_format; }; static int @@ -468,8 +469,8 @@ err: return ret; } -int -pkey_gost01_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) +static int +pkey_gost01_derive_4490(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) { /* * Public key of peer in the ctx field peerkey @@ -504,6 +505,38 @@ pkey_gost01_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) return 1; } +static int +pkey_gost01_derive_keg(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) +{ + /* + * Public key of peer in the ctx field peerkey + * Our private key in the ctx pkey + * ukm is in the algorithm specific context data + */ + EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx); + EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx); + struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); + + if (data->shared_ukm == NULL) { + GOSTerror(GOST_R_UKM_NOT_SET); + return 0; + } + + if (key == NULL) { + *keylen = 64; + return 64; + } + + if (!gost_keg(peer_key, my_key, data->digest_nid, data->shared_ukm, key)) { + GOSTerror(GOST_R_ERROR_COMPUTING_SHARED_KEY); + return 0; + } + + *keylen = 64; + + return 1; +} + int pkey_gost01_encrypt_4490(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len, const unsigned char *key, size_t key_len) @@ -816,6 +849,21 @@ pkey_gost01_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *out_len, } } +int +pkey_gost01_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) +{ + struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx); + + switch (pctx->derive_format) { + case GOST_DERIVE_FORMAT_4490: + return pkey_gost01_derive_4490(ctx, key, keylen); + case GOST_DERIVE_FORMAT_KEG: + return pkey_gost01_derive_keg(ctx, key, keylen); + default: + return -1; + } +} + static int pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { @@ -911,6 +959,22 @@ pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) pctx->enc_format = p1; return 1; break; + case EVP_PKEY_CTRL_GOST_DERIVE_FORMAT: + switch (p1) { + case GOST_DERIVE_FORMAT_4490: + /* All keys are supported */ + break; + case GOST_DERIVE_FORMAT_KEG: + if (pctx->digest_nid != NID_id_tc26_gost3411_2012_256 && + pctx->digest_nid != NID_id_tc26_gost3411_2012_512) + return 0; + break; + default: + return 0; + } + pctx->derive_format = p1; + return 1; + break; default: return -2; } -- 2.17.1