Example for HMAC with persistent key. ZD 20109.

pull/422/head
David Garske 2025-06-26 11:06:28 -07:00
parent 21d8604db9
commit 2d5a27d238
7 changed files with 306 additions and 14 deletions

1
.gitignore vendored
View File

@ -39,6 +39,7 @@ build/
examples/wrap/wrap_test
examples/wrap/caps
examples/wrap/hmac
examples/native/native_test
examples/bench/bench
examples/csr/csr

View File

@ -136,6 +136,38 @@ if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
[ $RESULT -ne 0 ] && echo -e "wrap_test (AES param enc) failed! $RESULT" && exit 1
fi
# HMAC tests
echo -e "HMAC tests"
./examples/wrap/hmac >> $TPMPWD/run.out 2>&1
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "hmac test failed! $RESULT" && exit 1
./examples/wrap/hmac -ecc >> $TPMPWD/run.out 2>&1
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "hmac test (ECC SRK) failed! $RESULT" && exit 1
./examples/wrap/hmac -rsa >> $TPMPWD/run.out 2>&1
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "hmac test (RSA SRK) failed! $RESULT" && exit 1
if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
./examples/wrap/hmac -aes >> $TPMPWD/run.out 2>&1
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "hmac test (AES param enc) failed! $RESULT" && exit 1
fi
if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
./examples/wrap/hmac -xor >> $TPMPWD/run.out 2>&1
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "hmac test (XOR param enc) failed! $RESULT" && exit 1
fi
if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
./examples/wrap/hmac -rsa -aes >> $TPMPWD/run.out 2>&1
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "hmac test (RSA SRK + AES param enc) failed! $RESULT" && exit 1
fi
if [ $WOLFCRYPT_ENABLE -eq 1 ]; then
./examples/wrap/hmac -ecc -xor >> $TPMPWD/run.out 2>&1
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "hmac test (ECC SRK + XOR param enc) failed! $RESULT" && exit 1
fi
# Key Generation Tests
echo -e "Key Generation Tests"

View File

@ -33,6 +33,7 @@
#define TPM2_DEMO_STORAGE_KEY_HANDLE 0x81000200 /* Persistent Storage Key Handle (RSA) */
#define TPM2_DEMO_STORAGE_EC_KEY_HANDLE 0x81000201 /* Persistent Storage Key Handle (ECC) */
#define TPM2_DEMO_PERSISTENT_KEY_HANDLE 0x81000202 /* Persistent Key Handle for common use */
#define TPM2_DEMO_HMAC_KEY_HANDLE 0x81000210 /* Persistent HMAC Key Handle */
#define TPM2_DEMO_RSA_IDX 0x20 /* offset handle to unused index */
#define TPM2_DEMO_RSA_KEY_HANDLE (0x81000000 + TPM2_DEMO_RSA_IDX) /* Persistent Key Handle */
#define TPM2_DEMO_RSA_CERT_HANDLE (0x01800000 + TPM2_DEMO_RSA_IDX) /* NV Handle */

View File

@ -0,0 +1,242 @@
/* hmac.c
*
* Copyright (C) 2006-2025 wolfSSL Inc.
*
* This file is part of wolfTPM.
*
* wolfTPM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfTPM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* This example shows using the TPM2 wrapper API's for HMAC
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolftpm/tpm2.h>
#include <wolftpm/tpm2_wrap.h>
#include <stdio.h>
#ifndef WOLFTPM2_NO_WRAPPER
#include <hal/tpm_io.h>
#include <examples/tpm_test.h>
#include <examples/tpm_test_keys.h>
#include <examples/wrap/wrap_test.h>
static void usage(void)
{
printf("Expected Usage:\n");
printf("./examples/wrap/hmac [-aes/xor] [-rsa/ecc]\n");
printf("* -aes/xor: Use Parameter Encryption\n");
printf("* -rsa/ecc: Use RSA or ECC for SRK (default ECC)\n");
printf("* -keep: Keep the HMAC key in persistent storage\n");
printf("\nThis example demonstrates:\n");
printf("1. Creating an SRK (Storage Root Key)\n");
printf("2. Loading an HMAC key using the SRK as parent\n");
printf("3. Storing the HMAC key persistently at handle 0x%x\n",
TPM2_DEMO_HMAC_KEY_HANDLE);
printf("4. Using the persistent HMAC key for HMAC operations\n");
printf("5. Reusing the persistent key for multiple operations\n\n");
}
int TPM2_Wrapper_Hmac(void* userCtx)
{
return TPM2_Wrapper_HmacArgs(userCtx, 0, NULL);
}
int TPM2_Wrapper_HmacArgs(void* userCtx, int argc, char *argv[])
{
int rc;
WOLFTPM2_DEV dev;
WOLFTPM2_KEY storage; /* SRK */
WOLFTPM2_HMAC hmac;
WOLFTPM2_SESSION tpmSession;
TPMI_ALG_PUBLIC srkAlg = TPM_ALG_ECC; /* prefer ECC, but allow RSA */
TPM_ALG_ID paramEncAlg = TPM_ALG_NULL;
WOLFTPM2_BUFFER cipher;
int keepKey = 0;
const char* hmacTestKey =
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
"\x0b\x0b\x0b\x0b";
const char* hmacTestData = "Hi There";
const char* hmacTestDig =
"\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b"
"\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7";
if (argc >= 2) {
if (XSTRCMP(argv[1], "-?") == 0 ||
XSTRCMP(argv[1], "-h") == 0 ||
XSTRCMP(argv[1], "--help") == 0) {
usage();
return 0;
}
}
while (argc > 1) {
if (XSTRCMP(argv[argc-1], "-rsa") == 0) {
srkAlg = TPM_ALG_RSA;
}
else if (XSTRCMP(argv[argc-1], "-ecc") == 0) {
srkAlg = TPM_ALG_ECC;
}
else if (XSTRCMP(argv[argc-1], "-aes") == 0) {
paramEncAlg = TPM_ALG_CFB;
}
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
paramEncAlg = TPM_ALG_XOR;
}
else if (XSTRCMP(argv[argc-1], "-keep") == 0) {
keepKey = 1;
}
else {
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
}
argc--;
}
XMEMSET(&hmac, 0, sizeof(hmac));
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
printf("TPM2.0 HMAC example\n");
printf("\tUse Parameter Encryption: %s\n", TPM2_GetAlgName(paramEncAlg));
printf("\tSRK: %s\n", TPM2_GetAlgName(srkAlg));
rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);
if (rc != 0) goto exit;
/* storage root key (SRK) */
rc = getPrimaryStoragekey(&dev, &storage, srkAlg);
if (rc != 0) goto exit;
/* Start an authenticated session (salted / unbound) with parameter encryption */
if (paramEncAlg != TPM_ALG_NULL) {
WOLFTPM2_KEY* bindKey = &storage;
#ifdef NO_RSA
if (srkAlg == TPM_ALG_RSA)
bindKey = NULL; /* cannot bind to key without RSA enabled */
#endif
#ifndef HAVE_ECC
if (srkAlg == TPM_ALG_ECC)
bindKey = NULL; /* cannot bind to key without ECC enabled */
#endif
rc = wolfTPM2_StartSession(&dev, &tpmSession, bindKey, NULL,
TPM_SE_HMAC, paramEncAlg);
if (rc != 0) goto exit;
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n",
(word32)tpmSession.handle.hndl);
/* set session for authorization of the storage key */
rc = wolfTPM2_SetAuthSession(&dev, 1, &tpmSession,
(TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | TPMA_SESSION_continueSession));
if (rc != 0) goto exit;
}
/* Try to load existing persistent HMAC key first */
rc = wolfTPM2_ReadPublicKey(&dev, &hmac.key, TPM2_DEMO_HMAC_KEY_HANDLE);
if (rc != 0) {
printf("Persistent HMAC key not found, creating new one...\n");
/* Load Keyed Hash Key */
rc = wolfTPM2_LoadKeyedHashKey(&dev, &hmac.key, &storage.handle,
TPM_ALG_SHA256,
(const byte*)hmacTestKey, (word32)XSTRLEN(hmacTestKey),
(const byte*)gUsageAuth, sizeof(gUsageAuth)-1);
if (rc != 0) goto exit;
printf("Storing HMAC key to persistent handle 0x%x\n", TPM2_DEMO_HMAC_KEY_HANDLE);
/* Store the HMAC key to persistent storage */
rc = wolfTPM2_NVStoreKey(&dev, TPM_RH_OWNER, &hmac.key,
TPM2_DEMO_HMAC_KEY_HANDLE);
if (rc != 0) {
printf("wolfTPM2_NVStoreKey failed 0x%x: %s\n", rc,
wolfTPM2_GetRCString(rc));
goto exit;
}
printf("HMAC key stored persistently at handle 0x%x\n",
TPM2_DEMO_HMAC_KEY_HANDLE);
}
else {
printf("Using existing persistent HMAC key at handle 0x%x\n",
TPM2_DEMO_HMAC_KEY_HANDLE);
/* Set auth for persistent key */
hmac.key.handle.auth.size = sizeof(gUsageAuth)-1;
XMEMCPY(hmac.key.handle.auth.buffer, gUsageAuth,
hmac.key.handle.auth.size);
}
/* Test HMAC operations using the persistent key */
printf("\nTesting HMAC operations with persistent key...\n");
hmac.hmacKeyKeep = 1; /* don't unload key on finish */
rc = wolfTPM2_HmacStart(&dev, &hmac, &storage.handle, TPM_ALG_SHA256,
NULL, 0, (const byte*)gUsageAuth, sizeof(gUsageAuth)-1);
if (rc != 0) goto exit;
rc = wolfTPM2_HmacUpdate(&dev, &hmac, (byte*)hmacTestData,
(word32)XSTRLEN(hmacTestData));
if (rc != 0) goto exit;
cipher.size = TPM_SHA256_DIGEST_SIZE;
rc = wolfTPM2_HmacFinish(&dev, &hmac, cipher.buffer, (word32*)&cipher.size);
if (rc != 0) goto exit;
if (cipher.size != TPM_SHA256_DIGEST_SIZE ||
XMEMCMP(cipher.buffer, hmacTestDig, cipher.size) != 0) {
printf("HMAC SHA256 test failed, result not as expected!\n");
goto exit;
}
printf("HMAC SHA256 test with persistent key: PASSED\n");
if (!keepKey) {
/* remove the key from persistent storage */
wolfTPM2_SetAuthPassword(&dev, 0, NULL);
wolfTPM2_NVDeleteKey(&dev, TPM_RH_OWNER, &hmac.key);
}
exit:
if (rc != 0) {
printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc));
}
/* Clean up session */
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
wolfTPM2_UnloadHandle(&dev, &hmac.key.handle);
wolfTPM2_Cleanup(&dev);
return rc;
}
#endif /* !WOLFTPM2_NO_WRAPPER */
#ifndef NO_MAIN_DRIVER
int main(int argc, char *argv[])
{
int rc = -1;
#ifndef WOLFTPM2_NO_WRAPPER
rc = TPM2_Wrapper_HmacArgs(NULL, argc, argv);
#else
(void)argc;
(void)argv;
printf("Wrapper code not compiled in\n");
#endif
return rc;
}
#endif /* !NO_MAIN_DRIVER */

View File

@ -3,8 +3,10 @@
if BUILD_EXAMPLES
noinst_PROGRAMS += examples/wrap/wrap_test \
examples/wrap/caps
examples/wrap/caps \
examples/wrap/hmac
noinst_HEADERS += examples/wrap/wrap_test.h
examples_wrap_wrap_test_SOURCES = examples/wrap/wrap_test.c
examples_wrap_wrap_test_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
examples_wrap_wrap_test_DEPENDENCIES = src/libwolftpm.la
@ -12,11 +14,18 @@ examples_wrap_wrap_test_DEPENDENCIES = src/libwolftpm.la
examples_wrap_caps_SOURCES = examples/wrap/caps.c
examples_wrap_caps_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
examples_wrap_caps_DEPENDENCIES = src/libwolftpm.la
examples_wrap_hmac_SOURCES = examples/wrap/hmac.c \
examples/tpm_test_keys.c
examples_wrap_hmac_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
examples_wrap_hmac_DEPENDENCIES = src/libwolftpm.la
endif
example_wrapdir = $(exampledir)/wrap
dist_example_wrap_DATA = examples/wrap/wrap_test.c \
examples/wrap/caps.c
examples/wrap/caps.c \
examples/wrap/hmac.c
DISTCLEANFILES+= examples/wrap/.libs/wrap_test \
examples/wrap/.libs/caps
examples/wrap/.libs/caps \
examples/wrap/.libs/hmac

View File

@ -32,6 +32,9 @@ int TPM2_Wrapper_TestArgs(void* userCtx, int argc, char *argv[]);
int TPM2_Wrapper_Caps(void* userCtx);
int TPM2_Wrapper_CapsArgs(void* userCtx, int argc, char *argv[]);
int TPM2_Wrapper_Hmac(void* userCtx);
int TPM2_Wrapper_HmacArgs(void* userCtx, int argc, char *argv[]);
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -5630,18 +5630,22 @@ int wolfTPM2_HmacStart(WOLFTPM2_DEV* dev, WOLFTPM2_HMAC* hmac,
return BAD_FUNC_ARG;
}
/* Capture usage auth */
if (usageAuthSz > sizeof(hmac->hash.handle.auth.buffer))
usageAuthSz = sizeof(hmac->hash.handle.auth.buffer);
hmac->hash.handle.auth.size = usageAuthSz;
XMEMCPY(hmac->hash.handle.auth.buffer, usageAuth, usageAuthSz);
if (usageAuth != NULL) {
/* Capture usage auth */
if (usageAuthSz > sizeof(hmac->hash.handle.auth.buffer))
usageAuthSz = sizeof(hmac->hash.handle.auth.buffer);
hmac->hash.handle.auth.size = usageAuthSz;
XMEMCPY(hmac->hash.handle.auth.buffer, usageAuth, usageAuthSz);
}
if (!hmac->hmacKeyLoaded || hmac->key.handle.hndl == TPM_RH_NULL) {
/* Load Keyed Hash Key */
rc = wolfTPM2_LoadKeyedHashKey(dev, &hmac->key, parent, hashAlg, keyBuf,
keySz, usageAuth, usageAuthSz);
if (rc != 0) {
return rc;
if (!hmac->hmacKeyLoaded) {
if (hmac->key.handle.hndl == TPM_RH_NULL) {
/* Load Keyed Hash Key */
rc = wolfTPM2_LoadKeyedHashKey(dev, &hmac->key, parent, hashAlg,
keyBuf, keySz, usageAuth, usageAuthSz);
if (rc != 0) {
return rc;
}
}
hmac->hmacKeyLoaded = 1;
}