mirror of
https://abf.rosa.ru/djam/libressl.git
synced 2025-02-23 08:02:54 +00:00
210 lines
6.1 KiB
Diff
210 lines
6.1 KiB
Diff
From d621042e04e5f28f76720df8491c97f1a4307670 Mon Sep 17 00:00:00 2001
|
|
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
|
Date: Wed, 8 Apr 2020 18:09:14 +0300
|
|
Subject: [PATCH 58/87] evp: support magma kexp15 keywrap algorithm
|
|
|
|
Add support for magma kexp15 key wrapping algorithm
|
|
(draft-smyshlyaev-tls12-gost-suites, Section 8.2.1).
|
|
|
|
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
|
---
|
|
src/lib/libcrypto/evp/c_all.c | 1 +
|
|
src/lib/libcrypto/evp/e_magma.c | 143 ++++++++++++++++++++++++++++++++
|
|
src/lib/libcrypto/evp/evp.h | 1 +
|
|
3 files changed, 145 insertions(+)
|
|
|
|
diff --git a/src/lib/libcrypto/evp/c_all.c b/src/lib/libcrypto/evp/c_all.c
|
|
index 482cc4e06..7afbb933e 100644
|
|
--- a/src/lib/libcrypto/evp/c_all.c
|
|
+++ b/src/lib/libcrypto/evp/c_all.c
|
|
@@ -236,6 +236,7 @@ OpenSSL_add_all_ciphers_internal(void)
|
|
EVP_add_cipher(EVP_magma_ctr());
|
|
EVP_add_cipher(EVP_magma_ctr_acpkm());
|
|
EVP_add_cipher(EVP_magma_ctr_acpkm_omac());
|
|
+ EVP_add_cipher(EVP_magma_kexp15_wrap());
|
|
EVP_add_cipher(EVP_magma_mgm());
|
|
EVP_add_cipher(EVP_kuznyechik_ecb());
|
|
EVP_add_cipher(EVP_kuznyechik_cbc());
|
|
diff --git a/src/lib/libcrypto/evp/e_magma.c b/src/lib/libcrypto/evp/e_magma.c
|
|
index ffaeda505..c9e26deb5 100644
|
|
--- a/src/lib/libcrypto/evp/e_magma.c
|
|
+++ b/src/lib/libcrypto/evp/e_magma.c
|
|
@@ -42,6 +42,13 @@ typedef struct {
|
|
unsigned char tag[8];
|
|
} EVP_MAGMA_CTR_ACPKM_OMAC_CTX;
|
|
|
|
+typedef struct {
|
|
+ MAGMA_KEY ks;
|
|
+ CMAC_CTX *cmac;
|
|
+ int iv_set;
|
|
+ int key_set;
|
|
+} EVP_MAGMA_KEXP15_WRAP_CTX;
|
|
+
|
|
static int
|
|
magma_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
|
const unsigned char *iv, int enc)
|
|
@@ -336,6 +343,131 @@ magma_ctr_acpkm_omac_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
|
|
return ret;
|
|
}
|
|
|
|
+#define KEXP15_IV_OFFSET 24
|
|
+#define KEXP15_MAGMA_IV_PART 4
|
|
+
|
|
+static int
|
|
+magma_kexp15_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
|
+ const unsigned char *iv, int enc)
|
|
+{
|
|
+ EVP_MAGMA_KEXP15_WRAP_CTX *c = ctx->cipher_data;
|
|
+
|
|
+ if (iv) {
|
|
+ memset(ctx->iv, 0, sizeof(ctx->iv));
|
|
+ memcpy(ctx->iv, iv + KEXP15_IV_OFFSET, KEXP15_MAGMA_IV_PART);
|
|
+ c->iv_set = 1;
|
|
+ if (c->key_set)
|
|
+ CMAC_Update(c->cmac, iv, KEXP15_MAGMA_IV_PART);
|
|
+ }
|
|
+
|
|
+ if (key) {
|
|
+ c->key_set = 1;
|
|
+ const EVP_CIPHER *ciph = EVP_magma_cbc();
|
|
+ int kl = EVP_CIPHER_key_length(ciph);
|
|
+
|
|
+ if (!CMAC_Init(c->cmac, key, kl, ciph, NULL))
|
|
+ return 0;
|
|
+
|
|
+ if (iv != NULL)
|
|
+ CMAC_Update(c->cmac, iv, KEXP15_MAGMA_IV_PART);
|
|
+ else if (c->iv_set)
|
|
+ CMAC_Update(c->cmac, ctx->iv, KEXP15_MAGMA_IV_PART);
|
|
+
|
|
+ Magma_set_key(&c->ks, key + 32);
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+magma_kexp15_wrap_cleanup(EVP_CIPHER_CTX *ctx)
|
|
+{
|
|
+ EVP_MAGMA_KEXP15_WRAP_CTX *c = ctx->cipher_data;
|
|
+
|
|
+ CMAC_CTX_free(c->cmac);
|
|
+ c->iv_set = 0;
|
|
+ c->key_set = 0;
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+magma_kexp15_wrap_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
|
|
+{
|
|
+ EVP_MAGMA_KEXP15_WRAP_CTX *key = EVP_C_DATA(EVP_MAGMA_KEXP15_WRAP_CTX, ctx);
|
|
+
|
|
+ switch (type) {
|
|
+ case EVP_CTRL_INIT:
|
|
+ key->cmac = CMAC_CTX_new();
|
|
+ key->iv_set = 0;
|
|
+ key->key_set = 0;
|
|
+ return 1;
|
|
+ default:
|
|
+ return magma_ctl(ctx, type, arg, ptr);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int
|
|
+magma_kexp15_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
|
|
+ size_t len)
|
|
+{
|
|
+ EVP_MAGMA_KEXP15_WRAP_CTX *key = EVP_C_DATA(EVP_MAGMA_KEXP15_WRAP_CTX, ctx);
|
|
+ unsigned char tmp[EVP_MAX_BLOCK_LENGTH];
|
|
+ size_t taglen = sizeof(tmp);
|
|
+ unsigned int bl = EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(key->cmac));
|
|
+
|
|
+ if (in == NULL)
|
|
+ return 0;
|
|
+
|
|
+ if (len % bl != 0)
|
|
+ return -1;
|
|
+ if (ctx->encrypt && len < bl)
|
|
+ return -1;
|
|
+ if (!ctx->encrypt && len < 2 *bl)
|
|
+ return -1;
|
|
+ if (out == NULL) {
|
|
+ if (ctx->encrypt)
|
|
+ return len + bl;
|
|
+ else
|
|
+ return len - bl;
|
|
+ }
|
|
+
|
|
+ /* Do not reuse IV */
|
|
+ key->iv_set = 0;
|
|
+
|
|
+ if (ctx->encrypt) {
|
|
+ CMAC_Update(key->cmac, in, len);
|
|
+ CRYPTO_ctr64_encrypt(in, out, len, &key->ks, ctx->iv, ctx->buf,
|
|
+ &ctx->num, (block64_f)Magma_encrypt);
|
|
+ CMAC_Final(key->cmac, tmp, &taglen);
|
|
+ CRYPTO_ctr64_encrypt(tmp, out + len, taglen, &key->ks, ctx->iv, ctx->buf,
|
|
+ &ctx->num, (block64_f)Magma_encrypt);
|
|
+ return len + taglen;
|
|
+ } else {
|
|
+ CRYPTO_ctr64_encrypt(in, out, len - bl, &key->ks, ctx->iv, ctx->buf,
|
|
+ &ctx->num, (block64_f)Magma_encrypt);
|
|
+ CMAC_Update(key->cmac, out, len - bl);
|
|
+ CMAC_Final(key->cmac, tmp, &taglen);
|
|
+ CRYPTO_ctr64_encrypt(tmp, tmp, taglen, &key->ks, ctx->iv, ctx->buf,
|
|
+ &ctx->num, (block64_f)Magma_encrypt);
|
|
+ return timingsafe_memcmp(in + len - bl, tmp, bl) ? -1 : len - bl;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int
|
|
+magma_kexp15_wrap_set_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
|
|
+{
|
|
+ /* FIXME: set key agreement OID, we need to pass it from upper layer */
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int
|
|
+magma_kexp15_wrap_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
|
|
+{
|
|
+ /* No useful information in ASN.1 params */
|
|
+ return 1;
|
|
+}
|
|
+
|
|
IMPLEMENT_BLOCK_CIPHER(magma, ks, Magma, EVP_MAGMA_CTX,
|
|
NID_magma, 8, 32, 8, 64, 0, magma_init_key, NULL,
|
|
EVP_CIPHER_set_asn1_iv,
|
|
@@ -369,6 +501,17 @@ BLOCK_CIPHER_def1(magma, ctr_acpkm_omac, ctr_acpkm_omac, CTR, EVP_MAGMA_CTR_ACPK
|
|
magma_ctr_acpkm_omac_get_asn1_params,
|
|
magma_ctr_acpkm_omac_ctl)
|
|
|
|
+#define NID_magma_kexp15_wrap NID_id_tc26_wrap_gostr3412_2015_magma_kexp15
|
|
+
|
|
+BLOCK_CIPHER_def1(magma, kexp15_wrap, kexp15_wrap, WRAP, EVP_MAGMA_KEXP15_WRAP_CTX,
|
|
+ NID_magma, 1, 64, 32,
|
|
+ EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT,
|
|
+ magma_kexp15_wrap_init_key,
|
|
+ magma_kexp15_wrap_cleanup,
|
|
+ magma_kexp15_wrap_set_asn1_params,
|
|
+ magma_kexp15_wrap_get_asn1_params,
|
|
+ magma_kexp15_wrap_ctl)
|
|
+
|
|
#define EVP_AEAD_MAGMA_MGM_TAG_LEN 16
|
|
|
|
typedef struct {
|
|
diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h
|
|
index 79ddcebc2..d5b78d8bd 100644
|
|
--- a/src/lib/libcrypto/evp/evp.h
|
|
+++ b/src/lib/libcrypto/evp/evp.h
|
|
@@ -857,6 +857,7 @@ 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_ctr_acpkm_omac(void);
|
|
+const EVP_CIPHER *EVP_magma_kexp15_wrap(void);
|
|
const EVP_CIPHER *EVP_magma_mgm(void);
|
|
const EVP_CIPHER *EVP_kuznyechik_ecb(void);
|
|
const EVP_CIPHER *EVP_kuznyechik_cbc(void);
|
|
--
|
|
2.17.1
|
|
|