From 7b39ad2f4d54da52dab0994b557afdab804c7f10 Mon Sep 17 00:00:00 2001 From: Bryan Hunt Date: Fri, 30 Aug 2019 16:33:50 -0600 Subject: [PATCH] Release 20190830 with support for new kits and big endian architectures --- CMakeLists.txt | 27 ++ README.md | 4 + app/secure_boot/secure_boot.c | 8 +- app/secure_boot/secure_boot.h | 4 +- app/tng/tng_root_cert.h | 2 + lib/CMakeLists.txt | 59 ++++- lib/atca_cfgs.c | 127 +++++---- lib/atca_command.c | 2 + lib/atca_command.h | 11 +- lib/atca_compiler.h | 26 +- lib/atca_iface.c | 9 +- lib/atca_iface.h | 22 +- lib/atcacert/atcacert_client.c | 2 +- lib/atcacert/atcacert_def.c | 1 + lib/atcacert/atcacert_def.h | 21 +- lib/atcacert/atcacert_der.c | 3 +- lib/basic/atca_basic_aes_ctr.c | 3 +- lib/basic/atca_basic_privwrite.c | 12 +- lib/basic/atca_basic_sha.c | 2 +- lib/basic/atca_helpers.c | 8 +- lib/crypto/hashes/sha1_routines.c | 11 +- lib/crypto/hashes/sha2_routines.c | 4 +- lib/hal/hal_linux_i2c_userspace.c | 85 +++--- lib/hal/hal_linux_i2c_userspace.h | 2 - lib/hal/hal_uc3_i2c_asf.c | 418 ++++++++++++++++++++++++++++++ lib/hal/hal_uc3_i2c_asf.h | 61 +++++ lib/hal/hal_uc3_timer_asf.c | 82 ++++++ lib/hal/kit_protocol.c | 117 ++++++--- lib/host/atca_host.c | 154 ++++++++--- lib/host/atca_host.h | 4 + test/CMakeLists.txt | 33 +++ test/atca_test.c | 18 +- test/atca_tests_gendig.c | 331 ++++++++++++++++++++++- test/cmd-processor.c | 18 +- 34 files changed, 1448 insertions(+), 243 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 lib/hal/hal_uc3_i2c_asf.c create mode 100644 lib/hal/hal_uc3_i2c_asf.h create mode 100644 lib/hal/hal_uc3_timer_asf.c create mode 100644 test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..691c1d1f4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 2.6.4) +project (cryptoauthlib) + +# Set the current release version +set(VERSION "2018.10.26") +set(VERSION_MAJOR 2028) +set(VERSION_MINOR 10) +set(VERSION_PATCH 26) + +# Build Options +option(BUILD_TESTS "Create Test Application with library" OFF) +#set(ATCA_PKCS11 ON CACHE INTERNAL "") + +message(STATUS "Building Configuration: ${CMAKE_BUILD_TYPE}") + + +if(BUILD_TESTS) +set(ATCA_BUILD_SHARED_LIBS OFF CACHE INTERNAL "") +endif(BUILD_TESTS) + +add_subdirectory(lib) + +# Tests +if(BUILD_TESTS) +add_subdirectory(test) +endif(BUILD_TESTS) + diff --git a/README.md b/README.md index 9efed455a..f647164c8 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,10 @@ Examples Release notes ----------- +Next Release + - Added big-endian architecture support + - Fixes to atcah_gen_dig() and atcah_nonce() + 05/17/2019 - Added support for TNG devices (cert transforms, new API) - atcab_write_pub_key() now works when the data zone is unlocked diff --git a/app/secure_boot/secure_boot.c b/app/secure_boot/secure_boot.c index bac48b047..981968e1c 100644 --- a/app/secure_boot/secure_boot.c +++ b/app/secure_boot/secure_boot.c @@ -26,14 +26,10 @@ * THIS SOFTWARE. */ -#include -#include +#include #include "secure_boot.h" -#include "atca_iface.h" -#include "hal/atca_hal.h" -#include "test/atca_test.h" #include "io_protection_key.h" -#include "crypto_device_app.h" +#include "basic/atca_basic.h" /*Initialization routines */ static ATCA_STATUS secure_boot_init(secure_boot_parameters* secure_boot_params); diff --git a/app/secure_boot/secure_boot.h b/app/secure_boot/secure_boot.h index abdaebd5c..1b2d049ee 100644 --- a/app/secure_boot/secure_boot.h +++ b/app/secure_boot/secure_boot.h @@ -36,9 +36,7 @@ extern "C" { #include "atca_status.h" #include "secure_boot_memory.h" #include "atca_command.h" -#include "crypto\atca_crypto_sw_sha2.h" -#include "host/atca_host.h" - +#include "crypto/atca_crypto_sw_sha2.h" #define SECURE_BOOT_CONFIG_DISABLE 0 #define SECURE_BOOT_CONFIG_FULL_BOTH 1 diff --git a/app/tng/tng_root_cert.h b/app/tng/tng_root_cert.h index 7895e6e89..c678f97ef 100644 --- a/app/tng/tng_root_cert.h +++ b/app/tng/tng_root_cert.h @@ -28,6 +28,8 @@ #ifndef TNG_ROOT_CERT_H #define TNG_ROOT_CERT_H +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 6cba30b3d..b15ec66e1 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -3,6 +3,7 @@ project(cryptoauth) # Various Options for Build option(ATCA_HAL_KIT_HID "Include the HID HAL Driver") +option(ATCA_HAL_KIT_CDC "Include the CDC HAL Driver (Legacy)" OFF) option(ATCA_HAL_I2C "Include the I2C Hal Driver - Linux & MCU only") option(ATCA_HAL_CUSTOM "Include support for Custom/Plug-in Hal Driver") option(ATCA_PRINTF "Enable Debug print statements in library") @@ -25,9 +26,14 @@ file(GLOB TNG_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "../app/tng/*.c") # Add the basic sources to the library set(CRYPTOAUTH_SRC ${LIB_SRC} ${ATCACERT_SRC} ${BASIC_SRC} ${CRYPTO_SRC} ${HOST_SRC} ${JWT_SRC} hal/atca_hal.c ${TNG_SRC}) +if(ATCA_HAL_KIT_HID OR ATCA_HAL_KIT_CDC) +set(NEED_USB true) +endif() + if(WIN32) set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} hal/hal_win_timer.c) set(HID_SRC ../third_party/hidapi/windows/hid.c) +set(CDC_SRC hal/hal_win_kit_cdc.c) elseif(APPLE) set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} hal/hal_linux_timer.c) set(HID_SRC ../third_party/hidapi/mac/hid.c) @@ -37,28 +43,55 @@ set(TWI_SRC hal/hal_linux_i2c_userspace.c) set(LINUX TRUE) endif() -if(LINUX AND ATCA_HAL_KIT_HID) +if(LINUX AND NEED_USB) find_path(LIBUSB_INCLUDE_DIR NAMES libusb.h PATH_SUFFIXES "include" "libusb" "libusb-1.0") find_path(LIBUDEV_INCLUDE_DIR NAMES libudev.h PATH_SUFFIXES "include") find_library(HAS_LIBUSB usb-1.0) find_library(HAS_LIBUDEV udev) + if(HAS_LIBUSB AND LIBUSB_INCLUDE_DIR) -set(HID_SRC ../third_party/hidapi/libusb/hid.c) -elseif(HAS_LIBUDEV AND LIBUDEV_INCLUDE_DIR) -set(LIBUSB_INCLUDE_DIR ${LIBUDEV_INCLUDE_DIR}) -set(HID_SRC ../third_party/hidapi/linux/hid.c) -else() -message(FATAL_ERROR, "Missing Build Dependencies for ATCA_HAL_KIT_HID - install libusb-1.0-0-dev or libudev-dev") +set(LIBUSB_GOOD TRUE) +endif() + +if(HAS_LIBUDEV AND LIBUDEV_INCLUDE_DIR) +set(LIBUDEV_GOOD TRUE) endif() + +if(ATCA_HAL_KIT_CDC AND LIBUDEV_GOOD) +set(USE_UDEV TRUE) +elseif(LIBUSB_GOOD AND NOT ATCA_HAL_KIT_CDC) +set(USE_LIBUSB TRUE) else() -set(LIBUSD_INCLUDE_DIR "") +message(FATAL_ERROR, "Missing Build Dependencies for USB - install libusb-1.0-0-dev or libudev-dev") +endif() + +endif(LINUX AND NEED_USB) + +if(USE_UDEV) +set(USB_INCLUDE_DIR ${LIBUDEV_INCLUDE_DIR}) +set(HID_SRC ../third_party/hidapi/linux/hid.c) +set(CDC_SRC hal/hal_linux_kit_cdc.c) +endif(USE_UDEV) + +if(USE_LIBUSB) +set(USB_INCLUDE_DIR ${LIBUSB_INCLUDE_DIR}) +set(HID_SRC ../third_party/hidapi/libusb/hid.c) +endif(USE_LIBUSB) + +if(NEED_USB) +set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} hal/kit_protocol.c) endif() if(ATCA_HAL_KIT_HID) add_definitions(-DATCA_HAL_KIT_HID) -set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} hal/kit_protocol.c hal/hal_all_platforms_kit_hidapi.c ${HID_SRC}) +set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} ${HID_SRC} hal/hal_all_platforms_kit_hidapi.c) endif(ATCA_HAL_KIT_HID) +if(ATCA_HAL_KIT_CDC) +add_definitions(-DATCA_HAL_KIT_CDC) +set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} ${CDC_SRC}) +endif(ATCA_HAL_KIT_CDC) + if(ATCA_HAL_I2C) add_definitions(-DATCA_HAL_I2C) set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} ${TWI_SRC}) @@ -90,7 +123,7 @@ if(ATCA_PRINTF) add_definitions(-DATCAPRINTF) endif(ATCA_PRINTF) -include_directories(cryptoauth PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ../third_party/hidapi/hidapi ${LIBUSB_INCLUDE_DIR}) +include_directories(cryptoauth PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ../third_party/hidapi/hidapi ${USB_INCLUDE_DIR}) if(WIN32) set_target_properties(cryptoauth PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS true) @@ -104,11 +137,11 @@ target_link_libraries(cryptoauth ${IO_KIT_LIB} ${CORE_LIB}) endif() if(LINUX) -if(HAS_LIBUSB AND ATCA_HAL_KIT_HID) +if(USE_LIBUSB) target_link_libraries(cryptoauth usb-1.0) -elseif(HAS_LIBUDEV AND ATCA_HAL_KIT_HID) +elseif(USE_UDEV) target_link_libraries(cryptoauth udev) endif() target_link_libraries(cryptoauth rt) -endif() +endif(LINUX) diff --git a/lib/atca_cfgs.c b/lib/atca_cfgs.c index 3002e2a8b..a217278a9 100644 --- a/lib/atca_cfgs.c +++ b/lib/atca_cfgs.c @@ -38,89 +38,106 @@ /** \brief default configuration for an ECCx08A device */ ATCAIfaceCfg cfg_ateccx08a_i2c_default = { - .iface_type = ATCA_I2C_IFACE, - .devtype = ATECC508A, - .atcai2c.slave_address = 0xC0, - .atcai2c.bus = 2, - .atcai2c.baud = 400000, - //.atcai2c.baud = 100000, - .wake_delay = 1500, - .rx_retries = 20 + .iface_type = ATCA_I2C_IFACE, + .devtype = ATECC608A, + { + .atcai2c.slave_address = 0xC0, + .atcai2c.bus = 2, + .atcai2c.baud = 400000, + //.atcai2c.baud = 100000, + }, + .wake_delay = 1500, + .rx_retries = 20 }; /** \brief default configuration for an ECCx08A device on the logical SWI bus over UART*/ ATCAIfaceCfg cfg_ateccx08a_swi_default = { - .iface_type = ATCA_SWI_IFACE, - .devtype = ATECC508A, - .atcaswi.bus = 4, - .wake_delay = 1500, - .rx_retries = 10 + .iface_type = ATCA_SWI_IFACE, + .devtype = ATECC608A, + { + .atcaswi.bus = 4, + }, + .wake_delay = 1500, + .rx_retries = 10 }; /** \brief default configuration for Kit protocol over the device's async interface */ ATCAIfaceCfg cfg_ateccx08a_kitcdc_default = { - .iface_type = ATCA_UART_IFACE, - .devtype = ATECC508A, - .atcauart.port = 0, - .atcauart.baud = 115200, - .atcauart.wordsize = 8, - .atcauart.parity = 2, - .atcauart.stopbits = 1, - .rx_retries = 1, + .iface_type = ATCA_UART_IFACE, + .devtype = ATECC608A, + { + .atcauart.port = 0, + .atcauart.baud = 115200, + .atcauart.wordsize = 8, + .atcauart.parity = 2, + .atcauart.stopbits = 1, + }, + .rx_retries = 1, }; /** \brief default configuration for Kit protocol over the device's async interface */ ATCAIfaceCfg cfg_ateccx08a_kithid_default = { - .iface_type = ATCA_HID_IFACE, - .devtype = ATECC508A, - .atcahid.idx = 0, - .atcahid.vid = 0x03EB, - .atcahid.pid = 0x2312, - .atcahid.packetsize = 64, - .atcahid.guid = { 0x4d, 0x1e, 0x55, 0xb2, 0xf1, 0x6f, 0x11, 0xcf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 }, + .iface_type = ATCA_HID_IFACE, + .devtype = ATECC608A, + { + .atcahid.dev_interface = ATCA_KIT_AUTO_IFACE, + .atcahid.dev_identity = 0, + .atcahid.idx = 0, + .atcahid.vid = 0x03EB, + .atcahid.pid = 0x2312, + .atcahid.packetsize = 64, + } }; + /** \brief default configuration for a SHA204A device on the first logical I2C bus */ ATCAIfaceCfg cfg_atsha204a_i2c_default = { - .iface_type = ATCA_I2C_IFACE, - .devtype = ATSHA204A, - .atcai2c.slave_address = 0xC8, - .atcai2c.bus = 2, - .atcai2c.baud = 400000, - .wake_delay = 2560, - .rx_retries = 20 + .iface_type = ATCA_I2C_IFACE, + .devtype = ATSHA204A, + { + .atcai2c.slave_address = 0xC8, + .atcai2c.bus = 2, + .atcai2c.baud = 400000, + }, + .wake_delay = 2560, + .rx_retries = 20 }; /** \brief default configuration for an SHA204A device on the logical SWI bus over UART*/ ATCAIfaceCfg cfg_atsha204a_swi_default = { - .iface_type = ATCA_SWI_IFACE, - .devtype = ATSHA204A, - .atcaswi.bus = 4, - .wake_delay = 2560, - .rx_retries = 10 + .iface_type = ATCA_SWI_IFACE, + .devtype = ATSHA204A, + { + .atcaswi.bus = 4, + }, + .wake_delay = 2560, + .rx_retries = 10 }; /** \brief default configuration for Kit protocol over the device's async interface */ ATCAIfaceCfg cfg_atsha204a_kitcdc_default = { - .iface_type = ATCA_UART_IFACE, - .devtype = ATSHA204A, - .atcauart.port = 0, - .atcauart.baud = 115200, - .atcauart.wordsize = 8, - .atcauart.parity = 2, - .atcauart.stopbits = 1, - .rx_retries = 1, + .iface_type = ATCA_UART_IFACE, + .devtype = ATSHA204A, + { + .atcauart.port = 0, + .atcauart.baud = 115200, + .atcauart.wordsize = 8, + .atcauart.parity = 2, + .atcauart.stopbits = 1, + }, + .rx_retries = 1, }; /** \brief default configuration for Kit protocol over the device's async interface */ ATCAIfaceCfg cfg_atsha204a_kithid_default = { - .iface_type = ATCA_HID_IFACE, - .devtype = ATSHA204A, - .atcahid.idx = 0, - .atcahid.vid = 0x03EB, - .atcahid.pid = 0x2312, - .atcahid.packetsize = 64, - .atcahid.guid = { 0x4d, 0x1e, 0x55, 0xb2, 0xf1, 0x6f, 0x11, 0xcf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 }, + .iface_type = ATCA_HID_IFACE, + .devtype = ATSHA204A, + .atcahid.dev_interface = ATCA_KIT_AUTO_IFACE, + .atcahid.dev_identity = 0, + .atcahid.idx = 0, + .atcahid.vid = 0x03EB, + .atcahid.pid = 0x2312, + .atcahid.packetsize = 64, }; /** @} */ diff --git a/lib/atca_command.c b/lib/atca_command.c index 036625a62..1aefec199 100644 --- a/lib/atca_command.c +++ b/lib/atca_command.c @@ -648,6 +648,8 @@ void atCalcCrc(ATCAPacket *packet) { uint8_t length, *crc; + packet->param2 = ATCA_UINT16_HOST_TO_LE(packet->param2); + length = packet->txsize - ATCA_CRC_SIZE; // computer pointer to CRC in the packet crc = &(packet->txsize) + length; diff --git a/lib/atca_command.h b/lib/atca_command.h index f2045c574..aebaacfbb 100644 --- a/lib/atca_command.h +++ b/lib/atca_command.h @@ -85,12 +85,16 @@ void deleteATCACommand(ATCACommand *ca_cmd); // Note: pack @ 2 is required, @ 1 causes word alignment crash (though it should not), a known bug in GCC. // @2, the wire still has the intended byte alignment with arm-eabi. this is likely the least portable part of atca -#pragma pack( push, ATCAPacket, 2 ) +#ifdef ATCA_NO_PRAGMA_PACK +typedef struct __attribute__ ((packed)) +#else +#pragma pack( push, ATCAPacket, 2 ) +typedef struct +#endif /** \brief an ATCA packet structure. This is a superset of the packet transmitted on the wire. It's also * used as a buffer for receiving the response */ -typedef struct { // used for transmit/send @@ -115,7 +119,9 @@ typedef struct } ATCAPacket; +#ifndef ATCA_NO_PRAGMA_PACK #pragma pack( pop, ATCAPacket) +#endif ATCA_STATUS atCheckMAC(ATCACommand ca_cmd, ATCAPacket *packet); @@ -340,6 +346,7 @@ ATCA_STATUS atCheckCrc(const uint8_t *response); #define COUNTER_MODE_READ ((uint8_t)0x00) //!< Counter command mode for reading #define COUNTER_MODE_INCREMENT ((uint8_t)0x01) //!< Counter command mode for incrementing #define COUNTER_RSP_SIZE ATCA_RSP_SIZE_4 //!< Counter command response packet size +#define COUNTER_SIZE ATCA_RSP_SIZE_MIN //!< Counter size in binary /** @} */ /** \name Definitions for the DeriveKey Command diff --git a/lib/atca_compiler.h b/lib/atca_compiler.h index 39553724d..94dbd46c0 100644 --- a/lib/atca_compiler.h +++ b/lib/atca_compiler.h @@ -34,11 +34,17 @@ #if defined(__clang__) /* Clang/LLVM. ---------------------------------------------- */ #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define ATCA_UINT16_HOST_TO_LE(x) __builtin_bswap16(x) +#define ATCA_UINT16_LE_TO_HOST(x) __builtin_bswap16(x) +#define ATCA_UINT32_HOST_TO_LE(x) __builtin_bswap32(x) #define ATCA_UINT32_HOST_TO_BE(x) (x) #define ATCA_UINT32_BE_TO_HOST(x) (x) #define ATCA_UINT64_HOST_TO_BE(x) (x) #define ATCA_UINT64_BE_TO_HOST(x) (x) #else +#define ATCA_UINT16_HOST_TO_LE(x) (x) +#define ATCA_UINT16_LE_TO_HOST(x) (x) +#define ATCA_UINT32_HOST_TO_LE(x) (x) #define ATCA_UINT32_HOST_TO_BE(x) __builtin_bswap32(x) #define ATCA_UINT32_BE_TO_HOST(x) __builtin_bswap32(x) #define ATCA_UINT64_HOST_TO_BE(x) __builtin_bswap64(x) @@ -50,12 +56,27 @@ #elif defined(__GNUC__) || defined(__GNUG__) /* GNU GCC/G++. --------------------------------------------- */ -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#if defined(__AVR32__) +#define ATCA_UINT16_HOST_TO_LE(x) __builtin_bswap_16(x) +#define ATCA_UINT16_LE_TO_HOST(x) __builtin_bswap_16(x) +#define ATCA_UINT32_HOST_TO_LE(x) __builtin_bswap_32(x) +#define ATCA_UINT32_HOST_TO_BE(x) (x) +#define ATCA_UINT32_BE_TO_HOST(x) (x) +#define ATCA_UINT64_HOST_TO_BE(x) (x) +#define ATCA_UINT64_BE_TO_HOST(x) (x) +#define ATCA_NO_PRAGMA_PACK +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define ATCA_UINT16_HOST_TO_LE(x) __builtin_bswap16(x) +#define ATCA_UINT16_LE_TO_HOST(x) __builtin_bswap16(x) +#define ATCA_UINT32_HOST_TO_LE(x) __builtin_bswap32(x) #define ATCA_UINT32_HOST_TO_BE(x) (x) #define ATCA_UINT32_BE_TO_HOST(x) (x) #define ATCA_UINT64_HOST_TO_BE(x) (x) #define ATCA_UINT64_BE_TO_HOST(x) (x) #else +#define ATCA_UINT16_HOST_TO_LE(x) (x) +#define ATCA_UINT16_LE_TO_HOST(x) (x) +#define ATCA_UINT32_HOST_TO_LE(x) (x) #define ATCA_UINT32_HOST_TO_BE(x) __builtin_bswap32(x) #define ATCA_UINT32_BE_TO_HOST(x) __builtin_bswap32(x) #define ATCA_UINT64_HOST_TO_BE(x) __builtin_bswap64(x) @@ -72,6 +93,9 @@ /* Microsoft Visual Studio. --------------------------------- */ // MSVC is usually always little-endian architecture #include +#define ATCA_UINT16_HOST_TO_LE(x) (x) +#define ATCA_UINT16_LE_TO_HOST(x) (x) +#define ATCA_UINT32_HOST_TO_LE(x) (x) #define ATCA_UINT32_HOST_TO_BE(x) _byteswap_ulong(x) #define ATCA_UINT32_BE_TO_HOST(x) _byteswap_ulong(x) #define ATCA_UINT64_HOST_TO_BE(x) _byteswap_uint64(x) diff --git a/lib/atca_iface.c b/lib/atca_iface.c index b3afb51af..f472a9133 100644 --- a/lib/atca_iface.c +++ b/lib/atca_iface.c @@ -227,12 +227,15 @@ void* atgetifacehaldat(ATCAIface ca_iface) */ ATCA_STATUS releaseATCAIface(ATCAIface ca_iface) { - if (ca_iface == NULL) + ATCA_STATUS ret = ATCA_BAD_PARAM; + + if (ca_iface) { - return ATCA_BAD_PARAM; + ret = hal_iface_release(ca_iface->mType, ca_iface->hal_data); + ca_iface->hal_data = NULL; } - return hal_iface_release(ca_iface->mType, ca_iface->hal_data); + return ret; } #ifndef ATCA_NO_HEAP diff --git a/lib/atca_iface.h b/lib/atca_iface.h index 8db967b32..a6c06fb54 100644 --- a/lib/atca_iface.h +++ b/lib/atca_iface.h @@ -53,6 +53,16 @@ typedef enum ATCA_UNKNOWN_IFACE, } ATCAIfaceType; + +/*The types are used within the kit protocol to identify the correct interface*/ +typedef enum +{ ATCA_KIT_AUTO_IFACE, //Selects the first device if the Kit interface is not defined + ATCA_KIT_I2C_IFACE, + ATCA_KIT_SWI_IFACE, + ATCA_KIT_UNKNOWN_IFACE, } ATCAKitType; + + + /* ATCAIfaceCfg is a mediator object between a completely abstract notion of a physical interface and an actual physical interface. @@ -94,11 +104,13 @@ typedef struct struct ATCAHID { - int idx; // HID enumeration index - uint32_t vid; // Vendor ID of kit (0x03EB for CK101) - uint32_t pid; // Product ID of kit (0x2312 for CK101) - uint32_t packetsize; // Size of the USB packet - uint8_t guid[16]; // The GUID for this HID device + int idx; // HID enumeration index + ATCAKitType dev_interface; // Kit interface type + uint8_t dev_identity; // I2C address for the I2C interface device or the bus number for the SWI interface device. + uint32_t vid; // Vendor ID of kit (0x03EB for CK101) + uint32_t pid; // Product ID of kit (0x2312 for CK101) + uint32_t packetsize; // Size of the USB packet + uint8_t guid[16]; // The GUID for this HID device } atcahid; struct ATCACUSTOM diff --git a/lib/atcacert/atcacert_client.c b/lib/atcacert/atcacert_client.c index 6d6daa9d9..ce040dd58 100644 --- a/lib/atcacert/atcacert_client.c +++ b/lib/atcacert/atcacert_client.c @@ -84,7 +84,7 @@ int atcacert_read_device_loc(const atcacert_device_loc_t* device_loc, { return ret; } - if (device_loc->offset + device_loc->count > zone_size) + if (device_loc->offset + device_loc->count > (uint16_t)zone_size) { if (device_loc->offset > zone_size) { diff --git a/lib/atcacert/atcacert_def.c b/lib/atcacert/atcacert_def.c index 7cc01f191..345f904db 100644 --- a/lib/atcacert/atcacert_def.c +++ b/lib/atcacert/atcacert_def.c @@ -1710,6 +1710,7 @@ int atcacert_transform_data(atcacert_transform_t transform, { status = ATCA_SMALL_BUFFER; } + break; case TF_REVERSE: status = atcab_reversal(data, data_size, destination, destination_size); break; diff --git a/lib/atcacert/atcacert_def.h b/lib/atcacert/atcacert_def.h index edb50c761..0662f4f2f 100644 --- a/lib/atcacert/atcacert_def.h +++ b/lib/atcacert/atcacert_def.h @@ -41,6 +41,7 @@ #include #include +#include "atca_compiler.h" #include "atcacert.h" #include "atcacert_date.h" #include "basic/atca_helpers.h" @@ -126,13 +127,17 @@ typedef enum atcacert_std_cert_element_e } atcacert_std_cert_element_t; // Some of these structures may need to be byte-accurate - +#ifndef ATCA_NO_PRAGMA_PACK #pragma pack(push, 1) +#define ATCA_PACKED +#else +#define ATCA_PACKED __attribute__ ((packed)) +#endif /** * Defines a chunk of data in an ATECC device. */ -typedef struct atcacert_device_loc_s +typedef struct ATCA_PACKED atcacert_device_loc_s { atcacert_device_zone_t zone; //!< Zone in the device. uint8_t slot; //!< Slot within the data zone. Only applies if zone is DEVZONE_DATA. @@ -144,7 +149,7 @@ typedef struct atcacert_device_loc_s /** * Defines a chunk of data in a certificate template. */ -typedef struct atcacert_cert_loc_s +typedef struct ATCA_PACKED atcacert_cert_loc_s { uint16_t offset; //!< Byte offset in the certificate template. uint16_t count; //!< Byte count. Set to 0 if it doesn't exist. @@ -153,8 +158,7 @@ typedef struct atcacert_cert_loc_s /** * Defines a generic dynamic element for a certificate including the device and template locations. */ - -typedef struct atcacert_cert_element_s +typedef struct ATCA_PACKED atcacert_cert_element_s { char id[25]; //!< ID identifying this element. atcacert_device_loc_t device_loc; //!< Location in the device for the element. @@ -168,7 +172,7 @@ typedef struct atcacert_cert_element_s * If any of the standard certificate elements (std_cert_elements) are not a part of the certificate * definition, set their count to 0 to indicate their absence. */ -typedef struct atcacert_def_s +typedef struct ATCA_PACKED atcacert_def_s { atcacert_cert_type_t type; //!< Certificate type. uint8_t template_id; //!< ID for the this certificate definition (4-bit value). @@ -193,7 +197,8 @@ typedef struct atcacert_def_s /** * Tracks the state of a certificate as it's being rebuilt from device information. */ -typedef struct atcacert_build_state_s + +typedef struct ATCA_PACKED atcacert_build_state_s { const atcacert_def_t* cert_def; //!< Certificate definition for the certificate being rebuilt. uint8_t* cert; //!< Buffer to contain the rebuilt certificate. @@ -203,7 +208,9 @@ typedef struct atcacert_build_state_s uint8_t device_sn[9]; //!< Storage for the device SN, when it's found. } atcacert_build_state_t; +#ifndef ATCA_NO_PRAGMA_PACK #pragma pack(pop) +#endif // Inform function naming when compiling in C++ #ifdef __cplusplus diff --git a/lib/atcacert/atcacert_der.c b/lib/atcacert/atcacert_der.c index 35752f047..f35c68eb3 100644 --- a/lib/atcacert/atcacert_der.c +++ b/lib/atcacert/atcacert_der.c @@ -191,6 +191,7 @@ int atcacert_der_enc_integer(const uint8_t* int_data, size_t der_int_size_calc = 0; size_t trim = 0; size_t pad = 0; + int ret; if (int_data == NULL || der_int_size == NULL || int_data_size <= 0) { @@ -215,7 +216,7 @@ int atcacert_der_enc_integer(const uint8_t* int_data, pad = 1; } - int ret = atcacert_der_enc_length((uint32_t)(int_data_size + pad - trim), der_length, &der_length_size); + ret = atcacert_der_enc_length((uint32_t)(int_data_size + pad - trim), der_length, &der_length_size); if (ret != ATCACERT_E_SUCCESS) { return ret; diff --git a/lib/basic/atca_basic_aes_ctr.c b/lib/basic/atca_basic_aes_ctr.c index cc31d29cb..d8dbb3758 100644 --- a/lib/basic/atca_basic_aes_ctr.c +++ b/lib/basic/atca_basic_aes_ctr.c @@ -91,6 +91,7 @@ ATCA_STATUS atcab_aes_ctr_init(atca_aes_ctr_ctx_t* ctx, uint16_t key_id, uint8_t ATCA_STATUS atcab_aes_ctr_init_rand(atca_aes_ctr_ctx_t* ctx, uint16_t key_id, uint8_t key_block, uint8_t counter_size, uint8_t* iv) { ATCA_STATUS status = ATCA_SUCCESS; + uint8_t nonce_size; if (ctx == NULL || iv == NULL || counter_size > AES_DATA_SIZE) { @@ -102,7 +103,7 @@ ATCA_STATUS atcab_aes_ctr_init_rand(atca_aes_ctr_ctx_t* ctx, uint16_t key_id, ui ctx->counter_size = counter_size; // Generate random nonce - uint8_t nonce_size = AES_DATA_SIZE - ctx->counter_size; + nonce_size = AES_DATA_SIZE - ctx->counter_size; if (nonce_size != 0) { uint8_t random_nonce[32]; diff --git a/lib/basic/atca_basic_privwrite.c b/lib/basic/atca_basic_privwrite.c index c2833ee71..7bb221bc0 100644 --- a/lib/basic/atca_basic_privwrite.c +++ b/lib/basic/atca_basic_privwrite.c @@ -76,10 +76,10 @@ ATCA_STATUS atcab_priv_write(uint16_t key_id, const uint8_t priv_key[36], uint16 { // Caller requested an unencrypted PrivWrite, which is only allowed when the data zone is unlocked // build an PrivWrite command - packet.param1 = 0x00; // Mode is unencrypted write - packet.param2 = key_id; // Key ID - memcpy(&packet.data[0], priv_key, 36); // Private key - memset(&packet.data[36], 0, 32); // MAC (ignored for unencrypted write) + packet.param1 = 0x00; // Mode is unencrypted write + packet.param2 = key_id; // Key ID + memcpy(&packet.data[0], priv_key, 36); // Private key + memset(&packet.data[36], 0, 32); // MAC (ignored for unencrypted write) } else { @@ -153,8 +153,8 @@ ATCA_STATUS atcab_priv_write(uint16_t key_id, const uint8_t priv_key[36], uint16 } // build a write command for encrypted writes - packet.param1 = PRIVWRITE_MODE_ENCRYPT; // Mode is encrypted write - packet.param2 = key_id; // Key ID + packet.param1 = PRIVWRITE_MODE_ENCRYPT; // Mode is encrypted write + packet.param2 = key_id; // Key ID memcpy(&packet.data[0], cipher_text, sizeof(cipher_text)); memcpy(&packet.data[sizeof(cipher_text)], host_mac, sizeof(host_mac)); } diff --git a/lib/basic/atca_basic_sha.c b/lib/basic/atca_basic_sha.c index 972a1667d..4aa19a6cc 100644 --- a/lib/basic/atca_basic_sha.c +++ b/lib/basic/atca_basic_sha.c @@ -288,7 +288,7 @@ ATCA_STATUS atcab_hw_sha2_256_finish(atca_sha256_ctx_t* ctx, uint8_t* digest) // Calculate the total message size in bits ctx->total_msg_size += ctx->block_size; - msg_size_bits = ctx->total_msg_size * 8; + msg_size_bits = (ctx->total_msg_size * 8); // Calculate the number of padding zero bytes required between the 1 bit byte and the ATCA_SHA256_BLOCK_SIZEbit message size in bits. pad_zero_count = (ATCA_SHA256_BLOCK_SIZE - ((ctx->block_size + 9) % ATCA_SHA256_BLOCK_SIZE)) % ATCA_SHA256_BLOCK_SIZE; diff --git a/lib/basic/atca_helpers.c b/lib/basic/atca_helpers.c index 7d9f2b59d..28cafc2fe 100644 --- a/lib/basic/atca_helpers.c +++ b/lib/basic/atca_helpers.c @@ -82,9 +82,11 @@ static void uint8_to_hex(uint8_t num, char* hex_str) static void hex_to_lowercase(char *buffer, size_t length) { + size_t index; + if ((buffer != NULL) && (length > 0)) { - for (size_t index = 0; index < length; index++) + for (index = 0; index < length; index++) { buffer[index] = tolower(buffer[index]); } @@ -94,9 +96,11 @@ static void hex_to_lowercase(char *buffer, size_t length) static void hex_to_uppercase(char *buffer, size_t length) { + size_t index; + if ((buffer != NULL) && (length > 0)) { - for (size_t index = 0; index < length; index++) + for (index = 0; index < length; index++) { buffer[index] = toupper(buffer[index]); } diff --git a/lib/crypto/hashes/sha1_routines.c b/lib/crypto/hashes/sha1_routines.c index 19f08ed15..9c418a61a 100644 --- a/lib/crypto/hashes/sha1_routines.c +++ b/lib/crypto/hashes/sha1_routines.c @@ -27,7 +27,7 @@ #include "sha1_routines.h" #include - +#include "atca_compiler.h" /** * \brief Initialize context for performing SHA1 hash in software. @@ -147,6 +147,8 @@ void CL_hashFinal(CL_HashContext *ctx, U8 *dest) U8 i; U8 nbytes; U32 temp; + U32* dest_addr = (U32*)dest; + U8 *ptr; /* Append pad byte, clear trailing bytes */ @@ -193,13 +195,10 @@ void CL_hashFinal(CL_HashContext *ctx, U8 *dest) shaEngine(ctx->buf, ctx->h); /* Unpack chaining variables to dest bytes. */ - memcpy(dest, ctx->h, 20); for (i = 0; i < 5; i++) { - dest[i * 4 + 0] = (ctx->h[i] >> 24) & 0xFF; - dest[i * 4 + 1] = (ctx->h[i] >> 16) & 0xFF; - dest[i * 4 + 2] = (ctx->h[i] >> 8) & 0xFF; - dest[i * 4 + 3] = (ctx->h[i] >> 0) & 0xFF; + dest_addr[i] = ATCA_UINT32_BE_TO_HOST(ctx->h[i]); + } } diff --git a/lib/crypto/hashes/sha2_routines.c b/lib/crypto/hashes/sha2_routines.c index 8f0dc1a87..c59402d10 100644 --- a/lib/crypto/hashes/sha2_routines.c +++ b/lib/crypto/hashes/sha2_routines.c @@ -27,7 +27,7 @@ #include #include "sha2_routines.h" - +#include "atca_compiler.h" #define rotate_right(value, places) ((value >> places) | (value << (32 - places))) /** @@ -77,8 +77,10 @@ static void sw_sha256_process(sw_sha256_ctx* ctx, const uint8_t* blocks, uint32_ w_union.w_byte[i + 2] = cur_msg_block[i + 1]; w_union.w_byte[i + 1] = cur_msg_block[i + 2]; w_union.w_byte[i + 0] = cur_msg_block[i + 3]; + w_union.w_word[i / 4] = ATCA_UINT32_HOST_TO_LE(w_union.w_word[i / 4]); } + w_index = 16; while (w_index < SHA256_BLOCK_SIZE) { diff --git a/lib/hal/hal_linux_i2c_userspace.c b/lib/hal/hal_linux_i2c_userspace.c index cb1326a0c..7edb3cd1e 100644 --- a/lib/hal/hal_linux_i2c_userspace.c +++ b/lib/hal/hal_linux_i2c_userspace.c @@ -47,10 +47,6 @@ * @{ */ -// File scope globals -ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index -int i2c_bus_ref_ct = 0; // total in-use count across buses - /** \brief discover i2c buses available for this hardware * this maintains a list of logical to physical bus mappings freeing the application * of the a-priori knowledge.This function is not implemented. @@ -88,50 +84,46 @@ ATCA_STATUS hal_i2c_discover_devices(int bus_num, ATCAIfaceCfg cfg[], int *found ATCA_STATUS hal_i2c_init(void* hal, ATCAIfaceCfg* cfg) { - int bus = cfg->atcai2c.bus; // 0-based logical bus number - ATCAHAL_t *phal = (ATCAHAL_t*)hal; - uint8_t i; - - if (i2c_bus_ref_ct == 0) // power up state, no i2c buses will have been used + ATCAHAL_t *pHal = (ATCAHAL_t*)hal; + ATCA_STATUS ret = ATCA_BAD_PARAM; + if (!pHal || !cfg) { - for (i = 0; i < MAX_I2C_BUSES; i++) - { - i2c_hal_data[i] = NULL; - } + return ret; } - i2c_bus_ref_ct++; // total across buses + if (pHal->hal_data) + { + ATCAI2CMaster_t * hal_data = (ATCAI2CMaster_t*)pHal->hal_data; + + // Assume the bus had already been initialized + hal_data->ref_ct++; - if (bus >= 0 && bus < MAX_I2C_BUSES) + ret = ATCA_SUCCESS; + } + else { - // if this is the first time this bus and interface has been created, do the physical work of enabling it - if (i2c_hal_data[bus] == NULL) + ATCAI2CMaster_t * hal_data = malloc(sizeof(ATCAI2CMaster_t)); + int bus = cfg->atcai2c.bus; // 0-based logical bus number + + if (hal_data) { - i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t) ); - i2c_hal_data[bus]->ref_ct = 1; // buses are shared, this is the first instance + hal_data->ref_ct = 1; // buses are shared, this is the first instance + + (void)snprintf(hal_data->i2c_file, sizeof(hal_data->i2c_file) - 1, "/dev/i2c-%d", bus); - switch (bus) - { - case 0: strcpy(i2c_hal_data[bus]->i2c_file, "/dev/i2c-0"); break; - case 1: strcpy(i2c_hal_data[bus]->i2c_file, "/dev/i2c-1"); break; - } + pHal->hal_data = hal_data; - // store this for use during the release phase - i2c_hal_data[bus]->bus_index = bus; + ret = ATCA_SUCCESS; } else { - // otherwise, another interface already initialized the bus, so this interface will share it and any different - // cfg parameters will be ignored...first one to initialize this sets the configuration - i2c_hal_data[bus]->ref_ct++; + ret = ATCA_ALLOC_FAILURE; } + } - phal->hal_data = i2c_hal_data[bus]; + return ret; - return ATCA_SUCCESS; - } - return ATCA_COMM_FAIL; } /** \brief HAL implementation of I2C post init @@ -153,7 +145,7 @@ ATCA_STATUS hal_i2c_post_init(ATCAIface iface) ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); - int bus = cfg->atcai2c.bus; + ATCAI2CMaster_t * hal_data = (ATCAI2CMaster_t*)atgetifacehaldat(iface); int f_i2c; // I2C file descriptor // for this implementation of I2C with CryptoAuth chips, txdata is assumed to have ATCAPacket format @@ -165,7 +157,7 @@ ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) txlength++; // account for word address value byte. // Initiate I2C communication - if ( (f_i2c = open(i2c_hal_data[bus]->i2c_file, O_RDWR)) < 0) + if ( (f_i2c = open(hal_data->i2c_file, O_RDWR)) < 0) { return ATCA_COMM_FAIL; } @@ -198,7 +190,7 @@ ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); - int bus = cfg->atcai2c.bus; + ATCAI2CMaster_t * hal_data = (ATCAI2CMaster_t*)atgetifacehaldat(iface); int f_i2c; // I2C file descriptor uint16_t count; uint16_t rxdata_max_size = *rxlength; @@ -210,7 +202,7 @@ ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength } // Initiate I2C communication - if ( (f_i2c = open(i2c_hal_data[bus]->i2c_file, O_RDWR)) < 0) + if ( (f_i2c = open(hal_data->i2c_file, O_RDWR)) < 0) { return ATCA_COMM_FAIL; } @@ -271,13 +263,13 @@ void change_i2c_speed(ATCAIface iface, uint32_t speed) ATCA_STATUS hal_i2c_wake(ATCAIface iface) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); - int bus = cfg->atcai2c.bus; + ATCAI2CMaster_t * hal_data = (ATCAI2CMaster_t*)atgetifacehaldat(iface); int f_i2c; // I2C file descriptor uint8_t data[4]; uint8_t dummy_byte = 0x00; // Initiate I2C communication - if ( (f_i2c = open(i2c_hal_data[bus]->i2c_file, O_RDWR)) < 0) + if ( (f_i2c = open(hal_data->i2c_file, O_RDWR)) < 0) { return ATCA_COMM_FAIL; } @@ -328,12 +320,12 @@ ATCA_STATUS hal_i2c_wake(ATCAIface iface) ATCA_STATUS hal_i2c_idle(ATCAIface iface) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); - int bus = cfg->atcai2c.bus; + ATCAI2CMaster_t * hal_data = (ATCAI2CMaster_t*)atgetifacehaldat(iface); uint8_t data = 0x02; // idle word address value int f_i2c; // I2C file descriptor // Initiate I2C communication - if ( (f_i2c = open(i2c_hal_data[bus]->i2c_file, O_RDWR) ) < 0) + if ( (f_i2c = open(hal_data->i2c_file, O_RDWR) ) < 0) { return ATCA_COMM_FAIL; } @@ -364,12 +356,12 @@ ATCA_STATUS hal_i2c_idle(ATCAIface iface) ATCA_STATUS hal_i2c_sleep(ATCAIface iface) { ATCAIfaceCfg *cfg = atgetifacecfg(iface); - int bus = cfg->atcai2c.bus; + ATCAI2CMaster_t * hal_data = (ATCAI2CMaster_t*)atgetifacehaldat(iface); uint8_t data = 0x01; // sleep word address value int f_i2c; // I2C file descriptor // Initiate I2C communication - if ( (f_i2c = open(i2c_hal_data[bus]->i2c_file, O_RDWR)) < 0) + if ( (f_i2c = open(hal_data->i2c_file, O_RDWR)) < 0) { return ATCA_COMM_FAIL; } @@ -401,13 +393,10 @@ ATCA_STATUS hal_i2c_release(void *hal_data) { ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; - i2c_bus_ref_ct--; // track total i2c bus interface instances for consistency checking and debugging - // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release - if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL) + if (hal && --(hal->ref_ct) <= 0) { - free(i2c_hal_data[hal->bus_index]); - i2c_hal_data[hal->bus_index] = NULL; + free(hal); } return ATCA_SUCCESS; diff --git a/lib/hal/hal_linux_i2c_userspace.h b/lib/hal/hal_linux_i2c_userspace.h index fe0838c70..063fb0977 100644 --- a/lib/hal/hal_linux_i2c_userspace.h +++ b/lib/hal/hal_linux_i2c_userspace.h @@ -42,8 +42,6 @@ typedef struct atcaI2Cmaster { char i2c_file[16]; int ref_ct; - // for conveniences during interface release phase - int bus_index; } ATCAI2CMaster_t; /** @} */ diff --git a/lib/hal/hal_uc3_i2c_asf.c b/lib/hal/hal_uc3_i2c_asf.c new file mode 100644 index 000000000..0fb42ce52 --- /dev/null +++ b/lib/hal/hal_uc3_i2c_asf.c @@ -0,0 +1,418 @@ +/** + * \file + * \brief ATCA Hardware abstraction layer for SAMV71 I2C over ASF drivers. + * + * This code is structured in two parts. Part 1 is the connection of the ATCA HAL API to the physical I2C + * implementation. Part 2 is the ASF I2C primitives to set up the interface. + * + * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio + * + * \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 +#include +#include + +#include "atca_hal.h" +#include "atca_device.h" +#include "atca_execution.h" +#include "hal_uc3_i2c_asf.h" + +/** \defgroup hal_ Hardware abstraction layer (hal_) + * + * \brief + * These methods define the hardware abstraction layer for communicating with a CryptoAuth device + * using I2C driver of ASF. + * + @{ */ + +/** \brief logical to physical bus mapping structure */ +static ATCAI2CMaster_t i2c_hal_data[MAX_I2C_BUSES]; // map logical, 0-based bus number to index + +/** \brief discover i2c buses available for this hardware + * this maintains a list of logical to physical bus mappings freeing the application + * of the a-priori knowledge + * \param[in] i2c_buses - an array of logical bus numbers + * \param[in] max_buses - maximum number of buses the app wants to attempt to discover + * \return ATCA_SUCCESS + */ + +ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) +{ + return ATCA_UNIMPLEMENTED; +} + +/** \brief discover any CryptoAuth devices on a given logical bus number + * \param[in] bus_num Logical bus number on which to look for CryptoAuth devices + * \param[out] cfg Pointer to head of an array of interface config structures which get filled in by this method + * \param[out] found Number of devices found on this bus + * \return ATCA_SUCCESS on success, otherwise an error code. + */ +ATCA_STATUS hal_i2c_discover_devices(int bus_num, ATCAIfaceCfg cfg[], int *found) +{ + return ATCA_UNIMPLEMENTED; +} + +/** \brief + - this HAL implementation assumes you've included the ASF Twi libraries in your project, otherwise, + the HAL layer will not compile because the ASF TWI drivers are a dependency * + */ + +/** \brief hal_i2c_init manages requests to initialize a physical interface. it manages use counts so when an interface + * has released the physical layer, it will disable the interface for some other use. + * You can have multiple ATCAIFace instances using the same bus, and you can have multiple ATCAIFace instances on + * multiple i2c buses, so hal_i2c_init manages these things and ATCAIFace is abstracted from the physical details. + */ + +/** \brief initialize an I2C interface using given config + * \param[in] hal - opaque ptr to HAL data + * \param[in] cfg - interface configuration + * \return ATCA_SUCCESS on success, otherwise an error code. + */ +ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) +{ + twi_options_t opt; + ATCA_STATUS status = !ATCA_SUCCESS; + ATCAI2CMaster_t* data = &i2c_hal_data[cfg->atcai2c.bus]; + + + if (data->ref_ct <= 0) + { + // Bus isn't being used, enable it + switch (cfg->atcai2c.bus) + { + + case 2: + data->twi_master_instance = &AVR32_TWI; + static const gpio_map_t TWI_GPIO_MAP = + { + { AVR32_TWI_SDA_0_0_PIN, AVR32_TWI_SDA_0_0_FUNCTION }, + { AVR32_TWI_SCL_0_0_PIN, AVR32_TWI_SCL_0_0_FUNCTION } + }; + + gpio_enable_module(TWI_GPIO_MAP, sizeof(TWI_GPIO_MAP) / sizeof(TWI_GPIO_MAP[0])); + // options settings + opt.pba_hz = 48000000; + opt.speed = 100000; + opt.chip = 0; + + // initialize TWI driver with options + twi_master_init(&AVR32_TWI, &opt); + break; + default: + return ATCA_COMM_FAIL; + } + + // store this for use during the release phase + data->bus_index = cfg->atcai2c.bus; + // buses are shared, this is the first instance + data->ref_ct = 1; + } + else + { + // Bus is already is use, increment reference counter + data->ref_ct++; + } + + ((ATCAHAL_t*)hal)->hal_data = data; + + return ATCA_SUCCESS; +} + +/** \brief HAL implementation of I2C post init + * \param[in] iface instance + * \return ATCA_SUCCESS + */ +ATCA_STATUS hal_i2c_post_init(ATCAIface iface) +{ + return ATCA_SUCCESS; +} + + +/** \brief HAL implementation of I2C send over ASF + * \param[in] iface instance + * \param[in] txdata pointer to space to bytes to send + * \param[in] txlength number of bytes to send + * \return ATCA_SUCCESS on success, otherwise an error code. + */ + +ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) +{ + twi_package_t packet; + + ATCAIfaceCfg *cfg = atgetifacecfg(iface); + + txdata[0] = 0x03; // insert the Word Address Value, Command token + txlength++; + + // TWI chip address to communicate with + packet.chip = cfg->atcai2c.slave_address >> 1; + // TWI address/commands to issue to the other chip (node) + packet.addr[0] = 0; + packet.addr[1] = 0; + packet.addr[2] = 0; + // Length of the TWI data address segment (1-3 bytes) + packet.addr_length = 0; + // Where to find the data to be written + packet.buffer = (void*)txdata; + // How many bytes do we want to write + packet.length = (uint32_t)txlength; + + if (twi_master_write(i2c_hal_data[cfg->atcai2c.bus].twi_master_instance, &packet) != TWI_SUCCESS) + { + return ATCA_COMM_FAIL; + } + + + return ATCA_SUCCESS; +} + +/** \brief HAL implementation of I2C receive function for ASF I2C + * \param[in] iface Device to interact with. + * \param[out] rxdata Data received will be returned here. + * \param[inout] rxlength As input, the size of the rxdata buffer. + * As output, the number of bytes received. + * \return ATCA_SUCCESS on success, otherwise an error code. + */ +ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength) +{ + ATCAIfaceCfg *cfg = atgetifacecfg(iface); + int retries = cfg->rx_retries; + uint32_t status = !ATCA_SUCCESS; + uint16_t rxdata_max_size = *rxlength; + + twi_package_t packet = { + .chip = cfg->atcai2c.slave_address >> 1, + .addr[0] = { 0 }, + .addr[1] = { 0 }, + .addr[2] = { 0 }, + .addr_length = 0, + .buffer = (void*)rxdata, + .length = (uint32_t)1 + }; + + *rxlength = 0; + if (rxdata_max_size < 1) + { + return ATCA_SMALL_BUFFER; + } + + while (retries-- > 0 && status != ATCA_SUCCESS) + { + if (twi_master_read(i2c_hal_data[cfg->atcai2c.bus].twi_master_instance, &packet) != TWI_SUCCESS) + { + status = ATCA_COMM_FAIL; + } + else + { + status = ATCA_SUCCESS; + } + } + + if (status != ATCA_SUCCESS) + { + return status; + } + if (rxdata[0] < ATCA_RSP_SIZE_MIN) + { + return ATCA_INVALID_SIZE; + } + if (rxdata[0] > rxdata_max_size) + { + return ATCA_SMALL_BUFFER; + } + + atca_delay_ms(1); + + //Update receive length with first byte received and set to read rest of the data + packet.length = rxdata[0] - 1; + packet.buffer = &rxdata[1]; + + if (twi_master_read(i2c_hal_data[cfg->atcai2c.bus].twi_master_instance, &packet) != TWI_SUCCESS) + { + status = ATCA_COMM_FAIL; + } + else + { + status = ATCA_SUCCESS; + } + if (status != ATCA_SUCCESS) + { + return status; + } + + *rxlength = rxdata[0]; + + return ATCA_SUCCESS; +} + +/** \brief method to change the bus speed of I2C + * \param[in] iface interface on which to change bus speed + * \param[in] speed baud rate (typically 100000 or 400000) + * \return ATCA_SUCCESS on success, otherwise an error code. + */ + +ATCA_STATUS change_i2c_speed(ATCAIface iface, uint32_t speed) +{ + return ATCA_UNIMPLEMENTED; +} + +/** \brief wake up CryptoAuth device using I2C bus + * \param[in] iface interface to logical device to wakeup + * \return ATCA_SUCCESS on success, otherwise an error code. + + */ + +ATCA_STATUS hal_i2c_wake(ATCAIface iface) +{ + ATCAIfaceCfg *cfg = atgetifacecfg(iface); + int retries = cfg->rx_retries; + uint32_t bdrt = cfg->atcai2c.baud; + int status = !TWI_SUCCESS; + uint8_t data[4]; + twi_package_t packet; + + // TWI chip address to communicate with + packet.chip = 0x00; + // TWI address/commands to issue to the other chip (node) + packet.addr[0] = 0; + packet.addr[1] = 0; + packet.addr[2] = 0; + // Length of the TWI data address segment (1-3 bytes) + packet.addr_length = 0; + // Where to find the data to be written + packet.buffer = (void*)&data[0]; + // How many bytes do we want to write + packet.length = 1; + + // if not already at 100kHz, change it + if (bdrt != 100000) + { + change_i2c_speed(iface, 100000); + } + + // Send 0x00 as wake pulse + twi_master_write(i2c_hal_data[cfg->atcai2c.bus].twi_master_instance, &packet); + + // rounded up to the nearest ms + atca_delay_ms(((uint32_t)cfg->wake_delay + (1000 - 1)) / 1000); // wait tWHI + tWLO which is configured based on device type and configuration structure + + + + // if necessary, revert baud rate to what came in. + if (bdrt != 100000) + { + change_i2c_speed(iface, bdrt); + } + + packet.chip = cfg->atcai2c.slave_address >> 1; + packet.buffer = (void*)data; + packet.length = (uint32_t)4; + while (retries-- > 0 && status != TWI_SUCCESS) + { + status = twi_master_read(i2c_hal_data[cfg->atcai2c.bus].twi_master_instance, &packet); + } + if (status != TWI_SUCCESS) + { + return ATCA_COMM_FAIL; + } + + return hal_check_wake(data, 4); +} + + +/** \brief idle CryptoAuth device using I2C bus + * \param[in] iface interface to logical device to idle + * \return ATCA_SUCCESS on success, otherwise an error code. + */ + +ATCA_STATUS hal_i2c_idle(ATCAIface iface) +{ + ATCAIfaceCfg *cfg = atgetifacecfg(iface); + uint8_t data[4]; + + data[0] = 0x02; // idle word address value + twi_package_t packet = { + .chip = cfg->atcai2c.slave_address >> 1, + .addr = { 0 }, + .addr_length = 0, + .buffer = (void*)data, + .length = 1 + }; + + if (twi_master_write(i2c_hal_data[cfg->atcai2c.bus].twi_master_instance, &packet) != TWI_SUCCESS) + { + return ATCA_COMM_FAIL; + } + + return ATCA_SUCCESS; +} + +/** \brief sleep CryptoAuth device using I2C bus + * \param[in] iface interface to logical device to sleep + * \return ATCA_SUCCESS on success, otherwise an error code. + */ + +ATCA_STATUS hal_i2c_sleep(ATCAIface iface) +{ + ATCAIfaceCfg *cfg = atgetifacecfg(iface); + uint8_t data[4]; + + data[0] = 0x01; // sleep word address value + twi_package_t packet = { + .chip = cfg->atcai2c.slave_address >> 1, + .addr = { 0 }, + .addr_length = 0, + .buffer = (void*)data, + .length = 1 + }; + + if (twi_master_write(i2c_hal_data[cfg->atcai2c.bus].twi_master_instance, &packet) != TWI_SUCCESS) + { + return ATCA_COMM_FAIL; + } + + return ATCA_SUCCESS; +} + +/** \brief manages reference count on given bus and releases resource if no more refences exist + * \param[in] hal_data - opaque pointer to hal data structure - known only to the HAL implementation + * \return ATCA_SUCCESS + */ + +ATCA_STATUS hal_i2c_release(void *hal_data) +{ + ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data; + + // if the use count for this bus has gone to 0 references, disable it. protect against an unbracketed release + if (hal && --(hal->ref_ct) <= 0) + { + twi_master_disable(hal->twi_master_instance); + hal->ref_ct = 0; + } + + return ATCA_SUCCESS; +} + +/** @} */ diff --git a/lib/hal/hal_uc3_i2c_asf.h b/lib/hal/hal_uc3_i2c_asf.h new file mode 100644 index 000000000..0933206ab --- /dev/null +++ b/lib/hal/hal_uc3_i2c_asf.h @@ -0,0 +1,61 @@ +/** + * \file + * \brief ATCA Hardware abstraction layer for SAMV71 I2C over ASF drivers. + * + * Prerequisite: add SERCOM I2C Master Polled support to application in Atmel Studio + * + * \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 HAL_SAMV71_I2C_ASF_H_ +#define HAL_SAMV71_I2C_ASF_H_ + +#include +#include "twi.h" + +/** \defgroup hal_ Hardware abstraction layer (hal_) + * + * \brief + * These methods define the hardware abstraction layer for communicating with a CryptoAuth device + * using I2C driver of ASF. + * + @{ */ + + +#define MAX_I2C_BUSES 3 + +/** \brief this is the hal_data for ATCA HAL for ASF SERCOM + */ +typedef struct atcaI2Cmaster +{ + uint8_t twi_id; + avr32_twi_t * twi_master_instance; + int ref_ct; + // for conveniences during interface release phase + int bus_index; +} ATCAI2CMaster_t; + +ATCA_STATUS change_i2c_speed(ATCAIface iface, uint32_t speed); + +/** @} */ +#endif /* HAL_SAMD21_I2C_ASF_H_ */ \ No newline at end of file diff --git a/lib/hal/hal_uc3_timer_asf.c b/lib/hal/hal_uc3_timer_asf.c new file mode 100644 index 000000000..e8c671750 --- /dev/null +++ b/lib/hal/hal_uc3_timer_asf.c @@ -0,0 +1,82 @@ +/** + * \file + * \brief ATCA Hardware abstraction layer for SAM4S I2C over ASF drivers. + * + * Prerequisite: add "Delay routines (service)" module to application in Atmel Studio + * + * \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 +#include +#include "atca_hal.h" + + +/* ASF already have delay_us and delay_ms - see delay.h */ + +/** + * \defgroup hal_ Hardware abstraction layer (hal_) + * + * \brief + * These methods define the hardware abstraction layer for communicating with a CryptoAuth device + * + @{ */ + +/** + * \brief This function delays for a number of microseconds. + * + * \param[in] delay number of 0.001 milliseconds to delay + */ +void atca_delay_us(uint32_t delay) +{ + // use ASF supplied delay + delay_us(delay); +} + +/** + * \brief This function delays for a number of tens of microseconds. + * + * \param[in] delay number of 0.01 milliseconds to delay + */ +void atca_delay_10us(uint32_t delay) +{ + // use ASF supplied delay + delay_us(delay * 10); + +} + +/** + * \brief This function delays for a number of milliseconds. + * + * You can override this function if you like to do + * something else in your system while delaying. + * + * \param[in] delay number of milliseconds to delay + */ +void atca_delay_ms(uint32_t delay) +{ + // use ASF supplied delay + delay_ms(delay); +} + +/** @} */ diff --git a/lib/hal/kit_protocol.c b/lib/hal/kit_protocol.c index 7d86337e7..93945cf37 100644 --- a/lib/hal/kit_protocol.c +++ b/lib/hal/kit_protocol.c @@ -62,20 +62,35 @@ char * strnchr(const char * s, size_t count, int c) #endif /** Kit Protocol is key */ -char kit_id_from_devtype(ATCADeviceType devtype) +const char * kit_id_from_devtype(ATCADeviceType devtype) { switch (devtype) { case ATSHA204A: - return 'S'; + return "SHA204A"; case ATECC108A: - /* fallthrough */ + return "ECC108A"; case ATECC508A: - /* fallthrough */ + return "ECC508A"; case ATECC608A: - return 'E'; + return "ECC608A"; default: - return 'd'; + return "unknown"; + } +} + + +/** Kit interface from device */ +const char * kit_interface_from_kittype(ATCAKitType kittype) +{ + switch (kittype) + { + case ATCA_KIT_I2C_IFACE: + return "TWI"; + case ATCA_KIT_SWI_IFACE: + return "SWI"; + default: + return "unknown"; } } @@ -92,10 +107,14 @@ ATCA_STATUS kit_init(ATCAIface iface) int txlen; char rxbuf[KIT_RX_WRAP_SIZE + 4]; int rxlen; - char match; + char* device_match, *interface_match; + char *dev_type, *dev_interface; + char delim[] = " "; int i; + int address; - match = kit_id_from_devtype(iface->mIfaceCFG->devtype); + device_match = kit_id_from_devtype(iface->mIfaceCFG->devtype); + interface_match = kit_interface_from_kittype(iface->mIfaceCFG->atcahid.dev_interface); /* Iterate to find the target device */ for (i = 0; i < KIT_MAX_SCAN_COUNT; i++) @@ -120,25 +139,28 @@ ATCA_STATUS kit_init(ATCAIface iface) break; } - /* If the device type is correct the device has to be "selected" use the - returned I2C address */ - if (match == rxbuf[0]) + dev_type = strtok(rxbuf, delim); + dev_interface = strtok(NULL, delim); + char * addr = strnchr(rxbuf, rxlen, '('); /* Gets the identity from the kit used for selecting the device*/ + address = 0; + + if (!addr) { - char * addr = strnchr(rxbuf, rxlen, '('); - int address = 0; - if (!addr) - { - status = ATCA_GEN_FAIL; - break; - } + status = ATCA_GEN_FAIL; + break; + } - if (1 != sscanf(addr, "(%02X)", &address)) - { - status = ATCA_GEN_FAIL; - break; - } + if (1 != sscanf(addr, "(%02X)", &address)) + { + status = ATCA_GEN_FAIL; + break; + } + + /*Selects the first device type if both device interface and device identity is not defined*/ + if (iface->mIfaceCFG->atcahid.dev_interface == ATCA_KIT_AUTO_IFACE && iface->mIfaceCFG->atcahid.dev_identity == 0 && (strcmp(device_match, dev_type) == 0)) + { - txlen = snprintf(txbuf, sizeof(txbuf) - 1, kit_device_select, match, address); + txlen = snprintf(txbuf, sizeof(txbuf) - 1, kit_device_select, device_match[0], address); txbuf[sizeof(txbuf) - 1] = '\0'; if (txlen < 0) { @@ -154,6 +176,36 @@ ATCA_STATUS kit_init(ATCAIface iface) rxlen = sizeof(rxbuf); status = kit_phy_receive(iface, rxbuf, &rxlen); break; + + + } + + else + { + + + /*Selects the device only if the device type, device interface and device identity matches*/ + if ((strcmp(device_match, dev_type) == 0) && (iface->mIfaceCFG->atcahid.dev_identity == address) && (strcmp(interface_match, dev_interface) == 0)) + { + + + txlen = snprintf(txbuf, sizeof(txbuf) - 1, kit_device_select, device_match[0], address); + txbuf[sizeof(txbuf) - 1] = '\0'; + if (txlen < 0) + { + status = ATCA_INVALID_SIZE; + break; + } + + if (ATCA_SUCCESS != (status = kit_phy_send(iface, txbuf, txlen))) + { + break; + } + + rxlen = sizeof(rxbuf); + status = kit_phy_receive(iface, rxbuf, &rxlen); + break; + } } } @@ -176,6 +228,7 @@ ATCA_STATUS kit_send(ATCAIface iface, const uint8_t* txdata, int txlength) ATCA_STATUS status = ATCA_SUCCESS; int nkitbuf = txlength * 2 + KIT_TX_WRAP_SIZE; char* pkitbuf = NULL; + char *target; // Check the pointers if (txdata == NULL) @@ -185,8 +238,8 @@ ATCA_STATUS kit_send(ATCAIface iface, const uint8_t* txdata, int txlength) // Wrap in kit protocol pkitbuf = malloc(nkitbuf); memset(pkitbuf, 0, nkitbuf); - status = kit_wrap_cmd(&txdata[1], txlength, pkitbuf, &nkitbuf, - kit_id_from_devtype(iface->mIfaceCFG->devtype)); + target = kit_id_from_devtype(iface->mIfaceCFG->devtype); + status = kit_wrap_cmd(&txdata[1], txlength, pkitbuf, &nkitbuf, target[0]); if (status != ATCA_SUCCESS) { free(pkitbuf); @@ -270,8 +323,10 @@ ATCA_STATUS kit_wake(ATCAIface iface) int replysize = sizeof(reply); uint8_t rxdata[10]; int rxsize = sizeof(rxdata); + char *target; - wake[0] = kit_id_from_devtype(iface->mIfaceCFG->devtype); + target = kit_id_from_devtype(iface->mIfaceCFG->devtype); + wake[0] = target[0]; // Send the bytes status = kit_phy_send(iface, wake, wakesize); @@ -315,8 +370,10 @@ ATCA_STATUS kit_idle(ATCAIface iface) int replysize = sizeof(reply); uint8_t rxdata[10]; int rxsize = sizeof(rxdata); + char *target; - idle[0] = kit_id_from_devtype(iface->mIfaceCFG->devtype); + target = kit_id_from_devtype(iface->mIfaceCFG->devtype); + idle[0] = target[0]; // Send the bytes status = kit_phy_send(iface, idle, idlesize); @@ -361,8 +418,10 @@ ATCA_STATUS kit_sleep(ATCAIface iface) int replysize = sizeof(reply); uint8_t rxdata[10]; int rxsize = sizeof(rxdata); + char* target; - sleep[0] = kit_id_from_devtype(iface->mIfaceCFG->devtype); + target = kit_id_from_devtype(iface->mIfaceCFG->devtype); + sleep[0] = target[0]; // Send the bytes status = kit_phy_send(iface, sleep, sleepsize); diff --git a/lib/host/atca_host.c b/lib/host/atca_host.c index b465ad35b..8915528f1 100644 --- a/lib/host/atca_host.c +++ b/lib/host/atca_host.c @@ -150,26 +150,45 @@ ATCA_STATUS atcah_nonce(struct atca_nonce_in_out *param) // Update TempKey to only 32 bytes param->temp_key->is_64 = 0; } - else if (param->mode == NONCE_MODE_PASSTHROUGH && (param->mode & NONCE_MODE_TARGET_MASK) != NONCE_MODE_TARGET_TEMPKEY) + else if ((param->mode & NONCE_MODE_MASK) == NONCE_MODE_PASSTHROUGH) { - // Pass-through mode for TempKey (other targets have no effect on TempKey) - if ((param->mode & NONCE_MODE_INPUT_LEN_MASK) == NONCE_MODE_INPUT_LEN_64) + + if ((param->mode & NONCE_MODE_TARGET_MASK) == NONCE_MODE_TARGET_TEMPKEY) { - memcpy(param->temp_key->value, param->num_in, 64); - param->temp_key->is_64 = 1; + // Pass-through mode for TempKey (other targets have no effect on TempKey) + if ((param->mode & NONCE_MODE_INPUT_LEN_MASK) == NONCE_MODE_INPUT_LEN_64) + { + memcpy(param->temp_key->value, param->num_in, 64); + param->temp_key->is_64 = 1; + } + else + { + memcpy(param->temp_key->value, param->num_in, 32); + param->temp_key->is_64 = 0; + } + + // Update TempKey flags + param->temp_key->source_flag = 1; // Not Random + param->temp_key->key_id = 0; + param->temp_key->gen_dig_data = 0; + param->temp_key->no_mac_flag = 0; + param->temp_key->valid = 1; } - else + else //In the case of ECC608A, passthrough message may be stored in message digest buffer/ Alternate Key buffer { - memcpy(param->temp_key->value, param->num_in, 32); - param->temp_key->is_64 = 0; - } - // Update TempKey flags - param->temp_key->source_flag = 1; // Not Random - param->temp_key->key_id = 0; - param->temp_key->gen_dig_data = 0; - param->temp_key->no_mac_flag = 0; - param->temp_key->valid = 1; + // Update TempKey flags + param->temp_key->source_flag = 1; //Not Random + param->temp_key->key_id = 0; + param->temp_key->gen_dig_data = 0; + param->temp_key->no_mac_flag = 0; + param->temp_key->valid = 0; + + } + } + else + { + return ATCA_BAD_PARAM; } return ATCA_SUCCESS; @@ -703,14 +722,16 @@ ATCA_STATUS atcah_gen_dig(struct atca_gen_dig_in_out *param) { return ATCA_BAD_PARAM; } - if (param->zone != GENDIG_ZONE_SHARED_NONCE && param->stored_value == NULL) + if ((param->zone <= GENDIG_ZONE_DATA) && (param->stored_value == NULL)) { - return ATCA_BAD_PARAM; // Stored value can only be null with the shared_nonce mode + return ATCA_BAD_PARAM; // Stored value cannot be null for Config,OTP and Data } + if ((param->zone == GENDIG_ZONE_SHARED_NONCE || (param->zone == GENDIG_ZONE_DATA && param->is_key_nomac)) && param->other_data == NULL) { return ATCA_BAD_PARAM; // Other data is required in these cases } + if (param->zone > 5) { return ATCA_BAD_PARAM; // Unknown zone @@ -719,17 +740,34 @@ ATCA_STATUS atcah_gen_dig(struct atca_gen_dig_in_out *param) // Start calculation p_temp = temporary; + // (1) 32 bytes inputKey - if (param->zone == GENDIG_ZONE_SHARED_NONCE && param->key_id & 0x8000) + if (param->zone == GENDIG_ZONE_SHARED_NONCE) { - memcpy(p_temp, param->other_data, ATCA_KEY_SIZE); + if (param->key_id & 0x8000) + { + memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE); // 32 bytes TempKey + } + else + { + memcpy(p_temp, param->other_data, ATCA_KEY_SIZE); // 32 bytes other data + + } + } + else if (param->zone == GENDIG_ZONE_COUNTER || param->zone == GENDIG_ZONE_KEY_CONFIG) + { + memset(p_temp, 0x00, ATCA_KEY_SIZE); // 32 bytes of zero. + } else { - memcpy(p_temp, param->stored_value, ATCA_KEY_SIZE); + memcpy(p_temp, param->stored_value, ATCA_KEY_SIZE); // 32 bytes of stored data + } + p_temp += ATCA_KEY_SIZE; + if (param->zone == GENDIG_ZONE_DATA && param->is_key_nomac) { // If a key has the SlotConfig.NoMac bit set, then opcode and parameters come from OtherData @@ -744,9 +782,18 @@ ATCA_STATUS atcah_gen_dig(struct atca_gen_dig_in_out *param) // (3) 1 byte Param1 (zone) *p_temp++ = param->zone; - // (4) 2 bytes Param2 (keyID) + // (4) 1 byte LSB of Param2 (keyID) *p_temp++ = (uint8_t)(param->key_id & 0xFF); - *p_temp++ = (uint8_t)(param->key_id >> 8); + if (param->zone == GENDIG_ZONE_SHARED_NONCE) + { + //(4) 1 byte zero for shared nonce mode + *p_temp++ = 0; + } + else + { + //(4) 1 byte MSB of Param2 (keyID) for other modes + *p_temp++ = (uint8_t)(param->key_id >> 8); + } } // (5) 1 byte SN[8] @@ -756,21 +803,66 @@ ATCA_STATUS atcah_gen_dig(struct atca_gen_dig_in_out *param) *p_temp++ = param->sn[0]; *p_temp++ = param->sn[1]; - // (7) 25 zeros - memset(p_temp, 0, ATCA_GENDIG_ZEROS_SIZE); - p_temp += ATCA_GENDIG_ZEROS_SIZE; - if (param->zone == GENDIG_ZONE_SHARED_NONCE && !(param->key_id & 0x8000)) + // (7) + if (param->zone == GENDIG_ZONE_COUNTER) + { + *p_temp++ = 0; + *p_temp++ = (uint8_t)(param->counter & 0xFF); // (7) 4 bytes of counter + *p_temp++ = (uint8_t)(param->counter >> 8); + *p_temp++ = (uint8_t)(param->counter >> 16); + *p_temp++ = (uint8_t)(param->counter >> 24); + + memset(p_temp, 0x00, 20); // (7) 20 bytes of zero + p_temp += 20; + + } + else if (param->zone == GENDIG_ZONE_KEY_CONFIG) + { + *p_temp++ = 0; + *p_temp++ = param->slot_conf & 0xFF; // (7) 2 bytes of Slot config + *p_temp++ = (uint8_t)(param->slot_conf >> 8); + + *p_temp++ = param->key_conf & 0xFF; + *p_temp++ = (uint8_t)(param->key_conf >> 8); // (7) 2 bytes of key config + + *p_temp++ = param->slot_locked; // (7) 1 byte of slot locked + + memset(p_temp, 0x00, 19); // (7) 19 bytes of zero + p_temp += 19; + + + } + else + { + + memset(p_temp, 0, ATCA_GENDIG_ZEROS_SIZE); // (7) 25 zeros + p_temp += ATCA_GENDIG_ZEROS_SIZE; + + } + + + + + if (param->zone == GENDIG_ZONE_SHARED_NONCE && (param->key_id & 0x8000)) { - memcpy(p_temp, param->other_data, ATCA_KEY_SIZE); // (8) 32 bytes OtherData + memcpy(p_temp, param->other_data, ATCA_KEY_SIZE); // (8) 32 bytes OtherData + p_temp += ATCA_KEY_SIZE; + } else { - memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE); // (8) 32 bytes TempKey + memcpy(p_temp, param->temp_key->value, ATCA_KEY_SIZE); // (8) 32 bytes TempKey + p_temp += ATCA_KEY_SIZE; } + + + + + // Calculate SHA256 to get the new TempKey - atcac_sw_sha2_256(temporary, ATCA_MSG_SIZE_GEN_DIG, param->temp_key->value); + atcac_sw_sha2_256(temporary, (p_temp - temporary), param->temp_key->value); // Update TempKey fields param->temp_key->valid = 1; @@ -779,6 +871,10 @@ ATCA_STATUS atcah_gen_dig(struct atca_gen_dig_in_out *param) { param->temp_key->gen_dig_data = 1; param->temp_key->key_id = (param->key_id & 0xF); // mask lower 4-bit only + if (param->is_key_nomac == 1) + { + param->temp_key->no_mac_flag = 1; + } } else { diff --git a/lib/host/atca_host.h b/lib/host/atca_host.h index 64be091e7..8589b3290 100644 --- a/lib/host/atca_host.h +++ b/lib/host/atca_host.h @@ -273,6 +273,10 @@ typedef struct atca_gen_dig_in_out { uint8_t zone; //!< [in] Zone/Param1 for the GenDig command uint16_t key_id; //!< [in] KeyId/Param2 for the GenDig command + uint16_t slot_conf; //!< [in] Slot config for the GenDig command + uint16_t key_conf; //!< [in] Key config for the GenDig command + uint8_t slot_locked; //!< [in] slot locked for the GenDig command + uint32_t counter; //!< [in] counter for the GenDig command bool is_key_nomac; //!< [in] Set to true if the slot pointed to be key_id has the SotConfig.NoMac bit set const uint8_t * sn; //!< [in] Device serial number SN[0:8]. Only SN[0:1] and SN[8] are required though. const uint8_t * stored_value; //!< [in] 32-byte slot value, config block, OTP block as specified by the Zone/KeyId parameters diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 000000000..77efad71a --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 2.6.4) +project (cryptoauth_test) + +file(GLOB TEST_ATCACERT_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "atcacert/*.c") +file(GLOB TEST_JWT_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "jwt/*.c") +file(GLOB TEST_TNG_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "tng/*.c") +file(GLOB TEST_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.c") + +if(ATCA_HAL_KIT_HID) +add_definitions(-DATCA_HAL_KIT_HID) +endif(ATCA_HAL_KIT_HID) + +if(ATCA_HAL_KIT_CDC) +add_definitions(-DATCA_HAL_KIT_CDC) +endif(ATCA_HAL_KIT_CDC) + +if(ATCA_HAL_I2C) +add_definitions(-DATCA_HAL_I2C) +endif(ATCA_HAL_I2C) + +if(ATCA_HAL_CUSTOM) +add_definitions(-DATCA_HAL_CUSTOM) +endif() + +add_executable(cryptoauth_test ${TEST_SRC} ${TEST_TNG_SRC} ${TEST_JWT_SRC} ${TEST_ATCACERT_SRC}) + +include_directories(cryptoauth_test ${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../lib) + +target_link_libraries(cryptoauth_test cryptoauth) + +if(UNIX) +target_link_libraries(cryptoauth_test pthread) +endif() diff --git a/test/atca_test.c b/test/atca_test.c index 220df87c0..8ada03765 100644 --- a/test/atca_test.c +++ b/test/atca_test.c @@ -33,15 +33,17 @@ extern tng_type_t g_tng_test_type; // gCfg must point to one of the cfg_ structures for any unit test to work. this allows // the command console to switch device types at runtime. ATCAIfaceCfg g_iface_config = { - .iface_type = ATCA_UNKNOWN_IFACE, - .devtype = ATCA_DEV_UNKNOWN, - .atcai2c = { - .slave_address = 0xC0, - .bus = 2, - .baud = 400000, + .iface_type = ATCA_UNKNOWN_IFACE, + .devtype = ATCA_DEV_UNKNOWN, + { + .atcai2c = { + .slave_address = 0xC0, + .bus = 2, + .baud = 400000, + }, }, - .wake_delay = 1500, - .rx_retries = 20 + .wake_delay = 1500, + .rx_retries = 20 }; ATCAIfaceCfg *gCfg = &g_iface_config; diff --git a/test/atca_tests_gendig.c b/test/atca_tests_gendig.c index 661e6bca0..87ac58b7f 100644 --- a/test/atca_tests_gendig.c +++ b/test/atca_tests_gendig.c @@ -68,39 +68,348 @@ TEST(atca_cmd_unit_test, gendig) TEST_ASSERT_EQUAL(0x00, packet.data[ATCA_RSP_DATA_IDX]); } -TEST(atca_cmd_basic_test, gendig) + +TEST(atca_cmd_basic_test, gendig_shared_nonce) +{ + ATCA_STATUS status = ATCA_GEN_FAIL; + uint8_t i, sn[9]; + atca_temp_key_t temp_key; + uint8_t num_in[NONCE_NUMIN_SIZE]; + uint8_t rand_out[RANDOM_NUM_SIZE]; + atca_nonce_in_out_t nonce_params; + atca_mac_in_out_t mac_params; + uint8_t host_response[ATCA_KEY_SIZE]; + uint8_t client_response[ATCA_KEY_SIZE]; + atca_gen_dig_in_out_t gen_dig_params; + uint8_t other_data[32]; + + test_assert_data_is_locked(); + + uint16_t key_id[] = { 0x0004, 0x8004 }; + // Read serial number for host-side MAC calculations + status = atcab_read_serial_number(sn); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + for (i = 0; i < sizeof(key_id) / sizeof(key_id[0]); i++) + { + // Setup nonce command + memset(&temp_key, 0, sizeof(temp_key)); + memset(num_in, 0, sizeof(num_in)); + memset(&nonce_params, 0, sizeof(nonce_params)); + nonce_params.mode = NONCE_MODE_SEED_UPDATE; + nonce_params.zero = 0; + nonce_params.num_in = num_in; + nonce_params.rand_out = rand_out; + nonce_params.temp_key = &temp_key; + + // Create random nonce + status = atcab_nonce_base(nonce_params.mode, nonce_params.zero, nonce_params.num_in, rand_out); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Calculate nonce + status = atcah_nonce(&nonce_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + memset(other_data, 0x00, sizeof(other_data)); + // Use GenDig to create an initial digest across the internal key to be signed + memset(&gen_dig_params, 0, sizeof(gen_dig_params)); + gen_dig_params.zone = GENDIG_ZONE_SHARED_NONCE; + gen_dig_params.key_id = key_id[i]; + gen_dig_params.is_key_nomac = false; + gen_dig_params.stored_value = NULL; + gen_dig_params.sn = sn; + gen_dig_params.other_data = other_data; + gen_dig_params.temp_key = &temp_key; + status = atcab_gendig(gen_dig_params.zone, gen_dig_params.key_id, other_data, 32); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + status = atcah_gen_dig(&gen_dig_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Setup MAC command + memset(&mac_params, 0, sizeof(mac_params)); + mac_params.mode = MAC_MODE_BLOCK2_TEMPKEY | MAC_MODE_INCLUDE_SN; // Block 1 is a key, block 2 is TempKey + mac_params.key_id = 4; + mac_params.challenge = NULL; + mac_params.key = g_slot4_key; + mac_params.otp = NULL; + mac_params.sn = sn; + mac_params.response = host_response; + mac_params.temp_key = &temp_key; + + // Run MAC command + status = atcab_mac(mac_params.mode, mac_params.key_id, mac_params.challenge, client_response); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Calculate expected MAC + status = atcah_mac(&mac_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(host_response, client_response, sizeof(host_response)); + } +} + +TEST(atca_cmd_basic_test, gendig_keyconfig) +{ + ATCA_STATUS status = ATCA_GEN_FAIL; + uint8_t sn[9]; + atca_temp_key_t temp_key; + uint8_t num_in[NONCE_NUMIN_SIZE]; + uint8_t rand_out[RANDOM_NUM_SIZE]; + atca_nonce_in_out_t nonce_params; + atca_mac_in_out_t mac_params; + uint8_t host_response[ATCA_KEY_SIZE]; + uint8_t client_response[ATCA_KEY_SIZE]; + atca_gen_dig_in_out_t gen_dig_params; + uint8_t config_zone[128]; + uint32_t counter_read_value; + + test_assert_data_is_locked(); + + // Read serial number for host-side MAC calculations + status = atcab_read_serial_number(sn); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Setup nonce command + memset(&temp_key, 0, sizeof(temp_key)); + memset(num_in, 0, sizeof(num_in)); + memset(&nonce_params, 0, sizeof(nonce_params)); + nonce_params.mode = NONCE_MODE_SEED_UPDATE; + nonce_params.zero = 0; + nonce_params.num_in = num_in; + nonce_params.rand_out = rand_out; + nonce_params.temp_key = &temp_key; + + // Create random nonce + status = atcab_nonce_base(nonce_params.mode, nonce_params.zero, nonce_params.num_in, rand_out); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Calculate nonce + status = atcah_nonce(&nonce_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + status = atcab_counter_read(0, &counter_read_value); //Read the counter_value from counter0 + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + atcab_read_config_zone(config_zone); + + // Use GenDig to create an initial digest across the internal key to be signed + memset(&gen_dig_params, 0, sizeof(gen_dig_params)); + gen_dig_params.zone = GENDIG_ZONE_KEY_CONFIG; + gen_dig_params.slot_conf = (uint16_t)(config_zone[20 + (4 * 2)] | config_zone[21 + (4 * 2)] << 8); + gen_dig_params.key_conf = (uint16_t)(config_zone[96 + (4 * 2)] | config_zone[97 + (4 * 2)] << 8); + gen_dig_params.slot_locked = 1; + gen_dig_params.key_id = 4; + gen_dig_params.is_key_nomac = false; + gen_dig_params.stored_value = NULL; + gen_dig_params.counter = counter_read_value; + gen_dig_params.sn = sn; + gen_dig_params.other_data = NULL; + gen_dig_params.temp_key = &temp_key; + status = atcab_gendig(gen_dig_params.zone, gen_dig_params.key_id, NULL, 0); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + status = atcah_gen_dig(&gen_dig_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Setup MAC command + memset(&mac_params, 0, sizeof(mac_params)); + mac_params.mode = MAC_MODE_BLOCK2_TEMPKEY | MAC_MODE_INCLUDE_SN; // Block 1 is a key, block 2 is TempKey + mac_params.key_id = 4; + mac_params.challenge = NULL; + mac_params.key = g_slot4_key; + mac_params.otp = NULL; + mac_params.sn = sn; + mac_params.response = host_response; + mac_params.temp_key = &temp_key; + + // Run MAC command + status = atcab_mac(mac_params.mode, mac_params.key_id, mac_params.challenge, client_response); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Calculate expected MAC + status = atcah_mac(&mac_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(host_response, client_response, sizeof(host_response)); +} + +TEST(atca_cmd_basic_test, gendig_counter) { ATCA_STATUS status = ATCA_GEN_FAIL; - uint8_t random_number[32]; - uint16_t key_id = 0x04; - uint8_t dummy[32]; + uint8_t sn[9]; + atca_temp_key_t temp_key; + uint8_t num_in[NONCE_NUMIN_SIZE]; + uint8_t rand_out[RANDOM_NUM_SIZE]; + atca_nonce_in_out_t nonce_params; + atca_mac_in_out_t mac_params; + uint8_t host_response[ATCA_KEY_SIZE]; + uint8_t client_response[ATCA_KEY_SIZE]; + atca_gen_dig_in_out_t gen_dig_params; + uint32_t counter_read_value; + + test_assert_data_is_locked(); + + // Read serial number for host-side MAC calculations + status = atcab_read_serial_number(sn); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Setup nonce command + memset(&temp_key, 0, sizeof(temp_key)); + memset(num_in, 0, sizeof(num_in)); + memset(&nonce_params, 0, sizeof(nonce_params)); + nonce_params.mode = NONCE_MODE_SEED_UPDATE; + nonce_params.zero = 0; + nonce_params.num_in = num_in; + nonce_params.rand_out = rand_out; + nonce_params.temp_key = &temp_key; - status = atcab_init(gCfg); + // Create random nonce + status = atcab_nonce_base(nonce_params.mode, nonce_params.zero, nonce_params.num_in, rand_out); TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + // Calculate nonce + status = atcah_nonce(&nonce_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + status = atcab_counter_read(0, &counter_read_value); //Read the counter_value from counter0 + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Use GenDig to create an initial digest across the internal key to be signed + memset(&gen_dig_params, 0, sizeof(gen_dig_params)); + gen_dig_params.zone = GENDIG_ZONE_COUNTER; + gen_dig_params.key_id = 0; + gen_dig_params.is_key_nomac = false; + gen_dig_params.stored_value = NULL; + gen_dig_params.counter = counter_read_value; + gen_dig_params.sn = sn; + gen_dig_params.other_data = NULL; + gen_dig_params.temp_key = &temp_key; + status = atcab_gendig(gen_dig_params.zone, gen_dig_params.key_id, NULL, 0); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + status = atcah_gen_dig(&gen_dig_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Setup MAC command + memset(&mac_params, 0, sizeof(mac_params)); + mac_params.mode = MAC_MODE_BLOCK2_TEMPKEY | MAC_MODE_INCLUDE_SN; // Block 1 is a key, block 2 is TempKey + mac_params.key_id = 4; + mac_params.challenge = NULL; + mac_params.key = g_slot4_key; + mac_params.otp = NULL; + mac_params.sn = sn; + mac_params.response = host_response; + mac_params.temp_key = &temp_key; + + // Run MAC command + status = atcab_mac(mac_params.mode, mac_params.key_id, mac_params.challenge, client_response); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Calculate expected MAC + status = atcah_mac(&mac_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(host_response, client_response, sizeof(host_response)); +} + +TEST(atca_cmd_basic_test, gendig_config_otp_data) +{ + ATCA_STATUS status = ATCA_GEN_FAIL; + uint8_t i, sn[9]; + atca_temp_key_t temp_key; + uint8_t num_in[NONCE_NUMIN_SIZE]; + uint8_t rand_out[RANDOM_NUM_SIZE]; + atca_nonce_in_out_t nonce_params; + atca_mac_in_out_t mac_params; + uint8_t host_response[ATCA_KEY_SIZE]; + uint8_t client_response[ATCA_KEY_SIZE]; + atca_gen_dig_in_out_t gen_dig_params; + uint8_t config_zone[ATCA_ECC_CONFIG_SIZE]; + uint8_t read_otp[ATCA_OTP_SIZE]; + test_assert_data_is_locked(); - status = atcab_random(random_number); + + uint8_t gendig_modes[] = { GENDIG_ZONE_CONFIG, GENDIG_ZONE_OTP, GENDIG_ZONE_DATA }; + const uint8_t* gendig_modes_data[] = { config_zone, read_otp, g_slot4_key }; + uint8_t gendig_modes_key[] = { 0, 0, 4 }; + + + // Read current state of OTP + status = atcab_read_bytes_zone(ATCA_ZONE_OTP, 0, 0, read_otp, sizeof(read_otp)); TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); - status = atcab_nonce(random_number); TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + atcab_read_config_zone(config_zone); - status = atcab_gendig(GENDIG_ZONE_DATA, key_id, dummy, sizeof(dummy)); + // Read serial number for host-side MAC calculations + status = atcab_read_serial_number(sn); TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + for (i = 0; i < sizeof(gendig_modes) / sizeof(gendig_modes[0]); i++) + { + // Setup nonce command + memset(&temp_key, 0, sizeof(temp_key)); + memset(num_in, 0, sizeof(num_in)); + memset(&nonce_params, 0, sizeof(nonce_params)); + nonce_params.mode = NONCE_MODE_SEED_UPDATE; + nonce_params.zero = 0; + nonce_params.num_in = num_in; + nonce_params.rand_out = rand_out; + nonce_params.temp_key = &temp_key; + + // Create random nonce + status = atcab_nonce_base(nonce_params.mode, nonce_params.zero, nonce_params.num_in, rand_out); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Calculate nonce + status = atcah_nonce(&nonce_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Use GenDig to create an initial digest across the internal key to be signed + memset(&gen_dig_params, 0, sizeof(gen_dig_params)); + gen_dig_params.zone = gendig_modes[i]; + gen_dig_params.key_id = gendig_modes_key[i]; + gen_dig_params.is_key_nomac = false; + gen_dig_params.stored_value = gendig_modes_data[i]; + gen_dig_params.sn = sn; + gen_dig_params.other_data = NULL; + gen_dig_params.temp_key = &temp_key; + status = atcab_gendig(gen_dig_params.zone, gen_dig_params.key_id, NULL, 0); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + status = atcah_gen_dig(&gen_dig_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Setup MAC command + memset(&mac_params, 0, sizeof(mac_params)); + mac_params.mode = MAC_MODE_BLOCK2_TEMPKEY | MAC_MODE_INCLUDE_SN; // Block 1 is a key, block 2 is TempKey + mac_params.key_id = 4; + mac_params.challenge = NULL; + mac_params.key = g_slot4_key; + mac_params.otp = NULL; + mac_params.sn = sn; + mac_params.response = host_response; + mac_params.temp_key = &temp_key; + + // Run MAC command + status = atcab_mac(mac_params.mode, mac_params.key_id, mac_params.challenge, client_response); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + + // Calculate expected MAC + status = atcah_mac(&mac_params); + TEST_ASSERT_EQUAL(ATCA_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(host_response, client_response, sizeof(host_response)); + } } // *INDENT-OFF* - Preserve formatting t_test_case_info gendig_basic_test_info[] = { - { REGISTER_TEST_CASE(atca_cmd_basic_test, gendig), DEVICE_MASK(ATSHA204A) | DEVICE_MASK(ATECC108A) | DEVICE_MASK(ATECC508A) | DEVICE_MASK(ATECC608A) }, - { (fp_test_case)NULL, (uint8_t)0 },/* Array Termination element*/ + { REGISTER_TEST_CASE(atca_cmd_basic_test, gendig_config_otp_data), DEVICE_MASK(ATSHA204A) | DEVICE_MASK(ATECC108A) | DEVICE_MASK(ATECC508A) | DEVICE_MASK(ATECC608A) }, + { REGISTER_TEST_CASE(atca_cmd_basic_test, gendig_counter), DEVICE_MASK(ATECC608A) }, + { REGISTER_TEST_CASE(atca_cmd_basic_test, gendig_keyconfig), DEVICE_MASK(ATECC608A) }, + { REGISTER_TEST_CASE(atca_cmd_basic_test, gendig_shared_nonce), DEVICE_MASK(ATECC508A) | DEVICE_MASK(ATECC608A) }, + { (fp_test_case)NULL, (uint8_t)0 }, /* Array Termination element*/ }; t_test_case_info gendig_unit_test_info[] = { { REGISTER_TEST_CASE(atca_cmd_unit_test, gendig), DEVICE_MASK(ATSHA204A) | DEVICE_MASK(ATECC108A) | DEVICE_MASK(ATECC508A) | DEVICE_MASK(ATECC608A) }, - { (fp_test_case)NULL, (uint8_t)0 },/* Array Termination element*/ + { (fp_test_case)NULL, (uint8_t)0 }, /* Array Termination element*/ }; // *INDENT-ON* diff --git a/test/cmd-processor.c b/test/cmd-processor.c index c0f819ff2..1ce07715a 100644 --- a/test/cmd-processor.c +++ b/test/cmd-processor.c @@ -81,6 +81,9 @@ static void set_clock_divider_m1(void); static void set_clock_divider_m2(void); static void tng22_tests(void); static void tngtn_tests(void); +#if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) +static void call_exit(int code); +#endif static const char* argv[] = { "manual", "-v" }; // *INDENT-OFF* - Preserve formatting @@ -118,6 +121,9 @@ static t_menu_info mas_menu_info[] = #ifndef DO_NOT_TEST_SW_CRYPTO { "crypto", "Run Unit Tests for Software Crypto Functions", (fp_menu_handler)atca_crypto_sw_tests}, #endif + #if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) + { "exit", "Exit the test application", call_exit }, + #endif { NULL, NULL, NULL }, }; // *INDENT-ON* @@ -126,11 +132,19 @@ static t_menu_info mas_menu_info[] = #include #include #include "cmd-processor.h" + +static int exit_code; + +static void call_exit(int code) +{ + exit_code = code; +} + int main(int argc, char* argv[]) { char buffer[1024]; - while (true) + while (!exit_code) { printf("$ "); if (fgets(buffer, sizeof(buffer), stdin)) @@ -139,7 +153,7 @@ int main(int argc, char* argv[]) } } - return 0; + return exit_code; } #else int processCmd(void)