Skip to content

Commit

Permalink
Minor issue fixes, keystore backup support, version bump (#45)
Browse files Browse the repository at this point in the history
* PMU irq pulling improvements

* NRF SDK unexpected flash allocation conflict workaround

* axp2101 battery temp. accuracy issue fix

* device keystore backup to uicr support

* version bump to 2.3.1

* downgrade prevention

---------

Signed-off-by: Adam BZH <adam@onekey.so>
  • Loading branch information
424778940z authored Jul 16, 2024
1 parent f8bbd58 commit c996464
Show file tree
Hide file tree
Showing 12 changed files with 433 additions and 37 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ add_custom_target(
${CMAKE_PROJECT_NAME}_BL_CONF ALL
COMMAND ${DIR_UTILS}/nrfutil
settings generate --family NRF52 --bootloader-version 2 --bl-settings-version 2
--app-boot-validation VALIDATE_ECDSA_P256_SHA256 --application ${FILE_INPUT_APP} --application-version 4
--app-boot-validation VALIDATE_ECDSA_P256_SHA256 --application ${FILE_INPUT_APP} --application-version 5
--sd-boot-validation VALIDATE_ECDSA_P256_SHA256 --softdevice ${FILE_INPUT_SD}
--key-file ${FILE_KEY} ${FILE_INPUT_BL_CONFIG}
DEPENDS ${CMAKE_PROJECT_NAME}_OUT_DIR ${CMAKE_PROJECT_NAME}_UTIL ${CMAKE_PROJECT_NAME}_KEY app
Expand Down Expand Up @@ -151,7 +151,7 @@ add_custom_target(
${CMAKE_PROJECT_NAME}_OTA_BIN ALL
COMMAND ${DIR_UTILS}/nrfutil pkg generate
--hw-version 52 --sd-req 0xCB
--application ${FILE_INPUT_APP} --application-version 4 --app-boot-validation VALIDATE_ECDSA_P256_SHA256
--application ${FILE_INPUT_APP} --application-version 5 --app-boot-validation VALIDATE_ECDSA_P256_SHA256
--key-file ${FILE_KEY} ${FILE_OUTPUT_ZIP}
COMMAND ${PYTHON_RUNNER} ${DIR_UTILS}/ota_to_onekey_bin.py ${FILE_OUTPUT_ZIP} ${FILE_OUTPUT_OTA_BIN}
DEPENDS ${CMAKE_PROJECT_NAME}_OUT_DIR ${CMAKE_PROJECT_NAME}_UTIL ${CMAKE_PROJECT_NAME}_KEY dfu app
Expand Down
1 change: 1 addition & 0 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ target_sources(
${CMAKE_PROJECT_NAME} PRIVATE
${NRF_SDK_SRC}
../drivers/nrf_i2c.c
../drivers/nrf_uicr.c
../drivers/nrf_flash.c
../drivers/pmu/pmu.c
../drivers/pmu/ntc_util.c
Expand Down
8 changes: 6 additions & 2 deletions app/ble_app_gcc_nrf52.ld
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ GROUP(-lgcc -lc -lnosys)
MEMORY
{
RAM (rwx) : ORIGIN = 0x20003268, LENGTH = 0xCD98
CONFIG (rw) : ORIGIN = 0x6D000, LENGTH = 0x1000
FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x47000
CONFIG (rw) : ORIGIN = 0x6A000, LENGTH = 0x1000
FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x44000
/* Note: FDS from SDK using few pages of flash without mention in this file! */
/* size depends on sdk_config.h settings for FDS_VIRTUAL_PAGE_SIZE and FDS_VIRTUAL_PAGES */
/* the spcace counts down from the end of flash or bootloader, towards app space */
/* this unexpected and hidden flash allocation is really odd to see in a commercial SDK */
}

SECTIONS
Expand Down
219 changes: 206 additions & 13 deletions app/device_config.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
// own headers
#include "device_config.h"
#include "ecdsa.h"

// std library
#include <memory.h>

// sdk
#include "crc32.h"
#define NRF_LOG_MODULE_NAME DeviceConfig
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
NRF_LOG_MODULE_REGISTER();

#include "util_macros.h"
// project library
#include "nrf_flash.h"
#include "ecdsa.h"
#include "nrf_uicr.h"
#include "util_macros.h"

#define EC_E_BOOL_R_BOOL(expr) ExecuteCheck_ADV(expr, true, { return false; })

Expand Down Expand Up @@ -41,13 +50,36 @@ static bool deviceCfg_keystore_convert_legacy(deviceCfg_keystore_t* converted)
memcpy(&(converted->private_key), &(keystore_legacy->private_key), sizeof(converted->private_key));
memcpy(&(converted->public_key), &(keystore_legacy->public_key), sizeof(converted->public_key));

// calculate crc32
converted->crc32 = deviceCfg_keystore_crc32(converted);

// backup to uicr
if ( !deviceCfg_keystore_backup_to_uicr(converted) )
return false;

// do not wipe the legacy store, just in case

return true;
}
#endif

static uint32_t deviceCfg_keystore_crc32(deviceCfg_keystore_t* keystore)
static bool deviceCfg_keystore_write_to_uicr(deviceCfg_keystore_t* keystore)
{
// write to uicr
if ( !uicr_update_customer((uint8_t*)(keystore), sizeof(deviceCfg_keystore_t)) )
return false;

// no need to wait busy as UICR programming is a blocking operation
// we are not going to reboot, since we don't need it to be available ASAP
return true;
}

static bool deviceCfg_keystore_read_from_uicr(deviceCfg_keystore_t* keystore)
{
return uicr_get_customer((uint8_t*)keystore, sizeof(deviceCfg_keystore_t));
}

uint32_t deviceCfg_keystore_crc32(deviceCfg_keystore_t* keystore)
{
uint32_t crc32 = 0;
crc32 = crc32_compute((uint8_t*)(&(keystore->private_key)), sizeof(keystore->private_key), NULL);
Expand All @@ -61,16 +93,90 @@ bool deviceCfg_keystore_validate(deviceCfg_keystore_t* keystore)
return (keystore->crc32 == deviceCfg_keystore_crc32(keystore));
}

void deviceCfg_keystore_setup(deviceCfg_keystore_t* keystore)
bool deviceCfg_keystore_restore_from_uicr(deviceCfg_keystore_t* keystore)
{
// try convert legacy
if ( !deviceCfg_keystore_convert_legacy(keystore) )
{
// no legacy found, setup new
generate_ecdsa_keypair(keystore->private_key, keystore->public_key);
}
deviceCfg_keystore_t keystore_uicr;

if ( !deviceCfg_keystore_read_from_uicr(&keystore_uicr) )
return false;

// check if update needed
if ( memcmp(keystore, &keystore_uicr, sizeof(deviceCfg_keystore_t)) == 0 )
return true;

// check if both valid
bool is_flash_keystore_valid = deviceCfg_keystore_validate(keystore);
bool is_uicr_keystore_valid = deviceCfg_keystore_validate(&keystore_uicr);

// if uicr copy in valid, no restore action
if ( !is_uicr_keystore_valid )
return false;

// if uicr copy invalid, no flag check, restore only
if ( is_uicr_keystore_valid && !is_flash_keystore_valid )
memcpy(keystore, &keystore_uicr, sizeof(deviceCfg_keystore_t));

// if both copy valid, flash copy check flag, no restore action if flash copy flag locked
if ( is_uicr_keystore_valid && is_flash_keystore_valid )
if ( keystore->flag_locked != DEVICE_CONFIG_FLAG_MAGIC )
memcpy(keystore, &keystore_uicr, sizeof(deviceCfg_keystore_t));

return true;
}

bool deviceCfg_keystore_backup_to_uicr(deviceCfg_keystore_t* keystore)
{
deviceCfg_keystore_t keystore_uicr;

// don't care the result, either empty or corrupted we still proceed.
deviceCfg_keystore_read_from_uicr(&keystore_uicr);

// check if both valid
bool is_flash_keystore_valid = deviceCfg_keystore_validate(keystore);
bool is_uicr_keystore_valid = deviceCfg_keystore_validate(&keystore_uicr);

// if flash copy in valid, no backup action
if ( !is_flash_keystore_valid )
return false;

// if uicr copy invalid, no flag check, backup only
if ( is_flash_keystore_valid && !is_uicr_keystore_valid )
if ( !deviceCfg_keystore_write_to_uicr(keystore) )
return false;

// if both copy valid, uicr copy check flag, no backup action if uicr copy flag locked
if ( is_flash_keystore_valid && is_uicr_keystore_valid )
if ( keystore_uicr.flag_locked != DEVICE_CONFIG_FLAG_MAGIC )
if ( !deviceCfg_keystore_write_to_uicr(keystore) )
return false;

return true;
}

bool deviceCfg_keystore_backup_compare(deviceCfg_keystore_t* keystore)
{
deviceCfg_keystore_t keystore_uicr;

// don't care the result, either empty or corrupted we still proceed.
deviceCfg_keystore_read_from_uicr(&keystore_uicr);

// check if update needed
return (memcmp(keystore, &keystore_uicr, sizeof(deviceCfg_keystore_t)) == 0);
}

bool deviceCfg_keystore_setup_new(deviceCfg_keystore_t* keystore)
{
// set up new keypair
generate_ecdsa_keypair(keystore->private_key, keystore->public_key);

// calculate crc32
keystore->crc32 = deviceCfg_keystore_crc32(keystore);

// backup to uicr
if ( !deviceCfg_keystore_backup_to_uicr(keystore) )
return false;

return true;
}

bool deviceCfg_keystore_lock(deviceCfg_keystore_t* keystore)
Expand All @@ -86,6 +192,9 @@ bool deviceCfg_keystore_lock(deviceCfg_keystore_t* keystore)
// lock
keystore->flag_locked = DEVICE_CONFIG_FLAG_MAGIC;

// backup to uicr
// not here, will be triggered next reboot

return true;
}

Expand Down Expand Up @@ -138,6 +247,26 @@ void deviceCfg_settings_setup(deviceCfg_settings_t* settings)
// ======================
// Device Configs

#if DEVICE_CONFIG_HANDLE_LEGACY
#define DEVICE_CONFIG_LEGACY_ADDR 0x6D000U

static bool device_config_convert_legacy()
{
deviceCfg_t devcfg_legacy;

EC_E_BOOL_R_BOOL(flash_read(DEVICE_CONFIG_LEGACY_ADDR, (uint8_t*)(&devcfg_legacy), sizeof(deviceCfg_t)));

if ( devcfg_legacy.header != DEVICE_CONFIG_HEADER_MAGIC || devcfg_legacy.version != DEVICE_CONFIG_VERSION )
return false;

memcpy(&deviceConfig, &devcfg_legacy, sizeof(deviceCfg_t));

EC_E_BOOL_R_BOOL(flash_erase(DEVICE_CONFIG_LEGACY_ADDR, DEVICE_CONFIG_SIZE));

return true;
}
#endif

bool device_config_commit(void)
{
EC_E_BOOL_R_BOOL(sizeof(deviceCfg_t) < DEVICE_CONFIG_SIZE);
Expand All @@ -156,11 +285,20 @@ bool device_config_init(void)
// flash init
EC_E_BOOL_R_BOOL(flash_init());

// try convert legacy
if ( device_config_convert_legacy() )
{
NRF_LOG_INFO("Converted from legacy format!");
// legacy found, commit
EC_E_BOOL_R_BOOL(device_config_commit());
NRF_LOG_INFO("Commited!");
}

// read
EC_E_BOOL_R_BOOL(flash_read(DEVICE_CONFIG_ADDR, (uint8_t*)(&deviceConfig), sizeof(deviceCfg_t)))

// check header
// currently only one version of config layout, so not upgrade provided
// currently only one version of config layout, no upgrade method provided
if ( deviceConfig.header != DEVICE_CONFIG_HEADER_MAGIC || deviceConfig.version != DEVICE_CONFIG_VERSION )
{
deviceConfig.header = DEVICE_CONFIG_HEADER_MAGIC;
Expand All @@ -171,20 +309,75 @@ bool device_config_init(void)
// check keystore
if ( !deviceCfg_keystore_validate(&(deviceConfig.keystore)) )
{
deviceCfg_keystore_setup(&(deviceConfig.keystore));
commit_pending = true;
// current flash keystore invalid
NRF_LOG_INFO("Keystore invalid!");

do
{
// try restore from uicr
if ( deviceCfg_keystore_restore_from_uicr(&(deviceConfig.keystore)) )
{
NRF_LOG_INFO("Keystore restored from uicr");
commit_pending = true;
break;
}

// try convert from legacy store
if ( deviceCfg_keystore_convert_legacy(&(deviceConfig.keystore)) )
{
NRF_LOG_INFO("Keystore converted from legacy store");
commit_pending = true;
break;
}

// setup new
if ( deviceCfg_keystore_setup_new(&(deviceConfig.keystore)) )
{
NRF_LOG_INFO("Keystore generated new keypair");
commit_pending = true;
break;
}
}
while ( false );
}
else
NRF_LOG_INFO("Keystore valid!");

// check keystore backup
if ( !deviceCfg_keystore_backup_compare(&(deviceConfig.keystore)) )
{
NRF_LOG_INFO("Keystore uicr compare missmatch, backup required");
if ( deviceCfg_keystore_backup_to_uicr(&(deviceConfig.keystore)) )
{
NRF_LOG_INFO("Keystore backup to uicr succeed");
}
else
{
NRF_LOG_INFO("Keystore backup to uicr failed");
}
}
else
{
NRF_LOG_INFO("Keystore uicr compare match, backup skiped");
}

// check settings
if ( !deviceCfg_settings_validate(&(deviceConfig.settings)) )
{
NRF_LOG_INFO("Settings invalid!");
deviceCfg_settings_setup(&(deviceConfig.settings));
NRF_LOG_INFO("Settings created new!");
commit_pending = true;
}
else
NRF_LOG_INFO("Settings valid!");

// commit (if any pending)
if ( commit_pending )
{
EC_E_BOOL_R_BOOL(device_config_commit());
NRF_LOG_INFO("Commited!");
}

// set interface pointer
deviceConfig_p = &deviceConfig;
Expand Down
17 changes: 11 additions & 6 deletions app/device_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ typedef struct
uint8_t private_key[32]; // 8*UINT32
uint8_t public_key[64]; // 16*UINT32
} deviceCfg_keystore_t;
uint32_t deviceCfg_keystore_crc32(deviceCfg_keystore_t* keystore);
bool deviceCfg_keystore_validate(deviceCfg_keystore_t* keystore);
void deviceCfg_keystore_setup(deviceCfg_keystore_t* keystore);
bool deviceCfg_keystore_restore_from_uicr(deviceCfg_keystore_t* keystore);
bool deviceCfg_keystore_backup_to_uicr(deviceCfg_keystore_t* keystore);
bool deviceCfg_keystore_backup_compare(deviceCfg_keystore_t* keystore);
bool deviceCfg_keystore_setup_new(deviceCfg_keystore_t* keystore);
bool deviceCfg_keystore_lock(deviceCfg_keystore_t* keystore);

// *** general settings ***
Expand All @@ -35,12 +39,13 @@ void deviceCfg_settings_setup(deviceCfg_settings_t* settings);

// ======================
// Device Configs
#define DEVICE_CONFIG_HANDLE_LEGACY 1

#define DEVICE_CONFIG_HEADER_MAGIC 0xAAAAAAAAU
#define DEVICE_CONFIG_FLAG_MAGIC 0xa55aa55aU
#define DEVICE_CONFIG_ADDR 0x6D000U
#define DEVICE_CONFIG_SIZE 0x1000U
#define DEVICE_CONFIG_VERSION 1U
#define DEVICE_CONFIG_HEADER_MAGIC 0xAAAAAAAAU
#define DEVICE_CONFIG_FLAG_MAGIC 0xa55aa55aU
#define DEVICE_CONFIG_ADDR 0x6A000U
#define DEVICE_CONFIG_SIZE 0x1000U
#define DEVICE_CONFIG_VERSION 1U

typedef struct
{
Expand Down
2 changes: 1 addition & 1 deletion app/firmware_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
0xEEBBEE /**< DUMMY Organisation Unique ID. Will be passed to Device Information Service. You shall use the \
Organisation Unique ID relevant for your Company */
#define HW_REVISION "1.0.0"
#define FW_REVISION "2.3.0"
#define FW_REVISION "2.3.1"
#define SW_REVISION "s132_nrf52_7.0.1"
#define BT_REVISION "1.0.1"

Expand Down
Loading

0 comments on commit c996464

Please sign in to comment.