Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handshake failed: error:1400A09F:SSL routines:CONNECT_CR_CERT_REQ:length mismatch #950

Open
jpavco-quadient opened this issue Nov 22, 2023 · 3 comments

Comments

@jpavco-quadient
Copy link

Hello,

I can't connect to server https://api.communicalia.com with LibreSSL. Connection failed on handshake:

handshake failed: error:1400A09F:SSL routines:CONNECT_CR_CERT_REQ:length mismatch

I have simple c++ application to try it:

#include <stdlib.h>
#include <stdio.h>
#include "tls.h"

int main(int argc, char* argv[]) {
	if (argc != 3) {
		printf("Usage: %s hostname port\n", argv[0]);
		return 1;
	}

	tls_config *mTLSConfig = tls_config_new();
	tls *mTLS = tls_client();
	tls_config_set_protocols(mTLSConfig, TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3);
	tls_configure(mTLS, mTLSConfig);
	
	if (tls_connect(mTLS, argv[1], argv[2]) != 0)
		{
		const char* error = tls_error(mTLS);
		printf("tls_connect failed: %s\n", error);
		return 2;
		}

	if (tls_handshake(mTLS) != 0)
		{
		const char* error = tls_error(mTLS);
		printf("tls_handshake failed: %s\n", error);
		return 2;
		}

	printf("TLS handhake has sucess\n");
	tls_close(mTLS);
	tls_free(mTLS);
	tls_config_free(mTLSConfig);
	return 0;
}

I built it by:

[developer@2d4e2a14d2bc data]# g++ /data/libressl-handshake-test/main.cpp -o handshake-test -I/data/libressl/include -L/data/libressl/lib/ -Wl,-rpath /data/libressl/lib -lcrypto -lssl -ltls

I linked it with different version of LibreSSL (v3.5.3, v3.6.3, v3.7.3, v3.8.2), but handshake to this server has failed with every tested version:

[developer@2d4e2a14d2bc data]# ./handshake-test api.communicalia.com 443
tls_handshake failed: handshake failed: error:1400A09F:SSL routines:CONNECT_CR_CERT_REQ:length mismatch

I found in curl output, that server requires client certificate:

curl -v https://api.communicalia.com
*   Trying 52.50.170.116:443...
* Connected to api.communicalia.com (52.50.170.116) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=*.communicalia.com
*  start date: Mar  9 00:00:00 2023 GMT
*  expire date: Apr  8 23:59:59 2024 GMT
*  subjectAltName: host "api.communicalia.com" matched cert's "*.communicalia.com"
*  issuer: C=ES; ST=Illes Balears; L=Manacor; O=Soluciones Corporativas IP, SL; CN=Don Dominio / MrDomain RSA DV CA
*  SSL certificate verify ok.

Handshake failed with TLSv1.3. When I downgrade tls version to 1.2, handshake successes.

Why does handshake fail in connection to this server? It is bug in implementation of TLSv1.3 in LibreSSL?

Thanks,
Jakub

@botovq
Copy link
Contributor

botovq commented Nov 22, 2023

The error you are hitting is this error in ssl_tlsext_ocsp_client_parse():

	if (ssl_effective_tls_version(s) >= TLS1_3_VERSION) {
		if (msg_type == SSL_TLSEXT_MSG_CR) {
			/*
			 * RFC 8446, 4.4.2.1 - the server may request an OCSP
			 * response with an empty status_request.
			 */
			if (CBS_len(cbs) == 0)
				return 1;

			SSLerror(s, SSL_R_LENGTH_MISMATCH);
			return 0;
		}
	...

If you comment out the SSLerror and the return 0 the handshake completes. The point is that the server sends its OCSP response data as part of the CertificateRequest.

However, RFC 8446, section 4.4.2.1 says this:

   In TLS 1.3, the server's OCSP information is carried in an extension in 
   the CertificateEntry containing the associated certificate.

The definition of the CertificateRequest does not mention CertificateEntry . There is the exception mentioned in the comment that the server may request an OCSP status for the client's cert by sending an empty OCSP extension as part of the CertificateRequest.

Now we seem to be stricter than OpenSSL who complete the handshake, but gnutls-cli doesn't seem to be able to connect to this server either:

$ gnutls-cli --ocsp -V api.communicalia.com
Processed 134 CA certificate(s).
Resolving 'api.communicalia.com:443'...
Connecting to '52.50.170.116:443'...
*** Fatal error: Error decoding the received TLS packet.

So I'd argue this is the server misbehaving, not a LibreSSL bug.

Added: Running gnutls-cli with -d 3, we see this:

...
|<3>| ASSERT: buffers.c[get_last_packet]:1139
|<3>| ASSERT: buffers.c[get_last_packet]:1139
|<3>| ASSERT: tls13/certificate_request.c[parse_cert_extension]:125
|<3>| ASSERT: extv.c[_gnutls_extv_parse]:71
|<3>| ASSERT: tls13/certificate_request.c[_gnutls13_recv_certificate_request_int]:201
|<3>| ASSERT: handshake-tls13.c[_gnutls13_handshake_client]:123
*** Fatal error: Error decoding the received TLS packet.

Which points at this code in tls13/certificate_request.c:

	} else if (tls_id == ext_mod_status_request.tls_id) {
		if (data_size != 0)
			return gnutls_assert_val(
				GNUTLS_E_TLS_PACKET_DECODING_ERROR);

which is precisely the same check as we have.

@jpavco-quadient
Copy link
Author

I will turn to server's provider. Thank you very much for your help.

@botovq
Copy link
Contributor

botovq commented Nov 22, 2023

I don't know what TLS library the server provider is running, but I can reproduce this with a LibreSSL-backed Apache http2 server, so this may well involve a LibreSSL server-side bug. I can work around it, but then there are other issues...

I'll get back to you when I have time to look more deeply into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants