From f313d342a2dffc44c39d99c1cb563be55ae6242f Mon Sep 17 00:00:00 2001 From: tb Date: Thu, 27 Apr 2023 10:53:58 +0000 Subject: [PATCH] tlsexttest: check additional logic in tlsext randomization This verifies that we put PSK always last and that the Apache 2 special does what it is supposed to do. There is also some weak validation of the Fisher-Yates shuffle that will likely catch errors introduced in tlsext_randomize_build_order() --- regress/lib/libssl/tlsext/tlsexttest.c | 104 ++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/regress/lib/libssl/tlsext/tlsexttest.c b/regress/lib/libssl/tlsext/tlsexttest.c index f5241c8f626..2da1b6487bb 100644 --- a/regress/lib/libssl/tlsext/tlsexttest.c +++ b/regress/lib/libssl/tlsext/tlsexttest.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tlsexttest.c,v 1.80 2023/04/23 18:59:41 tb Exp $ */ +/* $OpenBSD: tlsexttest.c,v 1.81 2023/04/27 10:53:58 tb Exp $ */ /* * Copyright (c) 2017 Joel Sing * Copyright (c) 2017 Doug Hogan @@ -33,6 +33,7 @@ struct tls_extension_funcs { int (*parse)(SSL *s, uint16_t msg_type, CBS *cbs, int *alert); }; +uint16_t tls_extension_type(const struct tls_extension *); const struct tls_extension *tls_extension_find(uint16_t, size_t *); const struct tls_extension_funcs *tlsext_funcs(const struct tls_extension *, int); @@ -4442,6 +4443,105 @@ test_tlsext_valid_hostnames(void) return failure; } +#define N_TLSEXT_RANDOMIZATION_TESTS 1000 + +static int +test_tlsext_check_extension_order(SSL *ssl) +{ + const struct tls_extension *ext; + uint16_t type; + size_t alpn_idx, sni_idx; + size_t i; + + if (ssl->tlsext_build_order_len == 0) { + FAIL("Unexpected zero build order length"); + return 1; + } + + ext = ssl->tlsext_build_order[ssl->tlsext_build_order_len - 1]; + if ((type = tls_extension_type(ext)) != TLSEXT_TYPE_psk) { + FAIL("last extension is %u, want %u\n", type, TLSEXT_TYPE_psk); + return 1; + } + + if (ssl->server) + return 0; + + alpn_idx = sni_idx = ssl->tlsext_build_order_len; + for (i = 0; i < ssl->tlsext_build_order_len; i++) { + ext = ssl->tlsext_build_order[i]; + if (tls_extension_type(ext) == TLSEXT_TYPE_alpn) + alpn_idx = i; + if (tls_extension_type(ext) == TLSEXT_TYPE_server_name) + sni_idx = i; + } + + if (alpn_idx == ssl->tlsext_build_order_len) { + FAIL("could not find alpn extension\n"); + return 1; + } + + if (sni_idx == ssl->tlsext_build_order_len) { + FAIL("could not find alpn extension\n"); + return 1; + } + + if (sni_idx >= alpn_idx) { + FAIL("sni does not precede alpn: %zu >= %zu\n", + sni_idx, alpn_idx); + return 1; + } + + return 0; +} + +static int +test_tlsext_randomized_extensions(SSL *ssl) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_TLSEXT_RANDOMIZATION_TESTS; i++) { + if (!tlsext_randomize_build_order(ssl)) + errx(1, "failed to randomize extensions"); + failed |= test_tlsext_check_extension_order(ssl); + } + + return failed; +} + +static int +test_tlsext_extension_order(void) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int failure; + + failure = 0; + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + failure |= test_tlsext_randomized_extensions(ssl); + + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + failure |= test_tlsext_randomized_extensions(ssl); + + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return failure; +} + int main(int argc, char **argv) { @@ -4500,5 +4600,7 @@ main(int argc, char **argv) failed |= test_tlsext_quic_transport_parameters_client(); failed |= test_tlsext_quic_transport_parameters_server(); + failed |= test_tlsext_extension_order(); + return (failed); } -- 2.20.1