1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

pkg/cryptoauthlib: Add PSA Wrappers

This commit is contained in:
Lena Boeckmann 2023-08-29 19:19:42 +02:00
parent a6f3b59e7a
commit 40902cd947
15 changed files with 1114 additions and 62 deletions

View File

@ -36,7 +36,15 @@ static const i2c_conf_t i2c_config[] = {
.scl = 27,
.sda = 26,
.speed = I2C_SPEED_NORMAL
},
#ifdef BOARD_NRF52840DK
{
.dev = NRF_TWIM0,
.scl = 28,
.sda = 29,
.speed = I2C_SPEED_NORMAL
}
#endif
};
#define I2C_NUMOF ARRAY_SIZE(i2c_config)
/** @} */

View File

@ -9,6 +9,7 @@ menuconfig PACKAGE_CRYPTOAUTHLIB
bool "Microchip CryptoAuthentication Library package"
depends on TEST_KCONFIG
depends on !HAS_ARCH_EFM32
depends on HAS_PERIPH_I2C
select MODULE_AUTO_INIT_SECURITY
select MODULE_CRYPTOAUTHLIB_CONTRIB
@ -20,6 +21,12 @@ config MODULE_CRYPTOAUTHLIB_CONTRIB
select MODULE_PERIPH_I2C
select MODULE_PERIPH_I2C_RECONFIGURE if HAS_PERIPH_I2C_RECONFIGURE
config MODULE_PSA_ATCA_DRIVER
bool
depends on PACKAGE_CRYPTOAUTHLIB
default y if MODULE_PSA_CRYPTO
select PSA_KEY_MANAGEMENT
config MODULE_CRYPTOAUTHLIB_TEST
bool "Module for cryptoauthlib tests"
depends on TEST_KCONFIG
@ -56,4 +63,4 @@ config MODULE_CRYPTOAUTHLIB_TEST_API_CRYPTO
config MODULE_CRYPTOAUTHLIB_TEST_VECTORS
bool
endif
endif # PACKAGE_CRYPTOAUTHLIB

View File

@ -10,7 +10,7 @@ include $(RIOTBASE)/pkg/pkg.mk
CMAKE_MINIMAL_VERSION = 3.6.0
CFLAGS += $(INCLUDES)
CFLAGS += $(INCLUDES) # for some reason this is needed by llvm, but not for gcc
CFLAGS += -DATCA_HAL_I2C
CFLAGS += -Wno-cast-align
CFLAGS += -Wno-char-subscripts

View File

@ -19,3 +19,11 @@ endif
# Some EFM32 CPU families define AES_COUNT, which is also defined by this
# library.
FEATURES_BLACKLIST += arch_efm32
ifneq (,$(filter psa_crypto,$(USEMODULE)))
USEMODULE += psa_atca_driver
endif
ifneq (,$(filter psa_secure_element_ateccx08a_ecc_p256, $(USEMODULE)))
USEMODULE += psa_secure_element_asymmetric
endif

View File

@ -7,6 +7,11 @@ INCLUDES += -I$(PKG_SOURCE_DIR)/app
INCLUDES += -I$(PKG_SOURCE_DIR)/lib/calib
INCLUDES += -I$(RIOTPKG)/cryptoauthlib/include
ifneq (,$(filter psa_crypto, $(USEMODULE)))
DIRS += $(RIOTPKG)/cryptoauthlib/psa_atca_driver
INCLUDES += -I$(RIOTBASE)/sys/psa_crypto/include
endif
DIRS += $(RIOTPKG)/cryptoauthlib/contrib
ARCHIVES += $(BINDIR)/cryptoauthlib.a
@ -21,3 +26,8 @@ ifneq (,$(filter cryptoauthlib_test,$(USEMODULE)))
INCLUDES += -I$(PKG_TESTINCLDIR)/vectors
INCLUDES += -I$(PKG_SOURCE_DIR)/third_party/unity
endif
ifneq (,$(filter psa_crypto,$(USEMODULE)))
PSEUDOMODULES += psa_secure_element_ateccx08a
PSEUDOMODULES += psa_secure_element_ateccx08a_ecc_p256
endif

View File

@ -27,7 +27,6 @@
#include "atca.h"
#include "atca_params.h"
/* Timer functions */
void atca_delay_us(uint32_t delay)
{
@ -65,7 +64,7 @@ ATCA_STATUS hal_i2c_post_init(ATCAIface iface)
ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t word_address, uint8_t *txdata, int txlength)
{
(void) word_address;
(void)word_address;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
int ret;
@ -84,7 +83,7 @@ ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t word_address, uint8_t *txdata,
ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t word_address, uint8_t *rxdata,
uint16_t *rxlength)
{
(void) word_address;
(void)word_address;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint8_t retries = cfg->rx_retries;
int ret = -1;
@ -170,24 +169,24 @@ ATCA_STATUS hal_i2c_sleep(ATCAIface iface)
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_control(ATCAIface iface, uint8_t option, void* param, size_t paramlen)
ATCA_STATUS hal_i2c_control(ATCAIface iface, uint8_t option, void *param, size_t paramlen)
{
(void) param;
(void) paramlen;
(void)param;
(void)paramlen;
switch (option) {
case ATCA_HAL_CONTROL_WAKE:
return hal_i2c_wake(iface);
case ATCA_HAL_CONTROL_IDLE:
return hal_i2c_idle(iface);
case ATCA_HAL_CONTROL_SLEEP:
return hal_i2c_sleep(iface);
case ATCA_HAL_CHANGE_BAUD:
return ATCA_UNIMPLEMENTED;
case ATCA_HAL_CONTROL_SELECT:
case ATCA_HAL_CONTROL_DESELECT:
return ATCA_SUCCESS;
default:
return ATCA_BAD_PARAM;
case ATCA_HAL_CONTROL_WAKE:
return hal_i2c_wake(iface);
case ATCA_HAL_CONTROL_IDLE:
return hal_i2c_idle(iface);
case ATCA_HAL_CONTROL_SLEEP:
return hal_i2c_sleep(iface);
case ATCA_HAL_CHANGE_BAUD:
return ATCA_UNIMPLEMENTED;
case ATCA_HAL_CONTROL_SELECT:
case ATCA_HAL_CONTROL_DESELECT:
return ATCA_SUCCESS;
default:
return ATCA_BAD_PARAM;
}
return ATCA_UNIMPLEMENTED;
}

View File

@ -1,6 +1,6 @@
/**
* @defgroup pkg_cryptoauthlib Microchip CryptoAuthentication Library
* @ingroup pkg drivers_misc sys_crypto
* @ingroup pkg drivers_misc
* @brief Provides the library for Microchip CryptoAuth devices
* @see https://github.com/MicrochipTech/cryptoauthlib
*
@ -8,22 +8,19 @@
*
* This package provides support for the official library for Microchip CryptoAuth devices.
*
*
* ## Warning
*
* Some functions can only be used, when the data, config and otp zones of the
* device are locked. Locking is permanent and cannot be undone. Be careful if
* you're not sure you've configured everything correctly.
* For more information we refer to the data sheet of the device.
*
* @warning Some functions can only be used, when the data, config and otp zones
* of the device are locked. Locking is permanent and cannot be undone.
* Be careful if you're not sure you've configured everything correctly.
* For more information please refer to the data sheet of the device.
*
* ## Usage
*
* Add
* @code
* USEPKG += cryptoauthlib
* @endcode
* to your Makefile.
*
*
* ### Shell
*
* To facilitate the device configuration the RIOT shell provides some
@ -33,7 +30,6 @@
* The shell handler is enabled, if cryptoauthlib is included as a package in the
* Makefile of an application that also includes the shell (e.g. examples/default).
*
*
* ### No poll mode
*
* After sending a command to the device, responses are usually polled to enable
@ -41,25 +37,11 @@
* Alternatively ATCA_NO_POLL can be enabled through CFLAGS to simply
* wait for the max execution time of a command before reading the response.
*
*
* ## Implementation status
*
* This implementation was partly tested with ATECC508A and ATECC608A devices.
* We haven't tested the functions that require locking the device, yet. There's
* a wrapper in the cryptoauthlib/contrib folder, which implements most of the
* HAL functions.
* Currently the functions hal_i2c_discover_devices and hal_i2c_discover_buses
* are unimplemented, as well as hal_i2c_post_init.
*
* ### Wake function
*
* The wake function only works when a 0x00 byte is sent on an i2c interface that
* runs with with 133kHz or less.
* Currently RIOT sets the baudrate to the default value of 100 kHz and there's
* no interface to change that. If the default speed ever changes to a value
* higher than 133 kHz the wake function needs to be adapted.
* For more information on how to send a proper wake condition we refer to the
* data sheet of the device.
* Currently the functions `hal_i2c_release`, `hal_i2c_discover_devices` and
* `hal_i2c_discover_buses` are unimplemented, as well as `hal_i2c_post_init`.
*
* ## Tests
*
@ -72,4 +54,189 @@
* permanently. Unlocking is not possible!
* Also there is a test for comparing the runtime of the RIOT software implementation
* and the CryptoAuth hardware implementation for calculating a SHA-256 hash value.
*
* ## Using Multiple ATECCX08A Devices {#multi-ateccx08a}
*
* When using more than one device, you can either connect devices with different
* I2C addresses to one bus or devices with the same address to separate buses.
* The ATECCX08A devices provide a way to change the I2C address during device
* configuration (for more details, read the datasheet or the API documentation).
*
* ATECCX08A device parameters are configured in
* `RIOT/pkg/cryptoauthlib/include/atca_params.h`.
* There you can specify your device's address, the I2C bus to use and more by
* defining `ATCA_PARAMS`. Per default one device is defined in RIOT (example shown below).
*
* @code
* #define ATCA_PARAM_I2C (I2C_DEV(0))
* #define ATCA_PARAM_ADDR (ATCA_I2C_ADDR)
* #define ATCA_RX_RETRIES (20)
* #define ATCA_DEVTYPE (ATECC608A)
*
* #define ATCA_PARAMS { .iface_type = ATCA_I2C_IFACE, \
* .devtype = ATCA_DEVTYPE, \
* .atcai2c.address = ATCA_PARAM_ADDR, \
* .atcai2c.bus = ATCA_PARAM_I2C, \
* .atcai2c.baud = -1, \
* .wake_delay = 1500, \
* .rx_retries = ATCA_RX_RETRIES }
* @endcode
*
* If you want to use more than one device, the best way is to create a file called
* `custom_atca_params.h` in your application folder (you can see an example of this in
* `examples/psa_crypto`).
*
* In your custom file you can now add a second device to `ATCA_PARAMS`:
* @code
* #define ATCA_PARAM_I2C_DEV0 (I2C_DEV(0))
* #define ATCA_PARAM_ADDR_DEV0 (ATCA_I2C_ADDR_DEV0)
* #define ATCA_RX_RETRIES_DEV0 (20)
* #define ATCA_DEVTYPE_DEV0 (ATECC608A)
*
* #define ATCA_PARAM_I2C_DEV1 (I2C_DEV(0))
* #define ATCA_PARAM_ADDR_DEV1 (ATCA_I2C_ADDR_DEV1)
* #define ATCA_RX_RETRIES_DEV1 (20)
* #define ATCA_DEVTYPE_DEV1 (ATECC608A)
*
* #define ATCA_PARAMS { .iface_type = ATCA_I2C_IFACE, \
* .devtype = ATCA_DEVTYPE_DEV0, \
* .atcai2c.address = ATCA_PARAM_ADDR_DEV0, \
* .atcai2c.bus = ATCA_PARAM_I2C_DEV0, \
* .atcai2c.baud = -1, \
* .wake_delay = 1500, \
* .rx_retries = ATCA_RX_RETRIES }, \
* { .iface_type = ATCA_I2C_IFACE, \
* .devtype = ATCA_DEVTYPE_DEV1, \
* .atcai2c.address = ATCA_PARAM_ADDR_DEV1, \
* .atcai2c.bus = ATCA_PARAM_I2C_DEV1, \
* .atcai2c.baud = -1, \
* .wake_delay = 1500, \
* .rx_retries = ATCA_RX_RETRIES }
* @endcode
*
* Now you just need to add the following to your Makefile:
* @code
* CFLAGS += -DCUSTOM_ATCA_PARAMS
* INCLUDES += -I$(APPDIR)
* @endcode
*
* This way your custom params file is included in the build process and both your
* devices will be initialized by the `auto_init` module.
*
* To use them you need to utilize the `calib`-API of the cryptoauth driver, which
* allows you to pass a device handle. Pointers to all initialized devices are stored
* in the `atca_devs_ptr` array, which is included in `atca_params.h`.
* Include `atca_params.h` in your source file and pass the device handle as shown below.
*
* @code {.c}
* ATCADevice dev = atca_devs_ptr[0];
* calib_sha_start(dev);
* @endcode
*
* ## Using Cryptoauthlib as a backend for PSA Crypto {#psa-cryptoauthlib}
*
* To use cryptoauthlib as a backend for [PSA Crypto](#sys_psa_crypto), it is best to
* overwrite the `atca_params.h` file with your own `custom_atca_params.h` file, similar
* to the one described in [Using Multiple ATECCX08A Devices](#multi-ateccx08a).
*
* When using PSA, the `ATCA_PARAMS` define contains an additional value: A location
* value of the type @ref psa_key_location_t. Each secure element you use needs its own
* location value. The primary device can get the value
* @ref PSA_KEY_LOCATION_PRIMARY_SECURE_ELEMENT. All others must be within the range of
* @ref PSA_KEY_LOCATION_SE_MIN and @ref PSA_KEY_LOCATION_SE_MAX.
*
* Your structure should now look like this:
* @code
* #define PSA_ATCA_LOCATION (PSA_KEY_LOCATION_PRIMARY_SECURE_ELEMENT)
* #define ATCA_PARAM_I2C (I2C_DEV(0))
* #define ATCA_PARAM_ADDR (ATCA_I2C_ADDR)
* #define ATCA_DEVTYPE (ATECC608A)
* #define ATCA_RX_RETRIES (20)
*
* #define ATCA_PARAMS { .atca_loc = PSA_ATCA_LOCATION,\
* .cfg = {\
* .iface_type = ATCA_I2C_IFACE, \
* .devtype = ATCA_DEVTYPE, \
* .atcai2c.address = ATCA_PARAM_ADDR, \
* .atcai2c.bus = ATCA_PARAM_I2C, \
* .atcai2c.baud = -1, \
* .wake_delay = 1500, \
* .rx_retries = ATCA_RX_RETRIES } \
* }
* @endcode
*
* When using multiple SEs, just add more device parameters as shown in section
* [Using Multiple ATECCX08A Devices](#multi-ateccx08a).
*
* ## Slot Configurations
* The ATECCX08A devices have their own key management, which can be configured by
* setting flags in the device's configuration and data zone. There is a large variety
* of possible configurations, which can not entirely be represented by PSA Crypto.
*
* For now we assume that users are familiar with their device's datasheet and have configured
* it in a way that it is usable. PSA can not yet work with keys that are already stored on the
* device, which means all key slots must be writable after locking the configuration and data zone.
*
* For ECC operations this means that key slot configurations need to allow at least the
* use of the `gen_key` command, for AES and HMAC key slots it means that clear write operations
* must be allowed.
*
* @warning In case of AES and HMAC keys this may lead to security issues,
* as it allows for manipulating key material.
*
* Users need to make their configurations known to PSA Crypto.
* For this you need to initialize a list of key slot configuration structures, with a structure
* for each slot.
*
* For these devices the structure looks like this:
* @code {.c}
* typedef struct {
* psa_key_type_t key_type_allowed; // Declare the key type allowed in this slot
* uint8_t key_persistent; // Ignore for now, PSA does not yet support persistent keys
* uint8_t slot_occupied; // Set to 0, PSA will set this to one after writing a key
* } psa_atca_slot_config_t;
* @endcode
*
* To make your configurations known to PSA, simply add the following to your `custom_atca_params.h`
* file (these values are only an example, of course you need to modify them according to
* your needs).
*
* @code {.c}
* #define ATCA_SLOTS_DEV0 { { PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { PSA_KEY_TYPE_AES, 0, 0 }, \
* { PSA_KEY_TYPE_HMAC, 0, 0 }, \
* { PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { 0, 1, 1 }, \
* { 0, 0, 0 }, \
* { PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1), 0, 0 }, \
* { 0, 0, 0 }, \
* { 0, 0, 0 }}
*
* #define ATCA_CONFIG_LIST { ATCA_SLOTS_DEV0 }
* @endcode
*
* To use multiple devices, define `ATCA_SLOTS_DEV0` - `ATCA_SLOTS_DEVX` and add them to
* `ATCA_CONFIG_LIST` like so:
*
* @code {.c}
* #define ATCA_CONFIG_LIST { ATCA_SLOTS_DEV0 }, \
* { ATCA_SLOTS_DEV1 }, \
* ... \
* { ATCA_SLOTS_DEVX }
* @endcode
*
* A usage example for this can be found in `examples/psa_crypto`.
*
* ## Troubleshooting
*
* ### Device Initialization fails
*
* Make sure the I2C bus speed is set to `I2C_SPEED_NORMAL`.
*/

View File

@ -29,6 +29,7 @@ extern "C" {
/**
* @brief Default device and word addresses for ATECC508A
* @{
*/
#define ATCA_I2C_ADDR (0xC0) /**< Default device address is 0xC0 */
@ -36,6 +37,38 @@ extern "C" {
#define ATCA_SLEEP_ADDR (0x01) /**< Word address to write to for sleep mode */
#define ATCA_IDLE_ADDR (0x02) /**< Word address to write to for idle mode */
#define ATCA_DATA_ADDR (0x03) /**< Word address to read and write to data area */
/** @} */
#if IS_USED(MODULE_PSA_SECURE_ELEMENT_ATECCX08A)
#include "psa/crypto_types.h"
/**
* @brief Structure containing the Cryptoauthlib specific AES context
*/
typedef struct {
uint8_t iv[16];
psa_encrypt_or_decrypt_t direction;
union atca_context {
atca_aes_cbc_ctx_t aes_cbc;
} aes_ctx;
} psa_atca_cipher_context_t;
/**
* @brief Structure containing information about which type of key
* can be held by a specific key slot on an ATECCX08 device.
*
* If a slot should be ignored by the implementation,
* just mark it as persistent and occupied.
*/
typedef struct {
/* Type of key permitted for slot */
psa_key_type_t key_type_allowed;
/* Specify if key should be stored persistently or can be overwritten */
uint8_t key_persistent;
/* Specify whether slot is already occupied */
uint8_t slot_occupied;
} psa_atca_slot_config_t;
#endif /* MODULE_PSA_SECURE_ELEMENT_ATECCX08A */
#ifdef __cplusplus
}

View File

@ -49,4 +49,4 @@ extern "C" {
}
#endif
#endif /* ATCA_CONFIG_H */
/** @} */
/** @} */

View File

@ -22,8 +22,19 @@
#include "board.h"
#include "periph/i2c.h"
#include "atca.h"
#include "cryptoauthlib.h"
#include "kernel_defines.h"
#ifdef CUSTOM_ATCA_PARAMS
#include "custom_atca_params.h"
#endif
#if IS_USED(MODULE_PSA_SECURE_ELEMENT_ATECCX08A)
#include "psa/crypto_types.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -45,8 +56,9 @@ extern "C" {
*/
#ifndef ATCA_PARAM_I2C
#define ATCA_PARAM_I2C I2C_DEV(0)
#define ATCA_PARAM_I2C (I2C_DEV(0))
#endif
#ifndef ATCA_PARAM_ADDR
#define ATCA_PARAM_ADDR (ATCA_I2C_ADDR)
#endif
@ -58,17 +70,37 @@ extern "C" {
#endif
#ifndef ATCA_PARAMS
#define ATCA_PARAMS { .iface_type = ATCA_I2C_IFACE, \
.devtype = ATCA_DEVTYPE, \
.atcai2c.address = ATCA_PARAM_ADDR, \
.atcai2c.bus = ATCA_PARAM_I2C, \
.atcai2c.baud = -1, /**< Not used in RIOT */ \
.wake_delay = 1500, \
.rx_retries = ATCA_RX_RETRIES }
/**
* @brief Configuration parameters for the primary ATCA device
*/
#define ATCA_PARAMS { .iface_type = ATCA_I2C_IFACE, \
.devtype = ATCA_DEVTYPE, \
.atcai2c.address = ATCA_PARAM_ADDR, \
.atcai2c.bus = ATCA_PARAM_I2C, \
.atcai2c.baud = -1, /**< Not used in RIOT */ \
.wake_delay = 1500, \
.rx_retries = ATCA_RX_RETRIES }
#endif
/**@}*/
#if IS_USED(MODULE_PSA_SECURE_ELEMENT_ATECCX08A)
/**
* @brief Structure to store ATCA device configuration
*/
typedef struct {
psa_key_location_t atca_loc;
ATCAIfaceCfg cfg; /**< ATCA configuration parameters */
} atca_params_t;
/**
* @brief Allocation of ATCA device descriptors
*/
static const atca_params_t atca_params[] =
{
ATCA_PARAMS
};
#else
/**
* @brief Allocation of ATCA device descriptors
*/
@ -76,6 +108,17 @@ static const ATCAIfaceCfg atca_params[] =
{
ATCA_PARAMS
};
#endif
/**
* @brief Number of connected devices
*/
#define ATCA_NUMOF (ARRAY_SIZE(atca_params))
/**
* @brief List of device pointers for all available devices
*/
extern ATCADevice atca_devs_ptr[ATCA_NUMOF];
#ifdef __cplusplus
}

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,691 @@
/*
* Copyright (C) 2021 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_psa_crypto
* @{
*
* @file
* @brief Glue code translating between PSA Crypto and the Microchip Cryptoauth Library APIs
*
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg.de>
*
* @}
*/
#include "atca_params.h"
#include "psa/crypto.h"
#include "psa_crypto_se_driver.h"
#define ENABLE_DEBUG 0
#include "debug.h"
/**
* @brief AES block size supported by ATCA devices
*/
#define AES_128_BLOCK_SIZE (16)
/**
* @brief AES key size supported by ATCA devices
*/
#define AES_128_KEY_SIZE (16)
/**
* @brief Size of an ellipic curve public key supported by ATCA devices
*/
#define ECC_P256_PUB_KEY_SIZE (64)
/**
* @brief Maximum IV length supported by ATCA devices
*/
#define ATCA_MAX_IV_LEN (16)
/**
* @brief Size of ATCA TempKey Register
*/
#define ATCA_WRITE_BUFFER_SIZE (32)
/**
* @brief Check whether a specified algorithm is supported by this driver
*
* @param alg Algorithm of type @ref psa_algorithm_t
*
* @return int
* 1 if @c alg is supported
* 0 otherwise
*/
#define ALG_IS_SUPPORTED(alg) \
((alg == PSA_ALG_ECB_NO_PADDING) || \
(alg == PSA_ALG_CBC_NO_PADDING) || \
(alg == PSA_ALG_ECDSA(PSA_ALG_SHA_256)) || \
(alg == PSA_ALG_HMAC(PSA_ALG_SHA_256)))
/**
* @brief Check whether a specified key size is supported by this driver
*
* @param size Size of the specified key
* @param type Type of the specified key
*
* @return int
* 1 if @c size is supported
* 0 otherwise
*/
#define KEY_SIZE_IS_SUPPORTED(size, type) \
((type == PSA_KEY_TYPE_AES && size == AES_128_KEY_SIZE) || \
(PSA_KEY_TYPE_IS_ECC(type) && size == (ECC_P256_PUB_KEY_SIZE + 1)) || \
(type == PSA_KEY_TYPE_HMAC && size == 32))
/**
* @brief Convert ATCA status values to PSA errors
*
* @param error
*
* @return @ref psa_status_t
*/
static psa_status_t atca_to_psa_error(ATCA_STATUS error)
{
switch (error) {
case ATCA_NOT_LOCKED:
case ATCA_EXECUTION_ERROR:
case ATCA_FUNC_FAIL:
return PSA_ERROR_BAD_STATE;
case ATCA_WAKE_FAILED:
case ATCA_RX_FAIL:
case ATCA_RX_NO_RESPONSE:
case ATCA_TX_TIMEOUT:
case ATCA_RX_TIMEOUT:
case ATCA_TOO_MANY_COMM_RETRIES:
case ATCA_COMM_FAIL:
case ATCA_TIMEOUT:
case ATCA_TX_FAIL:
return PSA_ERROR_COMMUNICATION_FAILURE;
case ATCA_RX_CRC_ERROR:
case ATCA_STATUS_CRC:
return PSA_ERROR_DATA_CORRUPT;
case ATCA_SMALL_BUFFER:
return PSA_ERROR_BUFFER_TOO_SMALL;
case ATCA_BAD_OPCODE:
case ATCA_BAD_PARAM:
case ATCA_INVALID_SIZE:
case ATCA_INVALID_ID:
return PSA_ERROR_INVALID_ARGUMENT;
case ATCA_UNIMPLEMENTED:
return PSA_ERROR_NOT_SUPPORTED;
default:
return PSA_ERROR_GENERIC_ERROR;
}
}
const char *atca_status_to_humanly_readable(ATCA_STATUS status)
{
switch (status) {
case ATCA_NOT_LOCKED:
return "ATCA_NOT_LOCKED";
case ATCA_EXECUTION_ERROR:
return "ATCA_EXECUTION_ERROR";
case ATCA_FUNC_FAIL:
return "ATCA_FUNC_FAIL";
case ATCA_WAKE_FAILED:
return "ATCA_WAKE_FAILED";
case ATCA_RX_FAIL:
return "ATCA_RX_FAIL";
case ATCA_RX_NO_RESPONSE:
return "ATCA_RX_NO_RESPONSE";
case ATCA_TX_TIMEOUT:
return "ATCA_TX_TIMEOUT";
case ATCA_RX_TIMEOUT:
return "ATCA_RX_TIMEOUT";
case ATCA_TOO_MANY_COMM_RETRIES:
return "ATCA_TOO_MANY_COMM_RETRIES";
case ATCA_COMM_FAIL:
return "ATCA_COMM_FAIL";
case ATCA_TIMEOUT:
return "ATCA_TIMEOUT";
case ATCA_TX_FAIL:
return "ATCA_TX_FAIL";
case ATCA_RX_CRC_ERROR:
return "ATCA_RX_CRC_ERROR";
case ATCA_STATUS_CRC:
return "ATCA_STATUS_CRC";
case ATCA_SMALL_BUFFER:
return "ATCA_SMALL_BUFFER";
case ATCA_BAD_OPCODE:
return "ATCA_BAD_OPCODE";
case ATCA_BAD_PARAM:
return "ATCA_BAD_PARAM";
case ATCA_INVALID_SIZE:
return "ATCA_INVALID_SIZE";
case ATCA_INVALID_ID:
return "ATCA_INVALID_ID";
case ATCA_UNIMPLEMENTED:
return "ATCA_UNIMPLEMENTED";
default:
return "Error value not recognized";
}
}
/* Secure Element Cipher Functions */
/**
* @brief Set up a driver specific AES CBC mode operation
*
* @param ctx
* @param dev
* @param key_slot
*/
static void atca_cbc_setup(atca_aes_cbc_ctx_t *ctx,
ATCADevice dev,
psa_key_slot_number_t key_slot)
{
ctx->device = dev;
ctx->key_id = key_slot;
ctx->key_block = 0;
}
psa_status_t atca_cipher_setup(psa_drv_se_context_t *drv_context,
void *op_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t algorithm,
psa_encrypt_or_decrypt_t direction)
{
ATCADevice dev = (ATCADevice)drv_context->transient_data;
psa_se_cipher_context_t *ctx = (psa_se_cipher_context_t *)op_context;
/* Only device type ATECC608 supports AES operations */
if (dev->mIface.mIfaceCFG->devtype != ATECC608) {
DEBUG("ATCA Cipher Setup: Only ATECC608 devices support AES operations.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
switch (algorithm) {
case PSA_ALG_CBC_NO_PADDING:
atca_cbc_setup(&ctx->drv_ctx.atca_aes_cbc, dev, key_slot);
break;
default:
DEBUG("ATCA Cipher Setup: Algorithm not supported by implementation.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
ctx->direction = direction;
return PSA_SUCCESS;
}
psa_status_t atca_cipher_set_iv(void *op_context,
const uint8_t *p_iv,
size_t iv_length)
{
atca_aes_cbc_ctx_t *ctx = &((psa_se_cipher_context_t *)op_context)->drv_ctx.atca_aes_cbc;
if (iv_length != ATCA_MAX_IV_LEN) {
DEBUG("ATCA Cipher Set IV: Invalid IV length: Expected %d, was %d\n", \
ATCA_MAX_IV_LEN, iv_length);
return PSA_ERROR_INVALID_ARGUMENT;
}
memcpy(ctx->ciphertext, p_iv, iv_length);
return PSA_SUCCESS;
}
psa_status_t atca_cipher_update(void *op_context,
const uint8_t *p_input,
size_t input_size,
uint8_t *p_output,
size_t output_size,
size_t *p_output_length)
{
psa_se_cipher_context_t *ctx = (psa_se_cipher_context_t *)op_context;
ATCA_STATUS status = ATCA_EXECUTION_ERROR;
size_t offset = 0;
for (size_t data_block = 0; data_block < (input_size / AES_128_BLOCK_SIZE); data_block++) {
offset = data_block * AES_128_BLOCK_SIZE;
if (ctx->direction == PSA_CRYPTO_DRIVER_ENCRYPT) {
status = atcab_aes_cbc_encrypt_block(&ctx->drv_ctx.atca_aes_cbc, p_input + offset,
p_output + offset);
}
else {
status = atcab_aes_cbc_decrypt_block(&ctx->drv_ctx.atca_aes_cbc, p_input + offset,
p_output + offset);
}
if (status != ATCA_SUCCESS) {
DEBUG("ATCA Cipher Update failed. ATCA Error: %s\n",
atca_status_to_humanly_readable(status));
return atca_to_psa_error(status);
}
}
*p_output_length += input_size;
(void)output_size;
return PSA_SUCCESS;
}
psa_status_t atca_cipher_finish(void *op_context,
uint8_t *p_output,
size_t output_size,
size_t *p_output_length)
{
(void)op_context;
(void)p_output;
(void)output_size;
(void)p_output_length;
return PSA_SUCCESS;
}
psa_status_t atca_cipher_ecb(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t algorithm,
psa_encrypt_or_decrypt_t direction,
const uint8_t *p_input,
size_t input_size,
uint8_t *p_output,
size_t output_size)
{
ATCA_STATUS status;
ATCADevice dev = (ATCADevice)drv_context->transient_data;
size_t offset = 0;
if (dev->mIface.mIfaceCFG->devtype != ATECC608) {
DEBUG("ATCA Cipher ECB: Only ATECC608 devices support AES operations.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
if (algorithm != PSA_ALG_ECB_NO_PADDING || direction != PSA_CRYPTO_DRIVER_ENCRYPT) {
DEBUG("ATCA Cipher ECB: Only AES ECB encryption without padding is supported.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
if (input_size % AES_128_BLOCK_SIZE != 0) {
DEBUG("ATCA Cipher ECB: Input must be multiple of 16, was %d.\n", input_size);
return PSA_ERROR_INVALID_ARGUMENT;
}
do {
status = calib_aes_encrypt(dev, key_slot, 0, p_input + offset, p_output + offset);
if (status != ATCA_SUCCESS) {
DEBUG("ATCA Cipher ECB encrypt failed. ATCA Error: %s\n",
atca_status_to_humanly_readable(status));
return atca_to_psa_error(status);
}
offset += AES_128_BLOCK_SIZE;
} while (offset < input_size);
(void)output_size;
return PSA_SUCCESS;
}
/* Secure Element Key Management Functions */
psa_status_t atca_allocate(psa_drv_se_context_t *drv_context,
void *persistent_data,
const psa_key_attributes_t *attributes,
psa_key_creation_method_t method,
psa_key_slot_number_t *key_slot)
{
if (!ALG_IS_SUPPORTED(attributes->policy.alg)) {
DEBUG("ATCA allocate: Algorithm is not supported by device.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
psa_key_type_t type = attributes->type;
psa_se_config_t *device_config = (psa_se_config_t *)persistent_data;
psa_atca_slot_config_t *slot_config = device_config->slots;
for (int i = 0; i < 16; i++) {
if (slot_config[i].key_type_allowed == type) {
/* If a slot is occupied, but the stored key is not marked as persistent,
we treat it as an empty slot and overwrite the key */
if (slot_config[i].slot_occupied && slot_config[i].key_persistent) {
continue;
}
*key_slot = i;
(&slot_config[i])->slot_occupied = 1;
DEBUG("Allocating slot %d for key type %x\n", (int)*key_slot, attributes->type);
if (PSA_KEY_LIFETIME_GET_PERSISTENCE(attributes->lifetime) != \
PSA_KEY_PERSISTENCE_VOLATILE) {
(&slot_config[i])->key_persistent = 1;
}
return PSA_SUCCESS;
}
}
(void)drv_context;
(void)method;
DEBUG("ATCA allocate: No free slot available.\n");
return PSA_ERROR_INSUFFICIENT_STORAGE;
}
psa_status_t atca_destroy(psa_drv_se_context_t *drv_context,
void *persistent_data,
psa_key_slot_number_t key_slot)
{
/**
* The ATECCX08A driver does not provide a key destruction function.
*
* This function just sets the `slot_occupied` flag in the driver's persistent
* data to 0, in case the key generation or import goes wrong, so the slot can
* be reused.
*/
psa_atca_slot_config_t *slot_config = (psa_atca_slot_config_t *)persistent_data;
DEBUG("Setting Key Slot %d to not occupied.\n", (int)key_slot);
(&slot_config[key_slot])->slot_occupied = 0;
(void)drv_context;
return PSA_SUCCESS;
}
psa_status_t atca_import(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
size_t *bits)
{
ATCA_STATUS status;
ATCADevice dev = (ATCADevice)drv_context->transient_data;
if (!ALG_IS_SUPPORTED(attributes->policy.alg)) {
DEBUG("ATCA import: Algorithm is not supported by device.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
if (!KEY_SIZE_IS_SUPPORTED(data_length, attributes->type)) {
DEBUG("ATCA import: Key size is not supported by device.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
if (PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(attributes->type)) {
status = calib_write_pubkey(dev, key_slot, data + 1);
if (status != ATCA_SUCCESS) {
DEBUG("ATCA Write Pubkey failed. ATCA Error: %s\n",
atca_status_to_humanly_readable(status));
return atca_to_psa_error(status);
}
*bits = PSA_BYTES_TO_BITS(data_length);
return PSA_SUCCESS;
}
else {
if (data_length > ATCA_WRITE_BUFFER_SIZE) {
DEBUG("ATCA import: Key size too large.\n");
return PSA_ERROR_INVALID_ARGUMENT;
}
uint8_t buf_in[ATCA_WRITE_BUFFER_SIZE] = { 0 };
/* AES keys can be written to slots in 32 or 64 byte chunks. For this we
copy them into a 32 byte buffer first and pad the empty bits with 0 */
memcpy(buf_in, data, data_length);
status = calib_write_bytes_zone(dev, ATCA_ZONE_DATA, key_slot, 0, buf_in, sizeof(buf_in));
if (status != ATCA_SUCCESS) {
DEBUG("ATCA Write AES key failed. ATCA Error: %s\n",
atca_status_to_humanly_readable(status));
return atca_to_psa_error(status);
}
*bits = PSA_BYTES_TO_BITS(data_length);
return PSA_SUCCESS;
}
DEBUG("ATCA import: Operation is not supported.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t atca_generate_key(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
const psa_key_attributes_t *attributes,
uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length)
{
ATCA_STATUS status;
ATCADevice dev = (ATCADevice)drv_context->transient_data;
if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) {
DEBUG("ATCA Generate Key: Only ECC key generation is supported.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
if (pubkey_size > PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(attributes->type, attributes->bits)) {
DEBUG("ATCA Generate Key: Pubkey size not supported. Expected %d, was %d.\n", \
PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(attributes->type, attributes->bits), pubkey_size);
return PSA_ERROR_NOT_SUPPORTED;
}
if (pubkey != NULL) {
/**
* PSA supports the uncompressed binary format to encode ECC public keys.
* This means, that both the x and y coordinate are stored.
* This format is encoded by adding an extra byte containing the value 0x04
* (see also "Technical Guideline BSI TR-03111").
*
* The ATECCX08A stores and exports the x and y coordinate, so all we need to do is
* add the byte before the coordinates.
*/
pubkey[0] = 0x04;
*pubkey_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(attributes->type, attributes->bits);
status = calib_genkey(dev, key_slot, &pubkey[1]);
}
else {
status = calib_genkey(dev, key_slot, NULL);
}
if (status != ATCA_SUCCESS) {
DEBUG("ATCA Genkey failed. ATCA Error: %s\n",
atca_status_to_humanly_readable(status));
return atca_to_psa_error(status);
}
return PSA_SUCCESS;
}
psa_status_t atca_export_public_key(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
uint8_t *p_data,
size_t data_size,
size_t *p_data_length)
{
ATCA_STATUS status;
ATCADevice dev = (ATCADevice)drv_context->transient_data;
if (data_size < ECC_P256_PUB_KEY_SIZE) {
DEBUG("ATCA Export public key: Buffer too small, expected %d, was %d\n", \
ECC_P256_PUB_KEY_SIZE, data_size);
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = calib_get_pubkey(dev, key_slot, &p_data[1]);
if (status != ATCA_SUCCESS) {
DEBUG("ATCA Get Pubkey failed. ATCA Error: %s\n",
atca_status_to_humanly_readable(status));
return atca_to_psa_error(status);
}
/**
* PSA supports the uncompressed binary format to encode ECC public keys.
* This means, that both the x and y coordinate are stored.
* This format is encoded by adding an extra byte containing the value 0x04
* (see also "Technical Guideline BSI TR-03111").
*
* The ATECCX08A stored and exports the x and y coordinate, so all we need to do is
* add the byte before the coordinates.
*/
p_data[0] = 0x04;
/* Since we added the encoding byte, the stored public key is now 65 bytes long instead of 64 */
*p_data_length = ECC_P256_PUB_KEY_SIZE + 1;
return PSA_SUCCESS;
}
psa_status_t atca_sign(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t alg,
const uint8_t *p_hash,
size_t hash_length,
uint8_t *p_signature,
size_t signature_size,
size_t *p_signature_length)
{
ATCA_STATUS status;
ATCADevice dev = (ATCADevice)drv_context->transient_data;
if (alg != PSA_ALG_ECDSA(PSA_ALG_SHA_256)) {
DEBUG("ATCA Sign: Only ECDSA with SHA256 Messages is supported.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
if ((signature_size != ECC_P256_PUB_KEY_SIZE) || \
(hash_length != PSA_HASH_LENGTH(PSA_ALG_SHA_256))) {
DEBUG("ATCA Sign: Invalid signature or hash size. Expected Sig: %d |\
Hash %d, were Sig: %d | Hash: %d\n",\
ECC_P256_PUB_KEY_SIZE, PSA_HASH_LENGTH(PSA_ALG_SHA_256),\
signature_size, hash_length);
return PSA_ERROR_INVALID_ARGUMENT;
}
status = calib_sign(dev, key_slot, p_hash, p_signature);
if (status != ATCA_SUCCESS) {
DEBUG("ATCA Sign failed. ATCA Error: %s\n",
atca_status_to_humanly_readable(status));
return atca_to_psa_error(status);
}
*p_signature_length = signature_size;
return PSA_SUCCESS;
}
psa_status_t atca_verify(psa_drv_se_context_t *drv_context,
psa_key_slot_number_t key_slot,
psa_algorithm_t alg,
const uint8_t *p_hash,
size_t hash_length,
const uint8_t *p_signature,
size_t signature_length)
{
ATCA_STATUS status;
ATCADevice dev = (ATCADevice)drv_context->transient_data;
bool is_verified;
/* We only support the operation on public keys, if they're stored on a device. */
if (alg != PSA_ALG_ECDSA(PSA_ALG_SHA_256)) {
DEBUG("ATCA Verify: Only ECDSA with SHA256 Messages is supported.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
if ((signature_length != ECC_P256_PUB_KEY_SIZE) || \
(hash_length != PSA_HASH_LENGTH(PSA_ALG_SHA_256))) {
DEBUG("ATCA Sign: Invalid signature or hash size. Expected Sig: %d |\
Hash %d, were Sig: %d | Hash: %d\n",\
ECC_P256_PUB_KEY_SIZE, PSA_HASH_LENGTH(PSA_ALG_SHA_256),\
signature_length, hash_length);
return PSA_ERROR_INVALID_ARGUMENT;
}
status = calib_verify_stored(dev, p_hash, p_signature, key_slot, &is_verified);
if (status != ATCA_SUCCESS) {
DEBUG("ATCA Verify failed. ATCA Error: %s\n",
atca_status_to_humanly_readable(status));
return atca_to_psa_error(status);
}
return is_verified ? PSA_SUCCESS : PSA_ERROR_INVALID_SIGNATURE;
}
psa_status_t atca_generate_mac(psa_drv_se_context_t *drv_context,
const uint8_t *p_input,
size_t input_length,
psa_key_slot_number_t key_slot,
psa_algorithm_t alg,
uint8_t *p_mac,
size_t mac_size,
size_t *p_mac_length)
{
ATCA_STATUS status;
ATCADevice dev = (ATCADevice)drv_context->transient_data;
if (!PSA_ALG_IS_HMAC(alg)) {
DEBUG("ATCA Generate MAC: Only HMAC SHA256 is supported.\n");
return PSA_ERROR_NOT_SUPPORTED;
}
if (mac_size < PSA_HASH_LENGTH(PSA_ALG_SHA_256)) {
DEBUG("ATCA Generate Mac: Buffer too small, expected %d, was %d\n", \
PSA_HASH_LENGTH(PSA_ALG_SHA_256), mac_size);
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = calib_sha_hmac(dev, p_input, input_length, key_slot, p_mac, SHA_MODE_TARGET_OUT_ONLY);
if (status != ATCA_SUCCESS) {
DEBUG("ATCA SHA HMAC failed. ATCA Error: %s\n",
atca_status_to_humanly_readable(status));
return atca_to_psa_error(status);
}
*p_mac_length = PSA_HASH_LENGTH(PSA_ALG_SHA_256);
return PSA_SUCCESS;
}
static psa_drv_se_mac_t atca_mac = {
.context_size = 0,
.p_setup = NULL,
.p_update = NULL,
.p_finish = NULL,
.p_finish_verify = NULL,
.p_abort = NULL,
.p_mac = atca_generate_mac,
.p_mac_verify = NULL,
};
static psa_drv_se_cipher_t atca_cipher = {
.context_size = 0,
.p_setup = atca_cipher_setup,
.p_set_iv = atca_cipher_set_iv,
.p_update = atca_cipher_update,
.p_finish = atca_cipher_finish,
.p_abort = NULL,
.p_ecb = atca_cipher_ecb
};
static psa_drv_se_key_management_t atca_key_management = {
.p_allocate = atca_allocate,
.p_validate_slot_number = NULL,
.p_import = atca_import,
.p_generate = atca_generate_key,
.p_destroy = atca_destroy,
.p_export = NULL,
.p_export_public = atca_export_public_key
};
static psa_drv_se_asymmetric_t atca_asymmetric = {
.p_sign = atca_sign,
.p_verify = atca_verify,
.p_encrypt = NULL,
.p_decrypt = NULL
};
psa_drv_se_t atca_methods = {
.hal_version = PSA_DRV_SE_HAL_VERSION,
.persistent_data_size = 0,
.p_init = NULL,
.key_management = &atca_key_management,
.mac = &atca_mac,
.cipher = &atca_cipher,
.aead = NULL,
.asymmetric = &atca_asymmetric,
.derivation = NULL
};

View File

@ -19,18 +19,62 @@
#include "log.h"
#include "atca.h"
#include "atca_params.h"
#include "kernel_defines.h"
#define ENABLE_DEBUG 0
#include "debug.h"
#define ATCA_NUMOF (ARRAY_SIZE(atca_params))
#if IS_USED(MODULE_PSA_SECURE_ELEMENT_ATECCX08A)
#include "psa/crypto.h"
#include "psa_crypto_se_management.h"
extern psa_drv_se_t atca_methods;
psa_se_config_t atca_config_list[] = { ATCA_CONFIG_LIST };
#endif
ATCADevice atca_devs_ptr[ATCA_NUMOF];
static struct atca_device atca_devs[ATCA_NUMOF];
#if IS_USED(MODULE_PSA_SECURE_ELEMENT_ATECCX08A)
void auto_init_atca(void)
{
DEBUG("[auto_init_atca] Number of secure elements: %d\n", ATCA_NUMOF);
for (unsigned i = 0; i < ATCA_NUMOF; i++) {
if (atcab_init((ATCAIfaceCfg *)&atca_params[i]) != ATCA_SUCCESS) {
LOG_ERROR("[auto_init_atca] error initializing cryptoauth device #%u\n", i);
int status = initATCADevice((ATCAIfaceCfg *)&atca_params[i].cfg, (ATCADevice)&atca_devs[i]);
if (status != ATCA_SUCCESS) {
LOG_ERROR("[auto_init_atca] error initializing cryptoauth device #%u, status: %d\n",
i, status);
continue;
}
atca_devs_ptr[i] = &atca_devs[i];
DEBUG("[auto_init_atca] Registering Driver with address: %x and location: %lx\n", atca_params[i].cfg.atcai2c.address, atca_params[i].atca_loc);
status = psa_register_secure_element(atca_params[i].atca_loc,
&atca_methods,
&atca_config_list[i],
&atca_devs[i]);
if (status != PSA_SUCCESS) {
LOG_ERROR(
"[auto_init_atca] PSA Crypto error registering cryptoauth PSA driver\
for device #%u, status: %s\n", i, psa_status_to_humanly_readable(status));
continue;
}
}
}
#else
void auto_init_atca(void)
{
DEBUG("[auto_init_atca] Number of secure elements: %d\n", ATCA_NUMOF);
for (unsigned i = 0; i < ATCA_NUMOF; i++) {
int status = initATCADevice((ATCAIfaceCfg *)&atca_params[i], (ATCADevice)&atca_devs[i]);
if (status != ATCA_SUCCESS) {
LOG_ERROR("[auto_init_atca] error initializing cryptoauth device #%u, status: %d\n",
i, status);
continue;
}
atca_devs_ptr[i] = &atca_devs[i];
}
}
#endif

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_auto_init
* @{
* @file
* @brief Initializes security modules
*
* @author Bennet Blischke <bennet.blischke@haw-hamburg.de>
* @author Lena Boeckmann <lena.boeckmann@haw-hamburg,de>
* @}
*/
#define ENABLE_DEBUG 0
#include "debug.h"
void auto_init_security(void)
{
#if IS_USED(MODULE_CRYPTOAUTHLIB)
extern void auto_init_atca(void);
DEBUG("auto_init_security: atca\n");
auto_init_atca();
#endif
}

View File

@ -50,8 +50,19 @@ static int test_riot_sha256(uint8_t *teststring, uint16_t len,
static int test_atca_sha(uint8_t *teststring, uint16_t len, uint8_t *expected,
uint8_t *result)
{
atcab_sha_start();
atcab_sha_end(result, len, teststring);
ATCA_STATUS status;
ATCADevice dev = atca_devs_ptr[0];
status = calib_sha_start(dev);
if (status != ATCA_SUCCESS) {
printf("ATCA SHA start failed: %02x\n", status);
}
status = calib_sha_end(dev, result, len, teststring);
if (status != ATCA_SUCCESS) {
printf("ATCA SHA end failed: %02x\n", status);
}
return memcmp(expected, result, SHA256_HASH_SIZE);
}