NuMaker Pelion Device Management example

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers provision.cpp Source File

provision.cpp

00001 /* 
00002  * Copyright (c) 2019 Nuvoton Technology Corporation
00003  *
00004  * SPDX-License-Identifier: Apache-2.0
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *     http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 #include "mbed.h"
00020 #include "mbedtls/config.h"
00021 #include "entropy_poll.h"
00022 #include "kvstore_global_api.h"
00023 #include "KVStore.h"
00024 #include "TDBStore.h"
00025 #include "KVMap.h"
00026 #include "kv_config.h"
00027 #if MBED_MAJOR_VERSION >= 6
00028 #include "DeviceKey.h"
00029 #endif
00030 
00031 #ifndef __STDC_FORMAT_MACROS
00032 #define __STDC_FORMAT_MACROS
00033 #endif
00034 #include <inttypes.h>
00035 
00036 /* Simulate provision process for development
00037  *
00038  * 1. Reset kvstore
00039  * 2. Inject entropy seed (if no entropy source)
00040  * 3. Initialize user filesystem (if enabled)
00041  * 4. Mark the device as provisioned
00042  *
00043  * WARNING: For mass production, remove this file and run real provision process.
00044  */
00045 
00046 /* Check weak reference/definition at the link:
00047  * http://www.keil.com/support/man/docs/ARMLINK/armlink_pge1362065917715.htm */
00048 
00049 extern "C" {
00050     MBED_USED void provision(void);
00051 }
00052 
00053 /* Stringize */
00054 #define STR_EXPAND(tok) #tok
00055 #define STR(tok) STR_EXPAND(tok)
00056 
00057 #define _GET_FILESYSTEM_concat(dev, ...) _get_filesystem_##dev(__VA_ARGS__)
00058 #define GET_FILESYSTEM(dev, ...) _GET_FILESYSTEM_concat(dev, __VA_ARGS__)
00059 
00060 /* Key for the device provisioned */
00061 #define KV_KEY_PROVISION    "provision"
00062 
00063 void provision(void)
00064 {
00065     int kv_reset(const char *kvstore_path);
00066     
00067     /* Initialize kvstore */
00068     int kv_status = kv_init_storage_config();
00069     if (kv_status != MBED_SUCCESS) {
00070         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Initialize kvstore failed", kv_status);
00071     }
00072 
00073     /* Get kvstore internal storage */
00074     KVMap &kv_map = KVMap::get_instance();
00075     KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
00076     if (inner_store == NULL) {
00077         MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "kvstore internal storage failed");
00078     }
00079 
00080     /* Check if the device has provisioned */
00081     KVStore::info_t kv_info;
00082     kv_status = inner_store->get_info(KV_KEY_PROVISION, &kv_info);
00083     if (kv_status == MBED_SUCCESS) {
00084         do {
00085             /* Get KV_KEY_PROVISION key */
00086             char buffer[4];
00087             size_t actual_size = 0;
00088             int kv_status = inner_store->get(KV_KEY_PROVISION, buffer, sizeof(buffer), &actual_size);
00089             if (kv_status != MBED_SUCCESS) {
00090                 printf("Get \'%s\' failed: %d\r\n", KV_KEY_PROVISION, kv_status);
00091                 break;
00092             }
00093             /* Check KV_KEY_PROVISION key's value */
00094             if (actual_size != 1 || buffer[0] != '1') {
00095                 printf("\"%s\" not equal \"%s\"\r\n", KV_KEY_PROVISION, "1");
00096                 break;
00097             }
00098 
00099             printf("The device has provisioned. Skip provision process\r\n");
00100             return;
00101         } while (0);
00102     } else if (kv_status == MBED_ERROR_ITEM_NOT_FOUND) {
00103         /* Not provisioned yet */
00104         printf("The device has not provisioned yet. Try to provision it...\r\n");
00105     } else {
00106         printf("Get \'%s\' key failed: %d\r\n", KV_KEY_PROVISION, kv_status);
00107     }
00108 
00109     /* Provision from here */
00110     printf("Provision for development...\r\n");
00111     
00112     printf("Reset kvstore...\r\n");
00113 
00114     /* Reset kvstore for clean kvstore */
00115     kv_status = kv_reset("/" STR(MBED_CONF_STORAGE_DEFAULT_KV) "/");
00116     if (kv_status != MBED_SUCCESS) {
00117         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "kv_reset() failed", kv_status);
00118     }
00119 
00120     printf("\rReset kvstore...OK\r\n");
00121 
00122 #if !DEVICE_TRNG && !TARGET_PSA
00123 #if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
00124     /* Inject trivial seed for development */
00125 
00126     printf("Inject NV seed...\r\n");
00127 
00128     psa_status_t psa_status;
00129     uint8_t seed[SEED_SIZE] = { 0 };
00130 
00131     /* First inject seed, expect OK or seed has injected by some provision process */
00132     psa_status = mbedtls_psa_inject_entropy(seed, sizeof(seed));
00133     if (psa_status != PSA_SUCCESS && psa_status != PSA_ERROR_NOT_PERMITTED) {
00134         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Inject entropy failed", psa_status);
00135     }
00136 
00137     /* Second inject seed, expect seed has injected above or by some provision process */
00138     psa_status = mbedtls_psa_inject_entropy(seed, sizeof(seed));
00139     if (psa_status != PSA_ERROR_NOT_PERMITTED) {
00140         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Re-jnject entropy expects PSA_ERROR_NOT_PERMITTED", psa_status);
00141     }
00142 
00143     printf("\rInject NV seed...OK\r\n");
00144 #endif  /* !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) */
00145 #endif  /* #if !DEVICE_TRNG && !TARGET_PSA */
00146 
00147 #if MBED_MAJOR_VERSION >= 6
00148     /* Since Mbedd OS 6.0, device key is not installed automatically and silently, possibly via generate_derived_key(...). Install it manually. */
00149     printf("Install device key...\r\n");
00150 
00151     /* DeviceKey is a singleton */
00152     DeviceKey &devkey = DeviceKey::get_instance();
00153 
00154     /* To be compatible with mbed-bootloader, install 16-byte version. */
00155     int device_key_status = devkey.generate_root_of_trust(DEVICE_KEY_16BYTE);
00156     switch (device_key_status) {
00157         case DEVICEKEY_SUCCESS:
00158             printf("\rInstall device key...OK\r\n");
00159             break;
00160 
00161         case DEVICEKEY_ALREADY_EXIST:
00162             printf("\rInstall device key...Already existed\r\n");
00163             break;
00164 
00165         case DEVICEKEY_GENERATE_RANDOM_ERROR:
00166             MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "No entropy sources and cannot generate device key");
00167             MBED_FALLTHROUGH;
00168 
00169         default:
00170             MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Install device key failed", device_key_status);
00171     }
00172 #endif
00173 
00174     /* Mark the device as provisioned */
00175     kv_status = inner_store->set(KV_KEY_PROVISION, "1", 1, KVStore::WRITE_ONCE_FLAG);
00176     if (kv_status != MBED_SUCCESS) {
00177         MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNKNOWN), "Mark the device as provisioned failed", kv_status);
00178     }
00179 
00180     printf("Provision for development...OK\r\n");
00181 }