]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
nettle: provide GOST 28147-89 CNT mode support
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Thu, 14 Jun 2018 12:36:55 +0000 (15:36 +0300)
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Sat, 28 Sep 2019 11:18:46 +0000 (14:18 +0300)
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
devel/libgnutls-latest-x86_64.abi
lib/algorithms/ciphers.c
lib/includes/gnutls/gnutls.h.in
lib/nettle/cipher.c
lib/nettle/gost/gost28147.c
lib/nettle/gost/gost28147.h

index 49044fe9380f0b4563f3ef21d37327f409d82a71..f76c3ed7c794e35659141438812bef4811cc9917 100644 (file)
       <enumerator name='GNUTLS_CIPHER_AES_256_CFB8' value='31'/>
       <enumerator name='GNUTLS_CIPHER_AES_128_XTS' value='32'/>
       <enumerator name='GNUTLS_CIPHER_AES_256_XTS' value='33'/>
+      <enumerator name='GNUTLS_CIPHER_GOST28147_TC26Z_CNT' value='34'/>
       <enumerator name='GNUTLS_CIPHER_IDEA_PGP_CFB' value='200'/>
       <enumerator name='GNUTLS_CIPHER_3DES_PGP_CFB' value='201'/>
       <enumerator name='GNUTLS_CIPHER_CAST5_PGP_CFB' value='202'/>
index 6f503fd0b2426f67863de8831e146318da7cd464..aab370812899f7c2c1d1502deadd1ab2204652fb 100644 (file)
@@ -255,6 +255,13 @@ static const cipher_entry_st algorithms[] = {
          .type = CIPHER_BLOCK,
          .explicit_iv = 16,
          .cipher_iv = 16},
+       { .name = "GOST28147-TC26Z-CNT",
+         .id = GNUTLS_CIPHER_GOST28147_TC26Z_CNT,
+         .blocksize = 8,
+         .keysize = 32,
+         .type = CIPHER_STREAM,
+         .implicit_iv = 8,
+         .cipher_iv = 8},
        { .name = "3DES-CBC",
          .id = GNUTLS_CIPHER_3DES_CBC,
          .blocksize = 8,
index f5a5a66acb723002ae3a618478b3802b0c0facf9..fa16dd9a7a2ff1cbc538103062d7a8bff4c11245 100644 (file)
@@ -125,6 +125,7 @@ extern "C" {
  *                             The whole message needs to be provided with a single call, because
  *                             cipher-stealing requires to know where the message actually terminates
  *                             in order to be able to compute where the stealing occurs.
+ * @GNUTLS_CIPHER_GOST28147_TC26Z_CNT: GOST 28147-89 (Magma) cipher in CNT mode with TC26 Z S-box.
  * @GNUTLS_CIPHER_IDEA_PGP_CFB: IDEA in CFB mode (placeholder - unsupported).
  * @GNUTLS_CIPHER_3DES_PGP_CFB: 3DES in CFB mode (placeholder - unsupported).
  * @GNUTLS_CIPHER_CAST5_PGP_CFB: CAST5 in CFB mode (placeholder - unsupported).
@@ -172,6 +173,7 @@ typedef enum gnutls_cipher_algorithm {
        GNUTLS_CIPHER_AES_256_CFB8 = 31,
        GNUTLS_CIPHER_AES_128_XTS = 32,
        GNUTLS_CIPHER_AES_256_XTS = 33,
+       GNUTLS_CIPHER_GOST28147_TC26Z_CNT = 34,
 
        /* used only for PGP internals. Ignored in TLS/SSL
         */
index 09032f353d6ddad16856463f537e8ab53f71f0fd..28f676a480504f64f4ab82796a9d5e1892657522 100644 (file)
@@ -197,6 +197,25 @@ _gost28147_set_key_cpd(void *ctx, const uint8_t *key)
        gost28147_set_key(ctx, key);
        gost28147_set_param(ctx, &gost28147_param_CryptoPro_D);
 }
+
+static void
+_gost28147_cnt_set_key_tc26z(void *ctx, const uint8_t *key)
+{
+       gost28147_cnt_init(ctx, key, &gost28147_param_TC26_Z);
+}
+
+static void
+_gost28147_cnt_set_nonce (void *ctx, size_t length, const uint8_t *nonce)
+{
+       gost28147_cnt_set_iv (ctx, nonce);
+}
+
+static void
+_gost28147_cnt_crypt(struct nettle_cipher_ctx *ctx, size_t length, uint8_t * dst,
+                    const uint8_t * src)
+{
+       gost28147_cnt_crypt((void *)ctx->ctx_ptr, length, dst, src);
+}
 #endif
 
 static void
@@ -670,6 +689,20 @@ static const struct nettle_cipher_st builtin_ciphers[] = {
           .set_encrypt_key = _gost28147_set_key_cpd,
           .set_decrypt_key = _gost28147_set_key_cpd,
        },
+       {
+          .algo = GNUTLS_CIPHER_GOST28147_TC26Z_CNT,
+          .block_size = GOST28147_BLOCK_SIZE,
+          .key_size = GOST28147_KEY_SIZE,
+          .encrypt_block = (nettle_cipher_func*)gost28147_encrypt, /* unused */
+          .decrypt_block = (nettle_cipher_func*)gost28147_decrypt, /* unused */
+
+          .ctx_size = sizeof(struct gost28147_cnt_ctx),
+          .encrypt = _gost28147_cnt_crypt,
+          .decrypt = _gost28147_cnt_crypt,
+          .set_encrypt_key = _gost28147_cnt_set_key_tc26z,
+          .set_decrypt_key = _gost28147_cnt_set_key_tc26z,
+          .set_iv = (setiv_func)_gost28147_cnt_set_nonce,
+       },
 #endif
        {  .algo = GNUTLS_CIPHER_AES_128_CFB8,
           .block_size = AES_BLOCK_SIZE,
index 0b047242f2de15ba35d9f2cb0b7dc933775fa4f8..f7a67138a4e929ab540efbe4ec17c13c9d1c4470 100644 (file)
@@ -2367,4 +2367,89 @@ gost28147_encrypt_for_cfb(struct gost28147_ctx *ctx,
       ctx->key_count += GOST28147_BLOCK_SIZE;
     }
 }
+
+static void
+gost28147_cnt_next_iv(struct gost28147_cnt_ctx *ctx,
+                     uint8_t *out)
+{
+  uint32_t block[2];
+  uint32_t temp;
+
+  if (ctx->ctx.key_meshing && ctx->ctx.key_count == 1024)
+    {
+      gost28147_key_mesh_cryptopro(&ctx->ctx);
+      gost28147_encrypt_simple(ctx->ctx.key, ctx->ctx.sbox, ctx->iv, ctx->iv);
+      ctx->ctx.key_count = 0;
+    }
+
+  ctx->iv[0] += 0x01010101;
+  temp = ctx->iv[1] + 0x01010104;
+  if (temp < ctx->iv[1])
+    ctx->iv[1] = temp + 1; /* Overflow */
+  else
+    ctx->iv[1] = temp;
+
+  gost28147_encrypt_simple(ctx->ctx.key, ctx->ctx.sbox, ctx->iv, block);
+
+  LE_WRITE_UINT32(out + 0, block[0]);
+  LE_WRITE_UINT32(out + 4, block[1]);
+
+  ctx->ctx.key_count += GOST28147_BLOCK_SIZE;
+}
+
+void
+gost28147_cnt_init(struct gost28147_cnt_ctx *ctx,
+                  const uint8_t *key,
+                  const struct gost28147_param *param)
+{
+  gost28147_set_key(&ctx->ctx, key);
+  gost28147_set_param(&ctx->ctx, param);
+  ctx->bytes = 0;
+}
+
+void
+gost28147_cnt_set_iv(struct gost28147_cnt_ctx *ctx,
+                    const uint8_t *iv)
+{
+  uint32_t block[2];
+
+  block[0] = LE_READ_UINT32(iv + 0);
+  block[1] = LE_READ_UINT32(iv + 4);
+
+  gost28147_encrypt_simple(ctx->ctx.key, ctx->ctx.sbox, block, ctx->iv);
+}
+
+void
+gost28147_cnt_crypt(struct gost28147_cnt_ctx *ctx,
+                   size_t length, uint8_t *dst,
+                   const uint8_t *src)
+{
+  size_t block_size = GOST28147_BLOCK_SIZE;
+
+  if (ctx->bytes)
+    {
+      size_t part = ctx->bytes < length ? ctx->bytes : length;
+      memxor3(dst, src, ctx->buffer + block_size - ctx->bytes, part);
+      dst += part;
+      src += part;
+      length -= part;
+      ctx->bytes -= part;
+      ctx->bytes %= block_size;
+    }
+  while (length >= block_size)
+    {
+      gost28147_cnt_next_iv(ctx, ctx->buffer);
+      memxor3(dst, src, ctx->buffer, block_size);
+      length -= block_size;
+      src += block_size;
+      dst += block_size;
+    }
+
+  if (length != 0)
+    {
+      gost28147_cnt_next_iv(ctx, ctx->buffer);
+      memxor3(dst, src, ctx->buffer, length);
+      ctx->bytes = block_size - length;
+    }
+}
 #endif
index 7329d2ed8bf3e403c8e738c44b1f753070b758d3..0e68db34ca445e5d2778bbf9f257dcf099bafa99 100644 (file)
@@ -65,6 +65,10 @@ extern "C" {
 #define gost28147_encrypt_for_cfb _gnutls_gost28147_encrypt_for_cfb
 #define gost28147_decrypt _gnutls_gost28147_decrypt
 
+#define gost28147_cnt_init _gnutls_gost28147_cnt_init
+#define gost28147_cnt_set_iv _gnutls_gost28147_cnt_set_iv
+#define gost28147_cnt_crypt _gnutls_gost28147_cnt_crypt
+
 #define GOST28147_KEY_SIZE 32
 #define GOST28147_BLOCK_SIZE 8
 
@@ -115,6 +119,27 @@ gost28147_encrypt_for_cfb(struct gost28147_ctx *ctx,
                          size_t length, uint8_t *dst,
                          const uint8_t *src);
 
+struct gost28147_cnt_ctx {
+  struct gost28147_ctx ctx;
+  size_t bytes;
+  uint32_t iv[2];
+  uint8_t buffer[GOST28147_BLOCK_SIZE];
+};
+
+void
+gost28147_cnt_init(struct gost28147_cnt_ctx *ctx,
+                  const uint8_t *key,
+                  const struct gost28147_param *param);
+
+void
+gost28147_cnt_set_iv(struct gost28147_cnt_ctx *ctx,
+                    const uint8_t *iv);
+
+void
+gost28147_cnt_crypt(struct gost28147_cnt_ctx *ctx,
+                   size_t length, uint8_t *dst,
+                   const uint8_t *src);
+
 #ifdef __cplusplus
 }
 #endif