From 34c3ccf1b4a56b5d218487112efb2e741598df7c Mon Sep 17 00:00:00 2001 From: Aleksandr Khromykh Date: Mon, 7 Jul 2025 14:23:08 +0200 Subject: [PATCH] tests: bluetooth: mesh: extend provisioning test with gotten stuck key Commit extends existing persistent provisioning bsim mesh test that checks that mesh removes gotten stuck persisted key if key is reused. Correct key is imported normally after that. Signed-off-by: Aleksandr Khromykh --- .../bluetooth/mesh/src/test_persistence.c | 73 +++++++++++++++++++ .../persistence/prov_with_stuck_key.sh | 29 ++++++++ .../tests_scripts/persistence/provisioning.sh | 18 +++-- 3 files changed, 115 insertions(+), 5 deletions(-) create mode 100755 tests/bsim/bluetooth/mesh/tests_scripts/persistence/prov_with_stuck_key.sh diff --git a/tests/bsim/bluetooth/mesh/src/test_persistence.c b/tests/bsim/bluetooth/mesh/src/test_persistence.c index 4bf1f9faa93..568df63d919 100644 --- a/tests/bsim/bluetooth/mesh/src/test_persistence.c +++ b/tests/bsim/bluetooth/mesh/src/test_persistence.c @@ -12,6 +12,9 @@ #include "mesh/keys.h" #include +#include +#include + #define LOG_MODULE_NAME test_persistence #include @@ -247,6 +250,7 @@ static const struct stack_cfg { }, }; static const struct stack_cfg *current_stack_cfg; +static bool persist_stuck_key; static void test_args_parse(int argc, char *argv[]) { @@ -267,6 +271,13 @@ static void test_args_parse(int argc, char *argv[]) .name = "{0, 1}", .option = "stack-cfg", .descript = "" + }, + { + .dest = &persist_stuck_key, + .type = 'b', + .name = "{0, 1}", + .option = "persist-stuck-key", + .descript = "PSA ITS has a gotten stuck key" } }; @@ -458,10 +469,68 @@ static void provisioner_setup(void) provisioner_ready = true; } +static void fake_key_setup(void) +{ + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + psa_key_id_t key_id = ZEPHYR_PSA_BT_MESH_KEY_ID_RANGE_BEGIN; + psa_key_id_t key_id_imported; + const uint8_t in[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}; + uint8_t out[16] = {0}; + size_t out_len; + + psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT); + psa_set_key_id(&key_attributes, key_id); + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_EXPORT); + psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&key_attributes, 128); + + status = psa_import_key(&key_attributes, in, 16, &key_id_imported); + psa_reset_key_attributes(&key_attributes); + if (status != PSA_SUCCESS) { + FAIL("Failed to import fake key"); + } + + if (key_id_imported != key_id) { + FAIL("Imported key ID does not match expected key ID"); + } + + status = psa_export_key(key_id_imported, out, sizeof(out), &out_len); + if (status != PSA_SUCCESS) { + FAIL("Failed to export fake key"); + } + + if (memcmp(out, in, sizeof(in)) != 0 || out_len != sizeof(in)) { + FAIL("Exported key does not match imported key"); + } +} + +static void fake_key_destruction_check(void) +{ + psa_status_t status; + psa_key_id_t key_id = ZEPHYR_PSA_BT_MESH_KEY_ID_RANGE_BEGIN; + uint8_t out[16] = {0}; + size_t out_len; + + status = psa_export_key(key_id, out, sizeof(out), &out_len); + if (status != PSA_SUCCESS) { + FAIL("Failed to export former fake key ID"); + } + + if (memcmp(out, test_devkey, sizeof(out)) != 0 || out_len != sizeof(test_devkey)) { + FAIL("Exported fake key does not match test device key"); + } +} + static void test_provisioning_data_save(void) { bt_mesh_test_cfg_set(NULL, WAIT_TIME); + if (persist_stuck_key) { + fake_key_setup(); + } + if (device_setup_and_self_provision()) { FAIL("Mesh setup failed. Settings should not be loaded."); } @@ -476,6 +545,10 @@ static void test_provisioning_data_load(void) /* In this test stack should boot as provisioned */ bt_mesh_test_cfg_set(NULL, WAIT_TIME); + if (persist_stuck_key) { + fake_key_destruction_check(); + } + if (device_setup_and_self_provision() != -EALREADY) { FAIL("Device should boot up as already provisioned"); } diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/persistence/prov_with_stuck_key.sh b/tests/bsim/bluetooth/mesh/tests_scripts/persistence/prov_with_stuck_key.sh new file mode 100755 index 00000000000..90d65d5cf41 --- /dev/null +++ b/tests/bsim/bluetooth/mesh/tests_scripts/persistence/prov_with_stuck_key.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Copyright 2025 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh + +# Test checks that mesh provisioning data is saved and loaded correctly +# if a key with ID from mesh PSA key ID range exists in the PSA ITS, +# it is destroyed and the correct key is used instead. +# +# Test must be added in pair and in sequence. +# First test: saves data; second test: verifies it. +# +# Test procedure: +# 1. Fake key is created in the PSA ITS to emulate gotten stuck key. +# 2. Device Under Test (DUT) initializes the Mesh stack, +# and starts provisioning and configuration itself. +# 3. Test scenario emulates hardware reset by running the second test +# with stored data from the first test. +# 4. DUT checks that the stuck key was substituted by the real key. +# 5. DUT starts mesh with loading stored data and checks that if they were restored correctly. + +overlay=overlay_pst_conf +RunTestFlash mesh_pst_prov_data_check_stuck_key persistence_provisioning_data_save -flash_erase \ + -- -argstest persist-stuck-key=1 + +overlay=overlay_pst_conf +RunTestFlash mesh_pst_prov_data_check_stuck_key persistence_provisioning_data_load -flash_rm \ + -- -argstest persist-stuck-key=1 diff --git a/tests/bsim/bluetooth/mesh/tests_scripts/persistence/provisioning.sh b/tests/bsim/bluetooth/mesh/tests_scripts/persistence/provisioning.sh index d8edd471cac..34581b4c6e1 100755 --- a/tests/bsim/bluetooth/mesh/tests_scripts/persistence/provisioning.sh +++ b/tests/bsim/bluetooth/mesh/tests_scripts/persistence/provisioning.sh @@ -4,14 +4,22 @@ source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh -# Note: +# Test checks that mesh provisioning data is saved and loaded correctly. +# # Tests must be added in pairs and in sequence. # First test: saves data; second test: verifies it. +# +# Test procedure: +# 1. Device Under Test (DUT) initializes the Mesh stack, +# and starts provisioning and configuration itself. +# 2. Test scenario emulates hardware reset by running the second test +# with stored data from the first test. +# 3. DUT starts mesh with loading stored data and checks that if they were restored correctly. -# SKIP=(persistence_provisioning_data_save) overlay=overlay_pst_conf -RunTestFlash mesh_pst_prov_data_check persistence_provisioning_data_save -flash_erase +RunTestFlash mesh_pst_prov_data_check persistence_provisioning_data_save -flash_erase \ + -- -argstest persist-stuck-key=0 -# SKIP=(persistence_provisioning_data_load) overlay=overlay_pst_conf -RunTestFlash mesh_pst_prov_data_check persistence_provisioning_data_load -flash_rm +RunTestFlash mesh_pst_prov_data_check persistence_provisioning_data_load -flash_rm \ + -- -argstest persist-stuck-key=0