Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
DeviceKey.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2018 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "DeviceKey.h" 00018 00019 #if DEVICEKEY_ENABLED 00020 #include "mbedtls/config.h" 00021 #include "mbedtls/cmac.h" 00022 #include "mbedtls/platform.h" 00023 #include "features/storage/kvstore/include/KVStore.h" 00024 #include "features/storage/kvstore/tdbstore/TDBStore.h" 00025 #include "features/storage/kvstore/kv_map/KVMap.h" 00026 #include "features/storage/kvstore/conf/kv_config.h" 00027 #include "mbed_wait_api.h" 00028 #include <stdlib.h> 00029 #include "platform/mbed_error.h" 00030 #include <string.h> 00031 #include "entropy.h" 00032 #include "mbed_trace.h" 00033 00034 #define TRACE_GROUP "DEVKEY" 00035 00036 #if !defined(MBEDTLS_CMAC_C) 00037 #error [NOT_SUPPORTED] MBEDTLS_CMAC_C needs to be enabled for this driver 00038 #else 00039 00040 00041 namespace mbed { 00042 00043 #define DEVKEY_WRITE_UINT32_LE( dst, src ) \ 00044 do \ 00045 { \ 00046 (dst)[0] = ( (src) >> 0 ) & 0xFF; \ 00047 (dst)[1] = ( (src) >> 8 ) & 0xFF; \ 00048 (dst)[2] = ( (src) >> 16 ) & 0xFF; \ 00049 (dst)[3] = ( (src) >> 24 ) & 0xFF; \ 00050 } while( 0 ) 00051 00052 #define DEVKEY_WRITE_UINT8_LE( dst, src ) \ 00053 do \ 00054 { \ 00055 (dst)[0] = (src) & 0xFF; \ 00056 } while( 0 ) 00057 00058 00059 DeviceKey::DeviceKey() 00060 { 00061 00062 int ret = kv_init_storage_config(); 00063 if (ret != MBED_SUCCESS) { 00064 tr_error("DeviceKey: Fail to initialize KvStore configuration."); 00065 } 00066 #if defined(MBEDTLS_PLATFORM_C) 00067 ret = mbedtls_platform_setup(NULL); 00068 if (ret != MBED_SUCCESS) { 00069 tr_error("DeviceKey: Fail in mbedtls_platform_setup."); 00070 } 00071 #endif /* MBEDTLS_PLATFORM_C */ 00072 return; 00073 } 00074 00075 DeviceKey::~DeviceKey() 00076 { 00077 #if defined(MBEDTLS_PLATFORM_C) 00078 mbedtls_platform_teardown(NULL); 00079 #endif /* MBEDTLS_PLATFORM_C */ 00080 return; 00081 } 00082 00083 int DeviceKey::generate_derived_key(const unsigned char *salt, size_t isalt_size, unsigned char *output, 00084 uint16_t ikey_type) 00085 { 00086 uint32_t key_buff[DEVICE_KEY_32BYTE / sizeof(uint32_t)]; 00087 size_t actual_size = DEVICE_KEY_32BYTE; 00088 00089 if (DEVICE_KEY_16BYTE != ikey_type && DEVICE_KEY_32BYTE != ikey_type) { 00090 return DEVICEKEY_INVALID_KEY_TYPE; 00091 } 00092 00093 actual_size = DEVICE_KEY_16BYTE != ikey_type ? DEVICE_KEY_32BYTE : DEVICE_KEY_16BYTE; 00094 00095 //First try to read the key from KVStore 00096 int ret = read_key_from_kvstore(key_buff, actual_size); 00097 if (DEVICEKEY_SUCCESS != ret && DEVICEKEY_NOT_FOUND != ret) { 00098 return ret; 00099 } 00100 00101 //If the key was not found in KVStore we will create it by using random generation and then save it to KVStore 00102 if (DEVICEKEY_NOT_FOUND == ret) { 00103 ret = generate_key_by_random(key_buff, actual_size); 00104 if (DEVICEKEY_SUCCESS != ret) { 00105 return ret; 00106 } 00107 00108 ret = device_inject_root_of_trust(key_buff, actual_size); 00109 if (DEVICEKEY_SUCCESS != ret) { 00110 return ret; 00111 } 00112 } 00113 00114 ret = get_derived_key(key_buff, actual_size, salt, isalt_size, output, ikey_type); 00115 return ret; 00116 } 00117 00118 int DeviceKey::device_inject_root_of_trust(uint32_t *value, size_t isize) 00119 { 00120 return write_key_to_kvstore(value, isize); 00121 } 00122 00123 int DeviceKey::write_key_to_kvstore(uint32_t *input, size_t isize) 00124 { 00125 if (DEVICE_KEY_16BYTE != isize && DEVICE_KEY_32BYTE != isize) { 00126 return DEVICEKEY_INVALID_KEY_SIZE; 00127 } 00128 00129 //First we read if key exist. If it is exists, we return DEVICEKEY_ALREADY_EXIST error 00130 uint32_t read_key[DEVICE_KEY_32BYTE / sizeof(uint32_t)] = {0}; 00131 size_t read_size = DEVICE_KEY_32BYTE; 00132 int ret = read_key_from_kvstore(read_key, read_size); 00133 if (DEVICEKEY_SUCCESS == ret) { 00134 return DEVICEKEY_ALREADY_EXIST; 00135 } 00136 if (DEVICEKEY_NOT_FOUND != ret) { 00137 return ret; 00138 } 00139 00140 KVMap &kv_map = KVMap::get_instance(); 00141 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL); 00142 if (inner_store == NULL) { 00143 return DEVICEKEY_SAVE_FAILED; 00144 } 00145 00146 ret = ((TDBStore *)inner_store)->reserved_data_set(input, isize); 00147 if (MBED_ERROR_WRITE_FAILED == ret) { 00148 return DEVICEKEY_SAVE_FAILED; 00149 } 00150 00151 if (MBED_SUCCESS != ret) { 00152 return DEVICEKEY_KVSTORE_UNPREDICTED_ERROR; 00153 } 00154 00155 return DEVICEKEY_SUCCESS; 00156 } 00157 00158 int DeviceKey::read_key_from_kvstore(uint32_t *output, size_t &size) 00159 { 00160 if (size > (uint16_t) -1) { 00161 return DEVICEKEY_INVALID_PARAM; 00162 } 00163 00164 KVMap &kv_map = KVMap::get_instance(); 00165 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL); 00166 if (inner_store == NULL) { 00167 return DEVICEKEY_NOT_FOUND; 00168 } 00169 00170 int kvStatus = ((TDBStore *)inner_store)->reserved_data_get(output, size, &size); 00171 if (MBED_ERROR_ITEM_NOT_FOUND == kvStatus) { 00172 return DEVICEKEY_NOT_FOUND; 00173 } 00174 00175 if (MBED_ERROR_READ_FAILED == kvStatus || MBED_ERROR_INVALID_SIZE == kvStatus) { 00176 return DEVICEKEY_READ_FAILED; 00177 } 00178 00179 if (MBED_SUCCESS != kvStatus) { 00180 return DEVICEKEY_KVSTORE_UNPREDICTED_ERROR; 00181 } 00182 00183 return DEVICEKEY_SUCCESS; 00184 } 00185 00186 int DeviceKey::get_derived_key(uint32_t *ikey_buff, size_t ikey_size, const unsigned char *isalt, 00187 size_t isalt_size, unsigned char *output, uint32_t ikey_type) 00188 { 00189 //KDF in counter mode implementation as described in Section 5.1 00190 //of NIST SP 800-108, Recommendation for Key Derivation Using Pseudorandom Functions 00191 int ret; 00192 size_t counter = 0; 00193 char separator = 0x00; 00194 mbedtls_cipher_context_t ctx; 00195 unsigned char output_len_enc[ 4 ] = {0}; 00196 unsigned char counter_enc[ 1 ] = {0}; 00197 00198 DEVKEY_WRITE_UINT32_LE(output_len_enc, ikey_type); 00199 00200 mbedtls_cipher_type_t mbedtls_cipher_type = MBEDTLS_CIPHER_AES_128_ECB; 00201 if (DEVICE_KEY_32BYTE == ikey_size) { 00202 mbedtls_cipher_type = MBEDTLS_CIPHER_AES_256_ECB; 00203 } 00204 00205 const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type(mbedtls_cipher_type); 00206 00207 do { 00208 00209 mbedtls_cipher_init(&ctx); 00210 ret = mbedtls_cipher_setup(&ctx, cipher_info); 00211 if (ret != 0) { 00212 goto finish; 00213 } 00214 00215 ret = mbedtls_cipher_cmac_starts(&ctx, (unsigned char *)ikey_buff, ikey_size * 8); 00216 if (ret != 0) { 00217 goto finish; 00218 } 00219 00220 DEVKEY_WRITE_UINT8_LE(counter_enc, (counter + 1)); 00221 00222 ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)counter_enc, sizeof(counter_enc)); 00223 if (ret != 0) { 00224 goto finish; 00225 } 00226 00227 ret = mbedtls_cipher_cmac_update(&ctx, isalt, isalt_size); 00228 if (ret != 0) { 00229 goto finish; 00230 } 00231 00232 ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&separator, sizeof(char)); 00233 if (ret != 0) { 00234 goto finish; 00235 } 00236 00237 ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&output_len_enc, sizeof(output_len_enc)); 00238 if (ret != 0) { 00239 goto finish; 00240 } 00241 00242 ret = mbedtls_cipher_cmac_finish(&ctx, output + (DEVICE_KEY_16BYTE * (counter))); 00243 if (ret != 0) { 00244 goto finish; 00245 } 00246 00247 mbedtls_cipher_free(&ctx); 00248 00249 counter++; 00250 00251 } while (DEVICE_KEY_16BYTE * counter < ikey_type); 00252 00253 finish: 00254 if (DEVICEKEY_SUCCESS != ret) { 00255 mbedtls_cipher_free(&ctx); 00256 return DEVICEKEY_ERR_CMAC_GENERIC_FAILURE; 00257 } 00258 00259 return DEVICEKEY_SUCCESS; 00260 } 00261 00262 int DeviceKey::generate_key_by_random(uint32_t *output, size_t size) 00263 { 00264 int ret = DEVICEKEY_GENERATE_RANDOM_ERROR; 00265 00266 if (DEVICE_KEY_16BYTE > size) { 00267 return DEVICEKEY_BUFFER_TOO_SMALL; 00268 } else if (DEVICE_KEY_16BYTE != size && DEVICE_KEY_32BYTE != size) { 00269 return DEVICEKEY_INVALID_PARAM; 00270 } 00271 00272 #if defined(DEVICE_TRNG) || defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 00273 mbedtls_entropy_context *entropy = new mbedtls_entropy_context; 00274 mbedtls_entropy_init(entropy); 00275 memset(output, 0, size); 00276 00277 ret = mbedtls_entropy_func(entropy, (unsigned char *)output, size); 00278 if (ret != MBED_SUCCESS) { 00279 ret = DEVICEKEY_GENERATE_RANDOM_ERROR; 00280 } else { 00281 ret = DEVICEKEY_SUCCESS; 00282 } 00283 00284 mbedtls_entropy_free(entropy); 00285 delete entropy; 00286 00287 #endif 00288 00289 return ret; 00290 } 00291 00292 } // namespace mbed 00293 00294 #endif 00295 #endif 00296 00297
Generated on Tue Jul 12 2022 13:54:16 by
