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.
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 Aug 9 2022 00:37:05 by
