mirror of https://github.com/wolfSSL/wolfBoot.git
Fixes to delta updates, reinforced size checks, improved hardening (#716)
Fixes to delta updates, reinforced size checks, improved hardeningpull/704/head
commit
a910645309
|
|
@ -82,6 +82,9 @@ const uint8_t __attribute__((section(".sig_wolfboot_raw")))
|
|||
#define FSP_STATUS_RESET_REQUIRED_WARM 0x40000002
|
||||
#define MEMORY_4GB (4ULL * 1024 * 1024 * 1024)
|
||||
#define ENDLINE "\r\n"
|
||||
/* Standard PCI capabilities live in conventional config space at 0x40-0xFC,
|
||||
* on 4-byte alignment, so there are at most 48 distinct capability headers. */
|
||||
#define PCI_MAX_STANDARD_CAPABILITIES 48
|
||||
|
||||
|
||||
/* compile time alignment checks */
|
||||
|
|
@ -257,13 +260,23 @@ static void jump_into_wolfboot(void)
|
|||
/* The image needs to be already verified */
|
||||
int wolfBoot_image_measure(uint8_t *image)
|
||||
{
|
||||
uint16_t hash_len;
|
||||
uint8_t *hash;
|
||||
struct wolfBoot_image img;
|
||||
int ret;
|
||||
|
||||
hash_len = wolfBoot_find_header(image + IMAGE_HEADER_OFFSET,
|
||||
WOLFBOOT_SHA_HDR, &hash);
|
||||
wolfBoot_print_hexstr(hash, hash_len, 0);
|
||||
return wolfBoot_tpm2_extend(WOLFBOOT_MEASURED_PCR_A, hash, __LINE__);
|
||||
memset(&img, 0, sizeof(img));
|
||||
ret = wolfBoot_open_image_address(&img, image);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wolfBoot_verify_integrity(&img);
|
||||
if (ret != 0 || img.sha_hash == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
wolfBoot_print_hexstr(img.sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, 0);
|
||||
return wolfBoot_tpm2_extend(WOLFBOOT_MEASURED_PCR_A, img.sha_hash,
|
||||
__LINE__);
|
||||
}
|
||||
#endif /* WOLFBOOT_MEASURED_BOOT */
|
||||
|
||||
|
|
@ -332,19 +345,21 @@ static int pci_get_capability(uint8_t bus, uint8_t dev, uint8_t fun,
|
|||
uint8_t cap_id, uint8_t *cap_off)
|
||||
{
|
||||
uint8_t r8, id;
|
||||
uint8_t cap_count = 0;
|
||||
uint32_t r32;
|
||||
|
||||
r32 = pci_config_read16(bus, dev, fun, PCI_STATUS_OFFSET);
|
||||
if (!(r32 & PCI_STATUS_CAP_LIST))
|
||||
return -1;
|
||||
r8 = pci_config_read8(bus, dev, fun, PCI_CAP_OFFSET);
|
||||
while (r8 != 0) {
|
||||
while ((r8 != 0) && (cap_count < PCI_MAX_STANDARD_CAPABILITIES)) {
|
||||
id = pci_config_read8(bus, dev, fun, r8);
|
||||
if (id == cap_id) {
|
||||
*cap_off = r8;
|
||||
return 0;
|
||||
}
|
||||
r8 = pci_config_read8(bus, dev, fun, r8 + 1);
|
||||
cap_count++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,8 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
|
|||
continue;
|
||||
}
|
||||
if (*pp == ESC) {
|
||||
if ((ctx->patch_size - ctx->p_off) < 2)
|
||||
return -1;
|
||||
if (*(pp + 1) == ESC) {
|
||||
*(dst + dst_off) = ESC;
|
||||
/* Two bytes of the patch have been consumed to produce ESC */
|
||||
|
|
@ -142,6 +144,8 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
|
|||
dst_off++;
|
||||
continue;
|
||||
} else {
|
||||
if ((ctx->patch_size - ctx->p_off) < BLOCK_HDR_SIZE)
|
||||
return -1;
|
||||
hdr = (struct block_hdr *)pp;
|
||||
src_off = (hdr->off[0] << 16) + (hdr->off[1] << 8) +
|
||||
hdr->off[2];
|
||||
|
|
|
|||
28
src/gpt.c
28
src/gpt.c
|
|
@ -34,6 +34,23 @@
|
|||
|
||||
#include "gpt.h"
|
||||
|
||||
static uint32_t gpt_crc32(const uint8_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFFU;
|
||||
uint32_t i;
|
||||
uint32_t j;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
crc ^= data[i];
|
||||
for (j = 0; j < 8; j++) {
|
||||
uint32_t mask = -(crc & 1U);
|
||||
crc = (crc >> 1) ^ (0xEDB88320U & mask);
|
||||
}
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check MBR for protective GPT partition entry.
|
||||
*
|
||||
|
|
@ -98,6 +115,7 @@ int gpt_check_mbr_protective(const uint8_t *mbr_sector, uint32_t *gpt_lba)
|
|||
int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr)
|
||||
{
|
||||
const struct guid_ptable *src;
|
||||
struct guid_ptable tmp;
|
||||
|
||||
if (sector == NULL || hdr == NULL) {
|
||||
return -1;
|
||||
|
|
@ -110,6 +128,16 @@ int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (src->hdr_size < 0x5C || src->hdr_size > GPT_SECTOR_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&tmp, src, sizeof(tmp));
|
||||
tmp.hdr_crc32 = 0;
|
||||
if (gpt_crc32((const uint8_t *)&tmp, src->hdr_size) != src->hdr_crc32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy header to output */
|
||||
memcpy(hdr, src, sizeof(struct guid_ptable));
|
||||
|
||||
|
|
|
|||
46
src/image.c
46
src/image.c
|
|
@ -58,6 +58,19 @@
|
|||
/* Globals */
|
||||
static uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE] XALIGNED(4);
|
||||
|
||||
static int image_CT_compare(const uint8_t *expected, const uint8_t *actual,
|
||||
uint32_t len)
|
||||
{
|
||||
uint8_t diff = 0;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
diff |= expected[i] ^ actual[i];
|
||||
}
|
||||
|
||||
return diff == 0;
|
||||
}
|
||||
|
||||
#if defined(WOLFBOOT_CERT_CHAIN_VERIFY) && \
|
||||
(defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \
|
||||
defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER))
|
||||
|
|
@ -367,6 +380,9 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot,
|
|||
static inline int DecodeAsn1Tag(const uint8_t* input, int inputSz, int* inOutIdx,
|
||||
int* tag_len, uint8_t tag)
|
||||
{
|
||||
if (*inOutIdx < 0 || *inOutIdx >= inputSz || (*inOutIdx + 1) >= inputSz) {
|
||||
return -1;
|
||||
}
|
||||
if (input[*inOutIdx] != tag) {
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1492,6 +1508,12 @@ int wolfBoot_open_self_address(struct wolfBoot_image* img, uint8_t* hdr,
|
|||
|
||||
img->hdr = hdr;
|
||||
img->fw_size = wolfBoot_image_size(hdr);
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
if (img->fw_size > (WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE)) {
|
||||
img->fw_size = WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
img->fw_base = image;
|
||||
img->part = PART_SELF;
|
||||
img->hdr_ok = 1;
|
||||
|
|
@ -1518,7 +1540,7 @@ int wolfBoot_verify_integrity(struct wolfBoot_image *img)
|
|||
return -1;
|
||||
if (image_hash(img, digest) != 0)
|
||||
return -1;
|
||||
if (memcmp(digest, stored_sha, stored_sha_len) != 0)
|
||||
if (!image_CT_compare(digest, stored_sha, stored_sha_len))
|
||||
return -1;
|
||||
img->sha_ok = 1;
|
||||
img->sha_hash = stored_sha;
|
||||
|
|
@ -2366,6 +2388,21 @@ uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
|
|||
|
||||
#if !defined(WOLFBOOT_NO_SIGN) && !defined(WOLFBOOT_RENESAS_SCEPROTECT)
|
||||
|
||||
/* Compare fixed-size key hints without early exit to avoid leaking hash prefix
|
||||
* matches through lookup timing. */
|
||||
static int keyslot_CT_hint_matches(const uint8_t *expected,
|
||||
const uint8_t *actual)
|
||||
{
|
||||
uint8_t diff = 0;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < WOLFBOOT_SHA_DIGEST_SIZE; i++) {
|
||||
diff |= expected[i] ^ actual[i];
|
||||
}
|
||||
|
||||
return diff == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the key slot ID by SHA hash.
|
||||
*
|
||||
|
|
@ -2378,13 +2415,14 @@ uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
|
|||
int keyslot_id_by_sha(const uint8_t *hint)
|
||||
{
|
||||
int id;
|
||||
int match_id = -1;
|
||||
|
||||
for (id = 0; id < keystore_num_pubkeys(); id++) {
|
||||
key_hash(id, digest);
|
||||
if (memcmp(digest, hint, WOLFBOOT_SHA_DIGEST_SIZE) == 0) {
|
||||
return id;
|
||||
if ((match_id < 0) && keyslot_CT_hint_matches(digest, hint)) {
|
||||
match_id = id;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return match_id;
|
||||
}
|
||||
#endif /* !WOLFBOOT_NO_SIGN && !WOLFBOOT_RENESAS_SCEPROTECT */
|
||||
|
|
|
|||
|
|
@ -107,8 +107,8 @@ int wolfBoot_initialize_encryption(void)
|
|||
(2 * WOLFBOOT_SECTOR_SIZE)))
|
||||
/* MAGIC (4B) + PART_FLAG (1B) + (N_SECTORS / 2) */
|
||||
#define START_FLAGS_OFFSET (ENCRYPT_TMP_SECRET_OFFSET - TRAILER_OVERHEAD)
|
||||
#define SECTOR_FLAGS_SIZE WOLFBOOT_SECTOR_SIZE - (4 + 1 + \
|
||||
ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE)
|
||||
#define SECTOR_FLAGS_SIZE (WOLFBOOT_SECTOR_SIZE - (4 + 1 + \
|
||||
ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE))
|
||||
/* MAGIC (4B) + PART_FLAG (1B) + ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE */
|
||||
#else
|
||||
#define ENCRYPT_TMP_SECRET_OFFSET (WOLFBOOT_PARTITION_SIZE - (TRAILER_SKIP))
|
||||
|
|
|
|||
|
|
@ -506,8 +506,8 @@ int wolfPKCS11_Store_Write(void* store, unsigned char* buffer, int len)
|
|||
% WOLFBOOT_SECTOR_SIZE;
|
||||
sector_base = (uintptr_t)handle->buffer + handle->in_buffer_offset - in_sector_offset;
|
||||
in_sector_len = WOLFBOOT_SECTOR_SIZE - in_sector_offset;
|
||||
if (in_sector_len > (uint32_t)len)
|
||||
in_sector_len = len;
|
||||
if (in_sector_len > (uint32_t)(len - written))
|
||||
in_sector_len = len - written;
|
||||
|
||||
/* Cache the corresponding sector */
|
||||
memcpy(cached_sector, (void *)(uintptr_t)sector_base, WOLFBOOT_SECTOR_SIZE);
|
||||
|
|
|
|||
|
|
@ -512,8 +512,8 @@ int wolfPSA_Store_Write(void* store, unsigned char* buffer, int len)
|
|||
% WOLFBOOT_SECTOR_SIZE;
|
||||
sector_base = (uintptr_t)handle->buffer + handle->in_buffer_offset - in_sector_offset;
|
||||
in_sector_len = WOLFBOOT_SECTOR_SIZE - in_sector_offset;
|
||||
if (in_sector_len > (uint32_t)len)
|
||||
in_sector_len = len;
|
||||
if (in_sector_len > (uint32_t)(len - written))
|
||||
in_sector_len = len - written;
|
||||
|
||||
/* Cache the corresponding sector */
|
||||
memcpy(cached_sector, (void *)(uintptr_t)sector_base, WOLFBOOT_SECTOR_SIZE);
|
||||
|
|
|
|||
|
|
@ -417,8 +417,10 @@ int spi_flash_read(uint32_t address, void *data, int len)
|
|||
int spi_flash_write(uint32_t address, const void *data, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
int remaining = len;
|
||||
uint32_t xferSz, page, pages;
|
||||
uintptr_t addr;
|
||||
uint8_t* ptr = (uint8_t*)data;
|
||||
|
||||
#ifdef DEBUG_QSPI
|
||||
wolfBoot_printf("QSPI Flash Write: Len %d, %p -> 0x%x\n",
|
||||
|
|
@ -430,13 +432,12 @@ int spi_flash_write(uint32_t address, const void *data, int len)
|
|||
for (page = 0; page < pages; page++) {
|
||||
ret = qspi_write_enable();
|
||||
if (ret == 0) {
|
||||
uint8_t* ptr;
|
||||
xferSz = len;
|
||||
if (xferSz > FLASH_PAGE_SIZE)
|
||||
xferSz = (uint32_t)remaining;
|
||||
if (xferSz > FLASH_PAGE_SIZE) {
|
||||
xferSz = FLASH_PAGE_SIZE;
|
||||
}
|
||||
|
||||
addr = address + (page * FLASH_PAGE_SIZE);
|
||||
ptr = ((uint8_t*)data + (page * FLASH_PAGE_SIZE));
|
||||
|
||||
/* ------ Write Flash (page at a time) ------ */
|
||||
ret = qspi_transfer(QSPI_MODE_WRITE, FLASH_WRITE_CMD,
|
||||
|
|
@ -459,6 +460,8 @@ int spi_flash_write(uint32_t address, const void *data, int len)
|
|||
break;
|
||||
}
|
||||
/* write disable is automatic */
|
||||
remaining -= (int)xferSz;
|
||||
ptr += xferSz;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -361,7 +361,7 @@ void uart_vprintf(const char* fmt, va_list argp)
|
|||
if (*fmtp == '0' && maxdigits == 0) {
|
||||
zeropad = 1;
|
||||
}
|
||||
maxdigits <<= 8;
|
||||
maxdigits *= 10;
|
||||
maxdigits += (*fmtp - '0');
|
||||
fmtp++;
|
||||
}
|
||||
|
|
|
|||
13
src/tpm.c
13
src/tpm.c
|
|
@ -382,6 +382,8 @@ int wolfBoot_load_pubkey(const uint8_t* pubkey_hint, WOLFTPM2_KEY* pubKey,
|
|||
defined(WOLFBOOT_SIGN_RSA3072) || \
|
||||
defined(WOLFBOOT_SIGN_RSA4096)
|
||||
uint32_t inOutIdx = 0;
|
||||
uint32_t exponent = 0;
|
||||
uint32_t j;
|
||||
const uint8_t*n = NULL, *e = NULL;
|
||||
uint32_t nSz = 0, eSz = 0;
|
||||
if (key_type != AUTH_KEY_RSA2048 && key_type != AUTH_KEY_RSA3072 &&
|
||||
|
|
@ -395,10 +397,19 @@ int wolfBoot_load_pubkey(const uint8_t* pubkey_hint, WOLFTPM2_KEY* pubKey,
|
|||
&e, &eSz /* exponent */
|
||||
);
|
||||
}
|
||||
if (rc == 0) {
|
||||
if (eSz == 0 || eSz > sizeof(exponent))
|
||||
rc = -1;
|
||||
}
|
||||
if (rc == 0) {
|
||||
for (j = 0; j < eSz; j++) {
|
||||
exponent = (exponent << 8) | e[j];
|
||||
}
|
||||
}
|
||||
if (rc == 0) {
|
||||
/* Load public key into TPM */
|
||||
rc = wolfTPM2_LoadRsaPublicKey_ex(&wolftpm_dev, pubKey,
|
||||
n, nSz, *((uint32_t*)e),
|
||||
n, nSz, exponent,
|
||||
TPM_ALG_NULL, WOLFBOOT_TPM_HASH_ALG);
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -45,6 +45,15 @@ int WP11_Library_Init(void);
|
|||
|
||||
#ifdef EXT_ENCRYPTED
|
||||
#include "encrypt.h"
|
||||
|
||||
static void wolfBoot_zeroize(void *ptr, size_t len)
|
||||
{
|
||||
volatile uint8_t *p = (volatile uint8_t *)ptr;
|
||||
|
||||
while (len-- > 0) {
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
#endif /* EXT_ENCRYPTED */
|
||||
|
||||
#ifdef MMU
|
||||
|
|
@ -224,6 +233,7 @@ void RAMFUNCTION wolfBoot_check_self_update(void)
|
|||
static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
|
||||
struct wolfBoot_image *dst, uint32_t sector)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t pos = 0;
|
||||
uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
|
||||
uint32_t dst_sector_offset = src_sector_offset;
|
||||
|
|
@ -245,8 +255,10 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
|
|||
dst_sector_offset = 0;
|
||||
|
||||
#ifdef EXT_ENCRYPTED
|
||||
if (wolfBoot_initialize_encryption() < 0)
|
||||
return -1;
|
||||
if (wolfBoot_initialize_encryption() < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
wolfBoot_get_encrypt_key(key, nonce);
|
||||
if (src->part == PART_SWAP)
|
||||
|
|
@ -286,7 +298,8 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
|
|||
}
|
||||
pos += FLASHBUFFER_SIZE;
|
||||
}
|
||||
return pos;
|
||||
ret = pos;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
wb_flash_erase(dst, dst_sector_offset, WOLFBOOT_SECTOR_SIZE);
|
||||
|
|
@ -298,12 +311,21 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
|
|||
}
|
||||
pos += FLASHBUFFER_SIZE;
|
||||
}
|
||||
return pos;
|
||||
ret = pos;
|
||||
#if defined(EXT_FLASH) || defined(EXT_ENCRYPTED)
|
||||
out:
|
||||
#endif
|
||||
#ifdef EXT_ENCRYPTED
|
||||
wolfBoot_zeroize(key, sizeof(key));
|
||||
wolfBoot_zeroize(nonce, sizeof(nonce));
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef EXT_ENCRYPTED
|
||||
static int RAMFUNCTION wolfBoot_backup_last_boot_sector(uint32_t sector)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t pos = 0;
|
||||
uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
|
||||
uint32_t dst_sector_offset = 0;
|
||||
|
|
@ -325,8 +347,10 @@ static int RAMFUNCTION wolfBoot_backup_last_boot_sector(uint32_t sector)
|
|||
|
||||
iv_counter = src_sector_offset;
|
||||
iv_counter /= ENCRYPT_BLOCK_SIZE;
|
||||
if (wolfBoot_initialize_encryption() < 0)
|
||||
return -1;
|
||||
if (wolfBoot_initialize_encryption() < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Preserve the IV sequence used by the source sector so that the staging
|
||||
* copy in SWAP can be decrypted with exactly the same keystream when it is
|
||||
|
|
@ -345,9 +369,14 @@ static int RAMFUNCTION wolfBoot_backup_last_boot_sector(uint32_t sector)
|
|||
wb_flash_write(dst, dst_sector_offset + pos, encrypted_block, ENCRYPT_BLOCK_SIZE);
|
||||
pos += ENCRYPT_BLOCK_SIZE;
|
||||
}
|
||||
return 0;
|
||||
} else
|
||||
return wolfBoot_copy_sector(src, dst, sector);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = wolfBoot_copy_sector(src, dst, sector);
|
||||
}
|
||||
out:
|
||||
wolfBoot_zeroize(key, sizeof(key));
|
||||
wolfBoot_zeroize(nonce, sizeof(nonce));
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#define wolfBoot_backup_last_boot_sector(sec) wolfBoot_copy_sector(boot, swap, sec)
|
||||
|
|
@ -701,6 +730,10 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
|
|||
sector++;
|
||||
}
|
||||
out:
|
||||
#ifdef EXT_ENCRYPTED
|
||||
wolfBoot_zeroize(key, sizeof(key));
|
||||
wolfBoot_zeroize(nonce, sizeof(nonce));
|
||||
#endif
|
||||
#ifdef EXT_FLASH
|
||||
ext_flash_lock();
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ bmdiff.o:
|
|||
gcc -c -o bmdiff.o bmdiff.c -I../../include -ggdb $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f bmpatch bmdiff delta.o
|
||||
rm -f bmpatch bmdiff bmdiff-test delta.o test-bmdiff.o
|
||||
|
||||
delta-test: FORCE bmdiff bmpatch
|
||||
@./bmdiff delta-test/0.txt delta-test/1.txt 0-to-1.patch
|
||||
|
|
@ -45,4 +45,13 @@ delta-test: FORCE bmdiff bmpatch
|
|||
@diff 1p.txt delta-test/0.txt && echo "Test 1-to-0: OK"
|
||||
@rm -f 0-to-1.patch 1-to-0.patch 0p.txt 1p.txt
|
||||
|
||||
bmdiff-test: test-bmdiff.o
|
||||
gcc -o bmdiff-test test-bmdiff.o
|
||||
|
||||
test-bmdiff.o:
|
||||
gcc -c -o test-bmdiff.o test-bmdiff.c -I../../include -ggdb $(CFLAGS)
|
||||
|
||||
test: FORCE bmdiff-test
|
||||
@./bmdiff-test && echo "bmdiff mmap failure test: OK"
|
||||
|
||||
.PHONY: FORCE
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
len2 = st.st_size;
|
||||
buffer = mmap(NULL, len2, PROT_READ, MAP_SHARED, fd2, 0);
|
||||
if (base == (void *)(-1)) {
|
||||
if (buffer == (void *)(-1)) {
|
||||
perror("mmap");
|
||||
exit(3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
#include <assert.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static jmp_buf exit_jmp;
|
||||
static int exit_code = -1;
|
||||
static int mmap_calls = 0;
|
||||
static int patch_init_called = 0;
|
||||
static int perror_called = 0;
|
||||
|
||||
static int mock_stat(const char *path, struct stat *st)
|
||||
{
|
||||
memset(st, 0, sizeof(*st));
|
||||
if (strcmp(path, "source.bin") == 0) {
|
||||
st->st_size = 16;
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(path, "patch.bin") == 0) {
|
||||
st->st_size = 8;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mock_open(const char *path, int flags, ...)
|
||||
{
|
||||
(void)flags;
|
||||
if ((strcmp(path, "source.bin") == 0) || (strcmp(path, "patch.bin") == 0))
|
||||
return 3;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void *mock_mmap(void *addr, size_t len, int prot, int flags, int fd,
|
||||
off_t offset)
|
||||
{
|
||||
static uint8_t source_map[16];
|
||||
|
||||
(void)addr;
|
||||
(void)len;
|
||||
(void)prot;
|
||||
(void)flags;
|
||||
(void)fd;
|
||||
(void)offset;
|
||||
|
||||
mmap_calls++;
|
||||
if (mmap_calls == 1)
|
||||
return source_map;
|
||||
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
static void mock_perror(const char *s)
|
||||
{
|
||||
(void)s;
|
||||
perror_called = 1;
|
||||
}
|
||||
|
||||
static void mock_exit(int code)
|
||||
{
|
||||
exit_code = code;
|
||||
longjmp(exit_jmp, 1);
|
||||
}
|
||||
|
||||
#define WOLFBOOT_SECTOR_SIZE 1024
|
||||
#define stat(path, st) mock_stat(path, st)
|
||||
#define open(path, flags, ...) mock_open(path, flags, ##__VA_ARGS__)
|
||||
#define mmap(addr, len, prot, flags, fd, offset) \
|
||||
mock_mmap(addr, len, prot, flags, fd, offset)
|
||||
#define perror(s) mock_perror(s)
|
||||
#define exit(code) mock_exit(code)
|
||||
#define main bmdiff_tool_main
|
||||
#include "bmdiff.c"
|
||||
#undef main
|
||||
#undef exit
|
||||
#undef perror
|
||||
#undef mmap
|
||||
#undef open
|
||||
#undef stat
|
||||
|
||||
int wb_patch_init(WB_PATCH_CTX *bm, uint8_t *src, uint32_t ssz, uint8_t *patch,
|
||||
uint32_t psz)
|
||||
{
|
||||
(void)bm;
|
||||
(void)src;
|
||||
(void)ssz;
|
||||
(void)patch;
|
||||
(void)psz;
|
||||
|
||||
patch_init_called = 1;
|
||||
mock_exit(99);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)dst;
|
||||
(void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wb_diff_init(WB_DIFF_CTX *ctx, uint8_t *src_a, uint32_t len_a,
|
||||
uint8_t *src_b, uint32_t len_b)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)src_a;
|
||||
(void)len_a;
|
||||
(void)src_b;
|
||||
(void)len_b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wb_diff(WB_DIFF_CTX *ctx, uint8_t *patch, uint32_t len)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)patch;
|
||||
(void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *argv[] = { (char *)"bmpatch", (char *)"source.bin", (char *)"patch.bin" };
|
||||
|
||||
if (setjmp(exit_jmp) == 0)
|
||||
bmdiff_tool_main(3, argv);
|
||||
|
||||
assert(exit_code == 3);
|
||||
assert(perror_called == 1);
|
||||
assert(patch_init_called == 0);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1144,13 +1144,13 @@ test-all: clean
|
|||
|
||||
|
||||
test-size-all:
|
||||
make test-size SIGN=NONE LIMIT=5040 NO_ARM_ASM=1
|
||||
make test-size SIGN=NONE LIMIT=5060 NO_ARM_ASM=1
|
||||
make keysclean
|
||||
make test-size SIGN=ED25519 LIMIT=11724 NO_ARM_ASM=1
|
||||
make test-size SIGN=ED25519 LIMIT=11778 NO_ARM_ASM=1
|
||||
make keysclean
|
||||
make test-size SIGN=ECC256 LIMIT=18944 NO_ARM_ASM=1
|
||||
make clean
|
||||
make test-size SIGN=ECC256 NO_ASM=1 LIMIT=13856 NO_ARM_ASM=1
|
||||
make test-size SIGN=ECC256 NO_ASM=1 LIMIT=13894 NO_ARM_ASM=1
|
||||
make keysclean
|
||||
make test-size SIGN=RSA2048 LIMIT=11916 NO_ARM_ASM=1
|
||||
make clean
|
||||
|
|
@ -1162,9 +1162,9 @@ test-size-all:
|
|||
make keysclean
|
||||
make test-size SIGN=ECC384 LIMIT=19888 NO_ARM_ASM=1
|
||||
make clean
|
||||
make test-size SIGN=ECC384 NO_ASM=1 LIMIT=15232 NO_ARM_ASM=1
|
||||
make test-size SIGN=ECC384 NO_ASM=1 LIMIT=15270 NO_ARM_ASM=1
|
||||
make keysclean
|
||||
make test-size SIGN=ED448 LIMIT=13776 NO_ARM_ASM=1
|
||||
make test-size SIGN=ED448 LIMIT=13846 NO_ARM_ASM=1
|
||||
make keysclean
|
||||
make test-size SIGN=RSA3072 LIMIT=12056 NO_ARM_ASM=1
|
||||
make clean
|
||||
|
|
@ -1172,12 +1172,12 @@ test-size-all:
|
|||
make keysclean
|
||||
make test-size SIGN=LMS LMS_LEVELS=2 LMS_HEIGHT=5 LMS_WINTERNITZ=8 \
|
||||
WOLFBOOT_SMALL_STACK=0 IMAGE_SIGNATURE_SIZE=2644 \
|
||||
IMAGE_HEADER_SIZE?=5288 LIMIT=7712 NO_ARM_ASM=1
|
||||
IMAGE_HEADER_SIZE?=5288 LIMIT=7782 NO_ARM_ASM=1
|
||||
make keysclean
|
||||
make test-size SIGN=XMSS XMSS_PARAMS='XMSS-SHA2_10_256' \
|
||||
IMAGE_SIGNATURE_SIZE=2500 IMAGE_HEADER_SIZE?=4096 \
|
||||
LIMIT=8568 NO_ARM_ASM=1
|
||||
LIMIT=8638 NO_ARM_ASM=1
|
||||
make keysclean
|
||||
make clean
|
||||
make test-size SIGN=ML_DSA ML_DSA_LEVEL=2 LIMIT=19362 \
|
||||
make test-size SIGN=ML_DSA ML_DSA_LEVEL=2 LIMIT=19392 \
|
||||
IMAGE_SIGNATURE_SIZE=2420 IMAGE_HEADER_SIZE?=8192
|
||||
|
|
|
|||
|
|
@ -8,10 +8,21 @@ endif
|
|||
# Default library paths (can be overridden)
|
||||
WOLFBOOT_LIB_WOLFSSL?=../../lib/wolfssl
|
||||
WOLFBOOT_LIB_WOLFPKCS11?=../../lib/wolfPKCS11
|
||||
WOLFBOOT_LIB_WOLFPSA?=../../lib/wolfPSA
|
||||
WOLFBOOT_LIB_WOLFTPM?=../../lib/wolfTPM
|
||||
|
||||
ifeq ($(wildcard $(WOLFBOOT_LIB_WOLFPSA)),)
|
||||
WOLFBOOT_LIB_WOLFPSA=../../../external-libs/wolfPSA
|
||||
endif
|
||||
ifeq ($(wildcard $(WOLFBOOT_LIB_WOLFTPM)),)
|
||||
WOLFBOOT_LIB_WOLFTPM=../../../external-libs/wolfTPM
|
||||
endif
|
||||
|
||||
# Convert to absolute paths for standalone usage
|
||||
WOLFBOOT_LIB_WOLFSSL:=$(abspath $(WOLFBOOT_LIB_WOLFSSL))
|
||||
WOLFBOOT_LIB_WOLFPKCS11:=$(abspath $(WOLFBOOT_LIB_WOLFPKCS11))
|
||||
WOLFBOOT_LIB_WOLFPSA:=$(abspath $(WOLFBOOT_LIB_WOLFPSA))
|
||||
WOLFBOOT_LIB_WOLFTPM:=$(abspath $(WOLFBOOT_LIB_WOLFTPM))
|
||||
|
||||
CFLAGS=-I. -I../../src -I../../include -I$(WOLFBOOT_LIB_WOLFSSL)
|
||||
CFLAGS+=-g -ggdb
|
||||
|
|
@ -33,10 +44,10 @@ endif
|
|||
|
||||
TESTS:=unit-parser unit-extflash unit-string unit-spi-flash unit-aes128 \
|
||||
unit-aes256 unit-chacha20 unit-pci unit-mock-state unit-sectorflags \
|
||||
unit-image unit-nvm unit-nvm-flagshome unit-enc-nvm \
|
||||
unit-image unit-image-rsa unit-nvm unit-nvm-flagshome unit-enc-nvm \
|
||||
unit-enc-nvm-flagshome unit-delta unit-update-flash \
|
||||
unit-update-flash-enc unit-update-ram unit-pkcs11_store unit-disk \
|
||||
unit-multiboot
|
||||
unit-update-flash-enc unit-update-ram unit-pkcs11_store unit-psa_store unit-disk \
|
||||
unit-multiboot unit-boot-x86-fsp unit-qspi-flash unit-tpm-rsa-exp
|
||||
|
||||
all: $(TESTS)
|
||||
|
||||
|
|
@ -75,6 +86,7 @@ unit-enc-nvm-flagshome:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS \
|
|||
unit-enc-nvm-flagshome:WOLFCRYPT_SRC+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/chacha.c
|
||||
unit-delta:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS -DDELTA_UPDATES -DDELTA_BLOCK_SIZE=512
|
||||
unit-pkcs11_store:CFLAGS+=-I$(WOLFBOOT_LIB_WOLFPKCS11) -DMOCK_PARTITIONS -DMOCK_KEYVAULT -DSECURE_PKCS11
|
||||
unit-psa_store:CFLAGS+=-I$(WOLFBOOT_LIB_WOLFPSA) -DMOCK_PARTITIONS -DMOCK_KEYVAULT -DWOLFCRYPT_TZ_PSA
|
||||
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
|
||||
unit-update-ram:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
|
||||
|
|
@ -103,6 +115,15 @@ unit-extflash: ../../include/target.h unit-extflash.c
|
|||
unit-spi-flash: ../../include/target.h unit-spi-flash.c
|
||||
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-qspi-flash: ../../include/target.h unit-qspi-flash.c
|
||||
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-tpm-rsa-exp: ../../include/target.h unit-tpm-rsa-exp.c
|
||||
gcc -o $@ $^ $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) -DWOLFBOOT_TPM \
|
||||
-DWOLFTPM_USER_SETTINGS -DWOLFBOOT_TPM_VERIFY -DWOLFBOOT_SIGN_RSA2048 \
|
||||
-DWOLFBOOT_HASH_SHA256 \
|
||||
-ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections
|
||||
|
||||
unit-string: ../../include/target.h unit-string.c
|
||||
gcc -o $@ $^ $(CFLAGS) -DDEBUG_UART -DPRINTF_ENABLED $(LDFLAGS)
|
||||
|
||||
|
|
@ -118,6 +139,11 @@ unit-chacha20: ../../include/target.h unit-extflash.c
|
|||
unit-pci: unit-pci.c ../../src/pci.c
|
||||
gcc -o $@ $< $(CFLAGS) -DWOLFBOOT_USE_PCI $(LDFLAGS)
|
||||
|
||||
unit-boot-x86-fsp: ../../include/target.h unit-boot-x86_fsp.c
|
||||
gcc -o $@ $^ $(CFLAGS) -DWOLFBOOT_LOAD_BASE=0x100000 -DWOLFBOOT_FSP \
|
||||
-DUCODE0_ADDRESS=0 -ffunction-sections -fdata-sections $(LDFLAGS) \
|
||||
-Wl,--gc-sections
|
||||
|
||||
unit-mock-state: ../../include/target.h unit-mock-state.c
|
||||
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
|
|
@ -127,6 +153,11 @@ unit-sectorflags: ../../include/target.h unit-sectorflags.c
|
|||
unit-image: unit-image.c unit-common.c $(WOLFCRYPT_SRC)
|
||||
gcc -o $@ $^ $(CFLAGS) $(WOLFCRYPT_CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-image-rsa: CFLAGS += -DWOLFBOOT_SIGN_RSA2048
|
||||
unit-image-rsa: ../../include/target.h unit-image.c unit-common.c
|
||||
gcc -o $@ unit-image.c unit-common.c $(WOLFCRYPT_SRC) \
|
||||
$(CFLAGS) -D__WOLFBOOT $(LDFLAGS)
|
||||
|
||||
unit-nvm: ../../include/target.h unit-nvm.c
|
||||
gcc -o $@ unit-nvm.c $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
|
|
@ -161,6 +192,9 @@ unit-update-ram: ../../include/target.h unit-update-ram.c
|
|||
unit-pkcs11_store: ../../include/target.h unit-pkcs11_store.c
|
||||
gcc -o $@ $(WOLFCRYPT_SRC) unit-pkcs11_store.c $(CFLAGS) $(WOLFCRYPT_CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-psa_store: ../../include/target.h unit-psa_store.c
|
||||
gcc -o $@ $(WOLFCRYPT_SRC) unit-psa_store.c $(CFLAGS) $(WOLFCRYPT_CFLAGS) $(LDFLAGS)
|
||||
|
||||
gpt-sfdisk-test.h:
|
||||
truncate -s 131072 .gpt-tmp.img
|
||||
printf 'label: gpt\nfirst-lba: 34\nstart=34, size=67, name="boot"\nstart=101, size=100, name="rootfs"\n' \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
/* unit-boot-x86_fsp.c
|
||||
*
|
||||
* Unit tests for selected boot_x86_fsp helpers.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TEST_CFG_SIZE 256
|
||||
#define TEST_READ_LIMIT 200
|
||||
|
||||
static uint8_t test_cfg[TEST_CFG_SIZE];
|
||||
static unsigned int test_read_count;
|
||||
|
||||
uint8_t pci_config_read8(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off)
|
||||
{
|
||||
(void)bus;
|
||||
(void)dev;
|
||||
(void)fun;
|
||||
|
||||
test_read_count++;
|
||||
ck_assert_msg(test_read_count < TEST_READ_LIMIT,
|
||||
"pci_get_capability exceeded read limit on cyclic list");
|
||||
return test_cfg[off];
|
||||
}
|
||||
|
||||
uint16_t pci_config_read16(uint8_t bus, uint8_t dev, uint8_t fun, uint8_t off)
|
||||
{
|
||||
uint16_t value;
|
||||
|
||||
(void)bus;
|
||||
(void)dev;
|
||||
(void)fun;
|
||||
|
||||
test_read_count++;
|
||||
ck_assert_msg(test_read_count < TEST_READ_LIMIT,
|
||||
"pci_get_capability exceeded read limit on cyclic list");
|
||||
memcpy(&value, &test_cfg[off], sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
#include "../../src/boot_x86_fsp.c"
|
||||
|
||||
static void setup(void)
|
||||
{
|
||||
memset(test_cfg, 0, sizeof(test_cfg));
|
||||
test_read_count = 0;
|
||||
}
|
||||
|
||||
START_TEST(test_pci_get_capability_finds_requested_capability)
|
||||
{
|
||||
uint8_t cap_off = 0;
|
||||
uint16_t status = PCI_STATUS_CAP_LIST;
|
||||
|
||||
memcpy(&test_cfg[PCI_STATUS_OFFSET], &status, sizeof(status));
|
||||
test_cfg[PCI_CAP_OFFSET] = 0x40;
|
||||
test_cfg[0x40] = 0x01;
|
||||
test_cfg[0x41] = 0x48;
|
||||
test_cfg[0x48] = PCI_PCIE_CAP_ID;
|
||||
test_cfg[0x49] = 0x00;
|
||||
|
||||
ck_assert_int_eq(pci_get_capability(0, 0, 0, PCI_PCIE_CAP_ID, &cap_off), 0);
|
||||
ck_assert_uint_eq(cap_off, 0x48);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_pci_get_capability_rejects_cyclic_capability_lists)
|
||||
{
|
||||
uint8_t cap_off = 0xAA;
|
||||
uint16_t status = PCI_STATUS_CAP_LIST;
|
||||
|
||||
memcpy(&test_cfg[PCI_STATUS_OFFSET], &status, sizeof(status));
|
||||
test_cfg[PCI_CAP_OFFSET] = 0x40;
|
||||
test_cfg[0x40] = 0x01;
|
||||
test_cfg[0x41] = 0x48;
|
||||
test_cfg[0x48] = 0x05;
|
||||
test_cfg[0x49] = 0x40;
|
||||
|
||||
ck_assert_int_eq(pci_get_capability(0, 0, 0, PCI_PCIE_CAP_ID, &cap_off), -1);
|
||||
ck_assert_uint_eq(cap_off, 0xAA);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite *boot_x86_fsp_suite(void)
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc;
|
||||
|
||||
s = suite_create("boot_x86_fsp");
|
||||
tc = tcase_create("pci_get_capability");
|
||||
tcase_add_checked_fixture(tc, setup, NULL);
|
||||
tcase_add_test(tc, test_pci_get_capability_finds_requested_capability);
|
||||
tcase_add_test(tc, test_pci_get_capability_rejects_cyclic_capability_lists);
|
||||
suite_add_tcase(s, tc);
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
int failed;
|
||||
|
||||
s = boot_x86_fsp_suite();
|
||||
sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
|
|
@ -114,6 +114,22 @@ START_TEST(test_wb_patch_resume_large_len)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_wb_patch_trailing_escape_invalid)
|
||||
{
|
||||
WB_PATCH_CTX patch_ctx;
|
||||
uint8_t src[SRC_SIZE] = {0};
|
||||
uint8_t patch[1] = {ESC};
|
||||
uint8_t dst[DELTA_BLOCK_SIZE] = {0};
|
||||
int ret;
|
||||
|
||||
ret = wb_patch_init(&patch_ctx, src, SRC_SIZE, patch, sizeof(patch));
|
||||
ck_assert_int_eq(ret, 0);
|
||||
|
||||
ret = wb_patch(&patch_ctx, dst, sizeof(dst));
|
||||
ck_assert_int_eq(ret, -1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_wb_diff_init_invalid)
|
||||
{
|
||||
WB_DIFF_CTX ctx;
|
||||
|
|
@ -230,6 +246,7 @@ Suite *patch_diff_suite(void)
|
|||
tcase_add_test(tc_wolfboot_delta, test_wb_patch_src_bounds_invalid);
|
||||
tcase_add_test(tc_wolfboot_delta, test_wb_patch_resume_bounds_invalid);
|
||||
tcase_add_test(tc_wolfboot_delta, test_wb_patch_resume_large_len);
|
||||
tcase_add_test(tc_wolfboot_delta, test_wb_patch_trailing_escape_invalid);
|
||||
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff);
|
||||
suite_add_tcase(s, tc_wolfboot_delta);
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,29 @@ static const int PART0_END = 100;
|
|||
static const int PART1_OFF = 101;
|
||||
static const int PART1_END = 200;
|
||||
|
||||
static uint32_t test_crc32(const uint8_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFFU;
|
||||
uint32_t i;
|
||||
uint32_t j;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
crc ^= data[i];
|
||||
for (j = 0; j < 8; j++) {
|
||||
uint32_t mask = -(crc & 1U);
|
||||
crc = (crc >> 1) ^ (0xEDB88320U & mask);
|
||||
}
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
static void finalize_gpt_header_crc(struct guid_ptable *hdr)
|
||||
{
|
||||
hdr->hdr_crc32 = 0;
|
||||
hdr->hdr_crc32 = test_crc32((const uint8_t *)hdr, hdr->hdr_size);
|
||||
}
|
||||
|
||||
/* --- Helpers to build fake disk layouts --- */
|
||||
|
||||
/* Write a UTF-16LE string into a buffer (no BOM).
|
||||
|
|
@ -133,6 +156,8 @@ static void build_gpt_disk(void)
|
|||
(PART0_END - PART0_OFF + 1) * GPT_SECTOR_SIZE);
|
||||
memset(fake_disk + PART1_OFF * GPT_SECTOR_SIZE, 0xBB,
|
||||
(PART1_END - PART1_OFF + 1) * GPT_SECTOR_SIZE);
|
||||
|
||||
finalize_gpt_header_crc(gpt_hdr);
|
||||
}
|
||||
|
||||
/* Populate fake_disk with MBR-only layout (no GPT protective entry).
|
||||
|
|
@ -200,6 +225,17 @@ START_TEST(test_gpt_parse_header)
|
|||
ck_assert_uint_eq(hdr.start_array, 2);
|
||||
ck_assert_uint_eq(hdr.array_sz, 128);
|
||||
|
||||
/* Corrupt a header field without updating CRC */
|
||||
{
|
||||
struct guid_ptable *gpt_hdr =
|
||||
(struct guid_ptable *)(fake_disk + GPT_SECTOR_SIZE);
|
||||
gpt_hdr->n_part = 3;
|
||||
ck_assert_int_eq(
|
||||
gpt_parse_header(fake_disk + GPT_SECTOR_SIZE, &hdr), -1);
|
||||
gpt_hdr->n_part = 2;
|
||||
finalize_gpt_header_crc(gpt_hdr);
|
||||
}
|
||||
|
||||
/* Corrupt signature in the real header */
|
||||
{
|
||||
struct guid_ptable *gpt_hdr =
|
||||
|
|
@ -208,6 +244,7 @@ START_TEST(test_gpt_parse_header)
|
|||
ck_assert_int_eq(
|
||||
gpt_parse_header(fake_disk + GPT_SECTOR_SIZE, &hdr), -1);
|
||||
gpt_hdr->signature = GPT_SIGNATURE;
|
||||
finalize_gpt_header_crc(gpt_hdr);
|
||||
}
|
||||
|
||||
/* NULL inputs */
|
||||
|
|
@ -537,6 +574,7 @@ START_TEST(test_disk_open_gpt_excess_partitions)
|
|||
|
||||
gpt_hdr = (struct guid_ptable *)(fake_disk + GPT_SECTOR_SIZE);
|
||||
gpt_hdr->n_part = MAX_PARTITIONS + 10;
|
||||
finalize_gpt_header_crc(gpt_hdr);
|
||||
|
||||
/* Only 2 actual entries on disk so loop will break after parsing them,
|
||||
* but the capping branch is exercised. */
|
||||
|
|
@ -555,6 +593,7 @@ START_TEST(test_disk_open_gpt_large_array_sz)
|
|||
|
||||
gpt_hdr = (struct guid_ptable *)(fake_disk + GPT_SECTOR_SIZE);
|
||||
gpt_hdr->array_sz = GPT_PART_ENTRY_SIZE + 1; /* 257 > 256 */
|
||||
finalize_gpt_header_crc(gpt_hdr);
|
||||
|
||||
ck_assert_int_eq(disk_open(0), 0); /* 0 partitions found */
|
||||
}
|
||||
|
|
@ -571,6 +610,7 @@ START_TEST(test_disk_open_gpt_empty_entry_mid_table)
|
|||
|
||||
gpt_hdr = (struct guid_ptable *)(fake_disk + GPT_SECTOR_SIZE);
|
||||
gpt_hdr->n_part = 3;
|
||||
finalize_gpt_header_crc(gpt_hdr);
|
||||
|
||||
/* Zero out entry 1's type GUID */
|
||||
pe = (struct gpt_part_entry *)(fake_disk + 2 * GPT_SECTOR_SIZE + 128);
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ uint8_t flash[FLASH_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);
|
||||
printf("Called ext_flash_read %p %p %d\n", (void *)address, (void *)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);
|
||||
|
|
@ -106,7 +106,7 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int 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);
|
||||
printf("Called ext_flash_write %p %p %d\n", (void *)address, (const void *)data, len);
|
||||
|
||||
|
||||
/* Check that the write address and size are within the bounds of the flash memory */
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#define EXT_FLASH
|
||||
#define PART_UPDATE_EXT
|
||||
#define NVM_FLASH_WRITEONCE
|
||||
#define WOLFBOOT_SELF_HEADER
|
||||
|
||||
#if defined(ENCRYPT_WITH_AES256) || defined(ENCRYPT_WITH_AES128)
|
||||
#define WOLFSSL_AES_COUNTER
|
||||
|
|
@ -61,6 +62,10 @@
|
|||
#include "wolfssl/wolfcrypt/sha.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
|
||||
#ifndef ARCH_FLASH_OFFSET
|
||||
#define ARCH_FLASH_OFFSET WOLFBOOT_PARTITION_BOOT_ADDRESS
|
||||
#endif
|
||||
|
||||
#include "unit-keystore.c"
|
||||
|
||||
#include "image.c"
|
||||
|
|
@ -76,6 +81,11 @@ static int find_header_fail = 0;
|
|||
static int find_header_called = 0;
|
||||
static int find_header_mocked = 1;
|
||||
|
||||
uint8_t *wolfBoot_get_self_header(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(WOLFBOOT_SIGN_ECC256)
|
||||
static const unsigned char pubkey_digest[SHA256_DIGEST_SIZE] = {
|
||||
0x17, 0x20, 0xa5, 0x9b, 0xe0, 0x9b, 0x80, 0x0c, 0xaa, 0xc4, 0xf5, 0x3f,
|
||||
|
|
@ -309,7 +319,7 @@ uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(WOLFBOOT_SIGN_ECC256)
|
||||
int wc_ecc_init(ecc_key* key) {
|
||||
if (ecc_init_fail)
|
||||
return -1;
|
||||
|
|
@ -338,7 +348,9 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
|
|||
*res = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WOLFBOOT_SIGN_ECC256)
|
||||
START_TEST(test_verify_signature)
|
||||
{
|
||||
uint8_t pubkey[32];
|
||||
|
|
@ -373,6 +385,73 @@ START_TEST(test_verify_signature)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_keyslot_id_by_sha_scans_all_slots)
|
||||
{
|
||||
int id;
|
||||
|
||||
unit_keystore_reset_counters();
|
||||
id = keyslot_id_by_sha(pubkey_digest);
|
||||
|
||||
ck_assert_int_eq(id, 0);
|
||||
ck_assert_int_eq(unit_keystore_get_buffer_calls(), keystore_num_pubkeys());
|
||||
ck_assert_int_eq(unit_keystore_get_size_calls(), keystore_num_pubkeys());
|
||||
}
|
||||
END_TEST
|
||||
#endif
|
||||
|
||||
#if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_RSA3072) || \
|
||||
defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) || \
|
||||
defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) || \
|
||||
defined(WOLFBOOT_SIGN_SECONDARY_RSA4096)
|
||||
int wc_InitRsaKey(RsaKey* key, void* heap)
|
||||
{
|
||||
(void)key;
|
||||
(void)heap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_FreeRsaKey(RsaKey* key)
|
||||
{
|
||||
(void)key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
|
||||
word32 inSz)
|
||||
{
|
||||
(void)input;
|
||||
(void)inOutIdx;
|
||||
(void)key;
|
||||
(void)inSz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
|
||||
{
|
||||
(void)in;
|
||||
(void)inLen;
|
||||
(void)out;
|
||||
(void)key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
START_TEST(test_decode_asn1_tag_start_bounds)
|
||||
{
|
||||
uint8_t *input = malloc(1);
|
||||
int idx = 0;
|
||||
volatile int input_sz = 1;
|
||||
int tag_len = -1;
|
||||
|
||||
ck_assert_ptr_nonnull(input);
|
||||
input[0] = ASN_SEQUENCE | ASN_CONSTRUCTED;
|
||||
|
||||
ck_assert_int_eq(DecodeAsn1Tag(input, input_sz, &idx, &tag_len,
|
||||
ASN_SEQUENCE | ASN_CONSTRUCTED), -1);
|
||||
free(input);
|
||||
}
|
||||
END_TEST
|
||||
#endif
|
||||
|
||||
|
||||
START_TEST(test_sha_ops)
|
||||
{
|
||||
|
|
@ -507,6 +586,7 @@ START_TEST(test_headers)
|
|||
ck_assert_uint_eq(sz, test_img_len - 256);
|
||||
}
|
||||
|
||||
#if defined(WOLFBOOT_SIGN_ECC256)
|
||||
START_TEST(test_verify_authenticity)
|
||||
{
|
||||
struct wolfBoot_image test_img;
|
||||
|
|
@ -573,6 +653,7 @@ START_TEST(test_verify_authenticity_bad_siglen)
|
|||
ck_assert_int_eq(ret, -1);
|
||||
}
|
||||
END_TEST
|
||||
#endif
|
||||
|
||||
START_TEST(test_verify_integrity)
|
||||
{
|
||||
|
|
@ -606,6 +687,8 @@ START_TEST(test_open_image)
|
|||
{
|
||||
struct wolfBoot_image img;
|
||||
int ret;
|
||||
uint8_t self_hdr[IMAGE_HEADER_SIZE];
|
||||
uint32_t oversize;
|
||||
|
||||
|
||||
/* invalid argument */
|
||||
|
|
@ -651,6 +734,17 @@ START_TEST(test_open_image)
|
|||
ck_assert_ptr_eq(img.hdr, (void *)WOLFBOOT_PARTITION_UPDATE_ADDRESS);
|
||||
ck_assert_ptr_eq(img.fw_base, (uint8_t *)WOLFBOOT_PARTITION_UPDATE_ADDRESS
|
||||
+ 256);
|
||||
|
||||
/* Self header must reject sizes beyond the partition payload budget */
|
||||
memset(self_hdr, 0xFF, sizeof(self_hdr));
|
||||
((uint32_t *)self_hdr)[0] = WOLFBOOT_MAGIC;
|
||||
oversize = WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE + 1;
|
||||
((uint32_t *)self_hdr)[1] = oversize;
|
||||
|
||||
memset(&img, 0, sizeof(img));
|
||||
ret = wolfBoot_open_self_address(&img, self_hdr,
|
||||
(uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS);
|
||||
ck_assert_int_eq(ret, -1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
|
@ -660,11 +754,36 @@ Suite *wolfboot_suite(void)
|
|||
/* Suite initialization */
|
||||
Suite *s = suite_create("wolfBoot");
|
||||
|
||||
#if defined(WOLFBOOT_SIGN_ECC256)
|
||||
TCase* tcase_verify_signature = tcase_create("verify_signature");
|
||||
tcase_set_timeout(tcase_verify_signature, 20);
|
||||
tcase_add_test(tcase_verify_signature, test_verify_signature);
|
||||
tcase_add_test(tcase_verify_signature, test_keyslot_id_by_sha_scans_all_slots);
|
||||
suite_add_tcase(s, tcase_verify_signature);
|
||||
#endif
|
||||
|
||||
#if defined(WOLFBOOT_SIGN_RSA2048) || defined(WOLFBOOT_SIGN_RSA3072) || \
|
||||
defined(WOLFBOOT_SIGN_RSA4096) || defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) || \
|
||||
defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) || \
|
||||
defined(WOLFBOOT_SIGN_SECONDARY_RSA4096)
|
||||
TCase* tcase_rsa_asn1 = tcase_create("rsa_asn1");
|
||||
tcase_set_timeout(tcase_rsa_asn1, 20);
|
||||
tcase_add_test(tcase_rsa_asn1, test_decode_asn1_tag_start_bounds);
|
||||
suite_add_tcase(s, tcase_rsa_asn1);
|
||||
#endif
|
||||
|
||||
#if defined(WOLFBOOT_SIGN_ECC256)
|
||||
TCase* tcase_verify_authenticity = tcase_create("verify_authenticity");
|
||||
tcase_set_timeout(tcase_verify_authenticity, 20);
|
||||
tcase_add_test(tcase_verify_authenticity, test_verify_authenticity);
|
||||
tcase_add_test(tcase_verify_authenticity, test_verify_authenticity_bad_siglen);
|
||||
suite_add_tcase(s, tcase_verify_authenticity);
|
||||
#endif
|
||||
|
||||
#if !defined(WOLFBOOT_SIGN_RSA2048) && !defined(WOLFBOOT_SIGN_RSA3072) && \
|
||||
!defined(WOLFBOOT_SIGN_RSA4096) && !defined(WOLFBOOT_SIGN_SECONDARY_RSA2048) && \
|
||||
!defined(WOLFBOOT_SIGN_SECONDARY_RSA3072) && \
|
||||
!defined(WOLFBOOT_SIGN_SECONDARY_RSA4096)
|
||||
TCase* tcase_sha_ops = tcase_create("sha_ops");
|
||||
tcase_set_timeout(tcase_sha_ops, 20);
|
||||
tcase_add_test(tcase_sha_ops, test_sha_ops);
|
||||
|
|
@ -675,12 +794,6 @@ Suite *wolfboot_suite(void)
|
|||
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);
|
||||
tcase_add_test(tcase_verify_authenticity, test_verify_authenticity_bad_siglen);
|
||||
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);
|
||||
|
|
@ -690,6 +803,7 @@ Suite *wolfboot_suite(void)
|
|||
tcase_set_timeout(tcase_open_image, 20);
|
||||
tcase_add_test(tcase_open_image, test_open_image);
|
||||
suite_add_tcase(s, tcase_open_image);
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,11 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define NUM_PUBKEYS 1
|
||||
#define NUM_PUBKEYS 3
|
||||
|
||||
static int keystore_get_buffer_calls;
|
||||
static int keystore_get_size_calls;
|
||||
|
||||
const KEYSTORE_SECTION struct keystore_slot PubKeys[NUM_PUBKEYS] = {
|
||||
|
||||
/* Key associated to file 'wolfboot_signing_private_key.der' */
|
||||
|
|
@ -110,6 +114,20 @@ const KEYSTORE_SECTION struct keystore_slot PubKeys[NUM_PUBKEYS] = {
|
|||
.pubkey_size = UNIT_PUBKEY_SIZE,
|
||||
.pubkey = UNIT_PUBKEY_INIT,
|
||||
},
|
||||
{
|
||||
.slot_id = 1,
|
||||
.key_type = UNIT_KEY_TYPE,
|
||||
.part_id_mask = 0xFFFFFFFF,
|
||||
.pubkey_size = UNIT_PUBKEY_SIZE,
|
||||
.pubkey = { 0x00 },
|
||||
},
|
||||
{
|
||||
.slot_id = 2,
|
||||
.key_type = UNIT_KEY_TYPE,
|
||||
.part_id_mask = 0xFFFFFFFF,
|
||||
.pubkey_size = UNIT_PUBKEY_SIZE,
|
||||
.pubkey = { 0x01 },
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
|
@ -123,6 +141,7 @@ uint8_t *keystore_get_buffer(int id)
|
|||
{
|
||||
if (id >= keystore_num_pubkeys())
|
||||
return (uint8_t *)0;
|
||||
keystore_get_buffer_calls++;
|
||||
return (uint8_t *)PubKeys[id].pubkey;
|
||||
}
|
||||
|
||||
|
|
@ -130,6 +149,7 @@ int keystore_get_size(int id)
|
|||
{
|
||||
if (id >= keystore_num_pubkeys())
|
||||
return -1;
|
||||
keystore_get_size_calls++;
|
||||
return (int)PubKeys[id].pubkey_size;
|
||||
}
|
||||
|
||||
|
|
@ -145,4 +165,20 @@ uint32_t keystore_get_key_type(int id)
|
|||
return PubKeys[id].key_type;
|
||||
}
|
||||
|
||||
void unit_keystore_reset_counters(void)
|
||||
{
|
||||
keystore_get_buffer_calls = 0;
|
||||
keystore_get_size_calls = 0;
|
||||
}
|
||||
|
||||
int unit_keystore_get_buffer_calls(void)
|
||||
{
|
||||
return keystore_get_buffer_calls;
|
||||
}
|
||||
|
||||
int unit_keystore_get_size_calls(void)
|
||||
{
|
||||
return keystore_get_size_calls;
|
||||
}
|
||||
|
||||
#endif /* WOLFBOOT_NO_SIGN */
|
||||
|
|
|
|||
|
|
@ -242,8 +242,8 @@ START_TEST (test_store_and_load_objs) {
|
|||
/* Read out the content */
|
||||
memset(secret_rd, 0, KEYVAULT_OBJ_SIZE);
|
||||
ret = wolfPKCS11_Store_Read(store, secret_rd, KEYVAULT_OBJ_SIZE);
|
||||
ck_assert(ret == KEYVAULT_OBJ_SIZE - 8);
|
||||
ck_assert(strncmp(dante_filler, secret_rd, KEYVAULT_OBJ_SIZE - 8) == 0);
|
||||
ck_assert_int_eq(ret, strlen(dante_filler) + 1);
|
||||
ck_assert(strncmp(dante_filler, secret_rd, strlen(dante_filler) + 1) == 0);
|
||||
wolfPKCS11_Store_Close(store);
|
||||
|
||||
/* Reopen for writing, test truncate */
|
||||
|
|
@ -280,14 +280,55 @@ START_TEST (test_store_and_load_objs) {
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_cross_sector_write_preserves_length)
|
||||
{
|
||||
const int type = DYNAMIC_TYPE_RSA;
|
||||
const CK_ULONG id_tok = 7;
|
||||
const CK_ULONG id_obj = 9;
|
||||
void *store = NULL;
|
||||
unsigned char *payload;
|
||||
struct store_handle *handle;
|
||||
int ret;
|
||||
|
||||
payload = malloc(WOLFBOOT_SECTOR_SIZE);
|
||||
ck_assert_ptr_nonnull(payload);
|
||||
|
||||
for (ret = 0; ret < WOLFBOOT_SECTOR_SIZE; ret++)
|
||||
payload[ret] = (unsigned char)(ret & 0xFF);
|
||||
|
||||
ret = mmap_file("/tmp/wolfboot-unit-keyvault.bin", vault_base,
|
||||
keyvault_size, NULL);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
memset(vault_base, 0xEE, keyvault_size);
|
||||
|
||||
ret = wolfPKCS11_Store_Open(type, id_tok, id_obj, 0, &store);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
ck_assert_ptr_nonnull(store);
|
||||
|
||||
ret = wolfPKCS11_Store_Write(store, payload, WOLFBOOT_SECTOR_SIZE);
|
||||
ck_assert_int_eq(ret, WOLFBOOT_SECTOR_SIZE);
|
||||
handle = store;
|
||||
ck_assert_uint_eq(handle->in_buffer_offset,
|
||||
2 * sizeof(uint32_t) + WOLFBOOT_SECTOR_SIZE);
|
||||
ck_assert_uint_eq(handle->hdr->size,
|
||||
2 * sizeof(uint32_t) + WOLFBOOT_SECTOR_SIZE);
|
||||
wolfPKCS11_Store_Close(store);
|
||||
|
||||
free(payload);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *wolfboot_suite(void)
|
||||
{
|
||||
/* Suite initialization */
|
||||
Suite *s = suite_create("wolfBoot-pkcs11-store");
|
||||
|
||||
TCase* tcase_store_and_load_objs = tcase_create("store_and_load_objs");
|
||||
TCase* tcase_cross_sector_write = tcase_create("cross_sector_write");
|
||||
tcase_add_test(tcase_store_and_load_objs, test_store_and_load_objs);
|
||||
tcase_add_test(tcase_cross_sector_write, test_cross_sector_write_preserves_length);
|
||||
suite_add_tcase(s, tcase_store_and_load_objs);
|
||||
suite_add_tcase(s, tcase_cross_sector_write);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
/* unit-psa_store.c
|
||||
*
|
||||
* Unit test for PSA storage module
|
||||
*
|
||||
* Copyright (C) 2026 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
|
||||
*/
|
||||
|
||||
#define WOLFBOOT_HASH_SHA256
|
||||
#define EXT_FLASH
|
||||
#define PART_UPDATE_EXT
|
||||
#define NVM_FLASH_WRITEONCE
|
||||
|
||||
#define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ECC256
|
||||
|
||||
#include <check.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define XMALLOC_OVERRIDE
|
||||
#define XMALLOC(n,h,t) malloc(n)
|
||||
#define XFREE(p,h,t) free(p)
|
||||
|
||||
#include "user_settings.h"
|
||||
#include "wolfssl/wolfcrypt/sha.h"
|
||||
#include "wolfssl/wolfcrypt/error-crypt.h"
|
||||
#include "wolfboot/wolfboot.h"
|
||||
#include "wolfpsa/psa_store.h"
|
||||
#include "hal.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define MOCK_ADDRESS 0xCF000000
|
||||
uint8_t *vault_base = (uint8_t *)MOCK_ADDRESS;
|
||||
#include "psa_store.c"
|
||||
const uint32_t keyvault_size = KEYVAULT_OBJ_SIZE * KEYVAULT_MAX_ITEMS + 2 * WOLFBOOT_SECTOR_SIZE;
|
||||
#include "unit-mock-flash.c"
|
||||
|
||||
START_TEST(test_cross_sector_write_preserves_length)
|
||||
{
|
||||
enum { type = WOLFPSA_STORE_KEY };
|
||||
const unsigned long id1 = 7;
|
||||
const unsigned long id2 = 9;
|
||||
void *store = NULL;
|
||||
unsigned char *payload;
|
||||
struct store_handle *handle;
|
||||
int ret;
|
||||
|
||||
payload = malloc(WOLFBOOT_SECTOR_SIZE);
|
||||
ck_assert_ptr_nonnull(payload);
|
||||
|
||||
for (ret = 0; ret < WOLFBOOT_SECTOR_SIZE; ret++)
|
||||
payload[ret] = (unsigned char)(ret & 0xFF);
|
||||
|
||||
ret = mmap_file("/tmp/wolfboot-unit-psa-keyvault.bin", vault_base,
|
||||
keyvault_size, NULL);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
memset(vault_base, 0xEE, keyvault_size);
|
||||
|
||||
ret = wolfPSA_Store_Open(type, id1, id2, 0, &store);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
ck_assert_ptr_nonnull(store);
|
||||
|
||||
ret = wolfPSA_Store_Write(store, payload, WOLFBOOT_SECTOR_SIZE);
|
||||
ck_assert_int_eq(ret, WOLFBOOT_SECTOR_SIZE);
|
||||
handle = store;
|
||||
ck_assert_uint_eq(handle->in_buffer_offset,
|
||||
2 * sizeof(uint32_t) + WOLFBOOT_SECTOR_SIZE);
|
||||
ck_assert_uint_eq(handle->hdr->size,
|
||||
2 * sizeof(uint32_t) + WOLFBOOT_SECTOR_SIZE);
|
||||
wolfPSA_Store_Close(store);
|
||||
|
||||
free(payload);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *wolfboot_suite(void)
|
||||
{
|
||||
Suite *s = suite_create("wolfBoot-psa-store");
|
||||
TCase *tcase_write = tcase_create("cross_sector_write");
|
||||
|
||||
tcase_add_test(tcase_write, test_cross_sector_write_preserves_length);
|
||||
suite_add_tcase(s, tcase_write);
|
||||
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,116 @@
|
|||
/* unit-qspi-flash.c
|
||||
*
|
||||
* Unit tests for qspi_flash.c.
|
||||
*/
|
||||
|
||||
#define QSPI_FLASH
|
||||
|
||||
#include <check.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static int program_call_count;
|
||||
static uint32_t program_sizes[8];
|
||||
static const uint8_t *program_ptrs[8];
|
||||
static uint32_t program_addrs[8];
|
||||
|
||||
void spi_init(int polarity, int phase)
|
||||
{
|
||||
(void)polarity;
|
||||
(void)phase;
|
||||
}
|
||||
|
||||
void spi_release(void)
|
||||
{
|
||||
}
|
||||
|
||||
#include "../../src/qspi_flash.c"
|
||||
|
||||
int qspi_transfer(uint8_t fmode, const uint8_t cmd,
|
||||
uint32_t addr, uint32_t addrSz, uint32_t addrMode,
|
||||
uint32_t alt, uint32_t altSz, uint32_t altMode,
|
||||
uint32_t dummySz,
|
||||
uint8_t* data, uint32_t dataSz, uint32_t dataMode)
|
||||
{
|
||||
(void)fmode;
|
||||
(void)addrSz;
|
||||
(void)addrMode;
|
||||
(void)alt;
|
||||
(void)altSz;
|
||||
(void)altMode;
|
||||
(void)dummySz;
|
||||
(void)dataMode;
|
||||
|
||||
if (cmd == READ_SR_CMD) {
|
||||
ck_assert_ptr_nonnull(data);
|
||||
ck_assert_uint_ge(dataSz, 1);
|
||||
data[0] = FLASH_SR_WRITE_EN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cmd == FLASH_WRITE_CMD) {
|
||||
ck_assert_int_lt(program_call_count, (int)(sizeof(program_sizes) / sizeof(program_sizes[0])));
|
||||
program_sizes[program_call_count] = dataSz;
|
||||
program_ptrs[program_call_count] = data;
|
||||
program_addrs[program_call_count] = addr;
|
||||
program_call_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup(void)
|
||||
{
|
||||
program_call_count = 0;
|
||||
memset(program_sizes, 0, sizeof(program_sizes));
|
||||
memset(program_ptrs, 0, sizeof(program_ptrs));
|
||||
memset(program_addrs, 0, sizeof(program_addrs));
|
||||
}
|
||||
|
||||
START_TEST(test_qspi_write_splits_last_page_to_remaining_bytes)
|
||||
{
|
||||
uint8_t buf[300];
|
||||
int ret;
|
||||
|
||||
memset(buf, 0xA5, sizeof(buf));
|
||||
|
||||
ret = spi_flash_write(0x1000, buf, sizeof(buf));
|
||||
|
||||
ck_assert_int_eq(ret, 0);
|
||||
ck_assert_int_eq(program_call_count, 2);
|
||||
ck_assert_uint_eq(program_sizes[0], FLASH_PAGE_SIZE);
|
||||
ck_assert_ptr_eq(program_ptrs[0], buf);
|
||||
ck_assert_uint_eq(program_addrs[0], 0x1000);
|
||||
ck_assert_uint_eq(program_sizes[1], sizeof(buf) - FLASH_PAGE_SIZE);
|
||||
ck_assert_ptr_eq(program_ptrs[1], buf + FLASH_PAGE_SIZE);
|
||||
ck_assert_uint_eq(program_addrs[1], 0x1000 + FLASH_PAGE_SIZE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite *qspi_flash_suite(void)
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc;
|
||||
|
||||
s = suite_create("QSPI Flash");
|
||||
tc = tcase_create("Write");
|
||||
tcase_add_checked_fixture(tc, setup, NULL);
|
||||
tcase_add_test(tc, test_qspi_write_splits_last_page_to_remaining_bytes);
|
||||
suite_add_tcase(s, tc);
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
int failed;
|
||||
|
||||
s = qspi_flash_suite();
|
||||
sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/* unit-tpm-rsa-exp.c
|
||||
*
|
||||
* Unit tests for TPM RSA public-key loading.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SPI_CS_TPM
|
||||
#define SPI_CS_TPM 1
|
||||
#endif
|
||||
#ifndef WOLFBOOT_SHA_DIGEST_SIZE
|
||||
#define WOLFBOOT_SHA_DIGEST_SIZE 32
|
||||
#endif
|
||||
#ifndef WOLFBOOT_TPM_HASH_ALG
|
||||
#define WOLFBOOT_TPM_HASH_ALG TPM_ALG_SHA256
|
||||
#endif
|
||||
|
||||
#include "wolfboot/wolfboot.h"
|
||||
#include "keystore.h"
|
||||
#include "tpm.h"
|
||||
|
||||
static uint8_t test_hdr[16];
|
||||
static uint8_t test_modulus[256];
|
||||
static uint8_t test_exponent_der[] = { 0xAA, 0x01, 0x00, 0x01, 0x7B };
|
||||
static uint32_t captured_exponent;
|
||||
|
||||
int keyslot_id_by_sha(const uint8_t* pubkey_hint)
|
||||
{
|
||||
(void)pubkey_hint;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t keystore_get_key_type(int id)
|
||||
{
|
||||
ck_assert_int_eq(id, 0);
|
||||
return AUTH_KEY_RSA2048;
|
||||
}
|
||||
|
||||
uint8_t *keystore_get_buffer(int id)
|
||||
{
|
||||
ck_assert_int_eq(id, 0);
|
||||
return test_hdr;
|
||||
}
|
||||
|
||||
int keystore_get_size(int id)
|
||||
{
|
||||
ck_assert_int_eq(id, 0);
|
||||
return (int)sizeof(test_hdr);
|
||||
}
|
||||
|
||||
int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz,
|
||||
const byte** n, word32* nSz, const byte** e, word32* eSz)
|
||||
{
|
||||
(void)input;
|
||||
(void)inSz;
|
||||
|
||||
*inOutIdx = 0;
|
||||
*n = test_modulus;
|
||||
*nSz = sizeof(test_modulus);
|
||||
*e = &test_exponent_der[1];
|
||||
*eSz = 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wolfTPM2_LoadRsaPublicKey_ex(WOLFTPM2_DEV* dev, WOLFTPM2_KEY* key,
|
||||
const byte* rsaPub, word32 rsaPubSz, word32 exponent,
|
||||
TPM_ALG_ID scheme, TPMI_ALG_HASH hashAlg)
|
||||
{
|
||||
(void)dev;
|
||||
(void)key;
|
||||
(void)rsaPub;
|
||||
(void)rsaPubSz;
|
||||
(void)scheme;
|
||||
(void)hashAlg;
|
||||
|
||||
captured_exponent = exponent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "../../src/tpm.c"
|
||||
|
||||
static void setup(void)
|
||||
{
|
||||
memset(test_hdr, 0x42, sizeof(test_hdr));
|
||||
memset(test_modulus, 0x5A, sizeof(test_modulus));
|
||||
captured_exponent = 0;
|
||||
}
|
||||
|
||||
START_TEST(test_wolfBoot_load_pubkey_decodes_der_exponent_bytes)
|
||||
{
|
||||
uint8_t hint[WOLFBOOT_SHA_DIGEST_SIZE] = { 0 };
|
||||
WOLFTPM2_KEY key;
|
||||
TPM_ALG_ID alg = TPM_ALG_NULL;
|
||||
int rc;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
rc = wolfBoot_load_pubkey(hint, &key, &alg);
|
||||
|
||||
ck_assert_int_eq(rc, 0);
|
||||
ck_assert_int_eq(alg, TPM_ALG_RSA);
|
||||
ck_assert_uint_eq(captured_exponent, 65537U);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite *tpm_suite(void)
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc;
|
||||
|
||||
s = suite_create("TPM RSA");
|
||||
tc = tcase_create("wolfBoot_load_pubkey");
|
||||
tcase_add_checked_fixture(tc, setup, NULL);
|
||||
tcase_add_test(tc, test_wolfBoot_load_pubkey_decodes_der_exponent_bytes);
|
||||
suite_add_tcase(s, tc);
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
int failed;
|
||||
|
||||
s = tpm_suite();
|
||||
sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
Loading…
Reference in New Issue