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