diff --git a/features/storage/TESTS/kvstore/direct_access_devicekey_test/main.cpp b/features/storage/TESTS/kvstore/direct_access_devicekey_test/main.cpp new file mode 100644 index 0000000000..781a08fc3f --- /dev/null +++ b/features/storage/TESTS/kvstore/direct_access_devicekey_test/main.cpp @@ -0,0 +1,336 @@ +/* Copyright (c) 2018 Arm Limited +* +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef COMPONENT_FLASHIAP +#error [NOT_SUPPORTED] Target must have internal FlashIAP for this test +#endif + +#include "mbed.h" +#include +#include +#include "DeviceKey.h" +#include "KVStore.h" +#include "KVMap.h" +#include "kv_config.h" +#include "TDBStore.h" +#include "FlashIAP.h" +#include "FlashIAPBlockDevice.h" +#include "DirectAccessDevicekey.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include + +using namespace utest::v1; +using namespace mbed; + +#define TEST_DEVICEKEY_LENGTH 32 + +static inline uint32_t align_up(uint64_t val, uint64_t size) +{ + return (((val - 1) / size) + 1) * size; +} + +static inline uint32_t align_down(uint64_t val, uint64_t size) +{ + return (((val) / size)) * size; +} + +int get_virtual_TDBStore_position(uint32_t conf_start_address, uint32_t conf_size, bool is_conf_tdb_internal, + uint32_t *tdb_start_address, uint32_t *tdb_end_address) +{ + uint32_t bd_final_size = conf_size;; + uint32_t flash_end_address; + uint32_t flash_start_address; + uint32_t aligned_start_address; + FlashIAP flash; + + int ret = flash.init(); + if (ret != 0) { + return -1; + } + + uint32_t flash_first_writable_sector_address = (uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR, + flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR))); + + //Get flash parameters before starting + flash_start_address = flash.get_flash_start(); + flash_end_address = flash_start_address + flash.get_flash_size(); + + bool request_default = false; + if (conf_start_address == 0 && conf_size == 0) { + request_default = true; + } + + if (!request_default) { + if (conf_start_address == 0) { + conf_start_address = flash_end_address - conf_size; + } + aligned_start_address = align_down(conf_start_address, flash.get_sector_size(conf_start_address)); + if (conf_size == 0) { + bd_final_size = (flash_end_address - aligned_start_address); + } + + if ((conf_size == 0) || (conf_start_address == 0)) { + if (aligned_start_address < flash_first_writable_sector_address) { + flash.deinit(); + return -2; + } + } + } else { + if (is_conf_tdb_internal == true) { + aligned_start_address = flash_first_writable_sector_address; + bd_size_t spare_size_for_app = 0; + bd_addr_t curr_addr = aligned_start_address; + int spare_sectors_for_app = 2; + int min_sectors_for_storage = 2; + for (int i = 0; i < spare_sectors_for_app + min_sectors_for_storage - 1; i++) { + bd_size_t sector_size = flash.get_sector_size(curr_addr); + curr_addr += sector_size; + if (curr_addr >= flash_end_address) { + spare_size_for_app = 0; + break; + } + + if (i < spare_sectors_for_app) { + spare_size_for_app += sector_size; + } + } + aligned_start_address += spare_size_for_app; + bd_final_size = (flash_end_address - aligned_start_address); + } else { + aligned_start_address = flash_end_address - (flash.get_sector_size(flash_end_address - 1) * 2); + if (aligned_start_address < flash_first_writable_sector_address) { + flash.deinit(); + return -2; + } + bd_final_size = (flash_end_address - aligned_start_address); + } + } + + (*tdb_start_address) = aligned_start_address; + (*tdb_end_address) = aligned_start_address + bd_final_size; + + flash.deinit(); + + return 0; +} + + +void test_direct_access_to_devicekey_tdb_flashiap_remainder() +{ + utest_printf("Test Direct Access To DeviceKey Test Entire FlashIAP Remainder\n"); + + uint32_t flash_bd_start_address; + uint32_t flash_bd_end_address; + + int err = get_virtual_TDBStore_position(0, 0, true, &flash_bd_start_address, &flash_bd_end_address); + TEST_SKIP_UNLESS_MESSAGE(err != -2, "Test skipped. Not enough available space on Internal FlashIAP"); + TEST_ASSERT_EQUAL(0, err); + uint32_t flash_bd_size = flash_bd_end_address - flash_bd_start_address; + + FlashIAPBlockDevice *flash_bd = new FlashIAPBlockDevice((bd_addr_t)flash_bd_start_address, (bd_size_t)flash_bd_size); + TEST_ASSERT_NOT_EQUAL(NULL, flash_bd); + + TDBStore *tdb = new TDBStore(flash_bd); + TEST_ASSERT_NOT_EQUAL(NULL, tdb); + // Start by Init and Reset to TDBStore + err = tdb->init(); + TEST_ASSERT_EQUAL_ERROR_CODE(0, err); + + err = tdb->reset(); + TEST_ASSERT_EQUAL_ERROR_CODE(0, err); + + // Assign a dummy DeviceKey, and set via tdb + uint8_t device_key_in[TEST_DEVICEKEY_LENGTH] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; + err = tdb->reserved_data_set(device_key_in, TEST_DEVICEKEY_LENGTH); + TEST_ASSERT_EQUAL_ERROR_CODE(0, err); + + + err = tdb->deinit(); + TEST_ASSERT_EQUAL(0, err); + + delete tdb; + delete flash_bd; + + // Now use Direct Access To DeviceKey to retrieve it + uint8_t device_key_out[TEST_DEVICEKEY_LENGTH] = {0}; + size_t actual_data_size = 0; + + err = direct_access_to_devicekey((uint32_t)flash_bd_start_address, (uint32_t)flash_bd_end_address, device_key_out, + TEST_DEVICEKEY_LENGTH, + &actual_data_size); + TEST_ASSERT_EQUAL_ERROR_CODE(0, err); + + // Assert DeviceKey value and length + TEST_ASSERT_EQUAL(actual_data_size, TEST_DEVICEKEY_LENGTH); + for (int i_ind = 0; i_ind < TEST_DEVICEKEY_LENGTH; i_ind++) { + TEST_ASSERT_EQUAL(device_key_in[i_ind], device_key_out[i_ind]); + } + +} + +void test_direct_access_to_devicekey_tdb_last_two_sectors() +{ + utest_printf("Test Direct Access To DeviceKey Test Entire FlashIAP Remainder\n"); + + uint32_t flash_bd_start_address; + uint32_t flash_bd_end_address; + + int err = get_virtual_TDBStore_position(0, 0, false, &flash_bd_start_address, &flash_bd_end_address); + TEST_SKIP_UNLESS_MESSAGE(err != -2, "Test skipped. Not enough available space on Internal FlashIAP"); + TEST_ASSERT_EQUAL(0, err); + + uint32_t flash_bd_size = flash_bd_end_address - flash_bd_start_address; + + FlashIAPBlockDevice *flash_bd = new FlashIAPBlockDevice((bd_addr_t)flash_bd_start_address, (bd_size_t)flash_bd_size); + + TDBStore *tdb = new TDBStore(flash_bd); + // Start by Init and Reset to TDBStore + err = tdb->init(); + TEST_ASSERT_EQUAL_ERROR_CODE(0, err); + + err = tdb->reset(); + TEST_ASSERT_EQUAL_ERROR_CODE(0, err); + + // Assign a dummy DeviceKey, and set via tdb + uint8_t device_key_in[TEST_DEVICEKEY_LENGTH] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; + err = tdb->reserved_data_set(device_key_in, TEST_DEVICEKEY_LENGTH); + TEST_ASSERT_EQUAL_ERROR_CODE(0, err); + + err = tdb->deinit(); + TEST_ASSERT_EQUAL(0, err); + + delete tdb; + delete flash_bd; + + // Now use Direct Access To DeviceKey to retrieve it + uint8_t device_key_out[TEST_DEVICEKEY_LENGTH] = {0}; + size_t actual_data_size = 0; + + err = direct_access_to_devicekey((uint32_t)flash_bd_start_address, (uint32_t)flash_bd_end_address, device_key_out, + TEST_DEVICEKEY_LENGTH, + &actual_data_size); + TEST_ASSERT_EQUAL_ERROR_CODE(0, err); + + // Assert DeviceKey value and length + TEST_ASSERT_EQUAL(TEST_DEVICEKEY_LENGTH, actual_data_size); + for (int i_ind = 0; i_ind < TEST_DEVICEKEY_LENGTH; i_ind++) { + TEST_ASSERT_EQUAL(device_key_in[i_ind], device_key_out[i_ind]); + } + +} +#define STR_EXPAND(tok) #tok +#define STR(tok) STR_EXPAND(tok) + +void test_direct_access_to_device_inject_root() +{ + kv_init_storage_config(); + DeviceKey &devkey = DeviceKey::get_instance(); + uint32_t rkey[DEVICE_KEY_16BYTE / sizeof(uint32_t)]; + uint32_t key[DEVICE_KEY_16BYTE / sizeof(uint32_t)]; + KVMap &kv_map = KVMap::get_instance(); + KVStore *inner_store = kv_map.get_internal_kv_instance(NULL); + TEST_ASSERT_NOT_EQUAL(NULL, inner_store); + + BlockDevice *flash_bd = kv_map.get_internal_blockdevice_instance(""); + TEST_ASSERT_NOT_EQUAL(NULL, flash_bd); + + int ret = inner_store->reset(); + TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret); + + memcpy(key, "abcdefghabcdefgh", sizeof(key)); + ret = devkey.device_inject_root_of_trust(key, DEVICE_KEY_16BYTE); + TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret); + + // Now use Direct Access To DeviceKey to retrieve it */ + uint32_t internal_start_address; + uint32_t internal_rbp_size; + bool is_conf_tdb_internal = false; + if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "FILESYSTEM") == 0) { + internal_start_address = MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS; + internal_rbp_size = MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE; + } else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL") == 0) { + internal_start_address = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS; + internal_rbp_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE; + } else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_INTERNAL") == 0) { + internal_start_address = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS; + internal_rbp_size = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE; + is_conf_tdb_internal = true; + } else { + TEST_SKIP_UNLESS_MESSAGE(false, "Test skipped. No KVStore Internal"); + } + + uint32_t tdb_st_add = 0; + uint32_t tdb_end_add = 0; + ret = get_virtual_TDBStore_position(internal_start_address, internal_rbp_size, is_conf_tdb_internal, &tdb_st_add, &tdb_end_add); + TEST_SKIP_UNLESS_MESSAGE(ret != -2, "Test skipped. Not enough available space on Internal FlashIAP"); + TEST_ASSERT_EQUAL(0, ret); + + uint32_t expected_tdb_st_add = 0; + uint32_t expected_tdb_end_add = 0; + ret = get_expected_internal_TDBStore_position(&expected_tdb_st_add, &expected_tdb_end_add); + if (ret == MBED_SUCCESS) { + TEST_ASSERT_EQUAL(expected_tdb_st_add, tdb_st_add); + TEST_ASSERT_EQUAL(expected_tdb_end_add, tdb_end_add); + } + + memset(rkey, 0, sizeof(rkey)); + size_t actual_data_size = 0; + ret = ((TDBStore *)inner_store)->reserved_data_get(rkey, DEVICE_KEY_16BYTE, &actual_data_size); + TEST_ASSERT_EQUAL_ERROR_CODE(0, ret); + TEST_ASSERT_EQUAL(actual_data_size, DEVICE_KEY_16BYTE); + TEST_ASSERT_EQUAL_INT32_ARRAY(key, rkey, DEVICE_KEY_16BYTE / sizeof(uint32_t)); + + memset(rkey, 0, sizeof(rkey)); + actual_data_size = 0; + + ret = direct_access_to_devicekey(tdb_st_add, tdb_end_add, rkey, DEVICE_KEY_16BYTE, &actual_data_size); + TEST_ASSERT_EQUAL_ERROR_CODE(0, ret); + /* Assert DeviceKey value and length */ + TEST_ASSERT_EQUAL(actual_data_size, DEVICE_KEY_16BYTE); + TEST_ASSERT_EQUAL_INT32_ARRAY(key, rkey, DEVICE_KEY_16BYTE / sizeof(uint32_t)); + + ret = inner_store->deinit(); + TEST_ASSERT_EQUAL_ERROR_CODE(0, ret); +} + +// Test setup +utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) +{ + greentea_case_failure_abort_handler(source, reason); + return STATUS_CONTINUE; +} + +Case cases[] = { + Case("Testing direct access to devicekey with tdb over flashiap remainder", test_direct_access_to_devicekey_tdb_flashiap_remainder, greentea_failure_handler), + Case("Testing direct access to devicekey with tdb over last two sectors", test_direct_access_to_devicekey_tdb_last_two_sectors, greentea_failure_handler), + Case("Testing direct access to injected devicekey ", test_direct_access_to_device_inject_root, greentea_failure_handler), +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(120, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + return !Harness::run(specification); +} diff --git a/features/storage/kvstore/tdbstore/DirectAccessDevicekey.cpp b/features/storage/kvstore/tdbstore/DirectAccessDevicekey.cpp new file mode 100644 index 0000000000..12741873a6 --- /dev/null +++ b/features/storage/kvstore/tdbstore/DirectAccessDevicekey.cpp @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2018 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ----------------------------------------------------------- Includes ----------------------------------------------------------- +#if DEVICE_FLASH +#include "DirectAccessDevicekey.h" +#include +#include +#include "mbed_error.h" +#include "MbedCRC.h" +#include "mbed_trace.h" +#define TRACE_GROUP "DADK" + +using namespace mbed; + +// --------------------------------------------------------- Definitions ---------------------------------------------------------- +typedef struct { + uint32_t address; + size_t size; +} tdbstore_area_data_t; + +typedef struct { + uint16_t trailer_size; + uint16_t data_size; + uint32_t crc; +} reserved_trailer_t; + +#define TDBSTORE_NUMBER_OF_AREAS 2 +#define MAX_DEVICEKEY_DATA_SIZE 64 +#define RESERVED_AREA_SIZE (MAX_DEVICEKEY_DATA_SIZE+sizeof(reserved_trailer_t)) /* DeviceKey Max Data size + metadata trailer */ + +#define STR_EXPAND(tok) #tok +#define STR(tok) STR_EXPAND(tok) + +// -------------------------------------------------- Local Functions Declaration ---------------------------------------------------- +static int calc_area_params(FlashIAP *flash, uint32_t out_tdb_start_offset, uint32_t tdb_end_offset, + tdbstore_area_data_t *area_params); +static int reserved_data_get(FlashIAP *flash, tdbstore_area_data_t *area_params, void *reserved_data_buf, + size_t reserved_data_buf_size, size_t *actual_data_size_ptr); +static inline uint32_t align_up(uint64_t val, uint64_t size); +static inline uint32_t align_down(uint64_t val, uint64_t size); +static uint32_t calc_crc(uint32_t init_crc, uint32_t data_size, const void *data_buf); + +// -------------------------------------------------- API Functions Implementation ---------------------------------------------------- +int direct_access_to_devicekey(uint32_t tdb_start_offset, uint32_t tdb_end_offset, void *data_buf, + size_t data_buf_size, size_t *actual_data_size_ptr) +{ + int status = MBED_ERROR_INVALID_ARGUMENT; + FlashIAP flash; + uint8_t active_area = 0; + tdbstore_area_data_t area_params[TDBSTORE_NUMBER_OF_AREAS]; + memset(area_params, 0, sizeof(area_params)); + bool is_flash_init = false; + + if (NULL == data_buf) { + tr_error("Invalid Data Buf Argument"); + goto exit_point; + } + + status = flash.init(); + if (status != 0) { + tr_error("FlashIAP init failed - err: %d", status); + status = MBED_ERROR_FAILED_OPERATION; + goto exit_point; + } + + is_flash_init = true; + + status = calc_area_params(&flash, tdb_start_offset, tdb_end_offset, area_params); + if (status != MBED_SUCCESS) { + tr_error("Couldn't calulate Area Params - err: %d", status); + goto exit_point; + } + + /* DeviceKey data can be found either in first or second Flash Area */ + /* Loop through Areas to find valid DeviceKey data */ + for (active_area = 0; active_area < TDBSTORE_NUMBER_OF_AREAS; active_area++) { + status = reserved_data_get(&flash, &area_params[active_area], data_buf, data_buf_size, actual_data_size_ptr); + if (status == MBED_SUCCESS) { + break; + } + } + + if (status != MBED_SUCCESS) { + status = MBED_ERROR_ITEM_NOT_FOUND; + tr_error("Couldn't find valid DeviceKey - err: %d", status); + } + +exit_point: + if (true == is_flash_init) { + flash.deinit(); + } + + return status; +} + +int get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uint32_t *out_tdb_end_offset) +{ + uint32_t flash_end_address; + uint32_t flash_start_address; + uint32_t aligned_start_address; + uint32_t aligned_end_address; + FlashIAP flash; + bool is_default_configuration = false; + uint32_t tdb_size; + + if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "FILESYSTEM") == 0) { + *out_tdb_start_offset = MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS; + tdb_size = MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE; + } else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL") == 0) { + *out_tdb_start_offset = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS; + tdb_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE; + } else { + return MBED_ERROR_UNSUPPORTED; + } + + *out_tdb_end_offset = (*out_tdb_start_offset) + tdb_size; + + if ((*out_tdb_start_offset == 0) && (tdb_size == 0)) { + is_default_configuration = true; + } else if ((*out_tdb_start_offset == 0) || (tdb_size == 0)) { + return MBED_ERROR_UNSUPPORTED; + } + + int ret = flash.init(); + if (ret != 0) { + return MBED_ERROR_FAILED_OPERATION; + } + + uint32_t flash_first_writable_sector_address = (uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR, + flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR))); + + //Get flash parameters before starting + flash_start_address = flash.get_flash_start(); + flash_end_address = flash_start_address + flash.get_flash_size(); + + if (!is_default_configuration) { + aligned_start_address = align_down(*out_tdb_start_offset, flash.get_sector_size(*out_tdb_start_offset)); + aligned_end_address = align_up(*out_tdb_end_offset, flash.get_sector_size(*out_tdb_end_offset - 1)); + if ((*out_tdb_start_offset != aligned_start_address) || (*out_tdb_end_offset != aligned_end_address) + || (*out_tdb_end_offset > flash_end_address)) { + flash.deinit(); + return MBED_ERROR_INVALID_OPERATION; + } + } else { + aligned_start_address = flash_end_address - (flash.get_sector_size(flash_end_address - 1) * 2); + if (aligned_start_address < flash_first_writable_sector_address) { + flash.deinit(); + return MBED_ERROR_INVALID_OPERATION; + } + *out_tdb_start_offset = aligned_start_address; + *out_tdb_end_offset = flash_end_address; + } + + flash.deinit(); + + return MBED_SUCCESS; +} + +// -------------------------------------------------- Local Functions Implementation ---------------------------------------------------- +static int calc_area_params(FlashIAP *flash, uint32_t out_tdb_start_offset, uint32_t tdb_end_offset, + tdbstore_area_data_t *area_params) +{ + uint32_t bd_size = 0; + uint32_t initial_erase_size = flash->get_sector_size(out_tdb_start_offset); + uint32_t erase_unit_size = initial_erase_size; + size_t cur_area_size = 0; + + if ((tdb_end_offset < (out_tdb_start_offset + 2 * RESERVED_AREA_SIZE - 1)) || + (tdb_end_offset > (flash->get_flash_start() + flash->get_flash_size()))) { + tr_error("calc_area_params failed - Invalid input addresses"); + return MBED_ERROR_INVALID_ARGUMENT; + } + + // Entire TDBStore can't exceed 32 bits + bd_size = (tdb_end_offset - out_tdb_start_offset + 1); + + while (cur_area_size < bd_size / 2) { + erase_unit_size = flash->get_sector_size(out_tdb_start_offset + cur_area_size); + cur_area_size += erase_unit_size; + } + + area_params[0].address = out_tdb_start_offset; + area_params[0].size = cur_area_size; + area_params[1].address = out_tdb_start_offset + cur_area_size; + area_params[1].size = bd_size - cur_area_size; + + return MBED_SUCCESS; +} + +static int reserved_data_get(FlashIAP *flash, tdbstore_area_data_t *area_params, void *reserved_data_buf, + size_t reserved_data_buf_size, size_t *actual_data_size_ptr) +{ + int status = MBED_SUCCESS; + reserved_trailer_t trailer; + uint8_t *buf; + int ret = MBED_SUCCESS; + bool erased = true; + size_t actual_size = 0; + uint32_t initial_crc = 0xFFFFFFFF; + uint32_t crc = initial_crc; + uint8_t blank = flash->get_erase_value(); + + /* Read Into trailer deviceKey metadata */ + ret = flash->read(&trailer, area_params->address + MAX_DEVICEKEY_DATA_SIZE, sizeof(trailer)); + if (ret != MBED_SUCCESS) { + status = MBED_ERROR_READ_FAILED; + goto exit_point; + } + + buf = reinterpret_cast (&trailer); + for (uint32_t i = 0; i < sizeof(trailer); i++) { + if (buf[i] != blank) { + erased = false; + break; + } + } + + if (true == erased) { + /* Metadata is erased , DeviceKey Data is NOT in this Area */ + status = MBED_ERROR_ITEM_NOT_FOUND; + goto exit_point; + } + + actual_size = trailer.data_size; + if (actual_data_size_ptr != NULL) { + *actual_data_size_ptr = actual_size; + } + if (reserved_data_buf_size < actual_size) { + status = MBED_ERROR_INVALID_SIZE; + goto exit_point; + } + + buf = reinterpret_cast (reserved_data_buf); + + /* Read DeviceKey Data */ + ret = flash->read(buf, area_params->address, (uint32_t)actual_size); + if (ret != MBED_SUCCESS) { + status = MBED_ERROR_READ_FAILED; + goto exit_point; + } + + crc = calc_crc(crc, (uint32_t)actual_size, buf); + if (crc != trailer.crc) { + status = MBED_ERROR_INVALID_DATA_DETECTED; + } + +exit_point: + + return status; +} + +static inline uint32_t align_up(uint64_t val, uint64_t size) +{ + return (((val - 1) / size) + 1) * size; +} + +static inline uint32_t align_down(uint64_t val, uint64_t size) +{ + return (((val) / size)) * size; +} + +static uint32_t calc_crc(uint32_t init_crc, uint32_t data_size, const void *data_buf) +{ + uint32_t crc; + MbedCRC ct(init_crc, 0x0, true, false); + ct.compute(const_cast(data_buf), data_size, &crc); + return crc; +} +#endif // DEVICE_FLASH diff --git a/features/storage/kvstore/tdbstore/DirectAccessDevicekey.h b/features/storage/kvstore/tdbstore/DirectAccessDevicekey.h new file mode 100644 index 0000000000..33933bbacb --- /dev/null +++ b/features/storage/kvstore/tdbstore/DirectAccessDevicekey.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_DIRECT_ACCESS_DEVICEKEY_H +#define MBED_DIRECT_ACCESS_DEVICEKEY_H + +#include "FlashIAP.h" +#include +/** + * @brief Returns devicekey directly from internal FlashIAP by given tdb internal position + * + * @param[in] tdb_start_offset FlashIAP Start address offset of tdb store + * @param[in] tdb_end_offset FlashIAP End address offset of tdb store + * @param[in] data_buf Buffer to store devicekey data + * @param[in] data_buf_size Max expected size of buffer to store the devicekey data + * @param[out] actual_data_size_ptr Actual retrieved devicekey size + * + * @returns MBED_ERROR_INVALID_ARGUMENT Illegal argument given + * MBED_ERROR_INVALID_SIZE data_buf_size is too small for retrieving actual data size + * MBED_ERROR_INVALID_DATA_DETECTED devicekey data invalid crc + * MBED_ERROR_ITEM_NOT_FOUND devicekey data not found + * MBED_ERROR_FAILED_OPERATION internal flash failure + * MBED_ERROR_READ_FAILED internal flash read failed + * MBED_SUCCESS successful + */ +int direct_access_to_devicekey(uint32_t tdb_start_offset, uint32_t tdb_end_offset, void *data_buf, + size_t data_buf_size, size_t *actual_data_size_ptr); + +/** + * @brief Returns the expected tdb internal position. + * Limitations: + * 1. supporting FILESYSTEM or TDB_EXTERNAL configuration only + * 2. supporting either both start_address and size are explicitly given (different than zero) + * or both of them are zero (default configuration) + * + * @param[out] out_tdb_start_offset Expected FlashIAP Start address offset of tdb store + * @param[out] out_tdb_end_offset Expected FlashIAP End address offset of tdb store + * + * @returns MBED_ERROR_FAILED_OPERATION internal flash failure + * MBED_ERROR_UNSUPPORTED kvstore configuration different than FILESYSTEM or TDB_EXTERNAL + * or start_address or size are different than 0 and the other isn't + * MBED_ERROR_INVALID_OPERATION tdb_start_offset or tdb_end_offset are not aligned or lower + * than end of code segment (when using default configuration) + * MBED_SUCCESS successful + * + */ +int get_expected_internal_TDBStore_position(uint32_t *out_tdb_start_offset, uint32_t *out_tdb_end_offset); + +#endif /* MBED_DIRECT_ACCESS_DEVICEKEY_H */