From 9f99531b874151be23364816d30657f108cdd120 Mon Sep 17 00:00:00 2001 From: Zhenghuan Zhang Date: Thu, 9 Jan 2025 15:17:48 +0800 Subject: [PATCH] riscv: telink: load DAC key/cert from flash zone. Signed-off-by: Zhenghuan Zhang --- config/telink/chip-module/Kconfig | 5 ++ config/telink/chip-module/Kconfig.defaults | 3 + .../telink/CHIPDevicePlatformConfig.h | 6 ++ src/platform/telink/FactoryDataParser.c | 70 +++++++++++++++++++ src/platform/telink/FactoryDataParser.h | 14 ++++ src/platform/telink/FactoryDataProvider.cpp | 22 ++++++ src/platform/telink/FactoryDataProvider.h | 21 ++++++ 7 files changed, 141 insertions(+) diff --git a/config/telink/chip-module/Kconfig b/config/telink/chip-module/Kconfig index 2937b2b0c66094..fb61f63f5ea138 100644 --- a/config/telink/chip-module/Kconfig +++ b/config/telink/chip-module/Kconfig @@ -254,3 +254,8 @@ config CHIP_USE_MARS_SENSOR bool "Use Mars board sensor" depends on SOC_SERIES_RISCV_TELINK_B9X && (BOARD_TLSR9518ADK80D || BOARD_TLSR9518ADK80D_RETENTION) default n + +config SECURE_PROGRAMMING + bool "Enable reading DAC and keys from the DAC partition" + depends on CHIP_FACTORY_DATA + default n diff --git a/config/telink/chip-module/Kconfig.defaults b/config/telink/chip-module/Kconfig.defaults index 2e1dcd85912d33..4dab0c11890739 100644 --- a/config/telink/chip-module/Kconfig.defaults +++ b/config/telink/chip-module/Kconfig.defaults @@ -233,6 +233,9 @@ config DYNAMIC_INTERRUPTS config CHIP_OTA_REQUESTOR default y +config SECURE_PROGRAMMING + default n + config MCUBOOT_SIGNATURE_KEY_FILE default "bootloader/mcuboot/root-ec-p256.pem" if BOARD_TLSR9118BDK40D depends on BOOTLOADER_MCUBOOT diff --git a/src/platform/telink/CHIPDevicePlatformConfig.h b/src/platform/telink/CHIPDevicePlatformConfig.h index 76ee91e8cdb349..d73cbe39847c47 100644 --- a/src/platform/telink/CHIPDevicePlatformConfig.h +++ b/src/platform/telink/CHIPDevicePlatformConfig.h @@ -126,6 +126,12 @@ #define CHIP_DEVICE_EXPOSE_CHIPID_VIA_BLE 0 #endif +#ifdef CONFIG_SECURE_PROGRAMMING +#define CHIP_DEVICE_SECURE_PROGRAMMING CONFIG_SECURE_PROGRAMMING +#else +#define CHIP_DEVICE_SECURE_PROGRAMMING 0 +#endif + // ========== Platform-specific Configuration ========= // These are configuration options that are unique to Zephyr platforms. diff --git a/src/platform/telink/FactoryDataParser.c b/src/platform/telink/FactoryDataParser.c index 12260631262342..b360de13348bc9 100644 --- a/src/platform/telink/FactoryDataParser.c +++ b/src/platform/telink/FactoryDataParser.c @@ -27,6 +27,10 @@ LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL); +#if CHIP_DEVICE_SECURE_PROGRAMMING +static uint8_t dac_key_decrypt[32] = { 0 }; +#endif + static inline bool uint16_decode(zcbor_state_t * states, uint16_t * value) { uint32_t u32; @@ -121,6 +125,7 @@ bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData { res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->rd_uid); } +#if !CHIP_DEVICE_SECURE_PROGRAMMING else if (strncmp("dac_cert", (const char *) currentString.value, currentString.len) == 0) { res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->dac_cert); @@ -129,6 +134,7 @@ bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData { res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->dac_priv_key); } +#endif else if (strncmp("pai_cert", (const char *) currentString.value, currentString.len) == 0) { res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->pai_cert); @@ -181,3 +187,67 @@ bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData return res && zcbor_list_map_end_force_decode(states); } + +#if CHIP_DEVICE_SECURE_PROGRAMMING + +#if defined(CONFIG_SOC_RISCV_TELINK_B92) +#include "aes.h" +#endif + +#if defined(CONFIG_SOC_RISCV_TELINK_TL321X) +#include +#include +#endif + +bool LoadDACCertAndKey(uint8_t * buffer, struct FactoryData * factoryData) +{ + size_t dac_priv_key_len; + uint8_t chip_id[16] = { 0 }; + dac_priv_key_len = buffer[0]; + dac_priv_key_len |= (uint16_t) buffer[1] << 8; + factoryData->dac_priv_key.len = dac_priv_key_len; + if (!factoryData->dac_priv_key.len) + { + return false; + } + +#if defined(CONFIG_SOC_RISCV_TELINK_B92) + if (efuse_get_chip_id(chip_id)) +#endif +#if defined(CONFIG_SOC_RISCV_TELINK_TL321X) + if (efuse_get_chip_id(chip_id) == DRV_API_SUCCESS) +#endif + { +#if defined(CONFIG_SOC_RISCV_TELINK_B92) + aes_decrypt(chip_id, buffer + 2, dac_key_decrypt); + aes_decrypt(chip_id, buffer + 18, dac_key_decrypt + 16); +#endif +#if defined(CONFIG_SOC_RISCV_TELINK_TL321X) + ske_dig_en(); + uint32_t r = core_interrupt_disable(); + ske_lp_crypto(SKE_ALG_AES_128, SKE_MODE_ECB, SKE_CRYPTO_DECRYPT, chip_id, 0, NULL, buffer + 2, dac_key_decrypt, 16); + ske_lp_crypto(SKE_ALG_AES_128, SKE_MODE_ECB, SKE_CRYPTO_DECRYPT, chip_id, 0, NULL, buffer + 18, dac_key_decrypt + 16, + 16); + core_restore_interrupt(r); +#endif + factoryData->dac_priv_key.data = dac_key_decrypt; + } + else + { + LOG_ERR("Private key decryption failed."); + return false; + } + + size_t dac_cert_len; + dac_cert_len = buffer[100]; + dac_cert_len |= (uint16_t) buffer[101] << 8; + factoryData->dac_cert.len = dac_cert_len; + if (!factoryData->dac_cert.len) + { + return false; + } + factoryData->dac_cert.data = buffer + 102; + + return true; +} +#endif diff --git a/src/platform/telink/FactoryDataParser.h b/src/platform/telink/FactoryDataParser.h index de8f7c72da838d..7e97ad1412606d 100644 --- a/src/platform/telink/FactoryDataParser.h +++ b/src/platform/telink/FactoryDataParser.h @@ -21,6 +21,8 @@ #include #include +#include "CHIPDevicePlatformConfig.h" + #ifdef __cplusplus extern "C" { #endif @@ -77,6 +79,18 @@ struct FactoryData */ bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData * factoryData); +#if CHIP_DEVICE_SECURE_PROGRAMMING +/** + * @brief Inject dac cert and dac private key into the factory data structure. + * + * @param[in] buffer Buffer containing dac data. + * @param[out] factoryData address of object to be filled with parsed factory data. + * + * @returns true on success, false otherwise. + */ +bool LoadDACCertAndKey(uint8_t * buffer, struct FactoryData * factoryData); +#endif + #ifdef __cplusplus } #endif diff --git a/src/platform/telink/FactoryDataProvider.cpp b/src/platform/telink/FactoryDataProvider.cpp index 4e0b24f49af2c4..2ccf862152a20c 100644 --- a/src/platform/telink/FactoryDataProvider.cpp +++ b/src/platform/telink/FactoryDataProvider.cpp @@ -58,6 +58,10 @@ CHIP_ERROR FactoryDataProvider::Init() { uint8_t * factoryData = nullptr; size_t factoryDataSize; +#if CHIP_DEVICE_SECURE_PROGRAMMING + uint8_t * dacData = nullptr; + size_t dacDataSize; +#endif CHIP_ERROR error = mFlashFactoryData.ProtectFactoryDataPartitionAgainstWrite(); @@ -81,12 +85,30 @@ CHIP_ERROR FactoryDataProvider::Init() return error; } +#if CHIP_DEVICE_SECURE_PROGRAMMING + error = mFlashFactoryData.GetDACDataPartition(dacData, dacDataSize); + + if (error != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Failed to read DAC data partition"); + return error; + } +#endif + if (!ParseFactoryData(factoryData + kFactoryDataOffset, factoryDataSize - kFactoryDataOffset, &mFactoryData)) { ChipLogError(DeviceLayer, "Failed to parse factory data"); return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; } +#if CHIP_DEVICE_SECURE_PROGRAMMING + if (!LoadDACCertAndKey(dacData, &mFactoryData)) + { + ChipLogError(DeviceLayer, "Failed to inject dac data"); + return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + } +#endif + // Check if factory data version is correct if (mFactoryData.version != CONFIG_CHIP_FACTORY_DATA_VERSION) { diff --git a/src/platform/telink/FactoryDataProvider.h b/src/platform/telink/FactoryDataProvider.h index 18bb8f3bea6867..f7b443f874566b 100644 --- a/src/platform/telink/FactoryDataProvider.h +++ b/src/platform/telink/FactoryDataProvider.h @@ -31,6 +31,9 @@ namespace chip { namespace DeviceLayer { __attribute__((section(".bss"))) static uint8_t mFactoryDataBuffer[FIXED_PARTITION_SIZE(factory_partition)]; +#if CHIP_DEVICE_SECURE_PROGRAMMING +__attribute__((section(".bss"))) static uint8_t mDACDataBuffer[FIXED_PARTITION_SIZE(dac_keypair_partition)]; +#endif struct InternalFlashFactoryData { @@ -62,6 +65,24 @@ struct ExternalFlashFactoryData return CHIP_NO_ERROR; } +#if CHIP_DEVICE_SECURE_PROGRAMMING + CHIP_ERROR GetDACDataPartition(uint8_t *& data, size_t & dataSize) + { + int ret = flash_read(mFlashDevice, FIXED_PARTITION_OFFSET(dac_keypair_partition), mDACDataBuffer, + FIXED_PARTITION_SIZE(dac_keypair_partition)); + + if (ret != 0) + { + return CHIP_ERROR_READ_FAILED; + } + + data = mDACDataBuffer; + dataSize = FIXED_PARTITION_SIZE(dac_keypair_partition); + + return CHIP_NO_ERROR; + } +#endif + CHIP_ERROR ProtectFactoryDataPartitionAgainstWrite() { return CHIP_ERROR_NOT_IMPLEMENTED; } const struct device * mFlashDevice = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));