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
SecureStore.cpp
00001 /* 00002 * Copyright (c) 2018 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * 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, WITHOUT 00012 * 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 // ----------------------------------------------------------- Includes ----------------------------------------------------------- 00018 00019 #include "SecureStore.h" 00020 00021 #if SECURESTORE_ENABLED 00022 00023 #include "aes.h" 00024 #include "cmac.h" 00025 #include "mbedtls/platform.h" 00026 #include "entropy.h" 00027 #include "DeviceKey.h" 00028 #include "mbed_assert.h" 00029 #include "mbed_wait_api.h" 00030 #include "mbed_error.h" 00031 #include <algorithm> 00032 #include <string.h> 00033 #include <stdio.h> 00034 00035 using namespace mbed; 00036 00037 // --------------------------------------------------------- Definitions ---------------------------------------------------------- 00038 00039 static const uint32_t securestore_revision = 1; 00040 00041 static const uint32_t enc_block_size = 16; 00042 static const uint32_t cmac_size = 16; 00043 static const uint32_t iv_size = 8; 00044 static const uint32_t scratch_buf_size = 256; 00045 static const uint32_t derived_key_size = 16; 00046 00047 static const char *const enc_prefix = "ENC"; 00048 static const char *const auth_prefix = "AUTH"; 00049 00050 static const uint32_t security_flags = KVStore::REQUIRE_CONFIDENTIALITY_FLAG | KVStore::REQUIRE_REPLAY_PROTECTION_FLAG; 00051 00052 namespace { 00053 typedef struct { 00054 uint16_t metadata_size = 0u; 00055 uint16_t revision = 0u; 00056 uint32_t data_size = 0u; 00057 uint32_t create_flags = 0u; 00058 uint8_t iv[iv_size] = { 0u }; 00059 } record_metadata_t; 00060 00061 // iterator handle 00062 typedef struct { 00063 KVStore::iterator_t underlying_it; 00064 } key_iterator_handle_t; 00065 00066 } 00067 00068 // incremental set handle 00069 struct SecureStore::inc_set_handle_t { 00070 record_metadata_t metadata; 00071 char *key = nullptr; 00072 uint32_t offset_in_data = 0u; 00073 uint8_t ctr_buf[enc_block_size] = { 0u }; 00074 mbedtls_aes_context enc_ctx; 00075 mbedtls_cipher_context_t auth_ctx; 00076 KVStore::set_handle_t underlying_handle; 00077 }; 00078 00079 // -------------------------------------------------- Local Functions Declaration ---------------------------------------------------- 00080 00081 // -------------------------------------------------- Functions Implementation ---------------------------------------------------- 00082 00083 int encrypt_decrypt_start(mbedtls_aes_context &enc_aes_ctx, uint8_t *iv, const char *key, 00084 uint8_t *ctr_buf, uint8_t *salt_buf, int salt_buf_size) 00085 { 00086 DeviceKey &devkey = DeviceKey::get_instance(); 00087 char *salt = reinterpret_cast<char *>(salt_buf); 00088 uint8_t encrypt_key[derived_key_size]; 00089 strcpy(salt, enc_prefix); 00090 int pos = strlen(enc_prefix); 00091 strncpy(salt + pos, key, salt_buf_size - pos - 1); 00092 salt_buf[salt_buf_size - 1] = 0; 00093 int os_ret = devkey.generate_derived_key(salt_buf, strlen(salt), encrypt_key, DEVICE_KEY_16BYTE); 00094 if (os_ret) { 00095 return os_ret; 00096 } 00097 00098 mbedtls_aes_init(&enc_aes_ctx); 00099 mbedtls_aes_setkey_enc(&enc_aes_ctx, encrypt_key, enc_block_size * 8); 00100 00101 memcpy(ctr_buf, iv, iv_size); 00102 memset(ctr_buf + iv_size, 0, iv_size); 00103 00104 return 0; 00105 } 00106 00107 int encrypt_decrypt_data(mbedtls_aes_context &enc_aes_ctx, const uint8_t *in_buf, 00108 uint8_t *out_buf, uint32_t chunk_size, uint8_t *ctr_buf, size_t &aes_offs) 00109 { 00110 uint8_t stream_block[enc_block_size] = { 0 }; 00111 00112 return mbedtls_aes_crypt_ctr(&enc_aes_ctx, chunk_size, &aes_offs, ctr_buf, 00113 stream_block, in_buf, out_buf); 00114 } 00115 00116 int cmac_calc_start(mbedtls_cipher_context_t &auth_ctx, const char *key, uint8_t *salt_buf, int salt_buf_size) 00117 { 00118 DeviceKey &devkey = DeviceKey::get_instance(); 00119 char *salt = reinterpret_cast<char *>(salt_buf); 00120 uint8_t auth_key[derived_key_size]; 00121 strcpy(salt, auth_prefix); 00122 int pos = strlen(auth_prefix); 00123 strncpy(salt + pos, key, salt_buf_size - pos - 1); 00124 salt_buf[salt_buf_size - 1] = 0; 00125 int os_ret = devkey.generate_derived_key(salt_buf, strlen(salt), auth_key, DEVICE_KEY_16BYTE); 00126 if (os_ret) { 00127 return os_ret; 00128 } 00129 00130 const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); 00131 00132 mbedtls_cipher_init(&auth_ctx); 00133 00134 if ((os_ret = mbedtls_cipher_setup(&auth_ctx, cipher_info)) != 0) { 00135 return os_ret; 00136 } 00137 00138 os_ret = mbedtls_cipher_cmac_starts(&auth_ctx, auth_key, cmac_size * 8); 00139 if (os_ret != 0) { 00140 return os_ret; 00141 } 00142 00143 return 0; 00144 } 00145 00146 int cmac_calc_data(mbedtls_cipher_context_t &auth_ctx, const void *input, size_t ilen) 00147 { 00148 int os_ret; 00149 00150 os_ret = mbedtls_cipher_cmac_update(&auth_ctx, static_cast<const uint8_t *>(input), ilen); 00151 00152 return os_ret; 00153 } 00154 00155 int cmac_calc_finish(mbedtls_cipher_context_t &auth_ctx, uint8_t *output) 00156 { 00157 int os_ret; 00158 00159 os_ret = mbedtls_cipher_cmac_finish(&auth_ctx, output); 00160 00161 return os_ret; 00162 } 00163 00164 00165 00166 // Class member functions 00167 00168 SecureStore::SecureStore(KVStore *underlying_kv, KVStore *rbp_kv) : 00169 _is_initialized(false), _underlying_kv(underlying_kv), _rbp_kv(rbp_kv), _entropy(0), 00170 _ih(0), _scratch_buf(0) 00171 { 00172 } 00173 00174 SecureStore::~SecureStore() 00175 { 00176 deinit(); 00177 } 00178 00179 00180 int SecureStore::set_start(set_handle_t *handle, const char *key, size_t final_data_size, 00181 uint32_t create_flags) 00182 { 00183 int ret, os_ret; 00184 info_t info; 00185 bool enc_started = false, auth_started = false; 00186 00187 if (!_is_initialized) { 00188 return MBED_ERROR_NOT_READY; 00189 } 00190 00191 if (!is_valid_key(key)) { 00192 return MBED_ERROR_INVALID_ARGUMENT; 00193 } 00194 00195 _mutex.lock(); 00196 *handle = reinterpret_cast<set_handle_t>(_ih); 00197 00198 // Validate internal RBP data 00199 if (_rbp_kv) { 00200 ret = _rbp_kv->get_info(key, &info); 00201 if (ret == MBED_SUCCESS) { 00202 if (info.flags & WRITE_ONCE_FLAG) { 00203 // Trying to re-write a key that is write protected 00204 ret = MBED_ERROR_WRITE_PROTECTED; 00205 goto fail; 00206 } 00207 if (!(create_flags & REQUIRE_REPLAY_PROTECTION_FLAG)) { 00208 // Trying to re-write a key that that has REPLAY_PROTECTION 00209 // with a new key that has this flag not set. 00210 ret = MBED_ERROR_INVALID_ARGUMENT; 00211 goto fail; 00212 } 00213 } else if (ret != MBED_ERROR_ITEM_NOT_FOUND) { 00214 ret = MBED_ERROR_READ_FAILED; 00215 goto fail; 00216 } 00217 } else { 00218 // Only trust external flags, if internal RBP is not in use 00219 ret = _underlying_kv->get(key, &_ih->metadata, sizeof(record_metadata_t)); 00220 if (ret == MBED_SUCCESS) { 00221 // Must not remove RP flag, even though internal RBP KV is not in use. 00222 if (!(create_flags & REQUIRE_REPLAY_PROTECTION_FLAG) && (_ih->metadata.create_flags & REQUIRE_REPLAY_PROTECTION_FLAG)) { 00223 ret = MBED_ERROR_INVALID_ARGUMENT; 00224 goto fail; 00225 } 00226 // Existing key is write protected 00227 if (_ih->metadata.create_flags & WRITE_ONCE_FLAG) { 00228 ret = MBED_ERROR_WRITE_PROTECTED; 00229 goto fail; 00230 } 00231 } 00232 } 00233 00234 // Fill metadata 00235 _ih->metadata.create_flags = create_flags; 00236 _ih->metadata.data_size = final_data_size; 00237 _ih->metadata.metadata_size = sizeof(record_metadata_t); 00238 _ih->metadata.revision = securestore_revision; 00239 00240 if (create_flags & REQUIRE_CONFIDENTIALITY_FLAG) { 00241 // generate a new random iv 00242 os_ret = mbedtls_entropy_func(_entropy, _ih->metadata.iv, iv_size); 00243 if (os_ret) { 00244 ret = MBED_ERROR_FAILED_OPERATION; 00245 goto fail; 00246 } 00247 os_ret = encrypt_decrypt_start(_ih->enc_ctx, _ih->metadata.iv, key, _ih->ctr_buf, _scratch_buf, 00248 scratch_buf_size); 00249 if (os_ret) { 00250 ret = MBED_ERROR_FAILED_OPERATION; 00251 goto fail; 00252 } 00253 enc_started = true; 00254 } else { 00255 memset(_ih->metadata.iv, 0, iv_size); 00256 } 00257 00258 os_ret = cmac_calc_start(_ih->auth_ctx, key, _scratch_buf, scratch_buf_size); 00259 if (os_ret) { 00260 ret = MBED_ERROR_FAILED_OPERATION; 00261 goto fail; 00262 } 00263 auth_started = true; 00264 // Although name is not part of the data, we calculate CMAC on it as well 00265 os_ret = cmac_calc_data(_ih->auth_ctx, key, strlen(key)); 00266 if (os_ret) { 00267 ret = MBED_ERROR_FAILED_OPERATION; 00268 goto fail; 00269 } 00270 os_ret = cmac_calc_data(_ih->auth_ctx, &_ih->metadata, sizeof(record_metadata_t)); 00271 if (os_ret) { 00272 ret = MBED_ERROR_FAILED_OPERATION; 00273 goto fail; 00274 } 00275 00276 _ih->offset_in_data = 0; 00277 _ih->key = 0; 00278 00279 // Should strip security flags from underlying storage 00280 ret = _underlying_kv->set_start(&_ih->underlying_handle, key, 00281 sizeof(record_metadata_t) + final_data_size + cmac_size, 00282 create_flags & ~security_flags); 00283 if (ret) { 00284 goto fail; 00285 } 00286 00287 ret = _underlying_kv->set_add_data(_ih->underlying_handle, &_ih->metadata, 00288 sizeof(record_metadata_t)); 00289 if (ret) { 00290 goto fail; 00291 } 00292 00293 if (create_flags & (REQUIRE_REPLAY_PROTECTION_FLAG | WRITE_ONCE_FLAG)) { 00294 _ih->key = new char[strlen(key) + 1]; 00295 strcpy(_ih->key, key); 00296 } 00297 00298 goto end; 00299 00300 fail: 00301 if (enc_started) { 00302 mbedtls_aes_free(&_ih->enc_ctx); 00303 } 00304 00305 if (auth_started) { 00306 mbedtls_cipher_free(&_ih->auth_ctx); 00307 } 00308 00309 // mark handle as invalid by clearing metadata size field in header 00310 _ih->metadata.metadata_size = 0; 00311 _mutex.unlock(); 00312 00313 end: 00314 return ret; 00315 } 00316 00317 int SecureStore::set_add_data(set_handle_t handle, const void *value_data, size_t data_size) 00318 { 00319 size_t aes_offs = 0; 00320 int os_ret, ret = MBED_SUCCESS; 00321 const uint8_t *src_ptr; 00322 00323 if (reinterpret_cast<inc_set_handle_t *>(handle) != _ih) { 00324 return MBED_ERROR_INVALID_ARGUMENT; 00325 } 00326 00327 if (!value_data && data_size) { 00328 return MBED_ERROR_INVALID_ARGUMENT; 00329 } 00330 00331 if (!_ih->metadata.metadata_size) { 00332 return MBED_ERROR_INVALID_ARGUMENT; 00333 } 00334 00335 if (_ih->offset_in_data + data_size > _ih->metadata.data_size) { 00336 ret = MBED_ERROR_INVALID_SIZE; 00337 goto end; 00338 } 00339 00340 src_ptr = static_cast<const uint8_t *>(value_data); 00341 while (data_size) { 00342 uint32_t chunk_size; 00343 const uint8_t *dst_ptr; 00344 if (_ih->metadata.create_flags & REQUIRE_CONFIDENTIALITY_FLAG) { 00345 // In encrypt mode we don't want to allocate a buffer in the size given by the user - 00346 // Encrypt the data chunk by chunk 00347 chunk_size = std::min((uint32_t) data_size, scratch_buf_size); 00348 dst_ptr = _scratch_buf; 00349 os_ret = encrypt_decrypt_data(_ih->enc_ctx, src_ptr, _scratch_buf, 00350 chunk_size, _ih->ctr_buf, aes_offs); 00351 if (os_ret) { 00352 ret = MBED_ERROR_FAILED_OPERATION; 00353 goto fail; 00354 } 00355 } else { 00356 chunk_size = data_size; 00357 dst_ptr = static_cast <const uint8_t *>(value_data); 00358 } 00359 00360 os_ret = cmac_calc_data(_ih->auth_ctx, dst_ptr, chunk_size); 00361 if (os_ret) { 00362 ret = MBED_ERROR_FAILED_OPERATION; 00363 goto fail; 00364 } 00365 00366 ret = _underlying_kv->set_add_data(_ih->underlying_handle, dst_ptr, chunk_size); 00367 if (ret) { 00368 goto fail; 00369 } 00370 data_size -= chunk_size; 00371 src_ptr += chunk_size; 00372 _ih->offset_in_data += chunk_size; 00373 } 00374 00375 goto end; 00376 00377 fail: 00378 if (_ih->key) { 00379 delete[] _ih->key; 00380 } 00381 if (_ih->metadata.create_flags & REQUIRE_CONFIDENTIALITY_FLAG) { 00382 mbedtls_aes_free(&_ih->enc_ctx); 00383 } 00384 00385 mbedtls_cipher_free(&_ih->auth_ctx); 00386 00387 // mark handle as invalid by clearing metadata size field in header 00388 _ih->metadata.metadata_size = 0; 00389 _mutex.unlock(); 00390 00391 end: 00392 return ret; 00393 } 00394 00395 int SecureStore::set_finalize(set_handle_t handle) 00396 { 00397 int os_ret, ret = MBED_SUCCESS; 00398 uint8_t cmac[cmac_size] = {0}; 00399 00400 if (reinterpret_cast<inc_set_handle_t *>(handle) != _ih) { 00401 return MBED_ERROR_INVALID_ARGUMENT; 00402 } 00403 00404 if (!_ih->metadata.metadata_size) { 00405 return MBED_ERROR_INVALID_ARGUMENT; 00406 } 00407 00408 if (_ih->offset_in_data != _ih->metadata.data_size) { 00409 ret = MBED_ERROR_INVALID_SIZE; 00410 goto end; 00411 } 00412 00413 os_ret = cmac_calc_finish(_ih->auth_ctx, cmac); 00414 if (os_ret) { 00415 ret = MBED_ERROR_FAILED_OPERATION; 00416 goto end; 00417 } 00418 00419 ret = _underlying_kv->set_add_data(_ih->underlying_handle, cmac, cmac_size); 00420 if (ret) { 00421 goto end; 00422 } 00423 00424 ret = _underlying_kv->set_finalize(_ih->underlying_handle); 00425 if (ret) { 00426 goto end; 00427 } 00428 00429 if (_rbp_kv && (_ih->metadata.create_flags & (REQUIRE_REPLAY_PROTECTION_FLAG | WRITE_ONCE_FLAG))) { 00430 // In rollback protect case, we need to store CMAC in RBP store. 00431 // If it's also write once case, set write once flag in the RBP key as well. 00432 // Use RBP storage also in write once case only - in order to prevent attacks removing 00433 // a written once value from underlying KV. 00434 ret = _rbp_kv->set(_ih->key, cmac, cmac_size, _ih->metadata.create_flags & WRITE_ONCE_FLAG); 00435 delete[] _ih->key; 00436 if (ret) { 00437 goto end; 00438 } 00439 } 00440 00441 end: 00442 // mark handle as invalid by clearing metadata size field in header 00443 _ih->metadata.metadata_size = 0; 00444 if (_ih->metadata.create_flags & REQUIRE_CONFIDENTIALITY_FLAG) { 00445 mbedtls_aes_free(&_ih->enc_ctx); 00446 } 00447 00448 mbedtls_cipher_free(&_ih->auth_ctx); 00449 00450 _mutex.unlock(); 00451 return ret; 00452 } 00453 00454 int SecureStore::set(const char *key, const void *buffer, size_t size, uint32_t create_flags) 00455 { 00456 int ret; 00457 set_handle_t handle; 00458 00459 // Don't wait till we get to set_add_data to catch this 00460 if (!buffer && size) { 00461 return MBED_ERROR_INVALID_ARGUMENT; 00462 } 00463 00464 ret = set_start(&handle, key, size, create_flags); 00465 if (ret) { 00466 return ret; 00467 } 00468 00469 ret = set_add_data(handle, buffer, size); 00470 if (ret) { 00471 return ret; 00472 } 00473 00474 ret = set_finalize(handle); 00475 return ret; 00476 } 00477 00478 int SecureStore::remove(const char *key) 00479 { 00480 info_t info; 00481 _mutex.lock(); 00482 00483 int ret = do_get(key, 0, 0, 0, 0, &info); 00484 // Allow deleting key if read error is of our own errors 00485 if ((ret != MBED_SUCCESS) && (ret != MBED_ERROR_AUTHENTICATION_FAILED) && 00486 (ret != MBED_ERROR_RBP_AUTHENTICATION_FAILED)) { 00487 goto end; 00488 } 00489 00490 if (ret == 0 && info.flags & WRITE_ONCE_FLAG) { 00491 ret = MBED_ERROR_WRITE_PROTECTED; 00492 goto end; 00493 } 00494 00495 ret = _underlying_kv->remove(key); 00496 if (ret) { 00497 goto end; 00498 } 00499 00500 if (_rbp_kv && (info.flags & REQUIRE_REPLAY_PROTECTION_FLAG)) { 00501 ret = _rbp_kv->remove(key); 00502 if ((ret != MBED_SUCCESS) && (ret != MBED_ERROR_ITEM_NOT_FOUND)) { 00503 goto end; 00504 } 00505 } 00506 00507 ret = MBED_SUCCESS; 00508 00509 end: 00510 _mutex.unlock(); 00511 return ret; 00512 } 00513 00514 int SecureStore::do_get(const char *key, void *buffer, size_t buffer_size, size_t *actual_size, 00515 size_t offset, info_t *info) 00516 { 00517 int os_ret, ret; 00518 bool rbp_key_exists = false; 00519 uint8_t rbp_cmac[cmac_size]; 00520 size_t aes_offs = 0; 00521 uint32_t data_size; 00522 uint32_t actual_data_size; 00523 uint32_t current_offset; 00524 uint32_t chunk_size; 00525 uint32_t enc_lead_size; 00526 uint8_t *dest_buf; 00527 bool enc_started = false, auth_started = false; 00528 uint32_t create_flags; 00529 size_t read_len; 00530 info_t rbp_info; 00531 00532 if (!is_valid_key(key)) { 00533 return MBED_ERROR_INVALID_ARGUMENT; 00534 } 00535 00536 if (_rbp_kv) { 00537 ret = _rbp_kv->get_info(key, &rbp_info); 00538 if (ret == MBED_SUCCESS) { 00539 rbp_key_exists = true; 00540 ret = _rbp_kv->get(key, rbp_cmac, cmac_size, &read_len); 00541 if (ret) { 00542 goto end; 00543 } 00544 if ((read_len != cmac_size) || (rbp_info.size != cmac_size)) { 00545 ret = MBED_ERROR_RBP_AUTHENTICATION_FAILED; 00546 } 00547 } else if (ret != MBED_ERROR_ITEM_NOT_FOUND) { 00548 goto end; 00549 } 00550 } 00551 00552 ret = _underlying_kv->get(key, &_ih->metadata, sizeof(record_metadata_t), &read_len); 00553 if (ret) { 00554 // In case we have the key in the RBP KV, then even if the key wasn't found in 00555 // the underlying KV, we may have been exposed to an attack. Return an RBP authentication error. 00556 if (rbp_key_exists) { 00557 ret = MBED_ERROR_RBP_AUTHENTICATION_FAILED; 00558 } 00559 goto end; 00560 } 00561 00562 // Validate header size 00563 if ((read_len != sizeof(record_metadata_t)) || (_ih->metadata.metadata_size != sizeof(record_metadata_t))) { 00564 ret = MBED_ERROR_RBP_AUTHENTICATION_FAILED; 00565 goto end; 00566 } 00567 00568 create_flags = _ih->metadata.create_flags; 00569 if (!_rbp_kv) { 00570 create_flags &= ~REQUIRE_REPLAY_PROTECTION_FLAG; 00571 } 00572 00573 // Another potential attack case - key hasn't got the RP flag set, but exists in the RBP KV 00574 if (rbp_key_exists && !(create_flags & (REQUIRE_REPLAY_PROTECTION_FLAG | WRITE_ONCE_FLAG))) { 00575 ret = MBED_ERROR_RBP_AUTHENTICATION_FAILED; 00576 goto end; 00577 } 00578 00579 os_ret = cmac_calc_start(_ih->auth_ctx, key, _scratch_buf, scratch_buf_size); 00580 if (os_ret) { 00581 ret = MBED_ERROR_FAILED_OPERATION; 00582 goto end; 00583 } 00584 auth_started = true; 00585 00586 // Although name is not part of the data, we calculate CMAC on it as well 00587 os_ret = cmac_calc_data(_ih->auth_ctx, key, strlen(key)); 00588 if (os_ret) { 00589 ret = MBED_ERROR_FAILED_OPERATION; 00590 goto end; 00591 } 00592 os_ret = cmac_calc_data(_ih->auth_ctx, &_ih->metadata, sizeof(record_metadata_t)); 00593 if (os_ret) { 00594 ret = MBED_ERROR_FAILED_OPERATION; 00595 goto end; 00596 } 00597 00598 if (create_flags & REQUIRE_CONFIDENTIALITY_FLAG) { 00599 os_ret = encrypt_decrypt_start(_ih->enc_ctx, _ih->metadata.iv, key, _ih->ctr_buf, _scratch_buf, 00600 scratch_buf_size); 00601 if (os_ret) { 00602 ret = MBED_ERROR_FAILED_OPERATION; 00603 goto end; 00604 } 00605 enc_started = true; 00606 } 00607 00608 data_size = _ih->metadata.data_size; 00609 actual_data_size = std::min((uint32_t) buffer_size, data_size - offset); 00610 current_offset = 0; 00611 enc_lead_size = 0; 00612 00613 while (data_size) { 00614 // Make sure we read to the user buffer only between offset and offset + actual_data_size 00615 if ((current_offset >= offset) && (current_offset < offset + actual_data_size)) { 00616 dest_buf = (static_cast <uint8_t *>(buffer)) + enc_lead_size; 00617 chunk_size = actual_data_size - enc_lead_size; 00618 enc_lead_size = 0; 00619 } else { 00620 dest_buf = _scratch_buf; 00621 if (current_offset < offset) { 00622 chunk_size = std::min(scratch_buf_size, offset - current_offset); 00623 // A special case: encrypted user data starts at a middle of an encryption block. 00624 // In this case, we need to read entire block into our scratch buffer, and copy 00625 // the encrypted lead size to the user buffer start 00626 if ((create_flags & REQUIRE_CONFIDENTIALITY_FLAG) && 00627 (chunk_size % enc_block_size)) { 00628 enc_lead_size = std::min(enc_block_size - chunk_size % enc_block_size, actual_data_size); 00629 chunk_size += enc_lead_size; 00630 } 00631 } else { 00632 chunk_size = std::min(scratch_buf_size, data_size); 00633 enc_lead_size = 0; 00634 } 00635 } 00636 00637 ret = _underlying_kv->get(key, dest_buf, chunk_size, 0, 00638 _ih->metadata.metadata_size + current_offset); 00639 if (ret != MBED_SUCCESS) { 00640 goto end; 00641 } 00642 00643 os_ret = cmac_calc_data(_ih->auth_ctx, dest_buf, chunk_size); 00644 if (os_ret) { 00645 ret = MBED_ERROR_FAILED_OPERATION; 00646 goto end; 00647 } 00648 00649 if (create_flags & REQUIRE_CONFIDENTIALITY_FLAG) { 00650 // Decrypt data in place 00651 os_ret = encrypt_decrypt_data(_ih->enc_ctx, dest_buf, dest_buf, chunk_size, _ih->ctr_buf, 00652 aes_offs); 00653 if (os_ret) { 00654 ret = MBED_ERROR_FAILED_OPERATION; 00655 goto end; 00656 } 00657 00658 if (enc_lead_size) { 00659 // Now copy decrypted lead size to user buffer start 00660 memcpy(buffer, dest_buf + chunk_size - enc_lead_size, enc_lead_size); 00661 } 00662 } 00663 00664 current_offset += chunk_size; 00665 data_size -= chunk_size; 00666 } 00667 00668 if (actual_size) { 00669 *actual_size = actual_data_size; 00670 } 00671 00672 uint8_t calc_cmac[cmac_size], read_cmac[cmac_size]; 00673 os_ret = cmac_calc_finish(_ih->auth_ctx, calc_cmac); 00674 if (os_ret) { 00675 ret = MBED_ERROR_FAILED_OPERATION; 00676 goto end; 00677 } 00678 00679 // Check with record CMAC 00680 ret = _underlying_kv->get(key, read_cmac, cmac_size, 0, 00681 _ih->metadata.metadata_size + _ih->metadata.data_size); 00682 if (ret) { 00683 goto end; 00684 } 00685 if (memcmp(calc_cmac, read_cmac, cmac_size) != 0) { 00686 ret = MBED_ERROR_AUTHENTICATION_FAILED; 00687 goto end; 00688 } 00689 00690 // If rollback protect, check also CMAC stored in RBP store 00691 if (_rbp_kv && (create_flags & (REQUIRE_REPLAY_PROTECTION_FLAG | WRITE_ONCE_FLAG))) { 00692 if (!rbp_key_exists) { 00693 ret = MBED_ERROR_RBP_AUTHENTICATION_FAILED; 00694 goto end; 00695 } 00696 if (memcmp(calc_cmac, rbp_cmac, cmac_size) != 0) { 00697 ret = MBED_ERROR_RBP_AUTHENTICATION_FAILED; 00698 goto end; 00699 } 00700 } 00701 00702 if (info) { 00703 info->flags = _ih->metadata.create_flags; 00704 info->size = _ih->metadata.data_size; 00705 } 00706 00707 end: 00708 _ih->metadata.metadata_size = 0; 00709 00710 if (enc_started) { 00711 mbedtls_aes_free(&_ih->enc_ctx); 00712 } 00713 00714 if (auth_started) { 00715 mbedtls_cipher_free(&_ih->auth_ctx); 00716 } 00717 00718 return ret; 00719 } 00720 00721 int SecureStore::get(const char *key, void *buffer, size_t buffer_size, size_t *actual_size, 00722 size_t offset) 00723 { 00724 _mutex.lock(); 00725 int ret = do_get(key, buffer, buffer_size, actual_size, offset); 00726 _mutex.unlock(); 00727 00728 return ret; 00729 } 00730 00731 int SecureStore::get_info(const char *key, info_t *info) 00732 { 00733 _mutex.lock(); 00734 int ret = do_get(key, 0, 0, 0, 0, info); 00735 _mutex.unlock(); 00736 00737 return ret; 00738 } 00739 00740 00741 int SecureStore::init() 00742 { 00743 int ret = MBED_SUCCESS; 00744 00745 MBED_ASSERT(!(scratch_buf_size % enc_block_size)); 00746 if (scratch_buf_size % enc_block_size) { 00747 return MBED_SYSTEM_ERROR_BASE; 00748 } 00749 00750 _mutex.lock(); 00751 #if defined(MBEDTLS_PLATFORM_C) 00752 ret = mbedtls_platform_setup(NULL); 00753 if (ret) { 00754 goto fail; 00755 } 00756 #endif /* MBEDTLS_PLATFORM_C */ 00757 00758 _entropy = new mbedtls_entropy_context; 00759 mbedtls_entropy_init(_entropy); 00760 00761 _scratch_buf = new uint8_t[scratch_buf_size]; 00762 _ih = new inc_set_handle_t; 00763 00764 ret = _underlying_kv->init(); 00765 if (ret) { 00766 goto fail; 00767 } 00768 00769 if (_rbp_kv) { 00770 ret = _rbp_kv->init(); 00771 if (ret) { 00772 goto fail; 00773 } 00774 } 00775 00776 _is_initialized = true; 00777 00778 fail: 00779 _mutex.unlock(); 00780 return ret; 00781 } 00782 00783 int SecureStore::deinit() 00784 { 00785 _mutex.lock(); 00786 int ret; 00787 if (_is_initialized) { 00788 if (_entropy) { 00789 mbedtls_entropy_free(_entropy); 00790 delete _entropy; 00791 delete _ih; 00792 delete _scratch_buf; 00793 _entropy = nullptr; 00794 } 00795 ret = _underlying_kv->deinit(); 00796 if (ret) { 00797 goto END; 00798 } 00799 if (_rbp_kv) { 00800 ret = _rbp_kv->deinit(); 00801 if (ret) { 00802 goto END; 00803 } 00804 } 00805 } 00806 00807 _is_initialized = false; 00808 #if defined(MBEDTLS_PLATFORM_C) 00809 mbedtls_platform_teardown(NULL); 00810 #endif /* MBEDTLS_PLATFORM_C */ 00811 ret = MBED_SUCCESS; 00812 END: 00813 _mutex.unlock(); 00814 00815 return ret; 00816 } 00817 00818 00819 int SecureStore::reset() 00820 { 00821 int ret; 00822 00823 if (!_is_initialized) { 00824 return MBED_ERROR_NOT_READY; 00825 } 00826 00827 _mutex.lock(); 00828 ret = _underlying_kv->reset(); 00829 if (ret) { 00830 goto end; 00831 } 00832 00833 if (_rbp_kv) { 00834 ret = _rbp_kv->reset(); 00835 if (ret) { 00836 goto end; 00837 } 00838 } 00839 00840 end: 00841 _mutex.unlock(); 00842 return ret; 00843 } 00844 00845 int SecureStore::iterator_open(iterator_t *it, const char *prefix) 00846 { 00847 key_iterator_handle_t *handle; 00848 00849 if (!_is_initialized) { 00850 return MBED_ERROR_NOT_READY; 00851 } 00852 00853 if (!it) { 00854 return MBED_ERROR_INVALID_ARGUMENT; 00855 } 00856 00857 handle = new key_iterator_handle_t; 00858 *it = reinterpret_cast<iterator_t>(handle); 00859 00860 return _underlying_kv->iterator_open(&handle->underlying_it, prefix); 00861 } 00862 00863 int SecureStore::iterator_next(iterator_t it, char *key, size_t key_size) 00864 { 00865 key_iterator_handle_t *handle; 00866 00867 if (!_is_initialized) { 00868 return MBED_ERROR_NOT_READY; 00869 } 00870 00871 handle = reinterpret_cast<key_iterator_handle_t *>(it); 00872 00873 return _underlying_kv->iterator_next(handle->underlying_it, key, key_size); 00874 } 00875 00876 int SecureStore::iterator_close(iterator_t it) 00877 { 00878 key_iterator_handle_t *handle; 00879 int ret; 00880 00881 if (!_is_initialized) { 00882 return MBED_ERROR_NOT_READY; 00883 } 00884 00885 handle = reinterpret_cast<key_iterator_handle_t *>(it); 00886 00887 ret = _underlying_kv->iterator_close(handle->underlying_it); 00888 00889 delete handle; 00890 00891 return ret; 00892 } 00893 00894 #endif
Generated on Tue Jul 12 2022 13:54:49 by
