mirror of
https://abf.rosa.ru/djam/libressl.git
synced 2025-02-23 16:12:53 +00:00
244 lines
8.6 KiB
Diff
244 lines
8.6 KiB
Diff
From c9c7e6ed9d8c2deffdfe30c977ca91d2297177a9 Mon Sep 17 00:00:00 2001
|
|
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
|
Date: Wed, 25 Mar 2020 23:44:15 +0300
|
|
Subject: [PATCH 48/87] evp: add EVP_CIPHER interface for kuznyechik-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_kuznyechik.c | 153 ++++++++++++++++++
|
|
src/lib/libcrypto/evp/evp.h | 3 +
|
|
.../lib/libcrypto/evp/evpaeadtests.txt | 3 +
|
|
5 files changed, 161 insertions(+)
|
|
|
|
diff --git a/src/lib/libcrypto/Symbols.list b/src/lib/libcrypto/Symbols.list
|
|
index 56169f990..d19720109 100644
|
|
--- a/src/lib/libcrypto/Symbols.list
|
|
+++ b/src/lib/libcrypto/Symbols.list
|
|
@@ -1732,6 +1732,7 @@ EVP_kuznyechik_cfb64
|
|
EVP_kuznyechik_ctr
|
|
EVP_kuznyechik_ctr_acpkm
|
|
EVP_kuznyechik_ecb
|
|
+EVP_kuznyechik_mgm
|
|
EVP_kuznyechik_ofb
|
|
EVP_magma_cbc
|
|
EVP_magma_cfb64
|
|
diff --git a/src/lib/libcrypto/evp/c_all.c b/src/lib/libcrypto/evp/c_all.c
|
|
index c15be0c4f..586466eb6 100644
|
|
--- a/src/lib/libcrypto/evp/c_all.c
|
|
+++ b/src/lib/libcrypto/evp/c_all.c
|
|
@@ -241,6 +241,7 @@ OpenSSL_add_all_ciphers_internal(void)
|
|
EVP_add_cipher(EVP_kuznyechik_ofb());
|
|
EVP_add_cipher(EVP_kuznyechik_ctr());
|
|
EVP_add_cipher(EVP_kuznyechik_ctr_acpkm());
|
|
+ EVP_add_cipher(EVP_kuznyechik_mgm());
|
|
#endif
|
|
|
|
#ifndef OPENSSL_NO_SM4
|
|
diff --git a/src/lib/libcrypto/evp/e_kuznyechik.c b/src/lib/libcrypto/evp/e_kuznyechik.c
|
|
index 88ecef8e5..d022db39c 100644
|
|
--- a/src/lib/libcrypto/evp/e_kuznyechik.c
|
|
+++ b/src/lib/libcrypto/evp/e_kuznyechik.c
|
|
@@ -202,6 +202,14 @@ BLOCK_CIPHER_def1(kuznyechik, ctr_acpkm, ctr_acpkm, CTR, EVP_KUZNYECHIK_CTX,
|
|
|
|
#define EVP_AEAD_KUZNYECHIK_MGM_TAG_LEN 16
|
|
|
|
+typedef struct {
|
|
+ KUZNYECHIK_KEY ks; /* KUZNYECHIK key schedule to use */
|
|
+ MGM128_CONTEXT mgm;
|
|
+ int key_set; /* Set if key initialised */
|
|
+ int iv_set; /* Set if an iv is set */
|
|
+ int tag_len;
|
|
+} EVP_KUZNYECHIK_MGM_CTX;
|
|
+
|
|
struct aead_kuznyechik_mgm_ctx {
|
|
KUZNYECHIK_KEY ks;
|
|
MGM128_CONTEXT mgm;
|
|
@@ -216,6 +224,151 @@ kuznyechik_mgm_set_key(KUZNYECHIK_KEY *kuznyechik_key, MGM128_CONTEXT *mgm_ctx,
|
|
CRYPTO_mgm128_init(mgm_ctx, kuznyechik_key, (block128_f)Kuznyechik_encrypt);
|
|
}
|
|
|
|
+static int
|
|
+kuznyechik_mgm_cleanup(EVP_CIPHER_CTX *c)
|
|
+{
|
|
+ EVP_KUZNYECHIK_MGM_CTX *gctx = c->cipher_data;
|
|
+
|
|
+ explicit_bzero(gctx, sizeof(*gctx));
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+kuznyechik_mgm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
|
|
+{
|
|
+ EVP_KUZNYECHIK_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 > 16 || 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 > 16 || !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_KUZNYECHIK_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
|
|
+kuznyechik_mgm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
|
+ const unsigned char *iv, int enc)
|
|
+{
|
|
+ EVP_KUZNYECHIK_MGM_CTX *gctx = ctx->cipher_data;
|
|
+
|
|
+ if (!iv && !key)
|
|
+ return 1;
|
|
+ if (key) {
|
|
+ kuznyechik_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_mgm128_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_mgm128_setiv(&gctx->mgm, iv);
|
|
+ else
|
|
+ memcpy(ctx->iv, iv, ctx->cipher->iv_len);
|
|
+ gctx->iv_set = 1;
|
|
+ }
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+kuznyechik_mgm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
|
+ const unsigned char *in, size_t len)
|
|
+{
|
|
+ EVP_KUZNYECHIK_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_mgm128_aad(&gctx->mgm, in, len))
|
|
+ return -1;
|
|
+ } else if (ctx->encrypt) {
|
|
+ if (CRYPTO_mgm128_encrypt(&gctx->mgm, in, out, len))
|
|
+ return -1;
|
|
+ } else {
|
|
+ if (CRYPTO_mgm128_decrypt(&gctx->mgm, in, out, len))
|
|
+ return -1;
|
|
+ }
|
|
+ return len;
|
|
+ } else {
|
|
+ if (!ctx->encrypt) {
|
|
+ if (gctx->tag_len < 0)
|
|
+ return -1;
|
|
+ if (CRYPTO_mgm128_finish(&gctx->mgm, ctx->buf, gctx->tag_len) != 0)
|
|
+ return -1;
|
|
+ gctx->iv_set = 0;
|
|
+ return 0;
|
|
+ }
|
|
+ CRYPTO_mgm128_tag(&gctx->mgm, ctx->buf, 16);
|
|
+ gctx->tag_len = 16;
|
|
+
|
|
+ /* 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_kuznyechik_mgm NID_id_tc26_cipher_gostr3412_2015_kuznyechik_mgm
|
|
+
|
|
+BLOCK_CIPHER_def1(kuznyechik, mgm, mgm, GCM, EVP_KUZNYECHIK_MGM_CTX,
|
|
+ NID_kuznyechik, 1, 32, 16,
|
|
+ EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS,
|
|
+ kuznyechik_mgm_init_key, kuznyechik_mgm_cleanup,
|
|
+ EVP_CIPHER_set_asn1_iv,
|
|
+ EVP_CIPHER_get_asn1_iv,
|
|
+ kuznyechik_mgm_ctrl)
|
|
+
|
|
static int
|
|
aead_kuznyechik_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 88d9b1989..334ce1cd3 100644
|
|
--- a/src/lib/libcrypto/evp/evp.h
|
|
+++ b/src/lib/libcrypto/evp/evp.h
|
|
@@ -385,6 +385,8 @@ struct evp_cipher_st {
|
|
#define EVP_CTRL_CCM_SET_TAG EVP_CTRL_GCM_SET_TAG
|
|
#define EVP_CTRL_CCM_SET_L 0x14
|
|
#define EVP_CTRL_CCM_SET_MSGLEN 0x15
|
|
+#define EVP_CTRL_MGM_GET_TAG EVP_CTRL_GCM_GET_TAG
|
|
+#define EVP_CTRL_MGM_SET_TAG EVP_CTRL_GCM_SET_TAG
|
|
/* AEAD cipher deduces payload length and returns number of bytes
|
|
* required to store MAC and eventual padding. Subsequent call to
|
|
* EVP_Cipher even appends/verifies MAC.
|
|
@@ -860,6 +862,7 @@ const EVP_CIPHER *EVP_kuznyechik_cfb128(void);
|
|
const EVP_CIPHER *EVP_kuznyechik_ofb(void);
|
|
const EVP_CIPHER *EVP_kuznyechik_ctr(void);
|
|
const EVP_CIPHER *EVP_kuznyechik_ctr_acpkm(void);
|
|
+const EVP_CIPHER *EVP_kuznyechik_mgm(void);
|
|
#endif
|
|
|
|
#ifndef OPENSSL_NO_SM4
|
|
diff --git a/src/regress/lib/libcrypto/evp/evpaeadtests.txt b/src/regress/lib/libcrypto/evp/evpaeadtests.txt
|
|
index 68156e7a5..69ccd8c17 100644
|
|
--- a/src/regress/lib/libcrypto/evp/evpaeadtests.txt
|
|
+++ b/src/regress/lib/libcrypto/evp/evpaeadtests.txt
|
|
@@ -12,3 +12,6 @@ aes-128-gcm:88EE087FD95DA9FBF6725AA9D757B0CD:7AE8E2CA4EC500012E58495C:68F2E77696
|
|
|
|
aes-256-gcm:4C973DBC7364621674F8B5B89E5C15511FCED9216490FB1C1A2CAA0FFE0407E5:7AE8E2CA4EC500012E58495C:68F2E77696CE7AE8E2CA4EC588E54D002E58495C:08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748490008:BA8AE31BC506486D6873E4FCE460E7DC57591FF00611F31C3834FE1C04AD80B66803AFCF5B27E6333FA67C99DA47C2F0CED68D531BD741A943CFF7A6713BD0:2611CD7DAA01D61C5C886DC1A8170107:1
|
|
aes-256-gcm:4C973DBC7364621674F8B5B89E5C15511FCED9216490FB1C1A2CAA0FFE0407E5:7AE8E2CA4EC500012E58495C:68F2E77696CE7AE8E2CA4EC588E54D002E58495C:08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748490008:BA8AE31BC506486D6873E4FCE460E7DC57591FF00611F31C3834FE1C04AD80B66803AFCF5B27E6333FA67C99DA47C2F0CED68D531BD741A943CFF7A6713BD0:2611CD7DAA01D61C5C886DC1A8170107:0
|
|
+
|
|
+kuznyechik-mgm:8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef:1122334455667700ffeeddccbbaa9988:0202020202020202010101010101010104040404040404040303030303030303ea0505050505050505:1122334455667700ffeeddccbbaa998800112233445566778899aabbcceeff0a112233445566778899aabbcceeff0a002233445566778899aabbcceeff0a0011aabbcc:a9757b8147956e9055b8a33de89f42fc8075d2212bf9fd5bd3f7069aadc16b39497ab15915a6ba85936b5d0ea9f6851cc60c14d4d3f883d0ab94420695c76deb2c7552:cf5d656f40c34f5c46e8bb0e29fcdb4c:1
|
|
+kuznyechik-mgm:8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef:1122334455667700ffeeddccbbaa9988:0202020202020202010101010101010104040404040404040303030303030303ea0505050505050505:1122334455667700ffeeddccbbaa998800112233445566778899aabbcceeff0a112233445566778899aabbcceeff0a002233445566778899aabbcceeff0a0011aabbcc:a9757b8147956e9055b8a33de89f42fc8075d2212bf9fd5bd3f7069aadc16b39497ab15915a6ba85936b5d0ea9f6851cc60c14d4d3f883d0ab94420695c76deb2c7552:cf5d656f40c34f5c46e8bb0e29fcdb4c:0
|
|
--
|
|
2.17.1
|
|
|