/*
- * Copyright (C) 2018 vt@altlinux.org. All Rights Reserved.
+ * Copyright (C) 2018,2020 Vitaly Chikunov <vt@altlinux.org>. All Rights Reserved.
* Copyright (c) 2010 The OpenSSL Project. All rights reserved.
*
* Contents licensed under the terms of the OpenSSL license
static CMAC_ACPKM_CTX *CMAC_ACPKM_CTX_new(void)
{
CMAC_ACPKM_CTX *ctx;
- ctx = OPENSSL_malloc(sizeof(CMAC_ACPKM_CTX));
+ ctx = OPENSSL_zalloc(sizeof(CMAC_ACPKM_CTX));
if (!ctx)
return NULL;
ctx->cctx = EVP_CIPHER_CTX_new();
}
ctx->actx = EVP_CIPHER_CTX_new();
if (ctx->actx == NULL) {
+ EVP_CIPHER_CTX_free(ctx->cctx);
OPENSSL_free(ctx);
return NULL;
}
OPENSSL_free(ctx);
}
-int CMAC_ACPKM_CTX_copy(CMAC_ACPKM_CTX *out, const CMAC_ACPKM_CTX *in)
+static int CMAC_ACPKM_CTX_copy(CMAC_ACPKM_CTX *out, const CMAC_ACPKM_CTX *in)
{
int bl;
if (in->nlast_block == -1)
if (!EVP_EncryptInit_ex(ctx->cctx, cipher, impl, NULL, NULL))
return 0;
- switch (EVP_CIPHER_nid(cipher)) {
- case NID_grasshopper_cbc:
- acpkm = cipher_gost_grasshopper_ctracpkm();
- break;
- default:
- return 0;
- }
+ if (!EVP_CIPHER_is_a(cipher, SN_grasshopper_cbc))
+ return 0;
+ acpkm = cipher_gost_grasshopper_ctracpkm();
if (!EVP_EncryptInit_ex(ctx->actx, acpkm, impl, NULL, NULL))
return 0;
}
/* Non-NULL key means initialisation is complete */
if (key) {
unsigned char acpkm_iv[EVP_MAX_BLOCK_LENGTH];
+ int block_size, key_len;
/* Initialize CTR for ACPKM-Master */
if (!EVP_CIPHER_CTX_cipher(ctx->actx))
return 0;
/* block size of ACPKM cipher could be 1, but,
* cbc cipher is same with correct block_size */
- const int block_size = EVP_CIPHER_CTX_block_size(ctx->cctx);
+ block_size = EVP_CIPHER_CTX_block_size(ctx->cctx);
/* Wide IV = 1^{n/2} || 0,
* where a^r denotes the string that consists of r 'a' bits */
memset(acpkm_iv, 0xff, block_size / 2);
if (!EVP_EncryptInit_ex(ctx->actx, NULL, NULL, key, acpkm_iv))
return 0;
/* EVP_CIPHER key_len may be different from EVP_CIPHER_CTX key_len */
- int key_len = EVP_CIPHER_key_length(EVP_CIPHER_CTX_cipher(ctx->actx));
+ key_len = EVP_CIPHER_key_length(EVP_CIPHER_CTX_cipher(ctx->actx));
/* Generate first key material (K^1 || K^1_1) */
if (!EVP_Cipher(ctx->actx, ctx->km, zero_iv, key_len + block_size))
static int CMAC_ACPKM_Final(CMAC_ACPKM_CTX *ctx, unsigned char *out,
size_t *poutlen)
{
- int i, bl, lb;
+ int i, bl, lb, key_len;
+ unsigned char *k1, k2[EVP_MAX_BLOCK_LENGTH];
if (ctx->nlast_block == -1)
return 0;
bl = EVP_CIPHER_CTX_block_size(ctx->cctx);
if (!CMAC_ACPKM_Mesh(ctx))
return 0;
- int key_len = EVP_CIPHER_key_length(EVP_CIPHER_CTX_cipher(ctx->actx));
+ key_len = EVP_CIPHER_key_length(EVP_CIPHER_CTX_cipher(ctx->actx));
/* Keys k1 and k2 */
- unsigned char *k1 = ctx->km + key_len;
- unsigned char k2[EVP_MAX_BLOCK_LENGTH];
+ k1 = ctx->km + key_len;
make_kn(k2, ctx->km + key_len, bl);
/* Is last block complete? */
typedef struct omac_acpkm_ctx {
CMAC_ACPKM_CTX *cmac_ctx;
size_t dgst_size;
- int cipher_nid;
+ const char *cipher_name;
int key_set;
} OMAC_ACPKM_CTX;
#define MAX_GOST_OMAC_ACPKM_SIZE 16
-static int omac_acpkm_init(EVP_MD_CTX *ctx, int cipher_nid)
+static int omac_acpkm_init(EVP_MD_CTX *ctx, const char *cipher_name)
{
OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx);
memset(c, 0, sizeof(OMAC_ACPKM_CTX));
- c->cipher_nid = cipher_nid;
+ c->cipher_name = cipher_name;
c->key_set = 0;
- switch (cipher_nid) {
+ switch (OBJ_txt2nid(cipher_name)) {
case NID_grasshopper_cbc:
c->dgst_size = 16;
break;
static int grasshopper_omac_acpkm_init(EVP_MD_CTX *ctx)
{
- return omac_acpkm_init(ctx, NID_grasshopper_cbc);
+ return omac_acpkm_init(ctx, SN_grasshopper_cbc);
}
static int omac_acpkm_imit_update(EVP_MD_CTX *ctx, const void *data,
return 1;
}
-int omac_acpkm_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
+static int omac_acpkm_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
{
OMAC_ACPKM_CTX *c_to = EVP_MD_CTX_md_data(to);
const OMAC_ACPKM_CTX *c_from = EVP_MD_CTX_md_data(from);
if (c_from && c_to) {
c_to->dgst_size = c_from->dgst_size;
- c_to->cipher_nid = c_from->cipher_nid;
+ c_to->cipher_name = c_from->cipher_name;
c_to->key_set = c_from->key_set;
} else {
return 0;
}
return 1;
}
- if (c_to->cmac_ctx == c_from->cmac_ctx) {
+ if ((c_to->cmac_ctx == c_from->cmac_ctx) || (c_to->cmac_ctx == NULL)) {
c_to->cmac_ctx = CMAC_ACPKM_CTX_new();
}
- return CMAC_ACPKM_CTX_copy(c_to->cmac_ctx, c_from->cmac_ctx);
+
+ return (c_to->cmac_ctx) ? CMAC_ACPKM_CTX_copy(c_to->cmac_ctx, c_from->cmac_ctx) : 0;
}
/* Clean up imit ctx */
-int omac_acpkm_imit_cleanup(EVP_MD_CTX *ctx)
+static int omac_acpkm_imit_cleanup(EVP_MD_CTX *ctx)
{
OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx);
{
OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx);
const EVP_MD *md = EVP_MD_CTX_md(ctx);
- const EVP_CIPHER *cipher = NULL;
+ EVP_CIPHER *cipher = NULL;
+ int ret = 0;
- if (c->cipher_nid == NID_undef) {
- switch (EVP_MD_nid(md)) {
- case NID_grasshopper_mac:
- c->cipher_nid = NID_grasshopper_cbc;
- break;
- }
+ if (c->cipher_name == NULL) {
+ if (EVP_MD_is_a(md, SN_grasshopper_mac)
+ || EVP_MD_is_a(md, SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac))
+ c->cipher_name = SN_grasshopper_cbc;
}
- cipher = EVP_get_cipherbynid(c->cipher_nid);
- if (cipher == NULL) {
+ if ((cipher =
+ (EVP_CIPHER *)EVP_get_cipherbyname(c->cipher_name)) == NULL
+ && (cipher =
+ EVP_CIPHER_fetch(NULL, c->cipher_name, NULL)) == NULL) {
GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_CIPHER_NOT_FOUND);
}
if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) {
GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET);
- return 0;
+ goto set_key_end;
}
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
if (c->key_set) {
GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_BAD_ORDER);
- return 0;
+ goto set_key_end;
}
if (arg == 0) {
struct gost_mac_key *key = (struct gost_mac_key *)ptr;
- return omac_acpkm_key(c, cipher, key->key, 32);
+ ret = omac_acpkm_key(c, cipher, key->key, 32);
+ goto set_key_end;
} else if (arg == 32) {
- return omac_acpkm_key(c, cipher, ptr, 32);
+ ret = omac_acpkm_key(c, cipher, ptr, 32);
+ goto set_key_end;
}
GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
- return 0;
+ set_key_end:
+ EVP_CIPHER_free(cipher);
+ return ret;
}
case EVP_CTRL_KEY_MESH:
{
c->cmac_ctx->section_size = arg;
if (ptr && *(int *)ptr) {
/* Set parameter T */
- if (!EVP_CIPHER_CTX_ctrl(c->cmac_ctx->actx, EVP_CTRL_KEY_MESH, *(int *)ptr, NULL))
- return 0;
+ if (EVP_CIPHER_get0_provider(EVP_CIPHER_CTX_cipher(c->cmac_ctx->actx))
+ == NULL) {
+ if (!EVP_CIPHER_CTX_ctrl(c->cmac_ctx->actx, EVP_CTRL_KEY_MESH,
+ *(int *)ptr, NULL))
+ return 0;
+ } else {
+ size_t cipher_key_mesh = (size_t)*(int *)ptr;
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ params[0] = OSSL_PARAM_construct_size_t("key-mesh",
+ &cipher_key_mesh);
+ if (!EVP_CIPHER_CTX_set_params(c->cmac_ctx->actx, params))
+ return 0;
+ }
}
return 1;
}
- case EVP_MD_CTRL_MAC_LEN:
+ case EVP_MD_CTRL_XOF_LEN: /* Supported in OpenSSL */
{
OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx);
- switch (c->cipher_nid) {
+ switch (OBJ_txt2nid(c->cipher_name)) {
case NID_grasshopper_cbc:
if (arg < 1 || arg > 16) {
GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
}
c->dgst_size = arg;
break;
+ case NID_magma_cbc:
+ if (arg < 1 || arg > 8) {
+ GOSTerr(GOST_F_OMAC_ACPKM_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
+ return 0;
+ }
+ c->dgst_size = arg;
+ break;
default:
return 0;
}
}
}
-static EVP_MD *_hidden_grasshopper_omac_acpkm_md = NULL;
-
-EVP_MD *grasshopper_omac_acpkm(void)
-{
- if (_hidden_grasshopper_omac_acpkm_md == NULL) {
- EVP_MD *md;
-
- if ((md =
- EVP_MD_meth_new(NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
- NID_undef)) == NULL
- || !EVP_MD_meth_set_result_size(md, MAX_GOST_OMAC_ACPKM_SIZE)
- || !EVP_MD_meth_set_input_blocksize(md, GRASSHOPPER_BLOCK_SIZE)
- || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_ACPKM_CTX))
- || !EVP_MD_meth_set_flags(md, 0)
- || !EVP_MD_meth_set_init(md, grasshopper_omac_acpkm_init)
- || !EVP_MD_meth_set_update(md, omac_acpkm_imit_update)
- || !EVP_MD_meth_set_final(md, omac_acpkm_imit_final)
- || !EVP_MD_meth_set_copy(md, omac_acpkm_imit_copy)
- || !EVP_MD_meth_set_cleanup(md, omac_acpkm_imit_cleanup)
- || !EVP_MD_meth_set_ctrl(md, omac_acpkm_imit_ctrl)) {
- EVP_MD_meth_free(md);
- md = NULL;
- }
- _hidden_grasshopper_omac_acpkm_md = md;
- }
- return _hidden_grasshopper_omac_acpkm_md;
-}
-
-void grasshopper_omac_acpkm_destroy(void)
-{
- EVP_MD_meth_free(_hidden_grasshopper_omac_acpkm_md);
- _hidden_grasshopper_omac_acpkm_md = NULL;
-}
+GOST_digest kuznyechik_ctracpkm_omac_digest = {
+ .nid = NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
+ .result_size = MAX_GOST_OMAC_ACPKM_SIZE,
+ .input_blocksize = GRASSHOPPER_BLOCK_SIZE,
+ .app_datasize = sizeof(OMAC_ACPKM_CTX),
+ .flags = EVP_MD_FLAG_XOF,
+ .init = grasshopper_omac_acpkm_init,
+ .update = omac_acpkm_imit_update,
+ .final = omac_acpkm_imit_final,
+ .copy = omac_acpkm_imit_copy,
+ .cleanup = omac_acpkm_imit_cleanup,
+ .ctrl = omac_acpkm_imit_ctrl,
+};