X-Git-Url: http://www.wagner.pp.ru/gitweb/?p=openssl-gost%2Fengine.git;a=blobdiff_plain;f=gost_omac_acpkm.c;h=8a3c841ad269feb43b297ae38c7123c7bf630eb5;hp=9bdb05f0e510ae2be0957531bfa777e329e79788;hb=HEAD;hpb=6b41c2e3f9335af1437a05e6f48bfec7e1841a75 diff --git a/gost_omac_acpkm.c b/gost_omac_acpkm.c index 9bdb05f..8a3c841 100644 --- a/gost_omac_acpkm.c +++ b/gost_omac_acpkm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 vt@altlinux.org. All Rights Reserved. + * Copyright (C) 2018,2020 Vitaly Chikunov . All Rights Reserved. * Copyright (c) 2010 The OpenSSL Project. All rights reserved. * * Contents licensed under the terms of the OpenSSL license @@ -58,7 +58,7 @@ static void make_kn(unsigned char *k1, unsigned char *l, int bl) 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(); @@ -68,6 +68,7 @@ static CMAC_ACPKM_CTX *CMAC_ACPKM_CTX_new(void) } ctx->actx = EVP_CIPHER_CTX_new(); if (ctx->actx == NULL) { + EVP_CIPHER_CTX_free(ctx->cctx); OPENSSL_free(ctx); return NULL; } @@ -97,7 +98,7 @@ static void CMAC_ACPKM_CTX_free(CMAC_ACPKM_CTX *ctx) 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) @@ -137,26 +138,23 @@ static int CMAC_ACPKM_Init(CMAC_ACPKM_CTX *ctx, const void *key, size_t keylen, 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); @@ -164,7 +162,7 @@ static int CMAC_ACPKM_Init(CMAC_ACPKM_CTX *ctx, const void *key, size_t keylen, 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)) @@ -251,13 +249,19 @@ static int CMAC_ACPKM_Update(CMAC_ACPKM_CTX *ctx, const void *in, size_t dlen) } +/* Return value is propagated to EVP_DigestFinal_ex */ 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 (bl != 8 && bl != 16) { + GOSTerr(GOST_F_OMAC_ACPKM_IMIT_FINAL, GOST_R_INVALID_MAC_PARAMS); + return 0; + } *poutlen = (size_t) bl; if (!out) return 1; @@ -265,10 +269,9 @@ static int CMAC_ACPKM_Final(CMAC_ACPKM_CTX *ctx, unsigned char *out, 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? */ @@ -299,20 +302,20 @@ static int CMAC_ACPKM_Final(CMAC_ACPKM_CTX *ctx, unsigned char *out, 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; @@ -323,7 +326,7 @@ static int omac_acpkm_init(EVP_MD_CTX *ctx, int cipher_nid) 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, @@ -343,26 +346,27 @@ int omac_acpkm_imit_final(EVP_MD_CTX *ctx, unsigned char *md) OMAC_ACPKM_CTX *c = EVP_MD_CTX_md_data(ctx); unsigned char mac[MAX_GOST_OMAC_ACPKM_SIZE]; size_t mac_size = sizeof(mac); + int ret; if (!c->key_set) { GOSTerr(GOST_F_OMAC_ACPKM_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET); return 0; } - CMAC_ACPKM_Final(c->cmac_ctx, mac, &mac_size); + ret = CMAC_ACPKM_Final(c->cmac_ctx, mac, &mac_size); memcpy(md, mac, c->dgst_size); - return 1; + return ret; } -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; @@ -374,14 +378,15 @@ int omac_acpkm_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) } 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); @@ -420,36 +425,41 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) { 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: { @@ -459,15 +469,26 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) 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); @@ -475,6 +496,13 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) } 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; } @@ -486,36 +514,16 @@ int omac_acpkm_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) } } -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, +};