ESP32-S3 AWS IoT - Error parsing certificate

slare09
Posts: 8
Joined: Wed Aug 02, 2023 1:32 pm

ESP32-S3 AWS IoT - Error parsing certificate

Postby slare09 » Mon Sep 11, 2023 4:03 pm

Hi,

I've got a demo program running which communicates with AWS IoT Core using MQTTS and certificates generated by AWS.
When the certificates are added to the firmware as binaries:

Code: Select all

target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT)
The code works without problems.
In order to go to production I am placing these certificates in the NVS, to start with, without encryption. Now when I try to do this I get a parsing error:

Code: Select all

I (8104) coreMQTT: Establishing a TLS session to aaaaa.amazonaws.com:8883.
E (8164) esp-tls-mbedtls: mbedtls_x509_crt_parse returned -0x2180
E (8174) esp-tls-mbedtls: Failed to set client pki context
E (8184) esp-tls-mbedtls: Failed to set client configurations, returned [0x8015] (ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED)
E (8194) esp-tls: create_ssl_handle failed
E (8194) esp-tls: Failed to open new connection
I could verify that the certificates are loaded correctly (by printing them out).
So what could the issue be? I read some things about nul termination, but this should be taken care of by the nvs_get_str...

The nvs.csv

Code: Select all

key,type,encoding,value
certs,namespace,,
certificate,file,string,main/certs/certificate.pem.crt
private_key,file,string,main/certs/private.pem.key
Reading the files:

Code: Select all

esp_err_t get_credentials_from_nvs(char **cert, char **priv_key){
    nvs_handle_t nvs_handle;
    esp_err_t err = nvs_open(NVS_AWS_IOT_NAMESPACE, NVS_READONLY, &nvs_handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG_AWS_IOT, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
        return err;
    }
    // Read cert from NVS
    size_t required_size;
    err = nvs_get_str(nvs_handle, NVS_AWS_IOT_KEY_CERT, NULL, &required_size);
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
        ESP_LOGE(TAG_AWS_IOT, "Error (%s) reading NVS!\n", esp_err_to_name(err));
        return err;
    }
    *cert = malloc(required_size);
    // *cert = calloc(1, required_size +1); // The extra byte is for the NULL termination
    err = nvs_get_str(nvs_handle, NVS_AWS_IOT_KEY_CERT, *cert, &required_size);
    // Print certificate content to console
    ESP_LOGI(TAG_AWS_IOT, "Certificate content: %s", *cert);
    
    // Read private key from NVS
    err = nvs_get_str(nvs_handle, NVS_AWS_IOT_KEY_PRIVATE_KEY, NULL, &required_size);
    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
        ESP_LOGE(TAG_AWS_IOT, "Error (%s) reading NVS!\n", esp_err_to_name(err));
        return err;
    }
    *priv_key = malloc(required_size);
    // *priv_key = calloc(1, required_size +1); // The extra byte is for the NULL termination
    err = nvs_get_str(nvs_handle, NVS_AWS_IOT_KEY_PRIVATE_KEY, *priv_key, &required_size);
    // Print private key content to console
    ESP_LOGI(TAG_AWS_IOT, "Private key content: %s", *priv_key);
    nvs_close(nvs_handle);

    return err;
}
I also once tried to store them as a binary and read them out as a blob, but this gave the same result.
Any help is highly appreciated.

MicroController
Posts: 1553
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32-S3 AWS IoT - Error parsing certificate

Postby MicroController » Mon Sep 11, 2023 7:23 pm

What length are you using for certificate_len and key_len?
keylen Size of key in bytes.
For PEM data, this includes the terminating null byte,
so keylen must be equal to `strlen(key) + 1`.

slare09
Posts: 8
Joined: Wed Aug 02, 2023 1:32 pm

Re: ESP32-S3 AWS IoT - Error parsing certificate

Postby slare09 » Tue Sep 12, 2023 8:33 am

Thanks @MicroController !

That fixed it, I've tried adding 1 to the size, but at the wrong place :roll:
So for future reference if anyone else encounters this problem, do not add 1 to the size while getting the certificate from nvs (in my code in

Code: Select all

esp_err_t get_credentials_from_nvs(char **cert, char **priv_key)
But add one for the pNetworkContext which is used by the MQTTClient (I am using the esp-aws-iot example code):

Code: Select all

 #ifndef CLIENT_USERNAME
        // Old code when storing certs as binary in firmware
        // pNetworkContext->pcClientCert = client_cert_start;
        // pNetworkContext->pcClientCertSize = client_cert_end - client_cert_start;
        // pNetworkContext->pcClientKey = client_key_start;
        // pNetworkContext->pcClientKeySize = client_key_end - client_key_start;
        // New code when storing certs in NVS
        pNetworkContext->pcClientCert = AWS_IOT_CERTIFICATE;
        pNetworkContext->pcClientCertSize = strlen(AWS_IOT_CERTIFICATE)+1;
        pNetworkContext->pcClientKey = AWS_IOT_PRIVATE_KEY;
        pNetworkContext->pcClientKeySize = strlen(AWS_IOT_PRIVATE_KEY)+1;
    #endif

Who is online

Users browsing this forum: No registered users and 71 guests