summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2024-07-11 13:48:52 +0000
committertb <>2024-07-11 13:48:52 +0000
commit5260b37984fa00e9dd3c39361386fef0634a29dd (patch)
tree947607486d185911b8a164dcc91eb9258875c27a
parentaaeb6af9ab85685268769224ce8866d0f7a3a0a6 (diff)
downloadopenbsd-5260b37984fa00e9dd3c39361386fef0634a29dd.tar.gz
openbsd-5260b37984fa00e9dd3c39361386fef0634a29dd.tar.bz2
openbsd-5260b37984fa00e9dd3c39361386fef0634a29dd.zip
Follow BoringSSL's nomenclature in SSL_select_next_proto()
SSL_select_next_poto() was written with NPN in mind. NPN has a weird fallback mechanism which is baked into the API. This is makes no sense for ALPN, where the API behavior is undesirable since it a server should not end up choosing a protocol it doesn't (want to) support. Arguably, ALPN should simply have had its own API for protocol selection supporting the proper semantics, instead of shoehorning an NPN API into working for ALPN. Commit https://boringssl-review.googlesource.com/c/boringssl/+/17206/ renamed the arguments to work for both NPN and ALPN, with the slight downside of honoring client preference instead of the SHOULD in RFC 7301, section 3.2. This grates for most consumers in the wild, but so be it. The behavior is saner and safer. discussed with davidben ok beck
-rw-r--r--src/lib/libssl/ssl_lib.c58
1 files changed, 30 insertions, 28 deletions
diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c
index f5d477e864..d78cb2ac3a 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.325 2024/06/29 07:34:12 tb Exp $ */ 1/* $OpenBSD: ssl_lib.c,v 1.326 2024/07/11 13:48:52 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 *
@@ -1791,56 +1791,58 @@ LSSL_ALIAS(SSL_get_servername_type);
1791 */ 1791 */
1792int 1792int
1793SSL_select_next_proto(unsigned char **out, unsigned char *outlen, 1793SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
1794 const unsigned char *server_list, unsigned int server_list_len, 1794 const unsigned char *peer_list, unsigned int peer_list_len,
1795 const unsigned char *client_list, unsigned int client_list_len) 1795 const unsigned char *supported_list, unsigned int supported_list_len)
1796{ 1796{
1797 CBS client, client_proto, server, server_proto; 1797 CBS peer, peer_proto, supported, supported_proto;
1798 1798
1799 *out = NULL; 1799 *out = NULL;
1800 *outlen = 0; 1800 *outlen = 0;
1801 1801
1802 /* First check that the client list is well-formed. */ 1802 /* First check that the supported list is well-formed. */
1803 CBS_init(&client, client_list, client_list_len); 1803 CBS_init(&supported, supported_list, supported_list_len);
1804 if (!tlsext_alpn_check_format(&client)) 1804 if (!tlsext_alpn_check_format(&supported))
1805 goto err; 1805 goto err;
1806 1806
1807 /* 1807 /*
1808 * Use first client protocol as fallback. This is one way of doing NPN's 1808 * Use first supported protocol as fallback. This is one way of doing
1809 * "opportunistic" protocol selection (see security considerations in 1809 * NPN's "opportunistic" protocol selection (see security considerations
1810 * draft-agl-tls-nextprotoneg-04), and it is the documented behavior of 1810 * in draft-agl-tls-nextprotoneg-04), and it is the documented behavior
1811 * this API. For ALPN it's the callback's responsibility to fail on 1811 * of this API. For ALPN it's the callback's responsibility to fail on
1812 * OPENSSL_NPN_NO_OVERLAP. 1812 * OPENSSL_NPN_NO_OVERLAP.
1813 */ 1813 */
1814 1814
1815 if (!CBS_get_u8_length_prefixed(&client, &client_proto)) 1815 if (!CBS_get_u8_length_prefixed(&supported, &supported_proto))
1816 goto err; 1816 goto err;
1817 1817
1818 *out = (unsigned char *)CBS_data(&client_proto); 1818 *out = (unsigned char *)CBS_data(&supported_proto);
1819 *outlen = CBS_len(&client_proto); 1819 *outlen = CBS_len(&supported_proto);
1820 1820
1821 /* Now check that the server list is well-formed. */ 1821 /* Now check that the peer list is well-formed. */
1822 CBS_init(&server, server_list, server_list_len); 1822 CBS_init(&peer, peer_list, peer_list_len);
1823 if (!tlsext_alpn_check_format(&server)) 1823 if (!tlsext_alpn_check_format(&peer))
1824 goto err; 1824 goto err;
1825 1825
1826 /* 1826 /*
1827 * Walk the server list and select the first protocol that appears in 1827 * Walk the peer list and select the first protocol that appears in
1828 * the client list. 1828 * the supported list. Thus we honor peer preference rather than local
1829 * preference contrary to a SHOULD in RFC 7301, section 3.2.
1829 */ 1830 */
1830 while (CBS_len(&server) > 0) { 1831 while (CBS_len(&peer) > 0) {
1831 if (!CBS_get_u8_length_prefixed(&server, &server_proto)) 1832 if (!CBS_get_u8_length_prefixed(&peer, &peer_proto))
1832 goto err; 1833 goto err;
1833 1834
1834 CBS_init(&client, client_list, client_list_len); 1835 CBS_init(&supported, supported_list, supported_list_len);
1835 1836
1836 while (CBS_len(&client) > 0) { 1837 while (CBS_len(&supported) > 0) {
1837 if (!CBS_get_u8_length_prefixed(&client, &client_proto)) 1838 if (!CBS_get_u8_length_prefixed(&supported,
1839 &supported_proto))
1838 goto err; 1840 goto err;
1839 1841
1840 if (CBS_mem_equal(&client_proto, 1842 if (CBS_mem_equal(&supported_proto,
1841 CBS_data(&server_proto), CBS_len(&server_proto))) { 1843 CBS_data(&peer_proto), CBS_len(&peer_proto))) {
1842 *out = (unsigned char *)CBS_data(&server_proto); 1844 *out = (unsigned char *)CBS_data(&peer_proto);
1843 *outlen = CBS_len(&server_proto); 1845 *outlen = CBS_len(&peer_proto);
1844 1846
1845 return OPENSSL_NPN_NEGOTIATED; 1847 return OPENSSL_NPN_NEGOTIATED;
1846 } 1848 }