NuMaker Pelion Device Management example
Fork of mbed-os-example-pelion by
pre-main/provision.cpp@16:75a4830fc40a, 2021-02-25 (annotated)
- 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?
User | Revision | Line number | New 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 | } |