blob: 1d614556a6df231ed9f0532b87197ecaae080b36 [file] [log] [blame]
Hanno Beckerbe9d6642020-08-21 13:20:06 +01001/*
2 * TLS 1.3 key schedule
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 ( the "License" ); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#if !defined(MBEDTLS_CONFIG_FILE)
21#include "mbedtls/config.h"
22#else
23#include MBEDTLS_CONFIG_FILE
24#endif
25
26#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
27
28#include "mbedtls/hkdf.h"
Hanno Becker3385a4d2020-08-21 13:03:34 +010029#include "mbedtls/ssl_internal.h"
Hanno Beckerbe9d6642020-08-21 13:20:06 +010030#include "ssl_tls13_keys.h"
31
32#include <stdint.h>
33#include <string.h>
34
35struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels =
36{
37 /* This seems to work in C, despite the string literal being one
38 * character too long due to the 0-termination. */
39 .finished = "finished",
40 .resumption = "resumption",
41 .traffic_upd = "traffic upd",
42 .export = "exporter",
43 .key = "key",
44 .iv = "iv",
45 .sn = "sn",
46 .c_hs_traffic = "c hs traffic",
47 .c_ap_traffic = "c ap traffic",
48 .c_e_traffic = "c e traffic",
49 .s_hs_traffic = "s hs traffic",
50 .s_ap_traffic = "s ap traffic",
51 .s_e_traffic = "s e traffic",
52 .exp_master = "exp master",
53 .res_master = "res master",
54 .ext_binder = "ext binder",
55 .res_binder = "res binder",
56 .derived = "derived"
57};
58
59/*
60 * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule.
61 *
62 * The HkdfLabel is specified in RFC 8446 as follows:
63 *
64 * struct HkdfLabel {
65 * uint16 length; // Length of expanded key material
66 * opaque label<7..255>; // Always prefixed by "tls13 "
67 * opaque context<0..255>; // Usually a communication transcript hash
68 * };
69 *
70 * Parameters:
71 * - desired_length: Length of expanded key material
72 * Even though the standard allows expansion to up to
73 * 2**16 Bytes, TLS 1.3 never uses expansion to more than
74 * 255 Bytes, so we require `desired_length` to be at most
75 * 255. This allows us to save a few Bytes of code by
76 * hardcoding the writing of the high bytes.
77 * - (label, llen): label + label length, without "tls13 " prefix
78 * The label length MUST be
79 * <= MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN
80 * It is the caller's responsiblity to ensure this.
81 * - (ctx, clen): context + context length
82 * The context length MUST be
83 * <= MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN
84 * It is the caller's responsiblity to ensure this.
85 * - dst: Target buffer for HkdfLabel structure,
86 * This MUST be a writable buffer of size
87 * at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes.
88 * - dlen: Pointer at which to store the actual length of
89 * the HkdfLabel structure on success.
90 */
91
92#define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN \
93 ( 2 /* expansion length */ \
94 + 1 /* label length */ \
95 + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \
96 + 1 /* context length */ \
97 + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
98
99static void ssl_tls1_3_hkdf_encode_label(
100 size_t desired_length,
101 const unsigned char *label, size_t llen,
102 const unsigned char *ctx, size_t clen,
103 unsigned char *dst, size_t *dlen )
104{
105 const char label_prefix[6] = { 't', 'l', 's', '1', '3', ' ' };
106 size_t total_label_len = sizeof( label_prefix ) + llen;
107 size_t total_hkdf_lbl_len =
108 2 /* length of expanded key material */
109 + 1 /* label length */
110 + total_label_len /* actual label, incl. prefix */
111 + 1 /* context length */
112 + clen; /* actual context */
113
114 unsigned char *p = dst;
115
116 /* Add total length. */
117 *p++ = 0;
118 *p++ = (unsigned char)( ( desired_length >> 0 ) & 0xFF );
119
120 /* Add label incl. prefix */
121 *p++ = (unsigned char)( total_label_len & 0xFF );
122 memcpy( p, label_prefix, sizeof(label_prefix) );
123 p += sizeof(label_prefix);
124 memcpy( p, label, llen );
125 p += llen;
126
127 /* Add context value */
128 *p++ = (unsigned char)( clen & 0xFF );
129 if( ctx != NULL )
130 memcpy( p, ctx, clen );
131
132 /* Return total length to the caller. */
133 *dlen = total_hkdf_lbl_len;
134}
135
136int mbedtls_ssl_tls1_3_hkdf_expand_label(
137 mbedtls_md_type_t hash_alg,
138 const unsigned char *secret, size_t slen,
139 const unsigned char *label, size_t llen,
140 const unsigned char *ctx, size_t clen,
141 unsigned char *buf, size_t blen )
142{
143 const mbedtls_md_info_t *md;
144 unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ];
145 size_t hkdf_label_len;
146
147 if( llen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN )
148 {
149 /* Should never happen since this is an internal
150 * function, and we know statically which labels
151 * are allowed. */
152 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
153 }
154
155 if( clen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
156 {
157 /* Should not happen, as above. */
158 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
159 }
160
161 if( blen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN )
162 {
163 /* Should not happen, as above. */
164 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
165 }
166
167 md = mbedtls_md_info_from_type( hash_alg );
168 if( md == NULL )
169 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
170
171 ssl_tls1_3_hkdf_encode_label( blen,
172 label, llen,
173 ctx, clen,
174 hkdf_label,
175 &hkdf_label_len );
176
177 return( mbedtls_hkdf_expand( md,
178 secret, slen,
179 hkdf_label, hkdf_label_len,
180 buf, blen ) );
181}
182
Hanno Becker3385a4d2020-08-21 13:03:34 +0100183/*
184 * The traffic keying material is generated from the following inputs:
185 *
186 * - One secret value per sender.
187 * - A purpose value indicating the specific value being generated
188 * - The desired lengths of key and IV.
189 *
190 * The expansion itself is based on HKDF:
191 *
192 * [sender]_write_key = HKDF-Expand-Label( Secret, "key", "", key_length )
193 * [sender]_write_iv = HKDF-Expand-Label( Secret, "iv" , "", iv_length )
194 *
195 * [sender] denotes the sending side and the Secret value is provided
196 * by the function caller. Note that we generate server and client side
197 * keys in a single function call.
198 */
199int mbedtls_ssl_tls1_3_make_traffic_keys(
200 mbedtls_md_type_t hash_alg,
201 const unsigned char *client_secret,
202 const unsigned char *server_secret,
203 size_t slen, size_t keyLen, size_t ivLen,
204 mbedtls_ssl_key_set *keys )
205{
206 int ret = 0;
207
208 ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
209 client_secret, slen,
210 MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
211 NULL, 0,
212 keys->client_write_key, keyLen );
213 if( ret != 0 )
214 return( ret );
215
216 ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
217 server_secret, slen,
218 MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
219 NULL, 0,
220 keys->server_write_key, keyLen );
221 if( ret != 0 )
222 return( ret );
223
224 ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
225 client_secret, slen,
226 MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
227 NULL, 0,
228 keys->client_write_iv, ivLen );
229 if( ret != 0 )
230 return( ret );
231
232 ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
233 server_secret, slen,
234 MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
235 NULL, 0,
236 keys->server_write_iv, ivLen );
237 if( ret != 0 )
238 return( ret );
239
240 keys->keyLen = keyLen;
241 keys->ivLen = ivLen;
242
243 return( 0 );
244}
245
Hanno Beckerb35d5222020-08-21 13:27:44 +0100246int mbedtls_ssl_tls1_3_derive_secret(
247 mbedtls_md_type_t hash_alg,
248 const unsigned char *secret, size_t slen,
249 const unsigned char *label, size_t llen,
250 const unsigned char *ctx, size_t clen,
251 int context_already_hashed,
252 unsigned char *dstbuf, size_t buflen )
253{
254 int ret;
255 unsigned char hashed_context[ MBEDTLS_MD_MAX_SIZE ];
256
257 const mbedtls_md_info_t *md;
258 md = mbedtls_md_info_from_type( hash_alg );
259 if( md == NULL )
260 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
261
262 if( context_already_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED )
263 {
264 ret = mbedtls_md( md, ctx, clen, hashed_context );
265 if( ret != 0 )
266 return( ret );
267 clen = mbedtls_md_get_size( md );
268 }
269 else
270 {
271 /* This should never happen since this function is internal
272 * and the code sets `context_already_hashed` correctly.
273 * Let's double-check nonetheless to not run at the risk
274 * of getting a stack overflow. */
275 if( clen > sizeof(hashed_context) )
276 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
277
278 memcpy( hashed_context, ctx, clen );
279 }
280
281 return( mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
282 secret, slen,
283 label, llen,
284 hashed_context, clen,
285 dstbuf, buflen ) );
286}
287
Hanno Beckere9cccb42020-08-20 13:42:46 +0100288int mbedtls_ssl_tls1_3_evolve_secret(
289 mbedtls_md_type_t hash_alg,
290 const unsigned char *secret_old,
291 const unsigned char *input, size_t input_len,
292 unsigned char *secret_new )
293{
294 int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
295 size_t hlen, ilen;
296 unsigned char _secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 };
297 unsigned char _input [ MBEDTLS_MD_MAX_SIZE ] = { 0 };
298
299 const mbedtls_md_info_t *md;
300 md = mbedtls_md_info_from_type( hash_alg );
301 if( md == NULL )
302 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
303
304 hlen = mbedtls_md_get_size( md );
305
306 /* For non-initial runs, call Derive-Secret( ., "derived", "")
307 * on the old secreet. */
308 if( secret_old != NULL )
309 {
310 ret = mbedtls_ssl_tls1_3_derive_secret(
311 hash_alg,
312 secret_old, hlen,
313 MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( derived ),
314 NULL, 0, /* context */
315 MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
316 _secret, hlen );
317 if( ret != 0 )
318 goto cleanup;
319 }
320
321 if( input != NULL )
322 {
323 memcpy( _input, input, input_len );
324 ilen = input_len;
325 }
326 else
327 {
328 ilen = hlen;
329 }
330
331 /* HKDF-Extract takes a salt and input key material.
332 * The salt is the old secret, and the input key material
333 * is the input secret (PSK / ECDHE). */
334 ret = mbedtls_hkdf_extract( md,
335 _secret, hlen,
336 _input, ilen,
337 secret_new );
338 if( ret != 0 )
339 goto cleanup;
340
341 ret = 0;
342
343 cleanup:
344
345 mbedtls_platform_zeroize( _secret, sizeof(_secret) );
346 mbedtls_platform_zeroize( _input, sizeof(_input) );
347 return( ret );
348}
349
Hanno Beckerbe9d6642020-08-21 13:20:06 +0100350#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */