]> www.wagner.pp.ru Git - openssl-gost/engine.git/commitdiff
Add TLS 1.3 new modes for TLSTREE algorithm
authorigrkir <i.kirillov@kryptonite.ru>
Mon, 27 Sep 2021 07:12:36 +0000 (10:12 +0300)
committerDmitry Belyavskiy <beldmit@users.noreply.github.com>
Wed, 29 Dec 2021 12:16:50 +0000 (15:16 +0300)
two new modes (long and short) per MGM algorithm (magma and kuznyechik).

gost89.c
gost89.h
gost_crypt.c
gost_gost2015.c
gost_gost2015.h
gost_grasshopper_cipher.c
gost_keyexpimp.c
gost_lcl.h
gost_omac.c
test_keyexpimp.c

index 953c6ec7788e96a45141dd6f0f03ea34ebdd9af0..08c90f33fb9567f7ecb5daa5badf386de06722af 100644 (file)
--- 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));
 }
index 569db5b059816eee5fa162fc74b6d0940c867913..2bf75c117e50334b43716c6789442f561c1b7dcc 100644 (file)
--- 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 */
index a6d5d37ebb42731fd9ffd631dbbd37dd165e94d6..9f608fe82099d4b98b26f33cad3c00ddf8bccf92 100644 (file)
@@ -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;
     }
index da5b795219bcd18e2eb6e0880d6f4df6df2aa1d8..38c16398f288af3a06e6c15ca7f7c411a598a7af 100644 (file)
@@ -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) {
index 427524a3b6c8669a8e605b5e7164960c9a65ebab..31e277ad835f913001c794d322ce8247668d1e6e 100644 (file)
@@ -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,
index c0031ad170221b7a12fb8b2e796abed4dfc7de9d..36156b520b9bacdf7e6cce5f1ff767fb54663800 100644 (file)
@@ -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--)
index e4af4180944cae514cbe334b6b99d85d04c7cea7..53029a80617f7cacce2020558fd0385de2d447f3 100644 (file)
@@ -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;
     }
index 6da6a66257ddd3bf1df21b6b0ad7548cd6f8b4c6..5a012c1d095220e45ad4112b00c1096bcdddce51 100644 (file)
@@ -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,
index c4026d4fdc758d6da9fa9654ca3b2b7d0833a200..fcfa810784c3ed9cb8b9969aa8c1cbbdbd989537 100644 (file)
@@ -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;
             }
index 7c40927cc9f03f91e36f009bc53a02e3263f4cbd..77820e0455fafdd15f8e061ea2e4395a7c50e3b6 100644 (file)
@@ -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;