Skip to content

Commit ec3e969

Browse files
committed
Validate blob size from TPM NV storage
F/372
1 parent 18b8091 commit ec3e969

3 files changed

Lines changed: 197 additions & 7 deletions

File tree

src/tpm.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -696,9 +696,14 @@ int wolfBoot_read_blob(uint32_t nvIndex, WOLFTPM2_KEYBLOB* blob,
696696
(uint8_t*)&blob->pub.size, &readSz, pos);
697697
if (rc == 0) {
698698
pos += readSz;
699-
readSz = blob->pub.size;
700-
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
701-
pubAreaBuffer, &readSz, pos);
699+
if (blob->pub.size > sizeof(pubAreaBuffer)) {
700+
rc = BUFFER_E;
701+
}
702+
else {
703+
readSz = blob->pub.size;
704+
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
705+
pubAreaBuffer, &readSz, pos);
706+
}
702707
}
703708
if (rc == 0) {
704709
pos += readSz;
@@ -712,9 +717,14 @@ int wolfBoot_read_blob(uint32_t nvIndex, WOLFTPM2_KEYBLOB* blob,
712717
}
713718
if (rc == 0) {
714719
pos += sizeof(blob->priv.size);
715-
readSz = blob->priv.size;
716-
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
717-
blob->priv.buffer, &readSz, pos);
720+
if (blob->priv.size > sizeof(blob->priv.buffer)) {
721+
rc = BUFFER_E;
722+
}
723+
else {
724+
readSz = blob->priv.size;
725+
rc = wolfTPM2_NVReadAuth(&wolftpm_dev, &nv, nv.handle.hndl,
726+
blob->priv.buffer, &readSz, pos);
727+
}
718728
}
719729
if (rc == 0) {
720730
pos += blob->priv.size;

tools/unit-tests/Makefile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ TESTS:=unit-parser unit-extflash unit-string unit-spi-flash unit-aes128 \
4747
unit-image unit-image-rsa unit-nvm unit-nvm-flagshome unit-enc-nvm \
4848
unit-enc-nvm-flagshome unit-delta unit-update-flash \
4949
unit-update-flash-enc unit-update-ram unit-pkcs11_store unit-psa_store unit-disk \
50-
unit-multiboot unit-boot-x86-fsp unit-qspi-flash unit-tpm-rsa-exp
50+
unit-multiboot unit-boot-x86-fsp unit-qspi-flash unit-tpm-rsa-exp \
51+
unit-tpm-blob
5152

5253
all: $(TESTS)
5354

@@ -124,6 +125,12 @@ unit-tpm-rsa-exp: ../../include/target.h unit-tpm-rsa-exp.c
124125
-DWOLFBOOT_HASH_SHA256 \
125126
-ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections
126127

128+
unit-tpm-blob: ../../include/target.h unit-tpm-blob.c
129+
gcc -o $@ $^ $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) -DWOLFBOOT_TPM \
130+
-DWOLFTPM_USER_SETTINGS -DWOLFBOOT_TPM_SEAL -DWOLFBOOT_SIGN_RSA2048 \
131+
-DWOLFBOOT_HASH_SHA256 \
132+
-ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections
133+
127134
unit-string: ../../include/target.h unit-string.c
128135
gcc -o $@ $^ $(CFLAGS) -DDEBUG_UART -DPRINTF_ENABLED $(LDFLAGS)
129136

tools/unit-tests/unit-tpm-blob.c

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/* unit-tpm-blob.c
2+
*
3+
* Unit tests for TPM blob NV reads.
4+
*/
5+
6+
#include <check.h>
7+
#include <stdarg.h>
8+
#include <stdint.h>
9+
#include <stdio.h>
10+
#include <string.h>
11+
12+
#ifndef SPI_CS_TPM
13+
#define SPI_CS_TPM 1
14+
#endif
15+
#ifndef WOLFBOOT_SHA_DIGEST_SIZE
16+
#define WOLFBOOT_SHA_DIGEST_SIZE 32
17+
#endif
18+
#ifndef WOLFBOOT_TPM_HASH_ALG
19+
#define WOLFBOOT_TPM_HASH_ALG TPM_ALG_SHA256
20+
#endif
21+
22+
#include "wolfboot/wolfboot.h"
23+
#include "tpm.h"
24+
25+
enum mock_mode {
26+
MOCK_OVERSIZE_PUB,
27+
MOCK_OVERSIZE_PRIV
28+
};
29+
30+
static enum mock_mode current_mode;
31+
static int nvread_calls;
32+
static int oversized_pub_read_attempted;
33+
static int oversized_priv_read_attempted;
34+
35+
int wolfBoot_printf(const char* fmt, ...)
36+
{
37+
(void)fmt;
38+
return 0;
39+
}
40+
41+
int wolfTPM2_SetAuthHandle(WOLFTPM2_DEV* dev, int index,
42+
const WOLFTPM2_HANDLE* handle)
43+
{
44+
(void)dev;
45+
(void)index;
46+
(void)handle;
47+
return 0;
48+
}
49+
50+
const char* TPM2_GetRCString(int rc)
51+
{
52+
(void)rc;
53+
return "mock";
54+
}
55+
56+
int TPM2_ParsePublic(TPM2B_PUBLIC* pub, byte* buf, word32 size, int* sizeUsed)
57+
{
58+
(void)buf;
59+
*sizeUsed = 0;
60+
pub->size = (UINT16)size;
61+
return 0;
62+
}
63+
64+
int wolfTPM2_NVReadAuth(WOLFTPM2_DEV* dev, WOLFTPM2_NV* nv,
65+
word32 nvIndex, byte* dataBuf, word32* pDataSz, word32 offset)
66+
{
67+
(void)dev;
68+
(void)nv;
69+
(void)nvIndex;
70+
(void)offset;
71+
72+
nvread_calls++;
73+
74+
switch (nvread_calls) {
75+
case 1:
76+
if (current_mode == MOCK_OVERSIZE_PUB) {
77+
*(uint16_t*)dataBuf = (uint16_t)(sizeof(TPM2B_PUBLIC) + 1);
78+
}
79+
else {
80+
*(uint16_t*)dataBuf = 4;
81+
}
82+
*pDataSz = sizeof(uint16_t);
83+
return 0;
84+
case 2:
85+
if (current_mode == MOCK_OVERSIZE_PUB) {
86+
oversized_pub_read_attempted = 1;
87+
return -100;
88+
}
89+
memset(dataBuf, 0, *pDataSz);
90+
return 0;
91+
case 3:
92+
*(uint16_t*)dataBuf = (uint16_t)(sizeof(((WOLFTPM2_KEYBLOB*)0)->priv.buffer) + 1);
93+
*pDataSz = sizeof(uint16_t);
94+
return 0;
95+
case 4:
96+
oversized_priv_read_attempted = 1;
97+
return -101;
98+
default:
99+
ck_abort_msg("Unexpected NV read call %d", nvread_calls);
100+
return -102;
101+
}
102+
}
103+
104+
#include "../../src/tpm.c"
105+
106+
static void setup(void)
107+
{
108+
current_mode = MOCK_OVERSIZE_PUB;
109+
nvread_calls = 0;
110+
oversized_pub_read_attempted = 0;
111+
oversized_priv_read_attempted = 0;
112+
}
113+
114+
START_TEST(test_wolfBoot_read_blob_rejects_oversized_public_area)
115+
{
116+
WOLFTPM2_KEYBLOB blob;
117+
int rc;
118+
119+
memset(&blob, 0, sizeof(blob));
120+
current_mode = MOCK_OVERSIZE_PUB;
121+
122+
rc = wolfBoot_read_blob(0x01400300, &blob, NULL, 0);
123+
124+
ck_assert_int_eq(rc, BUFFER_E);
125+
ck_assert_int_eq(nvread_calls, 1);
126+
ck_assert_int_eq(oversized_pub_read_attempted, 0);
127+
}
128+
END_TEST
129+
130+
START_TEST(test_wolfBoot_read_blob_rejects_oversized_private_area)
131+
{
132+
WOLFTPM2_KEYBLOB blob;
133+
int rc;
134+
135+
memset(&blob, 0, sizeof(blob));
136+
current_mode = MOCK_OVERSIZE_PRIV;
137+
blob.pub.size = 4;
138+
139+
rc = wolfBoot_read_blob(0x01400300, &blob, NULL, 0);
140+
141+
ck_assert_int_eq(rc, BUFFER_E);
142+
ck_assert_int_eq(nvread_calls, 3);
143+
ck_assert_int_eq(oversized_priv_read_attempted, 0);
144+
}
145+
END_TEST
146+
147+
static Suite *tpm_blob_suite(void)
148+
{
149+
Suite *s;
150+
TCase *tc;
151+
152+
s = suite_create("TPM Blob");
153+
tc = tcase_create("wolfBoot_read_blob");
154+
tcase_add_checked_fixture(tc, setup, NULL);
155+
tcase_add_test(tc, test_wolfBoot_read_blob_rejects_oversized_public_area);
156+
tcase_add_test(tc, test_wolfBoot_read_blob_rejects_oversized_private_area);
157+
suite_add_tcase(s, tc);
158+
return s;
159+
}
160+
161+
int main(void)
162+
{
163+
Suite *s;
164+
SRunner *sr;
165+
int failed;
166+
167+
s = tpm_blob_suite();
168+
sr = srunner_create(s);
169+
srunner_run_all(sr, CK_NORMAL);
170+
failed = srunner_ntests_failed(sr);
171+
srunner_free(sr);
172+
return failed == 0 ? 0 : 1;
173+
}

0 commit comments

Comments
 (0)