]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/pkey_mac.c
Clarify the POD source for the list command.
[thirdparty/openssl.git] / crypto / evp / pkey_mac.c
CommitLineData
5e55159b
RL
1/*
2 * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
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
16typedef 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
42static 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
72static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx);
73
74static 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
107static 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
124static 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
163static 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
172static 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
211static 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
219static 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
322static 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
330const 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
363const 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
396const 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};