diff options
author | Dmitry Belyavskiy <beldmit@gmail.com> | 2018-06-14 18:14:55 +0300 |
---|---|---|
committer | Dmitry Belyavskiy <beldmit@gmail.com> | 2018-06-14 18:14:55 +0300 |
commit | 14e654cab19089027b00733594480eb03d8c6da5 (patch) | |
tree | 7c52ab5c0ba83def7e2e66d3605a03b196c1a3d6 /gost_omac.c | |
parent | debbfa1ae38f18ea06750514dd950775ad9889d8 (diff) | |
download | gost-engine-14e654cab19089027b00733594480eb03d8c6da5.zip gost-engine-14e654cab19089027b00733594480eb03d8c6da5.tar.gz gost-engine-14e654cab19089027b00733594480eb03d8c6da5.tar.bz2 |
OMACs implementation. Unfinished.
Diffstat (limited to 'gost_omac.c')
-rw-r--r-- | gost_omac.c | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/gost_omac.c b/gost_omac.c new file mode 100644 index 0000000..ad96662 --- /dev/null +++ b/gost_omac.c @@ -0,0 +1,258 @@ +#include <string.h> +#include <openssl/cmac.h> +#include <openssl/conf.h> +#include <openssl/err.h> +#include <openssl/evp.h> + +#include "e_gost_err.h" +#include "gost_lcl.h" + +typedef struct omac_ctx { + CMAC_CTX *cmac_ctx; + size_t dgst_size; + int cipher_nid; + int key_set; +} OMAC_CTX; + +#define MAX_GOST_OMAC_SIZE 16 + +static int omac_init(EVP_MD_CTX *ctx, int cipher_nid) +{ + OMAC_CTX *c = EVP_MD_CTX_md_data(ctx); + memset(c, 0, sizeof(OMAC_CTX)); + c->cipher_nid = cipher_nid; + c->key_set = 0; + + switch(cipher_nid) { + case NID_magma_cbc: + c->dgst_size = 4; + break; + + case NID_grasshopper_cbc: + c->dgst_size = 8; + break; + } + + return 1; +} + +static int magma_imit_init(EVP_MD_CTX *ctx) +{ + return omac_init(ctx, NID_magma_cbc); +} + +static int grasshopper_imit_init(EVP_MD_CTX *ctx) +{ + return omac_init(ctx, NID_grasshopper_cbc); +} + +static int omac_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ + OMAC_CTX *c = EVP_MD_CTX_md_data(ctx); + if (!c->key_set) + { + GOSTerr(GOST_F_OMAC_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET); + return 0; + } + + return CMAC_Update(c->cmac_ctx, data, count); +} + +int omac_imit_final(EVP_MD_CTX *ctx, unsigned char *md) +{ + OMAC_CTX *c = EVP_MD_CTX_md_data(ctx); + unsigned char mac[MAX_GOST_OMAC_SIZE]; + size_t mac_size = sizeof(mac); + + if (!c->key_set) { + GOSTerr(GOST_F_OMAC_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET); + return 0; + } + + CMAC_Final(c->cmac_ctx, mac, &mac_size); + + memcpy(md, mac, c->dgst_size); + return 1; +} + +int omac_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) +{ + OMAC_CTX *c_to = EVP_MD_CTX_md_data(to); + const OMAC_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->key_set = c_from->key_set; + } + else + { + return 0; + } + return CMAC_CTX_copy(c_to->cmac_ctx, c_from->cmac_ctx); +} + +/* Clean up imit ctx */ +int omac_imit_cleanup(EVP_MD_CTX *ctx) +{ + OMAC_CTX *c = EVP_MD_CTX_md_data(ctx); + + if (c) + { + CMAC_CTX_free(c->cmac_ctx); + memset(EVP_MD_CTX_md_data(ctx), 0, sizeof(OMAC_CTX)); + } + return 1; +} + +static int omac_key(OMAC_CTX *c, const EVP_CIPHER *cipher, const unsigned char *key, size_t key_size) +{ + int ret = 0; + + c->cmac_ctx = CMAC_CTX_new(); + if (c->cmac_ctx == NULL) + { + GOSTerr(GOST_F_OMAC_KEY, ERR_R_MALLOC_FAILURE); + return 0; + } + + ret = CMAC_Init(c->cmac_ctx, key, key_size, cipher, NULL); + if (ret > 0) + { + c->key_set = 1; + } + return 1; +} + +int omac_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) +{ + switch (type) { + case EVP_MD_CTRL_KEY_LEN: + *((unsigned int *)(ptr)) = 32; + return 1; + case EVP_MD_CTRL_SET_KEY: + { + OMAC_CTX *c = EVP_MD_CTX_md_data(ctx); + const EVP_CIPHER *cipher = EVP_get_cipherbynid(c->cipher_nid); + + if (cipher == NULL) + { + GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_CIPHER_NOT_FOUND); + } + + if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) { + GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET); + return 0; + } + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT); + + if (c->key_set) + { + GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_BAD_ORDER); + return 0; + } + + if (arg == 0) { + struct gost_mac_key *key = (struct gost_mac_key *)ptr; + return omac_key(c, cipher, key->key, 32); + + } else if (arg == 32) { + return omac_key(c, cipher, ptr, 32); + } + GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE); + return 0; + } + case EVP_MD_CTRL_MAC_LEN: + { + OMAC_CTX *c = EVP_MD_CTX_md_data(ctx); + switch (c->cipher_nid) + { + case NID_magma_cbc: + if (arg < 1 || arg > 8) { + GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE); + return 0; + } + c->dgst_size = arg; + break; + case NID_grasshopper_cbc: + if (arg < 1 || arg > 16) { + GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE); + return 0; + } + c->dgst_size = arg; + break; + default: + return 0; + } + return 1; + } + + default: + return 0; + } +} + +static EVP_MD *_hidden_magma_mac_md = NULL; + +EVP_MD *magma_omac(void) +{ + if (_hidden_magma_mac_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_magma_mac, NID_undef)) == NULL + || !EVP_MD_meth_set_result_size(md, 4) + || !EVP_MD_meth_set_input_blocksize(md, 8) + || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX)) + || !EVP_MD_meth_set_flags(md, 0) + || !EVP_MD_meth_set_init(md, magma_imit_init) + || !EVP_MD_meth_set_update(md, omac_imit_update) + || !EVP_MD_meth_set_final(md, omac_imit_final) + || !EVP_MD_meth_set_copy(md, omac_imit_copy) + || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup) + || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) { + EVP_MD_meth_free(md); + md = NULL; + } + _hidden_magma_mac_md = md; + } + return _hidden_magma_mac_md; +} + +void magma_omac_destroy(void) +{ + EVP_MD_meth_free(_hidden_magma_mac_md); + _hidden_magma_mac_md = NULL; +} + +static EVP_MD *_hidden_grasshopper_mac_md = NULL; + +EVP_MD *grasshopper_omac(void) +{ + if (_hidden_grasshopper_mac_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_grasshopper_mac, NID_undef)) == NULL + || !EVP_MD_meth_set_result_size(md, 4) + || !EVP_MD_meth_set_input_blocksize(md, 8) + || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX)) + || !EVP_MD_meth_set_flags(md, 0) + || !EVP_MD_meth_set_init(md, grasshopper_imit_init) + || !EVP_MD_meth_set_update(md, omac_imit_update) + || !EVP_MD_meth_set_final(md, omac_imit_final) + || !EVP_MD_meth_set_copy(md, omac_imit_copy) + || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup) + || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) { + EVP_MD_meth_free(md); + md = NULL; + } + _hidden_grasshopper_mac_md = md; + } + return _hidden_grasshopper_mac_md; +} + +void grasshopper_omac_destroy(void) +{ + EVP_MD_meth_free(_hidden_grasshopper_mac_md); + _hidden_grasshopper_mac_md = NULL; +} + |