Fix CVE-2024-5535
The first patch caused a QUIC test to fail, so backport the entire series, which looks reasonable and adds good additional safeguards and checks. Resolves: RHEL-45692 Signed-off-by: Clemens Lang <cllang@redhat.com>
This commit is contained in:
parent
57fda30988
commit
f3cb03b52a
109
0129-Fix-SSL_select_next_proto.patch
Normal file
109
0129-Fix-SSL_select_next_proto.patch
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
From 99fb785a5f85315b95288921a321a935ea29a51e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@openssl.org>
|
||||||
|
Date: Fri, 31 May 2024 11:14:33 +0100
|
||||||
|
Subject: [PATCH 01/10] Fix SSL_select_next_proto
|
||||||
|
|
||||||
|
Ensure that the provided client list is non-NULL and starts with a valid
|
||||||
|
entry. When called from the ALPN callback the client list should already
|
||||||
|
have been validated by OpenSSL so this should not cause a problem. When
|
||||||
|
called from the NPN callback the client list is locally configured and
|
||||||
|
will not have already been validated. Therefore SSL_select_next_proto
|
||||||
|
should not assume that it is correctly formatted.
|
||||||
|
|
||||||
|
We implement stricter checking of the client protocol list. We also do the
|
||||||
|
same for the server list while we are about it.
|
||||||
|
|
||||||
|
CVE-2024-5535
|
||||||
|
|
||||||
|
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||||
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||||
|
(Merged from https://github.com/openssl/openssl/pull/24717)
|
||||||
|
---
|
||||||
|
ssl/ssl_lib.c | 63 ++++++++++++++++++++++++++++++++-------------------
|
||||||
|
1 file changed, 40 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
|
||||||
|
index 016135fe18..cf52b317cf 100644
|
||||||
|
--- a/ssl/ssl_lib.c
|
||||||
|
+++ b/ssl/ssl_lib.c
|
||||||
|
@@ -3518,37 +3518,54 @@ int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
|
||||||
|
unsigned int server_len,
|
||||||
|
const unsigned char *client, unsigned int client_len)
|
||||||
|
{
|
||||||
|
- unsigned int i, j;
|
||||||
|
- const unsigned char *result;
|
||||||
|
- int status = OPENSSL_NPN_UNSUPPORTED;
|
||||||
|
+ PACKET cpkt, csubpkt, spkt, ssubpkt;
|
||||||
|
+
|
||||||
|
+ if (!PACKET_buf_init(&cpkt, client, client_len)
|
||||||
|
+ || !PACKET_get_length_prefixed_1(&cpkt, &csubpkt)
|
||||||
|
+ || PACKET_remaining(&csubpkt) == 0) {
|
||||||
|
+ *out = NULL;
|
||||||
|
+ *outlen = 0;
|
||||||
|
+ return OPENSSL_NPN_NO_OVERLAP;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Set the default opportunistic protocol. Will be overwritten if we find
|
||||||
|
+ * a match.
|
||||||
|
+ */
|
||||||
|
+ *out = (unsigned char *)PACKET_data(&csubpkt);
|
||||||
|
+ *outlen = (unsigned char)PACKET_remaining(&csubpkt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For each protocol in server preference order, see if we support it.
|
||||||
|
*/
|
||||||
|
- for (i = 0; i < server_len;) {
|
||||||
|
- for (j = 0; j < client_len;) {
|
||||||
|
- if (server[i] == client[j] &&
|
||||||
|
- memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
|
||||||
|
- /* We found a match */
|
||||||
|
- result = &server[i];
|
||||||
|
- status = OPENSSL_NPN_NEGOTIATED;
|
||||||
|
- goto found;
|
||||||
|
+ if (PACKET_buf_init(&spkt, server, server_len)) {
|
||||||
|
+ while (PACKET_get_length_prefixed_1(&spkt, &ssubpkt)) {
|
||||||
|
+ if (PACKET_remaining(&ssubpkt) == 0)
|
||||||
|
+ continue; /* Invalid - ignore it */
|
||||||
|
+ if (PACKET_buf_init(&cpkt, client, client_len)) {
|
||||||
|
+ while (PACKET_get_length_prefixed_1(&cpkt, &csubpkt)) {
|
||||||
|
+ if (PACKET_equal(&csubpkt, PACKET_data(&ssubpkt),
|
||||||
|
+ PACKET_remaining(&ssubpkt))) {
|
||||||
|
+ /* We found a match */
|
||||||
|
+ *out = (unsigned char *)PACKET_data(&ssubpkt);
|
||||||
|
+ *outlen = (unsigned char)PACKET_remaining(&ssubpkt);
|
||||||
|
+ return OPENSSL_NPN_NEGOTIATED;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ /* Ignore spurious trailing bytes in the client list */
|
||||||
|
+ } else {
|
||||||
|
+ /* This should never happen */
|
||||||
|
+ return OPENSSL_NPN_NO_OVERLAP;
|
||||||
|
}
|
||||||
|
- j += client[j];
|
||||||
|
- j++;
|
||||||
|
}
|
||||||
|
- i += server[i];
|
||||||
|
- i++;
|
||||||
|
+ /* Ignore spurious trailing bytes in the server list */
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* There's no overlap between our protocols and the server's list. */
|
||||||
|
- result = client;
|
||||||
|
- status = OPENSSL_NPN_NO_OVERLAP;
|
||||||
|
-
|
||||||
|
- found:
|
||||||
|
- *out = (unsigned char *)result + 1;
|
||||||
|
- *outlen = result[0];
|
||||||
|
- return status;
|
||||||
|
+ /*
|
||||||
|
+ * There's no overlap between our protocols and the server's list. We use
|
||||||
|
+ * the default opportunistic protocol selected earlier
|
||||||
|
+ */
|
||||||
|
+ return OPENSSL_NPN_NO_OVERLAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
From 015255851371757d54c2560643eb3b3a88123cf1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@openssl.org>
|
||||||
|
Date: Fri, 31 May 2024 11:18:27 +0100
|
||||||
|
Subject: [PATCH 02/10] More correctly handle a selected_len of 0 when
|
||||||
|
processing NPN
|
||||||
|
|
||||||
|
In the case where the NPN callback returns with SSL_TLEXT_ERR_OK, but
|
||||||
|
the selected_len is 0 we should fail. Previously this would fail with an
|
||||||
|
internal_error alert because calling OPENSSL_malloc(selected_len) will
|
||||||
|
return NULL when selected_len is 0. We make this error detection more
|
||||||
|
explicit and return a handshake failure alert.
|
||||||
|
|
||||||
|
Follow on from CVE-2024-5535
|
||||||
|
|
||||||
|
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||||
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||||
|
(Merged from https://github.com/openssl/openssl/pull/24717)
|
||||||
|
---
|
||||||
|
ssl/statem/extensions_clnt.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
|
||||||
|
index 381a6c9d7b..1ab3c13d57 100644
|
||||||
|
--- a/ssl/statem/extensions_clnt.c
|
||||||
|
+++ b/ssl/statem/extensions_clnt.c
|
||||||
|
@@ -1560,8 +1560,8 @@ int tls_parse_stoc_npn(SSL_CONNECTION *s, PACKET *pkt, unsigned int context,
|
||||||
|
if (sctx->ext.npn_select_cb(SSL_CONNECTION_GET_SSL(s),
|
||||||
|
&selected, &selected_len,
|
||||||
|
PACKET_data(pkt), PACKET_remaining(pkt),
|
||||||
|
- sctx->ext.npn_select_cb_arg) !=
|
||||||
|
- SSL_TLSEXT_ERR_OK) {
|
||||||
|
+ sctx->ext.npn_select_cb_arg) != SSL_TLSEXT_ERR_OK
|
||||||
|
+ || selected_len == 0) {
|
||||||
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
34
0131-Use-correctly-formatted-ALPN-data-in-tserver.patch
Normal file
34
0131-Use-correctly-formatted-ALPN-data-in-tserver.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
From 6cc511826f09e513b4ec066d9b95acaf4f86d991 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@openssl.org>
|
||||||
|
Date: Fri, 31 May 2024 11:22:13 +0100
|
||||||
|
Subject: [PATCH 03/10] Use correctly formatted ALPN data in tserver
|
||||||
|
|
||||||
|
The QUIC test server was using incorrectly formatted ALPN data. With the
|
||||||
|
previous implementation of SSL_select_next_proto this went unnoticed. With
|
||||||
|
the new stricter implemenation it was failing.
|
||||||
|
|
||||||
|
Follow on from CVE-2024-5535
|
||||||
|
|
||||||
|
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||||
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||||
|
(Merged from https://github.com/openssl/openssl/pull/24717)
|
||||||
|
---
|
||||||
|
ssl/quic/quic_tserver.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c
|
||||||
|
index 86187d06ff..15694e723f 100644
|
||||||
|
--- a/ssl/quic/quic_tserver.c
|
||||||
|
+++ b/ssl/quic/quic_tserver.c
|
||||||
|
@@ -58,7 +58,7 @@ static int alpn_select_cb(SSL *ssl, const unsigned char **out,
|
||||||
|
|
||||||
|
if (srv->args.alpn == NULL) {
|
||||||
|
alpn = alpndeflt;
|
||||||
|
- alpnlen = sizeof(alpn);
|
||||||
|
+ alpnlen = sizeof(alpndeflt);
|
||||||
|
} else {
|
||||||
|
alpn = srv->args.alpn;
|
||||||
|
alpnlen = srv->args.alpnlen;
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
78
0132-Clarify-the-SSL_select_next_proto-documentation.patch
Normal file
78
0132-Clarify-the-SSL_select_next_proto-documentation.patch
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
From 8e81c57adbbf703dfb63955f65599765fdacc741 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@openssl.org>
|
||||||
|
Date: Fri, 31 May 2024 11:46:38 +0100
|
||||||
|
Subject: [PATCH 04/10] Clarify the SSL_select_next_proto() documentation
|
||||||
|
|
||||||
|
We clarify the input preconditions and the expected behaviour in the event
|
||||||
|
of no overlap.
|
||||||
|
|
||||||
|
Follow on from CVE-2024-5535
|
||||||
|
|
||||||
|
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||||
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||||
|
(Merged from https://github.com/openssl/openssl/pull/24717)
|
||||||
|
---
|
||||||
|
doc/man3/SSL_CTX_set_alpn_select_cb.pod | 26 +++++++++++++++++--------
|
||||||
|
1 file changed, 18 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/doc/man3/SSL_CTX_set_alpn_select_cb.pod b/doc/man3/SSL_CTX_set_alpn_select_cb.pod
|
||||||
|
index 05fee2fbec..79e1a252f6 100644
|
||||||
|
--- a/doc/man3/SSL_CTX_set_alpn_select_cb.pod
|
||||||
|
+++ b/doc/man3/SSL_CTX_set_alpn_select_cb.pod
|
||||||
|
@@ -52,7 +52,8 @@ SSL_select_next_proto, SSL_get0_alpn_selected, SSL_get0_next_proto_negotiated
|
||||||
|
SSL_CTX_set_alpn_protos() and SSL_set_alpn_protos() are used by the client to
|
||||||
|
set the list of protocols available to be negotiated. The B<protos> must be in
|
||||||
|
protocol-list format, described below. The length of B<protos> is specified in
|
||||||
|
-B<protos_len>.
|
||||||
|
+B<protos_len>. Setting B<protos_len> to 0 clears any existing list of ALPN
|
||||||
|
+protocols and no ALPN extension will be sent to the server.
|
||||||
|
|
||||||
|
SSL_CTX_set_alpn_select_cb() sets the application callback B<cb> used by a
|
||||||
|
server to select which protocol to use for the incoming connection. When B<cb>
|
||||||
|
@@ -73,9 +74,16 @@ B<server_len> and B<client>, B<client_len> must be in the protocol-list format
|
||||||
|
described below. The first item in the B<server>, B<server_len> list that
|
||||||
|
matches an item in the B<client>, B<client_len> list is selected, and returned
|
||||||
|
in B<out>, B<outlen>. The B<out> value will point into either B<server> or
|
||||||
|
-B<client>, so it should be copied immediately. If no match is found, the first
|
||||||
|
-item in B<client>, B<client_len> is returned in B<out>, B<outlen>. This
|
||||||
|
-function can also be used in the NPN callback.
|
||||||
|
+B<client>, so it should be copied immediately. The client list must include at
|
||||||
|
+least one valid (nonempty) protocol entry in the list.
|
||||||
|
+
|
||||||
|
+The SSL_select_next_proto() helper function can be useful from either the ALPN
|
||||||
|
+callback or the NPN callback (described below). If no match is found, the first
|
||||||
|
+item in B<client>, B<client_len> is returned in B<out>, B<outlen> and
|
||||||
|
+B<OPENSSL_NPN_NO_OVERLAP> is returned. This can be useful when implementating
|
||||||
|
+the NPN callback. In the ALPN case, the value returned in B<out> and B<outlen>
|
||||||
|
+must be ignored if B<OPENSSL_NPN_NO_OVERLAP> has been returned from
|
||||||
|
+SSL_select_next_proto().
|
||||||
|
|
||||||
|
SSL_CTX_set_next_proto_select_cb() sets a callback B<cb> that is called when a
|
||||||
|
client needs to select a protocol from the server's provided list, and a
|
||||||
|
@@ -85,9 +93,10 @@ must be set to point to the selected protocol (which may be within B<in>).
|
||||||
|
The length of the protocol name must be written into B<outlen>. The
|
||||||
|
server's advertised protocols are provided in B<in> and B<inlen>. The
|
||||||
|
callback can assume that B<in> is syntactically valid. The client must
|
||||||
|
-select a protocol. It is fatal to the connection if this callback returns
|
||||||
|
-a value other than B<SSL_TLSEXT_ERR_OK>. The B<arg> parameter is the pointer
|
||||||
|
-set via SSL_CTX_set_next_proto_select_cb().
|
||||||
|
+select a protocol (although it may be an empty, zero length protocol). It is
|
||||||
|
+fatal to the connection if this callback returns a value other than
|
||||||
|
+B<SSL_TLSEXT_ERR_OK> or if the zero length protocol is selected. The B<arg>
|
||||||
|
+parameter is the pointer set via SSL_CTX_set_next_proto_select_cb().
|
||||||
|
|
||||||
|
SSL_CTX_set_next_protos_advertised_cb() sets a callback B<cb> that is called
|
||||||
|
when a TLS server needs a list of supported protocols for Next Protocol
|
||||||
|
@@ -154,7 +163,8 @@ A match was found and is returned in B<out>, B<outlen>.
|
||||||
|
=item OPENSSL_NPN_NO_OVERLAP
|
||||||
|
|
||||||
|
No match was found. The first item in B<client>, B<client_len> is returned in
|
||||||
|
-B<out>, B<outlen>.
|
||||||
|
+B<out>, B<outlen> (or B<NULL> and 0 in the case where the first entry in
|
||||||
|
+B<client> is invalid).
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
172
0133-Add-a-test-for-SSL_select_next_proto.patch
Normal file
172
0133-Add-a-test-for-SSL_select_next_proto.patch
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
From add5c52a25c549cec4a730cdf96e2252f0a1862d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@openssl.org>
|
||||||
|
Date: Fri, 31 May 2024 16:35:16 +0100
|
||||||
|
Subject: [PATCH 05/10] Add a test for SSL_select_next_proto
|
||||||
|
|
||||||
|
Follow on from CVE-2024-5535
|
||||||
|
|
||||||
|
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||||
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||||
|
(Merged from https://github.com/openssl/openssl/pull/24717)
|
||||||
|
---
|
||||||
|
test/sslapitest.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 137 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/test/sslapitest.c b/test/sslapitest.c
|
||||||
|
index ce163322cd..15cb9060cb 100644
|
||||||
|
--- a/test/sslapitest.c
|
||||||
|
+++ b/test/sslapitest.c
|
||||||
|
@@ -11741,6 +11741,142 @@ static int test_multi_resume(int idx)
|
||||||
|
return testresult;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static struct next_proto_st {
|
||||||
|
+ int serverlen;
|
||||||
|
+ unsigned char server[40];
|
||||||
|
+ int clientlen;
|
||||||
|
+ unsigned char client[40];
|
||||||
|
+ int expected_ret;
|
||||||
|
+ size_t selectedlen;
|
||||||
|
+ unsigned char selected[40];
|
||||||
|
+} next_proto_tests[] = {
|
||||||
|
+ {
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ OPENSSL_NPN_NEGOTIATED,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 7, { 3, 'a', 'b', 'c', 2, 'a', 'b' },
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ OPENSSL_NPN_NEGOTIATED,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 7, { 2, 'a', 'b', 3, 'a', 'b', 'c', },
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ OPENSSL_NPN_NEGOTIATED,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ 7, { 3, 'a', 'b', 'c', 2, 'a', 'b', },
|
||||||
|
+ OPENSSL_NPN_NEGOTIATED,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ 7, { 2, 'a', 'b', 3, 'a', 'b', 'c'},
|
||||||
|
+ OPENSSL_NPN_NEGOTIATED,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 7, { 2, 'b', 'c', 3, 'a', 'b', 'c' },
|
||||||
|
+ 7, { 2, 'a', 'b', 3, 'a', 'b', 'c'},
|
||||||
|
+ OPENSSL_NPN_NEGOTIATED,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 10, { 2, 'b', 'c', 3, 'a', 'b', 'c', 2, 'a', 'b' },
|
||||||
|
+ 7, { 2, 'a', 'b', 3, 'a', 'b', 'c'},
|
||||||
|
+ OPENSSL_NPN_NEGOTIATED,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 4, { 3, 'b', 'c', 'd' },
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ OPENSSL_NPN_NO_OVERLAP,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 0, { 0 },
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ OPENSSL_NPN_NO_OVERLAP,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ -1, { 0 },
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ OPENSSL_NPN_NO_OVERLAP,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ 0, { 0 },
|
||||||
|
+ OPENSSL_NPN_NO_OVERLAP,
|
||||||
|
+ 0, { 0 }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ -1, { 0 },
|
||||||
|
+ OPENSSL_NPN_NO_OVERLAP,
|
||||||
|
+ 0, { 0 }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 3, { 3, 'a', 'b', 'c' },
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ OPENSSL_NPN_NO_OVERLAP,
|
||||||
|
+ 3, { 'a', 'b', 'c' }
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 4, { 3, 'a', 'b', 'c' },
|
||||||
|
+ 3, { 3, 'a', 'b', 'c' },
|
||||||
|
+ OPENSSL_NPN_NO_OVERLAP,
|
||||||
|
+ 0, { 0 }
|
||||||
|
+ }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int test_select_next_proto(int idx)
|
||||||
|
+{
|
||||||
|
+ struct next_proto_st *np = &next_proto_tests[idx];
|
||||||
|
+ int ret = 0;
|
||||||
|
+ unsigned char *out, *client, *server;
|
||||||
|
+ unsigned char outlen;
|
||||||
|
+ unsigned int clientlen, serverlen;
|
||||||
|
+
|
||||||
|
+ if (np->clientlen == -1) {
|
||||||
|
+ client = NULL;
|
||||||
|
+ clientlen = 0;
|
||||||
|
+ } else {
|
||||||
|
+ client = np->client;
|
||||||
|
+ clientlen = (unsigned int)np->clientlen;
|
||||||
|
+ }
|
||||||
|
+ if (np->serverlen == -1) {
|
||||||
|
+ server = NULL;
|
||||||
|
+ serverlen = 0;
|
||||||
|
+ } else {
|
||||||
|
+ server = np->server;
|
||||||
|
+ serverlen = (unsigned int)np->serverlen;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!TEST_int_eq(SSL_select_next_proto(&out, &outlen, server, serverlen,
|
||||||
|
+ client, clientlen),
|
||||||
|
+ np->expected_ret))
|
||||||
|
+ goto err;
|
||||||
|
+
|
||||||
|
+ if (np->selectedlen == 0) {
|
||||||
|
+ if (!TEST_ptr_null(out) || !TEST_uchar_eq(outlen, 0))
|
||||||
|
+ goto err;
|
||||||
|
+ } else {
|
||||||
|
+ if (!TEST_mem_eq(out, outlen, np->selected, np->selectedlen))
|
||||||
|
+ goto err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = 1;
|
||||||
|
+ err:
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n")
|
||||||
|
|
||||||
|
int setup_tests(void)
|
||||||
|
@@ -12053,6 +12189,7 @@ int setup_tests(void)
|
||||||
|
ADD_ALL_TESTS(test_handshake_retry, 16);
|
||||||
|
ADD_TEST(test_data_retry);
|
||||||
|
ADD_ALL_TESTS(test_multi_resume, 5);
|
||||||
|
+ ADD_ALL_TESTS(test_select_next_proto, OSSL_NELEM(next_proto_tests));
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
err:
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
1169
0134-Allow-an-empty-NPN-ALPN-protocol-list-in-the-tests.patch
Normal file
1169
0134-Allow-an-empty-NPN-ALPN-protocol-list-in-the-tests.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,39 @@
|
|||||||
|
From 53f5677f358c4a4f69830d944ea40e71950673b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@openssl.org>
|
||||||
|
Date: Fri, 21 Jun 2024 10:41:55 +0100
|
||||||
|
Subject: [PATCH 07/10] Correct return values for
|
||||||
|
tls_construct_stoc_next_proto_neg
|
||||||
|
|
||||||
|
Return EXT_RETURN_NOT_SENT in the event that we don't send the extension,
|
||||||
|
rather than EXT_RETURN_SENT. This actually makes no difference at all to
|
||||||
|
the current control flow since this return value is ignored in this case
|
||||||
|
anyway. But lets make it correct anyway.
|
||||||
|
|
||||||
|
Follow on from CVE-2024-5535
|
||||||
|
|
||||||
|
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||||
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||||
|
(Merged from https://github.com/openssl/openssl/pull/24717)
|
||||||
|
---
|
||||||
|
ssl/statem/extensions_srvr.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
|
||||||
|
index 800654450e..66ed7dacf2 100644
|
||||||
|
--- a/ssl/statem/extensions_srvr.c
|
||||||
|
+++ b/ssl/statem/extensions_srvr.c
|
||||||
|
@@ -1501,9 +1501,10 @@ EXT_RETURN tls_construct_stoc_next_proto_neg(SSL_CONNECTION *s, WPACKET *pkt,
|
||||||
|
return EXT_RETURN_FAIL;
|
||||||
|
}
|
||||||
|
s->s3.npn_seen = 1;
|
||||||
|
+ return EXT_RETURN_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return EXT_RETURN_SENT;
|
||||||
|
+ return EXT_RETURN_NOT_SENT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
62
0136-Add-ALPN-validation-in-the-client.patch
Normal file
62
0136-Add-ALPN-validation-in-the-client.patch
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
From 195e15421df113d7283aab2ccff8b8fb06df5465 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@openssl.org>
|
||||||
|
Date: Fri, 21 Jun 2024 11:51:54 +0100
|
||||||
|
Subject: [PATCH 08/10] Add ALPN validation in the client
|
||||||
|
|
||||||
|
The ALPN protocol selected by the server must be one that we originally
|
||||||
|
advertised. We should verify that it is.
|
||||||
|
|
||||||
|
Follow on from CVE-2024-5535
|
||||||
|
|
||||||
|
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||||
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||||
|
(Merged from https://github.com/openssl/openssl/pull/24717)
|
||||||
|
---
|
||||||
|
ssl/statem/extensions_clnt.c | 24 ++++++++++++++++++++++++
|
||||||
|
1 file changed, 24 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
|
||||||
|
index 1ab3c13d57..ff9c009ee5 100644
|
||||||
|
--- a/ssl/statem/extensions_clnt.c
|
||||||
|
+++ b/ssl/statem/extensions_clnt.c
|
||||||
|
@@ -1590,6 +1590,8 @@ int tls_parse_stoc_alpn(SSL_CONNECTION *s, PACKET *pkt, unsigned int context,
|
||||||
|
X509 *x, size_t chainidx)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
+ PACKET confpkt, protpkt;
|
||||||
|
+ int valid = 0;
|
||||||
|
|
||||||
|
/* We must have requested it. */
|
||||||
|
if (!s->s3.alpn_sent) {
|
||||||
|
@@ -1608,6 +1610,28 @@ int tls_parse_stoc_alpn(SSL_CONNECTION *s, PACKET *pkt, unsigned int context,
|
||||||
|
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /* It must be a protocol that we sent */
|
||||||
|
+ if (!PACKET_buf_init(&confpkt, s->ext.alpn, s->ext.alpn_len)) {
|
||||||
|
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ while (PACKET_get_length_prefixed_1(&confpkt, &protpkt)) {
|
||||||
|
+ if (PACKET_remaining(&protpkt) != len)
|
||||||
|
+ continue;
|
||||||
|
+ if (memcmp(PACKET_data(pkt), PACKET_data(&protpkt), len) == 0) {
|
||||||
|
+ /* Valid protocol found */
|
||||||
|
+ valid = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!valid) {
|
||||||
|
+ /* The protocol sent from the server does not match one we advertised */
|
||||||
|
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
OPENSSL_free(s->s3.alpn_selected);
|
||||||
|
s->s3.alpn_selected = OPENSSL_malloc(len);
|
||||||
|
if (s->s3.alpn_selected == NULL) {
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
267
0137-Add-explicit-testing-of-ALN-and-NPN-in-sslapitest.patch
Normal file
267
0137-Add-explicit-testing-of-ALN-and-NPN-in-sslapitest.patch
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
From 7c95191434415d1c9b7fe9b130df13cce630b6b5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@openssl.org>
|
||||||
|
Date: Fri, 21 Jun 2024 10:09:41 +0100
|
||||||
|
Subject: [PATCH 09/10] Add explicit testing of ALN and NPN in sslapitest
|
||||||
|
|
||||||
|
We already had some tests elsewhere - but this extends that testing with
|
||||||
|
additional tests.
|
||||||
|
|
||||||
|
Follow on from CVE-2024-5535
|
||||||
|
|
||||||
|
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||||
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||||
|
(Merged from https://github.com/openssl/openssl/pull/24717)
|
||||||
|
---
|
||||||
|
test/sslapitest.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 229 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/test/sslapitest.c b/test/sslapitest.c
|
||||||
|
index 15cb9060cb..7a55a2b721 100644
|
||||||
|
--- a/test/sslapitest.c
|
||||||
|
+++ b/test/sslapitest.c
|
||||||
|
@@ -11877,6 +11877,231 @@ static int test_select_next_proto(int idx)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static const unsigned char fooprot[] = {3, 'f', 'o', 'o' };
|
||||||
|
+static const unsigned char barprot[] = {3, 'b', 'a', 'r' };
|
||||||
|
+
|
||||||
|
+#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||||
|
+static int npn_advert_cb(SSL *ssl, const unsigned char **out,
|
||||||
|
+ unsigned int *outlen, void *arg)
|
||||||
|
+{
|
||||||
|
+ int *idx = (int *)arg;
|
||||||
|
+
|
||||||
|
+ switch (*idx) {
|
||||||
|
+ default:
|
||||||
|
+ case 0:
|
||||||
|
+ *out = fooprot;
|
||||||
|
+ *outlen = sizeof(fooprot);
|
||||||
|
+ return SSL_TLSEXT_ERR_OK;
|
||||||
|
+
|
||||||
|
+ case 1:
|
||||||
|
+ *outlen = 0;
|
||||||
|
+ return SSL_TLSEXT_ERR_OK;
|
||||||
|
+
|
||||||
|
+ case 2:
|
||||||
|
+ return SSL_TLSEXT_ERR_NOACK;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen,
|
||||||
|
+ const unsigned char *in, unsigned int inlen, void *arg)
|
||||||
|
+{
|
||||||
|
+ int *idx = (int *)arg;
|
||||||
|
+
|
||||||
|
+ switch (*idx) {
|
||||||
|
+ case 0:
|
||||||
|
+ case 1:
|
||||||
|
+ *out = (unsigned char *)(fooprot + 1);
|
||||||
|
+ *outlen = *fooprot;
|
||||||
|
+ return SSL_TLSEXT_ERR_OK;
|
||||||
|
+
|
||||||
|
+ case 3:
|
||||||
|
+ *out = (unsigned char *)(barprot + 1);
|
||||||
|
+ *outlen = *barprot;
|
||||||
|
+ return SSL_TLSEXT_ERR_OK;
|
||||||
|
+
|
||||||
|
+ case 4:
|
||||||
|
+ *outlen = 0;
|
||||||
|
+ return SSL_TLSEXT_ERR_OK;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ case 2:
|
||||||
|
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Test the NPN callbacks
|
||||||
|
+ * Test 0: advert = foo, select = foo
|
||||||
|
+ * Test 1: advert = <empty>, select = foo
|
||||||
|
+ * Test 2: no advert
|
||||||
|
+ * Test 3: advert = foo, select = bar
|
||||||
|
+ * Test 4: advert = foo, select = <empty> (should fail)
|
||||||
|
+ */
|
||||||
|
+static int test_npn(int idx)
|
||||||
|
+{
|
||||||
|
+ SSL_CTX *sctx = NULL, *cctx = NULL;
|
||||||
|
+ SSL *serverssl = NULL, *clientssl = NULL;
|
||||||
|
+ int testresult = 0;
|
||||||
|
+
|
||||||
|
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
|
||||||
|
+ TLS_client_method(), 0, TLS1_2_VERSION,
|
||||||
|
+ &sctx, &cctx, cert, privkey)))
|
||||||
|
+ goto end;
|
||||||
|
+
|
||||||
|
+ SSL_CTX_set_next_protos_advertised_cb(sctx, npn_advert_cb, &idx);
|
||||||
|
+ SSL_CTX_set_next_proto_select_cb(cctx, npn_select_cb, &idx);
|
||||||
|
+
|
||||||
|
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
|
||||||
|
+ NULL)))
|
||||||
|
+ goto end;
|
||||||
|
+
|
||||||
|
+ if (idx == 4) {
|
||||||
|
+ /* We don't allow empty selection of NPN, so this should fail */
|
||||||
|
+ if (!TEST_false(create_ssl_connection(serverssl, clientssl,
|
||||||
|
+ SSL_ERROR_NONE)))
|
||||||
|
+ goto end;
|
||||||
|
+ } else {
|
||||||
|
+ const unsigned char *prot;
|
||||||
|
+ unsigned int protlen;
|
||||||
|
+
|
||||||
|
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl,
|
||||||
|
+ SSL_ERROR_NONE)))
|
||||||
|
+ goto end;
|
||||||
|
+
|
||||||
|
+ SSL_get0_next_proto_negotiated(serverssl, &prot, &protlen);
|
||||||
|
+ switch (idx) {
|
||||||
|
+ case 0:
|
||||||
|
+ case 1:
|
||||||
|
+ if (!TEST_mem_eq(prot, protlen, fooprot + 1, *fooprot))
|
||||||
|
+ goto end;
|
||||||
|
+ break;
|
||||||
|
+ case 2:
|
||||||
|
+ if (!TEST_uint_eq(protlen, 0))
|
||||||
|
+ goto end;
|
||||||
|
+ break;
|
||||||
|
+ case 3:
|
||||||
|
+ if (!TEST_mem_eq(prot, protlen, barprot + 1, *barprot))
|
||||||
|
+ goto end;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ TEST_error("Should not get here");
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ testresult = 1;
|
||||||
|
+ end:
|
||||||
|
+ SSL_free(serverssl);
|
||||||
|
+ SSL_free(clientssl);
|
||||||
|
+ SSL_CTX_free(sctx);
|
||||||
|
+ SSL_CTX_free(cctx);
|
||||||
|
+
|
||||||
|
+ return testresult;
|
||||||
|
+}
|
||||||
|
+#endif /* !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG) */
|
||||||
|
+
|
||||||
|
+static int alpn_select_cb2(SSL *ssl, const unsigned char **out,
|
||||||
|
+ unsigned char *outlen, const unsigned char *in,
|
||||||
|
+ unsigned int inlen, void *arg)
|
||||||
|
+{
|
||||||
|
+ int *idx = (int *)arg;
|
||||||
|
+
|
||||||
|
+ switch (*idx) {
|
||||||
|
+ case 0:
|
||||||
|
+ *out = (unsigned char *)(fooprot + 1);
|
||||||
|
+ *outlen = *fooprot;
|
||||||
|
+ return SSL_TLSEXT_ERR_OK;
|
||||||
|
+
|
||||||
|
+ case 2:
|
||||||
|
+ *out = (unsigned char *)(barprot + 1);
|
||||||
|
+ *outlen = *barprot;
|
||||||
|
+ return SSL_TLSEXT_ERR_OK;
|
||||||
|
+
|
||||||
|
+ case 3:
|
||||||
|
+ *outlen = 0;
|
||||||
|
+ return SSL_TLSEXT_ERR_OK;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ case 1:
|
||||||
|
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Test the ALPN callbacks
|
||||||
|
+ * Test 0: client = foo, select = foo
|
||||||
|
+ * Test 1: client = <empty>, select = none
|
||||||
|
+ * Test 2: client = foo, select = bar (should fail)
|
||||||
|
+ * Test 3: client = foo, select = <empty> (should fail)
|
||||||
|
+ */
|
||||||
|
+static int test_alpn(int idx)
|
||||||
|
+{
|
||||||
|
+ SSL_CTX *sctx = NULL, *cctx = NULL;
|
||||||
|
+ SSL *serverssl = NULL, *clientssl = NULL;
|
||||||
|
+ int testresult = 0;
|
||||||
|
+ const unsigned char *prots = fooprot;
|
||||||
|
+ unsigned int protslen = sizeof(fooprot);
|
||||||
|
+
|
||||||
|
+ if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
|
||||||
|
+ TLS_client_method(), 0, 0,
|
||||||
|
+ &sctx, &cctx, cert, privkey)))
|
||||||
|
+ goto end;
|
||||||
|
+
|
||||||
|
+ SSL_CTX_set_alpn_select_cb(sctx, alpn_select_cb2, &idx);
|
||||||
|
+
|
||||||
|
+ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
|
||||||
|
+ NULL)))
|
||||||
|
+ goto end;
|
||||||
|
+
|
||||||
|
+ if (idx == 1) {
|
||||||
|
+ prots = NULL;
|
||||||
|
+ protslen = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* SSL_set_alpn_protos returns 0 for success! */
|
||||||
|
+ if (!TEST_false(SSL_set_alpn_protos(clientssl, prots, protslen)))
|
||||||
|
+ goto end;
|
||||||
|
+
|
||||||
|
+ if (idx == 2 || idx == 3) {
|
||||||
|
+ /* We don't allow empty selection of NPN, so this should fail */
|
||||||
|
+ if (!TEST_false(create_ssl_connection(serverssl, clientssl,
|
||||||
|
+ SSL_ERROR_NONE)))
|
||||||
|
+ goto end;
|
||||||
|
+ } else {
|
||||||
|
+ const unsigned char *prot;
|
||||||
|
+ unsigned int protlen;
|
||||||
|
+
|
||||||
|
+ if (!TEST_true(create_ssl_connection(serverssl, clientssl,
|
||||||
|
+ SSL_ERROR_NONE)))
|
||||||
|
+ goto end;
|
||||||
|
+
|
||||||
|
+ SSL_get0_alpn_selected(clientssl, &prot, &protlen);
|
||||||
|
+ switch (idx) {
|
||||||
|
+ case 0:
|
||||||
|
+ if (!TEST_mem_eq(prot, protlen, fooprot + 1, *fooprot))
|
||||||
|
+ goto end;
|
||||||
|
+ break;
|
||||||
|
+ case 1:
|
||||||
|
+ if (!TEST_uint_eq(protlen, 0))
|
||||||
|
+ goto end;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ TEST_error("Should not get here");
|
||||||
|
+ goto end;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ testresult = 1;
|
||||||
|
+ end:
|
||||||
|
+ SSL_free(serverssl);
|
||||||
|
+ SSL_free(clientssl);
|
||||||
|
+ SSL_CTX_free(sctx);
|
||||||
|
+ SSL_CTX_free(cctx);
|
||||||
|
+
|
||||||
|
+ return testresult;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n")
|
||||||
|
|
||||||
|
int setup_tests(void)
|
||||||
|
@@ -12190,6 +12415,10 @@ int setup_tests(void)
|
||||||
|
ADD_TEST(test_data_retry);
|
||||||
|
ADD_ALL_TESTS(test_multi_resume, 5);
|
||||||
|
ADD_ALL_TESTS(test_select_next_proto, OSSL_NELEM(next_proto_tests));
|
||||||
|
+#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||||
|
+ ADD_ALL_TESTS(test_npn, 5);
|
||||||
|
+#endif
|
||||||
|
+ ADD_ALL_TESTS(test_alpn, 4);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
err:
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
199
0138-Add-a-test-for-an-empty-NextProto-message.patch
Normal file
199
0138-Add-a-test-for-an-empty-NextProto-message.patch
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
From 301b870546d1c7b2d8f0d66e04a2596142f0399f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matt Caswell <matt@openssl.org>
|
||||||
|
Date: Fri, 21 Jun 2024 14:29:26 +0100
|
||||||
|
Subject: [PATCH 10/10] Add a test for an empty NextProto message
|
||||||
|
|
||||||
|
It is valid according to the spec for a NextProto message to have no
|
||||||
|
protocols listed in it. The OpenSSL implementation however does not allow
|
||||||
|
us to create such a message. In order to check that we work as expected
|
||||||
|
when communicating with a client that does generate such messages we have
|
||||||
|
to use a TLSProxy test.
|
||||||
|
|
||||||
|
Follow on from CVE-2024-5535
|
||||||
|
|
||||||
|
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||||
|
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||||
|
(Merged from https://github.com/openssl/openssl/pull/24717)
|
||||||
|
---
|
||||||
|
test/recipes/70-test_npn.t | 73 +++++++++++++++++++++++++++++++++
|
||||||
|
util/perl/TLSProxy/Message.pm | 9 ++++
|
||||||
|
util/perl/TLSProxy/NextProto.pm | 54 ++++++++++++++++++++++++
|
||||||
|
util/perl/TLSProxy/Proxy.pm | 1 +
|
||||||
|
4 files changed, 137 insertions(+)
|
||||||
|
create mode 100644 test/recipes/70-test_npn.t
|
||||||
|
create mode 100644 util/perl/TLSProxy/NextProto.pm
|
||||||
|
|
||||||
|
diff --git a/test/recipes/70-test_npn.t b/test/recipes/70-test_npn.t
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..f82e71af6a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/test/recipes/70-test_npn.t
|
||||||
|
@@ -0,0 +1,73 @@
|
||||||
|
+#! /usr/bin/env perl
|
||||||
|
+# Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
+#
|
||||||
|
+# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
|
+# this file except in compliance with the License. You can obtain a copy
|
||||||
|
+# in the file LICENSE in the source distribution or at
|
||||||
|
+# https://www.openssl.org/source/license.html
|
||||||
|
+
|
||||||
|
+use strict;
|
||||||
|
+use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file/;
|
||||||
|
+use OpenSSL::Test::Utils;
|
||||||
|
+
|
||||||
|
+use TLSProxy::Proxy;
|
||||||
|
+
|
||||||
|
+my $test_name = "test_npn";
|
||||||
|
+setup($test_name);
|
||||||
|
+
|
||||||
|
+plan skip_all => "TLSProxy isn't usable on $^O"
|
||||||
|
+ if $^O =~ /^(VMS)$/;
|
||||||
|
+
|
||||||
|
+plan skip_all => "$test_name needs the dynamic engine feature enabled"
|
||||||
|
+ if disabled("engine") || disabled("dynamic-engine");
|
||||||
|
+
|
||||||
|
+plan skip_all => "$test_name needs the sock feature enabled"
|
||||||
|
+ if disabled("sock");
|
||||||
|
+
|
||||||
|
+plan skip_all => "$test_name needs NPN enabled"
|
||||||
|
+ if disabled("nextprotoneg");
|
||||||
|
+
|
||||||
|
+plan skip_all => "$test_name needs TLSv1.2 enabled"
|
||||||
|
+ if disabled("tls1_2");
|
||||||
|
+
|
||||||
|
+my $proxy = TLSProxy::Proxy->new(
|
||||||
|
+ undef,
|
||||||
|
+ cmdstr(app(["openssl"]), display => 1),
|
||||||
|
+ srctop_file("apps", "server.pem"),
|
||||||
|
+ (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
|
||||||
|
+);
|
||||||
|
+
|
||||||
|
+$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
|
||||||
|
+plan tests => 1;
|
||||||
|
+
|
||||||
|
+my $npnseen = 0;
|
||||||
|
+
|
||||||
|
+# Test 1: Check sending an empty NextProto message from the client works. This is
|
||||||
|
+# valid as per the spec, but OpenSSL does not allow you to send it.
|
||||||
|
+# Therefore we must be prepared to receive such a message but we cannot
|
||||||
|
+# generate it except via TLSProxy
|
||||||
|
+$proxy->clear();
|
||||||
|
+$proxy->filter(\&npn_filter);
|
||||||
|
+$proxy->clientflags("-nextprotoneg foo -no_tls1_3");
|
||||||
|
+$proxy->serverflags("-nextprotoneg foo");
|
||||||
|
+$proxy->start();
|
||||||
|
+ok($npnseen && TLSProxy::Message->success(), "Empty NPN message");
|
||||||
|
+
|
||||||
|
+sub npn_filter
|
||||||
|
+{
|
||||||
|
+ my $proxy = shift;
|
||||||
|
+ my $message;
|
||||||
|
+
|
||||||
|
+ # The NextProto message always appears in flight 2
|
||||||
|
+ return if $proxy->flight != 2;
|
||||||
|
+
|
||||||
|
+ foreach my $message (@{$proxy->message_list}) {
|
||||||
|
+ if ($message->mt == TLSProxy::Message::MT_NEXT_PROTO) {
|
||||||
|
+ # Our TLSproxy NextProto message support doesn't support parsing of
|
||||||
|
+ # the message. If we repack it just creates an empty NextProto
|
||||||
|
+ # message - which is exactly the scenario we want to test here.
|
||||||
|
+ $message->repack();
|
||||||
|
+ $npnseen = 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm
|
||||||
|
index ce22187569..fb41b2ffc8 100644
|
||||||
|
--- a/util/perl/TLSProxy/Message.pm
|
||||||
|
+++ b/util/perl/TLSProxy/Message.pm
|
||||||
|
@@ -384,6 +384,15 @@ sub create_message
|
||||||
|
[@message_frag_lens]
|
||||||
|
);
|
||||||
|
$message->parse();
|
||||||
|
+ } elsif ($mt == MT_NEXT_PROTO) {
|
||||||
|
+ $message = TLSProxy::NextProto->new(
|
||||||
|
+ $server,
|
||||||
|
+ $data,
|
||||||
|
+ [@message_rec_list],
|
||||||
|
+ $startoffset,
|
||||||
|
+ [@message_frag_lens]
|
||||||
|
+ );
|
||||||
|
+ $message->parse();
|
||||||
|
} else {
|
||||||
|
#Unknown message type
|
||||||
|
$message = TLSProxy::Message->new(
|
||||||
|
diff --git a/util/perl/TLSProxy/NextProto.pm b/util/perl/TLSProxy/NextProto.pm
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..0e18347546
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/util/perl/TLSProxy/NextProto.pm
|
||||||
|
@@ -0,0 +1,54 @@
|
||||||
|
+# Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
+#
|
||||||
|
+# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
|
+# this file except in compliance with the License. You can obtain a copy
|
||||||
|
+# in the file LICENSE in the source distribution or at
|
||||||
|
+# https://www.openssl.org/source/license.html
|
||||||
|
+
|
||||||
|
+use strict;
|
||||||
|
+
|
||||||
|
+package TLSProxy::NextProto;
|
||||||
|
+
|
||||||
|
+use vars '@ISA';
|
||||||
|
+push @ISA, 'TLSProxy::Message';
|
||||||
|
+
|
||||||
|
+sub new
|
||||||
|
+{
|
||||||
|
+ my $class = shift;
|
||||||
|
+ my ($server,
|
||||||
|
+ $data,
|
||||||
|
+ $records,
|
||||||
|
+ $startoffset,
|
||||||
|
+ $message_frag_lens) = @_;
|
||||||
|
+
|
||||||
|
+ my $self = $class->SUPER::new(
|
||||||
|
+ $server,
|
||||||
|
+ TLSProxy::Message::MT_NEXT_PROTO,
|
||||||
|
+ $data,
|
||||||
|
+ $records,
|
||||||
|
+ $startoffset,
|
||||||
|
+ $message_frag_lens);
|
||||||
|
+
|
||||||
|
+ return $self;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+sub parse
|
||||||
|
+{
|
||||||
|
+ # We don't support parsing at the moment
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+# This is supposed to reconstruct the on-the-wire message data following changes.
|
||||||
|
+# For now though since we don't support parsing we just create an empty NextProto
|
||||||
|
+# message - this capability is used in test_npn
|
||||||
|
+sub set_message_contents
|
||||||
|
+{
|
||||||
|
+ my $self = shift;
|
||||||
|
+ my $data;
|
||||||
|
+
|
||||||
|
+ $data = pack("C32", 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
+ 0x00, 0x00, 0x00);
|
||||||
|
+ $self->data($data);
|
||||||
|
+}
|
||||||
|
+1;
|
||||||
|
diff --git a/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm
|
||||||
|
index 3de10eccb9..b707722b6b 100644
|
||||||
|
--- a/util/perl/TLSProxy/Proxy.pm
|
||||||
|
+++ b/util/perl/TLSProxy/Proxy.pm
|
||||||
|
@@ -23,6 +23,7 @@ use TLSProxy::CertificateRequest;
|
||||||
|
use TLSProxy::CertificateVerify;
|
||||||
|
use TLSProxy::ServerKeyExchange;
|
||||||
|
use TLSProxy::NewSessionTicket;
|
||||||
|
+use TLSProxy::NextProto;
|
||||||
|
|
||||||
|
my $have_IPv6;
|
||||||
|
my $IP_factory;
|
||||||
|
--
|
||||||
|
2.46.0
|
||||||
|
|
17
openssl.spec
17
openssl.spec
@ -29,7 +29,7 @@ print(string.sub(hash, 0, 16))
|
|||||||
Summary: Utilities from the general purpose cryptography library with TLS implementation
|
Summary: Utilities from the general purpose cryptography library with TLS implementation
|
||||||
Name: openssl
|
Name: openssl
|
||||||
Version: 3.2.2
|
Version: 3.2.2
|
||||||
Release: 10%{?dist}
|
Release: 11%{?dist}
|
||||||
Epoch: 1
|
Epoch: 1
|
||||||
Source: openssl-%{version}.tar.gz
|
Source: openssl-%{version}.tar.gz
|
||||||
Source2: Makefile.certificate
|
Source2: Makefile.certificate
|
||||||
@ -169,6 +169,17 @@ Patch126: 0126-pkeyutl-encap.patch
|
|||||||
# https://github.com/openssl/openssl/issues/25056
|
# https://github.com/openssl/openssl/issues/25056
|
||||||
Patch127: 0127-speedup-SSL_add_cert_subjects_to_stack.patch
|
Patch127: 0127-speedup-SSL_add_cert_subjects_to_stack.patch
|
||||||
Patch128: 0128-SAST-findings.patch
|
Patch128: 0128-SAST-findings.patch
|
||||||
|
# https://github.com/openssl/openssl/pull/24717
|
||||||
|
Patch129: 0129-Fix-SSL_select_next_proto.patch
|
||||||
|
Patch130: 0130-More-correctly-handle-a-selected_len-of-0-when-proce.patch
|
||||||
|
Patch131: 0131-Use-correctly-formatted-ALPN-data-in-tserver.patch
|
||||||
|
Patch132: 0132-Clarify-the-SSL_select_next_proto-documentation.patch
|
||||||
|
Patch133: 0133-Add-a-test-for-SSL_select_next_proto.patch
|
||||||
|
Patch134: 0134-Allow-an-empty-NPN-ALPN-protocol-list-in-the-tests.patch
|
||||||
|
Patch135: 0135-Correct-return-values-for-tls_construct_stoc_next_pr.patch
|
||||||
|
Patch136: 0136-Add-ALPN-validation-in-the-client.patch
|
||||||
|
Patch137: 0137-Add-explicit-testing-of-ALN-and-NPN-in-sslapitest.patch
|
||||||
|
Patch138: 0138-Add-a-test-for-an-empty-NextProto-message.patch
|
||||||
|
|
||||||
License: Apache-2.0
|
License: Apache-2.0
|
||||||
URL: http://www.openssl.org/
|
URL: http://www.openssl.org/
|
||||||
@ -514,6 +525,10 @@ ln -s /etc/crypto-policies/back-ends/openssl_fips.config $RPM_BUILD_ROOT%{_sysco
|
|||||||
%ldconfig_scriptlets libs
|
%ldconfig_scriptlets libs
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Aug 21 2024 Clemens Lang <cllang@redhat.com> - 1:3.2.2-11
|
||||||
|
- Fix CVE-2024-5535: SSL_select_next_proto buffer overread
|
||||||
|
Resolves: RHEL-45692
|
||||||
|
|
||||||
* Wed Aug 14 2024 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:3.2.2-10
|
* Wed Aug 14 2024 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:3.2.2-10
|
||||||
- Use PBMAC1 by default when creating PKCS#12 files in FIPS mode
|
- Use PBMAC1 by default when creating PKCS#12 files in FIPS mode
|
||||||
Related: RHEL-36659
|
Related: RHEL-36659
|
||||||
|
Loading…
Reference in New Issue
Block a user