diff --git a/.gitignore b/.gitignore index d03344c43c..ae120f7c65 100644 --- a/.gitignore +++ b/.gitignore @@ -158,6 +158,19 @@ tools/unit-tests/unit-string tools/unit-tests/unit-update-flash tools/unit-tests/unit-update-flash-enc tools/unit-tests/unit-update-ram +tools/unit-tests/unit-boot-x86-fsp +tools/unit-tests/unit-image-rsa +tools/unit-tests/unit-multiboot +tools/unit-tests/unit-psa_store +tools/unit-tests/unit-qspi-flash +tools/unit-tests/unit-tpm-rsa-exp +tools/unit-tests/unit-image-nopart +tools/unit-tests/unit-image-sha3-384 +tools/unit-tests/unit-image-sha384 +tools/unit-tests/unit-store-sbrk +tools/unit-tests/unit-tpm-blob +tools/unit-tests/unit-update-disk + # Elf preprocessing tools diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e10af46d0..35771220f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -557,6 +557,11 @@ set(WOLFBOOT_SOURCES "include/loader.h" "src/image.c" "src/loader.c") +if((DEFINED WOLFCRYPT_TZ_PKCS11 AND NOT WOLFCRYPT_TZ_PKCS11 STREQUAL "0") OR + (DEFINED WOLFCRYPT_TZ_PSA AND NOT WOLFCRYPT_TZ_PSA STREQUAL "0")) + list(APPEND WOLFBOOT_SOURCES "src/store_sbrk.c") +endif() + if(DEFINED WOLFCRYPT_TZ_PSA AND NOT WOLFCRYPT_TZ_PSA STREQUAL "0") list(APPEND WOLFBOOT_SOURCES "src/dice/dice.c") endif() diff --git a/hal/stm32h5.c b/hal/stm32h5.c index 9345895c7b..3f0d1651d1 100644 --- a/hal/stm32h5.c +++ b/hal/stm32h5.c @@ -323,7 +323,7 @@ void RAMFUNCTION hal_flash_opt_unlock(void) DMB(); FLASH_OPTKEYR = FLASH_OPTKEY2; DMB(); - while ((FLASH_CR & FLASH_CR_LOCK) != 0) + while ((FLASH_OPTCR & FLASH_OPTCR_OPTLOCK) != 0) ; } diff --git a/hal/stm32l5.c b/hal/stm32l5.c index ef01d34eae..6bfb02a1ef 100644 --- a/hal/stm32l5.c +++ b/hal/stm32l5.c @@ -228,7 +228,7 @@ void RAMFUNCTION hal_flash_opt_unlock(void) DMB(); FLASH_OPTKEYR = FLASH_OPTKEY2; DMB(); - while ((FLASH_CR & FLASH_CR_LOCK) != 0) + while ((FLASH_CR & FLASH_CR_OPTLOCK) != 0) ; } diff --git a/hal/stm32u5.c b/hal/stm32u5.c index fbcb990472..62940bbd42 100644 --- a/hal/stm32u5.c +++ b/hal/stm32u5.c @@ -158,7 +158,7 @@ void RAMFUNCTION hal_flash_opt_unlock(void) DMB(); FLASH_NS_OPTKEYR = FLASH_OPTKEY2; DMB(); - while ((FLASH_NS_CR & FLASH_CR_LOCK) != 0) + while ((FLASH_NS_CR & FLASH_CR_OPTLOCK) != 0) ; } } diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 2ce75c8e34..af6c7af9c5 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -219,7 +219,7 @@ target_link_libraries(wolfcrypt target user_settings) target_compile_definitions( wolfcrypt PUBLIC WOLFSSL_USER_SETTINGS - PRIVATE ${WOLFCRYPT_DEFS} ${SIGN_OPTIONS}) + PRIVATE ${WOLFCRYPT_DEFS} ${SIGN_OPTIONS} ${WOLFBOOT_DEFS}) if(WOLFBOOT_SMALL_STACK) target_compile_definitions(wolfcrypt PRIVATE WOLFBOOT_SMALL_STACK XMALLOC_USER) diff --git a/options.mk b/options.mk index be66a7dd2e..8e7d914fd7 100644 --- a/options.mk +++ b/options.mk @@ -793,6 +793,7 @@ ifeq ($(WOLFCRYPT_TZ_PKCS11),1) CFLAGS+=-I$(WOLFBOOT_LIB_WOLFPKCS11) CFLAGS+=-DWP11_HASH_PIN_COST=3 LDFLAGS+=--specs=nano.specs + WOLFCRYPT_OBJS+=src/store_sbrk.o WOLFCRYPT_OBJS+=src/pkcs11_store.o WOLFCRYPT_OBJS+=src/pkcs11_callable.o WOLFCRYPT_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/pwdbased.o @@ -839,6 +840,7 @@ ifeq ($(WOLFCRYPT_TZ_PSA),1) WOLFPSA_CFLAGS+=-I$(WOLFBOOT_LIB_WOLFPSA) WOLFPSA_CFLAGS+=-I$(WOLFBOOT_LIB_WOLFPSA)/wolfpsa LDFLAGS+=--specs=nano.specs + WOLFCRYPT_OBJS+=src/store_sbrk.o WOLFCRYPT_OBJS+=src/psa_store.o WOLFCRYPT_OBJS+=src/arm_tee_psa_veneer.o WOLFCRYPT_OBJS+=src/arm_tee_psa_ipc.o diff --git a/src/delta.c b/src/delta.c index 5f250291f4..c1f2e3be12 100644 --- a/src/delta.c +++ b/src/delta.c @@ -397,6 +397,8 @@ int wb_diff(WB_DIFF_CTX *ctx, uint8_t *patch, uint32_t len) if (!found) { if (*(ctx->src_b + ctx->off_b) == ESC) { + if ((p_off + 1) >= (len - BLOCK_HDR_SIZE)) + break; *(patch + p_off++) = ESC; *(patch + p_off++) = ESC; } else { @@ -407,6 +409,8 @@ int wb_diff(WB_DIFF_CTX *ctx, uint8_t *patch, uint32_t len) } while ((p_off < len - BLOCK_HDR_SIZE) && ctx->off_b < ctx->size_b) { if (*(ctx->src_b + ctx->off_b) == ESC) { + if ((p_off + 1) >= (len - BLOCK_HDR_SIZE)) + break; *(patch + p_off++) = ESC; *(patch + p_off++) = ESC; } else { diff --git a/src/image.c b/src/image.c index d0f388740f..6d87db1616 100644 --- a/src/image.c +++ b/src/image.c @@ -1989,7 +1989,7 @@ int wolfBoot_check_flash_image_elf(uint8_t part, unsigned long* entry_out) /* Finalize SHA calculation */ final_hash(&ctx, calc_digest); - if (memcmp(calc_digest, exp_digest, WOLFBOOT_SHA_DIGEST_SIZE) != 0) { + if (!image_CT_compare(exp_digest, calc_digest, WOLFBOOT_SHA_DIGEST_SIZE)) { wolfBoot_printf("ELF: [CHECK] SHA verification FAILED\n"); wolfBoot_printf( "ELF: [CHECK] Expected %02x%02x%02x%02x%02x%02x%02x%02x\n", diff --git a/src/pkcs11_store.c b/src/pkcs11_store.c index 59e9e30f8f..2f35d4649d 100644 --- a/src/pkcs11_store.c +++ b/src/pkcs11_store.c @@ -24,6 +24,7 @@ #include #include "hal.h" +#include "store_sbrk.h" #ifdef SECURE_PKCS11 @@ -72,17 +73,7 @@ void * _sbrk(unsigned int incr) { static uint8_t *heap = NULL; static uint32_t heapsize = (uint32_t)&_heap_size; - void *old_heap = heap; - (void)heapsize; - if (((incr >> 2) << 2) != incr) - incr = ((incr >> 2) + 1) << 2; - - if (heap == NULL) { - heap = (uint8_t*)&_start_heap; - old_heap = heap; - } else - heap += incr; - return old_heap; + return wolfboot_store_sbrk(incr, &heap, (uint8_t *)&_start_heap, heapsize); } #endif @@ -227,7 +218,7 @@ static void check_vault(void) static void delete_object(int32_t type, uint32_t tok_id, uint32_t obj_id) { - struct obj_hdr *hdr = (struct obj_hdr *)cached_sector; + struct obj_hdr *hdr = (struct obj_hdr *)(cached_sector + STORE_PRIV_HDR_OFFSET); check_vault(); memcpy(cached_sector, vault_base, WOLFBOOT_SECTOR_SIZE); diff --git a/src/psa_store.c b/src/psa_store.c index 3876f5ec25..a2ed5a701b 100644 --- a/src/psa_store.c +++ b/src/psa_store.c @@ -24,6 +24,7 @@ #include #include "hal.h" +#include "store_sbrk.h" #ifdef WOLFCRYPT_TZ_PSA @@ -71,17 +72,7 @@ void * _sbrk(unsigned int incr) { static uint8_t *heap = NULL; static uint32_t heapsize = (uint32_t)&_heap_size; - void *old_heap = heap; - (void)heapsize; - if (((incr >> 2) << 2) != incr) - incr = ((incr >> 2) + 1) << 2; - - if (heap == NULL) { - heap = (uint8_t*)&_start_heap; - old_heap = heap; - } else - heap += incr; - return old_heap; + return wolfboot_store_sbrk(incr, &heap, (uint8_t *)&_start_heap, heapsize); } #endif @@ -226,7 +217,7 @@ static void check_vault(void) static void delete_object(int32_t type, uint32_t tok_id, uint32_t obj_id) { - struct obj_hdr *hdr = (struct obj_hdr *)cached_sector; + struct obj_hdr *hdr = (struct obj_hdr *)(cached_sector + STORE_PRIV_HDR_OFFSET); check_vault(); memcpy(cached_sector, vault_base, WOLFBOOT_SECTOR_SIZE); diff --git a/src/store_sbrk.c b/src/store_sbrk.c new file mode 100644 index 0000000000..2c274d56e7 --- /dev/null +++ b/src/store_sbrk.c @@ -0,0 +1,50 @@ +/* store_sbrk.c + * + * Copyright (C) 2025 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 + */ + +#include +#include + +#include "store_sbrk.h" + +void *wolfboot_store_sbrk(unsigned int incr, uint8_t **heap, + uint8_t *heap_base, uint32_t heap_size) +{ + uint8_t *heap_limit = heap_base + heap_size; + void *old_heap = *heap; + + if ((incr & 3U) != 0U) { + if (incr > (UINT_MAX - 3U)) + return (void *)-1; + incr = (incr + 3U) & ~3U; + } + + if (*heap == NULL) { + *heap = heap_base; + old_heap = *heap; + } + + if ((uint32_t)(heap_limit - *heap) < incr) + return (void *)-1; + + *heap += incr; + + return old_heap; +} diff --git a/src/store_sbrk.h b/src/store_sbrk.h new file mode 100644 index 0000000000..444bedf937 --- /dev/null +++ b/src/store_sbrk.h @@ -0,0 +1,30 @@ +/* store_sbrk.h + * + * Copyright (C) 2025 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 + */ + +#ifndef WOLFBOOT_STORE_SBRK_H +#define WOLFBOOT_STORE_SBRK_H + +#include + +void *wolfboot_store_sbrk(unsigned int incr, uint8_t **heap, + uint8_t *heap_base, uint32_t heap_size); + +#endif diff --git a/src/tpm.c b/src/tpm.c index 6a6edc72b5..86cb70043d 100644 --- a/src/tpm.c +++ b/src/tpm.c @@ -891,15 +891,19 @@ int wolfBoot_seal_auth(const uint8_t* pubkey_hint, WOLFTPM2_KEYBLOB seal_blob; word32 nvAttributes; + if (authSz < 0) + return BAD_FUNC_ARG; if (auth == NULL && authSz > 0) return BAD_FUNC_ARG; + if (authSz > (int)sizeof(seal_blob.handle.auth.buffer)) + return BAD_FUNC_ARG; memset(&seal_blob, 0, sizeof(seal_blob)); seal_blob.handle.auth.size = authSz; if (auth != NULL) - XMEMCPY(seal_blob.handle.auth.buffer, auth, authSz); + memcpy(seal_blob.handle.auth.buffer, auth, authSz); /* creates a sealed keyed hash object (not loaded to TPM) */ rc = wolfBoot_seal_blob(pubkey_hint, policy, policySz, &seal_blob, @@ -1085,7 +1089,11 @@ int wolfBoot_unseal_blob(const uint8_t* pubkey_hint, #endif /* if using password auth, set it otherwise use policy auth */ + if (authSz < 0) + return BAD_FUNC_ARG; if (auth != NULL && authSz > 0) { + if (authSz > (int)sizeof(seal_blob->handle.auth.buffer)) + return BAD_FUNC_ARG; seal_blob->handle.auth.size = authSz; memcpy(seal_blob->handle.auth.buffer, auth, authSz); wolfTPM2_SetAuthHandle(&wolftpm_dev, 0, &seal_blob->handle); diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index 310c0f9103..8a889a8393 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -48,7 +48,7 @@ TESTS:=unit-parser unit-extflash unit-string unit-spi-flash unit-aes128 \ unit-enc-nvm-flagshome unit-delta unit-update-flash \ unit-update-flash-enc unit-update-ram unit-pkcs11_store unit-psa_store unit-disk \ unit-update-disk unit-multiboot unit-boot-x86-fsp unit-qspi-flash unit-tpm-rsa-exp \ - unit-image-nopart unit-image-sha384 unit-image-sha3-384 \ + unit-image-nopart unit-image-sha384 unit-image-sha3-384 unit-store-sbrk \ unit-tpm-blob all: $(TESTS) @@ -132,6 +132,9 @@ unit-tpm-blob: ../../include/target.h unit-tpm-blob.c -DWOLFBOOT_HASH_SHA256 \ -ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections +unit-store-sbrk: unit-store-sbrk.c ../../src/store_sbrk.c + gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) + unit-string: ../../include/target.h unit-string.c gcc -o $@ $^ $(CFLAGS) -DDEBUG_UART -DPRINTF_ENABLED $(LDFLAGS) diff --git a/tools/unit-tests/unit-delta.c b/tools/unit-tests/unit-delta.c index 17858e39bc..d648e39841 100644 --- a/tools/unit-tests/unit-delta.c +++ b/tools/unit-tests/unit-delta.c @@ -197,6 +197,47 @@ START_TEST(test_wb_diff_self_match_extends_to_src_b_end) } END_TEST +START_TEST(test_wb_diff_preserves_trailing_header_margin_for_escape) +{ + WB_DIFF_CTX diff_ctx; + uint8_t src_a[64] = {0}; + uint8_t src_b[64] = {0}; + uint8_t patch[BLOCK_HDR_SIZE + 2] = {0}; + int ret; + + src_b[0] = ESC; + + ret = wb_diff_init(&diff_ctx, src_a, sizeof(src_a), src_b, 1); + ck_assert_int_eq(ret, 0); + + ret = wb_diff(&diff_ctx, patch, BLOCK_HDR_SIZE + 1); + + ck_assert_int_eq(ret, 0); + ck_assert_uint_eq(patch[0], 0); +} +END_TEST + +START_TEST(test_wb_diff_preserves_main_loop_header_margin_for_escape) +{ + WB_DIFF_CTX diff_ctx; + uint8_t src_a[64] = {0}; + uint8_t src_b[64] = {0}; + uint8_t patch[BLOCK_HDR_SIZE + 2] = {0}; + int ret; + + memset(src_b, 0x5a, BLOCK_HDR_SIZE + 1); + src_b[0] = ESC; + + ret = wb_diff_init(&diff_ctx, src_a, sizeof(src_a), src_b, BLOCK_HDR_SIZE + 1); + ck_assert_int_eq(ret, 0); + + ret = wb_diff(&diff_ctx, patch, BLOCK_HDR_SIZE + 1); + + ck_assert_int_eq(ret, 0); + ck_assert_uint_eq(patch[0], 0); +} +END_TEST + static void initialize_buffers(uint8_t *src_a, uint8_t *src_b, size_t size) { uint32_t pseudo_rand = 0; @@ -305,6 +346,8 @@ Suite *patch_diff_suite(void) tcase_add_test(tc_wolfboot_delta, test_wb_patch_trailing_escape_invalid); tcase_add_test(tc_wolfboot_delta, test_wb_diff_match_extends_to_src_b_end); tcase_add_test(tc_wolfboot_delta, test_wb_diff_self_match_extends_to_src_b_end); + tcase_add_test(tc_wolfboot_delta, test_wb_diff_preserves_trailing_header_margin_for_escape); + tcase_add_test(tc_wolfboot_delta, test_wb_diff_preserves_main_loop_header_margin_for_escape); tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff); suite_add_tcase(s, tc_wolfboot_delta); diff --git a/tools/unit-tests/unit-pkcs11_store.c b/tools/unit-tests/unit-pkcs11_store.c index 9b459ad29d..2cf501d7fd 100644 --- a/tools/unit-tests/unit-pkcs11_store.c +++ b/tools/unit-tests/unit-pkcs11_store.c @@ -318,6 +318,37 @@ START_TEST(test_cross_sector_write_preserves_length) } END_TEST +START_TEST(test_delete_object_ignores_metadata_prefix) +{ + const int32_t type = DYNAMIC_TYPE_RSA; + const uint32_t tok_id = VAULT_HEADER_MAGIC; + const uint32_t obj_id = 0x01020308U; + uint32_t *words; + uint8_t bitmap_before[BITMAP_SIZE]; + int ret; + + ret = mmap_file("/tmp/wolfboot-unit-keyvault.bin", vault_base, + keyvault_size, NULL); + ck_assert_int_eq(ret, 0); + memset(vault_base, 0xFF, keyvault_size); + + words = (uint32_t *)vault_base; + words[0] = VAULT_HEADER_MAGIC; + words[1] = obj_id; + words[2] = (uint32_t)type; + words[3] = 0; + words[4] = 0; + + memcpy(bitmap_before, vault_base + sizeof(uint32_t), BITMAP_SIZE); + + delete_object(type, tok_id, obj_id); + + ck_assert_mem_eq(vault_base + sizeof(uint32_t), bitmap_before, BITMAP_SIZE); + ck_assert_uint_eq(((uint32_t *)vault_base)[0], VAULT_HEADER_MAGIC); + ck_assert_uint_eq(((uint32_t *)vault_base)[1], obj_id); +} +END_TEST + Suite *wolfboot_suite(void) { /* Suite initialization */ @@ -325,10 +356,13 @@ Suite *wolfboot_suite(void) TCase* tcase_store_and_load_objs = tcase_create("store_and_load_objs"); TCase* tcase_cross_sector_write = tcase_create("cross_sector_write"); + TCase* tcase_delete_object = tcase_create("delete_object"); 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); + tcase_add_test(tcase_delete_object, test_delete_object_ignores_metadata_prefix); suite_add_tcase(s, tcase_store_and_load_objs); suite_add_tcase(s, tcase_cross_sector_write); + suite_add_tcase(s, tcase_delete_object); return s; } diff --git a/tools/unit-tests/unit-psa_store.c b/tools/unit-tests/unit-psa_store.c index 4dafafba0b..91f8f9ebb3 100644 --- a/tools/unit-tests/unit-psa_store.c +++ b/tools/unit-tests/unit-psa_store.c @@ -90,13 +90,47 @@ START_TEST(test_cross_sector_write_preserves_length) } END_TEST +START_TEST(test_delete_object_ignores_metadata_prefix) +{ + enum { type = WOLFPSA_STORE_KEY }; + const uint32_t tok_id = VAULT_HEADER_MAGIC; + const uint32_t obj_id = 0x01020308U; + uint32_t *words; + uint8_t bitmap_before[BITMAP_SIZE]; + int ret; + + ret = mmap_file("/tmp/wolfboot-unit-psa-keyvault.bin", vault_base, + keyvault_size, NULL); + ck_assert_int_eq(ret, 0); + memset(vault_base, 0xFF, keyvault_size); + + words = (uint32_t *)vault_base; + words[0] = VAULT_HEADER_MAGIC; + words[1] = obj_id; + words[2] = (uint32_t)type; + words[3] = 0; + words[4] = 0; + + memcpy(bitmap_before, vault_base + sizeof(uint32_t), BITMAP_SIZE); + + delete_object(type, tok_id, obj_id); + + ck_assert_mem_eq(vault_base + sizeof(uint32_t), bitmap_before, BITMAP_SIZE); + ck_assert_uint_eq(((uint32_t *)vault_base)[0], VAULT_HEADER_MAGIC); + ck_assert_uint_eq(((uint32_t *)vault_base)[1], obj_id); +} +END_TEST + Suite *wolfboot_suite(void) { Suite *s = suite_create("wolfBoot-psa-store"); TCase *tcase_write = tcase_create("cross_sector_write"); + TCase *tcase_delete = tcase_create("delete_object"); tcase_add_test(tcase_write, test_cross_sector_write_preserves_length); + tcase_add_test(tcase_delete, test_delete_object_ignores_metadata_prefix); suite_add_tcase(s, tcase_write); + suite_add_tcase(s, tcase_delete); return s; } diff --git a/tools/unit-tests/unit-store-sbrk.c b/tools/unit-tests/unit-store-sbrk.c new file mode 100644 index 0000000000..4cddbdd595 --- /dev/null +++ b/tools/unit-tests/unit-store-sbrk.c @@ -0,0 +1,93 @@ +/* unit-store-sbrk.c + * + * Unit tests for store allocator helper. + * + * Copyright (C) 2025 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 + */ + +#include +#include +#include + +#include "../../src/store_sbrk.h" + +START_TEST(test_sbrk_first_call_advances_heap) +{ + uint8_t heap_buf[32]; + uint8_t *heap = NULL; + void *ret; + + ret = wolfboot_store_sbrk(5, &heap, heap_buf, sizeof(heap_buf)); + + ck_assert_ptr_eq(ret, heap_buf); + ck_assert_ptr_eq(heap, heap_buf + 8); +} +END_TEST + +START_TEST(test_sbrk_rejects_overflow) +{ + uint8_t heap_buf[16]; + uint8_t *heap = NULL; + void *ret; + + ret = wolfboot_store_sbrk(8, &heap, heap_buf, sizeof(heap_buf)); + ck_assert_ptr_eq(ret, heap_buf); + + ret = wolfboot_store_sbrk(16, &heap, heap_buf, sizeof(heap_buf)); + ck_assert_ptr_eq(ret, (void *)-1); + ck_assert_ptr_eq(heap, heap_buf + 8); +} +END_TEST + +START_TEST(test_sbrk_rejects_alignment_overflow) +{ + uint8_t heap_buf[16]; + uint8_t *heap = NULL; + void *ret; + + ret = wolfboot_store_sbrk(UINT_MAX - 1U, &heap, heap_buf, sizeof(heap_buf)); + + ck_assert_ptr_eq(ret, (void *)-1); + ck_assert_ptr_eq(heap, NULL); +} +END_TEST + +Suite *wolfboot_suite(void) +{ + Suite *s = suite_create("store-sbrk"); + TCase *tcase = tcase_create("store_sbrk"); + + tcase_add_test(tcase, test_sbrk_first_call_advances_heap); + tcase_add_test(tcase, test_sbrk_rejects_overflow); + tcase_add_test(tcase, test_sbrk_rejects_alignment_overflow); + suite_add_tcase(s, tcase); + 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; +} diff --git a/tools/unit-tests/unit-tpm-blob.c b/tools/unit-tests/unit-tpm-blob.c index 7ba3e0bf61..0a543ff950 100644 --- a/tools/unit-tests/unit-tpm-blob.c +++ b/tools/unit-tests/unit-tpm-blob.c @@ -228,6 +228,73 @@ int wolfTPM2_PolicyRefMake(TPM_ALG_ID pcrAlg, byte* digest, word32* digestSz, return 0; } +int TPM2_GetHashDigestSize(TPMI_ALG_HASH hashAlg) +{ + switch (hashAlg) { + case TPM_ALG_SHA1: + return 20; + case TPM_ALG_SHA256: + return 32; + case TPM_ALG_SHA384: + return 48; + case TPM_ALG_SHA512: + return 64; + case TPM_ALG_SM3_256: + return 32; + default: + return 0; + } +} + +int wolfTPM2_GetKeyTemplate_KeySeal(TPMT_PUBLIC* publicTemplate, + TPM_ALG_ID nameAlg) +{ + memset(publicTemplate, 0, sizeof(*publicTemplate)); + publicTemplate->nameAlg = nameAlg; + return 0; +} + +int wolfTPM2_PolicyAuthorizeMake(TPM_ALG_ID hashAlg, const TPM2B_PUBLIC* pub, + byte* digest, word32* digestSz, const byte* policyRef, + word32 policyRefSz) +{ + (void)hashAlg; + (void)pub; + (void)policyRef; + (void)policyRefSz; + memset(digest, 0x11, *digestSz); + return 0; +} + +int wolfTPM2_CreateKeySeal_ex(WOLFTPM2_DEV* dev, WOLFTPM2_KEYBLOB* keyBlob, + WOLFTPM2_HANDLE* parent, TPMT_PUBLIC* publicTemplate, const byte* auth, + int authSz, TPM_ALG_ID alg, byte* pcrSel, + word32 pcrSelSz, const byte* sealData, int sealSize) +{ + (void)dev; + (void)keyBlob; + (void)parent; + (void)publicTemplate; + (void)auth; + (void)authSz; + (void)alg; + (void)pcrSel; + (void)pcrSelSz; + (void)sealData; + (void)sealSize; + unexpected_nvcreate_calls++; + ck_abort_msg("Unexpected wolfTPM2_CreateKeySeal_ex call"); + return -1; +} + +int wolfTPM2_GetNvAttributesTemplate(TPM_HANDLE authHandle, + word32* attr) +{ + (void)authHandle; + *attr = 0; + return 0; +} + TPM_RC TPM2_Unseal(Unseal_In* in, Unseal_Out* out) { (void)in; @@ -492,6 +559,46 @@ START_TEST(test_wolfBoot_delete_blob_rejects_oversized_auth) } END_TEST +START_TEST(test_wolfBoot_seal_auth_rejects_oversized_auth) +{ + uint8_t auth[sizeof(((WOLFTPM2_KEYBLOB*)0)->handle.auth.buffer) + 1]; + uint8_t pubkey_hint[WOLFBOOT_SHA_DIGEST_SIZE] = {0}; + uint8_t policy[sizeof(uint32_t) + 4] = {0}; + uint8_t secret[8] = {0}; + int rc; + + memset(auth, 0x77, sizeof(auth)); + + rc = wolfBoot_seal_auth(pubkey_hint, policy, sizeof(policy), 0, + secret, sizeof(secret), auth, (int)sizeof(auth)); + + ck_assert_int_eq(rc, BAD_FUNC_ARG); + ck_assert_int_eq(unexpected_nvcreate_calls, 0); + ck_assert_int_eq(unexpected_nvwrite_calls, 0); + ck_assert_int_eq(unexpected_nvopen_calls, 0); + ck_assert_int_eq(unexpected_nvdelete_calls, 0); +} +END_TEST + +START_TEST(test_wolfBoot_seal_auth_rejects_negative_auth_size) +{ + uint8_t auth[8] = {0}; + uint8_t pubkey_hint[WOLFBOOT_SHA_DIGEST_SIZE] = {0}; + uint8_t policy[sizeof(uint32_t) + 4] = {0}; + uint8_t secret[8] = {0}; + int rc; + + rc = wolfBoot_seal_auth(pubkey_hint, policy, sizeof(policy), 0, + secret, sizeof(secret), auth, -1); + + ck_assert_int_eq(rc, BAD_FUNC_ARG); + ck_assert_int_eq(unexpected_nvcreate_calls, 0); + ck_assert_int_eq(unexpected_nvwrite_calls, 0); + ck_assert_int_eq(unexpected_nvopen_calls, 0); + ck_assert_int_eq(unexpected_nvdelete_calls, 0); +} +END_TEST + START_TEST(test_wolfBoot_unseal_blob_zeroes_unseal_output) { uint8_t secret[WOLFBOOT_MAX_SEAL_SZ]; @@ -516,6 +623,51 @@ START_TEST(test_wolfBoot_unseal_blob_zeroes_unseal_output) } END_TEST +START_TEST(test_wolfBoot_unseal_blob_rejects_oversized_auth) +{ + WOLFTPM2_KEYBLOB blob; + uint8_t auth[sizeof(((WOLFTPM2_KEYBLOB*)0)->handle.auth.buffer) + 1]; + uint8_t secret[WOLFBOOT_MAX_SEAL_SZ]; + uint8_t pubkey_hint[WOLFBOOT_SHA_DIGEST_SIZE] = {0}; + uint8_t policy[sizeof(uint32_t) + 4] = {0}; + int secret_sz; + int rc; + + memset(&blob, 0, sizeof(blob)); + memset(auth, 0x88, sizeof(auth)); + memset(secret, 0, sizeof(secret)); + secret_sz = (int)sizeof(secret); + current_mode = MOCK_OVERSIZE_PUB; + + rc = wolfBoot_unseal_blob(pubkey_hint, policy, sizeof(policy), &blob, + secret, &secret_sz, auth, (int)sizeof(auth)); + + ck_assert_int_eq(rc, BAD_FUNC_ARG); +} +END_TEST + +START_TEST(test_wolfBoot_unseal_blob_rejects_negative_auth_size) +{ + WOLFTPM2_KEYBLOB blob; + uint8_t auth[8] = {0}; + uint8_t secret[WOLFBOOT_MAX_SEAL_SZ]; + uint8_t pubkey_hint[WOLFBOOT_SHA_DIGEST_SIZE] = {0}; + uint8_t policy[sizeof(uint32_t) + 4] = {0}; + int secret_sz; + int rc; + + memset(&blob, 0, sizeof(blob)); + memset(secret, 0, sizeof(secret)); + secret_sz = (int)sizeof(secret); + current_mode = MOCK_OVERSIZE_PUB; + + rc = wolfBoot_unseal_blob(pubkey_hint, policy, sizeof(policy), &blob, + secret, &secret_sz, auth, -1); + + ck_assert_int_eq(rc, BAD_FUNC_ARG); +} +END_TEST + START_TEST(test_wolfBoot_unseal_blob_rejects_output_larger_than_capacity) { struct { @@ -575,9 +727,13 @@ static Suite *tpm_blob_suite(void) tcase_add_test(tc, test_wolfBoot_store_blob_rejects_oversized_auth); tcase_add_test(tc, test_wolfBoot_read_blob_rejects_oversized_auth); tcase_add_test(tc, test_wolfBoot_delete_blob_rejects_oversized_auth); + tcase_add_test(tc, test_wolfBoot_seal_auth_rejects_oversized_auth); + tcase_add_test(tc, test_wolfBoot_seal_auth_rejects_negative_auth_size); tcase_add_test(tc, test_wolfBoot_read_blob_rejects_oversized_public_area); tcase_add_test(tc, test_wolfBoot_read_blob_rejects_oversized_private_area); tcase_add_test(tc, test_wolfBoot_unseal_blob_zeroes_unseal_output); + tcase_add_test(tc, test_wolfBoot_unseal_blob_rejects_oversized_auth); + tcase_add_test(tc, test_wolfBoot_unseal_blob_rejects_negative_auth_size); tcase_add_test(tc, test_wolfBoot_unseal_blob_rejects_output_larger_than_capacity); suite_add_tcase(s, tc); return s;