]>
Commit | Line | Data |
---|---|---|
a39bc440 | 1 | /* |
a28d06f3 | 2 | * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. |
a39bc440 RH |
3 | * Copyright 2019 Red Hat, Inc. |
4 | * | |
5 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
6 | * this file except in compliance with the License. You can obtain a copy | |
7 | * in the file LICENSE in the source distribution or at | |
8 | * https://www.openssl.org/source/license.html | |
9 | */ | |
10 | ||
11 | /* | |
12 | * This implements https://csrc.nist.gov/publications/detail/sp/800-108/final | |
f6dead1b RH |
13 | * section 5.1 ("counter mode") and section 5.2 ("feedback mode") in both HMAC |
14 | * and CMAC. That document does not name the KDFs it defines; the name is | |
15 | * derived from | |
a39bc440 RH |
16 | * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation |
17 | * | |
f6dead1b RH |
18 | * Note that section 5.3 ("double-pipeline mode") is not implemented, though |
19 | * it would be possible to do so in the future. | |
a39bc440 RH |
20 | * |
21 | * These versions all assume the counter is used. It would be relatively | |
22 | * straightforward to expose a configuration handle should the need arise. | |
23 | * | |
24 | * Variable names attempt to match those of SP800-108. | |
25 | */ | |
26 | ||
27 | #include <stdarg.h> | |
28 | #include <stdlib.h> | |
29 | #include <string.h> | |
30 | ||
31 | #include <openssl/core_names.h> | |
32 | #include <openssl/evp.h> | |
33 | #include <openssl/hmac.h> | |
34 | #include <openssl/kdf.h> | |
35 | #include <openssl/params.h> | |
2741128e | 36 | #include <openssl/proverr.h> |
a39bc440 RH |
37 | |
38 | #include "internal/cryptlib.h" | |
25f2138b | 39 | #include "crypto/evp.h" |
a39bc440 | 40 | #include "internal/numbers.h" |
e23d850f | 41 | #include "internal/endian.h" |
af3e7e1b | 42 | #include "prov/implementations.h" |
ddd21319 RL |
43 | #include "prov/provider_ctx.h" |
44 | #include "prov/provider_util.h" | |
2b9e4e95 | 45 | #include "prov/providercommon.h" |
a39bc440 | 46 | |
d5f9166b | 47 | #include "internal/e_os.h" |
a39bc440 | 48 | |
f4f77c2d | 49 | #define ossl_min(a, b) ((a) < (b)) ? (a) : (b) |
a39bc440 | 50 | |
f6dead1b RH |
51 | typedef enum { |
52 | COUNTER = 0, | |
53 | FEEDBACK | |
54 | } kbkdf_mode; | |
55 | ||
a39bc440 RH |
56 | /* Our context structure. */ |
57 | typedef struct { | |
58 | void *provctx; | |
f6dead1b | 59 | kbkdf_mode mode; |
a39bc440 RH |
60 | EVP_MAC_CTX *ctx_init; |
61 | ||
62 | /* Names are lowercased versions of those found in SP800-108. */ | |
0e9a265e | 63 | int r; |
a39bc440 RH |
64 | unsigned char *ki; |
65 | size_t ki_len; | |
66 | unsigned char *label; | |
67 | size_t label_len; | |
68 | unsigned char *context; | |
69 | size_t context_len; | |
f6dead1b RH |
70 | unsigned char *iv; |
71 | size_t iv_len; | |
4757a347 SL |
72 | int use_l; |
73 | int use_separator; | |
a39bc440 RH |
74 | } KBKDF; |
75 | ||
76 | /* Definitions needed for typechecking. */ | |
363b1e5d | 77 | static OSSL_FUNC_kdf_newctx_fn kbkdf_new; |
d54c52c2 | 78 | static OSSL_FUNC_kdf_newctx_fn kbkdf_dup; |
363b1e5d DMSP |
79 | static OSSL_FUNC_kdf_freectx_fn kbkdf_free; |
80 | static OSSL_FUNC_kdf_reset_fn kbkdf_reset; | |
81 | static OSSL_FUNC_kdf_derive_fn kbkdf_derive; | |
82 | static OSSL_FUNC_kdf_settable_ctx_params_fn kbkdf_settable_ctx_params; | |
83 | static OSSL_FUNC_kdf_set_ctx_params_fn kbkdf_set_ctx_params; | |
af5e1e85 P |
84 | static OSSL_FUNC_kdf_gettable_ctx_params_fn kbkdf_gettable_ctx_params; |
85 | static OSSL_FUNC_kdf_get_ctx_params_fn kbkdf_get_ctx_params; | |
a39bc440 RH |
86 | |
87 | /* Not all platforms have htobe32(). */ | |
88 | static uint32_t be32(uint32_t host) | |
89 | { | |
90 | uint32_t big = 0; | |
e23d850f | 91 | DECLARE_IS_ENDIAN; |
a39bc440 | 92 | |
e23d850f | 93 | if (!IS_LITTLE_ENDIAN) |
a39bc440 RH |
94 | return host; |
95 | ||
96 | big |= (host & 0xff000000) >> 24; | |
97 | big |= (host & 0x00ff0000) >> 8; | |
98 | big |= (host & 0x0000ff00) << 8; | |
99 | big |= (host & 0x000000ff) << 24; | |
100 | return big; | |
101 | } | |
102 | ||
4757a347 SL |
103 | static void init(KBKDF *ctx) |
104 | { | |
0e9a265e | 105 | ctx->r = 32; |
4757a347 SL |
106 | ctx->use_l = 1; |
107 | ctx->use_separator = 1; | |
108 | } | |
109 | ||
a39bc440 RH |
110 | static void *kbkdf_new(void *provctx) |
111 | { | |
112 | KBKDF *ctx; | |
113 | ||
2b9e4e95 P |
114 | if (!ossl_prov_is_running()) |
115 | return NULL; | |
116 | ||
a39bc440 RH |
117 | ctx = OPENSSL_zalloc(sizeof(*ctx)); |
118 | if (ctx == NULL) { | |
119 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
120 | return NULL; | |
121 | } | |
122 | ||
123 | ctx->provctx = provctx; | |
4757a347 | 124 | init(ctx); |
a39bc440 RH |
125 | return ctx; |
126 | } | |
127 | ||
128 | static void kbkdf_free(void *vctx) | |
129 | { | |
130 | KBKDF *ctx = (KBKDF *)vctx; | |
131 | ||
3c659415 P |
132 | if (ctx != NULL) { |
133 | kbkdf_reset(ctx); | |
134 | OPENSSL_free(ctx); | |
135 | } | |
a39bc440 RH |
136 | } |
137 | ||
138 | static void kbkdf_reset(void *vctx) | |
139 | { | |
140 | KBKDF *ctx = (KBKDF *)vctx; | |
0577959c | 141 | void *provctx = ctx->provctx; |
a39bc440 | 142 | |
865adf97 | 143 | EVP_MAC_CTX_free(ctx->ctx_init); |
a39bc440 RH |
144 | OPENSSL_clear_free(ctx->context, ctx->context_len); |
145 | OPENSSL_clear_free(ctx->label, ctx->label_len); | |
146 | OPENSSL_clear_free(ctx->ki, ctx->ki_len); | |
f6dead1b | 147 | OPENSSL_clear_free(ctx->iv, ctx->iv_len); |
a39bc440 | 148 | memset(ctx, 0, sizeof(*ctx)); |
0577959c | 149 | ctx->provctx = provctx; |
4757a347 | 150 | init(ctx); |
a39bc440 RH |
151 | } |
152 | ||
d54c52c2 P |
153 | static void *kbkdf_dup(void *vctx) |
154 | { | |
155 | const KBKDF *src = (const KBKDF *)vctx; | |
156 | KBKDF *dest; | |
157 | ||
158 | dest = kbkdf_new(src->provctx); | |
159 | if (dest != NULL) { | |
160 | dest->ctx_init = EVP_MAC_CTX_dup(src->ctx_init); | |
161 | if (dest->ctx_init == NULL | |
162 | || !ossl_prov_memdup(src->ki, src->ki_len, | |
163 | &dest->ki, &dest->ki_len) | |
164 | || !ossl_prov_memdup(src->label, src->label_len, | |
165 | &dest->label, &dest->label_len) | |
166 | || !ossl_prov_memdup(src->context, src->context_len, | |
167 | &dest->context, &dest->context_len) | |
168 | || !ossl_prov_memdup(src->iv, src->iv_len, | |
169 | &dest->iv, &dest->iv_len)) | |
170 | goto err; | |
171 | dest->mode = src->mode; | |
172 | dest->r = src->r; | |
173 | dest->use_l = src->use_l; | |
174 | dest->use_separator = src->use_separator; | |
175 | } | |
176 | return dest; | |
177 | ||
178 | err: | |
179 | kbkdf_free(dest); | |
180 | return NULL; | |
181 | } | |
182 | ||
f6dead1b RH |
183 | /* SP800-108 section 5.1 or section 5.2 depending on mode. */ |
184 | static int derive(EVP_MAC_CTX *ctx_init, kbkdf_mode mode, unsigned char *iv, | |
185 | size_t iv_len, unsigned char *label, size_t label_len, | |
186 | unsigned char *context, size_t context_len, | |
4757a347 | 187 | unsigned char *k_i, size_t h, uint32_t l, int has_separator, |
0e9a265e | 188 | unsigned char *ko, size_t ko_len, int r) |
a39bc440 RH |
189 | { |
190 | int ret = 0; | |
191 | EVP_MAC_CTX *ctx = NULL; | |
f6dead1b | 192 | size_t written = 0, to_write, k_i_len = iv_len; |
a39bc440 RH |
193 | const unsigned char zero = 0; |
194 | uint32_t counter, i; | |
4757a347 SL |
195 | /* |
196 | * From SP800-108: | |
197 | * The fixed input data is a concatenation of a Label, | |
198 | * a separation indicator 0x00, the Context, and L. | |
199 | * One or more of these fixed input data fields may be omitted. | |
200 | * | |
201 | * has_separator == 0 means that the separator is omitted. | |
202 | * Passing a value of l == 0 means that L is omitted. | |
203 | * The Context and L are omitted automatically if a NULL buffer is passed. | |
204 | */ | |
205 | int has_l = (l != 0); | |
a39bc440 | 206 | |
f6dead1b RH |
207 | /* Setup K(0) for feedback mode. */ |
208 | if (iv_len > 0) | |
209 | memcpy(k_i, iv, iv_len); | |
210 | ||
a39bc440 RH |
211 | for (counter = 1; written < ko_len; counter++) { |
212 | i = be32(counter); | |
213 | ||
865adf97 | 214 | ctx = EVP_MAC_CTX_dup(ctx_init); |
a39bc440 RH |
215 | if (ctx == NULL) |
216 | goto done; | |
217 | ||
f6dead1b RH |
218 | /* Perform feedback, if appropriate. */ |
219 | if (mode == FEEDBACK && !EVP_MAC_update(ctx, k_i, k_i_len)) | |
220 | goto done; | |
221 | ||
0e9a265e | 222 | if (!EVP_MAC_update(ctx, 4 - (r / 8) + (unsigned char *)&i, r / 8) |
a39bc440 | 223 | || !EVP_MAC_update(ctx, label, label_len) |
4757a347 | 224 | || (has_separator && !EVP_MAC_update(ctx, &zero, 1)) |
a39bc440 | 225 | || !EVP_MAC_update(ctx, context, context_len) |
4757a347 | 226 | || (has_l && !EVP_MAC_update(ctx, (unsigned char *)&l, 4)) |
a39bc440 RH |
227 | || !EVP_MAC_final(ctx, k_i, NULL, h)) |
228 | goto done; | |
229 | ||
230 | to_write = ko_len - written; | |
f4f77c2d | 231 | memcpy(ko + written, k_i, ossl_min(to_write, h)); |
a39bc440 RH |
232 | written += h; |
233 | ||
f6dead1b | 234 | k_i_len = h; |
865adf97 | 235 | EVP_MAC_CTX_free(ctx); |
a39bc440 RH |
236 | ctx = NULL; |
237 | } | |
238 | ||
239 | ret = 1; | |
240 | done: | |
865adf97 | 241 | EVP_MAC_CTX_free(ctx); |
a39bc440 RH |
242 | return ret; |
243 | } | |
244 | ||
3469b388 P |
245 | static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen, |
246 | const OSSL_PARAM params[]) | |
a39bc440 RH |
247 | { |
248 | KBKDF *ctx = (KBKDF *)vctx; | |
249 | int ret = 0; | |
250 | unsigned char *k_i = NULL; | |
4757a347 | 251 | uint32_t l = 0; |
a39bc440 | 252 | size_t h = 0; |
0e9a265e | 253 | uint64_t counter_max; |
a39bc440 | 254 | |
3469b388 | 255 | if (!ossl_prov_is_running() || !kbkdf_set_ctx_params(ctx, params)) |
2b9e4e95 P |
256 | return 0; |
257 | ||
f6dead1b RH |
258 | /* label, context, and iv are permitted to be empty. Check everything |
259 | * else. */ | |
a39bc440 RH |
260 | if (ctx->ctx_init == NULL) { |
261 | if (ctx->ki_len == 0 || ctx->ki == NULL) { | |
262 | ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); | |
263 | return 0; | |
264 | } | |
f6dead1b RH |
265 | /* Could either be missing MAC or missing message digest or missing |
266 | * cipher - arbitrarily, I pick this one. */ | |
a39bc440 RH |
267 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC); |
268 | return 0; | |
269 | } | |
270 | ||
1cae59d1 JS |
271 | /* Fail if the output length is zero */ |
272 | if (keylen == 0) { | |
273 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); | |
274 | return 0; | |
275 | } | |
276 | ||
90a2576b | 277 | h = EVP_MAC_CTX_get_mac_size(ctx->ctx_init); |
a39bc440 RH |
278 | if (h == 0) |
279 | goto done; | |
f6dead1b RH |
280 | if (ctx->iv_len != 0 && ctx->iv_len != h) { |
281 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH); | |
282 | goto done; | |
283 | } | |
a39bc440 | 284 | |
0e9a265e PU |
285 | if (ctx->mode == COUNTER) { |
286 | /* Fail if keylen is too large for r */ | |
287 | counter_max = (uint64_t)1 << (uint64_t)ctx->r; | |
288 | if ((uint64_t)(keylen / h) >= counter_max) { | |
289 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); | |
290 | goto done; | |
291 | } | |
292 | } | |
293 | ||
4757a347 SL |
294 | if (ctx->use_l != 0) |
295 | l = be32(keylen * 8); | |
296 | ||
a39bc440 RH |
297 | k_i = OPENSSL_zalloc(h); |
298 | if (k_i == NULL) | |
299 | goto done; | |
300 | ||
f6dead1b RH |
301 | ret = derive(ctx->ctx_init, ctx->mode, ctx->iv, ctx->iv_len, ctx->label, |
302 | ctx->label_len, ctx->context, ctx->context_len, k_i, h, l, | |
0e9a265e | 303 | ctx->use_separator, key, keylen, ctx->r); |
a39bc440 RH |
304 | done: |
305 | if (ret != 1) | |
306 | OPENSSL_cleanse(key, keylen); | |
307 | OPENSSL_clear_free(k_i, h); | |
308 | return ret; | |
309 | } | |
310 | ||
311 | static int kbkdf_set_buffer(unsigned char **out, size_t *out_len, | |
312 | const OSSL_PARAM *p) | |
313 | { | |
314 | if (p->data == NULL || p->data_size == 0) | |
315 | return 1; | |
316 | ||
317 | OPENSSL_clear_free(*out, *out_len); | |
318 | *out = NULL; | |
319 | return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); | |
320 | } | |
321 | ||
322 | static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) | |
323 | { | |
324 | KBKDF *ctx = (KBKDF *)vctx; | |
a829b735 | 325 | OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); |
a39bc440 | 326 | const OSSL_PARAM *p; |
a39bc440 | 327 | |
c983a0e5 P |
328 | if (params == NULL) |
329 | return 1; | |
330 | ||
a39bc440 RH |
331 | if (!ossl_prov_macctx_load_from_params(&ctx->ctx_init, params, NULL, |
332 | NULL, NULL, libctx)) | |
333 | return 0; | |
334 | else if (ctx->ctx_init != NULL | |
ed576acd | 335 | && !EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init), |
f6dead1b | 336 | OSSL_MAC_NAME_HMAC) |
ed576acd | 337 | && !EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init), |
f6dead1b | 338 | OSSL_MAC_NAME_CMAC)) { |
a39bc440 RH |
339 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MAC); |
340 | return 0; | |
341 | } | |
342 | ||
f6dead1b RH |
343 | p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE); |
344 | if (p != NULL && strncasecmp("counter", p->data, p->data_size) == 0) { | |
345 | ctx->mode = COUNTER; | |
346 | } else if (p != NULL | |
347 | && strncasecmp("feedback", p->data, p->data_size) == 0) { | |
348 | ctx->mode = FEEDBACK; | |
349 | } else if (p != NULL) { | |
350 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); | |
351 | return 0; | |
352 | } | |
353 | ||
a39bc440 RH |
354 | p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY); |
355 | if (p != NULL && !kbkdf_set_buffer(&ctx->ki, &ctx->ki_len, p)) | |
356 | return 0; | |
357 | ||
358 | p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT); | |
359 | if (p != NULL && !kbkdf_set_buffer(&ctx->label, &ctx->label_len, p)) | |
360 | return 0; | |
361 | ||
362 | p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO); | |
363 | if (p != NULL && !kbkdf_set_buffer(&ctx->context, &ctx->context_len, p)) | |
364 | return 0; | |
365 | ||
f6dead1b RH |
366 | p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED); |
367 | if (p != NULL && !kbkdf_set_buffer(&ctx->iv, &ctx->iv_len, p)) | |
368 | return 0; | |
369 | ||
4757a347 SL |
370 | p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_USE_L); |
371 | if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_l)) | |
372 | return 0; | |
373 | ||
0e9a265e PU |
374 | p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_R); |
375 | if (p != NULL) { | |
376 | int new_r = 0; | |
377 | ||
378 | if (!OSSL_PARAM_get_int(p, &new_r)) | |
379 | return 0; | |
380 | if (new_r != 8 && new_r != 16 && new_r != 24 && new_r != 32) | |
381 | return 0; | |
382 | ctx->r = new_r; | |
383 | } | |
384 | ||
4757a347 SL |
385 | p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR); |
386 | if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_separator)) | |
387 | return 0; | |
388 | ||
a39bc440 | 389 | /* Set up digest context, if we can. */ |
2524ec1a P |
390 | if (ctx->ctx_init != NULL && ctx->ki_len != 0 |
391 | && !EVP_MAC_init(ctx->ctx_init, ctx->ki, ctx->ki_len, NULL)) | |
a39bc440 | 392 | return 0; |
a39bc440 RH |
393 | return 1; |
394 | } | |
395 | ||
1e8e5c60 P |
396 | static const OSSL_PARAM *kbkdf_settable_ctx_params(ossl_unused void *ctx, |
397 | ossl_unused void *provctx) | |
a39bc440 RH |
398 | { |
399 | static const OSSL_PARAM known_settable_ctx_params[] = { | |
400 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), | |
401 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), | |
402 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), | |
f6dead1b | 403 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0), |
a39bc440 | 404 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), |
f6dead1b | 405 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CIPHER, NULL, 0), |
a39bc440 | 406 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), |
f6dead1b | 407 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), |
a39bc440 | 408 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), |
4757a347 SL |
409 | OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_USE_L, NULL), |
410 | OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR, NULL), | |
0e9a265e | 411 | OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_R, NULL), |
a39bc440 RH |
412 | OSSL_PARAM_END, |
413 | }; | |
414 | return known_settable_ctx_params; | |
415 | } | |
416 | ||
417 | static int kbkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) | |
418 | { | |
419 | OSSL_PARAM *p; | |
420 | ||
421 | p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE); | |
422 | if (p == NULL) | |
423 | return -2; | |
424 | ||
425 | /* KBKDF can produce results as large as you like. */ | |
426 | return OSSL_PARAM_set_size_t(p, SIZE_MAX); | |
427 | } | |
428 | ||
1e8e5c60 P |
429 | static const OSSL_PARAM *kbkdf_gettable_ctx_params(ossl_unused void *ctx, |
430 | ossl_unused void *provctx) | |
a39bc440 RH |
431 | { |
432 | static const OSSL_PARAM known_gettable_ctx_params[] = | |
433 | { OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), OSSL_PARAM_END }; | |
434 | return known_gettable_ctx_params; | |
435 | } | |
436 | ||
1be63951 | 437 | const OSSL_DISPATCH ossl_kdf_kbkdf_functions[] = { |
a39bc440 | 438 | { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kbkdf_new }, |
d54c52c2 | 439 | { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kbkdf_dup }, |
a39bc440 RH |
440 | { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kbkdf_free }, |
441 | { OSSL_FUNC_KDF_RESET, (void(*)(void))kbkdf_reset }, | |
442 | { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kbkdf_derive }, | |
443 | { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, | |
444 | (void(*)(void))kbkdf_settable_ctx_params }, | |
445 | { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kbkdf_set_ctx_params }, | |
446 | { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, | |
447 | (void(*)(void))kbkdf_gettable_ctx_params }, | |
448 | { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kbkdf_get_ctx_params }, | |
449 | { 0, NULL }, | |
450 | }; |