diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2018-06-14 15:36:55 +0300 |
---|---|---|
committer | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2019-09-28 14:18:46 +0300 |
commit | ea536f9fc678592e756e6c0feb41602daea08e81 (patch) | |
tree | a2076874e89e2f3a75e106ca08bfd0af8f7670e0 | |
parent | 907c6ffd080b41300794fe66942ad7d1903738ca (diff) | |
download | gnutls-ea536f9fc678592e756e6c0feb41602daea08e81.tar.gz |
nettle: provide GOST 28147-89 CNT mode 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/ciphers.c | 7 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 2 | ||||
-rw-r--r-- | lib/nettle/cipher.c | 33 | ||||
-rw-r--r-- | lib/nettle/gost/gost28147.c | 85 | ||||
-rw-r--r-- | lib/nettle/gost/gost28147.h | 25 |
6 files changed, 153 insertions, 0 deletions
diff --git a/devel/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi index 49044fe938..f76c3ed7c7 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'/> 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/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index f5a5a66acb..fa16dd9a7a 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 */ 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..f7a67138a4 100644 --- a/lib/nettle/gost/gost28147.c +++ b/lib/nettle/gost/gost28147.c @@ -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 diff --git a/lib/nettle/gost/gost28147.h b/lib/nettle/gost/gost28147.h index 7329d2ed8b..0e68db34ca 100644 --- a/lib/nettle/gost/gost28147.h +++ b/lib/nettle/gost/gost28147.h @@ -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 |