/src/openssl36/providers/implementations/macs/kmac_prov.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the Apache License 2.0 (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 | | /* clang-format off */ |
10 | | |
11 | | /* clang-format on */ |
12 | | |
13 | | /* |
14 | | * See SP800-185 "Appendix A - KMAC, .... in Terms of Keccak[c]" |
15 | | * |
16 | | * Inputs are: |
17 | | * K = Key (len(K) < 2^2040 bits) |
18 | | * X = Input |
19 | | * L = Output length (0 <= L < 2^2040 bits) |
20 | | * S = Customization String Default="" (len(S) < 2^2040 bits) |
21 | | * |
22 | | * KMAC128(K, X, L, S) |
23 | | * { |
24 | | * newX = bytepad(encode_string(K), 168) || X || right_encode(L). |
25 | | * T = bytepad(encode_string("KMAC") || encode_string(S), 168). |
26 | | * return KECCAK[256](T || newX || 00, L). |
27 | | * } |
28 | | * |
29 | | * KMAC256(K, X, L, S) |
30 | | * { |
31 | | * newX = bytepad(encode_string(K), 136) || X || right_encode(L). |
32 | | * T = bytepad(encode_string("KMAC") || encode_string(S), 136). |
33 | | * return KECCAK[512](T || newX || 00, L). |
34 | | * } |
35 | | * |
36 | | * KMAC128XOF(K, X, L, S) |
37 | | * { |
38 | | * newX = bytepad(encode_string(K), 168) || X || right_encode(0). |
39 | | * T = bytepad(encode_string("KMAC") || encode_string(S), 168). |
40 | | * return KECCAK[256](T || newX || 00, L). |
41 | | * } |
42 | | * |
43 | | * KMAC256XOF(K, X, L, S) |
44 | | * { |
45 | | * newX = bytepad(encode_string(K), 136) || X || right_encode(0). |
46 | | * T = bytepad(encode_string("KMAC") || encode_string(S), 136). |
47 | | * return KECCAK[512](T || newX || 00, L). |
48 | | * } |
49 | | * |
50 | | */ |
51 | | |
52 | | #include <stdlib.h> |
53 | | #include <string.h> |
54 | | #include <openssl/core_dispatch.h> |
55 | | #include <openssl/core_names.h> |
56 | | #include <openssl/params.h> |
57 | | #include <openssl/evp.h> |
58 | | #include <openssl/err.h> |
59 | | #include <openssl/proverr.h> |
60 | | #include <openssl/fips_names.h> |
61 | | #include "prov/securitycheck.h" |
62 | | #include "prov/implementations.h" |
63 | | #include "prov/provider_ctx.h" |
64 | | #include "prov/provider_util.h" |
65 | | #include "prov/providercommon.h" |
66 | | #include "internal/cryptlib.h" /* ossl_assert */ |
67 | | |
68 | | /* |
69 | | * Forward declaration of everything implemented here. This is not strictly |
70 | | * necessary for the compiler, but provides an assurance that the signatures |
71 | | * of the functions in the dispatch table are correct. |
72 | | */ |
73 | | static OSSL_FUNC_mac_newctx_fn kmac128_new; |
74 | | static OSSL_FUNC_mac_newctx_fn kmac256_new; |
75 | | static OSSL_FUNC_mac_dupctx_fn kmac_dup; |
76 | | static OSSL_FUNC_mac_freectx_fn kmac_free; |
77 | | static OSSL_FUNC_mac_gettable_ctx_params_fn kmac_gettable_ctx_params; |
78 | | static OSSL_FUNC_mac_get_ctx_params_fn kmac_get_ctx_params; |
79 | | static OSSL_FUNC_mac_settable_ctx_params_fn kmac_settable_ctx_params; |
80 | | static OSSL_FUNC_mac_set_ctx_params_fn kmac_set_ctx_params; |
81 | | static OSSL_FUNC_mac_init_fn kmac_init; |
82 | | static OSSL_FUNC_mac_update_fn kmac_update; |
83 | | static OSSL_FUNC_mac_final_fn kmac_final; |
84 | | |
85 | | #define KMAC_MAX_BLOCKSIZE ((1600 - 128 * 2) / 8) /* 168 */ |
86 | | |
87 | | /* |
88 | | * Length encoding will be a 1 byte size + length in bits (3 bytes max) |
89 | | * This gives a range of 0..0XFFFFFF bits = 2097151 bytes). |
90 | | */ |
91 | 367 | #define KMAC_MAX_OUTPUT_LEN (0xFFFFFF / 8) |
92 | | #define KMAC_MAX_ENCODED_HEADER_LEN (1 + 3) |
93 | | |
94 | | /* |
95 | | * Restrict the maximum length of the customisation string. This must not |
96 | | * exceed 64 bits = 8k bytes. |
97 | | */ |
98 | 340 | #define KMAC_MAX_CUSTOM 512 |
99 | | |
100 | | /* Maximum size of encoded custom string */ |
101 | | #define KMAC_MAX_CUSTOM_ENCODED (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_HEADER_LEN) |
102 | | |
103 | | /* Maximum key size in bytes = 512 (4096 bits) */ |
104 | 7.82k | #define KMAC_MAX_KEY 512 |
105 | 15.8k | #define KMAC_MIN_KEY 4 |
106 | | |
107 | | /* |
108 | | * Maximum Encoded Key size will be padded to a multiple of the blocksize |
109 | | * i.e KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN = 512 + 4 |
110 | | * Padded to a multiple of KMAC_MAX_BLOCKSIZE |
111 | | */ |
112 | | #define KMAC_MAX_KEY_ENCODED (KMAC_MAX_BLOCKSIZE * 4) |
113 | | |
114 | | /* Fixed value of encode_string("KMAC") */ |
115 | | static const unsigned char kmac_string[] = { |
116 | | 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 |
117 | | }; |
118 | | |
119 | | #define KMAC_FLAG_XOF_MODE 1 |
120 | | |
121 | | struct kmac_data_st { |
122 | | void *provctx; |
123 | | EVP_MD_CTX *ctx; |
124 | | PROV_DIGEST digest; |
125 | | size_t out_len; |
126 | | size_t key_len; |
127 | | size_t custom_len; |
128 | | /* If xof_mode = 1 then we use right_encode(0) */ |
129 | | int xof_mode; |
130 | | /* key and custom are stored in encoded form */ |
131 | | unsigned char key[KMAC_MAX_KEY_ENCODED]; |
132 | | unsigned char custom[KMAC_MAX_CUSTOM_ENCODED]; |
133 | | #ifdef FIPS_MODULE |
134 | | /* |
135 | | * 'internal' is set to 1 if KMAC is used inside another algorithm such as a |
136 | | * KDF. In this case it is the parent algorithm that is responsible for |
137 | | * performing any conditional FIPS indicator related checks for KMAC. |
138 | | */ |
139 | | int internal; |
140 | | #endif |
141 | | OSSL_FIPS_IND_DECLARE |
142 | | }; |
143 | | |
144 | | static int encode_string(unsigned char *out, size_t out_max_len, size_t *out_len, |
145 | | const unsigned char *in, size_t in_len); |
146 | | static int right_encode(unsigned char *out, size_t out_max_len, size_t *out_len, |
147 | | size_t bits); |
148 | | static int bytepad(unsigned char *out, size_t *out_len, |
149 | | const unsigned char *in1, size_t in1_len, |
150 | | const unsigned char *in2, size_t in2_len, |
151 | | size_t w); |
152 | | static int kmac_bytepad_encode_key(unsigned char *out, size_t out_max_len, |
153 | | size_t *out_len, |
154 | | const unsigned char *in, size_t in_len, |
155 | | size_t w); |
156 | | |
157 | | static void kmac_free(void *vmacctx) |
158 | 642 | { |
159 | 642 | struct kmac_data_st *kctx = vmacctx; |
160 | | |
161 | 642 | if (kctx != NULL) { |
162 | 642 | EVP_MD_CTX_free(kctx->ctx); |
163 | 642 | ossl_prov_digest_reset(&kctx->digest); |
164 | 642 | OPENSSL_cleanse(kctx->key, kctx->key_len); |
165 | 642 | OPENSSL_cleanse(kctx->custom, kctx->custom_len); |
166 | 642 | OPENSSL_free(kctx); |
167 | 642 | } |
168 | 642 | } |
169 | | |
170 | | /* |
171 | | * We have KMAC implemented as a hash, which we can use instead of |
172 | | * reimplementing the EVP functionality with direct use of |
173 | | * keccak_mac_init() and friends. |
174 | | */ |
175 | | static struct kmac_data_st *kmac_new(void *provctx) |
176 | 642 | { |
177 | 642 | struct kmac_data_st *kctx; |
178 | | |
179 | 642 | if (!ossl_prov_is_running()) |
180 | 0 | return NULL; |
181 | | |
182 | 642 | if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL |
183 | 642 | || (kctx->ctx = EVP_MD_CTX_new()) == NULL) { |
184 | 0 | kmac_free(kctx); |
185 | 0 | return NULL; |
186 | 0 | } |
187 | 642 | kctx->provctx = provctx; |
188 | 642 | OSSL_FIPS_IND_INIT(kctx) |
189 | 642 | return kctx; |
190 | 642 | } |
191 | | |
192 | | static void *kmac_fetch_new(void *provctx, const OSSL_PARAM *params) |
193 | 461 | { |
194 | 461 | struct kmac_data_st *kctx = kmac_new(provctx); |
195 | 461 | int md_size; |
196 | | |
197 | 461 | if (kctx == NULL) |
198 | 0 | return 0; |
199 | 461 | if (!ossl_prov_digest_load_from_params(&kctx->digest, params, |
200 | 461 | PROV_LIBCTX_OF(provctx))) { |
201 | 0 | kmac_free(kctx); |
202 | 0 | return 0; |
203 | 0 | } |
204 | | |
205 | 461 | md_size = EVP_MD_get_size(ossl_prov_digest_md(&kctx->digest)); |
206 | 461 | if (md_size <= 0) { |
207 | 0 | kmac_free(kctx); |
208 | 0 | return 0; |
209 | 0 | } |
210 | 461 | kctx->out_len = (size_t)md_size; |
211 | 461 | return kctx; |
212 | 461 | } |
213 | | |
214 | | static void *kmac128_new(void *provctx) |
215 | 290 | { |
216 | 290 | static const OSSL_PARAM kmac128_params[] = { |
217 | 290 | OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC128, |
218 | 290 | sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC128)), |
219 | 290 | OSSL_PARAM_END |
220 | 290 | }; |
221 | 290 | return kmac_fetch_new(provctx, kmac128_params); |
222 | 290 | } |
223 | | |
224 | | static void *kmac256_new(void *provctx) |
225 | 315 | { |
226 | 315 | static const OSSL_PARAM kmac256_params[] = { |
227 | 315 | OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC256, |
228 | 315 | sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC256)), |
229 | 315 | OSSL_PARAM_END |
230 | 315 | }; |
231 | 315 | return kmac_fetch_new(provctx, kmac256_params); |
232 | 315 | } |
233 | | |
234 | | static void *kmac_dup(void *vsrc) |
235 | 37 | { |
236 | 37 | struct kmac_data_st *src = vsrc; |
237 | 37 | struct kmac_data_st *dst; |
238 | | |
239 | 37 | if (!ossl_prov_is_running()) |
240 | 0 | return NULL; |
241 | | |
242 | 37 | dst = kmac_new(src->provctx); |
243 | 37 | if (dst == NULL) |
244 | 0 | return NULL; |
245 | | |
246 | 37 | if (!EVP_MD_CTX_copy(dst->ctx, src->ctx) |
247 | 37 | || !ossl_prov_digest_copy(&dst->digest, &src->digest)) { |
248 | 0 | kmac_free(dst); |
249 | 0 | return NULL; |
250 | 0 | } |
251 | | #ifdef FIPS_MODULE |
252 | | dst->internal = src->internal; |
253 | | #endif |
254 | 37 | dst->out_len = src->out_len; |
255 | 37 | dst->key_len = src->key_len; |
256 | 37 | dst->custom_len = src->custom_len; |
257 | 37 | dst->xof_mode = src->xof_mode; |
258 | 37 | memcpy(dst->key, src->key, src->key_len); |
259 | 37 | memcpy(dst->custom, src->custom, dst->custom_len); |
260 | 37 | OSSL_FIPS_IND_COPY(dst, src) |
261 | | |
262 | 37 | return dst; |
263 | 37 | } |
264 | | |
265 | | static int kmac_setkey(struct kmac_data_st *kctx, const unsigned char *key, |
266 | | size_t keylen) |
267 | 7.91k | { |
268 | 7.91k | const EVP_MD *digest = ossl_prov_digest_md(&kctx->digest); |
269 | 7.91k | int w = EVP_MD_get_block_size(digest); |
270 | | |
271 | 7.91k | if (keylen < KMAC_MIN_KEY || keylen > KMAC_MAX_KEY) { |
272 | 149 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); |
273 | 149 | return 0; |
274 | 149 | } |
275 | | #ifdef FIPS_MODULE |
276 | | /* |
277 | | * Only do the key check if KMAC is fetched directly. |
278 | | * Other algorithms that embed KMAC such as SSKDF will ignore this check. |
279 | | */ |
280 | | if (!kctx->internal) { |
281 | | int approved = ossl_mac_check_key_size(keylen); |
282 | | |
283 | | if (!approved) { |
284 | | if (!OSSL_FIPS_IND_ON_UNAPPROVED(kctx, OSSL_FIPS_IND_SETTABLE1, |
285 | | PROV_LIBCTX_OF(kctx->provctx), |
286 | | "KMAC", "Key size", |
287 | | ossl_fips_config_kmac_key_check)) { |
288 | | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); |
289 | | return 0; |
290 | | } |
291 | | } |
292 | | } |
293 | | #endif |
294 | 7.76k | if (w <= 0) { |
295 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); |
296 | 0 | return 0; |
297 | 0 | } |
298 | 7.76k | if (!kmac_bytepad_encode_key(kctx->key, sizeof(kctx->key), &kctx->key_len, |
299 | 7.76k | key, keylen, (size_t)w)) |
300 | 0 | return 0; |
301 | 7.76k | return 1; |
302 | 7.76k | } |
303 | | |
304 | | /* |
305 | | * The init() assumes that any ctrl methods are set beforehand for |
306 | | * md, key and custom. Setting the fields afterwards will have no |
307 | | * effect on the output mac. |
308 | | */ |
309 | | static int kmac_init(void *vmacctx, const unsigned char *key, |
310 | | size_t keylen, const OSSL_PARAM params[]) |
311 | 7.33k | { |
312 | 7.33k | struct kmac_data_st *kctx = vmacctx; |
313 | 7.33k | EVP_MD_CTX *ctx = kctx->ctx; |
314 | 7.33k | unsigned char *out; |
315 | 7.33k | size_t out_len, block_len; |
316 | 7.33k | int res, t; |
317 | | |
318 | 7.33k | if (!ossl_prov_is_running() || !kmac_set_ctx_params(kctx, params)) |
319 | 156 | return 0; |
320 | | |
321 | 7.18k | if (key != NULL) { |
322 | 7.18k | if (!kmac_setkey(kctx, key, keylen)) |
323 | 19 | return 0; |
324 | 7.18k | } else if (kctx->key_len == 0) { |
325 | | /* Check key has been set */ |
326 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); |
327 | 0 | return 0; |
328 | 0 | } |
329 | 7.16k | if (!EVP_DigestInit_ex(kctx->ctx, ossl_prov_digest_md(&kctx->digest), |
330 | 7.16k | NULL)) |
331 | 0 | return 0; |
332 | | |
333 | 7.16k | t = EVP_MD_get_block_size(ossl_prov_digest_md(&kctx->digest)); |
334 | 7.16k | if (t <= 0) { |
335 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); |
336 | 0 | return 0; |
337 | 0 | } |
338 | 7.16k | block_len = t; |
339 | | |
340 | | /* Set default custom string if it is not already set */ |
341 | 7.16k | if (kctx->custom_len == 0) { |
342 | 42 | const OSSL_PARAM cparams[] = { |
343 | 42 | OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, "", 0), |
344 | 42 | OSSL_PARAM_END |
345 | 42 | }; |
346 | 42 | (void)kmac_set_ctx_params(kctx, cparams); |
347 | 42 | } |
348 | | |
349 | 7.16k | if (!bytepad(NULL, &out_len, kmac_string, sizeof(kmac_string), |
350 | 7.16k | kctx->custom, kctx->custom_len, block_len)) { |
351 | 0 | ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); |
352 | 0 | return 0; |
353 | 0 | } |
354 | 7.16k | out = OPENSSL_malloc(out_len); |
355 | 7.16k | if (out == NULL) |
356 | 0 | return 0; |
357 | 7.16k | res = bytepad(out, NULL, kmac_string, sizeof(kmac_string), |
358 | 7.16k | kctx->custom, kctx->custom_len, block_len) |
359 | 7.16k | && EVP_DigestUpdate(ctx, out, out_len) |
360 | 7.16k | && EVP_DigestUpdate(ctx, kctx->key, kctx->key_len); |
361 | 7.16k | OPENSSL_free(out); |
362 | 7.16k | return res; |
363 | 7.16k | } |
364 | | |
365 | | static int kmac_update(void *vmacctx, const unsigned char *data, |
366 | | size_t datalen) |
367 | 7.67k | { |
368 | 7.67k | struct kmac_data_st *kctx = vmacctx; |
369 | | |
370 | 7.67k | return EVP_DigestUpdate(kctx->ctx, data, datalen); |
371 | 7.67k | } |
372 | | |
373 | | static int kmac_final(void *vmacctx, unsigned char *out, size_t *outl, |
374 | | size_t outsize) |
375 | 7.15k | { |
376 | 7.15k | struct kmac_data_st *kctx = vmacctx; |
377 | 7.15k | EVP_MD_CTX *ctx = kctx->ctx; |
378 | 7.15k | size_t lbits, len; |
379 | 7.15k | unsigned char encoded_outlen[KMAC_MAX_ENCODED_HEADER_LEN]; |
380 | 7.15k | int ok; |
381 | | |
382 | 7.15k | if (!ossl_prov_is_running()) |
383 | 0 | return 0; |
384 | | |
385 | | /* KMAC XOF mode sets the encoded length to 0 */ |
386 | 7.15k | lbits = (kctx->xof_mode ? 0 : (kctx->out_len * 8)); |
387 | | |
388 | 7.15k | ok = right_encode(encoded_outlen, sizeof(encoded_outlen), &len, lbits) |
389 | 7.15k | && EVP_DigestUpdate(ctx, encoded_outlen, len) |
390 | 7.14k | && EVP_DigestFinalXOF(ctx, out, kctx->out_len); |
391 | 7.15k | *outl = kctx->out_len; |
392 | 7.15k | return ok; |
393 | 7.15k | } |
394 | | |
395 | | /* clang-format off */ |
396 | | /* Machine generated by util/perl/OpenSSL/paramnames.pm */ |
397 | | #ifndef kmac_get_ctx_params_list |
398 | | static const OSSL_PARAM kmac_get_ctx_params_list[] = { |
399 | | OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), |
400 | | OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL), |
401 | | # if defined(FIPS_MODULE) |
402 | | OSSL_PARAM_int(OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR, NULL), |
403 | | # endif |
404 | | OSSL_PARAM_END |
405 | | }; |
406 | | #endif |
407 | | |
408 | | #ifndef kmac_get_ctx_params_st |
409 | | struct kmac_get_ctx_params_st { |
410 | | OSSL_PARAM *bsize; |
411 | | # if defined(FIPS_MODULE) |
412 | | OSSL_PARAM *ind; |
413 | | # endif |
414 | | OSSL_PARAM *size; |
415 | | }; |
416 | | #endif |
417 | | |
418 | | #ifndef kmac_get_ctx_params_decoder |
419 | | static int kmac_get_ctx_params_decoder |
420 | | (const OSSL_PARAM *p, struct kmac_get_ctx_params_st *r) |
421 | 2.53k | { |
422 | 2.53k | const char *s; |
423 | | |
424 | 2.53k | memset(r, 0, sizeof(*r)); |
425 | 2.53k | if (p != NULL) |
426 | 5.06k | for (; (s = p->key) != NULL; p++) |
427 | 2.53k | switch(s[0]) { |
428 | 0 | default: |
429 | 0 | break; |
430 | 0 | case 'b': |
431 | 0 | if (ossl_likely(strcmp("lock-size", s + 1) == 0)) { |
432 | | /* OSSL_MAC_PARAM_BLOCK_SIZE */ |
433 | 0 | if (ossl_unlikely(r->bsize != NULL)) { |
434 | 0 | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
435 | 0 | "param %s is repeated", s); |
436 | 0 | return 0; |
437 | 0 | } |
438 | 0 | r->bsize = (OSSL_PARAM *)p; |
439 | 0 | } |
440 | 0 | break; |
441 | 0 | case 'f': |
442 | | # if defined(FIPS_MODULE) |
443 | | if (ossl_likely(strcmp("ips-indicator", s + 1) == 0)) { |
444 | | /* OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR */ |
445 | | if (ossl_unlikely(r->ind != NULL)) { |
446 | | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
447 | | "param %s is repeated", s); |
448 | | return 0; |
449 | | } |
450 | | r->ind = (OSSL_PARAM *)p; |
451 | | } |
452 | | # endif |
453 | 0 | break; |
454 | 2.53k | case 's': |
455 | 2.53k | if (ossl_likely(strcmp("ize", s + 1) == 0)) { |
456 | | /* OSSL_MAC_PARAM_SIZE */ |
457 | 2.53k | if (ossl_unlikely(r->size != NULL)) { |
458 | 0 | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
459 | 0 | "param %s is repeated", s); |
460 | 0 | return 0; |
461 | 0 | } |
462 | 2.53k | r->size = (OSSL_PARAM *)p; |
463 | 2.53k | } |
464 | 2.53k | } |
465 | 2.53k | return 1; |
466 | 2.53k | } |
467 | | #endif |
468 | | /* End of machine generated */ |
469 | | /* clang-format on */ |
470 | | |
471 | | static const OSSL_PARAM *kmac_gettable_ctx_params(ossl_unused void *ctx, |
472 | | ossl_unused void *provctx) |
473 | 0 | { |
474 | 0 | return kmac_get_ctx_params_list; |
475 | 0 | } |
476 | | |
477 | | static int kmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) |
478 | 2.53k | { |
479 | 2.53k | struct kmac_data_st *kctx = vmacctx; |
480 | 2.53k | struct kmac_get_ctx_params_st p; |
481 | 2.53k | int sz; |
482 | | |
483 | 2.53k | if (kctx == NULL || !kmac_get_ctx_params_decoder(params, &p)) |
484 | 0 | return 0; |
485 | | |
486 | 2.53k | if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, kctx->out_len)) |
487 | 0 | return 0; |
488 | | |
489 | 2.53k | if (p.bsize != NULL) { |
490 | 0 | sz = EVP_MD_block_size(ossl_prov_digest_md(&kctx->digest)); |
491 | 0 | if (!OSSL_PARAM_set_int(p.bsize, sz)) |
492 | 0 | return 0; |
493 | 0 | } |
494 | | |
495 | 2.53k | if (!OSSL_FIPS_IND_GET_CTX_FROM_PARAM(kctx, p.ind)) |
496 | 0 | return 0; |
497 | | |
498 | 2.53k | return 1; |
499 | 2.53k | } |
500 | | |
501 | | /* clang-format off */ |
502 | | /* Machine generated by util/perl/OpenSSL/paramnames.pm */ |
503 | | #ifndef kmac_set_ctx_params_list |
504 | | static const OSSL_PARAM kmac_set_ctx_params_list[] = { |
505 | | OSSL_PARAM_int(OSSL_MAC_PARAM_XOF, NULL), |
506 | | OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), |
507 | | OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), |
508 | | OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, NULL, 0), |
509 | | # if defined(FIPS_MODULE) |
510 | | OSSL_PARAM_int(OSSL_MAC_PARAM_FIPS_KEY_CHECK, NULL), |
511 | | # endif |
512 | | # if defined(FIPS_MODULE) |
513 | | OSSL_PARAM_int(OSSL_MAC_PARAM_FIPS_NO_SHORT_MAC, NULL), |
514 | | # endif |
515 | | OSSL_PARAM_END |
516 | | }; |
517 | | #endif |
518 | | |
519 | | #ifndef kmac_set_ctx_params_st |
520 | | struct kmac_set_ctx_params_st { |
521 | | OSSL_PARAM *custom; |
522 | | # if defined(FIPS_MODULE) |
523 | | OSSL_PARAM *ind_k; |
524 | | # endif |
525 | | # if defined(FIPS_MODULE) |
526 | | OSSL_PARAM *ind_sht; |
527 | | # endif |
528 | | OSSL_PARAM *key; |
529 | | OSSL_PARAM *size; |
530 | | OSSL_PARAM *xof; |
531 | | }; |
532 | | #endif |
533 | | |
534 | | #ifndef kmac_set_ctx_params_decoder |
535 | | static int kmac_set_ctx_params_decoder |
536 | | (const OSSL_PARAM *p, struct kmac_set_ctx_params_st *r) |
537 | 2.89k | { |
538 | 2.89k | const char *s; |
539 | | |
540 | 2.89k | memset(r, 0, sizeof(*r)); |
541 | 2.89k | if (p != NULL) |
542 | 2.07k | for (; (s = p->key) != NULL; p++) |
543 | 1.59k | switch(s[0]) { |
544 | 102 | default: |
545 | 102 | break; |
546 | 431 | case 'c': |
547 | 431 | if (ossl_likely(strcmp("ustom", s + 1) == 0)) { |
548 | | /* OSSL_MAC_PARAM_CUSTOM */ |
549 | 392 | if (ossl_unlikely(r->custom != NULL)) { |
550 | 0 | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
551 | 0 | "param %s is repeated", s); |
552 | 0 | return 0; |
553 | 0 | } |
554 | 392 | r->custom = (OSSL_PARAM *)p; |
555 | 392 | } |
556 | 431 | break; |
557 | 431 | case 'k': |
558 | 347 | switch(s[1]) { |
559 | 0 | default: |
560 | 0 | break; |
561 | 347 | case 'e': |
562 | 347 | switch(s[2]) { |
563 | 0 | default: |
564 | 0 | break; |
565 | 347 | case 'y': |
566 | 347 | switch(s[3]) { |
567 | 0 | default: |
568 | 0 | break; |
569 | 0 | case '-': |
570 | | # if defined(FIPS_MODULE) |
571 | | if (ossl_likely(strcmp("check", s + 4) == 0)) { |
572 | | /* OSSL_MAC_PARAM_FIPS_KEY_CHECK */ |
573 | | if (ossl_unlikely(r->ind_k != NULL)) { |
574 | | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
575 | | "param %s is repeated", s); |
576 | | return 0; |
577 | | } |
578 | | r->ind_k = (OSSL_PARAM *)p; |
579 | | } |
580 | | # endif |
581 | 0 | break; |
582 | 347 | case '\0': |
583 | 347 | if (ossl_unlikely(r->key != NULL)) { |
584 | 0 | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
585 | 0 | "param %s is repeated", s); |
586 | 0 | return 0; |
587 | 0 | } |
588 | 347 | r->key = (OSSL_PARAM *)p; |
589 | 347 | } |
590 | 347 | } |
591 | 347 | } |
592 | 347 | break; |
593 | 347 | case 'n': |
594 | | # if defined(FIPS_MODULE) |
595 | | if (ossl_likely(strcmp("o-short-mac", s + 1) == 0)) { |
596 | | /* OSSL_MAC_PARAM_FIPS_NO_SHORT_MAC */ |
597 | | if (ossl_unlikely(r->ind_sht != NULL)) { |
598 | | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
599 | | "param %s is repeated", s); |
600 | | return 0; |
601 | | } |
602 | | r->ind_sht = (OSSL_PARAM *)p; |
603 | | } |
604 | | # endif |
605 | 0 | break; |
606 | 367 | case 's': |
607 | 367 | if (ossl_likely(strcmp("ize", s + 1) == 0)) { |
608 | | /* OSSL_MAC_PARAM_SIZE */ |
609 | 367 | if (ossl_unlikely(r->size != NULL)) { |
610 | 0 | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
611 | 0 | "param %s is repeated", s); |
612 | 0 | return 0; |
613 | 0 | } |
614 | 367 | r->size = (OSSL_PARAM *)p; |
615 | 367 | } |
616 | 367 | break; |
617 | 367 | case 'x': |
618 | 347 | if (ossl_likely(strcmp("of", s + 1) == 0)) { |
619 | | /* OSSL_MAC_PARAM_XOF */ |
620 | 347 | if (ossl_unlikely(r->xof != NULL)) { |
621 | 0 | ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER, |
622 | 0 | "param %s is repeated", s); |
623 | 0 | return 0; |
624 | 0 | } |
625 | 347 | r->xof = (OSSL_PARAM *)p; |
626 | 347 | } |
627 | 1.59k | } |
628 | 2.89k | return 1; |
629 | 2.89k | } |
630 | | #endif |
631 | | /* End of machine generated */ |
632 | | /* clang-format on */ |
633 | | |
634 | | static const OSSL_PARAM *kmac_settable_ctx_params(ossl_unused void *ctx, |
635 | | ossl_unused void *provctx) |
636 | 444 | { |
637 | 444 | return kmac_set_ctx_params_list; |
638 | 444 | } |
639 | | |
640 | | /* |
641 | | * The following params can be set any time before final(): |
642 | | * - "outlen" or "size": The requested output length. |
643 | | * - "xof": If set, this indicates that right_encoded(0) |
644 | | * is part of the digested data, otherwise it |
645 | | * uses right_encoded(requested output length). |
646 | | * |
647 | | * All other params should be set before init(). |
648 | | */ |
649 | | static int kmac_set_ctx_params(void *vmacctx, const OSSL_PARAM *params) |
650 | 2.89k | { |
651 | 2.89k | struct kmac_data_st *kctx = vmacctx; |
652 | 2.89k | struct kmac_set_ctx_params_st p; |
653 | | |
654 | 2.89k | if (kctx == NULL || !kmac_set_ctx_params_decoder(params, &p)) |
655 | 0 | return 0; |
656 | | |
657 | 2.89k | if (!OSSL_FIPS_IND_SET_CTX_FROM_PARAM(kctx, OSSL_FIPS_IND_SETTABLE0, |
658 | 2.89k | p.ind_sht)) |
659 | 0 | return 0; |
660 | 2.89k | if (!OSSL_FIPS_IND_SET_CTX_FROM_PARAM(kctx, OSSL_FIPS_IND_SETTABLE1, p.ind_k)) |
661 | 0 | return 0; |
662 | | |
663 | 2.89k | if (p.xof != NULL && !OSSL_PARAM_get_int(p.xof, &kctx->xof_mode)) |
664 | 0 | return 0; |
665 | | |
666 | 2.89k | if (p.size != NULL) { |
667 | 367 | size_t sz = 0; |
668 | | |
669 | 367 | if (!OSSL_PARAM_get_size_t(p.size, &sz)) |
670 | 0 | return 0; |
671 | 367 | if (sz > KMAC_MAX_OUTPUT_LEN) { |
672 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH); |
673 | 0 | return 0; |
674 | 0 | } |
675 | | #ifdef FIPS_MODULE |
676 | | /* SP 800-185 8.4.2 mandates a minimum of 32 bits of output */ |
677 | | if (sz < 32 / 8) { |
678 | | if (!OSSL_FIPS_IND_ON_UNAPPROVED(kctx, OSSL_FIPS_IND_SETTABLE0, |
679 | | PROV_LIBCTX_OF(kctx->provctx), |
680 | | "KMAC", "length", |
681 | | ossl_fips_config_no_short_mac)) { |
682 | | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH); |
683 | | return 0; |
684 | | } |
685 | | } |
686 | | #endif |
687 | 367 | kctx->out_len = sz; |
688 | 367 | } |
689 | | |
690 | 2.89k | if (p.key != NULL) |
691 | 347 | if (p.key->data_type != OSSL_PARAM_OCTET_STRING |
692 | 347 | || !kmac_setkey(kctx, p.key->data, p.key->data_size)) |
693 | 52 | return 0; |
694 | | |
695 | 2.84k | if (p.custom != NULL) { |
696 | 340 | if (p.custom->data_type != OSSL_PARAM_OCTET_STRING) |
697 | 0 | return 0; |
698 | 340 | if (p.custom->data_size > KMAC_MAX_CUSTOM) { |
699 | 20 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH); |
700 | 20 | return 0; |
701 | 20 | } |
702 | 320 | if (!encode_string(kctx->custom, sizeof(kctx->custom), &kctx->custom_len, |
703 | 320 | p.custom->data, p.custom->data_size)) |
704 | 0 | return 0; |
705 | 320 | } |
706 | | |
707 | 2.82k | return 1; |
708 | 2.84k | } |
709 | | |
710 | | /* Encoding/Padding Methods. */ |
711 | | |
712 | | /* Returns the number of bytes required to store 'bits' into a byte array */ |
713 | | static unsigned int get_encode_size(size_t bits) |
714 | 15.6k | { |
715 | 15.6k | unsigned int cnt = 0, sz = sizeof(size_t); |
716 | | |
717 | 39.4k | while (bits && (cnt < sz)) { |
718 | 23.8k | ++cnt; |
719 | 23.8k | bits >>= 8; |
720 | 23.8k | } |
721 | | /* If bits is zero 1 byte is required */ |
722 | 15.6k | if (cnt == 0) |
723 | 605 | cnt = 1; |
724 | 15.6k | return cnt; |
725 | 15.6k | } |
726 | | |
727 | | /* |
728 | | * Convert an integer into bytes . The number of bytes is appended |
729 | | * to the end of the buffer. Returns an array of bytes 'out' of size |
730 | | * *out_len. |
731 | | * |
732 | | * e.g if bits = 32, out[2] = { 0x20, 0x01 } |
733 | | */ |
734 | | static int right_encode(unsigned char *out, size_t out_max_len, size_t *out_len, |
735 | | size_t bits) |
736 | 7.15k | { |
737 | 7.15k | unsigned int len = get_encode_size(bits); |
738 | 7.15k | int i; |
739 | | |
740 | 7.15k | if (len >= out_max_len) { |
741 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE); |
742 | 0 | return 0; |
743 | 0 | } |
744 | | |
745 | | /* MSB's are at the start of the bytes array */ |
746 | 21.1k | for (i = len - 1; i >= 0; --i) { |
747 | 14.0k | out[i] = (unsigned char)(bits & 0xFF); |
748 | 14.0k | bits >>= 8; |
749 | 14.0k | } |
750 | | /* Tack the length onto the end */ |
751 | 7.15k | out[len] = (unsigned char)len; |
752 | | |
753 | | /* The Returned length includes the tacked on byte */ |
754 | 7.15k | *out_len = len + 1; |
755 | 7.15k | return 1; |
756 | 7.15k | } |
757 | | |
758 | | /* |
759 | | * Encodes a string with a left encoded length added. Note that the |
760 | | * in_len is converted to bits (*8). |
761 | | * |
762 | | * e.g- in="KMAC" gives out[6] = { 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 } |
763 | | * len bits K M A C |
764 | | */ |
765 | | static int encode_string(unsigned char *out, size_t out_max_len, size_t *out_len, |
766 | | const unsigned char *in, size_t in_len) |
767 | 8.45k | { |
768 | 8.45k | if (in == NULL) { |
769 | 0 | *out_len = 0; |
770 | 8.45k | } else { |
771 | 8.45k | size_t i, bits, len, sz; |
772 | | |
773 | 8.45k | bits = 8 * in_len; |
774 | 8.45k | len = get_encode_size(bits); |
775 | 8.45k | sz = 1 + len + in_len; |
776 | | |
777 | 8.45k | if (sz > out_max_len) { |
778 | 0 | ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE); |
779 | 0 | return 0; |
780 | 0 | } |
781 | | |
782 | 8.45k | out[0] = (unsigned char)len; |
783 | 18.9k | for (i = len; i > 0; --i) { |
784 | 10.4k | out[i] = (bits & 0xFF); |
785 | 10.4k | bits >>= 8; |
786 | 10.4k | } |
787 | 8.45k | memcpy(out + len + 1, in, in_len); |
788 | 8.45k | *out_len = sz; |
789 | 8.45k | } |
790 | 8.45k | return 1; |
791 | 8.45k | } |
792 | | |
793 | | /* |
794 | | * Returns a zero padded encoding of the inputs in1 and an optional |
795 | | * in2 (can be NULL). The padded output must be a multiple of the blocksize 'w'. |
796 | | * The value of w is in bytes (< 256). |
797 | | * |
798 | | * The returned output is: |
799 | | * zero_padded(multiple of w, (left_encode(w) || in1 [|| in2]) |
800 | | */ |
801 | | static int bytepad(unsigned char *out, size_t *out_len, |
802 | | const unsigned char *in1, size_t in1_len, |
803 | | const unsigned char *in2, size_t in2_len, size_t w) |
804 | 29.8k | { |
805 | 29.8k | size_t len; |
806 | 29.8k | unsigned char *p = out; |
807 | 29.8k | size_t sz = w; |
808 | | |
809 | 29.8k | if (out == NULL) { |
810 | 14.9k | if (out_len == NULL) { |
811 | 0 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); |
812 | 0 | return 0; |
813 | 0 | } |
814 | 14.9k | sz = 2 + in1_len + (in2 != NULL ? in2_len : 0); |
815 | 14.9k | *out_len = (sz + w - 1) / w * w; |
816 | 14.9k | return 1; |
817 | 14.9k | } |
818 | | |
819 | 14.9k | if (!ossl_assert(w <= 255)) |
820 | 0 | return 0; |
821 | | |
822 | | /* Left encoded w */ |
823 | 14.9k | *p++ = 1; |
824 | 14.9k | *p++ = (unsigned char)w; |
825 | | /* || in1 */ |
826 | 14.9k | memcpy(p, in1, in1_len); |
827 | 14.9k | p += in1_len; |
828 | | /* [ || in2 ] */ |
829 | 14.9k | if (in2 != NULL && in2_len > 0) { |
830 | 7.16k | memcpy(p, in2, in2_len); |
831 | 7.16k | p += in2_len; |
832 | 7.16k | } |
833 | | /* Figure out the pad size (divisible by w) */ |
834 | 14.9k | len = p - out; |
835 | 14.9k | sz = (len + w - 1) / w * w; |
836 | | /* zero pad the end of the buffer */ |
837 | 14.9k | if (sz != len) |
838 | 14.8k | memset(p, 0, sz - len); |
839 | 14.9k | if (out_len != NULL) |
840 | 0 | *out_len = sz; |
841 | 14.9k | return 1; |
842 | 14.9k | } |
843 | | |
844 | | /* Returns out = bytepad(encode_string(in), w) */ |
845 | | static int kmac_bytepad_encode_key(unsigned char *out, size_t out_max_len, |
846 | | size_t *out_len, |
847 | | const unsigned char *in, size_t in_len, |
848 | | size_t w) |
849 | 7.76k | { |
850 | 7.76k | unsigned char tmp[KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN]; |
851 | 7.76k | size_t tmp_len; |
852 | | |
853 | 7.76k | if (!encode_string(tmp, sizeof(tmp), &tmp_len, in, in_len)) |
854 | 0 | return 0; |
855 | 7.76k | if (!bytepad(NULL, out_len, tmp, tmp_len, NULL, 0, w)) |
856 | 0 | return 0; |
857 | 7.76k | if (!ossl_assert(*out_len <= out_max_len)) |
858 | 0 | return 0; |
859 | 7.76k | return bytepad(out, NULL, tmp, tmp_len, NULL, 0, w); |
860 | 7.76k | } |
861 | | |
862 | | #define IMPLEMENT_KMAC_TABLE(size, funcname, newname) \ |
863 | | const OSSL_DISPATCH ossl_kmac##size##_##funcname[] = { \ |
864 | | { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac##size##_##newname }, \ |
865 | | { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup }, \ |
866 | | { OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free }, \ |
867 | | { OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init }, \ |
868 | | { OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update }, \ |
869 | | { OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final }, \ |
870 | | { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, \ |
871 | | (void (*)(void))kmac_gettable_ctx_params }, \ |
872 | | { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params }, \ |
873 | | { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, \ |
874 | | (void (*)(void))kmac_settable_ctx_params }, \ |
875 | | { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params }, \ |
876 | | OSSL_DISPATCH_END \ |
877 | | } |
878 | | |
879 | | #define KMAC_TABLE(size) IMPLEMENT_KMAC_TABLE(size, functions, new) |
880 | | |
881 | | KMAC_TABLE(128); |
882 | | KMAC_TABLE(256); |
883 | | |
884 | | #ifdef FIPS_MODULE |
885 | | #define KMAC_INTERNAL_TABLE(size) \ |
886 | | static OSSL_FUNC_mac_newctx_fn kmac##size##_internal_new; \ |
887 | | static void *kmac##size##_internal_new(void *provctx) \ |
888 | | { \ |
889 | | struct kmac_data_st *macctx = kmac##size##_new(provctx); \ |
890 | | \ |
891 | | if (macctx != NULL) \ |
892 | | macctx->internal = 1; \ |
893 | | return macctx; \ |
894 | | } \ |
895 | | IMPLEMENT_KMAC_TABLE(size, internal_functions, internal_new) |
896 | | |
897 | | KMAC_INTERNAL_TABLE(128); |
898 | | KMAC_INTERNAL_TABLE(256); |
899 | | #endif /* FIPS_MODULE */ |