From 20cdbac5fc8391a86a0b657c5daa613cbb0afd37 Mon Sep 17 00:00:00 2001 From: Lena Boeckmann Date: Wed, 15 May 2024 18:30:51 +0200 Subject: [PATCH 1/8] sys/shell: Update cryptoauthlib shell commands --- sys/shell/cmds/cryptoauthlib.c | 605 ++++++++++++++++++++++++++++++--- 1 file changed, 563 insertions(+), 42 deletions(-) diff --git a/sys/shell/cmds/cryptoauthlib.c b/sys/shell/cmds/cryptoauthlib.c index 4b03fddeb6..388ee7efe2 100644 --- a/sys/shell/cmds/cryptoauthlib.c +++ b/sys/shell/cmds/cryptoauthlib.c @@ -18,11 +18,24 @@ * @} */ #include +#include #include +#include "atca.h" +#include "atca_params.h" #include "cryptoauthlib.h" #include "shell.h" +#define ATCA_CONFIG_READ_ONLY_BYTES (15) +#define ATCA_KEY_SLOT_COUNT (15) +#define ATCA_X509_KEY_COUNT (4) + +/** + * @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 +44,472 @@ 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 ATSHA204A: + return "ATSHA204A"; + case ATECC108A: + return "ATECC108A"; + case ATECC508A: + return "ATECC508A"; + case ATECC608: + return "ATECC608"; + case ATSHA206A: + return "ATSHA206A"; + case ECC204: + return "ECC204"; + case TA100: + return "TA100"; + default: + return "ATCA_DEV_UNKNOWN"; + } +} + +/** + * @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 data_size Size of input buffer + * @param[in] data_count Current data count + * @param[out] communications Contains the device communications mode (0 = Single Wire, 1 = I2C) + * @return uint8_t Return updated @p data_count + * @return -1 if there are no bytes left in data + */ +static uint8_t _print_dev_info_ro(uint8_t* data, size_t data_size, uint8_t data_count, uint8_t* communications) +{ + if ((size_t)data_count >= data_size - ATCA_CONFIG_READ_ONLY_BYTES) { + return -1; + } + + printf("Serial No (Pt. 1) | "); + for (int i = 0; i < 4; i++) { + printf("0x%02x ", data[data_count]); + data_count++; + } + puts(""); + + printf("Revision No. | "); + for (int i = 0; i < 4; i++) { + printf("0x%02x ", data[data_count]); + data_count++; + } + puts(""); + + printf("Serial No (Pt. 2) | "); + for (int i = 0; i < 5; i++) { + printf("0x%02x ", data[data_count]); + data_count++; + } + puts(""); + + /* Skip reserved byte */ + data_count++; + *communications = data[data_count]; + if (*communications & 0x01) { + printf("I2C Enabled | True\n"); + printf("Single Wire | False\n"); + } + else { + printf("I2C Enabled | False\n"); + printf("Single Wire | True\n"); + } + + /* Skip reserved byte */ + data_count += 2; + return data_count; +} + +/** + * @brief Get authorization mode + * + * @param data Byte of data to interprete + * @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 interprete + * @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. + * + * @param data Byte of data to interprete + */ +static void _print_otp_mode(uint8_t data) +{ + uint8_t otp_mode = data; + switch(otp_mode) { + 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 interprete + */ +static void _print_chip_mode(uint8_t data) +{ + puts("ChipMode:"); + 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)"); + } +} + +/** + * @brief Print Key Slot Configurations in hexadecimal and binary format + * + * @param[in] data Pointer to buffer with input data + * @param data_size Size of input buffer + * @param[in] data_count Current data count + * @return uint8_t Return updated @p data_count + * @return -1 if there are no bytes left in data + */ +static uint8_t _print_slot_config(uint8_t* data, size_t data_size, uint8_t data_count) +{ + size_t atca_slot_config_bytes = ATCA_KEY_SLOT_COUNT*2; + if ((size_t)data_count >= data_size - atca_slot_config_bytes) { + return -1; + } + + char binary[9]; + puts("Slot Config"); + puts("----------------------------------------"); + puts("SlotID | Hex | Binary"); + puts(" | | 7 0 | 15 8"); + puts("--------+--------+----------------------"); + for (int i = 0; i < 32; i += 2) { + static int slotcount = 0; + if (slotcount < 10) { + printf("%d | 0x%02x%02x | ", slotcount, data[data_count], data[data_count+1]); + } + else { + printf("%d | 0x%02x%02x | ", slotcount, data[data_count], data[data_count+1]); + } + for (int j = 0; j < 2; j++) { + get_bin(binary, data[data_count]); + printf("%s | ", binary); + data_count++; + } + puts(""); + slotcount++; + } + puts(""); + + return data_count; +} + +/** + * @brief Print lock status of key slots + * + * @param[in] data Pointer to buffer with input data + * @param data_size Size of input buffer + * @param[in] data_count Current data count + * @return uint8_t Return updated @p data_count + * @return -1 if there are no bytes left in data + */ +static uint8_t _print_slot_lock(uint8_t* data, size_t data_size, uint8_t data_count) +{ + if ((size_t)data_count >= data_size - ATCA_KEY_SLOT_COUNT) { + return -1; + } + 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[data_count] >> i) & 0x01) { + printf(" X "); + } + else { + printf(" - "); + } + data_count++; + } + } + puts(""); + return data_count; +} + +/** + * @brief Print X509 format restrictions + * + * @param[in] data Pointer to buffer with input data + * @param data_size Size of input buffer + * @param[in] data_count Current data count + * @return uint8_t Return updated @p data_count + * @return -1 if there are no bytes left in data + */ +static uint8_t _print_x509_format(uint8_t* data, size_t data_size, uint8_t data_count) +{ + if ((size_t)data_count >= data_size - ATCA_X509_KEY_COUNT) { + return -1; + } + + puts("\nX509 Format:"); + for (int i = 0; i < 4; i++) { + if (data[data_count+i] == 0x00) { + printf("PubKey %d | No restrictions\n", i); + } + else { + printf("PubKey %d:\n", i); + printf("- PublicPosition | 0x%02x\n", data[data_count+i] & 0x0F); + printf("- TemplateLength | 0x%02x\n", data[data_count+i] & 0xF0); + } + } + return data_count += 4; +} + +/** + * @brief Print key configurations + * + * @param[in] data Pointer to buffer with input data + * @param data_size Size of input buffer + * @param[in] data_count Current data count + * @return uint8_t Return updated @p data_count + * @return -1 if there are no bytes left in data + */ +static uint8_t _print_key_config(uint8_t* data, size_t data_size, uint8_t data_count) +{ + size_t atca_key_config_bytes = ATCA_KEY_SLOT_COUNT*2; + if ((size_t)data_count >= data_size - atca_key_config_bytes) { + return -1; + } + + char binary[9]; + puts("\nKey Config"); + puts("----------------------------------------"); + puts("SlotID | Hex | Binary"); + puts(" | | 7 0 | 15 8"); + puts("--------+--------+----------------------"); + for (int i = 0; i < 32; i += 2) { + static int slotcount = 0; + if (slotcount < 10) { + printf("%d | 0x%02x%02x | ", slotcount, data[data_count], data[data_count+1]); + } + else { + printf("%d | 0x%02x%02x | ", slotcount, data[data_count], data[data_count+1]); + } + for (int j = 0; j < 2; j++) { + get_bin(binary, data[data_count]); + printf("%s | ", binary); + data_count++; + } + puts(""); + slotcount++; + } + puts(""); + + return data_count; +} + +static int _read_config(ATCADevice dev) { uint8_t data[ATCA_ECC_CONFIG_SIZE]; - uint8_t data_count = 0; - char binary[9]; + int data_count = 0; + uint8_t communications; 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)); + if (devtype == ATECC608) { + puts("\n***************************Note***************************"); + printf("This interpretation is valid for ATECC508A devices.\nIf you have an ATECC608, you'll need to get the datasheet\n(NDA signature required) and interprete it yourself.\nThe config zone is very similar, so you can print it\nin binary format with the 'read_bin' command and\nmatch the corresponding bytes.\n"); + puts("**********************************************************\n"); + } + data_count = _print_dev_info_ro(data, sizeof(data), data_count, &communications); + if (data_count == -1) { + printf("Error formatting read-only config zone\n"); + return 1; + } + puts("--------------------------------------------\n"); - printf("%03d:%03d ", data_count, data_count+3); + puts("Device Info (Writable)"); + puts("---------------------------------------------"); + _print_i2c_addr_or_gpio_mode(data[data_count], communications); + data_count += 2; + + _print_otp_mode(data[data_count]); + data_count++; + + _print_chip_mode(data[data_count]); + data_count++; + puts(""); + + data_count = _print_slot_config(data, sizeof(data), data_count); + if (data_count == -1) { + printf("Error formatting read-only config zone\n"); + return 1; + } + + printf("Counter 0 | 0x%02x 0x%02x 0x%02x 0x%02x\n", data[data_count], + data[data_count+1], + data[data_count+2], + data[data_count+3]); + data_count += 4; + + printf("Counter 1 | 0x%02x 0x%02x 0x%02x 0x%02x\n", data[data_count], + data[data_count+1], + data[data_count+2], + data[data_count+3]); + data_count += 4; + + printf("LastKeyUse | 0x%02x\n", data[data_count]); + data_count++; + + printf("UserExtra | 0x%02x\n", data[data_count]); + data_count++; + + printf("Selector | 0x%02x\n", data[data_count]); + data_count++; + + if (data[data_count] == 0x00) { + puts("LockValue | Data and OTP Locked"); + } + else { + puts("LockValue | Data and OTP Unlocked"); + } + data_count++; + + if (data[data_count] == 0x00) { + puts("LockConfig | Config Zone Locked"); + } + else { + puts("LockConfig | Config Zone Unlocked"); + } + data_count++; + + data_count = _print_slot_lock(data, sizeof(data), data_count); + if (data_count == -1) { + printf("Error formatting read-only config zone\n"); + return 1; + } + + data_count = _print_x509_format(data, sizeof(data), data_count); + if (data_count == -1) { + printf("Error formatting read-only config zone\n"); + return 1; + } + + data_count = _print_key_config(data, sizeof(data), data_count); + if (data_count == -1) { + printf("Error formatting read-only config zone\n"); + return 1; + } + 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 +517,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 +525,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 +533,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 +541,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 +570,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 +582,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 +591,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 +599,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 +607,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 +632,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 +650,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,44 +665,95 @@ 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, ATCADevice dev) +{ + int index = atoi(id); + if (index > (int)ATCA_NUMOF-1) { + printf("Invalid ID, can be 0 - %d\n", ATCA_NUMOF-1); + return 1; + } + atcab_init_ext(&dev, (ATCAIfaceCfg *)&atca_params[index]); + return 0; +} + +static int _atca(int argc, char **argv) +{ + ATCADevice dev; + atcab_init_ext(&dev, (ATCAIfaceCfg *)&atca_params[0]); + if (argc > 1) { + if ((strcmp(argv[1], "set_dev") == 0)) { + if (argc < 3) { + puts("Please enter valid device index number"); + return 1; + } + return _set_dev(argv[2], dev); + } if ((strcmp(argv[1], "read") == 0)) { - return _read_config(); + return _read_config(dev); + } + else if ((strcmp(argv[1], "read_bin") == 0)) { + return _read_config_bin(dev); } else if ((strcmp(argv[1], "lock_c") == 0)) { - return _lock_config(); + return _lock_config(dev); + } + else if ((strcmp(argv[1], "lock_d") == 0)) { + return _lock_data(dev); } else if ((strcmp(argv[1], "check_lc") == 0)) { - return _check_lock_config(); + return _check_lock_config(dev); } else if ((strcmp(argv[1], "check_ld") == 0)) { - return _check_lock_data(); + return _check_lock_data(dev); } } else { + printf("* set_dev - set and initialize an atca device from\ + the global atca_params array (defaults to device at index 0)"); printf("* read - read Microchip CryptoAuth device's config zone\n"); - printf("* lock_c - PERMANENTLY lock Microchip CryptoAuth device's config \ + 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"); @@ -240,5 +761,5 @@ static int _cryptoauth(int argc, char **argv) return 0; } -SHELL_COMMAND(cryptoauth, "Commands for Microchip CryptoAuth devices", - _cryptoauth); +SHELL_COMMAND(atca, "Commands for Microchip CryptoAuth devices", + _atca); From 2d4a597fa11093a3e3e96a3c8dec4b241b3f57f8 Mon Sep 17 00:00:00 2001 From: Lena Boeckmann Date: Thu, 16 May 2024 09:06:13 +0200 Subject: [PATCH 2/8] sys/shell: fix some output issues --- sys/shell/cmds/cryptoauthlib.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sys/shell/cmds/cryptoauthlib.c b/sys/shell/cmds/cryptoauthlib.c index 388ee7efe2..24c1a470f0 100644 --- a/sys/shell/cmds/cryptoauthlib.c +++ b/sys/shell/cmds/cryptoauthlib.c @@ -747,14 +747,11 @@ static int _atca(int argc, char **argv) } } else { - printf("* set_dev - set and initialize an atca device from\ - the global atca_params array (defaults to device at index 0)"); + printf("* set_dev - set and initialize an atca device (defaults to index 0)\n"); printf("* read - read Microchip CryptoAuth device's config zone\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("* 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"); } From 16f9c51014518db2162180b130379607da3a34cc Mon Sep 17 00:00:00 2001 From: Lena Boeckmann Date: Fri, 17 May 2024 17:00:15 +0200 Subject: [PATCH 3/8] sys/shell: Update read command to also support ATECC608 devices --- sys/shell/cmds/cryptoauthlib.c | 426 ++++++++++++++++++++------------- 1 file changed, 255 insertions(+), 171 deletions(-) diff --git a/sys/shell/cmds/cryptoauthlib.c b/sys/shell/cmds/cryptoauthlib.c index 24c1a470f0..93728e44fe 100644 --- a/sys/shell/cmds/cryptoauthlib.c +++ b/sys/shell/cmds/cryptoauthlib.c @@ -30,6 +30,35 @@ #define ATCA_KEY_SLOT_COUNT (15) #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) + +int device_index = 0; + /** * @brief Convert one byte into a binary number * @@ -53,22 +82,12 @@ void get_bin(char *result, uint8_t byte) static char* _convert_atca_devtype(ATCADeviceType devtype) { switch(devtype) { - case ATSHA204A: - return "ATSHA204A"; - case ATECC108A: - return "ATECC108A"; case ATECC508A: return "ATECC508A"; case ATECC608: return "ATECC608"; - case ATSHA206A: - return "ATSHA206A"; - case ECC204: - return "ECC204"; - case TA100: - return "TA100"; default: - return "ATCA_DEV_UNKNOWN"; + return "Unsupported device"; } } @@ -78,43 +97,38 @@ static char* _convert_atca_devtype(ATCADeviceType devtype) * Reserved bytes that don't mean anything are omitted. * * @param[in] data Pointer to buffer with input data - * @param data_size Size of input buffer - * @param[in] data_count Current data count - * @param[out] communications Contains the device communications mode (0 = Single Wire, 1 = I2C) - * @return uint8_t Return updated @p data_count - * @return -1 if there are no bytes left in data + * @param devtype Type of the device currently used */ -static uint8_t _print_dev_info_ro(uint8_t* data, size_t data_size, uint8_t data_count, uint8_t* communications) +static void _print_dev_info_ro(uint8_t* data, ATCADeviceType devtype) { - if ((size_t)data_count >= data_size - ATCA_CONFIG_READ_ONLY_BYTES) { - return -1; - } - printf("Serial No (Pt. 1) | "); for (int i = 0; i < 4; i++) { - printf("0x%02x ", data[data_count]); - data_count++; + printf("0x%02x ", data[SERIAL_NO_START_01+i]); } puts(""); printf("Revision No. | "); for (int i = 0; i < 4; i++) { - printf("0x%02x ", data[data_count]); - data_count++; + 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[data_count]); - data_count++; + printf("0x%02x ", data[SERIAL_NO_START_02+i]); } puts(""); - /* Skip reserved byte */ - data_count++; - *communications = data[data_count]; - if (*communications & 0x01) { + 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"); } @@ -122,10 +136,6 @@ static uint8_t _print_dev_info_ro(uint8_t* data, size_t data_size, uint8_t data_ printf("I2C Enabled | False\n"); printf("Single Wire | True\n"); } - - /* Skip reserved byte */ - data_count += 2; - return data_count; } /** @@ -189,14 +199,23 @@ static void _print_i2c_addr_or_gpio_mode(uint8_t data, uint8_t communications) } /** - * @brief Prints the OTP mode. + * @brief Prints the OTP mode or CountMatch, depending on device type. * * @param data Byte of data to interprete */ -static void _print_otp_mode(uint8_t data) +static void _print_countmatch_or_otp_mode(uint8_t data, ATCADeviceType devtype) { - uint8_t otp_mode = data; - switch(otp_mode) { + 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; @@ -205,6 +224,7 @@ static void _print_otp_mode(uint8_t data) break; default: printf("OTP Mode | None\n"); + } } } @@ -213,14 +233,24 @@ static void _print_otp_mode(uint8_t data) * * @param data Byte of data to interprete */ -static void _print_chip_mode(uint8_t data) +static void _print_chip_mode(uint8_t data, ATCADeviceType devtype) { puts("ChipMode:"); - if (data & 0x01) { - puts("SelectorMode | Only writeable if zero"); + 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 { - puts("SelectorMode | Always writeable"); + if (data & 0x01) { + puts("SelectorMode | Only writeable if zero"); + } + else { + puts("SelectorMode | Always writeable"); + } } if (data & 0x02) { @@ -236,127 +266,152 @@ static void _print_chip_mode(uint8_t data) 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 - * @param data_size Size of input buffer - * @param[in] data_count Current data count - * @return uint8_t Return updated @p data_count - * @return -1 if there are no bytes left in data */ -static uint8_t _print_slot_config(uint8_t* data, size_t data_size, uint8_t data_count) +static void _print_slot_config(uint8_t* data) { - size_t atca_slot_config_bytes = ATCA_KEY_SLOT_COUNT*2; - if ((size_t)data_count >= data_size - atca_slot_config_bytes) { - return -1; - } - char binary[9]; + puts("Slot Config"); puts("----------------------------------------"); puts("SlotID | Hex | Binary"); puts(" | | 7 0 | 15 8"); puts("--------+--------+----------------------"); - for (int i = 0; i < 32; i += 2) { + for (size_t i = 0; i < ATCA_KEY_SLOT_COUNT*2; i += 2) { static int slotcount = 0; if (slotcount < 10) { - printf("%d | 0x%02x%02x | ", slotcount, data[data_count], data[data_count+1]); + 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[data_count], data[data_count+1]); + 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[data_count]); + get_bin(binary, data[i]); printf("%s | ", binary); - data_count++; } puts(""); slotcount++; } puts(""); - - return data_count; } /** * @brief Print lock status of key slots * * @param[in] data Pointer to buffer with input data - * @param data_size Size of input buffer - * @param[in] data_count Current data count - * @return uint8_t Return updated @p data_count - * @return -1 if there are no bytes left in data */ -static uint8_t _print_slot_lock(uint8_t* data, size_t data_size, uint8_t data_count) +static void _print_slot_lock(uint8_t* data) { - if ((size_t)data_count >= data_size - ATCA_KEY_SLOT_COUNT) { - return -1; - } 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[data_count] >> i) & 0x01) { - printf(" X "); - } - else { + if ((data[SLOT_LOCKED_START+j] >> i) & 0x01) { printf(" - "); } - data_count++; + else { + printf(" X "); + } } } puts(""); - return data_count; +} + +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 - * @param data_size Size of input buffer - * @param[in] data_count Current data count - * @return uint8_t Return updated @p data_count - * @return -1 if there are no bytes left in data */ -static uint8_t _print_x509_format(uint8_t* data, size_t data_size, uint8_t data_count) +static void _print_x509_format(uint8_t* data) { - if ((size_t)data_count >= data_size - ATCA_X509_KEY_COUNT) { - return -1; - } - puts("\nX509 Format:"); for (int i = 0; i < 4; i++) { - if (data[data_count+i] == 0x00) { + 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[data_count+i] & 0x0F); - printf("- TemplateLength | 0x%02x\n", data[data_count+i] & 0xF0); + printf("- PublicPosition | 0x%02x\n", data[X509_FORMAT_START+i] & 0x0F); + printf("- TemplateLength | 0x%02x\n", data[X509_FORMAT_START+i] & 0xF0); } } - return data_count += 4; } /** * @brief Print key configurations * * @param[in] data Pointer to buffer with input data - * @param data_size Size of input buffer - * @param[in] data_count Current data count - * @return uint8_t Return updated @p data_count - * @return -1 if there are no bytes left in data */ -static uint8_t _print_key_config(uint8_t* data, size_t data_size, uint8_t data_count) +static void _print_key_config(uint8_t* data) { size_t atca_key_config_bytes = ATCA_KEY_SLOT_COUNT*2; - if ((size_t)data_count >= data_size - atca_key_config_bytes) { - return -1; - } char binary[9]; puts("\nKey Config"); @@ -364,32 +419,62 @@ static uint8_t _print_key_config(uint8_t* data, size_t data_size, uint8_t data_c puts("SlotID | Hex | Binary"); puts(" | | 7 0 | 15 8"); puts("--------+--------+----------------------"); - for (int i = 0; i < 32; i += 2) { + for (size_t i = 0; i < atca_key_config_bytes; i += 2) { static int slotcount = 0; if (slotcount < 10) { - printf("%d | 0x%02x%02x | ", slotcount, data[data_count], data[data_count+1]); + 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[data_count], data[data_count+1]); + 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[data_count]); + get_bin(binary, data[KEY_CONFIG_START+i]); printf("%s | ", binary); - data_count++; } puts(""); slotcount++; } puts(""); +} - return data_count; +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]; - int data_count = 0; - uint8_t communications; memset(data, 0, ATCA_ECC_CONFIG_SIZE); @@ -404,90 +489,91 @@ static int _read_config(ATCADevice dev) puts("--------------------------------------------"); ATCADeviceType devtype = dev->mIface.mIfaceCFG->devtype; printf("Device Type | %s\n", _convert_atca_devtype(devtype)); - if (devtype == ATECC608) { - puts("\n***************************Note***************************"); - printf("This interpretation is valid for ATECC508A devices.\nIf you have an ATECC608, you'll need to get the datasheet\n(NDA signature required) and interprete it yourself.\nThe config zone is very similar, so you can print it\nin binary format with the 'read_bin' command and\nmatch the corresponding bytes.\n"); - puts("**********************************************************\n"); - } - data_count = _print_dev_info_ro(data, sizeof(data), data_count, &communications); - if (data_count == -1) { - printf("Error formatting read-only config zone\n"); - return 1; - } + + _print_dev_info_ro(data, devtype); puts("--------------------------------------------\n"); puts("Device Info (Writable)"); puts("---------------------------------------------"); - _print_i2c_addr_or_gpio_mode(data[data_count], communications); - data_count += 2; + _print_i2c_addr_or_gpio_mode(data[I2C_ADDRESS], data[I2C_ENABLE] & 0x01); - _print_otp_mode(data[data_count]); - data_count++; + _print_countmatch_or_otp_mode(data[OTP_MODE], devtype); - _print_chip_mode(data[data_count]); - data_count++; + _print_chip_mode(data[CHIP_MODE], devtype); puts(""); - data_count = _print_slot_config(data, sizeof(data), data_count); - if (data_count == -1) { - printf("Error formatting read-only config zone\n"); - return 1; + _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("Counter 0 | 0x%02x 0x%02x 0x%02x 0x%02x\n", data[data_count], - data[data_count+1], - data[data_count+2], - data[data_count+3]); - data_count += 4; + printf("UserExtra | 0x%02x\n", data[USER_EXTRA]); - printf("Counter 1 | 0x%02x 0x%02x 0x%02x 0x%02x\n", data[data_count], - data[data_count+1], - data[data_count+2], - data[data_count+3]); - data_count += 4; + if (devtype == ATECC608) { + printf("UserExtraAdd (I2C)| 0x%02x\n", data[USER_EXTRA_ADD]); - printf("LastKeyUse | 0x%02x\n", data[data_count]); - data_count++; + } + else{ + printf("Selector | 0x%02x\n", data[SELECTOR]); + } - printf("UserExtra | 0x%02x\n", data[data_count]); - data_count++; - - printf("Selector | 0x%02x\n", data[data_count]); - data_count++; - - if (data[data_count] == 0x00) { + if (data[LOCK_VALUE] == 0x00) { puts("LockValue | Data and OTP Locked"); } else { puts("LockValue | Data and OTP Unlocked"); } - data_count++; - if (data[data_count] == 0x00) { + if (data[LOCK_CONFIG] == 0x00) { puts("LockConfig | Config Zone Locked"); } else { puts("LockConfig | Config Zone Unlocked"); } - data_count++; - data_count = _print_slot_lock(data, sizeof(data), data_count); - if (data_count == -1) { - printf("Error formatting read-only config zone\n"); - return 1; - } + _print_slot_lock(data); - data_count = _print_x509_format(data, sizeof(data), data_count); - if (data_count == -1) { - printf("Error formatting read-only config zone\n"); - return 1; + if (devtype == ATECC608) { + _print_chip_options(data); } + _print_x509_format(data); + + _print_key_config(data); - data_count = _print_key_config(data, sizeof(data), data_count); - if (data_count == -1) { - printf("Error formatting read-only config zone\n"); - return 1; - } return 0; } @@ -703,47 +789,45 @@ static int _lock_data(ATCADevice dev) return 0; } -static int _set_dev(char* id, ATCADevice dev) +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; } - atcab_init_ext(&dev, (ATCAIfaceCfg *)&atca_params[index]); + device_index = index; return 0; } static int _atca(int argc, char **argv) { - ATCADevice dev; - atcab_init_ext(&dev, (ATCAIfaceCfg *)&atca_params[0]); - if (argc > 1) { if ((strcmp(argv[1], "set_dev") == 0)) { if (argc < 3) { puts("Please enter valid device index number"); return 1; } - return _set_dev(argv[2], dev); + return _set_dev(argv[2]); } + if ((strcmp(argv[1], "read") == 0)) { - return _read_config(dev); + return _read_config(atca_devs_ptr[device_index]); } else if ((strcmp(argv[1], "read_bin") == 0)) { - return _read_config_bin(dev); + return _read_config_bin(atca_devs_ptr[device_index]); } else if ((strcmp(argv[1], "lock_c") == 0)) { - return _lock_config(dev); + return _lock_config(atca_devs_ptr[device_index]); } else if ((strcmp(argv[1], "lock_d") == 0)) { - return _lock_data(dev); + return _lock_data(atca_devs_ptr[device_index]); } else if ((strcmp(argv[1], "check_lc") == 0)) { - return _check_lock_config(dev); + return _check_lock_config(atca_devs_ptr[device_index]); } else if ((strcmp(argv[1], "check_ld") == 0)) { - return _check_lock_data(dev); + return _check_lock_data(atca_devs_ptr[device_index]); } } else { From b9ec5ad60fd492dbbb16b3005542491ead9ead3e Mon Sep 17 00:00:00 2001 From: Lena Boeckmann Date: Tue, 21 May 2024 09:13:20 +0200 Subject: [PATCH 4/8] sys/shell/cmds/cryptoauthlib: fix typos --- sys/shell/cmds/cryptoauthlib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/shell/cmds/cryptoauthlib.c b/sys/shell/cmds/cryptoauthlib.c index 93728e44fe..74f198e55b 100644 --- a/sys/shell/cmds/cryptoauthlib.c +++ b/sys/shell/cmds/cryptoauthlib.c @@ -141,7 +141,7 @@ static void _print_dev_info_ro(uint8_t* data, ATCADeviceType devtype) /** * @brief Get authorization mode * - * @param data Byte of data to interprete + * @param data Byte of data to interpret * @return char* Data interpretation as string */ static char* _get_authorization_mode(uint8_t data) @@ -154,7 +154,7 @@ static char* _get_authorization_mode(uint8_t data) * @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 interprete + * @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) @@ -201,7 +201,7 @@ static void _print_i2c_addr_or_gpio_mode(uint8_t data, uint8_t communications) /** * @brief Prints the OTP mode or CountMatch, depending on device type. * - * @param data Byte of data to interprete + * @param data Byte of data to interpret */ static void _print_countmatch_or_otp_mode(uint8_t data, ATCADeviceType devtype) { @@ -231,7 +231,7 @@ static void _print_countmatch_or_otp_mode(uint8_t data, ATCADeviceType devtype) /** * @brief Prints the chip mode * - * @param data Byte of data to interprete + * @param data Byte of data to interpret */ static void _print_chip_mode(uint8_t data, ATCADeviceType devtype) { From 1c062d8d6a63a3ff6cbbf075df8dcc360661ebd9 Mon Sep 17 00:00:00 2001 From: Lena Boeckmann Date: Fri, 31 May 2024 16:45:57 +0200 Subject: [PATCH 5/8] sys/shell: add atca write config --- sys/shell/cmds/cryptoauthlib.c | 78 +++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/sys/shell/cmds/cryptoauthlib.c b/sys/shell/cmds/cryptoauthlib.c index 74f198e55b..b316d7e384 100644 --- a/sys/shell/cmds/cryptoauthlib.c +++ b/sys/shell/cmds/cryptoauthlib.c @@ -13,6 +13,15 @@ * @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 * * @} @@ -26,6 +35,8 @@ #include "cryptoauthlib.h" #include "shell.h" +#include "atecc608a_config.h" + #define ATCA_CONFIG_READ_ONLY_BYTES (15) #define ATCA_KEY_SLOT_COUNT (15) #define ATCA_X509_KEY_COUNT (4) @@ -57,6 +68,8 @@ #define X509_FORMAT_START (92) #define KEY_CONFIG_START (96) +uint8_t config_backup[ATCA_NUMOF][ATCA_ECC_CONFIG_SIZE]; + int device_index = 0; /** @@ -286,8 +299,8 @@ static void _print_slot_config(uint8_t* data) 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) { - static int slotcount = 0; if (slotcount < 10) { printf("%d | 0x%02x%02x | ", slotcount, data[SLOT_CONFIG_START+i], data[SLOT_CONFIG_START+i+1]); } @@ -419,8 +432,8 @@ static void _print_key_config(uint8_t* data) 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) { - static int slotcount = 0; if (slotcount < 10) { printf("%d | 0x%02x%02x | ", slotcount, data[KEY_CONFIG_START+i], data[KEY_CONFIG_START+i+1]); } @@ -800,18 +813,68 @@ static int _set_dev(char* id) 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], "set_dev") == 0)) { + 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]); } - - if ((strcmp(argv[1], "read") == 0)) { + 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)) { @@ -831,7 +894,10 @@ static int _atca(int argc, char **argv) } } else { - printf("* set_dev - set and initialize an atca device (defaults to index 0)\n"); + 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("* 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"); From 002882a089a13a734082f9b3841b20c87c34fa8b Mon Sep 17 00:00:00 2001 From: Lena Boeckmann Date: Fri, 31 May 2024 16:46:19 +0200 Subject: [PATCH 6/8] pkg/cryptoauthlib: add example config --- pkg/cryptoauthlib/include/atecc608a_config.h | 104 +++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 pkg/cryptoauthlib/include/atecc608a_config.h diff --git a/pkg/cryptoauthlib/include/atecc608a_config.h b/pkg/cryptoauthlib/include/atecc608a_config.h new file mode 100644 index 0000000000..6d8c356ed3 --- /dev/null +++ b/pkg/cryptoauthlib/include/atecc608a_config.h @@ -0,0 +1,104 @@ +/* + * 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 + +#include + +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 */ +}; + +#endif /* ATECC608A_CONFIG_H */ From 1ce304cee05af1575c19990abc43f71e6e7b9055 Mon Sep 17 00:00:00 2001 From: Lena Boeckmann Date: Wed, 10 Jul 2024 13:53:01 +0200 Subject: [PATCH 7/8] sys/shell/cmds/cryptoauthlib: Fix key slot number --- sys/shell/cmds/cryptoauthlib.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/shell/cmds/cryptoauthlib.c b/sys/shell/cmds/cryptoauthlib.c index b316d7e384..05362cf6a5 100644 --- a/sys/shell/cmds/cryptoauthlib.c +++ b/sys/shell/cmds/cryptoauthlib.c @@ -37,8 +37,7 @@ #include "atecc608a_config.h" -#define ATCA_CONFIG_READ_ONLY_BYTES (15) -#define ATCA_KEY_SLOT_COUNT (15) +#define ATCA_KEY_SLOT_COUNT (16) #define ATCA_X509_KEY_COUNT (4) #define SERIAL_NO_START_01 (0) From 272d48db6382e09ab5ac5919aa044f61df2259cf Mon Sep 17 00:00:00 2001 From: Lena Boeckmann Date: Wed, 10 Jul 2024 14:07:47 +0200 Subject: [PATCH 8/8] pkg/cryptoauthlib: Address static test fails --- pkg/cryptoauthlib/include/atecc608a_config.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/cryptoauthlib/include/atecc608a_config.h b/pkg/cryptoauthlib/include/atecc608a_config.h index 6d8c356ed3..be77d7b6e7 100644 --- a/pkg/cryptoauthlib/include/atecc608a_config.h +++ b/pkg/cryptoauthlib/include/atecc608a_config.h @@ -29,8 +29,16 @@ #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 */ @@ -101,4 +109,8 @@ const uint8_t atecc608a_config[] = { 0x1C, 0x00, 0x1C, 0x00 /* KeyConfig 14, KeyConfig 15 */ }; +#ifdef __cplusplus +} +#endif + #endif /* ATECC608A_CONFIG_H */