From c9c7e6ed9d8c2deffdfe30c977ca91d2297177a9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov 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 --- 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