]>
Commit | Line | Data |
---|---|---|
5e55159b RL |
1 | /* |
2 | * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4a8b0c55 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5e55159b RL |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <openssl/err.h> | |
11 | #include <openssl/evp.h> | |
12 | #include "internal/evp_int.h" | |
13 | ||
14 | /* MAC PKEY context structure */ | |
15 | ||
16 | typedef struct { | |
17 | EVP_MAC_CTX *ctx; | |
18 | ||
19 | /* | |
20 | * We know of two MAC types: | |
21 | * | |
22 | * 1. those who take a secret in raw form, i.e. raw data as a | |
23 | * ASN1_OCTET_STRING embedded in a EVP_PKEY. So far, that's | |
24 | * all of them but CMAC. | |
25 | * 2. those who take a secret with associated cipher in very generic | |
26 | * form, i.e. a complete EVP_MAC_CTX embedded in a PKEY. So far, | |
27 | * only CMAC does this. | |
28 | * | |
29 | * (one might wonder why the second form isn't used for all) | |
30 | */ | |
31 | #define MAC_TYPE_RAW 1 /* HMAC like MAC type (all but CMAC so far) */ | |
32 | #define MAC_TYPE_MAC 2 /* CMAC like MAC type (only CMAC known so far) */ | |
33 | int type; | |
34 | ||
35 | /* The following is only used for MAC_TYPE_RAW implementations */ | |
36 | struct { | |
37 | const EVP_MD *md; /* temp storage of MD */ | |
38 | ASN1_OCTET_STRING ktmp; /* temp storage for key */ | |
39 | } raw_data; | |
40 | } MAC_PKEY_CTX; | |
41 | ||
42 | static int pkey_mac_init(EVP_PKEY_CTX *ctx) | |
43 | { | |
44 | MAC_PKEY_CTX *hctx; | |
45 | int nid = ctx->pmeth->pkey_id; | |
46 | ||
47 | if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) { | |
48 | EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE); | |
49 | return 0; | |
50 | } | |
51 | ||
52 | /* We're being smart and using the same base NIDs for PKEY and for MAC */ | |
53 | hctx->ctx = EVP_MAC_CTX_new_id(nid); | |
54 | if (hctx->ctx == NULL) { | |
55 | OPENSSL_free(hctx); | |
56 | return 0; | |
57 | } | |
58 | ||
59 | if (nid == EVP_PKEY_CMAC) { | |
60 | hctx->type = MAC_TYPE_MAC; | |
61 | } else { | |
62 | hctx->type = MAC_TYPE_RAW; | |
63 | hctx->raw_data.ktmp.type = V_ASN1_OCTET_STRING; | |
64 | } | |
65 | ||
66 | EVP_PKEY_CTX_set_data(ctx, hctx); | |
67 | ctx->keygen_info_count = 0; | |
68 | ||
69 | return 1; | |
70 | } | |
71 | ||
72 | static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx); | |
73 | ||
74 | static int pkey_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) | |
75 | { | |
76 | MAC_PKEY_CTX *sctx, *dctx; | |
77 | ||
78 | if (!pkey_mac_init(dst)) | |
79 | return 0; | |
80 | ||
81 | sctx = EVP_PKEY_CTX_get_data(src); | |
82 | dctx = EVP_PKEY_CTX_get_data(dst); | |
83 | ||
84 | if (!EVP_MAC_CTX_copy(dctx->ctx, sctx->ctx)) | |
85 | goto err; | |
86 | ||
87 | switch (dctx->type) { | |
88 | case MAC_TYPE_RAW: | |
89 | dctx->raw_data.md = sctx->raw_data.md; | |
90 | if (ASN1_STRING_get0_data(&sctx->raw_data.ktmp) != NULL && | |
91 | !ASN1_STRING_copy(&dctx->raw_data.ktmp, &sctx->raw_data.ktmp)) | |
92 | goto err; | |
93 | break; | |
94 | case MAC_TYPE_MAC: | |
95 | /* Nothing more to do */ | |
96 | break; | |
97 | default: | |
98 | /* This should be dead code */ | |
99 | return 0; | |
100 | } | |
101 | return 1; | |
102 | err: | |
103 | pkey_mac_cleanup (dst); | |
104 | return 0; | |
105 | } | |
106 | ||
107 | static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx) | |
108 | { | |
109 | MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); | |
110 | ||
111 | if (hctx != NULL) { | |
112 | switch (hctx->type) { | |
113 | case MAC_TYPE_RAW: | |
114 | OPENSSL_clear_free(hctx->raw_data.ktmp.data, | |
115 | hctx->raw_data.ktmp.length); | |
116 | break; | |
117 | } | |
118 | EVP_MAC_CTX_free(hctx->ctx); | |
119 | OPENSSL_free(hctx); | |
120 | EVP_PKEY_CTX_set_data(ctx, NULL); | |
121 | } | |
122 | } | |
123 | ||
124 | static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) | |
125 | { | |
126 | MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); | |
127 | int nid = ctx->pmeth->pkey_id; | |
128 | ||
129 | switch (hctx->type) { | |
130 | case MAC_TYPE_RAW: | |
131 | { | |
132 | ASN1_OCTET_STRING *hkey = NULL; | |
133 | ||
134 | if (!hctx->raw_data.ktmp.data) | |
135 | return 0; | |
136 | hkey = ASN1_OCTET_STRING_dup(&hctx->raw_data.ktmp); | |
137 | if (!hkey) | |
138 | return 0; | |
139 | EVP_PKEY_assign(pkey, nid, hkey); | |
140 | } | |
141 | break; | |
142 | case MAC_TYPE_MAC: | |
143 | { | |
144 | EVP_MAC_CTX *cmkey = EVP_MAC_CTX_new_id(nid); | |
145 | ||
146 | if (cmkey == NULL) | |
147 | return 0; | |
148 | if (!EVP_MAC_CTX_copy(cmkey, hctx->ctx)) { | |
149 | EVP_MAC_CTX_free(cmkey); | |
150 | return 0; | |
151 | } | |
152 | EVP_PKEY_assign(pkey, nid, cmkey); | |
153 | } | |
154 | break; | |
155 | default: | |
156 | /* This should be dead code */ | |
157 | return 0; | |
158 | } | |
159 | ||
160 | return 1; | |
161 | } | |
162 | ||
163 | static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count) | |
164 | { | |
165 | MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx)); | |
166 | ||
167 | if (!EVP_MAC_update(hctx->ctx, data, count)) | |
168 | return 0; | |
169 | return 1; | |
170 | } | |
171 | ||
172 | static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) | |
173 | { | |
174 | MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); | |
175 | ASN1_OCTET_STRING *key = NULL; | |
176 | int rv = 1; | |
177 | /* | |
178 | * For MACs with the EVP_PKEY_FLAG_SIGCTX_CUSTOM flag set and that | |
179 | * gets the key passed as an ASN.1 OCTET STRING, we set the key here, | |
180 | * as this may be only time it's set during a DigestSign. | |
181 | * | |
182 | * MACs that pass around the key in form of EVP_MAC_CTX are setting | |
183 | * the key through other mechanisms. (this is only CMAC for now) | |
184 | */ | |
185 | int set_key = | |
186 | hctx->type == MAC_TYPE_RAW | |
187 | && (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0; | |
188 | ||
189 | if (set_key) { | |
190 | if (EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx)) | |
191 | != EVP_MAC_nid(EVP_MAC_CTX_mac(hctx->ctx))) | |
192 | return 0; | |
193 | key = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx)); | |
194 | if (key == NULL) | |
195 | return 0; | |
196 | } | |
197 | ||
198 | /* Some MACs don't support this control... that's fine */ | |
199 | EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_FLAGS, | |
200 | EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT)); | |
201 | ||
202 | EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT); | |
203 | EVP_MD_CTX_set_update_fn(mctx, int_update); | |
204 | ||
205 | if (set_key) | |
206 | rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, key->data, | |
207 | key->length); | |
208 | return rv > 0; | |
209 | } | |
210 | ||
211 | static int pkey_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, | |
212 | size_t *siglen, EVP_MD_CTX *mctx) | |
213 | { | |
214 | MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); | |
215 | ||
216 | return EVP_MAC_final(hctx->ctx, sig, siglen); | |
217 | } | |
218 | ||
219 | static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) | |
220 | { | |
221 | MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); | |
222 | ||
223 | switch (type) { | |
224 | ||
225 | case EVP_PKEY_CTRL_CIPHER: | |
226 | switch (hctx->type) { | |
227 | case MAC_TYPE_RAW: | |
228 | return -2; /* The raw types don't support ciphers */ | |
229 | case MAC_TYPE_MAC: | |
230 | { | |
231 | int rv; | |
232 | ||
233 | if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE, | |
234 | ctx->engine)) < 0 | |
235 | || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_CIPHER, | |
236 | p2)) < 0 | |
237 | || !(rv = EVP_MAC_init(hctx->ctx))) | |
238 | return rv; | |
239 | } | |
240 | break; | |
241 | default: | |
242 | /* This should be dead code */ | |
243 | return 0; | |
244 | } | |
245 | break; | |
246 | ||
247 | case EVP_PKEY_CTRL_MD: | |
248 | switch (hctx->type) { | |
249 | case MAC_TYPE_RAW: | |
250 | hctx->raw_data.md = p2; | |
251 | break; | |
252 | case MAC_TYPE_MAC: | |
253 | if (ctx->pkey != NULL | |
254 | && !EVP_MAC_CTX_copy(hctx->ctx, | |
255 | (EVP_MAC_CTX *)ctx->pkey->pkey.ptr)) | |
256 | return 0; | |
257 | if (!EVP_MAC_init(hctx->ctx)) | |
258 | return 0; | |
259 | break; | |
260 | default: | |
261 | /* This should be dead code */ | |
262 | return 0; | |
263 | } | |
264 | break; | |
265 | ||
266 | case EVP_PKEY_CTRL_SET_DIGEST_SIZE: | |
267 | return EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_SIZE, (size_t)p1); | |
268 | ||
269 | case EVP_PKEY_CTRL_SET_MAC_KEY: | |
270 | switch (hctx->type) { | |
271 | case MAC_TYPE_RAW: | |
272 | if ((!p2 && p1 > 0) || (p1 < -1)) | |
273 | return 0; | |
274 | if (!ASN1_OCTET_STRING_set(&hctx->raw_data.ktmp, p2, p1)) | |
275 | return 0; | |
276 | break; | |
277 | case MAC_TYPE_MAC: | |
278 | if (!EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1)) | |
279 | return 0; | |
280 | break; | |
281 | default: | |
282 | /* This should be dead code */ | |
283 | return 0; | |
284 | } | |
285 | break; | |
286 | ||
287 | case EVP_PKEY_CTRL_DIGESTINIT: | |
288 | switch (hctx->type) { | |
289 | case MAC_TYPE_RAW: | |
290 | /* Ensure that we have attached the implementation */ | |
291 | if (!EVP_MAC_init(hctx->ctx)) | |
292 | return 0; | |
293 | { | |
294 | int rv; | |
295 | ASN1_OCTET_STRING *key = | |
296 | (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr; | |
297 | ||
298 | if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE, | |
299 | ctx->engine)) < 0 | |
300 | || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_MD, | |
301 | hctx->raw_data.md)) < 0 | |
302 | || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, | |
303 | key->data, key->length)) < 0) | |
304 | return rv; | |
305 | } | |
306 | break; | |
307 | case MAC_TYPE_MAC: | |
308 | return -2; /* The mac types don't support ciphers */ | |
309 | default: | |
310 | /* This should be dead code */ | |
311 | return 0; | |
312 | } | |
313 | break; | |
314 | ||
315 | default: | |
316 | return -2; | |
317 | ||
318 | } | |
319 | return 1; | |
320 | } | |
321 | ||
322 | static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx, | |
323 | const char *type, const char *value) | |
324 | { | |
325 | MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx); | |
326 | ||
327 | return EVP_MAC_ctrl_str(hctx->ctx, type, value); | |
328 | } | |
329 | ||
e74a435f RL |
330 | const EVP_PKEY_METHOD cmac_pkey_meth = { |
331 | EVP_PKEY_CMAC, | |
5e55159b RL |
332 | EVP_PKEY_FLAG_SIGCTX_CUSTOM, |
333 | pkey_mac_init, | |
334 | pkey_mac_copy, | |
335 | pkey_mac_cleanup, | |
336 | ||
337 | 0, 0, | |
338 | ||
339 | 0, | |
340 | pkey_mac_keygen, | |
341 | ||
342 | 0, 0, | |
343 | ||
344 | 0, 0, | |
345 | ||
346 | 0, 0, | |
347 | ||
348 | pkey_mac_signctx_init, | |
349 | pkey_mac_signctx, | |
350 | ||
351 | 0, 0, | |
352 | ||
353 | 0, 0, | |
354 | ||
355 | 0, 0, | |
356 | ||
357 | 0, 0, | |
358 | ||
359 | pkey_mac_ctrl, | |
360 | pkey_mac_ctrl_str | |
361 | }; | |
f8c9a8e3 RL |
362 | |
363 | const EVP_PKEY_METHOD hmac_pkey_meth = { | |
364 | EVP_PKEY_HMAC, | |
365 | 0, | |
366 | pkey_mac_init, | |
367 | pkey_mac_copy, | |
368 | pkey_mac_cleanup, | |
369 | ||
370 | 0, 0, | |
371 | ||
372 | 0, | |
373 | pkey_mac_keygen, | |
374 | ||
375 | 0, 0, | |
376 | ||
377 | 0, 0, | |
378 | ||
379 | 0, 0, | |
380 | ||
381 | pkey_mac_signctx_init, | |
382 | pkey_mac_signctx, | |
383 | ||
384 | 0, 0, | |
385 | ||
386 | 0, 0, | |
387 | ||
388 | 0, 0, | |
389 | ||
390 | 0, 0, | |
391 | ||
392 | pkey_mac_ctrl, | |
393 | pkey_mac_ctrl_str | |
394 | }; | |
14f61f81 RL |
395 | |
396 | const EVP_PKEY_METHOD siphash_pkey_meth = { | |
397 | EVP_PKEY_SIPHASH, | |
398 | EVP_PKEY_FLAG_SIGCTX_CUSTOM, | |
399 | pkey_mac_init, | |
400 | pkey_mac_copy, | |
401 | pkey_mac_cleanup, | |
402 | ||
403 | 0, 0, | |
404 | ||
405 | 0, | |
406 | pkey_mac_keygen, | |
407 | ||
408 | 0, 0, | |
409 | ||
410 | 0, 0, | |
411 | ||
412 | 0, 0, | |
413 | ||
414 | pkey_mac_signctx_init, | |
415 | pkey_mac_signctx, | |
416 | ||
417 | 0, 0, | |
418 | ||
419 | 0, 0, | |
420 | ||
421 | 0, 0, | |
422 | ||
423 | 0, 0, | |
424 | ||
425 | pkey_mac_ctrl, | |
426 | pkey_mac_ctrl_str | |
427 | }; | |
c1da4b2a PY |
428 | |
429 | const EVP_PKEY_METHOD poly1305_pkey_meth = { | |
430 | EVP_PKEY_POLY1305, | |
431 | EVP_PKEY_FLAG_SIGCTX_CUSTOM, | |
432 | pkey_mac_init, | |
433 | pkey_mac_copy, | |
434 | pkey_mac_cleanup, | |
435 | ||
436 | 0, 0, | |
437 | ||
438 | 0, | |
439 | pkey_mac_keygen, | |
440 | ||
441 | 0, 0, | |
442 | ||
443 | 0, 0, | |
444 | ||
445 | 0, 0, | |
446 | ||
447 | pkey_mac_signctx_init, | |
448 | pkey_mac_signctx, | |
449 | ||
450 | 0, 0, | |
451 | ||
452 | 0, 0, | |
453 | ||
454 | 0, 0, | |
455 | ||
456 | 0, 0, | |
457 | ||
458 | pkey_mac_ctrl, | |
459 | pkey_mac_ctrl_str | |
460 | }; |