Skip to content

Commit d6c014c

Browse files
author
Cruz Monrreal
authored
Merge pull request #9215 from offirko/offir_bootloader_get-device-key
Direct access to device key
2 parents f8d7c31 + 423c4fb commit d6c014c

File tree

3 files changed

+681
-0
lines changed

3 files changed

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

0 commit comments

Comments
 (0)