diff --git a/pkg/cryptoauthlib/include/atecc608a_config.h b/pkg/cryptoauthlib/include/atecc608a_config.h new file mode 100644 index 0000000000..be77d7b6e7 --- /dev/null +++ b/pkg/cryptoauthlib/include/atecc608a_config.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2024 HAW Hamburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @file + * @brief Example configuration for Microchip CryptoAuth devices + * + * This is an example configuration for an ATECC608A device with + * some explanation on what the bits mean (for more details + * see complete datasheet). + * + * @note This configuration works with the example/psa_crypto application. + * + * @warning Parts of this config are insecure (e.g. some key slots can be + * written to repeatedly), so it should only be used for + * testing and development. If you want to use your device for + * production, please refer to the datasheet and change the bits + * accordingly. + * + * @author Lena Boeckmann + * + */ + +#ifndef ATECC608A_CONFIG_H +#define ATECC608A_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * @brief Example device configuration for the atecc608a. + * + */ +const uint8_t atecc608a_config[] = { + 0x00, 0x00, 0x00, 0x00, /* Read only serial number */ + 0x00, 0x00, 0x00, 0x00, /* Read only revision number */ + 0x00, 0x00, 0x00, 0x00, /* Read only serial number */ + 0x00, 0x00, 0x00, 0x00, /* Read only reserved, I2C enable, reserved */ + 0xC0, 0x00, 0x00, 0x00, /* I2C address, reserved, CountMatch, chip mode*/ + + /* Private keys: + 0x8720 = 1 0 0 0 | 0 1 1 1 | 0 0 1 0 | 0 0 0 0 + 7 - 4 | 3 - 0 | 15 - 12 | 11 - 8 + - External signatures of arbitrary messages enabled + - Internal signatures of messages by GenDig/GenKey enabled + - ECDH operations permitted + - ECDH Master Secret will be output in the clear + - No write by write command */ + 0x87, 0x20, 0x87, 0x20, /* Slot 0, Slot 1 */ + 0x87, 0x20, 0x87, 0x20, /* Slot 2, Slot 3 */ + + /* Private Keys, write always allowed (use only for testing!!!)*/ + 0x87, 0x00, 0x87, 0x00, + + /* Private key: + - as above but + - ECDH Master Secret will be written into slot n + 1 (7)*/ + 0x8F, 0x20, 0x87, 0x20, /* Slot 6, Slot 7 */ + + /* Data storage and public keys, anything goes */ + 0x00, 0x00, 0x00, 0x00, /* Slot 8, Slot 9 */ + 0x00, 0x00, 0x00, 0x00, /* Slot 10, Slot 11 */ + 0x00, 0x00, 0x00, 0x00, /* Slot 12, Slot 13 */ + 0x00, 0x00, 0x00, 0x00, /* Slot 14, Slot 15 */ + + 0xFF, 0xFF, 0xFF, 0xFF, /* Counter 0 */ + 0x00, 0x00, 0x00, 0x00, /* Counter 0 */ + 0xFF, 0xFF, 0xFF, 0xFF, /* Counter 1 */ + 0x00, 0x00, 0x00, 0x00, /* Counter 1 */ + 0x00, 0x00, 0x00, 0x00, /* UseLock, VolatileKeyPermission, Secure Boot */ + 0x00, 0x00, 0x00, 0x00, /* KdflvLoc, KdflvStr, KdflcStr, Reserved */ + 0x00, 0x00, 0x00, 0x00, /* Reserved */ + 0x00, 0x00, 0x00, 0x00, /* Reserved */ + 0x00, 0x00, 0x55, 0x55, /* UserExtra, UserExtraAdd, LockValue, LockConfig */ + 0xFF, 0xFF, 0x00, 0x00, /* 2x SlotLocked, 2x ChipOptions */ + 0x00, 0x00, 0x00, 0x00, /* X509format */ + + /* Private Key, access only with Sign, GenKey, PrivWrite cmds + Public Version can always be generated + Slots are individually lockable with Lock command */ + 0x13, 0x00, 0x13, 0x00, /* KeyConfig 0, KeyConfig 1 */ + 0x13, 0x00, 0x13, 0x00, /* KeyConfig 2, KeyConfig 3 */ + + /* AES Key */ + 0x18, 0x00, 0x18, 0x00, /* KeyConfig 4, KeyConfig 5 -> not usable as AES keys! */ + + /* Private Key + - Used for ECDH + - Slot 7 will contain corresponding Master Secret */ + 0x13, 0x00, 0x1F, 0x00, /* KeyConfig 6, KeyConfig 7 */ + + /* SHA Key or other data */ + 0x1C, 0x00, /* KeyConfig 8 */ + + /* ECC Public Keys */ + 0x10, 0x00, /* KeyConfig 9 */ + 0x10, 0x00, 0x10, 0x00, /* KeyConfig 10, KeyConfig 11 */ + 0x10, 0x00, 0x10, 0x00, /* KeyConfig 12, KeyConfig 13 */ + + /* SHA Key or other data */ + 0x1C, 0x00, 0x1C, 0x00 /* KeyConfig 14, KeyConfig 15 */ +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ATECC608A_CONFIG_H */ diff --git a/sys/shell/cmds/cryptoauthlib.c b/sys/shell/cmds/cryptoauthlib.c index 4b03fddeb6..05362cf6a5 100644 --- a/sys/shell/cmds/cryptoauthlib.c +++ b/sys/shell/cmds/cryptoauthlib.c @@ -13,16 +13,70 @@ * @file * @brief Shell commands for the cryptoauthlib module * + * Currently supported devices: + * - ATECC508A + * - ATECC608 + * + * This relies on a config header file being present in + * pkg/cryptoauthlib/include. + * The present example configuration can be exchanged or + * modified if needed. + * * @author Lena Boeckmann * * @} */ #include +#include #include +#include "atca.h" +#include "atca_params.h" #include "cryptoauthlib.h" #include "shell.h" +#include "atecc608a_config.h" + +#define ATCA_KEY_SLOT_COUNT (16) +#define ATCA_X509_KEY_COUNT (4) + +#define SERIAL_NO_START_01 (0) +#define REVISION_NO_START (4) +#define SERIAL_NO_START_02 (8) +#define AES_ENABLE (13) +#define I2C_ENABLE (14) +#define I2C_ADDRESS (16) +#define COUNT_MATCH (18) +#define OTP_MODE (18) +#define CHIP_MODE (19) +#define SLOT_CONFIG_START (20) +#define COUNTER_01_START (52) +#define COUNTER_02_START (60) +#define LAST_KEY_USE_START (68) +#define USE_LOCK (68) +#define VOLATILE_KEY_PERMIT (69) +#define SECURE_BOOT_START (70) +#define KDF_IV_LOC (72) +#define USER_EXTRA (84) +#define USER_EXTRA_ADD (85) +#define SELECTOR (85) +#define LOCK_VALUE (86) +#define LOCK_CONFIG (87) +#define SLOT_LOCKED_START (88) +#define CHIP_OPTIONS_START (90) +#define X509_FORMAT_START (92) +#define KEY_CONFIG_START (96) + +uint8_t config_backup[ATCA_NUMOF][ATCA_ECC_CONFIG_SIZE]; + +int device_index = 0; + +/** + * @brief Convert one byte into a binary number + * + * @param[out] result Will contain binary number as a string + * @param[in] byte Byte to convert + */ void get_bin(char *result, uint8_t byte) { for (int i = 0; i < 8; i++) { @@ -31,22 +85,529 @@ void get_bin(char *result, uint8_t byte) result[8] = '\0'; } -static int _read_config(void) +/** + * @brief Converts an ATCA device type into a string + * + * @param devtype ATCADeviceType + * @return char* Device type as string + */ +static char* _convert_atca_devtype(ATCADeviceType devtype) +{ + switch(devtype) { + case ATECC508A: + return "ATECC508A"; + case ATECC608: + return "ATECC608"; + default: + return "Unsupported device"; + } +} + +/** + * @brief Print read-only section of the configuration zone. + * + * Reserved bytes that don't mean anything are omitted. + * + * @param[in] data Pointer to buffer with input data + * @param devtype Type of the device currently used + */ +static void _print_dev_info_ro(uint8_t* data, ATCADeviceType devtype) +{ + printf("Serial No (Pt. 1) | "); + for (int i = 0; i < 4; i++) { + printf("0x%02x ", data[SERIAL_NO_START_01+i]); + } + puts(""); + + printf("Revision No. | "); + for (int i = 0; i < 4; i++) { + printf("0x%02x ", data[REVISION_NO_START+i]); + } + puts(""); + + printf("Serial No (Pt. 2) | "); + for (int i = 0; i < 5; i++) { + printf("0x%02x ", data[SERIAL_NO_START_02+i]); + } + puts(""); + + if (devtype == ATECC608) { + if (data[AES_ENABLE] & 0x01) { + printf("AES Enabled | True\n"); + } + else { + printf("AES Enabled | False\n"); + } + } + + if (data[I2C_ENABLE] & 0x01) { + printf("I2C Enabled | True\n"); + printf("Single Wire | False\n"); + } + else { + printf("I2C Enabled | False\n"); + printf("Single Wire | True\n"); + } +} + +/** + * @brief Get authorization mode + * + * @param data Byte of data to interpret + * @return char* Data interpretation as string + */ +static char* _get_authorization_mode(uint8_t data) +{ + uint8_t auth_mode = data & 0x08; + return auth_mode ? "Authorization Output Mode" : "Intrustion Detection Mode"; +} + +/** + * @brief Prints the I2C address when I2C is enabled or the + * GPIO mode when Single Wire communication is enabled + * + * @param data Byte of data to interpret + * @param communications Device communications mode (0 = Single Wire, 1 = I2C) + */ +static void _print_i2c_addr_or_gpio_mode(uint8_t data, uint8_t communications) +{ + if (communications) { + /* I2C enabled */ + printf("I2C Address | 0x%02x\n", data); + } + else { + /* Single Wire enabled */ + uint8_t gpio_mode = data & 0x03; + printf("GPIO Mode | "); + switch(gpio_mode) { + case 0x01: + printf("%s\n", _get_authorization_mode(data)); + break; + case 0x10: + puts("Input"); + break; + case 0x11: + puts("Output"); + break; + default: + puts("Disabled"); + } + uint8_t gpio_default = data & 0x04; + if (gpio_default) { + puts("GPIO Default | high"); + } + else { + puts("GPIO Default | low"); + } + if (gpio_mode) { + if (gpio_mode == 0x01) { + printf("SignalKey for authorization has ID %d\n", data & 0xF0); + } + else { + printf("SignalKey/KeyID is non-zero and invalid: 0x%02x\n", data & 0xF0); + } + } + } +} + +/** + * @brief Prints the OTP mode or CountMatch, depending on device type. + * + * @param data Byte of data to interpret + */ +static void _print_countmatch_or_otp_mode(uint8_t data, ATCADeviceType devtype) +{ + if (devtype == ATECC608) { + if (data & 0x01) { + puts("Counter Match | Enabled"); + printf("CountMatchKey stored in slot %d\n", data & 0xF0); + } + else { + puts("Counter Match | Disabled"); + } + } + else { + switch(data) { + case 0xAA: + printf("OTP Mode | Read-only\n"); + break; + case 0x55: + printf("OTP Mode | Consumption\n"); + break; + default: + printf("OTP Mode | None\n"); + } + } +} + +/** + * @brief Prints the chip mode + * + * @param data Byte of data to interpret + */ +static void _print_chip_mode(uint8_t data, ATCADeviceType devtype) +{ + puts("ChipMode:"); + if (devtype == ATECC608) { + if (data & 0x01) { + puts("I2C Address | I2C address was set by user and is stored in UserExtraAdd"); + } + else { + puts("I2C Address | Default address"); + } + } + else { + if (data & 0x01) { + puts("SelectorMode | Only writeable if zero"); + } + else { + puts("SelectorMode | Always writeable"); + } + } + + if (data & 0x02) { + puts("TTLenable | Input levels VCC referenced"); + } + else { + puts("TTLenable | Fixed input levels"); + } + + if (data & 0x04) { + puts("Watchdog | 10 sec (not recommended)"); + } + else { + puts("Watchdog | 1.3 sec (recommended)"); + } + + if (devtype == ATECC608) { + printf("Clock Divider | 0x%02x\n", data & 0xF0); + } +} + +/** + * @brief Print Key Slot Configurations in hexadecimal and binary format + * + * @param[in] data Pointer to buffer with input data + */ +static void _print_slot_config(uint8_t* data) +{ + char binary[9]; + + puts("Slot Config"); + puts("----------------------------------------"); + puts("SlotID | Hex | Binary"); + puts(" | | 7 0 | 15 8"); + puts("--------+--------+----------------------"); + int slotcount = 0; + for (size_t i = 0; i < ATCA_KEY_SLOT_COUNT*2; i += 2) { + if (slotcount < 10) { + printf("%d | 0x%02x%02x | ", slotcount, data[SLOT_CONFIG_START+i], data[SLOT_CONFIG_START+i+1]); + } + else { + printf("%d | 0x%02x%02x | ", slotcount, data[SLOT_CONFIG_START+i], data[SLOT_CONFIG_START+i+1]); + } + for (int j = 0; j < 2; j++) { + get_bin(binary, data[i]); + printf("%s | ", binary); + } + puts(""); + slotcount++; + } + puts(""); +} + +/** + * @brief Print lock status of key slots + * + * @param[in] data Pointer to buffer with input data + */ +static void _print_slot_lock(uint8_t* data) +{ + puts("\nSlotLocked (X = locked, - = unlocked):"); + puts("Slot | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"); + printf("Locked | "); + for (int j = 0; j < 2; j++) { + for (int i = 0; i < 8; i++) { + if ((data[SLOT_LOCKED_START+j] >> i) & 0x01) { + printf(" - "); + } + else { + printf(" X "); + } + } + } + puts(""); +} + +static void _print_chip_options(uint8_t* data) +{ + puts("Chip Options:"); + if (data[CHIP_OPTIONS_START] & 0x01) { + puts("Power On Self Test| Enabled"); + } + else { + puts("Power On Self Test| Disabled"); + } + + if (data[CHIP_OPTIONS_START] & 0x02) { + puts("IO Prot Key | Enabled"); + } + else { + puts("IO Prot Key | Disabled"); + } + + if (data[CHIP_OPTIONS_START] & 0x04) { + puts("AES KDF | Enabled"); + } + else { + puts("AES KDF | Disabled"); + } + + uint8_t ecdh_prot = data[CHIP_OPTIONS_START+1] & 0x03; + switch(ecdh_prot) { + case 0x00: + puts("ECDH | Clear Output on Bus OK"); + break; + case 0x01: + puts("ECDH | Encrypted Output on Bus OK"); + break; + case 0x10: + puts("ECDH | Result stored in TempKey or EEPROM Key Slot"); + break; + default: + puts("ECDH | Usage Not permitted"); + } + + uint8_t kdf_prot = data[CHIP_OPTIONS_START+1] & 0x0C; + switch(kdf_prot) { + case 0x00: + puts("KDF | Clear Output on Bus OK"); + break; + case 0x01: + puts("KDF | Encrypted Output on Bus OK"); + break; + case 0x10: + puts("KDF | Result stored in TempKey or EEPROM Key Slot"); + break; + default: + puts("KDF | Usage Not permitted"); + } + + printf("IO Protection Key stored in slot %d\n", data[CHIP_OPTIONS_START+1] & 0xF0); +} + +/** + * @brief Print X509 format restrictions + * + * @param[in] data Pointer to buffer with input data + */ +static void _print_x509_format(uint8_t* data) +{ + puts("\nX509 Format:"); + for (int i = 0; i < 4; i++) { + if (data[X509_FORMAT_START+i] == 0x00) { + printf("PubKey %d | No restrictions\n", i); + } + else { + printf("PubKey %d:\n", i); + printf("- PublicPosition | 0x%02x\n", data[X509_FORMAT_START+i] & 0x0F); + printf("- TemplateLength | 0x%02x\n", data[X509_FORMAT_START+i] & 0xF0); + } + } +} + +/** + * @brief Print key configurations + * + * @param[in] data Pointer to buffer with input data + */ +static void _print_key_config(uint8_t* data) +{ + size_t atca_key_config_bytes = ATCA_KEY_SLOT_COUNT*2; + + char binary[9]; + puts("\nKey Config"); + puts("----------------------------------------"); + puts("SlotID | Hex | Binary"); + puts(" | | 7 0 | 15 8"); + puts("--------+--------+----------------------"); + int slotcount = 0; + for (size_t i = 0; i < atca_key_config_bytes; i += 2) { + if (slotcount < 10) { + printf("%d | 0x%02x%02x | ", slotcount, data[KEY_CONFIG_START+i], data[KEY_CONFIG_START+i+1]); + } + else { + printf("%d | 0x%02x%02x | ", slotcount, data[KEY_CONFIG_START+i], data[KEY_CONFIG_START+i+1]); + } + for (int j = 0; j < 2; j++) { + get_bin(binary, data[KEY_CONFIG_START+i]); + printf("%s | ", binary); + } + puts(""); + slotcount++; + } + puts(""); +} + +static void _print_secure_boot(uint8_t* data) +{ + uint8_t secure_boot_mode = data[SECURE_BOOT_START] & 0x03; + switch(secure_boot_mode) { + case 0x01: + puts("SecureBootMode | Full"); + break; + case 0x10: + puts("SecureBootMode | Stored signature"); + break; + case 0x11: + puts("SecureBootMode | Stored digest"); + break; + default: + puts("SecureBootMode | Disabled"); + } + + if (data[SECURE_BOOT_START] & 0x08) { + puts("SecureBootPersist | Enabled"); + } + else { + puts("SecureBootPersist | Disabled"); + } + + if (data[SECURE_BOOT_START] & 0x10) { + puts("SecureBootNonce | Required, must use ATECC608 RNG"); + } + else { + puts("SecureBootNonce | Optional, controlled by SecureBootMode"); + } + + printf("Secure Boot Signature or Digest stored in slot %d\n", data[SECURE_BOOT_START+1] & 0x0F); + printf("Secure Boot Public Key stored in slot %d\n", data[SECURE_BOOT_START+1] & 0xF0); +} + +static int _read_config(ATCADevice dev) { uint8_t data[ATCA_ECC_CONFIG_SIZE]; - uint8_t data_count = 0; - char binary[9]; memset(data, 0, ATCA_ECC_CONFIG_SIZE); - if (atcab_read_config_zone(data) != ATCA_SUCCESS) { + int status = calib_read_config_zone(dev, data); + if (status != ATCA_SUCCESS) { printf("Error reading config zone\n"); return 1; } - printf("Config zone: \n\n"); + printf("Config Zone\n"); + puts("Device Info (Read Only)"); + puts("--------------------------------------------"); + ATCADeviceType devtype = dev->mIface.mIfaceCFG->devtype; + printf("Device Type | %s\n", _convert_atca_devtype(devtype)); - printf("%03d:%03d ", data_count, data_count+3); + _print_dev_info_ro(data, devtype); + puts("--------------------------------------------\n"); + + puts("Device Info (Writable)"); + puts("---------------------------------------------"); + _print_i2c_addr_or_gpio_mode(data[I2C_ADDRESS], data[I2C_ENABLE] & 0x01); + + _print_countmatch_or_otp_mode(data[OTP_MODE], devtype); + + _print_chip_mode(data[CHIP_MODE], devtype); + puts(""); + + _print_slot_config(data); + + printf("Counter 0 | 0x%02x 0x%02x 0x%02x 0x%02x\n", data[COUNTER_01_START], + data[COUNTER_01_START+1], + data[COUNTER_01_START+2], + data[COUNTER_01_START+3]); + + printf("Counter 1 | 0x%02x 0x%02x 0x%02x 0x%02x\n", data[COUNTER_02_START], + data[COUNTER_02_START+1], + data[COUNTER_02_START+2], + data[COUNTER_02_START+3]); + + if (devtype == ATECC608) { + if ((data[USE_LOCK] & 0x0F) == 0x0A) { + puts("UseLockEnable | True"); + printf("UseLockKey is stored in slot %d\n", data[USE_LOCK] & 0xF0); + } + else { + puts("UseLockEnable | False"); + } + + if (data[VOLATILE_KEY_PERMIT] & 0x80) { + puts("VolatileKeyPermit | Enabled"); + printf("Volatile Key Permit key stored in slot %d\n", data[VOLATILE_KEY_PERMIT] & 0x0F); + } + else { + puts("VolatileKeyPermit | Disabled"); + } + + _print_secure_boot(data); + + printf("KDF IV Loc | %d\n", data[KDF_IV_LOC]); + } + else { + for (int i = LAST_KEY_USE_START; i < ATCA_KEY_SLOT_COUNT; i++) { + printf("LastKeyUse %d | 0x%02x\n", i, data[i]); + } + } + + printf("UserExtra | 0x%02x\n", data[USER_EXTRA]); + + if (devtype == ATECC608) { + printf("UserExtraAdd (I2C)| 0x%02x\n", data[USER_EXTRA_ADD]); + + } + else{ + printf("Selector | 0x%02x\n", data[SELECTOR]); + } + + if (data[LOCK_VALUE] == 0x00) { + puts("LockValue | Data and OTP Locked"); + } + else { + puts("LockValue | Data and OTP Unlocked"); + } + + if (data[LOCK_CONFIG] == 0x00) { + puts("LockConfig | Config Zone Locked"); + } + else { + puts("LockConfig | Config Zone Unlocked"); + } + + _print_slot_lock(data); + + if (devtype == ATECC608) { + _print_chip_options(data); + } + _print_x509_format(data); + + _print_key_config(data); + + return 0; +} + +static int _read_config_bin(ATCADevice dev) +{ + uint8_t data[ATCA_ECC_CONFIG_SIZE]; + int data_count = 0; + char binary[9]; + + memset(data, 0, ATCA_ECC_CONFIG_SIZE); + + int status = calib_read_config_zone(dev, data); + if (status != ATCA_SUCCESS) { + printf("Error reading config zone\n"); + return 1; + } + + puts("ConfigZone Binary Data:"); + puts("---------------------------------------------------"); + puts("Bytes \\ Bits | 7 0 7 0 7 0 7 0"); + puts("-------------+-------------------------------------"); + printf("%03d:%03d | ", data_count, data_count+3); for (int i = 0; i < 4; i++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -54,7 +615,7 @@ static int _read_config(void) } printf("SN0 SN1 SN2 SN3\n"); - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int i = 0; i < 4; i++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -62,7 +623,7 @@ static int _read_config(void) } printf("RN0 RN1 RN2 RN3\n"); - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int i = 0; i < 4; i++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -70,7 +631,7 @@ static int _read_config(void) } printf("SN4 SN5 SN6 SN7\n"); - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int i = 0; i < 4; i++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -78,17 +639,21 @@ static int _read_config(void) } printf("SN8 RSVD I2CE RSVD\n"); - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int i = 0; i < 4; i++) { get_bin(binary, data[data_count]); printf("%s ", binary); data_count++; } - printf("I2CA RSVD OTPM CM\n"); + printf("I2CA RSVD OTPM CM\n\n"); + puts("Slot Config"); + puts("---------------------------------------------------"); + puts("Bytes \\ Bits | 7 0 15 8 7 0 15 8"); + puts("-------------+-------------------------------------"); for (int i = 0; i < 32; i += 4) { static int slotcount = 0; - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int j = 0; j < 4; j++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -103,7 +668,7 @@ static int _read_config(void) for (int k = 0; k < 2; k++) { static int cnt_no = 0; for (int i = 0; i < 8; i += 4) { - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int j = 0; j < 4; j++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -115,7 +680,7 @@ static int _read_config(void) } for (int i = 0; i < 16; i += 4) { - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int j = 0; j < 4; j++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -124,7 +689,7 @@ static int _read_config(void) printf("LKU%d LKU%d LKU%d LKU%d\n", i, i+1, i+2, i+3); } - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int i = 0; i < 4; i++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -132,7 +697,7 @@ static int _read_config(void) } printf("UE SEL LV LC\n"); - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int i = 0; i < 4; i++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -140,17 +705,21 @@ static int _read_config(void) } printf("SL0 SL1 RFU0 RFU1\n"); - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int i = 0; i < 4; i++) { get_bin(binary, data[data_count]); printf("%s ", binary); data_count++; } - printf("X509-0 X509-1 X509-2 X509-3\n"); + printf("X509-0 X509-1 X509-2 X509-3\n\n"); + puts("Key Config"); + puts("---------------------------------------------------"); + puts("Bytes \\ Bits | 7 0 15 8 7 0 15 8"); + puts("-------------+-------------------------------------"); for (int i = 0; i < 32; i += 4) { static int key_cnt = 0; - printf("%03d:%03d ", data_count, data_count+3); + printf("%03d:%03d | ", data_count, data_count+3); for (int j = 0; j < 4; j++) { get_bin(binary, data[data_count]); printf("%s ", binary); @@ -161,16 +730,15 @@ static int _read_config(void) printf("KC%d KC%d\n", key_cnt, key_cnt); key_cnt++; } - return 0; } -static int _check_lock_config(void) +static int _check_lock_config(ATCADevice dev) { - bool is_locked = false; - atcab_is_locked(LOCK_ZONE_CONFIG, &is_locked); + bool is_locked_config = false; + calib_is_locked(dev, LOCK_ZONE_CONFIG, &is_locked_config); - if (is_locked) { + if (is_locked_config) { printf("Config zone is locked\n"); } else { @@ -180,12 +748,12 @@ static int _check_lock_config(void) return 0; } -static int _check_lock_data(void) +static int _check_lock_data(ATCADevice dev) { - bool is_locked = false; - atcab_is_locked(LOCK_ZONE_DATA, &is_locked); + bool is_locked_data = false; + calib_is_locked(dev, LOCK_ZONE_DATA, &is_locked_data); - if (is_locked) { + if (is_locked_data) { printf("Data zone is locked\n"); } else { @@ -195,50 +763,149 @@ static int _check_lock_data(void) return 0; } -static int _lock_config(void) +static int _lock_config(ATCADevice dev) { - bool is_locked = false; - atcab_is_locked(LOCK_ZONE_CONFIG, &is_locked); + bool is_locked_config = false; + calib_is_locked(dev, LOCK_ZONE_CONFIG, &is_locked_config); - if (is_locked) { + if (is_locked_config) { printf("Error: Config zone is already locked\n"); return 1; } - if (atcab_lock_config_zone() != ATCA_SUCCESS) { + if (calib_lock_config_zone(dev) != ATCA_SUCCESS) { printf("Error: Locking failed\n"); return 1; } - printf("Device successfully locked\n"); + printf("Config Zone successfully locked\n"); return 0; } -static int _cryptoauth(int argc, char **argv) +static int _lock_data(ATCADevice dev) +{ + bool is_locked_data = false; + calib_is_locked(dev, LOCK_ZONE_DATA, &is_locked_data); + + if (is_locked_data) { + printf("Error: Data zone is already locked\n"); + return 1; + } + + if (calib_lock_data_zone(dev) != ATCA_SUCCESS) { + printf("Error: Locking failed\n"); + return 1; + } + + printf("Data Zone successfully locked\n"); + return 0; +} + +static int _set_dev(char* id) +{ + int index = atoi(id); + if (index > (int)ATCA_NUMOF-1) { + printf("Invalid ID, can be 0 - %d\n", ATCA_NUMOF-1); + return 1; + } + device_index = index; + return 0; +} + +static int _show_dev(void) +{ + puts("Set | ID | DevType | I2C Addr"); + puts("----|----|-----------|---------"); + for (size_t i = 0; i < ATCA_NUMOF; i++) { + char dev_set = ((size_t)device_index == i ? '*' : ' '); + ATCADeviceType devtype = atca_devs_ptr[i]->mIface.mIfaceCFG->devtype; + printf("%c | %d | %s | 0x%02x\n", + dev_set, + i, + _convert_atca_devtype(devtype), + atca_devs_ptr[i]->mIface.mIfaceCFG->atcai2c.address); + } + return 0; +} + +static int _write_config(ATCADevice dev) +{ + ATCA_STATUS status = calib_read_config_zone(dev, config_backup[device_index]); + if (status != ATCA_SUCCESS) { + printf("Error reading config zone\n"); + return 1; + } + + status = calib_write_config_zone(dev, atecc608a_config); + if (status != ATCA_SUCCESS) { + printf("Writing config zone failed: 0x%02x\n", status); + return 1; + } + return 0; +} + +static int _restore_config(ATCADevice dev) +{ + ATCA_STATUS status = calib_write_config_zone(dev, config_backup[device_index]); + if (status != ATCA_SUCCESS) { + printf("Restoring config zone failed: 0x%02x\n", status); + return 1; + } + return 0; +} + +static int _atca(int argc, char **argv) { if (argc > 1) { - if ((strcmp(argv[1], "read") == 0)) { - return _read_config(); + if ((strcmp(argv[1], "show_dev") == 0)) { + return _show_dev(); + } + else if ((strcmp(argv[1], "set_dev") == 0)) { + if (argc < 3) { + puts("Please enter valid device index number"); + return 1; + } + return _set_dev(argv[2]); + } + else if ((strcmp(argv[1], "write") == 0)) { + return _write_config(atca_devs_ptr[device_index]); + } + else if ((strcmp(argv[1], "restore") == 0)) { + return _restore_config(atca_devs_ptr[device_index]); + } + else if ((strcmp(argv[1], "read") == 0)) { + return _read_config(atca_devs_ptr[device_index]); + } + else if ((strcmp(argv[1], "read_bin") == 0)) { + return _read_config_bin(atca_devs_ptr[device_index]); } else if ((strcmp(argv[1], "lock_c") == 0)) { - return _lock_config(); + return _lock_config(atca_devs_ptr[device_index]); + } + else if ((strcmp(argv[1], "lock_d") == 0)) { + return _lock_data(atca_devs_ptr[device_index]); } else if ((strcmp(argv[1], "check_lc") == 0)) { - return _check_lock_config(); + return _check_lock_config(atca_devs_ptr[device_index]); } else if ((strcmp(argv[1], "check_ld") == 0)) { - return _check_lock_data(); + return _check_lock_data(atca_devs_ptr[device_index]); } } else { + printf("* show_dev - list available devices and IDs\n"); + printf("* set_dev - set and initialize an atca device (defaults to ID 0)\n"); + printf("* write - write configuration to config zone (stores backup of current config)\n"); + printf("* restore - restore device config zone to previous state\n"); printf("* read - read Microchip CryptoAuth device's config zone\n"); - printf("* lock_c - PERMANENTLY lock Microchip CryptoAuth device's config \ - zone (cannot be undone!)\n"); + printf("* read_bin - read config zone and print binary data\n"); + printf("* lock_c - PERMANENTLY lock Microchip CryptoAuth device's config zone (cannot be undone!)\n"); + printf("* lock_d - PERMANENTLY lock Microchip CryptoAuth device's data zone (cannot be undone!)\n"); printf("* check_lc - check if Microchip CryptoAuth device's config zone is locked\n"); printf("* check_ld - check if Microchip CryptoAuth device's data zone is locked\n"); } return 0; } -SHELL_COMMAND(cryptoauth, "Commands for Microchip CryptoAuth devices", - _cryptoauth); +SHELL_COMMAND(atca, "Commands for Microchip CryptoAuth devices", + _atca);