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.
Dependencies: nRF51_Vdd TextLCD BME280
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 #include "mbedtls/config.h" 00019 #include "mbedtls/cmac.h" 00020 #include "nvstore.h" 00021 #include "trng_api.h" 00022 #include "mbed_wait_api.h" 00023 #include "stdlib.h" 00024 00025 #include <string.h> 00026 00027 #if !defined(MBEDTLS_CMAC_C) 00028 #error [NOT_SUPPORTED] MBEDTLS_CMAC_C needs to be enabled for this driver 00029 #else 00030 00031 #if NVSTORE_ENABLED 00032 00033 namespace mbed { 00034 00035 #define DEVKEY_WRITE_UINT32_LE( dst, src ) \ 00036 do \ 00037 { \ 00038 (dst)[0] = ( (src) >> 0 ) & 0xFF; \ 00039 (dst)[1] = ( (src) >> 8 ) & 0xFF; \ 00040 (dst)[2] = ( (src) >> 16 ) & 0xFF; \ 00041 (dst)[3] = ( (src) >> 24 ) & 0xFF; \ 00042 } while( 0 ) 00043 00044 #define DEVKEY_WRITE_UINT8_LE( dst, src ) \ 00045 do \ 00046 { \ 00047 (dst)[0] = (src) & 0xFF; \ 00048 } while( 0 ) 00049 00050 00051 DeviceKey::DeviceKey() 00052 { 00053 return; 00054 } 00055 00056 DeviceKey::~DeviceKey() 00057 { 00058 return; 00059 } 00060 00061 int DeviceKey::generate_derived_key(const unsigned char *salt, size_t isalt_size, unsigned char *output, 00062 uint16_t ikey_type) 00063 { 00064 uint32_t key_buff[DEVICE_KEY_32BYTE / sizeof(uint32_t)]; 00065 size_t actual_size = DEVICE_KEY_32BYTE; 00066 00067 if (DEVICE_KEY_16BYTE != ikey_type && DEVICE_KEY_32BYTE != ikey_type) { 00068 return DEVICEKEY_INVALID_KEY_TYPE; 00069 } 00070 00071 //First try to read the key from NVStore 00072 int ret = read_key_from_nvstore(key_buff, actual_size); 00073 if (DEVICEKEY_SUCCESS != ret && DEVICEKEY_NOT_FOUND != ret) { 00074 return ret; 00075 } 00076 00077 if (DEVICE_KEY_16BYTE != actual_size && DEVICE_KEY_32BYTE != actual_size) { 00078 return DEVICEKEY_READ_FAILED; 00079 } 00080 00081 //If the key was not found in NVStore we will create it by using TRNG and then save it to NVStore 00082 if (DEVICEKEY_NOT_FOUND == ret) { 00083 ret = generate_key_by_trng(key_buff, actual_size); 00084 if (DEVICEKEY_SUCCESS != ret) { 00085 return ret; 00086 } 00087 00088 ret = device_inject_root_of_trust(key_buff, actual_size); 00089 if (DEVICEKEY_SUCCESS != ret) { 00090 return ret; 00091 } 00092 } 00093 00094 ret = get_derived_key(key_buff, actual_size, salt, isalt_size, output, ikey_type); 00095 return ret; 00096 } 00097 00098 int DeviceKey::device_inject_root_of_trust(uint32_t *value, size_t isize) 00099 { 00100 return write_key_to_nvstore(value, isize); 00101 } 00102 00103 int DeviceKey::write_key_to_nvstore(uint32_t *input, size_t isize) 00104 { 00105 if (DEVICE_KEY_16BYTE != isize && DEVICE_KEY_32BYTE != isize) { 00106 return DEVICEKEY_INVALID_KEY_SIZE; 00107 } 00108 00109 //First we read if key exist. If it is exists, we return DEVICEKEY_ALREADY_EXIST error 00110 uint32_t read_key[DEVICE_KEY_32BYTE / sizeof(uint32_t)] = {0}; 00111 size_t read_size = DEVICE_KEY_32BYTE; 00112 int ret = read_key_from_nvstore(read_key, read_size); 00113 if (DEVICEKEY_SUCCESS == ret) { 00114 return DEVICEKEY_ALREADY_EXIST; 00115 } 00116 if (DEVICEKEY_NOT_FOUND != ret) { 00117 return ret; 00118 } 00119 00120 NVStore& nvstore = NVStore::get_instance(); 00121 ret = nvstore.set(NVSTORE_DEVICEKEY_KEY, (uint16_t)isize, input); 00122 if (NVSTORE_WRITE_ERROR == ret || NVSTORE_BUFF_TOO_SMALL == ret) { 00123 return DEVICEKEY_SAVE_FAILED; 00124 } 00125 00126 if (NVSTORE_SUCCESS != ret) { 00127 return DEVICEKEY_NVSTORE_UNPREDICTED_ERROR; 00128 } 00129 00130 return DEVICEKEY_SUCCESS; 00131 } 00132 00133 int DeviceKey::read_key_from_nvstore(uint32_t *output, size_t& size) 00134 { 00135 if (size > (uint16_t)-1) { 00136 return DEVICEKEY_INVALID_PARAM; 00137 } 00138 00139 uint16_t in_size = size; 00140 uint16_t out_size = 0; 00141 NVStore& nvstore = NVStore::get_instance(); 00142 int nvStatus = nvstore.get(NVSTORE_DEVICEKEY_KEY, in_size, output, out_size); 00143 if (NVSTORE_NOT_FOUND == nvStatus) { 00144 return DEVICEKEY_NOT_FOUND; 00145 } 00146 00147 if (NVSTORE_READ_ERROR == nvStatus || NVSTORE_BUFF_TOO_SMALL == nvStatus) { 00148 return DEVICEKEY_READ_FAILED; 00149 } 00150 00151 if (NVSTORE_SUCCESS != nvStatus) { 00152 return DEVICEKEY_NVSTORE_UNPREDICTED_ERROR; 00153 } 00154 00155 size = out_size; 00156 return DEVICEKEY_SUCCESS; 00157 } 00158 00159 int DeviceKey::get_derived_key(uint32_t *ikey_buff, size_t ikey_size, const unsigned char *isalt, 00160 size_t isalt_size, unsigned char *output, uint32_t ikey_type) 00161 { 00162 //KDF in counter mode implementation as described in Section 5.1 00163 //of NIST SP 800-108, Recommendation for Key Derivation Using Pseudorandom Functions 00164 int ret; 00165 size_t counter = 0; 00166 char separator = 0x00; 00167 mbedtls_cipher_context_t ctx; 00168 unsigned char output_len_enc[ 4 ] = {0}; 00169 unsigned char counter_enc[ 1 ] = {0}; 00170 00171 DEVKEY_WRITE_UINT32_LE(output_len_enc, ikey_type); 00172 00173 mbedtls_cipher_type_t mbedtls_cipher_type = MBEDTLS_CIPHER_AES_128_ECB; 00174 if (DEVICE_KEY_32BYTE == ikey_size) { 00175 mbedtls_cipher_type = MBEDTLS_CIPHER_AES_256_ECB; 00176 } 00177 00178 const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type(mbedtls_cipher_type); 00179 00180 do { 00181 00182 mbedtls_cipher_init(&ctx); 00183 ret = mbedtls_cipher_setup(&ctx, cipher_info); 00184 if (ret != 0) { 00185 goto finish; 00186 } 00187 00188 ret = mbedtls_cipher_cmac_starts(&ctx, (unsigned char *)ikey_buff, ikey_size * 8); 00189 if (ret != 0) { 00190 goto finish; 00191 } 00192 00193 DEVKEY_WRITE_UINT8_LE(counter_enc, (counter+1)); 00194 00195 ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)counter_enc, sizeof(counter_enc)); 00196 if (ret != 0) { 00197 goto finish; 00198 } 00199 00200 ret = mbedtls_cipher_cmac_update(&ctx, isalt, isalt_size); 00201 if (ret != 0) { 00202 goto finish; 00203 } 00204 00205 ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&separator, sizeof(char)); 00206 if (ret != 0) { 00207 goto finish; 00208 } 00209 00210 ret = mbedtls_cipher_cmac_update(&ctx, (unsigned char *)&output_len_enc, sizeof(output_len_enc)); 00211 if (ret != 0) { 00212 goto finish; 00213 } 00214 00215 ret = mbedtls_cipher_cmac_finish(&ctx, output + (DEVICE_KEY_16BYTE * (counter))); 00216 if (ret != 0) { 00217 goto finish; 00218 } 00219 00220 mbedtls_cipher_free( &ctx ); 00221 00222 counter++; 00223 00224 } while (DEVICE_KEY_16BYTE * counter < ikey_type); 00225 00226 finish: 00227 if (DEVICEKEY_SUCCESS != ret) { 00228 mbedtls_cipher_free( &ctx ); 00229 return DEVICEKEY_ERR_CMAC_GENERIC_FAILURE; 00230 } 00231 00232 return DEVICEKEY_SUCCESS; 00233 } 00234 00235 int DeviceKey::generate_key_by_trng(uint32_t *output, size_t size) 00236 { 00237 #if defined(DEVICE_TRNG) 00238 size_t in_size; 00239 size_t ongoing_size; 00240 trng_t trng_obj; 00241 int ret = DEVICEKEY_SUCCESS; 00242 unsigned char *pBuffer = (unsigned char *)output; 00243 00244 memset(output, 0, size); 00245 00246 if (DEVICE_KEY_16BYTE > size) { 00247 return DEVICEKEY_BUFFER_TOO_SMALL; 00248 } else if (DEVICE_KEY_16BYTE != size && DEVICE_KEY_32BYTE != size) { 00249 return DEVICEKEY_INVALID_PARAM; 00250 } 00251 00252 trng_init(&trng_obj); 00253 00254 in_size = size; 00255 while (in_size > 0) { 00256 00257 ongoing_size = 0; 00258 ret = trng_get_bytes(&trng_obj, (unsigned char *)pBuffer, in_size, &ongoing_size); 00259 if (0 != ret || ongoing_size > in_size) { 00260 ret = DEVICEKEY_TRNG_ERROR; 00261 goto finish; 00262 } 00263 00264 pBuffer += ongoing_size; 00265 in_size -= ongoing_size; 00266 } 00267 00268 ret = DEVICEKEY_SUCCESS; 00269 00270 finish: 00271 trng_free(&trng_obj); 00272 return ret; 00273 00274 #else 00275 return DEVICEKEY_NO_KEY_INJECTED; 00276 #endif 00277 } 00278 00279 } // namespace mbed 00280 00281 #endif //NVSTORE_ENABLED 00282 #endif 00283 00284
Generated on Tue Jul 12 2022 15:15:42 by
