diff options
author | jsing <> | 2022-11-07 11:58:45 +0000 |
---|---|---|
committer | jsing <> | 2022-11-07 11:58:45 +0000 |
commit | 9b1a5502ac166e7ddd3da7c143bb65686a035ac4 (patch) | |
tree | bfa8daa6e7b625129ae066d13e602b42c3262e43 /src/lib/libssl/tls12_key_schedule.c | |
parent | 7aa564fe60027590616687055794c45960ec44dd (diff) | |
download | openbsd-9b1a5502ac166e7ddd3da7c143bb65686a035ac4.tar.gz openbsd-9b1a5502ac166e7ddd3da7c143bb65686a035ac4.tar.bz2 openbsd-9b1a5502ac166e7ddd3da7c143bb65686a035ac4.zip |
Rewrite TLSv1.2 key exporter.
Replace the grotty TLSv1.2 key exporter with a cleaner version that uses
CBB and CBS.
ok tb@
Diffstat (limited to 'src/lib/libssl/tls12_key_schedule.c')
-rw-r--r-- | src/lib/libssl/tls12_key_schedule.c | 122 |
1 files changed, 121 insertions, 1 deletions
diff --git a/src/lib/libssl/tls12_key_schedule.c b/src/lib/libssl/tls12_key_schedule.c index c206460d95..e603e2c222 100644 --- a/src/lib/libssl/tls12_key_schedule.c +++ b/src/lib/libssl/tls12_key_schedule.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls12_key_schedule.c,v 1.1 2021/05/05 10:05:27 jsing Exp $ */ | 1 | /* $OpenBSD: tls12_key_schedule.c,v 1.2 2022/11/07 11:58:45 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2021 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2021 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include "bytestring.h" | 22 | #include "bytestring.h" |
23 | #include "ssl_locl.h" | 23 | #include "ssl_locl.h" |
24 | #include "tls12_internal.h" | ||
24 | 25 | ||
25 | struct tls12_key_block { | 26 | struct tls12_key_block { |
26 | CBS client_write_mac_key; | 27 | CBS client_write_mac_key; |
@@ -173,3 +174,122 @@ tls12_key_block_generate(struct tls12_key_block *kb, SSL *s, | |||
173 | 174 | ||
174 | return 0; | 175 | return 0; |
175 | } | 176 | } |
177 | |||
178 | struct tls12_reserved_label { | ||
179 | const char *label; | ||
180 | size_t label_len; | ||
181 | }; | ||
182 | |||
183 | /* | ||
184 | * RFC 5705 section 6. | ||
185 | */ | ||
186 | static const struct tls12_reserved_label tls12_reserved_labels[] = { | ||
187 | { | ||
188 | .label = TLS_MD_CLIENT_FINISH_CONST, | ||
189 | .label_len = TLS_MD_CLIENT_FINISH_CONST_SIZE, | ||
190 | }, | ||
191 | { | ||
192 | .label = TLS_MD_SERVER_FINISH_CONST, | ||
193 | .label_len = TLS_MD_SERVER_FINISH_CONST_SIZE, | ||
194 | }, | ||
195 | { | ||
196 | .label = TLS_MD_MASTER_SECRET_CONST, | ||
197 | .label_len = TLS_MD_MASTER_SECRET_CONST_SIZE, | ||
198 | }, | ||
199 | { | ||
200 | .label = TLS_MD_KEY_EXPANSION_CONST, | ||
201 | .label_len = TLS_MD_KEY_EXPANSION_CONST_SIZE, | ||
202 | }, | ||
203 | { | ||
204 | .label = NULL, | ||
205 | .label_len = 0, | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | int | ||
210 | tls12_exporter(SSL *s, const uint8_t *label, size_t label_len, | ||
211 | const uint8_t *context_value, size_t context_value_len, int use_context, | ||
212 | uint8_t *out, size_t out_len) | ||
213 | { | ||
214 | uint8_t *data = NULL; | ||
215 | size_t data_len = 0; | ||
216 | CBB cbb, context; | ||
217 | CBS seed; | ||
218 | size_t i; | ||
219 | int ret = 0; | ||
220 | |||
221 | /* | ||
222 | * RFC 5705 - Key Material Exporters for TLS. | ||
223 | */ | ||
224 | |||
225 | memset(&cbb, 0, sizeof(cbb)); | ||
226 | |||
227 | if (!SSL_is_init_finished(s)) { | ||
228 | SSLerror(s, SSL_R_BAD_STATE); | ||
229 | goto err; | ||
230 | } | ||
231 | |||
232 | if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION) | ||
233 | goto err; | ||
234 | |||
235 | /* | ||
236 | * Due to exceptional design choices, we need to build a concatenation | ||
237 | * of the label and the seed value, before checking for reserved | ||
238 | * labels. This prevents a reserved label from being split across the | ||
239 | * label and the seed (that includes the client random), which are | ||
240 | * concatenated by the PRF. | ||
241 | */ | ||
242 | if (!CBB_init(&cbb, 0)) | ||
243 | goto err; | ||
244 | if (!CBB_add_bytes(&cbb, label, label_len)) | ||
245 | goto err; | ||
246 | if (!CBB_add_bytes(&cbb, s->s3->client_random, SSL3_RANDOM_SIZE)) | ||
247 | goto err; | ||
248 | if (!CBB_add_bytes(&cbb, s->s3->server_random, SSL3_RANDOM_SIZE)) | ||
249 | goto err; | ||
250 | if (use_context) { | ||
251 | if (!CBB_add_u16_length_prefixed(&cbb, &context)) | ||
252 | goto err; | ||
253 | if (context_value_len > 0) { | ||
254 | if (!CBB_add_bytes(&context, context_value, | ||
255 | context_value_len)) | ||
256 | goto err; | ||
257 | } | ||
258 | } | ||
259 | if (!CBB_finish(&cbb, &data, &data_len)) | ||
260 | goto err; | ||
261 | |||
262 | /* | ||
263 | * Ensure that the block (label + seed) does not start with a reserved | ||
264 | * label - in an ideal world we would ensure that the label has an | ||
265 | * explicitly permitted prefix instead, but of course this also got | ||
266 | * messed up by the standards. | ||
267 | */ | ||
268 | for (i = 0; tls12_reserved_labels[i].label != NULL; i++) { | ||
269 | /* XXX - consider adding/using CBS_has_prefix(). */ | ||
270 | if (tls12_reserved_labels[i].label_len > data_len) | ||
271 | goto err; | ||
272 | if (memcmp(data, tls12_reserved_labels[i].label, | ||
273 | tls12_reserved_labels[i].label_len) == 0) { | ||
274 | SSLerror(s, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL); | ||
275 | goto err; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | CBS_init(&seed, data, data_len); | ||
280 | if (!CBS_skip(&seed, label_len)) | ||
281 | goto err; | ||
282 | |||
283 | if (!tls1_PRF(s, s->session->master_key, s->session->master_key_length, | ||
284 | label, label_len, CBS_data(&seed), CBS_len(&seed), NULL, 0, NULL, 0, | ||
285 | NULL, 0, out, out_len)) | ||
286 | goto err; | ||
287 | |||
288 | ret = 1; | ||
289 | |||
290 | err: | ||
291 | freezero(data, data_len); | ||
292 | CBB_cleanup(&cbb); | ||
293 | |||
294 | return ret; | ||
295 | } | ||