Hello folks,
Long time lurker and first time poster here. I do apologize if this looks like a commonly asked question, but I have hit a brick wall and require some help.
As the title states, I am trying to use the ATECC608A with STM32F103RC and libopenCM3 HAL. I am trying to port the cryptoauthlilb to STM32 and libopenCM3.
There are two distinct problems that I am facing.
1. Developing the appropriate custom hal to use libopenCM3 layer.
2. Getting the cryptoauthlib to compile successfully and link it into my project.
The cryptoauthlib documentation is very very daunting and does not make it easy to integrate the library without using their "trust platform". The pdf documentation
in the github repo is over 1200 pages long!!
So, I started looking for some work someone else has done to take inspiration from, and I found this.
https://github.com/pccr10001/cryptoauthlib
and it looked like it was an easy guide to follow and port. So I cloned the specific repo and tried to make the changes to suit the STM32
This is how my directory structure looks.
Top Level Directory
.
├── cryptoauth_test
│ └── bin
├── libopencm3
│ ├── doc
│ ├── include
│ ├── ld
│ ├── lib
│ ├── mk
│ ├── scripts
│ └── tests
└── shared_libs
├── cryptoauthlib
├── hd44780_v2
├── littlefs
└── mhz19bProject Directory ( cryptoauth_test )
.
├── Makefile
├── bin
│ ├── main.d
│ └── main.su
├── compile_commands.json
├── flash.cfg
├── main.c
└── usb.hcryptoauthlib contents ( trimmed to show relevant sections )
├── README.md
├── library.properties
├── license.txt
├── src
│ ├── CMakeLists.txt
│ ├── atca_bool.h
│ ├── atca_cfgs.c
│ ├── atca_cfgs.h
│ ├── atca_command.c
│ ├── atca_command.h
│ ├── atca_compiler.h
│ ├── atca_device.c
│ ├── atca_device.h
│ ├── atca_devtypes.h
│ ├── atca_execution.c
│ ├── atca_execution.h
│ ├── atca_iface.c
│ ├── atca_iface.h
│ ├── atca_status.h
│ ├── basic
│ │ ├── README.md
│ │ ├── atca_basic.c
│ │ ├── atca_basic.h
│ │ ├── atca_helpers.c
│ │ └── atca_helpers.h
..............
│ ├── cryptoauthlib.h
│ ├── hal
│ │ ├── atca_hal.c
│ │ ├── atca_hal.h
│ │ ├── hal_arduino_wire.cpp
│ │ ├── hal_esp32_i2c.c
│ │ ├── hal_esp32_timer.c
│ │ ├── hal_freertos.c
│ │ └── hal_stm32_i2c.c
This is what my hal_stm32_i2c.c file looks like
#include <stdio.h> #include <string.h> #include "../atca_iface.h" #include "../cryptoauthlib.h" #include "atca_hal.h" #include "delay.h" #include "libopencm3/stm32/rcc.h" #include "libopencm3/stm32/gpio.h" #include "libopencm3/stm32/i2c.h" #ifdef ATCA_HAL_STM32 void atca_delay_ms(uint32_t ms) { delay_ms(ms); } void hal_i2c_change_baud(ATCAIface iface, uint32_t speed) { return ATCA_SUCCESS; } ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) { rcc_clock_setup_in_hse_8mhz_out_72mhz();// For "blue pill" rcc_periph_clock_enable(RCC_GPIOB); // I2C rcc_periph_clock_enable(RCC_AFIO); rcc_periph_clock_enable(RCC_I2C1); gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO8 | GPIO9); gpio_set(GPIOB, GPIO8 | GPIO9); gpio_primary_remap(0, 0); } ATCA_STATUS hal_i2c_post_init(ATCAIface iface) { return ATCA_SUCCESS; } ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) { ATCAIfaceCfg *cfg = iface->mIfaceCFG; txdata[0] = 0x03; txlength++; i2c_send_start(I2C1); for (uint8_t i = 0; i < txlength; i++) { i2c_send_data(I2C1, txdata); txdata++; } i2c_send_stop(I2C1); return ATCA_SUCCESS; } ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) { ATCAIfaceCfg *cfg = iface->mIfaceCFG; int addr = cfg->atcai2c.slave_address; rxdata[0] = i2c_get_data(I2C1); // rxdata[0] = Wire.read(); *rxlength = rxdata[0]; if (*rxlength > 1) { for (uint8_t i = 0; i < *rxlength - 1; i++) { rxdata = i2c_get_data(I2C1); } } return ATCA_SUCCESS; } ATCA_STATUS hal_i2c_release(void *hal_data) { i2c_send_stop(I2C1); return ATCA_SUCCESS; } ATCA_STATUS hal_i2c_wake(ATCAIface iface) { return ATCA_SUCCESS; } ATCA_STATUS hal_i2c_idle(ATCAIface iface) { return ATCA_SUCCESS; } ATCA_STATUS hal_i2c_sleep(ATCAIface iface) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); int addr = cfg->atcai2c.slave_address; uint8_t sleep_data = 0x01; i2c_send_start(I2C1); i2c_send_data(I2C1, sleep_data); i2c_send_stop(I2C1); return ATCA_SUCCESS; } ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) { return ATCA_UNIMPLEMENTED; } ATCA_STATUS hal_i2c_discover_devices(int bus_num, ATCAIfaceCfg *cfg, int *found) { return ATCA_UNIMPLEMENTED; } #endif
For now, the contents of the hal_stm32_i2c.c are not critical as I would like to, first, be able to successfully build the library along with my source and then fine tune the hal to get it working with my hardware.
And this is what my Makefile in the source directory looks like
PROJECT = crypto_test BUILD_DIR = bin SHARED_DIR = ../shared_libs ../shared_libs/cryptoauthlib/src CFILES = main.c # CFILES += delay.c CFILES += delay.c atca_cfgs.c atca_iface.c hal/atca_hal.c hal/hal_stm32_i2c.c basic/atca_basic.c TGT_CFLAGS += -DATCA_HAL_STM32 # TODO - you will need to edit these two lines! DEVICE=stm32f103rct6 # ST-FLASH = st-flash OOCD_INTERFACE = jlink OOCD_TARGET = stm32f1x # OOCD_FILE = board/stm32ldiscovery.cfg # You shouldn't have to edit anything below here. VPATH += $(SHARED_DIR) INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR)) OPENCM3_DIR=../libopencm3 include $(OPENCM3_DIR)/mk/genlink-config.mk include ../rules.mk include $(OPENCM3_DIR)/mk/genlink-rules.mk size: all $(SIZE) $(PROJECT).elf write: $(PROJECT).bin $(ST-FLASH) write $(PROJECT).bin 0x8000000 erase: $(ST-FLASH) erase
This is what my atca_cfgs.c looks like
/** * \file * \brief a set of default configurations for various ATCA devices and interfaces * * \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. * * \page License * * Subject to your compliance with these terms, you may use Microchip software * and any derivatives exclusively with Microchip products. It is your * responsibility to comply with third party license terms applicable to your * use of third party software (including open source software) that may * accompany Microchip software. * * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, * SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE * OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF * MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE * FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL * LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED * THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR * THIS SOFTWARE. */ #include <stddef.h> #include "atca_cfgs.h" #include "atca_iface.h" #include "atca_device.h" #include "cryptoauthlib.h" /** \defgroup config Configuration (cfg_) * \brief Logical device configurations describe the CryptoAuth device type and logical interface. @{ */ /* if the number of these configurations grows large, we can #ifdef them based on required device support */ #ifdef ATCA_HAL_STM32 ATCAIfaceCfg cfg_ateccx08a_i2c_stm32 = { .iface_type = ATCA_I2C_IFACE, .devtype = ATECC608A, .atcai2c.slave_address = 0xC0, .atcai2c.bus = 0, .atcai2c.baud = 100000, //.atcai2c.baud = 100000, .wake_delay = 200, .rx_retries = 20, .sda_pin = 0, .scl_pin = 0 }; #endif /** @} */
and this is what my cryptoauthlib.h looks like
/** * \file * \brief Single aggregation point for all CryptoAuthLib header files * * \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. * * \page License * * Subject to your compliance with these terms, you may use Microchip software * and any derivatives exclusively with Microchip products. It is your * responsibility to comply with third party license terms applicable to your * use of third party software (including open source software) that may * accompany Microchip software. * * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER * EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, * SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE * OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF * MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE * FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL * LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED * THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR * THIS SOFTWARE. */ #ifndef _ATCA_LIB_H #define _ATCA_LIB_H #include <stddef.h> #include <string.h> #include "hal/atca_hal.h" #include "atca_status.h" #include "atca_device.h" #include "atca_command.h" #include "atca_cfgs.h" #include "basic/atca_basic.h" #include "basic/atca_helpers.h" #define ATCA_HAL_I2C #define ATCAPRINTF // #define ATCA_HAL_ESP32 #define ATCA_HAL_STM32 // #ifdef ATCA_HAL_ESP32 // #define USE_MBEDTLS // #define SDA_PIN 25 // #define SCL_PIN 26 // #endif #ifdef ATCAPRINTF #include <stdio.h> //#define BREAK(status, message) {printf(__FUNCTION__": "message" -- Status: %02X\r\n", status); break;} #define BREAK(status, message) { printf(": "message " -- Status: %02X\r\n", status); break; } #define RETURN(status, message) { printf(": "message " -- Status: %02X\r\n", status); return status; } #define PRINTSTAT(status, message) { printf(": "message " -- Status: %02X\r\n", status); } #define PRINT(message) { printf(": "message "\r\n"); break; } #define DBGOUT(message) { printf(": "message "\r\n"); break; } #else #define BREAK(status, message) { break; } #define RETURN(status, message) { return status; } #define PRINT(message) { break; } #define DBGOUT(message) { break; } #endif #endif
And this is what my main.c file looks like
#include <stdlib.h> #include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/gpio.h> #include <libopencm3/usb/usbd.h> #include <libopencm3/usb/cdc.h> #include "libopencm3/cm3/nvic.h" #include "libopencm3/cm3/systick.h" #include "libopencm3/stm32/spi.h" #include "usb.h" #include "cryptoauthlib.h" #include "atca_cfgs.h" uint32_t temp; char test_string[13] = "Hello World\n"; uint32_t i = 2000000; extern usbd_device *usbd_dev; int main(void) { rcc_clock_setup_in_hsi_out_48mhz(); //Enable GPIOC Peripheral clock rcc_periph_clock_enable(RCC_GPIOB); //Output mode, no pull ups or pull down gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO0 | GPIO1); //Set GPIO8 and clear GPIO9 to see toggle gpio_set(GPIOB, GPIO0); gpio_clear(GPIOB, GPIO1); usbd_dev = usbd_init(&st_usbfs_v1_usb_driver, &dev, &config, usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer)); usbd_register_set_config_callback(usbd_dev, cdcacm_set_config); nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ); temp = 0; //Sets systick clocksource to clock / 8 = 6000000 counts per second systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); //Sets systick reload counter to give a 'tick' once a millisecond. // 48000000 / 48000 = 1000 overflows every second or 48000-1 systick_set_reload(5999); //Enables systick interrupt - defined in sys_tick_interrupt() handler systick_interrupt_enable(); //Starts the systick counter. systick_counter_enable(); // usbd_ep_write_packet(usbd_dev, 0x82, "Hello World\n", strlen("Hello World\n")); setup_delay_timer(); delay_ms(10000); usbd_ep_write_packet(usbd_dev, 0x82, "Hello World\n", strlen("Hello World\n")); delay_ms(10000); ATCAIfaceCfg cfg = cfg_ateccx08a_i2c_stm32; ATCA_STATUS ret = atcab_init(&cfg_ateccx08a_i2c_stm32); // Get random number uint8_t rand[32]; ret = atcab_random(rand); if (ret != ATCA_SUCCESS) { USB_Write_Message("Error Initializing Cryptochip", strlen("Error Initializing Cryptochip")); } delay_ms(10000); while (1) { } } void sys_tick_handler(void) { temp++; if (temp >= 1000) { gpio_toggle(GPIOB, GPIO1); temp = 0; } } // This is the interrupt handler for low priority USB events. Implementing a // function with this name makes it the function used for the interrupt. // TODO: Handle the other USB interrupts. void usb_lp_can_rx0_isr(void) { gpio_toggle(GPIOB, GPIO0); usbd_poll(usbd_dev); }
And this is the error I get when I
make
CC main.c
In file included from main.c:10:
../shared_libs/cryptoauthlib/src/cryptoauthlib.h:47: warning: "ATCA_HAL_STM32" redefined
47 | #define ATCA_HAL_STM32
|
<command-line>: note: this is the location of the previous definition
main.c: In function 'main':
main.c:53:21: error: 'cfg_ateccx08a_i2c_stm32' undeclared (first use in this function); did you mean 'cfg_ateccx08a_i2c_esp32'?
53 | ATCAIfaceCfg cfg = cfg_ateccx08a_i2c_stm32;
| ^~~~~~~~~~~~~~~~~~~~~~~
| cfg_ateccx08a_i2c_esp32
main.c:53:21: note: each undeclared identifier is reported only once for each function it appears in
In file included from main.c:9:
At top level:
usb.h:210:13: warning: 'cdcacm_data_tx_cb' defined but not used [-Wunused-function]
210 | static void cdcacm_data_tx_cb(usbd_device *usbd_dev, uint8_t ep)
| ^~~~~~~~~~~~~~~~~
make: *** [bin/main.o] Error 1
It looks like make is complaining about not finding a valid definition for "cfg_ateccx08a_i2c_stm32" but I hope I have correctly setup the flags and defines in the cryptoauthlib.f, atecc_cfgs.c and the makefile.
Also, I do hope that building the library is as simple as adding the C source files to the list of compilation source files in the project Makefile. Please do correct me if I am mistakes here or if it needs additional configuration steps. Of course, the necessary defines and such will also have to be passed as compilation flags.
I apologize for the super long post, but I would like to give a complete picture of what I have tried and where I am hitting a wall.
I do hope a good samaritan and asomeone who is more knowledgeable in this library can pitch in and help a fellow out. :-)
Thank you in advance folks..
Once again, I apologize for the super long post.