Mbed TLS is now part of TrustedFirmware.org.

mbedtls_ssl_handshake failure, Received invalid SSL record


Aug 9, 2017 09:41
lee ching chun

Good day,

I am trying to connect to aws, by modifying example in https://github.com/SuperHouse/esp-open-rtos/tree/master/examples/aws_iot

I uses superhouse's code as a framework to connect to aws, and mbedtls library provided by espressif rtos sdk. And i went through several modification.

The certificate I am using is certificate generate by AWS, at aws iot console, security->certificate-> create new -> one-click-certificate creation (RSA coded)

I used this function to initiate handshake:

int ssl_connect(SSLConnection* conn, const char* host, int port) {
    int ret;
    char buffer[8];

    ret = mbedtls_ctr_drbg_seed(&conn->drbg_ctx, mbedtls_entropy_func,
            &conn->entropy_ctx, (const unsigned char *) pers, strlen(pers));
    if (ret < 0) {
        return -1;
    }

    ret = mbedtls_x509_crt_parse(&conn->ca_cert,
            (const unsigned char *) conn->ca_cert_str,
            strlen(conn->ca_cert_str) + 1);
    if (ret < 0) {
        return handle_error(ret);
    }

    ret = mbedtls_x509_crt_parse(&conn->client_cert,
            (const unsigned char *) conn->client_cert_str,
            strlen(conn->client_cert_str) + 1);
    if (ret < 0) {
        return handle_error(ret);
    }

    ret = mbedtls_pk_parse_key(&conn->client_key,
            (const unsigned char *) conn->client_key_str,
            strlen(conn->client_key_str) + 1, NULL, 0);
    if (ret != 0) {
        return handle_error(ret);
    }

    ret = mbedtls_pk_parse_public_key(&conn->public_key,
            (const unsigned char *) conn->public_key_str,
            strlen(conn->public_key_str) + 1);
    if (ret != 0) {
        return handle_error(ret);
    }

    snprintf(buffer, sizeof(buffer), "%d", port);
    ret = mbedtls_net_connect(&conn->net_ctx, host, buffer,
            MBEDTLS_NET_PROTO_TCP);
    if (ret != 0) {
        return handle_error(ret);
    }

    ret = mbedtls_ssl_config_defaults(&conn->ssl_conf, MBEDTLS_SSL_IS_CLIENT,
            MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
    if (ret != 0) {
        return handle_error(ret);
    }

#ifdef MBEDTLS_DEBUG_C
    mbedtls_ssl_conf_dbg(&conn->ssl_conf, my_debug, stdout);
    mbedtls_debug_set_threshold(5);
#endif

    mbedtls_ssl_conf_authmode(&conn->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
    mbedtls_ssl_conf_rng(&conn->ssl_conf, mbedtls_ctr_drbg_random,
            &conn->drbg_ctx);
    mbedtls_ssl_conf_read_timeout(&conn->ssl_conf, SSL_READ_TIMEOUT_MS);
    mbedtls_ssl_conf_ca_chain(&conn->ssl_conf, &conn->ca_cert, NULL);

    ret = mbedtls_ssl_conf_own_cert(&conn->ssl_conf, &conn->client_cert,
            &conn->client_key);
    if (ret != 0) {
        return handle_error(ret);
    }

    ret = mbedtls_ssl_setup(&conn->ssl_ctx, &conn->ssl_conf);
    if (ret != 0) {
        return handle_error(ret);
    }

    ret = mbedtls_ssl_set_hostname(&conn->ssl_ctx, host);
    if (ret != 0) {
        return handle_error(ret);
    }

    mbedtls_ssl_set_bio(&conn->ssl_ctx, &conn->net_ctx, mbedtls_net_send, NULL,
            mbedtls_net_recv_timeout);

    while ((ret = mbedtls_ssl_handshake(&conn->ssl_ctx)) != 0) {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ
                && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
            if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
                return handle_error(ret);
            }
        }
        printf("error at handshake.\r\n ");
        handle_error(ret);

        vTaskDelay(5000 / portTICK_RATE_MS);
    }

    mbedtls_ssl_get_record_expansion(&conn->ssl_ctx);
    ret = mbedtls_ssl_get_verify_result(&conn->ssl_ctx);
    if (ret != 0) {
         return handle_error(ret);
    }

    return ret;
}  

The handshake failed and return -29184.

https://ibb.co/fxjkzv

I captured packets sent between my esp8266 and AWS with wireshark.

Am I doing it the correct way? Any idea on why the handshake failed? I am confused and had no idea which part went wrong. Could it be the certificate I am using is in wrong format?

Thank you in advance. Your help mean a lot to me!

 
Aug 13, 2017 08:56
Ron Eldor

Hi lee ching chun,
As mentioned in this post, MBEDTLS_ERR_SSL_INVALID_RECORD is set by numerous locations. I suggest you compile your client with in debug mode, setting the log level to the highest possible, and look at the logs to understand better where you got the failure. I am trying to understand why you are parsing the certificates and keys prior to setting the ssl configuration, and doing the handshake, as these are done within the handshake. Please follow the ssl_client2 example to see how to implement an SSL client using mbed TLS.
Looking at the wireshark snapshot, there isn't much I could determine, except that 4 messages (Server Hello, Certificate, Certificate Request and Server Hello Done) were sent in the same TCP packet, and the the server sends the "Close Notify" warning after ~1 minute. Perhaps your client's bio callbacks don't parse the messages correct.
As mentioned before, check the log files to understand better the location and cause for the INVALID SSL RECORD error you are receiving.
Regards,
mbed TLS Team Member
Ron

 
Aug 23, 2017 07:12
Mariya

Hi lee ching chun,

I am also trying to get mbedTLS for ARM Cortx-M4 (different vendor board) and getting crashing error with memory in "ecp_precompute_comb()" while parse and validating server ceritificate. AWS IoT sent its certificate to verify at client side. I think some of the struct used on this code memory address not pointed correctly.

Also before going handshake ceriticate verification function fails (similar error).

I have Windows based demo application which connect to AWS IoT and send test Json payload thru MQTT

https://github.com/RaspiRepo/AWS-IoT-SDK-for-Windows

Mariya