From c4339fbb5abecaf1f30dcb6e80d360cfa865bfdf Mon Sep 17 00:00:00 2001 From: Dimitar Tomov Date: Wed, 15 Jul 2020 14:02:35 +0300 Subject: [PATCH] Add example of generating a TPM2.0 Quote using wolfTPM Signed-off-by: Dimitar Tomov --- .gitignore | 1 + examples/README.md | 9 +- examples/include.am | 1 + examples/pcr/include.am | 14 +++ examples/pcr/quote.c | 236 ++++++++++++++++++++++++++++++++++++++++ examples/pcr/quote.h | 35 ++++++ 6 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 examples/pcr/include.am create mode 100644 examples/pcr/quote.c create mode 100644 examples/pcr/quote.h diff --git a/.gitignore b/.gitignore index e3b942d..8e0ac6f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ examples/csr/csr examples/tls/tls_client examples/pkcs7/pkcs7 examples/timestamp/signed_timestamp +examples/timestamp/pcr pkcs7tpmsigned.p7s pkcs7tpmsignedex.p7s examples/tls/tls_server diff --git a/examples/README.md b/examples/README.md index 41ed5d5..fad1b12 100644 --- a/examples/README.md +++ b/examples/README.md @@ -20,7 +20,9 @@ Demonstrates calling the wolfTPM2_* wrapper API's. `./examples/wrap/wrap_test` -## Attestation Use Case (TPM signed timestamp) +## Attestation Use Cases + +# TPM signed timestamp, TPM2.0 GetTime Demonstrates creation of Attestation Identity Keys(AIK) and the generation of TPM signed timestamp that can be later used as protected report of the current system uptime. @@ -28,6 +30,11 @@ This example demonstrates the use of authSession(authorization Session) and poli `./examples/timestamp/signed_timestamp` +# TPM signed PCR(system) measurement, TPM2.0 Quote + +Demonstrates the generation of TPM2.0 Quote used for attestation of the system state by putting PCR value(s) in a TPM signed structure. + +`./examples/pcr/quote` ## CSR diff --git a/examples/include.am b/examples/include.am index ee3167c..2deb448 100644 --- a/examples/include.am +++ b/examples/include.am @@ -8,6 +8,7 @@ include examples/tls/include.am include examples/csr/include.am include examples/pkcs7/include.am include examples/timestamp/include.am +include examples/pcr/include.am dist_example_DATA+= examples/README.md \ examples/tpm_io.c \ diff --git a/examples/pcr/include.am b/examples/pcr/include.am new file mode 100644 index 0000000..cddf1d8 --- /dev/null +++ b/examples/pcr/include.am @@ -0,0 +1,14 @@ +# vim:ft=automake +# All paths should be given relative to the root + +if BUILD_EXAMPLES +noinst_PROGRAMS += examples/pcr/quote +noinst_HEADERS += examples/pcr/quote.h +examples_pcr_quote_SOURCES = examples/pcr/quote.c \ + examples/tpm_io.c +examples_pcr_quote_LDADD = src/libwolftpm.la $(LIB_STATIC_ADD) +examples_pcr_quote_DEPENDENCIES = src/libwolftpm.la +endif + +dist_example_DATA+= examples/pcr/quote.c +DISTCLEANFILES+= examples/pcr/.libs/quote diff --git a/examples/pcr/quote.c b/examples/pcr/quote.c new file mode 100644 index 0000000..02c7f6c --- /dev/null +++ b/examples/pcr/quote.c @@ -0,0 +1,236 @@ +/* quote.c + * + * Copyright (C) 2006-2020 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-1301, USA + */ + +/* This example shows how to generate a TPM2.0 Quote that holds a signed + * PCR measurement. PCR values are used as basis for system integrity. + */ + +#include + +#include +#include +#include + +#include + + +#define SET_PCR_SELECT_BIT( pcrSelection, pcr ) \ + (pcrSelection).pcrSelect[( (pcr)/8 )] |= ( 1 << ( (pcr) % 8) ); + +/******************************************************************************/ +/* --- BEGIN TPM2.0 Quote Test -- */ +/******************************************************************************/ + +int TPM2_Quote_Test(void* userCtx) +{ + int rc; + /* UINT32 i; */ + WOLFTPM2_DEV dev; + TPMS_ATTEST attestedData; + + union { + Quote_In quoteAsk; + /* For managing TPM session */ + StartAuthSession_In authSes; + PolicySecret_In policySecret; + /* For removing keys after use */ + FlushContext_In flushCtx; + byte maxInput[MAX_COMMAND_SIZE]; + } cmdIn; + union { + Quote_Out quoteResult; + /* Output from session operations */ + StartAuthSession_Out authSes; + PolicySecret_Out policySecret; + byte maxOutput[MAX_RESPONSE_SIZE]; + } cmdOut; + + TPM_HANDLE sessionHandle = TPM_RH_NULL; + + WOLFTPM2_KEY endorse; /* EK */ + WOLFTPM2_KEY storage; /* SRK */ + WOLFTPM2_KEY rsaKey; /* AIK */ + + const byte storagePwd[] = "WolfTPMpassword"; + const byte usageAuth[] = "ThisIsASecretUsageAuth"; + + TPMS_AUTH_COMMAND session[MAX_SESSION_NUM]; + + XMEMSET(&endorse, 0, sizeof(endorse)); + XMEMSET(&storage, 0, sizeof(storage)); + XMEMSET(&rsaKey, 0, sizeof(rsaKey)); + + printf("Demo of generating signed PCR measurement (TPM2.0 Quote)\n"); + rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc)); + goto exit; + } + printf("wolfTPM2_Init: success\n"); + + + /* Define the default session auth that has NULL password */ + XMEMSET(session, 0, sizeof(session)); + session[0].sessionHandle = TPM_RS_PW; + session[0].auth.size = 0; /* NULL Password */ + TPM2_SetSessionAuth(session); + + + /* Create Endorsement Key, also called EK */ + rc = wolfTPM2_CreateEK(&dev, &endorse, TPM_ALG_RSA); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_CreateEK: Endorsement failed 0x%x: %s\n", + rc, TPM2_GetRCString(rc)); + goto exit; + } + printf("wolfTPM2_CreateEK: Endorsement 0x%x (%d bytes)\n", + (word32)endorse.handle.hndl, endorse.pub.size); + + + /* Create Storage Key, also called SRK */ + rc = wolfTPM2_CreateSRK(&dev, &storage, TPM_ALG_RSA, storagePwd, + sizeof(storagePwd)-1); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_CreateSRK: Storage failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + printf("wolfTPM2_CreateSRK: Storage 0x%x (%d bytes)\n", + (word32)storage.handle.hndl, storage.pub.size); + + + /* Start Auth Session */ + XMEMSET(&cmdIn.authSes, 0, sizeof(cmdIn.authSes)); + cmdIn.authSes.sessionType = TPM_SE_POLICY; + cmdIn.authSes.tpmKey = TPM_RH_NULL; + cmdIn.authSes.bind = TPM_RH_NULL; + cmdIn.authSes.symmetric.algorithm = TPM_ALG_NULL; + cmdIn.authSes.authHash = TPM_ALG_SHA256; + cmdIn.authSes.nonceCaller.size = TPM_SHA256_DIGEST_SIZE; + rc = TPM2_GetNonce(cmdIn.authSes.nonceCaller.buffer, + cmdIn.authSes.nonceCaller.size); + if (rc < 0) { + printf("TPM2_GetNonce failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + rc = TPM2_StartAuthSession(&cmdIn.authSes, &cmdOut.authSes); + if (rc != TPM_RC_SUCCESS) { + printf("TPM2_StartAuthSession failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + sessionHandle = cmdOut.authSes.sessionHandle; + printf("TPM2_StartAuthSession: sessionHandle 0x%x\n", (word32)sessionHandle); + + + /* set session auth for storage key */ + session[0].auth.size = sizeof(storagePwd)-1; + XMEMCPY(session[0].auth.buffer, storagePwd, session[0].auth.size); + + + /* Create an RSA key for Attestation purposes */ + rc = wolfTPM2_CreateAndLoadAIK(&dev, &rsaKey, TPM_ALG_RSA, &storage, + usageAuth, sizeof(usageAuth)-1); + if (rc != TPM_RC_SUCCESS) { + printf("wolfTPM2_CreateAndLoadAIK failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + printf("wolfTPM2_CreateAndLoadAIK: AIK 0x%x (%d bytes)\n", + (word32)rsaKey.handle.hndl, rsaKey.pub.size); + + + /* set auth for using the AIK */ + session[0].auth.size = sizeof(usageAuth)-1; + XMEMCPY(session[0].auth.buffer, usageAuth, session[0].auth.size); + + /* Prepare Quote request */ + XMEMSET(&cmdIn.quoteAsk, 0, sizeof(cmdIn.quoteAsk)); + XMEMSET(&cmdOut.quoteResult, 0, sizeof(cmdOut.quoteResult)); + cmdIn.quoteAsk.signHandle = rsaKey.handle.hndl; + cmdIn.quoteAsk.inScheme.scheme = TPM_ALG_RSASSA; + cmdIn.quoteAsk.inScheme.details.rsassa.hashAlg = TPM_ALG_SHA256; + cmdIn.quoteAsk.qualifyingData.size = 0; /* optional */ + /* Set the PCR for signing */ + cmdIn.quoteAsk.PCRselect.count = 1; + cmdIn.quoteAsk.PCRselect.pcrSelections[0].hash = TPM_ALG_SHA256; + cmdIn.quoteAsk.PCRselect.pcrSelections[0].sizeofSelect = 3; + /* PCR16 is for DEBUG purposes, therefore safe to use for a demo */ + SET_PCR_SELECT_BIT(cmdIn.quoteAsk.PCRselect.pcrSelections[0], 16); + + + /* Get PCR measurement signed by the TPM using the AIK key */ + rc = TPM2_Quote(&cmdIn.quoteAsk, &cmdOut.quoteResult); + if (rc != TPM_RC_SUCCESS) { + printf("TPM2_Quote failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + printf("TPM2_Quote: success\n"); + + rc = TPM2_ParseAttest(&cmdOut.quoteResult.quoted, &attestedData); + if (rc != TPM_RC_SUCCESS) { + printf("TPM2_Packet_ParseAttest failed 0x%x: %s\n", rc, + TPM2_GetRCString(rc)); + goto exit; + } + if (attestedData.magic != TPM_GENERATED_VALUE) { + printf("\tError, attested data not generated by the TPM = 0x%X\n", + attestedData.magic); + } + + printf("TPM with signature attests (type 0x%x):\n", attestedData.type); + printf("\tTPM signed %lu PCR\n", + (unsigned long)attestedData.attested.quote.pcrSelect.count); + +exit: + + /* Close session */ + if (sessionHandle != TPM_RH_NULL) { + cmdIn.flushCtx.flushHandle = sessionHandle; + TPM2_FlushContext(&cmdIn.flushCtx); + } + + /* Close key handles */ + wolfTPM2_UnloadHandle(&dev, &rsaKey.handle); + wolfTPM2_UnloadHandle(&dev, &storage.handle); + wolfTPM2_UnloadHandle(&dev, &endorse.handle); + + wolfTPM2_Cleanup(&dev); + return rc; +} + +/******************************************************************************/ +/* --- END TPM2.0 Quote Test -- */ +/******************************************************************************/ + + +#ifndef NO_MAIN_DRIVER +int main(void) +{ + int rc; + + rc = TPM2_Quote_Test(NULL); + + return rc; +} +#endif diff --git a/examples/pcr/quote.h b/examples/pcr/quote.h new file mode 100644 index 0000000..33b362e --- /dev/null +++ b/examples/pcr/quote.h @@ -0,0 +1,35 @@ +/* quote.h + * + * Copyright (C) 2006-2020 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-1301, USA + */ + +#ifndef _QUOTE_H_ +#define _QUOTE_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +int TPM2_Quote_Test(void* userCtx); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _quote_H_ */