summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2018-06-14 15:37:20 +0300
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-09-28 14:18:46 +0300
commitc589e198b34d2244dc233b44aec38a72842f953d (patch)
treee9917817af84a2df469b73a58b63147eafd1347a
parentea536f9fc678592e756e6c0feb41602daea08e81 (diff)
downloadgnutls-c589e198b34d2244dc233b44aec38a72842f953d.tar.gz
nettle: provide GOST 28147-89 IMIT MAC support
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
-rw-r--r--devel/libgnutls-latest-x86_64.abi1
-rw-r--r--lib/algorithms/mac.c5
-rw-r--r--lib/includes/gnutls/gnutls.h.in2
-rw-r--r--lib/nettle/gost/gost28147.c99
-rw-r--r--lib/nettle/gost/gost28147.h46
-rw-r--r--lib/nettle/mac.c19
6 files changed, 172 insertions, 0 deletions
diff --git a/devel/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi
index f76c3ed7c7..7198fa4632 100644
--- a/devel/libgnutls-latest-x86_64.abi
+++ b/devel/libgnutls-latest-x86_64.abi
@@ -1552,6 +1552,7 @@
<enumerator name='GNUTLS_MAC_AES_GMAC_128' value='205'/>
<enumerator name='GNUTLS_MAC_AES_GMAC_192' value='206'/>
<enumerator name='GNUTLS_MAC_AES_GMAC_256' value='207'/>
+ <enumerator name='GNUTLS_MAC_GOST28147_TC26Z_IMIT' value='208'/>
</enum-decl>
<typedef-decl name='gnutls_mac_algorithm_t' type-id='type-id-44' id='type-id-31'/>
<enum-decl name='__anonymous_enum__' is-anonymous='yes' id='type-id-45'>
diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c
index ddbba2f453..fc2e99b186 100644
--- a/lib/algorithms/mac.c
+++ b/lib/algorithms/mac.c
@@ -177,6 +177,11 @@ mac_entry_st hash_algorithms[] = {
.output_size = 16,
.key_size = 32,
.nonce_size = 12},
+ {.name = "GOST28147-TC26Z-IMIT",
+ .id = GNUTLS_MAC_GOST28147_TC26Z_IMIT,
+ .output_size = 4,
+ .key_size = 32,
+ .block_size = 8},
{.name = "MAC-NULL",
.id = GNUTLS_MAC_NULL},
{0, 0, 0, 0, 0, 0, 0, 0, 0}
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index fa16dd9a7a..6b35c44342 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -291,6 +291,7 @@ typedef enum {
* @GNUTLS_MAC_SHA3_256: Reserved; unimplemented.
* @GNUTLS_MAC_SHA3_384: Reserved; unimplemented.
* @GNUTLS_MAC_SHA3_512: Reserved; unimplemented.
+ * @GNUTLS_MAC_GOST28147_TC26Z_IMIT: The GOST 28147-89 working in IMIT mode with TC26 Z S-box.
*
* Enumeration of different Message Authentication Code (MAC)
* algorithms.
@@ -324,6 +325,7 @@ typedef enum {
GNUTLS_MAC_AES_GMAC_128 = 205,
GNUTLS_MAC_AES_GMAC_192 = 206,
GNUTLS_MAC_AES_GMAC_256 = 207,
+ GNUTLS_MAC_GOST28147_TC26Z_IMIT = 208,
} gnutls_mac_algorithm_t;
/**
diff --git a/lib/nettle/gost/gost28147.c b/lib/nettle/gost/gost28147.c
index f7a67138a4..da8ec9ef14 100644
--- a/lib/nettle/gost/gost28147.c
+++ b/lib/nettle/gost/gost28147.c
@@ -2244,6 +2244,23 @@ static void gost28147_decrypt_simple (const uint32_t *key, const uint32_t *sbox,
*out = l, *(out + 1) = r;
}
+static void gost28147_imit_simple (const uint32_t *key, const uint32_t *sbox,
+ const uint32_t *in, uint32_t *out)
+{
+ uint32_t l, r, tmp;
+
+ r = in[0], l = in[1];
+ GOST_ENCRYPT_ROUND(key[0], key[1], sbox)
+ GOST_ENCRYPT_ROUND(key[2], key[3], sbox)
+ GOST_ENCRYPT_ROUND(key[4], key[5], sbox)
+ GOST_ENCRYPT_ROUND(key[6], key[7], sbox)
+ GOST_ENCRYPT_ROUND(key[0], key[1], sbox)
+ GOST_ENCRYPT_ROUND(key[2], key[3], sbox)
+ GOST_ENCRYPT_ROUND(key[4], key[5], sbox)
+ GOST_ENCRYPT_ROUND(key[6], key[7], sbox)
+ *out = r, *(out + 1) = l;
+}
+
static const uint32_t gost28147_key_mesh_cryptopro_data[GOST28147_KEY_SIZE / 4] = {
0x22720069, 0x2304c964,
0x96db3a8d, 0xc42ae946,
@@ -2452,4 +2469,86 @@ gost28147_cnt_crypt(struct gost28147_cnt_ctx *ctx,
ctx->bytes = block_size - length;
}
}
+
+void
+gost28147_imit_init(struct gost28147_imit_ctx *ctx)
+{
+ memset(ctx->state, 0, GOST28147_BLOCK_SIZE);
+ ctx->index = 0;
+ ctx->count = 0;
+ gost28147_set_param(&ctx->cctx, &gost28147_param_TC26_Z); /* Default */
+}
+
+void
+gost28147_imit_set_key(struct gost28147_imit_ctx *ctx,
+ size_t length,
+ const uint8_t *key)
+{
+ assert(length == GOST28147_IMIT_KEY_SIZE);
+ assert(key);
+
+ _gost28147_set_key(&ctx->cctx, key);
+ /* Do not reset param here */
+}
+
+void
+gost28147_imit_set_nonce(struct gost28147_imit_ctx *ctx, const uint8_t *nonce)
+{
+ ctx->state[0] = LE_READ_UINT32(nonce + 0);
+ ctx->state[1] = LE_READ_UINT32(nonce + 4);
+}
+
+void
+gost28147_imit_set_param(struct gost28147_imit_ctx *ctx,
+ const struct gost28147_param *param)
+{
+ assert(param);
+ gost28147_set_param(&ctx->cctx, param);
+}
+
+static void
+gost28147_imit_compress(struct gost28147_imit_ctx *ctx,
+ const uint8_t *data)
+{
+ uint32_t block[2];
+
+ if (ctx->cctx.key_meshing && ctx->cctx.key_count == 1024)
+ gost28147_key_mesh_cryptopro(&ctx->cctx);
+
+ block[0] = LE_READ_UINT32(data + 0) ^ ctx->state[0];
+ block[1] = LE_READ_UINT32(data + 4) ^ ctx->state[1];
+ gost28147_imit_simple(ctx->cctx.key, ctx->cctx.sbox, block, ctx->state);
+ ctx->cctx.key_count += 8;
+}
+
+void
+gost28147_imit_update(struct gost28147_imit_ctx *ctx,
+ size_t length,
+ const uint8_t *data)
+{
+ MD_UPDATE(ctx, length, data, gost28147_imit_compress, ctx->count++);
+}
+
+void
+gost28147_imit_digest(struct gost28147_imit_ctx *ctx,
+ size_t length,
+ uint8_t *digest)
+{
+ assert(length <= GOST28147_IMIT_DIGEST_SIZE);
+ const uint8_t zero[GOST28147_IMIT_BLOCK_SIZE] = { 0 };
+
+ if (ctx->index)
+ {
+ assert(ctx->index < GOST28147_IMIT_BLOCK_SIZE);
+ gost28147_imit_update(ctx, GOST28147_IMIT_BLOCK_SIZE - ctx->index, zero);
+ }
+
+ if (ctx->count == 1)
+ {
+ gost28147_imit_update(ctx, GOST28147_IMIT_BLOCK_SIZE, zero);
+ }
+
+ _nettle_write_le32(length, digest, ctx->state);
+ gost28147_imit_init(ctx);
+}
#endif
diff --git a/lib/nettle/gost/gost28147.h b/lib/nettle/gost/gost28147.h
index 0e68db34ca..5fbab90ef1 100644
--- a/lib/nettle/gost/gost28147.h
+++ b/lib/nettle/gost/gost28147.h
@@ -69,6 +69,13 @@ extern "C" {
#define gost28147_cnt_set_iv _gnutls_gost28147_cnt_set_iv
#define gost28147_cnt_crypt _gnutls_gost28147_cnt_crypt
+#define gost28147_imit_init _gnutls_gost28147_imit_init
+#define gost28147_imit_set_key _gnutls_gost28147_imit_set_key
+#define gost28147_imit_set_nonce _gnutls_gost28147_imit_set_nonce
+#define gost28147_imit_set_param _gnutls_gost28147_imit_set_param
+#define gost28147_imit_update _gnutls_gost28147_imit_update
+#define gost28147_imit_digest _gnutls_gost28147_imit_digest
+
#define GOST28147_KEY_SIZE 32
#define GOST28147_BLOCK_SIZE 8
@@ -140,6 +147,45 @@ gost28147_cnt_crypt(struct gost28147_cnt_ctx *ctx,
size_t length, uint8_t *dst,
const uint8_t *src);
+#define GOST28147_IMIT_DIGEST_SIZE 4
+#define GOST28147_IMIT_BLOCK_SIZE GOST28147_BLOCK_SIZE
+#define GOST28147_IMIT_KEY_SIZE GOST28147_KEY_SIZE
+
+struct gost28147_imit_ctx
+{
+ struct gost28147_ctx cctx;
+ uint64_t count; /* Block count */
+ uint8_t block[GOST28147_IMIT_BLOCK_SIZE]; /* Block buffer */
+ unsigned index; /* Into buffer */
+ uint32_t state[GOST28147_IMIT_BLOCK_SIZE/4];
+};
+
+void
+gost28147_imit_init(struct gost28147_imit_ctx *ctx);
+
+void
+gost28147_imit_set_key(struct gost28147_imit_ctx *ctx,
+ size_t length,
+ const uint8_t *key);
+
+void
+gost28147_imit_set_nonce(struct gost28147_imit_ctx *ctx,
+ const uint8_t *nonce);
+
+void
+gost28147_imit_set_param(struct gost28147_imit_ctx *ctx,
+ const struct gost28147_param *param);
+
+void
+gost28147_imit_update(struct gost28147_imit_ctx *ctx,
+ size_t length,
+ const uint8_t *data);
+
+void
+gost28147_imit_digest(struct gost28147_imit_ctx *ctx,
+ size_t length,
+ uint8_t *digest);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/nettle/mac.c b/lib/nettle/mac.c
index b6c0bce85d..ac3140fcfb 100644
--- a/lib/nettle/mac.c
+++ b/lib/nettle/mac.c
@@ -39,6 +39,7 @@
#endif
#ifndef HAVE_NETTLE_STREEBOG512_UPDATE
#include "gost/streebog.h"
+#include "gost/gost28147.h"
#endif
#endif
#ifdef HAVE_NETTLE_CMAC128_UPDATE
@@ -113,6 +114,7 @@ struct nettle_mac_ctx {
struct hmac_gosthash94cp_ctx gosthash94cp;
struct hmac_streebog256_ctx streebog256;
struct hmac_streebog512_ctx streebog512;
+ struct gost28147_imit_ctx gost28147_imit;
#endif
struct umac96_ctx umac96;
struct umac128_ctx umac128;
@@ -130,6 +132,15 @@ struct nettle_mac_ctx {
set_nonce_func set_nonce;
};
+#if ENABLE_GOST
+static void
+_wrap_gost28147_imit_set_key_tc26z(void *ctx, size_t len, const uint8_t * key)
+{
+ gost28147_imit_set_key(ctx, len, key);
+ gost28147_imit_set_param(ctx, &gost28147_param_TC26_Z);
+}
+#endif
+
static void
_wrap_umac96_set_key(void *ctx, size_t len, const uint8_t * key)
{
@@ -316,6 +327,13 @@ static int _mac_ctx_init(gnutls_mac_algorithm_t algo,
ctx->ctx_ptr = &ctx->ctx.streebog512;
ctx->length = STREEBOG512_DIGEST_SIZE;
break;
+ case GNUTLS_MAC_GOST28147_TC26Z_IMIT:
+ ctx->update = (update_func) gost28147_imit_update;
+ ctx->digest = (digest_func) gost28147_imit_digest;
+ ctx->set_key = _wrap_gost28147_imit_set_key_tc26z;
+ ctx->ctx_ptr = &ctx->ctx.gost28147_imit;
+ ctx->length = GOST28147_IMIT_DIGEST_SIZE;
+ break;
#endif
case GNUTLS_MAC_UMAC_96:
ctx->update = (update_func) umac96_update;
@@ -430,6 +448,7 @@ static int wrap_nettle_mac_exists(gnutls_mac_algorithm_t algo)
case GNUTLS_MAC_GOSTR_94:
case GNUTLS_MAC_STREEBOG_256:
case GNUTLS_MAC_STREEBOG_512:
+ case GNUTLS_MAC_GOST28147_TC26Z_IMIT:
#endif
return 1;
default: