2 * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * Refer to "The TLS Protocol Version 1.0" Section 5
12 * (https://tools.ietf.org/html/rfc2246#section-5) and
13 * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
14 * (https://tools.ietf.org/html/rfc5246#section-5).
16 * For TLS v1.0 and TLS v1.1 the TLS PRF algorithm is given by:
18 * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
19 * P_SHA-1(S2, label + seed)
21 * where P_MD5 and P_SHA-1 are defined by P_<hash>, below, and S1 and S2 are
22 * two halves of the secret (with the possibility of one shared byte, in the
23 * case where the length of the original secret is odd). S1 is taken from the
24 * first half of the secret, S2 from the second half.
26 * For TLS v1.2 the TLS PRF algorithm is given by:
28 * PRF(secret, label, seed) = P_<hash>(secret, label + seed)
30 * where hash is SHA-256 for all cipher suites defined in RFC 5246 as well as
31 * those published prior to TLS v1.2 while the TLS v1.2 protocol is in effect,
32 * unless defined otherwise by the cipher suite.
34 * P_<hash> is an expansion function that uses a single hash function to expand
35 * a secret and seed into an arbitrary quantity of output:
37 * P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
38 * HMAC_<hash>(secret, A(2) + seed) +
39 * HMAC_<hash>(secret, A(3) + seed) + ...
41 * where + indicates concatenation. P_<hash> can be iterated as many times as
42 * is necessary to produce the required quantity of data.
46 * A(i) = HMAC_<hash>(secret, A(i-1))
50 * Low level APIs (such as DH) are deprecated for public use, but still ok for
53 #include "internal/deprecated.h"
58 #include <openssl/evp.h>
59 #include <openssl/kdf.h>
60 #include <openssl/core_names.h>
61 #include <openssl/params.h>
62 #include <openssl/proverr.h>
63 #include "internal/cryptlib.h"
64 #include "internal/numbers.h"
65 #include "crypto/evp.h"
66 #include "prov/provider_ctx.h"
67 #include "prov/providercommon.h"
68 #include "prov/implementations.h"
69 #include "prov/provider_util.h"
70 #include "prov/securitycheck.h"
71 #include "internal/e_os.h"
73 static OSSL_FUNC_kdf_newctx_fn kdf_tls1_prf_new
;
74 static OSSL_FUNC_kdf_dupctx_fn kdf_tls1_prf_dup
;
75 static OSSL_FUNC_kdf_freectx_fn kdf_tls1_prf_free
;
76 static OSSL_FUNC_kdf_reset_fn kdf_tls1_prf_reset
;
77 static OSSL_FUNC_kdf_derive_fn kdf_tls1_prf_derive
;
78 static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params
;
79 static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_prf_set_ctx_params
;
80 static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_tls1_prf_gettable_ctx_params
;
81 static OSSL_FUNC_kdf_get_ctx_params_fn kdf_tls1_prf_get_ctx_params
;
83 static int tls1_prf_alg(EVP_MAC_CTX
*mdctx
, EVP_MAC_CTX
*sha1ctx
,
84 const unsigned char *sec
, size_t slen
,
85 const unsigned char *seed
, size_t seed_len
,
86 unsigned char *out
, size_t olen
);
88 #define TLS1_PRF_MAXBUF 1024
89 #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"
90 #define TLS_MD_MASTER_SECRET_CONST_SIZE 13
92 /* TLS KDF kdf context structure */
96 /* MAC context for the main digest */
98 /* MAC context for SHA1 for the MD5/SHA-1 combined PRF */
101 /* Secret value to use for PRF */
104 /* Buffer of concatenated seed data */
105 unsigned char seed
[TLS1_PRF_MAXBUF
];
109 static void *kdf_tls1_prf_new(void *provctx
)
113 if (!ossl_prov_is_running())
116 if ((ctx
= OPENSSL_zalloc(sizeof(*ctx
))) != NULL
)
117 ctx
->provctx
= provctx
;
121 static void kdf_tls1_prf_free(void *vctx
)
123 TLS1_PRF
*ctx
= (TLS1_PRF
*)vctx
;
126 kdf_tls1_prf_reset(ctx
);
131 static void kdf_tls1_prf_reset(void *vctx
)
133 TLS1_PRF
*ctx
= (TLS1_PRF
*)vctx
;
134 void *provctx
= ctx
->provctx
;
136 EVP_MAC_CTX_free(ctx
->P_hash
);
137 EVP_MAC_CTX_free(ctx
->P_sha1
);
138 OPENSSL_clear_free(ctx
->sec
, ctx
->seclen
);
139 OPENSSL_cleanse(ctx
->seed
, ctx
->seedlen
);
140 memset(ctx
, 0, sizeof(*ctx
));
141 ctx
->provctx
= provctx
;
144 static void *kdf_tls1_prf_dup(void *vctx
)
146 const TLS1_PRF
*src
= (const TLS1_PRF
*)vctx
;
149 dest
= kdf_tls1_prf_new(src
->provctx
);
151 if (src
->P_hash
!= NULL
152 && (dest
->P_hash
= EVP_MAC_CTX_dup(src
->P_hash
)) == NULL
)
154 if (src
->P_sha1
!= NULL
155 && (dest
->P_sha1
= EVP_MAC_CTX_dup(src
->P_sha1
)) == NULL
)
157 if (!ossl_prov_memdup(src
->sec
, src
->seclen
, &dest
->sec
, &dest
->seclen
))
159 memcpy(dest
->seed
, src
->seed
, src
->seedlen
);
160 dest
->seedlen
= src
->seedlen
;
165 kdf_tls1_prf_free(dest
);
169 static int kdf_tls1_prf_derive(void *vctx
, unsigned char *key
, size_t keylen
,
170 const OSSL_PARAM params
[])
172 TLS1_PRF
*ctx
= (TLS1_PRF
*)vctx
;
173 OSSL_LIB_CTX
*libctx
= PROV_LIBCTX_OF(ctx
->provctx
);
175 if (!ossl_prov_is_running() || !kdf_tls1_prf_set_ctx_params(ctx
, params
))
178 if (ctx
->P_hash
== NULL
) {
179 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_MESSAGE_DIGEST
);
182 if (ctx
->sec
== NULL
) {
183 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_SECRET
);
186 if (ctx
->seedlen
== 0) {
187 ERR_raise(ERR_LIB_PROV
, PROV_R_MISSING_SEED
);
191 ERR_raise(ERR_LIB_PROV
, PROV_R_INVALID_KEY_LENGTH
);
196 * The seed buffer is prepended with a label.
197 * If EMS mode is enforced then the label "master secret" is not allowed,
198 * We do the check this way since the PRF is used for other purposes, as well
199 * as "extended master secret".
201 if (ossl_tls1_prf_ems_check_enabled(libctx
)) {
202 if (ctx
->seedlen
>= TLS_MD_MASTER_SECRET_CONST_SIZE
203 && memcmp(ctx
->seed
, TLS_MD_MASTER_SECRET_CONST
,
204 TLS_MD_MASTER_SECRET_CONST_SIZE
) == 0) {
205 ERR_raise(ERR_LIB_PROV
, PROV_R_EMS_NOT_ENABLED
);
210 return tls1_prf_alg(ctx
->P_hash
, ctx
->P_sha1
,
211 ctx
->sec
, ctx
->seclen
,
212 ctx
->seed
, ctx
->seedlen
,
216 static int kdf_tls1_prf_set_ctx_params(void *vctx
, const OSSL_PARAM params
[])
219 TLS1_PRF
*ctx
= vctx
;
220 OSSL_LIB_CTX
*libctx
= PROV_LIBCTX_OF(ctx
->provctx
);
225 if ((p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_DIGEST
)) != NULL
) {
226 if (OPENSSL_strcasecmp(p
->data
, SN_md5_sha1
) == 0) {
227 if (!ossl_prov_macctx_load_from_params(&ctx
->P_hash
, params
,
229 NULL
, SN_md5
, libctx
)
230 || !ossl_prov_macctx_load_from_params(&ctx
->P_sha1
, params
,
232 NULL
, SN_sha1
, libctx
))
235 EVP_MAC_CTX_free(ctx
->P_sha1
);
236 if (!ossl_prov_macctx_load_from_params(&ctx
->P_hash
, params
,
243 if ((p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_SECRET
)) != NULL
) {
244 OPENSSL_clear_free(ctx
->sec
, ctx
->seclen
);
246 if (!OSSL_PARAM_get_octet_string(p
, (void **)&ctx
->sec
, 0, &ctx
->seclen
))
249 /* The seed fields concatenate, so process them all */
250 if ((p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_SEED
)) != NULL
) {
251 for (; p
!= NULL
; p
= OSSL_PARAM_locate_const(p
+ 1,
252 OSSL_KDF_PARAM_SEED
)) {
253 const void *q
= ctx
->seed
+ ctx
->seedlen
;
256 if (p
->data_size
!= 0
258 && !OSSL_PARAM_get_octet_string(p
, (void **)&q
,
259 TLS1_PRF_MAXBUF
- ctx
->seedlen
,
268 static const OSSL_PARAM
*kdf_tls1_prf_settable_ctx_params(
269 ossl_unused
void *ctx
, ossl_unused
void *provctx
)
271 static const OSSL_PARAM known_settable_ctx_params
[] = {
272 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES
, NULL
, 0),
273 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST
, NULL
, 0),
274 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET
, NULL
, 0),
275 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED
, NULL
, 0),
278 return known_settable_ctx_params
;
281 static int kdf_tls1_prf_get_ctx_params(void *vctx
, OSSL_PARAM params
[])
285 if ((p
= OSSL_PARAM_locate(params
, OSSL_KDF_PARAM_SIZE
)) != NULL
)
286 return OSSL_PARAM_set_size_t(p
, SIZE_MAX
);
290 static const OSSL_PARAM
*kdf_tls1_prf_gettable_ctx_params(
291 ossl_unused
void *ctx
, ossl_unused
void *provctx
)
293 static const OSSL_PARAM known_gettable_ctx_params
[] = {
294 OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE
, NULL
),
297 return known_gettable_ctx_params
;
300 const OSSL_DISPATCH ossl_kdf_tls1_prf_functions
[] = {
301 { OSSL_FUNC_KDF_NEWCTX
, (void(*)(void))kdf_tls1_prf_new
},
302 { OSSL_FUNC_KDF_DUPCTX
, (void(*)(void))kdf_tls1_prf_dup
},
303 { OSSL_FUNC_KDF_FREECTX
, (void(*)(void))kdf_tls1_prf_free
},
304 { OSSL_FUNC_KDF_RESET
, (void(*)(void))kdf_tls1_prf_reset
},
305 { OSSL_FUNC_KDF_DERIVE
, (void(*)(void))kdf_tls1_prf_derive
},
306 { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS
,
307 (void(*)(void))kdf_tls1_prf_settable_ctx_params
},
308 { OSSL_FUNC_KDF_SET_CTX_PARAMS
,
309 (void(*)(void))kdf_tls1_prf_set_ctx_params
},
310 { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS
,
311 (void(*)(void))kdf_tls1_prf_gettable_ctx_params
},
312 { OSSL_FUNC_KDF_GET_CTX_PARAMS
,
313 (void(*)(void))kdf_tls1_prf_get_ctx_params
},
318 * Refer to "The TLS Protocol Version 1.0" Section 5
319 * (https://tools.ietf.org/html/rfc2246#section-5) and
320 * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
321 * (https://tools.ietf.org/html/rfc5246#section-5).
323 * P_<hash> is an expansion function that uses a single hash function to expand
324 * a secret and seed into an arbitrary quantity of output:
326 * P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
327 * HMAC_<hash>(secret, A(2) + seed) +
328 * HMAC_<hash>(secret, A(3) + seed) + ...
330 * where + indicates concatenation. P_<hash> can be iterated as many times as
331 * is necessary to produce the required quantity of data.
333 * A(i) is defined as:
335 * A(i) = HMAC_<hash>(secret, A(i-1))
337 static int tls1_prf_P_hash(EVP_MAC_CTX
*ctx_init
,
338 const unsigned char *sec
, size_t sec_len
,
339 const unsigned char *seed
, size_t seed_len
,
340 unsigned char *out
, size_t olen
)
343 EVP_MAC_CTX
*ctx
= NULL
, *ctx_Ai
= NULL
;
344 unsigned char Ai
[EVP_MAX_MD_SIZE
];
348 if (!EVP_MAC_init(ctx_init
, sec
, sec_len
, NULL
))
350 chunk
= EVP_MAC_CTX_get_mac_size(ctx_init
);
354 ctx_Ai
= EVP_MAC_CTX_dup(ctx_init
);
357 if (seed
!= NULL
&& !EVP_MAC_update(ctx_Ai
, seed
, seed_len
))
361 /* calc: A(i) = HMAC_<hash>(secret, A(i-1)) */
362 if (!EVP_MAC_final(ctx_Ai
, Ai
, &Ai_len
, sizeof(Ai
)))
364 EVP_MAC_CTX_free(ctx_Ai
);
367 /* calc next chunk: HMAC_<hash>(secret, A(i) + seed) */
368 ctx
= EVP_MAC_CTX_dup(ctx_init
);
371 if (!EVP_MAC_update(ctx
, Ai
, Ai_len
))
373 /* save state for calculating next A(i) value */
375 ctx_Ai
= EVP_MAC_CTX_dup(ctx
);
379 if (seed
!= NULL
&& !EVP_MAC_update(ctx
, seed
, seed_len
))
382 /* last chunk - use Ai as temp bounce buffer */
383 if (!EVP_MAC_final(ctx
, Ai
, &Ai_len
, sizeof(Ai
)))
385 memcpy(out
, Ai
, olen
);
388 if (!EVP_MAC_final(ctx
, out
, NULL
, olen
))
390 EVP_MAC_CTX_free(ctx
);
397 EVP_MAC_CTX_free(ctx
);
398 EVP_MAC_CTX_free(ctx_Ai
);
399 OPENSSL_cleanse(Ai
, sizeof(Ai
));
404 * Refer to "The TLS Protocol Version 1.0" Section 5
405 * (https://tools.ietf.org/html/rfc2246#section-5) and
406 * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5
407 * (https://tools.ietf.org/html/rfc5246#section-5).
409 * For TLS v1.0 and TLS v1.1:
411 * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
412 * P_SHA-1(S2, label + seed)
414 * S1 is taken from the first half of the secret, S2 from the second half.
416 * L_S = length in bytes of secret;
417 * L_S1 = L_S2 = ceil(L_S / 2);
421 * PRF(secret, label, seed) = P_<hash>(secret, label + seed)
423 static int tls1_prf_alg(EVP_MAC_CTX
*mdctx
, EVP_MAC_CTX
*sha1ctx
,
424 const unsigned char *sec
, size_t slen
,
425 const unsigned char *seed
, size_t seed_len
,
426 unsigned char *out
, size_t olen
)
428 if (sha1ctx
!= NULL
) {
429 /* TLS v1.0 and TLS v1.1 */
432 /* calc: L_S1 = L_S2 = ceil(L_S / 2) */
433 size_t L_S1
= (slen
+ 1) / 2;
436 if (!tls1_prf_P_hash(mdctx
, sec
, L_S1
,
437 seed
, seed_len
, out
, olen
))
440 if ((tmp
= OPENSSL_malloc(olen
)) == NULL
)
443 if (!tls1_prf_P_hash(sha1ctx
, sec
+ slen
- L_S2
, L_S2
,
444 seed
, seed_len
, tmp
, olen
)) {
445 OPENSSL_clear_free(tmp
, olen
);
448 for (i
= 0; i
< olen
; i
++)
450 OPENSSL_clear_free(tmp
, olen
);
455 if (!tls1_prf_P_hash(mdctx
, sec
, slen
, seed
, seed_len
, out
, olen
))