Mbedtls_ssl_handshake return error -0x2700

Hi,
I am new to mbed and i want to make a connection between the server and the client using https. I called mbedtls_ssl_handshake and get error code -0x2700. Actually i have tested the cert on ESP32 and it works. I tried to find the error and found that when i remove the certain code in line 2627 in x509_cert.c and it will work correctly.

if( *flags != 0 )
        return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );

Can anyone help me? Thank you!

P.S. I also tried to enable the error log by adding MBEDTLS_DEBUG_C and set Debug_Level to 4, but i can not get the log through serial. Do anyone know why?

Hi @KennethSong
There are several reasons for certificate verification to fail.
Invalid certificate being one of them.

  • Have you set the correct trusted root CA certificate?
  • Is the server hostname same as the certificate CN in subject name \ subject alternative name ?

You should check what the verification flags are to determine the reasons, by calling mbedtls_ssl_get_verify_result()

P.S. I also tried to enable the error log by adding MBEDTLS_DEBUG_C and set Debug_Level to 4, but i can not get the log through serial. Do anyone know why?

Have you set correct debug function in mbedtls_ssl_conf_dbg() ?
regards,
Mbed TLS Team member
Ron

Hi @roneld01
Thank you for your reply!
I got error code 0x08 from

mbedtls_ssl_get_verify_result()

which means the cert is not correctly signed by the trusted CA. Does it means that the input *buf of

int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen );

is invaild? But i use the same cert on ESP32 with the same input to this function, and it will not return error. Do you know why?

Hi @KennethSong

Does it means that the input *buf is invaild?

Not necessary. As I asked in my previous comment, have you set the correct CA root certificate in mbedtls_ssl_conf_ca_chain() or mbedtls_ssl_conf_ca_cb()? Have you set the correct hostname?

The error mostly means that the certificate couldn’t be verified using the ca certificates that were set in your application.

But i use the same cert on ESP32 with the same input to this function, and it will not return error. Do you know why?

What same certificate? Device certificate or ca root certificate? It could also be some memory related issue, that caused the verification to fail.
Regards

Hi @roneld01
I called mbedtls_ssl_conf_ca_chain() to input the cert according to the esp32 wificlient secure library:

mbedtls_ssl_conf_ca_chain(&_ssl_conf, &_cacert, NULL);

and mbedtls_ssl_conf_ca_cb() is not called.
i get the two inputs here:

if ((ret = mbedtls_x509_crt_parse(&_cacert, (const unsigned char *)_ssl_ca_pem,
                       strlen(_ssl_ca_pem) + 1)) != 0)
    {
        return -1;
    }
if ((ret = mbedtls_ssl_config_defaults(&_ssl_conf,
                    MBEDTLS_SSL_IS_CLIENT,
                    MBEDTLS_SSL_TRANSPORT_STREAM,
                    MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
    {
        return -1;
    }

The _ssl_ca_pem is the input cert. The full code is here:

if (_ssl_ca_pem == NULL)
    {
        // No SSL
        return _tcp_socket->connect(host, port);
    }
    
    // Initialize TLS-related stuf.
    int ret;
    if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy,
                      (const unsigned char *) TLS_CUNSTOM,
                      sizeof (TLS_CUNSTOM))) != 0)
    {
        return -1;
    }

    if ((ret = mbedtls_x509_crt_parse(&_cacert, (const unsigned char *)_ssl_ca_pem,
                       strlen(_ssl_ca_pem) + 1)) != 0)
    {
        return -1;
    }

    if ((ret = mbedtls_ssl_config_defaults(&_ssl_conf,
                    MBEDTLS_SSL_IS_CLIENT,
                    MBEDTLS_SSL_TRANSPORT_STREAM,
                    MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
    {
        return -1;
    }

    mbedtls_ssl_conf_ca_chain(&_ssl_conf, &_cacert, NULL);
    mbedtls_ssl_conf_rng(&_ssl_conf, mbedtls_ctr_drbg_random, &_ctr_drbg);

    /* It is possible to disable authentication by passing
     * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
     */
    // mbedtls_ssl_conf_authmode(&_ssl_conf, /* MBEDTLS_SSL_VERIFY_REQUIRED*/MBEDTLS_SSL_VERIFY_OPTIONAL);
    mbedtls_ssl_conf_authmode(&_ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);

#if DEBUG_LEVEL > 0
    mbedtls_ssl_conf_verify(&_ssl_conf, my_verify, NULL);
    mbedtls_ssl_conf_dbg(&_ssl_conf, my_debug, NULL);
    mbedtls_debug_set_threshold(DEBUG_LEVEL);
#endif

    if ((ret = mbedtls_ssl_setup(&_ssl, &_ssl_conf)) != 0)
    {
        return -1;
    }
    
    mbedtls_ssl_set_hostname(&_ssl, host);
    
    mbedtls_ssl_set_bio(&_ssl, static_cast<void *>(_tcp_socket), ssl_send, ssl_recv, NULL );

    /* Connect to the server */
    ret = _tcp_socket->connect(host, port);
    if (ret != NSAPI_ERROR_OK)
    {
        return ret;
    }

   /* Start the handshake */
    ret = mbedtls_ssl_handshake(&_ssl);
    int res = mbedtls_ssl_get_verify_result(&_ssl);

I found the 0x2700 error comes from the second step of server hello here:

case MBEDTLS_SSL_SERVER_HELLO:
           ret = ssl_parse_server_hello( ssl );
           break;

       case MBEDTLS_SSL_SERVER_CERTIFICATE:
           printf(ssl->state);
           ret = mbedtls_ssl_parse_certificate( ssl );
           break;

       case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
           ret = ssl_parse_server_key_exchange( ssl );
           break;

       case MBEDTLS_SSL_CERTIFICATE_REQUEST:
           ret = ssl_parse_certificate_request( ssl );
           break;

       case MBEDTLS_SSL_SERVER_HELLO_DONE:
           ret = ssl_parse_server_hello_done( ssl );
           break;

Does it means that the cert from the server is not vaild?
Thank you for your help!

Hi @KennethSong
It mprobably means that the server certificate sent to the client is not signed by the ca certificate you have sent.
Please check what’s the ca certificate you are using, and information on the server certificate.

You can extract the ca certificate information with:

openssl x509 -in <_ssl_ca_pem file> -noout -text

The server certificate information you can see in the logs.
Please check the following:

  1. the ca certificate is actually a CA certificate (has CA: true)
  2. The CA certificate subject name is identical to the root of the device certificate chain issuer name.
  3. The device certificate is signed with same algorithm as ca certificate.
    Regards

Hi @roneld01
The problem is exactly the same as you mentioned above. It finally works after changing the CA cert. Thank you a lot for your help!
Regards

I have a follow up question on this, I also receive error number -0x2700
I am trying to run secure connection with tcp (tcp over ssl) and I follow the control configuration sequence and find that key is needed in addition to the root certificate to upload in my target. My question is why key is needed for TCPS connection but not HTTPS? Because with HTTPS I was able to put the root certificate in my target and establish a GET connection.

HI @mbiuki
Thank you for your question.
As mentioned in my previous comment this error is returned for several reasons. I believe this follow up merrits a new forum topic.
However, if your key is needed for the TLS handshake, it is probably bercause the server in this specific case (TCPS) requests for your client certificate, while in the HTPS use case, the server didn’t ask for one.
It couls also be an issue of the key exchange used in the negotiated ciphersuite, where the key exchange message is signed.

Regards,
Mbed TLS Support
Ron