NuMaker Pelion Device Management example
Fork of mbed-os-example-pelion by
Revision 4:e564fd8be648, committed 2019-11-22
- Comitter:
- ccli8
- Date:
- Fri Nov 22 11:16:39 2019 +0800
- Parent:
- 3:bda8852d7723
- Child:
- 5:ae686808e015
- Commit message:
- Update to mbed-os 5.14.2 and related modifications
1. Provide custom entropy source on targets without real TRNG
The targets below don't have real TRNG and cannot annouce TRNG support. A custom entropy source with EADC seeded PRNG is given to remedy it:
- NUMAKER_PFM_NUC47
- NUMAKER_PFM_M487
- NUMAKER_IOT_M487
2. Override mbed_main() for simulating provision process
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TARGET_NUVOTON/platform_entropy.cpp Fri Nov 22 11:16:39 2019 +0800 @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2019 Nuvoton Technology Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !DEVICE_TRNG && !TARGET_PSA + +#include "mbed.h" +#include "mbedtls/config.h" + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + +/* Support entropy source with EADC seeded PRNG on non-PSA targets without TRNG + * + * Follow the steps below to replace TRNG with EADC seeded PRNG: + * + * 1. Seed PRNG with EADC band gap + * 2. Define MBEDTLS_ENTROPY_HARDWARE_ALT and provide custom mbedtls_hardware_poll(...) + * + * Reference configuration in mbed_app.json: + * + * For Pelion/mbedtls: + * + * "target.macros_add": [ + * "MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\"", + * "MBEDTLS_ENTROPY_HARDWARE_ALT" + * ], + * + * For non-Pelion/mbedtls: + * + * "target.macros_add": [ + * "MBEDTLS_ENTROPY_HARDWARE_ALT" + * ], + * + * For both Pelion/non-Pelion (skip when done in targets.json): + * + * "target.device_has_remove": ["TRNG"], + * + * WARNING: If the security level of EADC seeded PRNG cannot meet requirements, replace it with another entropy source. + */ + +#include "crypto-misc.h" + +extern "C" { + int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen); +} + +/* Support EADC band gap + * + * Mbed OS defines analog-in HAL for normal purposes, but EADC band gap is not defined. + * To avoid EADC code conflict and fit into existent analog-in HAL, we: + * + * 1. Hijack AnalogIn driver to involve analog-in HAL protection and EADC initialization. + * This needs one dedicated EADC pin EADC_AUX_PINNAME. + * 2. Run EADC band gap conversion, with EADC module already initialized via above. This needs + * one dedicated sample module and one dedicated channel. + */ + +#if TARGET_NUC472 + #define EADC_AUX_PINNAME A0 + #define EADC_BANDGAP_SMPLMOD 7 + #define EADC_BANDGAP_CHN 8 + #define PRNG_KEYSIZE_ID PRNG_KEY_SIZE_128 + #define PRNG_KEYSIZE 16 +#elif TARGET_M480 + #define EADC_AUX_PINNAME A0 + #define EADC_BANDGAP_SMPLMOD 16 + #define EADC_BANDGAP_CHN 16 + #define PRNG_KEYSIZE_ID PRNG_KEY_SIZE_128 + #define PRNG_KEYSIZE 16 +#else + #error("Target not support") +#endif + +class NuBandGap : public mbed::AnalogIn { +public: + NuBandGap(); + ~NuBandGap(); + + /* Generate bitstream based on EADC band gap + * + * @returns 1/0 bitstream + */ + uint16_t read_bitstream(); +}; + +class NuEADCSeedPRNG : private mbed::NonCopyable<NuEADCSeedPRNG> +{ +public: + NuEADCSeedPRNG(); + ~NuEADCSeedPRNG(); + + /* Get random data + * + * @param output The pointer to an output array + * @param len The size of output data, to avoid buffer overwrite + * @param olen The length of generated data + */ + int get_bytes(unsigned char *output, size_t len, size_t *olen); + +private: + NuBandGap band_gap; +}; + +int mbedtls_hardware_poll(MBED_UNUSED void *data, unsigned char *output, size_t len, size_t *olen) +{ + static NuEADCSeedPRNG eadc_seed_prng; + + return eadc_seed_prng.get_bytes(output, len, olen); +} + +NuBandGap::NuBandGap() : mbed::AnalogIn(EADC_AUX_PINNAME) +{ + EADC_T *eadc_base = (EADC_T *) EADC_BASE; + + EADC_ConfigSampleModule(eadc_base, EADC_BANDGAP_SMPLMOD, EADC_SOFTWARE_TRIGGER, EADC_BANDGAP_CHN); +} + +NuBandGap::~NuBandGap() +{ +} + +uint16_t NuBandGap::read_bitstream() +{ + uint16_t one_or_zero; + + lock(); + + EADC_T *eadc_base = (EADC_T *) EADC_BASE; + + EADC_START_CONV(eadc_base, 1 << EADC_BANDGAP_SMPLMOD); + while (EADC_GET_DATA_VALID_FLAG(eadc_base, 1 << EADC_BANDGAP_SMPLMOD) != (1 << EADC_BANDGAP_SMPLMOD)); + uint16_t conv_res_12 = EADC_GET_CONV_DATA(eadc_base, EADC_BANDGAP_SMPLMOD); + + /* 1 as number of 'one' is odd; 0 otherwise */ + unsigned i; + uint16_t count_one = 0; + for (i = 0; i < 12; i ++) { + if (conv_res_12 & 1) { + count_one ++; + } + conv_res_12 >>= 1; + } + one_or_zero = count_one & 1; + + unlock(); + + return one_or_zero; +} + +NuEADCSeedPRNG::NuEADCSeedPRNG() +{ + crypto_init(); + PRNG_ENABLE_INT(); + + uint32_t seed = 0; + unsigned i = 32; + + /* Get seed from EADC band gap */ + while (i --) { + seed <<= 1; + seed |= band_gap.read_bitstream(); + } + + /* PRNG reload seed */ + PRNG_Open(PRNG_KEYSIZE_ID, 1, seed); +} + +NuEADCSeedPRNG::~NuEADCSeedPRNG() +{ + PRNG_DISABLE_INT(); + crypto_uninit(); +} + +int NuEADCSeedPRNG::get_bytes(unsigned char *output, size_t len, size_t *olen) +{ + /* Check argument validity */ + if (!output && len) { + return -1; + } + + unsigned char *output_ind = output; + size_t rmn = len; + uint32_t rand_data[PRNG_KEYSIZE / sizeof(uint32_t)]; + while (rmn) { + crypto_prng_prestart(); + PRNG_Start(); + crypto_prng_wait(); + + PRNG_Read(rand_data); + + size_t n = (rmn >= PRNG_KEYSIZE) ? PRNG_KEYSIZE : rmn; + memcpy(output_ind, rand_data, n); + + output_ind += n; + rmn -= n; + } + + if (olen) { + *olen = len; + } + + return 0; +} + +#else + +/* Support entropy source with mbedtls NV seed on non-PSA targets without TRNG + * + * Follow the steps below to replace TRNG with mbedtls NV seed: + * + * 1. Define MBEDTLS_ENTROPY_NV_SEED + * 2. Define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO/MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and provide custom mbedtls_nv_seed_read(...)/mbedtls_nv_seed_write(...). + * 3. Don't define MBEDTLS_PSA_INJECT_ENTROPY. Meet mbedtls_psa_inject_entropy(...) undefined and then provide custom one, which must be compatible with mbedtls_nv_seed_read(...)/mbedtls_nv_seed_write(...) above. + * 4. For development, simulating partial provision process, inject entropy seed via mbedtls_psa_inject_entropy(...) pre-main. + * + * Reference configuration in mbed_app.json: + * + * For Pelion/mbedtls, don't define MBEDTLS_ENTROPY_NV_SEED because it has defined in: + * https://github.com/ARMmbed/mbed-cloud-client/blob/master/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_mbedOS_SW_TRNG.h + * + * "target.macros_add": [ + * "MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS_SW_TRNG.h\"", + * "PAL_USE_HW_TRNG=0", + * "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO=mbedtls_platform_seed_read", + * "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO=mbedtls_platform_seed_write" + * ], + * + * For non-Pelion/mbedtls: + * + * "target.macros_add": [ + * "MBEDTLS_ENTROPY_NV_SEED", + * "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO=mbedtls_platform_seed_read", + * "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO=mbedtls_platform_seed_write" + * ], + * + * For both Pelion/non-Pelion (skip when done in targets.json): + * + * "target.device_has_remove": ["TRNG"], + * + * WARNING: The injection of mbedtls NV seed pre-main is only for development. Run provision process for mass production. + */ + +#include "entropy_poll.h" +#include "psa/crypto.h" +#include "KVStore.h" +#include "TDBStore.h" +#include "KVMap.h" +#include "kv_config.h" + +extern "C" { + psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size); + int mbedtls_platform_seed_read(unsigned char *buf, size_t buf_len); + int mbedtls_platform_seed_write(unsigned char *buf, size_t buf_len); +} + +/* Requirement of seed size + * + * 1. >= MBEDTLS_ENTROPY_MIN_PLATFORM + * 2. >= MBEDTLS_ENTROPY_BLOCK_SIZE + * 3. <= MBEDTLS_ENTROPY_MAX_SEED_SIZE + */ +#define SEED_SIZE 64 +MBED_STATIC_ASSERT(SEED_SIZE >= MBEDTLS_ENTROPY_MIN_PLATFORM, "Seed size must be larger than or equal to MBEDTLS_ENTROPY_MIN_PLATFORM"); +MBED_STATIC_ASSERT(SEED_SIZE >= MBEDTLS_ENTROPY_BLOCK_SIZE, "Seed size must be larger than or equal to MBEDTLS_ENTROPY_BLOCK_SIZE"); +MBED_STATIC_ASSERT(SEED_SIZE <= MBEDTLS_ENTROPY_MAX_SEED_SIZE, "Seed size must be smaller than or equal to MBEDTLS_ENTROPY_MAX_SEED_SIZE"); + +/* Seed key name in kvstore */ +#define KV_KEY_SEED "seed" + +/* Inject an initial entropy seed for the random generator into secure storage + * + * See reference below for its prototype: + * https://github.com/ARMmbed/mbed-os/blob/master/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h + */ +psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size) +{ + /* Check seed size requirement */ + if ((( seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) || (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) || + (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Get kvstore internal storage where seed is injected */ + KVMap &kv_map = KVMap::get_instance(); + KVStore *inner_store = kv_map.get_internal_kv_instance(NULL); + if (inner_store == NULL) { + return PSA_ERROR_STORAGE_FAILURE; + } + + /* Check if seed has injected */ + KVStore::info_t kv_info; + int kv_status = inner_store->get_info(KV_KEY_SEED, &kv_info); + if (kv_status == MBED_SUCCESS) { + return PSA_ERROR_NOT_PERMITTED; + } else if (kv_status == MBED_ERROR_ITEM_NOT_FOUND) { + /* No seed injected, inject it below */ + } else { + return PSA_ERROR_STORAGE_FAILURE; + } + + /* Inject seed into kvstore internal storage */ + kv_status = inner_store->set(KV_KEY_SEED, seed, seed_size, 0); + if (kv_status == MBED_SUCCESS) { + return PSA_SUCCESS; + } else { + return PSA_ERROR_STORAGE_FAILURE; + } +} + +int mbedtls_platform_seed_read(unsigned char *buf, size_t buf_len) +{ + /* Get kvstore internal storage where seed is injected */ + KVMap &kv_map = KVMap::get_instance(); + KVStore *inner_store = kv_map.get_internal_kv_instance(NULL); + if (inner_store == NULL) { + return -1; + } + + /* Read seed from kvstore internal storage */ + size_t actual_size = 0; + int kv_status = inner_store->get(KV_KEY_SEED, buf, buf_len, &actual_size, 0); + if (kv_status != MBED_SUCCESS || actual_size != buf_len) { + return -1; + } else { + return buf_len; + } +} + +int mbedtls_platform_seed_write(unsigned char *buf, size_t buf_len) +{ + /* Get kvstore internal storage where seed is injected */ + KVMap &kv_map = KVMap::get_instance(); + KVStore *inner_store = kv_map.get_internal_kv_instance(NULL); + if (inner_store == NULL) { + return -1; + } + + /* Write seed into kvstore internal storage */ + int kv_status = inner_store->set(KV_KEY_SEED, buf, buf_len, 0); + if (kv_status != MBED_SUCCESS) { + return -1; + } else { + return buf_len; + } +} + +#endif /* #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) */ + +#endif /* !DEVICE_TRNG && !TARGET_PSA */
--- a/mbed-os.lib Fri Nov 22 11:08:23 2019 +0800 +++ b/mbed-os.lib Fri Nov 22 11:16:39 2019 +0800 @@ -1,1 +1,1 @@ -https://github.com/ARMmbed/mbed-os/#b6e5a0a8afa34dec9dae8963778aebce0c82a54b +https://github.com/ARMmbed/mbed-os/#cf4f12a123c05fcae83fc56d76442015cb8a39e9
--- a/mbed_app.json Fri Nov 22 11:08:23 2019 +0800 +++ b/mbed_app.json Fri Nov 22 11:16:39 2019 +0800 @@ -44,7 +44,7 @@ "storage_filesystem.rbp_internal_size" : "(2*4*1024)", "storage_filesystem.external_base_address" : "(0x0)", "storage_filesystem.external_size" : "(1024*1024*64)", - "target.macros_add" : ["MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\""] + "target.macros_add" : ["MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\"", "MBEDTLS_ENTROPY_HARDWARE_ALT"] }, "NUMAKER_PFM_M487": { "target.network-default-interface-type" : "ETHERNET", @@ -68,7 +68,7 @@ "storage_filesystem.rbp_internal_size" : "(2*4*1024)", "storage_filesystem.external_base_address" : "(0x0)", "storage_filesystem.external_size" : "(1024*1024*64)", - "target.macros_add" : ["MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\""] + "target.macros_add" : ["MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\"", "MBEDTLS_ENTROPY_HARDWARE_ALT"] }, "NUMAKER_IOT_M487": { "target.network-default-interface-type" : "WIFI", @@ -98,7 +98,7 @@ "esp8266.cts" : "A3", "esp8266.rst" : "PH_3", "esp8266.provide-default" : true, - "target.macros_add" : ["MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\"", "ESP8266_SEND_TIMEOUT=8000"] + "target.macros_add" : ["MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\"", "ESP8266_SEND_TIMEOUT=8000", "MBEDTLS_ENTROPY_HARDWARE_ALT"] }, "NUMAKER_IOT_M263A": { "target.network-default-interface-type" : "WIFI",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre-main/mbed_main.cpp Fri Nov 22 11:16:39 2019 +0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 Nuvoton Technology Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" + +/* Run pre-main tasks via mbed_main() + * + * In Mbed OS boot sequence, mbed_main(), designed for user application override, is run + * before main(). We use it to run the following tasks: + * + * 1. Simulate provision process for development + * 2. Set up event queue for dispatching host command + * + * WARNING: For mass production, remove this file. + */ + +/* Check weak reference/definition at the link: + * http://www.keil.com/support/man/docs/ARMLINK/armlink_pge1362065917715.htm */ + +extern "C" { + MBED_USED void mbed_main(void); + MBED_WEAK void provision(void); + MBED_WEAK void pump_host_command(void); +} + +void mbed_main(void) +{ + provision(); + /* Spare memory if event queue is unnecessary */ + if (pump_host_command) { + mbed_event_queue()->call_every(2000, pump_host_command); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre-main/provision.cpp Fri Nov 22 11:16:39 2019 +0800 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2019 Nuvoton Technology Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "mbedtls/config.h" +#include "entropy_poll.h" +#include "psa/crypto.h" +#include "kvstore_global_api.h" +#include "KVStore.h" +#include "TDBStore.h" +#include "KVMap.h" +#include "kv_config.h" + +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include <inttypes.h> + +/* Simulate provision process for development + * + * 1. Reset kvstore + * 2. Inject entropy seed (if no entropy source) + * 3. Initialize user filesystem (if enabled) + * 4. Mark the device as provisioned + * + * WARNING: For mass production, remove this file and run real provision process. + */ + +/* Check weak reference/definition at the link: + * http://www.keil.com/support/man/docs/ARMLINK/armlink_pge1362065917715.htm */ + +extern "C" { + MBED_USED void provision(void); +} + +/* Stringize */ +#define STR_EXPAND(tok) #tok +#define STR(tok) STR_EXPAND(tok) + +#define _GET_FILESYSTEM_concat(dev, ...) _get_filesystem_##dev(__VA_ARGS__) +#define GET_FILESYSTEM(dev, ...) _GET_FILESYSTEM_concat(dev, __VA_ARGS__) + +/* Key for the device provisioned */ +#define KV_KEY_PROVISION "provision" + +void provision(void) +{ + int kv_reset(const char *kvstore_path); + + /* Initialize kvstore */ + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Initialize kvstore failed", kv_status); + } + + /* Get kvstore internal storage */ + KVMap &kv_map = KVMap::get_instance(); + KVStore *inner_store = kv_map.get_internal_kv_instance(NULL); + if (inner_store == NULL) { + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "kvstore internal storage failed"); + } + + /* Check if the device has provisioned */ + KVStore::info_t kv_info; + kv_status = inner_store->get_info(KV_KEY_PROVISION, &kv_info); + if (kv_status == MBED_SUCCESS) { + do { + /* Get KV_KEY_PROVISION key */ + char buffer[4]; + size_t actual_size = 0; + int kv_status = inner_store->get(KV_KEY_PROVISION, buffer, sizeof(buffer), &actual_size); + if (kv_status != MBED_SUCCESS) { + printf("Get \'%s\' failed: %d\r\n", KV_KEY_PROVISION, kv_status); + break; + } + /* Check KV_KEY_PROVISION key's value */ + if (actual_size != 1 || buffer[0] != '1') { + printf("\"%s\" not equal \"%s\"\r\n", KV_KEY_PROVISION, "1"); + break; + } + + printf("The device has provisioned. Skip provision process\r\n"); + return; + } while (0); + } else if (kv_status == MBED_ERROR_ITEM_NOT_FOUND) { + /* Not provisioned yet */ + printf("The device has not provisioned yet. Try to provision it...\r\n"); + } else { + printf("Get \'%s\' key failed: %d\r\n", KV_KEY_PROVISION, kv_status); + } + + /* Provision from here */ + printf("Provision for development...\r\n"); + + printf("Reset kvstore...\r\n"); + + /* Reset kvstore for clean kvstore */ + kv_status = kv_reset("/" STR(MBED_CONF_STORAGE_DEFAULT_KV) "/"); + if (kv_status != MBED_SUCCESS) { + MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "kv_reset() failed", kv_status); + } + + printf("\rReset kvstore...OK\r\n"); + +#if !DEVICE_TRNG && !TARGET_PSA +#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + /* Inject trivial seed for development */ + + printf("Inject NV seed...\r\n"); + + psa_status_t psa_status; + uint8_t seed[SEED_SIZE] = { 0 }; + + /* First inject seed, expect OK or seed has injected by some provision process */ + psa_status = mbedtls_psa_inject_entropy(seed, sizeof(seed)); + if (psa_status != PSA_SUCCESS && psa_status != PSA_ERROR_NOT_PERMITTED) { + MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Inject entropy failed", psa_status); + } + + /* Second inject seed, expect seed has injected above or by some provision process */ + psa_status = mbedtls_psa_inject_entropy(seed, sizeof(seed)); + if (psa_status != PSA_ERROR_NOT_PERMITTED) { + MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Re-jnject entropy expects PSA_ERROR_NOT_PERMITTED", psa_status); + } + + printf("\rInject NV seed...OK\r\n"); +#endif /* !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) */ +#endif /* #if !DEVICE_TRNG && !TARGET_PSA */ + + /* Mark the device as provisioned */ + kv_status = inner_store->set(KV_KEY_PROVISION, "1", 1, KVStore::WRITE_ONCE_FLAG); + if (kv_status != MBED_SUCCESS) { + MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Mark the device as provisioned failed", kv_status); + } + + printf("Provision for development...OK\r\n"); +}