mbedTLS SSL handshake issue 2

Hello, guys.
I’m trying to make a secure connection between the server and the client.
The server is on stm32f4 platform with LwIp and FreeRTOS.
For test connection I am using two utilities:
First, compiled from mbedtls repository ssl_client2
ssl_client2 ca_file=~/ca.crt key_file=~/client.key crt_file=~/client.crt debug_level=5 server_addr=192.168.0.254 server_port=4433
Second is openssl s_client:
openssl s_client -crlf -cert ~/client.crt -key ~/client.key -CAfile ~/ca.crt -debug -connect 192.168.0.254:4433

Both clients can successfully connect to server and fail with different cases:
openssl is failed with Illegal Parameter (47)
image
ssl_client2 failed with Decrypt Error (51)

About keys and certs.
Device uses server cert and server pk, client uses client cert and client pk, both use same CA cert.
All certs and pk taken from cert.c in mbedtls git repo.

Device config file:

#define MBEDTLS_HAVE_ASM
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_EXIT_ALT
#define MBEDTLS_PLATFORM_PRINTF_ALT
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
#define MBEDTLS_AES_FEWER_TABLES
#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_PK_PARSE_EC_EXTENDED
#define MBEDTLS_NO_PLATFORM_ENTROPY
#define MBEDTLS_SHA256_SMALLER
#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
#define MBEDTLS_SSL_PROTO_TLS1_2
#define MBEDTLS_AES_C
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_ASN1_WRITE_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_DEBUG_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ECP_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_GCM_C
#define MBEDTLS_MD_C
#define MBEDTLS_NET_C
#define MBEDTLS_OID_C
#define MBEDTLS_PADLOCK_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_BASE64_C
#define MBEDTLS_CERTS_C
#define MBEDTLS_PEM_PARSE_C
#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE 0
#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_MPI_MAX_SIZE  48
#define MBEDTLS_ECP_MAX_BITS  384
#define MBEDTLS_ECP_WINDOW_SIZE 2
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0
#define MBEDTLS_ENTROPY_MAX_SOURCES 2
#define MBEDTLS_SSL_CIPHERSUITES                        \
    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,    \
    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024

As well we dont have RTC and NTC but this can’t be an issue since server certs are valid.

The questions:

  1. How to prove the validity of keys and certs?
  2. Can I make more optimizations in device config to save flash?
  3. Why clients fails with different codes?
  4. Does these codes rely on my configuration or on cert/pk contains?
  5. Ho I can debug, of fix this issue?

Thank you for help!

UPD:

    openssl verify -CAfile=./ca.crt -show_chain -verbose ./client.crt 
    ./client.crt: OK
    Chain:
    depth=0: C = NL, O = PolarSSL, CN = PolarSSL Test Client 2 (untrusted)
    depth=1: C = NL, O = PolarSSL, CN = Polarssl Test EC CA

Hi @disgust
Thank you for your question and interest in Mbed TLS!

  1. How to prove the validity of keys and certs?

You can use the sample applications ./cert_app to verify the certificates. However, since your client throws a decrypt error, it probably means that you are doing some renegotiation, which means that first negotiation was probably some successful.

  1. Can I make more optimizations in device config to save flash?

The following articles may help:

  1. Why clients fails with different codes?

These two clients are two different TLS stacks, and implemented differently. One client may decide the fatal alert is of type A and the other may decide it’s of type B.

  1. Does these codes rely on my configuration or on cert/pk contains?

Could be. It depends what ciphersuite was sent\ ecp curve, cerdtificate, etc…

  1. Ho I can debug, of fix this issue?

Since the failure is on your client application, which sends the fatal alert, you could( on ssl_client2 application):

  1. use a debugger on the client application.
  2. Look at the log output ( printed with debug_level=5 )
  3. Use a local server ( ssl_server2 ) compiled with the shown configuration.

I suggest you look at Debugging TLS sessions — Mbed TLS documentation

Regards,
Mbed TLS Team member
Ron

Thank you Ron!

I use test PK and test certs provided by mbedtls, as well as mbed tls client application built without any changes. Why this does not work? What can be wrong?

With cert_app I have following output.
Unfortunately I’m new in SSL/TLS so this error does not tell anything to me.
How can I get or set expecting CN?

./cert_app ca_file="/root/ca.crt" mode=ssl server_name=192.168.0.254 server_port=4433 debug_level=5 permissive=1
  . Loading the CA root certificate ... ok (0 skipped)
...
Verify requested for (Depth 1):
cert. version     : 3
serial number     : C1:43:E2:7E:62:43:CC:E8
issuer name       : C=NL, O=PolarSSL, CN=Polarssl Test EC CA
subject name      : C=NL, O=PolarSSL, CN=Polarssl Test EC CA
issued  on        : 2013-09-24 15:49:48
expires on        : 2023-09-22 15:49:48
signed using      : ECDSA with SHA256
EC key size       : 384 bits
basic constraints : CA=true
  This certificate has no flags

Verify requested for (Depth 0):
cert. version     : 3
serial number     : 09
issuer name       : C=NL, O=PolarSSL, CN=Polarssl Test EC CA
subject name      : C=NL, O=PolarSSL, CN=localhost
issued  on        : 2013-09-24 15:52:04
expires on        : 2023-09-22 15:52:04
signed using      : ECDSA with SHA256
EC key size       : 256 bits
basic constraints : CA=false
  ! The certificate Common Name (CN) does not match with the expected CN
...

Which ciphersuites I need to include to project to be able to work with test PK and Certs provided in mbedtls repo?

The reason for your failure is because the server hostname doesn’t fit the server certificate subject \ subject alternative name. ( This is one of the checks done on the certificate)
Unfortunately, in the cert_app the server_name and server_addr are the same.
You should change the value of the server_name given in mbedtls_ssl_set_hostname to “localhost” as this is the CN of your server certificate

So this changes should be performed in client code?
Because in server code I never set server_name

Which ciphersuites I need to include to project to be able to work with test PK and Certs provided in mbedtls repo?

There are RSA and ECC certificates in “certs”, so your configuration seems to be fine, as the failure is in the server certificate failure

So this changes should be performed in client code?
Because in server code I never set server_name

If your authentication method is only verifying the server, then there is no need to set hostname in the server side.

The hostname is set for verifying that the Server common name is valid.

I used only ECC certs and keys.
Same with configuration.
But I even tried to add all the ciphersuites. Nothing changed.

On server side I switched off auth (as recommended for debug in some tutorial):
mbedtls_ssl_conf_authmode( &tls.conf, MBEDTLS_SSL_VERIFY_NONE );

After I changed cert_app code it start returning

mbedtls_ssl_fetch_input() returned -29312 (-0x7280)

This is because, as mentioned, the issue is not the configuration, but the hostname.
For test purposes please set in your client:

mbedtls_ssl_conf_authmode( &tls.conf, MBEDTLS_SSL_VERIFY_OPTIONAL);

To see if all the rest of the handshake succeeds. Note that this is not secure, as it doesn’t verify your server!

On server side I switched off auth (as recommended for debug in some tutorial):
mbedtls_ssl_conf_authmode( &tls.conf, MBEDTLS_SSL_VERIFY_NONE );

This is dependent on your threat model, as defined for the purpose of your server device.
Regards

If I plovide big list of ciphersuites on both sides how mbedtls stack choose the one to use?

OK, seems I have same error with cert_app as with ssl_client2

 mbedtls_pk_verify() returned -19968 (-0x4e00)

Since this alert is produced by client this means that here is something wrong with client PK…
I have double checked contains of keyfile and it’s same key provided in repo along with client certificate.
Is it possible it’s requires non-NULL password?

UPD:
Finaly. I checked my initializing flow. Make a few changes in this (using ssl_pthread_server.c as an example).
Now I got an error -19584 on server side.
And sometimes it hangs on

MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T,  &P->X,  &S      ) ); MOD_ADD( T );

Looks like while( 0 ) in the macro turns to while( 1 ).
I have checked heap and stacks and there is no problems with overflow. Strange.

I looked for the function which emits an error step by step:

    /*
     * Step 8: check if v (that is, R.X) is equal to r
     */
   if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0) ...

In file ecdsa.c returns -1;
Can anyone explain what does it mean?
What is wrong with key?

Anyone?
@roneld01?

Hi @disgust

The error you are referencing means that the calculated R is not equal to the given r.
In short, that the signature is not correct.
This could probably mean that the public key you are using to verify your certificate is not the key pair of the private key that was used to sign the certificate.

Is the certificate self signed? Did you supply the correct CA root certificate( e.g. subject name of CA certificate is same is the issuer name of the server certificate, the Ca certificate public key is of same algorithm type that signed the device certificate, etc… )?

If I plovide big list of ciphersuites on both sides how mbedtls stack choose the one to use?

As you can see here, the server iterates over the list of configured ciphersuites, and compares to the list of ciphersuites given in the client hello message. The first ciphersuite that matches, is chosen by the server.

Regards,
Ron

I hope I understand correct. I use CA certificate from cert.c file from mbedtls folder. I hope client and server certificates provided in the same folder issued with given CA cert. As well I hope the private keys matches with public keys from that certificates.

So if client uses full list and I change the order of ciphersuites on server side - I have different algorhitm. Can selected ciphersuite affect to handshake?

As well I get that chosen curves (defined in config file) should match to used in certificates. How to know curve used in certificate?

UPD:
Finaly I am sure that provided certs and key are correct. I can successfully connect between openssl s_client and openssl s_server on localhost using it.
So now I think that there is something wrong with one of following instances:

  • mbedtls configuration on server side
  • server initialization procedure
  • enthropy source (hardware RNG)

Still need help.

Hi @disgust
I don’t think that it’s our entropy source, as randomness is not involved in the verification process, and the certificate is not signed by the device.
However, it is quite possible that the server initialization process is lacking something.
What is the ECP window size in your configuration? ECP max bits? etc…

Regards

Thanks for fast reply, @roneld01.
I am fighting with tls server more than week.
My teamlead started looking suspicious at me )))

As mentioned in first message I use:

#define MBEDTLS_MPI_MAX_SIZE  48
#define MBEDTLS_ECP_MAX_BITS  384
#define MBEDTLS_ECP_WINDOW_SIZE 2
#define MBEDTLS_SSL_MAX_CONTENT_LEN 1024

Some observation:
When I am trying to connect first time - the error -19584 on server side
After that all errors is happening on client side (-19968 (-0x4e00))

Hi @disgust
The error -19584 is:

./strerror -19584 
Last error was: -0x4c80 - ECP - Invalid private or public key

It is returned by sev eral places, but this means that there is something wrong in the key pair you are using, which could hint on further failures.
Have you checked you don’t have any memory leak or buffer overflow?
Have you managed to look at logs from server side?
Regards

Unfortunately I can’t use full logs because of lack of flash space.

No issues.

I checked Wireshark dump:

Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Server Key Exchange
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 180
        Handshake Protocol: Server Key Exchange
            Handshake Type: Server Key Exchange (12)
            Length: 176
            EC Diffie-Hellman Server Params
                Curve Type: named_curve (0x03)
                Named Curve: secp384r1 (0x0018)
                Pubkey Length: 97
                Pubkey: 0429bad785169392dc6e93a7f592a379beb381d5ce5d1c7f...
                Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
                    Signature Hash Algorithm Hash: SHA512 (6)
                    Signature Hash Algorithm Signature: ECDSA (3)
                Signature Length: 71
                Signature: 3045022100f2e4739d43617c4f5f2a89c28d6d02fa6c3be7...

And found this:
Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
There are only two curves enabled on server side:

#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED

Should I define third?

Hi @disgust,

Unfortunately I can’t use full logs because of lack of flash space.

You could try a lower debug level, to print only the errors.

If the error is in the server key exchange algorithm, I would also check the entropy source, since the message includes signature and randomness.

If the signature algorithm is ecdsa_secp521r1_sha512, it probably means the the server private key is for thesecp521r1 curve, and this could probably explain the issue.
In addition, if your server key is for the 521r1 curve, then it is strange why the certificate is not for signed with a key of this curve.
Please try defining MBEDTLS_ECP_DP_SECP521R1_ENABLED as it probab ly causes the issue, however, there might be some mixup in the settings as well.
Regards