]> git.ipfire.org Git - thirdparty/openssl.git/blob - providers/implementations/kdfs/tls1_prf.c
Copyright year updates
[thirdparty/openssl.git] / providers / implementations / kdfs / tls1_prf.c
1 /*
2 * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
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
8 */
9
10 /*
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).
15 *
16 * For TLS v1.0 and TLS v1.1 the TLS PRF algorithm is given by:
17 *
18 * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
19 * P_SHA-1(S2, label + seed)
20 *
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.
25 *
26 * For TLS v1.2 the TLS PRF algorithm is given by:
27 *
28 * PRF(secret, label, seed) = P_<hash>(secret, label + seed)
29 *
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.
33 *
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:
36 *
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) + ...
40 *
41 * where + indicates concatenation. P_<hash> can be iterated as many times as
42 * is necessary to produce the required quantity of data.
43 *
44 * A(i) is defined as:
45 * A(0) = seed
46 * A(i) = HMAC_<hash>(secret, A(i-1))
47 */
48
49 /*
50 * Low level APIs (such as DH) are deprecated for public use, but still ok for
51 * internal use.
52 */
53 #include "internal/deprecated.h"
54
55 #include <stdio.h>
56 #include <stdarg.h>
57 #include <string.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"
72
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;
82
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);
87
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
91
92 /* TLS KDF kdf context structure */
93 typedef struct {
94 void *provctx;
95
96 /* MAC context for the main digest */
97 EVP_MAC_CTX *P_hash;
98 /* MAC context for SHA1 for the MD5/SHA-1 combined PRF */
99 EVP_MAC_CTX *P_sha1;
100
101 /* Secret value to use for PRF */
102 unsigned char *sec;
103 size_t seclen;
104 /* Buffer of concatenated seed data */
105 unsigned char seed[TLS1_PRF_MAXBUF];
106 size_t seedlen;
107 } TLS1_PRF;
108
109 static void *kdf_tls1_prf_new(void *provctx)
110 {
111 TLS1_PRF *ctx;
112
113 if (!ossl_prov_is_running())
114 return NULL;
115
116 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL)
117 ctx->provctx = provctx;
118 return ctx;
119 }
120
121 static void kdf_tls1_prf_free(void *vctx)
122 {
123 TLS1_PRF *ctx = (TLS1_PRF *)vctx;
124
125 if (ctx != NULL) {
126 kdf_tls1_prf_reset(ctx);
127 OPENSSL_free(ctx);
128 }
129 }
130
131 static void kdf_tls1_prf_reset(void *vctx)
132 {
133 TLS1_PRF *ctx = (TLS1_PRF *)vctx;
134 void *provctx = ctx->provctx;
135
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;
142 }
143
144 static void *kdf_tls1_prf_dup(void *vctx)
145 {
146 const TLS1_PRF *src = (const TLS1_PRF *)vctx;
147 TLS1_PRF *dest;
148
149 dest = kdf_tls1_prf_new(src->provctx);
150 if (dest != NULL) {
151 if (src->P_hash != NULL
152 && (dest->P_hash = EVP_MAC_CTX_dup(src->P_hash)) == NULL)
153 goto err;
154 if (src->P_sha1 != NULL
155 && (dest->P_sha1 = EVP_MAC_CTX_dup(src->P_sha1)) == NULL)
156 goto err;
157 if (!ossl_prov_memdup(src->sec, src->seclen, &dest->sec, &dest->seclen))
158 goto err;
159 memcpy(dest->seed, src->seed, src->seedlen);
160 dest->seedlen = src->seedlen;
161 }
162 return dest;
163
164 err:
165 kdf_tls1_prf_free(dest);
166 return NULL;
167 }
168
169 static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen,
170 const OSSL_PARAM params[])
171 {
172 TLS1_PRF *ctx = (TLS1_PRF *)vctx;
173 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
174
175 if (!ossl_prov_is_running() || !kdf_tls1_prf_set_ctx_params(ctx, params))
176 return 0;
177
178 if (ctx->P_hash == NULL) {
179 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
180 return 0;
181 }
182 if (ctx->sec == NULL) {
183 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
184 return 0;
185 }
186 if (ctx->seedlen == 0) {
187 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SEED);
188 return 0;
189 }
190 if (keylen == 0) {
191 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
192 return 0;
193 }
194
195 /*
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".
200 */
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);
206 return 0;
207 }
208 }
209
210 return tls1_prf_alg(ctx->P_hash, ctx->P_sha1,
211 ctx->sec, ctx->seclen,
212 ctx->seed, ctx->seedlen,
213 key, keylen);
214 }
215
216 static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
217 {
218 const OSSL_PARAM *p;
219 TLS1_PRF *ctx = vctx;
220 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
221
222 if (params == NULL)
223 return 1;
224
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,
228 OSSL_MAC_NAME_HMAC,
229 NULL, SN_md5, libctx)
230 || !ossl_prov_macctx_load_from_params(&ctx->P_sha1, params,
231 OSSL_MAC_NAME_HMAC,
232 NULL, SN_sha1, libctx))
233 return 0;
234 } else {
235 EVP_MAC_CTX_free(ctx->P_sha1);
236 if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
237 OSSL_MAC_NAME_HMAC,
238 NULL, NULL, libctx))
239 return 0;
240 }
241 }
242
243 if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL) {
244 OPENSSL_clear_free(ctx->sec, ctx->seclen);
245 ctx->sec = NULL;
246 if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->sec, 0, &ctx->seclen))
247 return 0;
248 }
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;
254 size_t sz = 0;
255
256 if (p->data_size != 0
257 && p->data != NULL
258 && !OSSL_PARAM_get_octet_string(p, (void **)&q,
259 TLS1_PRF_MAXBUF - ctx->seedlen,
260 &sz))
261 return 0;
262 ctx->seedlen += sz;
263 }
264 }
265 return 1;
266 }
267
268 static const OSSL_PARAM *kdf_tls1_prf_settable_ctx_params(
269 ossl_unused void *ctx, ossl_unused void *provctx)
270 {
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),
276 OSSL_PARAM_END
277 };
278 return known_settable_ctx_params;
279 }
280
281 static int kdf_tls1_prf_get_ctx_params(void *vctx, OSSL_PARAM params[])
282 {
283 OSSL_PARAM *p;
284
285 if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
286 return OSSL_PARAM_set_size_t(p, SIZE_MAX);
287 return -2;
288 }
289
290 static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params(
291 ossl_unused void *ctx, ossl_unused void *provctx)
292 {
293 static const OSSL_PARAM known_gettable_ctx_params[] = {
294 OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
295 OSSL_PARAM_END
296 };
297 return known_gettable_ctx_params;
298 }
299
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 },
314 OSSL_DISPATCH_END
315 };
316
317 /*
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).
322 *
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:
325 *
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) + ...
329 *
330 * where + indicates concatenation. P_<hash> can be iterated as many times as
331 * is necessary to produce the required quantity of data.
332 *
333 * A(i) is defined as:
334 * A(0) = seed
335 * A(i) = HMAC_<hash>(secret, A(i-1))
336 */
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)
341 {
342 size_t chunk;
343 EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL;
344 unsigned char Ai[EVP_MAX_MD_SIZE];
345 size_t Ai_len;
346 int ret = 0;
347
348 if (!EVP_MAC_init(ctx_init, sec, sec_len, NULL))
349 goto err;
350 chunk = EVP_MAC_CTX_get_mac_size(ctx_init);
351 if (chunk == 0)
352 goto err;
353 /* A(0) = seed */
354 ctx_Ai = EVP_MAC_CTX_dup(ctx_init);
355 if (ctx_Ai == NULL)
356 goto err;
357 if (seed != NULL && !EVP_MAC_update(ctx_Ai, seed, seed_len))
358 goto err;
359
360 for (;;) {
361 /* calc: A(i) = HMAC_<hash>(secret, A(i-1)) */
362 if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai)))
363 goto err;
364 EVP_MAC_CTX_free(ctx_Ai);
365 ctx_Ai = NULL;
366
367 /* calc next chunk: HMAC_<hash>(secret, A(i) + seed) */
368 ctx = EVP_MAC_CTX_dup(ctx_init);
369 if (ctx == NULL)
370 goto err;
371 if (!EVP_MAC_update(ctx, Ai, Ai_len))
372 goto err;
373 /* save state for calculating next A(i) value */
374 if (olen > chunk) {
375 ctx_Ai = EVP_MAC_CTX_dup(ctx);
376 if (ctx_Ai == NULL)
377 goto err;
378 }
379 if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len))
380 goto err;
381 if (olen <= chunk) {
382 /* last chunk - use Ai as temp bounce buffer */
383 if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai)))
384 goto err;
385 memcpy(out, Ai, olen);
386 break;
387 }
388 if (!EVP_MAC_final(ctx, out, NULL, olen))
389 goto err;
390 EVP_MAC_CTX_free(ctx);
391 ctx = NULL;
392 out += chunk;
393 olen -= chunk;
394 }
395 ret = 1;
396 err:
397 EVP_MAC_CTX_free(ctx);
398 EVP_MAC_CTX_free(ctx_Ai);
399 OPENSSL_cleanse(Ai, sizeof(Ai));
400 return ret;
401 }
402
403 /*
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).
408 *
409 * For TLS v1.0 and TLS v1.1:
410 *
411 * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
412 * P_SHA-1(S2, label + seed)
413 *
414 * S1 is taken from the first half of the secret, S2 from the second half.
415 *
416 * L_S = length in bytes of secret;
417 * L_S1 = L_S2 = ceil(L_S / 2);
418 *
419 * For TLS v1.2:
420 *
421 * PRF(secret, label, seed) = P_<hash>(secret, label + seed)
422 */
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)
427 {
428 if (sha1ctx != NULL) {
429 /* TLS v1.0 and TLS v1.1 */
430 size_t i;
431 unsigned char *tmp;
432 /* calc: L_S1 = L_S2 = ceil(L_S / 2) */
433 size_t L_S1 = (slen + 1) / 2;
434 size_t L_S2 = L_S1;
435
436 if (!tls1_prf_P_hash(mdctx, sec, L_S1,
437 seed, seed_len, out, olen))
438 return 0;
439
440 if ((tmp = OPENSSL_malloc(olen)) == NULL)
441 return 0;
442
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);
446 return 0;
447 }
448 for (i = 0; i < olen; i++)
449 out[i] ^= tmp[i];
450 OPENSSL_clear_free(tmp, olen);
451 return 1;
452 }
453
454 /* TLS v1.2 */
455 if (!tls1_prf_P_hash(mdctx, sec, slen, seed, seed_len, out, olen))
456 return 0;
457
458 return 1;
459 }