diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2018-06-14 15:37:20 +0300 |
---|---|---|
committer | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2019-09-28 14:18:46 +0300 |
commit | c589e198b34d2244dc233b44aec38a72842f953d (patch) | |
tree | e9917817af84a2df469b73a58b63147eafd1347a | |
parent | ea536f9fc678592e756e6c0feb41602daea08e81 (diff) | |
download | gnutls-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.abi | 1 | ||||
-rw-r--r-- | lib/algorithms/mac.c | 5 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 2 | ||||
-rw-r--r-- | lib/nettle/gost/gost28147.c | 99 | ||||
-rw-r--r-- | lib/nettle/gost/gost28147.h | 46 | ||||
-rw-r--r-- | lib/nettle/mac.c | 19 |
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: |