Skip to content

Commit 22b324f

Browse files
authored
Merge pull request #422 from dgarske/hmac_persist_key
Example for HMAC with persistent key
2 parents 77867d0 + fde0571 commit 22b324f

7 files changed

Lines changed: 307 additions & 15 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ build/
3939

4040
examples/wrap/wrap_test
4141
examples/wrap/caps
42+
examples/wrap/hmac
4243
examples/native/native_test
4344
examples/bench/bench
4445
examples/csr/csr

examples/run_examples.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,38 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
136136
[ $RESULT -ne 0 ] && echo -e "wrap_test (AES param enc) failed! $RESULT" && exit 1
137137
fi
138138

139+
# HMAC tests
140+
echo -e "HMAC tests"
141+
./examples/wrap/hmac >> $TPMPWD/run.out 2>&1
142+
RESULT=$?
143+
[ $RESULT -ne 0 ] && echo -e "hmac test failed! $RESULT" && exit 1
144+
./examples/wrap/hmac -ecc >> $TPMPWD/run.out 2>&1
145+
RESULT=$?
146+
[ $RESULT -ne 0 ] && echo -e "hmac test (ECC SRK) failed! $RESULT" && exit 1
147+
./examples/wrap/hmac -rsa >> $TPMPWD/run.out 2>&1
148+
RESULT=$?
149+
[ $RESULT -ne 0 ] && echo -e "hmac test (RSA SRK) failed! $RESULT" && exit 1
150+
if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
151+
./examples/wrap/hmac -aes >> $TPMPWD/run.out 2>&1
152+
RESULT=$?
153+
[ $RESULT -ne 0 ] && echo -e "hmac test (AES param enc) failed! $RESULT" && exit 1
154+
fi
155+
if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
156+
./examples/wrap/hmac -xor >> $TPMPWD/run.out 2>&1
157+
RESULT=$?
158+
[ $RESULT -ne 0 ] && echo -e "hmac test (XOR param enc) failed! $RESULT" && exit 1
159+
fi
160+
if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
161+
./examples/wrap/hmac -rsa -aes >> $TPMPWD/run.out 2>&1
162+
RESULT=$?
163+
[ $RESULT -ne 0 ] && echo -e "hmac test (RSA SRK + AES param enc) failed! $RESULT" && exit 1
164+
fi
165+
if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
166+
./examples/wrap/hmac -ecc -xor >> $TPMPWD/run.out 2>&1
167+
RESULT=$?
168+
[ $RESULT -ne 0 ] && echo -e "hmac test (ECC SRK + XOR param enc) failed! $RESULT" && exit 1
169+
fi
170+
139171

140172
# Key Generation Tests
141173
echo -e "Key Generation Tests"

examples/tpm_test.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#define TPM2_DEMO_STORAGE_KEY_HANDLE 0x81000200 /* Persistent Storage Key Handle (RSA) */
3434
#define TPM2_DEMO_STORAGE_EC_KEY_HANDLE 0x81000201 /* Persistent Storage Key Handle (ECC) */
3535
#define TPM2_DEMO_PERSISTENT_KEY_HANDLE 0x81000202 /* Persistent Key Handle for common use */
36+
#define TPM2_DEMO_HMAC_KEY_HANDLE 0x81000210 /* Persistent HMAC Key Handle */
3637
#define TPM2_DEMO_RSA_IDX 0x20 /* offset handle to unused index */
3738
#define TPM2_DEMO_RSA_KEY_HANDLE (0x81000000 + TPM2_DEMO_RSA_IDX) /* Persistent Key Handle */
3839
#define TPM2_DEMO_RSA_CERT_HANDLE (0x01800000 + TPM2_DEMO_RSA_IDX) /* NV Handle */

examples/wrap/hmac.c

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
/* hmac.c
2+
*
3+
* Copyright (C) 2006-2025 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+
/* This example shows using the TPM2 wrapper API's for HMAC
23+
*/
24+
25+
#ifdef HAVE_CONFIG_H
26+
#include <config.h>
27+
#endif
28+
29+
#include <wolftpm/tpm2.h>
30+
#include <wolftpm/tpm2_wrap.h>
31+
32+
#include <stdio.h>
33+
34+
#ifndef WOLFTPM2_NO_WRAPPER
35+
36+
#include <hal/tpm_io.h>
37+
#include <examples/tpm_test.h>
38+
#include <examples/tpm_test_keys.h>
39+
#include <examples/wrap/wrap_test.h>
40+
41+
static void usage(void)
42+
{
43+
printf("Expected Usage:\n");
44+
printf("./examples/wrap/hmac [-aes/xor] [-rsa/ecc]\n");
45+
printf("* -aes/xor: Use Parameter Encryption\n");
46+
printf("* -rsa/ecc: Use RSA or ECC for SRK (default ECC)\n");
47+
printf("* -keep: Keep the HMAC key in persistent storage\n");
48+
printf("\nThis example demonstrates:\n");
49+
printf("1. Creating an SRK (Storage Root Key)\n");
50+
printf("2. Loading an HMAC key using the SRK as parent\n");
51+
printf("3. Storing the HMAC key persistently at handle 0x%x\n",
52+
TPM2_DEMO_HMAC_KEY_HANDLE);
53+
printf("4. Using the persistent HMAC key for HMAC operations\n");
54+
printf("5. Reusing the persistent key for multiple operations\n\n");
55+
}
56+
57+
int TPM2_Wrapper_Hmac(void* userCtx)
58+
{
59+
return TPM2_Wrapper_HmacArgs(userCtx, 0, NULL);
60+
}
61+
int TPM2_Wrapper_HmacArgs(void* userCtx, int argc, char *argv[])
62+
{
63+
int rc;
64+
WOLFTPM2_DEV dev;
65+
WOLFTPM2_KEY storage; /* SRK */
66+
WOLFTPM2_HMAC hmac;
67+
WOLFTPM2_SESSION tpmSession;
68+
TPMI_ALG_PUBLIC srkAlg = TPM_ALG_ECC; /* prefer ECC, but allow RSA */
69+
TPM_ALG_ID paramEncAlg = TPM_ALG_NULL;
70+
WOLFTPM2_BUFFER cipher;
71+
int keepKey = 0;
72+
73+
const char* hmacTestKey =
74+
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
75+
"\x0b\x0b\x0b\x0b";
76+
const char* hmacTestData = "Hi There";
77+
const char* hmacTestDig =
78+
"\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b"
79+
"\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7";
80+
81+
if (argc >= 2) {
82+
if (XSTRCMP(argv[1], "-?") == 0 ||
83+
XSTRCMP(argv[1], "-h") == 0 ||
84+
XSTRCMP(argv[1], "--help") == 0) {
85+
usage();
86+
return 0;
87+
}
88+
}
89+
while (argc > 1) {
90+
if (XSTRCMP(argv[argc-1], "-rsa") == 0) {
91+
srkAlg = TPM_ALG_RSA;
92+
}
93+
else if (XSTRCMP(argv[argc-1], "-ecc") == 0) {
94+
srkAlg = TPM_ALG_ECC;
95+
}
96+
else if (XSTRCMP(argv[argc-1], "-aes") == 0) {
97+
paramEncAlg = TPM_ALG_CFB;
98+
}
99+
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
100+
paramEncAlg = TPM_ALG_XOR;
101+
}
102+
else if (XSTRCMP(argv[argc-1], "-keep") == 0) {
103+
keepKey = 1;
104+
}
105+
else {
106+
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
107+
}
108+
109+
argc--;
110+
}
111+
112+
XMEMSET(&hmac, 0, sizeof(hmac));
113+
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
114+
115+
printf("TPM2.0 HMAC example\n");
116+
printf("\tUse Parameter Encryption: %s\n", TPM2_GetAlgName(paramEncAlg));
117+
printf("\tSRK: %s\n", TPM2_GetAlgName(srkAlg));
118+
119+
rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);
120+
if (rc != 0) goto exit;
121+
122+
/* storage root key (SRK) */
123+
rc = getPrimaryStoragekey(&dev, &storage, srkAlg);
124+
if (rc != 0) goto exit;
125+
126+
/* Start an authenticated session (salted / unbound) with parameter encryption */
127+
if (paramEncAlg != TPM_ALG_NULL) {
128+
WOLFTPM2_KEY* bindKey = &storage;
129+
#ifdef NO_RSA
130+
if (srkAlg == TPM_ALG_RSA)
131+
bindKey = NULL; /* cannot bind to key without RSA enabled */
132+
#endif
133+
#ifndef HAVE_ECC
134+
if (srkAlg == TPM_ALG_ECC)
135+
bindKey = NULL; /* cannot bind to key without ECC enabled */
136+
#endif
137+
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
138+
TPM_SE_HMAC, paramEncAlg);
139+
if (rc != 0) goto exit;
140+
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n",
141+
(word32)tpmSession.handle.hndl);
142+
143+
/* set session for authorization of the storage key */
144+
rc = wolfTPM2_SetAuthSession(&dev, 0, &tpmSession,
145+
(TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | TPMA_SESSION_continueSession));
146+
if (rc != 0) goto exit;
147+
}
148+
149+
/* Try to load existing persistent HMAC key first */
150+
rc = wolfTPM2_ReadPublicKey(&dev, &hmac.key, TPM2_DEMO_HMAC_KEY_HANDLE);
151+
if (rc != 0) {
152+
printf("Persistent HMAC key not found, creating new one...\n");
153+
154+
/* Load Keyed Hash Key */
155+
rc = wolfTPM2_LoadKeyedHashKey(&dev, &hmac.key, &storage.handle,
156+
TPM_ALG_SHA256,
157+
(const byte*)hmacTestKey, (word32)XSTRLEN(hmacTestKey),
158+
(const byte*)gUsageAuth, sizeof(gUsageAuth)-1);
159+
if (rc != 0) goto exit;
160+
161+
printf("Storing HMAC key to persistent handle 0x%x\n", TPM2_DEMO_HMAC_KEY_HANDLE);
162+
/* Store the HMAC key to persistent storage */
163+
rc = wolfTPM2_NVStoreKey(&dev, TPM_RH_OWNER, &hmac.key,
164+
TPM2_DEMO_HMAC_KEY_HANDLE);
165+
if (rc != 0) {
166+
printf("wolfTPM2_NVStoreKey failed 0x%x: %s\n", rc,
167+
wolfTPM2_GetRCString(rc));
168+
goto exit;
169+
}
170+
printf("HMAC key stored persistently at handle 0x%x\n",
171+
TPM2_DEMO_HMAC_KEY_HANDLE);
172+
}
173+
else {
174+
printf("Using existing persistent HMAC key at handle 0x%x\n",
175+
TPM2_DEMO_HMAC_KEY_HANDLE);
176+
177+
/* Set auth for persistent key */
178+
hmac.key.handle.auth.size = sizeof(gUsageAuth)-1;
179+
XMEMCPY(hmac.key.handle.auth.buffer, gUsageAuth,
180+
hmac.key.handle.auth.size);
181+
}
182+
183+
/* Test HMAC operations using the persistent key */
184+
printf("\nTesting HMAC operations with persistent key...\n");
185+
186+
hmac.hmacKeyKeep = 1; /* don't unload key on finish */
187+
rc = wolfTPM2_HmacStart(&dev, &hmac, &storage.handle, TPM_ALG_SHA256,
188+
NULL, 0, (const byte*)gUsageAuth, sizeof(gUsageAuth)-1);
189+
if (rc != 0) goto exit;
190+
191+
rc = wolfTPM2_HmacUpdate(&dev, &hmac, (byte*)hmacTestData,
192+
(word32)XSTRLEN(hmacTestData));
193+
if (rc != 0) goto exit;
194+
195+
cipher.size = TPM_SHA256_DIGEST_SIZE;
196+
rc = wolfTPM2_HmacFinish(&dev, &hmac, cipher.buffer, (word32*)&cipher.size);
197+
if (rc != 0) goto exit;
198+
199+
if (cipher.size != TPM_SHA256_DIGEST_SIZE ||
200+
XMEMCMP(cipher.buffer, hmacTestDig, cipher.size) != 0) {
201+
printf("HMAC SHA256 test failed, result not as expected!\n");
202+
goto exit;
203+
}
204+
printf("HMAC SHA256 test with persistent key: PASSED\n");
205+
206+
if (!keepKey) {
207+
/* remove the key from persistent storage */
208+
wolfTPM2_SetAuthPassword(&dev, 0, NULL);
209+
wolfTPM2_NVDeleteKey(&dev, TPM_RH_OWNER, &hmac.key);
210+
}
211+
212+
exit:
213+
if (rc != 0) {
214+
printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc));
215+
}
216+
217+
/* Clean up session */
218+
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
219+
wolfTPM2_UnloadHandle(&dev, &hmac.key.handle);
220+
221+
wolfTPM2_Cleanup(&dev);
222+
return rc;
223+
}
224+
225+
#endif /* !WOLFTPM2_NO_WRAPPER */
226+
227+
#ifndef NO_MAIN_DRIVER
228+
int main(int argc, char *argv[])
229+
{
230+
int rc = -1;
231+
232+
#ifndef WOLFTPM2_NO_WRAPPER
233+
rc = TPM2_Wrapper_HmacArgs(NULL, argc, argv);
234+
#else
235+
(void)argc;
236+
(void)argv;
237+
printf("Wrapper code not compiled in\n");
238+
#endif
239+
240+
return rc;
241+
}
242+
#endif /* !NO_MAIN_DRIVER */

examples/wrap/include.am

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,29 @@
33

44
if BUILD_EXAMPLES
55
noinst_PROGRAMS += examples/wrap/wrap_test \
6-
examples/wrap/caps
6+
examples/wrap/caps \
7+
examples/wrap/hmac
78
noinst_HEADERS += examples/wrap/wrap_test.h
9+
810
examples_wrap_wrap_test_SOURCES = examples/wrap/wrap_test.c
911
examples_wrap_wrap_test_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
1012
examples_wrap_wrap_test_DEPENDENCIES = src/libwolftpm.la
1113

1214
examples_wrap_caps_SOURCES = examples/wrap/caps.c
1315
examples_wrap_caps_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
1416
examples_wrap_caps_DEPENDENCIES = src/libwolftpm.la
17+
18+
examples_wrap_hmac_SOURCES = examples/wrap/hmac.c \
19+
examples/tpm_test_keys.c
20+
examples_wrap_hmac_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
21+
examples_wrap_hmac_DEPENDENCIES = src/libwolftpm.la
1522
endif
1623

1724
example_wrapdir = $(exampledir)/wrap
1825
dist_example_wrap_DATA = examples/wrap/wrap_test.c \
19-
examples/wrap/caps.c
26+
examples/wrap/caps.c \
27+
examples/wrap/hmac.c
2028

2129
DISTCLEANFILES+= examples/wrap/.libs/wrap_test \
22-
examples/wrap/.libs/caps
30+
examples/wrap/.libs/caps \
31+
examples/wrap/.libs/hmac

examples/wrap/wrap_test.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ int TPM2_Wrapper_TestArgs(void* userCtx, int argc, char *argv[]);
3232
int TPM2_Wrapper_Caps(void* userCtx);
3333
int TPM2_Wrapper_CapsArgs(void* userCtx, int argc, char *argv[]);
3434

35+
int TPM2_Wrapper_Hmac(void* userCtx);
36+
int TPM2_Wrapper_HmacArgs(void* userCtx, int argc, char *argv[]);
37+
3538
#ifdef __cplusplus
3639
} /* extern "C" */
3740
#endif

src/tpm2_wrap.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5630,18 +5630,22 @@ int wolfTPM2_HmacStart(WOLFTPM2_DEV* dev, WOLFTPM2_HMAC* hmac,
56305630
return BAD_FUNC_ARG;
56315631
}
56325632

5633-
/* Capture usage auth */
5634-
if (usageAuthSz > sizeof(hmac->hash.handle.auth.buffer))
5635-
usageAuthSz = sizeof(hmac->hash.handle.auth.buffer);
5636-
hmac->hash.handle.auth.size = usageAuthSz;
5637-
XMEMCPY(hmac->hash.handle.auth.buffer, usageAuth, usageAuthSz);
5638-
5639-
if (!hmac->hmacKeyLoaded || hmac->key.handle.hndl == TPM_RH_NULL) {
5640-
/* Load Keyed Hash Key */
5641-
rc = wolfTPM2_LoadKeyedHashKey(dev, &hmac->key, parent, hashAlg, keyBuf,
5642-
keySz, usageAuth, usageAuthSz);
5643-
if (rc != 0) {
5644-
return rc;
5633+
if (usageAuth != NULL) {
5634+
/* Capture usage auth */
5635+
if (usageAuthSz > sizeof(hmac->hash.handle.auth.buffer))
5636+
usageAuthSz = sizeof(hmac->hash.handle.auth.buffer);
5637+
hmac->hash.handle.auth.size = usageAuthSz;
5638+
XMEMCPY(hmac->hash.handle.auth.buffer, usageAuth, usageAuthSz);
5639+
}
5640+
5641+
if (!hmac->hmacKeyLoaded) {
5642+
if (hmac->key.handle.hndl == 0 || hmac->key.handle.hndl == TPM_RH_NULL){
5643+
/* Load Keyed Hash Key */
5644+
rc = wolfTPM2_LoadKeyedHashKey(dev, &hmac->key, parent, hashAlg,
5645+
keyBuf, keySz, usageAuth, usageAuthSz);
5646+
if (rc != 0) {
5647+
return rc;
5648+
}
56455649
}
56465650
hmac->hmacKeyLoaded = 1;
56475651
}

0 commit comments

Comments
 (0)