summaryrefslogtreecommitdiff
path: root/src/lib/libssl/ssl_tlsext.c
diff options
context:
space:
mode:
authortb <>2023-04-23 18:51:53 +0000
committertb <>2023-04-23 18:51:53 +0000
commitfb7a7adad4b566192144a21e4c93b739671b0cae (patch)
treefa6d649a58d3a734a4bc9dea3b97a71426074f8b /src/lib/libssl/ssl_tlsext.c
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
Diffstat (limited to 'src/lib/libssl/ssl_tlsext.c')
-rw-r--r--src/lib/libssl/ssl_tlsext.c63
1 files changed, 61 insertions, 2 deletions
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 */