1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2016-2022 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 * Refer to "The TLS Protocol Version 1.0" Section 5
12e1051a39Sopenharmony_ci * (https://tools.ietf.org/html/rfc2246#section-5) and
13e1051a39Sopenharmony_ci * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
14e1051a39Sopenharmony_ci * (https://tools.ietf.org/html/rfc5246#section-5).
15e1051a39Sopenharmony_ci *
16e1051a39Sopenharmony_ci * For TLS v1.0 and TLS v1.1 the TLS PRF algorithm is given by:
17e1051a39Sopenharmony_ci *
18e1051a39Sopenharmony_ci *   PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
19e1051a39Sopenharmony_ci *                              P_SHA-1(S2, label + seed)
20e1051a39Sopenharmony_ci *
21e1051a39Sopenharmony_ci * where P_MD5 and P_SHA-1 are defined by P_<hash>, below, and S1 and S2 are
22e1051a39Sopenharmony_ci * two halves of the secret (with the possibility of one shared byte, in the
23e1051a39Sopenharmony_ci * case where the length of the original secret is odd).  S1 is taken from the
24e1051a39Sopenharmony_ci * first half of the secret, S2 from the second half.
25e1051a39Sopenharmony_ci *
26e1051a39Sopenharmony_ci * For TLS v1.2 the TLS PRF algorithm is given by:
27e1051a39Sopenharmony_ci *
28e1051a39Sopenharmony_ci *   PRF(secret, label, seed) = P_<hash>(secret, label + seed)
29e1051a39Sopenharmony_ci *
30e1051a39Sopenharmony_ci * where hash is SHA-256 for all cipher suites defined in RFC 5246 as well as
31e1051a39Sopenharmony_ci * those published prior to TLS v1.2 while the TLS v1.2 protocol is in effect,
32e1051a39Sopenharmony_ci * unless defined otherwise by the cipher suite.
33e1051a39Sopenharmony_ci *
34e1051a39Sopenharmony_ci * P_<hash> is an expansion function that uses a single hash function to expand
35e1051a39Sopenharmony_ci * a secret and seed into an arbitrary quantity of output:
36e1051a39Sopenharmony_ci *
37e1051a39Sopenharmony_ci *   P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
38e1051a39Sopenharmony_ci *                            HMAC_<hash>(secret, A(2) + seed) +
39e1051a39Sopenharmony_ci *                            HMAC_<hash>(secret, A(3) + seed) + ...
40e1051a39Sopenharmony_ci *
41e1051a39Sopenharmony_ci * where + indicates concatenation.  P_<hash> can be iterated as many times as
42e1051a39Sopenharmony_ci * is necessary to produce the required quantity of data.
43e1051a39Sopenharmony_ci *
44e1051a39Sopenharmony_ci * A(i) is defined as:
45e1051a39Sopenharmony_ci *     A(0) = seed
46e1051a39Sopenharmony_ci *     A(i) = HMAC_<hash>(secret, A(i-1))
47e1051a39Sopenharmony_ci */
48e1051a39Sopenharmony_ci#include <stdio.h>
49e1051a39Sopenharmony_ci#include <stdarg.h>
50e1051a39Sopenharmony_ci#include <string.h>
51e1051a39Sopenharmony_ci#include <openssl/evp.h>
52e1051a39Sopenharmony_ci#include <openssl/kdf.h>
53e1051a39Sopenharmony_ci#include <openssl/core_names.h>
54e1051a39Sopenharmony_ci#include <openssl/params.h>
55e1051a39Sopenharmony_ci#include <openssl/proverr.h>
56e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
57e1051a39Sopenharmony_ci#include "internal/numbers.h"
58e1051a39Sopenharmony_ci#include "crypto/evp.h"
59e1051a39Sopenharmony_ci#include "prov/provider_ctx.h"
60e1051a39Sopenharmony_ci#include "prov/providercommon.h"
61e1051a39Sopenharmony_ci#include "prov/implementations.h"
62e1051a39Sopenharmony_ci#include "prov/provider_util.h"
63e1051a39Sopenharmony_ci#include "e_os.h"
64e1051a39Sopenharmony_ci
65e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_newctx_fn kdf_tls1_prf_new;
66e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_freectx_fn kdf_tls1_prf_free;
67e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_reset_fn kdf_tls1_prf_reset;
68e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_derive_fn kdf_tls1_prf_derive;
69e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params;
70e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_prf_set_ctx_params;
71e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_tls1_prf_gettable_ctx_params;
72e1051a39Sopenharmony_cistatic OSSL_FUNC_kdf_get_ctx_params_fn kdf_tls1_prf_get_ctx_params;
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_cistatic int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx,
75e1051a39Sopenharmony_ci                        const unsigned char *sec, size_t slen,
76e1051a39Sopenharmony_ci                        const unsigned char *seed, size_t seed_len,
77e1051a39Sopenharmony_ci                        unsigned char *out, size_t olen);
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci#define TLS1_PRF_MAXBUF 1024
80e1051a39Sopenharmony_ci
81e1051a39Sopenharmony_ci/* TLS KDF kdf context structure */
82e1051a39Sopenharmony_citypedef struct {
83e1051a39Sopenharmony_ci    void *provctx;
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ci    /* MAC context for the main digest */
86e1051a39Sopenharmony_ci    EVP_MAC_CTX *P_hash;
87e1051a39Sopenharmony_ci    /* MAC context for SHA1 for the MD5/SHA-1 combined PRF */
88e1051a39Sopenharmony_ci    EVP_MAC_CTX *P_sha1;
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ci    /* Secret value to use for PRF */
91e1051a39Sopenharmony_ci    unsigned char *sec;
92e1051a39Sopenharmony_ci    size_t seclen;
93e1051a39Sopenharmony_ci    /* Buffer of concatenated seed data */
94e1051a39Sopenharmony_ci    unsigned char seed[TLS1_PRF_MAXBUF];
95e1051a39Sopenharmony_ci    size_t seedlen;
96e1051a39Sopenharmony_ci} TLS1_PRF;
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_cistatic void *kdf_tls1_prf_new(void *provctx)
99e1051a39Sopenharmony_ci{
100e1051a39Sopenharmony_ci    TLS1_PRF *ctx;
101e1051a39Sopenharmony_ci
102e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
103e1051a39Sopenharmony_ci        return NULL;
104e1051a39Sopenharmony_ci
105e1051a39Sopenharmony_ci    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
106e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
107e1051a39Sopenharmony_ci        return NULL;
108e1051a39Sopenharmony_ci    }
109e1051a39Sopenharmony_ci    ctx->provctx = provctx;
110e1051a39Sopenharmony_ci    return ctx;
111e1051a39Sopenharmony_ci}
112e1051a39Sopenharmony_ci
113e1051a39Sopenharmony_cistatic void kdf_tls1_prf_free(void *vctx)
114e1051a39Sopenharmony_ci{
115e1051a39Sopenharmony_ci    TLS1_PRF *ctx = (TLS1_PRF *)vctx;
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ci    if (ctx != NULL) {
118e1051a39Sopenharmony_ci        kdf_tls1_prf_reset(ctx);
119e1051a39Sopenharmony_ci        OPENSSL_free(ctx);
120e1051a39Sopenharmony_ci    }
121e1051a39Sopenharmony_ci}
122e1051a39Sopenharmony_ci
123e1051a39Sopenharmony_cistatic void kdf_tls1_prf_reset(void *vctx)
124e1051a39Sopenharmony_ci{
125e1051a39Sopenharmony_ci    TLS1_PRF *ctx = (TLS1_PRF *)vctx;
126e1051a39Sopenharmony_ci    void *provctx = ctx->provctx;
127e1051a39Sopenharmony_ci
128e1051a39Sopenharmony_ci    EVP_MAC_CTX_free(ctx->P_hash);
129e1051a39Sopenharmony_ci    EVP_MAC_CTX_free(ctx->P_sha1);
130e1051a39Sopenharmony_ci    OPENSSL_clear_free(ctx->sec, ctx->seclen);
131e1051a39Sopenharmony_ci    OPENSSL_cleanse(ctx->seed, ctx->seedlen);
132e1051a39Sopenharmony_ci    memset(ctx, 0, sizeof(*ctx));
133e1051a39Sopenharmony_ci    ctx->provctx = provctx;
134e1051a39Sopenharmony_ci}
135e1051a39Sopenharmony_ci
136e1051a39Sopenharmony_cistatic int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen,
137e1051a39Sopenharmony_ci                               const OSSL_PARAM params[])
138e1051a39Sopenharmony_ci{
139e1051a39Sopenharmony_ci    TLS1_PRF *ctx = (TLS1_PRF *)vctx;
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_ci    if (!ossl_prov_is_running() || !kdf_tls1_prf_set_ctx_params(ctx, params))
142e1051a39Sopenharmony_ci        return 0;
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ci    if (ctx->P_hash == NULL) {
145e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
146e1051a39Sopenharmony_ci        return 0;
147e1051a39Sopenharmony_ci    }
148e1051a39Sopenharmony_ci    if (ctx->sec == NULL) {
149e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
150e1051a39Sopenharmony_ci        return 0;
151e1051a39Sopenharmony_ci    }
152e1051a39Sopenharmony_ci    if (ctx->seedlen == 0) {
153e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SEED);
154e1051a39Sopenharmony_ci        return 0;
155e1051a39Sopenharmony_ci    }
156e1051a39Sopenharmony_ci    if (keylen == 0) {
157e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
158e1051a39Sopenharmony_ci        return 0;
159e1051a39Sopenharmony_ci    }
160e1051a39Sopenharmony_ci
161e1051a39Sopenharmony_ci    return tls1_prf_alg(ctx->P_hash, ctx->P_sha1,
162e1051a39Sopenharmony_ci                        ctx->sec, ctx->seclen,
163e1051a39Sopenharmony_ci                        ctx->seed, ctx->seedlen,
164e1051a39Sopenharmony_ci                        key, keylen);
165e1051a39Sopenharmony_ci}
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_cistatic int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
168e1051a39Sopenharmony_ci{
169e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
170e1051a39Sopenharmony_ci    TLS1_PRF *ctx = vctx;
171e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci    if (params == NULL)
174e1051a39Sopenharmony_ci        return 1;
175e1051a39Sopenharmony_ci
176e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
177e1051a39Sopenharmony_ci        if (OPENSSL_strcasecmp(p->data, SN_md5_sha1) == 0) {
178e1051a39Sopenharmony_ci            if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
179e1051a39Sopenharmony_ci                                                   OSSL_MAC_NAME_HMAC,
180e1051a39Sopenharmony_ci                                                   NULL, SN_md5, libctx)
181e1051a39Sopenharmony_ci                || !ossl_prov_macctx_load_from_params(&ctx->P_sha1, params,
182e1051a39Sopenharmony_ci                                                      OSSL_MAC_NAME_HMAC,
183e1051a39Sopenharmony_ci                                                      NULL, SN_sha1, libctx))
184e1051a39Sopenharmony_ci                return 0;
185e1051a39Sopenharmony_ci        } else {
186e1051a39Sopenharmony_ci            EVP_MAC_CTX_free(ctx->P_sha1);
187e1051a39Sopenharmony_ci            if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
188e1051a39Sopenharmony_ci                                                   OSSL_MAC_NAME_HMAC,
189e1051a39Sopenharmony_ci                                                   NULL, NULL, libctx))
190e1051a39Sopenharmony_ci                return 0;
191e1051a39Sopenharmony_ci        }
192e1051a39Sopenharmony_ci    }
193e1051a39Sopenharmony_ci
194e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL) {
195e1051a39Sopenharmony_ci        OPENSSL_clear_free(ctx->sec, ctx->seclen);
196e1051a39Sopenharmony_ci        ctx->sec = NULL;
197e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->sec, 0, &ctx->seclen))
198e1051a39Sopenharmony_ci            return 0;
199e1051a39Sopenharmony_ci    }
200e1051a39Sopenharmony_ci    /* The seed fields concatenate, so process them all */
201e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED)) != NULL) {
202e1051a39Sopenharmony_ci        for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1,
203e1051a39Sopenharmony_ci                                                      OSSL_KDF_PARAM_SEED)) {
204e1051a39Sopenharmony_ci            const void *q = ctx->seed + ctx->seedlen;
205e1051a39Sopenharmony_ci            size_t sz = 0;
206e1051a39Sopenharmony_ci
207e1051a39Sopenharmony_ci            if (p->data_size != 0
208e1051a39Sopenharmony_ci                && p->data != NULL
209e1051a39Sopenharmony_ci                && !OSSL_PARAM_get_octet_string(p, (void **)&q,
210e1051a39Sopenharmony_ci                                                TLS1_PRF_MAXBUF - ctx->seedlen,
211e1051a39Sopenharmony_ci                                                &sz))
212e1051a39Sopenharmony_ci                return 0;
213e1051a39Sopenharmony_ci            ctx->seedlen += sz;
214e1051a39Sopenharmony_ci        }
215e1051a39Sopenharmony_ci    }
216e1051a39Sopenharmony_ci    return 1;
217e1051a39Sopenharmony_ci}
218e1051a39Sopenharmony_ci
219e1051a39Sopenharmony_cistatic const OSSL_PARAM *kdf_tls1_prf_settable_ctx_params(
220e1051a39Sopenharmony_ci        ossl_unused void *ctx, ossl_unused void *provctx)
221e1051a39Sopenharmony_ci{
222e1051a39Sopenharmony_ci    static const OSSL_PARAM known_settable_ctx_params[] = {
223e1051a39Sopenharmony_ci        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
224e1051a39Sopenharmony_ci        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
225e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0),
226e1051a39Sopenharmony_ci        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0),
227e1051a39Sopenharmony_ci        OSSL_PARAM_END
228e1051a39Sopenharmony_ci    };
229e1051a39Sopenharmony_ci    return known_settable_ctx_params;
230e1051a39Sopenharmony_ci}
231e1051a39Sopenharmony_ci
232e1051a39Sopenharmony_cistatic int kdf_tls1_prf_get_ctx_params(void *vctx, OSSL_PARAM params[])
233e1051a39Sopenharmony_ci{
234e1051a39Sopenharmony_ci    OSSL_PARAM *p;
235e1051a39Sopenharmony_ci
236e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
237e1051a39Sopenharmony_ci        return OSSL_PARAM_set_size_t(p, SIZE_MAX);
238e1051a39Sopenharmony_ci    return -2;
239e1051a39Sopenharmony_ci}
240e1051a39Sopenharmony_ci
241e1051a39Sopenharmony_cistatic const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params(
242e1051a39Sopenharmony_ci        ossl_unused void *ctx, ossl_unused void *provctx)
243e1051a39Sopenharmony_ci{
244e1051a39Sopenharmony_ci    static const OSSL_PARAM known_gettable_ctx_params[] = {
245e1051a39Sopenharmony_ci        OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
246e1051a39Sopenharmony_ci        OSSL_PARAM_END
247e1051a39Sopenharmony_ci    };
248e1051a39Sopenharmony_ci    return known_gettable_ctx_params;
249e1051a39Sopenharmony_ci}
250e1051a39Sopenharmony_ci
251e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_kdf_tls1_prf_functions[] = {
252e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_tls1_prf_new },
253e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_tls1_prf_free },
254e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_tls1_prf_reset },
255e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_prf_derive },
256e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
257e1051a39Sopenharmony_ci      (void(*)(void))kdf_tls1_prf_settable_ctx_params },
258e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_SET_CTX_PARAMS,
259e1051a39Sopenharmony_ci      (void(*)(void))kdf_tls1_prf_set_ctx_params },
260e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
261e1051a39Sopenharmony_ci      (void(*)(void))kdf_tls1_prf_gettable_ctx_params },
262e1051a39Sopenharmony_ci    { OSSL_FUNC_KDF_GET_CTX_PARAMS,
263e1051a39Sopenharmony_ci      (void(*)(void))kdf_tls1_prf_get_ctx_params },
264e1051a39Sopenharmony_ci    { 0, NULL }
265e1051a39Sopenharmony_ci};
266e1051a39Sopenharmony_ci
267e1051a39Sopenharmony_ci/*
268e1051a39Sopenharmony_ci * Refer to "The TLS Protocol Version 1.0" Section 5
269e1051a39Sopenharmony_ci * (https://tools.ietf.org/html/rfc2246#section-5) and
270e1051a39Sopenharmony_ci * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
271e1051a39Sopenharmony_ci * (https://tools.ietf.org/html/rfc5246#section-5).
272e1051a39Sopenharmony_ci *
273e1051a39Sopenharmony_ci * P_<hash> is an expansion function that uses a single hash function to expand
274e1051a39Sopenharmony_ci * a secret and seed into an arbitrary quantity of output:
275e1051a39Sopenharmony_ci *
276e1051a39Sopenharmony_ci *   P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
277e1051a39Sopenharmony_ci *                            HMAC_<hash>(secret, A(2) + seed) +
278e1051a39Sopenharmony_ci *                            HMAC_<hash>(secret, A(3) + seed) + ...
279e1051a39Sopenharmony_ci *
280e1051a39Sopenharmony_ci * where + indicates concatenation.  P_<hash> can be iterated as many times as
281e1051a39Sopenharmony_ci * is necessary to produce the required quantity of data.
282e1051a39Sopenharmony_ci *
283e1051a39Sopenharmony_ci * A(i) is defined as:
284e1051a39Sopenharmony_ci *     A(0) = seed
285e1051a39Sopenharmony_ci *     A(i) = HMAC_<hash>(secret, A(i-1))
286e1051a39Sopenharmony_ci */
287e1051a39Sopenharmony_cistatic int tls1_prf_P_hash(EVP_MAC_CTX *ctx_init,
288e1051a39Sopenharmony_ci                           const unsigned char *sec, size_t sec_len,
289e1051a39Sopenharmony_ci                           const unsigned char *seed, size_t seed_len,
290e1051a39Sopenharmony_ci                           unsigned char *out, size_t olen)
291e1051a39Sopenharmony_ci{
292e1051a39Sopenharmony_ci    size_t chunk;
293e1051a39Sopenharmony_ci    EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL;
294e1051a39Sopenharmony_ci    unsigned char Ai[EVP_MAX_MD_SIZE];
295e1051a39Sopenharmony_ci    size_t Ai_len;
296e1051a39Sopenharmony_ci    int ret = 0;
297e1051a39Sopenharmony_ci
298e1051a39Sopenharmony_ci    if (!EVP_MAC_init(ctx_init, sec, sec_len, NULL))
299e1051a39Sopenharmony_ci        goto err;
300e1051a39Sopenharmony_ci    chunk = EVP_MAC_CTX_get_mac_size(ctx_init);
301e1051a39Sopenharmony_ci    if (chunk == 0)
302e1051a39Sopenharmony_ci        goto err;
303e1051a39Sopenharmony_ci    /* A(0) = seed */
304e1051a39Sopenharmony_ci    ctx_Ai = EVP_MAC_CTX_dup(ctx_init);
305e1051a39Sopenharmony_ci    if (ctx_Ai == NULL)
306e1051a39Sopenharmony_ci        goto err;
307e1051a39Sopenharmony_ci    if (seed != NULL && !EVP_MAC_update(ctx_Ai, seed, seed_len))
308e1051a39Sopenharmony_ci        goto err;
309e1051a39Sopenharmony_ci
310e1051a39Sopenharmony_ci    for (;;) {
311e1051a39Sopenharmony_ci        /* calc: A(i) = HMAC_<hash>(secret, A(i-1)) */
312e1051a39Sopenharmony_ci        if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai)))
313e1051a39Sopenharmony_ci            goto err;
314e1051a39Sopenharmony_ci        EVP_MAC_CTX_free(ctx_Ai);
315e1051a39Sopenharmony_ci        ctx_Ai = NULL;
316e1051a39Sopenharmony_ci
317e1051a39Sopenharmony_ci        /* calc next chunk: HMAC_<hash>(secret, A(i) + seed) */
318e1051a39Sopenharmony_ci        ctx = EVP_MAC_CTX_dup(ctx_init);
319e1051a39Sopenharmony_ci        if (ctx == NULL)
320e1051a39Sopenharmony_ci            goto err;
321e1051a39Sopenharmony_ci        if (!EVP_MAC_update(ctx, Ai, Ai_len))
322e1051a39Sopenharmony_ci            goto err;
323e1051a39Sopenharmony_ci        /* save state for calculating next A(i) value */
324e1051a39Sopenharmony_ci        if (olen > chunk) {
325e1051a39Sopenharmony_ci            ctx_Ai = EVP_MAC_CTX_dup(ctx);
326e1051a39Sopenharmony_ci            if (ctx_Ai == NULL)
327e1051a39Sopenharmony_ci                goto err;
328e1051a39Sopenharmony_ci        }
329e1051a39Sopenharmony_ci        if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len))
330e1051a39Sopenharmony_ci            goto err;
331e1051a39Sopenharmony_ci        if (olen <= chunk) {
332e1051a39Sopenharmony_ci            /* last chunk - use Ai as temp bounce buffer */
333e1051a39Sopenharmony_ci            if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai)))
334e1051a39Sopenharmony_ci                goto err;
335e1051a39Sopenharmony_ci            memcpy(out, Ai, olen);
336e1051a39Sopenharmony_ci            break;
337e1051a39Sopenharmony_ci        }
338e1051a39Sopenharmony_ci        if (!EVP_MAC_final(ctx, out, NULL, olen))
339e1051a39Sopenharmony_ci            goto err;
340e1051a39Sopenharmony_ci        EVP_MAC_CTX_free(ctx);
341e1051a39Sopenharmony_ci        ctx = NULL;
342e1051a39Sopenharmony_ci        out += chunk;
343e1051a39Sopenharmony_ci        olen -= chunk;
344e1051a39Sopenharmony_ci    }
345e1051a39Sopenharmony_ci    ret = 1;
346e1051a39Sopenharmony_ci err:
347e1051a39Sopenharmony_ci    EVP_MAC_CTX_free(ctx);
348e1051a39Sopenharmony_ci    EVP_MAC_CTX_free(ctx_Ai);
349e1051a39Sopenharmony_ci    OPENSSL_cleanse(Ai, sizeof(Ai));
350e1051a39Sopenharmony_ci    return ret;
351e1051a39Sopenharmony_ci}
352e1051a39Sopenharmony_ci
353e1051a39Sopenharmony_ci/*
354e1051a39Sopenharmony_ci * Refer to "The TLS Protocol Version 1.0" Section 5
355e1051a39Sopenharmony_ci * (https://tools.ietf.org/html/rfc2246#section-5) and
356e1051a39Sopenharmony_ci * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
357e1051a39Sopenharmony_ci * (https://tools.ietf.org/html/rfc5246#section-5).
358e1051a39Sopenharmony_ci *
359e1051a39Sopenharmony_ci * For TLS v1.0 and TLS v1.1:
360e1051a39Sopenharmony_ci *
361e1051a39Sopenharmony_ci *   PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
362e1051a39Sopenharmony_ci *                              P_SHA-1(S2, label + seed)
363e1051a39Sopenharmony_ci *
364e1051a39Sopenharmony_ci * S1 is taken from the first half of the secret, S2 from the second half.
365e1051a39Sopenharmony_ci *
366e1051a39Sopenharmony_ci *   L_S = length in bytes of secret;
367e1051a39Sopenharmony_ci *   L_S1 = L_S2 = ceil(L_S / 2);
368e1051a39Sopenharmony_ci *
369e1051a39Sopenharmony_ci * For TLS v1.2:
370e1051a39Sopenharmony_ci *
371e1051a39Sopenharmony_ci *   PRF(secret, label, seed) = P_<hash>(secret, label + seed)
372e1051a39Sopenharmony_ci */
373e1051a39Sopenharmony_cistatic int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx,
374e1051a39Sopenharmony_ci                        const unsigned char *sec, size_t slen,
375e1051a39Sopenharmony_ci                        const unsigned char *seed, size_t seed_len,
376e1051a39Sopenharmony_ci                        unsigned char *out, size_t olen)
377e1051a39Sopenharmony_ci{
378e1051a39Sopenharmony_ci    if (sha1ctx != NULL) {
379e1051a39Sopenharmony_ci        /* TLS v1.0 and TLS v1.1 */
380e1051a39Sopenharmony_ci        size_t i;
381e1051a39Sopenharmony_ci        unsigned char *tmp;
382e1051a39Sopenharmony_ci        /* calc: L_S1 = L_S2 = ceil(L_S / 2) */
383e1051a39Sopenharmony_ci        size_t L_S1 = (slen + 1) / 2;
384e1051a39Sopenharmony_ci        size_t L_S2 = L_S1;
385e1051a39Sopenharmony_ci
386e1051a39Sopenharmony_ci        if (!tls1_prf_P_hash(mdctx, sec, L_S1,
387e1051a39Sopenharmony_ci                             seed, seed_len, out, olen))
388e1051a39Sopenharmony_ci            return 0;
389e1051a39Sopenharmony_ci
390e1051a39Sopenharmony_ci        if ((tmp = OPENSSL_malloc(olen)) == NULL) {
391e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
392e1051a39Sopenharmony_ci            return 0;
393e1051a39Sopenharmony_ci        }
394e1051a39Sopenharmony_ci
395e1051a39Sopenharmony_ci        if (!tls1_prf_P_hash(sha1ctx, sec + slen - L_S2, L_S2,
396e1051a39Sopenharmony_ci                             seed, seed_len, tmp, olen)) {
397e1051a39Sopenharmony_ci            OPENSSL_clear_free(tmp, olen);
398e1051a39Sopenharmony_ci            return 0;
399e1051a39Sopenharmony_ci        }
400e1051a39Sopenharmony_ci        for (i = 0; i < olen; i++)
401e1051a39Sopenharmony_ci            out[i] ^= tmp[i];
402e1051a39Sopenharmony_ci        OPENSSL_clear_free(tmp, olen);
403e1051a39Sopenharmony_ci        return 1;
404e1051a39Sopenharmony_ci    }
405e1051a39Sopenharmony_ci
406e1051a39Sopenharmony_ci    /* TLS v1.2 */
407e1051a39Sopenharmony_ci    if (!tls1_prf_P_hash(mdctx, sec, slen, seed, seed_len, out, olen))
408e1051a39Sopenharmony_ci        return 0;
409e1051a39Sopenharmony_ci
410e1051a39Sopenharmony_ci    return 1;
411e1051a39Sopenharmony_ci}
412