Skip to content

Commit 66badb2

Browse files
committed
Improved PSA & PKCS11 store write boundary checks
F/220
1 parent 4d2c7bb commit 66badb2

5 files changed

Lines changed: 167 additions & 7 deletions

File tree

src/pkcs11_store.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,8 +506,8 @@ int wolfPKCS11_Store_Write(void* store, unsigned char* buffer, int len)
506506
% WOLFBOOT_SECTOR_SIZE;
507507
sector_base = (uintptr_t)handle->buffer + handle->in_buffer_offset - in_sector_offset;
508508
in_sector_len = WOLFBOOT_SECTOR_SIZE - in_sector_offset;
509-
if (in_sector_len > (uint32_t)len)
510-
in_sector_len = len;
509+
if (in_sector_len > (uint32_t)(len - written))
510+
in_sector_len = len - written;
511511

512512
/* Cache the corresponding sector */
513513
memcpy(cached_sector, (void *)(uintptr_t)sector_base, WOLFBOOT_SECTOR_SIZE);

src/psa_store.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,8 +512,8 @@ int wolfPSA_Store_Write(void* store, unsigned char* buffer, int len)
512512
% WOLFBOOT_SECTOR_SIZE;
513513
sector_base = (uintptr_t)handle->buffer + handle->in_buffer_offset - in_sector_offset;
514514
in_sector_len = WOLFBOOT_SECTOR_SIZE - in_sector_offset;
515-
if (in_sector_len > (uint32_t)len)
516-
in_sector_len = len;
515+
if (in_sector_len > (uint32_t)(len - written))
516+
in_sector_len = len - written;
517517

518518
/* Cache the corresponding sector */
519519
memcpy(cached_sector, (void *)(uintptr_t)sector_base, WOLFBOOT_SECTOR_SIZE);

tools/unit-tests/Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ endif
88
# Default library paths (can be overridden)
99
WOLFBOOT_LIB_WOLFSSL?=../../lib/wolfssl
1010
WOLFBOOT_LIB_WOLFPKCS11?=../../lib/wolfPKCS11
11+
WOLFBOOT_LIB_WOLFPSA?=../../lib/wolfPSA
1112

1213
# Convert to absolute paths for standalone usage
1314
WOLFBOOT_LIB_WOLFSSL:=$(abspath $(WOLFBOOT_LIB_WOLFSSL))
1415
WOLFBOOT_LIB_WOLFPKCS11:=$(abspath $(WOLFBOOT_LIB_WOLFPKCS11))
16+
WOLFBOOT_LIB_WOLFPSA:=$(abspath $(WOLFBOOT_LIB_WOLFPSA))
1517

1618
CFLAGS=-I. -I../../src -I../../include -I$(WOLFBOOT_LIB_WOLFSSL)
1719
CFLAGS+=-g -ggdb
@@ -35,7 +37,7 @@ TESTS:=unit-parser unit-extflash unit-string unit-spi-flash unit-aes128 \
3537
unit-aes256 unit-chacha20 unit-pci unit-mock-state unit-sectorflags \
3638
unit-image unit-nvm unit-nvm-flagshome unit-enc-nvm \
3739
unit-enc-nvm-flagshome unit-delta unit-update-flash \
38-
unit-update-flash-enc unit-update-ram unit-pkcs11_store unit-disk \
40+
unit-update-flash-enc unit-update-ram unit-pkcs11_store unit-psa_store unit-disk \
3941
unit-multiboot
4042

4143
all: $(TESTS)
@@ -75,6 +77,7 @@ unit-enc-nvm-flagshome:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS \
7577
unit-enc-nvm-flagshome:WOLFCRYPT_SRC+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/chacha.c
7678
unit-delta:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS -DDELTA_UPDATES -DDELTA_BLOCK_SIZE=512
7779
unit-pkcs11_store:CFLAGS+=-I$(WOLFBOOT_LIB_WOLFPKCS11) -DMOCK_PARTITIONS -DMOCK_KEYVAULT -DSECURE_PKCS11
80+
unit-psa_store:CFLAGS+=-I$(WOLFBOOT_LIB_WOLFPSA) -DMOCK_PARTITIONS -DMOCK_KEYVAULT -DWOLFCRYPT_TZ_PSA
7881
unit-update-flash:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
7982
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT -DPART_SWAP_EXT
8083
unit-update-ram:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
@@ -161,6 +164,9 @@ unit-update-ram: ../../include/target.h unit-update-ram.c
161164
unit-pkcs11_store: ../../include/target.h unit-pkcs11_store.c
162165
gcc -o $@ $(WOLFCRYPT_SRC) unit-pkcs11_store.c $(CFLAGS) $(WOLFCRYPT_CFLAGS) $(LDFLAGS)
163166

167+
unit-psa_store: ../../include/target.h unit-psa_store.c
168+
gcc -o $@ $(WOLFCRYPT_SRC) unit-psa_store.c $(CFLAGS) $(WOLFCRYPT_CFLAGS) $(LDFLAGS)
169+
164170
gpt-sfdisk-test.h:
165171
truncate -s 131072 .gpt-tmp.img
166172
printf 'label: gpt\nfirst-lba: 34\nstart=34, size=67, name="boot"\nstart=101, size=100, name="rootfs"\n' \

tools/unit-tests/unit-pkcs11_store.c

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,8 @@ START_TEST (test_store_and_load_objs) {
242242
/* Read out the content */
243243
memset(secret_rd, 0, KEYVAULT_OBJ_SIZE);
244244
ret = wolfPKCS11_Store_Read(store, secret_rd, KEYVAULT_OBJ_SIZE);
245-
ck_assert(ret == KEYVAULT_OBJ_SIZE - 8);
246-
ck_assert(strncmp(dante_filler, secret_rd, KEYVAULT_OBJ_SIZE - 8) == 0);
245+
ck_assert_int_eq(ret, strlen(dante_filler) + 1);
246+
ck_assert(strncmp(dante_filler, secret_rd, strlen(dante_filler) + 1) == 0);
247247
wolfPKCS11_Store_Close(store);
248248

249249
/* Reopen for writing, test truncate */
@@ -280,14 +280,55 @@ START_TEST (test_store_and_load_objs) {
280280
}
281281
END_TEST
282282

283+
START_TEST(test_cross_sector_write_preserves_length)
284+
{
285+
const int type = DYNAMIC_TYPE_RSA;
286+
const CK_ULONG id_tok = 7;
287+
const CK_ULONG id_obj = 9;
288+
void *store = NULL;
289+
unsigned char *payload;
290+
struct store_handle *handle;
291+
int ret;
292+
293+
payload = malloc(WOLFBOOT_SECTOR_SIZE);
294+
ck_assert_ptr_nonnull(payload);
295+
296+
for (ret = 0; ret < WOLFBOOT_SECTOR_SIZE; ret++)
297+
payload[ret] = (unsigned char)(ret & 0xFF);
298+
299+
ret = mmap_file("/tmp/wolfboot-unit-keyvault.bin", vault_base,
300+
keyvault_size, NULL);
301+
ck_assert_int_eq(ret, 0);
302+
memset(vault_base, 0xEE, keyvault_size);
303+
304+
ret = wolfPKCS11_Store_Open(type, id_tok, id_obj, 0, &store);
305+
ck_assert_int_eq(ret, 0);
306+
ck_assert_ptr_nonnull(store);
307+
308+
ret = wolfPKCS11_Store_Write(store, payload, WOLFBOOT_SECTOR_SIZE);
309+
ck_assert_int_eq(ret, WOLFBOOT_SECTOR_SIZE);
310+
handle = store;
311+
ck_assert_uint_eq(handle->in_buffer_offset,
312+
2 * sizeof(uint32_t) + WOLFBOOT_SECTOR_SIZE);
313+
ck_assert_uint_eq(handle->hdr->size,
314+
2 * sizeof(uint32_t) + WOLFBOOT_SECTOR_SIZE);
315+
wolfPKCS11_Store_Close(store);
316+
317+
free(payload);
318+
}
319+
END_TEST
320+
283321
Suite *wolfboot_suite(void)
284322
{
285323
/* Suite initialization */
286324
Suite *s = suite_create("wolfBoot-pkcs11-store");
287325

288326
TCase* tcase_store_and_load_objs = tcase_create("store_and_load_objs");
327+
TCase* tcase_cross_sector_write = tcase_create("cross_sector_write");
289328
tcase_add_test(tcase_store_and_load_objs, test_store_and_load_objs);
329+
tcase_add_test(tcase_cross_sector_write, test_cross_sector_write_preserves_length);
290330
suite_add_tcase(s, tcase_store_and_load_objs);
331+
suite_add_tcase(s, tcase_cross_sector_write);
291332
return s;
292333
}
293334

tools/unit-tests/unit-psa_store.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* unit-psa_store.c
2+
*
3+
* Unit test for PSA storage module
4+
*
5+
* Copyright (C) 2026 wolfSSL Inc.
6+
*
7+
* This file is part of wolfBoot.
8+
*
9+
* wolfBoot is free software; you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License as published by
11+
* the Free Software Foundation; either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* wolfBoot is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program; if not, write to the Free Software
21+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
22+
*/
23+
24+
#define WOLFBOOT_HASH_SHA256
25+
#define EXT_FLASH
26+
#define PART_UPDATE_EXT
27+
#define NVM_FLASH_WRITEONCE
28+
29+
#define KEYSTORE_PUBKEY_SIZE KEYSTORE_PUBKEY_SIZE_ECC256
30+
31+
#include <check.h>
32+
#include <stdint.h>
33+
#include <stdlib.h>
34+
#include <string.h>
35+
#define XMALLOC_OVERRIDE
36+
#define XMALLOC(n,h,t) malloc(n)
37+
#define XFREE(p,h,t) free(p)
38+
39+
#include "user_settings.h"
40+
#include "wolfssl/wolfcrypt/sha.h"
41+
#include "wolfssl/wolfcrypt/error-crypt.h"
42+
#include "wolfboot/wolfboot.h"
43+
#include "wolfpsa/psa_store.h"
44+
#include "hal.h"
45+
#include <fcntl.h>
46+
#include <unistd.h>
47+
#include <sys/mman.h>
48+
49+
#define MOCK_ADDRESS 0xCF000000
50+
uint8_t *vault_base = (uint8_t *)MOCK_ADDRESS;
51+
#include "psa_store.c"
52+
const uint32_t keyvault_size = KEYVAULT_OBJ_SIZE * KEYVAULT_MAX_ITEMS + 2 * WOLFBOOT_SECTOR_SIZE;
53+
#include "unit-mock-flash.c"
54+
55+
START_TEST(test_cross_sector_write_preserves_length)
56+
{
57+
enum { type = WOLFPSA_STORE_KEY };
58+
const unsigned long id1 = 7;
59+
const unsigned long id2 = 9;
60+
void *store = NULL;
61+
unsigned char *payload;
62+
struct store_handle *handle;
63+
int ret;
64+
65+
payload = malloc(WOLFBOOT_SECTOR_SIZE);
66+
ck_assert_ptr_nonnull(payload);
67+
68+
for (ret = 0; ret < WOLFBOOT_SECTOR_SIZE; ret++)
69+
payload[ret] = (unsigned char)(ret & 0xFF);
70+
71+
ret = mmap_file("/tmp/wolfboot-unit-psa-keyvault.bin", vault_base,
72+
keyvault_size, NULL);
73+
ck_assert_int_eq(ret, 0);
74+
memset(vault_base, 0xEE, keyvault_size);
75+
76+
ret = wolfPSA_Store_Open(type, id1, id2, 0, &store);
77+
ck_assert_int_eq(ret, 0);
78+
ck_assert_ptr_nonnull(store);
79+
80+
ret = wolfPSA_Store_Write(store, payload, WOLFBOOT_SECTOR_SIZE);
81+
ck_assert_int_eq(ret, WOLFBOOT_SECTOR_SIZE);
82+
handle = store;
83+
ck_assert_uint_eq(handle->in_buffer_offset,
84+
2 * sizeof(uint32_t) + WOLFBOOT_SECTOR_SIZE);
85+
ck_assert_uint_eq(handle->hdr->size,
86+
2 * sizeof(uint32_t) + WOLFBOOT_SECTOR_SIZE);
87+
wolfPSA_Store_Close(store);
88+
89+
free(payload);
90+
}
91+
END_TEST
92+
93+
Suite *wolfboot_suite(void)
94+
{
95+
Suite *s = suite_create("wolfBoot-psa-store");
96+
TCase *tcase_write = tcase_create("cross_sector_write");
97+
98+
tcase_add_test(tcase_write, test_cross_sector_write_preserves_length);
99+
suite_add_tcase(s, tcase_write);
100+
return s;
101+
}
102+
103+
int main(void)
104+
{
105+
int fails;
106+
Suite *s = wolfboot_suite();
107+
SRunner *sr = srunner_create(s);
108+
109+
srunner_run_all(sr, CK_NORMAL);
110+
fails = srunner_ntests_failed(sr);
111+
srunner_free(sr);
112+
return fails;
113+
}

0 commit comments

Comments
 (0)