mirror of https://github.com/wolfSSL/wolfBoot.git
Merge pull request #379 from danielinux/unit-test-extend
Added more unit tests. Added 'make cov'.pull/383/head
commit
c1abfdd630
|
@ -22,27 +22,10 @@ jobs:
|
|||
run: |
|
||||
make keysclean && make -C tools/keytools clean && rm -f include/target.h
|
||||
|
||||
- name: Build wolfboot and test footprint
|
||||
- name: Build unit tests
|
||||
run: |
|
||||
make -C tools/unit-tests
|
||||
|
||||
|
||||
- name: Run manifest header parser unit tests
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
./tools/unit-tests/unit-parser
|
||||
|
||||
- name: Run non-encrypted ext_flash unit tests
|
||||
run: |
|
||||
./tools/unit-tests/unit-extflash
|
||||
|
||||
- name: Run aes128 ext_flash unit tests
|
||||
run: |
|
||||
./tools/unit-tests/unit-aes128
|
||||
|
||||
- name: Run aes256 ext_flash unit tests
|
||||
run: |
|
||||
./tools/unit-tests/unit-aes256
|
||||
|
||||
- name: Run chacha20 ext_flash unit tests
|
||||
run: |
|
||||
./tools/unit-tests/unit-chacha20
|
||||
make -C tools/unit-tests run
|
||||
|
|
|
@ -134,4 +134,10 @@ stage1/loader_stage1.ld
|
|||
debug/lauterbach
|
||||
|
||||
#cland cache
|
||||
.cache/*
|
||||
.cache/*
|
||||
|
||||
#gcov files
|
||||
*.gcov
|
||||
*.gcda
|
||||
*.gcno
|
||||
coverage.*
|
||||
|
|
|
@ -398,6 +398,7 @@ static int RAMFUNCTION partition_magic_write(uint8_t part, uintptr_t addr)
|
|||
(void*)&wolfboot_magic_trail, sizeof(uint32_t));
|
||||
#endif
|
||||
|
||||
#ifndef MOCK_PARTITION_TRAILER
|
||||
#ifdef EXT_FLASH
|
||||
|
||||
/**
|
||||
|
@ -558,6 +559,7 @@ static void RAMFUNCTION set_partition_magic(uint8_t part)
|
|||
}
|
||||
}
|
||||
#endif /* EXT_FLASH */
|
||||
#endif /* MOCK_PARTITION_TRAILER */
|
||||
|
||||
|
||||
|
||||
|
@ -626,6 +628,8 @@ int RAMFUNCTION wolfBoot_set_partition_state(uint8_t part, uint8_t newst)
|
|||
{
|
||||
uint32_t *magic;
|
||||
uint8_t *state;
|
||||
if (part == PART_NONE)
|
||||
return -1;
|
||||
magic = get_partition_magic(part);
|
||||
if (*magic != WOLFBOOT_MAGIC_TRAIL)
|
||||
set_partition_magic(part);
|
||||
|
@ -669,6 +673,8 @@ int RAMFUNCTION wolfBoot_get_partition_state(uint8_t part, uint8_t *st)
|
|||
{
|
||||
uint32_t *magic;
|
||||
uint8_t *state;
|
||||
if (part == PART_NONE)
|
||||
return -1;
|
||||
magic = get_partition_magic(part);
|
||||
if (*magic != WOLFBOOT_MAGIC_TRAIL)
|
||||
return -1;
|
||||
|
|
|
@ -7,15 +7,50 @@ endif
|
|||
|
||||
CFLAGS=-I. -I../../src -I../../include -I../../lib/wolfssl
|
||||
CFLAGS+=-g -ggdb
|
||||
CFLAGS+=-fprofile-arcs
|
||||
CFLAGS+=-ftest-coverage
|
||||
CFLAGS+=--coverage
|
||||
LDFLAGS+=-fprofile-arcs
|
||||
LDFLAGS+=-ftest-coverage
|
||||
WOLFCRYPT=../../lib/wolfssl/
|
||||
|
||||
|
||||
|
||||
all: unit-parser unit-extflash unit-aes128 unit-aes256 unit-chacha20
|
||||
TESTS:=unit-parser unit-extflash unit-aes128 unit-aes256 unit-chacha20 unit-pci \
|
||||
unit-mock-state unit-sectorflags unit-image
|
||||
|
||||
all: $(TESTS)
|
||||
|
||||
cov:
|
||||
gcovr -f "^\.\.\/\.\.\/src.*\.c" -r ../.. --verbose \
|
||||
--merge-mode-functions merge-use-line-0 \
|
||||
--html-medium-threshold 60 \
|
||||
--html-high-threshold 80 \
|
||||
--html-details coverage.html
|
||||
firefox coverage.html
|
||||
|
||||
run: $(TESTS)
|
||||
for unit in $(TESTS); do \
|
||||
./$$unit || exit 1; \
|
||||
done
|
||||
|
||||
|
||||
unit-aes128:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_AES128
|
||||
unit-aes256:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_AES256
|
||||
unit-chacha20:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA
|
||||
unit-parser:CFLAGS+=-DNVM_FLASH_WRITEONCE
|
||||
|
||||
|
||||
WOLFCRYPT_SRC:=$(WOLFCRYPT)/wolfcrypt/src/sha.c \
|
||||
$(WOLFCRYPT)/wolfcrypt/src/sha256.c \
|
||||
$(WOLFCRYPT)/wolfcrypt/src/sp_int.c \
|
||||
$(WOLFCRYPT)/wolfcrypt/src/sp_c64.c \
|
||||
$(WOLFCRYPT)/wolfcrypt/src/random.c \
|
||||
$(WOLFCRYPT)/wolfcrypt/src/memory.c
|
||||
|
||||
WOLFCRYPT_CFLAGS+=-DWOLFSSL_USER_SETTINGS -DWOLFBOOT_SIGN_ECC256 -DWOLFBOOT_SIGN_ECC256 -DHAVE_ECC_KEY_IMPORT -DWOLFBOOT_HASH_SHA256 -D__WOLFBOOT
|
||||
|
||||
|
||||
|
||||
../../include/target.h: FORCE
|
||||
cp -f target.h $@
|
||||
|
@ -24,7 +59,7 @@ unit-extflash.o: FORCE
|
|||
rm -f $@
|
||||
gcc -c -o $@ unit-extflash.c $(CFLAGS)
|
||||
|
||||
unit-parser: ../../include/target.h unit-parser.o
|
||||
unit-parser: ../../include/target.h unit-parser.c
|
||||
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-extflash: ../../include/target.h unit-extflash.c
|
||||
|
@ -42,10 +77,23 @@ unit-chacha20: ../../include/target.h unit-extflash.c
|
|||
unit-pci: unit-pci.c ../../src/pci.c
|
||||
gcc -o $@ $< $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-mock-state: ../../include/target.h unit-mock-state.c
|
||||
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-sectorflags: ../../include/target.h unit-sectorflags.c
|
||||
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-image: unit-image.c unit-common.c $(WOLFCRYPT_SRC)
|
||||
gcc -o $@ $^ $(CFLAGS) $(WOLFCRYPT_CFLAGS) $(LDFLAGS)
|
||||
|
||||
%.o:%.c
|
||||
gcc -c -o $@ $^ $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f unit-parser unit-extflash *.o
|
||||
|
||||
covclean:
|
||||
rm -f *.gcov *.gcno *.gcda coverage.*
|
||||
|
||||
clean: covclean
|
||||
rm -f $(TESTS) *.o *.gcno *.gcda coverage.*
|
||||
|
||||
.PHONY: FORCE
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/* unit-common.c
|
||||
*
|
||||
* Unit test common tools
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2023 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 2 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
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <check.h>
|
||||
#include "target.h"
|
||||
#define FLASH_SIZE (33 * 1024)
|
||||
|
||||
/* Emulation of external flash with a static buffer of 32KB (update) + 1KB (swap) */
|
||||
uint8_t flash[FLASH_SIZE];
|
||||
|
||||
/* Flash lock/unlock counter */
|
||||
static int elocked = 0;
|
||||
|
||||
#ifndef BACKUP_MOCKED
|
||||
|
||||
uint8_t image_backup(uint8_t part_id)
|
||||
{
|
||||
printf("Called image_backup\n");
|
||||
return 0xFF; /* PART_NONE */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef EXT_MOCKED
|
||||
|
||||
/* Mocks for ext_flash_read, ext_flash_write, and ext_flash_erase functions */
|
||||
int ext_flash_read(uintptr_t address, uint8_t *data, int len) {
|
||||
printf("Called ext_flash_read %p %p %d\n", address, data, len);
|
||||
|
||||
/* Check that the read address and size are within the bounds of the flash memory */
|
||||
ck_assert_int_le(address + len, FLASH_SIZE);
|
||||
|
||||
/* Copy the data from the flash memory to the output buffer */
|
||||
memcpy(data, &flash[address], len);
|
||||
|
||||
printf("Return value: %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int ext_flash_write(uintptr_t address, const uint8_t *data, int len) {
|
||||
printf("Called ext_flash_write %p %p %d\n", address, data, len);
|
||||
|
||||
|
||||
/* Check that the write address and size are within the bounds of the flash memory */
|
||||
ck_assert_int_le(address + len, FLASH_SIZE);
|
||||
|
||||
/* Copy the data from the input buffer to the flash memory */
|
||||
memcpy(&flash[address], data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext_flash_erase(uintptr_t address, int len) {
|
||||
/* Check that the erase address and size are within the bounds of the flash memory */
|
||||
ck_assert_int_le(address + len, FLASH_SIZE);
|
||||
|
||||
/* Check that address is aligned to WOLFBOOT_SECTOR_SIZE */
|
||||
ck_assert_int_eq(address, address & ~(WOLFBOOT_SECTOR_SIZE - 1));
|
||||
|
||||
/* Check that len is aligned to WOLFBOOT_SECTOR_SIZE */
|
||||
ck_assert_int_eq(len, len & ~(WOLFBOOT_SECTOR_SIZE - 1));
|
||||
|
||||
|
||||
/* Erase the flash memory by setting each byte to 0xFF, WOLFBOOT_SECTOR_SIZE bytes at a time */
|
||||
uint32_t i;
|
||||
for (i = address; i < address + len; i += WOLFBOOT_SECTOR_SIZE) {
|
||||
memset(&flash[i], 0xFF, WOLFBOOT_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ext_flash_unlock(void)
|
||||
{
|
||||
fail_unless(elocked, "Double ext unlock detected\n");
|
||||
elocked--;
|
||||
}
|
||||
void ext_flash_lock(void)
|
||||
{
|
||||
fail_if(elocked, "Double ext lock detected\n");
|
||||
elocked++;
|
||||
}
|
||||
|
||||
#endif /* EXT_MOCKED */
|
|
@ -0,0 +1,607 @@
|
|||
/* unit-image.c
|
||||
*
|
||||
* Unit test for parser functions in image.c
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2023 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 2 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
|
||||
*/
|
||||
|
||||
/* Option to enable sign tool debugging */
|
||||
/* Must also define DEBUG_WOLFSSL in user_settings.h */
|
||||
#define WOLFBOOT_HASH_SHA256
|
||||
#define EXT_FLASH
|
||||
#define PART_UPDATE_EXT
|
||||
#define NVM_FLASH_WRITEONCE
|
||||
|
||||
#if defined(ENCRYPT_WITH_AES256) || defined(ENCRYPT_WITH_AES128)
|
||||
#define WOLFSSL_AES_COUNTER
|
||||
#define WOLFSSL_AES_DIRECT
|
||||
#endif
|
||||
#if defined(ENCRYPT_WITH_AES256)
|
||||
#define WOLFSSL_AES_256
|
||||
#endif
|
||||
#if defined(ENCRYPT_WITH_CHACHA)
|
||||
#define HAVE_CHACHA
|
||||
#endif
|
||||
//#define WC_NO_HARDEN
|
||||
#define ECC_TIMING_RESISTANT
|
||||
|
||||
#define WOLFSSL_USER_SETTINGS
|
||||
#define ENCRYPT_KEY "123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
#define UNIT_TEST
|
||||
#define WOLFBOOT_SIGN_ECC256
|
||||
#define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ECC256
|
||||
#define __WOLFBOOT
|
||||
|
||||
#include <stdio.h>
|
||||
#include <check.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "user_settings.h"
|
||||
#include "wolfssl/wolfcrypt/sha.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
|
||||
#include "unit-keystore.c"
|
||||
|
||||
#include "image.c"
|
||||
|
||||
const uint8_t a;
|
||||
|
||||
static int ecc_init_fail = 1;
|
||||
static int ecc_import_fail = 1;
|
||||
|
||||
static int verify_called = 0;
|
||||
|
||||
static int find_header_fail = 0;
|
||||
static int find_header_called = 0;
|
||||
static int find_header_mocked = 1;
|
||||
|
||||
static const unsigned char pubkey_digest[SHA256_DIGEST_SIZE] = {
|
||||
0x17, 0x20, 0xa5, 0x9b, 0xe0, 0x9b, 0x80, 0x0c, 0xaa, 0xc4, 0xf5, 0x3f,
|
||||
0xae, 0xe5, 0x72, 0x4f, 0xf2, 0x1f, 0x33, 0x53, 0xd1, 0xd4, 0xcd, 0x8b,
|
||||
0x5c, 0xc3, 0x4e, 0xda, 0xea, 0xc8, 0x4a, 0x68
|
||||
};
|
||||
|
||||
|
||||
static const unsigned char test_img_v200000000_signed_bin[] = {
|
||||
0x57, 0x4f, 0x4c, 0x46, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
|
||||
0x00, 0xc2, 0xeb, 0x0b, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x08, 0x00,
|
||||
0x77, 0x33, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
|
||||
0x01, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x20, 0x00,
|
||||
0xda, 0x9c, 0xee, 0x7e, 0x12, 0xcf, 0xa0, 0xe1, 0xda, 0xa1, 0xb4, 0x23,
|
||||
0xbf, 0x31, 0xe5, 0xdd, 0x6f, 0x58, 0xfe, 0xd9, 0x8d, 0xb7, 0x7b, 0x31,
|
||||
0x6f, 0x7b, 0x01, 0x84, 0xe0, 0x63, 0x5e, 0xe9, 0x10, 0x00, 0x20, 0x00,
|
||||
0x17, 0x20, 0xa5, 0x9b, 0xe0, 0x9b, 0x80, 0x0c, 0xaa, 0xc4, 0xf5, 0x3f,
|
||||
0xae, 0xe5, 0x72, 0x4f, 0xf2, 0x1f, 0x33, 0x53, 0xd1, 0xd4, 0xcd, 0x8b,
|
||||
0x5c, 0xc3, 0x4e, 0xda, 0xea, 0xc8, 0x4a, 0x68, 0x20, 0x00, 0x40, 0x00,
|
||||
0xb0, 0x22, 0xb3, 0x91, 0xf7, 0x4e, 0xe1, 0x37, 0x6c, 0xb5, 0x64, 0x2e,
|
||||
0xe6, 0x80, 0x4b, 0xcb, 0xa7, 0x1d, 0xa1, 0xa7, 0x16, 0x2e, 0x4b, 0xa5,
|
||||
0xee, 0x67, 0xd2, 0x02, 0xff, 0x1b, 0xd3, 0x4c, 0xc6, 0x09, 0x62, 0x66,
|
||||
0x08, 0x4c, 0xfc, 0x32, 0x4b, 0x47, 0x56, 0xe0, 0x9b, 0x98, 0xd9, 0xa4,
|
||||
0x2a, 0x5e, 0x53, 0xd3, 0xb4, 0xde, 0x80, 0xe1, 0x9a, 0x95, 0x2a, 0x58,
|
||||
0xc9, 0xd6, 0x9a, 0x2a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x54, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6d, 0x61,
|
||||
0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a
|
||||
};
|
||||
|
||||
|
||||
static const unsigned char test_img_v200000000_wrong_signature_bin[] = {
|
||||
0x57, 0x4f, 0x4c, 0x46, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
|
||||
0x00, 0xc2, 0xeb, 0x0b, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x08, 0x00,
|
||||
0x77, 0x33, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
|
||||
0x01, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x20, 0x00,
|
||||
0xda, 0x9c, 0xee, 0x7e, 0x12, 0xcf, 0xa0, 0xe1, 0xda, 0xa1, 0xb4, 0x23,
|
||||
0xbf, 0x31, 0xe5, 0xdd, 0x6f, 0x58, 0xfe, 0xd9, 0x8d, 0xb7, 0x7b, 0x31,
|
||||
0x6f, 0x7b, 0x01, 0x84, 0xe0, 0x63, 0x5e, 0xe9, 0x10, 0x00, 0x20, 0x00,
|
||||
0x17, 0x20, 0xa5, 0x9b, 0xe0, 0x9b, 0x80, 0x0c, 0xaa, 0xc4, 0xf5, 0x3f,
|
||||
0xae, 0xe5, 0x72, 0x4f, 0xf2, 0x1f, 0x33, 0x53, 0xd1, 0xd4, 0xcd, 0x8b,
|
||||
0x5c, 0xc3, 0x4e, 0xda, 0xea, 0xc8, 0x4a, 0x68, 0x20, 0x00, 0x40, 0x00,
|
||||
0xb0, 0x22, 0xb3, 0x91, 0xf7, 0x4e, 0xe1, 0x37, 0x6c, 0xb5, 0x64, 0x2f,
|
||||
0xe6, 0x80, 0x4b, 0xcb, 0xa7, 0x1d, 0xa1, 0xa7, 0x16, 0x2e, 0x4b, 0xa5,
|
||||
0xee, 0x67, 0xd2, 0x02, 0xff, 0x1b, 0xd3, 0x4c, 0xc6, 0x09, 0x62, 0x66,
|
||||
0x08, 0x4c, 0xfc, 0x32, 0x4b, 0x47, 0x56, 0xe0, 0x9b, 0x98, 0xd9, 0xa4,
|
||||
0x2a, 0x5e, 0x53, 0xd3, 0xb4, 0xde, 0x80, 0xe1, 0x9a, 0x95, 0x2a, 0x58,
|
||||
0xc9, 0xd6, 0x9a, 0x2a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x54, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6d, 0x61,
|
||||
0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a
|
||||
};
|
||||
|
||||
static const unsigned char test_img_v200000000_wrong_pubkey_bin[] = {
|
||||
0x57, 0x4f, 0x4c, 0x46, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
|
||||
0x00, 0xc2, 0xeb, 0x0b, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x08, 0x00,
|
||||
0x77, 0x33, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
|
||||
0x01, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x20, 0x00,
|
||||
0xda, 0x9c, 0xee, 0x7e, 0x12, 0xcf, 0xa0, 0xe1, 0xda, 0xa1, 0xb4, 0x24,
|
||||
0xbf, 0x31, 0xe5, 0xdd, 0x6f, 0x58, 0xfe, 0xd9, 0x8d, 0xb7, 0x7b, 0x31,
|
||||
0x6f, 0x7b, 0x01, 0x84, 0xe0, 0x63, 0x5e, 0xe9, 0x10, 0x00, 0x20, 0x00,
|
||||
0x17, 0x20, 0xa5, 0x9b, 0xe0, 0x9b, 0x80, 0x0c, 0xaa, 0xc4, 0xf5, 0x3f,
|
||||
0xae, 0xe5, 0x72, 0x4f, 0xf2, 0x1f, 0x33, 0x53, 0xd1, 0xd4, 0xcd, 0x8b,
|
||||
0x5c, 0xc3, 0x4e, 0xda, 0xea, 0xc8, 0x4a, 0x68, 0x20, 0x00, 0x40, 0x00,
|
||||
0xb0, 0x22, 0xb3, 0x91, 0xf7, 0x4e, 0xe1, 0x37, 0x6c, 0xb5, 0x64, 0x2e,
|
||||
0xe6, 0x80, 0x4b, 0xcb, 0xa7, 0x1d, 0xa1, 0xa7, 0x16, 0x2e, 0x4b, 0xa5,
|
||||
0xee, 0x67, 0xd2, 0x02, 0xff, 0x1b, 0xd3, 0x4c, 0xc6, 0x09, 0x62, 0x66,
|
||||
0x08, 0x4c, 0xfc, 0x32, 0x4b, 0x47, 0x56, 0xe0, 0x9b, 0x98, 0xd9, 0xa4,
|
||||
0x2a, 0x5e, 0x53, 0xd3, 0xb4, 0xde, 0x80, 0xe1, 0x9a, 0x95, 0x2a, 0x58,
|
||||
0xc9, 0xd6, 0x9a, 0x2a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x54, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6d, 0x61,
|
||||
0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a
|
||||
};
|
||||
static const unsigned int test_img_len = 275;
|
||||
|
||||
|
||||
unsigned char test_img_v123_signed_bin[] = {
|
||||
0x57, 0x4f, 0x4c, 0x46, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
|
||||
0x7b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x08, 0x00,
|
||||
0x77, 0x33, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
|
||||
0x01, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x20, 0x00,
|
||||
0x89, 0xbd, 0x89, 0x01, 0xb9, 0xaf, 0xa9, 0xbd, 0x78, 0x88, 0xba, 0xd1,
|
||||
0x97, 0xc1, 0x6f, 0xd0, 0x7f, 0x11, 0xbd, 0x29, 0x97, 0x4a, 0x10, 0x27,
|
||||
0xa0, 0x53, 0x8c, 0x32, 0x3d, 0xfc, 0xc9, 0x9b, 0x10, 0x00, 0x20, 0x00,
|
||||
0x17, 0x20, 0xa5, 0x9b, 0xe0, 0x9b, 0x80, 0x0c, 0xaa, 0xc4, 0xf5, 0x3f,
|
||||
0xae, 0xe5, 0x72, 0x4f, 0xf2, 0x1f, 0x33, 0x53, 0xd1, 0xd4, 0xcd, 0x8b,
|
||||
0x5c, 0xc3, 0x4e, 0xda, 0xea, 0xc8, 0x4a, 0x68, 0x20, 0x00, 0x40, 0x00,
|
||||
0xfc, 0x1d, 0x02, 0x10, 0xb7, 0x60, 0x63, 0x7b, 0x55, 0xe0, 0x0e, 0xd5,
|
||||
0xb0, 0x64, 0xcd, 0x14, 0x9c, 0x1c, 0x80, 0x5f, 0x02, 0xb5, 0x54, 0x67,
|
||||
0x54, 0x93, 0x6d, 0xaf, 0x72, 0x74, 0x7b, 0x96, 0x94, 0x5c, 0x62, 0xb2,
|
||||
0x6d, 0x0f, 0xc9, 0xf4, 0x9f, 0x82, 0xa7, 0xd4, 0x28, 0xb9, 0x4c, 0x64,
|
||||
0x01, 0x5d, 0x03, 0x0f, 0x81, 0x05, 0x13, 0xf1, 0xe0, 0xbd, 0xdc, 0xe2,
|
||||
0x17, 0x84, 0xa3, 0x25, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x54, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6d, 0x61,
|
||||
0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a
|
||||
};
|
||||
unsigned int test_img_v123_signed_bin_len = 275;
|
||||
|
||||
|
||||
static uint16_t _find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr)
|
||||
{
|
||||
uint8_t *p = haystack;
|
||||
uint16_t len;
|
||||
const volatile uint8_t *max_p = (haystack - IMAGE_HEADER_OFFSET) +
|
||||
IMAGE_HEADER_SIZE;
|
||||
*ptr = NULL;
|
||||
if (p > max_p) {
|
||||
printf("Illegal address (too high)\n");
|
||||
return 0;
|
||||
}
|
||||
while ((p + 4) < max_p) {
|
||||
if ((p[0] == 0) && (p[1] == 0)) {
|
||||
printf("Explicit end of options reached\n");
|
||||
break;
|
||||
}
|
||||
if (*p == HDR_PADDING) {
|
||||
/* Padding byte (skip one position) */
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
/* Sanity check to prevent dereferencing unaligned half-words */
|
||||
if ((((unsigned long)p) & 0x01) != 0) {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
len = p[2] | (p[3] << 8);
|
||||
if ((4 + len) > (uint16_t)(IMAGE_HEADER_SIZE - IMAGE_HEADER_OFFSET)) {
|
||||
printf("This field is too large (bigger than the space available "
|
||||
"in the current header)\n");
|
||||
printf("%d %d %d\n", len, IMAGE_HEADER_SIZE, IMAGE_HEADER_OFFSET);
|
||||
break;
|
||||
}
|
||||
if (p + 4 + len > max_p) {
|
||||
printf("This field is too large and would overflow the image "
|
||||
"header\n");
|
||||
break;
|
||||
}
|
||||
if ((p[0] | (p[1] << 8)) == type) {
|
||||
*ptr = (p + 4);
|
||||
return len;
|
||||
}
|
||||
p += 4 + len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t wolfBoot_get_blob_type(uint8_t *addr)
|
||||
{
|
||||
return HDR_IMG_TYPE_APP;
|
||||
}
|
||||
|
||||
uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr)
|
||||
{
|
||||
find_header_called++;
|
||||
if (find_header_mocked) {
|
||||
if (find_header_fail) {
|
||||
return -1;
|
||||
} else {
|
||||
return sizeof(uint16_t);
|
||||
}
|
||||
} else {
|
||||
return _find_header(haystack, type, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int wc_ecc_init(ecc_key* key) {
|
||||
if (ecc_init_fail)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_ecc_free(ecc_key *key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_ecc_import_unsigned(ecc_key* key, const byte* qx, const byte* qy,
|
||||
const byte* d, int curve_id)
|
||||
{
|
||||
if (ecc_import_fail)
|
||||
return -1;
|
||||
|
||||
key->type = ECC_PUBLICKEY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
|
||||
word32 hashlen, int* res, ecc_key* key)
|
||||
{
|
||||
verify_called++;
|
||||
*res = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
START_TEST(test_verify_signature)
|
||||
{
|
||||
uint8_t pubkey[32];
|
||||
struct wolfBoot_image test_img;
|
||||
|
||||
test_img.part = PART_UPDATE;
|
||||
test_img.fw_size = test_img_len;
|
||||
test_img.fw_base = 0;
|
||||
|
||||
wolfBoot_verify_signature(0, NULL, NULL);
|
||||
ck_assert_int_eq(verify_called, 0);
|
||||
|
||||
ecc_init_fail = 1;
|
||||
wolfBoot_verify_signature(0, NULL, pubkey);
|
||||
ck_assert_int_eq(verify_called, 0);
|
||||
|
||||
ecc_init_fail = 0;
|
||||
verify_called = 0;
|
||||
ecc_import_fail = 1;
|
||||
wolfBoot_verify_signature(0, NULL, pubkey);
|
||||
ck_assert_int_eq(verify_called, 0);
|
||||
|
||||
ecc_init_fail = 0;
|
||||
ecc_import_fail = 0;
|
||||
verify_called = 0;
|
||||
find_header_mocked = 0;
|
||||
ext_flash_erase(0, 2 * WOLFBOOT_SECTOR_SIZE);
|
||||
ext_flash_write(0, test_img_v200000000_signed_bin,
|
||||
test_img_len);
|
||||
wolfBoot_verify_signature(0, &test_img, pubkey);
|
||||
ck_assert_int_eq(verify_called, 1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST(test_sha_ops)
|
||||
{
|
||||
uint8_t hash[SHA256_DIGEST_SIZE];
|
||||
static uint8_t FlashImg[32 * 1024];
|
||||
uint8_t *retp = NULL;
|
||||
struct wolfBoot_image test_img;
|
||||
uint32_t offset;
|
||||
uint32_t sz = 0;
|
||||
find_header_mocked = 1;
|
||||
memset(&test_img, 0, sizeof(struct wolfBoot_image));
|
||||
test_img.part = PART_BOOT;
|
||||
test_img.fw_size = 0x1000;
|
||||
test_img.fw_base = FlashImg;
|
||||
|
||||
/* Test get_sha_block */
|
||||
offset = 0x2000;
|
||||
retp = get_sha_block(&test_img, offset);
|
||||
ck_assert_ptr_null(retp);
|
||||
|
||||
offset = 0x100;
|
||||
retp = get_sha_block(&test_img, offset);
|
||||
ck_assert_ptr_eq(retp, FlashImg + offset);
|
||||
|
||||
test_img.part = PART_UPDATE;
|
||||
test_img.fw_size = 0x1000;
|
||||
test_img.fw_base = 0x0000;
|
||||
|
||||
offset = 0x2000;
|
||||
retp = get_sha_block(&test_img, offset);
|
||||
ck_assert_ptr_null(retp);
|
||||
|
||||
offset = 0x100;
|
||||
retp = get_sha_block(&test_img, offset);
|
||||
ck_assert_ptr_eq(retp, ext_hash_block);
|
||||
|
||||
/* Test wolfBoot_peek_image */
|
||||
hdr_cpy_done = 0;
|
||||
offset = 0x100;
|
||||
retp = get_sha_block(&test_img, offset);
|
||||
ck_assert_ptr_eq(retp, ext_hash_block);
|
||||
retp = wolfBoot_peek_image(&test_img, offset, NULL);
|
||||
ck_assert_ptr_eq(retp, ext_hash_block);
|
||||
retp = wolfBoot_peek_image(&test_img, offset, &sz);
|
||||
ck_assert_ptr_eq(retp, ext_hash_block);
|
||||
ck_assert_uint_eq(sz, WOLFBOOT_SHA_BLOCK_SIZE);
|
||||
|
||||
/* Test image_sha256 */
|
||||
|
||||
/* NULL img */
|
||||
ck_assert_int_lt(image_sha256(NULL, hash), 0);
|
||||
|
||||
/* Too short, internal partition field */
|
||||
test_img.part = PART_BOOT;
|
||||
test_img.fw_size = 0x1000;
|
||||
ck_assert_int_lt(image_sha256(&test_img, hash), 0);
|
||||
|
||||
/* Ext partition with a valid SHA */
|
||||
find_header_mocked = 0;
|
||||
find_header_fail = 0;
|
||||
hdr_cpy_done = 0;
|
||||
ext_flash_write(0, test_img_v200000000_signed_bin,
|
||||
test_img_len);
|
||||
test_img.part = PART_UPDATE;
|
||||
test_img.fw_base = 0;
|
||||
test_img.fw_size = test_img_len;
|
||||
ck_assert_int_eq(image_sha256(&test_img, hash), 0);
|
||||
|
||||
/* key_sha256 */
|
||||
key_sha256(0, hash);
|
||||
ck_assert_mem_eq(hash, pubkey_digest, SHA256_DIGEST_SIZE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_headers)
|
||||
{
|
||||
struct wolfBoot_image img;
|
||||
uint16_t type;
|
||||
void *ptr;
|
||||
uint16_t ret;
|
||||
uint32_t sz;
|
||||
memset(&img, 0, sizeof(struct wolfBoot_image));
|
||||
|
||||
|
||||
/* Test get_header() */
|
||||
img.part = PART_BOOT;
|
||||
find_header_fail = 1;
|
||||
find_header_called = 0;
|
||||
ret = get_header(&img, type, &ptr);
|
||||
ck_assert_uint_eq(ret, 0xFFFF);
|
||||
ck_assert_int_eq(find_header_called, 1);
|
||||
|
||||
img.part = PART_BOOT;
|
||||
find_header_fail = 0;
|
||||
find_header_called = 0;
|
||||
ret = get_header(&img, type, &ptr);
|
||||
ck_assert_uint_ne(ret, 0xFFFF);
|
||||
ck_assert_int_eq(find_header_called, 1);
|
||||
|
||||
img.part = PART_UPDATE;
|
||||
find_header_fail = 1;
|
||||
find_header_called = 0;
|
||||
ret = get_header(&img, type, &ptr);
|
||||
ck_assert_uint_eq(ret, 0xFFFF);
|
||||
ck_assert_int_eq(find_header_called, 1);
|
||||
|
||||
img.part = PART_UPDATE;
|
||||
find_header_fail = 0;
|
||||
find_header_called = 0;
|
||||
ret = get_header(&img, type, &ptr);
|
||||
ck_assert_uint_ne(ret, 0xFFFF);
|
||||
ck_assert_int_eq(find_header_called, 1);
|
||||
|
||||
/* Test get_img_hdr */
|
||||
img.part = PART_BOOT;
|
||||
img.hdr = (void *)0xAABBCCDD;
|
||||
ptr = get_img_hdr(&img);
|
||||
ck_assert_ptr_eq(ptr, img.hdr);
|
||||
|
||||
img.part = PART_UPDATE;
|
||||
img.hdr = 0;
|
||||
ptr = get_img_hdr(&img);
|
||||
ck_assert_ptr_eq(ptr, hdr_cpy);
|
||||
|
||||
/* Test image_size */
|
||||
sz = wolfBoot_image_size(test_img_v200000000_signed_bin);
|
||||
ck_assert_uint_eq(sz, test_img_len - 256);
|
||||
}
|
||||
|
||||
START_TEST(test_verify_authenticity)
|
||||
{
|
||||
struct wolfBoot_image test_img;
|
||||
int ret;
|
||||
memset(&test_img, 0, sizeof(struct wolfBoot_image));
|
||||
test_img.part = PART_UPDATE;
|
||||
|
||||
/* Wrong sha field */
|
||||
find_header_mocked = 1;
|
||||
ret = wolfBoot_verify_authenticity(&test_img);
|
||||
ck_assert_int_eq(ret, -1);
|
||||
|
||||
/* Wrong pubkey */
|
||||
find_header_mocked = 0;
|
||||
hdr_cpy_done = 0;
|
||||
ext_flash_write(0, test_img_v200000000_wrong_pubkey_bin,
|
||||
test_img_len);
|
||||
ret = wolfBoot_verify_authenticity(&test_img);
|
||||
ck_assert_int_lt(ret, 0);
|
||||
|
||||
/* Wrong signature */
|
||||
find_header_mocked = 0;
|
||||
find_header_fail = 0;
|
||||
hdr_cpy_done = 0;
|
||||
ext_flash_write(0, test_img_v200000000_wrong_signature_bin,
|
||||
test_img_len);
|
||||
ret = wolfBoot_verify_authenticity(&test_img);
|
||||
ck_assert_int_lt(ret, 0);
|
||||
|
||||
/* Correct image */
|
||||
find_header_mocked = 0;
|
||||
ecc_import_fail = 0;
|
||||
ecc_init_fail = 0;
|
||||
hdr_cpy_done = 0;
|
||||
ext_flash_erase(0, 2 * WOLFBOOT_SECTOR_SIZE);
|
||||
ext_flash_write(0, test_img_v123_signed_bin,
|
||||
test_img_v123_signed_bin_len);
|
||||
test_img.signature_ok = 1; /* mock for VERIFY_FN */
|
||||
ret = wolfBoot_verify_authenticity(&test_img);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_verify_integrity)
|
||||
{
|
||||
struct wolfBoot_image test_img;
|
||||
int ret;
|
||||
/* Wrong sha field */
|
||||
find_header_mocked = 1;
|
||||
ret = wolfBoot_verify_integrity(&test_img);
|
||||
ck_assert_int_eq(ret, -1);
|
||||
|
||||
/* Correct image */
|
||||
find_header_mocked = 0;
|
||||
find_header_fail = 0;
|
||||
hdr_cpy_done = 0;
|
||||
ecc_import_fail = 0;
|
||||
ecc_init_fail = 0;
|
||||
memset(&test_img, 0, sizeof(struct wolfBoot_image));
|
||||
ext_flash_erase(WOLFBOOT_PARTITION_UPDATE_ADDRESS, WOLFBOOT_SECTOR_SIZE);
|
||||
ext_flash_write(WOLFBOOT_PARTITION_UPDATE_ADDRESS,
|
||||
test_img_v123_signed_bin,
|
||||
test_img_v123_signed_bin_len);
|
||||
ret = wolfBoot_open_image(&test_img, PART_UPDATE);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
ck_assert_uint_eq(test_img.hdr, WOLFBOOT_PARTITION_UPDATE_ADDRESS);
|
||||
ret = wolfBoot_verify_integrity(&test_img);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_open_image)
|
||||
{
|
||||
struct wolfBoot_image img;
|
||||
int ret;
|
||||
|
||||
|
||||
/* invalid argument */
|
||||
ret = wolfBoot_open_image(NULL, PART_UPDATE);
|
||||
ck_assert_int_eq(ret, -1);
|
||||
|
||||
/* Empty flash */
|
||||
find_header_mocked = 0;
|
||||
hdr_cpy_done = 0;
|
||||
ext_flash_erase(0, WOLFBOOT_SECTOR_SIZE);
|
||||
ret = wolfBoot_open_image(&img, PART_UPDATE);
|
||||
ck_assert_int_eq(ret, -1);
|
||||
|
||||
/* Swap partition */
|
||||
ret = wolfBoot_open_image(&img, PART_SWAP);
|
||||
ck_assert_uint_eq(img.hdr_ok, 1);
|
||||
ck_assert_ptr_eq(img.hdr, WOLFBOOT_PARTITION_SWAP_ADDRESS);
|
||||
ck_assert_ptr_eq(img.hdr, img.fw_base);
|
||||
ck_assert_uint_eq(img.fw_size, WOLFBOOT_SECTOR_SIZE);
|
||||
|
||||
/* Valid image */
|
||||
hdr_cpy_done = 0;
|
||||
ext_flash_write(0, test_img_v200000000_signed_bin,
|
||||
test_img_len);
|
||||
ret = wolfBoot_open_image(&img, PART_UPDATE);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
ck_assert_uint_eq(img.hdr_ok, 1);
|
||||
ck_assert_ptr_eq(img.hdr, WOLFBOOT_PARTITION_UPDATE_ADDRESS);
|
||||
ck_assert_ptr_eq(img.fw_base, WOLFBOOT_PARTITION_UPDATE_ADDRESS + 256);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
Suite *wolfboot_suite(void)
|
||||
{
|
||||
/* Suite initialization */
|
||||
Suite *s = suite_create("wolfBoot");
|
||||
|
||||
TCase* tcase_verify_signature = tcase_create("verify_signature");
|
||||
tcase_set_timeout(tcase_verify_signature, 20);
|
||||
tcase_add_test(tcase_verify_signature, test_verify_signature);
|
||||
suite_add_tcase(s, tcase_verify_signature);
|
||||
|
||||
TCase* tcase_sha_ops = tcase_create("sha_ops");
|
||||
tcase_set_timeout(tcase_sha_ops, 20);
|
||||
tcase_add_test(tcase_sha_ops, test_sha_ops);
|
||||
suite_add_tcase(s, tcase_sha_ops);
|
||||
|
||||
TCase* tcase_headers = tcase_create("headers");
|
||||
tcase_set_timeout(tcase_headers, 20);
|
||||
tcase_add_test(tcase_headers, test_headers);
|
||||
suite_add_tcase(s, tcase_headers);
|
||||
|
||||
TCase* tcase_verify_authenticity = tcase_create("verify_authenticity");
|
||||
tcase_set_timeout(tcase_verify_authenticity, 20);
|
||||
tcase_add_test(tcase_verify_authenticity, test_verify_authenticity);
|
||||
suite_add_tcase(s, tcase_verify_authenticity);
|
||||
|
||||
TCase* tcase_verify_integrity = tcase_create("verify_integrity");
|
||||
tcase_set_timeout(tcase_verify_integrity, 20);
|
||||
tcase_add_test(tcase_verify_integrity, test_verify_integrity);
|
||||
suite_add_tcase(s, tcase_verify_integrity);
|
||||
|
||||
TCase* tcase_open_image = tcase_create("open_image");
|
||||
tcase_set_timeout(tcase_open_image, 20);
|
||||
tcase_add_test(tcase_open_image, test_open_image);
|
||||
suite_add_tcase(s, tcase_open_image);
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fails;
|
||||
Suite *s = wolfboot_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
fails = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return fails;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/* unit-keystore.c
|
||||
*
|
||||
* example keystore used for image.c unit tests
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2023 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 2 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
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "wolfboot/wolfboot.h"
|
||||
#include "keystore.h"
|
||||
#ifdef WOLFBOOT_NO_SIGN
|
||||
#define NUM_PUBKEYS 0
|
||||
#else
|
||||
|
||||
#if !defined(KEYSTORE_ANY) && (KEYSTORE_PUBKEY_SIZE != KEYSTORE_PUBKEY_SIZE_ECC256)
|
||||
#error Key algorithm mismatch. Remove old keys via 'make keysclean'
|
||||
#else
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#define KEYSTORE_SECTION __attribute__((section ("__KEYSTORE,__keystore")))
|
||||
#else
|
||||
#define KEYSTORE_SECTION __attribute__((section (".keystore")))
|
||||
#endif
|
||||
|
||||
#define NUM_PUBKEYS 1
|
||||
const KEYSTORE_SECTION struct keystore_slot PubKeys[NUM_PUBKEYS] = {
|
||||
|
||||
/* Key associated to file 'wolfboot_signing_private_key.der' */
|
||||
{
|
||||
.slot_id = 0,
|
||||
.key_type = AUTH_KEY_ECC256,
|
||||
.part_id_mask = 0xFFFFFFFF,
|
||||
.pubkey_size = KEYSTORE_PUBKEY_SIZE_ECC256,
|
||||
.pubkey = {
|
||||
|
||||
0xc5, 0x7d, 0xbf, 0xfb, 0x23, 0x79, 0xba, 0xb6,
|
||||
0x31, 0x8f, 0x7b, 0x8d, 0xfe, 0xc9, 0x5d, 0x46,
|
||||
0xf5, 0x95, 0xb4, 0xa8, 0xbd, 0x45, 0xb7, 0x46,
|
||||
0xf3, 0x6c, 0x1b, 0x86, 0x28, 0x7b, 0x23, 0xd1,
|
||||
0x83, 0xf3, 0x27, 0x5c, 0x08, 0x1f, 0x9d, 0x9e,
|
||||
0x6c, 0xca, 0xee, 0xb3, 0x0d, 0x5c, 0x01, 0xb2,
|
||||
0xc5, 0x98, 0xf3, 0x85, 0x6c, 0xdd, 0x42, 0x54,
|
||||
0xef, 0x44, 0x94, 0x59, 0xf3, 0x08, 0x3d, 0xcd
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
||||
int keystore_num_pubkeys(void)
|
||||
{
|
||||
return NUM_PUBKEYS;
|
||||
}
|
||||
|
||||
uint8_t *keystore_get_buffer(int id)
|
||||
{
|
||||
if (id >= keystore_num_pubkeys())
|
||||
return (uint8_t *)0;
|
||||
return (uint8_t *)PubKeys[id].pubkey;
|
||||
}
|
||||
|
||||
int keystore_get_size(int id)
|
||||
{
|
||||
if (id >= keystore_num_pubkeys())
|
||||
return -1;
|
||||
return (int)PubKeys[id].pubkey_size;
|
||||
}
|
||||
|
||||
uint32_t keystore_get_mask(int id)
|
||||
{
|
||||
if (id >= keystore_num_pubkeys())
|
||||
return -1;
|
||||
return (int)PubKeys[id].part_id_mask;
|
||||
}
|
||||
|
||||
uint32_t keystore_get_key_type(int id)
|
||||
{
|
||||
return PubKeys[id].key_type;
|
||||
}
|
||||
|
||||
#endif /* Keystore public key size check */
|
||||
#endif /* WOLFBOOT_NO_SIGN */
|
|
@ -0,0 +1,398 @@
|
|||
/* unit-mock-state.c
|
||||
*
|
||||
* Unit test for parser functions in libwolfboot.c
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2023 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 2 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
|
||||
*/
|
||||
|
||||
/* Option to enable sign tool debugging */
|
||||
/* Must also define DEBUG_WOLFSSL in user_settings.h */
|
||||
#define WOLFBOOT_HASH_SHA256
|
||||
|
||||
#if defined(ENCRYPT_WITH_AES256) || defined(ENCRYPT_WITH_AES128)
|
||||
#define WOLFSSL_AES_COUNTER
|
||||
#define WOLFSSL_AES_DIRECT
|
||||
#endif
|
||||
#if defined(ENCRYPT_WITH_AES256)
|
||||
#define WOLFSSL_AES_256
|
||||
#endif
|
||||
#if defined(ENCRYPT_WITH_CHACHA)
|
||||
#define HAVE_CHACHA
|
||||
#endif
|
||||
#define WC_NO_HARDEN
|
||||
#define NVM_FLASH_WRITEONCE
|
||||
|
||||
#define WOLFSSL_USER_SETTINGS
|
||||
#define UNIT_TEST
|
||||
#define MOCK_PARTITION_TRAILER
|
||||
#define MOCK_BLOB_TYPE
|
||||
#include <stdio.h>
|
||||
#include <check.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "user_settings.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
static uint8_t* get_trailer_at(uint8_t part, uint32_t at);
|
||||
static void set_trailer_at(uint8_t part, uint32_t at, uint8_t val);
|
||||
static void set_partition_magic(uint8_t part);
|
||||
|
||||
static uint8_t current_backup_part = 1;
|
||||
uint8_t image_backup(uint8_t part_id)
|
||||
{
|
||||
printf("Called image_backup\n");
|
||||
return current_backup_part;
|
||||
}
|
||||
|
||||
#ifndef PART_TOTAL_IDS
|
||||
# define PART_TOTAL_IDS 3
|
||||
#endif
|
||||
|
||||
#include "libwolfboot.c"
|
||||
|
||||
/* Mocks */
|
||||
|
||||
static int locked = 0;
|
||||
static int hal_flash_write_mock_called = 0;
|
||||
static uintptr_t hal_flash_write_mock_address = 0U;
|
||||
static uint8_t *hal_flash_write_mock_data = NULL;
|
||||
static int hal_flash_write_mock_len = 0;
|
||||
|
||||
static uintptr_t hal_flash_erase_mock_address = 0;
|
||||
static int hal_flash_erase_mock_len = 0;
|
||||
|
||||
static int hal_flash_erase_mock_called = 0;
|
||||
|
||||
static void hal_flash_write_mock_reset(void)
|
||||
{
|
||||
hal_flash_write_mock_called = 0;
|
||||
hal_flash_write_mock_address = 0U;
|
||||
hal_flash_write_mock_data = NULL;
|
||||
hal_flash_write_mock_len = 0;
|
||||
}
|
||||
|
||||
static void hal_flash_erase_mock_reset(void)
|
||||
{
|
||||
hal_flash_erase_mock_called = 0;
|
||||
hal_flash_erase_mock_address = 0U;
|
||||
hal_flash_erase_mock_len = 0;
|
||||
}
|
||||
|
||||
void hal_init(void)
|
||||
{
|
||||
}
|
||||
int hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
||||
{
|
||||
printf("Called hal_flash_write\r\n");
|
||||
hal_flash_write_mock_called++;
|
||||
hal_flash_write_mock_address = address;
|
||||
hal_flash_write_mock_data = data;
|
||||
hal_flash_write_mock_len = len;
|
||||
return 0;
|
||||
}
|
||||
int hal_flash_erase(uint32_t address, int len)
|
||||
{
|
||||
printf("Called hal_flash_erase\r\n");
|
||||
hal_flash_erase_mock_called++;
|
||||
hal_flash_erase_mock_address = address;
|
||||
hal_flash_erase_mock_len = len;
|
||||
return 0;
|
||||
}
|
||||
void hal_flash_unlock(void)
|
||||
{
|
||||
}
|
||||
void hal_flash_lock(void)
|
||||
{
|
||||
}
|
||||
|
||||
void hal_prepare_boot(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int ext_locked = 1;
|
||||
static int ext_flash_write_mock_called = 0;
|
||||
static uintptr_t ext_flash_write_mock_address = 0U;
|
||||
static uint8_t *ext_flash_write_mock_data = NULL;
|
||||
static int ext_flash_write_mock_len = 0;
|
||||
|
||||
static int ext_flash_read_mock_called = 0;
|
||||
static uint32_t ext_flash_read_mock_address = 0U;
|
||||
static uint8_t *ext_flash_read_mock_data = NULL;
|
||||
static int ext_flash_read_mock_len = 0;
|
||||
|
||||
static uintptr_t ext_flash_erase_mock_address = 0U;
|
||||
static int ext_flash_erase_mock_len = 0;
|
||||
|
||||
static int ext_flash_erase_mock_called = 0;
|
||||
|
||||
static void ext_flash_write_mock_reset(void)
|
||||
{
|
||||
ext_flash_write_mock_called = 0;
|
||||
ext_flash_write_mock_address = 0U;
|
||||
ext_flash_write_mock_data = NULL;
|
||||
ext_flash_write_mock_len = 0;
|
||||
}
|
||||
|
||||
static void ext_flash_erase_mock_reset(void)
|
||||
{
|
||||
ext_flash_erase_mock_called = 0;
|
||||
ext_flash_erase_mock_address = 0U;
|
||||
ext_flash_erase_mock_len = 0;
|
||||
}
|
||||
|
||||
void ext_init(void)
|
||||
{
|
||||
}
|
||||
int ext_flash_read(uintptr_t address, uint8_t *data, int len)
|
||||
{
|
||||
printf("Called ext_flash_read\r\n");
|
||||
ext_flash_read_mock_called++;
|
||||
ext_flash_read_mock_address = address;
|
||||
ext_flash_read_mock_data = data;
|
||||
ext_flash_read_mock_len = len;
|
||||
return 0;
|
||||
}
|
||||
int ext_flash_write(uintptr_t address, const uint8_t *data, int len)
|
||||
{
|
||||
printf("Called ext_flash_write\r\n");
|
||||
ext_flash_write_mock_called++;
|
||||
ext_flash_write_mock_address = address;
|
||||
ext_flash_write_mock_data = data;
|
||||
ext_flash_write_mock_len = len;
|
||||
return 0;
|
||||
}
|
||||
int ext_flash_erase(uintptr_t address, int len)
|
||||
{
|
||||
printf("Called ext_flash_erase\r\n");
|
||||
ext_flash_erase_mock_called++;
|
||||
ext_flash_erase_mock_address = address;
|
||||
ext_flash_erase_mock_len = len;
|
||||
return 0;
|
||||
}
|
||||
void ext_flash_unlock(void)
|
||||
{
|
||||
fail_unless(ext_locked, "Double unlock detected (ext)\n");
|
||||
ext_locked--;
|
||||
}
|
||||
void ext_flash_lock(void)
|
||||
{
|
||||
fail_if(ext_locked, "Double lock detected(ext)\n");
|
||||
ext_locked++;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t test_buffer[512] = {
|
||||
'W', 'O', 'L', 'F', 0x00, 0x00, 0x01, 0x00,
|
||||
0x01, 0x00, 0x04, 0x00, 0x0d, 0x0c, 0x0b, 0x0a,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x08, 0x00,
|
||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x20, 0x00,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*<-- end of options */
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* End HDR */
|
||||
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
|
||||
};
|
||||
|
||||
|
||||
static uint8_t mock_partition_state;
|
||||
static int mock_partition_state_retval;
|
||||
static uint8_t mock_partition_state_arg_part;
|
||||
static int mock_get_partition_state_called = 0;
|
||||
|
||||
struct mock_state {
|
||||
uint8_t part;
|
||||
uint8_t state;
|
||||
int retval;
|
||||
int getstate_called;
|
||||
int setstate_called;
|
||||
};
|
||||
|
||||
static struct mock_state mock_state[PART_TOTAL_IDS] = {
|
||||
{ PART_BOOT, IMG_STATE_NEW, -1, 0, 0 },
|
||||
{ PART_UPDATE, IMG_STATE_NEW, -1, 0, 0 },
|
||||
{ PART_SWAP, IMG_STATE_NEW, -1, 0, 0 }
|
||||
};
|
||||
|
||||
static void mock_set_initial_partition_state(uint8_t part, uint8_t st)
|
||||
{
|
||||
mock_state[part].retval = 0;
|
||||
mock_state[part].state = st;
|
||||
}
|
||||
|
||||
static void mock_reset_partition_states(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < PART_TOTAL_IDS; i++) {
|
||||
mock_state[i].retval = -1;
|
||||
mock_state[i].state = IMG_STATE_NEW;
|
||||
mock_state[i].getstate_called = 0;
|
||||
mock_state[i].setstate_called = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t magic_trailer[4] = { 'B','O','O','T' };
|
||||
static uint8_t erased_trailer[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
static uint8_t* get_trailer_at(uint8_t part, uint32_t at)
|
||||
{
|
||||
//ck_assert_uint_lt(part, PART_TOTAL_IDS);
|
||||
if (part >= PART_TOTAL_IDS)
|
||||
return NULL;
|
||||
if (at == 1)
|
||||
mock_state[part].getstate_called++;
|
||||
if ((at == 0) && (mock_state[part].retval == 0)) {
|
||||
return magic_trailer;
|
||||
} else if ((at == 1) && (mock_state[part].retval == 0)) {
|
||||
return &mock_state[part].state;
|
||||
} else {
|
||||
return erased_trailer;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_trailer_at(uint8_t part, uint32_t at, uint8_t val)
|
||||
{
|
||||
ck_assert_uint_lt(part, PART_TOTAL_IDS);
|
||||
if (at == 1) {
|
||||
printf("Setting part %d state %02x\n", part, val);
|
||||
mock_state[part].setstate_called++;
|
||||
mock_state[part].state = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_partition_magic(uint8_t part)
|
||||
{
|
||||
ck_assert_uint_lt(part, PART_TOTAL_IDS);
|
||||
mock_state[part].retval = 0;
|
||||
}
|
||||
|
||||
/* End Mocks */
|
||||
|
||||
START_TEST(test_wolfBoot_set_partition_state)
|
||||
{
|
||||
int i;
|
||||
uint8_t st = 0x0D;
|
||||
/* Corner cases: PART_NONE should have no effect */
|
||||
mock_reset_partition_states();
|
||||
wolfBoot_set_partition_state(PART_NONE, IMG_STATE_SUCCESS);
|
||||
ck_assert_uint_eq(mock_state[PART_BOOT].state, IMG_STATE_NEW);
|
||||
ck_assert_uint_eq(mock_state[PART_BOOT].getstate_called, 0);
|
||||
ck_assert_uint_eq(mock_state[PART_UPDATE].state, IMG_STATE_NEW);
|
||||
ck_assert_uint_eq(mock_state[PART_UPDATE].getstate_called, 0);
|
||||
|
||||
/* Ensure 'get_partition_state()' with 'PART_NONE' is invalid and
|
||||
* has no side effects
|
||||
*/
|
||||
ck_assert_int_eq(wolfBoot_get_partition_state(PART_NONE, &st), -1);
|
||||
for (i = 0; i < PART_TOTAL_IDS - 1; i++) {
|
||||
ck_assert_uint_eq(mock_state[i].state, IMG_STATE_NEW);
|
||||
ck_assert_int_eq(mock_state[i].retval, -1);
|
||||
ck_assert_uint_eq(mock_state[i].getstate_called, 0);
|
||||
ck_assert_uint_eq(mock_state[i].setstate_called, 0);
|
||||
}
|
||||
|
||||
/* Sunny day set state change */
|
||||
mock_reset_partition_states();
|
||||
wolfBoot_set_partition_state(PART_UPDATE, IMG_STATE_TESTING);
|
||||
ck_assert_uint_eq(mock_state[PART_UPDATE].state, IMG_STATE_TESTING);
|
||||
ck_assert_int_eq(mock_state[PART_UPDATE].retval, 0);
|
||||
ck_assert_uint_ge(mock_state[PART_UPDATE].getstate_called, 1);
|
||||
ck_assert_uint_ge(mock_state[PART_UPDATE].setstate_called, 1);
|
||||
|
||||
}
|
||||
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_wolfBoot_misc_utils)
|
||||
{
|
||||
uint16_t word2 = 0xA0B1;
|
||||
uint32_t word4 = 0xA0B1C2D3;
|
||||
uint8_t *hdr_cpy_ptr = NULL;
|
||||
ext_flash_erase_mock_reset();
|
||||
mock_reset_partition_states();
|
||||
ck_assert_uint_eq(wb_reverse_word32(word4), 0xD3C2B1A0);
|
||||
|
||||
ck_assert_uint_eq(im2n(word4), word4);
|
||||
ck_assert_uint_eq(im2ns(word2), word2);
|
||||
|
||||
ck_assert_ptr_eq(wolfBoot_get_image_from_part(PART_BOOT), (void *)WOLFBOOT_PARTITION_BOOT_ADDRESS);
|
||||
ck_assert_ptr_eq(wolfBoot_get_image_from_part(PART_UPDATE), (void *)WOLFBOOT_PARTITION_UPDATE_ADDRESS);
|
||||
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
|
||||
|
||||
Suite *wolfboot_suite(void)
|
||||
{
|
||||
|
||||
/* Suite initialization */
|
||||
Suite *s = suite_create("wolfBoot");
|
||||
|
||||
TCase* tcase_wolfBoot_set_partition_state = tcase_create("wolfBoot_set_partition_state");
|
||||
tcase_set_timeout(tcase_wolfBoot_set_partition_state, 20);
|
||||
tcase_add_test(tcase_wolfBoot_set_partition_state, test_wolfBoot_set_partition_state);
|
||||
suite_add_tcase(s, tcase_wolfBoot_set_partition_state);
|
||||
|
||||
TCase* tcase_wolfBoot_misc_utils = tcase_create("wolfBoot_misc_utils");
|
||||
tcase_set_timeout(tcase_wolfBoot_misc_utils, 20);
|
||||
tcase_add_test(tcase_wolfBoot_misc_utils, test_wolfBoot_misc_utils);
|
||||
suite_add_tcase(s, tcase_wolfBoot_misc_utils);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fails;
|
||||
Suite *s = wolfboot_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
fails = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return fails;
|
||||
}
|
|
@ -1,3 +1,26 @@
|
|||
/* unit-pci.c
|
||||
*
|
||||
* Unit test for pci functions
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2023 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 2 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
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
/* unit-sectorflags.c
|
||||
*
|
||||
* Unit test for sector flags functions in libwolfboot.c
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2023 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 2 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
|
||||
*/
|
||||
|
||||
/* Option to enable sign tool debugging */
|
||||
/* Must also define DEBUG_WOLFSSL in user_settings.h */
|
||||
#define FLASH_SIZE (33 * 1024)
|
||||
#define WOLFBOOT_HASH_SHA256
|
||||
#define IMAGE_HEADER_SIZE 256
|
||||
#define EXT_FLASH 1
|
||||
#define PART_UPDATE_EXT 1
|
||||
#define PART_SWAP_EXT 1
|
||||
|
||||
|
||||
#define WC_NO_HARDEN
|
||||
|
||||
#define WOLFSSL_USER_SETTINGS
|
||||
#define ENCRYPT_KEY "123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
#define UNIT_TEST
|
||||
#include <stdio.h>
|
||||
#include <check.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "user_settings.h"
|
||||
|
||||
uint8_t *ut_get_endpart(void);
|
||||
#include "libwolfboot.c"
|
||||
|
||||
/* Mocks */
|
||||
|
||||
static int locked = 0;
|
||||
static int ext_locked = 0;
|
||||
|
||||
void hal_init(void)
|
||||
{
|
||||
}
|
||||
int hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int hal_flash_erase(uint32_t address, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void hal_flash_unlock(void)
|
||||
{
|
||||
fail_unless(locked, "Double unlock detected\n");
|
||||
locked--;
|
||||
}
|
||||
void hal_flash_lock(void)
|
||||
{
|
||||
fail_if(locked, "Double lock detected\n");
|
||||
locked++;
|
||||
}
|
||||
|
||||
void ext_flash_unlock(void)
|
||||
{
|
||||
//fail_unless(ext_locked, "Double unlock detected\n");
|
||||
ext_locked--;
|
||||
}
|
||||
void ext_flash_lock(void)
|
||||
{
|
||||
//fail_if(ext_locked, "Double lock detected\n");
|
||||
ext_locked++;
|
||||
}
|
||||
|
||||
void hal_prepare_boot(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Emulation of external flash with a static buffer of 32KB (update) + 1KB (swap) */
|
||||
uint8_t flash[FLASH_SIZE];
|
||||
|
||||
uint8_t *ut_get_endpart(void)
|
||||
{
|
||||
return flash + WOLFBOOT_PARTITION_SIZE;
|
||||
}
|
||||
|
||||
/* Mocks for ext_flash_read, ext_flash_write, and ext_flash_erase functions */
|
||||
int ext_flash_read(uintptr_t address, uint8_t *data, int len) {
|
||||
printf("Called ext_flash_read %p %p %d\n", address, data, len);
|
||||
|
||||
/* Check that the read address and size are within the bounds of the flash memory */
|
||||
ck_assert_int_le(address + len, FLASH_SIZE);
|
||||
|
||||
/* Copy the data from the flash memory to the output buffer */
|
||||
memcpy(data, &flash[address], len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int ext_flash_write(uintptr_t address, const uint8_t *data, int len) {
|
||||
printf("Called ext_flash_write %p %p %d\n", address, data, len);
|
||||
/* Check that the write address and size are within the bounds of the flash memory */
|
||||
ck_assert_int_le(address + len, FLASH_SIZE);
|
||||
|
||||
/* Copy the data from the input buffer to the flash memory */
|
||||
memcpy(&flash[address], data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext_flash_erase(uintptr_t address, int len) {
|
||||
printf("Called ext_flash_erase %p %d\n", address, len);
|
||||
/* Check that the erase address and size are within the bounds of the flash memory */
|
||||
ck_assert_int_le(address + len, FLASH_SIZE);
|
||||
|
||||
/* Erase the flash memory by setting each byte to 0xFF, WOLFBOOT_SECTOR_SIZE bytes at a time */
|
||||
uint32_t i;
|
||||
for (i = address; i < address + len; i += WOLFBOOT_SECTOR_SIZE) {
|
||||
memset(&flash[i], 0xFF, WOLFBOOT_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t test_buffer[512] = {
|
||||
'W', 'O', 'L', 'F', 0x00, 0x00, 0x01, 0x00,
|
||||
0x01, 0x00, 0x04, 0x00, 0x0d, 0x0c, 0x0b, 0x0a,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x08, 0x00,
|
||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x20, 0x00,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*<-- end of options */
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
/* End HDR */
|
||||
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
|
||||
};
|
||||
|
||||
|
||||
START_TEST(test_partition_flags) {
|
||||
uint32_t address = 0;
|
||||
uint32_t size = 512;
|
||||
uint8_t data[2 * WOLFBOOT_SECTOR_SIZE];
|
||||
uint8_t empty_sector[WOLFBOOT_SECTOR_SIZE];
|
||||
int rres, wres, eres;
|
||||
uint8_t st;
|
||||
|
||||
memset(empty_sector, 0xFF, WOLFBOOT_SECTOR_SIZE);
|
||||
|
||||
/* Write data to the flash memory */
|
||||
wres = ext_flash_write(address, test_buffer, size);
|
||||
ck_assert_int_eq(wres, 0);
|
||||
|
||||
/* Read data from the flash memory */
|
||||
rres = ext_flash_read(address, data, size);
|
||||
ck_assert_int_eq(rres, size);
|
||||
|
||||
/* Check that the data read from the flash memory matches the data that was written */
|
||||
ck_assert_mem_eq(data, test_buffer, size);
|
||||
|
||||
/* Set partition to updating state */
|
||||
wolfBoot_update_trigger();
|
||||
|
||||
/* Get partition state */
|
||||
wolfBoot_get_partition_state(PART_UPDATE, &st);
|
||||
ck_assert_int_eq(st, IMG_STATE_UPDATING);
|
||||
|
||||
/* Change to IMG_STATE_TESTING */
|
||||
st = IMG_STATE_TESTING;
|
||||
wolfBoot_set_partition_state(PART_UPDATE, st);
|
||||
wolfBoot_get_partition_state(PART_UPDATE, &st);
|
||||
ck_assert_int_eq(st, IMG_STATE_TESTING);
|
||||
|
||||
/* Change to IMG_STATE_SUCCESS */
|
||||
st = IMG_STATE_SUCCESS;
|
||||
wolfBoot_set_partition_state(PART_UPDATE, st);
|
||||
wolfBoot_get_partition_state(PART_UPDATE, &st);
|
||||
ck_assert_int_eq(st, IMG_STATE_SUCCESS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_sector_flags) {
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/* End Mocks */
|
||||
|
||||
Suite *wolfboot_suite(void)
|
||||
{
|
||||
|
||||
/* Suite initialization */
|
||||
Suite *s = suite_create("wolfBoot");
|
||||
|
||||
/* Test cases */
|
||||
TCase *partition_flags = tcase_create("External flash operations: partition flags");
|
||||
TCase *sector_flags = tcase_create("External encrypted flash operations");
|
||||
|
||||
/* Set parameters + add to suite */
|
||||
tcase_add_test(partition_flags, test_partition_flags);
|
||||
tcase_add_test(sector_flags, test_sector_flags);
|
||||
|
||||
tcase_set_timeout(partition_flags, 20);
|
||||
tcase_set_timeout(sector_flags, 20);
|
||||
suite_add_tcase(s, partition_flags);
|
||||
suite_add_tcase(s, sector_flags);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fails;
|
||||
Suite *s = wolfboot_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
fails = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return fails;
|
||||
}
|
Loading…
Reference in New Issue