mirror of
https://abf.rosa.ru/djam/libressl.git
synced 2025-02-23 08:02:54 +00:00
211 lines
6.3 KiB
Diff
211 lines
6.3 KiB
Diff
![]() |
From 4d039c645d00d539a40cf52ff3e7e776b8ae792a Mon Sep 17 00:00:00 2001
|
||
|
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
||
|
Date: Wed, 8 Apr 2020 18:09:14 +0300
|
||
|
Subject: [PATCH 57/87] evp: support kuznyechik kexp15 keywrap algorithm
|
||
|
|
||
|
Add support for kuznyechik 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_kuznyechik.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 90d0f7e20..482cc4e06 100644
|
||
|
--- a/src/lib/libcrypto/evp/c_all.c
|
||
|
+++ b/src/lib/libcrypto/evp/c_all.c
|
||
|
@@ -244,6 +244,7 @@ OpenSSL_add_all_ciphers_internal(void)
|
||
|
EVP_add_cipher(EVP_kuznyechik_ctr());
|
||
|
EVP_add_cipher(EVP_kuznyechik_ctr_acpkm());
|
||
|
EVP_add_cipher(EVP_kuznyechik_ctr_acpkm_omac());
|
||
|
+ EVP_add_cipher(EVP_kuznyechik_kexp15_wrap());
|
||
|
EVP_add_cipher(EVP_kuznyechik_mgm());
|
||
|
#endif
|
||
|
|
||
|
diff --git a/src/lib/libcrypto/evp/e_kuznyechik.c b/src/lib/libcrypto/evp/e_kuznyechik.c
|
||
|
index c6b09173e..3c2a70aeb 100644
|
||
|
--- a/src/lib/libcrypto/evp/e_kuznyechik.c
|
||
|
+++ b/src/lib/libcrypto/evp/e_kuznyechik.c
|
||
|
@@ -42,6 +42,13 @@ typedef struct {
|
||
|
unsigned char tag[16];
|
||
|
} EVP_KUZNYECHIK_CTR_ACPKM_OMAC_CTX;
|
||
|
|
||
|
+typedef struct {
|
||
|
+ KUZNYECHIK_KEY ks;
|
||
|
+ CMAC_CTX *cmac;
|
||
|
+ int iv_set;
|
||
|
+ int key_set;
|
||
|
+} EVP_KUZNYECHIK_KEXP15_WRAP_CTX;
|
||
|
+
|
||
|
static int
|
||
|
kuznyechik_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||
|
const unsigned char *iv, int enc)
|
||
|
@@ -342,6 +349,131 @@ kuznyechik_ctr_acpkm_omac_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
+#define KEXP15_IV_OFFSET 24
|
||
|
+#define KEXP15_KUZNYECHIK_IV_PART 8
|
||
|
+
|
||
|
+static int
|
||
|
+kuznyechik_kexp15_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||
|
+ const unsigned char *iv, int enc)
|
||
|
+{
|
||
|
+ EVP_KUZNYECHIK_KEXP15_WRAP_CTX *c = ctx->cipher_data;
|
||
|
+
|
||
|
+ if (iv) {
|
||
|
+ memset(ctx->iv, 0, sizeof(ctx->iv));
|
||
|
+ memcpy(ctx->iv, iv + KEXP15_IV_OFFSET, KEXP15_KUZNYECHIK_IV_PART);
|
||
|
+ c->iv_set = 1;
|
||
|
+ if (c->key_set)
|
||
|
+ CMAC_Update(c->cmac, iv, KEXP15_KUZNYECHIK_IV_PART);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (key) {
|
||
|
+ c->key_set = 1;
|
||
|
+ const EVP_CIPHER *ciph = EVP_kuznyechik_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_KUZNYECHIK_IV_PART);
|
||
|
+ else if (c->iv_set)
|
||
|
+ CMAC_Update(c->cmac, ctx->iv, KEXP15_KUZNYECHIK_IV_PART);
|
||
|
+
|
||
|
+ Kuznyechik_set_key(&c->ks, key + kl, 1);
|
||
|
+ }
|
||
|
+
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+kuznyechik_kexp15_wrap_cleanup(EVP_CIPHER_CTX *ctx)
|
||
|
+{
|
||
|
+ EVP_KUZNYECHIK_KEXP15_WRAP_CTX *c = ctx->cipher_data;
|
||
|
+
|
||
|
+ CMAC_CTX_free(c->cmac);
|
||
|
+ c->iv_set = 0;
|
||
|
+ c->key_set = 0;
|
||
|
+
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+kuznyechik_kexp15_wrap_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
|
||
|
+{
|
||
|
+ EVP_KUZNYECHIK_KEXP15_WRAP_CTX *key = EVP_C_DATA(EVP_KUZNYECHIK_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 kuznyechik_ctl(ctx, type, arg, ptr);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+kuznyechik_kexp15_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
|
||
|
+ size_t len)
|
||
|
+{
|
||
|
+ EVP_KUZNYECHIK_KEXP15_WRAP_CTX *key = EVP_C_DATA(EVP_KUZNYECHIK_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_ctr128_encrypt(in, out, len, &key->ks, ctx->iv, ctx->buf,
|
||
|
+ &ctx->num, (block128_f)Kuznyechik_encrypt);
|
||
|
+ CMAC_Final(key->cmac, tmp, &taglen);
|
||
|
+ CRYPTO_ctr128_encrypt(tmp, out + len, taglen, &key->ks, ctx->iv, ctx->buf,
|
||
|
+ &ctx->num, (block128_f)Kuznyechik_encrypt);
|
||
|
+ return len + taglen;
|
||
|
+ } else {
|
||
|
+ CRYPTO_ctr128_encrypt(in, out, len - bl, &key->ks, ctx->iv, ctx->buf,
|
||
|
+ &ctx->num, (block128_f)Kuznyechik_encrypt);
|
||
|
+ CMAC_Update(key->cmac, out, len - bl);
|
||
|
+ CMAC_Final(key->cmac, tmp, &taglen);
|
||
|
+ CRYPTO_ctr128_encrypt(tmp, tmp, taglen, &key->ks, ctx->iv, ctx->buf,
|
||
|
+ &ctx->num, (block128_f)Kuznyechik_encrypt);
|
||
|
+ return timingsafe_memcmp(in + len - bl, tmp, bl) ? -1 : len - bl;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+kuznyechik_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
|
||
|
+kuznyechik_kexp15_wrap_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
|
||
|
+{
|
||
|
+ /* No useful information in ASN.1 params */
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
IMPLEMENT_BLOCK_CIPHER(kuznyechik, ks, Kuznyechik, EVP_KUZNYECHIK_CTX,
|
||
|
NID_kuznyechik, 16, 32, 16, 128, 0, kuznyechik_init_key, NULL,
|
||
|
EVP_CIPHER_set_asn1_iv,
|
||
|
@@ -375,6 +507,17 @@ BLOCK_CIPHER_def1(kuznyechik, ctr_acpkm_omac, ctr_acpkm_omac, CTR, EVP_KUZNYECHI
|
||
|
kuznyechik_ctr_acpkm_omac_get_asn1_params,
|
||
|
kuznyechik_ctr_acpkm_omac_ctl)
|
||
|
|
||
|
+#define NID_kuznyechik_kexp15_wrap NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15
|
||
|
+
|
||
|
+BLOCK_CIPHER_def1(kuznyechik, kexp15_wrap, kexp15_wrap, WRAP, EVP_KUZNYECHIK_KEXP15_WRAP_CTX,
|
||
|
+ NID_kuznyechik, 1, 64, 32,
|
||
|
+ EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT,
|
||
|
+ kuznyechik_kexp15_wrap_init_key,
|
||
|
+ kuznyechik_kexp15_wrap_cleanup,
|
||
|
+ kuznyechik_kexp15_wrap_set_asn1_params,
|
||
|
+ kuznyechik_kexp15_wrap_get_asn1_params,
|
||
|
+ kuznyechik_kexp15_wrap_ctl)
|
||
|
+
|
||
|
#define EVP_AEAD_KUZNYECHIK_MGM_TAG_LEN 16
|
||
|
|
||
|
typedef struct {
|
||
|
diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h
|
||
|
index 48c7e7360..79ddcebc2 100644
|
||
|
--- a/src/lib/libcrypto/evp/evp.h
|
||
|
+++ b/src/lib/libcrypto/evp/evp.h
|
||
|
@@ -865,6 +865,7 @@ 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_ctr_acpkm_omac(void);
|
||
|
+const EVP_CIPHER *EVP_kuznyechik_kexp15_wrap(void);
|
||
|
const EVP_CIPHER *EVP_kuznyechik_mgm(void);
|
||
|
#endif
|
||
|
|
||
|
--
|
||
|
2.17.1
|
||
|
|