espressif / ESP8266_RTOS_SDK

Latest ESP8266 SDK based on FreeRTOS, esp-idf style.
http://bbs.espressif.com
Apache License 2.0
3.33k stars 1.57k forks source link

mbedtls gives error MBEDTLS_ERR_X509_CERT_VERIFY_FAILED #77

Closed muboldi closed 6 years ago

muboldi commented 7 years ago

Hi,

I'm using RTOS_SDK 1.5, trying to connect to AWS Iot.

At first i have a certificate with eliptic curve. But i get the error -15488 MBEDTLS_ERR_PK_UNKNOWN_PK_ALG. The mbedTLS documentation (https://tls.mbed.org/api/pk_8h.html#a877b66447bfa2cd49c1b99f1dc887568) describes the error as "Key algorithm is unsupported (only RSA and EC are supported)". If EC is supported in mbedTLS, why i'm getting this error? The support to EC was removed for the RTOS_SDK?

Then i create a new certificate with RSA, and i'm getting the following error in the handshake -9984 MBEDTLS_ERR_X509_CERT_VERIFY_FAILED. I use the certificate in esp-open-rtos by SuperHouse (https://github.com/SuperHouse) and it works so is not the certificate.

Here is the code to establish the connection, i take it from the aws_iot example of SuperHouse, it is similar to the Mbedtls_demo example of Espressif:

#include <esp_common.h>
#include <freertos/portmacro.h>
#include <lwip/sockets.h>
#include <ipv4/lwip/inet.h>
#include <lwip/netdb.h>
#include <lwip/sys.h>
#include <string.h>

// this must be ahead of any mbedtls header files so the local mbedtls/config.h can be properly referenced
#include "ssl_connection.h"

#define SSL_READ_TIMEOUT_MS           2000

const char *pers = "esp-tls";

static int handle_error(int err) {

#ifdef MBEDTLS_ERROR_C
    char error_buf[100];

    mbedtls_strerror(err, error_buf, 100);
    printf("%s\n", error_buf);
#endif
    printf("Error: %d\n", err);
    return err;
}

void ssl_init(SSLConnection* conn) {
    /*
     * Initialize the RNG and the session data
     */
    mbedtls_net_init(&conn->net_ctx);
    mbedtls_ssl_init(&conn->ssl_ctx);
    mbedtls_ssl_config_init(&conn->ssl_conf);

    mbedtls_x509_crt_init(&conn->ca_cert);
    mbedtls_x509_crt_init(&conn->client_cert);
    mbedtls_pk_init(&conn->client_key);

    mbedtls_ctr_drbg_init(&conn->drbg_ctx);
    mbedtls_entropy_init(&conn->entropy_ctx);

}

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);
    }

    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);
    }

    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);
            }
        }
        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;
}

In this post https://forums.aws.amazon.com/thread.jspa?threadID=219255 suggest to check the root CA certificate to validate the AWS IoT server certificate. I alredy check it.

Any idea or suggestion of what could be happen?

Thanks.

gustavomassa commented 7 years ago

@muboldi Did you get any response?

muboldi commented 7 years ago

@gustavomassa No, i don't get any response.

Do you have some solution or you are getting the same errors?

gustavomassa commented 7 years ago

@muboldi No, I think I'm going to use the open-rtos-sdk... I did no try to use that example with the official SDK yet. I found some example on how to use the mbedtls library: http://iot-bits.com/articles/compiling-esp8266-mbed-tls-ssl-connection/

Are you using the same mbedtls library?

muboldi commented 7 years ago

@gustavomassa Yes, i'm using the same library. The RTOS_SDK and open-rtos-sdk use mbedtls.

I saw that example, is the example of espressif. It works but i wasn't able to change the certificates. I mean, i change the certificates but i got the error of the post. Those certificates are fine because i use them in open-rtos-sdk.

gustavomassa commented 7 years ago

@muboldi I got the open-rtos-sdk example and changed it to run on RTOS_SDK, but I'm having an issue to compile it with the libmbedtls.a: sdk/ESP8266_RTOS_SDK/lib/libmbedtls.a(ssl_tls.o):(.text.mbedtls_ssl_fetch_input+0x4): undefined reference to max_content_len

I think we may have the same issue.. We need to re-build the mbedtls lib using the config file from open-rtos-sdk:

#ifndef MBEDTLS_CONFIG_H
#define MBEDTLS_CONFIG_H

/* System support */
#define MBEDTLS_HAVE_ASM
#define MBEDTLS_DEPRECATED_WARNING
#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_NO_PLATFORM_ENTROPY

/* mbed TLS feature support */
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_SSL_PROTO_TLS1_2

/* Debug support (optional) */
// #define MBEDTLS_ERROR_C
// #define MBEDTLS_DEBUG_C

/* mbed TLS modules */
#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_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_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_X509_USE_C

/* For verify RSA based root CA certificate (optional if root CA cert is signed using ECC) */
#define MBEDTLS_RSA_C
#define MBEDTLS_SHA1_C
#define MBEDTLS_PKCS1_V15
#define MBEDTLS_PKCS1_V21

/* For test certificates */
#define MBEDTLS_BASE64_C
#define MBEDTLS_CERTS_C
#define MBEDTLS_PEM_PARSE_C

/* Save RAM at the expense of ROM */
#define MBEDTLS_AES_ROM_TABLES

/* Save RAM by adjusting to our exact needs */
#define MBEDTLS_ECP_MAX_BITS   384
#define MBEDTLS_MPI_MAX_SIZE   256 // 2048 bits

/* Save RAM at the expense of speed, see ecp.h */
#define MBEDTLS_ECP_WINDOW_SIZE        2
#define MBEDTLS_ECP_FIXED_POINT_OPTIM  0

/* Significant speed benefit at the expense of some ROM */
#define MBEDTLS_ECP_NIST_OPTIM

/*
 * You should adjust this to the exact number of sources you're using: default
 * is the "mbedtls_platform_entropy_poll" source, but you may want to add other ones.
 * Minimum is 2 for the entropy test suite.
 */
#define MBEDTLS_ENTROPY_MAX_SOURCES 2

/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
#define MBEDTLS_SSL_CIPHERSUITES                        \
    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

/*
 * Save RAM at the expense of interoperability: do this only if you control
 * both ends of the connection!  (See coments in "mbedtls/ssl.h".)
 * The minimum size here depends on the certificate chain used as well as the
 * typical size of records.
 */
#define MBEDTLS_SSL_MAX_CONTENT_LEN             4096

#include "mbedtls/check_config.h"

#endif /* MBEDTLS_CONFIG_H */

I don't have the mbedtls source code that was modified for RTOS_SDK.

muboldi commented 7 years ago

@gustavomassa I had got the same problem and i solved it defining the variable, as it is define in the official example of espressif. You can download it from here: https://github.com/espressif/esp8266-rtos-sample-code/tree/master/04Protocal/Mbedtls_demo.

unsigned int max_content_len = 3072;

The max_content_len variable is define in Mbedtls_demo/app/programs/programs.c. Declare it somewhere in your code and should it compile.

I copied the configuration of mbedtls library from open-rtos-sdk to RTOS_SDK and it gave me the same error (MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) when it try to establish the connection whit AWS IoT. I also ported the mbedtls library of open-rtos-sdk inside my project and i was able to compile it, but again i get the same error.

But give it a try and tell me if you could make it works, maybe i did some mistake.

Good luck.

gustavomassa commented 7 years ago

@muboldi I have good news, I'm testing here using the Mosquitto MQTT Broker instead of the AWS iot broker. I configured the broker to use TLS 1.2 and created CA/SERVER certs, using port 8883. On the ESP8266 side I'm using just the CA Cert, then I was able to connect to broker using SSL connection and publish to topics normally. I also receive the Error: -9984, but esp is still able to connect and publish messages normally.

I'm using the preprocessor flag to override the mbedtls config file, so it is using the open_rtos definitions: -DMBEDTLS_CONFIG_FILE='"mbedtls_config.h"'

Current free heap size while connected using TLS 1.2: 17416

Now I will try to find out what is the error -9984 and why it is ocurring...

muboldi commented 7 years ago

@gustavomassa There is something weird, you are just using the CA cert in the esp8266? Don't you flash the client cert and private key in your esp? If this is the case, are you sure that you are publishing messages over a TLS 1.2 connection and not just over MQTT?

Sorry if i'm confused but there is something that i don't get.

Also the Error -9984 means that the certificate verification failed, so it sounds very weird that you can establish the TLS 1.2 connection.

gustavomassa commented 7 years ago

@muboldi I found the problem: You need to set the correct domain name for the ssl_connection, the domain name was set when you generated the CA cert file using the openssl command: openssl req -new -out server.csr -key server.key The domain name is the "COMMON NAME" input. You need to set it here:

ret = mbedtls_ssl_set_hostname(&conn->ssl_ctx, "YOUR DOMAIN NAME");
    if (ret != 0) {
        return handle_error(ret);
    }

Here is the ssl code working just with the CA cert:

int ICACHE_FLASH_ATTR 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);
//    }

    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, "YOUR DOMAIN NAME");
    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) {
                printf("MBEDTLS_ERR_X509_CERT_VERIFY_FAILED\r\n");
                return handle_error(ret);
            }
        }
        printf("Handle error: %d\r\n", ret);
        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;
}

MQTT Task using the ssl_connection:

LOCAL void ICACHE_FLASH_ATTR mqtt_task(void *pvParameters) {
    int8 ret = 0;
    int8 mqtt_client_id[20];
    uint8 mqtt_buf[100];
    uint8 mqtt_readbuf[100];
    MQTTClient client = DefaultClient;
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    ssl_conn = (SSLConnection *) os_zalloc(sizeof(SSLConnection));
    struct Network network;
    network.my_socket = -1;
    network.mqttread = mqtt_ssl_read;
    network.mqttwrite = mqtt_ssl_write;

    // Unique client ID
    //memset(mqtt_client_id, 0, sizeof(mqtt_client_id));
    strcpy(mqtt_client_id, "ESP8266");
    strcat(mqtt_client_id, get_my_id());

    while (1) {
        if (!wifi_alive) {
            vTaskDelay(1000 / portTICK_RATE_MS);
            continue;
        }

        printf("Free heap size: %d\r\n", system_get_free_heap_size());
        printf("(Re)connecting to MQTT server..\r\n");

        mqtt_alive = 0;
        ssl_reset = 0;
        printf("Initializing SSL Connection..\r\n");

        ssl_init(ssl_conn);
        ssl_conn->ca_cert_str = ca_cert;
        ssl_conn->client_cert_str = client_cert;
        ssl_conn->client_key_str = client_key;

        printf("Connecting using SSL..\r\n");

        //ret = ConnectNetwork(&network, MQTT_HOST, MQTT_PORT);
        ret = ssl_connect(ssl_conn, MQTT_HOST, MQTT_PORT);
        if (ret) {
            printf("Could not open ssl connection: %d\r\n", ret);
            ssl_destroy(ssl_conn);
            vTaskDelay(1000 / portTICK_RATE_MS);
            continue;
        }

        printf("Opened socket TLS to MQTT Server\r\n");
        printf("network.mysocket = %d\r\n", network.my_socket);

        NewMQTTClient(&client, &network, 5000, mqtt_buf, 100, mqtt_readbuf, 100);
        data.willFlag = 0;
        data.MQTTVersion = 3;
        data.clientID.cstring = mqtt_client_id;
        data.username.cstring = MQTT_USER;
        data.password.cstring = MQTT_PASS;
        data.keepAliveInterval = MQTT_KEEP_ALIVE;
        data.cleansession = MQTT_CLEAN_SESSION;

        printf("Send MQTT connect ...\r\n");
        ret = MQTTConnect(&client, &data);

        if (ret) {
            printf("Client failed to connect to broker, error: %d.\r\n", ret);
            ssl_destroy(ssl_conn);
            vTaskDelay(1000 / portTICK_RATE_MS);
            continue;
        }

        mqtt_alive = 1;
        printf("Client connected to broker.\r\n");
        printf("network.mysocket = %d\r\n", network.my_socket);
        // Subscriptions
        MQTTSubscribe(&client, "/mytopic", QOS1, topic_received);
        // Empty the publish queue
        xQueueReset(publish_queue);

        while (wifi_alive && !ssl_reset) {
            // Publish all pending messages
            char msg[PUB_MSG_LEN];
            while (xQueueReceive(publish_queue, (void * )msg, 0) == pdTRUE) {
                msg[PUB_MSG_LEN - 1] = '\0';
                MQTTMessage message;
                message.payload = msg;
                message.payloadlen = PUB_MSG_LEN;
                message.dup = 0;
                message.qos = QOS1;
                message.retained = 0;
                ret = MQTTPublish(&client, "beat", &message);
                if (ret != SUCCESS)
                    break;
            }

            // Receiving / Ping
            ret = MQTTYield(&client, 1000);
            if (ret == DISCONNECTED) {
                break;
            }
        }
        mqtt_alive = 0;
        printf("Connection broken, request restart\r\n");
        ssl_destroy(ssl_conn);
        vTaskDelay(1000 / portTICK_RATE_MS); //broker reconnection delay
    }
    printf("MQTT task ended\r\n", ret);
    vTaskDelete(NULL);
}

Observations: 1 - The Network struct used by MQTT Paho library has a mysocket variable that represents the socket fd, using ssl connection this variable value is alwyas -1. It seems that the only thing that the MQTT Paho needs is a hook for ssl read/write functions. 2 -vTaskDelay function does not make sense to be used there, since the ssl_connection is not a task...

printf("Handle error: %d\r\n", ret);
        handle_error(ret);

        vTaskDelay(5000 / portTICK_RATE_MS);

I'm trying to load the CA cert file using the mbedtls_x509_crt_parse_file function:

    if( ( ret = mbedtls_x509_crt_parse_file( &conn->ca_cert, cafile_test ) ) != 0 )
    {
        printf( "failed - mbedtls_x509_crt_parse_file returned -0x%x\r\n", -ret);
        return handle_error(ret);
    }

But the compiled mbedtls used on RTOS_SDK is missing a define to enable mbedtls IO: #define MBEDTLS_FS_IO Could you re-compile mbedtls lib using this new esp_conf.h? I mixed both configs from ESP_RTOS and Open_Rtos:

#ifndef MBEDTLS_CONFIG_H
#define MBEDTLS_CONFIG_H

#include "c_types.h"

#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
#define _CRT_SECURE_NO_DEPRECATE 1
#endif

/* ESPRESSIF DEFINITIONS */
#define MBEDTLS_FS_IO
#define MBEDTLS_CIPHER_MODE_CBC
#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
#define MBEDTLS_PK_PARSE_EC_EXTENDED
#define MBEDTLS_ERROR_STRERROR_DUMMY
#define MBEDTLS_GENPRIME
#define MBEDTLS_PK_RSA_ALT_SUPPORT
#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
#define MBEDTLS_AESNI_C
#define MBEDTLS_PEM_WRITE_C
#define MBEDTLS_PK_WRITE_C
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_VERSION_C
#define MBEDTLS_X509_CRL_PARSE_C
#define MBEDTLS_X509_CSR_PARSE_C
#define MBEDTLS_X509_CREATE_C
#define MBEDTLS_X509_CRT_WRITE_C
#define MBEDTLS_X509_CSR_WRITE_C
#define MBEDTLS_XTEA_C
#define ESP8266_PLATFORM

/* System support */
#define MBEDTLS_HAVE_ASM
#define MBEDTLS_DEPRECATED_WARNING
#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_NO_PLATFORM_ENTROPY

/* mbed TLS feature support */
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_SSL_PROTO_TLS1_2

/* Debug support (optional) */
// #define MBEDTLS_ERROR_C
// #define MBEDTLS_DEBUG_C

/* mbed TLS modules */
#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_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_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_X509_USE_C

/* For verify RSA based root CA certificate (optional if root CA cert is signed using ECC) */
#define MBEDTLS_RSA_C
#define MBEDTLS_SHA1_C
#define MBEDTLS_PKCS1_V15
#define MBEDTLS_PKCS1_V21

/* For test certificates */
#define MBEDTLS_BASE64_C
#define MBEDTLS_CERTS_C
#define MBEDTLS_PEM_PARSE_C

/* Save RAM at the expense of ROM */
#define MBEDTLS_AES_ROM_TABLES

/* Save RAM by adjusting to our exact needs */
#define MBEDTLS_ECP_MAX_BITS   384
#define MBEDTLS_MPI_MAX_SIZE   256 // 2048 bits

/* Save RAM at the expense of speed, see ecp.h */
#define MBEDTLS_ECP_WINDOW_SIZE        2
#define MBEDTLS_ECP_FIXED_POINT_OPTIM  0

/* Significant speed benefit at the expense of some ROM */
#define MBEDTLS_ECP_NIST_OPTIM

/*
 * You should adjust this to the exact number of sources you're using: default
 * is the "mbedtls_platform_entropy_poll" source, but you may want to add other ones.
 * Minimum is 2 for the entropy test suite.
 */
#define MBEDTLS_ENTROPY_MAX_SOURCES 2

/* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
#define MBEDTLS_SSL_CIPHERSUITES                        \
    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

/*
 * Save RAM at the expense of interoperability: do this only if you control
 * both ends of the connection!  (See coments in "mbedtls/ssl.h".)
 * The minimum size here depends on the certificate chain used as well as the
 * typical size of records.
 */
extern unsigned int max_content_len;
#define MBEDTLS_SSL_MAX_CONTENT_LEN             max_content_len

#if defined(TARGET_LIKE_MBED)
#include "mbedtls/target_config.h"
#endif

/*
 * Allow user to override any previous default.
 *
 * Use two macro names for that, as:
 * - with yotta the prefix YOTTA_CFG_ is forced
 * - without yotta is looks weird to have a YOTTA prefix.
 */
#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE)
#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE
#elif defined(MBEDTLS_USER_CONFIG_FILE)
#include MBEDTLS_USER_CONFIG_FILE
#endif

#include "check_config"

#endif /* MBEDTLS_CONFIG_H */
PravallikaKG commented 7 years ago

I am implementing a C program where in client and server talks to each other through socket and mbedtls is used for secure communication between client and server. While running the server and client programs at client side i am facing '-9984 - X509 - Certificate verification failed, e.g. CRL, CA or signature check failed' at 'mbedtls_ssl_handshake' call.

I referred to mbedtls/programs/ssl/ssl_server2.c and ssl_client2.c files. I have created my own ca.cert, server.cert, client.cert, server.key,client.key and ca.key files.

Following is my piece of code at server side:

int ret = mbedtls_x509_crt_parse_file(&cacert, ca_file);
if (ret != 0) {
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned %d\n\n", ret );
goto exit;
}

ret = mbedtls_x509_crt_parse_file(&srvcert, server_file);
if (ret != 0) {
    mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_file returned %d\n\n", ret );
    goto exit;
}

ret = mbedtls_pk_parse_keyfile(&pkey,serverkey_file,password);
if (ret != 0) {
    mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile server returned %d\n\n", ret );
    goto exit;
}
..............
..............

mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
{
    mbedtls_printf( " failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
    goto exit;
}

if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
{
    mbedtls_printf( " failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret );
    goto exit;
}
........................
.....................
// Performing the SSL/TLS handshake...
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
{
    if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned %d\n\n", ret );
        goto reset;
    }
}

Following is the piece of my client code:

ret = mbedtls_x509_crt_parse_file(&cd->ca_cert, ca_cert_filename);
if (ret != 0) {
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file of ca returned %d\n\n", ret );
exit(ret);
}

ret = mbedtls_x509_crt_parse_file(&cd->client_cert, client_cert_filename);
if (ret != 0) {
        mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_file of client returned %d\n\n", ret );
        exit(ret);
}

ret = mbedtls_pk_parse_keyfile(&cd->client_pkey,client_key_filename,password);
if (ret != 0) {
    mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile client returned %d\n\n", ret );
    exit(ret);
}

mbedtls_ssl_conf_authmode( &cd->conf, MBEDTLS_SSL_VERIFY_REQUIRED );
mbedtls_ssl_conf_ca_chain( &cd->conf, &cd->ca_cert, NULL  );

if( ( ret = mbedtls_ssl_conf_own_cert( &cd->conf, &cd->client_cert, &cd->client_pkey ) ) != 0 )
{
        mbedtls_printf( " failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
    exit(ret);
}
mbedtls_ssl_conf_rng( &cd->conf, mbedtls_ctr_drbg_random, &cd->ctr_drbg );
mbedtls_ssl_conf_dbg( &cd->conf, my_debug, stdout );

if( ( ret = mbedtls_ssl_setup( &cd->ssl, &cd->conf ) ) != 0 )
{
            mbedtls_printf( " failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret );
            freeClientTLSData(ret,cd);
        exit(ret);
 }

 if( ( ret = mbedtls_ssl_set_hostname( &cd->ssl, COMMON_NAME ) ) != 0 )
 {
            mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
            freeClientTLSData(ret,cd);
        exit(ret);
 }
if( ( ret = mbedtls_ssl_setup( &cd->ssl, &cd->conf ) ) != 0 )
{
        mbedtls_printf( " failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret );
        freeClientTLSData(ret,cd);
    exit(ret);
}

while( ( ret = mbedtls_ssl_handshake( &cd->ssl ) ) != 0 )
{
        if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
        {
                mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
                freeClientTLSData(ret,cd);
        exit(ret);
        }
}

I tried passing server common name to the api 'mbedtls_ssl_set_hostname()' and also tried passing ca cert common name. Still the issue persists. I got the common name of server or ca by double clicking those ca.cert and server.cert files.

Please let me know if i am missing anything.

Thanks in Advance.

PravallikaKG commented 7 years ago

My issue is resolved. I am facing it because of using invalid certificates

FayeY commented 7 years ago

Hi muboldi, is this problem still unsolved now?