1/*
2 * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
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{-
11use OpenSSL::paramnames qw(produce_param_decoder);
12-}
13
14/*
15 * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
16 * Section 4.1.
17 *
18 * The Single Step KDF algorithm is given by:
19 *
20 * Result(0) = empty bit string (i.e., the null string).
21 * For i = 1 to reps, do the following:
22 *   Increment counter by 1.
23 *   Result(i) = Result(i - 1) || H(counter || Z || FixedInfo).
24 * DKM = LeftmostBits(Result(reps), L))
25 *
26 * NOTES:
27 *   Z is a shared secret required to produce the derived key material.
28 *   counter is a 4 byte buffer.
29 *   FixedInfo is a bit string containing context specific data.
30 *   DKM is the output derived key material.
31 *   L is the required size of the DKM.
32 *   reps = [L / H_outputBits]
33 *   H(x) is the auxiliary function that can be either a hash, HMAC or KMAC.
34 *   H_outputBits is the length of the output of the auxiliary function H(x).
35 *
36 * Currently there is not a comprehensive list of test vectors for this
37 * algorithm, especially for H(x) = HMAC and H(x) = KMAC.
38 * Test vectors for H(x) = Hash are indirectly used by CAVS KAS tests.
39 */
40#include <stdlib.h>
41#include <stdarg.h>
42#include <string.h>
43#include <openssl/hmac.h>
44#include <openssl/evp.h>
45#include <openssl/kdf.h>
46#include <openssl/core_names.h>
47#include <openssl/params.h>
48#include <openssl/proverr.h>
49#include "internal/cryptlib.h"
50#include "internal/numbers.h"
51#include "crypto/evp.h"
52#include "prov/provider_ctx.h"
53#include "prov/providercommon.h"
54#include "prov/implementations.h"
55#include "prov/provider_util.h"
56#include "prov/securitycheck.h"
57#include "internal/params.h"
58
59typedef struct {
60    void *provctx;
61    EVP_MAC_CTX *macctx;         /* H(x) = HMAC_hash OR H(x) = KMAC */
62    PROV_DIGEST digest;          /* H(x) = hash(x) */
63    unsigned char *secret;
64    size_t secret_len;
65    unsigned char *info;
66    size_t info_len;
67    unsigned char *salt;
68    size_t salt_len;
69    size_t out_len; /* optional KMAC parameter */
70    int is_kmac;
71    OSSL_FIPS_IND_DECLARE
72} KDF_SSKDF;
73
74#define SSKDF_MAX_INLEN (1<<30)
75#define SSKDF_KMAC128_DEFAULT_SALT_SIZE (168 - 4)
76#define SSKDF_KMAC256_DEFAULT_SALT_SIZE (136 - 4)
77
78#define SSKDF_MAX_INFOS 5
79
80/* KMAC uses a Customisation string of 'KDF' */
81static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 };
82
83static OSSL_FUNC_kdf_newctx_fn sskdf_new;
84static OSSL_FUNC_kdf_dupctx_fn sskdf_dup;
85static OSSL_FUNC_kdf_freectx_fn sskdf_free;
86static OSSL_FUNC_kdf_reset_fn sskdf_reset;
87static OSSL_FUNC_kdf_derive_fn sskdf_derive;
88static OSSL_FUNC_kdf_settable_ctx_params_fn sskdf_settable_ctx_params;
89static OSSL_FUNC_kdf_set_ctx_params_fn sskdf_set_ctx_params;
90static OSSL_FUNC_kdf_gettable_ctx_params_fn sskdf_common_gettable_ctx_params;
91static OSSL_FUNC_kdf_get_ctx_params_fn sskdf_common_get_ctx_params;
92static OSSL_FUNC_kdf_derive_fn x963kdf_derive;
93static OSSL_FUNC_kdf_settable_ctx_params_fn x963kdf_settable_ctx_params;
94static OSSL_FUNC_kdf_set_ctx_params_fn x963kdf_set_ctx_params;
95
96/*
97 * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
98 * Section 4. One-Step Key Derivation using H(x) = hash(x)
99 * Note: X9.63 also uses this code with the only difference being that the
100 * counter is appended to the secret 'z'.
101 * i.e.
102 *   result[i] = Hash(counter || z || info) for One Step OR
103 *   result[i] = Hash(z || counter || info) for X9.63.
104 */
105static int SSKDF_hash_kdm(const EVP_MD *kdf_md,
106                          const unsigned char *z, size_t z_len,
107                          const unsigned char *info, size_t info_len,
108                          unsigned int append_ctr,
109                          unsigned char *derived_key, size_t derived_key_len)
110{
111    int ret = 0, hlen;
112    size_t counter, out_len, len = derived_key_len;
113    unsigned char c[4];
114    unsigned char mac[EVP_MAX_MD_SIZE];
115    unsigned char *out = derived_key;
116    EVP_MD_CTX *ctx = NULL, *ctx_init = NULL;
117
118    if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
119            || derived_key_len > SSKDF_MAX_INLEN
120            || derived_key_len == 0)
121        return 0;
122
123    hlen = EVP_MD_get_size(kdf_md);
124    if (hlen <= 0)
125        return 0;
126    out_len = (size_t)hlen;
127
128    ctx = EVP_MD_CTX_create();
129    ctx_init = EVP_MD_CTX_create();
130    if (ctx == NULL || ctx_init == NULL)
131        goto end;
132
133    if (!EVP_DigestInit(ctx_init, kdf_md))
134        goto end;
135
136    for (counter = 1;; counter++) {
137        c[0] = (unsigned char)((counter >> 24) & 0xff);
138        c[1] = (unsigned char)((counter >> 16) & 0xff);
139        c[2] = (unsigned char)((counter >> 8) & 0xff);
140        c[3] = (unsigned char)(counter & 0xff);
141
142        if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init)
143                && (append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
144                && EVP_DigestUpdate(ctx, z, z_len)
145                && (!append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c)))
146                && EVP_DigestUpdate(ctx, info, info_len)))
147            goto end;
148        if (len >= out_len) {
149            if (!EVP_DigestFinal_ex(ctx, out, NULL))
150                goto end;
151            out += out_len;
152            len -= out_len;
153            if (len == 0)
154                break;
155        } else {
156            if (!EVP_DigestFinal_ex(ctx, mac, NULL))
157                goto end;
158            memcpy(out, mac, len);
159            break;
160        }
161    }
162    ret = 1;
163end:
164    EVP_MD_CTX_destroy(ctx);
165    EVP_MD_CTX_destroy(ctx_init);
166    OPENSSL_cleanse(mac, sizeof(mac));
167    return ret;
168}
169
170static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom,
171                     size_t custom_len, size_t kmac_out_len,
172                     size_t derived_key_len, unsigned char **out)
173{
174    OSSL_PARAM params[2];
175
176    /* Only KMAC has custom data - so return if not KMAC */
177    if (custom == NULL)
178        return 1;
179
180    params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM,
181                                                  (void *)custom, custom_len);
182    params[1] = OSSL_PARAM_construct_end();
183
184    if (!EVP_MAC_CTX_set_params(ctx, params))
185        return 0;
186
187    /* By default only do one iteration if kmac_out_len is not specified */
188    if (kmac_out_len == 0)
189        kmac_out_len = derived_key_len;
190    /* otherwise check the size is valid */
191    else if (!(kmac_out_len == derived_key_len
192            || kmac_out_len == 20
193            || kmac_out_len == 28
194            || kmac_out_len == 32
195            || kmac_out_len == 48
196            || kmac_out_len == 64))
197        return 0;
198
199    params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE,
200                                            &kmac_out_len);
201
202    if (EVP_MAC_CTX_set_params(ctx, params) <= 0)
203        return 0;
204
205    /*
206     * For kmac the output buffer can be larger than EVP_MAX_MD_SIZE: so
207     * alloc a buffer for this case.
208     */
209    if (kmac_out_len > EVP_MAX_MD_SIZE) {
210        *out = OPENSSL_zalloc(kmac_out_len);
211        if (*out == NULL)
212            return 0;
213    }
214    return 1;
215}
216
217/*
218 * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final
219 * Section 4. One-Step Key Derivation using MAC: i.e either
220 *     H(x) = HMAC-hash(salt, x) OR
221 *     H(x) = KMAC#(salt, x, outbits, CustomString='KDF')
222 */
223static int SSKDF_mac_kdm(EVP_MAC_CTX *ctx_init,
224                         const unsigned char *kmac_custom,
225                         size_t kmac_custom_len, size_t kmac_out_len,
226                         const unsigned char *salt, size_t salt_len,
227                         const unsigned char *z, size_t z_len,
228                         const unsigned char *info, size_t info_len,
229                         unsigned char *derived_key, size_t derived_key_len)
230{
231    int ret = 0;
232    size_t counter, out_len, len;
233    unsigned char c[4];
234    unsigned char mac_buf[EVP_MAX_MD_SIZE];
235    unsigned char *out = derived_key;
236    EVP_MAC_CTX *ctx = NULL;
237    unsigned char *mac = mac_buf, *kmac_buffer = NULL;
238
239    if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
240            || derived_key_len > SSKDF_MAX_INLEN
241            || derived_key_len == 0)
242        return 0;
243
244    if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len,
245                   derived_key_len, &kmac_buffer))
246        goto end;
247    if (kmac_buffer != NULL)
248        mac = kmac_buffer;
249
250    if (!EVP_MAC_init(ctx_init, salt, salt_len, NULL))
251        goto end;
252
253    out_len = EVP_MAC_CTX_get_mac_size(ctx_init); /* output size */
254    if (out_len <= 0 || (mac == mac_buf && out_len > sizeof(mac_buf)))
255        goto end;
256    len = derived_key_len;
257
258    for (counter = 1;; counter++) {
259        c[0] = (unsigned char)((counter >> 24) & 0xff);
260        c[1] = (unsigned char)((counter >> 16) & 0xff);
261        c[2] = (unsigned char)((counter >> 8) & 0xff);
262        c[3] = (unsigned char)(counter & 0xff);
263
264        ctx = EVP_MAC_CTX_dup(ctx_init);
265        if (!(ctx != NULL
266                && EVP_MAC_update(ctx, c, sizeof(c))
267                && EVP_MAC_update(ctx, z, z_len)
268                && EVP_MAC_update(ctx, info, info_len)))
269            goto end;
270        if (len >= out_len) {
271            if (!EVP_MAC_final(ctx, out, NULL, len))
272                goto end;
273            out += out_len;
274            len -= out_len;
275            if (len == 0)
276                break;
277        } else {
278            if (!EVP_MAC_final(ctx, mac, NULL, out_len))
279                goto end;
280            memcpy(out, mac, len);
281            break;
282        }
283        EVP_MAC_CTX_free(ctx);
284        ctx = NULL;
285    }
286    ret = 1;
287end:
288    if (kmac_buffer != NULL)
289        OPENSSL_clear_free(kmac_buffer, kmac_out_len);
290    else
291        OPENSSL_cleanse(mac_buf, sizeof(mac_buf));
292
293    EVP_MAC_CTX_free(ctx);
294    return ret;
295}
296
297static void *sskdf_new(void *provctx)
298{
299    KDF_SSKDF *ctx;
300
301    if (!ossl_prov_is_running())
302        return NULL;
303
304    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL) {
305        ctx->provctx = provctx;
306        OSSL_FIPS_IND_INIT(ctx)
307    }
308    return ctx;
309}
310
311static void sskdf_reset(void *vctx)
312{
313    KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
314    void *provctx = ctx->provctx;
315
316    EVP_MAC_CTX_free(ctx->macctx);
317    ossl_prov_digest_reset(&ctx->digest);
318    OPENSSL_clear_free(ctx->secret, ctx->secret_len);
319    OPENSSL_clear_free(ctx->info, ctx->info_len);
320    OPENSSL_clear_free(ctx->salt, ctx->salt_len);
321    memset(ctx, 0, sizeof(*ctx));
322    ctx->provctx = provctx;
323}
324
325static void sskdf_free(void *vctx)
326{
327    KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
328
329    if (ctx != NULL) {
330        sskdf_reset(ctx);
331        OPENSSL_free(ctx);
332    }
333}
334
335static void *sskdf_dup(void *vctx)
336{
337    const KDF_SSKDF *src = (const KDF_SSKDF *)vctx;
338    KDF_SSKDF *dest;
339
340    dest = sskdf_new(src->provctx);
341    if (dest != NULL) {
342        if (src->macctx != NULL) {
343            dest->macctx = EVP_MAC_CTX_dup(src->macctx);
344            if (dest->macctx == NULL)
345                goto err;
346        }
347        if (!ossl_prov_memdup(src->info, src->info_len,
348                              &dest->info, &dest->info_len)
349                || !ossl_prov_memdup(src->salt, src->salt_len,
350                                     &dest->salt , &dest->salt_len)
351                || !ossl_prov_memdup(src->secret, src->secret_len,
352                                     &dest->secret, &dest->secret_len)
353                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
354            goto err;
355        dest->out_len = src->out_len;
356        dest->is_kmac = src->is_kmac;
357        OSSL_FIPS_IND_COPY(dest, src)
358    }
359    return dest;
360
361 err:
362    sskdf_free(dest);
363    return NULL;
364}
365
366static size_t sskdf_size(KDF_SSKDF *ctx)
367{
368    int len;
369    const EVP_MD *md = NULL;
370
371    if (ctx->is_kmac)
372        return SIZE_MAX;
373
374    md = ossl_prov_digest_md(&ctx->digest);
375    if (md == NULL) {
376        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
377        return 0;
378    }
379    len = EVP_MD_get_size(md);
380    return (len <= 0) ? 0 : (size_t)len;
381}
382
383#ifdef FIPS_MODULE
384static int fips_sskdf_key_check_passed(KDF_SSKDF *ctx)
385{
386    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
387    int key_approved = ossl_kdf_check_key_size(ctx->secret_len);
388
389    if (!key_approved) {
390        if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0,
391                                         libctx, "SSKDF", "Key size",
392                                         ossl_fips_config_sskdf_key_check)) {
393            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
394            return 0;
395        }
396    }
397    return 1;
398}
399#endif
400
401static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen,
402                        const OSSL_PARAM params[])
403{
404    KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
405    const EVP_MD *md;
406
407    if (!ossl_prov_is_running() || !sskdf_set_ctx_params(ctx, params))
408        return 0;
409    if (ctx->secret == NULL) {
410        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
411        return 0;
412    }
413
414    md = ossl_prov_digest_md(&ctx->digest);
415
416    if (ctx->macctx != NULL) {
417        /* H(x) = KMAC or H(x) = HMAC */
418        int ret;
419        const unsigned char *custom = NULL;
420        size_t custom_len = 0;
421        int default_salt_len;
422        EVP_MAC *mac = EVP_MAC_CTX_get0_mac(ctx->macctx);
423
424        if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_HMAC)) {
425            /* H(x) = HMAC(x, salt, hash) */
426            if (md == NULL) {
427                ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
428                return 0;
429            }
430            default_salt_len = EVP_MD_get_size(md);
431            if (default_salt_len <= 0)
432                return 0;
433        } else if (ctx->is_kmac) {
434            /* H(x) = KMACzzz(x, salt, custom) */
435            custom = kmac_custom_str;
436            custom_len = sizeof(kmac_custom_str);
437            if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128))
438                default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE;
439            else
440                default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE;
441        } else {
442            ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_MAC_TYPE);
443            return 0;
444        }
445        /* If no salt is set then use a default_salt of zeros */
446        if (ctx->salt == NULL || ctx->salt_len <= 0) {
447            ctx->salt = OPENSSL_zalloc(default_salt_len);
448            if (ctx->salt == NULL)
449                return 0;
450            ctx->salt_len = default_salt_len;
451        }
452        ret = SSKDF_mac_kdm(ctx->macctx,
453                            custom, custom_len, ctx->out_len,
454                            ctx->salt, ctx->salt_len,
455                            ctx->secret, ctx->secret_len,
456                            ctx->info, ctx->info_len, key, keylen);
457        return ret;
458    } else {
459        /* H(x) = hash */
460        if (md == NULL) {
461            ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
462            return 0;
463        }
464        return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len,
465                              ctx->info, ctx->info_len, 0, key, keylen);
466    }
467}
468
469#ifdef FIPS_MODULE
470static int fips_x963kdf_digest_check_passed(KDF_SSKDF *ctx, const EVP_MD *md)
471{
472    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
473    /*
474     * Perform digest check
475     *
476     * X963KDF is a KDF defined in ANSI-X9.63. According to ACVP specification
477     * section 7.3.1, only SHA-2 and SHA-3 can be regarded as valid hash
478     * functions.
479     */
480    int digest_unapproved = (ctx->is_kmac != 1) && EVP_MD_is_a(md, SN_sha1);
481
482    if (digest_unapproved) {
483        if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0,
484                                         libctx, "X963KDF", "Digest",
485                                         ossl_fips_config_x963kdf_digest_check)) {
486            ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
487            return 0;
488        }
489    }
490    return 1;
491}
492
493static int fips_x963kdf_key_check_passed(KDF_SSKDF *ctx)
494{
495    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
496    int key_approved = ossl_kdf_check_key_size(ctx->secret_len);
497
498    if (!key_approved) {
499        if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE1,
500                                         libctx, "X963KDF", "Key size",
501                                         ossl_fips_config_x963kdf_key_check)) {
502            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
503            return 0;
504        }
505    }
506    return 1;
507}
508#endif
509
510static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen,
511                          const OSSL_PARAM params[])
512{
513    KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
514    const EVP_MD *md;
515
516    if (!ossl_prov_is_running() || !x963kdf_set_ctx_params(ctx, params))
517        return 0;
518
519    if (ctx->secret == NULL) {
520        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
521        return 0;
522    }
523
524    if (ctx->macctx != NULL) {
525        ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED);
526        return 0;
527    }
528
529    /* H(x) = hash */
530    md = ossl_prov_digest_md(&ctx->digest);
531    if (md == NULL) {
532        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
533        return 0;
534    }
535
536    return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len,
537                          ctx->info, ctx->info_len, 1, key, keylen);
538}
539
540struct sskdf_all_set_ctx_params_st {
541    OSSL_PARAM *secret;
542    OSSL_PARAM *propq;
543    OSSL_PARAM *engine;
544    OSSL_PARAM *digest;
545    OSSL_PARAM *mac;
546    OSSL_PARAM *salt;
547    OSSL_PARAM *size;
548#ifdef FIPS_MODULE
549    OSSL_PARAM *ind_k;
550    OSSL_PARAM *ind_d;
551#endif
552    OSSL_PARAM *info[SSKDF_MAX_INFOS];
553    int num_info;
554};
555
556static int sskdf_common_set_ctx_params
557        (KDF_SSKDF *ctx, struct sskdf_all_set_ctx_params_st *p,
558         const OSSL_PARAM *params)
559{
560    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
561    const EVP_MD *md = NULL;
562    size_t sz;
563    int r;
564
565    if (!ossl_prov_macctx_load(&ctx->macctx,
566                               p->mac, NULL, p->digest, p->propq, p->engine,
567                               NULL, NULL, NULL, libctx))
568        return 0;
569    if (ctx->macctx != NULL) {
570         if (EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx),
571                          OSSL_MAC_NAME_KMAC128)
572             || EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx),
573                             OSSL_MAC_NAME_KMAC256)) {
574             ctx->is_kmac = 1;
575         }
576    }
577
578    if (p->digest != NULL) {
579        if (!ossl_prov_digest_load(&ctx->digest, p->digest,
580                                   p->propq, p->engine, libctx))
581            return 0;
582
583        md = ossl_prov_digest_md(&ctx->digest);
584        if (EVP_MD_xof(md)) {
585            ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
586            return 0;
587        }
588    }
589
590    r = ossl_param_get1_octet_string_from_param(p->secret, &ctx->secret,
591                                                &ctx->secret_len);
592    if (r == 0)
593        return 0;
594
595    if (ossl_param_get1_concat_octet_string(p->num_info, p->info, &ctx->info,
596                                            &ctx->info_len) == 0)
597        return 0;
598
599    if (ossl_param_get1_octet_string_from_param(p->salt, &ctx->salt,
600                                                &ctx->salt_len) == 0)
601        return 0;
602
603    if (p->size != NULL) {
604        if (!OSSL_PARAM_get_size_t(p->size, &sz) || sz == 0)
605            return 0;
606        ctx->out_len = sz;
607    }
608    return 1;
609}
610
611#define sskdf_set_ctx_params_st sskdf_all_set_ctx_params_st
612
613{- produce_param_decoder('sskdf_set_ctx_params',
614                         (['KDF_PARAM_SECRET',         'secret', 'octet_string'],
615                          ['KDF_PARAM_KEY',            'secret', 'octet_string'],
616                          ['KDF_PARAM_INFO',           'info',   'octet_string', SSKDF_MAX_INFOS],
617                          ['KDF_PARAM_PROPERTIES',     'propq',  'utf8_string'],
618                          ['ALG_PARAM_ENGINE',         'engine', 'utf8_string', 'hidden'],
619                          ['KDF_PARAM_DIGEST',         'digest', 'utf8_string'],
620                          ['KDF_PARAM_MAC',            'mac',    'utf8_string'],
621                          ['KDF_PARAM_SALT',           'salt',   'octet_string'],
622                          ['KDF_PARAM_MAC_SIZE',       'size',   'size_t'],
623                          ['KDF_PARAM_FIPS_KEY_CHECK', 'ind_k',  'int', 'fips'],
624                         )); -}
625
626static int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
627{
628    KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
629    struct sskdf_all_set_ctx_params_st p;
630
631    if (ctx == NULL || !sskdf_set_ctx_params_decoder(params, &p))
632        return 0;
633
634    if (!OSSL_FIPS_IND_SET_CTX_FROM_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, p.ind_k))
635        return 0;
636
637    if (!sskdf_common_set_ctx_params(ctx, &p, params))
638        return 0;
639
640#ifdef FIPS_MODULE
641    if (p.secret != NULL)
642        if (!fips_sskdf_key_check_passed(ctx))
643            return 0;
644#endif
645
646    return 1;
647}
648
649static const OSSL_PARAM *sskdf_settable_ctx_params(ossl_unused void *ctx,
650                                                   ossl_unused void *provctx)
651{
652    return sskdf_set_ctx_params_list;
653}
654
655{- produce_param_decoder('sskdf_get_ctx_params',
656                         (['KDF_PARAM_SIZE',                    'size',   'size_t'],
657                          ['KDF_PARAM_FIPS_APPROVED_INDICATOR', 'ind',    'int', 'fips'],
658                         )); -}
659
660static int sskdf_common_get_ctx_params(void *vctx, OSSL_PARAM params[])
661{
662    KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
663    struct sskdf_get_ctx_params_st p;
664
665    if (ctx == NULL || !sskdf_get_ctx_params_decoder(params, &p))
666        return 0;
667
668    if (p.size != NULL) {
669        if (!OSSL_PARAM_set_size_t(p.size, sskdf_size(ctx)))
670            return 0;
671    }
672
673    if (!OSSL_FIPS_IND_GET_CTX_PARAM(ctx, p.ind))
674        return 0;
675
676    return 1;
677}
678
679static const OSSL_PARAM *sskdf_common_gettable_ctx_params
680        (ossl_unused void *ctx, ossl_unused void *provctx)
681{
682    return sskdf_get_ctx_params_list;
683}
684
685#define x963kdf_set_ctx_params_st sskdf_all_set_ctx_params_st
686
687{- produce_param_decoder('x963kdf_set_ctx_params',
688                         (['KDF_PARAM_SECRET',            'secret', 'octet_string'],
689                          ['KDF_PARAM_KEY',               'secret', 'octet_string'],
690                          ['KDF_PARAM_INFO',              'info',   'octet_string', SSKDF_MAX_INFOS],
691                          ['KDF_PARAM_PROPERTIES',        'propq',  'utf8_string'],
692                          ['ALG_PARAM_ENGINE',            'engine', 'utf8_string', 'hidden'],
693                          ['KDF_PARAM_DIGEST',            'digest', 'utf8_string'],
694                          ['KDF_PARAM_MAC',               'mac',    'utf8_string'],
695                          ['KDF_PARAM_SALT',              'salt',   'octet_string'],
696                          ['KDF_PARAM_MAC_SIZE',          'size',   'size_t'],
697                          ['KDF_PARAM_FIPS_DIGEST_CHECK', 'ind_d',  'int', 'fips'],
698                          ['KDF_PARAM_FIPS_KEY_CHECK',    'ind_k',  'int', 'fips'],
699                         )); -}
700
701static int x963kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
702{
703    KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
704    struct sskdf_all_set_ctx_params_st p;
705
706    if (ctx == NULL || !x963kdf_set_ctx_params_decoder(params, &p))
707        return 0;
708
709    if (!OSSL_FIPS_IND_SET_CTX_FROM_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, p.ind_d))
710        return 0;
711    if (!OSSL_FIPS_IND_SET_CTX_FROM_PARAM(ctx, OSSL_FIPS_IND_SETTABLE1, p.ind_k))
712        return 0;
713
714    if (!sskdf_common_set_ctx_params(ctx, &p, params))
715        return 0;
716
717#ifdef FIPS_MODULE
718    if (p.digest != NULL) {
719        const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
720
721        if (!fips_x963kdf_digest_check_passed(ctx, md))
722            return 0;
723    }
724
725    if (p.secret != NULL)
726        if (!fips_x963kdf_key_check_passed(ctx))
727            return 0;
728#endif
729
730    return 1;
731}
732
733static const OSSL_PARAM *x963kdf_settable_ctx_params(ossl_unused void *ctx,
734                                                     ossl_unused void *provctx)
735{
736    return x963kdf_set_ctx_params_list;
737}
738
739const OSSL_DISPATCH ossl_kdf_sskdf_functions[] = {
740    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new },
741    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))sskdf_dup },
742    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free },
743    { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset },
744    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))sskdf_derive },
745    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
746      (void(*)(void))sskdf_settable_ctx_params },
747    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params },
748    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
749      (void(*)(void))sskdf_common_gettable_ctx_params },
750    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_common_get_ctx_params },
751    OSSL_DISPATCH_END
752};
753
754const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[] = {
755    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new },
756    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))sskdf_dup },
757    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free },
758    { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset },
759    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive },
760    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
761      (void(*)(void))x963kdf_settable_ctx_params },
762    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))x963kdf_set_ctx_params },
763    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
764      (void(*)(void))sskdf_common_gettable_ctx_params },
765    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_common_get_ctx_params },
766    OSSL_DISPATCH_END
767};
768