Signed-off-by: Dmitry Baryshkov <[email protected]>
---
 Makefile.in                |  2 +-
 gost28147-params.c         | 11 +++++
 gost28147.c                | 86 ++++++++++++++++++++++++++++++++++++++
 gost28147.h                | 85 +++++++++++++++++++++++++++++++++++++
 testsuite/Makefile.in      |  2 +-
 testsuite/gost28147-test.c | 77 ++++++++++++++++++++++++++++++++++
 6 files changed, 261 insertions(+), 2 deletions(-)
 create mode 100644 gost28147.h
 create mode 100644 testsuite/gost28147-test.c

diff --git a/Makefile.in b/Makefile.in
index 41e0389f2979..d4bec88615ed 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -211,7 +211,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
          cbc.h ccm.h cfb.h chacha.h chacha-poly1305.h ctr.h \
          curve25519.h curve448.h des.h dsa.h dsa-compat.h eax.h \
          ecc-curve.h ecc.h ecdsa.h eddsa.h \
-         gcm.h gostdsa.h gosthash94.h hmac.h \
+         gcm.h gost28147.h gostdsa.h gosthash94.h hmac.h \
          knuth-lfib.h hkdf.h \
          macros.h \
          cmac.h siv-cmac.h \
diff --git a/gost28147-params.c b/gost28147-params.c
index 6addec31f170..7489641ba5a1 100644
--- a/gost28147-params.c
+++ b/gost28147-params.c
@@ -33,6 +33,7 @@
 #endif
 
 #include "macros.h"
+#include "gost28147.h"
 #include "gost28147-internal.h"
 
 /* pre-initialized GOST lookup tables based on rotated S-Box */
@@ -569,3 +570,13 @@ const struct gost28147_param 
_gost28147_param_CryptoPro_3411 =
     }
   }
 };
+
+const struct gost28147_param * gost28147_get_param_test_3411 (void)
+{
+  return &_gost28147_param_test_3411;
+}
+
+const struct gost28147_param * gost28147_get_param_CryptoPro_3411 (void)
+{
+  return &_gost28147_param_CryptoPro_3411;
+}
diff --git a/gost28147.c b/gost28147.c
index 669fc85d2083..9525b41b148b 100644
--- a/gost28147.c
+++ b/gost28147.c
@@ -32,7 +32,10 @@
 #include "config.h"
 #endif
 
+#include <assert.h>
+
 #include "macros.h"
+#include "gost28147.h"
 #include "gost28147-internal.h"
 
 /*
@@ -79,3 +82,86 @@ void _gost28147_encrypt_block (const uint32_t *key, const 
uint32_t sbox[4][256],
   GOST_ENCRYPT_ROUND(l, r, key[1], key[0], sbox);
   *out = l, *(out + 1) = r;
 }
+
+static
+void _gost28147_decrypt_block (const uint32_t *key, const uint32_t 
sbox[4][256],
+                              const uint32_t *in, uint32_t *out)
+{
+  uint32_t l, r;
+
+  r = in[0], l = in[1];
+  GOST_ENCRYPT_ROUND(l, r, key[0], key[1], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[2], key[3], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[4], key[5], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[6], key[7], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[7], key[6], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[5], key[4], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[3], key[2], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[1], key[0], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[7], key[6], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[5], key[4], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[3], key[2], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[1], key[0], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[7], key[6], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[5], key[4], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[3], key[2], sbox);
+  GOST_ENCRYPT_ROUND(l, r, key[1], key[0], sbox);
+  *out = l, *(out + 1) = r;
+}
+
+void
+gost28147_set_key(struct gost28147_ctx *ctx, const uint8_t *key)
+{
+  unsigned i;
+
+  assert(key);
+  for (i = 0; i < 8; i++, key += 4)
+    ctx->key[i] = LE_READ_UINT32(key);
+}
+
+void
+gost28147_set_param(struct gost28147_ctx *ctx, const struct gost28147_param 
*param)
+{
+  assert(param);
+  ctx->sbox = param->sbox;
+}
+
+void
+gost28147_encrypt(const 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;
+      _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;
+    }
+}
+
+void
+gost28147_decrypt(const 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;
+      _gost28147_decrypt_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;
+    }
+}
diff --git a/gost28147.h b/gost28147.h
new file mode 100644
index 000000000000..0df1662ce86d
--- /dev/null
+++ b/gost28147.h
@@ -0,0 +1,85 @@
+/* gost28147.h
+
+   The GOST 28147-89 cipher function, described in RFC 5831.
+
+   Copyright (C) 2020 Dmitry Baryshkov
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef NETTLE_GOST28147_H_INCLUDED
+#define NETTLE_GOST28147_H_INCLUDED
+
+#include "nettle-types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define gost28147_get_param_test_3411 nettle_gost28147_get_param_test_3411
+#define gost28147_get_param_CryptoPro_3411 
nettle_gost28147_get_param_CryptoPro_3411
+
+#define gost28147_set_key nettle_gost28147_set_key
+#define gost28147_set_param nettle_gost28147_set_param
+#define gost28147_encrypt nettle_gost28147_encrypt
+#define gost28147_decrypt nettle_gost28147_decrypt
+
+#define GOST28147_KEY_SIZE 32
+#define GOST28147_BLOCK_SIZE 8
+
+struct gost28147_ctx
+{
+  uint32_t key[GOST28147_KEY_SIZE/4];
+  const uint32_t (*sbox)[256];
+};
+
+struct gost28147_param;
+
+const struct gost28147_param * gost28147_get_param_test_3411 (void);
+const struct gost28147_param * gost28147_get_param_CryptoPro_3411 (void);
+
+void
+gost28147_set_key(struct gost28147_ctx *ctx, const uint8_t *key);
+
+void
+gost28147_set_param(struct gost28147_ctx *ctx,
+                   const struct gost28147_param *param);
+
+void
+gost28147_encrypt(const struct gost28147_ctx *ctx,
+                 size_t length, uint8_t *dst,
+                 const uint8_t *src);
+void
+gost28147_decrypt(const struct gost28147_ctx *ctx,
+                 size_t length, uint8_t *dst,
+                 const uint8_t *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_GOST28147_H_INCLUDED */
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 3f5e5f6b995c..07dd0ecf3e8d 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -17,7 +17,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
                    cnd-memcpy-test.c \
                    des-test.c des3-test.c \
                    md2-test.c md4-test.c md5-test.c md5-compat-test.c \
-                   memeql-test.c memxor-test.c gosthash94-test.c \
+                   memeql-test.c memxor-test.c gost28147-test.c 
gosthash94-test.c \
                    ripemd160-test.c hkdf-test.c \
                    salsa20-test.c \
                    sha1-test.c sha224-test.c sha256-test.c \
diff --git a/testsuite/gost28147-test.c b/testsuite/gost28147-test.c
new file mode 100644
index 000000000000..ee9615b15cf2
--- /dev/null
+++ b/testsuite/gost28147-test.c
@@ -0,0 +1,77 @@
+#include "testutils.h"
+#include "gost28147.h"
+#include "cfb.h"
+#include "macros.h"
+
+static void
+test_gost28147(const struct gost28147_param *param,
+              const struct tstring *key,
+              const struct tstring *cleartext,
+              const struct tstring *ciphertext)
+{
+  struct gost28147_ctx ctx;
+  uint8_t *data = xalloc(cleartext->length);
+  size_t length;
+
+  ASSERT (cleartext->length == ciphertext->length);
+  length = cleartext->length;
+
+  gost28147_set_param(&ctx, param);
+  gost28147_set_key(&ctx, key->data);
+  gost28147_encrypt(&ctx, 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_param(&ctx, param);
+  gost28147_set_key(&ctx, key->data);
+  gost28147_decrypt(&ctx, 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, see RFC 5831, Section 7.3.1.
+   * Exaples there are represented in different endianness */
+  test_gost28147(gost28147_get_param_test_3411(),
+      SHEX("546D2033 68656C32 69736520 73736E62 20616779 69677474 73656865 
202C3D73"),
+      SHEX("00000000 00000000"),
+      SHEX("1B0BBC32 CEBCAB42"));
+
+  test_gost28147(gost28147_get_param_test_3411(),
+      SHEX("2033394D 6C320D09 65201A16 6E62001D 67794106 74740E13 6865160D 
3D730C11"),
+      SHEX("00000000 00000000"),
+      SHEX("FDCF9B5D C8EB0352"));
+
+  test_gost28147(gost28147_get_param_test_3411(),
+      SHEX("39B213F5 F209A13F 1AE9BA3A FF1D0C62 41F9E1C7 F1130085 16F20D73 
F311B180"),
+      SHEX("00000000 00000000"),
+      SHEX("280EFF00 9958348D"));
+
+  test_gost28147(gost28147_get_param_test_3411(),
+      SHEX("EC0A8BA1 5EC004A8 BAC50CAC 0C621DEE E1C7B8E7 007AE2EC F2731BFF 
4E80E2A0 "),
+      SHEX("00000000 00000000"),
+      SHEX("2D562A0D 190486E7 "));
+}
-- 
2.27.0

_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to