Skip to content

Commit

Permalink
Added more unit tests. Found OOB access.
Browse files Browse the repository at this point in the history
  • Loading branch information
danielinux committed Aug 13, 2024
1 parent 295e3a8 commit 6083b9e
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 9 deletions.
3 changes: 2 additions & 1 deletion tools/unit-tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ unit-enc-nvm-flagshome:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS \
-DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA -DEXT_FLASH -DHAVE_CHACHA -DFLAGS_HOME
unit-enc-nvm-flagshome:WOLFCRYPT_SRC+=$(WOLFCRYPT)/wolfcrypt/src/chacha.c
unit-delta:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS -DDELTA_UPDATES -DDELTA_BLOCK_SIZE=512
unit-update-flash:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH -DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED
unit-update-flash:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT -DPART_SWAP_EXT



Expand Down
46 changes: 43 additions & 3 deletions tools/unit-tests/unit-mock-flash.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
/* unit-mock-flash.c
*
* Mock flash access for unit tests
* usage: #include "unit-mock-flash.c"
*
*
* Copyright (C) 2024 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/

static int locked = 1;
static int ext_locked = 1;
static int erased_boot = 0;
static int erased_update = 0;
static int erased_swap = 0;
Expand All @@ -18,6 +43,12 @@ int hal_flash_write(haladdr_t address, const uint8_t *data, int len)
int i;
uint8_t *a = (uint8_t *)address;
fail_if(locked, "Attempting to write to a locked FLASH");
if ((address >= WOLFBOOT_PARTITION_SWAP_ADDRESS) &&
(address < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_SECTOR_SIZE)) {
for (i = 0; i < len; i++) {
a[i] = data[i];
}
}
if ((address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) &&
(address < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
for (i = 0; i < len; i++) {
Expand Down Expand Up @@ -92,7 +123,6 @@ void hal_prepare_boot(void)

int ext_flash_erase(uintptr_t address, int len)
{
printf("%s", __FUNCTION__);
if ((address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) &&
(address < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
erased_update++;
Expand All @@ -117,8 +147,7 @@ int ext_flash_write(uintptr_t address, const uint8_t *data, int len)
{
int i;
uint8_t *a = (uint8_t *)address;
fail_if(locked, "Attempting to write to a locked FLASH");
printf("%s", __FUNCTION__);
fail_if(ext_locked, "Attempting to write to a locked FLASH");
for (i = 0; i < len; i++) {
a[i] = data[i];
}
Expand All @@ -135,6 +164,17 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len)
return 0;
}

void ext_flash_unlock(void)
{
fail_unless(ext_locked, "Double ext unlock detected\n");
ext_locked--;
}
void ext_flash_lock(void)
{
fail_if(ext_locked, "Double ext lock detected\n");
ext_locked++;
}

/* A simple mock memory */
static int mmap_file(const char *path, uint8_t *address, uint32_t len,
uint8_t** ret_address)
Expand Down
191 changes: 186 additions & 5 deletions tools/unit-tests/unit-update-flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#define MOCK_ADDRESS_SWAP 0xCE000000

#define TEST_SIZE_SMALL 5300
#define TEST_SIZE_BIG 9800
#define TEST_SIZE_LARGE 9800

#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -68,10 +68,9 @@ static void reset_mock_stats(void)
}


static void prepare_boot_image(int version)
static void prepare_flash(void)
{
int ret;
uint8_t part;
ret = mmap_file("/tmp/wolfboot-unit-ext-file.bin", MOCK_ADDRESS_UPDATE,
WOLFBOOT_PARTITION_SIZE, NULL);
fail_if(ret < 0);
Expand All @@ -83,8 +82,15 @@ static void prepare_boot_image(int version)
fail_if(ret < 0);
hal_flash_unlock();
hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS, WOLFBOOT_PARTITION_SIZE);
hal_flash_erase(WOLFBOOT_PARTITION_UPDATE_ADDRESS, WOLFBOOT_PARTITION_SIZE);
hal_flash_lock();
}

static void cleanup_flash(void)
{
munmap(MOCK_ADDRESS_UPDATE, WOLFBOOT_PARTITION_SIZE);
munmap(MOCK_ADDRESS_BOOT, WOLFBOOT_PARTITION_SIZE);
munmap(MOCK_ADDRESS_SWAP, WOLFBOOT_SECTOR_SIZE);
}


Expand Down Expand Up @@ -170,28 +176,168 @@ static int add_payload(uint8_t part, uint32_t version, uint32_t size)
START_TEST (test_empty_panic)
{
reset_mock_stats();
prepare_boot_image(1);
prepare_flash();
wolfBoot_start();
fail_if(wolfBoot_staged_ok);
fail_unless(wolfBoot_panicked);
cleanup_flash();

}
END_TEST


START_TEST (test_sunnyday_noupdate)
{
reset_mock_stats();
prepare_flash();
add_payload(PART_BOOT, 1, TEST_SIZE_SMALL);
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 1);
cleanup_flash();

}
END_TEST

START_TEST (test_forward_update_samesize_notrigger) {
reset_mock_stats();
prepare_boot_image(1);
prepare_flash();
add_payload(PART_BOOT, 1, TEST_SIZE_SMALL);
add_payload(PART_UPDATE, 2, TEST_SIZE_SMALL);
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 1);
cleanup_flash();
}
END_TEST

START_TEST (test_forward_update_samesize) {
reset_mock_stats();
prepare_flash();
add_payload(PART_BOOT, 1, TEST_SIZE_SMALL);
add_payload(PART_UPDATE, 2, TEST_SIZE_SMALL);
wolfBoot_update_trigger();
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 2);
cleanup_flash();
}
END_TEST

START_TEST (test_forward_update_tolarger) {
reset_mock_stats();
prepare_flash();
add_payload(PART_BOOT, 1, TEST_SIZE_SMALL);
add_payload(PART_UPDATE, 2, TEST_SIZE_LARGE);
wolfBoot_update_trigger();
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 2);
cleanup_flash();
}
END_TEST

START_TEST (test_forward_update_tosmaller) {
reset_mock_stats();
prepare_flash();
add_payload(PART_BOOT, 1, TEST_SIZE_LARGE);
add_payload(PART_UPDATE, 2, TEST_SIZE_SMALL);
wolfBoot_update_trigger();
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 2);
cleanup_flash();
}
END_TEST

START_TEST (test_forward_update_sameversion_denied) {
reset_mock_stats();
prepare_flash();
add_payload(PART_BOOT, 1, TEST_SIZE_SMALL);
add_payload(PART_UPDATE, 1, TEST_SIZE_LARGE);
wolfBoot_update_trigger();
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 1);
fail_if(*(uint32_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + 4) != TEST_SIZE_SMALL);
cleanup_flash();
}
END_TEST

START_TEST (test_update_oldversion_denied) {
reset_mock_stats();
prepare_flash();
add_payload(PART_BOOT, 2, TEST_SIZE_SMALL);
add_payload(PART_UPDATE, 1, TEST_SIZE_LARGE);
wolfBoot_update_trigger();
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 2);
fail_if(*(uint32_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + 4) != TEST_SIZE_SMALL);
cleanup_flash();
}

START_TEST (test_invalid_update_type) {
reset_mock_stats();
prepare_flash();
uint16_t word16 = 0xBAAD;
add_payload(PART_BOOT, 1, TEST_SIZE_SMALL);
add_payload(PART_UPDATE, 2, TEST_SIZE_SMALL);
ext_flash_unlock();
ext_flash_write(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 20, &word16, 2);
ext_flash_lock();
wolfBoot_update_trigger();
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 1);
cleanup_flash();
}

START_TEST (test_update_toolarge) {
uint32_t very_large = WOLFBOOT_PARTITION_SIZE;
reset_mock_stats();
prepare_flash();
add_payload(PART_BOOT, 1, TEST_SIZE_SMALL);
add_payload(PART_UPDATE, 2, TEST_SIZE_LARGE);
/* Change the size in the header to be larger than the actual size */
ext_flash_unlock();
ext_flash_write(WOLFBOOT_PARTITION_UPDATE_ADDRESS + 4, &very_large, 4);
ext_flash_lock();

wolfBoot_update_trigger();
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 1);
cleanup_flash();
}

START_TEST (test_invalid_sha) {
uint8_t bad_digest[SHA256_DIGEST_SIZE];
reset_mock_stats();
prepare_flash();
add_payload(PART_BOOT, 1, TEST_SIZE_SMALL);
add_payload(PART_UPDATE, 2, TEST_SIZE_SMALL);

memset(bad_digest, 0xBA, SHA256_DIGEST_SIZE);
ext_flash_unlock();
ext_flash_write(WOLFBOOT_PARTITION_UPDATE_ADDRESS + DIGEST_TLV_OFF_IN_HDR + 4, bad_digest, SHA256_DIGEST_SIZE);
ext_flash_lock();
wolfBoot_update_trigger();
wolfBoot_start();
fail_if(wolfBoot_panicked);
fail_unless(wolfBoot_staged_ok);
fail_if(wolfBoot_current_firmware_version() != 1);
cleanup_flash();
}

Suite *wolfboot_suite(void)
{
Expand All @@ -202,12 +348,46 @@ Suite *wolfboot_suite(void)
TCase *empty_panic = tcase_create("Empty partition panic test");
TCase *sunnyday_noupdate =
tcase_create("Sunny day test with no update available");
TCase *forward_update_samesize =
tcase_create("Forward update with same size");
TCase *forward_update_tolarger =
tcase_create("Forward update to larger size");
TCase *forward_update_tosmaller = tcase_create("Forward update to smaller size");
TCase *forward_update_sameversion_denied =
tcase_create("Forward update to same version denied");
TCase *update_oldversion_denied =
tcase_create("Update to older version denied");
TCase *invalid_update_type =
tcase_create("Invalid update type");
TCase *update_toolarge = tcase_create("Update too large");
TCase *invalid_sha = tcase_create("Invalid SHA digest");



tcase_add_test(empty_panic, test_empty_panic);
tcase_add_test(sunnyday_noupdate, test_sunnyday_noupdate);
tcase_add_test(forward_update_samesize, test_forward_update_samesize);
tcase_add_test(forward_update_tolarger, test_forward_update_tolarger);
tcase_add_test(forward_update_tosmaller, test_forward_update_tosmaller);
tcase_add_test(forward_update_sameversion_denied, test_forward_update_sameversion_denied);
tcase_add_test(update_oldversion_denied, test_update_oldversion_denied);
tcase_add_test(invalid_update_type, test_invalid_update_type);
tcase_add_test(update_toolarge, test_update_toolarge);
tcase_add_test(invalid_sha, test_invalid_sha);



suite_add_tcase(s, empty_panic);
suite_add_tcase(s, sunnyday_noupdate);
suite_add_tcase(s, forward_update_samesize);
suite_add_tcase(s, forward_update_tolarger);
suite_add_tcase(s, forward_update_tosmaller);
suite_add_tcase(s, forward_update_sameversion_denied);
suite_add_tcase(s, update_oldversion_denied);
suite_add_tcase(s, invalid_update_type);
suite_add_tcase(s, update_toolarge);
suite_add_tcase(s, invalid_sha);


return s;
}
Expand All @@ -219,6 +399,7 @@ int main(int argc, char *argv[])
argv0 = strdup(argv[0]);
Suite *s = wolfboot_suite();
SRunner *sr = srunner_create(s);
srunner_set_fork_status(sr, CK_NOFORK);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
Expand Down

0 comments on commit 6083b9e

Please sign in to comment.