181 lines
5.0 KiB
C
181 lines
5.0 KiB
C
/* tpm_handler.c
|
|
*
|
|
* Copyright (C) 2006-2025 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfBoot-Examples.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include "wolftpm/tpm2.h"
|
|
#include "wolftpm/tpm2_wrap.h"
|
|
#include "tpm_handler.h"
|
|
|
|
#define TPM2_DEMO_STORAGE_KEY_HANDLE 0x81000200
|
|
static const char gStorageKeyAuth[] = "ThisIsMyStorageKeyAuth";
|
|
static const char gAiKeyAuth[] = "ThisIsMyAiKeyAuth";
|
|
|
|
|
|
int getPrimaryStorageKey(WOLFTPM2_DEV *pDev, WOLFTPM2_KEY *pStorageKey)
|
|
{
|
|
int rc;
|
|
TPM_HANDLE handle = TPM2_DEMO_STORAGE_KEY_HANDLE;
|
|
|
|
rc = wolfTPM2_ReadPublicKey(pDev, pStorageKey, handle);
|
|
if (rc != 0)
|
|
{
|
|
/* Create primary storage key */
|
|
rc = wolfTPM2_CreateSRK(pDev, pStorageKey, TPM_ALG_RSA,
|
|
(byte *)gStorageKeyAuth, sizeof(gStorageKeyAuth) - 1);
|
|
}
|
|
else
|
|
{
|
|
/* specify auth password for storage key */
|
|
pStorageKey->handle.auth.size = sizeof(gStorageKeyAuth) - 1;
|
|
XMEMCPY(pStorageKey->handle.auth.buffer, gStorageKeyAuth,
|
|
pStorageKey->handle.auth.size);
|
|
}
|
|
|
|
if (rc != 0)
|
|
{
|
|
printf("Loading SRK: Storage failed\n");
|
|
}
|
|
else
|
|
{
|
|
printf("Loading SRK: Storage 0x%x (%d bytes)\n",
|
|
(word32)pStorageKey->handle.hndl, pStorageKey->pub.size);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int tpm_handler(void)
|
|
{
|
|
WOLFTPM2_DEV dev;
|
|
TPMS_ATTEST attestedData;
|
|
WOLFTPM2_CAPS caps;
|
|
WOLFTPM2_SESSION tpmSession;
|
|
TPMT_PUBLIC publicTemplate;
|
|
WOLFTPM2_KEY aikKey;
|
|
WOLFTPM2_KEY storage; /* SRK */
|
|
union
|
|
{
|
|
Quote_In quoteAsk;
|
|
byte maxInput[MAX_COMMAND_SIZE];
|
|
} cmdIn;
|
|
union
|
|
{
|
|
Quote_Out quoteResult;
|
|
byte maxOutput[MAX_RESPONSE_SIZE];
|
|
} cmdOut;
|
|
int rc;
|
|
|
|
printf("=== Attestation Test ===\n");
|
|
|
|
XMEMSET(&tpmSession, 0, sizeof(tpmSession));
|
|
XMEMSET(&storage, 0, sizeof(storage));
|
|
XMEMSET(&aikKey, 0, sizeof(aikKey));
|
|
|
|
rc = wolfTPM2_Init(&dev, NULL, NULL);
|
|
if (rc == 0)
|
|
{
|
|
/* Get device capabilities + options */
|
|
rc = wolfTPM2_GetCapabilities(&dev, &caps);
|
|
}
|
|
if (rc == 0)
|
|
{
|
|
printf("Mfg %s (%d), Vendor %s, Fw %u.%u (0x%x), "
|
|
"FIPS 140-2 %d, CC-EAL4 %d\n",
|
|
caps.mfgStr, caps.mfg, caps.vendorStr, caps.fwVerMajor,
|
|
caps.fwVerMinor, caps.fwVerVendor, caps.fips140_2, caps.cc_eal4);
|
|
}
|
|
else
|
|
{
|
|
printf("GetCapabilities failed\n");
|
|
return -1;
|
|
}
|
|
|
|
/* Generate or Read Storage Root Key */
|
|
rc = getPrimaryStorageKey(&dev, &storage);
|
|
|
|
if (rc == 0)
|
|
{
|
|
/* Generate AIK */
|
|
printf("Creating new key...\n");
|
|
rc = wolfTPM2_CreateAndLoadAIK(&dev, &aikKey, TPM_ALG_RSA,
|
|
&storage, (byte *)gAiKeyAuth, sizeof(gAiKeyAuth) - 1);
|
|
}
|
|
|
|
if (rc != TPM_RC_SUCCESS)
|
|
{
|
|
printf("wolfTPM2_CreateAndLoadAIK failed\n");
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
printf("New key created and loaded (pub %d bytes)\n",
|
|
aikKey.pub.size);
|
|
}
|
|
|
|
/* Set the handle of AIK */
|
|
wolfTPM2_SetAuthHandle(&dev, 0, &aikKey.handle);
|
|
|
|
/* Prepare Quote request */
|
|
XMEMSET(&cmdIn.quoteAsk, 0, sizeof(cmdIn.quoteAsk));
|
|
XMEMSET(&cmdOut.quoteResult, 0, sizeof(cmdOut.quoteResult));
|
|
cmdIn.quoteAsk.signHandle = aikKey.handle.hndl;
|
|
cmdIn.quoteAsk.inScheme.scheme = TPM_ALG_RSASSA;
|
|
cmdIn.quoteAsk.inScheme.details.any.hashAlg = TPM_ALG_SHA256;
|
|
cmdIn.quoteAsk.qualifyingData.size = 0; /* optional */
|
|
/* Choose PCR for signing */
|
|
TPM2_SetupPCRSel(&cmdIn.quoteAsk.PCRselect, TPM_ALG_SHA256, 16);
|
|
|
|
rc = TPM2_Quote(&cmdIn.quoteAsk, &cmdOut.quoteResult);
|
|
if (rc != TPM_RC_SUCCESS)
|
|
{
|
|
printf("TPM2_Quote failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
|
|
return -1;
|
|
}
|
|
printf("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));
|
|
return -1;
|
|
}
|
|
if (attestedData.magic != TPM_GENERATED_VALUE)
|
|
{
|
|
printf("\tError, attested data not generated by the TPM = 0x%X\n",
|
|
attestedData.magic);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
printf("TPM with signature attests (type 0x%x):\n", attestedData.type);
|
|
printf("\tTPM signed %lu count of PCRs\n",
|
|
(unsigned long)attestedData.attested.quote.pcrSelect.count);
|
|
#ifdef DEBUG_WOLFTPM
|
|
printf("\tPCR digest:\n");
|
|
TPM2_PrintBin(attestedData.attested.quote.pcrDigest.buffer,
|
|
attestedData.attested.quote.pcrDigest.size);
|
|
printf("\tTPM generated signature:\n");
|
|
TPM2_PrintBin(cmdOut.quoteResult.signature.signature.rsassa.sig.buffer,
|
|
cmdOut.quoteResult.signature.signature.rsassa.sig.size);
|
|
#endif
|
|
}
|
|
|
|
rc = wolfTPM2_Cleanup(&dev);
|
|
if (rc != TPM_RC_SUCCESS)
|
|
{
|
|
printf("Failed to clean up\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|