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