/** \file * \brief simple command processor for test console * * \copyright (c) 2015-2020 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 "atca_test.h" // Undefine the Unity FAIL macro so it doesn't conflict with the ASF definition #undef FAIL #if !defined(_WIN32) && !defined(__linux__) && !defined(__XC32__) && !defined(__APPLE__) && !defined(ESP32) #ifdef ATMEL_START #include "atmel_start.h" #else #include #endif #endif #include #ifndef _WIN32 #include "cbuf.h" #endif #include "cryptoauthlib.h" #include "atca_test.h" #include "atca_crypto_sw_tests.h" #include "cmd-processor.h" #include "atca_cfgs.h" static ATCA_STATUS set_test_config(ATCADeviceType deviceType); static int certdata_unit_tests(void); static int certio_unit_tests(void); static ATCA_STATUS is_device_locked(uint8_t zone, bool *isLocked); static ATCA_STATUS lock_status(void); static ATCA_STATUS lock_config_zone(void); static ATCA_STATUS lock_data_zone(void); static ATCA_STATUS get_info(uint8_t *revision); static ATCA_STATUS get_serial_no(uint8_t *sernum); static ATCA_STATUS do_randoms(void); static void read_config(void); static void lock_config(void); static void lock_data(void); static void info(void); static void sernum(void); static void discover(void); static void select_device(ATCADeviceType device_type); static int run_test(void* fptest); static void select_204(void); static void select_206(void); static void select_108(void); static void select_508(void); static void select_608(void); static void run_basic_tests(void); static void run_unit_tests(void); static void run_otpzero_tests(void); static void run_helper_tests(void); static void help(void); static int parse_cmd(const char *command); static void run_all_tests(void); static ATCA_STATUS set_chip_mode(uint8_t i2c_user_extra_add, uint8_t ttl_enable, uint8_t watchdog, uint8_t clock_divider); static void set_clock_divider_m0(void); static void set_clock_divider_m1(void); static void set_clock_divider_m2(void); static void tngtls_tests(void); static void tnglora_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 static t_menu_info mas_menu_info[] = { { "help", "Display Menu", help }, { "discover", "Discover Buses and Devices", discover }, { "204", "Set Target Device to ATSHA204A", select_204 }, { "206", "Set Target Device to ATSHA206A", select_206 }, { "108", "Set Target Device to ATECC108A", select_108 }, { "508", "Set Target Device to ATECC508A", select_508 }, { "608", "Set Target Device to ATECC608A", select_608 }, { "info", "Get the Chip Revision", info }, { "sernum", "Get the Chip Serial Number", sernum }, { "rand", "Generate Some Random Numbers", (fp_menu_handler)do_randoms }, { "readcfg", "Read the Config Zone", read_config }, { "lockstat", "Zone Lock Status", (fp_menu_handler)lock_status }, { "lockcfg", "Lock the Config Zone", lock_config }, { "lockdata", "Lock Data and OTP Zones", lock_data }, { "all", "Run all unit tests, locking as needed.", run_all_tests }, { "tngtls", "Run unit tests on TNG TLS type part.", tngtls_tests }, { "tnglora", "Run unit tests on TNG LORA type part.", tnglora_tests }, #ifndef DO_NOT_TEST_BASIC_UNIT { "basic", "Run Basic Test on Selected Device", run_basic_tests }, { "unit", "Run Unit Test on Selected Device", run_unit_tests }, { "otpzero", "Zero Out OTP Zone", run_otpzero_tests }, { "util", "Run Helper Function Tests", run_helper_tests }, { "clkdivm0", "Set ATECC608A to ClockDivider M0(0x00)", set_clock_divider_m0 }, { "clkdivm1", "Set ATECC608A to ClockDivider M1(0x05)", set_clock_divider_m1 }, { "clkdivm2", "Set ATECC608A to ClockDivider M2(0x0D)", set_clock_divider_m2 }, #endif #ifndef DO_NOT_TEST_CERT { "cd", "Run Unit Tests on Cert Data", (fp_menu_handler)certdata_unit_tests }, { "cio", "Run Unit Test on Cert I/O", (fp_menu_handler)certio_unit_tests }, #endif #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* #if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) #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 (!exit_code) { printf("$ "); if (fgets(buffer, sizeof(buffer), stdin)) { parse_cmd(buffer); } } return exit_code; } #else int processCmd(void) { static char cmd[cmdQ_SIZE + 1]; uint16_t i = 0; while (!CBUF_IsEmpty(cmdQ) && i < sizeof(cmd)) { cmd[i++] = CBUF_Pop(cmdQ); } cmd[i] = '\0'; //printf("\r\n%s\r\n", command ); parse_cmd(cmd); printf("$ "); return ATCA_SUCCESS; } #endif static int parse_cmd(const char *command) { uint8_t index = 0; printf("\r\n"); if (command[0] == '\0' || command[0] == '\n') { return ATCA_SUCCESS; } while (mas_menu_info[index].menu_cmd != NULL) { if (strstr(command, mas_menu_info[index].menu_cmd)) { if (mas_menu_info[index].fp_handler) { mas_menu_info[index].fp_handler(); } break; } index++; } if (mas_menu_info[index].menu_cmd == NULL) { printf("syntax error in command: %s", command); } printf("\r\n"); return ATCA_SUCCESS; } static void help(void) { uint8_t index = 0; printf("Usage:\r\n"); while (mas_menu_info[index].menu_cmd != NULL) { printf("%s - %s\r\n", mas_menu_info[index].menu_cmd, mas_menu_info[index].menu_cmd_description); index++; } } static void select_204(void) { select_device(ATSHA204A); } static void select_206(void) { select_device(ATSHA206A); } static void select_108(void) { select_device(ATECC108A); } static void select_508(void) { select_device(ATECC508A); } static void select_608(void) { select_device(ATECC608A); } static void update_chip_mode(uint8_t* chip_mode, uint8_t i2c_user_extra_add, uint8_t ttl_enable, uint8_t watchdog, uint8_t clock_divider) { if (i2c_user_extra_add != 0xFF) { *chip_mode &= ~ATCA_CHIPMODE_I2C_ADDRESS_FLAG; *chip_mode |= i2c_user_extra_add & ATCA_CHIPMODE_I2C_ADDRESS_FLAG; } if (ttl_enable != 0xFF) { *chip_mode &= ~ATCA_CHIPMODE_TTL_ENABLE_FLAG; *chip_mode |= ttl_enable & ATCA_CHIPMODE_TTL_ENABLE_FLAG; } if (watchdog != 0xFF) { *chip_mode &= ~ATCA_CHIPMODE_WATCHDOG_MASK; *chip_mode |= watchdog & ATCA_CHIPMODE_WATCHDOG_MASK; } if (clock_divider != 0xFF) { *chip_mode &= ~ATCA_CHIPMODE_CLOCK_DIV_MASK; *chip_mode |= clock_divider & ATCA_CHIPMODE_CLOCK_DIV_MASK; } } static ATCA_STATUS check_clock_divider(void) { ATCA_STATUS status; uint8_t chip_mode = 0; if (gCfg->devtype != ATECC608A) { printf("Current device doesn't support clock divider settings (only ATECC608A)\r\n"); return ATCA_GEN_FAIL; } // Update the actual ATECC608A chip mode so it takes effect immediately status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed with ret=0x%08X\r\n", status); return status; } do { // Read current config values status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, ATCA_CHIPMODE_OFFSET, &chip_mode, 1); if (status != ATCA_SUCCESS) { printf("atcab_read_bytes_zone() failed with ret=0x%08X\r\n", status); break; } // Update the ATECC608A test config data so all the unit tests will run with the new chip mode update_chip_mode(&test_ecc608_configdata[ATCA_CHIPMODE_OFFSET], 0xFF, 0xFF, chip_mode & ATCA_CHIPMODE_WATCHDOG_MASK, chip_mode & ATCA_CHIPMODE_CLOCK_DIV_MASK); } while (0); atcab_release(); return status; } static void run_basic_tests(void) { if (gCfg->devtype == ATECC608A) { check_clock_divider(); } run_test(RunAllBasicTests); } static void run_unit_tests(void) { if (gCfg->devtype == ATECC608A) { check_clock_divider(); } run_test(RunAllFeatureTests); } static void run_otpzero_tests(void) { run_test(RunBasicOtpZero); } static void run_helper_tests(void) { run_test(RunAllHelperTests); } static void read_config(void) { ATCA_STATUS status; uint8_t config[ATCA_ECC_CONFIG_SIZE]; size_t config_size = 0; size_t i = 0; status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed: %02x\r\n", status); return; } do { status = atcab_get_zone_size(ATCA_ZONE_CONFIG, 0, &config_size); if (status != ATCA_SUCCESS) { printf("atcab_get_zone_size() failed: %02x\r\n", status); break; } status = atcab_read_config_zone(config); if (status != ATCA_SUCCESS) { printf("atcab_read_config_zone() failed: %02x\r\n", status); break; } for (i = 0; i < config_size; i++) { if (i % 16 == 0) { printf("\r\n"); } else if (i % 8 == 0) { printf(" "); } else { printf(" "); } printf("%02X", (int)config[i]); } printf("\r\n"); } while (0); atcab_release(); } static ATCA_STATUS lock_status(void) { ATCA_STATUS status; bool is_locked = false; if ((status = is_device_locked(LOCK_ZONE_CONFIG, &is_locked)) != ATCA_SUCCESS) { printf("is_device_locked() failed with ret=0x%08X\r\n", status); return status; } printf("Config Zone: %s\r\n", is_locked ? "LOCKED" : "unlocked"); if ((status = is_device_locked(LOCK_ZONE_DATA, &is_locked)) != ATCA_SUCCESS) { printf("is_device_locked() failed with ret=0x%08X\r\n", status); return status; } printf("Data Zone : %s\r\n", is_locked ? "LOCKED" : "unlocked"); return status; } static void lock_config(void) { lock_config_zone(); lock_status(); } static void lock_data(void) { lock_data_zone(); lock_status(); } static ATCA_STATUS do_randoms(void) { ATCA_STATUS status; uint8_t randout[RANDOM_RSP_SIZE]; char displayStr[RANDOM_RSP_SIZE * 3]; size_t displen = sizeof(displayStr); int i; if (gCfg->devtype == ATSHA206A) { printf("ATSHA206A doesn't support random command\r\n"); return ATCA_GEN_FAIL; } status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed with ret=0x%08X\r\n", status); return status; } printf("Random Numbers:\r\n"); for (i = 0; i < 5; i++) { if ((status = atcab_random(randout)) != ATCA_SUCCESS) { break; } displen = sizeof(displayStr); atcab_bin2hex(randout, 32, displayStr, &displen); printf("%s\r\n", displayStr); } if (status != ATCA_SUCCESS) { printf("atcab_random() failed with ret=0x%08X\r\n", status); } atcab_release(); return status; } static void discover(void) { ATCAIfaceCfg ifaceCfgs[10]; int i; const char *devname[] = { "ATSHA204A", "ATECC108A", "ATECC508A", "ATECC608A", "ATSHA206A" }; // indexed by ATCADeviceType for (i = 0; i < (int)(sizeof(ifaceCfgs) / sizeof(ATCAIfaceCfg)); i++) { ifaceCfgs[i].devtype = ATCA_DEV_UNKNOWN; ifaceCfgs[i].iface_type = ATCA_UNKNOWN_IFACE; } printf("Searching...\r\n"); atcab_cfg_discover(ifaceCfgs, sizeof(ifaceCfgs) / sizeof(ATCAIfaceCfg)); for (i = 0; i < (int)(sizeof(ifaceCfgs) / sizeof(ATCAIfaceCfg)); i++) { if (ifaceCfgs[i].devtype != ATCA_DEV_UNKNOWN) { printf("Found %s ", devname[ifaceCfgs[i].devtype]); if (ifaceCfgs[i].iface_type == ATCA_I2C_IFACE) { printf("@ bus %d addr %02x", ifaceCfgs[i].atcai2c.bus, ifaceCfgs[i].atcai2c.slave_address); } if (ifaceCfgs[i].iface_type == ATCA_SWI_IFACE) { printf("@ bus %d", ifaceCfgs[i].atcaswi.bus); } printf("\r\n"); } } } static void info(void) { ATCA_STATUS status; uint8_t revision[4]; char displaystr[15]; size_t displaylen = sizeof(displaystr); status = get_info(revision); if (status == ATCA_SUCCESS) { // dump revision atcab_bin2hex(revision, 4, displaystr, &displaylen); printf("revision:\r\n%s\r\n", displaystr); } } static void sernum(void) { ATCA_STATUS status; uint8_t serialnum[ATCA_SERIAL_NUM_SIZE]; char displaystr[30]; size_t displaylen = sizeof(displaystr); status = get_serial_no(serialnum); if (status == ATCA_SUCCESS) { // dump serial num atcab_bin2hex(serialnum, ATCA_SERIAL_NUM_SIZE, displaystr, &displaylen); printf("serial number:\r\n%s\r\n", displaystr); } } void RunAllCertDataTests(void); static int certdata_unit_tests(void) { UnityMain(sizeof(argv) / sizeof(char*), argv, RunAllCertDataTests); return ATCA_SUCCESS; } void RunAllCertIOTests(void); static int certio_unit_tests(void) { UnityMain(sizeof(argv) / sizeof(char*), argv, RunAllCertIOTests); return ATCA_SUCCESS; } static ATCA_STATUS is_device_locked(uint8_t zone, bool *isLocked) { ATCA_STATUS status; status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { return status; } status = atcab_is_locked(zone, isLocked); atcab_release(); return status; } static ATCA_STATUS lock_config_zone(void) { ATCA_STATUS status; uint8_t ch = 0; if (gCfg->devtype == ATSHA206A) { printf("ATSHA206A doesn't support lock command\r\n"); return ATCA_GEN_FAIL; } printf("Locking with test configuration, which is suitable only for unit tests... \r\nConfirm by typing Y\r\n"); do { scanf("%c", &ch); } while (ch == '\n' || ch == '\r'); if (!((ch == 'Y') || (ch == 'y'))) { printf("Skipping Config Lock on request.\r\n"); return ATCA_GEN_FAIL; } status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed with ret=0x%08X\r\n", status); return status; } status = atcab_lock_config_zone(); atcab_release(); if (status != ATCA_SUCCESS) { printf("atcab_lock_config_zone() failed with ret=0x%08X\r\n", status); } return status; } static ATCA_STATUS lock_data_zone(void) { ATCA_STATUS status; uint8_t ch = 0; printf("Locking Data zone... \r\nConfirm by typing Y\r\n"); do { scanf("%c", &ch); } while (ch == '\n' || ch == '\r'); if (!((ch == 'Y') || (ch == 'y'))) { printf("Skipping Data Zone Lock on request.\r\n"); return ATCA_GEN_FAIL; } if (gCfg->devtype == ATSHA206A) { printf("ATSHA206A doesn't support lock command\r\n"); return ATCA_GEN_FAIL; } status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed with ret=0x%08X\r\n", status); return status; } status = atcab_lock_data_zone(); atcab_release(); if (status != ATCA_SUCCESS) { printf("atcab_lock_data_zone() failed with ret=0x%08X\r\n", status); } return status; } static ATCA_STATUS get_info(uint8_t *revision) { ATCA_STATUS status; status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed with ret=0x%08X\r\n", status); return status; } status = atcab_info(revision); atcab_release(); if (status != ATCA_SUCCESS) { printf("atcab_info() failed with ret=0x%08X\r\n", status); } return status; } static ATCA_STATUS get_serial_no(uint8_t *sernum) { ATCA_STATUS status; status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed with ret=0x%08X\r\n", status); return status; } status = atcab_read_serial_number(sernum); atcab_release(); if (status != ATCA_SUCCESS) { printf("atcab_read_serial_number() failed with ret=0x%08X\r\n", status); } return status; } static void select_device(ATCADeviceType device_type) { ATCA_STATUS status; status = set_test_config(device_type); if (status == ATCA_SUCCESS) { printf("Device Selected.\r\n"); } else { printf("IFace Cfg are NOT available\r\n"); } } static int run_test(void* fptest) { if (gCfg->devtype < ATCA_DEV_UNKNOWN) { return UnityMain(sizeof(argv) / sizeof(char*), argv, fptest); } else { printf("Device is NOT Selected... Select device before running tests!!!"); return -1; } } static void run_all_tests(void) { ATCA_STATUS status; bool is_config_locked = false; bool is_data_locked = false; int fails = 0; if (gCfg->devtype == ATECC608A) { check_clock_divider(); } info(); sernum(); do_randoms(); status = is_device_locked(LOCK_ZONE_CONFIG, &is_config_locked); if (status != ATCA_SUCCESS) { printf("is_device_locked() failed with ret=0x%08X\r\n", status); return; } status = is_device_locked(LOCK_ZONE_DATA, &is_data_locked); if (status != ATCA_SUCCESS) { printf("is_device_locked() failed with ret=0x%08X\r\n", status); return; } status = lock_status(); if (status != ATCA_SUCCESS) { printf("lock_status() failed with ret=0x%08X\r\n", status); return; } #ifndef DO_NOT_TEST_BASIC_UNIT if (!is_config_locked) { fails += run_test(RunAllFeatureTests); if (fails > 0) { printf("unit tests with config zone unlocked failed.\r\n"); return; } fails += run_test(RunAllBasicTests); if (fails > 0) { printf("basic tests with config zone unlocked failed.\r\n"); return; } status = lock_config_zone(); if (status != ATCA_SUCCESS) { printf("lock_config_zone() failed with ret=0x%08X\r\n", status); return; } status = lock_status(); if (status != ATCA_SUCCESS) { printf("lock_status() failed with ret=0x%08X\r\n", status); return; } } if (!is_data_locked) { fails += run_test(RunAllFeatureTests); if (fails > 0) { printf("unit tests with data zone unlocked failed.\r\n"); return; } fails += run_test(RunAllBasicTests); if (fails > 0) { printf("basic tests with data zone unlocked failed.\r\n"); return; } status = lock_data_zone(); if (status != ATCA_SUCCESS) { printf("lock_data_zone() failed with ret=0x%08X\r\n", status); return; } status = lock_status(); if (status != ATCA_SUCCESS) { printf("lock_status() failed with ret=0x%08X\r\n", status); return; } } fails += run_test(RunAllFeatureTests); if (fails > 0) { printf("unit tests with data zone locked failed.\r\n"); return; } fails += run_test(RunAllBasicTests); if (fails > 0) { printf("basic tests with data zone locked failed.\r\n"); return; } fails = run_test(RunAllHelperTests); if (fails > 0) { printf("util tests failed.\r\n"); return; } #endif #ifndef DO_NOT_TEST_SW_CRYPTO fails += atca_crypto_sw_tests(); if (fails > 0) { printf("crypto tests failed.\r\n"); return; } #endif #ifndef DO_NOT_TEST_CERT if (atIsECCFamily(gCfg->devtype)) { fails += run_test(RunAllCertIOTests); if (fails > 0) { printf("cio tests failed.\r\n"); return; } } else { printf("cio tests don't apply to non-ECC devices.\r\n"); } fails += run_test(RunAllCertDataTests); if (fails > 0) { printf("cd tests failed.\r\n"); return; } #endif printf("All unit tests passed.\r\n"); } static ATCA_STATUS set_test_config(ATCADeviceType deviceType) { gCfg->devtype = ATCA_DEV_UNKNOWN; gCfg->iface_type = ATCA_UNKNOWN_IFACE; switch (deviceType) { case ATSHA204A: #if defined(ATCA_HAL_I2C) *gCfg = cfg_atsha20xa_i2c_default; #elif defined(ATCA_HAL_SWI) *gCfg = cfg_atsha20xa_swi_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_HID) *gCfg = cfg_atsha20xa_kithid_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_CDC) *gCfg = cfg_atsha20xa_kitcdc_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_CUSTOM) *gCfg = g_cfg_atsha204a_custom; #else #error "HAL interface is not selected"; #endif break; case ATSHA206A: #if defined(ATCA_HAL_I2C) *gCfg = cfg_atsha20xa_i2c_default; #elif defined(ATCA_HAL_SWI) *gCfg = cfg_atsha20xa_swi_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_HID) *gCfg = cfg_atsha20xa_kithid_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_CDC) *gCfg = cfg_atsha20xa_kitcdc_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_CUSTOM) *gCfg = g_cfg_atsha206a_custom; #else #error "HAL interface is not selected"; #endif break; case ATECC108A: #if defined(ATCA_HAL_I2C) *gCfg = cfg_ateccx08a_i2c_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_SWI) *gCfg = cfg_ateccx08a_swi_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_HID) *gCfg = cfg_ateccx08a_kithid_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_CDC) *gCfg = cfg_ateccx08a_kitcdc_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_CUSTOM) *gCfg = g_cfg_atecc108a_custom; #else #error "HAL interface is not selected"; #endif break; case ATECC508A: #if defined(ATCA_HAL_I2C) *gCfg = cfg_ateccx08a_i2c_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_SWI) *gCfg = cfg_ateccx08a_swi_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_HID) *gCfg = cfg_ateccx08a_kithid_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_CDC) *gCfg = cfg_ateccx08a_kitcdc_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_CUSTOM) *gCfg = g_cfg_atecc508a_custom; #else #error "HAL interface is not selected"; #endif break; case ATECC608A: #if defined(ATCA_HAL_I2C) *gCfg = cfg_ateccx08a_i2c_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_SWI) *gCfg = cfg_ateccx08a_swi_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_HID) *gCfg = cfg_ateccx08a_kithid_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_KIT_CDC) *gCfg = cfg_ateccx08a_kitcdc_default; gCfg->devtype = deviceType; #elif defined(ATCA_HAL_CUSTOM) *gCfg = g_cfg_atecc608a_custom; #else #error "HAL interface is not selected"; #endif break; default: //device type wasn't found, return with error return ATCA_GEN_FAIL; } #ifdef ATCA_RASPBERRY_PI_3 gCfg->atcai2c.bus = 1; #endif return ATCA_SUCCESS; } static ATCA_STATUS set_chip_mode(uint8_t i2c_user_extra_add, uint8_t ttl_enable, uint8_t watchdog, uint8_t clock_divider) { ATCA_STATUS status; uint8_t config_word[ATCA_WORD_SIZE]; bool is_config_locked = false; if (gCfg->devtype != ATECC608A) { printf("Current device doesn't support clock divider settings (only ATECC608A)\r\n"); return ATCA_GEN_FAIL; } status = is_device_locked(LOCK_ZONE_CONFIG, &is_config_locked); if (status != ATCA_SUCCESS) { printf("is_device_locked() failed with ret=0x%08X\r\n", status); return status; } if (is_config_locked) { printf("Current device is config locked. Can't change clock divider. "); } // Update the actual ATECC608A chip mode so it takes effect immediately status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed with ret=0x%08X\r\n", status); return status; } do { // Read current config values status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, 16, config_word, 4); if (status != ATCA_SUCCESS) { printf("atcab_read_bytes_zone() failed with ret=0x%08X\r\n", status); break; } if (is_config_locked) { printf("Currently set to 0x%02X.\r\n", (int)(config_word[3] >> 3)); status = ATCA_GEN_FAIL; break; } // Update ChipMode update_chip_mode(&config_word[3], i2c_user_extra_add, ttl_enable, watchdog, clock_divider); // Write config values back to chip status = atcab_write_bytes_zone(ATCA_ZONE_CONFIG, 0, 16, config_word, 4); if (status != ATCA_SUCCESS) { printf("atcab_write_bytes_zone() failed with ret=0x%08X\r\n", status); break; } // Put to sleep so new values take effect status = atcab_wakeup(); if (status != ATCA_SUCCESS) { printf("atcab_wakeup() failed with ret=0x%08X\r\n", status); break; } status = atcab_sleep(); if (status != ATCA_SUCCESS) { printf("atcab_sleep() failed with ret=0x%08X\r\n", status); break; } // Update the ATECC608A test config data so all the unit tests will run with the new chip mode update_chip_mode(&test_ecc608_configdata[ATCA_CHIPMODE_OFFSET], i2c_user_extra_add, ttl_enable, watchdog, clock_divider); } while (0); atcab_release(); return status; } static void set_clock_divider_m0(void) { ATCA_STATUS status = set_chip_mode(0xFF, 0xFF, ATCA_CHIPMODE_WATCHDOG_SHORT, ATCA_CHIPMODE_CLOCK_DIV_M0); if (status == ATCA_SUCCESS) { printf("Set device to clock divider M0 (0x%02X) and watchdog to 1.3s nominal.\r\n", ATCA_CHIPMODE_CLOCK_DIV_M0 >> 3); } } static void set_clock_divider_m1(void) { ATCA_STATUS status = set_chip_mode(0xFF, 0xFF, ATCA_CHIPMODE_WATCHDOG_SHORT, ATCA_CHIPMODE_CLOCK_DIV_M1); if (status == ATCA_SUCCESS) { printf("Set device to clock divider M1 (0x%02X) and watchdog to 1.3s nominal.\r\n", ATCA_CHIPMODE_CLOCK_DIV_M1 >> 3); } } static void set_clock_divider_m2(void) { // Additionally set watchdog to long settings (~13s) as some commands // can't complete in time on the faster watchdog setting. ATCA_STATUS status = set_chip_mode(0xFF, 0xFF, ATCA_CHIPMODE_WATCHDOG_LONG, ATCA_CHIPMODE_CLOCK_DIV_M2); if (status == ATCA_SUCCESS) { printf("Set device to clock divider M2 (0x%02X) and watchdog to 13s nominal.\r\n", ATCA_CHIPMODE_CLOCK_DIV_M2 >> 3); } } static void tngtls_tests(void) { ATCA_STATUS status; status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed with ret=0x%08X\r\n", status); return; } run_test(RunTNGTLSTests); atcab_release(); } static void tnglora_tests(void) { ATCA_STATUS status; status = atcab_init(gCfg); if (status != ATCA_SUCCESS) { printf("atcab_init() failed with ret=0x%08X\r\n", status); return; } run_test(RunTNGLORATests); atcab_release(); }