From: Dmitry Eremin-Solenikov <dbarysh...@gmail.com>

Signed-off-by: Dmitry Eremin-Solenikov <dbarysh...@gmail.com>
---
 gost28147.c                |  85 +++++++++++++++++++---
 gost28147.h                |   8 +++
 testsuite/gost28147-test.c | 143 +++++++++++++++++++++++++++++++++++++
 3 files changed, 228 insertions(+), 8 deletions(-)

diff --git a/gost28147.c b/gost28147.c
index 9fe31043a3ff..ac94dfaa2ed8 100644
--- a/gost28147.c
+++ b/gost28147.c
@@ -33,6 +33,7 @@
 #endif
 
 #include <assert.h>
+#include <string.h>
 
 #include "macros.h"
 #include "gost28147.h"
@@ -303,7 +304,8 @@ const struct gost28147_param gost28147_param_test_3411 =
       0x00000600, 0x00000650, 0x00000670, 0x00000638,
       0x00000630, 0x00000640, 0x00000610, 0x00000660,
     }
-  }
+  },
+  0
 };
 
 const struct gost28147_param gost28147_param_CryptoPro_3411 =
@@ -570,7 +572,8 @@ const struct gost28147_param gost28147_param_CryptoPro_3411 
=
       0x00000618, 0x00000660, 0x00000640, 0x00000678,
       0x00000630, 0x00000610, 0x00000648, 0x00000658,
     }
-  }
+  },
+  0
 };
 
 const struct gost28147_param gost28147_param_Test_89 =
@@ -837,7 +840,8 @@ const struct gost28147_param gost28147_param_Test_89 =
       0x00000420, 0x00000440, 0x00000470, 0x00000478,
       0x00000408, 0x00000450, 0x00000410, 0x00000468,
     }
-  }
+  },
+  1
 };
 
 const struct gost28147_param gost28147_param_CryptoPro_A =
@@ -1104,7 +1108,8 @@ const struct gost28147_param gost28147_param_CryptoPro_A =
       0x00000240, 0x00000260, 0x00000220, 0x00000228,
       0x00000278, 0x00000218, 0x00000258, 0x00000270,
     }
-  }
+  },
+  1
 };
 
 const struct gost28147_param gost28147_param_CryptoPro_B =
@@ -1371,7 +1376,8 @@ const struct gost28147_param gost28147_param_CryptoPro_B =
       0x00000638, 0x00000620, 0x00000668, 0x00000600,
       0x00000630, 0x00000678, 0x00000640, 0x00000670,
     }
-  }
+  },
+  1
 };
 
 const struct gost28147_param gost28147_param_CryptoPro_C =
@@ -1638,7 +1644,8 @@ const struct gost28147_param gost28147_param_CryptoPro_C =
       0x00000478, 0x00000418, 0x00000428, 0x00000458,
       0x00000420, 0x00000408, 0x00000460, 0x00000438,
     }
-  }
+  },
+  1
 };
 
 const struct gost28147_param gost28147_param_CryptoPro_D =
@@ -1905,7 +1912,8 @@ const struct gost28147_param gost28147_param_CryptoPro_D =
       0x00000768, 0x00000740, 0x00000760, 0x00000720,
       0x00000758, 0x00000750, 0x00000728, 0x00000738,
     }
-  }
+  },
+  1
 };
 
 const struct gost28147_param gost28147_param_TC26_Z =
@@ -2172,7 +2180,8 @@ const struct gost28147_param gost28147_param_TC26_Z =
       0x00000178, 0x00000120, 0x00000158, 0x00000100,
       0x00000168, 0x00000150, 0x00000118, 0x00000138,
     }
-  }
+  },
+  1
 };
 
 /*
@@ -2245,6 +2254,37 @@ void _gost28147_decrypt_block (const uint32_t *key, 
const uint32_t sbox[4][256],
   *out = l, *(out + 1) = r;
 }
 
+static const uint32_t gost28147_key_mesh_cryptopro_data[GOST28147_KEY_SIZE / 
4] = {
+  0x22720069, 0x2304c964,
+  0x96db3a8d, 0xc42ae946,
+  0x94acfe18, 0x1207ed00,
+  0xc2dc86c0, 0x2ba94cef,
+};
+
+static void gost28147_key_mesh_cryptopro(struct gost28147_ctx *ctx)
+{
+  uint32_t newkey[GOST28147_KEY_SIZE/4];
+
+  _gost28147_decrypt_block(ctx->key, ctx->sbox,
+                          &gost28147_key_mesh_cryptopro_data[0],
+                          &newkey[0]);
+
+  _gost28147_decrypt_block(ctx->key, ctx->sbox,
+                          &gost28147_key_mesh_cryptopro_data[2],
+                          &newkey[2]);
+
+  _gost28147_decrypt_block(ctx->key, ctx->sbox,
+                          &gost28147_key_mesh_cryptopro_data[4],
+                          &newkey[4]);
+
+  _gost28147_decrypt_block(ctx->key, ctx->sbox,
+                          &gost28147_key_mesh_cryptopro_data[6],
+                          &newkey[6]);
+
+  memcpy(ctx->key, newkey, sizeof(newkey));
+  ctx->key_count = 0;
+}
+
 void
 gost28147_set_key(struct gost28147_ctx *ctx, const uint8_t *key)
 {
@@ -2253,6 +2293,7 @@ gost28147_set_key(struct gost28147_ctx *ctx, const 
uint8_t *key)
   assert(key);
   for (i = 0; i < 8; i++, key += 4)
     ctx->key[i] = LE_READ_UINT32(key);
+  ctx->key_count = 0;
   gost28147_set_param(ctx, &gost28147_param_TC26_Z);
 }
 
@@ -2261,6 +2302,7 @@ gost28147_set_param(struct gost28147_ctx *ctx, const 
struct gost28147_param *par
 {
   assert(param);
   ctx->sbox = param->sbox;
+  ctx->key_meshing = param->key_meshing;
 }
 
 void
@@ -2302,3 +2344,30 @@ gost28147_decrypt(const struct gost28147_ctx *ctx,
       length -= GOST28147_BLOCK_SIZE;
     }
 }
+
+void
+gost28147_encrypt_for_cfb(struct gost28147_ctx *ctx,
+                         size_t length, uint8_t *dst,
+                         const uint8_t *src)
+{
+  uint32_t block[2];
+
+  assert(!(length % GOST28147_BLOCK_SIZE));
+
+  while (length)
+    {
+      block[0] = LE_READ_UINT32(src); src += 4;
+      block[1] = LE_READ_UINT32(src); src += 4;
+      if (ctx->key_meshing && ctx->key_count == 1024)
+       {
+         gost28147_key_mesh_cryptopro(ctx);
+         _gost28147_encrypt_block(ctx->key, ctx->sbox, block, block);
+         ctx->key_count = 0;
+       }
+      _gost28147_encrypt_block(ctx->key, ctx->sbox, block, block);
+      LE_WRITE_UINT32(dst, block[0]); dst += 4;
+      LE_WRITE_UINT32(dst, block[1]); dst += 4;
+      length -= GOST28147_BLOCK_SIZE;
+      ctx->key_count += GOST28147_BLOCK_SIZE;
+    }
+}
diff --git a/gost28147.h b/gost28147.h
index 37633d9fd874..241c1e136fbc 100644
--- a/gost28147.h
+++ b/gost28147.h
@@ -53,6 +53,7 @@ extern "C" {
 #define gost28147_set_key nettle_gost28147_set_key
 #define gost28147_set_param nettle_gost28147_set_param
 #define gost28147_encrypt nettle_gost28147_encrypt
+#define gost28147_encrypt_for_cfb nettle_gost28147_encrypt_for_cfb
 #define gost28147_decrypt nettle_gost28147_decrypt
 
 #define GOST28147_KEY_SIZE 32
@@ -62,11 +63,14 @@ struct gost28147_ctx
 {
   uint32_t key[GOST28147_KEY_SIZE/4];
   const uint32_t (*sbox)[256];
+  int key_meshing;
+  int key_count; /* Used for key meshing */
 };
 
 struct gost28147_param
 {
   uint32_t sbox[4][256];
+  int key_meshing;
 };
 
 extern const struct gost28147_param gost28147_param_test_3411;
@@ -93,6 +97,10 @@ void
 gost28147_decrypt(const struct gost28147_ctx *ctx,
                  size_t length, uint8_t *dst,
                  const uint8_t *src);
+void
+gost28147_encrypt_for_cfb(struct gost28147_ctx *ctx,
+                         size_t length, uint8_t *dst,
+                         const uint8_t *src);
 
 #ifdef __cplusplus
 }
diff --git a/testsuite/gost28147-test.c b/testsuite/gost28147-test.c
index 3f8046e19e3f..939bedee9c66 100644
--- a/testsuite/gost28147-test.c
+++ b/testsuite/gost28147-test.c
@@ -1,5 +1,6 @@
 #include "testutils.h"
 #include "gost28147.h"
+#include "cfb.h"
 
 static void
 test_gost28147(const struct gost28147_param *param,
@@ -49,6 +50,60 @@ test_gost28147(const struct gost28147_param *param,
   free(data);
 }
 
+static void
+test_gost28147_cfb(const struct gost28147_param *param,
+                  const struct tstring *key,
+                  const struct tstring *iv,
+                  const struct tstring *cleartext,
+                  const struct tstring *ciphertext)
+{
+  struct ctx CFB_CTX(struct gost28147_ctx, GOST28147_BLOCK_SIZE) ctx;
+  uint8_t *data = xalloc(cleartext->length);
+  size_t length;
+
+  ASSERT (cleartext->length == ciphertext->length);
+  length = cleartext->length;
+
+  gost28147_set_key(&ctx.ctx, key->data);
+  gost28147_set_param(&ctx.ctx, param);
+  CFB_SET_IV(&ctx, iv->data);
+
+  CFB_ENCRYPT(&ctx, gost28147_encrypt_for_cfb, length,
+             data, cleartext->data);
+
+  if (!MEMEQ(length, data, ciphertext->data))
+    {
+      fprintf(stderr, "Encrypt failed:\nInput:");
+      tstring_print_hex(cleartext);
+      fprintf(stderr, "\nOutput: ");
+      print_hex(length, data);
+      fprintf(stderr, "\nExpected:");
+      tstring_print_hex(ciphertext);
+      fprintf(stderr, "\n");
+      FAIL();
+    }
+
+  gost28147_set_key(&ctx.ctx, key->data);
+  gost28147_set_param(&ctx.ctx, param);
+  CFB_SET_IV(&ctx, iv->data);
+  CFB_DECRYPT(&ctx, gost28147_encrypt_for_cfb, length,
+             data, data);
+
+  if (!MEMEQ(length, data, cleartext->data))
+    {
+      fprintf(stderr, "Decrypt failed:\nInput:");
+      tstring_print_hex(ciphertext);
+      fprintf(stderr, "\nOutput: ");
+      print_hex(length, data);
+      fprintf(stderr, "\nExpected:");
+      tstring_print_hex(cleartext);
+      fprintf(stderr, "\n");
+      FAIL();
+    }
+
+  free(data);
+}
+
 void test_main(void)
 {
   /* Examples from GOST R 34.11-94 standard */
@@ -116,4 +171,92 @@ void test_main(void)
       SHEX("ccddeeff8899aabb4455667700112233f3f2f1f0f7f6f5f4fbfaf9f8fffefdfc"),
       SHEX("1032547698badcfe"),
       SHEX("3dcad8c2e501e94e"));
+
+  test_gost28147_cfb(&gost28147_param_CryptoPro_A,
+      SHEX("8d5a2c83a7c70a61 d61b34b51fdf4268 6671a35d874cfd84 
993663b61ed60dad"),
+      SHEX("46606f0d8834235a"),
+      SHEX("d2fdf83ac1b43923 2eaacc980a02da33"),
+      SHEX("88b7751674a5ee2d 14fe9167d05ccc40"));
+
+  test_gost28147_cfb(&gost28147_param_CryptoPro_C,
+      SHEX("77c3458ef642e704 8efc08e47096d605 9359026d6f97cae9 
cf89444bde6c221d"),
+      SHEX("437c3e8e2f2a0098"),
+      SHEX("079c91be"),
+      SHEX("19358134"));
+
+  test_gost28147_cfb(&gost28147_param_CryptoPro_D,
+      SHEX("389fe837ff9c5d29 fc4855a087eae840 20875bb2011555a7 
e32dcb3dd6590473"),
+      SHEX("c5a2d21f2fdfb8eb"),
+      SHEX("2f31d883b420e86e da"),
+      SHEX("6da4ed40088871ad 16"));
+
+  test_gost28147_cfb(&gost28147_param_CryptoPro_B,
+      SHEX("480c741b026b55d5 b66dd71d4048056b 6deb3c290f848023 
ee0d4777e3fe61c9"),
+      SHEX("1f3f821e0dd81e22"),
+      SHEX("8c9c4435fbe9a5a3 a0ae285691108e1e d2bb185381270da6 
685936c581629a8e"
+          "7d50f16f976229ec 8051e37d6cc40795 2863dcb4b92db813 b105b5f9eb75374e"
+          "f7bf51f1988643c4 e43d3ea762ec4159 e0bdfbb6fdece077 13d25990a1b8976b"
+          "3d8b7dfc9dca8273 32700a7403c60c26 7f56f09db2eb7140 d7c3b1a7c51e2017"
+          "b3501d8a6e19cbbe 20862bd61cfdb4b7 5d9ab3e37d157a35 019f5d65894b34c6"
+          "f4813f7830cfe915 909af9deba63d019 14663cb9a4b28494 02cfce20cf76e7c5"
+          "48f7693a5decaf41 a7126483f5991e9e b2ab861600238ee6 d9800b6dc593e25c"
+          "8cd85e5aae4a85fd 7601ea30f3783410 7251bc9f76ce1fd4 8f335034c74d7bcf"
+          "91637d829ea12345 f545ac987a48ff64 d55947de2b3ffaec 50e081608bc3fc80"
+          "9817c7a3c2573dab 9167f5c4ab92c8d6 3b6b3fff156bcf53 6502f174caa9be24"
+          "d2f0b726a8d76ded 90367b3e41a97fa3 1bf443c551be2859 e94526493832f8f3"
+          "926e30ccb0a0f901 14c8bad9f02a29e2 529a76953a1632ec f410ecee47007019"
+          "e472356644532da2 f3aa7e8a3313cdc8 bf0e409000e442c3 0984e16617a2af03"
+          "ab6ba1ecfb177281 fe9a9ff4b2331fae 0cd16aae19b8afec e3ea00f8ac87075f"
+          "6db0ac6b224836bf 2218b0039f6c7045 36f06bc6c2a5722c d8e0273dec560705"
+          "7d83a1657d415bcd 7724e5aa7647d050 f6e7b559753127ef d8a64e7fb840b1df"
+          "5314edf1685ffc3f 02db05eb31e42c7f 32b5708e7585a45c 162337f21079cbdc"
+          "f81c25c2a13d9c33 6cedc3e7f3028782 4efbacb32dfcf80d 1d4a39d4b309bbe9"
+          "25c7ec6a877284ed 12601964eb162a5b 107627ff7be4aee5 a404027fbb0ab5f4"
+          "05a5561c53317a93 ba1615ab6260fcde 72366e28af980de6 f4de60a77e060786"
+          "f394b66d0d93a6bc 607033ac3fa1a84a 2061b6b543a3155a 00be76985772ab7a"
+          "0e1893823a18786e 717b784f7e8cde7a 62b50a7c451d16d5 c38c9b25b45090cd"
+          "9693ad0fd443cb49 0ffc5a31f419b7d4 eb4d4058d03bc8e0 4a542fdb22c3297b"
+          "40906143d37ee230 2b483cce9093b18b 3196656d578b9d4d 53f0831ce5a19d55"
+          "e3bf7eca1a746614 cc4743d9bbef977d b76efff122f8102d 3fcd4996d90911b8"
+          "33d0239afa16cb50 2657245c0ebaf03f 372fa3f718574848 95cfef87672ae9b6"
+          "8a21367fff486c46 3557f2bc48678f63 2378112bc208de51 e88b9229f99a9ead"
+          "ed0feba2d24092d4 de629576fd6e3cbf c0d70de51ba4c718 e158a456ef2e171b"
+          "75cbbcf92a9571a7 1d7fe77363056b19 4cf42214c4598866 9286615c6aaeec58"
+          "ffc9f244d4a2f598 eb5f09bc8abf3cb4 3eb120054496790a 40927f9dd1afbc90"
+          "950a81d4a7c6b8e0 e439301d79c0e5fa b4e963b409723b3e d9f6d91021187ee5"
+          "ad81d7d582d08c3b 3895f89201a99200 70d1a788771f3aeb b5e4f59dc73786b2"
+          "12463419728cf58c f67898e07cd3f4"),
+      SHEX("23c67f20a12358bc 7b05db2115cf9641 c788ef765c49db42 
bff3c0f5bd5dd98e"
+          "af3df4e4da88bdbc 475d7607c95f541d 1d6aa12e18d66084 021837929215ab21"
+          "ee21cc716e51d92b cc81973feb4599b8 1bdaff90d341069c 3ffbe4b2dcc9030d"
+          "a7aed77d02b832ab f365a3656c4ee4a2 5e9eeecdde79366b 1be13cdf10ad4f02"
+          "e114aa09b40b76eb 69382002cb8ec0df ca4874c331ad422c 519bd06ac136d721"
+          "dfb045baca7f3520 28bbc176fd435d23 7d31841a974d83aa 7ef1c4e683ac0def"
+          "ef3ca47c48e4c8ca 0d7dea7c45d77350 251d01c4021acde0 385ba85a169a1059"
+          "74d719c6f3b517f6 598d62af44e8dce9 c176f1d0bd29d7ec 1dac57db1a3fd8f6"
+          "6eb6e6df36e789ce 5635431c7d57790e d8f4d7a70dc68f91 6667820f49c9c565"
+          "81a1395a539f02a5 d53622a8a81c370e 7646dfbd6adbfc1b bd10b8b1bc724c58"
+          "4ada6d6600da7a66 a0e73b39a3f70507 fa214bc794c0d37b 19025d4a10f1c20f"
+          "196827c77dbf5503 577daf77ae802f7a e61f4bdc1518c062 a1e8d91c9e8c9639"
+          "c1c488f70ce10484 6851cef190da7f76 c8c088ef8e15253e 7be479b5662d9cd1"
+          "13dad0d546d58d46 1807eed8c964e3be 0e6827099626f6e2 19613ff458270aeb"
+          "ce7cb66892e7123b 31d448df358df486 422a154be8191f26 659ba8da4b791f8e"
+          "e6137e498fc1cedc 5e6474ce0278e0cf a0ed5e3174d1d0b4 ee7019143c8f16a6"
+          "cf12931588eb9165 7698fda19430ba43 62654004779ed6ab 8b0d9380505fa276"
+          "20a7d69c271527bc a55abfe9928205a8 41e9b560d5c0d74b ad38b2e9d1e5515f"
+          "2478249a23d2c248 bd0ef137729187b0 4ebd996b2c01b679 69ec0cede53f5064"
+          "7cb9dde19281b5d0 cb1783868bea4f93 08bc220cefe80df5 9e23e1f9b76b450b"
+          "cba9b64d2825ba3e 86f275475d9d6bf6 8a0558733d00defd 69b16116f52eb09f"
+          "316a00b9ef716347 a3cae040a87e0204 fee5ce4873e394cf e2ff297ef632bbb7"
+          "5512217a9c75040c b47cb03d40b3119a 7a9a13fb77a75168 f705473b0f525ce6"
+          "c2993a37545c4f2b a7010874bc91e3e2 fe6594fd3d18e0f0 62edc210829c587f"
+          "b2a3878a74d9c1fb 842817c72bcb531f 4e8a82fcb43fc147 25f321dc4c2d08fa"
+          "e70f03a968de6b41 a0f9416c574d3a0e ea51ca9f97117df6 8e886367c96513ca"
+          "38ed35bef427a9fc a9e6c34086083972 37eeb2870996b740 873692c15d6a2c43"
+          "ca25c835372db5a9 274450f26d227541 772adbb18c6d05e8 c999c708f9148f78"
+          "a98fc25a7a65c5d8 86bb72696b6b4583 5bb1f7cd1673eee9 8085fe8ee1ae538f"
+          "debe488b59eff67e d8b5a847c04e1558 cad32ff86ca63d78 4d7a54d610e5cc05"
+          "e229b58607397d78 8e5a8f834ce73d68 3ee502e6644f5eb4 4977f0c0fa6fc8fb"
+          "9f846f55fb305e89 93a9f3a6a3d726bb d8a8d9951dfefcd7 a893662f04530664"
+          "7f3129aeb79fbac4 6d68d12432f411"));
 }
-- 
2.23.0

_______________________________________________
nettle-bugs mailing list
nettle-bugs@lists.lysator.liu.se
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to