Skip to content

Commit 80da567

Browse files
authored
Merge pull request #389 from dgarske/nv_extend
Fix issue with session binding / add NV extend example
2 parents cb645d3 + 15add23 commit 80da567

File tree

13 files changed

+635
-133
lines changed

13 files changed

+635
-133
lines changed

examples/gpio/gpio_config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ int TPM2_GPIO_Config_Example(void* userCtx, int argc, char *argv[])
406406
rc = wolfTPM2_GetNvAttributesTemplate(parent.hndl, &nvAttributes);
407407
/* Add NV attributes required by Nuvoton specification */
408408
nvAttributes |= (TPMA_NV_PLATFORMCREATE | TPMA_NV_POLICY_DELETE);
409-
nvAttributes |= (TPM_NT_ORDINARY & TPMA_NV_TPM_NT);
409+
nvAttributes |= (TPMA_NV_TPM_NT & (TPM_NT_ORDINARY << 4));
410410
if (rc != TPM_RC_SUCCESS) {
411411
printf("Setting NV attributes failed\n");
412412
goto exit;

examples/nvram/extend.c

Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
/* extend.c
2+
*
3+
* Copyright (C) 2006-2024 wolfSSL Inc.
4+
*
5+
* This file is part of wolfTPM.
6+
*
7+
* wolfTPM is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfTPM is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
*/
21+
22+
/* Example for showing NV extend usage for bus protection:
23+
* See "TCG_-CPU_-TPM_Bus_Protection_Guidance_Active_Attack_Mitigations-V1-R30_PUB-1.pdf" */
24+
25+
#ifdef HAVE_CONFIG_H
26+
#include <config.h>
27+
#endif
28+
29+
#include <wolftpm/tpm2_wrap.h>
30+
#include <wolftpm/tpm2_packet.h>
31+
#include <stdio.h>
32+
33+
#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT)
34+
35+
#include <examples/nvram/nvram.h>
36+
#include <hal/tpm_io.h>
37+
#include <examples/tpm_test.h>
38+
#include <examples/tpm_test_keys.h>
39+
40+
41+
/******************************************************************************/
42+
/* --- BEGIN TPM NVRAM Extend Example -- */
43+
/******************************************************************************/
44+
static void usage(void)
45+
{
46+
printf("Expected usage:\n");
47+
printf("./examples/nvram/extend [-nvindex=handle] [-aes/-xor]\n");
48+
printf("* -nvindex=[handle] (default 0x%x)\n",
49+
TPM2_DEMO_NVRAM_EXTEND_INDEX);
50+
printf("* -aes/xor: Use Parameter Encryption\n");;
51+
}
52+
53+
static int BuildPolicyCommandCode(TPMI_ALG_HASH hashAlg,
54+
byte* digest, word32* digestSz, TPM_CC cc)
55+
{
56+
word32 val = cpu_to_be32(cc);
57+
return wolfTPM2_PolicyHash(hashAlg, digest, digestSz,
58+
TPM_CC_PolicyCommandCode, (byte*)&val, sizeof(val));
59+
}
60+
61+
static int PolicyOrApply(WOLFTPM2_DEV* dev, WOLFTPM2_SESSION* policySession,
62+
byte** hashList, word32 hashListSz, word32 digestSz)
63+
{
64+
word32 i;
65+
PolicyOR_In policyOR;
66+
XMEMSET(&policyOR, 0, sizeof(policyOR));
67+
policyOR.policySession = policySession->handle.hndl;
68+
policyOR.pHashList.count = hashListSz;
69+
for (i=0; i<hashListSz; i++) {
70+
policyOR.pHashList.digests[i].size = digestSz;
71+
XMEMCPY(policyOR.pHashList.digests[i].buffer, hashList[i], digestSz);
72+
}
73+
(void)dev;
74+
return TPM2_PolicyOR(&policyOR);
75+
}
76+
77+
int TPM2_NVRAM_Extend_Example(void* userCtx, int argc, char *argv[])
78+
{
79+
int rc;
80+
WOLFTPM2_DEV dev;
81+
WOLFTPM2_KEY endorse;
82+
WOLFTPM2_SESSION tpmSession;
83+
WOLFTPM2_HANDLE nvAuth;
84+
WOLFTPM2_HANDLE bind;
85+
WOLFTPM2_NV nv;
86+
word32 nvAttributes;
87+
int paramEncAlg = TPM_ALG_CFB;
88+
TPMI_RH_NV_AUTH authHandle = TPM_RH_PLATFORM;
89+
word32 nvIndex = TPM2_DEMO_NVRAM_EXTEND_INDEX;
90+
byte* auth = (byte*)"cpusecret";
91+
word32 authSz = (word32)XSTRLEN((const char*)auth);
92+
TPMI_ALG_HASH hashAlg = WOLFTPM2_WRAP_DIGEST;
93+
word32 nvSize = TPM2_GetHashDigestSize(hashAlg);
94+
byte nvDigest[TPM_MAX_DIGEST_SIZE]; /* buffer for nv read */
95+
byte policyDigest[3*TPM_MAX_DIGEST_SIZE]; /* Policy A/B/C */
96+
word32 policyDigestSz = 0;
97+
byte* policy[3]; /* pointers to policy A/B/C */
98+
byte policyOr[TPM_MAX_DIGEST_SIZE];
99+
100+
if (argc >= 2) {
101+
if (XSTRCMP(argv[1], "-?") == 0 ||
102+
XSTRCMP(argv[1], "-h") == 0 ||
103+
XSTRCMP(argv[1], "--help") == 0) {
104+
usage();
105+
return 0;
106+
}
107+
}
108+
while (argc > 1) {
109+
if (XSTRNCMP(argv[argc-1], "-nvindex=", XSTRLEN("-nvindex=")) == 0) {
110+
const char* nvIndexStr = argv[argc-1] + XSTRLEN("-nvindex=");
111+
nvIndex = (word32)XSTRTOUL(nvIndexStr, NULL, 0);
112+
if (nvIndex >= TPM_20_PLATFORM_MFG_NV_SPACE &&
113+
nvIndex < TPM_20_OWNER_NV_SPACE) {
114+
authHandle = TPM_RH_PLATFORM;
115+
}
116+
else if (nvIndex >= TPM_20_OWNER_NV_SPACE &&
117+
nvIndex < TPM_20_TCG_NV_SPACE) {
118+
authHandle = TPM_RH_OWNER;
119+
}
120+
else {
121+
fprintf(stderr, "Invalid NV Index %s\n", nvIndexStr);
122+
fprintf(stderr, "\tPlatform Range: 0x%x -> 0x%x\n",
123+
TPM_20_PLATFORM_MFG_NV_SPACE, TPM_20_OWNER_NV_SPACE);
124+
fprintf(stderr, "\tOwner Range: 0x%x -> 0x%x\n",
125+
TPM_20_OWNER_NV_SPACE, TPM_20_TCG_NV_SPACE);
126+
usage();
127+
return -1;
128+
}
129+
}
130+
else if (XSTRCMP(argv[argc-1], "-aes") == 0) {
131+
paramEncAlg = TPM_ALG_CFB;
132+
}
133+
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
134+
paramEncAlg = TPM_ALG_XOR;
135+
}
136+
else {
137+
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
138+
}
139+
argc--;
140+
};
141+
142+
printf("NVRAM Extend (bus protection example)\n");
143+
printf("Parameter Encryption: %s\n",
144+
(paramEncAlg == TPM_ALG_CFB) ? "AES CFB" : "XOR");
145+
146+
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
147+
XMEMSET(&endorse, 0, sizeof(endorse));
148+
XMEMSET(&bind, 0, sizeof(bind));
149+
XMEMSET(&nv, 0, sizeof(nv));
150+
XMEMSET(&nvAuth, 0, sizeof(nvAuth));
151+
XMEMSET(nvDigest, 0, sizeof(nvDigest));
152+
XMEMSET(policyDigest, 0, sizeof(policyDigest));
153+
154+
rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);
155+
if (rc != TPM_RC_SUCCESS) {
156+
printf("wolfTPM2_Init failed\n");
157+
goto exit;
158+
}
159+
160+
/* Build Policies A/B/C */
161+
/* Policy A: TPM2_PolicyCommandCode -> TPM_CC_NV_Read */
162+
/* 47ce3032d8bad1f3089cb0c09088de43501491d460402b90cd1b7fc0b68ca92f */
163+
policy[0] = &policyDigest[policyDigestSz];
164+
BuildPolicyCommandCode(hashAlg, policy[0], &nvSize, TPM_CC_NV_Read);
165+
printf("PolicyA: %d\n", nvSize);
166+
TPM2_PrintBin(policy[0], nvSize);
167+
policyDigestSz += nvSize;
168+
169+
/* Policy B: TPM2_PolicyCommandCode -> TPM_CC_NV_Extend */
170+
/* b6a2e7142ee56fd978047488483daa5b42b8dc4cc7ddcceddfb91793cf1ff1b7 */
171+
policy[1] = &policyDigest[policyDigestSz];
172+
BuildPolicyCommandCode(hashAlg, policy[1], &nvSize, TPM_CC_NV_Extend);
173+
printf("PolicyB: %d\n", nvSize);
174+
TPM2_PrintBin(policy[1], nvSize);
175+
policyDigestSz += nvSize;
176+
177+
/* Policy C: TPM2_PolicyCommandCode -> TPM_CC_PolicyNV */
178+
/* 203e4bd5d0448c9615cc13fa18e8d39222441cc40204d99a77262068dbd55a43 */
179+
policy[2] = &policyDigest[policyDigestSz];
180+
BuildPolicyCommandCode(hashAlg, policy[2], &nvSize, TPM_CC_PolicyNV);
181+
printf("PolicyC: %d\n", nvSize);
182+
TPM2_PrintBin(policy[2], nvSize);
183+
policyDigestSz += nvSize;
184+
185+
/* Policy OR A/B/C */
186+
/* 7f17937e206279a3f755fb60f40cf126b70e5b1d9bf202866d527613874a64ac */
187+
XMEMSET(policyOr, 0, sizeof(policyOr));
188+
rc = wolfTPM2_PolicyHash(hashAlg, policyOr, &nvSize,
189+
TPM_CC_PolicyOR, policyDigest, policyDigestSz);
190+
printf("PolicyOR A/B/C: %d\n", nvSize);
191+
TPM2_PrintBin(policyOr, nvSize);
192+
193+
/* 1: Create EK (RSA or ECC) */
194+
rc = wolfTPM2_CreateEK(&dev, &endorse,
195+
#ifndef NO_RSA
196+
TPM_ALG_RSA
197+
#else
198+
TPM_ALG_ECC
199+
#endif
200+
);
201+
if (rc != 0) {
202+
printf("Create EK RSA failed!\n");
203+
goto exit;
204+
}
205+
endorse.handle.policyAuth = 1; /* EK requires policy auth */
206+
printf("EK Handle: 0x%x\n", (word32)endorse.handle.hndl);
207+
208+
/* 2: Create a salted session with the TPM using the EK */
209+
rc = wolfTPM2_StartSession(&dev, &tpmSession, &endorse, NULL,
210+
TPM_SE_HMAC, paramEncAlg);
211+
if (rc == 0) {
212+
rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession,
213+
(TPMA_SESSION_decrypt | TPMA_SESSION_encrypt |
214+
TPMA_SESSION_continueSession));
215+
}
216+
if (rc != 0) {
217+
printf("Start HMAC session failed!\n");
218+
goto exit;
219+
}
220+
printf("Encrypted HMAC Session Handle 0x%x\n",
221+
(word32)tpmSession.handle.hndl);
222+
223+
/* 3. Create the NV Index with extend attribute.
224+
* Use "host secret" as password so it is used with the bind session later */
225+
226+
/* See TPM_Bus_Protection_Guidance_Active_Attack_Mitigations:
227+
* Section 3.4 Provisioning the NV Index */
228+
nvAttributes = (
229+
(TPMA_NV_TPM_NT & (TPM_NT_EXTEND << 4)) |
230+
TPMA_NV_ORDERLY |
231+
TPMA_NV_CLEAR_STCLEAR |
232+
TPMA_NV_PLATFORMCREATE |
233+
TPMA_NV_POLICYWRITE |
234+
TPMA_NV_POLICYREAD |
235+
TPMA_NV_NO_DA);
236+
nvSize = TPM2_GetHashDigestSize(WOLFTPM2_WRAP_DIGEST);
237+
238+
/* Try and open existing NV */
239+
rc = wolfTPM2_NVOpen(&dev, &nv, nvIndex, auth, authSz);
240+
if (rc != 0) {
241+
nvAuth.hndl = authHandle;
242+
243+
rc = wolfTPM2_NVCreateAuthPolicy(&dev, &nvAuth, &nv, nvIndex,
244+
nvAttributes, /* needs TPM_NT_EXTEND set */
245+
nvSize, /* must match nameAlg digest size */
246+
auth, authSz, /* the password to bind session with */
247+
policyOr, nvSize
248+
);
249+
}
250+
251+
/* Close session and unload endorsement */
252+
wolfTPM2_UnsetAuth(&dev, 0);
253+
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
254+
wolfTPM2_UnloadHandle(&dev, &endorse.handle);
255+
256+
257+
/* 4. Start a policy session and bind to NV handle */
258+
rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, &nv.handle,
259+
TPM_SE_POLICY, TPM_ALG_CFB);
260+
if (rc == 0) {
261+
rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession,
262+
(TPMA_SESSION_decrypt | TPMA_SESSION_encrypt |
263+
TPMA_SESSION_continueSession));
264+
}
265+
if (rc != 0) {
266+
printf("Start Policy session failed!\n");
267+
goto exit;
268+
}
269+
printf("Encrypted Policy Session Handle 0x%x\n",
270+
(word32)tpmSession.handle.hndl);
271+
272+
/* 5. Satisfy policy for NV Extend (policy B) */
273+
rc = wolfTPM2_PolicyCommandCode(&dev, &tpmSession, TPM_CC_NV_Extend);
274+
if (rc == 0) {
275+
rc = PolicyOrApply(&dev, &tpmSession, policy, 3, nvSize);
276+
}
277+
if (rc != 0) {
278+
printf("Failed to apply policy B\n");
279+
goto exit;
280+
}
281+
282+
/* 6. Perform NV extend */
283+
rc = wolfTPM2_NVExtend(&dev, &nv, nvIndex, auth, (word32)authSz);
284+
if (rc != 0) {
285+
printf("NV Extend failed!\n");
286+
goto exit;
287+
}
288+
printf("NV 0x%08x extended\n", (word32)nvIndex);
289+
290+
/* 7. Restart session policy */
291+
rc = wolfTPM2_PolicyRestart(&dev, tpmSession.handle.hndl);
292+
if (rc != 0) {
293+
printf("Policy restart failed!\n");
294+
goto exit;
295+
}
296+
297+
/* 8. Satisfy policy for NV Read (policy A) */
298+
rc = wolfTPM2_PolicyCommandCode(&dev, &tpmSession, TPM_CC_NV_Read);
299+
if (rc == 0) {
300+
rc = PolicyOrApply(&dev, &tpmSession, policy, 3, nvSize);
301+
}
302+
if (rc != 0) {
303+
printf("Failed to apply policy A\n");
304+
goto exit;
305+
}
306+
307+
/* 9. Read NV extend digest */
308+
rc = wolfTPM2_NVRead(&dev, authHandle, nv.handle.hndl,
309+
nvDigest, &nvSize, 0);
310+
if (rc == 0) {
311+
printf("NV Digest: %d\n", nvSize);
312+
TPM2_PrintBin(nvDigest, nvSize);
313+
314+
/* Should be:
315+
* 0ad80f8e4450587760d9137df41c9374f657bafa621fe37d4d5c8cecf0bcce5e */
316+
}
317+
318+
exit:
319+
320+
if (rc != 0) {
321+
printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc));
322+
}
323+
324+
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
325+
wolfTPM2_Cleanup(&dev);
326+
327+
return rc;
328+
}
329+
330+
/******************************************************************************/
331+
/* --- END TPM NVRAM Extend Example -- */
332+
/******************************************************************************/
333+
#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT */
334+
335+
#ifndef NO_MAIN_DRIVER
336+
int main(int argc, char *argv[])
337+
{
338+
int rc = NOT_COMPILED_IN;
339+
340+
#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT)
341+
rc = TPM2_NVRAM_Extend_Example(NULL, argc, argv);
342+
#else
343+
printf("NVRAM extend code not compiled in\n");
344+
(void)argc;
345+
(void)argv;
346+
#endif
347+
348+
return rc;
349+
}
350+
#endif

examples/nvram/include.am

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,24 @@ examples_nvram_policy_nv_SOURCES = examples/nvram/policy_nv.c \
2727
examples/tpm_test_keys.c
2828
examples_nvram_policy_nv_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
2929
examples_nvram_policy_nv_DEPENDENCIES = src/libwolftpm.la
30+
31+
noinst_PROGRAMS += examples/nvram/extend
32+
examples_nvram_extend_SOURCES = examples/nvram/extend.c \
33+
examples/tpm_test_keys.c
34+
examples_nvram_extend_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
35+
examples_nvram_extend_DEPENDENCIES = src/libwolftpm.la
3036
endif
3137

3238
example_nvramdir = $(exampledir)/nvram
3339
dist_example_nvram_DATA = \
3440
examples/nvram/store.c \
3541
examples/nvram/read.c \
3642
examples/nvram/counter.c \
37-
examples/nvram/policy_nv.c
43+
examples/nvram/policy_nv.c \
44+
examples/nvram/extend.c
3845

39-
DISTCLEANFILES+= examples/nvram/.libs/store
40-
DISTCLEANFILES+= examples/nvram/.libs/read
41-
DISTCLEANFILES+= examples/nvram/.libs/counter
42-
DISTCLEANFILES+= examples/nvram/.libs/policy_nv
46+
DISTCLEANFILES+= examples/nvram/.libs/store \
47+
examples/nvram/.libs/read \
48+
examples/nvram/.libs/counter \
49+
examples/nvram/.libs/policy_nv \
50+
examples/nvram/.libs/extend

examples/nvram/nvram.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[]);
3232
int TPM2_PCR_Seal_With_Policy_Auth_NV_Test(void* userCtx, int argc, char *argv[]);
3333
int TPM2_PCR_Seal_With_Policy_Auth_NV_External_Test(void* userCtx, int argc, char *argv[]);
3434
int TPM2_NVRAM_PolicyNV_Example(void* userCtx, int argc, char *argv[]);
35+
int TPM2_NVRAM_Extend_Example(void* userCtx, int argc, char *argv[]);
3536

3637
#ifdef __cplusplus
3738
} /* extern "C" */

0 commit comments

Comments
 (0)