mirror of
https://abf.rosa.ru/djam/libressl.git
synced 2025-02-23 16:12:53 +00:00
252 lines
7.2 KiB
Diff
252 lines
7.2 KiB
Diff
![]() |
From c797b2060c4a6bb2d7d9c3c9cb6aa6d4b6ed94c7 Mon Sep 17 00:00:00 2001
|
||
|
From: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
||
|
Date: Tue, 7 Apr 2020 16:34:52 +0300
|
||
|
Subject: [PATCH 51/87] evp: add support for Magma-ctr-acpkm-omac cipher
|
||
|
|
||
|
Add support for AEAD cipher implemented using CTR-ACPKM as block cipher
|
||
|
and CMAC as a MAC value.
|
||
|
|
||
|
Sponsored by ROSA Linux
|
||
|
|
||
|
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
|
||
|
---
|
||
|
src/lib/libcrypto/evp/c_all.c | 1 +
|
||
|
src/lib/libcrypto/evp/e_magma.c | 175 ++++++++++++++++++++++++++++++++
|
||
|
src/lib/libcrypto/evp/evp.h | 1 +
|
||
|
3 files changed, 177 insertions(+)
|
||
|
|
||
|
diff --git a/src/lib/libcrypto/evp/c_all.c b/src/lib/libcrypto/evp/c_all.c
|
||
|
index ef95d7d68..90d0f7e20 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_ctr_acpkm_omac());
|
||
|
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 ae78824eb..ffaeda505 100644
|
||
|
--- a/src/lib/libcrypto/evp/e_magma.c
|
||
|
+++ b/src/lib/libcrypto/evp/e_magma.c
|
||
|
@@ -25,6 +25,8 @@
|
||
|
#include <openssl/err.h>
|
||
|
#include <openssl/modes.h>
|
||
|
#include <openssl/gost.h>
|
||
|
+#include <openssl/cmac.h>
|
||
|
+#include <openssl/kdftree.h>
|
||
|
#include "evp_locl.h"
|
||
|
#include "modes_lcl.h"
|
||
|
|
||
|
@@ -32,6 +34,14 @@ typedef struct {
|
||
|
MAGMA_KEY ks;
|
||
|
} EVP_MAGMA_CTX;
|
||
|
|
||
|
+typedef struct {
|
||
|
+ MAGMA_KEY ks;
|
||
|
+ CMAC_CTX *cmac;
|
||
|
+ int iv_set;
|
||
|
+ int taglen;
|
||
|
+ unsigned char tag[8];
|
||
|
+} EVP_MAGMA_CTR_ACPKM_OMAC_CTX;
|
||
|
+
|
||
|
static int
|
||
|
magma_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||
|
const unsigned char *iv, int enc)
|
||
|
@@ -172,6 +182,160 @@ magma_ctr_acpkm_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
|
||
|
return gost3412_ctr_acpkm_get_asn1_params(ctx, params, EVP_CIPHER_CTX_iv_length(ctx));
|
||
|
}
|
||
|
|
||
|
+static int
|
||
|
+magma_ctr_acpkm_omac_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||
|
+ const unsigned char *iv, int enc)
|
||
|
+{
|
||
|
+ EVP_MAGMA_CTR_ACPKM_OMAC_CTX *c = ctx->cipher_data;
|
||
|
+ unsigned char out[64];
|
||
|
+
|
||
|
+ c->taglen = -1;
|
||
|
+ if (iv) {
|
||
|
+ unsigned int il = EVP_CIPHER_CTX_iv_length(ctx) - 8;
|
||
|
+ memcpy(ctx->iv, iv, il);
|
||
|
+ memset(ctx->iv + il, 0, EVP_MAX_IV_LENGTH - il);
|
||
|
+ memcpy(ctx->oiv, iv + il, 8);
|
||
|
+ c->iv_set = 1;
|
||
|
+ ctx->num = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!key)
|
||
|
+ return 1;
|
||
|
+
|
||
|
+ if (!c->iv_set)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if (!KDF_TREE(EVP_streebog256(), NULL,
|
||
|
+ key, EVP_CIPHER_CTX_key_length(ctx),
|
||
|
+ "kdf tree", 8,
|
||
|
+ ctx->oiv, 8,
|
||
|
+ 1,
|
||
|
+ out, sizeof(out)))
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ Magma_set_key(&c->ks, out);
|
||
|
+
|
||
|
+ return CMAC_Init(c->cmac, out + 32, 32, EVP_magma_cbc(), NULL);
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+magma_ctr_acpkm_omac_cleanup(EVP_CIPHER_CTX *ctx)
|
||
|
+{
|
||
|
+ EVP_MAGMA_CTR_ACPKM_OMAC_CTX *c = ctx->cipher_data;
|
||
|
+
|
||
|
+ CMAC_CTX_free(c->cmac);
|
||
|
+
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+magma_ctr_acpkm_omac_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
|
||
|
+{
|
||
|
+ EVP_MAGMA_CTR_ACPKM_OMAC_CTX *key = EVP_C_DATA(EVP_MAGMA_CTR_ACPKM_OMAC_CTX, ctx);
|
||
|
+
|
||
|
+ switch (type) {
|
||
|
+ case EVP_CTRL_GOST_SET_MESHING:
|
||
|
+ key->ks.key_meshing = arg;
|
||
|
+ return 1;
|
||
|
+ case EVP_CTRL_INIT:
|
||
|
+ /* deafult for tests */
|
||
|
+ key->ks.key_meshing = 16;
|
||
|
+ key->iv_set = 0;
|
||
|
+ key->cmac = CMAC_CTX_new();
|
||
|
+ return 1;
|
||
|
+ case EVP_CTRL_GCM_SET_TAG:
|
||
|
+ if (arg <= 0 || arg > sizeof(key->tag) || ctx->encrypt)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ memcpy(key->tag, ptr, arg);
|
||
|
+ key->taglen = arg;
|
||
|
+ return 1;
|
||
|
+ case EVP_CTRL_GCM_GET_TAG:
|
||
|
+ if (arg <= 0 || arg > sizeof(key->tag) || !ctx->encrypt || key->taglen < 0)
|
||
|
+ return 0;
|
||
|
+ memcpy(ptr, key->tag, arg);
|
||
|
+ return 1;
|
||
|
+ default:
|
||
|
+ return magma_ctl(ctx, type, arg, ptr);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+magma_ctr_acpkm_omac_final(EVP_CIPHER_CTX *ctx)
|
||
|
+{
|
||
|
+ EVP_MAGMA_CTR_ACPKM_OMAC_CTX *key = EVP_C_DATA(EVP_MAGMA_CTR_ACPKM_OMAC_CTX, ctx);
|
||
|
+ unsigned char tmp[EVP_MAX_BLOCK_LENGTH];
|
||
|
+ size_t taglen = sizeof(tmp);
|
||
|
+
|
||
|
+ /* Do not reuse IV */
|
||
|
+ key->iv_set = 0;
|
||
|
+
|
||
|
+ CMAC_Final(key->cmac, tmp, &taglen);
|
||
|
+ if (ctx->encrypt) {
|
||
|
+ CRYPTO_ctr64_encrypt(tmp, key->tag, taglen, &key->ks, ctx->iv, ctx->buf,
|
||
|
+ &ctx->num, (block64_f)Magma_acpkm_encrypt);
|
||
|
+ key->taglen = taglen;
|
||
|
+ } else {
|
||
|
+ CRYPTO_ctr64_encrypt(tmp, tmp, taglen, &key->ks, ctx->iv, ctx->buf,
|
||
|
+ &ctx->num, (block64_f)Magma_acpkm_encrypt);
|
||
|
+ if (key->taglen <= 0 ||
|
||
|
+ key->taglen > taglen ||
|
||
|
+ timingsafe_memcmp(tmp, key->tag, key->taglen))
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+magma_ctr_acpkm_omac_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
|
||
|
+ size_t len)
|
||
|
+{
|
||
|
+ EVP_MAGMA_CTR_ACPKM_OMAC_CTX *key = EVP_C_DATA(EVP_MAGMA_CTR_ACPKM_OMAC_CTX, ctx);
|
||
|
+
|
||
|
+ 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_acpkm_encrypt);
|
||
|
+ if (!ctx->encrypt)
|
||
|
+ CMAC_Update(key->cmac, out, len);
|
||
|
+
|
||
|
+ if (!in)
|
||
|
+ return magma_ctr_acpkm_omac_final(ctx);
|
||
|
+
|
||
|
+ return len;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+magma_ctr_acpkm_omac_set_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
|
||
|
+{
|
||
|
+ /* Also set meshing section size here.
|
||
|
+ * There is no other good place to enable meshing for CMS
|
||
|
+ */
|
||
|
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GOST_SET_MESHING, 8 * 1024, 0);
|
||
|
+
|
||
|
+ return gost3412_ctr_acpkm_set_asn1_params(ctx, params, EVP_CIPHER_CTX_iv_length(ctx) - 8);
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+magma_ctr_acpkm_omac_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
|
||
|
+{
|
||
|
+ int ret;
|
||
|
+ EVP_MAGMA_CTR_ACPKM_OMAC_CTX *key = EVP_C_DATA(EVP_MAGMA_CTR_ACPKM_OMAC_CTX, ctx);
|
||
|
+
|
||
|
+ /* Also set meshing section size here.
|
||
|
+ * There is no other good place to enable meshing for CMS
|
||
|
+ */
|
||
|
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GOST_SET_MESHING, 8 * 1024, 0);
|
||
|
+
|
||
|
+ ret = gost3412_ctr_acpkm_get_asn1_params(ctx, params, EVP_CIPHER_CTX_iv_length(ctx) - 8);
|
||
|
+ if (ret > 0)
|
||
|
+ key->iv_set = 1;
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
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,
|
||
|
@@ -194,6 +358,17 @@ BLOCK_CIPHER_def1(magma, ctr_acpkm, ctr_acpkm, CTR, EVP_MAGMA_CTX,
|
||
|
magma_ctr_acpkm_get_asn1_params,
|
||
|
magma_acpkm_ctl)
|
||
|
|
||
|
+#define NID_magma_ctr_acpkm_omac NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac
|
||
|
+
|
||
|
+BLOCK_CIPHER_def1(magma, ctr_acpkm_omac, ctr_acpkm_omac, CTR, EVP_MAGMA_CTR_ACPKM_OMAC_CTX,
|
||
|
+ NID_magma, 1, 32, 12,
|
||
|
+ EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CTRL_INIT | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV |EVP_CIPH_FLAG_CUSTOM_CIPHER,
|
||
|
+ magma_ctr_acpkm_omac_init_key,
|
||
|
+ magma_ctr_acpkm_omac_cleanup,
|
||
|
+ magma_ctr_acpkm_omac_set_asn1_params,
|
||
|
+ magma_ctr_acpkm_omac_get_asn1_params,
|
||
|
+ magma_ctr_acpkm_omac_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 9c618ddd5..981351d76 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_ctr_acpkm_omac(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
|
||
|
|