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 #define min(a,b) (((a) < (b)) ? (a) : (b))
12 typedef struct omac_ctx {
18 * Here begins stuff related to TLSTREE processing
19 * We MUST store the original key to derive TLSTREE keys from it
22 unsigned char key[32];
25 * TLSTREE intermediate values should be recalculated only when
26 * C_i & (seq_no+1) != C_i & (seq_no)
27 * so somewhen we will store C_i & (seq_no) in this structure
28 * to avoid redundant hash calculations.
32 #define MAX_GOST_OMAC_SIZE 16
34 static int omac_init(EVP_MD_CTX *ctx, int cipher_nid)
36 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
37 memset(c, 0, sizeof(OMAC_CTX));
38 c->cipher_nid = cipher_nid;
46 case NID_grasshopper_cbc:
54 static int magma_imit_init(EVP_MD_CTX *ctx)
56 return omac_init(ctx, NID_magma_cbc);
59 static int grasshopper_imit_init(EVP_MD_CTX *ctx)
61 return omac_init(ctx, NID_grasshopper_cbc);
64 static int omac_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
66 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
68 GOSTerr(GOST_F_OMAC_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET);
72 return CMAC_Update(c->cmac_ctx, data, count);
75 int omac_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
77 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
78 unsigned char mac[MAX_GOST_OMAC_SIZE];
79 size_t mac_size = sizeof(mac);
82 GOSTerr(GOST_F_OMAC_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET);
86 CMAC_Final(c->cmac_ctx, mac, &mac_size);
88 memcpy(md, mac, c->dgst_size);
92 int omac_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
94 OMAC_CTX *c_to = EVP_MD_CTX_md_data(to);
95 const OMAC_CTX *c_from = EVP_MD_CTX_md_data(from);
98 c_to->dgst_size = c_from->dgst_size;
99 c_to->cipher_nid = c_from->cipher_nid;
100 c_to->key_set = c_from->key_set;
101 memcpy(c_to->key, c_from->key, 32);
105 if (!c_from->cmac_ctx) {
106 if (c_to->cmac_ctx) {
107 CMAC_CTX_free(c_to->cmac_ctx);
108 c_to->cmac_ctx = NULL;
112 if (c_to->cmac_ctx == c_from->cmac_ctx) {
113 c_to->cmac_ctx = CMAC_CTX_new();
115 return CMAC_CTX_copy(c_to->cmac_ctx, c_from->cmac_ctx);
118 /* Clean up imit ctx */
119 int omac_imit_cleanup(EVP_MD_CTX *ctx)
121 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
124 CMAC_CTX_free(c->cmac_ctx);
125 memset(EVP_MD_CTX_md_data(ctx), 0, sizeof(OMAC_CTX));
130 static int omac_key(OMAC_CTX * c, const EVP_CIPHER *cipher,
131 const unsigned char *key, size_t key_size)
135 CMAC_CTX_free(c->cmac_ctx);
136 c->cmac_ctx = CMAC_CTX_new();
137 if (c->cmac_ctx == NULL) {
138 GOSTerr(GOST_F_OMAC_KEY, ERR_R_MALLOC_FAILURE);
142 ret = CMAC_Init(c->cmac_ctx, key, key_size, cipher, NULL);
149 int omac_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
152 case EVP_MD_CTRL_KEY_LEN:
153 *((unsigned int *)(ptr)) = 32;
155 case EVP_MD_CTRL_SET_KEY:
157 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
158 const EVP_MD *md = EVP_MD_CTX_md(ctx);
159 const EVP_CIPHER *cipher = NULL;
162 if (c->cipher_nid == NID_undef) {
163 switch (EVP_MD_nid(md)) {
165 c->cipher_nid = NID_magma_cbc;
168 case NID_grasshopper_mac:
169 c->cipher_nid = NID_grasshopper_cbc;
173 cipher = EVP_get_cipherbynid(c->cipher_nid);
175 if (cipher == NULL) {
176 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_CIPHER_NOT_FOUND);
179 if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) {
180 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET);
183 EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
186 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_BAD_ORDER);
191 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
192 ret = omac_key(c, cipher, key->key, 32);
194 memcpy(c->key, key->key, 32);
196 } else if (arg == 32) {
197 ret = omac_key(c, cipher, ptr, 32);
199 memcpy(c->key, ptr, 32);
202 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
205 case EVP_MD_CTRL_MAC_LEN:
206 case EVP_MD_CTRL_XOF_LEN: /* Supported in OpenSSL */
208 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
209 switch (c->cipher_nid) {
211 if (arg < 1 || arg > 8) {
212 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
217 case NID_grasshopper_cbc:
218 if (arg < 1 || arg > 16) {
219 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
229 #ifdef EVP_MD_CTRL_TLSTREE
230 case EVP_MD_CTRL_TLSTREE:
232 OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
234 unsigned char diversed_key[32];
235 return gost_tlstree(c->cipher_nid, c->key, diversed_key,
236 (const unsigned char *)ptr) ?
237 omac_key(c, EVP_get_cipherbynid(c->cipher_nid),
238 diversed_key, 32) : 0;
240 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_BAD_ORDER);
250 static EVP_MD *_hidden_magma_mac_md = NULL;
252 EVP_MD *magma_omac(void)
254 if (_hidden_magma_mac_md == NULL) {
257 if ((md = EVP_MD_meth_new(NID_magma_mac, NID_undef)) == NULL
258 || !EVP_MD_meth_set_result_size(md, 8)
259 || !EVP_MD_meth_set_input_blocksize(md, 8)
260 || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX))
261 || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_XOF)
262 || !EVP_MD_meth_set_init(md, magma_imit_init)
263 || !EVP_MD_meth_set_update(md, omac_imit_update)
264 || !EVP_MD_meth_set_final(md, omac_imit_final)
265 || !EVP_MD_meth_set_copy(md, omac_imit_copy)
266 || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup)
267 || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) {
268 EVP_MD_meth_free(md);
271 _hidden_magma_mac_md = md;
273 return _hidden_magma_mac_md;
276 void magma_omac_destroy(void)
278 EVP_MD_meth_free(_hidden_magma_mac_md);
279 _hidden_magma_mac_md = NULL;
282 static EVP_MD *_hidden_grasshopper_mac_md = NULL;
284 EVP_MD *grasshopper_omac(void)
286 if (_hidden_grasshopper_mac_md == NULL) {
289 if ((md = EVP_MD_meth_new(NID_grasshopper_mac, NID_undef)) == NULL
290 || !EVP_MD_meth_set_result_size(md, 16)
291 || !EVP_MD_meth_set_input_blocksize(md, 8)
292 || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX))
293 || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_XOF)
294 || !EVP_MD_meth_set_init(md, grasshopper_imit_init)
295 || !EVP_MD_meth_set_update(md, omac_imit_update)
296 || !EVP_MD_meth_set_final(md, omac_imit_final)
297 || !EVP_MD_meth_set_copy(md, omac_imit_copy)
298 || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup)
299 || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) {
300 EVP_MD_meth_free(md);
303 _hidden_grasshopper_mac_md = md;
305 return _hidden_grasshopper_mac_md;
308 void grasshopper_omac_destroy(void)
310 EVP_MD_meth_free(_hidden_grasshopper_mac_md);
311 _hidden_grasshopper_mac_md = NULL;