VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/Library/DcsTpmLib
diff options
context:
space:
mode:
authorkavsrf <kavsrf@gmail.com>2016-12-04 13:46:48 +0300
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2017-06-05 17:36:42 +0200
commit6701b862aa96775609a7d42662ae4a98e43071bb (patch)
tree3900fcd874625898d9ab921ec6f2e3f5f8ef4b97 /Library/DcsTpmLib
parentebe8c240166ef25ed0ca8898f8bfd34b415a75d0 (diff)
downloadVeraCrypt-DCS-6701b862aa96775609a7d42662ae4a98e43071bb.tar.gz
VeraCrypt-DCS-6701b862aa96775609a7d42662ae4a98e43071bb.zip
TPM12 support
Diffstat (limited to 'Library/DcsTpmLib')
-rw-r--r--Library/DcsTpmLib/DcsTpmLib.inf48
-rw-r--r--Library/DcsTpmLib/Tpm12.c1344
2 files changed, 1392 insertions, 0 deletions
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 <Library/CommonLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DcsTpmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseCryptLib.h>
+
+#include <IndustryStandard/Tpm12.h>
+#include <IndustryStandard/TcpaAcpi.h>
+#include <Library/Tpm12DeviceLib.h>
+#include <Protocol/TcgService.h>
+#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;
+}