libressl/0049-evp-add-EVP_CIPHER-interface-for-magma-mgm.patch

236 lines
8.1 KiB
Diff
Raw Permalink Normal View History

From 10686e4b5c14cbff10d40e5ae630c0aa35aaa8fe Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
Date: Wed, 25 Mar 2020 23:44:15 +0300
Subject: [PATCH 49/87] evp: add EVP_CIPHER interface for magma-mgm
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
src/lib/libcrypto/Symbols.list | 1 +
src/lib/libcrypto/evp/c_all.c | 1 +
src/lib/libcrypto/evp/e_magma.c | 153 ++++++++++++++++++
src/lib/libcrypto/evp/evp.h | 1 +
.../lib/libcrypto/evp/evpaeadtests.txt | 3 +
5 files changed, 159 insertions(+)
diff --git a/src/lib/libcrypto/Symbols.list b/src/lib/libcrypto/Symbols.list
index d19720109..3eda9f3bd 100644
--- a/src/lib/libcrypto/Symbols.list
+++ b/src/lib/libcrypto/Symbols.list
@@ -1739,6 +1739,7 @@ EVP_magma_cfb64
EVP_magma_ctr
EVP_magma_ctr_acpkm
EVP_magma_ecb
+EVP_magma_mgm
EVP_magma_ofb
EVP_md4
EVP_md5
diff --git a/src/lib/libcrypto/evp/c_all.c b/src/lib/libcrypto/evp/c_all.c
index 586466eb6..6a60624d3 100644
--- a/src/lib/libcrypto/evp/c_all.c
+++ b/src/lib/libcrypto/evp/c_all.c
@@ -235,6 +235,7 @@ OpenSSL_add_all_ciphers_internal(void)
EVP_add_cipher(EVP_magma_ofb());
EVP_add_cipher(EVP_magma_ctr());
EVP_add_cipher(EVP_magma_ctr_acpkm());
+ EVP_add_cipher(EVP_magma_mgm());
EVP_add_cipher(EVP_kuznyechik_ecb());
EVP_add_cipher(EVP_kuznyechik_cbc());
EVP_add_cipher(EVP_kuznyechik_cfb128());
diff --git a/src/lib/libcrypto/evp/e_magma.c b/src/lib/libcrypto/evp/e_magma.c
index 3d3083b95..ae78824eb 100644
--- a/src/lib/libcrypto/evp/e_magma.c
+++ b/src/lib/libcrypto/evp/e_magma.c
@@ -196,6 +196,14 @@ BLOCK_CIPHER_def1(magma, ctr_acpkm, ctr_acpkm, CTR, EVP_MAGMA_CTX,
#define EVP_AEAD_MAGMA_MGM_TAG_LEN 16
+typedef struct {
+ MAGMA_KEY ks; /* MAGMA key schedule to use */
+ MGM64_CONTEXT mgm;
+ int key_set; /* Set if key initialised */
+ int iv_set; /* Set if an iv is set */
+ int tag_len;
+} EVP_MAGMA_MGM_CTX;
+
struct aead_magma_mgm_ctx {
MAGMA_KEY ks;
MGM64_CONTEXT mgm;
@@ -210,6 +218,151 @@ magma_mgm_set_key(MAGMA_KEY *magma_key, MGM64_CONTEXT *mgm_ctx,
CRYPTO_mgm64_init(mgm_ctx, magma_key, (block64_f)Magma_encrypt);
}
+static int
+magma_mgm_cleanup(EVP_CIPHER_CTX *c)
+{
+ EVP_MAGMA_MGM_CTX *gctx = c->cipher_data;
+
+ explicit_bzero(gctx, sizeof(*gctx));
+ return 1;
+}
+
+static int
+magma_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+{
+ EVP_MAGMA_MGM_CTX *gctx = c->cipher_data;
+
+ switch (type) {
+ case EVP_CTRL_INIT:
+ gctx->key_set = 0;
+ gctx->iv_set = 0;
+ gctx->tag_len = -1;
+ return 1;
+
+ case EVP_CTRL_MGM_SET_TAG:
+ if (arg <= 0 || arg > 8 || c->encrypt)
+ return 0;
+ memcpy(c->buf, ptr, arg);
+ gctx->tag_len = arg;
+ return 1;
+
+ case EVP_CTRL_MGM_GET_TAG:
+ if (arg <= 0 || arg > 8 || !c->encrypt || gctx->tag_len < 0)
+ return 0;
+ memcpy(ptr, c->buf, arg);
+ return 1;
+
+ case EVP_CTRL_COPY:
+ {
+ EVP_CIPHER_CTX *out = ptr;
+ EVP_MAGMA_MGM_CTX *gctx_out = out->cipher_data;
+
+ if (gctx->mgm.key) {
+ if (gctx->mgm.key != &gctx->ks)
+ return 0;
+ gctx_out->mgm.key = &gctx_out->ks;
+ }
+
+ return 1;
+ }
+
+ default:
+ return -1;
+
+ }
+}
+
+static int
+magma_mgm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ EVP_MAGMA_MGM_CTX *gctx = ctx->cipher_data;
+
+ if (!iv && !key)
+ return 1;
+ if (key) {
+ magma_mgm_set_key(&gctx->ks, &gctx->mgm, key, ctx->key_len);
+
+ /* If we have an iv can set it directly, otherwise use
+ * saved IV.
+ */
+ if (gctx->iv_set)
+ iv = ctx->iv;
+ if (iv) {
+ CRYPTO_mgm64_setiv(&gctx->mgm, iv);
+ gctx->iv_set = 1;
+ }
+ gctx->key_set = 1;
+ } else {
+ /* If key set use IV, otherwise copy */
+ if (gctx->key_set)
+ CRYPTO_mgm64_setiv(&gctx->mgm, iv);
+ else
+ memcpy(ctx->iv, iv, ctx->cipher->iv_len);
+ gctx->iv_set = 1;
+ }
+ return 1;
+}
+
+static int
+magma_mgm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ EVP_MAGMA_MGM_CTX *gctx = ctx->cipher_data;
+
+ /* If not set up, return error */
+ if (!gctx->key_set)
+ return -1;
+
+ if (!gctx->iv_set)
+ return -1;
+
+ if (in) {
+ if (out == NULL) {
+ if (CRYPTO_mgm64_aad(&gctx->mgm, in, len))
+ return -1;
+ } else if (ctx->encrypt) {
+ if (CRYPTO_mgm64_encrypt(&gctx->mgm, in, out, len))
+ return -1;
+ } else {
+ if (CRYPTO_mgm64_decrypt(&gctx->mgm, in, out, len))
+ return -1;
+ }
+ return len;
+ } else {
+ if (!ctx->encrypt) {
+ if (gctx->tag_len < 0)
+ return -1;
+ if (CRYPTO_mgm64_finish(&gctx->mgm, ctx->buf, gctx->tag_len) != 0)
+ return -1;
+ gctx->iv_set = 0;
+ return 0;
+ }
+ CRYPTO_mgm64_tag(&gctx->mgm, ctx->buf, 8);
+ gctx->tag_len = 8;
+
+ /* Don't reuse the IV */
+ gctx->iv_set = 0;
+ return 0;
+ }
+
+}
+
+#define CUSTOM_FLAGS \
+ ( EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV | \
+ EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | \
+ EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY )
+
+#define NID_magma_mgm NID_id_tc26_cipher_gostr3412_2015_magma_mgm
+
+BLOCK_CIPHER_def1(magma, mgm, mgm, GCM, EVP_MAGMA_MGM_CTX,
+ NID_magma, 1, 32, 8,
+ EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS,
+ magma_mgm_init_key, magma_mgm_cleanup,
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ magma_mgm_ctrl)
+
static int
aead_magma_mgm_init(EVP_AEAD_CTX *ctx, const unsigned char *key, size_t key_len,
size_t tag_len)
diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h
index 334ce1cd3..50b157525 100644
--- a/src/lib/libcrypto/evp/evp.h
+++ b/src/lib/libcrypto/evp/evp.h
@@ -856,6 +856,7 @@ const EVP_CIPHER *EVP_magma_cfb64(void);
const EVP_CIPHER *EVP_magma_ofb(void);
const EVP_CIPHER *EVP_magma_ctr(void);
const EVP_CIPHER *EVP_magma_ctr_acpkm(void);
+const EVP_CIPHER *EVP_magma_mgm(void);
const EVP_CIPHER *EVP_kuznyechik_ecb(void);
const EVP_CIPHER *EVP_kuznyechik_cbc(void);
const EVP_CIPHER *EVP_kuznyechik_cfb128(void);
diff --git a/src/regress/lib/libcrypto/evp/evpaeadtests.txt b/src/regress/lib/libcrypto/evp/evpaeadtests.txt
index 69ccd8c17..9c8dd7142 100644
--- a/src/regress/lib/libcrypto/evp/evpaeadtests.txt
+++ b/src/regress/lib/libcrypto/evp/evpaeadtests.txt
@@ -15,3 +15,6 @@ aes-256-gcm:4C973DBC7364621674F8B5B89E5C15511FCED9216490FB1C1A2CAA0FFE0407E5:7AE
kuznyechik-mgm:8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef:1122334455667700ffeeddccbbaa9988:0202020202020202010101010101010104040404040404040303030303030303ea0505050505050505:1122334455667700ffeeddccbbaa998800112233445566778899aabbcceeff0a112233445566778899aabbcceeff0a002233445566778899aabbcceeff0a0011aabbcc:a9757b8147956e9055b8a33de89f42fc8075d2212bf9fd5bd3f7069aadc16b39497ab15915a6ba85936b5d0ea9f6851cc60c14d4d3f883d0ab94420695c76deb2c7552:cf5d656f40c34f5c46e8bb0e29fcdb4c:1
kuznyechik-mgm:8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef:1122334455667700ffeeddccbbaa9988:0202020202020202010101010101010104040404040404040303030303030303ea0505050505050505:1122334455667700ffeeddccbbaa998800112233445566778899aabbcceeff0a112233445566778899aabbcceeff0a002233445566778899aabbcceeff0a0011aabbcc:a9757b8147956e9055b8a33de89f42fc8075d2212bf9fd5bd3f7069aadc16b39497ab15915a6ba85936b5d0ea9f6851cc60c14d4d3f883d0ab94420695c76deb2c7552:cf5d656f40c34f5c46e8bb0e29fcdb4c:0
+
+magma-mgm:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:92def06b3c130a59:01010101010101010202020202020202030303030303030304040404040404040505050505050505EA:ffeeddccbbaa998811223344556677008899aabbcceeff0a001122334455667799aabbcceeff0a001122334455667788aabbcceeff0a00112233445566778899aabbcc:c795066c5f9ea03b85113342459185ae1f2e00d6bf2b785d940470b8bb9c8e7d9a5dd3731f7ddc70ec27cb0ace6fa57670f65c646abb75d547aa37c3bcb5c34e03bb9c:a7928069aa10fd10:1
+magma-mgm:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:92def06b3c130a59:01010101010101010202020202020202030303030303030304040404040404040505050505050505EA:ffeeddccbbaa998811223344556677008899aabbcceeff0a001122334455667799aabbcceeff0a001122334455667788aabbcceeff0a00112233445566778899aabbcc:c795066c5f9ea03b85113342459185ae1f2e00d6bf2b785d940470b8bb9c8e7d9a5dd3731f7ddc70ec27cb0ace6fa57670f65c646abb75d547aa37c3bcb5c34e03bb9c:a7928069aa10fd10:0
--
2.17.1