From 122fb42e19f37838ff5402673a75ccf8299d94ea Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Thu, 16 May 2024 15:04:11 +0200 Subject: [PATCH 01/35] Allow temporarily disabling protected device mode via a backup register --- hal/src/nRF52840/bootloader.cpp | 6 ++++++ hal/src/rtl872x/bootloader.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/hal/src/nRF52840/bootloader.cpp b/hal/src/nRF52840/bootloader.cpp index 95c47edd7c..9b4b40b148 100644 --- a/hal/src/nRF52840/bootloader.cpp +++ b/hal/src/nRF52840/bootloader.cpp @@ -89,6 +89,12 @@ uint16_t bootloader_get_version(void) } int bootloader_init_security_mode(void* reserved) { + // Skip setting the security mode if device protection is temporarily disabled + uint32_t disabled = HAL_Core_Read_Backup_Register(BKP_DR_08); + if (disabled) { + return 0; + } + CHECK_TRUE(FLASH_VerifyCRC32(FLASH_INTERNAL, BOOTLOADER_ADDR, FLASH_ModuleLength(FLASH_INTERNAL, BOOTLOADER_ADDR)), SYSTEM_ERROR_BAD_DATA); module_info_security_mode_ext_t ext = {}; ext.ext.length = sizeof(ext); diff --git a/hal/src/rtl872x/bootloader.cpp b/hal/src/rtl872x/bootloader.cpp index 4d34077bc9..f02848b2a3 100644 --- a/hal/src/rtl872x/bootloader.cpp +++ b/hal/src/rtl872x/bootloader.cpp @@ -90,6 +90,12 @@ uint16_t bootloader_get_version(void) } int bootloader_init_security_mode(void* reserved) { + // Skip setting the security mode if device protection is temporarily disabled + uint32_t disabled = HAL_Core_Read_Backup_Register(BKP_DR_08); + if (disabled) { + return 0; + } + CHECK_TRUE(FLASH_VerifyCRC32(FLASH_INTERNAL, BOOTLOADER_ADDR, FLASH_ModuleLength(FLASH_INTERNAL, BOOTLOADER_ADDR)), SYSTEM_ERROR_BAD_DATA); module_info_security_mode_ext_t ext = {}; ext.ext.length = sizeof(ext); From 8f20dec1a2fcb003611f9f83c5d0920e8e546c9d Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Mon, 20 May 2024 23:42:14 +0200 Subject: [PATCH 02/35] Add a control request for temporarily disabling device protection --- proto_defs/shared | 2 +- proto_defs/src/control/config.pb.c | 7 + proto_defs/src/control/config.pb.h | 65 +++++++- services/src/security_mode.cpp | 1 + system/inc/system_control.h | 1 + system/src/control/config.cpp | 215 ++++++++++++++++++++++++- system/src/control/config.h | 1 + system/src/system_control_internal.cpp | 4 + 8 files changed, 287 insertions(+), 9 deletions(-) diff --git a/proto_defs/shared b/proto_defs/shared index 6147552100..a36c2f3161 160000 --- a/proto_defs/shared +++ b/proto_defs/shared @@ -1 +1 @@ -Subproject commit 6147552100a405b6e3207c8df6a45d7e59515dd6 +Subproject commit a36c2f3161c51df870f51371dfd89429284f03c7 diff --git a/proto_defs/src/control/config.pb.c b/proto_defs/src/control/config.pb.c index e2facc4fc5..56b10e955d 100644 --- a/proto_defs/src/control/config.pb.c +++ b/proto_defs/src/control/config.pb.c @@ -132,6 +132,12 @@ PB_BIND(particle_ctrl_GetProtectedStateRequest, particle_ctrl_GetProtectedStateR PB_BIND(particle_ctrl_GetProtectedStateReply, particle_ctrl_GetProtectedStateReply, AUTO) +PB_BIND(particle_ctrl_SetProtectedStateRequest, particle_ctrl_SetProtectedStateRequest, AUTO) + + +PB_BIND(particle_ctrl_SetProtectedStateReply, particle_ctrl_SetProtectedStateReply, AUTO) + + PB_BIND(particle_ctrl_SystemResetRequest, particle_ctrl_SystemResetRequest, AUTO) @@ -168,3 +174,4 @@ PB_BIND(particle_ctrl_StopNyanSignalReply, particle_ctrl_StopNyanSignalReply, AU + diff --git a/proto_defs/src/control/config.pb.h b/proto_defs/src/control/config.pb.h index 4f52ee5257..c9b2f26f2e 100644 --- a/proto_defs/src/control/config.pb.h +++ b/proto_defs/src/control/config.pb.h @@ -47,6 +47,13 @@ typedef enum _particle_ctrl_Feature { particle_ctrl_Feature_ETHERNET_DETECTION = 1 /* Ethernet FeatherWing detection on boot */ } particle_ctrl_Feature; +/* Note: Use the same values as defined by the security_key_type enum */ +typedef enum _particle_ctrl_SetProtectedStateRequest_Action { + particle_ctrl_SetProtectedStateRequest_Action_RESET = 0, /* Invalid key */ + particle_ctrl_SetProtectedStateRequest_Action_DISABLE_REQUEST = 1, /* TCP device private key */ + particle_ctrl_SetProtectedStateRequest_Action_DISABLE_CONFIRM = 2 /* TCP device public key */ +} particle_ctrl_SetProtectedStateRequest_Action; + /* Struct definitions */ /* Get the device ID */ typedef struct _particle_ctrl_GetDeviceIdRequest { @@ -208,6 +215,7 @@ typedef struct _particle_ctrl_GetNcpFirmwareVersionReply { typedef struct _particle_ctrl_GetProtectedStateReply { bool state; + bool overridden; } particle_ctrl_GetProtectedStateReply; typedef struct _particle_ctrl_GetSecurityKeyRequest { @@ -261,6 +269,21 @@ typedef struct _particle_ctrl_SetFeatureRequest { bool enabled; } particle_ctrl_SetFeatureRequest; +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateReply_client_nonce_t; +typedef struct _particle_ctrl_SetProtectedStateReply { + bool has_client_nonce; + particle_ctrl_SetProtectedStateReply_client_nonce_t client_nonce; + pb_callback_t client_signature; +} particle_ctrl_SetProtectedStateReply; + +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateRequest_server_nonce_t; +typedef struct _particle_ctrl_SetProtectedStateRequest { + particle_ctrl_SetProtectedStateRequest_Action action; + bool has_server_nonce; + particle_ctrl_SetProtectedStateRequest_server_nonce_t server_nonce; + pb_callback_t server_signature; +} particle_ctrl_SetProtectedStateRequest; + typedef struct _particle_ctrl_SetSecurityKeyRequest { particle_ctrl_SecurityKeyType type; /* Key type */ pb_callback_t data; /* Key data in DER format */ @@ -309,6 +332,10 @@ typedef struct _particle_ctrl_SetStartupModeRequest { #define _particle_ctrl_Feature_MAX particle_ctrl_Feature_ETHERNET_DETECTION #define _particle_ctrl_Feature_ARRAYSIZE ((particle_ctrl_Feature)(particle_ctrl_Feature_ETHERNET_DETECTION+1)) +#define _particle_ctrl_SetProtectedStateRequest_Action_MIN particle_ctrl_SetProtectedStateRequest_Action_RESET +#define _particle_ctrl_SetProtectedStateRequest_Action_MAX particle_ctrl_SetProtectedStateRequest_Action_DISABLE_CONFIRM +#define _particle_ctrl_SetProtectedStateRequest_Action_ARRAYSIZE ((particle_ctrl_SetProtectedStateRequest_Action)(particle_ctrl_SetProtectedStateRequest_Action_DISABLE_CONFIRM+1)) + #ifdef __cplusplus extern "C" { @@ -356,7 +383,9 @@ extern "C" { #define particle_ctrl_SetStartupModeRequest_init_default {_particle_ctrl_DeviceMode_MIN} #define particle_ctrl_SetStartupModeReply_init_default {0} #define particle_ctrl_GetProtectedStateRequest_init_default {0} -#define particle_ctrl_GetProtectedStateReply_init_default {0} +#define particle_ctrl_GetProtectedStateReply_init_default {0, 0} +#define particle_ctrl_SetProtectedStateRequest_init_default {_particle_ctrl_SetProtectedStateRequest_Action_MIN, false, {0, {0}}, {{NULL}, NULL}} +#define particle_ctrl_SetProtectedStateReply_init_default {false, {0, {0}}, {{NULL}, NULL}} #define particle_ctrl_SystemResetRequest_init_default {0} #define particle_ctrl_SystemResetReply_init_default {0} #define particle_ctrl_SetFeatureRequest_init_default {_particle_ctrl_Feature_MIN, 0} @@ -408,7 +437,9 @@ extern "C" { #define particle_ctrl_SetStartupModeRequest_init_zero {_particle_ctrl_DeviceMode_MIN} #define particle_ctrl_SetStartupModeReply_init_zero {0} #define particle_ctrl_GetProtectedStateRequest_init_zero {0} -#define particle_ctrl_GetProtectedStateReply_init_zero {0} +#define particle_ctrl_GetProtectedStateReply_init_zero {0, 0} +#define particle_ctrl_SetProtectedStateRequest_init_zero {_particle_ctrl_SetProtectedStateRequest_Action_MIN, false, {0, {0}}, {{NULL}, NULL}} +#define particle_ctrl_SetProtectedStateReply_init_zero {false, {0, {0}}, {{NULL}, NULL}} #define particle_ctrl_SystemResetRequest_init_zero {0} #define particle_ctrl_SystemResetReply_init_zero {0} #define particle_ctrl_SetFeatureRequest_init_zero {_particle_ctrl_Feature_MIN, 0} @@ -430,6 +461,7 @@ extern "C" { #define particle_ctrl_GetNcpFirmwareVersionReply_version_tag 1 #define particle_ctrl_GetNcpFirmwareVersionReply_module_version_tag 2 #define particle_ctrl_GetProtectedStateReply_state_tag 1 +#define particle_ctrl_GetProtectedStateReply_overridden_tag 2 #define particle_ctrl_GetSecurityKeyRequest_type_tag 1 #define particle_ctrl_GetSerialNumberReply_serial_tag 1 #define particle_ctrl_GetServerAddressReply_address_tag 1 @@ -443,6 +475,11 @@ extern "C" { #define particle_ctrl_SetDeviceSetupDoneRequest_done_tag 1 #define particle_ctrl_SetFeatureRequest_feature_tag 1 #define particle_ctrl_SetFeatureRequest_enabled_tag 2 +#define particle_ctrl_SetProtectedStateReply_client_nonce_tag 1 +#define particle_ctrl_SetProtectedStateReply_client_signature_tag 2 +#define particle_ctrl_SetProtectedStateRequest_action_tag 1 +#define particle_ctrl_SetProtectedStateRequest_server_nonce_tag 2 +#define particle_ctrl_SetProtectedStateRequest_server_signature_tag 3 #define particle_ctrl_SetSecurityKeyRequest_type_tag 1 #define particle_ctrl_SetSecurityKeyRequest_data_tag 2 #define particle_ctrl_SetServerAddressRequest_protocol_tag 1 @@ -666,10 +703,24 @@ X(a, STATIC, SINGULAR, UENUM, mode, 1) #define particle_ctrl_GetProtectedStateRequest_DEFAULT NULL #define particle_ctrl_GetProtectedStateReply_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, state, 1) +X(a, STATIC, SINGULAR, BOOL, state, 1) \ +X(a, STATIC, SINGULAR, BOOL, overridden, 2) #define particle_ctrl_GetProtectedStateReply_CALLBACK NULL #define particle_ctrl_GetProtectedStateReply_DEFAULT NULL +#define particle_ctrl_SetProtectedStateRequest_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, action, 1) \ +X(a, STATIC, OPTIONAL, BYTES, server_nonce, 2) \ +X(a, CALLBACK, OPTIONAL, BYTES, server_signature, 3) +#define particle_ctrl_SetProtectedStateRequest_CALLBACK pb_default_field_callback +#define particle_ctrl_SetProtectedStateRequest_DEFAULT NULL + +#define particle_ctrl_SetProtectedStateReply_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, BYTES, client_nonce, 1) \ +X(a, CALLBACK, OPTIONAL, BYTES, client_signature, 2) +#define particle_ctrl_SetProtectedStateReply_CALLBACK pb_default_field_callback +#define particle_ctrl_SetProtectedStateReply_DEFAULT NULL + #define particle_ctrl_SystemResetRequest_FIELDLIST(X, a) \ #define particle_ctrl_SystemResetRequest_CALLBACK NULL @@ -763,6 +814,8 @@ extern const pb_msgdesc_t particle_ctrl_SetStartupModeRequest_msg; extern const pb_msgdesc_t particle_ctrl_SetStartupModeReply_msg; extern const pb_msgdesc_t particle_ctrl_GetProtectedStateRequest_msg; extern const pb_msgdesc_t particle_ctrl_GetProtectedStateReply_msg; +extern const pb_msgdesc_t particle_ctrl_SetProtectedStateRequest_msg; +extern const pb_msgdesc_t particle_ctrl_SetProtectedStateReply_msg; extern const pb_msgdesc_t particle_ctrl_SystemResetRequest_msg; extern const pb_msgdesc_t particle_ctrl_SystemResetReply_msg; extern const pb_msgdesc_t particle_ctrl_SetFeatureRequest_msg; @@ -817,6 +870,8 @@ extern const pb_msgdesc_t particle_ctrl_StopNyanSignalReply_msg; #define particle_ctrl_SetStartupModeReply_fields &particle_ctrl_SetStartupModeReply_msg #define particle_ctrl_GetProtectedStateRequest_fields &particle_ctrl_GetProtectedStateRequest_msg #define particle_ctrl_GetProtectedStateReply_fields &particle_ctrl_GetProtectedStateReply_msg +#define particle_ctrl_SetProtectedStateRequest_fields &particle_ctrl_SetProtectedStateRequest_msg +#define particle_ctrl_SetProtectedStateReply_fields &particle_ctrl_SetProtectedStateReply_msg #define particle_ctrl_SystemResetRequest_fields &particle_ctrl_SystemResetRequest_msg #define particle_ctrl_SystemResetReply_fields &particle_ctrl_SystemResetReply_msg #define particle_ctrl_SetFeatureRequest_fields &particle_ctrl_SetFeatureRequest_msg @@ -834,6 +889,8 @@ extern const pb_msgdesc_t particle_ctrl_StopNyanSignalReply_msg; /* particle_ctrl_SetSecurityKeyRequest_size depends on runtime parameters */ /* particle_ctrl_GetSecurityKeyReply_size depends on runtime parameters */ /* particle_ctrl_GetServerAddressReply_size depends on runtime parameters */ +/* particle_ctrl_SetProtectedStateRequest_size depends on runtime parameters */ +/* particle_ctrl_SetProtectedStateReply_size depends on runtime parameters */ #define particle_ctrl_GetDeviceIdReply_size 26 #define particle_ctrl_GetDeviceIdRequest_size 0 #define particle_ctrl_GetDeviceModeReply_size 2 @@ -841,7 +898,7 @@ extern const pb_msgdesc_t particle_ctrl_StopNyanSignalReply_msg; #define particle_ctrl_GetFeatureReply_size 2 #define particle_ctrl_GetFeatureRequest_size 2 #define particle_ctrl_GetNcpFirmwareVersionRequest_size 0 -#define particle_ctrl_GetProtectedStateReply_size 2 +#define particle_ctrl_GetProtectedStateReply_size 4 #define particle_ctrl_GetProtectedStateRequest_size 0 #define particle_ctrl_GetSecurityKeyRequest_size 2 #define particle_ctrl_GetSerialNumberReply_size 18 diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index 97799e86ec..8c80b6a041 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -100,6 +100,7 @@ int security_mode_check_request(security_mode_transport transport, uint16_t id) if (transport == SECURITY_MODE_TRANSPORT_USB || transport == SECURITY_MODE_TRANSPORT_BLE) { switch (id) { + case CTRL_REQUEST_SET_PROTECTED_STATE: case CTRL_REQUEST_GET_PROTECTED_STATE: case CTRL_REQUEST_DEVICE_ID: case CTRL_REQUEST_APP_CUSTOM: { diff --git a/system/inc/system_control.h b/system/inc/system_control.h index 6c97c14e24..22b92c1431 100644 --- a/system/inc/system_control.h +++ b/system/inc/system_control.h @@ -61,6 +61,7 @@ typedef enum ctrl_request_type { CTRL_REQUEST_IS_DEVICE_SETUP_DONE = 74, CTRL_REQUEST_SET_STARTUP_MODE = 75, CTRL_REQUEST_GET_PROTECTED_STATE = 76, + CTRL_REQUEST_SET_PROTECTED_STATE = 77, CTRL_REQUEST_LOG_CONFIG = 80, CTRL_REQUEST_GET_MODULE_INFO = 90, CTRL_REQUEST_GET_ASSET_INFO = 91, diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index c70f6d1b1f..5f89c53a0c 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -26,16 +26,18 @@ #include "deviceid_hal.h" #include "core_hal.h" +#include "ota_flash_hal_impl.h" #include "hal_platform.h" #include "platforms.h" +#include "dct.h" +#include "eckeygen.h" +#include "sha256.h" +#include "random.h" #include "bytes2hexbuf.h" +#include "endian_util.h" #include "check.h" -#include "dct.h" - -#include "ota_flash_hal_impl.h" - #if HAL_PLATFORM_NCP #include "network/ncp/wifi/ncp.h" #include "network/ncp/wifi/wifi_network_manager.h" @@ -44,8 +46,11 @@ #include "control/config.pb.h" +#include #include +#include + #define PB(_name) particle_ctrl_##_name #define PB_FIELDS(_name) particle_ctrl_##_name##_fields @@ -55,8 +60,203 @@ namespace control { namespace config { +namespace { + using namespace particle::control::common; +struct ProtectedStateChangeContext { + char clientNonce[32]; +}; + +std::unique_ptr g_protectedStateChangeCtx; +bool g_protectedStateChangePending = false; + +inline void setProtectedStateOverride() { + HAL_Core_Write_Backup_Register(BKP_DR_08, 1); // Disable protection +} + +inline void clearProtectedStateOverride() { + HAL_Core_Write_Backup_Register(BKP_DR_08, 0); // Use normal protection settings +} + +inline bool protectedStateOverride() { + return HAL_Core_Read_Backup_Register(BKP_DR_08); +} + +// Completion handler for system_ctrl_set_result() +void systemResetCompletionHandler(int result, void* data) { + system_reset(SYSTEM_RESET_MODE_NORMAL, RESET_REASON_CONFIG_UPDATE, 0 /* value */, 0 /* flags */, nullptr /* reserved */); +} + +int getDevicePrivateKey(mbedtls_pk_context& pk) { + std::unique_ptr keyData(new(std::nothrow) uint8_t[DCT_ALT_DEVICE_PRIVATE_KEY_SIZE]); + int r = dct_read_app_data_copy(DCT_ALT_DEVICE_PRIVATE_KEY_OFFSET, keyData.get(), DCT_ALT_DEVICE_PRIVATE_KEY_SIZE); + if (r != 0) { + return SYSTEM_ERROR_IO; + } + size_t keyLen = determine_der_length(keyData.get(), DCT_ALT_DEVICE_PRIVATE_KEY_SIZE); + if (!keyLen) { + return SYSTEM_ERROR_BAD_DATA; + } + CHECK_MBEDTLS(mbedtls_pk_parse_key(&pk, keyData.get(), keyLen, nullptr /* pwd */, 0 /* pwdlen */)); + if (!mbedtls_pk_can_do(&pk, MBEDTLS_PK_ECDSA)) { // Sanity check + return SYSTEM_ERROR_NOT_SUPPORTED; + } + return 0; +} + +int getServerPublicKey(mbedtls_pk_context& pk) { + std::unique_ptr keyData(new(std::nothrow) uint8_t[DCT_ALT_SERVER_PUBLIC_KEY_SIZE]); + int r = dct_read_app_data_copy(DCT_ALT_SERVER_PUBLIC_KEY_OFFSET, keyData.get(), DCT_ALT_SERVER_PUBLIC_KEY_SIZE); + if (r != 0) { + return SYSTEM_ERROR_IO; + } + size_t keyLen = determine_der_length(keyData.get(), DCT_ALT_SERVER_PUBLIC_KEY_SIZE); + if (!keyLen) { + return SYSTEM_ERROR_BAD_DATA; + } + CHECK_MBEDTLS(mbedtls_pk_parse_public_key(&pk, keyData.get(), keyLen)); + return 0; +} + +int updateSha256Delimited(Sha256& sha, const char* data, size_t size) { + uint32_t n = nativeToLittleEndian(size); + CHECK(sha.update((const char*)&n, sizeof(n))); + CHECK(sha.update(data, size)); + return 0; +} + +int setProtectedStateImpl(ctrl_request* req) { + // TODO: Remove this check once the support for TCP is fully removed + if (!HAL_Feature_Get(FEATURE_CLOUD_UDP)) { + return SYSTEM_ERROR_PROTOCOL; + } + if (g_protectedStateChangePending) { + return SYSTEM_ERROR_BUSY; + } + + PB(SetProtectedStateRequest) pbReq = {}; + DecodedString pbServSig(&pbReq.server_signature); + CHECK(decodeRequestMessage(req, &PB(SetProtectedStateRequest_msg), &pbReq)); + + PB(SetProtectedStateReply) pbRep = {}; + bool changePending = false; + + switch (pbReq.action) { + case PB(SetProtectedStateRequest_Action_RESET): { + if (protectedStateOverride()) { + clearProtectedStateOverride(); + changePending = true; + } + g_protectedStateChangeCtx.reset(); + break; + } + case PB(SetProtectedStateRequest_Action_DISABLE_REQUEST): { + g_protectedStateChangeCtx.reset(); + if (security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_NONE) { + return 0; // Not protected + } + std::unique_ptr ctx(new(std::nothrow) ProtectedStateChangeContext()); + if (!ctx) { + return SYSTEM_ERROR_NO_MEMORY; + } + + // Get the device ID and private key + uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; // Binary-encoded + const auto n = hal_get_device_id(devId, sizeof(devId)); + if (n != HAL_DEVICE_ID_SIZE) { + return SYSTEM_ERROR_UNKNOWN; + } + mbedtls_pk_context pk = {}; + mbedtls_pk_init(&pk); + SCOPE_GUARD({ + mbedtls_pk_free(&pk); + }); + CHECK(getDevicePrivateKey(pk)); + + // Generate a client nonce and signature + Random::genSecure(ctx->clientNonce, sizeof(ctx->clientNonce)); + Sha256 sha; + CHECK(sha.init()); + CHECK(sha.start()); + CHECK(sha.update("client", 6)); + CHECK(sha.update((const char*)devId, HAL_DEVICE_ID_SIZE)); + updateSha256Delimited(sha, ctx->clientNonce, sizeof(ctx->clientNonce)); + char hash[Sha256::HASH_SIZE] = {}; + CHECK(sha.finish(hash)); + + uint8_t sig[MBEDTLS_ECDSA_MAX_LEN] = {}; + size_t sigLen = 0; + CHECK_MBEDTLS(mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, (const uint8_t*)hash, sizeof(hash), sig, &sigLen, + mbedtls_default_rng, nullptr /* p_rng */)); + + // Encode a reply + EncodedString pbSig(&pbRep.client_signature, (const char*)sig, sigLen); + static_assert(sizeof(ctx->clientNonce) <= sizeof(pbRep.client_nonce.bytes)); + std::memcpy(pbRep.client_nonce.bytes, ctx->clientNonce, sizeof(ctx->clientNonce)); + pbRep.client_nonce.size = sizeof(ctx->clientNonce); + pbRep.has_client_nonce = true; + CHECK(encodeReplyMessage(req, &PB(SetProtectedStateReply_msg), &pbRep)); + + g_protectedStateChangeCtx = std::move(ctx); + break; + } + case PB(SetProtectedStateRequest_Action_DISABLE_CONFIRM): { + if (!pbReq.has_server_nonce || !pbReq.server_nonce.size) { + return SYSTEM_ERROR_INVALID_ARGUMENT; + } + if (!g_protectedStateChangeCtx) { + return SYSTEM_ERROR_INVALID_STATE; + } + + // Get the device ID and server public key + uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; + const auto n = hal_get_device_id(devId, sizeof(devId)); + if (n != HAL_DEVICE_ID_SIZE) { + return SYSTEM_ERROR_UNKNOWN; + } + mbedtls_pk_context pk = {}; + mbedtls_pk_init(&pk); + SCOPE_GUARD({ + mbedtls_pk_free(&pk); + }); + CHECK(getServerPublicKey(pk)); + + // Validate the server signature + Sha256 sha; + CHECK(sha.init()); + CHECK(sha.start()); + CHECK(sha.update("server", 6)); + CHECK(sha.update((const char*)devId, HAL_DEVICE_ID_SIZE)); + updateSha256Delimited(sha, g_protectedStateChangeCtx->clientNonce, sizeof(g_protectedStateChangeCtx->clientNonce)); + updateSha256Delimited(sha, (const char*)pbReq.server_nonce.bytes, pbReq.server_nonce.size); + char hash[Sha256::HASH_SIZE] = {}; + CHECK(sha.finish(hash)); + + int r = mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA256, (const uint8_t*)hash, sizeof(hash), (const uint8_t*)pbServSig.data, + pbServSig.size); + if (r != 0) { + return SYSTEM_ERROR_NOT_ALLOWED; + } + + g_protectedStateChangeCtx.reset(); + setProtectedStateOverride(); + changePending = true; + break; + } + default: + return SYSTEM_ERROR_INVALID_ARGUMENT; + } + + g_protectedStateChangePending = changePending; + auto compHandler = changePending ? systemResetCompletionHandler : nullptr; + system_ctrl_set_result(req, 0 /* result */, compHandler, nullptr /* data */, nullptr /* reserved */); + + return 0; +} + +} // namespace + int getDeviceId(ctrl_request* req) { uint8_t id[HAL_DEVICE_ID_SIZE] = {}; const auto n = hal_get_device_id(id, sizeof(id)); @@ -206,6 +406,13 @@ int getProtectedState(ctrl_request* req) { return 0; } +void setProtectedState(ctrl_request* req) { + int r = setProtectedStateImpl(req); + if (r < 0) { + system_ctrl_set_result(req, r, nullptr /* handler */, nullptr /* data */, nullptr /* reserved */); + } +} + int setFeature(ctrl_request* req) { PB(SetFeatureRequest) pbReq = {}; CHECK(decodeRequestMessage(req, PB(SetFeatureRequest_fields), &pbReq)); diff --git a/system/src/control/config.h b/system/src/control/config.h index bfd06843ba..abc16ed185 100644 --- a/system/src/control/config.h +++ b/system/src/control/config.h @@ -33,6 +33,7 @@ int setDeviceSetupDone(ctrl_request* req); int isDeviceSetupDone(ctrl_request* req); int setStartupMode(ctrl_request* req); int getProtectedState(ctrl_request* req); +void setProtectedState(ctrl_request* req); int setFeature(ctrl_request* req); int getFeature(ctrl_request* req); int echo(ctrl_request* req); diff --git a/system/src/system_control_internal.cpp b/system/src/system_control_internal.cpp index 4ee3d2bf3a..abf39c8453 100644 --- a/system/src/system_control_internal.cpp +++ b/system/src/system_control_internal.cpp @@ -228,6 +228,10 @@ void SystemControl::processRequest(ctrl_request* req, ControlRequestChannel* cha setResult(req, control::config::getProtectedState(req)); break; } + case CTRL_REQUEST_SET_PROTECTED_STATE: { + control::config::setProtectedState(req); + break; + } case CTRL_REQUEST_ECHO: { setResult(req, control::config::echo(req)); break; From 8241e9918c0406b50abee03526aec644d4fe400c Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Tue, 21 May 2024 14:15:08 +0200 Subject: [PATCH 03/35] Minor fixes --- system/src/control/config.cpp | 41 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index 5f89c53a0c..999868ded3 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -64,22 +64,22 @@ namespace { using namespace particle::control::common; -struct ProtectedStateChangeContext { +struct SecurityModeChangeContext { char clientNonce[32]; }; -std::unique_ptr g_protectedStateChangeCtx; -bool g_protectedStateChangePending = false; +std::unique_ptr g_securityModeChangeCtx; +bool g_securityModeChangePending = false; -inline void setProtectedStateOverride() { - HAL_Core_Write_Backup_Register(BKP_DR_08, 1); // Disable protection +inline void setSecurityModeOverride() { + HAL_Core_Write_Backup_Register(BKP_DR_08, 1); // Disable security } -inline void clearProtectedStateOverride() { - HAL_Core_Write_Backup_Register(BKP_DR_08, 0); // Use normal protection settings +inline void clearSecurityModeOverride() { + HAL_Core_Write_Backup_Register(BKP_DR_08, 0); // Use default security mode } -inline bool protectedStateOverride() { +inline bool isSecurityModeOverridden() { return HAL_Core_Read_Backup_Register(BKP_DR_08); } @@ -131,7 +131,7 @@ int setProtectedStateImpl(ctrl_request* req) { if (!HAL_Feature_Get(FEATURE_CLOUD_UDP)) { return SYSTEM_ERROR_PROTOCOL; } - if (g_protectedStateChangePending) { + if (g_securityModeChangePending) { return SYSTEM_ERROR_BUSY; } @@ -144,19 +144,19 @@ int setProtectedStateImpl(ctrl_request* req) { switch (pbReq.action) { case PB(SetProtectedStateRequest_Action_RESET): { - if (protectedStateOverride()) { - clearProtectedStateOverride(); + if (isSecurityModeOverridden()) { + clearSecurityModeOverride(); changePending = true; } - g_protectedStateChangeCtx.reset(); + g_securityModeChangeCtx.reset(); break; } case PB(SetProtectedStateRequest_Action_DISABLE_REQUEST): { - g_protectedStateChangeCtx.reset(); + g_securityModeChangeCtx.reset(); if (security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_NONE) { return 0; // Not protected } - std::unique_ptr ctx(new(std::nothrow) ProtectedStateChangeContext()); + std::unique_ptr ctx(new(std::nothrow) SecurityModeChangeContext()); if (!ctx) { return SYSTEM_ERROR_NO_MEMORY; } @@ -198,14 +198,14 @@ int setProtectedStateImpl(ctrl_request* req) { pbRep.has_client_nonce = true; CHECK(encodeReplyMessage(req, &PB(SetProtectedStateReply_msg), &pbRep)); - g_protectedStateChangeCtx = std::move(ctx); + g_securityModeChangeCtx = std::move(ctx); break; } case PB(SetProtectedStateRequest_Action_DISABLE_CONFIRM): { if (!pbReq.has_server_nonce || !pbReq.server_nonce.size) { return SYSTEM_ERROR_INVALID_ARGUMENT; } - if (!g_protectedStateChangeCtx) { + if (!g_securityModeChangeCtx) { return SYSTEM_ERROR_INVALID_STATE; } @@ -228,8 +228,8 @@ int setProtectedStateImpl(ctrl_request* req) { CHECK(sha.start()); CHECK(sha.update("server", 6)); CHECK(sha.update((const char*)devId, HAL_DEVICE_ID_SIZE)); - updateSha256Delimited(sha, g_protectedStateChangeCtx->clientNonce, sizeof(g_protectedStateChangeCtx->clientNonce)); updateSha256Delimited(sha, (const char*)pbReq.server_nonce.bytes, pbReq.server_nonce.size); + updateSha256Delimited(sha, g_securityModeChangeCtx->clientNonce, sizeof(g_securityModeChangeCtx->clientNonce)); char hash[Sha256::HASH_SIZE] = {}; CHECK(sha.finish(hash)); @@ -239,8 +239,8 @@ int setProtectedStateImpl(ctrl_request* req) { return SYSTEM_ERROR_NOT_ALLOWED; } - g_protectedStateChangeCtx.reset(); - setProtectedStateOverride(); + g_securityModeChangeCtx.reset(); + setSecurityModeOverride(); changePending = true; break; } @@ -248,7 +248,7 @@ int setProtectedStateImpl(ctrl_request* req) { return SYSTEM_ERROR_INVALID_ARGUMENT; } - g_protectedStateChangePending = changePending; + g_securityModeChangePending = changePending; auto compHandler = changePending ? systemResetCompletionHandler : nullptr; system_ctrl_set_result(req, 0 /* result */, compHandler, nullptr /* data */, nullptr /* reserved */); @@ -402,6 +402,7 @@ int setStartupMode(ctrl_request* req) { int getProtectedState(ctrl_request* req) { PB(GetProtectedStateReply) pbRep = {}; pbRep.state = security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_PROTECTED; + pbRep.overridden = isSecurityModeOverridden(); CHECK(encodeReplyMessage(req, PB(GetProtectedStateReply_fields), &pbRep)); return 0; } From dd232bf1782dac2026e95a7ac505163b0e36c9a9 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Thu, 23 May 2024 15:57:23 +0200 Subject: [PATCH 04/35] Add timeout for confirmation request --- system/src/control/config.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index 999868ded3..9cd86cb341 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -26,6 +26,7 @@ #include "deviceid_hal.h" #include "core_hal.h" +#include "timer_hal.h" #include "ota_flash_hal_impl.h" #include "hal_platform.h" #include "platforms.h" @@ -66,6 +67,7 @@ using namespace particle::control::common; struct SecurityModeChangeContext { char clientNonce[32]; + uint64_t requestTime; }; std::unique_ptr g_securityModeChangeCtx; @@ -198,6 +200,7 @@ int setProtectedStateImpl(ctrl_request* req) { pbRep.has_client_nonce = true; CHECK(encodeReplyMessage(req, &PB(SetProtectedStateReply_msg), &pbRep)); + ctx->requestTime = hal_timer_millis(nullptr); g_securityModeChangeCtx = std::move(ctx); break; } @@ -208,6 +211,10 @@ int setProtectedStateImpl(ctrl_request* req) { if (!g_securityModeChangeCtx) { return SYSTEM_ERROR_INVALID_STATE; } + if (hal_timer_millis(nullptr) - g_securityModeChangeCtx->requestTime >= 60000) { + g_securityModeChangeCtx.reset(); + return SYSTEM_ERROR_TIMEOUT; + } // Get the device ID and server public key uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; From ad2609d32a94fbad708744d9617bb9f9f453a916 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Thu, 23 May 2024 16:35:17 +0200 Subject: [PATCH 05/35] Minor bugfixes and refactoring --- hal/src/nRF52840/bootloader.cpp | 3 +-- hal/src/rtl872x/bootloader.cpp | 3 +-- services/inc/security_mode.h | 4 ++++ services/src/security_mode.cpp | 15 +++++++++++++++ system/src/control/config.cpp | 20 ++++---------------- system/src/system_info.cpp | 5 ++++- 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/hal/src/nRF52840/bootloader.cpp b/hal/src/nRF52840/bootloader.cpp index 9b4b40b148..10733e483b 100644 --- a/hal/src/nRF52840/bootloader.cpp +++ b/hal/src/nRF52840/bootloader.cpp @@ -90,8 +90,7 @@ uint16_t bootloader_get_version(void) int bootloader_init_security_mode(void* reserved) { // Skip setting the security mode if device protection is temporarily disabled - uint32_t disabled = HAL_Core_Read_Backup_Register(BKP_DR_08); - if (disabled) { + if (security_mode_is_overridden()) { return 0; } diff --git a/hal/src/rtl872x/bootloader.cpp b/hal/src/rtl872x/bootloader.cpp index f02848b2a3..1068f64f86 100644 --- a/hal/src/rtl872x/bootloader.cpp +++ b/hal/src/rtl872x/bootloader.cpp @@ -91,8 +91,7 @@ uint16_t bootloader_get_version(void) int bootloader_init_security_mode(void* reserved) { // Skip setting the security mode if device protection is temporarily disabled - uint32_t disabled = HAL_Core_Read_Backup_Register(BKP_DR_08); - if (disabled) { + if (security_mode_is_overridden()) { return 0; } diff --git a/services/inc/security_mode.h b/services/inc/security_mode.h index 000e2ce1f0..f47cf25fbf 100644 --- a/services/inc/security_mode.h +++ b/services/inc/security_mode.h @@ -49,6 +49,10 @@ int security_mode_set(module_info_security_mode mode, void* reserved); int security_mode_get(void* reserved); int security_mode_check_request(security_mode_transport transport, uint16_t id); +void security_mode_set_override(); +void security_mode_clear_override(); +bool security_mode_is_overridden(); + #ifdef __cplusplus } diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index 8c80b6a041..e02585911f 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -23,9 +23,12 @@ #include #include "system_control.h" #include "flash_device_hal.h" +#include "core_hal.h" namespace { +const uint32_t SECURITY_MODE_OVERRIDE_MAGIC = 0x8cd69adfu; + module_info_security_mode sSecurityMode = MODULE_INFO_SECURITY_MODE_NONE; } // namespace @@ -121,3 +124,15 @@ int security_mode_check_request(security_mode_transport transport, uint16_t id) return SYSTEM_ERROR_PROTECTED; } + +void security_mode_set_override() { + HAL_Core_Write_Backup_Register(BKP_DR_08, SECURITY_MODE_OVERRIDE_MAGIC); // Disable security +} + +void security_mode_clear_override() { + HAL_Core_Write_Backup_Register(BKP_DR_08, 0); // Use default security mode +} + +bool security_mode_is_overridden() { + return HAL_Core_Read_Backup_Register(BKP_DR_08) == SECURITY_MODE_OVERRIDE_MAGIC; +} diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index 9cd86cb341..b95e7dc963 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -73,18 +73,6 @@ struct SecurityModeChangeContext { std::unique_ptr g_securityModeChangeCtx; bool g_securityModeChangePending = false; -inline void setSecurityModeOverride() { - HAL_Core_Write_Backup_Register(BKP_DR_08, 1); // Disable security -} - -inline void clearSecurityModeOverride() { - HAL_Core_Write_Backup_Register(BKP_DR_08, 0); // Use default security mode -} - -inline bool isSecurityModeOverridden() { - return HAL_Core_Read_Backup_Register(BKP_DR_08); -} - // Completion handler for system_ctrl_set_result() void systemResetCompletionHandler(int result, void* data) { system_reset(SYSTEM_RESET_MODE_NORMAL, RESET_REASON_CONFIG_UPDATE, 0 /* value */, 0 /* flags */, nullptr /* reserved */); @@ -146,8 +134,8 @@ int setProtectedStateImpl(ctrl_request* req) { switch (pbReq.action) { case PB(SetProtectedStateRequest_Action_RESET): { - if (isSecurityModeOverridden()) { - clearSecurityModeOverride(); + if (security_mode_is_overridden()) { + security_mode_clear_override(); changePending = true; } g_securityModeChangeCtx.reset(); @@ -247,7 +235,7 @@ int setProtectedStateImpl(ctrl_request* req) { } g_securityModeChangeCtx.reset(); - setSecurityModeOverride(); + security_mode_set_override(); changePending = true; break; } @@ -409,7 +397,7 @@ int setStartupMode(ctrl_request* req) { int getProtectedState(ctrl_request* req) { PB(GetProtectedStateReply) pbRep = {}; pbRep.state = security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_PROTECTED; - pbRep.overridden = isSecurityModeOverridden(); + pbRep.overridden = security_mode_is_overridden(); CHECK(encodeReplyMessage(req, PB(GetProtectedStateReply_fields), &pbRep)); return 0; } diff --git a/system/src/system_info.cpp b/system/src/system_info.cpp index ca75f5c8a9..1316be062b 100644 --- a/system/src/system_info.cpp +++ b/system/src/system_info.cpp @@ -474,7 +474,10 @@ bool system_module_info_pb(appender_fn appender, void* append_data, void* reserv // Firmware modules EncodeFirmwareModules modules(&pbDesc.firmware_modules, EncodeFirmwareModules::Flag::SYSTEM_INFO_CLOUD); - pbDesc.protected_state = (security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_PROTECTED); + // Report the actual status of device protection, even if it's temporarily disabled + if (security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_PROTECTED || security_mode_is_overridden()) { + pbDesc.protected_state = true; + } // IMEI, ICCID, modem firmware version EncodedString pbImei(&pbDesc.imei); From 92634b9a0cd2243526bd4c7bec834ab9f7ad25f8 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 24 May 2024 15:57:16 +0200 Subject: [PATCH 06/35] Use a fake server key for testing --- system/src/control/config.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index b95e7dc963..a769c61441 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -55,6 +55,8 @@ #define PB(_name) particle_ctrl_##_name #define PB_FIELDS(_name) particle_ctrl_##_name##_fields +#define USE_TEST_SERVER_KEY 1 // FIXME + namespace particle { namespace control { @@ -73,6 +75,21 @@ struct SecurityModeChangeContext { std::unique_ptr g_securityModeChangeCtx; bool g_securityModeChangePending = false; +#if USE_TEST_SERVER_KEY + +const uint8_t TEST_SERVER_KEY[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x02, 0x49, 0x5a, 0xee, 0xee, 0x46, 0xc4, 0x25, 0x22, + 0x13, 0xa0, 0x95, 0xd5, 0x80, 0x17, 0x0e, 0x8a, 0xc2, 0xc1, 0x10, 0xb6, + 0x42, 0x70, 0xd3, 0x29, 0x8c, 0xbf, 0x63, 0x53, 0x5a, 0x8e, 0xc3, 0x64, + 0xea, 0x6b, 0xef, 0xf5, 0xde, 0xd7, 0x66, 0x11, 0x91, 0x19, 0x96, 0x65, + 0x38, 0x38, 0x2f, 0x8d, 0x8e, 0xc0, 0xe1, 0xaa, 0x6d, 0x9b, 0x9c, 0xf1, + 0xc9, 0xef, 0x1d, 0x28, 0x9c, 0x6e, 0x81 +}; + +#endif // USE_TEST_SERVER_KEY + // Completion handler for system_ctrl_set_result() void systemResetCompletionHandler(int result, void* data) { system_reset(SYSTEM_RESET_MODE_NORMAL, RESET_REASON_CONFIG_UPDATE, 0 /* value */, 0 /* flags */, nullptr /* reserved */); @@ -96,6 +113,9 @@ int getDevicePrivateKey(mbedtls_pk_context& pk) { } int getServerPublicKey(mbedtls_pk_context& pk) { +#if USE_TEST_SERVER_KEY + CHECK_MBEDTLS(mbedtls_pk_parse_public_key(&pk, TEST_SERVER_KEY, sizeof(TEST_SERVER_KEY) / sizeof(TEST_SERVER_KEY[0]))); +#else std::unique_ptr keyData(new(std::nothrow) uint8_t[DCT_ALT_SERVER_PUBLIC_KEY_SIZE]); int r = dct_read_app_data_copy(DCT_ALT_SERVER_PUBLIC_KEY_OFFSET, keyData.get(), DCT_ALT_SERVER_PUBLIC_KEY_SIZE); if (r != 0) { @@ -106,6 +126,7 @@ int getServerPublicKey(mbedtls_pk_context& pk) { return SYSTEM_ERROR_BAD_DATA; } CHECK_MBEDTLS(mbedtls_pk_parse_public_key(&pk, keyData.get(), keyLen)); +#endif // !USE_TEST_SERVER_KEY return 0; } From 7527d73c086f34a2db818a52a94641df4d575bb1 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 24 May 2024 16:07:10 +0200 Subject: [PATCH 07/35] Bugfixes --- system/src/control/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index a769c61441..e6300208ff 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -165,7 +165,7 @@ int setProtectedStateImpl(ctrl_request* req) { case PB(SetProtectedStateRequest_Action_DISABLE_REQUEST): { g_securityModeChangeCtx.reset(); if (security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_NONE) { - return 0; // Not protected + break; // Not protected } std::unique_ptr ctx(new(std::nothrow) SecurityModeChangeContext()); if (!ctx) { From fc1568da492d87f8de2facfd941d5a7209b32125 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Wed, 29 May 2024 15:50:18 +0200 Subject: [PATCH 08/35] Allow disabling device protection on the fly --- bootloader/src/nRF52840/nrf_it.c | 2 + bootloader/src/rtl872x/rtl_it.c | 2 + hal/inc/bootloader.h | 2 - hal/src/nRF52840/bootloader.cpp | 18 -- hal/src/rtl872x/bootloader.cpp | 18 -- platform/MCU/nRF52840/inc/dct.h | 2 +- .../MCU/nRF52840/inc/platform_system_flags.h | 7 +- platform/MCU/nRF52840/src/hw_config.c | 9 +- platform/MCU/rtl872x/inc/dct.h | 2 +- platform/MCU/rtl872x/src/hw_config.c | 9 +- services/inc/security_mode.h | 26 ++- services/src/security_mode.cpp | 209 ++++++++++++++++-- system/src/control/config.cpp | 2 +- system/src/main.cpp | 2 + system/src/system_control_internal.cpp | 2 +- system/src/system_info_encoding.cpp | 2 +- 16 files changed, 231 insertions(+), 83 deletions(-) diff --git a/bootloader/src/nRF52840/nrf_it.c b/bootloader/src/nRF52840/nrf_it.c index 1606455e09..f84b14e8e6 100644 --- a/bootloader/src/nRF52840/nrf_it.c +++ b/bootloader/src/nRF52840/nrf_it.c @@ -24,6 +24,7 @@ #include "hw_config.h" #include "button_hal.h" #include "hal_platform_nrf52840_config.h" +#include "security_mode.h" extern void Timing_Decrement(void); @@ -120,6 +121,7 @@ void UsageFault_Handler(void) void SysTick_Handler(void) { System1MsTick(); + security_mode_notify_system_tick(); Timing_Decrement(); #if HAL_PLATFORM_BUTTON_DEBOUNCE_IN_SYSTICK diff --git a/bootloader/src/rtl872x/rtl_it.c b/bootloader/src/rtl872x/rtl_it.c index 01eb6a4a49..fa53e0c501 100644 --- a/bootloader/src/rtl872x/rtl_it.c +++ b/bootloader/src/rtl872x/rtl_it.c @@ -23,6 +23,7 @@ #include "button_hal.h" #include "hal_platform_config.h" #include "interrupts_irq.h" +#include "security_mode.h" extern void Timing_Decrement(void); @@ -170,6 +171,7 @@ void SecureFault_Handler(void) { void SysTick_Handler(void) { System1MsTick(); + security_mode_notify_system_tick(); Timing_Decrement(); #if HAL_PLATFORM_BUTTON_DEBOUNCE_IN_SYSTICK diff --git a/hal/inc/bootloader.h b/hal/inc/bootloader.h index a5f20d93b2..a200dbdb50 100644 --- a/hal/inc/bootloader.h +++ b/hal/inc/bootloader.h @@ -36,8 +36,6 @@ int bootloader_update(const void* bootloader_image, unsigned length); // Make sure we have only one function to retrieve the bootloader version going forward. uint16_t bootloader_get_version(void); -int bootloader_init_security_mode(void* reserved); - #ifdef __cplusplus } #endif diff --git a/hal/src/nRF52840/bootloader.cpp b/hal/src/nRF52840/bootloader.cpp index 10733e483b..2bf4ddba02 100644 --- a/hal/src/nRF52840/bootloader.cpp +++ b/hal/src/nRF52840/bootloader.cpp @@ -87,21 +87,3 @@ uint16_t bootloader_get_version(void) } return info.module_version; } - -int bootloader_init_security_mode(void* reserved) { - // Skip setting the security mode if device protection is temporarily disabled - if (security_mode_is_overridden()) { - return 0; - } - - CHECK_TRUE(FLASH_VerifyCRC32(FLASH_INTERNAL, BOOTLOADER_ADDR, FLASH_ModuleLength(FLASH_INTERNAL, BOOTLOADER_ADDR)), SYSTEM_ERROR_BAD_DATA); - module_info_security_mode_ext_t ext = {}; - ext.ext.length = sizeof(ext); - CHECK(security_mode_find_extension(HAL_STORAGE_ID_INTERNAL_FLASH, BOOTLOADER_ADDR, &ext)); - - if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { - security_mode_set(ext.security_mode, nullptr); - } - - return 0; -} diff --git a/hal/src/rtl872x/bootloader.cpp b/hal/src/rtl872x/bootloader.cpp index 1068f64f86..49d2b9a2f2 100644 --- a/hal/src/rtl872x/bootloader.cpp +++ b/hal/src/rtl872x/bootloader.cpp @@ -88,21 +88,3 @@ uint16_t bootloader_get_version(void) // hard code to unblock porting work for now return 1001; } - -int bootloader_init_security_mode(void* reserved) { - // Skip setting the security mode if device protection is temporarily disabled - if (security_mode_is_overridden()) { - return 0; - } - - CHECK_TRUE(FLASH_VerifyCRC32(FLASH_INTERNAL, BOOTLOADER_ADDR, FLASH_ModuleLength(FLASH_INTERNAL, BOOTLOADER_ADDR)), SYSTEM_ERROR_BAD_DATA); - module_info_security_mode_ext_t ext = {}; - ext.ext.length = sizeof(ext); - CHECK(security_mode_find_extension(HAL_STORAGE_ID_INTERNAL_FLASH, BOOTLOADER_ADDR, &ext)); - - if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { - security_mode_set(ext.security_mode, nullptr); - } - - return 0; -} diff --git a/platform/MCU/nRF52840/inc/dct.h b/platform/MCU/nRF52840/inc/dct.h index 0099694cd3..0cd25a5e3c 100644 --- a/platform/MCU/nRF52840/inc/dct.h +++ b/platform/MCU/nRF52840/inc/dct.h @@ -255,7 +255,7 @@ STATIC_ASSERT_FLAGS_OFFSET(Factory_Reset_Done_SysFlag, 17); STATIC_ASSERT_FLAGS_OFFSET(StartupMode_SysFlag, 18); STATIC_ASSERT_FLAGS_OFFSET(FeaturesEnabled_SysFlag, 19); STATIC_ASSERT_FLAGS_OFFSET(RCC_CSR_SysFlag, 20); -STATIC_ASSERT_FLAGS_OFFSET(reserved, 24); +STATIC_ASSERT_FLAGS_OFFSET(reserved, 30); #ifdef __cplusplus diff --git a/platform/MCU/nRF52840/inc/platform_system_flags.h b/platform/MCU/nRF52840/inc/platform_system_flags.h index 7bef6abe8b..80b50cdd95 100644 --- a/platform/MCU/nRF52840/inc/platform_system_flags.h +++ b/platform/MCU/nRF52840/inc/platform_system_flags.h @@ -36,7 +36,12 @@ typedef struct __attribute__((packed)) platform_system_flags { uint8_t FeaturesEnabled_SysFlag; // default is 0xFF all features enabled. If any bits are cleared in the bottom 4-bits, then the upper 4 bits should be the logical inverse of these. // This is to prevent against corrupted data causing the bootloader to be unavailable. uint32_t RCC_CSR_SysFlag; - uint16_t reserved[4]; + + uint8_t security_mode_is_overridden; // If 1, the security mode is temporarily lowered to NONE, otherwise the normal security mode is in effect + uint8_t security_mode_override_reset_count; // Number of system resets after which the normal security mode will be restored + uint32_t security_mode_override_timeout; // Timeout, in seconds, after which the normal security mode will be restored + + uint16_t reserved[1]; } platform_system_flags_t; PARTICLE_STATIC_ASSERT(platform_system_flags_size_changed, sizeof(platform_system_flags_t) == 32); diff --git a/platform/MCU/nRF52840/src/hw_config.c b/platform/MCU/nRF52840/src/hw_config.c index 7ba072cf80..8959554564 100644 --- a/platform/MCU/nRF52840/src/hw_config.c +++ b/platform/MCU/nRF52840/src/hw_config.c @@ -202,7 +202,10 @@ void Set_System(void) SPARK_ASSERT(!hal_flash_init()); SPARK_ASSERT(!hal_exflash_init()); - bootloader_init_security_mode(NULL); + security_mode_init(); +#if MODULE_FUNCTION == MOD_FUNC_BOOTLOADER + security_mode_notify_system_reset(); +#endif configure_uicr(); @@ -324,7 +327,7 @@ __attribute__((section(".retained_system_flags"))) platform_system_flags_t syste #define SYSTEM_FLAGS_MAGIC_NUMBER 0x1ADEACC0u -void Load_SystemFlags() +void Load_SystemFlags() // TODO: Rename to Init_SystemFlags() and call once on startup { // if the header does not match the expected magic value, then initialize if (system_flags.header!=SYSTEM_FLAGS_MAGIC_NUMBER) { @@ -333,7 +336,7 @@ void Load_SystemFlags() } } -void Save_SystemFlags() +void Save_SystemFlags() // TODO: Remove { // nothing to do here } diff --git a/platform/MCU/rtl872x/inc/dct.h b/platform/MCU/rtl872x/inc/dct.h index 3d26e273b3..dc82f011f2 100644 --- a/platform/MCU/rtl872x/inc/dct.h +++ b/platform/MCU/rtl872x/inc/dct.h @@ -249,7 +249,7 @@ STATIC_ASSERT_FLAGS_OFFSET(StartupMode_SysFlag, 18); STATIC_ASSERT_FLAGS_OFFSET(FeaturesEnabled_SysFlag, 19); STATIC_ASSERT_FLAGS_OFFSET(RCC_CSR_SysFlag, 20); STATIC_ASSERT_FLAGS_OFFSET(restore_backup_ram, 24); -STATIC_ASSERT_FLAGS_OFFSET(reserved, 26); +STATIC_ASSERT_FLAGS_OFFSET(reserved, 32); #ifdef __cplusplus diff --git a/platform/MCU/rtl872x/src/hw_config.c b/platform/MCU/rtl872x/src/hw_config.c index 663d51a73d..5a39438443 100644 --- a/platform/MCU/rtl872x/src/hw_config.c +++ b/platform/MCU/rtl872x/src/hw_config.c @@ -376,7 +376,10 @@ void Set_System(void) /* Configure flash */ SPARK_ASSERT(!hal_exflash_init()); - bootloader_init_security_mode(NULL); + security_mode_init(); +#if MODULE_FUNCTION == MOD_FUNC_BOOTLOADER + security_mode_notify_system_reset(); +#endif efuse_configure(); DWT_Init(); @@ -495,7 +498,7 @@ __attribute__((section(".retained_system_flags"))) platform_system_flags_t syste #define SYSTEM_FLAGS_MAGIC_NUMBER 0x1ADEACC0u -void Load_SystemFlags() +void Load_SystemFlags() // TODO: Rename to Init_SystemFlags() and call once on startup { // if the header does not match the expected magic value, then initialize if (system_flags.header!=SYSTEM_FLAGS_MAGIC_NUMBER) { @@ -504,7 +507,7 @@ void Load_SystemFlags() } } -void Save_SystemFlags() +void Save_SystemFlags() // TODO: Remove { // nothing to do here } diff --git a/services/inc/security_mode.h b/services/inc/security_mode.h index f47cf25fbf..398a54d7f1 100644 --- a/services/inc/security_mode.h +++ b/services/inc/security_mode.h @@ -19,6 +19,7 @@ #include "module_info.h" #include "system_error.h" + #include #define CHECK_SECURITY_MODE_PROTECTED() \ @@ -32,11 +33,7 @@ _ret _fn ## _protected _args; \ _ret _fn _args -#include "storage_hal.h" - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus +#include "storage_hal.h" // Needs SECURITY_MODE_PROTECTED_FN typedef enum security_mode_transport { SECURITY_MODE_TRANSPORT_NONE = 0, @@ -44,16 +41,25 @@ typedef enum security_mode_transport { SECURITY_MODE_TRANSPORT_BLE = 2 } security_mode_transport; -int security_mode_find_extension(hal_storage_id storageId, uintptr_t start, module_info_security_mode_ext_t* ext); -int security_mode_set(module_info_security_mode mode, void* reserved); +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +int security_mode_init(); + int security_mode_get(void* reserved); -int security_mode_check_request(security_mode_transport transport, uint16_t id); -void security_mode_set_override(); +int security_mode_find_module_extension(hal_storage_id storageId, uintptr_t start, module_info_security_mode_ext_t* ext); +int security_mode_check_control_request(security_mode_transport transport, uint16_t id); + +void security_mode_override_to_none(); void security_mode_clear_override(); bool security_mode_is_overridden(); +void security_mode_notify_system_ready(); // Called in the system firmware +void security_mode_notify_system_reset(); // Called in the bootloader +void security_mode_notify_system_tick(); // ditto + #ifdef __cplusplus } - #endif // __cplusplus diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index e02585911f..728b6691a1 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -15,25 +15,111 @@ * License along with this library; if not, see . */ +#include + #include "security_mode.h" #include "flash_mal.h" #include "system_error.h" #include "check.h" #include "scope_guard.h" -#include +#include "atomic_section.h" #include "system_control.h" #include "flash_device_hal.h" -#include "core_hal.h" +#include "concurrent_hal.h" +#include "ota_flash_hal_impl.h" +#include "hw_config.h" namespace { -const uint32_t SECURITY_MODE_OVERRIDE_MAGIC = 0x8cd69adfu; +volatile int sCurrentSecurityMode = MODULE_INFO_SECURITY_MODE_NONE; +int sNormalSecurityMode = MODULE_INFO_SECURITY_MODE_NONE; + +#if MODULE_FUNCTION == MOD_FUNC_BOOTLOADER + +volatile int sSystemTickCount = 1000; + +#else + +os_timer_t sTimer = nullptr; + +void timerCallback(os_timer_t timer); + +void stopTimer() { + if (sTimer) { + int r = os_timer_change(sTimer, OS_TIMER_CHANGE_STOP, false /* fromISR */, 0 /* period */, 0xffffffffu /* block */, nullptr /* reserved */); + if (r != 0) { + LOG_DEBUG(ERROR, "Failed to stop timer"); // Should not happen + } + } +} + +int startTimer() { + if (!sTimer) { + int r = os_timer_create(&sTimer, 1000 /* period */, timerCallback, nullptr /* timer_id */, false /* one_shot */, nullptr /* reserved */); + if (r != 0) { + return SYSTEM_ERROR_NO_MEMORY; + } + } else { + stopTimer(); + } + int r = os_timer_change(sTimer, OS_TIMER_CHANGE_START, false /* fromISR */, 0 /* period */, 0xffffffffu /* block */, nullptr /* reserved */); + if (r != 0) { + return SYSTEM_ERROR_UNKNOWN; // Should not happen + } + return 0; +} + +void timerCallback(os_timer_t) { + bool stop = false; + ATOMIC_BLOCK() { + Load_SystemFlags(); + if (system_flags.security_mode_is_overridden) { + if (system_flags.security_mode_override_timeout > 0) { + --system_flags.security_mode_override_timeout; + } + if (!system_flags.security_mode_override_timeout) { + system_flags.security_mode_is_overridden = 0; + } + Save_SystemFlags(); + } + if (!system_flags.security_mode_is_overridden) { + sCurrentSecurityMode = sNormalSecurityMode; + stop = true; + } + } + if (stop) { + stopTimer(); + } +} -module_info_security_mode sSecurityMode = MODULE_INFO_SECURITY_MODE_NONE; +#endif // MODULE_FUNCTION != MOD_FUNC_BOOTLOADER } // namespace -int security_mode_find_extension(hal_storage_id storageId, uintptr_t start, module_info_security_mode_ext_t* securityModeExt) { +int security_mode_init() { + // Note that this function is called early on boot, before the heap is configured and C++ + // constructors are called + if (!FLASH_VerifyCRC32(FLASH_INTERNAL, module_bootloader.start_address, FLASH_ModuleLength(FLASH_INTERNAL, module_bootloader.start_address))) { + return SYSTEM_ERROR_BAD_DATA; + } + module_info_security_mode_ext_t ext = {}; + ext.ext.length = sizeof(ext); + CHECK(security_mode_find_module_extension(HAL_STORAGE_ID_INTERNAL_FLASH, module_bootloader.start_address, &ext)); + if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { + sNormalSecurityMode = ext.security_mode; + } + if (sNormalSecurityMode != MODULE_INFO_SECURITY_MODE_NONE) { + Load_SystemFlags(); + sCurrentSecurityMode = system_flags.security_mode_is_overridden ? MODULE_INFO_SECURITY_MODE_NONE : sNormalSecurityMode; + } + return 0; +} + +int security_mode_get(void* reserved) { + return sCurrentSecurityMode; +} + +int security_mode_find_module_extension(hal_storage_id storageId, uintptr_t start, module_info_security_mode_ext_t* securityModeExt) { module_info_t info = {}; int flashDevId = -1; if (storageId == HAL_STORAGE_ID_INTERNAL_FLASH) { @@ -84,26 +170,13 @@ int security_mode_find_extension(hal_storage_id storageId, uintptr_t start, modu return SYSTEM_ERROR_NOT_FOUND; } -int security_mode_set(module_info_security_mode mode, void* reserved) { - if (sSecurityMode == MODULE_INFO_SECURITY_MODE_NONE) { - sSecurityMode = mode; - return 0; - } - return SYSTEM_ERROR_INVALID_STATE; -} - -int security_mode_get(void* reserved) { - return sSecurityMode; -} - -int security_mode_check_request(security_mode_transport transport, uint16_t id) { +int security_mode_check_control_request(security_mode_transport transport, uint16_t id) { if (security_mode_get(nullptr) != MODULE_INFO_SECURITY_MODE_PROTECTED) { return 0; } if (transport == SECURITY_MODE_TRANSPORT_USB || transport == SECURITY_MODE_TRANSPORT_BLE) { switch (id) { - case CTRL_REQUEST_SET_PROTECTED_STATE: case CTRL_REQUEST_GET_PROTECTED_STATE: case CTRL_REQUEST_DEVICE_ID: case CTRL_REQUEST_APP_CUSTOM: { @@ -112,6 +185,14 @@ int security_mode_check_request(security_mode_transport transport, uint16_t id) } } + if (transport == SECURITY_MODE_TRANSPORT_USB) { + switch (id) { + case CTRL_REQUEST_SET_PROTECTED_STATE: { + return 0; + } + } + } + if (transport == SECURITY_MODE_TRANSPORT_BLE) { switch (id) { case CTRL_REQUEST_WIFI_SCAN_NETWORKS: @@ -125,14 +206,96 @@ int security_mode_check_request(security_mode_transport transport, uint16_t id) return SYSTEM_ERROR_PROTECTED; } -void security_mode_set_override() { - HAL_Core_Write_Backup_Register(BKP_DR_08, SECURITY_MODE_OVERRIDE_MAGIC); // Disable security +void security_mode_override_to_none() { + if (sNormalSecurityMode == MODULE_INFO_SECURITY_MODE_NONE) { + return; + } + ATOMIC_BLOCK() { + Load_SystemFlags(); + system_flags.security_mode_is_overridden = 1; + system_flags.security_mode_override_reset_count = 20; + system_flags.security_mode_override_timeout = 24 * 60 * 60; // Seconds + Save_SystemFlags(); + sCurrentSecurityMode = MODULE_INFO_SECURITY_MODE_NONE; + } + startTimer(); } void security_mode_clear_override() { - HAL_Core_Write_Backup_Register(BKP_DR_08, 0); // Use default security mode + if (sCurrentSecurityMode == sNormalSecurityMode) { + return; + } + ATOMIC_BLOCK() { + Load_SystemFlags(); + system_flags.security_mode_is_overridden = 0; + Save_SystemFlags(); + sCurrentSecurityMode = sNormalSecurityMode; + } + stopTimer(); } bool security_mode_is_overridden() { - return HAL_Core_Read_Backup_Register(BKP_DR_08) == SECURITY_MODE_OVERRIDE_MAGIC; + return sCurrentSecurityMode != sNormalSecurityMode; } + +#if MODULE_FUNCTION == MOD_FUNC_BOOTLOADER + +void security_mode_notify_system_reset() { + if (sCurrentSecurityMode == sNormalSecurityMode) { + return; + } + ATOMIC_BLOCK() { + Load_SystemFlags(); + if (system_flags.security_mode_override_reset_count > 0) { + --system_flags.security_mode_override_reset_count; + } + if (!system_flags.security_mode_override_reset_count) { + system_flags.security_mode_is_overridden = 0; + } + Save_SystemFlags(); + if (!system_flags.security_mode_is_overridden) { + sCurrentSecurityMode = sNormalSecurityMode; + } + } +} + +void security_mode_notify_system_tick() { + if (sCurrentSecurityMode == sNormalSecurityMode) { + return; + } + if (sSystemTickCount > 0) { + --sSystemTickCount; + } + if (!sSystemTickCount) { + ATOMIC_BLOCK() { + Load_SystemFlags(); + if (system_flags.security_mode_is_overridden) { + if (system_flags.security_mode_override_timeout > 0) { + --system_flags.security_mode_override_timeout; + } + if (!system_flags.security_mode_override_timeout) { + system_flags.security_mode_is_overridden = 0; + } + Save_SystemFlags(); + } + if (!system_flags.security_mode_is_overridden) { + sCurrentSecurityMode = sNormalSecurityMode; + } + } + sSystemTickCount = 1000; + } +} + +#else + +void security_mode_notify_system_ready() { + if (sCurrentSecurityMode == sNormalSecurityMode) { + return; + } + int r = startTimer(); + if (r < 0) { + LOG(ERROR, "Failed to start timer: %d", r); + } +} + +#endif // MODULE_FUNCTION != MOD_FUNC_BOOTLOADER diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index e6300208ff..6dbbaee4b3 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -256,7 +256,7 @@ int setProtectedStateImpl(ctrl_request* req) { } g_securityModeChangeCtx.reset(); - security_mode_set_override(); + security_mode_override_to_none(); changePending = true; break; } diff --git a/system/src/main.cpp b/system/src/main.cpp index cd06fb28d7..21446d227f 100644 --- a/system/src/main.cpp +++ b/system/src/main.cpp @@ -767,6 +767,8 @@ void app_setup_and_loop(void) // Start the diagnostics service diag_command(DIAG_SERVICE_CMD_START, nullptr, nullptr); + security_mode_notify_system_ready(); + DEBUG("Hello from Particle!"); String s = spark_deviceID(); INFO("Device %s started", s.c_str()); diff --git a/system/src/system_control_internal.cpp b/system/src/system_control_internal.cpp index abf39c8453..b9851948be 100644 --- a/system/src/system_control_internal.cpp +++ b/system/src/system_control_internal.cpp @@ -115,7 +115,7 @@ void SystemControl::run() { } void SystemControl::processRequest(ctrl_request* req, ControlRequestChannel* channel) { - auto secModeCheck = security_mode_check_request(channel == &bleChannel_ ? SECURITY_MODE_TRANSPORT_BLE : SECURITY_MODE_TRANSPORT_USB, req->type); + auto secModeCheck = security_mode_check_control_request(channel == &bleChannel_ ? SECURITY_MODE_TRANSPORT_BLE : SECURITY_MODE_TRANSPORT_USB, req->type); if (secModeCheck) { setResult(req, secModeCheck); return; diff --git a/system/src/system_info_encoding.cpp b/system/src/system_info_encoding.cpp index 2a3804cd55..fb422c4b0e 100644 --- a/system/src/system_info_encoding.cpp +++ b/system/src/system_info_encoding.cpp @@ -143,7 +143,7 @@ EncodeFirmwareModules::EncodeFirmwareModules(pb_callback_t* cb, Flags flags) if (module.info.module_function == MODULE_FUNCTION_BOOTLOADER && (module.validity_result & MODULE_VALIDATION_INTEGRITY)) { module_info_security_mode_ext_t ext = {}; ext.ext.length = sizeof(ext); - if (!security_mode_find_extension(module.bounds.location == MODULE_BOUNDS_LOC_INTERNAL_FLASH ? HAL_STORAGE_ID_INTERNAL_FLASH : HAL_STORAGE_ID_EXTERNAL_FLASH, + if (!security_mode_find_module_extension(module.bounds.location == MODULE_BOUNDS_LOC_INTERNAL_FLASH ? HAL_STORAGE_ID_INTERNAL_FLASH : HAL_STORAGE_ID_EXTERNAL_FLASH, module.bounds.start_address, &ext)) { if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { pbModule.security.mode = PB(FirmwareModuleSecurityMode_PROTECTED); From 126ce4dafa7ce896a61a5e84c9fd5f777e09cefe Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Wed, 29 May 2024 16:17:19 +0200 Subject: [PATCH 09/35] Include server nonce in device signature --- proto_defs/shared | 2 +- system/src/control/config.cpp | 273 ++++++++++++------------- system/src/control/config.h | 2 +- system/src/system_control_internal.cpp | 2 +- 4 files changed, 131 insertions(+), 148 deletions(-) diff --git a/proto_defs/shared b/proto_defs/shared index a36c2f3161..8ee86d233c 160000 --- a/proto_defs/shared +++ b/proto_defs/shared @@ -1 +1 @@ -Subproject commit a36c2f3161c51df870f51371dfd89429284f03c7 +Subproject commit 8ee86d233cf1b8e96379891908c745364c342c9b diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index 6dbbaee4b3..3e567a66ad 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -67,13 +67,18 @@ namespace { using namespace particle::control::common; +const size_t SECURITY_MODE_NONCE_SIZE = 32; + +static_assert(sizeof(decltype(PB(SetProtectedStateRequest::server_nonce))::bytes) == SECURITY_MODE_NONCE_SIZE); +static_assert(sizeof(decltype(PB(SetProtectedStateReply::client_nonce))::bytes) == SECURITY_MODE_NONCE_SIZE); + struct SecurityModeChangeContext { - char clientNonce[32]; + char clientNonce[SECURITY_MODE_NONCE_SIZE]; + char serverNonce[SECURITY_MODE_NONCE_SIZE]; uint64_t requestTime; }; std::unique_ptr g_securityModeChangeCtx; -bool g_securityModeChangePending = false; #if USE_TEST_SERVER_KEY @@ -90,11 +95,6 @@ const uint8_t TEST_SERVER_KEY[] = { #endif // USE_TEST_SERVER_KEY -// Completion handler for system_ctrl_set_result() -void systemResetCompletionHandler(int result, void* data) { - system_reset(SYSTEM_RESET_MODE_NORMAL, RESET_REASON_CONFIG_UPDATE, 0 /* value */, 0 /* flags */, nullptr /* reserved */); -} - int getDevicePrivateKey(mbedtls_pk_context& pk) { std::unique_ptr keyData(new(std::nothrow) uint8_t[DCT_ALT_DEVICE_PRIVATE_KEY_SIZE]); int r = dct_read_app_data_copy(DCT_ALT_DEVICE_PRIVATE_KEY_OFFSET, keyData.get(), DCT_ALT_DEVICE_PRIVATE_KEY_SIZE); @@ -137,140 +137,6 @@ int updateSha256Delimited(Sha256& sha, const char* data, size_t size) { return 0; } -int setProtectedStateImpl(ctrl_request* req) { - // TODO: Remove this check once the support for TCP is fully removed - if (!HAL_Feature_Get(FEATURE_CLOUD_UDP)) { - return SYSTEM_ERROR_PROTOCOL; - } - if (g_securityModeChangePending) { - return SYSTEM_ERROR_BUSY; - } - - PB(SetProtectedStateRequest) pbReq = {}; - DecodedString pbServSig(&pbReq.server_signature); - CHECK(decodeRequestMessage(req, &PB(SetProtectedStateRequest_msg), &pbReq)); - - PB(SetProtectedStateReply) pbRep = {}; - bool changePending = false; - - switch (pbReq.action) { - case PB(SetProtectedStateRequest_Action_RESET): { - if (security_mode_is_overridden()) { - security_mode_clear_override(); - changePending = true; - } - g_securityModeChangeCtx.reset(); - break; - } - case PB(SetProtectedStateRequest_Action_DISABLE_REQUEST): { - g_securityModeChangeCtx.reset(); - if (security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_NONE) { - break; // Not protected - } - std::unique_ptr ctx(new(std::nothrow) SecurityModeChangeContext()); - if (!ctx) { - return SYSTEM_ERROR_NO_MEMORY; - } - - // Get the device ID and private key - uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; // Binary-encoded - const auto n = hal_get_device_id(devId, sizeof(devId)); - if (n != HAL_DEVICE_ID_SIZE) { - return SYSTEM_ERROR_UNKNOWN; - } - mbedtls_pk_context pk = {}; - mbedtls_pk_init(&pk); - SCOPE_GUARD({ - mbedtls_pk_free(&pk); - }); - CHECK(getDevicePrivateKey(pk)); - - // Generate a client nonce and signature - Random::genSecure(ctx->clientNonce, sizeof(ctx->clientNonce)); - Sha256 sha; - CHECK(sha.init()); - CHECK(sha.start()); - CHECK(sha.update("client", 6)); - CHECK(sha.update((const char*)devId, HAL_DEVICE_ID_SIZE)); - updateSha256Delimited(sha, ctx->clientNonce, sizeof(ctx->clientNonce)); - char hash[Sha256::HASH_SIZE] = {}; - CHECK(sha.finish(hash)); - - uint8_t sig[MBEDTLS_ECDSA_MAX_LEN] = {}; - size_t sigLen = 0; - CHECK_MBEDTLS(mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, (const uint8_t*)hash, sizeof(hash), sig, &sigLen, - mbedtls_default_rng, nullptr /* p_rng */)); - - // Encode a reply - EncodedString pbSig(&pbRep.client_signature, (const char*)sig, sigLen); - static_assert(sizeof(ctx->clientNonce) <= sizeof(pbRep.client_nonce.bytes)); - std::memcpy(pbRep.client_nonce.bytes, ctx->clientNonce, sizeof(ctx->clientNonce)); - pbRep.client_nonce.size = sizeof(ctx->clientNonce); - pbRep.has_client_nonce = true; - CHECK(encodeReplyMessage(req, &PB(SetProtectedStateReply_msg), &pbRep)); - - ctx->requestTime = hal_timer_millis(nullptr); - g_securityModeChangeCtx = std::move(ctx); - break; - } - case PB(SetProtectedStateRequest_Action_DISABLE_CONFIRM): { - if (!pbReq.has_server_nonce || !pbReq.server_nonce.size) { - return SYSTEM_ERROR_INVALID_ARGUMENT; - } - if (!g_securityModeChangeCtx) { - return SYSTEM_ERROR_INVALID_STATE; - } - if (hal_timer_millis(nullptr) - g_securityModeChangeCtx->requestTime >= 60000) { - g_securityModeChangeCtx.reset(); - return SYSTEM_ERROR_TIMEOUT; - } - - // Get the device ID and server public key - uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; - const auto n = hal_get_device_id(devId, sizeof(devId)); - if (n != HAL_DEVICE_ID_SIZE) { - return SYSTEM_ERROR_UNKNOWN; - } - mbedtls_pk_context pk = {}; - mbedtls_pk_init(&pk); - SCOPE_GUARD({ - mbedtls_pk_free(&pk); - }); - CHECK(getServerPublicKey(pk)); - - // Validate the server signature - Sha256 sha; - CHECK(sha.init()); - CHECK(sha.start()); - CHECK(sha.update("server", 6)); - CHECK(sha.update((const char*)devId, HAL_DEVICE_ID_SIZE)); - updateSha256Delimited(sha, (const char*)pbReq.server_nonce.bytes, pbReq.server_nonce.size); - updateSha256Delimited(sha, g_securityModeChangeCtx->clientNonce, sizeof(g_securityModeChangeCtx->clientNonce)); - char hash[Sha256::HASH_SIZE] = {}; - CHECK(sha.finish(hash)); - - int r = mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA256, (const uint8_t*)hash, sizeof(hash), (const uint8_t*)pbServSig.data, - pbServSig.size); - if (r != 0) { - return SYSTEM_ERROR_NOT_ALLOWED; - } - - g_securityModeChangeCtx.reset(); - security_mode_override_to_none(); - changePending = true; - break; - } - default: - return SYSTEM_ERROR_INVALID_ARGUMENT; - } - - g_securityModeChangePending = changePending; - auto compHandler = changePending ? systemResetCompletionHandler : nullptr; - system_ctrl_set_result(req, 0 /* result */, compHandler, nullptr /* data */, nullptr /* reserved */); - - return 0; -} - } // namespace int getDeviceId(ctrl_request* req) { @@ -423,11 +289,128 @@ int getProtectedState(ctrl_request* req) { return 0; } -void setProtectedState(ctrl_request* req) { - int r = setProtectedStateImpl(req); - if (r < 0) { - system_ctrl_set_result(req, r, nullptr /* handler */, nullptr /* data */, nullptr /* reserved */); +int setProtectedState(ctrl_request* req) { + // TODO: Remove this check once the support for TCP is fully removed + if (!HAL_Feature_Get(FEATURE_CLOUD_UDP)) { + return SYSTEM_ERROR_PROTOCOL; } + + PB(SetProtectedStateRequest) pbReq = {}; + DecodedString pbServSig(&pbReq.server_signature); + CHECK(decodeRequestMessage(req, &PB(SetProtectedStateRequest_msg), &pbReq)); + + PB(SetProtectedStateReply) pbRep = {}; + + switch (pbReq.action) { + case PB(SetProtectedStateRequest_Action_RESET): { + security_mode_clear_override(); + g_securityModeChangeCtx.reset(); + break; + } + case PB(SetProtectedStateRequest_Action_DISABLE_REQUEST): { + if (!pbReq.has_server_nonce || pbReq.server_nonce.size != SECURITY_MODE_NONCE_SIZE) { + return SYSTEM_ERROR_INVALID_ARGUMENT; + } + + g_securityModeChangeCtx.reset(); + if (security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_NONE && !security_mode_is_overridden()) { + break; // Not protected + } + std::unique_ptr ctx(new(std::nothrow) SecurityModeChangeContext()); + if (!ctx) { + return SYSTEM_ERROR_NO_MEMORY; + } + std::memcpy(ctx->serverNonce, pbReq.server_nonce.bytes, SECURITY_MODE_NONCE_SIZE); + + // Get the device ID and private key + uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; // Binary-encoded + const auto n = hal_get_device_id(devId, sizeof(devId)); + if (n != HAL_DEVICE_ID_SIZE) { + return SYSTEM_ERROR_UNKNOWN; + } + mbedtls_pk_context pk = {}; + mbedtls_pk_init(&pk); + SCOPE_GUARD({ + mbedtls_pk_free(&pk); + }); + CHECK(getDevicePrivateKey(pk)); + + // Generate a client nonce and signature + Random::genSecure(ctx->clientNonce, SECURITY_MODE_NONCE_SIZE); + Sha256 sha; + CHECK(sha.init()); + CHECK(sha.start()); + CHECK(sha.update("client", 6)); + CHECK(sha.update((const char*)devId, HAL_DEVICE_ID_SIZE)); + updateSha256Delimited(sha, ctx->clientNonce, SECURITY_MODE_NONCE_SIZE); + updateSha256Delimited(sha, ctx->serverNonce, SECURITY_MODE_NONCE_SIZE); + char hash[Sha256::HASH_SIZE] = {}; + CHECK(sha.finish(hash)); + + uint8_t sig[MBEDTLS_ECDSA_MAX_LEN] = {}; + size_t sigLen = 0; + CHECK_MBEDTLS(mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, (const uint8_t*)hash, sizeof(hash), sig, &sigLen, + mbedtls_default_rng, nullptr /* p_rng */)); + + // Encode a reply + EncodedString pbSig(&pbRep.client_signature, (const char*)sig, sigLen); + std::memcpy(pbRep.client_nonce.bytes, ctx->clientNonce, SECURITY_MODE_NONCE_SIZE); + pbRep.client_nonce.size = SECURITY_MODE_NONCE_SIZE; + pbRep.has_client_nonce = true; + CHECK(encodeReplyMessage(req, &PB(SetProtectedStateReply_msg), &pbRep)); + + ctx->requestTime = hal_timer_millis(nullptr); + g_securityModeChangeCtx = std::move(ctx); + break; + } + case PB(SetProtectedStateRequest_Action_DISABLE_CONFIRM): { + if (!g_securityModeChangeCtx) { + return SYSTEM_ERROR_INVALID_STATE; + } + if (hal_timer_millis(nullptr) - g_securityModeChangeCtx->requestTime >= 60000) { + g_securityModeChangeCtx.reset(); + return SYSTEM_ERROR_TIMEOUT; + } + + // Get the device ID and server public key + uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; + const auto n = hal_get_device_id(devId, sizeof(devId)); + if (n != HAL_DEVICE_ID_SIZE) { + return SYSTEM_ERROR_UNKNOWN; + } + mbedtls_pk_context pk = {}; + mbedtls_pk_init(&pk); + SCOPE_GUARD({ + mbedtls_pk_free(&pk); + }); + CHECK(getServerPublicKey(pk)); + + // Validate the server signature + Sha256 sha; + CHECK(sha.init()); + CHECK(sha.start()); + CHECK(sha.update("server", 6)); + CHECK(sha.update((const char*)devId, HAL_DEVICE_ID_SIZE)); + updateSha256Delimited(sha, g_securityModeChangeCtx->serverNonce, SECURITY_MODE_NONCE_SIZE); + updateSha256Delimited(sha, g_securityModeChangeCtx->clientNonce, SECURITY_MODE_NONCE_SIZE); + char hash[Sha256::HASH_SIZE] = {}; + CHECK(sha.finish(hash)); + + int r = mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA256, (const uint8_t*)hash, sizeof(hash), (const uint8_t*)pbServSig.data, + pbServSig.size); + if (r != 0) { + return SYSTEM_ERROR_NOT_ALLOWED; + } + + g_securityModeChangeCtx.reset(); + security_mode_override_to_none(); + break; + } + default: + return SYSTEM_ERROR_INVALID_ARGUMENT; + } + + return 0; } int setFeature(ctrl_request* req) { diff --git a/system/src/control/config.h b/system/src/control/config.h index abc16ed185..14e271720e 100644 --- a/system/src/control/config.h +++ b/system/src/control/config.h @@ -33,7 +33,7 @@ int setDeviceSetupDone(ctrl_request* req); int isDeviceSetupDone(ctrl_request* req); int setStartupMode(ctrl_request* req); int getProtectedState(ctrl_request* req); -void setProtectedState(ctrl_request* req); +int setProtectedState(ctrl_request* req); int setFeature(ctrl_request* req); int getFeature(ctrl_request* req); int echo(ctrl_request* req); diff --git a/system/src/system_control_internal.cpp b/system/src/system_control_internal.cpp index b9851948be..69666ef307 100644 --- a/system/src/system_control_internal.cpp +++ b/system/src/system_control_internal.cpp @@ -229,7 +229,7 @@ void SystemControl::processRequest(ctrl_request* req, ControlRequestChannel* cha break; } case CTRL_REQUEST_SET_PROTECTED_STATE: { - control::config::setProtectedState(req); + setResult(req, control::config::setProtectedState(req)); break; } case CTRL_REQUEST_ECHO: { From 276ae458cd080730db94b6f3d9e88332c8e7aeb0 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Thu, 30 May 2024 15:07:14 +0200 Subject: [PATCH 10/35] Check if the device is protected on every log operation --- services/src/logging.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/services/src/logging.cpp b/services/src/logging.cpp index 44733c788b..d72e35657f 100644 --- a/services/src/logging.cpp +++ b/services/src/logging.cpp @@ -73,9 +73,6 @@ volatile log_enabled_callback_type log_enabled_callback = 0; void log_set_callbacks(log_message_callback_type log_msg, log_write_callback_type log_write, log_enabled_callback_type log_enabled, void *reserved) { - if (security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_PROTECTED) { - return; - } log_msg_callback = log_msg; log_write_callback = log_write; log_enabled_callback = log_enabled; @@ -83,7 +80,8 @@ void log_set_callbacks(log_message_callback_type log_msg, log_write_callback_typ void log_message_v(int level, const char *category, LogAttributes *attr, void *reserved, const char *fmt, va_list args) { const log_message_callback_type msg_callback = log_msg_callback; - if (!msg_callback && (!log_compat_callback || level < log_compat_level)) { + if ((!msg_callback && (!log_compat_callback || level < log_compat_level)) || + security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_PROTECTED) { return; } // Set default attributes @@ -131,7 +129,7 @@ void log_message(int level, const char *category, LogAttributes *attr, void *res } void log_write(int level, const char *category, const char *data, size_t size, void *reserved) { - if (!size) { + if (!size || security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_PROTECTED) { return; } const log_write_callback_type write_callback = log_write_callback; From e6b0f95558983657ce905a728833dbccbb7f2bed Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 7 Jun 2024 15:12:53 +0200 Subject: [PATCH 11/35] Remove the test key --- system/src/control/config.cpp | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index 3e567a66ad..d042d810aa 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -55,8 +55,6 @@ #define PB(_name) particle_ctrl_##_name #define PB_FIELDS(_name) particle_ctrl_##_name##_fields -#define USE_TEST_SERVER_KEY 1 // FIXME - namespace particle { namespace control { @@ -80,21 +78,6 @@ struct SecurityModeChangeContext { std::unique_ptr g_securityModeChangeCtx; -#if USE_TEST_SERVER_KEY - -const uint8_t TEST_SERVER_KEY[] = { - 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, - 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, - 0x42, 0x00, 0x04, 0x02, 0x49, 0x5a, 0xee, 0xee, 0x46, 0xc4, 0x25, 0x22, - 0x13, 0xa0, 0x95, 0xd5, 0x80, 0x17, 0x0e, 0x8a, 0xc2, 0xc1, 0x10, 0xb6, - 0x42, 0x70, 0xd3, 0x29, 0x8c, 0xbf, 0x63, 0x53, 0x5a, 0x8e, 0xc3, 0x64, - 0xea, 0x6b, 0xef, 0xf5, 0xde, 0xd7, 0x66, 0x11, 0x91, 0x19, 0x96, 0x65, - 0x38, 0x38, 0x2f, 0x8d, 0x8e, 0xc0, 0xe1, 0xaa, 0x6d, 0x9b, 0x9c, 0xf1, - 0xc9, 0xef, 0x1d, 0x28, 0x9c, 0x6e, 0x81 -}; - -#endif // USE_TEST_SERVER_KEY - int getDevicePrivateKey(mbedtls_pk_context& pk) { std::unique_ptr keyData(new(std::nothrow) uint8_t[DCT_ALT_DEVICE_PRIVATE_KEY_SIZE]); int r = dct_read_app_data_copy(DCT_ALT_DEVICE_PRIVATE_KEY_OFFSET, keyData.get(), DCT_ALT_DEVICE_PRIVATE_KEY_SIZE); @@ -113,9 +96,6 @@ int getDevicePrivateKey(mbedtls_pk_context& pk) { } int getServerPublicKey(mbedtls_pk_context& pk) { -#if USE_TEST_SERVER_KEY - CHECK_MBEDTLS(mbedtls_pk_parse_public_key(&pk, TEST_SERVER_KEY, sizeof(TEST_SERVER_KEY) / sizeof(TEST_SERVER_KEY[0]))); -#else std::unique_ptr keyData(new(std::nothrow) uint8_t[DCT_ALT_SERVER_PUBLIC_KEY_SIZE]); int r = dct_read_app_data_copy(DCT_ALT_SERVER_PUBLIC_KEY_OFFSET, keyData.get(), DCT_ALT_SERVER_PUBLIC_KEY_SIZE); if (r != 0) { @@ -126,7 +106,6 @@ int getServerPublicKey(mbedtls_pk_context& pk) { return SYSTEM_ERROR_BAD_DATA; } CHECK_MBEDTLS(mbedtls_pk_parse_public_key(&pk, keyData.get(), keyLen)); -#endif // !USE_TEST_SERVER_KEY return 0; } From 6ef46970e68163249ef2c132db1f92d731907d3e Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 7 Jun 2024 16:25:35 +0200 Subject: [PATCH 12/35] Bugfixes --- services/src/security_mode.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index 728b6691a1..c4bbff77b5 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -73,7 +73,7 @@ void timerCallback(os_timer_t) { bool stop = false; ATOMIC_BLOCK() { Load_SystemFlags(); - if (system_flags.security_mode_is_overridden) { + if (system_flags.security_mode_is_overridden == 1) { if (system_flags.security_mode_override_timeout > 0) { --system_flags.security_mode_override_timeout; } @@ -82,7 +82,7 @@ void timerCallback(os_timer_t) { } Save_SystemFlags(); } - if (!system_flags.security_mode_is_overridden) { + if (system_flags.security_mode_is_overridden != 1) { sCurrentSecurityMode = sNormalSecurityMode; stop = true; } @@ -110,7 +110,7 @@ int security_mode_init() { } if (sNormalSecurityMode != MODULE_INFO_SECURITY_MODE_NONE) { Load_SystemFlags(); - sCurrentSecurityMode = system_flags.security_mode_is_overridden ? MODULE_INFO_SECURITY_MODE_NONE : sNormalSecurityMode; + sCurrentSecurityMode = (system_flags.security_mode_is_overridden == 1) ? MODULE_INFO_SECURITY_MODE_NONE : sNormalSecurityMode; } return 0; } @@ -246,14 +246,16 @@ void security_mode_notify_system_reset() { } ATOMIC_BLOCK() { Load_SystemFlags(); - if (system_flags.security_mode_override_reset_count > 0) { - --system_flags.security_mode_override_reset_count; - } - if (!system_flags.security_mode_override_reset_count) { - system_flags.security_mode_is_overridden = 0; + if (system_flags.security_mode_is_overridden == 1) { + if (system_flags.security_mode_override_reset_count > 0) { + --system_flags.security_mode_override_reset_count; + } + if (!system_flags.security_mode_override_reset_count) { + system_flags.security_mode_is_overridden = 0; + } + Save_SystemFlags(); } - Save_SystemFlags(); - if (!system_flags.security_mode_is_overridden) { + if (system_flags.security_mode_is_overridden != 1) { sCurrentSecurityMode = sNormalSecurityMode; } } @@ -269,7 +271,7 @@ void security_mode_notify_system_tick() { if (!sSystemTickCount) { ATOMIC_BLOCK() { Load_SystemFlags(); - if (system_flags.security_mode_is_overridden) { + if (system_flags.security_mode_is_overridden == 1) { if (system_flags.security_mode_override_timeout > 0) { --system_flags.security_mode_override_timeout; } @@ -278,7 +280,7 @@ void security_mode_notify_system_tick() { } Save_SystemFlags(); } - if (!system_flags.security_mode_is_overridden) { + if (system_flags.security_mode_is_overridden != 1) { sCurrentSecurityMode = sNormalSecurityMode; } } From 5145cb2fa282192df3da72373bb60d32a5063e53 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Mon, 10 Jun 2024 11:14:10 +0200 Subject: [PATCH 13/35] Regenerate Protobuf definitions; update submodule refs --- proto_defs/shared | 2 +- proto_defs/src/control/config.pb.c | 9 ++ proto_defs/src/control/config.pb.h | 129 +++++++++++++++++++++-------- 3 files changed, 103 insertions(+), 37 deletions(-) diff --git a/proto_defs/shared b/proto_defs/shared index 8ee86d233c..3a692c7d5f 160000 --- a/proto_defs/shared +++ b/proto_defs/shared @@ -1 +1 @@ -Subproject commit 8ee86d233cf1b8e96379891908c745364c342c9b +Subproject commit 3a692c7d5f5654f834789e37edaafef4225e4cd5 diff --git a/proto_defs/src/control/config.pb.c b/proto_defs/src/control/config.pb.c index 56b10e955d..53402ee9fb 100644 --- a/proto_defs/src/control/config.pb.c +++ b/proto_defs/src/control/config.pb.c @@ -135,9 +135,18 @@ PB_BIND(particle_ctrl_GetProtectedStateReply, particle_ctrl_GetProtectedStateRep PB_BIND(particle_ctrl_SetProtectedStateRequest, particle_ctrl_SetProtectedStateRequest, AUTO) +PB_BIND(particle_ctrl_SetProtectedStateRequest_PrepareChange, particle_ctrl_SetProtectedStateRequest_PrepareChange, AUTO) + + +PB_BIND(particle_ctrl_SetProtectedStateRequest_ConfirmChange, particle_ctrl_SetProtectedStateRequest_ConfirmChange, AUTO) + + PB_BIND(particle_ctrl_SetProtectedStateReply, particle_ctrl_SetProtectedStateReply, AUTO) +PB_BIND(particle_ctrl_SetProtectedStateReply_PrepareChange, particle_ctrl_SetProtectedStateReply_PrepareChange, AUTO) + + PB_BIND(particle_ctrl_SystemResetRequest, particle_ctrl_SystemResetRequest, AUTO) diff --git a/proto_defs/src/control/config.pb.h b/proto_defs/src/control/config.pb.h index c9b2f26f2e..75d8c3d74a 100644 --- a/proto_defs/src/control/config.pb.h +++ b/proto_defs/src/control/config.pb.h @@ -50,8 +50,8 @@ typedef enum _particle_ctrl_Feature { /* Note: Use the same values as defined by the security_key_type enum */ typedef enum _particle_ctrl_SetProtectedStateRequest_Action { particle_ctrl_SetProtectedStateRequest_Action_RESET = 0, /* Invalid key */ - particle_ctrl_SetProtectedStateRequest_Action_DISABLE_REQUEST = 1, /* TCP device private key */ - particle_ctrl_SetProtectedStateRequest_Action_DISABLE_CONFIRM = 2 /* TCP device public key */ + particle_ctrl_SetProtectedStateRequest_Action_PREPARE_CHANGE = 1, /* TCP device private key */ + particle_ctrl_SetProtectedStateRequest_Action_CONFIRM_CHANGE = 2 /* TCP device public key */ } particle_ctrl_SetProtectedStateRequest_Action; /* Struct definitions */ @@ -119,6 +119,7 @@ typedef struct _particle_ctrl_SetDeviceSetupDoneReply { char dummy_field; } particle_ctrl_SetDeviceSetupDoneReply; +/* Make the device's status LED display a rainbow pattern aka Nyan mode */ typedef struct _particle_ctrl_SetFeatureReply { char dummy_field; } particle_ctrl_SetFeatureReply; @@ -156,7 +157,6 @@ typedef struct _particle_ctrl_StartNyanSignalReply { char dummy_field; } particle_ctrl_StartNyanSignalReply; -/* Make the device's status LED display a rainbow pattern aka Nyan mode */ typedef struct _particle_ctrl_StartNyanSignalRequest { char dummy_field; } particle_ctrl_StartNyanSignalRequest; @@ -174,16 +174,15 @@ typedef struct _particle_ctrl_StopNyanSignalReply { char dummy_field; } particle_ctrl_StopNyanSignalReply; -/* Exit the Nyan mode */ typedef struct _particle_ctrl_StopNyanSignalRequest { char dummy_field; } particle_ctrl_StopNyanSignalRequest; +/* Check if the system feature is enabled or disabled */ typedef struct _particle_ctrl_SystemResetReply { char dummy_field; } particle_ctrl_SystemResetReply; -/* Resets the device, just like hitting the reset button or powering down and back up */ typedef struct _particle_ctrl_SystemResetRequest { char dummy_field; } particle_ctrl_SystemResetRequest; @@ -197,11 +196,11 @@ typedef struct _particle_ctrl_GetDeviceModeReply { particle_ctrl_DeviceMode mode; } particle_ctrl_GetDeviceModeReply; +/* Exit the Nyan mode */ typedef struct _particle_ctrl_GetFeatureReply { bool enabled; } particle_ctrl_GetFeatureReply; -/* Check if the system feature is enabled or disabled */ typedef struct _particle_ctrl_GetFeatureRequest { particle_ctrl_Feature feature; } particle_ctrl_GetFeatureRequest; @@ -263,26 +262,31 @@ typedef struct _particle_ctrl_SetDeviceSetupDoneRequest { bool done; } particle_ctrl_SetDeviceSetupDoneRequest; -/* Enable/disable system features */ typedef struct _particle_ctrl_SetFeatureRequest { particle_ctrl_Feature feature; bool enabled; } particle_ctrl_SetFeatureRequest; -typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateReply_client_nonce_t; -typedef struct _particle_ctrl_SetProtectedStateReply { - bool has_client_nonce; - particle_ctrl_SetProtectedStateReply_client_nonce_t client_nonce; - pb_callback_t client_signature; -} particle_ctrl_SetProtectedStateReply; +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateReply_PrepareChange_device_nonce_t; +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateReply_PrepareChange_device_public_key_fingerprint_t; +/* Enable/disable system features */ +typedef struct _particle_ctrl_SetProtectedStateReply_PrepareChange { + particle_ctrl_SetProtectedStateReply_PrepareChange_device_nonce_t device_nonce; + pb_callback_t device_signature; + particle_ctrl_SetProtectedStateReply_PrepareChange_device_public_key_fingerprint_t device_public_key_fingerprint; +} particle_ctrl_SetProtectedStateReply_PrepareChange; -typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateRequest_server_nonce_t; -typedef struct _particle_ctrl_SetProtectedStateRequest { - particle_ctrl_SetProtectedStateRequest_Action action; - bool has_server_nonce; - particle_ctrl_SetProtectedStateRequest_server_nonce_t server_nonce; +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateRequest_ConfirmChange_server_public_key_fingerprint_t; +/* Resets the device, just like hitting the reset button or powering down and back up */ +typedef struct _particle_ctrl_SetProtectedStateRequest_ConfirmChange { pb_callback_t server_signature; -} particle_ctrl_SetProtectedStateRequest; + particle_ctrl_SetProtectedStateRequest_ConfirmChange_server_public_key_fingerprint_t server_public_key_fingerprint; +} particle_ctrl_SetProtectedStateRequest_ConfirmChange; + +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateRequest_PrepareChange_server_nonce_t; +typedef struct _particle_ctrl_SetProtectedStateRequest_PrepareChange { + particle_ctrl_SetProtectedStateRequest_PrepareChange_server_nonce_t server_nonce; +} particle_ctrl_SetProtectedStateRequest_PrepareChange; typedef struct _particle_ctrl_SetSecurityKeyRequest { particle_ctrl_SecurityKeyType type; /* Key type */ @@ -310,6 +314,19 @@ typedef struct _particle_ctrl_SetStartupModeRequest { particle_ctrl_DeviceMode mode; } particle_ctrl_SetStartupModeRequest; +typedef struct _particle_ctrl_SetProtectedStateReply { + particle_ctrl_SetProtectedStateReply_PrepareChange prepare_change; +} particle_ctrl_SetProtectedStateReply; + +typedef struct _particle_ctrl_SetProtectedStateRequest { + particle_ctrl_SetProtectedStateRequest_Action action; + pb_size_t which_data; + union { + particle_ctrl_SetProtectedStateRequest_PrepareChange prepare_change; + particle_ctrl_SetProtectedStateRequest_ConfirmChange confirm_change; + } data; +} particle_ctrl_SetProtectedStateRequest; + /* Helper constants for enums */ #define _particle_ctrl_SecurityKeyType_MIN particle_ctrl_SecurityKeyType_INVALID_SECURITY_KEY @@ -333,8 +350,8 @@ typedef struct _particle_ctrl_SetStartupModeRequest { #define _particle_ctrl_Feature_ARRAYSIZE ((particle_ctrl_Feature)(particle_ctrl_Feature_ETHERNET_DETECTION+1)) #define _particle_ctrl_SetProtectedStateRequest_Action_MIN particle_ctrl_SetProtectedStateRequest_Action_RESET -#define _particle_ctrl_SetProtectedStateRequest_Action_MAX particle_ctrl_SetProtectedStateRequest_Action_DISABLE_CONFIRM -#define _particle_ctrl_SetProtectedStateRequest_Action_ARRAYSIZE ((particle_ctrl_SetProtectedStateRequest_Action)(particle_ctrl_SetProtectedStateRequest_Action_DISABLE_CONFIRM+1)) +#define _particle_ctrl_SetProtectedStateRequest_Action_MAX particle_ctrl_SetProtectedStateRequest_Action_CONFIRM_CHANGE +#define _particle_ctrl_SetProtectedStateRequest_Action_ARRAYSIZE ((particle_ctrl_SetProtectedStateRequest_Action)(particle_ctrl_SetProtectedStateRequest_Action_CONFIRM_CHANGE+1)) #ifdef __cplusplus @@ -384,8 +401,11 @@ extern "C" { #define particle_ctrl_SetStartupModeReply_init_default {0} #define particle_ctrl_GetProtectedStateRequest_init_default {0} #define particle_ctrl_GetProtectedStateReply_init_default {0, 0} -#define particle_ctrl_SetProtectedStateRequest_init_default {_particle_ctrl_SetProtectedStateRequest_Action_MIN, false, {0, {0}}, {{NULL}, NULL}} -#define particle_ctrl_SetProtectedStateReply_init_default {false, {0, {0}}, {{NULL}, NULL}} +#define particle_ctrl_SetProtectedStateRequest_init_default {_particle_ctrl_SetProtectedStateRequest_Action_MIN, 0, {particle_ctrl_SetProtectedStateRequest_PrepareChange_init_default}} +#define particle_ctrl_SetProtectedStateRequest_PrepareChange_init_default {{0, {0}}} +#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_default {{{NULL}, NULL}, {0, {0}}} +#define particle_ctrl_SetProtectedStateReply_init_default {particle_ctrl_SetProtectedStateReply_PrepareChange_init_default} +#define particle_ctrl_SetProtectedStateReply_PrepareChange_init_default {{0, {0}}, {{NULL}, NULL}, {0, {0}}} #define particle_ctrl_SystemResetRequest_init_default {0} #define particle_ctrl_SystemResetReply_init_default {0} #define particle_ctrl_SetFeatureRequest_init_default {_particle_ctrl_Feature_MIN, 0} @@ -438,8 +458,11 @@ extern "C" { #define particle_ctrl_SetStartupModeReply_init_zero {0} #define particle_ctrl_GetProtectedStateRequest_init_zero {0} #define particle_ctrl_GetProtectedStateReply_init_zero {0, 0} -#define particle_ctrl_SetProtectedStateRequest_init_zero {_particle_ctrl_SetProtectedStateRequest_Action_MIN, false, {0, {0}}, {{NULL}, NULL}} -#define particle_ctrl_SetProtectedStateReply_init_zero {false, {0, {0}}, {{NULL}, NULL}} +#define particle_ctrl_SetProtectedStateRequest_init_zero {_particle_ctrl_SetProtectedStateRequest_Action_MIN, 0, {particle_ctrl_SetProtectedStateRequest_PrepareChange_init_zero}} +#define particle_ctrl_SetProtectedStateRequest_PrepareChange_init_zero {{0, {0}}} +#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_zero {{{NULL}, NULL}, {0, {0}}} +#define particle_ctrl_SetProtectedStateReply_init_zero {particle_ctrl_SetProtectedStateReply_PrepareChange_init_zero} +#define particle_ctrl_SetProtectedStateReply_PrepareChange_init_zero {{0, {0}}, {{NULL}, NULL}, {0, {0}}} #define particle_ctrl_SystemResetRequest_init_zero {0} #define particle_ctrl_SystemResetReply_init_zero {0} #define particle_ctrl_SetFeatureRequest_init_zero {_particle_ctrl_Feature_MIN, 0} @@ -475,11 +498,12 @@ extern "C" { #define particle_ctrl_SetDeviceSetupDoneRequest_done_tag 1 #define particle_ctrl_SetFeatureRequest_feature_tag 1 #define particle_ctrl_SetFeatureRequest_enabled_tag 2 -#define particle_ctrl_SetProtectedStateReply_client_nonce_tag 1 -#define particle_ctrl_SetProtectedStateReply_client_signature_tag 2 -#define particle_ctrl_SetProtectedStateRequest_action_tag 1 -#define particle_ctrl_SetProtectedStateRequest_server_nonce_tag 2 -#define particle_ctrl_SetProtectedStateRequest_server_signature_tag 3 +#define particle_ctrl_SetProtectedStateReply_PrepareChange_device_nonce_tag 1 +#define particle_ctrl_SetProtectedStateReply_PrepareChange_device_signature_tag 2 +#define particle_ctrl_SetProtectedStateReply_PrepareChange_device_public_key_fingerprint_tag 3 +#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_server_signature_tag 1 +#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_server_public_key_fingerprint_tag 2 +#define particle_ctrl_SetProtectedStateRequest_PrepareChange_server_nonce_tag 1 #define particle_ctrl_SetSecurityKeyRequest_type_tag 1 #define particle_ctrl_SetSecurityKeyRequest_data_tag 2 #define particle_ctrl_SetServerAddressRequest_protocol_tag 1 @@ -489,6 +513,10 @@ extern "C" { #define particle_ctrl_SetSoftApSsidRequest_prefix_tag 1 #define particle_ctrl_SetSoftApSsidRequest_suffix_tag 2 #define particle_ctrl_SetStartupModeRequest_mode_tag 1 +#define particle_ctrl_SetProtectedStateReply_prepare_change_tag 1 +#define particle_ctrl_SetProtectedStateRequest_action_tag 1 +#define particle_ctrl_SetProtectedStateRequest_prepare_change_tag 2 +#define particle_ctrl_SetProtectedStateRequest_confirm_change_tag 3 /* Struct field encoding specification for nanopb */ #define particle_ctrl_GetDeviceIdRequest_FIELDLIST(X, a) \ @@ -710,16 +738,36 @@ X(a, STATIC, SINGULAR, BOOL, overridden, 2) #define particle_ctrl_SetProtectedStateRequest_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, action, 1) \ -X(a, STATIC, OPTIONAL, BYTES, server_nonce, 2) \ -X(a, CALLBACK, OPTIONAL, BYTES, server_signature, 3) -#define particle_ctrl_SetProtectedStateRequest_CALLBACK pb_default_field_callback +X(a, STATIC, ONEOF, MESSAGE, (data,prepare_change,data.prepare_change), 2) \ +X(a, STATIC, ONEOF, MESSAGE, (data,confirm_change,data.confirm_change), 3) +#define particle_ctrl_SetProtectedStateRequest_CALLBACK NULL #define particle_ctrl_SetProtectedStateRequest_DEFAULT NULL +#define particle_ctrl_SetProtectedStateRequest_data_prepare_change_MSGTYPE particle_ctrl_SetProtectedStateRequest_PrepareChange +#define particle_ctrl_SetProtectedStateRequest_data_confirm_change_MSGTYPE particle_ctrl_SetProtectedStateRequest_ConfirmChange + +#define particle_ctrl_SetProtectedStateRequest_PrepareChange_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BYTES, server_nonce, 1) +#define particle_ctrl_SetProtectedStateRequest_PrepareChange_CALLBACK NULL +#define particle_ctrl_SetProtectedStateRequest_PrepareChange_DEFAULT NULL + +#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, server_signature, 1) \ +X(a, STATIC, SINGULAR, BYTES, server_public_key_fingerprint, 2) +#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_CALLBACK pb_default_field_callback +#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_DEFAULT NULL #define particle_ctrl_SetProtectedStateReply_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, BYTES, client_nonce, 1) \ -X(a, CALLBACK, OPTIONAL, BYTES, client_signature, 2) -#define particle_ctrl_SetProtectedStateReply_CALLBACK pb_default_field_callback +X(a, STATIC, SINGULAR, MESSAGE, prepare_change, 1) +#define particle_ctrl_SetProtectedStateReply_CALLBACK NULL #define particle_ctrl_SetProtectedStateReply_DEFAULT NULL +#define particle_ctrl_SetProtectedStateReply_prepare_change_MSGTYPE particle_ctrl_SetProtectedStateReply_PrepareChange + +#define particle_ctrl_SetProtectedStateReply_PrepareChange_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BYTES, device_nonce, 1) \ +X(a, CALLBACK, SINGULAR, BYTES, device_signature, 2) \ +X(a, STATIC, SINGULAR, BYTES, device_public_key_fingerprint, 3) +#define particle_ctrl_SetProtectedStateReply_PrepareChange_CALLBACK pb_default_field_callback +#define particle_ctrl_SetProtectedStateReply_PrepareChange_DEFAULT NULL #define particle_ctrl_SystemResetRequest_FIELDLIST(X, a) \ @@ -815,7 +863,10 @@ extern const pb_msgdesc_t particle_ctrl_SetStartupModeReply_msg; extern const pb_msgdesc_t particle_ctrl_GetProtectedStateRequest_msg; extern const pb_msgdesc_t particle_ctrl_GetProtectedStateReply_msg; extern const pb_msgdesc_t particle_ctrl_SetProtectedStateRequest_msg; +extern const pb_msgdesc_t particle_ctrl_SetProtectedStateRequest_PrepareChange_msg; +extern const pb_msgdesc_t particle_ctrl_SetProtectedStateRequest_ConfirmChange_msg; extern const pb_msgdesc_t particle_ctrl_SetProtectedStateReply_msg; +extern const pb_msgdesc_t particle_ctrl_SetProtectedStateReply_PrepareChange_msg; extern const pb_msgdesc_t particle_ctrl_SystemResetRequest_msg; extern const pb_msgdesc_t particle_ctrl_SystemResetReply_msg; extern const pb_msgdesc_t particle_ctrl_SetFeatureRequest_msg; @@ -871,7 +922,10 @@ extern const pb_msgdesc_t particle_ctrl_StopNyanSignalReply_msg; #define particle_ctrl_GetProtectedStateRequest_fields &particle_ctrl_GetProtectedStateRequest_msg #define particle_ctrl_GetProtectedStateReply_fields &particle_ctrl_GetProtectedStateReply_msg #define particle_ctrl_SetProtectedStateRequest_fields &particle_ctrl_SetProtectedStateRequest_msg +#define particle_ctrl_SetProtectedStateRequest_PrepareChange_fields &particle_ctrl_SetProtectedStateRequest_PrepareChange_msg +#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_fields &particle_ctrl_SetProtectedStateRequest_ConfirmChange_msg #define particle_ctrl_SetProtectedStateReply_fields &particle_ctrl_SetProtectedStateReply_msg +#define particle_ctrl_SetProtectedStateReply_PrepareChange_fields &particle_ctrl_SetProtectedStateReply_PrepareChange_msg #define particle_ctrl_SystemResetRequest_fields &particle_ctrl_SystemResetRequest_msg #define particle_ctrl_SystemResetReply_fields &particle_ctrl_SystemResetReply_msg #define particle_ctrl_SetFeatureRequest_fields &particle_ctrl_SetFeatureRequest_msg @@ -890,7 +944,9 @@ extern const pb_msgdesc_t particle_ctrl_StopNyanSignalReply_msg; /* particle_ctrl_GetSecurityKeyReply_size depends on runtime parameters */ /* particle_ctrl_GetServerAddressReply_size depends on runtime parameters */ /* particle_ctrl_SetProtectedStateRequest_size depends on runtime parameters */ +/* particle_ctrl_SetProtectedStateRequest_ConfirmChange_size depends on runtime parameters */ /* particle_ctrl_SetProtectedStateReply_size depends on runtime parameters */ +/* particle_ctrl_SetProtectedStateReply_PrepareChange_size depends on runtime parameters */ #define particle_ctrl_GetDeviceIdReply_size 26 #define particle_ctrl_GetDeviceIdRequest_size 0 #define particle_ctrl_GetDeviceModeReply_size 2 @@ -919,6 +975,7 @@ extern const pb_msgdesc_t particle_ctrl_StopNyanSignalReply_msg; #define particle_ctrl_SetDeviceSetupDoneRequest_size 2 #define particle_ctrl_SetFeatureReply_size 0 #define particle_ctrl_SetFeatureRequest_size 4 +#define particle_ctrl_SetProtectedStateRequest_PrepareChange_size 34 #define particle_ctrl_SetSecurityKeyReply_size 0 #define particle_ctrl_SetServerAddressReply_size 0 #define particle_ctrl_SetServerAddressRequest_size 79 From d4f6c0eb4b72f04fe360f5144e3ef1ebcd6fb57f Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Mon, 10 Jun 2024 13:57:04 +0200 Subject: [PATCH 14/35] Bugfix --- services/inc/preprocessor.h | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/services/inc/preprocessor.h b/services/inc/preprocessor.h index 765f6e15b5..65d0bcfa73 100644 --- a/services/inc/preprocessor.h +++ b/services/inc/preprocessor.h @@ -325,25 +325,26 @@ #define _PP_FOR_EACH_99(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99) \ _PP_FOR_EACH_98(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98) m(d, _99) #define _PP_FOR_EACH_100(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100) \ - _PP_FOR_EACH_99 (m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99) m(d, _100) + _PP_FOR_EACH_99(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99) m(d, _100) #define _PP_FOR_EACH_101(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101) \ - _PP_FOR_EACH_100(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _100) m(d, _101) + _PP_FOR_EACH_100(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100) m(d, _101) #define _PP_FOR_EACH_102(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102) \ - _PP_FOR_EACH_101(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _101) m(d, _102) + _PP_FOR_EACH_101(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101) m(d, _102) #define _PP_FOR_EACH_103(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103) \ - _PP_FOR_EACH_102(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _102) m(d, _103) -#define _PP_FOR_EACH_104(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _104) \ - _PP_FOR_EACH_103(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _103) m(d, _104) -#define _PP_FOR_EACH_105(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _104, _105) \ - _PP_FOR_EACH_104(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _104) m(d, _105) -#define _PP_FOR_EACH_106(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _104, _106) \ - _PP_FOR_EACH_105(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _105) m(d, _106) -#define _PP_FOR_EACH_107(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _104, _106, _107) \ - _PP_FOR_EACH_106(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _105, _106) m(d, _107) -#define _PP_FOR_EACH_108(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _104, _106, _107, _108) \ - _PP_FOR_EACH_107(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _105, _106, _107) m(d, _108) -#define _PP_FOR_EACH_109(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _104, _106, _107, _108, _109) \ - _PP_FOR_EACH_108(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _105, _106, _107, _108) m(d, _109) -#define _PP_FOR_EACH_110(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _104, _106, _107, _108, _109, _110) \ - _PP_FOR_EACH_109(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _105, _106, _107, _108, _109) m(d, _110) + _PP_FOR_EACH_102(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102) m(d, _103) +#define _PP_FOR_EACH_104(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104) \ + _PP_FOR_EACH_103(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103) m(d, _104) +#define _PP_FOR_EACH_105(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105) \ + _PP_FOR_EACH_104(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104) m(d, _105) +#define _PP_FOR_EACH_106(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106) \ + _PP_FOR_EACH_105(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105) m(d, _106) +#define _PP_FOR_EACH_107(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107) \ + _PP_FOR_EACH_106(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106) m(d, _107) +#define _PP_FOR_EACH_108(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108) \ + _PP_FOR_EACH_107(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107) m(d, _108) +#define _PP_FOR_EACH_109(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109) \ + _PP_FOR_EACH_108(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108) m(d, _109) +#define _PP_FOR_EACH_110(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110) \ + _PP_FOR_EACH_109(m, d, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109) m(d, _110) + #endif // _PREPROCESSOR_H From 49cd77079e1579cd0a8a27098678f2b05cb2e5c2 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Mon, 10 Jun 2024 13:58:04 +0200 Subject: [PATCH 15/35] Regenerate Protobuf definitions; update submodule refs --- proto_defs/shared | 2 +- proto_defs/src/control/config.pb.h | 19 ++++++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/proto_defs/shared b/proto_defs/shared index 3a692c7d5f..5ce398bf66 160000 --- a/proto_defs/shared +++ b/proto_defs/shared @@ -1 +1 @@ -Subproject commit 3a692c7d5f5654f834789e37edaafef4225e4cd5 +Subproject commit 5ce398bf66051bc9684c652d5fdba94c4ba86b06 diff --git a/proto_defs/src/control/config.pb.h b/proto_defs/src/control/config.pb.h index 75d8c3d74a..bf4eebdc85 100644 --- a/proto_defs/src/control/config.pb.h +++ b/proto_defs/src/control/config.pb.h @@ -320,11 +320,8 @@ typedef struct _particle_ctrl_SetProtectedStateReply { typedef struct _particle_ctrl_SetProtectedStateRequest { particle_ctrl_SetProtectedStateRequest_Action action; - pb_size_t which_data; - union { - particle_ctrl_SetProtectedStateRequest_PrepareChange prepare_change; - particle_ctrl_SetProtectedStateRequest_ConfirmChange confirm_change; - } data; + particle_ctrl_SetProtectedStateRequest_PrepareChange prepare_change; + particle_ctrl_SetProtectedStateRequest_ConfirmChange confirm_change; } particle_ctrl_SetProtectedStateRequest; @@ -401,7 +398,7 @@ extern "C" { #define particle_ctrl_SetStartupModeReply_init_default {0} #define particle_ctrl_GetProtectedStateRequest_init_default {0} #define particle_ctrl_GetProtectedStateReply_init_default {0, 0} -#define particle_ctrl_SetProtectedStateRequest_init_default {_particle_ctrl_SetProtectedStateRequest_Action_MIN, 0, {particle_ctrl_SetProtectedStateRequest_PrepareChange_init_default}} +#define particle_ctrl_SetProtectedStateRequest_init_default {_particle_ctrl_SetProtectedStateRequest_Action_MIN, particle_ctrl_SetProtectedStateRequest_PrepareChange_init_default, particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_default} #define particle_ctrl_SetProtectedStateRequest_PrepareChange_init_default {{0, {0}}} #define particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_default {{{NULL}, NULL}, {0, {0}}} #define particle_ctrl_SetProtectedStateReply_init_default {particle_ctrl_SetProtectedStateReply_PrepareChange_init_default} @@ -458,7 +455,7 @@ extern "C" { #define particle_ctrl_SetStartupModeReply_init_zero {0} #define particle_ctrl_GetProtectedStateRequest_init_zero {0} #define particle_ctrl_GetProtectedStateReply_init_zero {0, 0} -#define particle_ctrl_SetProtectedStateRequest_init_zero {_particle_ctrl_SetProtectedStateRequest_Action_MIN, 0, {particle_ctrl_SetProtectedStateRequest_PrepareChange_init_zero}} +#define particle_ctrl_SetProtectedStateRequest_init_zero {_particle_ctrl_SetProtectedStateRequest_Action_MIN, particle_ctrl_SetProtectedStateRequest_PrepareChange_init_zero, particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_zero} #define particle_ctrl_SetProtectedStateRequest_PrepareChange_init_zero {{0, {0}}} #define particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_zero {{{NULL}, NULL}, {0, {0}}} #define particle_ctrl_SetProtectedStateReply_init_zero {particle_ctrl_SetProtectedStateReply_PrepareChange_init_zero} @@ -738,12 +735,12 @@ X(a, STATIC, SINGULAR, BOOL, overridden, 2) #define particle_ctrl_SetProtectedStateRequest_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, action, 1) \ -X(a, STATIC, ONEOF, MESSAGE, (data,prepare_change,data.prepare_change), 2) \ -X(a, STATIC, ONEOF, MESSAGE, (data,confirm_change,data.confirm_change), 3) +X(a, STATIC, SINGULAR, MESSAGE, prepare_change, 2) \ +X(a, STATIC, SINGULAR, MESSAGE, confirm_change, 3) #define particle_ctrl_SetProtectedStateRequest_CALLBACK NULL #define particle_ctrl_SetProtectedStateRequest_DEFAULT NULL -#define particle_ctrl_SetProtectedStateRequest_data_prepare_change_MSGTYPE particle_ctrl_SetProtectedStateRequest_PrepareChange -#define particle_ctrl_SetProtectedStateRequest_data_confirm_change_MSGTYPE particle_ctrl_SetProtectedStateRequest_ConfirmChange +#define particle_ctrl_SetProtectedStateRequest_prepare_change_MSGTYPE particle_ctrl_SetProtectedStateRequest_PrepareChange +#define particle_ctrl_SetProtectedStateRequest_confirm_change_MSGTYPE particle_ctrl_SetProtectedStateRequest_ConfirmChange #define particle_ctrl_SetProtectedStateRequest_PrepareChange_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BYTES, server_nonce, 1) From 06ed956b44cfde29d602fbf10673bcd81a2d3daa Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Mon, 10 Jun 2024 13:59:09 +0200 Subject: [PATCH 16/35] Add device/server key fingerprints; minor refactoring --- services/inc/system_error.h | 2 + services/src/security_mode.cpp | 4 ++ system/src/control/config.cpp | 106 +++++++++++++++++++++------------ 3 files changed, 74 insertions(+), 38 deletions(-) diff --git a/services/inc/system_error.h b/services/inc/system_error.h index 89270f8597..00f1fda0da 100644 --- a/services/inc/system_error.h +++ b/services/inc/system_error.h @@ -97,6 +97,8 @@ (PPP_NO_CARRIER_IN_NETWORK_PHASE, "Received NO CARRIER in network phase", -1712), \ (INVALID_SERVER_SETTINGS, "Server settings are invalid", -1800), /* -1899 ... -1800: Miscellaneous system errors */ \ (PROTECTED, "Device is in a protected state, action prohibited", -1801), \ + (KEY_MISMATCH, "Unrecognized cryptographic key", -1802), \ + (INVALID_SIGNATURE, "Signature validation failed", -1803), \ (FILESYSTEM, "Filesystem error", -1900), /* -1999 ... -1900: Filesystem errors */ \ (FILESYSTEM_IO, "Filesystem IO error", -1901), \ (FILESYSTEM_CORRUPT, "Filesystem corrupted", -1902), \ diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index c4bbff77b5..d6538424b5 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -218,7 +218,9 @@ void security_mode_override_to_none() { Save_SystemFlags(); sCurrentSecurityMode = MODULE_INFO_SECURITY_MODE_NONE; } +#if MODULE_FUNCTION != MOD_FUNC_BOOTLOADER startTimer(); +#endif } void security_mode_clear_override() { @@ -231,7 +233,9 @@ void security_mode_clear_override() { Save_SystemFlags(); sCurrentSecurityMode = sNormalSecurityMode; } +#if MODULE_FUNCTION != MOD_FUNC_BOOTLOADER stopTimer(); +#endif } bool security_mode_is_overridden() { diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index d042d810aa..2ff277adec 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -67,45 +67,62 @@ using namespace particle::control::common; const size_t SECURITY_MODE_NONCE_SIZE = 32; -static_assert(sizeof(decltype(PB(SetProtectedStateRequest::server_nonce))::bytes) == SECURITY_MODE_NONCE_SIZE); -static_assert(sizeof(decltype(PB(SetProtectedStateReply::client_nonce))::bytes) == SECURITY_MODE_NONCE_SIZE); - struct SecurityModeChangeContext { - char clientNonce[SECURITY_MODE_NONCE_SIZE]; char serverNonce[SECURITY_MODE_NONCE_SIZE]; - uint64_t requestTime; + char deviceNonce[SECURITY_MODE_NONCE_SIZE]; + char devicePublicKeyFingerprint[Sha256::HASH_SIZE]; + uint64_t prepareTime; }; std::unique_ptr g_securityModeChangeCtx; -int getDevicePrivateKey(mbedtls_pk_context& pk) { +int getPublicKeyFingerprint(mbedtls_pk_context& pk, char fingerprint[Sha256::HASH_SIZE]) { + char pubKeyDer[128]; + int n = mbedtls_pk_write_pubkey_der(&pk, (uint8_t*)pubKeyDer, sizeof(pubKeyDer)); + if (n < 0) { + return mbedtls_to_system_error(n); + } + Sha256 sha; + CHECK(sha.init()); + CHECK(sha.start()); + CHECK(sha.update(pubKeyDer, n)); + CHECK(sha.finish(fingerprint)); + return 0; +} + +int getDevicePrivateKey(mbedtls_pk_context& pk, char pubKeyFingerprint[Sha256::HASH_SIZE]) { std::unique_ptr keyData(new(std::nothrow) uint8_t[DCT_ALT_DEVICE_PRIVATE_KEY_SIZE]); int r = dct_read_app_data_copy(DCT_ALT_DEVICE_PRIVATE_KEY_OFFSET, keyData.get(), DCT_ALT_DEVICE_PRIVATE_KEY_SIZE); if (r != 0) { return SYSTEM_ERROR_IO; } size_t keyLen = determine_der_length(keyData.get(), DCT_ALT_DEVICE_PRIVATE_KEY_SIZE); - if (!keyLen) { + if (!keyLen || keyLen > DCT_ALT_DEVICE_PRIVATE_KEY_SIZE) { return SYSTEM_ERROR_BAD_DATA; } CHECK_MBEDTLS(mbedtls_pk_parse_key(&pk, keyData.get(), keyLen, nullptr /* pwd */, 0 /* pwdlen */)); if (!mbedtls_pk_can_do(&pk, MBEDTLS_PK_ECDSA)) { // Sanity check return SYSTEM_ERROR_NOT_SUPPORTED; } + CHECK(getPublicKeyFingerprint(pk, pubKeyFingerprint)); return 0; } -int getServerPublicKey(mbedtls_pk_context& pk) { +int getServerPublicKey(mbedtls_pk_context& pk, char fingerprint[Sha256::HASH_SIZE]) { std::unique_ptr keyData(new(std::nothrow) uint8_t[DCT_ALT_SERVER_PUBLIC_KEY_SIZE]); int r = dct_read_app_data_copy(DCT_ALT_SERVER_PUBLIC_KEY_OFFSET, keyData.get(), DCT_ALT_SERVER_PUBLIC_KEY_SIZE); if (r != 0) { return SYSTEM_ERROR_IO; } size_t keyLen = determine_der_length(keyData.get(), DCT_ALT_SERVER_PUBLIC_KEY_SIZE); - if (!keyLen) { + if (!keyLen || keyLen > DCT_ALT_SERVER_PUBLIC_KEY_SIZE) { return SYSTEM_ERROR_BAD_DATA; } CHECK_MBEDTLS(mbedtls_pk_parse_public_key(&pk, keyData.get(), keyLen)); + if (!mbedtls_pk_can_do(&pk, MBEDTLS_PK_ECDSA)) { // Sanity check + return SYSTEM_ERROR_NOT_SUPPORTED; + } + CHECK(getPublicKeyFingerprint(pk, fingerprint)); return 0; } @@ -275,7 +292,7 @@ int setProtectedState(ctrl_request* req) { } PB(SetProtectedStateRequest) pbReq = {}; - DecodedString pbServSig(&pbReq.server_signature); + DecodedString pbServSig(&pbReq.confirm_change.server_signature); CHECK(decodeRequestMessage(req, &PB(SetProtectedStateRequest_msg), &pbReq)); PB(SetProtectedStateReply) pbRep = {}; @@ -286,11 +303,10 @@ int setProtectedState(ctrl_request* req) { g_securityModeChangeCtx.reset(); break; } - case PB(SetProtectedStateRequest_Action_DISABLE_REQUEST): { - if (!pbReq.has_server_nonce || pbReq.server_nonce.size != SECURITY_MODE_NONCE_SIZE) { + case PB(SetProtectedStateRequest_Action_PREPARE_CHANGE): { + if (pbReq.prepare_change.server_nonce.size != SECURITY_MODE_NONCE_SIZE) { return SYSTEM_ERROR_INVALID_ARGUMENT; } - g_securityModeChangeCtx.reset(); if (security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_NONE && !security_mode_is_overridden()) { break; // Not protected @@ -299,7 +315,7 @@ int setProtectedState(ctrl_request* req) { if (!ctx) { return SYSTEM_ERROR_NO_MEMORY; } - std::memcpy(ctx->serverNonce, pbReq.server_nonce.bytes, SECURITY_MODE_NONCE_SIZE); + std::memcpy(ctx->serverNonce, pbReq.prepare_change.server_nonce.bytes, SECURITY_MODE_NONCE_SIZE); // Get the device ID and private key uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; // Binary-encoded @@ -312,57 +328,70 @@ int setProtectedState(ctrl_request* req) { SCOPE_GUARD({ mbedtls_pk_free(&pk); }); - CHECK(getDevicePrivateKey(pk)); + CHECK(getDevicePrivateKey(pk, ctx->devicePublicKeyFingerprint)); - // Generate a client nonce and signature - Random::genSecure(ctx->clientNonce, SECURITY_MODE_NONCE_SIZE); + // Generate a device nonce and signature + Random::genSecure(ctx->deviceNonce, SECURITY_MODE_NONCE_SIZE); Sha256 sha; CHECK(sha.init()); CHECK(sha.start()); - CHECK(sha.update("client", 6)); + CHECK(sha.update("device", 6)); CHECK(sha.update((const char*)devId, HAL_DEVICE_ID_SIZE)); - updateSha256Delimited(sha, ctx->clientNonce, SECURITY_MODE_NONCE_SIZE); + updateSha256Delimited(sha, ctx->deviceNonce, SECURITY_MODE_NONCE_SIZE); updateSha256Delimited(sha, ctx->serverNonce, SECURITY_MODE_NONCE_SIZE); char hash[Sha256::HASH_SIZE] = {}; CHECK(sha.finish(hash)); - uint8_t sig[MBEDTLS_ECDSA_MAX_LEN] = {}; - size_t sigLen = 0; - CHECK_MBEDTLS(mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, (const uint8_t*)hash, sizeof(hash), sig, &sigLen, + uint8_t devSig[MBEDTLS_ECDSA_MAX_LEN] = {}; + size_t devSigLen = 0; + CHECK_MBEDTLS(mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, (const uint8_t*)hash, sizeof(hash), devSig, &devSigLen, mbedtls_default_rng, nullptr /* p_rng */)); // Encode a reply - EncodedString pbSig(&pbRep.client_signature, (const char*)sig, sigLen); - std::memcpy(pbRep.client_nonce.bytes, ctx->clientNonce, SECURITY_MODE_NONCE_SIZE); - pbRep.client_nonce.size = SECURITY_MODE_NONCE_SIZE; - pbRep.has_client_nonce = true; + EncodedString pbDevSig(&pbRep.prepare_change.device_signature, (const char*)devSig, devSigLen); + std::memcpy(pbRep.prepare_change.device_nonce.bytes, ctx->deviceNonce, SECURITY_MODE_NONCE_SIZE); + pbRep.prepare_change.device_nonce.size = SECURITY_MODE_NONCE_SIZE; + std::memcpy(pbRep.prepare_change.device_public_key_fingerprint.bytes, ctx->devicePublicKeyFingerprint, Sha256::HASH_SIZE); + pbRep.prepare_change.device_public_key_fingerprint.size = Sha256::HASH_SIZE; CHECK(encodeReplyMessage(req, &PB(SetProtectedStateReply_msg), &pbRep)); - ctx->requestTime = hal_timer_millis(nullptr); + ctx->prepareTime = hal_timer_millis(nullptr); g_securityModeChangeCtx = std::move(ctx); break; } - case PB(SetProtectedStateRequest_Action_DISABLE_CONFIRM): { + case PB(SetProtectedStateRequest_Action_CONFIRM_CHANGE): { if (!g_securityModeChangeCtx) { return SYSTEM_ERROR_INVALID_STATE; } - if (hal_timer_millis(nullptr) - g_securityModeChangeCtx->requestTime >= 60000) { + if (pbReq.confirm_change.server_signature.size == 0 || + pbReq.confirm_change.server_public_key_fingerprint.size != Sha256::HASH_SIZE) { + return SYSTEM_ERROR_INVALID_ARGUMENT; + } + if (hal_timer_millis(nullptr) - g_securityModeChangeCtx->prepareTime >= 60000) { g_securityModeChangeCtx.reset(); return SYSTEM_ERROR_TIMEOUT; } - // Get the device ID and server public key - uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; - const auto n = hal_get_device_id(devId, sizeof(devId)); - if (n != HAL_DEVICE_ID_SIZE) { - return SYSTEM_ERROR_UNKNOWN; - } + // Get the server public key mbedtls_pk_context pk = {}; mbedtls_pk_init(&pk); SCOPE_GUARD({ mbedtls_pk_free(&pk); }); - CHECK(getServerPublicKey(pk)); + char servPubKeyFingerprint[Sha256::HASH_SIZE] = {}; + CHECK(getServerPublicKey(pk, servPubKeyFingerprint)); + + // Validate that the server signature was generated using the correct key + if (std::memcmp(pbReq.confirm_change.server_public_key_fingerprint.bytes, servPubKeyFingerprint, Sha256::HASH_SIZE) != 0) { + return SYSTEM_ERROR_KEY_MISMATCH; + } + + // Get the device ID + uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; + const auto n = hal_get_device_id(devId, sizeof(devId)); + if (n != HAL_DEVICE_ID_SIZE) { + return SYSTEM_ERROR_UNKNOWN; + } // Validate the server signature Sha256 sha; @@ -371,14 +400,15 @@ int setProtectedState(ctrl_request* req) { CHECK(sha.update("server", 6)); CHECK(sha.update((const char*)devId, HAL_DEVICE_ID_SIZE)); updateSha256Delimited(sha, g_securityModeChangeCtx->serverNonce, SECURITY_MODE_NONCE_SIZE); - updateSha256Delimited(sha, g_securityModeChangeCtx->clientNonce, SECURITY_MODE_NONCE_SIZE); + updateSha256Delimited(sha, g_securityModeChangeCtx->deviceNonce, SECURITY_MODE_NONCE_SIZE); + updateSha256Delimited(sha, g_securityModeChangeCtx->devicePublicKeyFingerprint, Sha256::HASH_SIZE); char hash[Sha256::HASH_SIZE] = {}; CHECK(sha.finish(hash)); int r = mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA256, (const uint8_t*)hash, sizeof(hash), (const uint8_t*)pbServSig.data, pbServSig.size); if (r != 0) { - return SYSTEM_ERROR_NOT_ALLOWED; + return SYSTEM_ERROR_INVALID_SIGNATURE; } g_securityModeChangeCtx.reset(); From 0ea7f26a3ddac7b99a3588853f4d40cdc4b96e7a Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Mon, 10 Jun 2024 14:27:44 +0200 Subject: [PATCH 17/35] Minor fix --- system/src/control/config.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index 2ff277adec..43fb55a1e0 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -363,8 +363,7 @@ int setProtectedState(ctrl_request* req) { if (!g_securityModeChangeCtx) { return SYSTEM_ERROR_INVALID_STATE; } - if (pbReq.confirm_change.server_signature.size == 0 || - pbReq.confirm_change.server_public_key_fingerprint.size != Sha256::HASH_SIZE) { + if (pbServSig.size == 0 || pbReq.confirm_change.server_public_key_fingerprint.size != Sha256::HASH_SIZE) { return SYSTEM_ERROR_INVALID_ARGUMENT; } if (hal_timer_millis(nullptr) - g_securityModeChangeCtx->prepareTime >= 60000) { From 0d0b6a48977349e781d6ce80fae16cf79977a91a Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Mon, 10 Jun 2024 15:13:05 +0200 Subject: [PATCH 18/35] Regenerate Protobuf definitions; update submodule refs --- proto_defs/shared | 2 +- proto_defs/src/control/config.pb.c | 6 +- proto_defs/src/control/config.pb.h | 129 +++++++++++++++-------------- 3 files changed, 69 insertions(+), 68 deletions(-) diff --git a/proto_defs/shared b/proto_defs/shared index 5ce398bf66..576c7da3c2 160000 --- a/proto_defs/shared +++ b/proto_defs/shared @@ -1 +1 @@ -Subproject commit 5ce398bf66051bc9684c652d5fdba94c4ba86b06 +Subproject commit 576c7da3c238e6319e7cf2eb62c2b6eb8747e79f diff --git a/proto_defs/src/control/config.pb.c b/proto_defs/src/control/config.pb.c index 53402ee9fb..2996a71ca4 100644 --- a/proto_defs/src/control/config.pb.c +++ b/proto_defs/src/control/config.pb.c @@ -135,16 +135,16 @@ PB_BIND(particle_ctrl_GetProtectedStateReply, particle_ctrl_GetProtectedStateRep PB_BIND(particle_ctrl_SetProtectedStateRequest, particle_ctrl_SetProtectedStateRequest, AUTO) -PB_BIND(particle_ctrl_SetProtectedStateRequest_PrepareChange, particle_ctrl_SetProtectedStateRequest_PrepareChange, AUTO) +PB_BIND(particle_ctrl_SetProtectedStateRequest_Prepare, particle_ctrl_SetProtectedStateRequest_Prepare, AUTO) -PB_BIND(particle_ctrl_SetProtectedStateRequest_ConfirmChange, particle_ctrl_SetProtectedStateRequest_ConfirmChange, AUTO) +PB_BIND(particle_ctrl_SetProtectedStateRequest_Confirm, particle_ctrl_SetProtectedStateRequest_Confirm, AUTO) PB_BIND(particle_ctrl_SetProtectedStateReply, particle_ctrl_SetProtectedStateReply, AUTO) -PB_BIND(particle_ctrl_SetProtectedStateReply_PrepareChange, particle_ctrl_SetProtectedStateReply_PrepareChange, AUTO) +PB_BIND(particle_ctrl_SetProtectedStateReply_Prepare, particle_ctrl_SetProtectedStateReply_Prepare, AUTO) PB_BIND(particle_ctrl_SystemResetRequest, particle_ctrl_SystemResetRequest, AUTO) diff --git a/proto_defs/src/control/config.pb.h b/proto_defs/src/control/config.pb.h index bf4eebdc85..6150b18bfd 100644 --- a/proto_defs/src/control/config.pb.h +++ b/proto_defs/src/control/config.pb.h @@ -50,8 +50,8 @@ typedef enum _particle_ctrl_Feature { /* Note: Use the same values as defined by the security_key_type enum */ typedef enum _particle_ctrl_SetProtectedStateRequest_Action { particle_ctrl_SetProtectedStateRequest_Action_RESET = 0, /* Invalid key */ - particle_ctrl_SetProtectedStateRequest_Action_PREPARE_CHANGE = 1, /* TCP device private key */ - particle_ctrl_SetProtectedStateRequest_Action_CONFIRM_CHANGE = 2 /* TCP device public key */ + particle_ctrl_SetProtectedStateRequest_Action_PREPARE = 1, /* TCP device private key */ + particle_ctrl_SetProtectedStateRequest_Action_CONFIRM = 2 /* TCP device public key */ } particle_ctrl_SetProtectedStateRequest_Action; /* Struct definitions */ @@ -267,26 +267,26 @@ typedef struct _particle_ctrl_SetFeatureRequest { bool enabled; } particle_ctrl_SetFeatureRequest; -typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateReply_PrepareChange_device_nonce_t; -typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateReply_PrepareChange_device_public_key_fingerprint_t; +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateReply_Prepare_device_nonce_t; +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateReply_Prepare_device_public_key_fingerprint_t; /* Enable/disable system features */ -typedef struct _particle_ctrl_SetProtectedStateReply_PrepareChange { - particle_ctrl_SetProtectedStateReply_PrepareChange_device_nonce_t device_nonce; +typedef struct _particle_ctrl_SetProtectedStateReply_Prepare { + particle_ctrl_SetProtectedStateReply_Prepare_device_nonce_t device_nonce; pb_callback_t device_signature; - particle_ctrl_SetProtectedStateReply_PrepareChange_device_public_key_fingerprint_t device_public_key_fingerprint; -} particle_ctrl_SetProtectedStateReply_PrepareChange; + particle_ctrl_SetProtectedStateReply_Prepare_device_public_key_fingerprint_t device_public_key_fingerprint; +} particle_ctrl_SetProtectedStateReply_Prepare; -typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateRequest_ConfirmChange_server_public_key_fingerprint_t; +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateRequest_Confirm_server_public_key_fingerprint_t; /* Resets the device, just like hitting the reset button or powering down and back up */ -typedef struct _particle_ctrl_SetProtectedStateRequest_ConfirmChange { +typedef struct _particle_ctrl_SetProtectedStateRequest_Confirm { pb_callback_t server_signature; - particle_ctrl_SetProtectedStateRequest_ConfirmChange_server_public_key_fingerprint_t server_public_key_fingerprint; -} particle_ctrl_SetProtectedStateRequest_ConfirmChange; + particle_ctrl_SetProtectedStateRequest_Confirm_server_public_key_fingerprint_t server_public_key_fingerprint; +} particle_ctrl_SetProtectedStateRequest_Confirm; -typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateRequest_PrepareChange_server_nonce_t; -typedef struct _particle_ctrl_SetProtectedStateRequest_PrepareChange { - particle_ctrl_SetProtectedStateRequest_PrepareChange_server_nonce_t server_nonce; -} particle_ctrl_SetProtectedStateRequest_PrepareChange; +typedef PB_BYTES_ARRAY_T(32) particle_ctrl_SetProtectedStateRequest_Prepare_server_nonce_t; +typedef struct _particle_ctrl_SetProtectedStateRequest_Prepare { + particle_ctrl_SetProtectedStateRequest_Prepare_server_nonce_t server_nonce; +} particle_ctrl_SetProtectedStateRequest_Prepare; typedef struct _particle_ctrl_SetSecurityKeyRequest { particle_ctrl_SecurityKeyType type; /* Key type */ @@ -315,13 +315,14 @@ typedef struct _particle_ctrl_SetStartupModeRequest { } particle_ctrl_SetStartupModeRequest; typedef struct _particle_ctrl_SetProtectedStateReply { - particle_ctrl_SetProtectedStateReply_PrepareChange prepare_change; + bool has_prepare; + particle_ctrl_SetProtectedStateReply_Prepare prepare; } particle_ctrl_SetProtectedStateReply; typedef struct _particle_ctrl_SetProtectedStateRequest { particle_ctrl_SetProtectedStateRequest_Action action; - particle_ctrl_SetProtectedStateRequest_PrepareChange prepare_change; - particle_ctrl_SetProtectedStateRequest_ConfirmChange confirm_change; + particle_ctrl_SetProtectedStateRequest_Prepare prepare; + particle_ctrl_SetProtectedStateRequest_Confirm confirm; } particle_ctrl_SetProtectedStateRequest; @@ -347,8 +348,8 @@ typedef struct _particle_ctrl_SetProtectedStateRequest { #define _particle_ctrl_Feature_ARRAYSIZE ((particle_ctrl_Feature)(particle_ctrl_Feature_ETHERNET_DETECTION+1)) #define _particle_ctrl_SetProtectedStateRequest_Action_MIN particle_ctrl_SetProtectedStateRequest_Action_RESET -#define _particle_ctrl_SetProtectedStateRequest_Action_MAX particle_ctrl_SetProtectedStateRequest_Action_CONFIRM_CHANGE -#define _particle_ctrl_SetProtectedStateRequest_Action_ARRAYSIZE ((particle_ctrl_SetProtectedStateRequest_Action)(particle_ctrl_SetProtectedStateRequest_Action_CONFIRM_CHANGE+1)) +#define _particle_ctrl_SetProtectedStateRequest_Action_MAX particle_ctrl_SetProtectedStateRequest_Action_CONFIRM +#define _particle_ctrl_SetProtectedStateRequest_Action_ARRAYSIZE ((particle_ctrl_SetProtectedStateRequest_Action)(particle_ctrl_SetProtectedStateRequest_Action_CONFIRM+1)) #ifdef __cplusplus @@ -398,11 +399,11 @@ extern "C" { #define particle_ctrl_SetStartupModeReply_init_default {0} #define particle_ctrl_GetProtectedStateRequest_init_default {0} #define particle_ctrl_GetProtectedStateReply_init_default {0, 0} -#define particle_ctrl_SetProtectedStateRequest_init_default {_particle_ctrl_SetProtectedStateRequest_Action_MIN, particle_ctrl_SetProtectedStateRequest_PrepareChange_init_default, particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_default} -#define particle_ctrl_SetProtectedStateRequest_PrepareChange_init_default {{0, {0}}} -#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_default {{{NULL}, NULL}, {0, {0}}} -#define particle_ctrl_SetProtectedStateReply_init_default {particle_ctrl_SetProtectedStateReply_PrepareChange_init_default} -#define particle_ctrl_SetProtectedStateReply_PrepareChange_init_default {{0, {0}}, {{NULL}, NULL}, {0, {0}}} +#define particle_ctrl_SetProtectedStateRequest_init_default {_particle_ctrl_SetProtectedStateRequest_Action_MIN, particle_ctrl_SetProtectedStateRequest_Prepare_init_default, particle_ctrl_SetProtectedStateRequest_Confirm_init_default} +#define particle_ctrl_SetProtectedStateRequest_Prepare_init_default {{0, {0}}} +#define particle_ctrl_SetProtectedStateRequest_Confirm_init_default {{{NULL}, NULL}, {0, {0}}} +#define particle_ctrl_SetProtectedStateReply_init_default {false, particle_ctrl_SetProtectedStateReply_Prepare_init_default} +#define particle_ctrl_SetProtectedStateReply_Prepare_init_default {{0, {0}}, {{NULL}, NULL}, {0, {0}}} #define particle_ctrl_SystemResetRequest_init_default {0} #define particle_ctrl_SystemResetReply_init_default {0} #define particle_ctrl_SetFeatureRequest_init_default {_particle_ctrl_Feature_MIN, 0} @@ -455,11 +456,11 @@ extern "C" { #define particle_ctrl_SetStartupModeReply_init_zero {0} #define particle_ctrl_GetProtectedStateRequest_init_zero {0} #define particle_ctrl_GetProtectedStateReply_init_zero {0, 0} -#define particle_ctrl_SetProtectedStateRequest_init_zero {_particle_ctrl_SetProtectedStateRequest_Action_MIN, particle_ctrl_SetProtectedStateRequest_PrepareChange_init_zero, particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_zero} -#define particle_ctrl_SetProtectedStateRequest_PrepareChange_init_zero {{0, {0}}} -#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_init_zero {{{NULL}, NULL}, {0, {0}}} -#define particle_ctrl_SetProtectedStateReply_init_zero {particle_ctrl_SetProtectedStateReply_PrepareChange_init_zero} -#define particle_ctrl_SetProtectedStateReply_PrepareChange_init_zero {{0, {0}}, {{NULL}, NULL}, {0, {0}}} +#define particle_ctrl_SetProtectedStateRequest_init_zero {_particle_ctrl_SetProtectedStateRequest_Action_MIN, particle_ctrl_SetProtectedStateRequest_Prepare_init_zero, particle_ctrl_SetProtectedStateRequest_Confirm_init_zero} +#define particle_ctrl_SetProtectedStateRequest_Prepare_init_zero {{0, {0}}} +#define particle_ctrl_SetProtectedStateRequest_Confirm_init_zero {{{NULL}, NULL}, {0, {0}}} +#define particle_ctrl_SetProtectedStateReply_init_zero {false, particle_ctrl_SetProtectedStateReply_Prepare_init_zero} +#define particle_ctrl_SetProtectedStateReply_Prepare_init_zero {{0, {0}}, {{NULL}, NULL}, {0, {0}}} #define particle_ctrl_SystemResetRequest_init_zero {0} #define particle_ctrl_SystemResetReply_init_zero {0} #define particle_ctrl_SetFeatureRequest_init_zero {_particle_ctrl_Feature_MIN, 0} @@ -495,12 +496,12 @@ extern "C" { #define particle_ctrl_SetDeviceSetupDoneRequest_done_tag 1 #define particle_ctrl_SetFeatureRequest_feature_tag 1 #define particle_ctrl_SetFeatureRequest_enabled_tag 2 -#define particle_ctrl_SetProtectedStateReply_PrepareChange_device_nonce_tag 1 -#define particle_ctrl_SetProtectedStateReply_PrepareChange_device_signature_tag 2 -#define particle_ctrl_SetProtectedStateReply_PrepareChange_device_public_key_fingerprint_tag 3 -#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_server_signature_tag 1 -#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_server_public_key_fingerprint_tag 2 -#define particle_ctrl_SetProtectedStateRequest_PrepareChange_server_nonce_tag 1 +#define particle_ctrl_SetProtectedStateReply_Prepare_device_nonce_tag 1 +#define particle_ctrl_SetProtectedStateReply_Prepare_device_signature_tag 2 +#define particle_ctrl_SetProtectedStateReply_Prepare_device_public_key_fingerprint_tag 3 +#define particle_ctrl_SetProtectedStateRequest_Confirm_server_signature_tag 1 +#define particle_ctrl_SetProtectedStateRequest_Confirm_server_public_key_fingerprint_tag 2 +#define particle_ctrl_SetProtectedStateRequest_Prepare_server_nonce_tag 1 #define particle_ctrl_SetSecurityKeyRequest_type_tag 1 #define particle_ctrl_SetSecurityKeyRequest_data_tag 2 #define particle_ctrl_SetServerAddressRequest_protocol_tag 1 @@ -510,10 +511,10 @@ extern "C" { #define particle_ctrl_SetSoftApSsidRequest_prefix_tag 1 #define particle_ctrl_SetSoftApSsidRequest_suffix_tag 2 #define particle_ctrl_SetStartupModeRequest_mode_tag 1 -#define particle_ctrl_SetProtectedStateReply_prepare_change_tag 1 +#define particle_ctrl_SetProtectedStateReply_prepare_tag 1 #define particle_ctrl_SetProtectedStateRequest_action_tag 1 -#define particle_ctrl_SetProtectedStateRequest_prepare_change_tag 2 -#define particle_ctrl_SetProtectedStateRequest_confirm_change_tag 3 +#define particle_ctrl_SetProtectedStateRequest_prepare_tag 2 +#define particle_ctrl_SetProtectedStateRequest_confirm_tag 3 /* Struct field encoding specification for nanopb */ #define particle_ctrl_GetDeviceIdRequest_FIELDLIST(X, a) \ @@ -735,36 +736,36 @@ X(a, STATIC, SINGULAR, BOOL, overridden, 2) #define particle_ctrl_SetProtectedStateRequest_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, action, 1) \ -X(a, STATIC, SINGULAR, MESSAGE, prepare_change, 2) \ -X(a, STATIC, SINGULAR, MESSAGE, confirm_change, 3) +X(a, STATIC, SINGULAR, MESSAGE, prepare, 2) \ +X(a, STATIC, SINGULAR, MESSAGE, confirm, 3) #define particle_ctrl_SetProtectedStateRequest_CALLBACK NULL #define particle_ctrl_SetProtectedStateRequest_DEFAULT NULL -#define particle_ctrl_SetProtectedStateRequest_prepare_change_MSGTYPE particle_ctrl_SetProtectedStateRequest_PrepareChange -#define particle_ctrl_SetProtectedStateRequest_confirm_change_MSGTYPE particle_ctrl_SetProtectedStateRequest_ConfirmChange +#define particle_ctrl_SetProtectedStateRequest_prepare_MSGTYPE particle_ctrl_SetProtectedStateRequest_Prepare +#define particle_ctrl_SetProtectedStateRequest_confirm_MSGTYPE particle_ctrl_SetProtectedStateRequest_Confirm -#define particle_ctrl_SetProtectedStateRequest_PrepareChange_FIELDLIST(X, a) \ +#define particle_ctrl_SetProtectedStateRequest_Prepare_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BYTES, server_nonce, 1) -#define particle_ctrl_SetProtectedStateRequest_PrepareChange_CALLBACK NULL -#define particle_ctrl_SetProtectedStateRequest_PrepareChange_DEFAULT NULL +#define particle_ctrl_SetProtectedStateRequest_Prepare_CALLBACK NULL +#define particle_ctrl_SetProtectedStateRequest_Prepare_DEFAULT NULL -#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_FIELDLIST(X, a) \ +#define particle_ctrl_SetProtectedStateRequest_Confirm_FIELDLIST(X, a) \ X(a, CALLBACK, SINGULAR, BYTES, server_signature, 1) \ X(a, STATIC, SINGULAR, BYTES, server_public_key_fingerprint, 2) -#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_CALLBACK pb_default_field_callback -#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_DEFAULT NULL +#define particle_ctrl_SetProtectedStateRequest_Confirm_CALLBACK pb_default_field_callback +#define particle_ctrl_SetProtectedStateRequest_Confirm_DEFAULT NULL #define particle_ctrl_SetProtectedStateReply_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, MESSAGE, prepare_change, 1) +X(a, STATIC, OPTIONAL, MESSAGE, prepare, 1) #define particle_ctrl_SetProtectedStateReply_CALLBACK NULL #define particle_ctrl_SetProtectedStateReply_DEFAULT NULL -#define particle_ctrl_SetProtectedStateReply_prepare_change_MSGTYPE particle_ctrl_SetProtectedStateReply_PrepareChange +#define particle_ctrl_SetProtectedStateReply_prepare_MSGTYPE particle_ctrl_SetProtectedStateReply_Prepare -#define particle_ctrl_SetProtectedStateReply_PrepareChange_FIELDLIST(X, a) \ +#define particle_ctrl_SetProtectedStateReply_Prepare_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BYTES, device_nonce, 1) \ X(a, CALLBACK, SINGULAR, BYTES, device_signature, 2) \ X(a, STATIC, SINGULAR, BYTES, device_public_key_fingerprint, 3) -#define particle_ctrl_SetProtectedStateReply_PrepareChange_CALLBACK pb_default_field_callback -#define particle_ctrl_SetProtectedStateReply_PrepareChange_DEFAULT NULL +#define particle_ctrl_SetProtectedStateReply_Prepare_CALLBACK pb_default_field_callback +#define particle_ctrl_SetProtectedStateReply_Prepare_DEFAULT NULL #define particle_ctrl_SystemResetRequest_FIELDLIST(X, a) \ @@ -860,10 +861,10 @@ extern const pb_msgdesc_t particle_ctrl_SetStartupModeReply_msg; extern const pb_msgdesc_t particle_ctrl_GetProtectedStateRequest_msg; extern const pb_msgdesc_t particle_ctrl_GetProtectedStateReply_msg; extern const pb_msgdesc_t particle_ctrl_SetProtectedStateRequest_msg; -extern const pb_msgdesc_t particle_ctrl_SetProtectedStateRequest_PrepareChange_msg; -extern const pb_msgdesc_t particle_ctrl_SetProtectedStateRequest_ConfirmChange_msg; +extern const pb_msgdesc_t particle_ctrl_SetProtectedStateRequest_Prepare_msg; +extern const pb_msgdesc_t particle_ctrl_SetProtectedStateRequest_Confirm_msg; extern const pb_msgdesc_t particle_ctrl_SetProtectedStateReply_msg; -extern const pb_msgdesc_t particle_ctrl_SetProtectedStateReply_PrepareChange_msg; +extern const pb_msgdesc_t particle_ctrl_SetProtectedStateReply_Prepare_msg; extern const pb_msgdesc_t particle_ctrl_SystemResetRequest_msg; extern const pb_msgdesc_t particle_ctrl_SystemResetReply_msg; extern const pb_msgdesc_t particle_ctrl_SetFeatureRequest_msg; @@ -919,10 +920,10 @@ extern const pb_msgdesc_t particle_ctrl_StopNyanSignalReply_msg; #define particle_ctrl_GetProtectedStateRequest_fields &particle_ctrl_GetProtectedStateRequest_msg #define particle_ctrl_GetProtectedStateReply_fields &particle_ctrl_GetProtectedStateReply_msg #define particle_ctrl_SetProtectedStateRequest_fields &particle_ctrl_SetProtectedStateRequest_msg -#define particle_ctrl_SetProtectedStateRequest_PrepareChange_fields &particle_ctrl_SetProtectedStateRequest_PrepareChange_msg -#define particle_ctrl_SetProtectedStateRequest_ConfirmChange_fields &particle_ctrl_SetProtectedStateRequest_ConfirmChange_msg +#define particle_ctrl_SetProtectedStateRequest_Prepare_fields &particle_ctrl_SetProtectedStateRequest_Prepare_msg +#define particle_ctrl_SetProtectedStateRequest_Confirm_fields &particle_ctrl_SetProtectedStateRequest_Confirm_msg #define particle_ctrl_SetProtectedStateReply_fields &particle_ctrl_SetProtectedStateReply_msg -#define particle_ctrl_SetProtectedStateReply_PrepareChange_fields &particle_ctrl_SetProtectedStateReply_PrepareChange_msg +#define particle_ctrl_SetProtectedStateReply_Prepare_fields &particle_ctrl_SetProtectedStateReply_Prepare_msg #define particle_ctrl_SystemResetRequest_fields &particle_ctrl_SystemResetRequest_msg #define particle_ctrl_SystemResetReply_fields &particle_ctrl_SystemResetReply_msg #define particle_ctrl_SetFeatureRequest_fields &particle_ctrl_SetFeatureRequest_msg @@ -941,9 +942,9 @@ extern const pb_msgdesc_t particle_ctrl_StopNyanSignalReply_msg; /* particle_ctrl_GetSecurityKeyReply_size depends on runtime parameters */ /* particle_ctrl_GetServerAddressReply_size depends on runtime parameters */ /* particle_ctrl_SetProtectedStateRequest_size depends on runtime parameters */ -/* particle_ctrl_SetProtectedStateRequest_ConfirmChange_size depends on runtime parameters */ +/* particle_ctrl_SetProtectedStateRequest_Confirm_size depends on runtime parameters */ /* particle_ctrl_SetProtectedStateReply_size depends on runtime parameters */ -/* particle_ctrl_SetProtectedStateReply_PrepareChange_size depends on runtime parameters */ +/* particle_ctrl_SetProtectedStateReply_Prepare_size depends on runtime parameters */ #define particle_ctrl_GetDeviceIdReply_size 26 #define particle_ctrl_GetDeviceIdRequest_size 0 #define particle_ctrl_GetDeviceModeReply_size 2 @@ -972,7 +973,7 @@ extern const pb_msgdesc_t particle_ctrl_StopNyanSignalReply_msg; #define particle_ctrl_SetDeviceSetupDoneRequest_size 2 #define particle_ctrl_SetFeatureReply_size 0 #define particle_ctrl_SetFeatureRequest_size 4 -#define particle_ctrl_SetProtectedStateRequest_PrepareChange_size 34 +#define particle_ctrl_SetProtectedStateRequest_Prepare_size 34 #define particle_ctrl_SetSecurityKeyReply_size 0 #define particle_ctrl_SetServerAddressReply_size 0 #define particle_ctrl_SetServerAddressRequest_size 79 From 171a6de0d48d2747de47fd898aebba8dcbfaf062 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Mon, 10 Jun 2024 15:13:23 +0200 Subject: [PATCH 19/35] Minor fixes --- system/src/control/config.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index 43fb55a1e0..5b8dd6c4c7 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -292,7 +292,7 @@ int setProtectedState(ctrl_request* req) { } PB(SetProtectedStateRequest) pbReq = {}; - DecodedString pbServSig(&pbReq.confirm_change.server_signature); + DecodedString pbServSig(&pbReq.confirm.server_signature); CHECK(decodeRequestMessage(req, &PB(SetProtectedStateRequest_msg), &pbReq)); PB(SetProtectedStateReply) pbRep = {}; @@ -303,8 +303,8 @@ int setProtectedState(ctrl_request* req) { g_securityModeChangeCtx.reset(); break; } - case PB(SetProtectedStateRequest_Action_PREPARE_CHANGE): { - if (pbReq.prepare_change.server_nonce.size != SECURITY_MODE_NONCE_SIZE) { + case PB(SetProtectedStateRequest_Action_PREPARE): { + if (pbReq.prepare.server_nonce.size != SECURITY_MODE_NONCE_SIZE) { return SYSTEM_ERROR_INVALID_ARGUMENT; } g_securityModeChangeCtx.reset(); @@ -315,7 +315,7 @@ int setProtectedState(ctrl_request* req) { if (!ctx) { return SYSTEM_ERROR_NO_MEMORY; } - std::memcpy(ctx->serverNonce, pbReq.prepare_change.server_nonce.bytes, SECURITY_MODE_NONCE_SIZE); + std::memcpy(ctx->serverNonce, pbReq.prepare.server_nonce.bytes, SECURITY_MODE_NONCE_SIZE); // Get the device ID and private key uint8_t devId[HAL_DEVICE_ID_SIZE] = {}; // Binary-encoded @@ -348,22 +348,23 @@ int setProtectedState(ctrl_request* req) { mbedtls_default_rng, nullptr /* p_rng */)); // Encode a reply - EncodedString pbDevSig(&pbRep.prepare_change.device_signature, (const char*)devSig, devSigLen); - std::memcpy(pbRep.prepare_change.device_nonce.bytes, ctx->deviceNonce, SECURITY_MODE_NONCE_SIZE); - pbRep.prepare_change.device_nonce.size = SECURITY_MODE_NONCE_SIZE; - std::memcpy(pbRep.prepare_change.device_public_key_fingerprint.bytes, ctx->devicePublicKeyFingerprint, Sha256::HASH_SIZE); - pbRep.prepare_change.device_public_key_fingerprint.size = Sha256::HASH_SIZE; + EncodedString pbDevSig(&pbRep.prepare.device_signature, (const char*)devSig, devSigLen); + std::memcpy(pbRep.prepare.device_nonce.bytes, ctx->deviceNonce, SECURITY_MODE_NONCE_SIZE); + pbRep.prepare.device_nonce.size = SECURITY_MODE_NONCE_SIZE; + std::memcpy(pbRep.prepare.device_public_key_fingerprint.bytes, ctx->devicePublicKeyFingerprint, Sha256::HASH_SIZE); + pbRep.prepare.device_public_key_fingerprint.size = Sha256::HASH_SIZE; + pbRep.has_prepare = true; CHECK(encodeReplyMessage(req, &PB(SetProtectedStateReply_msg), &pbRep)); ctx->prepareTime = hal_timer_millis(nullptr); g_securityModeChangeCtx = std::move(ctx); break; } - case PB(SetProtectedStateRequest_Action_CONFIRM_CHANGE): { + case PB(SetProtectedStateRequest_Action_CONFIRM): { if (!g_securityModeChangeCtx) { return SYSTEM_ERROR_INVALID_STATE; } - if (pbServSig.size == 0 || pbReq.confirm_change.server_public_key_fingerprint.size != Sha256::HASH_SIZE) { + if (pbServSig.size == 0 || pbReq.confirm.server_public_key_fingerprint.size != Sha256::HASH_SIZE) { return SYSTEM_ERROR_INVALID_ARGUMENT; } if (hal_timer_millis(nullptr) - g_securityModeChangeCtx->prepareTime >= 60000) { @@ -381,7 +382,7 @@ int setProtectedState(ctrl_request* req) { CHECK(getServerPublicKey(pk, servPubKeyFingerprint)); // Validate that the server signature was generated using the correct key - if (std::memcmp(pbReq.confirm_change.server_public_key_fingerprint.bytes, servPubKeyFingerprint, Sha256::HASH_SIZE) != 0) { + if (std::memcmp(pbReq.confirm.server_public_key_fingerprint.bytes, servPubKeyFingerprint, Sha256::HASH_SIZE) != 0) { return SYSTEM_ERROR_KEY_MISMATCH; } From 6633acab46e81c6305f59bfef590094844c52d28 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Tue, 11 Jun 2024 16:29:49 +0200 Subject: [PATCH 20/35] Bugfix --- system/src/control/config.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/system/src/control/config.cpp b/system/src/control/config.cpp index 5b8dd6c4c7..48498d44be 100644 --- a/system/src/control/config.cpp +++ b/system/src/control/config.cpp @@ -77,7 +77,7 @@ struct SecurityModeChangeContext { std::unique_ptr g_securityModeChangeCtx; int getPublicKeyFingerprint(mbedtls_pk_context& pk, char fingerprint[Sha256::HASH_SIZE]) { - char pubKeyDer[128]; + char pubKeyDer[128] = {}; // A secp256r1 public key is about 90 bytes long in DER format int n = mbedtls_pk_write_pubkey_der(&pk, (uint8_t*)pubKeyDer, sizeof(pubKeyDer)); if (n < 0) { return mbedtls_to_system_error(n); @@ -85,7 +85,8 @@ int getPublicKeyFingerprint(mbedtls_pk_context& pk, char fingerprint[Sha256::HAS Sha256 sha; CHECK(sha.init()); CHECK(sha.start()); - CHECK(sha.update(pubKeyDer, n)); + // mbedtls_pk_write_pubkey_der() writes at the end of the buffer + CHECK(sha.update(pubKeyDer + sizeof(pubKeyDer) - n, n)); CHECK(sha.finish(fingerprint)); return 0; } From dd2f50c3278e18a2d3c5d0a421f68353724cc6e9 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Wed, 12 Jun 2024 16:20:34 +0200 Subject: [PATCH 21/35] Refactoring --- .../MCU/nRF52840/inc/platform_system_flags.h | 2 +- services/src/security_mode.cpp | 30 ++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/platform/MCU/nRF52840/inc/platform_system_flags.h b/platform/MCU/nRF52840/inc/platform_system_flags.h index 80b50cdd95..f08a4b21b0 100644 --- a/platform/MCU/nRF52840/inc/platform_system_flags.h +++ b/platform/MCU/nRF52840/inc/platform_system_flags.h @@ -37,7 +37,7 @@ typedef struct __attribute__((packed)) platform_system_flags { // This is to prevent against corrupted data causing the bootloader to be unavailable. uint32_t RCC_CSR_SysFlag; - uint8_t security_mode_is_overridden; // If 1, the security mode is temporarily lowered to NONE, otherwise the normal security mode is in effect + uint8_t security_mode_override_value; // If not 0xff, specifies the temporary security mode that overrides the normal mode uint8_t security_mode_override_reset_count; // Number of system resets after which the normal security mode will be restored uint32_t security_mode_override_timeout; // Timeout, in seconds, after which the normal security mode will be restored diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index d6538424b5..af9cb54fef 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -73,16 +73,16 @@ void timerCallback(os_timer_t) { bool stop = false; ATOMIC_BLOCK() { Load_SystemFlags(); - if (system_flags.security_mode_is_overridden == 1) { + if (system_flags.security_mode_override_value != 0xff) { if (system_flags.security_mode_override_timeout > 0) { --system_flags.security_mode_override_timeout; } if (!system_flags.security_mode_override_timeout) { - system_flags.security_mode_is_overridden = 0; + system_flags.security_mode_override_value = 0xff; } Save_SystemFlags(); } - if (system_flags.security_mode_is_overridden != 1) { + if (system_flags.security_mode_override_value == 0xff) { sCurrentSecurityMode = sNormalSecurityMode; stop = true; } @@ -108,9 +108,11 @@ int security_mode_init() { if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { sNormalSecurityMode = ext.security_mode; } - if (sNormalSecurityMode != MODULE_INFO_SECURITY_MODE_NONE) { - Load_SystemFlags(); - sCurrentSecurityMode = (system_flags.security_mode_is_overridden == 1) ? MODULE_INFO_SECURITY_MODE_NONE : sNormalSecurityMode; + Load_SystemFlags(); + if (system_flags.security_mode_override_value != 0xff) { + sCurrentSecurityMode = system_flags.security_mode_override_value; + } else { + sCurrentSecurityMode = sNormalSecurityMode; } return 0; } @@ -212,7 +214,7 @@ void security_mode_override_to_none() { } ATOMIC_BLOCK() { Load_SystemFlags(); - system_flags.security_mode_is_overridden = 1; + system_flags.security_mode_override_value = MODULE_INFO_SECURITY_MODE_NONE; system_flags.security_mode_override_reset_count = 20; system_flags.security_mode_override_timeout = 24 * 60 * 60; // Seconds Save_SystemFlags(); @@ -229,7 +231,7 @@ void security_mode_clear_override() { } ATOMIC_BLOCK() { Load_SystemFlags(); - system_flags.security_mode_is_overridden = 0; + system_flags.security_mode_override_value = 0xff; Save_SystemFlags(); sCurrentSecurityMode = sNormalSecurityMode; } @@ -250,16 +252,16 @@ void security_mode_notify_system_reset() { } ATOMIC_BLOCK() { Load_SystemFlags(); - if (system_flags.security_mode_is_overridden == 1) { + if (system_flags.security_mode_override_value != 0xff) { if (system_flags.security_mode_override_reset_count > 0) { --system_flags.security_mode_override_reset_count; } if (!system_flags.security_mode_override_reset_count) { - system_flags.security_mode_is_overridden = 0; + system_flags.security_mode_override_value = 0xff; } Save_SystemFlags(); } - if (system_flags.security_mode_is_overridden != 1) { + if (system_flags.security_mode_override_value == 0xff) { sCurrentSecurityMode = sNormalSecurityMode; } } @@ -275,16 +277,16 @@ void security_mode_notify_system_tick() { if (!sSystemTickCount) { ATOMIC_BLOCK() { Load_SystemFlags(); - if (system_flags.security_mode_is_overridden == 1) { + if (system_flags.security_mode_override_value != 0xff) { if (system_flags.security_mode_override_timeout > 0) { --system_flags.security_mode_override_timeout; } if (!system_flags.security_mode_override_timeout) { - system_flags.security_mode_is_overridden = 0; + system_flags.security_mode_override_value = 0xff; } Save_SystemFlags(); } - if (system_flags.security_mode_is_overridden != 1) { + if (system_flags.security_mode_override_value == 0xff) { sCurrentSecurityMode = sNormalSecurityMode; } } From 4cac07d03f35e6c0ab3f33180fc99d538468471c Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Wed, 12 Jun 2024 16:27:02 +0200 Subject: [PATCH 22/35] Do not disable logging when the device is protected --- services/src/logging.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/services/src/logging.cpp b/services/src/logging.cpp index d72e35657f..90de5a87ea 100644 --- a/services/src/logging.cpp +++ b/services/src/logging.cpp @@ -22,7 +22,6 @@ #include "timer_hal.h" #include "service_debug.h" #include "static_assert.h" -#include "security_mode.h" #define STATIC_ASSERT_FIELD_SIZE(struct, field, size) \ STATIC_ASSERT(field_size_changed_##struct##_##field, sizeof(struct::field) == size); @@ -80,8 +79,7 @@ void log_set_callbacks(log_message_callback_type log_msg, log_write_callback_typ void log_message_v(int level, const char *category, LogAttributes *attr, void *reserved, const char *fmt, va_list args) { const log_message_callback_type msg_callback = log_msg_callback; - if ((!msg_callback && (!log_compat_callback || level < log_compat_level)) || - security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_PROTECTED) { + if (!msg_callback && (!log_compat_callback || level < log_compat_level)) { return; } // Set default attributes @@ -129,7 +127,7 @@ void log_message(int level, const char *category, LogAttributes *attr, void *res } void log_write(int level, const char *category, const char *data, size_t size, void *reserved) { - if (!size || security_mode_get(nullptr) == MODULE_INFO_SECURITY_MODE_PROTECTED) { + if (!size) { return; } const log_write_callback_type write_callback = log_write_callback; From 46d4e6d48cadcc7d42d6865d018b97af458b44b7 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Wed, 12 Jun 2024 18:21:05 +0200 Subject: [PATCH 23/35] Disable Serial if the device is protected --- hal/inc/hal_dynalib_usb.h | 10 +++++----- hal/inc/usb_hal.h | 12 +++++++----- hal/src/nRF52840/usb_hal.cpp | 27 +++++++++++++++++++++++++++ hal/src/rtl872x/usb_hal.cpp | 27 +++++++++++++++++++++++++++ system-dynalib/makefile | 2 +- 5 files changed, 67 insertions(+), 11 deletions(-) diff --git a/hal/inc/hal_dynalib_usb.h b/hal/inc/hal_dynalib_usb.h index d501e81cf2..93c5f43914 100644 --- a/hal/inc/hal_dynalib_usb.h +++ b/hal/inc/hal_dynalib_usb.h @@ -43,11 +43,11 @@ DYNALIB_FN(0, hal_usb, HAL_USB_USART_Init, void(HAL_USB_USART_Serial, const HAL_ DYNALIB_FN(1, hal_usb, HAL_USB_USART_Begin, void(HAL_USB_USART_Serial, uint32_t, void *)) DYNALIB_FN(2, hal_usb, HAL_USB_USART_End, void(HAL_USB_USART_Serial)) DYNALIB_FN(3, hal_usb, HAL_USB_USART_Baud_Rate, unsigned int(HAL_USB_USART_Serial)) -DYNALIB_FN(4, hal_usb, HAL_USB_USART_Available_Data, int32_t(HAL_USB_USART_Serial)) -DYNALIB_FN(5, hal_usb, HAL_USB_USART_Available_Data_For_Write, int32_t(HAL_USB_USART_Serial)) -DYNALIB_FN(6, hal_usb, HAL_USB_USART_Receive_Data, int32_t(HAL_USB_USART_Serial, uint8_t)) -DYNALIB_FN(7, hal_usb, HAL_USB_USART_Send_Data, int32_t(HAL_USB_USART_Serial, uint8_t)) -DYNALIB_FN(8, hal_usb, HAL_USB_USART_Flush_Data, void(HAL_USB_USART_Serial)) +DYNALIB_FN_WRAP(4, hal_usb, HAL_USB_USART_Available_Data, protected, int32_t(HAL_USB_USART_Serial)) +DYNALIB_FN_WRAP(5, hal_usb, HAL_USB_USART_Available_Data_For_Write, protected, int32_t(HAL_USB_USART_Serial)) +DYNALIB_FN_WRAP(6, hal_usb, HAL_USB_USART_Receive_Data, protected, int32_t(HAL_USB_USART_Serial, uint8_t)) +DYNALIB_FN_WRAP(7, hal_usb, HAL_USB_USART_Send_Data, protected, int32_t(HAL_USB_USART_Serial, uint8_t)) +DYNALIB_FN_WRAP(8, hal_usb, HAL_USB_USART_Flush_Data, protected, void(HAL_USB_USART_Serial)) DYNALIB_FN(9, hal_usb, HAL_USB_USART_Is_Enabled, bool(HAL_USB_USART_Serial)) DYNALIB_FN(10, hal_usb, HAL_USB_USART_Is_Connected, bool(HAL_USB_USART_Serial)) DYNALIB_FN(11, hal_usb, HAL_USB_USART_LineCoding_BitRate_Handler, int32_t(void (*handler)(uint32_t bitRate), void* reserved)) diff --git a/hal/inc/usb_hal.h b/hal/inc/usb_hal.h index fb511accee..551b5bcb6d 100644 --- a/hal/inc/usb_hal.h +++ b/hal/inc/usb_hal.h @@ -43,6 +43,8 @@ #include "hw_config.h" #endif +#include "security_mode.h" + #ifdef __cplusplus extern "C" { #endif @@ -204,11 +206,11 @@ void HAL_USB_USART_Init(HAL_USB_USART_Serial serial, const HAL_USB_USART_Config* void HAL_USB_USART_Begin(HAL_USB_USART_Serial serial, uint32_t baud, void *reserved); void HAL_USB_USART_End(HAL_USB_USART_Serial serial); unsigned int HAL_USB_USART_Baud_Rate(HAL_USB_USART_Serial serial); -int32_t HAL_USB_USART_Available_Data(HAL_USB_USART_Serial serial); -int32_t HAL_USB_USART_Available_Data_For_Write(HAL_USB_USART_Serial serial); -int32_t HAL_USB_USART_Receive_Data(HAL_USB_USART_Serial serial, uint8_t peek); -int32_t HAL_USB_USART_Send_Data(HAL_USB_USART_Serial serial, uint8_t data); -void HAL_USB_USART_Flush_Data(HAL_USB_USART_Serial serial); +SECURITY_MODE_PROTECTED_FN(int32_t, HAL_USB_USART_Available_Data, (HAL_USB_USART_Serial serial)); +SECURITY_MODE_PROTECTED_FN(int32_t, HAL_USB_USART_Available_Data_For_Write, (HAL_USB_USART_Serial serial)); +SECURITY_MODE_PROTECTED_FN(int32_t, HAL_USB_USART_Receive_Data, (HAL_USB_USART_Serial serial, uint8_t peek)); +SECURITY_MODE_PROTECTED_FN(int32_t, HAL_USB_USART_Send_Data, (HAL_USB_USART_Serial serial, uint8_t data)); +SECURITY_MODE_PROTECTED_FN(void, HAL_USB_USART_Flush_Data, (HAL_USB_USART_Serial serial)); bool HAL_USB_USART_Is_Enabled(HAL_USB_USART_Serial serial); bool HAL_USB_USART_Is_Connected(HAL_USB_USART_Serial serial); int32_t HAL_USB_USART_LineCoding_BitRate_Handler(void (*handler)(uint32_t bitRate), void* reserved); diff --git a/hal/src/nRF52840/usb_hal.cpp b/hal/src/nRF52840/usb_hal.cpp index ddc3f225f5..bb2429f1ef 100644 --- a/hal/src/nRF52840/usb_hal.cpp +++ b/hal/src/nRF52840/usb_hal.cpp @@ -92,10 +92,20 @@ int32_t HAL_USB_USART_Available_Data(HAL_USB_USART_Serial serial) { return usb_uart_available_rx_data(); } +int32_t HAL_USB_USART_Available_Data_protected(HAL_USB_USART_Serial serial) { + CHECK_SECURITY_MODE_PROTECTED(); + return HAL_USB_USART_Available_Data(serial); +} + int32_t HAL_USB_USART_Available_Data_For_Write(HAL_USB_USART_Serial serial) { return usb_uart_available_tx_data(); } +int32_t HAL_USB_USART_Available_Data_For_Write_protected(HAL_USB_USART_Serial serial) { + CHECK_SECURITY_MODE_PROTECTED(); + return HAL_USB_USART_Available_Data_For_Write(serial); +} + int32_t HAL_USB_USART_Receive_Data(HAL_USB_USART_Serial serial, uint8_t peek) { if (usb_uart_available_rx_data() == 0) { return -1; @@ -108,14 +118,31 @@ int32_t HAL_USB_USART_Receive_Data(HAL_USB_USART_Serial serial, uint8_t peek) { } } +int32_t HAL_USB_USART_Receive_Data_protected(HAL_USB_USART_Serial serial, uint8_t peek) { + CHECK_SECURITY_MODE_PROTECTED(); + return HAL_USB_USART_Receive_Data(serial, peek); +} + int32_t HAL_USB_USART_Send_Data(HAL_USB_USART_Serial serial, uint8_t data) { return usb_uart_send(&data, 1); } +int32_t HAL_USB_USART_Send_Data_protected(HAL_USB_USART_Serial serial, uint8_t data) { + CHECK_SECURITY_MODE_PROTECTED(); + return HAL_USB_USART_Send_Data(serial, data); +} + void HAL_USB_USART_Flush_Data(HAL_USB_USART_Serial serial) { usb_uart_flush_tx_data(); } +void HAL_USB_USART_Flush_Data_protected(HAL_USB_USART_Serial serial) { + if (security_mode_get(NULL) == MODULE_INFO_SECURITY_MODE_PROTECTED) { + return; + } + HAL_USB_USART_Flush_Data(serial); +} + bool HAL_USB_USART_Is_Enabled(HAL_USB_USART_Serial serial) { return usb_hal_is_enabled(); } diff --git a/hal/src/rtl872x/usb_hal.cpp b/hal/src/rtl872x/usb_hal.cpp index 3fea189f21..eb93e93771 100644 --- a/hal/src/rtl872x/usb_hal.cpp +++ b/hal/src/rtl872x/usb_hal.cpp @@ -170,6 +170,11 @@ int32_t HAL_USB_USART_Available_Data(HAL_USB_USART_Serial serial) { return getCdcClassDriver().available(); } +int32_t HAL_USB_USART_Available_Data_protected(HAL_USB_USART_Serial serial) { + CHECK_SECURITY_MODE_PROTECTED(); + return HAL_USB_USART_Available_Data(serial); +} + int32_t HAL_USB_USART_Available_Data_For_Write(HAL_USB_USART_Serial serial) { if (serial != HAL_USB_USART_SERIAL) { return SYSTEM_ERROR_INVALID_ARGUMENT; @@ -180,6 +185,11 @@ int32_t HAL_USB_USART_Available_Data_For_Write(HAL_USB_USART_Serial serial) { return getCdcClassDriver().availableForWrite(); } +int32_t HAL_USB_USART_Available_Data_For_Write_protected(HAL_USB_USART_Serial serial) { + CHECK_SECURITY_MODE_PROTECTED(); + return HAL_USB_USART_Available_Data_For_Write(serial); +} + int32_t HAL_USB_USART_Receive_Data(HAL_USB_USART_Serial serial, uint8_t peek) { if (serial != HAL_USB_USART_SERIAL) { return SYSTEM_ERROR_INVALID_ARGUMENT; @@ -197,6 +207,11 @@ int32_t HAL_USB_USART_Receive_Data(HAL_USB_USART_Serial serial, uint8_t peek) { return r; } +int32_t HAL_USB_USART_Receive_Data_protected(HAL_USB_USART_Serial serial, uint8_t peek) { + CHECK_SECURITY_MODE_PROTECTED(); + return HAL_USB_USART_Receive_Data(serial, peek); +} + int32_t HAL_USB_USART_Send_Data(HAL_USB_USART_Serial serial, uint8_t data) { if (serial != HAL_USB_USART_SERIAL) { return SYSTEM_ERROR_INVALID_ARGUMENT; @@ -220,6 +235,11 @@ int32_t HAL_USB_USART_Send_Data(HAL_USB_USART_Serial serial, uint8_t data) { return -1; } +int32_t HAL_USB_USART_Send_Data_protected(HAL_USB_USART_Serial serial, uint8_t data) { + CHECK_SECURITY_MODE_PROTECTED(); + return HAL_USB_USART_Send_Data(serial, data); +} + void HAL_USB_USART_Flush_Data(HAL_USB_USART_Serial serial) { if (serial != HAL_USB_USART_SERIAL) { return; @@ -227,6 +247,13 @@ void HAL_USB_USART_Flush_Data(HAL_USB_USART_Serial serial) { return getCdcClassDriver().flush(); } +void HAL_USB_USART_Flush_Data_protected(HAL_USB_USART_Serial serial) { + if (security_mode_get(NULL) == MODULE_INFO_SECURITY_MODE_PROTECTED) { + return; + } + return HAL_USB_USART_Flush_Data(serial); +} + bool HAL_USB_USART_Is_Enabled(HAL_USB_USART_Serial serial) { if (serial != HAL_USB_USART_SERIAL) { return false; diff --git a/system-dynalib/makefile b/system-dynalib/makefile index da49e7ca9f..7687940574 100644 --- a/system-dynalib/makefile +++ b/system-dynalib/makefile @@ -4,6 +4,6 @@ SYSTEM_DYNALIB_MODULE_PATH=. TARGET_TYPE = a BUILD_PATH_EXT = $(SYSTEM_DYNALIB_BUILD_PATH_EXT) -DEPENDENCIES = system dynalib hal +DEPENDENCIES = system dynalib hal services include ../build/arm-tlm.mk From 0b0a07fcdfa33da783da7b2e265828f2cb66aed0 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 14 Jun 2024 10:01:18 +0200 Subject: [PATCH 24/35] Allow unprotecting the device over BLE --- services/src/security_mode.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index af9cb54fef..16e1d604c7 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -107,12 +107,12 @@ int security_mode_init() { CHECK(security_mode_find_module_extension(HAL_STORAGE_ID_INTERNAL_FLASH, module_bootloader.start_address, &ext)); if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { sNormalSecurityMode = ext.security_mode; - } - Load_SystemFlags(); - if (system_flags.security_mode_override_value != 0xff) { - sCurrentSecurityMode = system_flags.security_mode_override_value; - } else { - sCurrentSecurityMode = sNormalSecurityMode; + Load_SystemFlags(); + if (system_flags.security_mode_override_value != 0xff) { + sCurrentSecurityMode = system_flags.security_mode_override_value; + } else { + sCurrentSecurityMode = sNormalSecurityMode; + } } return 0; } @@ -179,6 +179,7 @@ int security_mode_check_control_request(security_mode_transport transport, uint1 if (transport == SECURITY_MODE_TRANSPORT_USB || transport == SECURITY_MODE_TRANSPORT_BLE) { switch (id) { + case CTRL_REQUEST_SET_PROTECTED_STATE: case CTRL_REQUEST_GET_PROTECTED_STATE: case CTRL_REQUEST_DEVICE_ID: case CTRL_REQUEST_APP_CUSTOM: { @@ -187,14 +188,6 @@ int security_mode_check_control_request(security_mode_transport transport, uint1 } } - if (transport == SECURITY_MODE_TRANSPORT_USB) { - switch (id) { - case CTRL_REQUEST_SET_PROTECTED_STATE: { - return 0; - } - } - } - if (transport == SECURITY_MODE_TRANSPORT_BLE) { switch (id) { case CTRL_REQUEST_WIFI_SCAN_NETWORKS: From f314d64b869792dfb16644a39589e45950ba74c3 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 14 Jun 2024 13:16:42 +0200 Subject: [PATCH 25/35] Fix GCC build --- services/src/security_mode.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index 16e1d604c7..2fecfc5dac 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -15,9 +15,11 @@ * License along with this library; if not, see . */ -#include - #include "security_mode.h" +#include "hal_platform.h" + +#if PLATFORM_ID != PLATFORM_GCC + #include "flash_mal.h" #include "system_error.h" #include "check.h" @@ -29,6 +31,8 @@ #include "ota_flash_hal_impl.h" #include "hw_config.h" +#include + namespace { volatile int sCurrentSecurityMode = MODULE_INFO_SECURITY_MODE_NONE; @@ -104,8 +108,8 @@ int security_mode_init() { } module_info_security_mode_ext_t ext = {}; ext.ext.length = sizeof(ext); - CHECK(security_mode_find_module_extension(HAL_STORAGE_ID_INTERNAL_FLASH, module_bootloader.start_address, &ext)); - if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { + int r = security_mode_find_module_extension(HAL_STORAGE_ID_INTERNAL_FLASH, module_bootloader.start_address, &ext); + if (r >= 0 && ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { sNormalSecurityMode = ext.security_mode; Load_SystemFlags(); if (system_flags.security_mode_override_value != 0xff) { @@ -300,3 +304,22 @@ void security_mode_notify_system_ready() { } #endif // MODULE_FUNCTION != MOD_FUNC_BOOTLOADER + +#else // PLATFORM_ID == PLATFORM_GCC + +int security_mode_get(void* reserved) { + return MODULE_INFO_SECURITY_MODE_NONE; +} + +bool security_mode_is_overridden() { + return false; +} + +void security_mode_notify_system_ready() { +} + +int security_mode_find_module_extension(hal_storage_id storageId, uintptr_t start, module_info_security_mode_ext_t* securityModeExt) { + return SYSTEM_ERROR_NOT_FOUND; +} + +#endif // PLATFORM_ID == PLATFORM_GCC From 2e07037ea232fd08f7a3dc5e9c7801fea6863239 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 14 Jun 2024 13:40:00 +0200 Subject: [PATCH 26/35] Fix newhal build --- services/src/security_mode.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index 2fecfc5dac..594854431d 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -18,7 +18,7 @@ #include "security_mode.h" #include "hal_platform.h" -#if PLATFORM_ID != PLATFORM_GCC +#if PLATFORM_ID != PLATFORM_GCC && PLATFORM_ID != PLATFORM_NEWHAL #include "flash_mal.h" #include "system_error.h" @@ -109,7 +109,12 @@ int security_mode_init() { module_info_security_mode_ext_t ext = {}; ext.ext.length = sizeof(ext); int r = security_mode_find_module_extension(HAL_STORAGE_ID_INTERNAL_FLASH, module_bootloader.start_address, &ext); - if (r >= 0 && ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { + // XXX: security_mode_find_module_extension() should ideally not return an error if the bootloader + // is not protected + if (r < 0 && r != SYSTEM_ERROR_NOT_FOUND) { + return r; + } + if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { sNormalSecurityMode = ext.security_mode; Load_SystemFlags(); if (system_flags.security_mode_override_value != 0xff) { @@ -305,7 +310,7 @@ void security_mode_notify_system_ready() { #endif // MODULE_FUNCTION != MOD_FUNC_BOOTLOADER -#else // PLATFORM_ID == PLATFORM_GCC +#else // PLATFORM_ID == PLATFORM_GCC || PLATFORM_ID == PLATFORM_NEWHAL int security_mode_get(void* reserved) { return MODULE_INFO_SECURITY_MODE_NONE; @@ -322,4 +327,4 @@ int security_mode_find_module_extension(hal_storage_id storageId, uintptr_t star return SYSTEM_ERROR_NOT_FOUND; } -#endif // PLATFORM_ID == PLATFORM_GCC +#endif // PLATFORM_ID == PLATFORM_GCC || PLATFORM_ID == PLATFORM_NEWHAL From 03b1275ad203056a6fde7d306429cd2931f9be25 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 14 Jun 2024 15:37:53 +0200 Subject: [PATCH 27/35] Fix rtl872x builds --- platform/MCU/rtl872x/inc/platform_system_flags.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/MCU/rtl872x/inc/platform_system_flags.h b/platform/MCU/rtl872x/inc/platform_system_flags.h index d763154616..85d0f8f373 100644 --- a/platform/MCU/rtl872x/inc/platform_system_flags.h +++ b/platform/MCU/rtl872x/inc/platform_system_flags.h @@ -39,7 +39,12 @@ typedef struct __attribute__((packed)) platform_system_flags { // bit 0: 1: restore backup ram from flash // bit 1: 1: session data in flash is stale uint16_t restore_backup_ram; - uint16_t reserved[3]; + + uint8_t security_mode_override_value; // If not 0xff, specifies the temporary security mode that overrides the normal mode + uint8_t security_mode_override_reset_count; // Number of system resets after which the normal security mode will be restored + uint32_t security_mode_override_timeout; // Timeout, in seconds, after which the normal security mode will be restored + + uint16_t reserved[0]; } platform_system_flags_t; PARTICLE_STATIC_ASSERT(platform_system_flags_size_changed, sizeof(platform_system_flags_t) == 32); From c116ce7e55a9710612c8e5eb07dceea2f21b5496 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 14 Jun 2024 17:52:55 +0200 Subject: [PATCH 28/35] Clear the device protection override if the bootloader is not protected --- services/src/security_mode.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index 594854431d..f7f9c4f41e 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -114,14 +114,18 @@ int security_mode_init() { if (r < 0 && r != SYSTEM_ERROR_NOT_FOUND) { return r; } + Load_SystemFlags(); if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { sNormalSecurityMode = ext.security_mode; - Load_SystemFlags(); if (system_flags.security_mode_override_value != 0xff) { sCurrentSecurityMode = system_flags.security_mode_override_value; } else { sCurrentSecurityMode = sNormalSecurityMode; } + } else if (system_flags.security_mode_override_value != 0xff) { + // Clear the override in case the bootloader was protected previously + system_flags.security_mode_override_value = 0xff; + Save_SystemFlags(); } return 0; } From 3c92c5dda54b26171be75d1ec213507f666e7417 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Fri, 14 Jun 2024 18:54:25 +0200 Subject: [PATCH 29/35] Minor refactoring --- services/src/security_mode.cpp | 48 ++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/services/src/security_mode.cpp b/services/src/security_mode.cpp index f7f9c4f41e..3b1aa18da1 100644 --- a/services/src/security_mode.cpp +++ b/services/src/security_mode.cpp @@ -103,31 +103,39 @@ void timerCallback(os_timer_t) { int security_mode_init() { // Note that this function is called early on boot, before the heap is configured and C++ // constructors are called - if (!FLASH_VerifyCRC32(FLASH_INTERNAL, module_bootloader.start_address, FLASH_ModuleLength(FLASH_INTERNAL, module_bootloader.start_address))) { - return SYSTEM_ERROR_BAD_DATA; - } - module_info_security_mode_ext_t ext = {}; - ext.ext.length = sizeof(ext); - int r = security_mode_find_module_extension(HAL_STORAGE_ID_INTERNAL_FLASH, module_bootloader.start_address, &ext); - // XXX: security_mode_find_module_extension() should ideally not return an error if the bootloader - // is not protected - if (r < 0 && r != SYSTEM_ERROR_NOT_FOUND) { - return r; + int result = 0; + int normalMode = MODULE_INFO_SECURITY_MODE_NONE; + if (FLASH_VerifyCRC32(FLASH_INTERNAL, module_bootloader.start_address, FLASH_ModuleLength(FLASH_INTERNAL, module_bootloader.start_address))) { + module_info_security_mode_ext_t ext = {}; + ext.ext.length = sizeof(ext); + int r = security_mode_find_module_extension(HAL_STORAGE_ID_INTERNAL_FLASH, module_bootloader.start_address, &ext); + if (r >= 0 && ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { + normalMode = ext.security_mode; + } else if (r < 0 && r != SYSTEM_ERROR_NOT_FOUND) { + // XXX: It's not ideal that security_mode_find_module_extension() returns SYSTEM_ERROR_NOT_FOUND + // if the bootloader is not protected as that code may also indicate a legit error that occurred + // elsewhere down the stack + LOG(ERROR, "Failed to parse bootloader module extensions: %d", r); + result = r; + } + } else { + LOG(ERROR, "Invalid bootloader checksum"); + result = SYSTEM_ERROR_BAD_DATA; } + int currentMode = normalMode; Load_SystemFlags(); - if (ext.security_mode == MODULE_INFO_SECURITY_MODE_PROTECTED) { - sNormalSecurityMode = ext.security_mode; - if (system_flags.security_mode_override_value != 0xff) { - sCurrentSecurityMode = system_flags.security_mode_override_value; + if (system_flags.security_mode_override_value != 0xff) { + if (normalMode != MODULE_INFO_SECURITY_MODE_NONE) { + currentMode = system_flags.security_mode_override_value; } else { - sCurrentSecurityMode = sNormalSecurityMode; + // Clear the override in case the bootloader was protected previously + system_flags.security_mode_override_value = 0xff; + Save_SystemFlags(); } - } else if (system_flags.security_mode_override_value != 0xff) { - // Clear the override in case the bootloader was protected previously - system_flags.security_mode_override_value = 0xff; - Save_SystemFlags(); } - return 0; + sNormalSecurityMode = normalMode; + sCurrentSecurityMode = currentMode; + return result; } int security_mode_get(void* reserved) { From 2a023fc0a15b5486c22fbd422ed25a4183eb49d6 Mon Sep 17 00:00:00 2001 From: Andrey Tolstoy Date: Tue, 18 Jun 2024 16:17:08 +0700 Subject: [PATCH 30/35] [gen3] disable IP_FRAG and IP_REASSEMBLY to save flash space --- hal/src/nRF52840/lwip/lwipopts.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hal/src/nRF52840/lwip/lwipopts.h b/hal/src/nRF52840/lwip/lwipopts.h index bd50666ff7..dea45d09aa 100644 --- a/hal/src/nRF52840/lwip/lwipopts.h +++ b/hal/src/nRF52840/lwip/lwipopts.h @@ -451,14 +451,14 @@ void sys_unlock_tcpip_core(void); * this option does not affect outgoing packet sizes, which can be controlled * via IP_FRAG. */ -#define IP_REASSEMBLY (PLATFORM_ID != PLATFORM_TRACKER) +#define IP_REASSEMBLY (0) /** * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note * that this option does not affect incoming packet sizes, which can be * controlled via IP_REASSEMBLY. */ -#define IP_FRAG (PLATFORM_ID != PLATFORM_TRACKER) +#define IP_FRAG (0) /** * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. From 13605e36fc602743ca73abf4248aa6e605ceaac9 Mon Sep 17 00:00:00 2001 From: Sergey Polyakov Date: Tue, 18 Jun 2024 16:13:41 +0200 Subject: [PATCH 31/35] Add a custom DfuSe command for entring safe mode --- bootloader/src/nRF52840/usbd_dfu.cpp | 11 ++++++++++- bootloader/src/nRF52840/usbd_dfu.h | 3 ++- bootloader/src/rtl872x/usbd_dfu.cpp | 11 ++++++++++- bootloader/src/rtl872x/usbd_dfu.h | 3 ++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/bootloader/src/nRF52840/usbd_dfu.cpp b/bootloader/src/nRF52840/usbd_dfu.cpp index 57953ab972..72a8ae9eb9 100644 --- a/bootloader/src/nRF52840/usbd_dfu.cpp +++ b/bootloader/src/nRF52840/usbd_dfu.cpp @@ -19,6 +19,8 @@ #include #include "hal_irq_flag.h" #include "security_mode.h" +#include "core_hal.h" +#include "syshealth_hal.h" using namespace particle::usbd; using namespace particle::usbd::dfu; @@ -215,8 +217,9 @@ int DfuClassDriver::handleDfuUpload(SetupRequest* req) { transferBuf_[0] = detail::DFUSE_COMMAND_GET_COMMAND; transferBuf_[1] = detail::DFUSE_COMMAND_SET_ADDRESS_POINTER; transferBuf_[2] = detail::DFUSE_COMMAND_ERASE; + transferBuf_[3] = detail::DFUSE_COMMAND_ENTER_SAFE_MODE; setState(detail::dfuIDLE); - dev_->setupReply(req, transferBuf_, 3); + dev_->setupReply(req, transferBuf_, 4); } else if (req_.wValue > 1) { /* Normal request */ setState(detail::dfuUPLOAD_IDLE); @@ -488,6 +491,12 @@ int DfuClassDriver::inDone(uint8_t ep, unsigned status) { } break; } + case detail::DFUSE_COMMAND_ENTER_SAFE_MODE: { + HAL_Core_Write_Backup_Register(BKP_DR_01, ENTER_SAFE_MODE_APP_REQUEST); + setState(detail::dfuMANIFEST_SYNC); + setStatus(detail::OK); + break; + } case detail::DFUSE_COMMAND_READ_UNPROTECT: { /* Unsupported */ setError(detail::errUNKNOWN); diff --git a/bootloader/src/nRF52840/usbd_dfu.h b/bootloader/src/nRF52840/usbd_dfu.h index 8a1d9e4808..e1f560ac5f 100644 --- a/bootloader/src/nRF52840/usbd_dfu.h +++ b/bootloader/src/nRF52840/usbd_dfu.h @@ -166,7 +166,8 @@ enum DfuseCommand { DFUSE_COMMAND_GET_COMMAND = 0x00, DFUSE_COMMAND_SET_ADDRESS_POINTER = 0x21, DFUSE_COMMAND_ERASE = 0x41, - DFUSE_COMMAND_READ_UNPROTECT = 0x92 + DFUSE_COMMAND_READ_UNPROTECT = 0x92, + DFUSE_COMMAND_ENTER_SAFE_MODE = 0xfa /* Particle's extension */ }; #pragma pack(push, 1) diff --git a/bootloader/src/rtl872x/usbd_dfu.cpp b/bootloader/src/rtl872x/usbd_dfu.cpp index 8adbfb9a13..59f45dbfd9 100644 --- a/bootloader/src/rtl872x/usbd_dfu.cpp +++ b/bootloader/src/rtl872x/usbd_dfu.cpp @@ -20,6 +20,8 @@ #include "hal_irq_flag.h" #include #include "security_mode.h" +#include "core_hal.h" +#include "syshealth_hal.h" using namespace particle::usbd; using namespace particle::usbd::dfu; @@ -216,8 +218,9 @@ int DfuClassDriver::handleDfuUpload(SetupRequest* req) { transferBuf_[0] = detail::DFUSE_COMMAND_GET_COMMAND; transferBuf_[1] = detail::DFUSE_COMMAND_SET_ADDRESS_POINTER; transferBuf_[2] = detail::DFUSE_COMMAND_ERASE; + transferBuf_[3] = detail::DFUSE_COMMAND_ENTER_SAFE_MODE; setState(detail::dfuIDLE); - dev_->setupReply(req, transferBuf_, 3); + dev_->setupReply(req, transferBuf_, 4); } else if (req_.wValue > 1) { /* Normal request */ setState(detail::dfuUPLOAD_IDLE); @@ -473,6 +476,12 @@ int DfuClassDriver::dataIn(unsigned ep, particle::usbd::EndpointEvent ev, size_t } break; } + case detail::DFUSE_COMMAND_ENTER_SAFE_MODE: { + HAL_Core_Write_Backup_Register(BKP_DR_01, ENTER_SAFE_MODE_APP_REQUEST); + setState(detail::dfuMANIFEST_SYNC); + setStatus(detail::OK); + break; + } case detail::DFUSE_COMMAND_READ_UNPROTECT: { /* Unsupported */ setError(detail::errUNKNOWN); diff --git a/bootloader/src/rtl872x/usbd_dfu.h b/bootloader/src/rtl872x/usbd_dfu.h index feb8ffcdf5..3aaf5a6663 100644 --- a/bootloader/src/rtl872x/usbd_dfu.h +++ b/bootloader/src/rtl872x/usbd_dfu.h @@ -162,7 +162,8 @@ enum DfuseCommand { DFUSE_COMMAND_GET_COMMAND = 0x00, DFUSE_COMMAND_SET_ADDRESS_POINTER = 0x21, DFUSE_COMMAND_ERASE = 0x41, - DFUSE_COMMAND_READ_UNPROTECT = 0x92 + DFUSE_COMMAND_READ_UNPROTECT = 0x92, + DFUSE_COMMAND_ENTER_SAFE_MODE = 0xfa /* Particle's extension */ }; #pragma pack(push, 1) From dcf2c8f80fae80ba87c3d2908f1052f4ae432281 Mon Sep 17 00:00:00 2001 From: Andrey Tolstoy Date: Tue, 18 Jun 2024 22:53:29 +0700 Subject: [PATCH 32/35] [tracker] enable -fipa-pta (interprocedural pointer analysis and interprocedural modification and reference analysis) --- build/arm-tools.mk | 5 +++++ hal/src/nRF52840/ble_hal.cpp | 2 +- modules/tracker/system-part1/makefile | 3 +++ third_party/nrf5_sdk/nrf5_sdk | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/build/arm-tools.mk b/build/arm-tools.mk index ce92c3baeb..2f33ea2414 100644 --- a/build/arm-tools.mk +++ b/build/arm-tools.mk @@ -112,6 +112,11 @@ endif # We are using newlib-nano for all the platforms CFLAGS += --specs=nano.specs +ifneq ($(CFLAGS_USE_IPA_PTA),) +CFLAGS += -fipa-pta +LDFLAGS += -fipa-pta +endif + # Check if the compiler version is the minimum required version_to_number=$(shell v=$1; v=($${v//./ }); echo $$((v[0] * 10000 + v[1] * 100 + v[2]))) get_major_version=$(shell v=$1; v=($${v//./ }); echo $${v[0]}) diff --git a/hal/src/nRF52840/ble_hal.cpp b/hal/src/nRF52840/ble_hal.cpp index fba5de234a..069b224962 100644 --- a/hal/src/nRF52840/ble_hal.cpp +++ b/hal/src/nRF52840/ble_hal.cpp @@ -869,7 +869,7 @@ int BleObject::BleGap::setDeviceAddress(const hal_ble_addr_t* address) const { int BleObject::BleGap::getDeviceAddress(hal_ble_addr_t* address) const { CHECK_TRUE(address, SYSTEM_ERROR_INVALID_ARGUMENT); - ble_gap_addr_t localAddr; + ble_gap_addr_t localAddr = {}; int ret = sd_ble_gap_addr_get(&localAddr); CHECK_NRF_RETURN(ret, nrf_system_error(ret)); *address = toHalAddress(localAddr); diff --git a/modules/tracker/system-part1/makefile b/modules/tracker/system-part1/makefile index 0e90eabb88..d02cca21e7 100644 --- a/modules/tracker/system-part1/makefile +++ b/modules/tracker/system-part1/makefile @@ -5,6 +5,9 @@ BUILD_PATH_EXT = $(BUILD_TARGET_PLATFORM) HAL_LINK := PLATFORM_DFU = 0x30000 +# Add -fipa-pta to CFLAGS/LDFLAGS (interprocedural pointer analysis) +export CFLAGS_USE_IPA_PTA=1 + DEPENDENCIES = newlib_nano modules/tracker/user-part modules/tracker/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs wiring_globals LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs wiring_globals # newlib_nano is special in that it's linked automatically by the system, so no need to add it to the library path here diff --git a/third_party/nrf5_sdk/nrf5_sdk b/third_party/nrf5_sdk/nrf5_sdk index 87ec701f42..c3dbc4fa6b 160000 --- a/third_party/nrf5_sdk/nrf5_sdk +++ b/third_party/nrf5_sdk/nrf5_sdk @@ -1 +1 @@ -Subproject commit 87ec701f42da25a3dc7148aca6729f743c14d22d +Subproject commit c3dbc4fa6b142a98062704e3ef68df5499200ae5 From 700bfc9a5c48b79075e66bd5a02b3968574f4022 Mon Sep 17 00:00:00 2001 From: Andrey Tolstoy Date: Wed, 19 Jun 2024 23:59:20 +0700 Subject: [PATCH 33/35] [build] extra -fdevirtualize-at-ltrans optimization for tracker --- build/arm-tools.mk | 6 +++--- modules/tracker/system-part1/makefile | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/arm-tools.mk b/build/arm-tools.mk index 2f33ea2414..8c778d41c8 100644 --- a/build/arm-tools.mk +++ b/build/arm-tools.mk @@ -112,9 +112,9 @@ endif # We are using newlib-nano for all the platforms CFLAGS += --specs=nano.specs -ifneq ($(CFLAGS_USE_IPA_PTA),) -CFLAGS += -fipa-pta -LDFLAGS += -fipa-pta +ifneq ($(LTO_EXTRA_OPTIMIZATIONS),) +CFLAGS += -fipa-pta -fdevirtualize-at-ltrans +LDFLAGS += -fipa-pta -fdevirtualize-at-ltrans endif # Check if the compiler version is the minimum required diff --git a/modules/tracker/system-part1/makefile b/modules/tracker/system-part1/makefile index d02cca21e7..0eac8cef87 100644 --- a/modules/tracker/system-part1/makefile +++ b/modules/tracker/system-part1/makefile @@ -5,8 +5,8 @@ BUILD_PATH_EXT = $(BUILD_TARGET_PLATFORM) HAL_LINK := PLATFORM_DFU = 0x30000 -# Add -fipa-pta to CFLAGS/LDFLAGS (interprocedural pointer analysis) -export CFLAGS_USE_IPA_PTA=1 +# Add -fipa-pta and -fdevirtualize-at-ltrans to CFLAGS/LDFLAGS (interprocedural pointer analysis) + more aggressive virtual call optimizations +export LTO_EXTRA_OPTIMIZATIONS=1 DEPENDENCIES = newlib_nano modules/tracker/user-part modules/tracker/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs wiring_globals LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs wiring_globals From ad6f4d51f24dc611ab2225d6d93b3437f15513ae Mon Sep 17 00:00:00 2001 From: Andrey Tolstoy Date: Thu, 20 Jun 2024 00:16:54 +0700 Subject: [PATCH 34/35] [build] clean up LTO usage --- build/arm-tools.mk | 11 +++++++++++ modules/argon/system-part1/makefile | 4 +++- modules/b5som/system-part1/makefile | 4 +++- modules/boron/system-part1/makefile | 4 +++- modules/tracker/system-part1/makefile | 3 ++- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/build/arm-tools.mk b/build/arm-tools.mk index 8c778d41c8..b8ac2e1d3f 100644 --- a/build/arm-tools.mk +++ b/build/arm-tools.mk @@ -102,8 +102,19 @@ CPPFLAGS += $(LTO_FLAGS) -fno-use-cxa-atexit CONLYFLAGS += $(LTO_FLAGS) LDFLAGS += -fno-use-cxa-atexit +USE_LTO=0 + +ifneq ($(FORCE_LTO),) +USE_LTO=1 +endif + ifeq ($(COMPILE_LTO),y) +USE_LTO=1 +endif + +ifeq ($(USE_LTO),1) LDFLAGS += -flto -Os -fuse-linker-plugin +CFLAGS += -fuse-linker-plugin else # Be explicit and disable LTO LDFLAGS += -fno-lto diff --git a/modules/argon/system-part1/makefile b/modules/argon/system-part1/makefile index d928b67ce0..42d7755b3a 100644 --- a/modules/argon/system-part1/makefile +++ b/modules/argon/system-part1/makefile @@ -9,6 +9,8 @@ NCP_FIRMWARE_MODULE_VERSION=4 DEPENDENCIES = newlib_nano modules/argon/user-part modules/argon/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs +export FORCE_LTO=1 + # newlib_nano is special in that it's linked automatically by the system, so no need to add it to the library path here MAKE_DEPENDENCIES = newlib_nano $(LIB_DEPENDENCIES) include ../modular.mk @@ -29,7 +31,7 @@ include $(PROJECT_ROOT)/build/arm-tlm.mk # NOTE: When compiling with LTO vTaskSwitchContext is getting linked out, despite the fact that it's # marked as used. -LDFLAGS += -flto -Os -fuse-linker-plugin -Wl,--undefined=vTaskSwitchContext +LDFLAGS += -Wl,--undefined=vTaskSwitchContext $(call check_modular) diff --git a/modules/b5som/system-part1/makefile b/modules/b5som/system-part1/makefile index 0a6af8aa62..b102028215 100644 --- a/modules/b5som/system-part1/makefile +++ b/modules/b5som/system-part1/makefile @@ -5,6 +5,8 @@ BUILD_PATH_EXT = $(BUILD_TARGET_PLATFORM) HAL_LINK := PLATFORM_DFU = 0x30000 +export FORCE_LTO=1 + DEPENDENCIES = newlib_nano modules/b5som/user-part modules/b5som/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs wiring_globals LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs wiring_globals # newlib_nano is special in that it's linked automatically by the system, so no need to add it to the library path here @@ -22,7 +24,7 @@ include $(PROJECT_ROOT)/build/arm-tlm.mk # NOTE: When compiling with LTO vTaskSwitchContext is getting linked out, despite the fact that it's # marked as used. -LDFLAGS += -flto -Os -fuse-linker-plugin -Wl,--undefined=vTaskSwitchContext +LDFLAGS += -Wl,--undefined=vTaskSwitchContext $(call check_modular) diff --git a/modules/boron/system-part1/makefile b/modules/boron/system-part1/makefile index 51cfd534d5..052d761d00 100644 --- a/modules/boron/system-part1/makefile +++ b/modules/boron/system-part1/makefile @@ -5,6 +5,8 @@ BUILD_PATH_EXT = $(BUILD_TARGET_PLATFORM) HAL_LINK := PLATFORM_DFU = 0x30000 +export FORCE_LTO=1 + DEPENDENCIES = newlib_nano modules/boron/user-part modules/boron/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs wiring_globals LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs wiring_globals # newlib_nano is special in that it's linked automatically by the system, so no need to add it to the library path here @@ -22,7 +24,7 @@ include $(PROJECT_ROOT)/build/arm-tlm.mk # NOTE: When compiling with LTO vTaskSwitchContext is getting linked out, despite the fact that it's # marked as used. -LDFLAGS += -flto -Os -fuse-linker-plugin -Wl,--undefined=vTaskSwitchContext +LDFLAGS += -Wl,--undefined=vTaskSwitchContext $(call check_modular) diff --git a/modules/tracker/system-part1/makefile b/modules/tracker/system-part1/makefile index 0eac8cef87..170832acc7 100644 --- a/modules/tracker/system-part1/makefile +++ b/modules/tracker/system-part1/makefile @@ -7,6 +7,7 @@ PLATFORM_DFU = 0x30000 # Add -fipa-pta and -fdevirtualize-at-ltrans to CFLAGS/LDFLAGS (interprocedural pointer analysis) + more aggressive virtual call optimizations export LTO_EXTRA_OPTIMIZATIONS=1 +export FORCE_LTO=1 DEPENDENCIES = newlib_nano modules/tracker/user-part modules/tracker/system-part1 dynalib services hal platform system wiring communication rt-dynalib crypto proto_defs wiring_globals LIB_DEPENDENCIES = services system wiring communication hal platform crypto proto_defs wiring_globals @@ -25,7 +26,7 @@ include $(PROJECT_ROOT)/build/arm-tlm.mk # NOTE: When compiling with LTO vTaskSwitchContext is getting linked out, despite the fact that it's # marked as used. -LDFLAGS += -flto -Os -fuse-linker-plugin -Wl,--undefined=vTaskSwitchContext +LDFLAGS += -Wl,--undefined=vTaskSwitchContext $(call check_modular) From edefb7e9f581088ed0bda9f669809efbc5752731 Mon Sep 17 00:00:00 2001 From: Andrey Tolstoy Date: Thu, 20 Jun 2024 01:31:55 +0700 Subject: [PATCH 35/35] [build] more optimizations --- build/arm-tools.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/arm-tools.mk b/build/arm-tools.mk index b8ac2e1d3f..26d2ae1609 100644 --- a/build/arm-tools.mk +++ b/build/arm-tools.mk @@ -124,8 +124,8 @@ endif CFLAGS += --specs=nano.specs ifneq ($(LTO_EXTRA_OPTIMIZATIONS),) -CFLAGS += -fipa-pta -fdevirtualize-at-ltrans -LDFLAGS += -fipa-pta -fdevirtualize-at-ltrans +CFLAGS += -fipa-pta -fdevirtualize-at-ltrans -fdevirtualize-speculatively -flto-partition=balanced -fmerge-all-constants +LDFLAGS += -fipa-pta -fdevirtualize-at-ltrans -fdevirtualize-speculatively -flto-partition=balanced -fmerge-all-constants endif # Check if the compiler version is the minimum required