wolfTPM/examples/timestamp/signed_timestamp.c

311 lines
11 KiB
C

/* signed_timestamp.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 use extended authorization sessions (TPM2.0) and
* generate a signed timestamp from the TPM using a Attestation Identity Key.
*/
#include <wolftpm/tpm2_wrap.h>
#ifndef WOLFTPM2_NO_WRAPPER
#include <examples/tpm_io.h>
#include <examples/tpm_test.h>
#include "signed_timestamp.h"
#include <stdio.h>
/******************************************************************************/
/* --- BEGIN TPM Timestamp Test -- */
/******************************************************************************/
int TPM2_Timestamp_Test(void* userCtx, int argc, char *argv[])
{
int rc;
WOLFTPM2_DEV dev;
TPMS_ATTEST attestedData;
#ifdef WOLFTPM_WINAPI
int tryNVkey = 0;
#else
int tryNVkey = 1;
#endif
union {
/* 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 {
ReadClock_Out readClock;
GetTime_Out getTime;
/* 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 */
(void)argc;
(void)argv;
XMEMSET(&endorse, 0, sizeof(endorse));
XMEMSET(&storage, 0, sizeof(storage));
XMEMSET(&rsaKey, 0, sizeof(rsaKey));
printf("TPM2 Demo of generating signed timestamp from the TPM\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");
/* ReadClock for quick test of the TPM communication */
XMEMSET(&cmdOut.readClock, 0, sizeof(cmdOut.readClock));
rc = TPM2_ReadClock(&cmdOut.readClock);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_ReadClock failed 0x%x: %s\n", rc,
TPM2_GetRCString(rc));
goto exit;
}
printf("TPM2_ReadClock: success\n");
/* 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 RSA Storage Key, also called SRK */
/* See if SRK already exists */
if (tryNVkey) {
rc = wolfTPM2_ReadPublicKey(&dev, &storage, TPM2_DEMO_STORAGE_KEY_HANDLE);
#ifdef TEST_WRAP_DELETE_KEY
if (rc == 0) {
storage.handle.hndl = TPM2_DEMO_STORAGE_KEY_HANDLE;
rc = wolfTPM2_NVDeleteKey(&dev, TPM_RH_OWNER, &storage);
if (rc != 0) goto exit;
rc = TPM_RC_HANDLE; /* mark handle as missing */
}
#endif
}
if (!tryNVkey || (tryNVkey && rc != 0)) {
/* Create primary storage key (RSA) */
rc = wolfTPM2_CreateSRK(&dev, &storage, TPM_ALG_RSA,
(byte*)gStorageKeyAuth, sizeof(gStorageKeyAuth)-1);
if (rc != 0) goto exit;
if (tryNVkey) {
/* Move storage key into persistent NV */
rc = wolfTPM2_NVStoreKey(&dev, TPM_RH_OWNER, &storage,
TPM2_DEMO_STORAGE_KEY_HANDLE);
if (rc != 0) {
wolfTPM2_UnloadHandle(&dev, &storage.handle);
goto exit;
}
}
printf("Created new RSA Primary Storage Key at 0x%x\n",
storage.handle.hndl);
}
else {
/* specify auth password for storage key */
storage.handle.auth.size = sizeof(gStorageKeyAuth)-1;
XMEMCPY(storage.handle.auth.buffer, gStorageKeyAuth,
storage.handle.auth.size);
}
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 PolicySecret for our session to enable use of the Endorsement Hierarchy */
XMEMSET(&cmdIn.policySecret, 0, sizeof(cmdIn.policySecret));
cmdIn.policySecret.authHandle = TPM_RH_ENDORSEMENT;
cmdIn.policySecret.policySession = sessionHandle;
rc = TPM2_PolicySecret(&cmdIn.policySecret, &cmdOut.policySecret);
if (rc != TPM_RC_SUCCESS) {
printf("policySecret failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
goto exit;
}
printf("TPM2_policySecret success\n"); /* No use of the output */
/* At this stage, the EK is created and NULL password has already been set
* The EH is enabled through policySecret over the active TPM session and
* the creation of Attestation Identity Key (AIK) under the EH can take place.
*/
/* Create an Attestation RSA key (AIK) */
rc = wolfTPM2_CreateAndLoadAIK(&dev, &rsaKey, TPM_ALG_RSA, &storage,
(const byte*)gAiKeyAuth, sizeof(gAiKeyAuth)-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 NULL password auth for using EK */
wolfTPM2_SetAuthPassword(&dev, 0, NULL);
/* set auth for using the AIK */
wolfTPM2_SetAuthHandle(&dev, 1, &rsaKey.handle);
/* At this stage: The EK is created, AIK is created and loaded,
* Endorsement Hierarchy is enabled through policySecret,
* the use of the loaded AIK is enabled through its usageAuth.
* Invoking attestation of the TPM time structure can take place.
*/
/* Get signed by the TPM timestamp using the AIK key */
rc = wolfTPM2_GetTime(&rsaKey, &cmdOut.getTime);
if (rc != TPM_RC_SUCCESS) {
printf("wolfTPM2_GetTime failed 0x%x: %s\n", rc,
TPM2_GetRCString(rc));
goto exit;
}
printf("wolfTPM2_GetTime: success\n");
rc = TPM2_ParseAttest(&cmdOut.getTime.timeInfo, &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);
/* time value in milliseconds that advances while the TPM is powered */
printf("\tTPM uptime since last power-up(in ms): %lu\n",
(unsigned long)attestedData.attested.time.time.time);
/* time value in milliseconds that advances while the TPM is powered */
printf("\tTPM clock, total time the TPM has been on(in ms): %lu\n",
(unsigned long)attestedData.attested.time.time.clockInfo.clock);
/* number of occurrences of TPM Reset since the last TPM2_Clear() */
printf("\tReset Count: %u\n",
attestedData.attested.time.time.clockInfo.resetCount);
/* number of times that TPM2_Shutdown() or _TPM_Hash_Start have occurred since the last TPM Reset or TPM2_Clear(). */
printf("\tRestart Count: %u\n",
attestedData.attested.time.time.clockInfo.restartCount);
/* This parameter is set to YES when the value reported in Clock is guaranteed to be unique for the current Owner */
printf("\tClock Safe: %u\n",
attestedData.attested.time.time.clockInfo.safe);
/* a TPM vendor-specific value indicating the version number of the firmware */
printf("\tFirmware Version(vendor specific): 0x%lX\n",
(unsigned long)attestedData.attested.time.firmwareVersion);
exit:
if (rc != 0) {
printf("Failure 0x%x: %s\n", rc, wolfTPM2_GetRCString(rc));
}
/* Close session */
if (sessionHandle != TPM_RH_NULL) {
cmdIn.flushCtx.flushHandle = sessionHandle;
TPM2_FlushContext(&cmdIn.flushCtx);
}
/* Close key handles */
if (!tryNVkey) {
wolfTPM2_UnloadHandle(&dev, &storage.handle);
}
wolfTPM2_UnloadHandle(&dev, &rsaKey.handle);
wolfTPM2_UnloadHandle(&dev, &endorse.handle);
wolfTPM2_Cleanup(&dev);
return rc;
}
/******************************************************************************/
/* --- END TPM Timestamp Test -- */
/******************************************************************************/
#endif /* !WOLFTPM2_NO_WRAPPER */
#ifndef NO_MAIN_DRIVER
int main(int argc, char *argv[])
{
int rc = -1;
#ifndef WOLFTPM2_NO_WRAPPER
rc = TPM2_Timestamp_Test(NULL, argc, argv);
#else
printf("Wrapper code not compiled in\n");
#endif /* !WOLFTPM2_NO_WRAPPER */
return rc;
}
#endif