Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Using Provisioning example, Storing Cert and PVT Key in storage NVS partition pcks11 module. How to retrieve so as to use demo_tasks. #108

Open
wreyford opened this issue Aug 14, 2024 · 2 comments

Comments

@wreyford
Copy link

I have managed to provision a device using fleet provisioning
Amazon Web Services IoT MQTT (Fleet Provisioning With CSR) Example
I'm using ESP-IDF 5.2
ESP32S3-F16-R8

I have for now stored the certificate and private key (obtained during fleet provisioning) in the
nvs storage partition: storage,data,nvs,,0x4000,,

The example disconnects, then reconnects, so all is fine.

Now I'm trying to implement MQTT for publish of data to the IoT Hub, using the
main/demo_tasks/temp_sub_pub_and_led_control_demo

the network context differs from the one used in fleet provisioning.

struct NetworkContext
{
    MbedtlsPkcs11Context_t * pParams;
};

I wish to use the more refined approach used in the temp_sub_pub_and_led_control_demo for our MQTT telemetry (publish) framework.

To set up the NetworkContext, it uses:

/* Static function definitions ************************************************/

static BaseType_t prvInitializeNetworkContext( void )
{
    /* This is returned by this function. */
    BaseType_t xRet = pdPASS;

    /* This is used to store the error return of ESP-IDF functions. */
    esp_err_t xEspErrRet;

    /* Verify that the MQTT endpoint and thing name have been configured by the
     * user. */
    if( strlen( CONFIG_GRI_MQTT_ENDPOINT ) == 0 )
    {
        ESP_LOGE( TAG, "Empty endpoint for MQTT broker. Set endpoint by "
                       "running idf.py menuconfig, then Golden Reference Integration -> "
                       "Endpoint for MQTT Broker to use." );
        xRet = pdFAIL;
    }

    if( strlen( CONFIG_GRI_THING_NAME ) == 0 )
    {
        ESP_LOGE( TAG, "Empty thingname for MQTT broker. Set thing name by "
                       "running idf.py menuconfig, then Golden Reference Integration -> "
                       "Thing name." );
        xRet = pdFAIL;
    }

    /* Initialize network context. */

    xNetworkContext.pcHostname = CONFIG_GRI_MQTT_ENDPOINT;
    xNetworkContext.xPort = CONFIG_GRI_MQTT_PORT;

    /* Get the device certificate from esp_secure_crt_mgr and put into network
     * context. */
    xEspErrRet = esp_secure_cert_get_device_cert( &xNetworkContext.pcClientCert,
                                                  &xNetworkContext.pcClientCertSize );

    if( xEspErrRet == ESP_OK )
    {
        #if CONFIG_GRI_OUTPUT_CERTS_KEYS
            ESP_LOGI( TAG, "\nDevice Cert: \nLength: %" PRIu32 "\n%s",
                      xNetworkContext.pcClientCertSize,
                      xNetworkContext.pcClientCert );
        #endif /* CONFIG_GRI_OUTPUT_CERTS_KEYS */
    }
    else
    {
        ESP_LOGE( TAG, "Error in getting device certificate. Error: %s",
                  esp_err_to_name( xEspErrRet ) );

        xRet = pdFAIL;
    }

    /* Putting the Root CA certificate into the network context. */
    xNetworkContext.pcServerRootCA = root_cert_auth_start;
    xNetworkContext.pcServerRootCASize = root_cert_auth_end - root_cert_auth_start;

    if( xEspErrRet == ESP_OK )
    {
        #if CONFIG_GRI_OUTPUT_CERTS_KEYS
            ESP_LOGI( TAG, "\nCA Cert: \nLength: %" PRIu32 "\n%s",
                      xNetworkContext.pcServerRootCASize,
                      xNetworkContext.pcServerRootCA );
        #endif /* CONFIG_GRI_OUTPUT_CERTS_KEYS */
    }
    else
    {
        ESP_LOGE( TAG, "Error in getting CA certificate. Error: %s",
                  esp_err_to_name( xEspErrRet ) );

        xRet = pdFAIL;
    }

    #if CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL

        /* If the digital signature peripheral is being used, get the digital
         * signature peripheral context from esp_secure_crt_mgr and put into
         * network context. */

        xNetworkContext.ds_data = esp_secure_cert_get_ds_ctx();

        if( xNetworkContext.ds_data == NULL )
        {
            ESP_LOGE( TAG, "Error in getting digital signature peripheral data." );
            xRet = pdFAIL;
        }
    #else /* if CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */
        xEspErrRet = esp_secure_cert_get_priv_key( &xNetworkContext.pcClientKey,
                                                   &xNetworkContext.pcClientKeySize );

        if( xEspErrRet == ESP_OK )
        {
            #if CONFIG_GRI_OUTPUT_CERTS_KEYS
                ESP_LOGI( TAG, "\nPrivate Key: \nLength: %" PRIu32 "\n%s",
                          xNetworkContext.pcClientKeySize,
                          xNetworkContext.pcClientKey );
            #endif /* CONFIG_GRI_OUTPUT_CERTS_KEYS */
        }
        else
        {
            ESP_LOGE( TAG, "Error in getting private key. Error: %s",
                      esp_err_to_name( xEspErrRet ) );

            xRet = pdFAIL;
        }
    #endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */

    xNetworkContext.pxTls = NULL;
    xNetworkContext.xTlsContextSemaphore = xSemaphoreCreateMutex();

    if( xNetworkContext.xTlsContextSemaphore == NULL )
    {
        ESP_LOGE( TAG, "Not enough memory to create TLS semaphore for global "
                       "network context." );

        xRet = pdFAIL;
    }

    return xRet;
}

The examples use the certificate and private key stored in esp_secure_cert_manager partition, (thus a different approach to storing in storage nvs partition as keypair values written by pcks11 module in the fleet provisioning example).:
esp_secure_cert, 0x3F, , 0xD000, 0x2000, encrypted

I need to retrieve the client certificate from the pcks11 module, also the private key using their respective labels,
and then I need to populate xNetworkContext with them, as in this example:

xEspErrRet = esp_secure_cert_get_device_cert( &xNetworkContext.pcClientCert,
                                                  &xNetworkContext.pcClientCertSize );

How can I read the certificate into xNetworkContext.pcClientCert from the nvs partition using pkcs11 module?
I'm trying to get this to work, so we can migrate our application to AWS.
I'm building out the framework as I go.

As an alternative later see below.

(I have a ATECC608B TRUST CUSTOM chip on the same custom PCB. It is not utilized at this moment.
I could possibly write the Private Key and Client key obtained during fleet provisioning to the trust custom chip at runtime, and then use it for the examples, but have no idea how to do that. )

@cookpate
Copy link
Member

I haven't worked with the secure element on ESP32, but the functions referenced in this issue appear to be implemented by https://github.com/espressif/esp_secure_cert_mgr
Perhaps check documentation there, first.

Otherwise, additional Espressif documentation for ESP-IDF 5.2 can be found here:
https://docs.espressif.com/projects/esp-idf/en/v5.2.2/esp32s3/api-reference

@aggarg
Copy link
Member

aggarg commented Aug 29, 2024

@wreyford, were you able to try out @cookpate's suggestion?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants