eclipse-threadx / netxduo

Eclipse ThreadX - NetXDuo is an advanced, industrial-grade TCP/IP network stack designed specifically for deeply embedded real-time and IoT applications
https://github.com/eclipse-threadx/rtos-docs/blob/main/rtos-docs/netx-duo/index.md
MIT License
230 stars 131 forks source link

TLS 1.0 connection issues #143

Open dougbenedict opened 1 year ago

dougbenedict commented 1 year ago

Hi Team,

I am performing testing using NetX Duo v6.2.0 and am running into behavior I am not understanding when trying to use TLS 1.0 connections both as a server and as a client.

Client connection issues I have a python script running on a RPi as a server. The script is forcing use of TLS 1.0 by using ssl_version=ssl.PROTOCOL_TLSv1 in the wrap socket call.

In my NetX Duo code, I am establishing the TLS connection to the RPi. If I use the protocol version override API to force the client to use TLS 1.0 by calling

error = nx_secure_tls_session_protocol_version_override(&tls_session, NX_SECURE_TLS_VERSION_TLS_1_0);

then the connection is successfully established.

If I remove the call to nx_secure_tls_session_protocol_version_override then the connection fails. nx_secure_tls_session_start returns an error code of NX_SECURE_TLS_ALERT_RECEIVED (0x114) and the python script displays the error:

('(accept) ERROR: ', SSLError(1, '[SSL: NO_SHARED_CIPHER] no shared cipher (_ssl.c:1056)'))

Everything is exactly the same on both sides except for the call to nx_secure_tls_session_protocol_version_override. Why the difference in behavior?

Server connection issues For the server connection test, on the RPi I am using the program ssl_client2 from the mbedTLS distribution. Using the command:

./ssl_client2 server_addr=$1 ca_file=ec-cacert.pem crt_file=device-cert.pem key_file=device-key.pem server_name="NJSASC" server_port=50007 debug_level=1

The connection to my NetX Duo test program succeeds. But if I force using TLS 1.0 using the command

./ssl_client2 server_addr=$1 ca_file=ec-cacert.pem crt_file=device-cert.pem key_file=device-key.pem force_version=tls1 server_name="NJSASC" server_port=50007 debug_level=1

then the connection fails. If I use the call to nx_secure_tls_session_protocol_version_override then the error returned from nx_secure_tls_session_start is NX_SECURE_TLS_CERTIFICATE_VERIFY_FAILURE (0x131). If I remove the call to version_override than the error returned is NX_SECURE_TLS_NO_SUPPORTED_CIPHERS (0x10e).

I don't understand the difference in behavior I'm seeing. The different results seem like a bug to me. The certificates used are the same in every test case for both client and server test cases.

Environment NetX Duo: v6.2.0 RPi: Linux raspberrypi 5.10.103-v7+ #1529 SMP Tue Mar 8 12:21:37 GMT 2022 armv7l GNU/Linux mbedTLS: 2.25.0 - programs/ssl/ssl_client2 Python3: 3.7.3 OpenSSL: 1.1.1n 15 Mar 2022 I had to modify the OpenSSL config for TLS 1.0 to work: [system_default_sect] MinProtocol = TLSv1.0 CipherString = DEFAULT@SECLEVEL=1

GCC: 10.3.1

In nx_secure_user.h I have:

define NX_SECURE_TLS_ENABLE_TLS_1_0

define NX_SECURE_TLS_ENABLE_TLS_1_1

define NX_SECURE_TLS_ENABLE_TLS_1_3

and in nx_crypto_ciphersuite_lookup_table_ecc[] I added / Added for TLS1.0 testing / {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, &crypto_method_ecdhe, &crypto_method_ecdsa, &crypto_method_aes_cbc_256, 16, 32, &crypto_method_hmac_sha1, 20, &crypto_method_tls_prf_sha256},

If you can help me understand the behavior, I would greatly appreciate it.

Thanks, Doug

dougbenedict commented 1 year ago

I have determined that the client connection issue is a problem with my code. Investigating more I found out that the ciphersuites that the code was using was being set differently when the nx_secure_tls_session_protocol_version_override() was being used. If the override call wasn't being used, the TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA cipher wasn't being added. Fixing that fixed the client connection issue.

But I am still seeing a problem with the server connection. If the remote client forces TLS1.0 then the NetXSecure code is failing the certificate verification. If the remote client does not force TLS 1.0 then a TLS 1.2 connection is established using the same certificate.

Remote client command for successful connection:

./ssl_client2 server_addr=$1 ca_file=ec-cacert.pem crt_file=device-cert.pem key_file=device-key.pem server_name="NJSASC" server_port=50007 debug_level=1

Connection succeeds using the TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 cipher.

Remote client command for failed connection:

./ssl_client2 server_addr=$1 ca_file=ec-cacert.pem crt_file=device-cert.pem key_file=device-key.pem force_version=tls1 server_name="NJSASC" server_port=50007 debug_level=1

Connection fails using the TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA cipher. The certificate check is failing in _nx_crypto_method_ecdsa_operation().

How can I determine why the same certificate works with one cipher but not the other?

dougbenedict commented 1 year ago

Did a little more digging into this today. When using TLS 1.0, the verification of the signature of the hash data is failing in _nx_crypto_ecdsa_verify. I've included some of the debug statements I've added in my environment. Limited use to you but it does show the cipher being choosen for the connection.

The entry in the ciphersuite table for TLS 1.0: {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, &crypto_method_ecdhe, &crypto_method_ecdsa, &crypto_method_aes_cbc_256, 16, 32, &crypto_method_hmac_sha1, 20, &crypto_method_tls_prf_sha256},

Happy to run any tests that would be helpful. At this point I don't know what to do to figure out why the verification is failing.

Successful server test using TLS 1.3.

Test TLS server mode ======TLS server test=========== ======TLS server waiting for client connection=========== ======Client connected=========== TLS session created Assigning protocol_version #1 to 0x303 (1) Found ciphersuite match: 0x1301 ...saving ciphersuite: 0x1301, priority: 0 Found acceptable ciphersuite: 0x1301 Assigning protocol_version #1 to 0x303 (1) Found ciphersuite match: 0x1301 ...saving ciphersuite: 0x1301, priority: 0 Found acceptable ciphersuite: 0x1301 Found certificate method - index 0, method 0x80024a8 _nx_crypto_method_ecdsa_operation: op 41 _nx_crypto_method_ecdsa_operation: op 3 Found certificate method - index 0, method 0x80024a8 _nx_crypto_method_ecdsa_operation: op 41 _nx_crypto_method_ecdsa_operation: op 4 NX_CRYPTO_VERIFY #1 _nx_crypto_ecdsa_verify: curve 0x100438e0, hash_length 32 3694fbcf74aae9aa713722f6ade9bbd0a95907eb2756ddea683a0a2800dd47df verify: compare IS successful status of verify: 0x00 _nx_secure_tls_process_certificate_verify: tls version 0x0303 (1) Found certificate method - index 0, method 0x80024a8 _nx_crypto_method_ecdsa_operation: op 41 Calling nx_crypto_operation: 0x1001dd85 _nx_crypto_method_ecdsa_operation: op 4 NX_CRYPTO_VERIFY #1 _nx_crypto_ecdsa_verify: curve 0x100438e0, hash_length 32 1d2f41b28a34ab485f4db73aa125d7ee8ba6466fc7350578ca0ec0751149b191 verify: compare IS successful status of verify: 0x00 SUCCESS compare_value: 0 --Connection successful

Failed server test with client specifying TLS 1.0

Test TLS server mode with client specifying TLS1.0 ======TLS server test=========== ======TLS server waiting for client connection=========== ======Client connected=========== TLS session created Assigning protocol_version #1 to 0x301 (1) Assigning protocol_version #1 to 0x301 (0) Found ciphersuite match: 0xc00a ...saving ciphersuite: 0xc00a, priority: 12 *****Found acceptable ciphersuite: 0xc00a Found certificate method - index 7, method 0x80024fc _nx_crypto_method_ecdsa_operation: op 41 _nx_crypto_method_ecdsa_operation: op 3 Found certificate method - index 0, method 0x80024a8 _nx_crypto_method_ecdsa_operation: op 41 _nx_crypto_method_ecdsa_operation: op 4 NX_CRYPTO_VERIFY #1 _nx_crypto_ecdsa_verify: curve 0x100438e0, hash_length 32 3694fbcf74aae9aa713722f6ade9bbd0a95907eb2756ddea683a0a2800dd47df verify: compare IS successful status of verify: 0x00 _nx_secure_tls_process_certificate_verify: tls version 0x0301 (0) Found certificate method - index 0, method 0x80024a8 -----MD5 hash method: 0x80029b0 (crypto_method_md5) -----SHA1 hash method: 0x8002a10 (crypto_method_sha1) _nx_crypto_method_ecdsa_operation: op 41 Calling nx_crypto_operation: 0x1001dd85 _nx_crypto_method_ecdsa_operation: op 4 NX_CRYPTO_VERIFY #1 _nx_crypto_ecdsa_verify: curve 0x100438e0, hash_length 36 08029ea6ab3c2c119bba51c30475dabec3e8c44f7567cfa970c4b7ed5460b7f8dd4fcb55 verify: compare not success status of verify: 0x20009 NOT SUCCESS compare_value: 1 nx_secure_tls_session_start failed 131

balajicyp commented 7 months ago

Description:

The TLS 1.1/1.0 handshake fails certificate verify (when using auth_mode=required using mbedtls server/client)

The issue is because for EC cipher suites the handshake verify hash is of size 20 bytes while the netxsecure code is sending MD5 + SHA1 (36bytes) of hash causing failure.

With tls_10_tls_11.patch the issue is resolved.

tls_10_tls_11.patch