From 6701b862aa96775609a7d42662ae4a98e43071bb Mon Sep 17 00:00:00 2001 From: kavsrf Date: Sun, 4 Dec 2016 13:46:48 +0300 Subject: TPM12 support --- Library/DcsTpmLib/DcsTpmLib.inf | 48 ++ Library/DcsTpmLib/Tpm12.c | 1344 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 1392 insertions(+) create mode 100644 Library/DcsTpmLib/DcsTpmLib.inf create mode 100644 Library/DcsTpmLib/Tpm12.c (limited to 'Library/DcsTpmLib') diff --git a/Library/DcsTpmLib/DcsTpmLib.inf b/Library/DcsTpmLib/DcsTpmLib.inf new file mode 100644 index 0000000..79ea0f7 --- /dev/null +++ b/Library/DcsTpmLib/DcsTpmLib.inf @@ -0,0 +1,48 @@ +## @file +# TPM library +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DcsTpmLib + MODULE_UNI_FILE = DcsTpmLib.uni + FILE_GUID = D920E43F-730D-4C48-9BF6-5FA81C5F7697 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DcsTpmLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + Tpm12.c + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + SecurityPkg/SecurityPkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + PrintLib + Tpm12DeviceLib + BaseCryptLib + +[Protocols] + gEfiTcgProtocolGuid + +# [Guids] + diff --git a/Library/DcsTpmLib/Tpm12.c b/Library/DcsTpmLib/Tpm12.c new file mode 100644 index 0000000..502677b --- /dev/null +++ b/Library/DcsTpmLib/Tpm12.c @@ -0,0 +1,1344 @@ +/** @file +EFI TPM12 helpers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "Library/DcsCfgLib.h" + + +#define TPM_PREPARE Tpm12RequestUseTpm +#define TPM_TRANSMIT Tpm12SubmitCommand + +//#pragma warning(disable: 4706) + +extern EFI_TCG_PROTOCOL *mTcgProtocol; + +EFI_STATUS +InitTpm12() { + EFI_STATUS res = EFI_SUCCESS; + if (mTcgProtocol == NULL) { + return TPM_PREPARE(); + } + return res; +} + +typedef struct { + UINT8 *Cmd; + UINTN CmdPos; + UINTN CmdSize; + UINT8 *Resp; + UINTN RespPos; + UINTN RespSize; + UINT8 *Hash; +} DCS_TPM12IO; + +EFI_STATUS +Sha1Hash( + IN VOID *data, + IN UINTN dataSize, + OUT UINT8 *hash + ) +{ + UINTN ctxSize; + VOID *ctx; + ctxSize = Sha1GetContextSize(); + ctx = MEM_ALLOC(ctxSize); + if (ctx == NULL) return EFI_BUFFER_TOO_SMALL; + Sha1Init(ctx); + Sha1Update(ctx, data, dataSize); + if (!Sha1Final(ctx, hash)) return EFI_DEVICE_ERROR; + return EFI_SUCCESS; +} + +////////////////////////////////////////////////////////////////////////// +// TPM IO Create/ Free +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12IOCreate( + DCS_TPM12IO **tpmio, + UINTN cmdSize, + UINTN respSize) +{ + DCS_TPM12IO *io; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + io = *tpmio; + if (io == NULL) { + io = MEM_ALLOC(sizeof(*io)); + if (io == NULL) return EFI_BUFFER_TOO_SMALL; + } + if (io->CmdSize < cmdSize) { + MEM_FREE(io->Cmd); + io->Cmd = MEM_ALLOC(cmdSize); + if (io->Cmd == NULL) goto err; + } + io->CmdPos = 0; + io->CmdSize = cmdSize; + if (io->RespSize < respSize) { + MEM_FREE(io->Resp); + io->Resp = MEM_ALLOC(respSize); + if (io->Resp == NULL) goto err; + } + io->RespPos = 0; + io->RespSize = respSize; + if (io->Hash == NULL) { + UINTN sha1ctxsize; + sha1ctxsize = Sha1GetContextSize(); + io->Hash = MEM_ALLOC(sha1ctxsize); + if (io->Hash == NULL) goto err; + } + if(!Sha1Init(io->Hash)) goto err; + *tpmio = io; + return EFI_SUCCESS; +err: + MEM_FREE(io->Cmd); + MEM_FREE(io->Resp); + MEM_FREE(io->Hash); + MEM_FREE(io); + *tpmio = NULL; + return EFI_BUFFER_TOO_SMALL; +} + +VOID +Tpm12IOFree( + DCS_TPM12IO **tpmio) +{ + DCS_TPM12IO *io; + if (tpmio == NULL) return; + io = *tpmio; + if (io == NULL) return; + MEM_FREE(io->Cmd); + MEM_FREE(io->Resp); + MEM_FREE(io->Hash); + MEM_FREE(io); + *tpmio = NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Cmd init and write +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12IOUpdateCmdSize( + DCS_TPM12IO *tpmio) +{ + UINT32 *data; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + data = (UINT32*)&tpmio->Cmd[2]; + *data = SwapBytes32((UINT32)tpmio->CmdPos); + return EFI_SUCCESS; +} + +EFI_STATUS +Tpm12IOWrite16( + DCS_TPM12IO *tpmio, + UINT16 prm, + BOOLEAN hashIt) +{ + UINT16 *data; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->CmdPos + 2 >= tpmio->CmdSize) { + tpmio->CmdPos = tpmio->CmdSize; + return EFI_BUFFER_TOO_SMALL; + } + data = (UINT16*)&tpmio->Cmd[tpmio->CmdPos]; + *data = SwapBytes16(prm); + if(hashIt) { + Sha1Update(tpmio->Hash, data, 2); + } + tpmio->CmdPos += 2; + return Tpm12IOUpdateCmdSize(tpmio); +} + +EFI_STATUS +Tpm12IOWrite32( + DCS_TPM12IO *tpmio, + UINT32 prm, + BOOLEAN hashIt) +{ + UINT32 *data; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->CmdPos + 4 >= tpmio->CmdSize){ + tpmio->CmdPos = tpmio->CmdSize; + return EFI_BUFFER_TOO_SMALL; + } + data = (UINT32*)&tpmio->Cmd[tpmio->CmdPos]; + *data = SwapBytes32(prm); + if (hashIt) { + Sha1Update(tpmio->Hash, data, 4); + } + tpmio->CmdPos += 4; + return Tpm12IOUpdateCmdSize(tpmio); +} + +EFI_STATUS +Tpm12IOWriteBytes( + DCS_TPM12IO *tpmio, + VOID *prm, + UINTN prmSize, + BOOLEAN hashIt) +{ + UINT8 *data; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->CmdPos + prmSize >= tpmio->CmdSize) { + tpmio->CmdPos = tpmio->CmdSize; + return EFI_BUFFER_TOO_SMALL; + } + data = &tpmio->Cmd[tpmio->CmdPos]; + CopyMem(data, prm, prmSize); + if (hashIt) { + Sha1Update(tpmio->Hash, data, prmSize); + } + tpmio->CmdPos += prmSize; + return Tpm12IOUpdateCmdSize(tpmio); +} + +EFI_STATUS +Tpm12IOWrite8( + DCS_TPM12IO *tpmio, + UINT8 prm, + BOOLEAN hashIt) +{ + return Tpm12IOWriteBytes(tpmio, &prm, 1, hashIt); +} + +EFI_STATUS +Tpm12IOInit( + DCS_TPM12IO *tpmio, + UINT16 tag, + UINT32 ord) +{ + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + tpmio->CmdPos = 0; + ZeroMem(tpmio->Cmd, tpmio->CmdSize); + tpmio->RespPos = 0; + ZeroMem(tpmio->Resp, tpmio->RespSize); + Sha1Init(tpmio->Hash); + Tpm12IOWrite16(tpmio, tag, FALSE); + Tpm12IOWrite32(tpmio, 0, FALSE); + return Tpm12IOWrite32(tpmio, ord, TRUE); +} + + +////////////////////////////////////////////////////////////////////////// +// Read / Parse responces +////////////////////////////////////////////////////////////////////////// +UINT16 +Tpm12RespTag( + DCS_TPM12IO *tpmio) +{ + UINT16 *tag; + if (tpmio == NULL) return 0; + tag = (UINT16*)tpmio->Resp; + return SwapBytes16(*tag); +} + +UINT32 +Tpm12RespCode( + IN DCS_TPM12IO *tpmio + ) +{ + UINT32 *code; + if (tpmio == NULL) return 0; + code = (UINT32*)&tpmio->Resp[6]; + return SwapBytes32(*code); +} + +UINT32 +Tpm12RespSize( + IN DCS_TPM12IO *tpmio + ) +{ + UINT32 *size; + if (tpmio == NULL) return 0; + size = (UINT32*)&tpmio->Resp[2]; + return SwapBytes32(*size); +} + +UINT8* +Tpm12RespData( + IN DCS_TPM12IO *tpmio + ) +{ + if (tpmio == NULL) return NULL; + return &tpmio->Resp[10]; +} + +EFI_STATUS +Tpm12RespRead16( + IN DCS_TPM12IO *tpmio, + OUT UINT16 *data, + IN BOOLEAN hashIt + ) +{ + UINT16 *tmp; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if(tpmio->RespPos + 2 > tpmio->RespSize) return EFI_BUFFER_TOO_SMALL; + tmp = (UINT16 *)&tpmio->Resp[tpmio->RespPos]; + if (data != NULL) { + *data = SwapBytes16(*tmp); + } + if (hashIt) { + Sha1Update(tpmio->Hash, tmp, 2); + } + tpmio->RespPos += 2; + return EFI_SUCCESS; +} + +EFI_STATUS +Tpm12RespRead32( + IN DCS_TPM12IO *tpmio, + OUT UINT32 *data, + IN BOOLEAN hashIt + ) +{ + UINT32 *tmp; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->RespPos + 4 > tpmio->RespSize) return EFI_BUFFER_TOO_SMALL; + tmp = (UINT32 *)&tpmio->Resp[tpmio->RespPos]; + if (data != NULL) { + *data = SwapBytes32(*tmp); + } + if (hashIt) { + Sha1Update(tpmio->Hash, tmp, 4); + } + tpmio->RespPos += 4; + return EFI_SUCCESS; +} + +EFI_STATUS +Tpm12RespReadBytes( + IN DCS_TPM12IO *tpmio, + OUT VOID *data, + IN UINT32 dataSize, + IN BOOLEAN hashIt + ) +{ + UINT8 *tmp; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->RespPos + dataSize > tpmio->RespSize) return EFI_BUFFER_TOO_SMALL; + tmp = &tpmio->Resp[tpmio->RespPos]; + if (data != NULL) { + CopyMem(data, tmp, dataSize); + } + if (hashIt) { + Sha1Update(tpmio->Hash, tmp, dataSize); + } + tpmio->RespPos += dataSize; + return EFI_SUCCESS; +} + +VOID +Tpm12Parse16(UINT8** pos, UINT16 *data) { + if (data == NULL) { + data = (UINT16*)(*pos); + } + *data = SwapBytes16(*((UINT16*)(*pos))); + (*pos) += 2; +} + +VOID +Tpm12Parse32(UINT8** pos, UINT32 *data) { + if (data == NULL) { + data = (UINT32*)(*pos); + } + *data = SwapBytes32(*((UINT32*)(*pos))); + (*pos) += 4; +} + +VOID +Tpm12ParsePcrInfoShort(UINT8** pos, TPM_PCR_INFO_SHORT*data) { + if (data == NULL) { + data = (TPM_PCR_INFO_SHORT*)(*pos); + } + data->pcrSelection.sizeOfSelect = SwapBytes16(*((UINT16*)(*pos))); + (*pos) += data->pcrSelection.sizeOfSelect + 2 + 1 + 20; +} + +////////////////////////////////////////////////////////////////////////// +// Transmit command +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12Transmit( + DCS_TPM12IO *tpmio) +{ + UINT32 TpmRecvSize; + EFI_STATUS res; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->CmdPos >= tpmio->CmdSize) return EFI_BUFFER_TOO_SMALL; + TpmRecvSize = (UINT32)tpmio->RespSize; + res = TPM_TRANSMIT((UINT32)tpmio->CmdPos, tpmio->Cmd, &TpmRecvSize, tpmio->Resp); + if (EFI_ERROR(res)) { + return res; + } + if (Tpm12RespCode(tpmio) != TPM_SUCCESS) { + return EFI_DEVICE_ERROR; + } + Sha1Init(tpmio->Hash); // Init hash + tpmio->RespPos = 6; // Skip tag and size + Tpm12RespRead32(tpmio, NULL, TRUE); // Hash return code + Sha1Update(tpmio->Hash, tpmio->Cmd + 2, 4); // Hash ordinal + return res; +} + +////////////////////////////////////////////////////////////////////////// +// Global TPM12 I/O +////////////////////////////////////////////////////////////////////////// +DCS_TPM12IO *gTpm12Io = NULL; +EFI_STATUS +GetTpm12Io() +{ + EFI_STATUS res = EFI_SUCCESS; + if (gTpm12Io == NULL) { + res = Tpm12IOCreate(&gTpm12Io, 1024, 1024); + } + if (mTcgProtocol == NULL) { + return EFI_NOT_READY; + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// PCRs +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12Cmd_PcrRead( + DCS_TPM12IO *tpmio, + IN UINT32 PcrIndex + ) +{ + Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_PcrRead); + return Tpm12IOWrite32(tpmio, PcrIndex, TRUE); +} + +/** +Send PCR Read command to TPM1.2. + +@param PcrIndex The index of the PCR to read. +@param PcrValue The PCR value. + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +Tpm12PcrRead( + IN UINT32 PcrIndex, + OUT void *PcrValue + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_PcrRead(gTpm12Io, PcrIndex); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + Tpm12RespReadBytes(gTpm12Io, PcrValue, sizeof(TPM_PCRVALUE), TRUE); + return res; +} + +EFI_STATUS +Tpm12Cmd_PcrExtend( + DCS_TPM12IO *tpmio, + IN UINT32 PcrIndex, + IN UINTN dataSz, + IN VOID *data + ) +{ + TPM_DIGEST digest; + Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_Extend); + Sha1Hash(data, dataSz, (UINT8*)&digest); + Tpm12IOWrite32(tpmio, PcrIndex, TRUE); + return Tpm12IOWriteBytes(tpmio, &digest, sizeof(digest), TRUE); +} + +/** +Send PCR Extend command to TPM1.2. + +@param PcrIndex The index of the PCR to read. +@param dataSz size of data +@param data data. Extend PCR with Sha1(data) + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +Tpm12PcrExtend( + IN UINT32 PcrIndex, + IN UINTN dataSz, + IN VOID *data + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_PcrExtend(gTpm12Io, PcrIndex, dataSz, data); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + return res; +} + +EFI_STATUS +Tpm12PcrExtendAndLog( + IN UINT32 PcrIndex, + IN UINTN dataSz, + IN VOID *data + ) +{ + EFI_STATUS res = EFI_NOT_FOUND; + + /*TCG_PCR_EVENT_HDR TcgEvent; + TcgEvent->PCRIndex = PcrIndex; + TcgEvent->EventType = EventType; + TcgEvent->EventSize = LogLen; + CopyMem(&TcgEvent->Event[0], EventLog, LogLen); + EventNumber = 1; + Status = TcgProtocol->HashLogExtendEvent( + TcgProtocol, + (EFI_PHYSICAL_ADDRESS)(UINTN)HashData, + HashDataLen, + TPM_ALG_SHA, + TcgEvent, + &EventNumber, + &EventLogLastEntry + ); +// TcgEvent.PCRIndex = PcrIndex; +// TcgEvent.EventType = EV_EFI_VARIABLE_DRIVER_CONFIG; +// res = TpmMeasureAndLogData(PcrIndex, EV_EFI_VARIABLE_DRIVER_CONFIG, &TcgEvent, sizeof(TcgEvent), data, dataSz); +*/ + + return res; +} + +EFI_STATUS +Tpm12PcrsSave( + IN UINTN sPcr, + IN UINTN ePcr, + TPM_DIGEST *Pcrs + ) { + UINT32 i; + EFI_STATUS Status = EFI_SUCCESS; + for (i = (UINT32)sPcr; i <= (UINT32)ePcr; ++i) { + Status = Tpm12PcrRead(i, &Pcrs[i].digest); + if (EFI_ERROR(Status)) { + return Status; + } + } + return Status; +} + +EFI_STATUS +Tpm12PrintPCR( + IN UINT32 PcrIndex) +{ + TPM_PCRVALUE PcrValue; + EFI_STATUS Status; + OUT_PRINT(L"%HPCR%02d%N ", PcrIndex); + Status = Tpm12PcrRead(PcrIndex, &PcrValue); + if (EFI_ERROR(Status)) { + ERR_PRINT(L"%r(%x)\n", Status, Tpm12RespCode(gTpm12Io)); + return Status; + } + PrintBytes(PcrValue.digest, sizeof(PcrValue)); + OUT_PRINT(L"\n"); + return EFI_SUCCESS; +} + +EFI_STATUS +Tpm12DumpPcrs( + IN UINT32 sPcr, + IN UINT32 ePcr) +{ + UINT32 i; + EFI_STATUS Status = EFI_SUCCESS; + for (i = sPcr; i <= ePcr; ++i) { + Status = Tpm12PrintPCR(i); + if (EFI_ERROR(Status)) { + return Status; + } + } + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// Get Capability +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12Cmd_GetCapability( + DCS_TPM12IO *tpmio, + IN UINT32 capArea, + IN UINT32 subCapSize, + IN UINT8 *subCap + ) +{ + EFI_STATUS res; + Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_GetCapability); + Tpm12IOWrite32(tpmio, capArea, TRUE); + res = Tpm12IOWrite32(tpmio, subCapSize, TRUE); + if (subCapSize > 0) { + res = Tpm12IOWriteBytes(tpmio, subCap, subCapSize, TRUE); + } + return res; +} + +/** +Send GetCapability command to TPM1.2. + +@param capArea The index of the Capability +@param subCapSize The size of details. +@param subCap Details + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +EFIAPI +Tpm12GetCapability( + IN UINT32 capArea, + IN UINT32 subCapSize, + IN UINT8 *subCap, + OUT UINT32 *respSize, + OUT UINT8 *resp + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_GetCapability(gTpm12Io, capArea, subCapSize, subCap); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + res = Tpm12RespRead32(gTpm12Io, respSize, TRUE); + if (!EFI_ERROR(res)) { + res = Tpm12RespReadBytes(gTpm12Io, resp, *respSize, TRUE); + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// NV +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12GetNvList( + OUT UINT32 *respSize, + OUT UINT32 *resp + ) { + return Tpm12GetCapability(TPM_CAP_NV_LIST, 0, NULL, respSize, (UINT8*)resp); +} + +EFI_STATUS +Tpm12PcrsDigest( + IN UINT16 sizeOfSelect, + IN UINT8 *pcrSelect, + IN TPM_DIGEST *Pcrs, + OUT TPM_DIGEST *digest + ) +{ + UINTN Sha1CtxSize; + UINTN i; + UINTN j; + UINTN k; + VOID* Sha1Ctx; + UINT16 tmp16; + UINT32 tmp32; + + k = 0; + for (i = 0; i < sizeOfSelect; ++i) { + UINT8 tmp = pcrSelect[i]; + for (j = 0; j < 8; ++j) { + if ((tmp & 1) == 1) { + k++; + } + tmp >>= 1; + } + } + if (k == 0) return EFI_SUCCESS; + Sha1CtxSize = Sha1GetContextSize(); + Sha1Ctx = MEM_ALLOC(Sha1CtxSize); + if (Sha1Ctx == NULL) return EFI_BUFFER_TOO_SMALL; + Sha1Init(Sha1Ctx); + tmp16 = SwapBytes16(sizeOfSelect); + Sha1Update(Sha1Ctx, &tmp16, sizeof(tmp16)); + Sha1Update(Sha1Ctx, pcrSelect, sizeOfSelect); + + tmp32 = SwapBytes32((UINT32)(k * sizeof(TPM_DIGEST))); + Sha1Update(Sha1Ctx, &tmp32, sizeof(tmp32)); + k = 0; + for (i = 0; i < sizeOfSelect; ++i) { + UINT8 tmp = pcrSelect[i]; + for (j = 0; j < 8; ++j) { + if ((tmp & 1) == 1) { + Sha1Update(Sha1Ctx, &Pcrs[k], sizeof(TPM_DIGEST)); + } + tmp >>= 1; + k++; + } + } + if (Sha1Final(Sha1Ctx, digest->digest)) return EFI_SUCCESS; + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +Tpm12NvDetails( + IN UINT32 index, + OUT UINT32 *attr, + OUT UINT32 *dataSz, + OUT UINT32 *pcrR, + OUT UINT32 *pcrW + ) +{ + EFI_STATUS res; + TPM_PCR_INFO_SHORT* pcrRead; + TPM_PCR_INFO_SHORT* pcrWrite; + UINT8 nvdata[sizeof(TPM_NV_DATA_PUBLIC) + 256]; + UINT8* pos = nvdata; + UINT32 sz = sizeof(nvdata); + UINT32 swapindex = SwapBytes32(index); + res = Tpm12GetCapability(TPM_CAP_NV_INDEX, 4, (UINT8*)&swapindex, &sz, nvdata); + if(EFI_ERROR(res)) return res; + Tpm12Parse16(&pos, NULL); + Tpm12Parse32(&pos, &index); + pcrRead = (TPM_PCR_INFO_SHORT*)pos; + Tpm12ParsePcrInfoShort(&pos, NULL); + pcrWrite = (TPM_PCR_INFO_SHORT*)pos; + Tpm12ParsePcrInfoShort(&pos, NULL); + Tpm12Parse16(&pos, NULL); + Tpm12Parse32(&pos, attr); + pos += 3; + Tpm12Parse32(&pos, dataSz); + if (pcrR != NULL) { + *pcrR = pcrRead->pcrSelection.pcrSelect[0]; + *pcrR |= pcrRead->pcrSelection.sizeOfSelect > 1 ? pcrRead->pcrSelection.pcrSelect[1] << 8 : 0; + *pcrR |= pcrRead->pcrSelection.sizeOfSelect > 2 ? pcrRead->pcrSelection.pcrSelect[2] << 16 : 0; + *pcrR |= pcrRead->pcrSelection.sizeOfSelect > 3 ? pcrRead->pcrSelection.pcrSelect[3] << 24 : 0; + } + if (pcrW != NULL) { + *pcrW = pcrWrite->pcrSelection.pcrSelect[0]; + *pcrW |= pcrWrite->pcrSelection.sizeOfSelect > 1 ? pcrWrite->pcrSelection.pcrSelect[1] << 8 : 0; + *pcrW |= pcrWrite->pcrSelection.sizeOfSelect > 2 ? pcrWrite->pcrSelection.pcrSelect[2] << 16 : 0; + *pcrW |= pcrWrite->pcrSelection.sizeOfSelect > 3 ? pcrWrite->pcrSelection.pcrSelect[3] << 24 : 0; + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// OSAP +////////////////////////////////////////////////////////////////////////// +#pragma pack(1) +typedef struct { + TPM_NONCE nonceOdd; + TPM_NONCE nonceOddOSAP; + TPM_NONCE nonceEven; + TPM_NONCE nonceEvenOSAP; + TPM_DIGEST SharedSecret; + TPM_AUTHHANDLE authHandle; +} TPM12_OSAP; +#pragma pack() + +EFI_STATUS +Tpm12Cmd_OSAP( + IN DCS_TPM12IO *tpmio, + IN TPM12_OSAP *osap, + IN UINT16 entityType, + IN UINT32 entityValue + ) +{ + EFI_STATUS res; + Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP); + res = Tpm12IOWrite16(tpmio, entityType, TRUE); + res = Tpm12IOWrite32(tpmio, entityValue, TRUE); + res = Tpm12IOWriteBytes(tpmio, &osap->nonceOddOSAP, sizeof(osap->nonceOddOSAP), TRUE); + return res; +} + +TPM12_OSAP *gTpm12Osap; + +EFI_STATUS +Tpm12OSAPStart( + IN UINT16 entityType, + IN UINT32 entityValue, + IN CHAR16 *ownerPass + ) +{ + EFI_STATUS res; + TPM_DIGEST ownerKey; + UINTN CtxSize; + VOID* HmacCtx; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + if (gTpm12Osap == NULL) { + gTpm12Osap = MEM_ALLOC(sizeof(TPM12_OSAP)); + } + res = Tpm12Cmd_OSAP(gTpm12Io, gTpm12Osap, entityType, entityValue); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + Tpm12RespRead32(gTpm12Io, &gTpm12Osap->authHandle, FALSE); + Tpm12RespReadBytes(gTpm12Io, &gTpm12Osap->nonceEven, sizeof(TPM_NONCE), FALSE); + res = Tpm12RespReadBytes(gTpm12Io, &gTpm12Osap->nonceEvenOSAP, sizeof(TPM_NONCE), FALSE); + if (EFI_ERROR(res)) return res; + Sha1Hash(ownerPass, StrLen(ownerPass) * 2, (UINT8*)&ownerKey); + CtxSize = HmacSha1GetContextSize(); + HmacCtx = MEM_ALLOC(CtxSize); + HmacSha1Init(HmacCtx, (UINT8*)&ownerKey, sizeof(ownerKey)); + HmacSha1Update(HmacCtx, &gTpm12Osap->nonceEvenOSAP, sizeof(gTpm12Osap->nonceEvenOSAP)); + HmacSha1Update(HmacCtx, &gTpm12Osap->nonceOddOSAP, sizeof(gTpm12Osap->nonceOddOSAP)); + HmacSha1Final(HmacCtx, (UINT8*)&gTpm12Osap->SharedSecret); + MEM_FREE(HmacCtx); + return res; +} + +EFI_STATUS +Tpm12OSAPAppend( + IN UINT8 continueSession + ) +{ + EFI_STATUS res; + UINTN CtxSize; + VOID* HmacCtx; + TPM_DIGEST hashCmd; + TPM_DIGEST auth; + + Tpm12IOWrite32(gTpm12Io, gTpm12Osap->authHandle, FALSE); + Tpm12IOWriteBytes(gTpm12Io, &gTpm12Osap->nonceOdd, sizeof(gTpm12Osap->nonceOdd), FALSE); + res = Tpm12IOWrite8(gTpm12Io, continueSession, FALSE); + *((UINT16*)gTpm12Io->Cmd) = SwapBytes16(TPM_TAG_RQU_AUTH1_COMMAND); // Update Tag + Sha1Final(gTpm12Io->Hash, (UINT8*)&hashCmd); + CtxSize = HmacSha1GetContextSize(); + HmacCtx = MEM_ALLOC(CtxSize); + if (HmacCtx == NULL) return EFI_BUFFER_TOO_SMALL; + HmacSha1Init(HmacCtx, (UINT8*)&gTpm12Osap->SharedSecret, sizeof(gTpm12Osap->SharedSecret)); + HmacSha1Update(HmacCtx, &hashCmd, sizeof(hashCmd)); + HmacSha1Update(HmacCtx, &gTpm12Osap->nonceEven, sizeof(gTpm12Osap->nonceEven)); + HmacSha1Update(HmacCtx, &gTpm12Osap->nonceOdd, sizeof(gTpm12Osap->nonceOdd)); + HmacSha1Update(HmacCtx, &continueSession, sizeof(continueSession)); + HmacSha1Final(HmacCtx, (UINT8*)&auth); + MEM_FREE(HmacCtx); + res = Tpm12IOWriteBytes(gTpm12Io, &auth, sizeof(auth), FALSE); + return res; +} + +////////////////////////////////////////////////////////////////////////// +// NV +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12WritePcrInfo( + IN DCS_TPM12IO *tpmio, + IN UINT16 sizeOfSelect, + IN UINT8 *pcrSelect, + IN UINT8 localityAtRelease, + IN TPM_DIGEST* pcrs) +{ + TPM_DIGEST digestAtRelease; + ZeroMem(&digestAtRelease, sizeof(digestAtRelease)); + Tpm12IOWrite16 (tpmio, sizeOfSelect, TRUE); + Tpm12IOWriteBytes(tpmio, pcrSelect, sizeOfSelect, TRUE); + Tpm12IOWrite8(tpmio, localityAtRelease, TRUE); + Tpm12PcrsDigest(sizeOfSelect, pcrSelect, pcrs, &digestAtRelease); + return Tpm12IOWriteBytes(tpmio, &digestAtRelease, sizeof(TPM_DIGEST), TRUE); +} + +TPM_DIGEST gTpm12Pcrs[24]; +TPM_DIGEST gTpm12OwnerPass; + +VOID +PcrUpdateMask( + UINT32 mask, + UINT8 *pcr) +{ + pcr[0] = (UINT8)(mask & 0xFF); + pcr[1] = (UINT8)((mask >> 8) & 0xFF); + pcr[2] = (UINT8)((mask >> 16) & 0xFF); +} + +EFI_STATUS +Tpm12NvSpace( + IN UINT32 index, + IN UINT32 size, + IN CHAR16 *ownerPass, + TPM_DIGEST *pcrs, + IN UINT32 pcrReadMask, + IN UINT32 pcrWriteMask, + IN UINT32 Attributes, + IN UINT8 bReadSTClear, + IN UINT8 bWriteSTClear, + IN UINT8 bWriteDefine + ) { + EFI_STATUS res; + TPM_DIGEST encAuth; + UINT8 pcrRead[3]; + UINT8 pcrWrite[3]; + + PcrUpdateMask(pcrReadMask, pcrRead); + PcrUpdateMask(pcrWriteMask, pcrWrite); + SetMem(&encAuth, sizeof(encAuth), 0xEA); // No Auth + + res = Tpm12OSAPStart(TPM_ET_OWNER, TPM_KH_OWNER, ownerPass); + if (EFI_ERROR(res)) { + return res; + } + Tpm12IOInit(gTpm12Io, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_NV_DefineSpace); + // NV_DATA_PUBLIC + Tpm12IOWrite16(gTpm12Io, TPM_TAG_NV_DATA_PUBLIC, TRUE); + Tpm12IOWrite32(gTpm12Io, index, TRUE); + Tpm12WritePcrInfo(gTpm12Io, sizeof(pcrRead) , pcrRead, 0x1F, pcrs); + Tpm12WritePcrInfo(gTpm12Io, sizeof(pcrWrite), pcrWrite, 0x1F, pcrs); + Tpm12IOWrite16(gTpm12Io, TPM_TAG_NV_ATTRIBUTES, TRUE); + Tpm12IOWrite32(gTpm12Io, Attributes, TRUE); + Tpm12IOWrite8(gTpm12Io, bReadSTClear, TRUE); + Tpm12IOWrite8(gTpm12Io, bWriteSTClear, TRUE); + Tpm12IOWrite8(gTpm12Io, bWriteDefine, TRUE); + Tpm12IOWrite32(gTpm12Io, size, TRUE); + // + Tpm12IOWriteBytes(gTpm12Io, &encAuth, sizeof(encAuth), TRUE); + // OSAP + Tpm12OSAPAppend(0); + + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + return res; +} + +EFI_STATUS +Tpm12Cmd_NvRead( + IN DCS_TPM12IO *tpmio, + IN TPM_NV_INDEX NvIndex, + IN UINT32 Offset, + IN UINT32 DataSize + ) +{ + EFI_STATUS res; + CE(Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_NV_ReadValue)); + CE(Tpm12IOWrite32(tpmio, NvIndex, TRUE)); + CE(Tpm12IOWrite32(tpmio, Offset, TRUE)); + CE(Tpm12IOWrite32(tpmio, DataSize, TRUE)); +err: + return res; +} + +/** +Send NV ReadValue command to TPM1.2. + +@param NvIndex The index of the area to set. +@param Offset The offset into the area. +@param DataSize The size of the data area. +@param Data The data to set the area to. + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +Tpm12NvRead( + IN TPM_NV_INDEX NvIndex, + IN UINT32 Offset, + IN OUT UINT32 *DataSize, + OUT UINT8 *Data + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_NvRead(gTpm12Io, NvIndex,Offset,*DataSize); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + res = Tpm12RespRead32(gTpm12Io, DataSize, TRUE); + if (!EFI_ERROR(res)) { + res = Tpm12RespReadBytes(gTpm12Io, Data, *DataSize, TRUE); + } + return res; +} + +EFI_STATUS +Tpm12Cmd_NvWrite( + IN DCS_TPM12IO *tpmio, + IN TPM_NV_INDEX NvIndex, + IN UINT32 Offset, + IN UINT32 DataSize, + IN UINT8 *Data + ) +{ + EFI_STATUS res; + CE(Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_NV_WriteValue)); + CE(Tpm12IOWrite32(tpmio, NvIndex, TRUE)); + CE(Tpm12IOWrite32(tpmio, Offset, TRUE)); + CE(Tpm12IOWrite32(tpmio, DataSize, TRUE)); + CE(Tpm12IOWriteBytes(tpmio, Data, DataSize, TRUE)); +err: + return res; +} + +/** +Send NV WriteValue command to TPM1.2. + +@param NvIndex The index of the area to set. +@param Offset The offset into the NV Area. +@param DataSize The size of the data parameter. +@param Data The data to set the area to. + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +EFIAPI +Tpm12NvWrite( + IN TPM_NV_INDEX NvIndex, + IN UINT32 Offset, + IN UINT32 DataSize, + IN UINT8 *Data, + CHAR16 *ownerPass + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12OSAPStart(TPM_ET_OWNER, TPM_KH_OWNER, ownerPass); + if (EFI_ERROR(res)) { + return res; + } + res = Tpm12Cmd_NvWrite(gTpm12Io, NvIndex, Offset, DataSize, Data); + if (EFI_ERROR(res)) return res; + // OSAP + Tpm12OSAPAppend(0); + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + return res; +} + +/* +EFI_STATUS +Tpm12NvDefine( + IN UINT32 index, + IN UINT32 size, + IN CHAR16 *ownerPass) { + EFI_STATUS res; +// UINT32 sz = 20; +// UINT8 data[20]; +// UINT8 dataR[20]; +// SetMem(data, 20, 1); +// +// CE(Tpm12PcrsSave(0, 23, gTpm12Pcrs)); +// CE(Tpm12NvSpace(index, size, ownerPass, gTpm12Pcrs, 0x100, 0, 0x2, 0, 0, 0)); +// CE(Tpm12NvWrite(index,0,size, data, ownerPass)); +// CE(Tpm12NvRead(index, 0, &sz, dataR)); + CE(GetTpm()); + if (gRnd == NULL) { + RndInit() + } + return res; +err: + ERR_PRINT(L"%r(%x),line %d\n", res, Tpm12RespCode(gTpm12Io), gCELine); + return res; +}*/ + +////////////////////////////////////////////////////////////////////////// +// Random +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12Cmd_GetRandom( + IN DCS_TPM12IO *tpmio, + IN UINT32 DataSize + ) +{ + EFI_STATUS res; + CE(Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_GetRandom)); + CE(Tpm12IOWrite32(tpmio, DataSize, TRUE)); +err: + return res; +} + +EFI_STATUS +Tpm12GetRandom( + IN OUT UINT32 *DataSize, + OUT UINT8 *Data + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_GetRandom(gTpm12Io, *DataSize); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + res = Tpm12RespRead32(gTpm12Io, DataSize, TRUE); + if (!EFI_ERROR(res)) { + res = Tpm12RespReadBytes(gTpm12Io, Data, *DataSize, TRUE); + } + return res; +} +////////////////////////////////////////////////////////////////////////// +// Protocol +////////////////////////////////////////////////////////////////////////// +#define DCS_TPM_NV_INDEX 0x0DC5B +#define DCS_TPM_NV_SIZE 128 +#define DCS_TPM_PCR_LOCK 8 + +typedef struct _Password Password; + +extern VOID +ApplyKeyFile( + IN OUT Password* password, + IN CHAR8* keyfileData, + IN UINTN keyfileDataSize + ); + +EFI_STATUS +DcsTpm12Lock( + DCS_TPM_PROTOCOL *tpm + ) +{ + UINT32 lock = 1; + return Tpm12PcrExtend(DCS_TPM_PCR_LOCK, sizeof(lock), &lock); +} + +EFI_STATUS +DcsTpm12Apply( + DCS_TPM_PROTOCOL *tpm, + OUT VOID* pwd + ) +{ + EFI_STATUS res; + UINT32 sz = DCS_TPM_NV_SIZE; + CHAR8 data[DCS_TPM_NV_SIZE]; + res = Tpm12NvRead(DCS_TPM_NV_INDEX, 0, &sz, data); + if (EFI_ERROR(res)) return res; + ApplyKeyFile(pwd, data, DCS_TPM_NV_SIZE); + ZeroMem(data, DCS_TPM_NV_SIZE); + return EFI_SUCCESS; +} + +BOOLEAN +DcsTpm12IsOpen( + DCS_TPM_PROTOCOL *tpm + ) +{ + EFI_STATUS res; + UINT32 sz = DCS_TPM_NV_SIZE; + UINT8 data[DCS_TPM_NV_SIZE]; + res = Tpm12NvRead(DCS_TPM_NV_INDEX, 0, &sz, data); + if (EFI_ERROR(res)) return FALSE; + ZeroMem(data, DCS_TPM_NV_SIZE); + return TRUE; +} + +BOOLEAN +DcsTpm12IsConfigured( + DCS_TPM_PROTOCOL *tpm + ) +{ + EFI_STATUS res; + UINT32 dataSz; + UINT32 attr; + UINT32 pcrR; + UINT32 pcrW; + res = Tpm12NvDetails(DCS_TPM_NV_INDEX, &attr, &dataSz, &pcrR, &pcrW); + if (EFI_ERROR(res)) return FALSE; + if (dataSz != DCS_TPM_NV_SIZE) return FALSE; + return TRUE; +} + +#define TPM_OWNER_PWD_MAX 64 +VOID +AskTpmOwnerPwd( + OUT CHAR16* ownerPass + ) { + UINTN ownerPassLen; + OUT_PRINT(L"TPM owner password:"); + ZeroMem(ownerPass, TPM_OWNER_PWD_MAX * 2); + GetLine(&ownerPassLen, ownerPass, NULL, TPM_OWNER_PWD_MAX - 1, FALSE); +} + +UINT32 +AskPcrsMask( + IN UINT32 def + ) +{ + OUT_PRINT(L"PCR selection bits(hex):\n\ + 1 BIOS 2 BIOS data 4 EFI drivers\n\ + 8 EFI variables 10 EFI boot loader 20 EFI boot loader data\n\ +40 Boot event 80 Manufacture 100 DcsProp\n"); + return (UINT32)AskHexUINT64("PCRs mask:", def); +} + +EFI_STATUS +ActionTpm12Update( + IN VOID *ctx + ) +{ + EFI_STATUS res; + CHAR16 ownerPass[TPM_OWNER_PWD_MAX]; + UINT32 pcrMask; + UINT8 data[DCS_TPM_NV_SIZE]; + ZeroMem(data, DCS_TPM_NV_SIZE); + CE(Tpm12PcrsSave(0, 23, gTpm12Pcrs)); + AskTpmOwnerPwd(ownerPass); + pcrMask = AskPcrsMask(0x137); + CE(Tpm12NvSpace(DCS_TPM_NV_INDEX, DCS_TPM_NV_SIZE, ownerPass, gTpm12Pcrs, pcrMask, 0, 0x2, 0, 0, 0)); + CE(gRnd == NULL ? EFI_NOT_READY : EFI_SUCCESS); + CE(gRnd->GetBytes(gRnd, data, sizeof(data))); + CE(Tpm12NvWrite(DCS_TPM_NV_INDEX, 0, DCS_TPM_NV_SIZE, data, ownerPass)); +err: + return res; +} + +EFI_STATUS +ActionTpm12Clean( + IN VOID *ctx + ) +{ + EFI_STATUS res; + CHAR16 ownerPass[TPM_OWNER_PWD_MAX]; + AskTpmOwnerPwd(ownerPass); + CE(Tpm12NvSpace(DCS_TPM_NV_INDEX, 0, ownerPass, gTpm12Pcrs, 0, 0, 0x2, 0, 0, 0)); +err: + return res; +} + +EFI_STATUS +ActionTpm12PrintPcrs( + IN VOID *ctx + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN i; + UINT32 pcrMask = 0x1FF; + UINT32 tmp; + Tpm12NvDetails(DCS_TPM_NV_INDEX, NULL, NULL, &pcrMask, NULL); + pcrMask = AskPcrsMask(pcrMask); + tmp = pcrMask; + for (i = 0; i < 32; ++i) { + if ((tmp & 1) == 1) { + Tpm12PrintPCR((UINT32)i); + } + tmp >>= 1; + } + return res; +} + +PMENU_ITEM gTpmMenu = NULL; +BOOLEAN gTpmMenuContinue = TRUE; + +EFI_STATUS +ActionTpmExit( + IN VOID *ctx + ) +{ + gTpmMenuContinue = FALSE; + return EFI_SUCCESS; +} + + +EFI_STATUS +DcsTpm12Configure( + IN DCS_TPM_PROTOCOL* tpm + ) { + PMENU_ITEM item = NULL; + EFI_STATUS res; + item = DcsMenuAppend(item, L"Update TPM secret", 'u', ActionTpm12Update, NULL); + gTpmMenu = item; + item = DcsMenuAppend(item, L"Delete TPM secret", 'd', ActionTpm12Clean, NULL); + item = DcsMenuAppend(item, L"Print PCRs", 'p', ActionTpm12PrintPcrs, NULL); + item = DcsMenuAppend(item, L"Exit", 'e', ActionTpmExit, NULL); + do { + EFI_INPUT_KEY key; + OUT_PRINT(L"TPM "); + if (tpm->IsConfigured(tpm)) { + OUT_PRINT(L"%Vconfigured%N, "); + if (tpm->IsOpen(tpm)) { + OUT_PRINT(L"%Vopen%N"); + } + else { + ERR_PRINT(L"locked"); + } + } + else { + ERR_PRINT(L"not configured"); + } + OUT_PRINT(L"\n"); + DcsMenuPrint(gTpmMenu); + item = NULL; + key.UnicodeChar = 0; + while (item == NULL) { + item = gTpmMenu; + key = GetKey(); + while (item != NULL) { + if (item->Select == key.UnicodeChar) break; + item = item->Next; + } + } + OUT_PRINT(L"%c\n", key.UnicodeChar); + res = item->Action(item->Context); + if (EFI_ERROR(res)) { + ERR_PRINT(L"%r(%x),line %d\n", res, Tpm12RespCode(gTpm12Io), gCELine); + } + } while (gTpmMenuContinue); + return EFI_SUCCESS; +} + +DCS_TPM_PROTOCOL* gTpm = (DCS_TPM_PROTOCOL*)NULL; + +EFI_STATUS +GetTpm() { + EFI_STATUS res; + res = InitTpm12(); + if (EFI_ERROR(res)) { + return res; + } + gTpm = (DCS_TPM_PROTOCOL*)MEM_ALLOC(sizeof(DCS_TPM_PROTOCOL)); + if (gTpm == NULL) return EFI_BUFFER_TOO_SMALL; + gTpm->IsConfigured = DcsTpm12IsConfigured; + gTpm->IsOpen = DcsTpm12IsOpen; + gTpm->Configure = DcsTpm12Configure; + gTpm->Apply = DcsTpm12Apply; + gTpm->Lock = DcsTpm12Lock; + return EFI_SUCCESS; +} + +EFI_STATUS +TpmMeasure( + IN VOID* data, + IN UINTN dataSz + ) { + EFI_STATUS res; + TPM_DIGEST hash; + CE(Sha1Hash(data, dataSz, (UINT8*)&hash)); + CE(Tpm12PcrExtend(DCS_TPM_PCR_LOCK, sizeof(hash), &hash)); + +err: + return res; +} -- cgit v1.2.3