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.
(cherry picked from commit f3cb03b52a)
Resolves: RHEL-45657
Signed-off-by: Clemens Lang <cllang@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									35940569f1
								
							
						
					
					
						commit
						8bdb45e21d
					
				
							
								
								
									
										109
									
								
								0124-Fix-SSL_select_next_proto.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								0124-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
									
								
								0126-Use-correctly-formatted-ALPN-data-in-tserver.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								0126-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
									
								
								0127-Clarify-the-SSL_select_next_proto-documentation.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								0127-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
									
								
								0128-Add-a-test-for-SSL_select_next_proto.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								0128-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
									
								
								0129-Allow-an-empty-NPN-ALPN-protocol-list-in-the-tests.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1169
									
								
								0129-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
									
								
								0131-Add-ALPN-validation-in-the-client.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								0131-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
									
								
								0132-Add-explicit-testing-of-ALN-and-NPN-in-sslapitest.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								0132-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
									
								
								0133-Add-a-test-for-an-empty-NextProto-message.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								0133-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: 3%{?dist} | Release: 4%{?dist} | ||||||
| Epoch: 1 | Epoch: 1 | ||||||
| # We have to remove certain patented algorithms from the openssl source | # We have to remove certain patented algorithms from the openssl source | ||||||
| # tarball with the hobble-openssl script which is included below. | # tarball with the hobble-openssl script which is included below. | ||||||
| @ -159,6 +159,17 @@ Patch121: 0121-FIPS-cms-defaults.patch | |||||||
| Patch122: 0122-TMP-KTLS-test-skip.patch | Patch122: 0122-TMP-KTLS-test-skip.patch | ||||||
| # HKDF regression with older provider implementations | # HKDF regression with older provider implementations | ||||||
| Patch123: 0123-kdf-Preserve-backward-compatibility-with-older-provi.patch | Patch123: 0123-kdf-Preserve-backward-compatibility-with-older-provi.patch | ||||||
|  | # https://github.com/openssl/openssl/pull/24717 | ||||||
|  | Patch124: 0124-Fix-SSL_select_next_proto.patch | ||||||
|  | Patch125: 0125-More-correctly-handle-a-selected_len-of-0-when-proce.patch | ||||||
|  | Patch126: 0126-Use-correctly-formatted-ALPN-data-in-tserver.patch | ||||||
|  | Patch127: 0127-Clarify-the-SSL_select_next_proto-documentation.patch | ||||||
|  | Patch128: 0128-Add-a-test-for-SSL_select_next_proto.patch | ||||||
|  | Patch129: 0129-Allow-an-empty-NPN-ALPN-protocol-list-in-the-tests.patch | ||||||
|  | Patch130: 0130-Correct-return-values-for-tls_construct_stoc_next_pr.patch | ||||||
|  | Patch131: 0131-Add-ALPN-validation-in-the-client.patch | ||||||
|  | Patch132: 0132-Add-explicit-testing-of-ALN-and-NPN-in-sslapitest.patch | ||||||
|  | Patch133: 0133-Add-a-test-for-an-empty-NextProto-message.patch | ||||||
| 
 | 
 | ||||||
| License: ASL 2.0 | License: ASL 2.0 | ||||||
| URL: http://www.openssl.org/ | URL: http://www.openssl.org/ | ||||||
| @ -498,6 +509,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-4 | ||||||
|  | - Fix CVE-2024-5535: SSL_select_next_proto buffer overread | ||||||
|  |   Resolves: RHEL-45657 | ||||||
|  | 
 | ||||||
| * Sat Jun 22 2024 Daiki Ueno <dueno@redhat.com> - 1:3.2.2-3 | * Sat Jun 22 2024 Daiki Ueno <dueno@redhat.com> - 1:3.2.2-3 | ||||||
| - Replace HKDF backward compatibility patch with the official one | - Replace HKDF backward compatibility patch with the official one | ||||||
|   Related: RHEL-40823 |   Related: RHEL-40823 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user