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