From: igrkir Date: Mon, 27 Sep 2021 07:12:36 +0000 (+0300) Subject: Add TLS 1.3 new modes for TLSTREE algorithm X-Git-Url: http://wagner.pp.ru/gitweb/?a=commitdiff_plain;h=380a2c4f6ff07abed342a7cdc8fb0c5a97ffec9f;p=openssl-gost%2Fengine.git Add TLS 1.3 new modes for TLSTREE algorithm two new modes (long and short) per MGM algorithm (magma and kuznyechik). --- diff --git a/gost89.c b/gost89.c index 953c6ec..08c90f3 100644 --- a/gost89.c +++ b/gost89.c @@ -472,6 +472,10 @@ void magma_key(gost_ctx * c, const byte * k) } } +void magma_master_key(gost_ctx *c, const byte *k) { + memcpy(c->master_key, k, sizeof(c->master_key)); +} + /* Retrieve 256-bit gost89 key from context */ void gost_get_key(gost_ctx * c, byte * k) { @@ -508,6 +512,7 @@ void gost_init(gost_ctx * c, const gost_subst_block * b) /* Cleans up key from context */ void gost_destroy(gost_ctx * c) { + OPENSSL_cleanse(c->master_key, sizeof(c->master_key)); OPENSSL_cleanse(c->key, sizeof(c->key)); OPENSSL_cleanse(c->mask, sizeof(c->mask)); } diff --git a/gost89.h b/gost89.h index 569db5b..2bf75c1 100644 --- a/gost89.h +++ b/gost89.h @@ -33,6 +33,7 @@ typedef struct { /* Cipher context includes key and preprocessed substitution block */ typedef struct { + u4 master_key[8]; u4 key[8]; u4 mask[8]; /* Constant s-boxes -- set up in gost_init(). */ @@ -62,6 +63,8 @@ void gostdecrypt(gost_ctx * c, const byte * in, byte * out); void gost_key(gost_ctx * c, const byte * k); /* Set key into context */ void magma_key(gost_ctx * c, const byte * k); +/* Set master 256-bit key to be used in TLSTREE calculation into context */ +void magma_master_key(gost_ctx *c, const byte *k); /* Get key from context */ void gost_get_key(gost_ctx * c, byte * k); /* Set S-blocks into context */ diff --git a/gost_crypt.c b/gost_crypt.c index a6d5d37..9f608fe 100644 --- a/gost_crypt.c +++ b/gost_crypt.c @@ -476,8 +476,10 @@ static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, } } - if (key) + if (key) { magma_key(&(c->cctx), key); + magma_master_key(&(c->cctx), key); + } if (iv) { memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, EVP_CIPHER_CTX_iv_length(ctx)); @@ -599,6 +601,7 @@ static int gost_magma_cipher_init_mgm(EVP_CIPHER_CTX *ctx, const unsigned char * if (!gost_cipher_set_param(&mctx->ks.g_ks, NID_id_tc26_gost_28147_param_Z)) return 0; magma_key(&(mctx->ks.g_ks.cctx), key); + magma_master_key(&(mctx->ks.g_ks.cctx), key); gost_mgm128_init(&mctx->mgm, &mctx->ks, (block128_f) gost_magma_encrypt_wrap, gf64_mul, bl); @@ -1069,6 +1072,7 @@ static int gost_magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) mctx->ivlen = ivlen; mctx->iv = iv; mctx->taglen = -1; + mctx->tlstree_mode = TLSTREE_MODE_NONE; return 1; case EVP_CTRL_GET_IVLEN: @@ -1108,6 +1112,30 @@ static int gost_magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) memcpy(ptr, buf, arg); return 1; + case EVP_CTRL_SET_TLSTREE_PARAMS: + if (strcmp((char *)ptr, "short") == 0) + mctx->tlstree_mode = TLSTREE_MODE_S; + else if (strcmp((char *)ptr, "long") == 0) + mctx->tlstree_mode = TLSTREE_MODE_L; + else { + // TODO: set err + return 0; + } + return 1; + + case EVP_CTRL_TLSTREE: + { + unsigned char newkey[32]; + if (gost_tlstree(NID_magma_mgm, + (const unsigned char *)mctx->ks.g_ks.cctx.master_key, + newkey, (const unsigned char *)ptr, mctx->tlstree_mode) + > 0) { + magma_key(&mctx->ks.g_ks.cctx, newkey); + memset(newkey, 0, sizeof(newkey)); + } + } + return 1; + default: return -1; } diff --git a/gost_gost2015.c b/gost_gost2015.c index da5b795..38c1639 100644 --- a/gost_gost2015.c +++ b/gost_gost2015.c @@ -227,6 +227,8 @@ int gost_mgm128_setiv(mgm128_context *ctx, const unsigned char *iv, ctx->ACi.u[0] = 0; ctx->ACi.u[1] = 0; + ctx->sum.u[0] = 0; + ctx->sum.u[1] = 0; memcpy(ctx->nonce.c, iv, ctx->blocklen); ctx->nonce.c[0] &= 0x7f; /* IV - random vector, but 1st bit should be 0 */ @@ -315,6 +317,10 @@ int gost_mgm128_encrypt(mgm128_context *ctx, const unsigned char *in, int bl = ctx->blocklen; if (mlen == 0) { + if (alen == 0) { + ctx->nonce.c[0] |= 0x80; + (*block) (ctx->nonce.c, ctx->Zi.c, key); // Z_1 = E_K(1 || nonce) + } ctx->nonce.c[0] &= 0x7f; (*block) (ctx->nonce.c, ctx->Yi.c, key); // Y_1 = E_K(0 || nonce) } @@ -345,7 +351,7 @@ int gost_mgm128_encrypt(mgm128_context *ctx, const unsigned char *in, } n = mres % bl; - // TODO: full blocks + // TODO: replace with full blocks processing for (i = 0; i < len; ++i) { if (n == 0) { (*block) (ctx->Yi.c, ctx->EKi.c, key); // E_K(Y_i) @@ -408,7 +414,7 @@ int gost_mgm128_decrypt(mgm128_context *ctx, const unsigned char *in, } n = mres % bl; - // TODO: full blocks + // TODO: replace with full blocks processing for (i = 0; i < len; ++i) { uint8_t c; if (n == 0) { diff --git a/gost_gost2015.h b/gost_gost2015.h index 427524a..31e277a 100644 --- a/gost_gost2015.h +++ b/gost_gost2015.h @@ -54,6 +54,7 @@ typedef struct { unsigned char *iv; int ivlen; int taglen; + int tlstree_mode; } gost_mgm_ctx; int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_size, diff --git a/gost_grasshopper_cipher.c b/gost_grasshopper_cipher.c index c0031ad..36156b5 100644 --- a/gost_grasshopper_cipher.c +++ b/gost_grasshopper_cipher.c @@ -471,6 +471,7 @@ gost_grasshopper_cipher_init_mgm(EVP_CIPHER_CTX *ctx, const unsigned char *key, if (key) { bl = EVP_CIPHER_CTX_iv_length(ctx); gost_grasshopper_cipher_key(&mctx->ks.gh_ks, key); + gost_grasshopper_master_key(&mctx->ks.gh_ks, key); gost_mgm128_init(&mctx->mgm, &mctx->ks, (block128_f) gost_grasshopper_encrypt_wrap, gf128_mul_uint64, bl); @@ -1036,6 +1037,7 @@ static int gost_grasshopper_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void mctx->ivlen = ivlen; mctx->iv = iv; mctx->taglen = -1; + mctx->tlstree_mode = TLSTREE_MODE_NONE; return 1; case EVP_CTRL_GET_IVLEN: @@ -1075,6 +1077,30 @@ static int gost_grasshopper_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void memcpy(ptr, buf, arg); return 1; + case EVP_CTRL_SET_TLSTREE_PARAMS: + if (strcmp((char *)ptr, "short") == 0) + mctx->tlstree_mode = TLSTREE_MODE_S; + else if (strcmp((char *)ptr, "long") == 0) + mctx->tlstree_mode = TLSTREE_MODE_L; + else { + // TODO: set err + return 0; + } + return 1; + + case EVP_CTRL_TLSTREE: + { + unsigned char newkey[32]; + if (gost_tlstree(NID_kuznyechik_mgm, + mctx->ks.gh_ks.master_key.k.b, newkey, + (const unsigned char *)ptr, mctx->tlstree_mode) + > 0) { + gost_grasshopper_cipher_key(&mctx->ks.gh_ks, newkey); + memset(newkey, 0, sizeof(newkey)); + } + } + return 1; + default: return -1; } @@ -1138,7 +1164,7 @@ static int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, v } } if (gost_tlstree(NID_grasshopper_cbc, c->master_key.k.b, newkey, - (const unsigned char *)seq) > 0) { + (const unsigned char *)seq, TLSTREE_MODE_NONE) > 0) { memset(adjusted_iv, 0, 16); memcpy(adjusted_iv, EVP_CIPHER_CTX_original_iv(ctx), 8); for(j=7,carry=0; j>=0; j--) diff --git a/gost_keyexpimp.c b/gost_keyexpimp.c index e4af418..53029a8 100644 --- a/gost_keyexpimp.c +++ b/gost_keyexpimp.c @@ -251,7 +251,7 @@ int gost_kdftree2012_256(unsigned char *keyout, size_t keyout_len, } int gost_tlstree(int cipher_nid, const unsigned char *in, unsigned char *out, - const unsigned char *tlsseq) + const unsigned char *tlsseq, int mode) { uint64_t gh_c1 = 0x00000000FFFFFFFF, gh_c2 = 0x0000F8FFFFFFFFFF, gh_c3 = 0xC0FFFFFFFFFFFFFF; @@ -273,6 +273,37 @@ int gost_tlstree(int cipher_nid, const unsigned char *in, unsigned char *out, c2 = gh_c2; c3 = gh_c3; break; + case NID_magma_mgm: + switch (mode) { + case TLSTREE_MODE_S: // TLS_GOSTR341112_256_WITH_MAGMA_MGM_S + c1 = 0x000000fcffffffff; + c2 = 0x00e0ffffffffffff; + c3 = 0xffffffffffffffff; + break; + case TLSTREE_MODE_L: // TLS_GOSTR341112_256_WITH_MAGMA_MGM_L + c1 = 0x000000000000e0ff; + c2 = 0x000000c0ffffffff; + c3 = 0x80ffffffffffffff; + break; + default: + return 0; + } + break; + case NID_kuznyechik_mgm: + switch (mode) { + case TLSTREE_MODE_S: // TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S + c1 = 0x000000e0ffffffff; + c2 = 0x0000ffffffffffff; + c3 = 0xf8ffffffffffffff; + break; + case TLSTREE_MODE_L: // TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L + c1 = 0x00000000000000f8; + c2 = 0x00000000f0ffffff; + c3 = 0x00e0ffffffffffff; + default: + return 0; + } + break; default: return 0; } diff --git a/gost_lcl.h b/gost_lcl.h index 6da6a66..5a012c1 100644 --- a/gost_lcl.h +++ b/gost_lcl.h @@ -66,6 +66,9 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags); # define EVP_PKEY_CTRL_GOST_MAC_HEXKEY (EVP_PKEY_ALG_CTRL+3) # define EVP_PKEY_CTRL_MAC_LEN (EVP_PKEY_ALG_CTRL+5) # define EVP_PKEY_CTRL_SET_VKO (EVP_PKEY_ALG_CTRL+11) +# define TLSTREE_MODE_NONE 0 +# define TLSTREE_MODE_S 1 +# define TLSTREE_MODE_L 2 /* Pmeth internal representation */ struct gost_pmeth_data { int sign_param_nid; /* Should be set whenever parameters are @@ -76,6 +79,7 @@ struct gost_pmeth_data { int peer_key_used; int cipher_nid; /* KExp15/KImp15 algs */ int vko_dgst_nid; + char derive_mode; }; struct gost_mac_pmeth_data { @@ -283,7 +287,7 @@ int gost_kdftree2012_256(unsigned char *keyout, size_t keyout_len, const size_t representation); int gost_tlstree(int cipher_nid, const unsigned char *in, unsigned char *out, - const unsigned char *tlsseq); + const unsigned char *tlsseq, int mode); /* KExp/KImp */ int gost_kexp15(const unsigned char *shared_key, const int shared_len, int cipher_nid, const unsigned char *cipher_key, diff --git a/gost_omac.c b/gost_omac.c index c4026d4..fcfa810 100644 --- a/gost_omac.c +++ b/gost_omac.c @@ -240,7 +240,7 @@ int omac_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) if (c->key_set) { unsigned char diversed_key[32]; return gost_tlstree(c->cipher_nid, c->key, diversed_key, - (const unsigned char *)ptr) ? + (const unsigned char *)ptr, TLSTREE_MODE_NONE) ? omac_key(c, EVP_get_cipherbynid(c->cipher_nid), diversed_key, 32) : 0; } diff --git a/test_keyexpimp.c b/test_keyexpimp.c index 7c40927..77820e0 100644 --- a/test_keyexpimp.c +++ b/test_keyexpimp.c @@ -161,7 +161,7 @@ int main(void) } } - ret = gost_tlstree(NID_grasshopper_cbc, kroot, out, tlsseq); + ret = gost_tlstree(NID_grasshopper_cbc, kroot, out, tlsseq, TLSTREE_MODE_NONE); if (ret <= 0) { ERR_print_errors_fp(stderr); err = 7;