Skip to content

Commit 7136c78

Browse files
offirkoadbridge
authored andcommitted
Adding low code size tool for direct access to Devicekey. This enables application with code size restrictions to access devicekey directly based on address in internal flash without kvconfig overhead
1 parent 0f9098d commit 7136c78

File tree

3 files changed

+561
-0
lines changed

3 files changed

+561
-0
lines changed
Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
/* Copyright (c) 2018 Arm Limited
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "mbed.h"
19+
#include <stdio.h>
20+
#include <string.h>
21+
#include "DeviceKey.h"
22+
#include "KVStore.h"
23+
#include "KVMap.h"
24+
#include "kv_config.h"
25+
#include "TDBStore.h"
26+
#include "FlashIAP.h"
27+
#include "FlashIAPBlockDevice.h"
28+
#include "DirectAccessDevicekey.h"
29+
#include "greentea-client/test_env.h"
30+
#include "unity.h"
31+
#include "utest.h"
32+
#include <stdlib.h>
33+
34+
#ifndef DEVICE_FLASH
35+
#error [NOT_SUPPORTED] Target must have internal FlashIAP for this test
36+
#endif
37+
38+
39+
using namespace utest::v1;
40+
using namespace mbed;
41+
42+
#define TEST_DEVICEKEY_LENGTH 32
43+
44+
static inline uint32_t align_up(uint64_t val, uint64_t size)
45+
{
46+
return (((val - 1) / size) + 1) * size;
47+
}
48+
49+
static inline uint32_t align_down(uint64_t val, uint64_t size)
50+
{
51+
return (((val) / size)) * size;
52+
}
53+
54+
int get_virtual_TDBStore_position(uint32_t conf_start_address, uint32_t conf_size, bool is_conf_tdb_internal,
55+
uint32_t *tdb_start_address, uint32_t *tdb_end_address)
56+
{
57+
uint32_t bd_final_size;
58+
uint32_t flash_end_address;
59+
uint32_t flash_start_address;
60+
uint32_t aligned_start_address;
61+
FlashIAP flash;
62+
63+
int ret = flash.init();
64+
if (ret != 0) {
65+
return -1;
66+
}
67+
68+
uint32_t flash_first_writable_sector_address = (uint32_t)(align_up(FLASHIAP_APP_ROM_END_ADDR,
69+
flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR)));
70+
71+
//Get flash parameters before starting
72+
flash_start_address = flash.get_flash_start();
73+
flash_end_address = flash_start_address + flash.get_flash_size();
74+
75+
bool request_default = false;
76+
if (conf_start_address == 0 && conf_size == 0) {
77+
request_default = true;
78+
}
79+
80+
if (!request_default) {
81+
aligned_start_address = align_down(conf_start_address, flash.get_sector_size(conf_start_address));
82+
if (aligned_start_address < flash_first_writable_sector_address) {
83+
aligned_start_address = flash_first_writable_sector_address;
84+
}
85+
bd_final_size = (flash_end_address - aligned_start_address);
86+
if (bd_final_size < 2 * 4096) {
87+
flash.deinit();
88+
return -2;
89+
}
90+
} else {
91+
if (is_conf_tdb_internal == true) {
92+
aligned_start_address = flash_first_writable_sector_address;
93+
bd_final_size = (flash_end_address - aligned_start_address);
94+
if (bd_final_size < 2 * 4096) {
95+
flash.deinit();
96+
return -2;
97+
}
98+
} else {
99+
//update start_address to double the size for TDBStore needs
100+
aligned_start_address = flash_end_address - (flash.get_sector_size(flash_end_address - 1) * 2);
101+
if (aligned_start_address < flash_first_writable_sector_address) {
102+
flash.deinit();
103+
return -2;
104+
}
105+
bd_final_size = (flash_end_address - aligned_start_address);
106+
}
107+
}
108+
109+
(*tdb_start_address) = aligned_start_address;
110+
(*tdb_end_address) = aligned_start_address + bd_final_size;
111+
112+
flash.deinit();
113+
114+
return 0;
115+
}
116+
117+
118+
void test_direct_access_to_devicekey_tdb_flashiap_remainder()
119+
{
120+
utest_printf("Test Direct Access To DeviceKey Test Entire FlashIAP Remainder\n");
121+
122+
uint32_t flash_bd_start_address;
123+
uint32_t flash_bd_end_address;
124+
125+
int err = get_virtual_TDBStore_position(0, 0, true, &flash_bd_start_address, &flash_bd_end_address);
126+
TEST_SKIP_UNLESS_MESSAGE(err != -2, "Test skipped. Not enough available space on Internal FlashIAP");
127+
TEST_ASSERT_EQUAL(0, err);
128+
uint32_t flash_bd_size = flash_bd_end_address - flash_bd_start_address;
129+
130+
FlashIAPBlockDevice *flash_bd = new FlashIAPBlockDevice((bd_addr_t)flash_bd_start_address, (bd_size_t)flash_bd_size);
131+
TEST_ASSERT_NOT_EQUAL(NULL, flash_bd);
132+
133+
TDBStore *tdb = new TDBStore(flash_bd);
134+
TEST_ASSERT_NOT_EQUAL(NULL, tdb);
135+
// Start by Init and Reset to TDBStore
136+
err = tdb->init();
137+
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
138+
139+
err = tdb->reset();
140+
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
141+
142+
// Assign a dummy DeviceKey, and set via tdb
143+
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};
144+
err = tdb->reserved_data_set(device_key_in, TEST_DEVICEKEY_LENGTH);
145+
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
146+
147+
148+
err = tdb->deinit();
149+
TEST_ASSERT_EQUAL(0, err);
150+
151+
delete tdb;
152+
delete flash_bd;
153+
154+
// Now use Direct Access To DeviceKey to retrieve it
155+
uint8_t device_key_out[TEST_DEVICEKEY_LENGTH] = {0};
156+
size_t actual_data_size = 0;
157+
158+
err = direct_access_to_devicekey((uint32_t)flash_bd_start_address, (uint32_t)flash_bd_end_address, device_key_out,
159+
TEST_DEVICEKEY_LENGTH,
160+
&actual_data_size);
161+
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
162+
163+
// Assert DeviceKey value and length
164+
TEST_ASSERT_EQUAL(actual_data_size, TEST_DEVICEKEY_LENGTH);
165+
for (int i_ind = 0; i_ind < TEST_DEVICEKEY_LENGTH; i_ind++) {
166+
TEST_ASSERT_EQUAL(device_key_in[i_ind], device_key_out[i_ind]);
167+
}
168+
169+
}
170+
171+
void test_direct_access_to_devicekey_tdb_last_two_sectors()
172+
{
173+
utest_printf("Test Direct Access To DeviceKey Test Entire FlashIAP Remainder\n");
174+
175+
uint32_t flash_bd_start_address;
176+
uint32_t flash_bd_end_address;
177+
178+
int err = get_virtual_TDBStore_position(0, 0, false, &flash_bd_start_address, &flash_bd_end_address);
179+
TEST_SKIP_UNLESS_MESSAGE(err != -2, "Test skipped. Not enough available space on Internal FlashIAP");
180+
TEST_ASSERT_EQUAL(0, err);
181+
182+
uint32_t flash_bd_size = flash_bd_end_address - flash_bd_start_address;
183+
184+
FlashIAPBlockDevice *flash_bd = new FlashIAPBlockDevice((bd_addr_t)flash_bd_start_address, (bd_size_t)flash_bd_size);
185+
186+
TDBStore *tdb = new TDBStore(flash_bd);
187+
// Start by Init and Reset to TDBStore
188+
err = tdb->init();
189+
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
190+
191+
err = tdb->reset();
192+
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
193+
194+
// Assign a dummy DeviceKey, and set via tdb
195+
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};
196+
err = tdb->reserved_data_set(device_key_in, TEST_DEVICEKEY_LENGTH);
197+
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
198+
199+
err = tdb->deinit();
200+
TEST_ASSERT_EQUAL(0, err);
201+
202+
delete tdb;
203+
delete flash_bd;
204+
205+
// Now use Direct Access To DeviceKey to retrieve it
206+
uint8_t device_key_out[TEST_DEVICEKEY_LENGTH] = {0};
207+
size_t actual_data_size = 0;
208+
209+
err = direct_access_to_devicekey((uint32_t)flash_bd_start_address, (uint32_t)flash_bd_end_address, device_key_out,
210+
TEST_DEVICEKEY_LENGTH,
211+
&actual_data_size);
212+
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
213+
214+
// Assert DeviceKey value and length
215+
TEST_ASSERT_EQUAL(TEST_DEVICEKEY_LENGTH, actual_data_size);
216+
for (int i_ind = 0; i_ind < TEST_DEVICEKEY_LENGTH; i_ind++) {
217+
TEST_ASSERT_EQUAL(device_key_in[i_ind], device_key_out[i_ind]);
218+
}
219+
220+
}
221+
#define STR_EXPAND(tok) #tok
222+
#define STR(tok) STR_EXPAND(tok)
223+
224+
void test_direct_access_to_device_inject_root()
225+
{
226+
kv_init_storage_config();
227+
DeviceKey &devkey = DeviceKey::get_instance();
228+
uint32_t rkey[DEVICE_KEY_16BYTE / sizeof(uint32_t)];
229+
uint32_t key[DEVICE_KEY_16BYTE / sizeof(uint32_t)];
230+
KVMap &kv_map = KVMap::get_instance();
231+
KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
232+
TEST_ASSERT_NOT_EQUAL(NULL, inner_store);
233+
234+
BlockDevice *flash_bd = kv_map.get_internal_blockdevice_instance("");
235+
TEST_ASSERT_NOT_EQUAL(NULL, flash_bd);
236+
237+
int ret = inner_store->reset();
238+
TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret);
239+
240+
memcpy(key, "abcdefghabcdefgh", sizeof(key));
241+
ret = devkey.device_inject_root_of_trust(key, DEVICE_KEY_16BYTE);
242+
TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret);
243+
244+
// Now use Direct Access To DeviceKey to retrieve it */
245+
uint32_t internal_start_address;
246+
uint32_t internal_rbp_size;
247+
bool is_conf_tdb_internal = false;
248+
if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "FILESYSTEM") == 0) {
249+
internal_start_address = MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS;
250+
internal_rbp_size = MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE;
251+
} else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_EXTERNAL") == 0) {
252+
internal_start_address = MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS;
253+
internal_rbp_size = MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE;
254+
} else if (strcmp(STR(MBED_CONF_STORAGE_STORAGE_TYPE), "TDB_INTERNAL") == 0) {
255+
internal_start_address = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS;
256+
internal_rbp_size = MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE;
257+
is_conf_tdb_internal = true;
258+
} else {
259+
TEST_SKIP_UNLESS_MESSAGE(false, "Test skipped. No KVStore Internal");
260+
}
261+
262+
uint32_t tdb_st_add = 0;
263+
uint32_t tdb_end_add = 0;
264+
265+
ret = get_virtual_TDBStore_position(internal_start_address, internal_rbp_size, is_conf_tdb_internal, &tdb_st_add, &tdb_end_add);
266+
TEST_SKIP_UNLESS_MESSAGE(ret != -2, "Test skipped. Not enough available space on Internal FlashIAP");
267+
TEST_ASSERT_EQUAL(0, ret);
268+
269+
memset(rkey, 0, sizeof(rkey));
270+
size_t actual_data_size = 0;
271+
ret = ((TDBStore *)inner_store)->reserved_data_get(rkey, DEVICE_KEY_16BYTE, &actual_data_size);
272+
TEST_ASSERT_EQUAL_ERROR_CODE(0, ret);
273+
TEST_ASSERT_EQUAL(actual_data_size, DEVICE_KEY_16BYTE);
274+
TEST_ASSERT_EQUAL_INT32_ARRAY(key, rkey, DEVICE_KEY_16BYTE / sizeof(uint32_t));
275+
276+
memset(rkey, 0, sizeof(rkey));
277+
actual_data_size = 0;
278+
279+
ret = direct_access_to_devicekey(tdb_st_add, tdb_end_add, rkey, DEVICE_KEY_16BYTE, &actual_data_size);
280+
TEST_ASSERT_EQUAL_ERROR_CODE(0, ret);
281+
/* Assert DeviceKey value and length */
282+
TEST_ASSERT_EQUAL(actual_data_size, DEVICE_KEY_16BYTE);
283+
TEST_ASSERT_EQUAL_INT32_ARRAY(key, rkey, DEVICE_KEY_16BYTE / sizeof(uint32_t));
284+
285+
ret = inner_store->deinit();
286+
TEST_ASSERT_EQUAL_ERROR_CODE(0, ret);
287+
}
288+
289+
// Test setup
290+
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
291+
{
292+
greentea_case_failure_abort_handler(source, reason);
293+
return STATUS_CONTINUE;
294+
}
295+
296+
Case cases[] = {
297+
Case("Testing direct access to devicekey with tdb over flashiap remainder", test_direct_access_to_devicekey_tdb_flashiap_remainder, greentea_failure_handler),
298+
Case("Testing direct access to devicekey with tdb over last two sectors", test_direct_access_to_devicekey_tdb_last_two_sectors, greentea_failure_handler),
299+
Case("Testing direct access to injected devicekey ", test_direct_access_to_device_inject_root, greentea_failure_handler),
300+
};
301+
302+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
303+
{
304+
GREENTEA_SETUP(120, "default_auto");
305+
return greentea_test_setup_handler(number_of_cases);
306+
}
307+
308+
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
309+
310+
int main()
311+
{
312+
return !Harness::run(specification);
313+
}

0 commit comments

Comments
 (0)