diff --git a/.gitignore b/.gitignore index ecdf1caff5..321868d275 100644 --- a/.gitignore +++ b/.gitignore @@ -140,6 +140,7 @@ tools/unit-tests/unit-aes128 tools/unit-tests/unit-aes256 tools/unit-tests/unit-chacha20 tools/unit-tests/unit-delta +tools/unit-tests/unit-disk tools/unit-tests/unit-enc-nvm tools/unit-tests/unit-enc-nvm-flagshome tools/unit-tests/unit-extflash @@ -153,7 +154,9 @@ tools/unit-tests/unit-pci tools/unit-tests/unit-pkcs11_store tools/unit-tests/unit-sectorflags tools/unit-tests/unit-spi-flash +tools/unit-tests/unit-string tools/unit-tests/unit-update-flash +tools/unit-tests/unit-update-flash-enc tools/unit-tests/unit-update-ram diff --git a/lib/wolfssl b/lib/wolfssl index a08efc9b0a..8741805e9d 160000 --- a/lib/wolfssl +++ b/lib/wolfssl @@ -1 +1 @@ -Subproject commit a08efc9b0afe99d6a448804746eb16febb67cbba +Subproject commit 8741805e9d1fd9c3014b5b774ad09a77ccb5b0dc diff --git a/src/libwolfboot.c b/src/libwolfboot.c index b5dc650a72..1ef9456b31 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -861,51 +861,74 @@ void RAMFUNCTION wolfBoot_success(void) */ uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr) { - uint8_t *p = haystack; + uint8_t *p; uint16_t len, htype; - const volatile uint8_t *max_p = (haystack - IMAGE_HEADER_OFFSET) + - IMAGE_HEADER_SIZE; + uintptr_t p_addr, max_addr; + *ptr = NULL; - if (p > max_p) { + + if (haystack == NULL) { + unit_dbg("Illegal address (NULL)\n"); + return 0; + } + + p_addr = (uintptr_t)haystack; + if (p_addr < IMAGE_HEADER_OFFSET) { + unit_dbg("Illegal address (too low)\n"); + return 0; + } + + max_addr = p_addr - IMAGE_HEADER_OFFSET; + if (max_addr > (UINTPTR_MAX - IMAGE_HEADER_SIZE)) { + unit_dbg("Illegal address (overflow)\n"); + return 0; + } + max_addr += IMAGE_HEADER_SIZE; + + if (p_addr > max_addr) { unit_dbg("Illegal address (too high)\n"); return 0; } - while ((p + 4) < max_p) { + + while (p_addr < max_addr) { + if ((max_addr - p_addr) < 4U) { + break; + } + p = (uint8_t *)p_addr; htype = p[0] | (p[1] << 8); if (htype == 0) { unit_dbg("Explicit end of options reached\n"); break; } /* skip unaligned half-words and padding bytes */ - if ((p[0] == HDR_PADDING) || ((((size_t)p) & 0x01) != 0)) { - p++; + if ((p[0] == HDR_PADDING) || ((p_addr & 0x01U) != 0U)) { + p_addr++; continue; } len = p[2] | (p[3] << 8); /* check len */ - if ((4 + len) > (uint16_t)(IMAGE_HEADER_SIZE - IMAGE_HEADER_OFFSET)) { + if ((4U + len) > (uint16_t)(IMAGE_HEADER_SIZE - IMAGE_HEADER_OFFSET)) { unit_dbg("This field is too large (bigger than the space available " "in the current header)\n"); - unit_dbg("%d %d %d\n", len, IMAGE_HEADER_SIZE, IMAGE_HEADER_OFFSET); + unit_dbg("%u %u %u\n", (unsigned int)len, + (unsigned int)IMAGE_HEADER_SIZE, + (unsigned int)IMAGE_HEADER_OFFSET); break; } /* check max pointer */ - if (p + 4 + len > max_p) { + if ((max_addr - p_addr) < (uintptr_t)(4U + len)) { unit_dbg("This field is too large and would overflow the image " "header\n"); break; } - /* skip header [type|len] */ - p += 4; - if (htype == type) { /* found, return pointer to data portion */ - *ptr = p; + *ptr = (uint8_t *)(p_addr + 4U); return len; } - p += len; + p_addr += (uintptr_t)(4U + len); } return 0; } diff --git a/src/string.c b/src/string.c index 7245ead8cd..778940edd8 100644 --- a/src/string.c +++ b/src/string.c @@ -105,54 +105,41 @@ char *strcat(char *dest, const char *src) int strcmp(const char *s1, const char *s2) { - int diff = 0; - - while (!diff && *s1) { - diff = (int)*s1 - (int)*s2; - s1++; - s2++; + while (*s1 && *s2) { + int c1 = ((unsigned char)*s1++); + int c2 = ((unsigned char)*s2++); + if (c1 != c2) + return c1 - c2; } - - return diff; + return ((unsigned char)*s1) - ((unsigned char)*s2); } #endif /* Renesas CCRX */ int strcasecmp(const char *s1, const char *s2) { - int diff = 0; - - while (!diff && *s1) { - diff = (int)*s1 - (int)*s2; - - if (((diff == 'A' - 'a') || (diff == 'a' - 'A')) && - (isalpha((unsigned char)*s1) && isalpha((unsigned char)*s2))) - diff = 0; - - s1++; - s2++; + while (*s1 && *s2) { + int c1 = tolower((unsigned char)*s1++); + int c2 = tolower((unsigned char)*s2++); + if (c1 != c2) + return c1 - c2; } - - return diff; + return tolower((unsigned char)*s1) - tolower((unsigned char)*s2); } int strncasecmp(const char *s1, const char *s2, size_t n) { - int diff = 0; - size_t i = 0; - - while (!diff && *s1) { - diff = (int)*s1 - (int)*s2; + if (n == 0) + return 0; - if (((diff == 'A' - 'a') || (diff == 'a' - 'A')) && - (isalpha((unsigned char)*s1) && isalpha((unsigned char)*s2))) - diff = 0; - - s1++; - s2++; - if (++i >= n) - break; + while (n--) { + int c1 = tolower((unsigned char)*s1++); + int c2 = tolower((unsigned char)*s2++); + if (c1 != c2) + return c1 - c2; + if (c1 == '\0') + return 0; } - return diff; + return 0; } #if !defined(__CCRX__) /* Renesas CCRX */ @@ -202,7 +189,7 @@ char *strcpy(char *dst, const char *src) { size_t i = 0; - while(1) { + while (1) { dst[i] = src[i]; if (src[i] == '\0') break; diff --git a/tools/test.mk b/tools/test.mk index c177bdfb53..2bace003cd 100644 --- a/tools/test.mk +++ b/tools/test.mk @@ -1110,11 +1110,11 @@ test-all: clean test-size-all: make test-size SIGN=NONE LIMIT=5040 NO_ARM_ASM=1 make keysclean - make test-size SIGN=ED25519 LIMIT=11700 NO_ARM_ASM=1 + make test-size SIGN=ED25519 LIMIT=11724 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=13840 NO_ARM_ASM=1 + make test-size SIGN=ECC256 NO_ASM=1 LIMIT=13856 NO_ARM_ASM=1 make keysclean make test-size SIGN=RSA2048 LIMIT=11916 NO_ARM_ASM=1 make clean @@ -1126,9 +1126,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=15216 NO_ARM_ASM=1 + make test-size SIGN=ECC384 NO_ASM=1 LIMIT=15232 NO_ARM_ASM=1 make keysclean - make test-size SIGN=ED448 LIMIT=13760 NO_ARM_ASM=1 + make test-size SIGN=ED448 LIMIT=13776 NO_ARM_ASM=1 make keysclean make test-size SIGN=RSA3072 LIMIT=12056 NO_ARM_ASM=1 make clean @@ -1136,11 +1136,11 @@ 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=7696 NO_ARM_ASM=1 + IMAGE_HEADER_SIZE?=5288 LIMIT=7712 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=8560 NO_ARM_ASM=1 + LIMIT=8568 NO_ARM_ASM=1 make keysclean make clean make test-size SIGN=ML_DSA ML_DSA_LEVEL=2 LIMIT=19362 \ diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index 1999993aef..dd755d1a38 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -22,6 +22,12 @@ CFLAGS+=-DUNIT_TEST -DWOLFSSL_USER_SETTINGS LDFLAGS+=-fprofile-arcs LDFLAGS+=-ftest-coverage +ASAN?=0 +ifeq ($(ASAN),1) + CFLAGS+=-fsanitize=address -fno-omit-frame-pointer -O1 + LDFLAGS+=-fsanitize=address +endif + @@ -73,6 +79,7 @@ unit-update-flash:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH unit-update-ram:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \ -DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT \ -DPART_SWAP_EXT -DPART_BOOT_EXT -DWOLFBOOT_DUALBOOT -DNO_XIP +unit-string:CFLAGS+=-fno-builtin WOLFCRYPT_CFLAGS+=-DWOLFBOOT_SIGN_ECC256 -DWOLFBOOT_SIGN_ECC256 -DHAVE_ECC_KEY_IMPORT -D__WOLFBOOT diff --git a/tools/unit-tests/unit-string.c b/tools/unit-tests/unit-string.c index f1479f6249..a10b40c902 100644 --- a/tools/unit-tests/unit-string.c +++ b/tools/unit-tests/unit-string.c @@ -92,6 +92,24 @@ START_TEST(test_case_insensitive_alpha_only) } END_TEST +START_TEST(test_strcasecmp_prefix_regression) +{ + ck_assert_int_lt(strcasecmp("a", "ab"), 0); + ck_assert_int_gt(strcasecmp("ab", "a"), 0); + ck_assert_int_lt(strcasecmp("", "a"), 0); + ck_assert_int_gt(strcasecmp("a", ""), 0); +} +END_TEST + +START_TEST(test_strncasecmp_n_limit_regression) +{ + ck_assert_int_eq(strncasecmp("ABC", "abc", 0), 0); + ck_assert_int_eq(strncasecmp("", "a", 0), 0); + ck_assert_int_eq(strncasecmp("AbCd", "aBcE", 3), 0); + ck_assert_int_lt(strncasecmp("AbCd", "aBcE", 4), 0); +} +END_TEST + START_TEST(test_isalpha_helpers) { ck_assert_int_eq(islower('a'), 1); @@ -145,6 +163,16 @@ START_TEST(test_strlen_strcmp) } END_TEST +START_TEST(test_strcmp_prefix_termination) +{ + ck_assert_int_lt(strcmp("a", "abc"), 0); + ck_assert_int_lt(strcmp("ab", "abc"), 0); + ck_assert_int_gt(strcmp("abc", "ab"), 0); + ck_assert_int_gt(strcmp("abc", "a"), 0); + ck_assert_int_eq(strcmp("", ""), 0); +} +END_TEST + START_TEST(test_strcpy_strncpy_strcat_strncat) { char buf[8]; @@ -329,9 +357,12 @@ Suite *string_suite(void) tcase_add_test(tcase_strncasecmp, test_strncasecmp_n_exact); tcase_add_test(tcase_strncasecmp, test_strncasecmp_diff_before_n); tcase_add_test(tcase_strncasecmp, test_case_insensitive_alpha_only); + tcase_add_test(tcase_strncasecmp, test_strcasecmp_prefix_regression); + tcase_add_test(tcase_strncasecmp, test_strncasecmp_n_limit_regression); tcase_add_test(tcase_misc, test_isalpha_helpers); tcase_add_test(tcase_misc, test_memset_memcmp_memchr); tcase_add_test(tcase_misc, test_strlen_strcmp); + tcase_add_test(tcase_misc, test_strcmp_prefix_termination); tcase_add_test(tcase_misc, test_strcpy_strncpy_strcat_strncat); tcase_add_test(tcase_misc, test_strncmp); tcase_add_test(tcase_misc, test_memcpy_memmove);