Skip to content

Adds ATECC608 secure element support for Espressif esp32 #173

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

Merged
merged 18 commits into from
Aug 10, 2022

Conversation

sckulkarni246
Copy link
Contributor

Purpose

  • Adds support for Microchip ATECC608 secure element to the Espressif esp32 processor

Does this introduce a breaking change?

[ ] Yes
[x] No

Pull Request Type

What kind of change does this Pull Request introduce?

[ ] Bugfix
[x] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Documentation content changes
[ ] Other... Please describe:

How to Test

  • Get the code
$ git clone https://github.com/sckulkarni246/iot-middleware-freertos-samples --recurse-submodules
$ cd iot-middleware-freertos-samples
  • Open the menuconfig window
$ cd demos/projects/ESPRESSIF/esp32
$ idf.py menuconfig
  • Configure your Wi-Fi and Azure DPS ID scope
  • Select the authentication mechanism as X509 certificates
  • Enable support for Secure Element in the ESP-TLS component and mbedTLS
  • Configure the I2C pins correctly for the ATECC608 chip and select the correct variant
$ idf.py build
$ idf.py -p <port> flash monitor

What to Check

Verify that once the Wi-Fi connection is successful, the logs now mention that ATECC is used for the TLS handshake and that the registration happens successfully

I (8987) esp-tls-mbedtls: Initialize the ATECC interface...
I (11917) tls_freertos: (Network connection 0x3ffca760) Connection to global.azure-devices-provisioning.net established.
I (12077) MQTT: Packet received. ReceivedBytes=2.
I (12077) MQTT: CONNACK session present bit not set.
I (12077) MQTT: Connection accepted.
I (12087) MQTT: Received MQTT CONNACK successfully from broker.
I (12097) MQTT: MQTT connection established with the broker.
I (12097) AZ IOT: AzureIoTProvisioning established an MQTT connection with global.azure-devices-provisioning.net
I (14117) AZ IOT: AzureIoTProvisioning attempting to subscribe to the MQTT topic: devices/+/messages/devicebound/#
I (14317) MQTT: Packet received. ReceivedBytes=3.
I (17087) MQTT: Packet received. ReceivedBytes=144.
I (17087) MQTT: De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
I (17087) MQTT: State record updated. New state=MQTTPublishDone.
I (17107) AZ IOT: $dps/registrations/res/202/?$rid=1&retry-after=3
I (17107) AZ IOT: {"operationId":"4.zzzz711fa18225c0.yyyyc2fb-3afe-4ce7-9f2d-3ec21227xxxx","status":"assigning"}

Other Information

  • This software was tested on a NodeMCU ESP32 board based on the ESP32-WROOM module
  • The ATECC608 variants tested are ATECC608-TNGTLS and ATECC608-TFLXTLS
  • The device and the signer certificates are obtained from the ATECC608 device beforehand using Microchip's cryptoauthlib-based python sample code.
  • ESP IDF version used is v4.4

…ks correctly for device certificate and registration ID generated at runtime using added functions
@ghost
Copy link

ghost commented May 16, 2022

CLA assistant check
All CLA requirements met.

@danewalton-msft danewalton-msft self-assigned this May 16, 2022
@danewalton-msft danewalton-msft added the customer-issued Issues submitted by customers label May 16, 2022
}

ATCA_STATUS s;
s = atcab_read_serial_number(sernum);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a minor question -
This call to atcab_read_serial_number will only succeed if the initialization with the secure element which is currently done here is successful.

Are we sure that we have already initialised esp-tls at this point ( and thus the secure element ) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure that we have already initialised esp-tls at this point ( and thus the secure element ) ?

Yes, we can be sure as the call to the Azure function would be done only after the TLS connection has been established with the Azure DPS service. The hint for me was that these lines appear in the log before the Azure code kicks in.

...
I (8987) esp-tls-mbedtls: Initialize the ATECC interface...
I (11917) tls_freertos: (Network connection 0x3ffca760) Connection to global.azure-devices-provisioning.net established.
...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, thanks for the explanation. I think this is fine.

@@ -90,6 +90,11 @@ TlsTransportStatus_t TLS_Socket_Connect( NetworkContext_t * pNetworkContext,
{
esp_transport_ssl_set_cert_data_der( pNetworkContext->xTransport, ( const char * ) pNetworkCredentials->pucRootCa, pNetworkCredentials->xRootCaSize );
}
#if CONFIG_ESP_TLS_USE_SECURE_ELEMENT
Copy link

@AdityaHPatwardhan AdityaHPatwardhan May 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you have just enabled the secure element boolean in the esp_tls_cfg_t with this structure I think it would only be possible to use secure element of type TrustNGo ( and TrustFlex if it is not modified).
for TrustNGo no additional data is necessary just enabling the boolean and selecting the appropriate type of secure element ( which is set to TrustNGo by default) is enough.

But if you choose to use TrustCustom or TrustFlex with a modified certificate then I think you will have to provide the option to also provide the client certificate with this.
Also currently the esp-tls is hardcoded (For simplicity) to use key block 0 for the TLS connection. Should that be mentioned somethere in a comment ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if you choose to use TrustCustom or TrustFlex with a modified certificate then I think you will have to provide the option to also provide the client certificate with this.

Hi @AdityaHPatwardhan - this is a very good point.. thanks for bringing this up! I actually tested the development with a trustflex chip as well (with Microchip factory certs in them). It worked correctly as the cert defs were found correctly. I will add a comment to this effect in the transport_tls_esp32.c file for now.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, sounds good!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AdityaHPatwardhan Added the comment.

31b21c4

@CIPop
Copy link
Contributor

CIPop commented May 18, 2022

Thank you @sckulkarni246 and @AdityaHPatwardhan for the contribution to add support for ATECC608!

Here are some overall comments and questions:

  1. Do you know of any developer boards we can advertise that use ESP32 and ATECC608 (no breadboard / soldering required)?
  2. Please add documentation to our ESP32 sample on how to obtain the certificate (or point to existing documentation).
    1. I assume there is a certificate signing request that would allow that certificate to either be self-signed or signed by a CA (for DPS group authentication). The certificate name must be the same as the serial number in that case.
    2. You've mentioned custom certificates - in that case, it may be that the serial number is not the same as the certificate and should still be hardcoded.
  3. We have talked about the PR and decided to modify the architecture a bit:
    1. Depending on your answers re the second question above, we will need to add a common (not ESP/ATECC) specific interface to obtain the registrationID.
    2. The changes you have added will be specific to a new ESP TLS layer compiled specifically for ATECC support.
    3. An ESP IDF Menuconfig option should be available to toggle ATECC usage on/off.
    4. We would like to keep submodules to a minimum and instead use CMake's FetchContent to avoid increasing the download sizes for devs not using ESP.

Copy link
Contributor

@CIPop CIPop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few comments.

.gitmodules Outdated
@@ -1,3 +1,6 @@
[submodule "libs/azure-iot-middleware-freertos"]
path = libs/azure-iot-middleware-freertos
url = https://github.com/Azure/azure-iot-middleware-freertos.git
[submodule "demos/projects/ESPRESSIF/esp32/components/esp-cryptoauthlib"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided to move this to CMake FetchContent to avoid downloading the new lib for samples not using it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good! Do I need to amend anything in my code?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please move this to be a CMake component instead.

The implementation should be similar to the FREERTOS_PATH and free_rtos_fetch() function in the root CMakeLists.txt.
We would also need documentation on how to use this in conjunction with the ESP32 sample (i.e. within the demo\projects\espressif\esp32\readme.md file).

Copy link
Contributor Author

@sckulkarni246 sckulkarni246 Jul 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to see where to plug in the esp-cryptoauthlib as a CMake component. One finding is that the CMakeLists.txt for the ESPRESSIF projects (esp32, aziot) simply calls the project.cmake of the IDF.

Considering that the IDF CMake does all the steps within itself (configure -> generate -> build...), there seems to be no way to tell the CMake file in the Azure IoT project that we need the esp-cryptoauthlib component.
If this is true, a viable solution can be one of the below two (unless I have misunderstood the CMake component concept itself - please correct me if I am wrong here).... @CIPop and @AdityaHPatwardhan

Do you recommend a better option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CIPop Please ignore my comment above - I have figured out what I need to do to read the sdkconfig variable and conditionally fetch the esp-cryptoauthlib.

esp_transport_ssl_use_secure_element( pNetworkContext->xTransport );

#ifndef CONFIG_ATECC608A_TNG
/* This is either a TrustFLEX or a TrustCUSTOM chip - generate (using atcacert_* API) or plug in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unclear. I'm not familiar with TrustFLEX vs TrustCUSTOM (I assume it's a discussion between using the factory provisioned ATECC certificates vs custom ones?)
Please clarify or add code on how one would add their certificate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I assume it's a discussion between using the factory provisioned ATECC certificates vs custom ones?)

You are correct - it is indeed about that.

Please clarify or add code on how one would add their certificate.

Let me work on this and commit. Also, I noticed an error in my comment. The parts that need no action are TrustFLEX and TrustCUSTOM. Thank you for bringing this up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CIPop I have corrected the comments as well as added code that plugs in the custom device certificate.

c405422

@@ -25,6 +25,11 @@
/* Crypto helper header. */
#include "crypto.h"

/* For using the ATECC608 secure element if support is configured */
#if CONFIG_ESP_TLS_USE_SECURE_ELEMENT && CONFIG_ATCA_MBEDTLS_ECDSA
#include "cryptoauthlib.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd like to maintain common code to be device-agnostic.
We will provide a different include file with an interface that extracts the registration ID.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good! Do let me know if there is a change you want me to do.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move any code related to ESP32 to files within demos/projects/espressif/esp32/*. I think this should be moved into transport_tls_esp32.c.

I am still reading about deriving certificates from ATEC608. If I understand correctly, only Trust&Go is guaranteed to always have the same certificate. Our Provisioning Service validates the certificate's key and the Common Name must match the Registration ID.

Since for TrustFlex and TrustCUSTOM the certificate can be changed, the ESP-IDF Azure IoT config should take precendence.

Copy link
Contributor Author

@sckulkarni246 sckulkarni246 Jul 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still reading about deriving certificates from ATEC608. If I understand correctly, only Trust&Go is guaranteed to always have the same certificate.

Yes, this is always right.

Since for TrustFlex and TrustCUSTOM the certificate can be changed, the ESP-IDF Azure IoT config should take precendence.

For TrustFLEX, if someone chooses to use the Microchip template certs, then the CN and hence the registration ID can be derived from ATECC608 chip.
But, I see why accommodating everything can be tricky here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The design I'm thinking of is to either:

  1. Use the #defines that we already have
  2. Use a common interface to extract information such as registrationID/deviceID, etc (we could, in the future, add hub name, global endpoint, etc)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the #defines that we already have

Do we have a #define to allow using any alternative mechanism for private key, cert, etc. if not using the kconfig menu?

If not, how do you feel about checking if the registration ID macro is blank wherever the registration ID is being used? If blank, we call the function that populates the registration ID correctly. This function can then be moved to the transport_tls_esp32.c file.

Pseudocode:

...

if registration ID macro is blank

    call the function that calls cryptoauthlib API to populate the registration ID

endif

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a #define to allow using any alternative mechanism for private key, cert, etc. if not using the kconfig menu?

We do not, and the sample code is common among many other platforms so we cannot rely on kconfig only.

I propose adding a new #define USE_HSM (hardware security module) and a new interface - let's start with a single function to obtain the registration ID.

ifdef USE_HSM
   call getRegistrationID() (transport_tls_esp32.c would need to define one specific to reading it from the ATECC chip _if_ the chip is enabled in kconfig).
else
  use the registration ID maco
endif

For this application specifically, the developer would need to enable the ATECC chip in kconfig. Ideally, that could also automatically define USE_HSM.

This creates a design open to addition of new types of HSMs in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @CIPop - I need your feedback.

Based on the comments above, I have altered the implementation such that there are no cryptoauthlib or ESP32 macros/functions in the common code.

For instance, the dynamic registration ID part in sample_azure_iot_pnp.c looks like this.

#ifdef democonfigUSE_HSM
        /* Redefine the democonfigREGISTRATION_ID macro using registration ID 
        generated dynamically using the HSM */
        
        /* We use a pointer instead of a buffer so that the getRegistrationId
         function can allocate the necessary memory depending on the HSM */
        char *registration_id = NULL;
        ulStatus = getRegistrationId( &registration_id );
        configASSERT( ulStatus == 0);
        #undef democonfigREGISTRATION_ID
        #define democonfigREGISTRATION_ID   registration_id
             
#endif

The democonfigUSE_HSM gets defined inside demo_config.h depending on whether the use of secure element is enabled as below.

/**
 * @brief Defines the macro for HSM usage depending on whether 
 * the support for ATECC608 is enabled in the kconfig menu
 */
#ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT
    #if CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN & CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY
        #define democonfigUSE_HSM
        uint32_t getRegistrationId( char ** ); // should be defined by provider
    #endif
#endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */

One change that may be necessary is that we can no more use sizeof(democonfigREGISTRATION_ID) - 1 - will have to use strlen(democonfigREGISTRATION_ID).
What are your thoughts on this code structure?

Quick question: Why are we using sizeof(...) - 1 instead of strlen(...) considering these macros are all strings anyway?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

Why are we using sizeof(...) - 1 instead of strlen(...) considering these macros are all strings anyway?

Asked the original devs: It was out of caution to make sure the value isn't determined at runtime, in case the compiler isn't smart enough to collapse strlen(const) to the appropriate numerical value.

I'm OK with either solution:

  • use strlen() everywhere
  • create an #else branch leaving the old code as-is

… TrustCUSTOM v/s other variants - added code that will plug in the provided custom device cert to the network context. No code needed for other variants - esp-tls handles device cert attachment internally
@sckulkarni246
Copy link
Contributor Author

@CIPop Below, I attempt to respond to some of your comments/questions posted above.

  1. Do you know of any developer boards we can advertise that use ESP32 and ATECC608 (no breadboard / soldering required)?

@AdityaHPatwardhan I remember Amey mentioning ESP32 DevkitC supports the WROOM32-SE module. Do you know which kits can be added to the below list?

Please add documentation to our ESP32 sample on how to obtain the certificate (or point to existing documentation).

I found this resource on esp-cryptoauthlib repo. Is this close to what you would need?

I assume there is a certificate signing request that would allow that certificate to either be self-signed or signed by a CA (for DPS group authentication).

For pre-provisioned variants, that CA would be the Microchip signer. The Microchip signer cert is one of the outputs of the esp_cryptoauth_utility shared above.
For custom variant, that CA would be generated on the fly during the provisioning process using the esp_cryptoauth_utility shared above.

The certificate name must be the same as the serial number in that case.

Yes. More specifically, the device cert CN would be snXXXXXXXXXXXXXXXXXX where XX...XX is the 9-byte serial number of the chip.

You've mentioned custom certificates - in that case, it may be that the serial number is not the same as the certificate and should still be hardcoded.

That is theoretically correct. But, I do not know if the utility linked above generates a CSR with the device serial number as the CN or uses a fixed value. @AdityaHPatwardhan I seek your help for getting this info...thanks!

The changes you have added will be specific to a new ESP TLS layer compiled specifically for ATECC support.

Yes, this compilation would happen once the configuration has been correctly done to enable the ATECC support.

An ESP IDF Menuconfig option should be available to toggle ATECC usage on/off.

There is an option to toggle the usage of secure element on or off - CONFIG_ESP_TLS_USE_SECURE_ELEMENT. But just enabling this and triggering a build gives an error. It expects the esp_cryptoauthlib to be present as a component already before the build is attempted.

@AdityaHPatwardhan
Copy link

@CIPop Thanks for your review comments. @sckulkarni246 has already anserwed most of them. Please find additional explanation below.

  1. Do you know of any developer boards we can advertise that use ESP32 and ATECC608 (no breadboard / soldering required)?

@AdityaHPatwardhan I remember Amey mentioning ESP32 DevkitC supports the WROOM32-SE module. Do you know which kits can be added to the below list?

I think we can add ESP32-WROOM32-SE to that list. The module has microchips ATECC608A or ATECC608B integrated in the chip.

Please add documentation to our ESP32 sample on how to obtain the certificate (or point to existing documentation).

I found this resource on esp-cryptoauthlib repo. Is this close to what you would need?

I think this document would surely provide the information on how to generate the device certificate for TrustCustom type of ATECC. This link https://github.com/espressif/esp-cryptoauthlib/tree/master/esp_cryptoauth_utility#step-2--provision-the-modulegenerate-manifest-file explains the steps performed by the utility.

You've mentioned custom certificates - in that case, it may be that the serial number is not the same as the certificate and should still be hardcoded.

That is theoretically correct. But, I do not know if the utility linked above generates a CSR with the device serial number as the CN or uses a fixed value. @AdityaHPatwardhan I seek your help for getting this info...thanks!

Hi, Thanks for raising this point. I think we might have to change the code for obtaining the registration id slightly for that. The reason being that in case of TrustCustom certificates the cn is set as the serial number of the chip without the sn parameter. e.g. 01232592FD80DDCBEE.

@sckulkarni246
Copy link
Contributor Author

@AdityaHPatwardhan Just for clarity, is the below assumption correct? I will make the changes accordingly.

  • Trust&GO, TrustFLEX - no change needed. The CN should be snXXXXXXXXX.
  • TrustCUSTOM - the CN should be XXXXXXXXX.

Where XXXXXXXXX is the device serial number hex string.

@AdityaHPatwardhan
Copy link

@AdityaHPatwardhan Just for clarity, is the below assumption correct? I will make the changes accordingly.

  • Trust&GO, TrustFLEX - no change needed. The CN should be snXXXXXXXXX.
  • TrustCUSTOM - the CN should be XXXXXXXXX.

Where XXXXXXXXX is the device serial number hex string.

Yes, this is right.

… the beginning of the CN - this change is now done in each of the implementations of registration ID preparation functions
@CIPop
Copy link
Contributor

CIPop commented May 23, 2022

Thank you for the documentation pointers. We'll need to add a readme document to point to the official Espressif docs.

Once I have everything tested, I can help refactor the code to maintain all sample code separate from any ESP32 or ATECC changes (we'll need a separate compilation unit for that).

I think we can add ESP32-WROOM32-SE to that list. The module has microchips ATECC608A or ATECC608B integrated in the chip.

We have confirmed with Espressif that the above module is not recommended for new designs (NRND) and should not be referenced. Instead I have investigated other possibilities, ideally without the need for a breadboard/hardware changes and found a likely candidate:

I just got the ATECC608 board and will test with an ESP32-WROOM-DevKit and connector wires. I'll need some time to set everything up and give this a quick try.

@sckulkarni246
Copy link
Contributor Author

Hi @CIPop - Just want to check in... were you able to use the software to connect to the Azure DPS?

@CIPop
Copy link
Contributor

CIPop commented Jun 3, 2022

@sckulkarni246 , so far this isn't working for me. I'm still investigating.

I'm seeing issues with the driver and my ATECC:

I (5982) esp-tls-mbedtls: Initialize the ATECC interface...
../components/esp-cryptoauthlib/cryptoauthlib/lib/calib/calib_read.c:103:f0:calib_read_zone - execution failed
../components/esp-cryptoauthlib/cryptoauthlib/lib/calib/calib_read.c:619:f0:calib_read_zone - falied
E (27502) esp-tls-mbedtls: Failed to initialize atca device, returned -0xFFFFFF10

Looking at the I2C driver, I see that the pins I wanted to use are considered to be on a secondary bus and I couldn't find any documentation how that is configured yet (I wanted to use SDA pin 22 and SCL pin 20).
Changing to the lib defaults (SCL - pin 16 and SDL - pin 17) didn't work either.

The ATECC608 that I have is stating the address is 0x60 but, looking at the driver, I see different addresses being used for different purposes during initialization:
image

I'm using an ESP-WROVER-KIT with JTAG debugging and I will be attaching a logic analyzer to see if this is a hardware issue.

@AdityaHPatwardhan
Copy link

AdityaHPatwardhan commented Jun 3, 2022

@CIPop I just checked, I think there seems to be some discrepancy in updating the latest config option in esp-cryptoauthlib and esp-idf about selecting I2C slave address.
I think that menuconfig option is not propogated in esp-idf.
so even if you select the appropriate slave address in menuconfig, I think esp_tls_mbedtls.c might still use hardcoded slave addresses for respective types of atecc608.
I will fix the bug on esp-idf side.
Meanwhile can you please modify appropriate type of slave address at this place

@CIPop
Copy link
Contributor

CIPop commented Jun 3, 2022

I have verified that the right address is used in hal_i2c_send now but I don't see any activity on the pins I'm using: IO16 and IO17 for my ESP-WROVER-KIT.
Is there any additional I2C pin configuration or initialization that I need to make?

image

@AdityaHPatwardhan
Copy link

AdityaHPatwardhan commented Jun 3, 2022

Hi @CIPop, I think there might be some problem with the I2C PIN numbers. From where did you refer pin 16 and pin 17 as the I2C SDA and SCL pins ?. I think those pin numbers are for ESP32-WROOM32-SE but AFAIK for esp32 the numbers were SDA=21 ans SCL=22. Can you please try those, Thanks

@CIPop
Copy link
Contributor

CIPop commented Jun 3, 2022

@AdityaHPatwardhan those pins were the defaults. I originally tried with 21, 22. I can't find any documentation where I2C is tied to specific pins so I'm assuming this is a software I2C implementation and any pins can be used?
I did find the reason 16 and 17 did not work for ESP-WROVER-Kit: they are reserved for PSRAM signaling and so they are not connected to the pin headers.

I've tried 21,22 and 25,26 and, in both cases the I2C signal as recorded by my logic analyzer doesn't look correct.
I've enabled I2C hal logging.

There is still something wrong with the I2C communication:

D (121080) HAL_I2C: addr: 0, txdata: 0x3ffc9ec0 , txlength: 1
I (121080) HAL_I2C: 0x3ffc9ec0   01                                                |.|
D (122130) HAL_I2C: addr: 6a, rxdata: 0x3ffc9ec4 , rxlength: 4
I (122130) HAL_I2C: 0x3ffc9ec4   ff ff ff 3f                                       |...?|
D (122130) HAL_I2C: addr: 0, txdata: 0x3ffc9ec0 , txlength: 1
I (122140) HAL_I2C: 0x3ffc9ec0   01                                                |.|
D (123170) HAL_I2C: addr: 6a, rxdata: 0x3ffc9ec4 , rxlength: 4
I (123170) HAL_I2C: 0x3ffc9ec4   ff ff ff 3f                                       |...?|
D (123170) HAL_I2C: addr: 0, txdata: 0x3ffc9ec0 , txlength: 1
I (123190) HAL_I2C: 0x3ffc9ec0   01                                                |.|
D (124220) HAL_I2C: addr: 6a, rxdata: 0x3ffc9ec4 , rxlength: 4

Updated above:

Regardless of the configured address, the code is always trying to send data on address 0.
Reading is done on the correct address (in above case I have reverted the change to 0x6A - the default address).

@CIPop
Copy link
Contributor

CIPop commented Jun 3, 2022

My logic analyzer shows that the wrong data is being sent:
image

image

@CIPop
Copy link
Contributor

CIPop commented Jun 4, 2022

I think we need to investigate more issues for the cryptoauthlibrary:

  1. The issue with menuconfig not properly passing the address to esp_tls_mbedtls.c.
  2. The driver ignores the ATECC address for I2C and always writes to address 0x0 (confirmed by adding logs) addr: 0,:
D (122130) HAL_I2C: addr: 0, txdata: 0x3ffc9ec0 , txlength: 1
I (122140) HAL_I2C: 0x3ffc9ec0   01                                                |.|
  1. After hardcoding the address in hal_esp32_i2c.c (from cryptoauthlib's HAL esp32 port, the data on the I2C bus seems shifted to the left by 1 bit.

I have confirmed this using 2 different logic analyzers at very high sampling rates (>25MHz). I used both DSView and Sigrock (with 2 different USB analyzers). Note how the reading is adding an extra 0 at the beginning and reinterpreting the last bit:

// The address for my device:
Actual: 30: 0110000
Expect: 60: 1100000

// The default address in cryptoauthlib:
Actual: 35: 0110101
Expect: 6A: 1101010

I tried with I2C was configured at either 100kHz (default) or 400kHz (below images):

image

image

I did find this issue mentioning pull-up resistors espressif/arduino-esp32#741.

@AdityaHPatwardhan I noticed that the HAL (hal_i2c_init) supports 2 I2C busses (0 and 1). The pins I'm currently using are the default for I2C_NUM_1 (I2C1_SDA_PIN=21, I2C1_SCL_PIN=22) but, in my case, I2C_NUM_0 is used with the ones configured via menuconfig.
In both cases the internal pull-up resistors have been disabled (GPIO_PULLUP_DISABLE).

@AdityaHPatwardhan
Copy link

AdityaHPatwardhan commented Jun 4, 2022

@CIPop Thanks for your analysis. I shall also investigate from my side.

I would just like to note that I am using ATECC608B of TnG type for atecc608_ecdsa example in esp-idf and it is succeeding at my end.
But in this case I am using ESP32-WROOM32-SE module hence the default I2C configurations are working in my case.

I (353) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (363) atecc_example: Seeding the random number generator...
I (373) atecc_example:  ok
I (373) atecc_example:   . Initialize the ATECC interface for Trust & GO ...
I (393) atecc_example:  ok
I (393) atecc_example:  Check the data zone lock status...
I (393) atecc_example:  ok: locked
I (403) atecc_example:  Get the device info (type)...
I (403) atecc_example:  ok: 60 03
I (403) atecc_example:  Get the public key...
I (463) atecc_example:  ok
I (463) atecc_example:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJnlD3q4AsBlc63H1FGF5Px3wWzSx
hQ5CZ5YWsOlRZuhoVOJ4afq1zK8TXI37IbKpmgsP3K19n0fHJPRvkOxJCA==
-----END PUBLIC KEY-----
I (473) atecc_example:  Using a hardware private key ...
I (543) atecc_example:  ok
I (543) atecc_example:  Generating ECDSA Signature...
I (643) atecc_example:  ok
I (643) atecc_example:  Verifying ECDSA Signature...
I (693) atecc_example:  ok

@CIPop
Copy link
Contributor

CIPop commented Jun 7, 2022

Thank you @AdityaHPatwardhan. I have narrowed this down I2C timing (SCL). The first clock pulse is too shallow and is ignored, shifting the entire transaction by 1 bit to the left.
(Edit): I meant the other way - the first part is noise and is considered a pulse adding a 0 and shifting the entire transaction to the right.

image
image

I have tried turning on pull-up resistors, tried 2 separate ESP boards (different types), 100kHz/300kHz, ESP-IDF versions 4.4.1 (latest) and 4.3.

@sckulkarni246
Copy link
Contributor Author

Hi @CIPop ,

The driver ignores the ATECC address for I2C and always writes to address 0x0 (confirmed by adding logs) addr: 0

You have mentioned above about the address 0x00 being sent out. I want to clarify that it may be happening because the cryptoauthlib sends out a wake token to the ATECC608 chip. The wake token is implemented using I2C at 100 kHz and sending out 0x00 as the device address. This is followed by the actual command for the device. So, the 0x00 should not be a problem.

About I2C addresses

If the 7-bit address of the device is 0x60 (I2C write should send 0xC0), it means it is a TrustCUSTOM device (blank). The device address for Trust&GO is 0x35 (I2C write should send 0x6A) and TrustFLEX device is 0x36 (I2C write should send 0x6C).

A quick question - what is the I2C speed you are working at? If not 100 kHz, can you try switching the I2C frequency to 100 kHz and try the operations that don't work?

@CIPop
Copy link
Contributor

CIPop commented Jun 29, 2022

@AdityaHPatwardhan, here's the SDKConfig (redacted to remove credentials): sdkconfig.txt

Also, this is the UX config related to ATECC. The DT100104 board has all switches off except either 5 or 6 (first two ATECC608B TrustCUSTOM):
image

For the case that worked (TnG), the only changes were the chip type and the I2C address (0x6A). The DT100104 was configured with switch 1 on (rest off).

@AdityaHPatwardhan
Copy link

AdityaHPatwardhan commented Jun 29, 2022

Hi @CIPop Thanks for sharing the configurations. For TrustnGo/TFlex case the certificate have already been stored in the ATECC608 by Microchip. In that case they can be read from the device by using microchip provided API.
But in case of TrustCustom, this is not the case. so in esp-tls, mbedtls asks the user to provide the device certificate externally ref - https://github.com/espressif/esp-idf/blob/c2ccc383dae2a47c2c2dc8c7ad78175a3fd11361/components/esp-tls/esp_tls_mbedtls.c#L923.
Can you make sure that the client certificate provided to esp-tls by your project is valid ?
I think that is the same certificate that the mbedtls is failing to parse .

@sckulkarni246
Copy link
Contributor Author

@CIPop @AdityaHPatwardhan Gentlemen, unfortunately I am down with a rather serious health thing.
I will respond to the various questions and push code early next week.
Thanks!

@CIPop
Copy link
Contributor

CIPop commented Jun 29, 2022

I am down with a rather serious health thing.

I am very sorry to hear that! Take care @sckulkarni246 ! I will also be on vacation - we can resume working on this in about 2 weeks.

Can you make sure that the client certificate provided to esp-tls by your project is valid ?

@AdityaHPatwardhan I have used the defaults within esp-cryptoauthlib to generate the certificate and generation was successful, but I did have to change the crypto library version in the Python tool to get it working:

python secure_cert_mfg.py --port COM6 --i2c-sda-pin 21 --i2c-scl-pin 22

I have sent you the certificates and the log output via email. Please compare with your configuration and let me know if there is anything wrong on your end.

OpenSSL is able to parse both:

Trust and Go

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            72:79:25:12:ac:70:76:c9:59:f7:eb:d5:d9:eb:34:71
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: O = Microchip Technology Inc, CN = Crypto Authentication Signer 2C90
        Validity
            Not Before: Nov 11 03:00:00 2020 GMT
            Not After : Nov 11 03:00:00 2048 GMT
        Subject: O = Microchip Technology Inc, CN = sn0123AE96783DE0B801
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:14:c4:5f:e1:da:99:4f:b5:a1:2a:32:58:29:89:
                    a8:08:14:ea:c8:af:45:f2:bc:99:7f:b4:22:e5:75:
                    ef:d4:c7:b6:2d:d3:7b:ff:fd:0e:f4:03:04:f9:64:
                    26:cc:64:12:a7:da:38:82:9d:a8:af:2d:a3:33:ad:
                    7c:c7:09:7e:6f
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DirName:/serialNumber=eui48_E8EB1B20198A
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Key Usage: critical
                Digital Signature, Key Agreement
            X509v3 Subject Key Identifier:
                9E:C5:16:EB:18:91:9D:AC:D9:60:B7:22:AA:16:38:17:9B:57:85:45
            X509v3 Authority Key Identifier:
                keyid:11:F4:F2:05:23:97:D2:58:24:79:EE:2B:D6:99:10:3A:BF:45:C8:93

    Signature Algorithm: ecdsa-with-SHA256
         30:44:02:20:31:06:09:73:fc:46:c5:dd:cd:c1:06:af:0c:e4:
         51:3c:24:33:b8:3d:f0:f3:81:2d:35:a8:07:a1:e8:f3:0a:21:
         02:20:5c:28:42:4e:1c:37:6d:fd:f3:13:96:dd:b9:19:6c:25:
         94:f0:ec:68:9c:65:88:56:57:0d:0a:73:7f:0b:af:5c
SHA1 Fingerprint=BA:6B:C8:42:2A:09:00:BF:15:69:FB:C4:3A:3F:5F:86:EB:A4:98:00

TrustCUSTOM

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            53:0b:b8:ff:84:f1:aa:df:ea:09:00:be:f9:b9:53:3b
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: O = ESP, CN = Sample Signer FFFF
        Validity
            Not Before: Jun 28 23:00:00 2022 GMT
            Not After : Jun 28 23:00:00 2062 GMT
        Subject: O = ESP, CN = 0123F626D1819819EE
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:e5:20:d1:7d:f9:a7:d6:4c:c4:e7:d5:5e:5a:7d:
                    41:1a:de:20:5b:82:a5:26:98:2c:b6:e9:a0:87:3e:
                    f5:60:91:e3:cc:e3:56:53:8b:c3:41:67:e8:3b:2e:
                    1d:30:53:e6:c3:5c:2a:d3:5f:27:79:cb:f9:ea:db:
                    d0:1e:96:46:a3
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Authority Key Identifier:
                keyid:03:2E:B1:1A:A7:B3:0B:12:46:C3:0D:D8:47:61:98:1E:5A:2A:6A:FF

    Signature Algorithm: ecdsa-with-SHA256
         30:45:02:21:00:a7:0a:d6:df:7d:2b:59:77:45:1b:c2:a7:e5:
         93:13:6a:26:b3:8c:60:ab:73:61:8b:26:78:50:18:23:3e:6a:
         4a:02:20:2e:4e:29:21:bd:2c:cd:6c:37:09:47:2b:7c:fe:04:
         7a:62:ac:2a:1b:7a:bf:e2:8b:f4:0c:8c:5e:6c:f4:5c:f7
SHA1 Fingerprint=AC:45:65:B7:21:B6:4F:88:F7:DB:98:39:6A:18:A9:5A:31:3F:C1:23

@AdityaHPatwardhan
Copy link

@sckulkarni246 No issues, Please take care !

@CIPop
Copy link
Contributor

CIPop commented Jul 21, 2022

@sckulkarni246 , @AdityaHPatwardhan any progress on this?

  • I have left some comments to change the design a bit.
  • Tests for TrustFlex and TrustCUSTOM failed for me. The reason is the ESP tooling rather than this PR. @AdityaHPatwardhan could you please take a look?

@sckulkarni246
Copy link
Contributor Author

I have left some comments to change the design a bit.

Hi @CIPop - I am working on it. I shall push the usage doc and change the ESP-Cryptoauthlib to a CMake Fetch module soon and push both of these.
I do have a few questions about some other suggested change...will post them as well.

1. Removes esp-cryptoauthlib as a git submodule
2. Adds esp-cryptoauthlib as a CMake FetchComponent for the ESPRESSIF esp32/ target (aziotkit support will be added later)
3. Adds a README for ATECC608 support enablement
4. Adds images required by the README referred to in 3 above
@sckulkarni246
Copy link
Contributor Author

I shall push the usage doc and change the ESP-Cryptoauthlib to a CMake Fetch module soon and push both of these.

@CIPop This is now done. I have tested this by cloning separately into a new folder and following the steps as mentioned in the newly added README.
Please note - I have done the push just for esp32 target for now. Once you and @AdityaHPatwardhan give me the go-ahead, I will make the necessary changes for aziotkit as well and push.

1. Defines a new macro for enabling usage of HSM
2. Uses the new macro to dynamically generate registration ID for Azure DPS
3. For ESPRESSIF: Separates implementation for registration ID generation depending on the ATECC608 Trust variant selected
4. Removes any device specific code from Azure common code
@sckulkarni246
Copy link
Contributor Author

Hi @CIPop , @AdityaHPatwardhan - I am summarising here the various feedbacks addressed by the last two commits:

  • Removed esp-cryptoauthlib as a git submodule and made it a CMake FetchComponent
  • Removed any device-specific code and macros from Azure common code. No more cryptoauthlib or ESP32 references in sample_azure_iot*.c files.
  • transport_tls_esp32.c : Implemented a new function called getRegistrationId(...) that dynamically generates the registration ID depending on the ATECC608 trust variant selected using separate static functions.
  • transport_tls_esp32.c : Custom cert provided in the kconfig menu will be used for TrustCUSTOM and TrustFLEX variant
  • Added a README with relevant snapshots to help customers in their process of adding ATECC608 support to esp32 target.

Do let me know your comments about the PR in its current state and how we can take it to the next stage.
Thanks!

@sckulkarni246
Copy link
Contributor Author

sckulkarni246 commented Aug 9, 2022

@CIPop Bump!

Any comments or feedback on the last 2 commits? These address some of the points mentioned in the review comments.

Regards,
Shashank

Copy link
Contributor

@CIPop CIPop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @sckulkarni246 !
I'm going to try this out on my board before merging.

**If build fails**, ensure that above steps are followed correctly. Before re-attempting the process,
- delete the build directory using `rm -rf build/`
- delete the sdkconfig file by using `rm sdkconfig`.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: we need more information and steps how to provision the ATECC as well as how to configure the application. I think we can move forward with this PR and add more documentation later.

ulStatus = getRegistrationId( &registration_id );
configASSERT( ulStatus == 0);
#undef democonfigREGISTRATION_ID
#define democonfigREGISTRATION_ID registration_id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for maintaining the old behavior: very elegant solution!

@sckulkarni246
Copy link
Contributor Author

Hi @CIPop - thank you for approving the changes and your review comments. It was fun working with you and @AdityaHPatwardhan !
Do let me know if any more changes are needed.

Copy link

@AdityaHPatwardhan AdityaHPatwardhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late review, I have reviewed the MR again.
The code now looks very good to me!
Thanks @sckulkarni246 for adding the support of using ATECC608 in Azure.
Thanks @CIPop for your contribution and additions.

Copy link
Collaborator

@danewalton-msft danewalton-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for the late review but otherwise looks good to me! tried the compilation locally

@CIPop CIPop merged commit 96010d1 into Azure-Samples:main Aug 10, 2022
@CIPop
Copy link
Contributor

CIPop commented Aug 10, 2022

Thank you @sckulkarni246 and @AdityaHPatwardhan for the contribution!
The change has been integrated and a CI step is verifying the build for ATECC TnG.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
customer-issued Issues submitted by customers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants