From 2e13c372f1419f08dab7797b244681f889dd9bcf Mon Sep 17 00:00:00 2001 From: Michal Hanus Date: Mon, 14 Apr 2025 22:04:32 +0200 Subject: nrfdemo --- .../tfm/api_ns/platform/common/nrf_provisioning.c | 145 +++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 nrfdemo/build/tfm/api_ns/platform/common/nrf_provisioning.c (limited to 'nrfdemo/build/tfm/api_ns/platform/common/nrf_provisioning.c') diff --git a/nrfdemo/build/tfm/api_ns/platform/common/nrf_provisioning.c b/nrfdemo/build/tfm/api_ns/platform/common/nrf_provisioning.c new file mode 100644 index 0000000..4ce7792 --- /dev/null +++ b/nrfdemo/build/tfm/api_ns/platform/common/nrf_provisioning.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "tfm_plat_provisioning.h" +#include "tfm_plat_otp.h" +#include "tfm_platform_system.h" +#include "tfm_attest_hal.h" +#include "hw_unique_key.h" +#include "nrfx_nvmc.h" +#include +#include +#include +#include "nrf_provisioning.h" +#include +#include + +static enum tfm_plat_err_t disable_debugging(void) +{ + /* Configure the UICR such that upon the next reset, APPROTECT will be enabled */ + bool approt_writable; + + approt_writable = nrfx_nvmc_word_writable_check((uint32_t)&NRF_UICR_S->APPROTECT, + UICR_APPROTECT_PALL_Protected); + approt_writable &= nrfx_nvmc_word_writable_check((uint32_t)&NRF_UICR_S->SECUREAPPROTECT, + UICR_SECUREAPPROTECT_PALL_Protected); + + if (approt_writable) { + nrfx_nvmc_word_write((uint32_t)&NRF_UICR_S->APPROTECT, + UICR_APPROTECT_PALL_Protected); + nrfx_nvmc_word_write((uint32_t)&NRF_UICR_S->SECUREAPPROTECT, + UICR_SECUREAPPROTECT_PALL_Protected); + } else { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + return TFM_PLAT_ERR_SUCCESS; +} + +int tfm_plat_provisioning_is_required(void) +{ + enum tfm_security_lifecycle_t lcs; + + lcs = tfm_attest_hal_get_security_lifecycle(); + + return lcs == TFM_SLC_PSA_ROT_PROVISIONING; +} + +enum tfm_plat_err_t tfm_plat_provisioning_perform(void) +{ + enum tfm_security_lifecycle_t lcs; + + lcs = tfm_attest_hal_get_security_lifecycle(); + + /* + * Provisioning in NRF defines has two steps, the first step is to execute + * the provisioning_image sample. When this sample is executed it will + * always set the lifecycle state to PROVISIONING. This is a requirement for + * the TF-M provisioning to be completed so we don't accept any other + * lifecycle state here. + */ + + /* The Hardware Unique Keys should be already written */ + if (!hw_unique_key_are_any_written()) { + SPMLOG_ERRMSG("This device has not been provisioned with Hardware Unique Keys."); + return TFM_PLAT_ERR_SYSTEM_ERR; + } + +#ifdef TFM_PARTITION_INITIAL_ATTESTATION + /* The Initial Attestation key should be already written */ + if (!identity_key_is_written()) { + SPMLOG_ERRMSG( + "This device has not been provisioned with an Initial Attestation Key."); + return TFM_PLAT_ERR_SYSTEM_ERR; + } +#endif + + /* + * We don't need to make sure that the validation key is written here since we assume + * that secure boot is already enabled at this stage + */ + + /* Disable debugging in UICR */ + if (disable_debugging() != TFM_PLAT_ERR_SUCCESS) { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + /* Transition to the SECURED lifecycle state */ + if (tfm_attest_update_security_lifecycle_otp(TFM_SLC_SECURED) != 0) { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + lcs = tfm_attest_hal_get_security_lifecycle(); + if (lcs != TFM_SLC_SECURED) { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + + /* Perform a mandatory reset since we switch to an attestable LCS state */ + tfm_platform_hal_system_reset(); + + /* + * We should never return from this function, a reset should be triggered + * before we reach this point. Returning an error to signal that something + * is wrong if we reached here. + */ + return TFM_PLAT_ERR_SYSTEM_ERR; +} + +static bool dummy_key_is_present(void) +{ +#ifdef TFM_PARTITION_INITIAL_ATTESTATION + uint8_t key[IDENTITY_KEY_SIZE_BYTES]; + int err; + + err = identity_key_read(key); + if (err < 0) { + /* Unable to read out the key. Then it is likely not present. */ + return false; + } + + /* The first 8 bytes of the dummy key */ + uint8_t first_8_bytes[8] = {0xA9, 0xB4, 0x54, 0xB2, 0x6D, 0x6F, 0x90, 0xA4}; + + /* Check if any bytes differ */ + for (int i = 0; i < 8; i++) { + if (key[i] != first_8_bytes[i]) { + return false; + } + } + + /* The first 8 bytes matched the dummy key, so it is most likely the dummy key */ + return true; +#else + return false; +#endif +} + +void tfm_plat_provisioning_check_for_dummy_keys(void) +{ + if (dummy_key_is_present()) { + SPMLOG_ERRMSG("This device was provisioned with dummy keys and is NOT secure."); + } +} -- cgit v1.2.3