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