From 5186d798730c1ecec7ed40126beaf493804fcf45 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Tue, 19 Jun 2018 17:03:50 +0300 Subject: [PATCH] Magma CTR (no meshing), compile-only version. --- gost_crypt.c | 104 ++++++++++++++++++++++++++++++++++++-- gost_eng.c | 4 ++ gost_grasshopper_cipher.c | 12 +++-- gost_lcl.h | 4 ++ 4 files changed, 117 insertions(+), 7 deletions(-) diff --git a/gost_crypt.c b/gost_crypt.c index 035a46a..d094c5e 100644 --- a/gost_crypt.c +++ b/gost_crypt.c @@ -46,11 +46,14 @@ static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params); /* Control function */ static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); -static int magma_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key, +static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); /* Handles block of data in CBC mode */ static int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl); +static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); + static EVP_CIPHER *_hidden_Gost28147_89_cipher = NULL; const EVP_CIPHER *cipher_gost(void) { @@ -192,6 +195,41 @@ const EVP_CIPHER *cipher_gost_cpcnt_12(void) return _hidden_gost89_cnt_12; } +static EVP_CIPHER *_hidden_magma_ctr = NULL; +const EVP_CIPHER *cipher_magma_ctr(void) +{ + if (_hidden_magma_ctr == NULL + && ((_hidden_magma_ctr = + EVP_CIPHER_meth_new(NID_magma_ctr, 1 /* block_size */ , + 32 /* key_size */ )) == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_magma_ctr, 8) + || !EVP_CIPHER_meth_set_flags(_hidden_magma_ctr, + EVP_CIPH_CTR_MODE | + EVP_CIPH_NO_PADDING | + EVP_CIPH_CUSTOM_IV | + EVP_CIPH_RAND_KEY | + EVP_CIPH_ALWAYS_CALL_INIT) + || !EVP_CIPHER_meth_set_init(_hidden_magma_ctr, + magma_cipher_init) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_magma_ctr, + magma_cipher_do_ctr) + || !EVP_CIPHER_meth_set_cleanup(_hidden_magma_ctr, + gost_cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_magma_ctr, + sizeof(struct + ossl_gost_cipher_ctx)) + || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_magma_ctr, + gost89_set_asn1_parameters) + || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_magma_ctr, + gost89_get_asn1_parameters) + || !EVP_CIPHER_meth_set_ctrl(_hidden_magma_ctr, + gost_cipher_ctl))) { + EVP_CIPHER_meth_free(_hidden_magma_ctr); + _hidden_magma_ctr = NULL; + } + return _hidden_magma_ctr; +} + static EVP_CIPHER *_hidden_magma_cbc = NULL; const EVP_CIPHER *cipher_magma_cbc(void) { @@ -206,7 +244,7 @@ const EVP_CIPHER *cipher_magma_cbc(void) EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT) || !EVP_CIPHER_meth_set_init(_hidden_magma_cbc, - magma_cipher_init_cbc) + magma_cipher_init) || !EVP_CIPHER_meth_set_do_cipher(_hidden_magma_cbc, magma_cipher_do_cbc) || !EVP_CIPHER_meth_set_cleanup(_hidden_magma_cbc, @@ -238,6 +276,8 @@ void cipher_gost_destroy(void) _hidden_gost89_cnt_12 = NULL; EVP_CIPHER_meth_free(_hidden_magma_cbc); _hidden_magma_cbc = NULL; + EVP_CIPHER_meth_free(_hidden_magma_ctr); + _hidden_magma_ctr = NULL; } /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */ @@ -498,7 +538,7 @@ int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key, } /* Initializes EVP_CIPHER_CTX with default values */ -int magma_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key, +int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { return magma_cipher_init_param(ctx, key, iv, enc, NID_undef, @@ -591,7 +631,7 @@ int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, return 1; } -/* GOST encryption in CBC mode */ +/* MAGMA encryption in CBC mode */ int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { @@ -636,6 +676,62 @@ int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, return 1; } +/* increment counter (64-bit int) by 1 */ +static void ctr64_inc(unsigned char *counter) +{ + inc_counter(counter, 8); +} + +/* MAGMA encryption in CTR mode */ +static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + const unsigned char *in_ptr = in; + unsigned char *out_ptr = out; + size_t i = 0; + size_t j; + struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); +/* Process partial blocks */ + if (EVP_CIPHER_CTX_num(ctx)) { + for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl; + j++, i++, in_ptr++, out_ptr++) { + *out_ptr = buf[j] ^ (*in_ptr); + } + if (j == 8) { + EVP_CIPHER_CTX_set_num(ctx, 0); + } else { + EVP_CIPHER_CTX_set_num(ctx, j); + return 1; + } + } + +/* Process full blocks */ + for (; i + 8 < inl; i += 8, in_ptr += 8, out_ptr += 8) { + gostcrypt(&(c->cctx), iv, buf); + for (j = 0; j < 8; j++) { + out_ptr[j] = buf[j] ^ in_ptr[j]; + } + ctr64_inc(iv); + } + +/* Process the rest of plaintext */ + if (i < inl) { + gostcrypt(&(c->cctx), iv, buf); + ctr64_inc(iv); + for (j = 0; i < inl; j++, i++) { + out_ptr[j] = buf[j] ^ in_ptr[j]; + } + + EVP_CIPHER_CTX_set_num(ctx, j); + } else { + EVP_CIPHER_CTX_set_num(ctx, 0); + } + + return 1; +} + /* GOST encryption in CFB mode */ int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) diff --git a/gost_eng.c b/gost_eng.c index 33659a5..1f25654 100644 --- a/gost_eng.c +++ b/gost_eng.c @@ -48,6 +48,7 @@ static int gost_cipher_nids[] = { NID_grasshopper_ofb, NID_grasshopper_ctr, NID_magma_cbc, + NID_magma_ctr, 0 }; @@ -252,6 +253,7 @@ static int bind_gost(ENGINE* e, const char* id) { || !EVP_add_cipher(cipher_gost_grasshopper_ofb()) || !EVP_add_cipher(cipher_gost_grasshopper_ctr()) || !EVP_add_cipher(cipher_magma_cbc()) + || !EVP_add_cipher(cipher_magma_ctr()) || !EVP_add_digest(digest_gost()) || !EVP_add_digest(digest_gost2012_512()) || !EVP_add_digest(digest_gost2012_256()) @@ -331,6 +333,8 @@ static int gost_ciphers(ENGINE* e, const EVP_CIPHER** cipher, *cipher = cipher_gost_grasshopper_ctr(); } else if (nid == NID_magma_cbc) { *cipher = cipher_magma_cbc(); + } else if (nid == NID_magma_ctr) { + *cipher = cipher_magma_ctr(); } else { ok = 0; *cipher = NULL; diff --git a/gost_grasshopper_cipher.c b/gost_grasshopper_cipher.c index 20c04b0..e7c8dd6 100644 --- a/gost_grasshopper_cipher.c +++ b/gost_grasshopper_cipher.c @@ -17,6 +17,7 @@ extern "C" { #include #include +#include "gost_lcl.h" #include "e_gost_err.h" enum GRASSHOPPER_CIPHER_TYPE { @@ -279,11 +280,10 @@ int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX* ctx, unsigned char* out, return 1; } -/* increment counter (128-bit int) by 1 */ -static void ctr128_inc(unsigned char *counter) +void inc_counter(unsigned char* counter, size_t counter_bytes) { - unsigned int n = 16; unsigned char c; + unsigned int n = counter_bytes; do { --n; @@ -294,6 +294,12 @@ static void ctr128_inc(unsigned char *counter) } while (n); } +/* increment counter (128-bit int) by 1 */ +static void ctr128_inc(unsigned char *counter) +{ + inc_counter(counter, 16); +} + int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, const unsigned char* in, size_t inl) { gost_grasshopper_cipher_ctx_ctr* c = (gost_grasshopper_cipher_ctx_ctr*) EVP_CIPHER_CTX_get_cipher_data(ctx); diff --git a/gost_lcl.h b/gost_lcl.h index 58ac94d..0da46c7 100644 --- a/gost_lcl.h +++ b/gost_lcl.h @@ -216,7 +216,11 @@ const EVP_CIPHER *cipher_gost_cbc(); const EVP_CIPHER *cipher_gost_cpacnt(); const EVP_CIPHER *cipher_gost_cpcnt_12(); const EVP_CIPHER *cipher_magma_cbc(); +const EVP_CIPHER *cipher_magma_ctr(); void cipher_gost_destroy(); + +void inc_counter(unsigned char* buffer, size_t buf_len); + # define EVP_MD_CTRL_KEY_LEN (EVP_MD_CTRL_ALG_CTRL+3) # define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+4) # define EVP_MD_CTRL_MAC_LEN (EVP_MD_CTRL_ALG_CTRL+5) -- 2.39.2