]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_omac.c
Merge pull request #86 from vt-alt/curves
[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 #define min(a,b) (((a) < (b)) ? (a) : (b))
11
12 typedef struct omac_ctx {
13     CMAC_CTX *cmac_ctx;
14     size_t dgst_size;
15     int cipher_nid;
16     int key_set;
17 /* 
18  * Here begins stuff related to TLSTREE processing
19  * We MUST store the original key to derive TLSTREE keys from it
20  * and TLS seq no.
21  * */
22     unsigned char key[32];
23 /*
24  * TODO
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.
29  * */
30 } OMAC_CTX;
31
32 #define MAX_GOST_OMAC_SIZE 16
33
34 static int omac_init(EVP_MD_CTX *ctx, int cipher_nid)
35 {
36     OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
37     memset(c, 0, sizeof(OMAC_CTX));
38     c->cipher_nid = cipher_nid;
39     c->key_set = 0;
40
41     switch (cipher_nid) {
42     case NID_magma_cbc:
43         c->dgst_size = 8;
44         break;
45
46     case NID_grasshopper_cbc:
47         c->dgst_size = 16;
48         break;
49     }
50
51     return 1;
52 }
53
54 static int magma_imit_init(EVP_MD_CTX *ctx)
55 {
56     return omac_init(ctx, NID_magma_cbc);
57 }
58
59 static int grasshopper_imit_init(EVP_MD_CTX *ctx)
60 {
61     return omac_init(ctx, NID_grasshopper_cbc);
62 }
63
64 static int omac_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
65 {
66     OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
67     if (!c->key_set) {
68         GOSTerr(GOST_F_OMAC_IMIT_UPDATE, GOST_R_MAC_KEY_NOT_SET);
69         return 0;
70     }
71
72     return CMAC_Update(c->cmac_ctx, data, count);
73 }
74
75 int omac_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
76 {
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);
80
81     if (!c->key_set) {
82         GOSTerr(GOST_F_OMAC_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET);
83         return 0;
84     }
85
86     CMAC_Final(c->cmac_ctx, mac, &mac_size);
87
88     memcpy(md, mac, c->dgst_size);
89     return 1;
90 }
91
92 int omac_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
93 {
94     OMAC_CTX *c_to = EVP_MD_CTX_md_data(to);
95     const OMAC_CTX *c_from = EVP_MD_CTX_md_data(from);
96
97     if (c_from && c_to) {
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);
102     } else {
103         return 0;
104     }
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;
109         }
110         return 1;
111     }
112     if (c_to->cmac_ctx == c_from->cmac_ctx) {
113         c_to->cmac_ctx = CMAC_CTX_new();
114     }
115     return CMAC_CTX_copy(c_to->cmac_ctx, c_from->cmac_ctx);
116 }
117
118 /* Clean up imit ctx */
119 int omac_imit_cleanup(EVP_MD_CTX *ctx)
120 {
121     OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
122
123     if (c) {
124         CMAC_CTX_free(c->cmac_ctx);
125         memset(EVP_MD_CTX_md_data(ctx), 0, sizeof(OMAC_CTX));
126     }
127     return 1;
128 }
129
130 static int omac_key(OMAC_CTX * c, const EVP_CIPHER *cipher,
131                     const unsigned char *key, size_t key_size)
132 {
133     int ret = 0;
134
135     c->cmac_ctx = CMAC_CTX_new();
136     if (c->cmac_ctx == NULL) {
137         GOSTerr(GOST_F_OMAC_KEY, ERR_R_MALLOC_FAILURE);
138         return 0;
139     }
140
141     ret = CMAC_Init(c->cmac_ctx, key, key_size, cipher, NULL);
142     if (ret > 0) {
143         c->key_set = 1;
144     }
145     return 1;
146 }
147
148 int omac_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
149 {
150     switch (type) {
151     case EVP_MD_CTRL_KEY_LEN:
152         *((unsigned int *)(ptr)) = 32;
153         return 1;
154     case EVP_MD_CTRL_SET_KEY:
155         {
156             OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
157             const EVP_MD *md = EVP_MD_CTX_md(ctx);
158             const EVP_CIPHER *cipher = NULL;
159             int ret = 0;
160
161             if (c->cipher_nid == NID_undef) {
162                 switch (EVP_MD_nid(md)) {
163                 case NID_magma_mac:
164                     c->cipher_nid = NID_magma_cbc;
165                     break;
166
167                 case NID_grasshopper_mac:
168                     c->cipher_nid = NID_grasshopper_cbc;
169                     break;
170                 }
171             }
172             cipher = EVP_get_cipherbynid(c->cipher_nid);
173
174             if (cipher == NULL) {
175                 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_CIPHER_NOT_FOUND);
176             }
177
178             if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) {
179                 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET);
180                 return 0;
181             }
182             EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
183
184             if (c->key_set) {
185                 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_BAD_ORDER);
186                 return 0;
187             }
188
189             if (arg == 0) {
190                 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
191                 ret = omac_key(c, cipher, key->key, 32);
192                 if (ret > 0)
193                     memcpy(c->key, key->key, 32);
194                 return ret;
195             } else if (arg == 32) {
196                 ret = omac_key(c, cipher, ptr, 32);
197                 if (ret > 0)
198                     memcpy(c->key, ptr, 32);
199                 return ret;
200             }
201             GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
202             return 0;
203         }
204     case EVP_MD_CTRL_MAC_LEN:
205         {
206             OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
207             switch (c->cipher_nid) {
208             case NID_magma_cbc:
209                 if (arg < 1 || arg > 8) {
210                     GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
211                     return 0;
212                 }
213                 c->dgst_size = arg;
214                 break;
215             case NID_grasshopper_cbc:
216                 if (arg < 1 || arg > 16) {
217                     GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
218                     return 0;
219                 }
220                 c->dgst_size = arg;
221                 break;
222             default:
223                 return 0;
224             }
225             return 1;
226         }
227 #ifdef EVP_MD_CTRL_TLSTREE
228     case EVP_MD_CTRL_TLSTREE:
229         {
230             OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
231             if (c->key_set) {
232                 unsigned char diversed_key[32];
233                 return gost_tlstree(c->cipher_nid, c->key, diversed_key,
234                                     (const unsigned char *)ptr) ?
235                     omac_key(c, EVP_get_cipherbynid(c->cipher_nid),
236                              diversed_key, 32) : 0;
237             }
238             GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_BAD_ORDER);
239             return 0;
240         }
241         return 0;
242 #endif
243     default:
244         return 0;
245     }
246 }
247
248 static EVP_MD *_hidden_magma_mac_md = NULL;
249
250 EVP_MD *magma_omac(void)
251 {
252     if (_hidden_magma_mac_md == NULL) {
253         EVP_MD *md;
254
255         if ((md = EVP_MD_meth_new(NID_magma_mac, NID_undef)) == NULL
256             || !EVP_MD_meth_set_result_size(md, 8)
257             || !EVP_MD_meth_set_input_blocksize(md, 8)
258             || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX))
259             || !EVP_MD_meth_set_flags(md, 0)
260             || !EVP_MD_meth_set_init(md, magma_imit_init)
261             || !EVP_MD_meth_set_update(md, omac_imit_update)
262             || !EVP_MD_meth_set_final(md, omac_imit_final)
263             || !EVP_MD_meth_set_copy(md, omac_imit_copy)
264             || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup)
265             || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) {
266             EVP_MD_meth_free(md);
267             md = NULL;
268         }
269         _hidden_magma_mac_md = md;
270     }
271     return _hidden_magma_mac_md;
272 }
273
274 void magma_omac_destroy(void)
275 {
276     EVP_MD_meth_free(_hidden_magma_mac_md);
277     _hidden_magma_mac_md = NULL;
278 }
279
280 static EVP_MD *_hidden_grasshopper_mac_md = NULL;
281
282 EVP_MD *grasshopper_omac(void)
283 {
284     if (_hidden_grasshopper_mac_md == NULL) {
285         EVP_MD *md;
286
287         if ((md = EVP_MD_meth_new(NID_grasshopper_mac, NID_undef)) == NULL
288             || !EVP_MD_meth_set_result_size(md, 16)
289             || !EVP_MD_meth_set_input_blocksize(md, 8)
290             || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX))
291             || !EVP_MD_meth_set_flags(md, 0)
292             || !EVP_MD_meth_set_init(md, grasshopper_imit_init)
293             || !EVP_MD_meth_set_update(md, omac_imit_update)
294             || !EVP_MD_meth_set_final(md, omac_imit_final)
295             || !EVP_MD_meth_set_copy(md, omac_imit_copy)
296             || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup)
297             || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) {
298             EVP_MD_meth_free(md);
299             md = NULL;
300         }
301         _hidden_grasshopper_mac_md = md;
302     }
303     return _hidden_grasshopper_mac_md;
304 }
305
306 void grasshopper_omac_destroy(void)
307 {
308     EVP_MD_meth_free(_hidden_grasshopper_mac_md);
309     _hidden_grasshopper_mac_md = NULL;
310 }