summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2018-06-14 15:36:55 +0300
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-09-28 14:18:46 +0300
commitea536f9fc678592e756e6c0feb41602daea08e81 (patch)
treea2076874e89e2f3a75e106ca08bfd0af8f7670e0
parent907c6ffd080b41300794fe66942ad7d1903738ca (diff)
downloadgnutls-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.abi1
-rw-r--r--lib/algorithms/ciphers.c7
-rw-r--r--lib/includes/gnutls/gnutls.h.in2
-rw-r--r--lib/nettle/cipher.c33
-rw-r--r--lib/nettle/gost/gost28147.c85
-rw-r--r--lib/nettle/gost/gost28147.h25
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