NuMaker Pelion Device Management example

Fork of mbed-os-example-pelion by cc li

Committer:
SHLIU1@OANBE02333.nuvoton.com
Date:
Thu Feb 25 11:51:01 2021 +0800
Revision:
16:75a4830fc40a
Parent:
14:0e7b5aeba173
Support the both V5.X and V6.X for mbed-os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ccli8 4:e564fd8be648 1 /*
ccli8 4:e564fd8be648 2 * Copyright (c) 2019 Nuvoton Technology Corporation
ccli8 4:e564fd8be648 3 *
ccli8 4:e564fd8be648 4 * SPDX-License-Identifier: Apache-2.0
ccli8 4:e564fd8be648 5 *
ccli8 4:e564fd8be648 6 * Licensed under the Apache License, Version 2.0 (the "License");
ccli8 4:e564fd8be648 7 * you may not use this file except in compliance with the License.
ccli8 4:e564fd8be648 8 * You may obtain a copy of the License at
ccli8 4:e564fd8be648 9 *
ccli8 4:e564fd8be648 10 * http://www.apache.org/licenses/LICENSE-2.0
ccli8 4:e564fd8be648 11 *
ccli8 4:e564fd8be648 12 * Unless required by applicable law or agreed to in writing, software
ccli8 4:e564fd8be648 13 * distributed under the License is distributed on an "AS IS" BASIS,
ccli8 4:e564fd8be648 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ccli8 4:e564fd8be648 15 * See the License for the specific language governing permissions and
ccli8 4:e564fd8be648 16 * limitations under the License.
ccli8 4:e564fd8be648 17 */
ccli8 4:e564fd8be648 18
ccli8 4:e564fd8be648 19 #include "mbed.h"
ccli8 4:e564fd8be648 20 #include "mbedtls/config.h"
ccli8 4:e564fd8be648 21 #include "entropy_poll.h"
ccli8 4:e564fd8be648 22 #include "kvstore_global_api.h"
ccli8 4:e564fd8be648 23 #include "KVStore.h"
ccli8 4:e564fd8be648 24 #include "TDBStore.h"
ccli8 4:e564fd8be648 25 #include "KVMap.h"
ccli8 4:e564fd8be648 26 #include "kv_config.h"
ccli8 14:0e7b5aeba173 27 #if MBED_MAJOR_VERSION >= 6
ccli8 14:0e7b5aeba173 28 #include "DeviceKey.h"
ccli8 14:0e7b5aeba173 29 #endif
ccli8 4:e564fd8be648 30
ccli8 4:e564fd8be648 31 #ifndef __STDC_FORMAT_MACROS
ccli8 4:e564fd8be648 32 #define __STDC_FORMAT_MACROS
ccli8 4:e564fd8be648 33 #endif
ccli8 4:e564fd8be648 34 #include <inttypes.h>
ccli8 4:e564fd8be648 35
ccli8 4:e564fd8be648 36 /* Simulate provision process for development
ccli8 4:e564fd8be648 37 *
ccli8 4:e564fd8be648 38 * 1. Reset kvstore
ccli8 4:e564fd8be648 39 * 2. Inject entropy seed (if no entropy source)
ccli8 4:e564fd8be648 40 * 3. Initialize user filesystem (if enabled)
ccli8 4:e564fd8be648 41 * 4. Mark the device as provisioned
ccli8 4:e564fd8be648 42 *
ccli8 4:e564fd8be648 43 * WARNING: For mass production, remove this file and run real provision process.
ccli8 4:e564fd8be648 44 */
ccli8 4:e564fd8be648 45
ccli8 4:e564fd8be648 46 /* Check weak reference/definition at the link:
ccli8 4:e564fd8be648 47 * http://www.keil.com/support/man/docs/ARMLINK/armlink_pge1362065917715.htm */
ccli8 4:e564fd8be648 48
ccli8 4:e564fd8be648 49 extern "C" {
ccli8 4:e564fd8be648 50 MBED_USED void provision(void);
ccli8 4:e564fd8be648 51 }
ccli8 4:e564fd8be648 52
ccli8 4:e564fd8be648 53 /* Stringize */
ccli8 4:e564fd8be648 54 #define STR_EXPAND(tok) #tok
ccli8 4:e564fd8be648 55 #define STR(tok) STR_EXPAND(tok)
ccli8 4:e564fd8be648 56
ccli8 4:e564fd8be648 57 #define _GET_FILESYSTEM_concat(dev, ...) _get_filesystem_##dev(__VA_ARGS__)
ccli8 4:e564fd8be648 58 #define GET_FILESYSTEM(dev, ...) _GET_FILESYSTEM_concat(dev, __VA_ARGS__)
ccli8 4:e564fd8be648 59
ccli8 4:e564fd8be648 60 /* Key for the device provisioned */
ccli8 4:e564fd8be648 61 #define KV_KEY_PROVISION "provision"
ccli8 4:e564fd8be648 62
ccli8 4:e564fd8be648 63 void provision(void)
ccli8 4:e564fd8be648 64 {
ccli8 4:e564fd8be648 65 int kv_reset(const char *kvstore_path);
ccli8 4:e564fd8be648 66
ccli8 4:e564fd8be648 67 /* Initialize kvstore */
ccli8 4:e564fd8be648 68 int kv_status = kv_init_storage_config();
ccli8 4:e564fd8be648 69 if (kv_status != MBED_SUCCESS) {
ccli8 4:e564fd8be648 70 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Initialize kvstore failed", kv_status);
ccli8 4:e564fd8be648 71 }
ccli8 4:e564fd8be648 72
ccli8 4:e564fd8be648 73 /* Get kvstore internal storage */
ccli8 4:e564fd8be648 74 KVMap &kv_map = KVMap::get_instance();
ccli8 4:e564fd8be648 75 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
ccli8 4:e564fd8be648 76 if (inner_store == NULL) {
ccli8 4:e564fd8be648 77 MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "kvstore internal storage failed");
ccli8 4:e564fd8be648 78 }
ccli8 4:e564fd8be648 79
ccli8 4:e564fd8be648 80 /* Check if the device has provisioned */
ccli8 4:e564fd8be648 81 KVStore::info_t kv_info;
ccli8 4:e564fd8be648 82 kv_status = inner_store->get_info(KV_KEY_PROVISION, &kv_info);
ccli8 4:e564fd8be648 83 if (kv_status == MBED_SUCCESS) {
ccli8 4:e564fd8be648 84 do {
ccli8 4:e564fd8be648 85 /* Get KV_KEY_PROVISION key */
ccli8 4:e564fd8be648 86 char buffer[4];
ccli8 4:e564fd8be648 87 size_t actual_size = 0;
ccli8 4:e564fd8be648 88 int kv_status = inner_store->get(KV_KEY_PROVISION, buffer, sizeof(buffer), &actual_size);
ccli8 4:e564fd8be648 89 if (kv_status != MBED_SUCCESS) {
ccli8 4:e564fd8be648 90 printf("Get \'%s\' failed: %d\r\n", KV_KEY_PROVISION, kv_status);
ccli8 4:e564fd8be648 91 break;
ccli8 4:e564fd8be648 92 }
ccli8 4:e564fd8be648 93 /* Check KV_KEY_PROVISION key's value */
ccli8 4:e564fd8be648 94 if (actual_size != 1 || buffer[0] != '1') {
ccli8 4:e564fd8be648 95 printf("\"%s\" not equal \"%s\"\r\n", KV_KEY_PROVISION, "1");
ccli8 4:e564fd8be648 96 break;
ccli8 4:e564fd8be648 97 }
ccli8 4:e564fd8be648 98
ccli8 4:e564fd8be648 99 printf("The device has provisioned. Skip provision process\r\n");
ccli8 4:e564fd8be648 100 return;
ccli8 4:e564fd8be648 101 } while (0);
ccli8 4:e564fd8be648 102 } else if (kv_status == MBED_ERROR_ITEM_NOT_FOUND) {
ccli8 4:e564fd8be648 103 /* Not provisioned yet */
ccli8 4:e564fd8be648 104 printf("The device has not provisioned yet. Try to provision it...\r\n");
ccli8 4:e564fd8be648 105 } else {
ccli8 4:e564fd8be648 106 printf("Get \'%s\' key failed: %d\r\n", KV_KEY_PROVISION, kv_status);
ccli8 4:e564fd8be648 107 }
ccli8 4:e564fd8be648 108
ccli8 4:e564fd8be648 109 /* Provision from here */
ccli8 4:e564fd8be648 110 printf("Provision for development...\r\n");
ccli8 4:e564fd8be648 111
ccli8 4:e564fd8be648 112 printf("Reset kvstore...\r\n");
ccli8 4:e564fd8be648 113
ccli8 4:e564fd8be648 114 /* Reset kvstore for clean kvstore */
ccli8 4:e564fd8be648 115 kv_status = kv_reset("/" STR(MBED_CONF_STORAGE_DEFAULT_KV) "/");
ccli8 4:e564fd8be648 116 if (kv_status != MBED_SUCCESS) {
ccli8 4:e564fd8be648 117 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "kv_reset() failed", kv_status);
ccli8 4:e564fd8be648 118 }
ccli8 4:e564fd8be648 119
ccli8 4:e564fd8be648 120 printf("\rReset kvstore...OK\r\n");
ccli8 4:e564fd8be648 121
ccli8 4:e564fd8be648 122 #if !DEVICE_TRNG && !TARGET_PSA
ccli8 4:e564fd8be648 123 #if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
ccli8 4:e564fd8be648 124 /* Inject trivial seed for development */
ccli8 4:e564fd8be648 125
ccli8 4:e564fd8be648 126 printf("Inject NV seed...\r\n");
ccli8 4:e564fd8be648 127
ccli8 4:e564fd8be648 128 psa_status_t psa_status;
ccli8 4:e564fd8be648 129 uint8_t seed[SEED_SIZE] = { 0 };
ccli8 4:e564fd8be648 130
ccli8 4:e564fd8be648 131 /* First inject seed, expect OK or seed has injected by some provision process */
ccli8 4:e564fd8be648 132 psa_status = mbedtls_psa_inject_entropy(seed, sizeof(seed));
ccli8 4:e564fd8be648 133 if (psa_status != PSA_SUCCESS && psa_status != PSA_ERROR_NOT_PERMITTED) {
ccli8 4:e564fd8be648 134 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Inject entropy failed", psa_status);
ccli8 4:e564fd8be648 135 }
ccli8 4:e564fd8be648 136
ccli8 4:e564fd8be648 137 /* Second inject seed, expect seed has injected above or by some provision process */
ccli8 4:e564fd8be648 138 psa_status = mbedtls_psa_inject_entropy(seed, sizeof(seed));
ccli8 4:e564fd8be648 139 if (psa_status != PSA_ERROR_NOT_PERMITTED) {
ccli8 4:e564fd8be648 140 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Re-jnject entropy expects PSA_ERROR_NOT_PERMITTED", psa_status);
ccli8 4:e564fd8be648 141 }
ccli8 4:e564fd8be648 142
ccli8 4:e564fd8be648 143 printf("\rInject NV seed...OK\r\n");
ccli8 4:e564fd8be648 144 #endif /* !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) */
ccli8 4:e564fd8be648 145 #endif /* #if !DEVICE_TRNG && !TARGET_PSA */
ccli8 4:e564fd8be648 146
ccli8 14:0e7b5aeba173 147 #if MBED_MAJOR_VERSION >= 6
ccli8 14:0e7b5aeba173 148 /* Since Mbedd OS 6.0, device key is not installed automatically and silently, possibly via generate_derived_key(...). Install it manually. */
ccli8 14:0e7b5aeba173 149 printf("Install device key...\r\n");
ccli8 14:0e7b5aeba173 150
ccli8 14:0e7b5aeba173 151 /* DeviceKey is a singleton */
ccli8 14:0e7b5aeba173 152 DeviceKey &devkey = DeviceKey::get_instance();
ccli8 14:0e7b5aeba173 153
ccli8 14:0e7b5aeba173 154 /* To be compatible with mbed-bootloader, install 16-byte version. */
ccli8 14:0e7b5aeba173 155 int device_key_status = devkey.generate_root_of_trust(DEVICE_KEY_16BYTE);
ccli8 14:0e7b5aeba173 156 switch (device_key_status) {
ccli8 14:0e7b5aeba173 157 case DEVICEKEY_SUCCESS:
ccli8 14:0e7b5aeba173 158 printf("\rInstall device key...OK\r\n");
ccli8 14:0e7b5aeba173 159 break;
ccli8 14:0e7b5aeba173 160
ccli8 14:0e7b5aeba173 161 case DEVICEKEY_ALREADY_EXIST:
ccli8 14:0e7b5aeba173 162 printf("\rInstall device key...Already existed\r\n");
ccli8 14:0e7b5aeba173 163 break;
ccli8 14:0e7b5aeba173 164
ccli8 14:0e7b5aeba173 165 case DEVICEKEY_GENERATE_RANDOM_ERROR:
ccli8 14:0e7b5aeba173 166 MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "No entropy sources and cannot generate device key");
ccli8 14:0e7b5aeba173 167 MBED_FALLTHROUGH;
ccli8 14:0e7b5aeba173 168
ccli8 14:0e7b5aeba173 169 default:
ccli8 14:0e7b5aeba173 170 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Install device key failed", device_key_status);
ccli8 14:0e7b5aeba173 171 }
ccli8 14:0e7b5aeba173 172 #endif
ccli8 14:0e7b5aeba173 173
ccli8 4:e564fd8be648 174 /* Mark the device as provisioned */
ccli8 4:e564fd8be648 175 kv_status = inner_store->set(KV_KEY_PROVISION, "1", 1, KVStore::WRITE_ONCE_FLAG);
ccli8 4:e564fd8be648 176 if (kv_status != MBED_SUCCESS) {
ccli8 4:e564fd8be648 177 MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Mark the device as provisioned failed", kv_status);
ccli8 4:e564fd8be648 178 }
ccli8 4:e564fd8be648 179
ccli8 4:e564fd8be648 180 printf("Provision for development...OK\r\n");
ccli8 4:e564fd8be648 181 }