Example for secure boot solution to store root of trust in NV. Provides authentication and tamper protection. Fixed uses of arg= in examples.

pull/276/head
David Garske 2023-07-05 15:44:12 -07:00
parent bb82dd26c4
commit 14a331d648
15 changed files with 416 additions and 14 deletions

1
.gitignore vendored
View File

@ -75,6 +75,7 @@ examples/seal/unseal
examples/seal/seal_policy_auth
examples/attestation/make_credential
examples/attestation/activate_credential
examples/boot/secure_rot
# Generated Cert Files
certs/ca-*.pem

Binary file not shown.

View File

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnj22EdUiGQC/9vBWG4Kc
cpxDYLxwAjPS3M2Z7IFZGWMcdzvQ022tlU8YTDdtYv2qHCQs2Qd+ar8/kYnJMr1g
ajw12riRJ/YnD14EpJ6sc8NGQE8y9MG6v05OU/qCExRQhifP22haJLTiroj+R+dA
8el9ltajR4i5GxquzW1xwPGBtsMyvZMIpKMEl0FQe6WeW4I1tqu97yBkrHlvNNn+
yP99MG3+KEdb35ODkLq7E/bJdghSzbeWyUsOpRU5uAToAu0N26Rz8wv2CrhWFihn
kC/RgrBGVVhwjOr83pOkjcENHqENIvSLhdKLP9JyQ8HVxGV/TqAYRU+9e7L5cQ16
RQIDAQAB
-----END PUBLIC KEY-----

Binary file not shown.

View File

@ -8,4 +8,7 @@ EXTRA_DIST += \
certs/ca-ecc.cnf \
certs/wolf-ca-ecc-cert.pem \
certs/wolf-ca-rsa-cert.pem \
certs/example-rsa-key.pem
certs/example-rsa-key.pem \
certs/example-rsa-key.der \
certs/example-rsa-key-pub.pem \
certs/example-rsa-key-pub.der

View File

@ -0,0 +1,11 @@
# Secure Boot Root-of-Trust (ROT)
Design for storage of public key based root of trust into TPM:
1) Use AES-CFB parameter encryption for all communication (salted and bound)
2) Derive a password based on unique device parameters used as "auth" to load NV (authenticate)
3) The NV contains a hash of the public key (hash matches .config setting)
4) WolfBoot still has the public key internally and programs the TPM with the NV if not populated.
5) The NV is locked and created under the platform hierarchy

View File

@ -0,0 +1,35 @@
/* boot.h
*
* Copyright (C) 2006-2023 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
*/
#ifndef _BOOT_SECURE_EXAMPLES_H_
#define _BOOT_SECURE_EXAMPLES_H_
#ifdef __cplusplus
extern "C" {
#endif
int TPM2_Boot_SecureROT_Example(void* userCtx, int argc, char *argv[]);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _BOOT_SECURE_EXAMPLES_H_ */

View File

@ -0,0 +1,15 @@
# vim:ft=automake
# All paths should be given relative to the root
if BUILD_EXAMPLES
noinst_PROGRAMS += examples/boot/secure_rot
noinst_HEADERS += examples/boot/boot.h
examples_boot_secure_rot_SOURCES = examples/boot/secure_rot.c
examples_boot_secure_rot_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD)
examples_boot_secure_rot_DEPENDENCIES = src/libwolftpm.la
endif
example_bootdir = $(exampledir)/boot
dist_example_boot_DATA = examples/boot/secure_rot.c
DISTCLEANFILES+= examples/boot/.libs/secure_rot

View File

@ -0,0 +1,319 @@
/* secure_rot.c
*
* Copyright (C) 2006-2023 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
*/
/* Example for using TPM for secure boot root of trust
*/
#include <wolftpm/tpm2_wrap.h>
#include <stdio.h>
#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT)
#include <examples/boot/boot.h>
#include <hal/tpm_io.h>
#include <examples/tpm_test.h>
#include <wolfssl/wolfcrypt/hash.h>
/* WC_HASH_TYPE_SHA256 or WC_HASH_TYPE_SHA384 */
#define TPM2_SECURE_ROT_HASH_ALGO WC_HASH_TYPE_SHA256
#define TPM2_SECURE_ROT_EXAMPLE_PUB_KEY "certs/example-rsa-key-pub.der"
/******************************************************************************/
/* --- BEGIN TPM NVRAM Secure Boot Root of Trust Example -- */
/******************************************************************************/
static void usage(void)
{
printf("Expected usage:\n");
printf("./examples/boot/secure_rot [-nvindex] [-write] [-lock]\n");
printf("* -nvindex=[handle] (default 0x%x)\n",
TPM2_DEMO_NV_SECURE_ROT_INDEX);
printf("* -write=filename: DER formatted public key to write\n");
printf("\tDefault public key: " TPM2_SECURE_ROT_EXAMPLE_PUB_KEY "\n");
printf("* -lock: Lock the write\n");
}
/* forward declaration */
static int load_file(const char* fname, byte** buf, size_t* bufLen);
/* Example for reading unique system registers for derived authentication
* used to access TPM NV */
static int GetSystemUniqueAuth(enum wc_HashType hashType, byte* authBuf)
{
int rc;
wc_HashAlg hash;
uint32_t reg1 = 0x01234567;
uint32_t reg2 = 0x89ABCDEF;
uint32_t reg3 = 0x01234567;
uint32_t reg4 = 0x89ABCDEF;
rc = wc_HashInit(&hash, hashType);
if (rc == 0) {
rc = wc_HashUpdate(&hash, hashType, (byte*)&reg1, sizeof(reg1));
if (rc == 0)
rc = wc_HashUpdate(&hash, hashType, (byte*)&reg2, sizeof(reg2));
if (rc == 0)
rc = wc_HashUpdate(&hash, hashType, (byte*)&reg3, sizeof(reg3));
if (rc == 0)
rc = wc_HashUpdate(&hash, hashType, (byte*)&reg4, sizeof(reg4));
if (rc == 0) {
rc = wc_HashFinal(&hash, hashType, authBuf);
}
wc_HashFree(&hash, hashType);
}
return rc;
}
int TPM2_Boot_SecureROT_Example(void* userCtx, int argc, char *argv[])
{
int rc;
WOLFTPM2_DEV dev;
WOLFTPM2_SESSION tpmSession;
WOLFTPM2_HANDLE parent;
WOLFTPM2_NV nv;
word32 nvAttributes;
int paramEncAlg = TPM_ALG_CFB; /* always use AES CFB parameter encryption */
const char* filename = TPM2_SECURE_ROT_EXAMPLE_PUB_KEY;
word32 nvIndex = TPM2_DEMO_NV_SECURE_ROT_INDEX;
int doWrite = 0, doLock = 0;
byte* buf = NULL;
size_t bufSz = 0;
enum wc_HashType hashType = TPM2_SECURE_ROT_HASH_ALGO;
byte digest[WC_MAX_DIGEST_SIZE];
word32 digestSz = wc_HashGetDigestSize(hashType);
byte authBuf[WC_SHA256_DIGEST_SIZE];
if (digestSz <= 0) {
printf("Unsupported hash type %d!\n", hashType);
usage();
return -1;
}
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 (XSTRNCMP(argv[argc-1], "-nvindex=", XSTRLEN("-nvindex=")) == 0) {
nvIndex = (word32)XSTRTOL(argv[argc-1] +
XSTRLEN("-nvindex="), NULL, 0);
if (nvIndex > TPM_20_PLATFORM_MFG_NV_SPACE &&
nvIndex < TPM_20_OWNER_NV_SPACE) {
printf("Invalid NV Index %s\n", argv[argc-1] + 8);
nvIndex = 0;
}
}
else if (XSTRNCMP(argv[argc-1], "-write=", XSTRLEN("-write=")) == 0) {
doWrite = 1;
filename = argv[argc-1] + XSTRLEN("-write=");
}
else if (XSTRCMP(argv[argc-1], "-write") == 0) {
doWrite = 1;
}
else if (XSTRCMP(argv[argc-1], "-lock") == 0) {
doLock = 1;
}
else {
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);
}
argc--;
};
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
XMEMSET(&parent, 0, sizeof(parent));
XMEMSET(digest, 0, sizeof(digest));
rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);
if (rc != TPM_RC_SUCCESS) {
printf("\nwolfTPM2_Init failed\n");
goto exit;
}
rc = GetSystemUniqueAuth(hashType, authBuf);
if (rc != 0) {
printf("Error getting system unique NV auth! %d\n", rc);
goto exit;
}
printf("NV Auth (%d)\n", (int)sizeof(authBuf));
TPM2_PrintBin(authBuf, sizeof(authBuf));
/* Start TPM session for parameter encryption */
printf("Parameter Encryption: Enabled. (AES CFB)\n\n");
rc = wolfTPM2_StartSession(&dev, &tpmSession, NULL, NULL,
TPM_SE_HMAC, paramEncAlg);
if (rc != 0) goto exit;
printf("TPM2_StartAuthSession: sessionHandle 0x%x\n",
(word32)tpmSession.handle.hndl);
/* Set TPM session attributes for parameter encryption */
rc = wolfTPM2_SetAuthSession(&dev, 1, &tpmSession,
(TPMA_SESSION_decrypt | TPMA_SESSION_encrypt | TPMA_SESSION_continueSession));
if (rc != 0) goto exit;
/* Open file */
if (doWrite) {
printf("Storing hash of public key file %s to "
"NV index 0x%x with password protection\n\n",
filename, nvIndex);
rc = load_file(filename, &buf, &bufSz);
if (rc == 0) {
/* hash public key */
rc = wc_Hash(hashType, buf, (word32)bufSz, digest, digestSz);
printf("Public Key Hash (%d)\n", digestSz);
TPM2_PrintBin(digest, digestSz);
}
if (rc == 0) {
/* Get NV attributes */
parent.hndl = TPM_RH_PLATFORM;
rc = wolfTPM2_GetNvAttributesTemplate(parent.hndl, &nvAttributes);
}
if (rc == 0) {
if (doLock) {
nvAttributes |= TPMA_NV_WRITELOCKED;
}
printf("nvAttributes=0x%x\n", nvAttributes);
/* Try and create NV */
rc = wolfTPM2_NVCreateAuth(&dev, &parent, &nv, nvIndex,
nvAttributes, digestSz, authBuf, sizeof(authBuf));
if (rc == TPM_RC_NV_DEFINED) {
printf("Warning: NV Index 0x%x already exists!\n", nvIndex);
rc = 0;
}
}
if (rc == 0) {
rc = wolfTPM2_NVWriteAuth(&dev, &nv, nvIndex,
digest, digestSz, 0);
}
if (rc != 0) goto exit;
printf("Wrote %d bytes to NV 0x%x\n", digestSz, nvIndex);
}
/* Do NV Auth Read */
XMEMSET(&nv, 0, sizeof(nv));
nv.handle.hndl = nvIndex;
nv.handle.auth.size = sizeof(authBuf);
XMEMCPY(nv.handle.auth.buffer, authBuf, sizeof(authBuf));
printf("Reading NV 0x%x public key hash\n", nvIndex);
rc = wolfTPM2_NVReadAuth(&dev, &nv, nvIndex, digest, &digestSz, 0);
if (rc == 0) {
printf("Read Public Key Hash (%d)\n", digestSz);
TPM2_PrintBin(digest, digestSz);
}
else if ((rc & RC_MAX_FMT1) == TPM_RC_HANDLE) {
printf("NV index does not exist\n");
}
exit:
if (rc != 0) {
printf("\nFailure 0x%x: %s\n\n", rc, wolfTPM2_GetRCString(rc));
}
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfTPM2_UnloadHandle(&dev, &tpmSession.handle);
wolfTPM2_Cleanup(&dev);
return rc;
}
static int load_file(const char* fname, byte** buf, size_t* bufLen)
{
int ret;
#if !defined(NO_FILESYSTEM)
long int fileSz;
XFILE lFile;
if (fname == NULL || buf == NULL || bufLen == NULL)
return BAD_FUNC_ARG;
/* set defaults */
*buf = NULL;
*bufLen = 0;
/* open file (read-only binary) */
lFile = XFOPEN(fname, "rb");
if (!lFile) {
fprintf(stderr, "Error loading %s\n", fname);
return BUFFER_E;
}
XFSEEK(lFile, 0, XSEEK_END);
fileSz = (int)ftell(lFile);
XFSEEK(lFile, 0, XSEEK_SET);
if (fileSz > 0) {
*bufLen = (size_t)fileSz;
*buf = (byte*)XMALLOC(*bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (*buf == NULL) {
ret = MEMORY_E;
fprintf(stderr,
"Error allocating %lu bytes\n", (unsigned long)*bufLen);
}
else {
size_t readLen = fread(*buf, *bufLen, 1, lFile);
/* check response code */
ret = (readLen > 0) ? 0 : -1;
}
}
else {
ret = BUFFER_E;
}
fclose(lFile);
#else
(void)fname;
(void)buf;
(void)bufLen;
ret = NOT_COMPILED_IN;
#endif
return ret;
}
/* !NO_FILESYSTEM */
/******************************************************************************/
/* --- END TPM NVRAM Secure Boot Root of Trust Example -- */
/******************************************************************************/
#endif /* !WOLFTPM2_NO_WRAPPER && !WOLFTPM2_NO_WOLFCRYPT */
#ifndef NO_MAIN_DRIVER
int main(int argc, char *argv[])
{
int rc = NOT_COMPILED_IN;
#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_WOLFCRYPT)
rc = TPM2_Boot_SecureROT_Example(NULL, argc, argv);
#else
printf("Example not compiled in! Requires Wrapper and wolfCrypt\n");
(void)argc;
(void)argv;
#endif
return rc;
}
#endif /* NO_MAIN_DRIVER */

View File

@ -4,6 +4,7 @@
include examples/native/include.am
include examples/wrap/include.am
include examples/bench/include.am
include examples/boot/include.am
include examples/tls/include.am
include examples/csr/include.am
include examples/pkcs7/include.am

View File

@ -111,11 +111,11 @@ int TPM2_CreatePrimaryKey_Example(void* userCtx, int argc, char *argv[])
else if (XSTRCMP(argv[argc-1], "-oh") == 0) {
hierarchy = TPM_RH_OWNER;
}
else if (XSTRCMP(argv[argc-1], "-unique=") == 0) {
uniqueStr = argv[argc-1] + 8;
else if (XSTRNCMP(argv[argc-1], "-unique=", XSTRLEN("-unique=")) == 0) {
uniqueStr = argv[argc-1] + XSTRLEN("-unique=");
}
else if (XSTRCMP(argv[argc-1], "-auth=") == 0) {
authStr = argv[argc-1] + 6;
else if (XSTRNCMP(argv[argc-1], "-auth=", XSTRLEN("-auth=")) == 0) {
authStr = argv[argc-1] + XSTRLEN("-auth=");
}
else if (XSTRNCMP(argv[argc-1], "-store=", XSTRLEN("-store=")) == 0) {
persistHandle = (word32)XSTRTOL(argv[argc-1] + XSTRLEN("-store="),

View File

@ -199,8 +199,8 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
paramEncAlg = TPM_ALG_XOR;
}
else if (XSTRCMP(argv[argc-1], "-unique=") == 0) {
uniqueStr = argv[argc-1] + 8;
else if (XSTRNCMP(argv[argc-1], "-unique=", XSTRLEN("-unique=")) == 0) {
uniqueStr = argv[argc-1] + XSTRLEN("-unique=");
}
else {
printf("Warning: Unrecognized option: %s\n", argv[argc-1]);

View File

@ -80,7 +80,7 @@ int TPM2_NVRAM_Counter_Example(void* userCtx, int argc, char *argv[])
else if (XSTRCMP(argv[argc-1], "-xor") == 0) {
paramEncAlg = TPM_ALG_XOR;
}
else if (XSTRCMP(argv[argc-1], "-nvindex=") == 0) {
else if (XSTRNCMP(argv[argc-1], "-nvindex=", XSTRLEN("-nvindex=")) == 0) {
nvIndex = (word32)XSTRTOL(argv[argc-1] + XSTRLEN("-nvindex="),
NULL, 0);
if (nvIndex > TPM_20_OWNER_NV_SPACE &&

View File

@ -47,6 +47,8 @@
#define TPM2_DEMO_NV_TEST_SIZE 1024 /* max size on Infineon SLB9670 is 1664 */
#define TPM2_DEMO_NV_COUNTER_INDEX 0x01800300
#define TPM2_DEMO_NV_SECURE_ROT_INDEX 0x01400200
#define TPM2_DEMO_PCR_INDEX 16
static const char gStorageKeyAuth[] = "ThisIsMyStorageKeyAuth";

View File

@ -5177,16 +5177,22 @@ int wolfTPM2_GetNvAttributesTemplate(TPM_HANDLE auth, word32* nvAttributes)
return BAD_FUNC_ARG;
*nvAttributes = (
TPMA_NV_AUTHWRITE | /* password or HMAC can authorize writing */
TPMA_NV_AUTHREAD | /* password or HMAC can authorize reading */
TPMA_NV_OWNERWRITE | /* Owner Hierarchy auth can be used also */
TPMA_NV_OWNERREAD | /* Owner Hierarchy auth for read */
TPMA_NV_NO_DA /* Don't increment dictionary attack counter */
TPMA_NV_AUTHWRITE | /* password or HMAC can authorize writing */
TPMA_NV_AUTHREAD | /* password or HMAC can authorize reading */
TPMA_NV_NO_DA /* Don't increment dictionary attack counter */
);
if (auth == TPM_RH_PLATFORM) {
*nvAttributes |= (
TPMA_NV_PPWRITE | TPMA_NV_PPREAD
TPMA_NV_PLATFORMCREATE | /* Platform created NV */
TPMA_NV_PPWRITE | /* Write may be authorized by platform */
TPMA_NV_PPREAD /* Read may be authorized by platform */
);
}
else if (auth == TPM_RH_OWNER) {
*nvAttributes |= (
TPMA_NV_OWNERWRITE | /* Owner Hierarchy auth can be used also */
TPMA_NV_OWNERREAD /* Owner Hierarchy auth for read */
);
}