From: Dmitry Belyavskiy Date: Sun, 3 May 2020 16:42:05 +0000 (+0300) Subject: Magma/Kuznyechik ASN1 parameters and functions X-Git-Tag: v3.0.0~174 X-Git-Url: http://wagner.pp.ru/gitweb/?a=commitdiff_plain;h=41b4121253a9c0e8d82d3eebcfe728d5d43e1b51;p=openssl-gost%2Fengine.git Magma/Kuznyechik ASN1 parameters and functions --- diff --git a/CMakeLists.txt b/CMakeLists.txt index ada8842..e38b496 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,6 +160,7 @@ set(GOST_ENGINE_SOURCE_FILES gost_pmeth.c gost_omac.c gost_omac_acpkm.c + gost_gost2015.c ) add_executable(test_digest test_digest.c) diff --git a/e_gost_err.c b/e_gost_err.c index b7aa855..43f328d 100644 --- a/e_gost_err.c +++ b/e_gost_err.c @@ -20,6 +20,10 @@ static ERR_STRING_DATA GOST_str_functs[] = { "encode_gost_algor_params"}, {ERR_PACK(0, GOST_F_FILL_GOST_EC_PARAMS, 0), "fill_GOST_EC_params"}, {ERR_PACK(0, GOST_F_GET_ENCRYPTION_PARAMS, 0), "get_encryption_params"}, + {ERR_PACK(0, GOST_F_GOST2015_GET_ASN1_PARAMS, 0), + "gost2015_get_asn1_params"}, + {ERR_PACK(0, GOST_F_GOST2015_SET_ASN1_PARAMS, 0), + "gost2015_set_asn1_params"}, {ERR_PACK(0, GOST_F_GOST89_GET_ASN1_PARAMETERS, 0), "gost89_get_asn1_parameters"}, {ERR_PACK(0, GOST_F_GOST89_SET_ASN1_PARAMETERS, 0), diff --git a/e_gost_err.h b/e_gost_err.h index f656239..d17a165 100644 --- a/e_gost_err.h +++ b/e_gost_err.h @@ -33,6 +33,8 @@ void ERR_GOST_error(int function, int reason, char *file, int line); # define GOST_F_ENCODE_GOST_ALGOR_PARAMS 101 # define GOST_F_FILL_GOST_EC_PARAMS 102 # define GOST_F_GET_ENCRYPTION_PARAMS 103 +# define GOST_F_GOST2015_GET_ASN1_PARAMS 158 +# define GOST_F_GOST2015_SET_ASN1_PARAMS 159 # define GOST_F_GOST89_GET_ASN1_PARAMETERS 104 # define GOST_F_GOST89_SET_ASN1_PARAMETERS 105 # define GOST_F_GOST_CIPHER_CTL 106 diff --git a/gost.txt b/gost.txt index 959b99c..538cccf 100644 --- a/gost.txt +++ b/gost.txt @@ -10,6 +10,8 @@ GOST_F_DECODE_GOST_ALGOR_PARAMS:100:decode_gost_algor_params GOST_F_ENCODE_GOST_ALGOR_PARAMS:101:encode_gost_algor_params GOST_F_FILL_GOST_EC_PARAMS:102:fill_GOST_EC_params GOST_F_GET_ENCRYPTION_PARAMS:103:get_encryption_params +GOST_F_GOST2015_GET_ASN1_PARAMS:158:gost2015_get_asn1_params +GOST_F_GOST2015_SET_ASN1_PARAMS:159:gost2015_set_asn1_params GOST_F_GOST89_GET_ASN1_PARAMETERS:104:gost89_get_asn1_parameters GOST_F_GOST89_SET_ASN1_PARAMETERS:105:gost89_set_asn1_parameters GOST_F_GOST_CIPHER_CTL:106:gost_cipher_ctl diff --git a/gost_asn1.c b/gost_asn1.c index 35b9050..cb8883e 100644 --- a/gost_asn1.c +++ b/gost_asn1.c @@ -48,6 +48,11 @@ ASN1_NDEF_SEQUENCE(GOST_CIPHER_PARAMS) = } ASN1_NDEF_SEQUENCE_END(GOST_CIPHER_PARAMS) IMPLEMENT_ASN1_FUNCTIONS(GOST_CIPHER_PARAMS) +ASN1_NDEF_SEQUENCE(GOST2015_CIPHER_PARAMS) = { + ASN1_SIMPLE(GOST2015_CIPHER_PARAMS, ukm, ASN1_OCTET_STRING), +} ASN1_NDEF_SEQUENCE_END(GOST2015_CIPHER_PARAMS) +IMPLEMENT_ASN1_FUNCTIONS(GOST2015_CIPHER_PARAMS) + ASN1_NDEF_SEQUENCE(GOST_CLIENT_KEY_EXCHANGE_PARAMS) = { /* FIXME incomplete */ ASN1_SIMPLE(GOST_CLIENT_KEY_EXCHANGE_PARAMS, gkt, GOST_KEY_TRANSPORT) diff --git a/gost_gost2015.c b/gost_gost2015.c new file mode 100644 index 0000000..6ae65d6 --- /dev/null +++ b/gost_gost2015.c @@ -0,0 +1,122 @@ +#include "gost_lcl.h" +#include "gost_gost2015.h" +#include "e_gost_err.h" +#include + +int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_size, + unsigned char *encrypted_mac, + int (*do_cipher) (EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl)) +{ + unsigned char calculated_mac[KUZNYECHIK_MAC_MAX_SIZE]; + memset(calculated_mac, 0, KUZNYECHIK_MAC_MAX_SIZE); + + if (EVP_CIPHER_CTX_encrypting(ctx)) { + EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size); + + if (do_cipher(ctx, encrypted_mac, calculated_mac, mac_size) <= 0) { + return -1; + } + } else { + unsigned char expected_mac[KUZNYECHIK_MAC_MAX_SIZE]; + + memset(expected_mac, 0, KUZNYECHIK_MAC_MAX_SIZE); + EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size); + + if (do_cipher(ctx, expected_mac, encrypted_mac, mac_size) <= 0) { + return -1; + } + + if (CRYPTO_memcmp(expected_mac, calculated_mac, mac_size) != 0) + return -1; + } + return 0; +} + +/* + * UKM = iv|kdf_seed + * */ +#define MAX_GOST2015_UKM_SIZE 16 +#define KDF_SEED_SIZE 8 +int gost2015_get_asn1_params(const ASN1_TYPE *params, size_t ukm_size, + unsigned char *iv, size_t ukm_offset, unsigned char *kdf_seed) +{ + int iv_len = 16; + GOST2015_CIPHER_PARAMS *gcp = NULL; + + unsigned char *p = NULL; + + memset(iv, 0, iv_len); + + /* Проверяем тип params */ + if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) { + GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS); + return 0; + } + + p = params->value.sequence->data; + /* Извлекаем структуру параметров */ + gcp = d2i_GOST2015_CIPHER_PARAMS(NULL, (const unsigned char **)&p, params->value.sequence->length); + if (gcp == NULL) { + GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS); + return 0; + } + + /* Проверяем длину синхропосылки */ + if (gcp->ukm->length != (int)ukm_size) { + GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS); + GOST2015_CIPHER_PARAMS_free(gcp); + return 0; + } + + memcpy(iv, gcp->ukm->data, ukm_offset); + memcpy(kdf_seed, gcp->ukm->data+ukm_offset, KDF_SEED_SIZE); + + GOST2015_CIPHER_PARAMS_free(gcp); + return 1; +} + +int gost2015_set_asn1_params(ASN1_TYPE *params, + const unsigned char *iv, size_t iv_size, const unsigned char *kdf_seed) +{ + GOST2015_CIPHER_PARAMS *gcp = GOST2015_CIPHER_PARAMS_new(); + int ret = 0, len = 0; + + ASN1_OCTET_STRING *os = NULL; + unsigned char ukm_buf[MAX_GOST2015_UKM_SIZE]; + unsigned char *buf = NULL; + + if (gcp == NULL) { + GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE); + return 0; + } + + memcpy(ukm_buf, iv, iv_size); + memcpy(ukm_buf+iv_size, kdf_seed, KDF_SEED_SIZE); + + if (ASN1_STRING_set(gcp->ukm, ukm_buf, iv_size + KDF_SEED_SIZE) == 0) { + GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE); + goto end; + } + + len = i2d_GOST2015_CIPHER_PARAMS(gcp, &buf); + + if (len <= 0 + || (os = ASN1_OCTET_STRING_new()) == NULL + || ASN1_OCTET_STRING_set(os, buf, len) == 0) { + goto end; + } + + ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os); + ret = 1; + +end: + OPENSSL_free(buf); + if (ret <= 0 && os) + ASN1_OCTET_STRING_free(os); + + GOST2015_CIPHER_PARAMS_free(gcp); + return ret; +} diff --git a/gost_gost2015.h b/gost_gost2015.h new file mode 100644 index 0000000..797fbca --- /dev/null +++ b/gost_gost2015.h @@ -0,0 +1,22 @@ +#ifndef GOST_GOST2015_H +#define GOST_GOST2015_H + +#include + +#define MAGMA_MAC_MAX_SIZE 8 +#define KUZNYECHIK_MAC_MAX_SIZE 16 + +int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_size, + unsigned char *encrypted_mac, + int (*do_cipher) (EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + size_t inl)); + +/* IV is expected to be 16 bytes*/ +int gost2015_get_asn1_params(const ASN1_TYPE *params, size_t ukm_size, + unsigned char *iv, size_t ukm_offset, unsigned char *kdf_seed); + +int gost2015_set_asn1_params(ASN1_TYPE *params, + const unsigned char *iv, size_t iv_size, const unsigned char *kdf_seed); +#endif diff --git a/gost_lcl.h b/gost_lcl.h index 9740994..032886f 100644 --- a/gost_lcl.h +++ b/gost_lcl.h @@ -167,6 +167,12 @@ typedef struct { DECLARE_ASN1_FUNCTIONS(GOST_CIPHER_PARAMS) +typedef struct { + ASN1_OCTET_STRING *ukm; + } GOST2015_CIPHER_PARAMS; + +DECLARE_ASN1_FUNCTIONS(GOST2015_CIPHER_PARAMS) + typedef struct { ASN1_OCTET_STRING *masked_priv_key; ASN1_OCTET_STRING *public_key;