summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-09-28 18:24:56 +0000
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-09-28 18:24:56 +0000
commit477d44b3a3afffd05b275b9d40e4e66c6b55d68c (patch)
treec2b20e9721de325e2454ebd5e54d0b07cf7a4446
parent320137bf17c6ba80b7b866339e9aaf9ef558ad57 (diff)
parent2902a436cb0fbb3d9706a182c87d2625fed0c3d9 (diff)
downloadgnutls-477d44b3a3afffd05b275b9d40e4e66c6b55d68c.tar.gz
Merge branch 'gost-split-1' into 'master'
GOST-CNT split, part 1 See merge request gnutls/gnutls!1072
-rw-r--r--NEWS8
-rw-r--r--devel/libgnutls-latest-x86_64.abi2
-rw-r--r--lib/algorithms/ciphers.c7
-rw-r--r--lib/algorithms/mac.c5
-rw-r--r--lib/crypto-selftests.c31
-rw-r--r--lib/includes/gnutls/gnutls.h.in4
-rw-r--r--lib/nettle/cipher.c33
-rw-r--r--lib/nettle/gost/gost28147.c184
-rw-r--r--lib/nettle/gost/gost28147.h71
-rw-r--r--lib/nettle/mac.c19
10 files changed, 363 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 4165de6e7a..2a29f50649 100644
--- a/NEWS
+++ b/NEWS
@@ -25,10 +25,16 @@ See the end for copying conditions.
** libgnutls: the server now selects the highest TLS protocol version,
if TLS 1.3 is enabled and the client advertises an older protocol version first (#837).
+** libgnutls: added support for GOST 28147-89 cipher in CNT (GOST counter) mode
+ and MAC generation based on GOST 28147-89 (IMIT). For description of the
+ modes see RFC 5830. S-Box is id-tc26-gost-28147-param-Z (TC26Z) defined in
+ RFC 7836.
+
** API and ABI modifications:
gnutls_aead_cipher_encryptv2: Added
gnutls_aead_cipher_decryptv2: Added
-
+GNUTLS_CIPHER_GOST28147_TC26Z_CNT: Added
+GNUTLS_MAC_GOST28147_TC26Z_IMIT: Added
* Version 3.6.9 (released 2019-07-25)
diff --git a/devel/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi
index 49044fe938..7198fa4632 100644
--- a/devel/libgnutls-latest-x86_64.abi
+++ b/devel/libgnutls-latest-x86_64.abi
@@ -1492,6 +1492,7 @@
<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'/>
@@ -1551,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/ciphers.c b/lib/algorithms/ciphers.c
index 6f503fd0b2..aab3708128 100644
--- a/lib/algorithms/ciphers.c
+++ b/lib/algorithms/ciphers.c
@@ -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,
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/crypto-selftests.c b/lib/crypto-selftests.c
index 821271f22b..6caf817e82 100644
--- a/lib/crypto-selftests.c
+++ b/lib/crypto-selftests.c
@@ -511,6 +511,20 @@ const struct cipher_vectors_st gost28147_tc26z_cfb_vectors[] = {
},
};
+const struct cipher_vectors_st gost28147_tc26z_cnt_vectors[] = {
+ {
+ STR(key, key_size,
+ "\x59\x9f\x84\xba\xc3\xf3\xd2\xf1\x60\xe1\xe3\xf2\x6a\x96\x1a\xf9"
+ "\x9c\x48\xb2\x4e\xbc\xbb\xbf\x7c\xd8\xf3\xac\xcd\x96\x8d\x28\x6a"),
+ STR(plaintext, plaintext_size,
+ "\x90\xa2\x39\x66\xae\x01\xb9\xa3\x52\x4e\xc8\xed\x6c\xdd\x88\x30"),
+ .ciphertext = (uint8_t *)
+ "\xe8\xb1\x4f\xc7\x30\xdc\x25\xbb\x36\xba\x64\x3c\x17\xdb\xff\x99",
+ STR(iv, iv_size,
+ "\x8d\xaf\xa8\xd1\x58\xed\x05\x8d"),
+ }
+};
+
const struct cipher_vectors_st aes128_xts_vectors[] = {
{
STR(key, key_size,
@@ -1603,6 +1617,18 @@ const struct mac_vectors_st aes_gmac_256_vectors[] = { /* NIST test vectors */
},
};
+const struct mac_vectors_st gost28147_tc26z_imit_vectors[] = {
+ {
+ STR(key, key_size,
+ "\x9d\x05\xb7\x9e\x90\xca\xd0\x0a\x2c\xda\xd2\x2e\xf4\xe8\x6f\x5c"
+ "\xf5\xdc\x37\x68\x19\x85\xb3\xbf\xaa\x18\xc1\xc3\x05\x0a\x91\xa2"),
+ STR(plaintext, plaintext_size,
+ "\xb5\xa1\xf0\xe3\xce\x2f\x02\x1d\x67\x61\x94\x34\x5c\x41\xe3\x6e"),
+ STR(output, output_size,
+ "\x03\xe5\x67\x66"),
+ },
+};
+
static int test_mac(gnutls_mac_algorithm_t mac,
const struct mac_vectors_st *vectors,
size_t vectors_size, unsigned flags)
@@ -1790,6 +1816,9 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher)
FALLTHROUGH;
NON_FIPS_CASE(GNUTLS_CIPHER_GOST28147_TC26Z_CFB, test_cipher,
gost28147_tc26z_cfb_vectors);
+ FALLTHROUGH;
+ NON_FIPS_CASE(GNUTLS_CIPHER_GOST28147_TC26Z_CNT, test_cipher,
+ gost28147_tc26z_cnt_vectors);
#endif
break;
default:
@@ -1837,6 +1866,8 @@ int gnutls_mac_self_test(unsigned flags, gnutls_mac_algorithm_t mac)
NON_FIPS_CASE(GNUTLS_MAC_STREEBOG_512, test_mac, hmac_streebog_512_vectors);
FALLTHROUGH;
NON_FIPS_CASE(GNUTLS_MAC_STREEBOG_256, test_mac, hmac_streebog_256_vectors);
+ FALLTHROUGH;
+ NON_FIPS_CASE(GNUTLS_MAC_GOST28147_TC26Z_IMIT, test_mac, gost28147_tc26z_imit_vectors);
#endif
FALLTHROUGH;
CASE(GNUTLS_MAC_AES_CMAC_128, test_mac, aes_cmac_128_vectors);
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index f5a5a66acb..6b35c44342 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -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
*/
@@ -289,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.
@@ -322,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/cipher.c b/lib/nettle/cipher.c
index 09032f353d..28f676a480 100644
--- a/lib/nettle/cipher.c
+++ b/lib/nettle/cipher.c
@@ -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,
diff --git a/lib/nettle/gost/gost28147.c b/lib/nettle/gost/gost28147.c
index 0b047242f2..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,
@@ -2367,4 +2384,171 @@ 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;
+ }
+}
+
+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 7329d2ed8b..5fbab90ef1 100644
--- a/lib/nettle/gost/gost28147.h
+++ b/lib/nettle/gost/gost28147.h
@@ -65,6 +65,17 @@ 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_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
@@ -115,6 +126,66 @@ 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);
+
+#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: