]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_omac.c
91e9a48b5794ac0c1eb075de3dea21f8aaaf2b09
[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     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);
139         return 0;
140     }
141
142     ret = CMAC_Init(c->cmac_ctx, key, key_size, cipher, NULL);
143     if (ret > 0) {
144         c->key_set = 1;
145     }
146     return 1;
147 }
148
149 int omac_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
150 {
151     switch (type) {
152     case EVP_MD_CTRL_KEY_LEN:
153         *((unsigned int *)(ptr)) = 32;
154         return 1;
155     case EVP_MD_CTRL_SET_KEY:
156         {
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;
160             int ret = 0;
161
162             if (c->cipher_nid == NID_undef) {
163                 switch (EVP_MD_nid(md)) {
164                 case NID_magma_mac:
165                     c->cipher_nid = NID_magma_cbc;
166                     break;
167
168                 case NID_grasshopper_mac:
169                     c->cipher_nid = NID_grasshopper_cbc;
170                     break;
171                 }
172             }
173             cipher = EVP_get_cipherbynid(c->cipher_nid);
174
175             if (cipher == NULL) {
176                 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_CIPHER_NOT_FOUND);
177             }
178
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);
181                 return 0;
182             }
183             EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT);
184
185             if (c->key_set) {
186                 GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_BAD_ORDER);
187                 return 0;
188             }
189
190             if (arg == 0) {
191                 struct gost_mac_key *key = (struct gost_mac_key *)ptr;
192                 ret = omac_key(c, cipher, key->key, 32);
193                 if (ret > 0)
194                     memcpy(c->key, key->key, 32);
195                 return ret;
196             } else if (arg == 32) {
197                 ret = omac_key(c, cipher, ptr, 32);
198                 if (ret > 0)
199                     memcpy(c->key, ptr, 32);
200                 return ret;
201             }
202             GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
203             return 0;
204         }
205     case EVP_MD_CTRL_MAC_LEN:
206         {
207             OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
208             switch (c->cipher_nid) {
209             case NID_magma_cbc:
210                 if (arg < 1 || arg > 8) {
211                     GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
212                     return 0;
213                 }
214                 c->dgst_size = arg;
215                 break;
216             case NID_grasshopper_cbc:
217                 if (arg < 1 || arg > 16) {
218                     GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
219                     return 0;
220                 }
221                 c->dgst_size = arg;
222                 break;
223             default:
224                 return 0;
225             }
226             return 1;
227         }
228 #ifdef EVP_MD_CTRL_TLSTREE
229     case EVP_MD_CTRL_TLSTREE:
230         {
231             OMAC_CTX *c = EVP_MD_CTX_md_data(ctx);
232             if (c->key_set) {
233                 unsigned char diversed_key[32];
234                 return gost_tlstree(c->cipher_nid, c->key, diversed_key,
235                                     (const unsigned char *)ptr) ?
236                     omac_key(c, EVP_get_cipherbynid(c->cipher_nid),
237                              diversed_key, 32) : 0;
238             }
239             GOSTerr(GOST_F_OMAC_IMIT_CTRL, GOST_R_BAD_ORDER);
240             return 0;
241         }
242         return 0;
243 #endif
244     default:
245         return 0;
246     }
247 }
248
249 static EVP_MD *_hidden_magma_mac_md = NULL;
250
251 EVP_MD *magma_omac(void)
252 {
253     if (_hidden_magma_mac_md == NULL) {
254         EVP_MD *md;
255
256         if ((md = EVP_MD_meth_new(NID_magma_mac, NID_undef)) == NULL
257             || !EVP_MD_meth_set_result_size(md, 8)
258             || !EVP_MD_meth_set_input_blocksize(md, 8)
259             || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX))
260             || !EVP_MD_meth_set_flags(md, 0)
261             || !EVP_MD_meth_set_init(md, magma_imit_init)
262             || !EVP_MD_meth_set_update(md, omac_imit_update)
263             || !EVP_MD_meth_set_final(md, omac_imit_final)
264             || !EVP_MD_meth_set_copy(md, omac_imit_copy)
265             || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup)
266             || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) {
267             EVP_MD_meth_free(md);
268             md = NULL;
269         }
270         _hidden_magma_mac_md = md;
271     }
272     return _hidden_magma_mac_md;
273 }
274
275 void magma_omac_destroy(void)
276 {
277     EVP_MD_meth_free(_hidden_magma_mac_md);
278     _hidden_magma_mac_md = NULL;
279 }
280
281 static EVP_MD *_hidden_grasshopper_mac_md = NULL;
282
283 EVP_MD *grasshopper_omac(void)
284 {
285     if (_hidden_grasshopper_mac_md == NULL) {
286         EVP_MD *md;
287
288         if ((md = EVP_MD_meth_new(NID_grasshopper_mac, NID_undef)) == NULL
289             || !EVP_MD_meth_set_result_size(md, 16)
290             || !EVP_MD_meth_set_input_blocksize(md, 8)
291             || !EVP_MD_meth_set_app_datasize(md, sizeof(OMAC_CTX))
292             || !EVP_MD_meth_set_flags(md, 0)
293             || !EVP_MD_meth_set_init(md, grasshopper_imit_init)
294             || !EVP_MD_meth_set_update(md, omac_imit_update)
295             || !EVP_MD_meth_set_final(md, omac_imit_final)
296             || !EVP_MD_meth_set_copy(md, omac_imit_copy)
297             || !EVP_MD_meth_set_cleanup(md, omac_imit_cleanup)
298             || !EVP_MD_meth_set_ctrl(md, omac_imit_ctrl)) {
299             EVP_MD_meth_free(md);
300             md = NULL;
301         }
302         _hidden_grasshopper_mac_md = md;
303     }
304     return _hidden_grasshopper_mac_md;
305 }
306
307 void grasshopper_omac_destroy(void)
308 {
309     EVP_MD_meth_free(_hidden_grasshopper_mac_md);
310     _hidden_grasshopper_mac_md = NULL;
311 }