mirror of
https://abf.rosa.ru/djam/libressl.git
synced 2025-02-23 08:02:54 +00:00
254 lines
7.5 KiB
Diff
254 lines
7.5 KiB
Diff
From 58d19972ccd8d8857633a578a3cfb10e6ae10d26 Mon Sep 17 00:00:00 2001
|
|
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
|
Date: Wed, 25 Mar 2020 21:56:51 +0300
|
|
Subject: [PATCH 46/87] gost: add magma-mgm support
|
|
|
|
Add EVP_AEAD interface for supporting magma cipher in MGM mode.
|
|
|
|
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
|
---
|
|
src/lib/libcrypto/Symbols.list | 1 +
|
|
src/lib/libcrypto/evp/e_magma.c | 160 +++++++++++++++++++
|
|
src/lib/libcrypto/evp/evp.h | 2 +
|
|
src/regress/lib/libcrypto/aead/aeadtest.c | 6 +
|
|
src/regress/lib/libcrypto/aead/aeadtests.txt | 9 ++
|
|
5 files changed, 178 insertions(+)
|
|
|
|
diff --git a/src/lib/libcrypto/Symbols.list b/src/lib/libcrypto/Symbols.list
|
|
index aff725bd4..56169f990 100644
|
|
--- a/src/lib/libcrypto/Symbols.list
|
|
+++ b/src/lib/libcrypto/Symbols.list
|
|
@@ -1619,6 +1619,7 @@ EVP_aead_aes_128_gcm
|
|
EVP_aead_aes_256_gcm
|
|
EVP_aead_chacha20_poly1305
|
|
EVP_aead_kuznyechik_mgm
|
|
+EVP_aead_magma_mgm
|
|
EVP_aead_xchacha20_poly1305
|
|
EVP_aes_128_cbc
|
|
EVP_aes_128_cbc_hmac_sha1
|
|
diff --git a/src/lib/libcrypto/evp/e_magma.c b/src/lib/libcrypto/evp/e_magma.c
|
|
index 0311e04b1..3d3083b95 100644
|
|
--- a/src/lib/libcrypto/evp/e_magma.c
|
|
+++ b/src/lib/libcrypto/evp/e_magma.c
|
|
@@ -26,6 +26,7 @@
|
|
#include <openssl/modes.h>
|
|
#include <openssl/gost.h>
|
|
#include "evp_locl.h"
|
|
+#include "modes_lcl.h"
|
|
|
|
typedef struct {
|
|
MAGMA_KEY ks;
|
|
@@ -193,4 +194,163 @@ BLOCK_CIPHER_def1(magma, ctr_acpkm, ctr_acpkm, CTR, EVP_MAGMA_CTX,
|
|
magma_ctr_acpkm_get_asn1_params,
|
|
magma_acpkm_ctl)
|
|
|
|
+#define EVP_AEAD_MAGMA_MGM_TAG_LEN 16
|
|
+
|
|
+struct aead_magma_mgm_ctx {
|
|
+ MAGMA_KEY ks;
|
|
+ MGM64_CONTEXT mgm;
|
|
+ unsigned char tag_len;
|
|
+};
|
|
+
|
|
+static void
|
|
+magma_mgm_set_key(MAGMA_KEY *magma_key, MGM64_CONTEXT *mgm_ctx,
|
|
+ const unsigned char *key, size_t key_len)
|
|
+{
|
|
+ Magma_set_key(magma_key, key);
|
|
+ CRYPTO_mgm64_init(mgm_ctx, magma_key, (block64_f)Magma_encrypt);
|
|
+}
|
|
+
|
|
+static int
|
|
+aead_magma_mgm_init(EVP_AEAD_CTX *ctx, const unsigned char *key, size_t key_len,
|
|
+ size_t tag_len)
|
|
+{
|
|
+ struct aead_magma_mgm_ctx *mgm_ctx;
|
|
+ const size_t key_bits = key_len * 8;
|
|
+
|
|
+ /* EVP_AEAD_CTX_init should catch this. */
|
|
+ if (key_bits != 256) {
|
|
+ EVPerror(EVP_R_BAD_KEY_LENGTH);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH)
|
|
+ tag_len = EVP_AEAD_MAGMA_MGM_TAG_LEN;
|
|
+
|
|
+ if (tag_len > EVP_AEAD_MAGMA_MGM_TAG_LEN) {
|
|
+ EVPerror(EVP_R_TAG_TOO_LARGE);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if ((mgm_ctx = calloc(1, sizeof(struct aead_magma_mgm_ctx))) == NULL)
|
|
+ return 0;
|
|
+
|
|
+ magma_mgm_set_key(&mgm_ctx->ks, &mgm_ctx->mgm, key, key_len);
|
|
+
|
|
+ mgm_ctx->tag_len = tag_len;
|
|
+ ctx->aead_state = mgm_ctx;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static void
|
|
+aead_magma_mgm_cleanup(EVP_AEAD_CTX *ctx)
|
|
+{
|
|
+ struct aead_magma_mgm_ctx *mgm_ctx = ctx->aead_state;
|
|
+
|
|
+ freezero(mgm_ctx, sizeof(*mgm_ctx));
|
|
+}
|
|
+
|
|
+static int
|
|
+aead_magma_mgm_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, size_t *out_len,
|
|
+ size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
|
|
+ const unsigned char *in, size_t in_len, const unsigned char *ad,
|
|
+ size_t ad_len)
|
|
+{
|
|
+ const struct aead_magma_mgm_ctx *mgm_ctx = ctx->aead_state;
|
|
+ MGM64_CONTEXT mgm;
|
|
+ size_t bulk = 0;
|
|
+
|
|
+ if (max_out_len < in_len + mgm_ctx->tag_len) {
|
|
+ EVPerror(EVP_R_BUFFER_TOO_SMALL);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (nonce_len != MGM64_NONCE_LEN) {
|
|
+ EVPerror(EVP_R_IV_TOO_LARGE);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ memcpy(&mgm, &mgm_ctx->mgm, sizeof(mgm));
|
|
+ CRYPTO_mgm64_setiv(&mgm, nonce);
|
|
+
|
|
+ if (ad_len > 0 && CRYPTO_mgm64_aad(&mgm, ad, ad_len))
|
|
+ return 0;
|
|
+
|
|
+ if (CRYPTO_mgm64_encrypt(&mgm, in + bulk, out + bulk,
|
|
+ in_len - bulk))
|
|
+ return 0;
|
|
+
|
|
+ CRYPTO_mgm64_tag(&mgm, out + in_len, mgm_ctx->tag_len);
|
|
+ *out_len = in_len + mgm_ctx->tag_len;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+aead_magma_mgm_open(const EVP_AEAD_CTX *ctx, unsigned char *out, size_t *out_len,
|
|
+ size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
|
|
+ const unsigned char *in, size_t in_len, const unsigned char *ad,
|
|
+ size_t ad_len)
|
|
+{
|
|
+ const struct aead_magma_mgm_ctx *mgm_ctx = ctx->aead_state;
|
|
+ unsigned char tag[EVP_AEAD_MAGMA_MGM_TAG_LEN];
|
|
+ MGM64_CONTEXT mgm;
|
|
+ size_t plaintext_len;
|
|
+ size_t bulk = 0;
|
|
+
|
|
+ if (in_len < mgm_ctx->tag_len) {
|
|
+ EVPerror(EVP_R_BAD_DECRYPT);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ plaintext_len = in_len - mgm_ctx->tag_len;
|
|
+
|
|
+ if (max_out_len < plaintext_len) {
|
|
+ EVPerror(EVP_R_BUFFER_TOO_SMALL);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (nonce_len != MGM64_NONCE_LEN) {
|
|
+ EVPerror(EVP_R_IV_TOO_LARGE);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ memcpy(&mgm, &mgm_ctx->mgm, sizeof(mgm));
|
|
+ CRYPTO_mgm64_setiv(&mgm, nonce);
|
|
+
|
|
+ if (CRYPTO_mgm64_aad(&mgm, ad, ad_len))
|
|
+ return 0;
|
|
+
|
|
+ if (CRYPTO_mgm64_decrypt(&mgm, in + bulk, out + bulk,
|
|
+ in_len - bulk - mgm_ctx->tag_len))
|
|
+ return 0;
|
|
+
|
|
+ CRYPTO_mgm64_tag(&mgm, tag, mgm_ctx->tag_len);
|
|
+ if (timingsafe_memcmp(tag, in + plaintext_len, mgm_ctx->tag_len) != 0) {
|
|
+ EVPerror(EVP_R_BAD_DECRYPT);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ *out_len = plaintext_len;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static const EVP_AEAD aead_magma_mgm = {
|
|
+ .key_len = 32,
|
|
+ .nonce_len = 8,
|
|
+ .overhead = EVP_AEAD_MAGMA_MGM_TAG_LEN,
|
|
+ .max_tag_len = EVP_AEAD_MAGMA_MGM_TAG_LEN,
|
|
+
|
|
+ .init = aead_magma_mgm_init,
|
|
+ .cleanup = aead_magma_mgm_cleanup,
|
|
+ .seal = aead_magma_mgm_seal,
|
|
+ .open = aead_magma_mgm_open,
|
|
+};
|
|
+
|
|
+const EVP_AEAD *
|
|
+EVP_aead_magma_mgm(void)
|
|
+{
|
|
+ return &aead_magma_mgm;
|
|
+}
|
|
#endif
|
|
diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h
|
|
index 3725dd17c..88d9b1989 100644
|
|
--- a/src/lib/libcrypto/evp/evp.h
|
|
+++ b/src/lib/libcrypto/evp/evp.h
|
|
@@ -1292,6 +1292,8 @@ const EVP_AEAD *EVP_aead_xchacha20_poly1305(void);
|
|
#if !defined(OPENSSL_NO_GOST)
|
|
/* EVP_aead_kuznyechik_mgm is Kuznyechik in Multilinear Galois Mode. */
|
|
const EVP_AEAD *EVP_aead_kuznyechik_mgm(void);
|
|
+/* EVP_aead_magma_mgm is Magma in Multilinear Galois Mode. */
|
|
+const EVP_AEAD *EVP_aead_magma_mgm(void);
|
|
#endif
|
|
|
|
/* EVP_AEAD_key_length returns the length of the keys used. */
|
|
diff --git a/src/regress/lib/libcrypto/aead/aeadtest.c b/src/regress/lib/libcrypto/aead/aeadtest.c
|
|
index 6f843e31c..37244931f 100644
|
|
--- a/src/regress/lib/libcrypto/aead/aeadtest.c
|
|
+++ b/src/regress/lib/libcrypto/aead/aeadtest.c
|
|
@@ -149,6 +149,12 @@ aead_from_name(const EVP_AEAD **aead, const char *name)
|
|
*aead = EVP_aead_kuznyechik_mgm();
|
|
#else
|
|
fprintf(stderr, "No kuznyechik-MGM support.\n");
|
|
+#endif
|
|
+ } else if (strcmp(name, "magma-mgm") == 0) {
|
|
+#ifndef OPENSSL_NO_GOST
|
|
+ *aead = EVP_aead_magma_mgm();
|
|
+#else
|
|
+ fprintf(stderr, "No magma-MGM support.\n");
|
|
#endif
|
|
} else {
|
|
fprintf(stderr, "Unknown AEAD: %s\n", name);
|
|
diff --git a/src/regress/lib/libcrypto/aead/aeadtests.txt b/src/regress/lib/libcrypto/aead/aeadtests.txt
|
|
index d2d4e54f7..86f5dac7e 100644
|
|
--- a/src/regress/lib/libcrypto/aead/aeadtests.txt
|
|
+++ b/src/regress/lib/libcrypto/aead/aeadtests.txt
|
|
@@ -93,3 +93,12 @@ AD: 0202020202020202010101010101010104040404040404040303030303030303ea0505050505
|
|
CT: a9757b8147956e9055b8a33de89f42fc8075d2212bf9fd5bd3f7069aadc16b39497ab15915a6ba85936b5d0ea9f6851cc60c14d4d3f883d0ab94420695c76deb2c7552
|
|
TAG: cf5d656f40c34f5c46e8bb0e29fcdb4c
|
|
|
|
+# Not defined in a draft, only in original R 1323565.1.026-2019
|
|
+AEAD: magma-mgm
|
|
+KEY: ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
|
|
+NONCE: 92def06b3c130a59
|
|
+IN: ffeeddccbbaa998811223344556677008899aabbcceeff0a001122334455667799aabbcceeff0a001122334455667788aabbcceeff0a00112233445566778899aabbcc
|
|
+AD: 01010101010101010202020202020202030303030303030304040404040404040505050505050505EA
|
|
+CT: c795066c5f9ea03b85113342459185ae1f2e00d6bf2b785d940470b8bb9c8e7d9a5dd3731f7ddc70ec27cb0ace6fa57670f65c646abb75d547aa37c3bcb5c34e03bb9c
|
|
+TAG: a7928069aa10fd10
|
|
+
|
|
--
|
|
2.17.1
|
|
|