1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * HMAC low level APIs are deprecated for public use, but still ok for internal
12e1051a39Sopenharmony_ci * use.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include <stdlib.h>
17e1051a39Sopenharmony_ci#include <stdarg.h>
18e1051a39Sopenharmony_ci#include <string.h>
19e1051a39Sopenharmony_ci#include <openssl/hmac.h>
20e1051a39Sopenharmony_ci#include <openssl/evp.h>
21e1051a39Sopenharmony_ci#include <openssl/kdf.h>
22e1051a39Sopenharmony_ci#include <openssl/core_names.h>
23e1051a39Sopenharmony_ci#include <openssl/proverr.h>
24e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
25e1051a39Sopenharmony_ci#include "internal/numbers.h"
26e1051a39Sopenharmony_ci#include "internal/packet.h"
27e1051a39Sopenharmony_ci#include "crypto/evp.h"
28e1051a39Sopenharmony_ci#include "prov/provider_ctx.h"
29e1051a39Sopenharmony_ci#include "prov/providercommon.h"
30e1051a39Sopenharmony_ci#include "prov/implementations.h"
31e1051a39Sopenharmony_ci#include "prov/provider_util.h"
32e1051a39Sopenharmony_ci#include "e_os.h"
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ci#define HKDF_MAXBUF 2048
35e1051a39Sopenharmony_ci#define HKDF_MAXINFO (32*1024)
36e1051a39Sopenharmony_ci
37e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_newctx_fn kdf_hkdf_new;
38e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_freectx_fn kdf_hkdf_free;
39e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_reset_fn kdf_hkdf_reset;
40e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_derive_fn kdf_hkdf_derive;
41e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
42e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params;
43e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params;
44e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params;
45e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_derive_fn kdf_tls1_3_derive;
46e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_3_settable_ctx_params;
47e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_3_set_ctx_params;
48e1051a39Sopenharmony_ci
49e1051a39Sopenharmony_cistatic int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
50e1051a39Sopenharmony_ci                const unsigned char *salt, size_t salt_len,
51e1051a39Sopenharmony_ci                const unsigned char *key, size_t key_len,
52e1051a39Sopenharmony_ci                const unsigned char *info, size_t info_len,
53e1051a39Sopenharmony_ci                unsigned char *okm, size_t okm_len);
54e1051a39Sopenharmony_cistatic int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
55e1051a39Sopenharmony_ci                        const unsigned char *salt, size_t salt_len,
56e1051a39Sopenharmony_ci                        const unsigned char *ikm, size_t ikm_len,
57e1051a39Sopenharmony_ci                        unsigned char *prk, size_t prk_len);
58e1051a39Sopenharmony_cistatic int HKDF_Expand(const EVP_MD *evp_md,
59e1051a39Sopenharmony_ci                       const unsigned char *prk, size_t prk_len,
60e1051a39Sopenharmony_ci                       const unsigned char *info, size_t info_len,
61e1051a39Sopenharmony_ci                       unsigned char *okm, size_t okm_len);
62e1051a39Sopenharmony_ci
63e1051a39Sopenharmony_ci/* Settable context parameters that are common across HKDF and the TLS KDF */
64e1051a39Sopenharmony_ci#define HKDF_COMMON_SETTABLES                                           \
65e1051a39Sopenharmony_ci        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0),           \
66e1051a39Sopenharmony_ci        OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL),                      \
67e1051a39Sopenharmony_ci        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),     \
68e1051a39Sopenharmony_ci        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),         \
69e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),           \
70e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0)
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_citypedef struct {
73e1051a39Sopenharmony_ci    void *provctx;
74e1051a39Sopenharmony_ci    int mode;
75e1051a39Sopenharmony_ci    PROV_DIGEST digest;
76e1051a39Sopenharmony_ci    unsigned char *salt;
77e1051a39Sopenharmony_ci    size_t salt_len;
78e1051a39Sopenharmony_ci    unsigned char *key;
79e1051a39Sopenharmony_ci    size_t key_len;
80e1051a39Sopenharmony_ci    unsigned char *prefix;
81e1051a39Sopenharmony_ci    size_t prefix_len;
82e1051a39Sopenharmony_ci    unsigned char *label;
83e1051a39Sopenharmony_ci    size_t label_len;
84e1051a39Sopenharmony_ci    unsigned char *data;
85e1051a39Sopenharmony_ci    size_t data_len;
86e1051a39Sopenharmony_ci    unsigned char *info;
87e1051a39Sopenharmony_ci    size_t info_len;
88e1051a39Sopenharmony_ci} KDF_HKDF;
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_cistatic void *kdf_hkdf_new(void *provctx)
91e1051a39Sopenharmony_ci{
92e1051a39Sopenharmony_ci    KDF_HKDF *ctx;
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
95e1051a39Sopenharmony_ci        return NULL;
96e1051a39Sopenharmony_ci
97e1051a39Sopenharmony_ci    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
98e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
99e1051a39Sopenharmony_ci    else
100e1051a39Sopenharmony_ci        ctx->provctx = provctx;
101e1051a39Sopenharmony_ci    return ctx;
102e1051a39Sopenharmony_ci}
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_cistatic void kdf_hkdf_free(void *vctx)
105e1051a39Sopenharmony_ci{
106e1051a39Sopenharmony_ci    KDF_HKDF *ctx = (KDF_HKDF *)vctx;
107e1051a39Sopenharmony_ci
108e1051a39Sopenharmony_ci    if (ctx != NULL) {
109e1051a39Sopenharmony_ci        kdf_hkdf_reset(ctx);
110e1051a39Sopenharmony_ci        OPENSSL_free(ctx);
111e1051a39Sopenharmony_ci    }
112e1051a39Sopenharmony_ci}
113e1051a39Sopenharmony_ci
114e1051a39Sopenharmony_cistatic void kdf_hkdf_reset(void *vctx)
115e1051a39Sopenharmony_ci{
116e1051a39Sopenharmony_ci    KDF_HKDF *ctx = (KDF_HKDF *)vctx;
117e1051a39Sopenharmony_ci    void *provctx = ctx->provctx;
118e1051a39Sopenharmony_ci
119e1051a39Sopenharmony_ci    ossl_prov_digest_reset(&ctx->digest);
120e1051a39Sopenharmony_ci    OPENSSL_free(ctx->salt);
121e1051a39Sopenharmony_ci    OPENSSL_free(ctx->prefix);
122e1051a39Sopenharmony_ci    OPENSSL_free(ctx->label);
123e1051a39Sopenharmony_ci    OPENSSL_clear_free(ctx->data, ctx->data_len);
124e1051a39Sopenharmony_ci    OPENSSL_clear_free(ctx->key, ctx->key_len);
125e1051a39Sopenharmony_ci    OPENSSL_clear_free(ctx->info, ctx->info_len);
126e1051a39Sopenharmony_ci    memset(ctx, 0, sizeof(*ctx));
127e1051a39Sopenharmony_ci    ctx->provctx = provctx;
128e1051a39Sopenharmony_ci}
129e1051a39Sopenharmony_ci
130e1051a39Sopenharmony_cistatic size_t kdf_hkdf_size(KDF_HKDF *ctx)
131e1051a39Sopenharmony_ci{
132e1051a39Sopenharmony_ci    int sz;
133e1051a39Sopenharmony_ci    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
134e1051a39Sopenharmony_ci
135e1051a39Sopenharmony_ci    if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
136e1051a39Sopenharmony_ci        return SIZE_MAX;
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_ci    if (md == NULL) {
139e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
140e1051a39Sopenharmony_ci        return 0;
141e1051a39Sopenharmony_ci    }
142e1051a39Sopenharmony_ci    sz = EVP_MD_get_size(md);
143e1051a39Sopenharmony_ci    if (sz < 0)
144e1051a39Sopenharmony_ci        return 0;
145e1051a39Sopenharmony_ci
146e1051a39Sopenharmony_ci    return sz;
147e1051a39Sopenharmony_ci}
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_cistatic int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen,
150e1051a39Sopenharmony_ci                           const OSSL_PARAM params[])
151e1051a39Sopenharmony_ci{
152e1051a39Sopenharmony_ci    KDF_HKDF *ctx = (KDF_HKDF *)vctx;
153e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
154e1051a39Sopenharmony_ci    const EVP_MD *md;
155e1051a39Sopenharmony_ci
156e1051a39Sopenharmony_ci    if (!ossl_prov_is_running() || !kdf_hkdf_set_ctx_params(ctx, params))
157e1051a39Sopenharmony_ci        return 0;
158e1051a39Sopenharmony_ci
159e1051a39Sopenharmony_ci    md = ossl_prov_digest_md(&ctx->digest);
160e1051a39Sopenharmony_ci    if (md == NULL) {
161e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
162e1051a39Sopenharmony_ci        return 0;
163e1051a39Sopenharmony_ci    }
164e1051a39Sopenharmony_ci    if (ctx->key == NULL) {
165e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
166e1051a39Sopenharmony_ci        return 0;
167e1051a39Sopenharmony_ci    }
168e1051a39Sopenharmony_ci    if (keylen == 0) {
169e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
170e1051a39Sopenharmony_ci        return 0;
171e1051a39Sopenharmony_ci    }
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci    switch (ctx->mode) {
174e1051a39Sopenharmony_ci    case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
175e1051a39Sopenharmony_ci    default:
176e1051a39Sopenharmony_ci        return HKDF(libctx, md, ctx->salt, ctx->salt_len,
177e1051a39Sopenharmony_ci                    ctx->key, ctx->key_len, ctx->info, ctx->info_len, key, keylen);
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci    case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
180e1051a39Sopenharmony_ci        return HKDF_Extract(libctx, md, ctx->salt, ctx->salt_len,
181e1051a39Sopenharmony_ci                            ctx->key, ctx->key_len, key, keylen);
182e1051a39Sopenharmony_ci
183e1051a39Sopenharmony_ci    case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
184e1051a39Sopenharmony_ci        return HKDF_Expand(md, ctx->key, ctx->key_len, ctx->info,
185e1051a39Sopenharmony_ci                           ctx->info_len, key, keylen);
186e1051a39Sopenharmony_ci    }
187e1051a39Sopenharmony_ci}
188e1051a39Sopenharmony_ci
189e1051a39Sopenharmony_cistatic int hkdf_common_set_ctx_params(KDF_HKDF *ctx, const OSSL_PARAM params[])
190e1051a39Sopenharmony_ci{
191e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
192e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
193e1051a39Sopenharmony_ci    int n;
194e1051a39Sopenharmony_ci
195e1051a39Sopenharmony_ci    if (params == NULL)
196e1051a39Sopenharmony_ci        return 1;
197e1051a39Sopenharmony_ci
198e1051a39Sopenharmony_ci    if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
199e1051a39Sopenharmony_ci        return 0;
200e1051a39Sopenharmony_ci
201e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) {
202e1051a39Sopenharmony_ci        if (p->data_type == OSSL_PARAM_UTF8_STRING) {
203e1051a39Sopenharmony_ci            if (OPENSSL_strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) {
204e1051a39Sopenharmony_ci                ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
205e1051a39Sopenharmony_ci            } else if (OPENSSL_strcasecmp(p->data, "EXTRACT_ONLY") == 0) {
206e1051a39Sopenharmony_ci                ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
207e1051a39Sopenharmony_ci            } else if (OPENSSL_strcasecmp(p->data, "EXPAND_ONLY") == 0) {
208e1051a39Sopenharmony_ci                ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
209e1051a39Sopenharmony_ci            } else {
210e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
211e1051a39Sopenharmony_ci                return 0;
212e1051a39Sopenharmony_ci            }
213e1051a39Sopenharmony_ci        } else if (OSSL_PARAM_get_int(p, &n)) {
214e1051a39Sopenharmony_ci            if (n != EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
215e1051a39Sopenharmony_ci                && n != EVP_KDF_HKDF_MODE_EXTRACT_ONLY
216e1051a39Sopenharmony_ci                && n != EVP_KDF_HKDF_MODE_EXPAND_ONLY) {
217e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
218e1051a39Sopenharmony_ci                return 0;
219e1051a39Sopenharmony_ci            }
220e1051a39Sopenharmony_ci            ctx->mode = n;
221e1051a39Sopenharmony_ci        } else {
222e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
223e1051a39Sopenharmony_ci            return 0;
224e1051a39Sopenharmony_ci        }
225e1051a39Sopenharmony_ci    }
226e1051a39Sopenharmony_ci
227e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) {
228e1051a39Sopenharmony_ci        OPENSSL_clear_free(ctx->key, ctx->key_len);
229e1051a39Sopenharmony_ci        ctx->key = NULL;
230e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->key, 0,
231e1051a39Sopenharmony_ci                                         &ctx->key_len))
232e1051a39Sopenharmony_ci            return 0;
233e1051a39Sopenharmony_ci    }
234e1051a39Sopenharmony_ci
235e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) {
236e1051a39Sopenharmony_ci        if (p->data_size != 0 && p->data != NULL) {
237e1051a39Sopenharmony_ci            OPENSSL_free(ctx->salt);
238e1051a39Sopenharmony_ci            ctx->salt = NULL;
239e1051a39Sopenharmony_ci            if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0,
240e1051a39Sopenharmony_ci                                             &ctx->salt_len))
241e1051a39Sopenharmony_ci                return 0;
242e1051a39Sopenharmony_ci        }
243e1051a39Sopenharmony_ci    }
244e1051a39Sopenharmony_ci
245e1051a39Sopenharmony_ci    return 1;
246e1051a39Sopenharmony_ci}
247e1051a39Sopenharmony_ci
248e1051a39Sopenharmony_ci/*
249e1051a39Sopenharmony_ci * Use WPACKET to concat one or more OSSL_KDF_PARAM_INFO fields into a fixed
250e1051a39Sopenharmony_ci * out buffer of size *outlen.
251e1051a39Sopenharmony_ci * If out is NULL then outlen is used to return the required buffer size.
252e1051a39Sopenharmony_ci */
253e1051a39Sopenharmony_cistatic int setinfo_fromparams(const OSSL_PARAM *p, unsigned char *out, size_t *outlen)
254e1051a39Sopenharmony_ci{
255e1051a39Sopenharmony_ci    int ret = 0;
256e1051a39Sopenharmony_ci    WPACKET pkt;
257e1051a39Sopenharmony_ci
258e1051a39Sopenharmony_ci    if (out == NULL) {
259e1051a39Sopenharmony_ci        if (!WPACKET_init_null(&pkt, 0))
260e1051a39Sopenharmony_ci            return 0;
261e1051a39Sopenharmony_ci    } else {
262e1051a39Sopenharmony_ci        if (!WPACKET_init_static_len(&pkt, out, *outlen, 0))
263e1051a39Sopenharmony_ci            return 0;
264e1051a39Sopenharmony_ci    }
265e1051a39Sopenharmony_ci
266e1051a39Sopenharmony_ci    for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, OSSL_KDF_PARAM_INFO)) {
267e1051a39Sopenharmony_ci        if (p->data_type != OSSL_PARAM_OCTET_STRING)
268e1051a39Sopenharmony_ci            goto err;
269e1051a39Sopenharmony_ci        if (p->data != NULL
270e1051a39Sopenharmony_ci                && p->data_size != 0
271e1051a39Sopenharmony_ci                && !WPACKET_memcpy(&pkt, p->data, p->data_size))
272e1051a39Sopenharmony_ci            goto err;
273e1051a39Sopenharmony_ci    }
274e1051a39Sopenharmony_ci    if (!WPACKET_get_total_written(&pkt, outlen)
275e1051a39Sopenharmony_ci            || !WPACKET_finish(&pkt))
276e1051a39Sopenharmony_ci        goto err;
277e1051a39Sopenharmony_ci    ret = 1;
278e1051a39Sopenharmony_cierr:
279e1051a39Sopenharmony_ci    WPACKET_cleanup(&pkt);
280e1051a39Sopenharmony_ci    return ret;
281e1051a39Sopenharmony_ci}
282e1051a39Sopenharmony_ci
283e1051a39Sopenharmony_cistatic int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
284e1051a39Sopenharmony_ci{
285e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
286e1051a39Sopenharmony_ci    KDF_HKDF *ctx = vctx;
287e1051a39Sopenharmony_ci
288e1051a39Sopenharmony_ci    if (params == NULL)
289e1051a39Sopenharmony_ci        return 1;
290e1051a39Sopenharmony_ci
291e1051a39Sopenharmony_ci    if (!hkdf_common_set_ctx_params(ctx, params))
292e1051a39Sopenharmony_ci        return 0;
293e1051a39Sopenharmony_ci
294e1051a39Sopenharmony_ci    /* The info fields concatenate, so process them all */
295e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) {
296e1051a39Sopenharmony_ci        size_t sz = 0;
297e1051a39Sopenharmony_ci
298e1051a39Sopenharmony_ci        /* calculate the total size */
299e1051a39Sopenharmony_ci        if (!setinfo_fromparams(p, NULL, &sz))
300e1051a39Sopenharmony_ci            return 0;
301e1051a39Sopenharmony_ci        if (sz > HKDF_MAXINFO)
302e1051a39Sopenharmony_ci            return 0;
303e1051a39Sopenharmony_ci
304e1051a39Sopenharmony_ci        OPENSSL_clear_free(ctx->info, ctx->info_len);
305e1051a39Sopenharmony_ci        ctx->info = NULL;
306e1051a39Sopenharmony_ci        if (sz == 0)
307e1051a39Sopenharmony_ci            return 1;
308e1051a39Sopenharmony_ci        /* Alloc the buffer */
309e1051a39Sopenharmony_ci        ctx->info = OPENSSL_malloc(sz);
310e1051a39Sopenharmony_ci        if (ctx->info == NULL)
311e1051a39Sopenharmony_ci            return 0;
312e1051a39Sopenharmony_ci        ctx->info_len = sz;
313e1051a39Sopenharmony_ci        /* Concat one or more OSSL_KDF_PARAM_INFO fields */
314e1051a39Sopenharmony_ci        if (!setinfo_fromparams(p, ctx->info, &sz))
315e1051a39Sopenharmony_ci            return 0;
316e1051a39Sopenharmony_ci    }
317e1051a39Sopenharmony_ci    return 1;
318e1051a39Sopenharmony_ci}
319e1051a39Sopenharmony_ci
320e1051a39Sopenharmony_cistatic const OSSL_PARAM *kdf_hkdf_settable_ctx_params(ossl_unused void *ctx,
321e1051a39Sopenharmony_ci                                                      ossl_unused void *provctx)
322e1051a39Sopenharmony_ci{
323e1051a39Sopenharmony_ci    static const OSSL_PARAM known_settable_ctx_params[] = {
324e1051a39Sopenharmony_ci        HKDF_COMMON_SETTABLES,
325e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
326e1051a39Sopenharmony_ci        OSSL_PARAM_END
327e1051a39Sopenharmony_ci    };
328e1051a39Sopenharmony_ci    return known_settable_ctx_params;
329e1051a39Sopenharmony_ci}
330e1051a39Sopenharmony_ci
331e1051a39Sopenharmony_cistatic int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
332e1051a39Sopenharmony_ci{
333e1051a39Sopenharmony_ci    KDF_HKDF *ctx = (KDF_HKDF *)vctx;
334e1051a39Sopenharmony_ci    OSSL_PARAM *p;
335e1051a39Sopenharmony_ci
336e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
337e1051a39Sopenharmony_ci        size_t sz = kdf_hkdf_size(ctx);
338e1051a39Sopenharmony_ci
339e1051a39Sopenharmony_ci        if (sz == 0)
340e1051a39Sopenharmony_ci            return 0;
341e1051a39Sopenharmony_ci        return OSSL_PARAM_set_size_t(p, sz);
342e1051a39Sopenharmony_ci    }
343e1051a39Sopenharmony_ci    return -2;
344e1051a39Sopenharmony_ci}
345e1051a39Sopenharmony_ci
346e1051a39Sopenharmony_cistatic const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx,
347e1051a39Sopenharmony_ci                                                      ossl_unused void *provctx)
348e1051a39Sopenharmony_ci{
349e1051a39Sopenharmony_ci    static const OSSL_PARAM known_gettable_ctx_params[] = {
350e1051a39Sopenharmony_ci        OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
351e1051a39Sopenharmony_ci        OSSL_PARAM_END
352e1051a39Sopenharmony_ci    };
353e1051a39Sopenharmony_ci    return known_gettable_ctx_params;
354e1051a39Sopenharmony_ci}
355e1051a39Sopenharmony_ci
356e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_kdf_hkdf_functions[] = {
357e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
358e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
359e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
360e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive },
361e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
362e1051a39Sopenharmony_ci      (void(*)(void))kdf_hkdf_settable_ctx_params },
363e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_set_ctx_params },
364e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
365e1051a39Sopenharmony_ci      (void(*)(void))kdf_hkdf_gettable_ctx_params },
366e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params },
367e1051a39Sopenharmony_ci    { 0, NULL }
368e1051a39Sopenharmony_ci};
369e1051a39Sopenharmony_ci
370e1051a39Sopenharmony_ci/*
371e1051a39Sopenharmony_ci * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
372e1051a39Sopenharmony_ci * Section 2 (https://tools.ietf.org/html/rfc5869#section-2) and
373e1051a39Sopenharmony_ci * "Cryptographic Extraction and Key Derivation: The HKDF Scheme"
374e1051a39Sopenharmony_ci * Section 4.2 (https://eprint.iacr.org/2010/264.pdf).
375e1051a39Sopenharmony_ci *
376e1051a39Sopenharmony_ci * From the paper:
377e1051a39Sopenharmony_ci *   The scheme HKDF is specified as:
378e1051a39Sopenharmony_ci *     HKDF(XTS, SKM, CTXinfo, L) = K(1) | K(2) | ... | K(t)
379e1051a39Sopenharmony_ci *
380e1051a39Sopenharmony_ci *     where:
381e1051a39Sopenharmony_ci *       SKM is source key material
382e1051a39Sopenharmony_ci *       XTS is extractor salt (which may be null or constant)
383e1051a39Sopenharmony_ci *       CTXinfo is context information (may be null)
384e1051a39Sopenharmony_ci *       L is the number of key bits to be produced by KDF
385e1051a39Sopenharmony_ci *       k is the output length in bits of the hash function used with HMAC
386e1051a39Sopenharmony_ci *       t = ceil(L/k)
387e1051a39Sopenharmony_ci *       the value K(t) is truncated to its first d = L mod k bits.
388e1051a39Sopenharmony_ci *
389e1051a39Sopenharmony_ci * From RFC 5869:
390e1051a39Sopenharmony_ci *   2.2.  Step 1: Extract
391e1051a39Sopenharmony_ci *     HKDF-Extract(salt, IKM) -> PRK
392e1051a39Sopenharmony_ci *   2.3.  Step 2: Expand
393e1051a39Sopenharmony_ci *     HKDF-Expand(PRK, info, L) -> OKM
394e1051a39Sopenharmony_ci */
395e1051a39Sopenharmony_cistatic int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
396e1051a39Sopenharmony_ci                const unsigned char *salt, size_t salt_len,
397e1051a39Sopenharmony_ci                const unsigned char *ikm, size_t ikm_len,
398e1051a39Sopenharmony_ci                const unsigned char *info, size_t info_len,
399e1051a39Sopenharmony_ci                unsigned char *okm, size_t okm_len)
400e1051a39Sopenharmony_ci{
401e1051a39Sopenharmony_ci    unsigned char prk[EVP_MAX_MD_SIZE];
402e1051a39Sopenharmony_ci    int ret, sz;
403e1051a39Sopenharmony_ci    size_t prk_len;
404e1051a39Sopenharmony_ci
405e1051a39Sopenharmony_ci    sz = EVP_MD_get_size(evp_md);
406e1051a39Sopenharmony_ci    if (sz < 0)
407e1051a39Sopenharmony_ci        return 0;
408e1051a39Sopenharmony_ci    prk_len = (size_t)sz;
409e1051a39Sopenharmony_ci
410e1051a39Sopenharmony_ci    /* Step 1: HKDF-Extract(salt, IKM) -> PRK */
411e1051a39Sopenharmony_ci    if (!HKDF_Extract(libctx, evp_md,
412e1051a39Sopenharmony_ci                      salt, salt_len, ikm, ikm_len, prk, prk_len))
413e1051a39Sopenharmony_ci        return 0;
414e1051a39Sopenharmony_ci
415e1051a39Sopenharmony_ci    /* Step 2: HKDF-Expand(PRK, info, L) -> OKM */
416e1051a39Sopenharmony_ci    ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
417e1051a39Sopenharmony_ci    OPENSSL_cleanse(prk, sizeof(prk));
418e1051a39Sopenharmony_ci
419e1051a39Sopenharmony_ci    return ret;
420e1051a39Sopenharmony_ci}
421e1051a39Sopenharmony_ci
422e1051a39Sopenharmony_ci/*
423e1051a39Sopenharmony_ci * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
424e1051a39Sopenharmony_ci * Section 2.2 (https://tools.ietf.org/html/rfc5869#section-2.2).
425e1051a39Sopenharmony_ci *
426e1051a39Sopenharmony_ci * 2.2.  Step 1: Extract
427e1051a39Sopenharmony_ci *
428e1051a39Sopenharmony_ci *   HKDF-Extract(salt, IKM) -> PRK
429e1051a39Sopenharmony_ci *
430e1051a39Sopenharmony_ci *   Options:
431e1051a39Sopenharmony_ci *      Hash     a hash function; HashLen denotes the length of the
432e1051a39Sopenharmony_ci *               hash function output in octets
433e1051a39Sopenharmony_ci *
434e1051a39Sopenharmony_ci *   Inputs:
435e1051a39Sopenharmony_ci *      salt     optional salt value (a non-secret random value);
436e1051a39Sopenharmony_ci *               if not provided, it is set to a string of HashLen zeros.
437e1051a39Sopenharmony_ci *      IKM      input keying material
438e1051a39Sopenharmony_ci *
439e1051a39Sopenharmony_ci *   Output:
440e1051a39Sopenharmony_ci *      PRK      a pseudorandom key (of HashLen octets)
441e1051a39Sopenharmony_ci *
442e1051a39Sopenharmony_ci *   The output PRK is calculated as follows:
443e1051a39Sopenharmony_ci *
444e1051a39Sopenharmony_ci *   PRK = HMAC-Hash(salt, IKM)
445e1051a39Sopenharmony_ci */
446e1051a39Sopenharmony_cistatic int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
447e1051a39Sopenharmony_ci                        const unsigned char *salt, size_t salt_len,
448e1051a39Sopenharmony_ci                        const unsigned char *ikm, size_t ikm_len,
449e1051a39Sopenharmony_ci                        unsigned char *prk, size_t prk_len)
450e1051a39Sopenharmony_ci{
451e1051a39Sopenharmony_ci    int sz = EVP_MD_get_size(evp_md);
452e1051a39Sopenharmony_ci
453e1051a39Sopenharmony_ci    if (sz < 0)
454e1051a39Sopenharmony_ci        return 0;
455e1051a39Sopenharmony_ci    if (prk_len != (size_t)sz) {
456e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE);
457e1051a39Sopenharmony_ci        return 0;
458e1051a39Sopenharmony_ci    }
459e1051a39Sopenharmony_ci    /* calc: PRK = HMAC-Hash(salt, IKM) */
460e1051a39Sopenharmony_ci    return
461e1051a39Sopenharmony_ci        EVP_Q_mac(libctx, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, salt,
462e1051a39Sopenharmony_ci                  salt_len, ikm, ikm_len, prk, EVP_MD_get_size(evp_md), NULL)
463e1051a39Sopenharmony_ci        != NULL;
464e1051a39Sopenharmony_ci}
465e1051a39Sopenharmony_ci
466e1051a39Sopenharmony_ci/*
467e1051a39Sopenharmony_ci * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
468e1051a39Sopenharmony_ci * Section 2.3 (https://tools.ietf.org/html/rfc5869#section-2.3).
469e1051a39Sopenharmony_ci *
470e1051a39Sopenharmony_ci * 2.3.  Step 2: Expand
471e1051a39Sopenharmony_ci *
472e1051a39Sopenharmony_ci *   HKDF-Expand(PRK, info, L) -> OKM
473e1051a39Sopenharmony_ci *
474e1051a39Sopenharmony_ci *   Options:
475e1051a39Sopenharmony_ci *      Hash     a hash function; HashLen denotes the length of the
476e1051a39Sopenharmony_ci *               hash function output in octets
477e1051a39Sopenharmony_ci *
478e1051a39Sopenharmony_ci *   Inputs:
479e1051a39Sopenharmony_ci *      PRK      a pseudorandom key of at least HashLen octets
480e1051a39Sopenharmony_ci *               (usually, the output from the extract step)
481e1051a39Sopenharmony_ci *      info     optional context and application specific information
482e1051a39Sopenharmony_ci *               (can be a zero-length string)
483e1051a39Sopenharmony_ci *      L        length of output keying material in octets
484e1051a39Sopenharmony_ci *               (<= 255*HashLen)
485e1051a39Sopenharmony_ci *
486e1051a39Sopenharmony_ci *   Output:
487e1051a39Sopenharmony_ci *      OKM      output keying material (of L octets)
488e1051a39Sopenharmony_ci *
489e1051a39Sopenharmony_ci *   The output OKM is calculated as follows:
490e1051a39Sopenharmony_ci *
491e1051a39Sopenharmony_ci *   N = ceil(L/HashLen)
492e1051a39Sopenharmony_ci *   T = T(1) | T(2) | T(3) | ... | T(N)
493e1051a39Sopenharmony_ci *   OKM = first L octets of T
494e1051a39Sopenharmony_ci *
495e1051a39Sopenharmony_ci *   where:
496e1051a39Sopenharmony_ci *   T(0) = empty string (zero length)
497e1051a39Sopenharmony_ci *   T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
498e1051a39Sopenharmony_ci *   T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
499e1051a39Sopenharmony_ci *   T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
500e1051a39Sopenharmony_ci *   ...
501e1051a39Sopenharmony_ci *
502e1051a39Sopenharmony_ci *   (where the constant concatenated to the end of each T(n) is a
503e1051a39Sopenharmony_ci *   single octet.)
504e1051a39Sopenharmony_ci */
505e1051a39Sopenharmony_cistatic int HKDF_Expand(const EVP_MD *evp_md,
506e1051a39Sopenharmony_ci                       const unsigned char *prk, size_t prk_len,
507e1051a39Sopenharmony_ci                       const unsigned char *info, size_t info_len,
508e1051a39Sopenharmony_ci                       unsigned char *okm, size_t okm_len)
509e1051a39Sopenharmony_ci{
510e1051a39Sopenharmony_ci    HMAC_CTX *hmac;
511e1051a39Sopenharmony_ci    int ret = 0, sz;
512e1051a39Sopenharmony_ci    unsigned int i;
513e1051a39Sopenharmony_ci    unsigned char prev[EVP_MAX_MD_SIZE];
514e1051a39Sopenharmony_ci    size_t done_len = 0, dig_len, n;
515e1051a39Sopenharmony_ci
516e1051a39Sopenharmony_ci    sz = EVP_MD_get_size(evp_md);
517e1051a39Sopenharmony_ci    if (sz <= 0)
518e1051a39Sopenharmony_ci        return 0;
519e1051a39Sopenharmony_ci    dig_len = (size_t)sz;
520e1051a39Sopenharmony_ci
521e1051a39Sopenharmony_ci    /* calc: N = ceil(L/HashLen) */
522e1051a39Sopenharmony_ci    n = okm_len / dig_len;
523e1051a39Sopenharmony_ci    if (okm_len % dig_len)
524e1051a39Sopenharmony_ci        n++;
525e1051a39Sopenharmony_ci
526e1051a39Sopenharmony_ci    if (n > 255 || okm == NULL)
527e1051a39Sopenharmony_ci        return 0;
528e1051a39Sopenharmony_ci
529e1051a39Sopenharmony_ci    if ((hmac = HMAC_CTX_new()) == NULL)
530e1051a39Sopenharmony_ci        return 0;
531e1051a39Sopenharmony_ci
532e1051a39Sopenharmony_ci    if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
533e1051a39Sopenharmony_ci        goto err;
534e1051a39Sopenharmony_ci
535e1051a39Sopenharmony_ci    for (i = 1; i <= n; i++) {
536e1051a39Sopenharmony_ci        size_t copy_len;
537e1051a39Sopenharmony_ci        const unsigned char ctr = i;
538e1051a39Sopenharmony_ci
539e1051a39Sopenharmony_ci        /* calc: T(i) = HMAC-Hash(PRK, T(i - 1) | info | i) */
540e1051a39Sopenharmony_ci        if (i > 1) {
541e1051a39Sopenharmony_ci            if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
542e1051a39Sopenharmony_ci                goto err;
543e1051a39Sopenharmony_ci
544e1051a39Sopenharmony_ci            if (!HMAC_Update(hmac, prev, dig_len))
545e1051a39Sopenharmony_ci                goto err;
546e1051a39Sopenharmony_ci        }
547e1051a39Sopenharmony_ci
548e1051a39Sopenharmony_ci        if (!HMAC_Update(hmac, info, info_len))
549e1051a39Sopenharmony_ci            goto err;
550e1051a39Sopenharmony_ci
551e1051a39Sopenharmony_ci        if (!HMAC_Update(hmac, &ctr, 1))
552e1051a39Sopenharmony_ci            goto err;
553e1051a39Sopenharmony_ci
554e1051a39Sopenharmony_ci        if (!HMAC_Final(hmac, prev, NULL))
555e1051a39Sopenharmony_ci            goto err;
556e1051a39Sopenharmony_ci
557e1051a39Sopenharmony_ci        copy_len = (dig_len > okm_len - done_len) ?
558e1051a39Sopenharmony_ci                       okm_len - done_len :
559e1051a39Sopenharmony_ci                       dig_len;
560e1051a39Sopenharmony_ci
561e1051a39Sopenharmony_ci        memcpy(okm + done_len, prev, copy_len);
562e1051a39Sopenharmony_ci
563e1051a39Sopenharmony_ci        done_len += copy_len;
564e1051a39Sopenharmony_ci    }
565e1051a39Sopenharmony_ci    ret = 1;
566e1051a39Sopenharmony_ci
567e1051a39Sopenharmony_ci err:
568e1051a39Sopenharmony_ci    OPENSSL_cleanse(prev, sizeof(prev));
569e1051a39Sopenharmony_ci    HMAC_CTX_free(hmac);
570e1051a39Sopenharmony_ci    return ret;
571e1051a39Sopenharmony_ci}
572e1051a39Sopenharmony_ci
573e1051a39Sopenharmony_ci/*
574e1051a39Sopenharmony_ci * TLS uses slight variations of the above and for FIPS validation purposes,
575e1051a39Sopenharmony_ci * they need to be present here.
576e1051a39Sopenharmony_ci * Refer to RFC 8446 section 7 for specific details.
577e1051a39Sopenharmony_ci */
578e1051a39Sopenharmony_ci
579e1051a39Sopenharmony_ci/*
580e1051a39Sopenharmony_ci * Given a |secret|; a |label| of length |labellen|; and |data| of length
581e1051a39Sopenharmony_ci * |datalen| (e.g. typically a hash of the handshake messages), derive a new
582e1051a39Sopenharmony_ci * secret |outlen| bytes long and store it in the location pointed to be |out|.
583e1051a39Sopenharmony_ci * The |data| value may be zero length. Returns 1 on success and 0 on failure.
584e1051a39Sopenharmony_ci */
585e1051a39Sopenharmony_cistatic int prov_tls13_hkdf_expand(const EVP_MD *md,
586e1051a39Sopenharmony_ci                                  const unsigned char *key, size_t keylen,
587e1051a39Sopenharmony_ci                                  const unsigned char *prefix, size_t prefixlen,
588e1051a39Sopenharmony_ci                                  const unsigned char *label, size_t labellen,
589e1051a39Sopenharmony_ci                                  const unsigned char *data, size_t datalen,
590e1051a39Sopenharmony_ci                                  unsigned char *out, size_t outlen)
591e1051a39Sopenharmony_ci{
592e1051a39Sopenharmony_ci    size_t hkdflabellen;
593e1051a39Sopenharmony_ci    unsigned char hkdflabel[HKDF_MAXBUF];
594e1051a39Sopenharmony_ci    WPACKET pkt;
595e1051a39Sopenharmony_ci
596e1051a39Sopenharmony_ci    /*
597e1051a39Sopenharmony_ci     * 2 bytes for length of derived secret + 1 byte for length of combined
598e1051a39Sopenharmony_ci     * prefix and label + bytes for the label itself + 1 byte length of hash
599e1051a39Sopenharmony_ci     * + bytes for the hash itself.  We've got the maximum the KDF can handle
600e1051a39Sopenharmony_ci     * which should always be sufficient.
601e1051a39Sopenharmony_ci     */
602e1051a39Sopenharmony_ci    if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0)
603e1051a39Sopenharmony_ci            || !WPACKET_put_bytes_u16(&pkt, outlen)
604e1051a39Sopenharmony_ci            || !WPACKET_start_sub_packet_u8(&pkt)
605e1051a39Sopenharmony_ci            || !WPACKET_memcpy(&pkt, prefix, prefixlen)
606e1051a39Sopenharmony_ci            || !WPACKET_memcpy(&pkt, label, labellen)
607e1051a39Sopenharmony_ci            || !WPACKET_close(&pkt)
608e1051a39Sopenharmony_ci            || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen)
609e1051a39Sopenharmony_ci            || !WPACKET_get_total_written(&pkt, &hkdflabellen)
610e1051a39Sopenharmony_ci            || !WPACKET_finish(&pkt)) {
611e1051a39Sopenharmony_ci        WPACKET_cleanup(&pkt);
612e1051a39Sopenharmony_ci        return 0;
613e1051a39Sopenharmony_ci    }
614e1051a39Sopenharmony_ci
615e1051a39Sopenharmony_ci    return HKDF_Expand(md, key, keylen, hkdflabel, hkdflabellen,
616e1051a39Sopenharmony_ci                       out, outlen);
617e1051a39Sopenharmony_ci}
618e1051a39Sopenharmony_ci
619e1051a39Sopenharmony_cistatic int prov_tls13_hkdf_generate_secret(OSSL_LIB_CTX *libctx,
620e1051a39Sopenharmony_ci                                           const EVP_MD *md,
621e1051a39Sopenharmony_ci                                           const unsigned char *prevsecret,
622e1051a39Sopenharmony_ci                                           size_t prevsecretlen,
623e1051a39Sopenharmony_ci                                           const unsigned char *insecret,
624e1051a39Sopenharmony_ci                                           size_t insecretlen,
625e1051a39Sopenharmony_ci                                           const unsigned char *prefix,
626e1051a39Sopenharmony_ci                                           size_t prefixlen,
627e1051a39Sopenharmony_ci                                           const unsigned char *label,
628e1051a39Sopenharmony_ci                                           size_t labellen,
629e1051a39Sopenharmony_ci                                           unsigned char *out, size_t outlen)
630e1051a39Sopenharmony_ci{
631e1051a39Sopenharmony_ci    size_t mdlen;
632e1051a39Sopenharmony_ci    int ret;
633e1051a39Sopenharmony_ci    unsigned char preextractsec[EVP_MAX_MD_SIZE];
634e1051a39Sopenharmony_ci    /* Always filled with zeros */
635e1051a39Sopenharmony_ci    static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
636e1051a39Sopenharmony_ci
637e1051a39Sopenharmony_ci    ret = EVP_MD_get_size(md);
638e1051a39Sopenharmony_ci    /* Ensure cast to size_t is safe */
639e1051a39Sopenharmony_ci    if (ret <= 0)
640e1051a39Sopenharmony_ci        return 0;
641e1051a39Sopenharmony_ci    mdlen = (size_t)ret;
642e1051a39Sopenharmony_ci
643e1051a39Sopenharmony_ci    if (insecret == NULL) {
644e1051a39Sopenharmony_ci        insecret = default_zeros;
645e1051a39Sopenharmony_ci        insecretlen = mdlen;
646e1051a39Sopenharmony_ci    }
647e1051a39Sopenharmony_ci    if (prevsecret == NULL) {
648e1051a39Sopenharmony_ci        prevsecret = default_zeros;
649e1051a39Sopenharmony_ci        prevsecretlen = 0;
650e1051a39Sopenharmony_ci    } else {
651e1051a39Sopenharmony_ci        EVP_MD_CTX *mctx = EVP_MD_CTX_new();
652e1051a39Sopenharmony_ci        unsigned char hash[EVP_MAX_MD_SIZE];
653e1051a39Sopenharmony_ci
654e1051a39Sopenharmony_ci        /* The pre-extract derive step uses a hash of no messages */
655e1051a39Sopenharmony_ci        if (mctx == NULL
656e1051a39Sopenharmony_ci                || EVP_DigestInit_ex(mctx, md, NULL) <= 0
657e1051a39Sopenharmony_ci                || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
658e1051a39Sopenharmony_ci            EVP_MD_CTX_free(mctx);
659e1051a39Sopenharmony_ci            return 0;
660e1051a39Sopenharmony_ci        }
661e1051a39Sopenharmony_ci        EVP_MD_CTX_free(mctx);
662e1051a39Sopenharmony_ci
663e1051a39Sopenharmony_ci        /* Generate the pre-extract secret */
664e1051a39Sopenharmony_ci        if (!prov_tls13_hkdf_expand(md, prevsecret, prevsecretlen,
665e1051a39Sopenharmony_ci                                    prefix, prefixlen, label, labellen,
666e1051a39Sopenharmony_ci                                    hash, mdlen, preextractsec, mdlen))
667e1051a39Sopenharmony_ci            return 0;
668e1051a39Sopenharmony_ci        prevsecret = preextractsec;
669e1051a39Sopenharmony_ci        prevsecretlen = mdlen;
670e1051a39Sopenharmony_ci    }
671e1051a39Sopenharmony_ci
672e1051a39Sopenharmony_ci    ret = HKDF_Extract(libctx, md, prevsecret, prevsecretlen,
673e1051a39Sopenharmony_ci                       insecret, insecretlen, out, outlen);
674e1051a39Sopenharmony_ci
675e1051a39Sopenharmony_ci    if (prevsecret == preextractsec)
676e1051a39Sopenharmony_ci        OPENSSL_cleanse(preextractsec, mdlen);
677e1051a39Sopenharmony_ci    return ret;
678e1051a39Sopenharmony_ci}
679e1051a39Sopenharmony_ci
680e1051a39Sopenharmony_cistatic int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen,
681e1051a39Sopenharmony_ci                             const OSSL_PARAM params[])
682e1051a39Sopenharmony_ci{
683e1051a39Sopenharmony_ci    KDF_HKDF *ctx = (KDF_HKDF *)vctx;
684e1051a39Sopenharmony_ci    const EVP_MD *md;
685e1051a39Sopenharmony_ci
686e1051a39Sopenharmony_ci    if (!ossl_prov_is_running() || !kdf_tls1_3_set_ctx_params(ctx, params))
687e1051a39Sopenharmony_ci        return 0;
688e1051a39Sopenharmony_ci
689e1051a39Sopenharmony_ci    md = ossl_prov_digest_md(&ctx->digest);
690e1051a39Sopenharmony_ci    if (md == NULL) {
691e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
692e1051a39Sopenharmony_ci        return 0;
693e1051a39Sopenharmony_ci    }
694e1051a39Sopenharmony_ci
695e1051a39Sopenharmony_ci    switch (ctx->mode) {
696e1051a39Sopenharmony_ci    default:
697e1051a39Sopenharmony_ci        return 0;
698e1051a39Sopenharmony_ci
699e1051a39Sopenharmony_ci    case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
700e1051a39Sopenharmony_ci        return prov_tls13_hkdf_generate_secret(PROV_LIBCTX_OF(ctx->provctx),
701e1051a39Sopenharmony_ci                                               md,
702e1051a39Sopenharmony_ci                                               ctx->salt, ctx->salt_len,
703e1051a39Sopenharmony_ci                                               ctx->key, ctx->key_len,
704e1051a39Sopenharmony_ci                                               ctx->prefix, ctx->prefix_len,
705e1051a39Sopenharmony_ci                                               ctx->label, ctx->label_len,
706e1051a39Sopenharmony_ci                                               key, keylen);
707e1051a39Sopenharmony_ci
708e1051a39Sopenharmony_ci    case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
709e1051a39Sopenharmony_ci        return prov_tls13_hkdf_expand(md, ctx->key, ctx->key_len,
710e1051a39Sopenharmony_ci                                      ctx->prefix, ctx->prefix_len,
711e1051a39Sopenharmony_ci                                      ctx->label, ctx->label_len,
712e1051a39Sopenharmony_ci                                      ctx->data, ctx->data_len,
713e1051a39Sopenharmony_ci                                      key, keylen);
714e1051a39Sopenharmony_ci    }
715e1051a39Sopenharmony_ci}
716e1051a39Sopenharmony_ci
717e1051a39Sopenharmony_cistatic int kdf_tls1_3_set_ctx_params(void *vctx, const OSSL_PARAM params[])
718e1051a39Sopenharmony_ci{
719e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
720e1051a39Sopenharmony_ci    KDF_HKDF *ctx = vctx;
721e1051a39Sopenharmony_ci
722e1051a39Sopenharmony_ci    if (params == NULL)
723e1051a39Sopenharmony_ci        return 1;
724e1051a39Sopenharmony_ci
725e1051a39Sopenharmony_ci    if (!hkdf_common_set_ctx_params(ctx, params))
726e1051a39Sopenharmony_ci        return 0;
727e1051a39Sopenharmony_ci
728e1051a39Sopenharmony_ci    if (ctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND) {
729e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
730e1051a39Sopenharmony_ci        return 0;
731e1051a39Sopenharmony_ci    }
732e1051a39Sopenharmony_ci
733e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PREFIX)) != NULL) {
734e1051a39Sopenharmony_ci        OPENSSL_free(ctx->prefix);
735e1051a39Sopenharmony_ci        ctx->prefix = NULL;
736e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->prefix, 0,
737e1051a39Sopenharmony_ci                                         &ctx->prefix_len))
738e1051a39Sopenharmony_ci            return 0;
739e1051a39Sopenharmony_ci    }
740e1051a39Sopenharmony_ci
741e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_LABEL)) != NULL) {
742e1051a39Sopenharmony_ci        OPENSSL_free(ctx->label);
743e1051a39Sopenharmony_ci        ctx->label = NULL;
744e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->label, 0,
745e1051a39Sopenharmony_ci                                         &ctx->label_len))
746e1051a39Sopenharmony_ci            return 0;
747e1051a39Sopenharmony_ci    }
748e1051a39Sopenharmony_ci
749e1051a39Sopenharmony_ci    OPENSSL_clear_free(ctx->data, ctx->data_len);
750e1051a39Sopenharmony_ci    ctx->data = NULL;
751e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DATA)) != NULL
752e1051a39Sopenharmony_ci            && !OSSL_PARAM_get_octet_string(p, (void **)&ctx->data, 0,
753e1051a39Sopenharmony_ci                                            &ctx->data_len))
754e1051a39Sopenharmony_ci        return 0;
755e1051a39Sopenharmony_ci    return 1;
756e1051a39Sopenharmony_ci}
757e1051a39Sopenharmony_ci
758e1051a39Sopenharmony_cistatic const OSSL_PARAM *kdf_tls1_3_settable_ctx_params(ossl_unused void *ctx,
759e1051a39Sopenharmony_ci                                                        ossl_unused void *provctx)
760e1051a39Sopenharmony_ci{
761e1051a39Sopenharmony_ci    static const OSSL_PARAM known_settable_ctx_params[] = {
762e1051a39Sopenharmony_ci        HKDF_COMMON_SETTABLES,
763e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PREFIX, NULL, 0),
764e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_LABEL, NULL, 0),
765e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_DATA, NULL, 0),
766e1051a39Sopenharmony_ci        OSSL_PARAM_END
767e1051a39Sopenharmony_ci    };
768e1051a39Sopenharmony_ci    return known_settable_ctx_params;
769e1051a39Sopenharmony_ci}
770e1051a39Sopenharmony_ci
771e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[] = {
772e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
773e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
774e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
775e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_3_derive },
776e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
777e1051a39Sopenharmony_ci      (void(*)(void))kdf_tls1_3_settable_ctx_params },
778e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_tls1_3_set_ctx_params },
779e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
780e1051a39Sopenharmony_ci      (void(*)(void))kdf_hkdf_gettable_ctx_params },
781e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params },
782e1051a39Sopenharmony_ci    { 0, NULL }
783e1051a39Sopenharmony_ci};
784