2 #include <openssl/cmac.h>
3 #include <openssl/conf.h>
4 #include <openssl/err.h>
5 #include <openssl/evp.h>
7 #include "e_gost_err.h"
10 typedef struct omac_ctx {
17 #define MAX_GOST_OMAC_SIZE 16
19 static int omac_init(EVP_MD_CTX *ctx, int cipher_nid)
21 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
22 memset(c, 0, sizeof(OMAC_CTX));
23 c->cipher_nid = cipher_nid;
31 case NID_grasshopper_cbc:
39 static int magma_imit_init(EVP_MD_CTX *ctx)
41 return omac_init(ctx, NID_magma_cbc);
44 static int grasshopper_imit_init(EVP_MD_CTX *ctx)
46 return omac_init(ctx, NID_grasshopper_cbc);
49 static int omac_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
51 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
54 GOSTerr(GOST_F_OMAC_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET);
58 return CMAC_Update(c->cmac_ctx, data, count);
61 int omac_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
63 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
64 unsigned char mac[MAX_GOST_OMAC_SIZE];
65 size_t mac_size = sizeof(mac);
68 GOSTerr(GOST_F_OMAC_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET);
72 CMAC_Final(c->cmac_ctx, mac, &mac_size);
74 memcpy(md, mac, c->dgst_size);
78 int omac_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
80 OMAC_CTX *c_to = EVP_MD_CTX_md_data(to);
81 const OMAC_CTX *c_from = EVP_MD_CTX_md_data(from);
84 c_to->dgst_size = c_from->dgst_size;
85 c_to->cipher_nid = c_from->cipher_nid;
86 c_to->key_set = c_from->key_set;
92 if (c_to->cmac_ctx == c_from->cmac_ctx)
94 c_to->cmac_ctx = CMAC_CTX_new();
96 return CMAC_CTX_copy(c_to->cmac_ctx, c_from->cmac_ctx);
99 /* Clean up imit ctx */
100 int omac_imit_cleanup(EVP_MD_CTX *ctx)
102 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
106 CMAC_CTX_free(c->cmac_ctx);
107 memset(EVP_MD_CTX_md_data(ctx), 0, sizeof(OMAC_CTX));
112 static int omac_key(OMAC_CTX *c, const EVP_CIPHER *cipher, const unsigned char *key, size_t key_size)
116 c->cmac_ctx = CMAC_CTX_new();
117 if (c->cmac_ctx == NULL)
119 GOSTerr(GOST_F_OMAC_KEY, ERR_R_MALLOC_FAILURE);
123 ret = CMAC_Init(c->cmac_ctx, key, key_size, cipher, NULL);
131 int omac_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
134 case EVP_MD_CTRL_KEY_LEN:
135 *((unsigned int *)(ptr)) = 32;
137 case EVP_MD_CTRL_SET_KEY:
139 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
140 const EVP_MD *md = EVP_MD_CTX_md(ctx);
141 const EVP_CIPHER *cipher = NULL;
143 if (c->cipher_nid == NID_undef)
145 switch (EVP_MD_nid(md))
148 c->cipher_nid = NID_magma_cbc;
151 case NID_grasshopper_mac:
152 c->cipher_nid = NID_grasshopper_cbc;
156 cipher = EVP_get_cipherbynid(c->cipher_nid);
160 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_CIPHER_NOT_FOUND);
163 if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) {
164 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET);
167 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
171 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_BAD_ORDER);
176 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
177 return omac_key(c, cipher, key->key, 32);
179 } else if (arg == 32) {
180 return omac_key(c, cipher, ptr, 32);
182 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
185 case EVP_MD_CTRL_MAC_LEN:
187 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
188 switch (c->cipher_nid)
191 if (arg < 1 || arg > 8) {
192 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
197 case NID_grasshopper_cbc:
198 if (arg < 1 || arg > 16) {
199 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
215 static EVP_MD *_hidden_magma_mac_md = NULL;
217 EVP_MD *magma_omac(void)
219 if (_hidden_magma_mac_md == NULL) {
222 if ((md = EVP_MD_meth_new(NID_magma_mac, NID_undef)) == NULL
223 || !EVP_MD_meth_set_result_size(md, 4)
224 || !EVP_MD_meth_set_input_blocksize(md, 8)
225 || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX))
226 || !EVP_MD_meth_set_flags(md, 0)
227 || !EVP_MD_meth_set_init(md, magma_imit_init)
228 || !EVP_MD_meth_set_update(md, omac_imit_update)
229 || !EVP_MD_meth_set_final(md, omac_imit_final)
230 || !EVP_MD_meth_set_copy(md, omac_imit_copy)
231 || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup)
232 || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) {
233 EVP_MD_meth_free(md);
236 _hidden_magma_mac_md = md;
238 return _hidden_magma_mac_md;
241 void magma_omac_destroy(void)
243 EVP_MD_meth_free(_hidden_magma_mac_md);
244 _hidden_magma_mac_md = NULL;
247 static EVP_MD *_hidden_grasshopper_mac_md = NULL;
249 EVP_MD *grasshopper_omac(void)
251 if (_hidden_grasshopper_mac_md == NULL) {
254 if ((md = EVP_MD_meth_new(NID_grasshopper_mac, NID_undef)) == NULL
255 || !EVP_MD_meth_set_result_size(md, 8)
256 || !EVP_MD_meth_set_input_blocksize(md, 8)
257 || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX))
258 || !EVP_MD_meth_set_flags(md, 0)
259 || !EVP_MD_meth_set_init(md, grasshopper_imit_init)
260 || !EVP_MD_meth_set_update(md, omac_imit_update)
261 || !EVP_MD_meth_set_final(md, omac_imit_final)
262 || !EVP_MD_meth_set_copy(md, omac_imit_copy)
263 || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup)
264 || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) {
265 EVP_MD_meth_free(md);
268 _hidden_grasshopper_mac_md = md;
270 return _hidden_grasshopper_mac_md;
273 void grasshopper_omac_destroy(void)
275 EVP_MD_meth_free(_hidden_grasshopper_mac_md);
276 _hidden_grasshopper_mac_md = NULL;