blob: 448d03a61aed268376573a97b6ad5b0dca3cb7c5 [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"
29#include "ssl_tls13_keys.h"
30
31#include <stdint.h>
32#include <string.h>
33
34struct 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 .finished = "finished",
39 .resumption = "resumption",
40 .traffic_upd = "traffic upd",
41 .export = "exporter",
42 .key = "key",
43 .iv = "iv",
44 .sn = "sn",
45 .c_hs_traffic = "c hs traffic",
46 .c_ap_traffic = "c ap traffic",
47 .c_e_traffic = "c e traffic",
48 .s_hs_traffic = "s hs traffic",
49 .s_ap_traffic = "s ap traffic",
50 .s_e_traffic = "s e traffic",
51 .exp_master = "exp master",
52 .res_master = "res master",
53 .ext_binder = "ext binder",
54 .res_binder = "res binder",
55 .derived = "derived"
56};
57
58/*
59 * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule.
60 *
61 * The HkdfLabel is specified in RFC 8446 as follows:
62 *
63 * struct HkdfLabel {
64 * uint16 length; // Length of expanded key material
65 * opaque label<7..255>; // Always prefixed by "tls13 "
66 * opaque context<0..255>; // Usually a communication transcript hash
67 * };
68 *
69 * Parameters:
70 * - desired_length: Length of expanded key material
71 * Even though the standard allows expansion to up to
72 * 2**16 Bytes, TLS 1.3 never uses expansion to more than
73 * 255 Bytes, so we require `desired_length` to be at most
74 * 255. This allows us to save a few Bytes of code by
75 * hardcoding the writing of the high bytes.
76 * - (label, llen): label + label length, without "tls13 " prefix
77 * The label length MUST be
78 * <= MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN
79 * It is the caller's responsiblity to ensure this.
80 * - (ctx, clen): context + context length
81 * The context length MUST be
82 * <= MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN
83 * It is the caller's responsiblity to ensure this.
84 * - dst: Target buffer for HkdfLabel structure,
85 * This MUST be a writable buffer of size
86 * at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes.
87 * - dlen: Pointer at which to store the actual length of
88 * the HkdfLabel structure on success.
89 */
90
91#define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN \
92 ( 2 /* expansion length */ \
93 + 1 /* label length */ \
94 + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \
95 + 1 /* context length */ \
96 + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
97
98static void ssl_tls1_3_hkdf_encode_label(
99 size_t desired_length,
100 const unsigned char *label, size_t llen,
101 const unsigned char *ctx, size_t clen,
102 unsigned char *dst, size_t *dlen )
103{
104 const char label_prefix[6] = { 't', 'l', 's', '1', '3', ' ' };
105 size_t total_label_len = sizeof( label_prefix ) + llen;
106 size_t total_hkdf_lbl_len =
107 2 /* length of expanded key material */
108 + 1 /* label length */
109 + total_label_len /* actual label, incl. prefix */
110 + 1 /* context length */
111 + clen; /* actual context */
112
113 unsigned char *p = dst;
114
115 /* Add total length. */
116 *p++ = 0;
117 *p++ = (unsigned char)( ( desired_length >> 0 ) & 0xFF );
118
119 /* Add label incl. prefix */
120 *p++ = (unsigned char)( total_label_len & 0xFF );
121 memcpy( p, label_prefix, sizeof(label_prefix) );
122 p += sizeof(label_prefix);
123 memcpy( p, label, llen );
124 p += llen;
125
126 /* Add context value */
127 *p++ = (unsigned char)( clen & 0xFF );
128 if( ctx != NULL )
129 memcpy( p, ctx, clen );
130
131 /* Return total length to the caller. */
132 *dlen = total_hkdf_lbl_len;
133}
134
135int mbedtls_ssl_tls1_3_hkdf_expand_label(
136 mbedtls_md_type_t hash_alg,
137 const unsigned char *secret, size_t slen,
138 const unsigned char *label, size_t llen,
139 const unsigned char *ctx, size_t clen,
140 unsigned char *buf, size_t blen )
141{
142 const mbedtls_md_info_t *md;
143 unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ];
144 size_t hkdf_label_len;
145
146 if( llen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN )
147 {
148 /* Should never happen since this is an internal
149 * function, and we know statically which labels
150 * are allowed. */
151 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
152 }
153
154 if( clen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
155 {
156 /* Should not happen, as above. */
157 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
158 }
159
160 if( blen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN )
161 {
162 /* Should not happen, as above. */
163 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
164 }
165
166 md = mbedtls_md_info_from_type( hash_alg );
167 if( md == NULL )
168 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
169
170 ssl_tls1_3_hkdf_encode_label( blen,
171 label, llen,
172 ctx, clen,
173 hkdf_label,
174 &hkdf_label_len );
175
176 return( mbedtls_hkdf_expand( md,
177 secret, slen,
178 hkdf_label, hkdf_label_len,
179 buf, blen ) );
180}
181
182#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */