Skip to content

Commit fb9faff

Browse files
committed
Add sign/parser roundtrip tests
F/2270
1 parent 13d232c commit fb9faff

1 file changed

Lines changed: 277 additions & 19 deletions

File tree

tools/unit-tests/unit-sign-encrypted-output.c

Lines changed: 277 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <sys/stat.h>
1313
#include <unistd.h>
1414

15+
#define WOLFBOOT_HASH_SHA256
16+
#define IMAGE_HEADER_SIZE 512
17+
1518
static const char *mock_fail_open_path;
1619
static int mock_fail_open_on_call;
1720
static int mock_open_call_count;
@@ -40,6 +43,45 @@ static int mock_fprintf(FILE *stream, const char *format, ...);
4043
#undef fopen
4144
#undef main
4245

46+
#include "../../src/libwolfboot.c"
47+
48+
static int locked;
49+
50+
void hal_init(void)
51+
{
52+
}
53+
54+
int hal_flash_write(haladdr_t address, const uint8_t *data, int len)
55+
{
56+
(void)address;
57+
(void)data;
58+
(void)len;
59+
return 0;
60+
}
61+
62+
int hal_flash_erase(haladdr_t address, int len)
63+
{
64+
(void)address;
65+
(void)len;
66+
return 0;
67+
}
68+
69+
void hal_flash_unlock(void)
70+
{
71+
ck_assert_msg(locked, "Double unlock detected\n");
72+
locked--;
73+
}
74+
75+
void hal_flash_lock(void)
76+
{
77+
ck_assert_msg(!locked, "Double lock detected\n");
78+
locked++;
79+
}
80+
81+
void hal_prepare_boot(void)
82+
{
83+
}
84+
4385
static void reset_mocks(const char *fail_open_path, int fail_open_on_call)
4486
{
4587
mock_fail_open_path = fail_open_path;
@@ -127,6 +169,89 @@ static int write_file(const char *path, const void *buf, size_t len)
127169
return written == len ? 0 : -1;
128170
}
129171

172+
static int read_file(const char *path, uint8_t **buf, size_t *len)
173+
{
174+
FILE *f;
175+
struct stat st;
176+
size_t read_len;
177+
178+
if (stat(path, &st) != 0) {
179+
return -1;
180+
}
181+
182+
*buf = malloc((size_t)st.st_size);
183+
if (*buf == NULL) {
184+
return -1;
185+
}
186+
187+
f = fopen(path, "rb");
188+
if (f == NULL) {
189+
free(*buf);
190+
*buf = NULL;
191+
return -1;
192+
}
193+
194+
read_len = fread(*buf, 1, (size_t)st.st_size, f);
195+
fclose(f);
196+
if (read_len != (size_t)st.st_size) {
197+
free(*buf);
198+
*buf = NULL;
199+
return -1;
200+
}
201+
202+
*len = read_len;
203+
return 0;
204+
}
205+
206+
static void reset_cmd_defaults(void)
207+
{
208+
memset(&CMD, 0, sizeof(CMD));
209+
CMD.sign = NO_SIGN;
210+
CMD.hash_algo = HASH_SHA256;
211+
CMD.partition_id = HDR_IMG_TYPE_APP;
212+
CMD.header_sz = IMAGE_HEADER_SIZE;
213+
CMD.fw_version = "7";
214+
CMD.no_ts = 1;
215+
}
216+
217+
static void free_custom_tlv_buffers(void)
218+
{
219+
uint32_t i;
220+
221+
for (i = 0; i < MAX_CUSTOM_TLVS; i++) {
222+
free(CMD.custom_tlv[i].buffer);
223+
CMD.custom_tlv[i].buffer = NULL;
224+
}
225+
}
226+
227+
static void assert_header_bytes(const uint8_t *image, uint16_t tag,
228+
const uint8_t *expected, uint16_t expected_len)
229+
{
230+
uint8_t *value = NULL;
231+
uint16_t len = wolfBoot_find_header((uint8_t *)image + IMAGE_HEADER_OFFSET,
232+
tag, &value);
233+
234+
ck_assert_uint_eq(len, expected_len);
235+
ck_assert_ptr_nonnull(value);
236+
ck_assert_msg(memcmp(value, expected, expected_len) == 0,
237+
"Tag 0x%04x mismatch", tag);
238+
}
239+
240+
static uint16_t find_exact_fill_custom_len(void)
241+
{
242+
uint16_t len;
243+
244+
for (len = 1; len < IMAGE_HEADER_SIZE; len++) {
245+
CMD.custom_tlvs = 1;
246+
CMD.custom_tlv[0].len = len;
247+
if (header_required_size(0, 0, 0) == CMD.header_sz) {
248+
return len;
249+
}
250+
}
251+
252+
return 0;
253+
}
254+
130255
START_TEST(test_make_header_ex_fails_when_encrypted_output_open_fails)
131256
{
132257
char tempdir[] = "/tmp/wolfboot-sign-XXXXXX";
@@ -151,14 +276,9 @@ START_TEST(test_make_header_ex_fails_when_encrypted_output_open_fails)
151276
ck_assert_int_eq(write_file(image_path, image_buf, sizeof(image_buf)), 0);
152277
ck_assert_int_eq(write_file(key_path, key_buf, sizeof(key_buf)), 0);
153278

154-
memset(&CMD, 0, sizeof(CMD));
155-
CMD.sign = NO_SIGN;
279+
reset_cmd_defaults();
156280
CMD.encrypt = ENC_AES128;
157-
CMD.hash_algo = HASH_SHA256;
158-
CMD.partition_id = HDR_IMG_TYPE_APP;
159281
CMD.header_sz = 256;
160-
CMD.fw_version = "7";
161-
CMD.no_ts = 1;
162282
CMD.encrypt_key_file = key_path;
163283
snprintf(CMD.output_encrypted_image_file,
164284
sizeof(CMD.output_encrypted_image_file), "%s", encrypted_output_path);
@@ -197,13 +317,8 @@ START_TEST(test_make_header_ex_fails_when_image_reopen_fails)
197317

198318
ck_assert_int_eq(write_file(image_path, image_buf, sizeof(image_buf)), 0);
199319

200-
memset(&CMD, 0, sizeof(CMD));
201-
CMD.sign = NO_SIGN;
202-
CMD.hash_algo = HASH_SHA256;
203-
CMD.partition_id = HDR_IMG_TYPE_APP;
320+
reset_cmd_defaults();
204321
CMD.header_sz = 256;
205-
CMD.fw_version = "7";
206-
CMD.no_ts = 1;
207322

208323
reset_mocks(image_path, 2);
209324
ret = make_header_ex(0, pubkey, sizeof(pubkey), image_path, output_path,
@@ -226,10 +341,13 @@ START_TEST(test_make_header_ex_grows_header_for_cert_chain_and_digest_tlvs)
226341
char image_path[PATH_MAX];
227342
char output_path[PATH_MAX];
228343
char cert_chain_path[PATH_MAX];
344+
uint8_t *output_buf = NULL;
345+
uint8_t *value = NULL;
229346
uint8_t image_buf[] = { 0x01, 0x02, 0x03, 0x04 };
230347
uint8_t cert_chain_buf[200];
231348
uint8_t pubkey[] = { 0xA5 };
232349
struct stat st;
350+
size_t output_len;
233351
int ret;
234352

235353
ck_assert_ptr_nonnull(mkdtemp(tempdir));
@@ -244,13 +362,8 @@ START_TEST(test_make_header_ex_grows_header_for_cert_chain_and_digest_tlvs)
244362
ck_assert_int_eq(write_file(cert_chain_path, cert_chain_buf,
245363
sizeof(cert_chain_buf)), 0);
246364

247-
memset(&CMD, 0, sizeof(CMD));
248-
CMD.sign = NO_SIGN;
249-
CMD.hash_algo = HASH_SHA256;
250-
CMD.partition_id = HDR_IMG_TYPE_APP;
365+
reset_cmd_defaults();
251366
CMD.header_sz = 256;
252-
CMD.fw_version = "7";
253-
CMD.no_ts = 1;
254367
CMD.cert_chain_file = cert_chain_path;
255368

256369
reset_mocks(NULL, 0);
@@ -264,14 +377,155 @@ START_TEST(test_make_header_ex_grows_header_for_cert_chain_and_digest_tlvs)
264377
ck_assert_int_eq(mock_null_fwrite_calls, 0);
265378
ck_assert_int_eq(mock_null_fread_calls, 0);
266379
ck_assert_int_eq(mock_null_fclose_calls, 0);
267-
380+
ck_assert_int_eq(read_file(output_path, &output_buf, &output_len), 0);
381+
ck_assert_uint_eq(output_len, CMD.header_sz + sizeof(image_buf));
382+
assert_header_bytes(output_buf, HDR_CERT_CHAIN, cert_chain_buf,
383+
sizeof(cert_chain_buf));
384+
ck_assert_uint_eq(wolfBoot_find_header(output_buf + IMAGE_HEADER_OFFSET,
385+
HDR_PUBKEY, &value), HDR_SHA256_LEN);
386+
ck_assert_uint_eq(wolfBoot_find_header(output_buf + IMAGE_HEADER_OFFSET,
387+
HDR_SHA256, &value), HDR_SHA256_LEN);
388+
389+
free(output_buf);
268390
unlink(output_path);
269391
unlink(cert_chain_path);
270392
unlink(image_path);
271393
rmdir(tempdir);
272394
}
273395
END_TEST
274396

397+
START_TEST(test_make_header_ex_roundtrip_custom_tlvs_via_wolfboot_parser)
398+
{
399+
char tempdir[] = "/tmp/wolfboot-sign-XXXXXX";
400+
char image_path[PATH_MAX];
401+
char output_path[PATH_MAX];
402+
uint8_t *output_buf = NULL;
403+
uint8_t *value = NULL;
404+
uint8_t image_buf[] = { 0x10, 0x20, 0x30, 0x40, 0x50 };
405+
uint8_t pubkey[] = { 0xA5, 0x5A, 0x33, 0xCC };
406+
uint8_t tlv_one[] = { 0xAB };
407+
uint8_t tlv_two[] = { 0x10, 0x11, 0x12, 0x13, 0x14 };
408+
uint8_t tlv_three[] = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28 };
409+
uint16_t image_type;
410+
uint32_t version = 7;
411+
size_t output_len;
412+
int ret;
413+
414+
ck_assert_ptr_nonnull(mkdtemp(tempdir));
415+
416+
snprintf(image_path, sizeof(image_path), "%s/image.bin", tempdir);
417+
snprintf(output_path, sizeof(output_path), "%s/output.bin", tempdir);
418+
ck_assert_int_eq(write_file(image_path, image_buf, sizeof(image_buf)), 0);
419+
420+
reset_cmd_defaults();
421+
image_type = (uint16_t)((CMD.sign & HDR_IMG_TYPE_AUTH_MASK) |
422+
CMD.partition_id);
423+
CMD.custom_tlvs = 3;
424+
CMD.custom_tlv[0].tag = 0x30;
425+
CMD.custom_tlv[0].len = sizeof(tlv_one);
426+
CMD.custom_tlv[0].buffer = malloc(sizeof(tlv_one));
427+
memcpy(CMD.custom_tlv[0].buffer, tlv_one, sizeof(tlv_one));
428+
CMD.custom_tlv[1].tag = 0x31;
429+
CMD.custom_tlv[1].len = sizeof(tlv_two);
430+
CMD.custom_tlv[1].buffer = malloc(sizeof(tlv_two));
431+
memcpy(CMD.custom_tlv[1].buffer, tlv_two, sizeof(tlv_two));
432+
CMD.custom_tlv[2].tag = 0x32;
433+
CMD.custom_tlv[2].len = sizeof(tlv_three);
434+
CMD.custom_tlv[2].buffer = malloc(sizeof(tlv_three));
435+
memcpy(CMD.custom_tlv[2].buffer, tlv_three, sizeof(tlv_three));
436+
437+
reset_mocks(NULL, 0);
438+
ret = make_header_ex(0, pubkey, sizeof(pubkey), image_path, output_path,
439+
0, 0, 0, 0, NULL, 0, NULL, 0);
440+
441+
ck_assert_int_eq(ret, 0);
442+
ck_assert_int_eq(read_file(output_path, &output_buf, &output_len), 0);
443+
ck_assert_uint_eq(output_len, CMD.header_sz + sizeof(image_buf));
444+
assert_header_bytes(output_buf, HDR_VERSION, (uint8_t *)&version,
445+
sizeof(version));
446+
assert_header_bytes(output_buf, HDR_IMG_TYPE, (uint8_t *)&image_type,
447+
sizeof(image_type));
448+
assert_header_bytes(output_buf, 0x30, tlv_one, sizeof(tlv_one));
449+
assert_header_bytes(output_buf, 0x31, tlv_two, sizeof(tlv_two));
450+
assert_header_bytes(output_buf, 0x32, tlv_three, sizeof(tlv_three));
451+
ck_assert_uint_eq(wolfBoot_find_header(output_buf + IMAGE_HEADER_OFFSET,
452+
HDR_PUBKEY, &value), HDR_SHA256_LEN);
453+
ck_assert_ptr_nonnull(value);
454+
ck_assert_uint_eq((uintptr_t)value % 8U, 0);
455+
ck_assert_uint_eq(wolfBoot_find_header(output_buf + IMAGE_HEADER_OFFSET,
456+
0x30, &value), sizeof(tlv_one));
457+
ck_assert_uint_eq((uintptr_t)value % 8U, 0);
458+
ck_assert_uint_eq(wolfBoot_find_header(output_buf + IMAGE_HEADER_OFFSET,
459+
0x31, &value), sizeof(tlv_two));
460+
ck_assert_uint_eq((uintptr_t)value % 8U, 0);
461+
ck_assert_uint_eq(wolfBoot_find_header(output_buf + IMAGE_HEADER_OFFSET,
462+
0x32, &value), sizeof(tlv_three));
463+
ck_assert_uint_eq((uintptr_t)value % 8U, 0);
464+
ck_assert_uint_eq(wolfBoot_find_header(output_buf + IMAGE_HEADER_OFFSET,
465+
HDR_SHA256, &value), HDR_SHA256_LEN);
466+
467+
free(output_buf);
468+
free_custom_tlv_buffers();
469+
unlink(output_path);
470+
unlink(image_path);
471+
rmdir(tempdir);
472+
}
473+
END_TEST
474+
475+
START_TEST(test_make_header_ex_roundtrip_finds_tlv_that_exactly_fills_header)
476+
{
477+
char tempdir[] = "/tmp/wolfboot-sign-XXXXXX";
478+
char image_path[PATH_MAX];
479+
char output_path[PATH_MAX];
480+
uint8_t *output_buf = NULL;
481+
uint8_t image_buf[] = { 0x61, 0x62, 0x63, 0x64 };
482+
uint8_t pubkey[] = { 0x01, 0x02 };
483+
uint8_t *custom_buf = NULL;
484+
uint8_t *value = NULL;
485+
size_t output_len;
486+
uint16_t exact_len;
487+
int ret;
488+
489+
ck_assert_ptr_nonnull(mkdtemp(tempdir));
490+
491+
snprintf(image_path, sizeof(image_path), "%s/image.bin", tempdir);
492+
snprintf(output_path, sizeof(output_path), "%s/output.bin", tempdir);
493+
ck_assert_int_eq(write_file(image_path, image_buf, sizeof(image_buf)), 0);
494+
495+
reset_cmd_defaults();
496+
exact_len = find_exact_fill_custom_len();
497+
ck_assert_uint_ne(exact_len, 0);
498+
custom_buf = malloc(exact_len);
499+
ck_assert_ptr_nonnull(custom_buf);
500+
memset(custom_buf, 0x6C, exact_len);
501+
502+
CMD.custom_tlvs = 1;
503+
CMD.custom_tlv[0].tag = 0x40;
504+
CMD.custom_tlv[0].len = exact_len;
505+
CMD.custom_tlv[0].buffer = custom_buf;
506+
ck_assert_uint_eq(header_required_size(0, 0, 0), CMD.header_sz);
507+
508+
reset_mocks(NULL, 0);
509+
ret = make_header_ex(0, pubkey, sizeof(pubkey), image_path, output_path,
510+
0, 0, 0, 0, NULL, 0, NULL, 0);
511+
512+
ck_assert_int_eq(ret, 0);
513+
ck_assert_int_eq(read_file(output_path, &output_buf, &output_len), 0);
514+
ck_assert_uint_eq(output_len, CMD.header_sz + sizeof(image_buf));
515+
ck_assert_uint_eq(wolfBoot_find_header(output_buf + IMAGE_HEADER_OFFSET,
516+
0x40, &value), exact_len);
517+
ck_assert_ptr_nonnull(value);
518+
ck_assert_msg(memcmp(value, custom_buf, exact_len) == 0,
519+
"Exact-fit TLV did not roundtrip");
520+
521+
free(output_buf);
522+
free_custom_tlv_buffers();
523+
unlink(output_path);
524+
unlink(image_path);
525+
rmdir(tempdir);
526+
}
527+
END_TEST
528+
275529
Suite *wolfboot_suite(void)
276530
{
277531
Suite *s = suite_create("sign-encrypted-output");
@@ -281,6 +535,10 @@ Suite *wolfboot_suite(void)
281535
tcase_add_test(tcase, test_make_header_ex_fails_when_image_reopen_fails);
282536
tcase_add_test(tcase,
283537
test_make_header_ex_grows_header_for_cert_chain_and_digest_tlvs);
538+
tcase_add_test(tcase,
539+
test_make_header_ex_roundtrip_custom_tlvs_via_wolfboot_parser);
540+
tcase_add_test(tcase,
541+
test_make_header_ex_roundtrip_finds_tlv_that_exactly_fills_header);
284542
suite_add_tcase(s, tcase);
285543

286544
return s;

0 commit comments

Comments
 (0)