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