wolfTPM/examples/tpm/tpm2_demo.c

265 lines
8.6 KiB
C

/* tpm2_demo.c
*
* Copyright (C) 2006-2017 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/tpm2.h>
#include <wolfssl/wolfcrypt/logging.h>
/* Local variables */
static TPM2_CTX gTpm2Ctx;
#ifdef WOLFSSL_STM32_CUBEMX
extern SPI_HandleTypeDef hspi1;
#define TPM2_USER_CTX &hspi1
#else
#define TPM2_USER_CTX NULL
#endif
/* IO Callback */
static TPM_RC TPM2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf,
word16 xferSz, void* userCtx)
{
#ifdef WOLFSSL_STM32_CUBEMX
SPI_HandleTypeDef* hspi = (SPI_HandleTypeDef*)userCtx;
HAL_StatusTypeDef status;
__HAL_SPI_ENABLE(hspi);
status = HAL_SPI_TransmitReceive(hspi, (byte*)txBuf, rxBuf, xferSz, 5000);
__HAL_SPI_DISABLE(hspi);
if (status == HAL_OK)
return TPM_RC_SUCCESS;
#else
/* TODO: Add your platform here for HW interface */
(void)ctx;
(void)txBuf;
(void)rxBuf;
(void)xferSz;
(void)userCtx;
#endif
return TPM_RC_FAILURE;
}
#define RAND_GET_SZ 32
int TPM2_Demo(void)
{
TPM_RC rc;
union {
Startup_In startup;
Shutdown_In shutdown;
SelfTest_In selfTest;
GetRandom_In getRand;
GetCapability_In cap;
IncrementalSelfTest_In incSelfTest;
PCR_Read_In pcrRead;
PCR_Extend_In pcrExtend;
CreatePrimary_In create;
EvictControl_In evict;
ReadPublic_In readPub;
StartAuthSession_In authSes;
Load_In load;
FlushContext_In flushCtx;
Unseal_In unseal;
byte maxInput[MAX_COMMAND_SIZE];
} cmdIn;
union {
GetCapability_Out cap;
GetRandom_Out getRand;
GetTestResult_Out tr;
IncrementalSelfTest_Out incSelfTest;
PCR_Read_Out pcrRead;
CreatePrimary_Out create;
ReadPublic_Out readPub;
StartAuthSession_Out authSes;
Load_Out load;
Unseal_Out unseal;
byte maxOutput[MAX_RESPONSE_SIZE];
} cmdOut;
int pcrCount, pcrIndex, i;
TPML_TAGGED_TPM_PROPERTY* tpmProp;
TPM_HANDLE ek;
#ifdef DEBUG_WOLFSSL
wolfSSL_Debugging_ON();
#endif
rc = TPM2_Init(&gTpm2Ctx, TPM2_IoCb, TPM2_USER_CTX);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_Init failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
cmdIn.startup.startupType = TPM_SU_CLEAR;
rc = TPM2_Startup(&cmdIn.startup);
if (rc != TPM_RC_SUCCESS &&
rc != TPM_RC_INITIALIZE /* TPM_RC_INITIALIZE = Already started */ ) {
printf("TPM2_Startup failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
printf("TPM2_Startup pass\n");
/* Full self test */
cmdIn.selfTest.fullTest = YES;
rc = TPM2_SelfTest(&cmdIn.selfTest);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_SelfTest failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
printf("TPM2_SelfTest pass\n");
/* Get Test Result */
rc = TPM2_GetTestResult(&cmdOut.tr);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_GetTestResult failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
printf("TPM2_GetTestResult: Size %d, Rc 0x%x\n", cmdOut.tr.outData.size,
cmdOut.tr.testResult);
WOLFSSL_BUFFER(cmdOut.tr.outData.buffer, cmdOut.tr.outData.size);
/* Incremental Test */
cmdIn.incSelfTest.toTest.count = 1;
cmdIn.incSelfTest.toTest.algorithms[0] = TPM_ALG_RSA;
rc = TPM2_IncrementalSelfTest(&cmdIn.incSelfTest, &cmdOut.incSelfTest);
printf("TPM2_IncrementalSelfTest: Rc 0x%x, Alg 0x%x (Todo %d)\n",
rc, cmdIn.incSelfTest.toTest.algorithms[0],
(int)cmdOut.incSelfTest.toDoList.count);
/* Get Capability for Property */
cmdIn.cap.capability = TPM_CAP_TPM_PROPERTIES;
cmdIn.cap.property = TPM_PT_FAMILY_INDICATOR;
cmdIn.cap.propertyCount = 1;
rc = TPM2_GetCapability(&cmdIn.cap, &cmdOut.cap);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_GetCapability failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
tpmProp = &cmdOut.cap.capabilityData.data.tpmProperties;
printf("TPM2_GetCapability: Property FamilyIndicator 0x%08x\n",
(unsigned int)tpmProp->tpmProperty[0].value);
cmdIn.cap.capability = TPM_CAP_TPM_PROPERTIES;
cmdIn.cap.property = TPM_PT_PCR_COUNT;
cmdIn.cap.propertyCount = 1;
rc = TPM2_GetCapability(&cmdIn.cap, &cmdOut.cap);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_GetCapability failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
tpmProp = &cmdOut.cap.capabilityData.data.tpmProperties;
pcrCount = tpmProp->tpmProperty[0].value;
printf("TPM2_GetCapability: Property PCR Count %d\n", pcrCount);
/* Random */
cmdIn.getRand.bytesRequested = RAND_GET_SZ;
rc = TPM2_GetRandom(&cmdIn.getRand, &cmdOut.getRand);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_GetRandom failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
if (cmdOut.getRand.randomBytes.size != RAND_GET_SZ) {
printf("TPM2_GetRandom length mismatch %d != %d\n",
cmdOut.getRand.randomBytes.size, RAND_GET_SZ);
return rc;
}
printf("TPM2_GetRandom: Got %d bytes\n", cmdOut.getRand.randomBytes.size);
WOLFSSL_BUFFER(cmdOut.getRand.randomBytes.buffer,
cmdOut.getRand.randomBytes.size);
/* PCR Read */
for (i=0; i<pcrCount; i++) {
pcrIndex = i;
TPM2_SetupPCRSel(&cmdIn.pcrRead.pcrSelectionIn, TPM_ALG_SHA256, pcrIndex);
rc = TPM2_PCR_Read(&cmdIn.pcrRead, &cmdOut.pcrRead);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_PCR_Read failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
printf("TPM2_PCR_Read: Index %d, Digest Sz %d, Update Counter %d\n",
pcrIndex,
(int)cmdOut.pcrRead.pcrValues.digests[0].size,
(int)cmdOut.pcrRead.pcrUpdateCounter);
WOLFSSL_BUFFER(cmdOut.pcrRead.pcrValues.digests[0].buffer,
cmdOut.pcrRead.pcrValues.digests[0].size);
}
/* PCR Extend and Verify */
pcrIndex = 0;
XMEMSET(&cmdIn.pcrExtend, 0, sizeof(cmdIn.pcrExtend));
cmdIn.pcrExtend.pcrHandle = pcrIndex;
cmdIn.pcrExtend.auth.sessionHandle = TPM_RS_PW;
cmdIn.pcrExtend.digests.count = 1;
cmdIn.pcrExtend.digests.digests[0].hashAlg = TPM_ALG_SHA256;
for (i=0; i<WC_SHA256_DIGEST_SIZE; i++) {
cmdIn.pcrExtend.digests.digests[0].digest.H[i] = i;
}
rc = TPM2_PCR_Extend(&cmdIn.pcrExtend);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_PCR_Extend failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
TPM2_SetupPCRSel(&cmdIn.pcrRead.pcrSelectionIn, TPM_ALG_SHA256, pcrIndex);
rc = TPM2_PCR_Read(&cmdIn.pcrRead, &cmdOut.pcrRead);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_PCR_Read failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
printf("TPM2_PCR_Read: Index %d, Digest Sz %d, Update Counter %d\n",
pcrIndex,
(int)cmdOut.pcrRead.pcrValues.digests[0].size,
(int)cmdOut.pcrRead.pcrUpdateCounter);
WOLFSSL_BUFFER(cmdOut.pcrRead.pcrValues.digests[0].buffer,
cmdOut.pcrRead.pcrValues.digests[0].size);
/* TODO: Add tests for API's */
//rc = TPM2_StartAuthSession(&cmdIn.authSes, &cmdOut.authSes);
//rc = TPM2_CreatePrimary(&cmdIn.create, &cmdOut.create);
//rc = TPM2_ReadPublic(&cmdIn.readPub, &cmdOut.readPub);
//TPM_RC TPM2_Load(Load_In* in, Load_Out* out);
//TPM_RC TPM2_FlushContext(FlushContext_In* in);
//TPM_RC TPM2_Unseal(Unseal_In* in, Unseal_Out* out);
/* Shutdown */
cmdIn.shutdown.shutdownType = TPM_SU_CLEAR;
rc = TPM2_Shutdown(&cmdIn.shutdown);
if (rc != TPM_RC_SUCCESS) {
printf("TPM2_Shutdown failed %d: %s\n", rc, TPM2_GetRCString(rc));
return rc;
}
return rc;
}