TLS 1.0 Client Handshake Error SDK 3.1.2

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Using SDK 3.1.2  ThreadX and NetX_Duo on a MXChip 3162 module.

My WiFi module is a client, trying to connect to secured server.

Both server A and B below have same root CA cert, Go Daddy.

Only code changes are to change the address and port number of the server for each test.

Test 1: iPad to MQTTS port 8883 on Server A (use a MQTT client app on my iPad) - Handshakes via TLS 1.0 just fine

Test 2: WiFi module to MQTTS 8883 on Server A - Fails to handshake for TLS 1.0

Test 3: WiFi module to MQTT 1883 on Server A - no encryption, clear, connects and talks just fine

Test 4: WiFi module to HTTPS 443 on Server B - Handshakes via TLS 1.2 just fine

Did this to make sure TLS is working on WiFi module, sanity check.

Could not find anything in the code to indicate the issue, unless I missed it?  Can do TLS 1.2 but not TLS 1.0 If anything, I would expected the opposite to happen.  Since the code debug lead to the BESL library with no source code to debug, I set up WireShark to capture the session.

Set up a Wi-Fi access point which connected to a hub which then connected to my firewall and Internet connection.

Plugged my laptop into this hub and ran WireShark to capture traffic to/from the WiFi module and my iPad for the various tests listed above.

For the failed handshake on TLS 1.0 I am seeing the client hello and server hello completing just fine.  The WiFi module then sends out a client key exchange to the server and nothing more, the WiFi module promptly terminates the connection and I get error code 5015 ERROR_PRIVATE_KEY_REQUIRED.  When I compare this capture to the iPad connecting to the same server via same port 8883, there are 2 additional messages from the client to the server: Change Cipher Spec, and Encrypted Handshake Message.  I see all 3 messages when the WiFi module connected to 443 too.

One thing I noticed, in the WiFi module to 443 capture I see 3 separate packets in the captured data.

Client Key Exchange 193

Change Cipher Spec 60

Encrypted Handshake Message 123

= 376 bytes

For the iPad to 8883, I see all 3 in a single packet capture of size 392, which seems right.

For the WiFi module to 8883, I see 1 packet of size 321 bytes, that Wireshark only decodes as the Client Key Exchange.

So what happened to the Change Cipher and Encrypted Handshake?  Why did it error out with ERROR_PRIVATE_KEY_REQUIRED ?

Attached are the WireShark captures for:

test 2 - the failed WiFi module to MQTTS port 8883 TLS 1.0 and 

test 4 - the successful handshake to HTTP 443

For the 8883 capture you need to tell WireShark to decode as SSL, makes it easier to view and debug.

Before this connection attempt is made, I do a connection to NTP for current date, time on the module so the TLS should work properly.  That will show up in the captures along with DHCP address assignment.

Source is very simple, follows the snip HTTPS client example, have extracted out the relevant calls and removed the error checks, etc.

host = server name

bind-address = resolved IP address of server

w_socket is global variable, not a pointer, no malloc required, same for w_context

wiced_tls_init_root_ca_certificates( GoDaddyRootCertificateAuthorityG2 );

wiced_tls_init_simple_context(&w_context, host );

wiced_tcp_create_socket(&w_socket, WICED_STA_INTERFACE);

wiced_tcp_enable_tls(&w_socket, &w_context);

wiced_tcp_connect(&w_socket, bind_address, port, SOCKET_CONNECT_TIMEOUT);


// and start tls is called with client mode and verification needed in wiced_tcp_connect()

//wiced_tcp_start_tls(socket, WICED_TLS_AS_CLIENT, TLS_VERIFICATION_REQUIRED);

I'm stuck.  Is there a #define that I need to change or add?  Do I need to init or clear some variable or member of a structure?  Or is this a bug in BESL?  Why is this failing?

Unfortunately this MQTTS connection only supports TLS 1.0 right now, no SSL 3 and no TLS 1.1 or 1.2  so have no choice.

Anybody?  Thanks.

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Yes the problem is in the BESL library. It's sending a zero length client certificate but not allowing the server to decide whether to continue the handshake. I'll upload new libraries with a tentative fix. This has been lightly tested against the Amazon server in the trace using a ThreadX NetX Duo build. Please try it out and we'll aim to get the fix into the next release.

View solution in original post

0 Likes
10 Replies
Anonymous
Not applicable

Update.  Another day of testing, seems like I can do TLS v1.0 v1.1 and v1.2 to other servers.  The server I need to talk to is limited to v1.0 and it would appear that BESL is choking on the cert chain it is getting in the Server Hello sequence.  The board acks it and sends out a client key exchange message, but then it errors out and closes the connection.  It never gets to the change cipher spec or encrypted handshake messages which should follow.  Very strange error.  Same cipher works on other connections.  Similar cert chain works for another server.  Combination of certs and cipher is the issue?

This is about as far as I can take this without source code to the BESL.  Anybody seen this before?  Any timeline as to when somebody can look at this and let me know what is going on or provide a fix?  Thanks.

0 Likes
Anonymous
Not applicable

More info.  The server is requesting a certificate from the client but the client does not have one.  The client responds with no certificate (certificates length = 0) and then chokes on a missing private key error in ssl_handshake_client_async() which I cannot debug since it is a library.  I have seen other clients handle this error gracefully, but not here in BESL.  It should still continue the conversation and let the server terminate if no certificate was sent to the server.   Looks like a bug in BESL to me.  If there is a workaround, please let me know because nothing I have tried works, it just results in another error.  And the server I am having trouble with does not require the certificate to be present, it is asking but not mandating, so I should be able to carry on without any client side certificates.  That is how it behaves for other clients. 

http://tools.ietf.org/html/rfc5246#section-7.4.6

7.4.6. Client Certificate

When this message will be sent:

This is the first message the client can send after receiving a ServerHelloDone message. This message is only sent if the server requests a certificate. If no suitable certificate is available, the client MUST send a certificate message containing no certificates. That is, the certificate_list structure has a length of zero. If the client does not send any certificates, the server MAY at its discretion either continue the handshake without client authentication, or respond with a fatal handshake_failure alert. Also, if some aspect of the certificate chain was unacceptable (e.g., it was not signed by a known, trusted CA), the server MAY at its discretion either continue the handshake (considering the client unauthenticated) or send a fatal alert.

So when can I expect acknowledgement of this bug and an ETA when it will be fixed?  Thanks.

0 Likes
Anonymous
Not applicable

Hi,

I just did similar test and I think I got similar failure.

It stuck at the place when context.state is 8 (SSL_CLIENT_KEY_EXCHANGE)

Then next ssl_handshake_client_async( &tls_context->context );

call never return.

0 Likes
Anonymous
Not applicable

Hi Sam

Have you solved your issues?

I also have same problem but state code is different.  For me state code is 3

ENV : BCM4390 SPIL's SIP Module.

SDK : 3.1.2

Error Location  file : wiced_tls.c

Error Location file : wiced_tcp_start_tls_with_ciphers

SSL Server side : openssl with Broadcom's Cert

Debug Message:

before wiced_tcp_connect

  TLS handshake : before ssl_handshake_client_async

  TLS handshake : after ssl_handshake_client_async :1

  TLS handshake : before ssl_handshake_client_async :1

  TLS handshake : after ssl_handshake_client_async :2

  TLS handshake : before ssl_handshake_client_async :2

  TLS handshake : after ssl_handshake_client_async :3

  TLS handshake : before ssl_handshake_client_async :3

--------> here never return

 

Partial code :

do

    {

        uint64_t curr_time;

        if (type == WICED_TLS_AS_SERVER)

        {

            result = ssl_handshake_server_async( &tls_context->context );

            if ( result != TLS_SUCCESS )

            {

                WPRINT_SECURITY_INFO(( "Error with TLS handshake : server_async\n" ));

                goto exit_with_inited_context;

            }

        }

        else

        {

            WPRINT_SECURITY_INFO(( "TLS handshake : before ssl_handshake_client_async :%d\n",tls_context->context.state ));

            result = ssl_handshake_client_async( &tls_context->context );

            if ( result != TLS_SUCCESS )

            {

                WPRINT_SECURITY_INFO(( "Error with TLS handshake : client_async \n" ));

                goto exit_with_inited_context;

            }

            WPRINT_SECURITY_INFO(( "TLS handshake : after ssl_handshake_client_async :%d\n",tls_context->context.state ));

        }

        /* break out if stuck */

        curr_time = tls_host_get_time_ms();

        if ( curr_time - start_time > MAX_HANDSHAKE_WAIT )

        {

            WPRINT_SECURITY_INFO(( "Timeout in SSL handshake\n" ));

            result = TLS_HANDSHAKE_TIMEOUT;

            goto exit_with_inited_context;

        }

        /* if no state change then wait on client */

        if ( prev_state == tls_context->context.state )

        {

            host_rtos_delay_milliseconds( 10 );

        }

        else /* otherwise process next state with no delay */

        {

            prev_state = tls_context->context.state;

        }

    } while ( tls_context->context.state != SSL_HANDSHAKE_OVER );

0 Likes
Anonymous
Not applicable

No, the problem is in the BESL, I cannot fix it.  The server in its server hello portion of the TLS handshake requests a client side certificate, but the client (WICED, me) does not have one so it replies with an empty cert, length = 0.  For other clients, the server says okay, we can continue without client cert, and they work.  With v3.1.2 WICED, the client side (WICED) somehow thinks that it does or should have a cert, probably because of the server request, and then errors out with a private key error because there is no cert.  I have tried to work around the error, but it never works well, always goes south for me.  I *think* that there is a bug in BESL that when the server requests a cert, then a cert is in play whether or not one got loaded, and when it tries to use the private key that does not exist, it errors out.  I have no access to the BESL code, so I am stuck,  I have used other clients like an app on my iPad to the same server and manages to get past this with no client side cert, so why cannot WICED? 

Anonymous
Not applicable

Hi sam and silengdmr

Thanks for your communication. In my case, this is solved and TLS works fine.

We need to test with full traffic also.

With my poor english, it is hard to explain it.  If you are urgent, I may check your code.

TKS

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Yes the problem is in the BESL library. It's sending a zero length client certificate but not allowing the server to decide whether to continue the handshake. I'll upload new libraries with a tentative fix. This has been lightly tested against the Amazon server in the trace using a ThreadX NetX Duo build. Please try it out and we'll aim to get the fix into the next release.

0 Likes
Anonymous
Not applicable

For me,

  sorry, we used FreeRTOS+LwIP

TKS

0 Likes
Anonymous
Not applicable

That fixed it.  Did a couple of tests to make sure it worked on the problem server and that it still works on other servers, did not break anything.  Never did extensive testing or WireShark captures, analysis, but thus far it looks fixed to me.  Thanks! 

0 Likes
Anonymous
Not applicable

Thanks, I'll get the fix into the next release.

It also works for FreeRTOS+LwIP.

0 Likes