1 /*
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 #include "common.h"
21 
22 #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
23 
24 #include "mbedtls/hkdf.h"
25 #include "mbedtls/ssl_internal.h"
26 #include "ssl_tls13_keys.h"
27 
28 #include <stdint.h>
29 #include <string.h>
30 
31 #define MBEDTLS_SSL_TLS1_3_LABEL( name, string )       \
32     .name = string,
33 
34 struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels =
35 {
36     /* This seems to work in C, despite the string literal being one
37      * character too long due to the 0-termination. */
38     MBEDTLS_SSL_TLS1_3_LABEL_LIST
39 };
40 
41 #undef MBEDTLS_SSL_TLS1_3_LABEL
42 
43 /*
44  * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule.
45  *
46  * The HkdfLabel is specified in RFC 8446 as follows:
47  *
48  * struct HkdfLabel {
49  *   uint16 length;            // Length of expanded key material
50  *   opaque label<7..255>;     // Always prefixed by "tls13 "
51  *   opaque context<0..255>;   // Usually a communication transcript hash
52  * };
53  *
54  * Parameters:
55  * - desired_length: Length of expanded key material
56  *                   Even though the standard allows expansion to up to
57  *                   2**16 Bytes, TLS 1.3 never uses expansion to more than
58  *                   255 Bytes, so we require `desired_length` to be at most
59  *                   255. This allows us to save a few Bytes of code by
60  *                   hardcoding the writing of the high bytes.
61  * - (label, llen): label + label length, without "tls13 " prefix
62  *                  The label length MUST be less than or equal to
63  *                  MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN
64  *                  It is the caller's responsibility to ensure this.
65  *                  All (label, label length) pairs used in TLS 1.3
66  *                  can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN().
67  * - (ctx, clen): context + context length
68  *                The context length MUST be less than or equal to
69  *                MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN
70  *                It is the caller's responsibility to ensure this.
71  * - dst: Target buffer for HkdfLabel structure,
72  *        This MUST be a writable buffer of size
73  *        at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes.
74  * - dlen: Pointer at which to store the actual length of
75  *         the HkdfLabel structure on success.
76  */
77 
78 static const char tls1_3_label_prefix[6] = "tls13 ";
79 
80 #define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( label_len, context_len ) \
81     (   2                  /* expansion length           */ \
82       + 1                  /* label length               */ \
83       + label_len                                           \
84       + 1                  /* context length             */ \
85       + context_len )
86 
87 #define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN                      \
88     SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(                             \
89                      sizeof(tls1_3_label_prefix) +                      \
90                      MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN,     \
91                      MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
92 
ssl_tls1_3_hkdf_encode_label(size_t desired_length,const unsigned char * label,size_t llen,const unsigned char * ctx,size_t clen,unsigned char * dst,size_t * dlen)93 static void ssl_tls1_3_hkdf_encode_label(
94                             size_t desired_length,
95                             const unsigned char *label, size_t llen,
96                             const unsigned char *ctx, size_t clen,
97                             unsigned char *dst, size_t *dlen )
98 {
99     size_t total_label_len =
100         sizeof(tls1_3_label_prefix) + llen;
101     size_t total_hkdf_lbl_len =
102         SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( total_label_len, clen );
103 
104     unsigned char *p = dst;
105 
106     /* Add the size of the expanded key material.
107      * We're hardcoding the high byte to 0 here assuming that we never use
108      * TLS 1.3 HKDF key expansion to more than 255 Bytes. */
109 #if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255
110 #error "The implementation of ssl_tls1_3_hkdf_encode_label() is not fit for the \
111         value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN"
112 #endif
113 
114     *p++ = 0;
115     *p++ = (unsigned char)( ( desired_length >> 0 ) & 0xFF );
116 
117     /* Add label incl. prefix */
118     *p++ = (unsigned char)( total_label_len & 0xFF );
119     memcpy( p, tls1_3_label_prefix, sizeof(tls1_3_label_prefix) );
120     p += sizeof(tls1_3_label_prefix);
121     memcpy( p, label, llen );
122     p += llen;
123 
124     /* Add context value */
125     *p++ = (unsigned char)( clen & 0xFF );
126     if( clen != 0 )
127         memcpy( p, ctx, clen );
128 
129     /* Return total length to the caller.  */
130     *dlen = total_hkdf_lbl_len;
131 }
132 
mbedtls_ssl_tls1_3_hkdf_expand_label(mbedtls_md_type_t hash_alg,const unsigned char * secret,size_t slen,const unsigned char * label,size_t llen,const unsigned char * ctx,size_t clen,unsigned char * buf,size_t blen)133 int mbedtls_ssl_tls1_3_hkdf_expand_label(
134                      mbedtls_md_type_t hash_alg,
135                      const unsigned char *secret, size_t slen,
136                      const unsigned char *label, size_t llen,
137                      const unsigned char *ctx, size_t clen,
138                      unsigned char *buf, size_t blen )
139 {
140     const mbedtls_md_info_t *md;
141     unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ];
142     size_t hkdf_label_len;
143 
144     if( llen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN )
145     {
146         /* Should never happen since this is an internal
147          * function, and we know statically which labels
148          * are allowed. */
149         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
150     }
151 
152     if( clen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
153     {
154         /* Should not happen, as above. */
155         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
156     }
157 
158     if( blen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN )
159     {
160         /* Should not happen, as above. */
161         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
162     }
163 
164     md = mbedtls_md_info_from_type( hash_alg );
165     if( md == NULL )
166         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
167 
168     ssl_tls1_3_hkdf_encode_label( blen,
169                                   label, llen,
170                                   ctx, clen,
171                                   hkdf_label,
172                                   &hkdf_label_len );
173 
174     return( mbedtls_hkdf_expand( md,
175                                  secret, slen,
176                                  hkdf_label, hkdf_label_len,
177                                  buf, blen ) );
178 }
179 
180 /*
181  * The traffic keying material is generated from the following inputs:
182  *
183  *  - One secret value per sender.
184  *  - A purpose value indicating the specific value being generated
185  *  - The desired lengths of key and IV.
186  *
187  * The expansion itself is based on HKDF:
188  *
189  *   [sender]_write_key = HKDF-Expand-Label( Secret, "key", "", key_length )
190  *   [sender]_write_iv  = HKDF-Expand-Label( Secret, "iv" , "", iv_length )
191  *
192  * [sender] denotes the sending side and the Secret value is provided
193  * by the function caller. Note that we generate server and client side
194  * keys in a single function call.
195  */
mbedtls_ssl_tls1_3_make_traffic_keys(mbedtls_md_type_t hash_alg,const unsigned char * client_secret,const unsigned char * server_secret,size_t slen,size_t key_len,size_t iv_len,mbedtls_ssl_key_set * keys)196 int mbedtls_ssl_tls1_3_make_traffic_keys(
197                      mbedtls_md_type_t hash_alg,
198                      const unsigned char *client_secret,
199                      const unsigned char *server_secret,
200                      size_t slen, size_t key_len, size_t iv_len,
201                      mbedtls_ssl_key_set *keys )
202 {
203     int ret = 0;
204 
205     ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
206                     client_secret, slen,
207                     MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
208                     NULL, 0,
209                     keys->client_write_key, key_len );
210     if( ret != 0 )
211         return( ret );
212 
213     ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
214                     server_secret, slen,
215                     MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
216                     NULL, 0,
217                     keys->server_write_key, key_len );
218     if( ret != 0 )
219         return( ret );
220 
221     ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
222                     client_secret, slen,
223                     MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
224                     NULL, 0,
225                     keys->client_write_iv, iv_len );
226     if( ret != 0 )
227         return( ret );
228 
229     ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
230                     server_secret, slen,
231                     MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
232                     NULL, 0,
233                     keys->server_write_iv, iv_len );
234     if( ret != 0 )
235         return( ret );
236 
237     keys->key_len = key_len;
238     keys->iv_len = iv_len;
239 
240     return( 0 );
241 }
242 
mbedtls_ssl_tls1_3_derive_secret(mbedtls_md_type_t hash_alg,const unsigned char * secret,size_t slen,const unsigned char * label,size_t llen,const unsigned char * ctx,size_t clen,int ctx_hashed,unsigned char * dstbuf,size_t buflen)243 int mbedtls_ssl_tls1_3_derive_secret(
244                    mbedtls_md_type_t hash_alg,
245                    const unsigned char *secret, size_t slen,
246                    const unsigned char *label, size_t llen,
247                    const unsigned char *ctx, size_t clen,
248                    int ctx_hashed,
249                    unsigned char *dstbuf, size_t buflen )
250 {
251     int ret;
252     unsigned char hashed_context[ MBEDTLS_MD_MAX_SIZE ];
253 
254     const mbedtls_md_info_t *md;
255     md = mbedtls_md_info_from_type( hash_alg );
256     if( md == NULL )
257         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
258 
259     if( ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED )
260     {
261         ret = mbedtls_md( md, ctx, clen, hashed_context );
262         if( ret != 0 )
263             return( ret );
264         clen = mbedtls_md_get_size( md );
265     }
266     else
267     {
268         if( clen > sizeof(hashed_context) )
269         {
270             /* This should never happen since this function is internal
271              * and the code sets `ctx_hashed` correctly.
272              * Let's double-check nonetheless to not run at the risk
273              * of getting a stack overflow. */
274             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
275         }
276 
277         memcpy( hashed_context, ctx, clen );
278     }
279 
280     return( mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
281                                                   secret, slen,
282                                                   label, llen,
283                                                   hashed_context, clen,
284                                                   dstbuf, buflen ) );
285 }
286 
mbedtls_ssl_tls1_3_evolve_secret(mbedtls_md_type_t hash_alg,const unsigned char * secret_old,const unsigned char * input,size_t input_len,unsigned char * secret_new)287 int mbedtls_ssl_tls1_3_evolve_secret(
288                    mbedtls_md_type_t hash_alg,
289                    const unsigned char *secret_old,
290                    const unsigned char *input, size_t input_len,
291                    unsigned char *secret_new )
292 {
293     int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
294     size_t hlen, ilen;
295     unsigned char tmp_secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 };
296     unsigned char tmp_input [ MBEDTLS_MD_MAX_SIZE ] = { 0 };
297 
298     const mbedtls_md_info_t *md;
299     md = mbedtls_md_info_from_type( hash_alg );
300     if( md == NULL )
301         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
302 
303     hlen = mbedtls_md_get_size( md );
304 
305     /* For non-initial runs, call Derive-Secret( ., "derived", "")
306      * on the old secret. */
307     if( secret_old != NULL )
308     {
309         ret = mbedtls_ssl_tls1_3_derive_secret(
310                    hash_alg,
311                    secret_old, hlen,
312                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( derived ),
313                    NULL, 0, /* context */
314                    MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
315                    tmp_secret, hlen );
316         if( ret != 0 )
317             goto cleanup;
318     }
319 
320     if( input != NULL )
321     {
322         memcpy( tmp_input, input, input_len );
323         ilen = input_len;
324     }
325     else
326     {
327         ilen = hlen;
328     }
329 
330     /* HKDF-Extract takes a salt and input key material.
331      * The salt is the old secret, and the input key material
332      * is the input secret (PSK / ECDHE). */
333     ret = mbedtls_hkdf_extract( md,
334                     tmp_secret, hlen,
335                     tmp_input, ilen,
336                     secret_new );
337     if( ret != 0 )
338         goto cleanup;
339 
340     ret = 0;
341 
342  cleanup:
343 
344     mbedtls_platform_zeroize( tmp_secret, sizeof(tmp_secret) );
345     mbedtls_platform_zeroize( tmp_input,  sizeof(tmp_input)  );
346     return( ret );
347 }
348 
349 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
350