summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2023-04-23 18:51:53 +0000
committertb <>2023-04-23 18:51:53 +0000
commitfb7a7adad4b566192144a21e4c93b739671b0cae (patch)
treefa6d649a58d3a734a4bc9dea3b97a71426074f8b
parent292e18c3ddebe32b0e929925c98c01b416d0210e (diff)
downloadopenbsd-fb7a7adad4b566192144a21e4c93b739671b0cae.tar.gz
openbsd-fb7a7adad4b566192144a21e4c93b739671b0cae.tar.bz2
openbsd-fb7a7adad4b566192144a21e4c93b739671b0cae.zip
Randomize the order of TLS extensions
On creation of an SSL using SSL_new(), randomize the order in which the extensions will be sent. There are several constraints: the PSK extension must always come last. The order cannot be randomized on a per-message basis as the strict interpretation of the standard chosen in the CH hashing doesn't allow changing the order between first and second ClientHello. Another constraint is that the current code calls callbacks directly on parsing an extension, which means that the order callbacks are called depends on the order in which the peer sent the extensions. This results in breaking apache-httpd setups using virtual hosts with full ranomization because virtual hosts don't work if the SNI is unknown at the time the ALPN callback is called. So for the time being, we ensure that SNI always precedes ALPN to avoid issues until this issue is fixed. This is based on an idea by David Benjamin https://boringssl-review.googlesource.com/c/boringssl/+/48045 Input & ok jsing
-rw-r--r--src/lib/libssl/ssl_lib.c7
-rw-r--r--src/lib/libssl/ssl_local.h3
-rw-r--r--src/lib/libssl/ssl_tlsext.c63
-rw-r--r--src/lib/libssl/ssl_tlsext.h3
4 files changed, 71 insertions, 5 deletions
diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c
index de4ef3fb5e..68e60a5481 100644
--- a/src/lib/libssl/ssl_lib.c
+++ b/src/lib/libssl/ssl_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_lib.c,v 1.308 2022/11/26 16:08:55 tb Exp $ */ 1/* $OpenBSD: ssl_lib.c,v 1.309 2023/04/23 18:51:53 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -302,6 +302,9 @@ SSL_new(SSL_CTX *ctx)
302 CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); 302 CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
303 s->initial_ctx = ctx; 303 s->initial_ctx = ctx;
304 304
305 if (!tlsext_randomize_build_order(s))
306 goto err;
307
305 if (ctx->tlsext_ecpointformatlist != NULL) { 308 if (ctx->tlsext_ecpointformatlist != NULL) {
306 s->tlsext_ecpointformatlist = 309 s->tlsext_ecpointformatlist =
307 calloc(ctx->tlsext_ecpointformatlist_length, 310 calloc(ctx->tlsext_ecpointformatlist_length,
@@ -550,6 +553,8 @@ SSL_free(SSL *s)
550 553
551 ssl_cert_free(s->cert); 554 ssl_cert_free(s->cert);
552 555
556 free(s->tlsext_build_order);
557
553 free(s->tlsext_hostname); 558 free(s->tlsext_hostname);
554 SSL_CTX_free(s->initial_ctx); 559 SSL_CTX_free(s->initial_ctx);
555 560
diff --git a/src/lib/libssl/ssl_local.h b/src/lib/libssl/ssl_local.h
index d510f80d8c..1748eccbfd 100644
--- a/src/lib/libssl/ssl_local.h
+++ b/src/lib/libssl/ssl_local.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_local.h,v 1.3 2022/12/26 07:31:44 jmc Exp $ */ 1/* $OpenBSD: ssl_local.h,v 1.4 2023/04/23 18:51:53 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -974,6 +974,7 @@ struct ssl_st {
974 974
975 unsigned int max_send_fragment; 975 unsigned int max_send_fragment;
976 976
977 const struct tls_extension **tlsext_build_order;
977 char *tlsext_hostname; 978 char *tlsext_hostname;
978 979
979 /* certificate status request info */ 980 /* certificate status request info */
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c
index e576384118..5ff61f39a5 100644
--- a/src/lib/libssl/ssl_tlsext.c
+++ b/src/lib/libssl/ssl_tlsext.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_tlsext.c,v 1.131 2022/11/26 16:08:56 tb Exp $ */ 1/* $OpenBSD: ssl_tlsext.c,v 1.132 2023/04/23 18:51:53 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2016, 2017, 2019 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2016, 2017, 2019 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -32,6 +32,8 @@
32#include "ssl_sigalgs.h" 32#include "ssl_sigalgs.h"
33#include "ssl_tlsext.h" 33#include "ssl_tlsext.h"
34 34
35#define TLSEXT_TYPE_alpn TLSEXT_TYPE_application_layer_protocol_negotiation
36
35/* 37/*
36 * Supported Application-Layer Protocol Negotiation - RFC 7301 38 * Supported Application-Layer Protocol Negotiation - RFC 7301
37 */ 39 */
@@ -2239,6 +2241,63 @@ tlsext_funcs(const struct tls_extension *tlsext, int is_server)
2239 return &tlsext->client; 2241 return &tlsext->client;
2240} 2242}
2241 2243
2244int
2245tlsext_randomize_build_order(SSL *s)
2246{
2247 size_t idx, new_idx, psk_idx;
2248 size_t alpn_idx, sni_idx;
2249
2250 if ((s->tlsext_build_order = calloc(sizeof(*s->tlsext_build_order),
2251 N_TLS_EXTENSIONS)) == NULL)
2252 return 0;
2253
2254 /* RFC 8446, section 4.2: PSK must be the last extension in the CH. */
2255 psk_idx = N_TLS_EXTENSIONS - 1;
2256 s->tlsext_build_order[psk_idx] = &tls_extensions[psk_idx];
2257
2258 /* Fisher-Yates shuffle with PSK fixed. */
2259 for (idx = 0; idx < psk_idx; idx++) {
2260 new_idx = arc4random_uniform(idx + 1);
2261 s->tlsext_build_order[idx] = s->tlsext_build_order[new_idx];
2262 s->tlsext_build_order[new_idx] = &tls_extensions[idx];
2263 }
2264
2265 /*
2266 * XXX - Apache2 special until year 2025: ensure that SNI precedes ALPN
2267 * for clients so that virtual host setups work correctly.
2268 */
2269
2270 if (s->server)
2271 return 1;
2272
2273 for (idx = 0; idx < N_TLS_EXTENSIONS; idx++) {
2274 if (s->tlsext_build_order[idx]->type == TLSEXT_TYPE_alpn)
2275 alpn_idx = idx;
2276 if (s->tlsext_build_order[idx]->type == TLSEXT_TYPE_server_name)
2277 sni_idx = idx;
2278 }
2279 if (alpn_idx < sni_idx) {
2280 const struct tls_extension *tmp;
2281
2282 tmp = s->tlsext_build_order[alpn_idx];
2283 s->tlsext_build_order[alpn_idx] = s->tlsext_build_order[sni_idx];
2284 s->tlsext_build_order[sni_idx] = tmp;
2285 }
2286
2287 return 1;
2288}
2289
2290int
2291tlsext_linearize_build_order(SSL *s)
2292{
2293 size_t idx;
2294
2295 for (idx = 0; idx < N_TLS_EXTENSIONS; idx++)
2296 s->tlsext_build_order[idx] = &tls_extensions[idx];
2297
2298 return 1;
2299}
2300
2242static int 2301static int
2243tlsext_build(SSL *s, int is_server, uint16_t msg_type, CBB *cbb) 2302tlsext_build(SSL *s, int is_server, uint16_t msg_type, CBB *cbb)
2244{ 2303{
@@ -2255,7 +2314,7 @@ tlsext_build(SSL *s, int is_server, uint16_t msg_type, CBB *cbb)
2255 return 0; 2314 return 0;
2256 2315
2257 for (i = 0; i < N_TLS_EXTENSIONS; i++) { 2316 for (i = 0; i < N_TLS_EXTENSIONS; i++) {
2258 tlsext = &tls_extensions[i]; 2317 tlsext = s->tlsext_build_order[i];
2259 ext = tlsext_funcs(tlsext, is_server); 2318 ext = tlsext_funcs(tlsext, is_server);
2260 2319
2261 /* RFC 8446 Section 4.2 */ 2320 /* RFC 8446 Section 4.2 */
diff --git a/src/lib/libssl/ssl_tlsext.h b/src/lib/libssl/ssl_tlsext.h
index 7a41c8095d..da14f7fa94 100644
--- a/src/lib/libssl/ssl_tlsext.h
+++ b/src/lib/libssl/ssl_tlsext.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_tlsext.h,v 1.32 2022/08/04 09:27:36 tb Exp $ */ 1/* $OpenBSD: ssl_tlsext.h,v 1.33 2023/04/23 18:51:53 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -41,6 +41,7 @@ int tlsext_server_build(SSL *s, uint16_t msg_type, CBB *cbb);
41int tlsext_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert); 41int tlsext_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert);
42 42
43int tlsext_extension_seen(SSL *s, uint16_t); 43int tlsext_extension_seen(SSL *s, uint16_t);
44int tlsext_randomize_build_order(SSL *s);
44 45
45__END_HIDDEN_DECLS 46__END_HIDDEN_DECLS
46 47