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 | ||||
| Name: openssl | ||||
| Version: 3.2.2 | ||||
| Release: 3%{?dist} | ||||
| Release: 4%{?dist} | ||||
| Epoch: 1 | ||||
| # We have to remove certain patented algorithms from the openssl source | ||||
| # 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 | ||||
| # HKDF regression with older provider implementations | ||||
| 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 | ||||
| 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 | ||||
| 
 | ||||
| %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 | ||||
| - Replace HKDF backward compatibility patch with the official one | ||||
|   Related: RHEL-40823 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user