]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/pkey_mac.c
Modify providers that keep track of underlying algorithms
[thirdparty/openssl.git] / crypto / evp / pkey_mac.c
CommitLineData
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
e74bd290 10#include <string.h>
5e55159b
RL
11#include <openssl/err.h>
12#include <openssl/evp.h>
e74bd290
RL
13#include <openssl/engine.h>
14#include <openssl/params.h>
15#include <openssl/core_names.h>
5e55159b 16#include "internal/evp_int.h"
be5fc053 17#include "evp_locl.h"
5e55159b
RL
18
19/* MAC PKEY context structure */
20
21typedef struct {
22 EVP_MAC_CTX *ctx;
23
24 /*
25 * We know of two MAC types:
26 *
27 * 1. those who take a secret in raw form, i.e. raw data as a
28 * ASN1_OCTET_STRING embedded in a EVP_PKEY. So far, that's
29 * all of them but CMAC.
30 * 2. those who take a secret with associated cipher in very generic
31 * form, i.e. a complete EVP_MAC_CTX embedded in a PKEY. So far,
32 * only CMAC does this.
33 *
34 * (one might wonder why the second form isn't used for all)
35 */
36#define MAC_TYPE_RAW 1 /* HMAC like MAC type (all but CMAC so far) */
37#define MAC_TYPE_MAC 2 /* CMAC like MAC type (only CMAC known so far) */
38 int type;
39
40 /* The following is only used for MAC_TYPE_RAW implementations */
41 struct {
42 const EVP_MD *md; /* temp storage of MD */
43 ASN1_OCTET_STRING ktmp; /* temp storage for key */
44 } raw_data;
45} MAC_PKEY_CTX;
46
e74bd290
RL
47static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx);
48
5e55159b
RL
49static int pkey_mac_init(EVP_PKEY_CTX *ctx)
50{
51 MAC_PKEY_CTX *hctx;
e74bd290 52 /* We're being smart and using the same base NIDs for PKEY and for MAC */
5e55159b 53 int nid = ctx->pmeth->pkey_id;
e74bd290 54 EVP_MAC *mac = EVP_MAC_fetch(NULL, OBJ_nid2sn(nid), NULL);
5e55159b
RL
55
56 if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
57 EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE);
58 return 0;
59 }
60
e74bd290 61 hctx->ctx = EVP_MAC_CTX_new(mac);
5e55159b
RL
62 if (hctx->ctx == NULL) {
63 OPENSSL_free(hctx);
64 return 0;
65 }
66
67 if (nid == EVP_PKEY_CMAC) {
68 hctx->type = MAC_TYPE_MAC;
69 } else {
70 hctx->type = MAC_TYPE_RAW;
71 hctx->raw_data.ktmp.type = V_ASN1_OCTET_STRING;
72 }
73
e74bd290 74 pkey_mac_cleanup(ctx);
5e55159b
RL
75 EVP_PKEY_CTX_set_data(ctx, hctx);
76 ctx->keygen_info_count = 0;
77
78 return 1;
79}
80
9fdcc21f 81static int pkey_mac_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
5e55159b
RL
82{
83 MAC_PKEY_CTX *sctx, *dctx;
84
be5fc053
KR
85 sctx = EVP_PKEY_CTX_get_data(src);
86 if (sctx->ctx->data == NULL)
5e55159b
RL
87 return 0;
88
be5fc053
KR
89 dctx = OPENSSL_zalloc(sizeof(*dctx));
90 if (dctx == NULL) {
91 EVPerr(EVP_F_PKEY_MAC_COPY, ERR_R_MALLOC_FAILURE);
92 return 0;
93 }
94
95 EVP_PKEY_CTX_set_data(dst, dctx);
96 dst->keygen_info_count = 0;
5e55159b 97
be5fc053
KR
98 dctx->ctx = EVP_MAC_CTX_dup(sctx->ctx);
99 if (dctx->ctx == NULL)
5e55159b
RL
100 goto err;
101
e74bd290
RL
102 /*
103 * Normally, nothing special would be done with the MAC method. In
104 * this particular case, though, the MAC method was fetched internally
105 * by pkey_mac_init() above or by EVP_PKEY_new_CMAC_key() and passed
106 * via the EVP_MAC_CTX, so it is effectively like every new EVP_MAC_CTX
107 * fetches the MAC method anew in this case. Therefore, its reference
108 * count must be adjusted here.
109 */
110 if (!EVP_MAC_up_ref(EVP_MAC_CTX_mac(dctx->ctx)))
111 goto err;
112
be5fc053
KR
113 dctx->type = sctx->type;
114
5e55159b
RL
115 switch (dctx->type) {
116 case MAC_TYPE_RAW:
117 dctx->raw_data.md = sctx->raw_data.md;
118 if (ASN1_STRING_get0_data(&sctx->raw_data.ktmp) != NULL &&
119 !ASN1_STRING_copy(&dctx->raw_data.ktmp, &sctx->raw_data.ktmp))
120 goto err;
121 break;
122 case MAC_TYPE_MAC:
123 /* Nothing more to do */
124 break;
125 default:
126 /* This should be dead code */
127 return 0;
128 }
129 return 1;
130 err:
be5fc053 131 pkey_mac_cleanup(dst);
5e55159b
RL
132 return 0;
133}
134
135static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx)
136{
e74bd290
RL
137 /*
138 * For the exact same reasons the MAC reference count is incremented
139 * in pkey_mac_copy() above, it must be explicitly freed here.
140 */
141
142 MAC_PKEY_CTX *hctx = ctx == NULL ? NULL : EVP_PKEY_CTX_get_data(ctx);
5e55159b
RL
143
144 if (hctx != NULL) {
e74bd290
RL
145 EVP_MAC *mac = EVP_MAC_CTX_mac(hctx->ctx);
146
5e55159b
RL
147 switch (hctx->type) {
148 case MAC_TYPE_RAW:
149 OPENSSL_clear_free(hctx->raw_data.ktmp.data,
150 hctx->raw_data.ktmp.length);
151 break;
152 }
153 EVP_MAC_CTX_free(hctx->ctx);
e74bd290 154 EVP_MAC_free(mac);
5e55159b
RL
155 OPENSSL_free(hctx);
156 EVP_PKEY_CTX_set_data(ctx, NULL);
157 }
158}
159
160static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
161{
162 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
163 int nid = ctx->pmeth->pkey_id;
164
165 switch (hctx->type) {
166 case MAC_TYPE_RAW:
167 {
168 ASN1_OCTET_STRING *hkey = NULL;
169
170 if (!hctx->raw_data.ktmp.data)
171 return 0;
172 hkey = ASN1_OCTET_STRING_dup(&hctx->raw_data.ktmp);
173 if (!hkey)
174 return 0;
175 EVP_PKEY_assign(pkey, nid, hkey);
176 }
177 break;
178 case MAC_TYPE_MAC:
179 {
be5fc053 180 EVP_MAC_CTX *cmkey = EVP_MAC_CTX_dup(hctx->ctx);
5e55159b
RL
181
182 if (cmkey == NULL)
183 return 0;
e74bd290
RL
184 if (!EVP_MAC_up_ref(EVP_MAC_CTX_mac(hctx->ctx)))
185 return 0;
5e55159b
RL
186 EVP_PKEY_assign(pkey, nid, cmkey);
187 }
188 break;
189 default:
190 /* This should be dead code */
191 return 0;
192 }
193
194 return 1;
195}
196
197static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
198{
199 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
200
201 if (!EVP_MAC_update(hctx->ctx, data, count))
202 return 0;
203 return 1;
204}
205
206static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
207{
208 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
209 ASN1_OCTET_STRING *key = NULL;
210 int rv = 1;
211 /*
212 * For MACs with the EVP_PKEY_FLAG_SIGCTX_CUSTOM flag set and that
213 * gets the key passed as an ASN.1 OCTET STRING, we set the key here,
214 * as this may be only time it's set during a DigestSign.
215 *
216 * MACs that pass around the key in form of EVP_MAC_CTX are setting
217 * the key through other mechanisms. (this is only CMAC for now)
218 */
219 int set_key =
220 hctx->type == MAC_TYPE_RAW
221 && (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0;
222
223 if (set_key) {
7cfa1717
RL
224 if (!EVP_MAC_is_a(EVP_MAC_CTX_mac(hctx->ctx),
225 OBJ_nid2sn(EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx)))))
5e55159b
RL
226 return 0;
227 key = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx));
228 if (key == NULL)
229 return 0;
230 }
231
5e55159b
RL
232 EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
233 EVP_MD_CTX_set_update_fn(mctx, int_update);
234
e74bd290
RL
235 /* Some MACs don't support this control... that's fine */
236 {
237 OSSL_PARAM params[3];
238 size_t params_n = 0;
239 int flags = EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT);
240
241 /* TODO(3.0) "flags" isn't quite right, i.e. a quick hack for now */
242 params[params_n++] =
243 OSSL_PARAM_construct_int(OSSL_MAC_PARAM_FLAGS, &flags);
244 if (set_key)
245 params[params_n++] =
246 OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
247 key->data, key->length);
248 params[params_n++] = OSSL_PARAM_construct_end();
249 rv = EVP_MAC_CTX_set_params(hctx->ctx, params);
250 }
251 return rv;
5e55159b
RL
252}
253
254static int pkey_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
255 size_t *siglen, EVP_MD_CTX *mctx)
256{
257 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
258
e74bd290 259 return EVP_MAC_final(hctx->ctx, sig, siglen, EVP_MAC_size(hctx->ctx));
5e55159b
RL
260}
261
262static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
263{
264 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
265
266 switch (type) {
267
268 case EVP_PKEY_CTRL_CIPHER:
269 switch (hctx->type) {
270 case MAC_TYPE_RAW:
271 return -2; /* The raw types don't support ciphers */
272 case MAC_TYPE_MAC:
273 {
e74bd290
RL
274 OSSL_PARAM params[3];
275 size_t params_n = 0;
276 char *ciphname = (char *)OBJ_nid2sn(EVP_CIPHER_nid(p2));
3be06e0d 277#ifndef OPENSSL_NO_ENGINE
e74bd290
RL
278 char *engineid = (char *)ENGINE_get_id(ctx->engine);
279
280 params[params_n++] =
281 OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
7f588d20 282 engineid, 0);
3be06e0d 283#endif
e74bd290 284 params[params_n++] =
703170d4 285 OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
7f588d20 286 ciphname, 0);
e74bd290
RL
287 params[params_n] = OSSL_PARAM_construct_end();
288
289 if (!EVP_MAC_CTX_set_params(hctx->ctx, params)
290 || !EVP_MAC_init(hctx->ctx))
291 return 0;
5e55159b
RL
292 }
293 break;
294 default:
295 /* This should be dead code */
296 return 0;
297 }
298 break;
299
300 case EVP_PKEY_CTRL_MD:
301 switch (hctx->type) {
302 case MAC_TYPE_RAW:
303 hctx->raw_data.md = p2;
304 break;
be5fc053
KR
305 case MAC_TYPE_MAC: {
306 EVP_MAC_CTX *new_mac_ctx;
307
308 if (ctx->pkey == NULL)
309 return 0;
310 new_mac_ctx = EVP_MAC_CTX_dup((EVP_MAC_CTX *)ctx->pkey
311 ->pkey.ptr);
312 if (new_mac_ctx == NULL)
313 return 0;
314 EVP_MAC_CTX_free(hctx->ctx);
315 hctx->ctx = new_mac_ctx;
316 }
5e55159b
RL
317 break;
318 default:
319 /* This should be dead code */
320 return 0;
321 }
322 break;
323
324 case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
e74bd290
RL
325 {
326 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
327 size_t size = (size_t)p1;
328 size_t verify = 0;
329
330 /*
331 * We verify that the length is actually set by getting back
332 * the same parameter and checking that it matches what we
333 * tried to set.
334 * TODO(3.0) when we have a more direct mechanism to check if
335 * a parameter was used, we must refactor this to use that.
336 */
337
338 params[0] =
703170d4 339 OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &size);
e74bd290
RL
340
341 if (!EVP_MAC_CTX_set_params(hctx->ctx, params))
342 return 0;
5e55159b 343
e74bd290 344 params[0] =
703170d4 345 OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &verify);
e74bd290
RL
346
347 if (!EVP_MAC_CTX_get_params(hctx->ctx, params))
348 return 0;
349
350 /*
351 * Since EVP_MAC_CTX_{get,set}_params() returned successfully,
352 * we can only assume that the size was ignored, i.e. this
353 * control is unsupported.
354 */
355 if (verify != size)
356 return -2;
357 }
358 break;
5e55159b
RL
359 case EVP_PKEY_CTRL_SET_MAC_KEY:
360 switch (hctx->type) {
361 case MAC_TYPE_RAW:
362 if ((!p2 && p1 > 0) || (p1 < -1))
363 return 0;
364 if (!ASN1_OCTET_STRING_set(&hctx->raw_data.ktmp, p2, p1))
365 return 0;
366 break;
367 case MAC_TYPE_MAC:
e74bd290
RL
368 {
369 OSSL_PARAM params[2];
370 size_t params_n = 0;
371
372 params[params_n++] =
373 OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
374 p2, p1);
375 params[params_n] = OSSL_PARAM_construct_end();
376
377 return EVP_MAC_CTX_set_params(hctx->ctx, params);
378 }
5e55159b
RL
379 break;
380 default:
381 /* This should be dead code */
382 return 0;
383 }
384 break;
385
386 case EVP_PKEY_CTRL_DIGESTINIT:
387 switch (hctx->type) {
388 case MAC_TYPE_RAW:
389 /* Ensure that we have attached the implementation */
390 if (!EVP_MAC_init(hctx->ctx))
391 return 0;
392 {
5e55159b
RL
393 ASN1_OCTET_STRING *key =
394 (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
e74bd290
RL
395 OSSL_PARAM params[4];
396 size_t params_n = 0;
397 char *mdname =
398 (char *)OBJ_nid2sn(EVP_MD_nid(hctx->raw_data.md));
3be06e0d 399#ifndef OPENSSL_NO_ENGINE
e74bd290
RL
400 char *engineid = ctx->engine == NULL
401 ? NULL : (char *)ENGINE_get_id(ctx->engine);
402
403 if (engineid != NULL) {
e74bd290
RL
404 params[params_n++] =
405 OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
7f588d20 406 engineid, 0);
e74bd290 407 }
3be06e0d 408#endif
e74bd290 409 params[params_n++] =
703170d4 410 OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
7f588d20 411 mdname, 0);
e74bd290
RL
412 params[params_n++] =
413 OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
414 key->data, key->length);
415 params[params_n] = OSSL_PARAM_construct_end();
416
417 return EVP_MAC_CTX_set_params(hctx->ctx, params);
5e55159b
RL
418 }
419 break;
420 case MAC_TYPE_MAC:
421 return -2; /* The mac types don't support ciphers */
422 default:
423 /* This should be dead code */
424 return 0;
425 }
426 break;
427
428 default:
429 return -2;
430
431 }
432 return 1;
433}
434
435static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx,
436 const char *type, const char *value)
437{
438 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
e74bd290
RL
439 const EVP_MAC *mac = EVP_MAC_CTX_mac(hctx->ctx);
440 OSSL_PARAM params[2];
441 int ok = 0;
5e55159b 442
703170d4
RL
443 /*
444 * Translation of some control names that are equivalent to a single
445 * parameter name.
446 *
447 * "md" and "digest" are the same thing, we use the single "digest"
448 *
449 * "digestsize" was a setting control in siphash, but naming wise,
450 * it's really the same as "size".
451 */
452 if (strcmp(type, "md") == 0)
453 type = OSSL_MAC_PARAM_DIGEST;
454 else if (strcmp(type, "digestsize") == 0)
455 type = OSSL_MAC_PARAM_SIZE;
456
e74bd290
RL
457 if (!OSSL_PARAM_allocate_from_text(&params[0],
458 EVP_MAC_CTX_settable_params(mac),
459 type, value, strlen(value) + 1))
460 return 0;
461 params[1] = OSSL_PARAM_construct_end();
462 ok = EVP_MAC_CTX_set_params(hctx->ctx, params);
463 OPENSSL_free(params[0].data);
464 return ok;
5e55159b
RL
465}
466
e74a435f
RL
467const EVP_PKEY_METHOD cmac_pkey_meth = {
468 EVP_PKEY_CMAC,
5e55159b
RL
469 EVP_PKEY_FLAG_SIGCTX_CUSTOM,
470 pkey_mac_init,
471 pkey_mac_copy,
472 pkey_mac_cleanup,
473
474 0, 0,
475
476 0,
477 pkey_mac_keygen,
478
479 0, 0,
480
481 0, 0,
482
483 0, 0,
484
485 pkey_mac_signctx_init,
486 pkey_mac_signctx,
487
488 0, 0,
489
490 0, 0,
491
492 0, 0,
493
494 0, 0,
495
496 pkey_mac_ctrl,
497 pkey_mac_ctrl_str
498};
f8c9a8e3
RL
499
500const EVP_PKEY_METHOD hmac_pkey_meth = {
501 EVP_PKEY_HMAC,
502 0,
503 pkey_mac_init,
504 pkey_mac_copy,
505 pkey_mac_cleanup,
506
507 0, 0,
508
509 0,
510 pkey_mac_keygen,
511
512 0, 0,
513
514 0, 0,
515
516 0, 0,
517
518 pkey_mac_signctx_init,
519 pkey_mac_signctx,
520
521 0, 0,
522
523 0, 0,
524
525 0, 0,
526
527 0, 0,
528
529 pkey_mac_ctrl,
530 pkey_mac_ctrl_str
531};
14f61f81
RL
532
533const EVP_PKEY_METHOD siphash_pkey_meth = {
534 EVP_PKEY_SIPHASH,
535 EVP_PKEY_FLAG_SIGCTX_CUSTOM,
536 pkey_mac_init,
537 pkey_mac_copy,
538 pkey_mac_cleanup,
539
540 0, 0,
541
542 0,
543 pkey_mac_keygen,
544
545 0, 0,
546
547 0, 0,
548
549 0, 0,
550
551 pkey_mac_signctx_init,
552 pkey_mac_signctx,
553
554 0, 0,
555
556 0, 0,
557
558 0, 0,
559
560 0, 0,
561
562 pkey_mac_ctrl,
563 pkey_mac_ctrl_str
564};
c1da4b2a
PY
565
566const EVP_PKEY_METHOD poly1305_pkey_meth = {
567 EVP_PKEY_POLY1305,
568 EVP_PKEY_FLAG_SIGCTX_CUSTOM,
569 pkey_mac_init,
570 pkey_mac_copy,
571 pkey_mac_cleanup,
572
573 0, 0,
574
575 0,
576 pkey_mac_keygen,
577
578 0, 0,
579
580 0, 0,
581
582 0, 0,
583
584 pkey_mac_signctx_init,
585 pkey_mac_signctx,
586
587 0, 0,
588
589 0, 0,
590
591 0, 0,
592
593 0, 0,
594
595 pkey_mac_ctrl,
596 pkey_mac_ctrl_str
597};