mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
Parent:
0:5b88d5760320
updated based on mbed-os5.15.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /* mbed Microcontroller Library
kenjiArai 0:5b88d5760320 2 * Copyright (c) 2018 ARM Limited
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 0:5b88d5760320 5 * you may not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 6 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 7 *
kenjiArai 0:5b88d5760320 8 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 9 *
kenjiArai 0:5b88d5760320 10 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 11 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 0:5b88d5760320 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 13 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 14 * limitations under the License.
kenjiArai 0:5b88d5760320 15 */
kenjiArai 0:5b88d5760320 16
kenjiArai 0:5b88d5760320 17 #include "DeviceKey.h"
kenjiArai 0:5b88d5760320 18
kenjiArai 0:5b88d5760320 19 #if DEVICEKEY_ENABLED
kenjiArai 0:5b88d5760320 20 #include "mbedtls/config.h"
kenjiArai 0:5b88d5760320 21 #include "mbedtls/cmac.h"
kenjiArai 0:5b88d5760320 22 #include "mbedtls/platform.h"
kenjiArai 1:9db0e321a9f4 23 #include "features/storage/kvstore/include/KVStore.h"
kenjiArai 1:9db0e321a9f4 24 #include "features/storage/kvstore/tdbstore/TDBStore.h"
kenjiArai 1:9db0e321a9f4 25 #include "features/storage/kvstore/kv_map/KVMap.h"
kenjiArai 1:9db0e321a9f4 26 #include "features/storage/kvstore/conf/kv_config.h"
kenjiArai 0:5b88d5760320 27 #include "mbed_wait_api.h"
kenjiArai 1:9db0e321a9f4 28 #include <stdlib.h>
kenjiArai 0:5b88d5760320 29 #include "platform/mbed_error.h"
kenjiArai 0:5b88d5760320 30 #include <string.h>
kenjiArai 0:5b88d5760320 31 #include "entropy.h"
kenjiArai 0:5b88d5760320 32 #include "mbed_trace.h"
kenjiArai 0:5b88d5760320 33
kenjiArai 0:5b88d5760320 34 #define TRACE_GROUP "DEVKEY"
kenjiArai 0:5b88d5760320 35
kenjiArai 0:5b88d5760320 36 #if !defined(MBEDTLS_CMAC_C)
kenjiArai 0:5b88d5760320 37 #error [NOT_SUPPORTED] MBEDTLS_CMAC_C needs to be enabled for this driver
kenjiArai 0:5b88d5760320 38 #else
kenjiArai 0:5b88d5760320 39
kenjiArai 0:5b88d5760320 40
kenjiArai 0:5b88d5760320 41 namespace mbed {
kenjiArai 0:5b88d5760320 42
kenjiArai 0:5b88d5760320 43 #define DEVKEY_WRITE_UINT32_LE( dst, src ) \
kenjiArai 0:5b88d5760320 44 do \
kenjiArai 0:5b88d5760320 45 { \
kenjiArai 0:5b88d5760320 46 (dst)[0] = ( (src) >> 0 ) & 0xFF; \
kenjiArai 0:5b88d5760320 47 (dst)[1] = ( (src) >> 8 ) & 0xFF; \
kenjiArai 0:5b88d5760320 48 (dst)[2] = ( (src) >> 16 ) & 0xFF; \
kenjiArai 0:5b88d5760320 49 (dst)[3] = ( (src) >> 24 ) & 0xFF; \
kenjiArai 0:5b88d5760320 50 } while( 0 )
kenjiArai 0:5b88d5760320 51
kenjiArai 0:5b88d5760320 52 #define DEVKEY_WRITE_UINT8_LE( dst, src ) \
kenjiArai 0:5b88d5760320 53 do \
kenjiArai 0:5b88d5760320 54 { \
kenjiArai 0:5b88d5760320 55 (dst)[0] = (src) & 0xFF; \
kenjiArai 0:5b88d5760320 56 } while( 0 )
kenjiArai 0:5b88d5760320 57
kenjiArai 0:5b88d5760320 58
kenjiArai 0:5b88d5760320 59 DeviceKey::DeviceKey()
kenjiArai 0:5b88d5760320 60 {
kenjiArai 0:5b88d5760320 61
kenjiArai 0:5b88d5760320 62 int ret = kv_init_storage_config();
kenjiArai 0:5b88d5760320 63 if (ret != MBED_SUCCESS) {
kenjiArai 0:5b88d5760320 64 tr_error("DeviceKey: Fail to initialize KvStore configuration.");
kenjiArai 0:5b88d5760320 65 }
kenjiArai 0:5b88d5760320 66 #if defined(MBEDTLS_PLATFORM_C)
kenjiArai 0:5b88d5760320 67 ret = mbedtls_platform_setup(NULL);
kenjiArai 0:5b88d5760320 68 if (ret != MBED_SUCCESS) {
kenjiArai 0:5b88d5760320 69 tr_error("DeviceKey: Fail in mbedtls_platform_setup.");
kenjiArai 0:5b88d5760320 70 }
kenjiArai 0:5b88d5760320 71 #endif /* MBEDTLS_PLATFORM_C */
kenjiArai 0:5b88d5760320 72 return;
kenjiArai 0:5b88d5760320 73 }
kenjiArai 0:5b88d5760320 74
kenjiArai 0:5b88d5760320 75 DeviceKey::~DeviceKey()
kenjiArai 0:5b88d5760320 76 {
kenjiArai 0:5b88d5760320 77 #if defined(MBEDTLS_PLATFORM_C)
kenjiArai 0:5b88d5760320 78 mbedtls_platform_teardown(NULL);
kenjiArai 0:5b88d5760320 79 #endif /* MBEDTLS_PLATFORM_C */
kenjiArai 0:5b88d5760320 80 return;
kenjiArai 0:5b88d5760320 81 }
kenjiArai 0:5b88d5760320 82
kenjiArai 0:5b88d5760320 83 int DeviceKey::generate_derived_key(const unsigned char *salt, size_t isalt_size, unsigned char *output,
kenjiArai 0:5b88d5760320 84 uint16_t ikey_type)
kenjiArai 0:5b88d5760320 85 {
kenjiArai 0:5b88d5760320 86 uint32_t key_buff[DEVICE_KEY_32BYTE / sizeof(uint32_t)];
kenjiArai 0:5b88d5760320 87 size_t actual_size = DEVICE_KEY_32BYTE;
kenjiArai 0:5b88d5760320 88
kenjiArai 0:5b88d5760320 89 if (DEVICE_KEY_16BYTE != ikey_type && DEVICE_KEY_32BYTE != ikey_type) {
kenjiArai 0:5b88d5760320 90 return DEVICEKEY_INVALID_KEY_TYPE;
kenjiArai 0:5b88d5760320 91 }
kenjiArai 0:5b88d5760320 92
kenjiArai 0:5b88d5760320 93 actual_size = DEVICE_KEY_16BYTE != ikey_type ? DEVICE_KEY_32BYTE : DEVICE_KEY_16BYTE;
kenjiArai 0:5b88d5760320 94
kenjiArai 0:5b88d5760320 95 //First try to read the key from KVStore
kenjiArai 0:5b88d5760320 96 int ret = read_key_from_kvstore(key_buff, actual_size);
kenjiArai 0:5b88d5760320 97 if (DEVICEKEY_SUCCESS != ret && DEVICEKEY_NOT_FOUND != ret) {
kenjiArai 0:5b88d5760320 98 return ret;
kenjiArai 0:5b88d5760320 99 }
kenjiArai 0:5b88d5760320 100
kenjiArai 0:5b88d5760320 101 //If the key was not found in KVStore we will create it by using random generation and then save it to KVStore
kenjiArai 0:5b88d5760320 102 if (DEVICEKEY_NOT_FOUND == ret) {
kenjiArai 0:5b88d5760320 103 ret = generate_key_by_random(key_buff, actual_size);
kenjiArai 0:5b88d5760320 104 if (DEVICEKEY_SUCCESS != ret) {
kenjiArai 0:5b88d5760320 105 return ret;
kenjiArai 0:5b88d5760320 106 }
kenjiArai 0:5b88d5760320 107
kenjiArai 0:5b88d5760320 108 ret = device_inject_root_of_trust(key_buff, actual_size);
kenjiArai 0:5b88d5760320 109 if (DEVICEKEY_SUCCESS != ret) {
kenjiArai 0:5b88d5760320 110 return ret;
kenjiArai 0:5b88d5760320 111 }
kenjiArai 0:5b88d5760320 112 }
kenjiArai 0:5b88d5760320 113
kenjiArai 0:5b88d5760320 114 ret = get_derived_key(key_buff, actual_size, salt, isalt_size, output, ikey_type);
kenjiArai 0:5b88d5760320 115 return ret;
kenjiArai 0:5b88d5760320 116 }
kenjiArai 0:5b88d5760320 117
kenjiArai 0:5b88d5760320 118 int DeviceKey::device_inject_root_of_trust(uint32_t *value, size_t isize)
kenjiArai 0:5b88d5760320 119 {
kenjiArai 0:5b88d5760320 120 return write_key_to_kvstore(value, isize);
kenjiArai 0:5b88d5760320 121 }
kenjiArai 0:5b88d5760320 122
kenjiArai 0:5b88d5760320 123 int DeviceKey::write_key_to_kvstore(uint32_t *input, size_t isize)
kenjiArai 0:5b88d5760320 124 {
kenjiArai 0:5b88d5760320 125 if (DEVICE_KEY_16BYTE != isize && DEVICE_KEY_32BYTE != isize) {
kenjiArai 0:5b88d5760320 126 return DEVICEKEY_INVALID_KEY_SIZE;
kenjiArai 0:5b88d5760320 127 }
kenjiArai 0:5b88d5760320 128
kenjiArai 0:5b88d5760320 129 //First we read if key exist. If it is exists, we return DEVICEKEY_ALREADY_EXIST error
kenjiArai 0:5b88d5760320 130 uint32_t read_key[DEVICE_KEY_32BYTE / sizeof(uint32_t)] = {0};
kenjiArai 0:5b88d5760320 131 size_t read_size = DEVICE_KEY_32BYTE;
kenjiArai 0:5b88d5760320 132 int ret = read_key_from_kvstore(read_key, read_size);
kenjiArai 0:5b88d5760320 133 if (DEVICEKEY_SUCCESS == ret) {
kenjiArai 0:5b88d5760320 134 return DEVICEKEY_ALREADY_EXIST;
kenjiArai 0:5b88d5760320 135 }
kenjiArai 0:5b88d5760320 136 if (DEVICEKEY_NOT_FOUND != ret) {
kenjiArai 0:5b88d5760320 137 return ret;
kenjiArai 0:5b88d5760320 138 }
kenjiArai 0:5b88d5760320 139
kenjiArai 0:5b88d5760320 140 KVMap &kv_map = KVMap::get_instance();
kenjiArai 0:5b88d5760320 141 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
kenjiArai 0:5b88d5760320 142 if (inner_store == NULL) {
kenjiArai 0:5b88d5760320 143 return DEVICEKEY_SAVE_FAILED;
kenjiArai 0:5b88d5760320 144 }
kenjiArai 0:5b88d5760320 145
kenjiArai 0:5b88d5760320 146 ret = ((TDBStore *)inner_store)->reserved_data_set(input, isize);
kenjiArai 0:5b88d5760320 147 if (MBED_ERROR_WRITE_FAILED == ret) {
kenjiArai 0:5b88d5760320 148 return DEVICEKEY_SAVE_FAILED;
kenjiArai 0:5b88d5760320 149 }
kenjiArai 0:5b88d5760320 150
kenjiArai 0:5b88d5760320 151 if (MBED_SUCCESS != ret) {
kenjiArai 0:5b88d5760320 152 return DEVICEKEY_KVSTORE_UNPREDICTED_ERROR;
kenjiArai 0:5b88d5760320 153 }
kenjiArai 0:5b88d5760320 154
kenjiArai 0:5b88d5760320 155 return DEVICEKEY_SUCCESS;
kenjiArai 0:5b88d5760320 156 }
kenjiArai 0:5b88d5760320 157
kenjiArai 0:5b88d5760320 158 int DeviceKey::read_key_from_kvstore(uint32_t *output, size_t &size)
kenjiArai 0:5b88d5760320 159 {
kenjiArai 0:5b88d5760320 160 if (size > (uint16_t) -1) {
kenjiArai 0:5b88d5760320 161 return DEVICEKEY_INVALID_PARAM;
kenjiArai 0:5b88d5760320 162 }
kenjiArai 0:5b88d5760320 163
kenjiArai 0:5b88d5760320 164 KVMap &kv_map = KVMap::get_instance();
kenjiArai 0:5b88d5760320 165 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
kenjiArai 0:5b88d5760320 166 if (inner_store == NULL) {
kenjiArai 0:5b88d5760320 167 return DEVICEKEY_NOT_FOUND;
kenjiArai 0:5b88d5760320 168 }
kenjiArai 0:5b88d5760320 169
kenjiArai 0:5b88d5760320 170 int kvStatus = ((TDBStore *)inner_store)->reserved_data_get(output, size, &size);
kenjiArai 0:5b88d5760320 171 if (MBED_ERROR_ITEM_NOT_FOUND == kvStatus) {
kenjiArai 0:5b88d5760320 172 return DEVICEKEY_NOT_FOUND;
kenjiArai 0:5b88d5760320 173 }
kenjiArai 0:5b88d5760320 174
kenjiArai 0:5b88d5760320 175 if (MBED_ERROR_READ_FAILED == kvStatus || MBED_ERROR_INVALID_SIZE == kvStatus) {
kenjiArai 0:5b88d5760320 176 return DEVICEKEY_READ_FAILED;
kenjiArai 0:5b88d5760320 177 }
kenjiArai 0:5b88d5760320 178
kenjiArai 0:5b88d5760320 179 if (MBED_SUCCESS != kvStatus) {
kenjiArai 0:5b88d5760320 180 return DEVICEKEY_KVSTORE_UNPREDICTED_ERROR;
kenjiArai 0:5b88d5760320 181 }
kenjiArai 0:5b88d5760320 182
kenjiArai 0:5b88d5760320 183 return DEVICEKEY_SUCCESS;
kenjiArai 0:5b88d5760320 184 }
kenjiArai 0:5b88d5760320 185
kenjiArai 0:5b88d5760320 186 int DeviceKey::get_derived_key(uint32_t *ikey_buff, size_t ikey_size, const unsigned char *isalt,
kenjiArai 0:5b88d5760320 187 size_t isalt_size, unsigned char *output, uint32_t ikey_type)
kenjiArai 0:5b88d5760320 188 {
kenjiArai 0:5b88d5760320 189 //KDF in counter mode implementation as described in Section 5.1
kenjiArai 0:5b88d5760320 190 //of NIST SP 800-108, Recommendation for Key Derivation Using Pseudorandom Functions
kenjiArai 0:5b88d5760320 191 int ret;
kenjiArai 0:5b88d5760320 192 size_t counter = 0;
kenjiArai 0:5b88d5760320 193 char separator = 0x00;
kenjiArai 0:5b88d5760320 194 mbedtls_cipher_context_t ctx;
kenjiArai 0:5b88d5760320 195 unsigned char output_len_enc[ 4 ] = {0};
kenjiArai 0:5b88d5760320 196 unsigned char counter_enc[ 1 ] = {0};
kenjiArai 0:5b88d5760320 197
kenjiArai 0:5b88d5760320 198 DEVKEY_WRITE_UINT32_LE(output_len_enc, ikey_type);
kenjiArai 0:5b88d5760320 199
kenjiArai 0:5b88d5760320 200 mbedtls_cipher_type_t mbedtls_cipher_type = MBEDTLS_CIPHER_AES_128_ECB;
kenjiArai 0:5b88d5760320 201 if (DEVICE_KEY_32BYTE == ikey_size) {
kenjiArai 0:5b88d5760320 202 mbedtls_cipher_type = MBEDTLS_CIPHER_AES_256_ECB;
kenjiArai 0:5b88d5760320 203 }
kenjiArai 0:5b88d5760320 204
kenjiArai 0:5b88d5760320 205 const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type(mbedtls_cipher_type);
kenjiArai 0:5b88d5760320 206
kenjiArai 0:5b88d5760320 207 do {
kenjiArai 0:5b88d5760320 208
kenjiArai 0:5b88d5760320 209 mbedtls_cipher_init(&ctx);
kenjiArai 0:5b88d5760320 210 ret = mbedtls_cipher_setup(&ctx, cipher_info);
kenjiArai 0:5b88d5760320 211 if (ret != 0) {
kenjiArai 0:5b88d5760320 212 goto finish;
kenjiArai 0:5b88d5760320 213 }
kenjiArai 0:5b88d5760320 214
kenjiArai 0:5b88d5760320 215 ret = mbedtls_cipher_cmac_starts(&ctx, (unsigned char *)ikey_buff, ikey_size * 8);
kenjiArai 0:5b88d5760320 216 if (ret != 0) {
kenjiArai 0:5b88d5760320 217 goto finish;
kenjiArai 0:5b88d5760320 218 }
kenjiArai 0:5b88d5760320 219
kenjiArai 0:5b88d5760320 220 DEVKEY_WRITE_UINT8_LE(counter_enc, (counter + 1));
kenjiArai 0:5b88d5760320 221
kenjiArai 0:5b88d5760320 222 ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)counter_enc, sizeof(counter_enc));
kenjiArai 0:5b88d5760320 223 if (ret != 0) {
kenjiArai 0:5b88d5760320 224 goto finish;
kenjiArai 0:5b88d5760320 225 }
kenjiArai 0:5b88d5760320 226
kenjiArai 0:5b88d5760320 227 ret = mbedtls_cipher_cmac_update(&ctx, isalt, isalt_size);
kenjiArai 0:5b88d5760320 228 if (ret != 0) {
kenjiArai 0:5b88d5760320 229 goto finish;
kenjiArai 0:5b88d5760320 230 }
kenjiArai 0:5b88d5760320 231
kenjiArai 0:5b88d5760320 232 ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&separator, sizeof(char));
kenjiArai 0:5b88d5760320 233 if (ret != 0) {
kenjiArai 0:5b88d5760320 234 goto finish;
kenjiArai 0:5b88d5760320 235 }
kenjiArai 0:5b88d5760320 236
kenjiArai 0:5b88d5760320 237 ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&output_len_enc, sizeof(output_len_enc));
kenjiArai 0:5b88d5760320 238 if (ret != 0) {
kenjiArai 0:5b88d5760320 239 goto finish;
kenjiArai 0:5b88d5760320 240 }
kenjiArai 0:5b88d5760320 241
kenjiArai 0:5b88d5760320 242 ret = mbedtls_cipher_cmac_finish(&ctx, output + (DEVICE_KEY_16BYTE * (counter)));
kenjiArai 0:5b88d5760320 243 if (ret != 0) {
kenjiArai 0:5b88d5760320 244 goto finish;
kenjiArai 0:5b88d5760320 245 }
kenjiArai 0:5b88d5760320 246
kenjiArai 0:5b88d5760320 247 mbedtls_cipher_free(&ctx);
kenjiArai 0:5b88d5760320 248
kenjiArai 0:5b88d5760320 249 counter++;
kenjiArai 0:5b88d5760320 250
kenjiArai 0:5b88d5760320 251 } while (DEVICE_KEY_16BYTE * counter < ikey_type);
kenjiArai 0:5b88d5760320 252
kenjiArai 0:5b88d5760320 253 finish:
kenjiArai 0:5b88d5760320 254 if (DEVICEKEY_SUCCESS != ret) {
kenjiArai 0:5b88d5760320 255 mbedtls_cipher_free(&ctx);
kenjiArai 0:5b88d5760320 256 return DEVICEKEY_ERR_CMAC_GENERIC_FAILURE;
kenjiArai 0:5b88d5760320 257 }
kenjiArai 0:5b88d5760320 258
kenjiArai 0:5b88d5760320 259 return DEVICEKEY_SUCCESS;
kenjiArai 0:5b88d5760320 260 }
kenjiArai 0:5b88d5760320 261
kenjiArai 0:5b88d5760320 262 int DeviceKey::generate_key_by_random(uint32_t *output, size_t size)
kenjiArai 0:5b88d5760320 263 {
kenjiArai 0:5b88d5760320 264 int ret = DEVICEKEY_GENERATE_RANDOM_ERROR;
kenjiArai 0:5b88d5760320 265
kenjiArai 0:5b88d5760320 266 if (DEVICE_KEY_16BYTE > size) {
kenjiArai 0:5b88d5760320 267 return DEVICEKEY_BUFFER_TOO_SMALL;
kenjiArai 0:5b88d5760320 268 } else if (DEVICE_KEY_16BYTE != size && DEVICE_KEY_32BYTE != size) {
kenjiArai 0:5b88d5760320 269 return DEVICEKEY_INVALID_PARAM;
kenjiArai 0:5b88d5760320 270 }
kenjiArai 0:5b88d5760320 271
kenjiArai 1:9db0e321a9f4 272 #if defined(DEVICE_TRNG) || defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
kenjiArai 0:5b88d5760320 273 mbedtls_entropy_context *entropy = new mbedtls_entropy_context;
kenjiArai 0:5b88d5760320 274 mbedtls_entropy_init(entropy);
kenjiArai 0:5b88d5760320 275 memset(output, 0, size);
kenjiArai 0:5b88d5760320 276
kenjiArai 0:5b88d5760320 277 ret = mbedtls_entropy_func(entropy, (unsigned char *)output, size);
kenjiArai 1:9db0e321a9f4 278 if (ret != MBED_SUCCESS) {
kenjiArai 0:5b88d5760320 279 ret = DEVICEKEY_GENERATE_RANDOM_ERROR;
kenjiArai 0:5b88d5760320 280 } else {
kenjiArai 0:5b88d5760320 281 ret = DEVICEKEY_SUCCESS;
kenjiArai 0:5b88d5760320 282 }
kenjiArai 0:5b88d5760320 283
kenjiArai 0:5b88d5760320 284 mbedtls_entropy_free(entropy);
kenjiArai 0:5b88d5760320 285 delete entropy;
kenjiArai 0:5b88d5760320 286
kenjiArai 0:5b88d5760320 287 #endif
kenjiArai 0:5b88d5760320 288
kenjiArai 0:5b88d5760320 289 return ret;
kenjiArai 0:5b88d5760320 290 }
kenjiArai 0:5b88d5760320 291
kenjiArai 0:5b88d5760320 292 } // namespace mbed
kenjiArai 0:5b88d5760320 293
kenjiArai 0:5b88d5760320 294 #endif
kenjiArai 0:5b88d5760320 295 #endif
kenjiArai 0:5b88d5760320 296
kenjiArai 0:5b88d5760320 297