]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_omac.c
Make grasshopper OMAC result size 8 instead of 4
[openssl-gost/engine.git] / gost_omac.c
1 #include <string.h>
2 #include <openssl/cmac.h>
3 #include <openssl/conf.h>
4 #include <openssl/err.h>
5 #include <openssl/evp.h>
6
7 #include "e_gost_err.h"
8 #include "gost_lcl.h"
9
10 typedef struct omac_ctx {
11         CMAC_CTX *cmac_ctx;
12         size_t   dgst_size;
13         int      cipher_nid;
14         int      key_set;
15 } OMAC_CTX;
16
17 #define MAX_GOST_OMAC_SIZE 16
18
19 static int omac_init(EVP_MD_CTX *ctx, int cipher_nid)
20 {
21     OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
22                 memset(c, 0, sizeof(OMAC_CTX));
23                 c->cipher_nid = cipher_nid;
24                 c->key_set    = 0;
25
26                 switch(cipher_nid) {
27                         case NID_magma_cbc:
28                                 c->dgst_size = 4;
29                         break;
30
31                         case NID_grasshopper_cbc:
32                                 c->dgst_size = 8;
33                         break;
34                 }
35
36     return 1;
37 }
38
39 static int magma_imit_init(EVP_MD_CTX *ctx)
40 {
41     return omac_init(ctx, NID_magma_cbc);
42 }
43
44 static int grasshopper_imit_init(EVP_MD_CTX *ctx)
45 {
46     return omac_init(ctx, NID_grasshopper_cbc);
47 }
48
49 static int omac_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
50 {
51     OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
52                 if (!c->key_set)
53                 {
54         GOSTerr(GOST_F_OMAC_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET);
55         return 0;
56                 }
57
58                 return CMAC_Update(c->cmac_ctx, data, count);
59 }
60
61 int omac_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
62 {
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);
66
67     if (!c->key_set) {
68         GOSTerr(GOST_F_OMAC_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET);
69         return 0;
70     }
71
72                 CMAC_Final(c->cmac_ctx, mac, &mac_size);
73
74     memcpy(md, mac, c->dgst_size);
75     return 1;
76 }
77
78 int omac_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
79 {
80     OMAC_CTX *c_to = EVP_MD_CTX_md_data(to);
81                 const OMAC_CTX *c_from = EVP_MD_CTX_md_data(from);
82
83     if (c_from && c_to) {
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;
87     }
88                 else
89                 {
90                         return 0;
91                 }
92                 if (c_to->cmac_ctx == c_from->cmac_ctx)
93                 {
94                         return 1;
95                 }
96                 return CMAC_CTX_copy(c_to->cmac_ctx, c_from->cmac_ctx);
97 }
98
99 /* Clean up imit ctx */
100 int omac_imit_cleanup(EVP_MD_CTX *ctx)
101 {
102     OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
103
104                 if (c)
105                 {
106                         CMAC_CTX_free(c->cmac_ctx);
107             memset(EVP_MD_CTX_md_data(ctx), 0, sizeof(OMAC_CTX));
108                 }
109     return 1;
110 }
111
112 static int omac_key(OMAC_CTX *c, const EVP_CIPHER *cipher, const unsigned char *key, size_t key_size)
113 {
114         int ret = 0;
115
116         c->cmac_ctx = CMAC_CTX_new();
117         if (c->cmac_ctx == NULL)
118         {
119                 GOSTerr(GOST_F_OMAC_KEY, ERR_R_MALLOC_FAILURE);
120                 return 0;
121         }
122
123         ret = CMAC_Init(c->cmac_ctx, key, key_size, cipher, NULL);
124         if (ret > 0)
125         {
126                 c->key_set = 1;
127         }
128         return 1;
129 }                                               
130
131 int omac_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
132 {
133     switch (type) {
134     case EVP_MD_CTRL_KEY_LEN:
135         *((unsigned int *)(ptr)) = 32;
136         return 1;
137     case EVP_MD_CTRL_SET_KEY:
138                                 {
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;
142
143                                         if (c->cipher_nid == NID_undef)
144                                         {
145                                                 switch (EVP_MD_nid(md))
146                                                 {
147                                                         case NID_magma_mac:
148                                                                 c->cipher_nid = NID_magma_cbc;
149                                                                 break;
150
151                                                         case NID_grasshopper_mac:
152                                                                 c->cipher_nid = NID_grasshopper_cbc;
153                                                                 break;
154                                                 }
155                                         }
156                                         cipher = EVP_get_cipherbynid(c->cipher_nid);
157
158                                         if (cipher == NULL)
159                                         {
160                                                 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_CIPHER_NOT_FOUND);
161                                         }
162
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);
165                                                 return 0;
166                                         }
167                                         EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
168
169                                         if (c->key_set)
170                                         {
171                                                 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_BAD_ORDER);
172                                                 return 0;
173                                         }
174
175                                         if (arg == 0) {
176                                                 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
177                                                 return omac_key(c, cipher, key->key, 32);
178
179                                         } else if (arg == 32) {
180                                                 return omac_key(c, cipher, ptr, 32);
181                                         }
182                                         GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
183                                         return 0;
184                                 }
185     case EVP_MD_CTRL_MAC_LEN:
186         {
187                                         OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
188                                         switch (c->cipher_nid)
189                                         {
190                                                 case NID_magma_cbc:
191             if (arg < 1 || arg > 8) {
192                 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
193                 return 0;
194             }
195             c->dgst_size = arg;
196                                                 break;
197                                                 case NID_grasshopper_cbc:
198             if (arg < 1 || arg > 16) {
199                 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
200                 return 0;
201             }
202             c->dgst_size = arg;
203                                                 break;
204                                                 default:
205                                                 return 0;
206                                         }
207           return 1;
208         }
209
210     default:
211         return 0;
212     }
213 }
214
215 static EVP_MD *_hidden_magma_mac_md = NULL;
216
217 EVP_MD *magma_omac(void)
218 {
219     if (_hidden_magma_mac_md == NULL) {
220         EVP_MD *md;
221
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);
234             md = NULL;
235         }
236        _hidden_magma_mac_md = md;
237     }
238     return _hidden_magma_mac_md;
239 }
240
241 void magma_omac_destroy(void)
242 {
243     EVP_MD_meth_free(_hidden_magma_mac_md);
244     _hidden_magma_mac_md = NULL;
245 }
246
247 static EVP_MD *_hidden_grasshopper_mac_md = NULL;
248
249 EVP_MD *grasshopper_omac(void)
250 {
251     if (_hidden_grasshopper_mac_md == NULL) {
252         EVP_MD *md;
253
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);
266             md = NULL;
267         }
268        _hidden_grasshopper_mac_md = md;
269     }
270     return _hidden_grasshopper_mac_md;
271 }
272
273 void grasshopper_omac_destroy(void)
274 {
275     EVP_MD_meth_free(_hidden_grasshopper_mac_md);
276     _hidden_grasshopper_mac_md = NULL;
277 }
278