[Skiboot] [PATCH 09/15] libstb: Add TSS and EventLogMgr for TPM 2.0
Claudio Carvalho
cclaudio at linux.vnet.ibm.com
Thu Aug 11 15:23:51 AEST 2016
TSS and EventLogMgr are hostboot implementations, but their source code are
shared with skiboot and phyp. The files tss/trustedbootUtils.* are not
from hostboot.
This adds both TSS and EventLogMgr with a few modifications. This initial
version supports multibank. The PCR extend operation extends measurements
to both sha1 and sha256 banks in a single operation, and the event recorded
in the event log includes both sha1 and sha256 measurements.
For more information please refer to 'doc/stb.txt'
Signed-off-by: Claudio Carvalho <cclaudio at linux.vnet.ibm.com>
---
libstb/Makefile.inc | 4 +-
libstb/tpm.h | 48 ++
libstb/tss/Makefile.inc | 13 +
libstb/tss/tpmLogMgr.C | 563 +++++++++++++++++++
libstb/tss/tpmLogMgr.H | 248 +++++++++
libstb/tss/trustedTypes.C | 926 +++++++++++++++++++++++++++++++
libstb/tss/trustedTypes.H | 470 ++++++++++++++++
libstb/tss/trustedbootCmds.C | 1016 ++++++++++++++++++++++++++++++++++
libstb/tss/trustedbootCmds.H | 177 ++++++
libstb/tss/trustedbootUtils.C | 22 +
libstb/tss/trustedbootUtils.H | 85 +++
libstb/tss/trustedboot_reasoncodes.H | 88 +++
12 files changed, 3659 insertions(+), 1 deletion(-)
create mode 100644 libstb/tpm.h
create mode 100644 libstb/tss/Makefile.inc
create mode 100644 libstb/tss/tpmLogMgr.C
create mode 100644 libstb/tss/tpmLogMgr.H
create mode 100644 libstb/tss/trustedTypes.C
create mode 100644 libstb/tss/trustedTypes.H
create mode 100644 libstb/tss/trustedbootCmds.C
create mode 100644 libstb/tss/trustedbootCmds.H
create mode 100644 libstb/tss/trustedbootUtils.C
create mode 100644 libstb/tss/trustedbootUtils.H
create mode 100644 libstb/tss/trustedboot_reasoncodes.H
diff --git a/libstb/Makefile.inc b/libstb/Makefile.inc
index 15cdfbe..642269f 100644
--- a/libstb/Makefile.inc
+++ b/libstb/Makefile.inc
@@ -8,4 +8,6 @@ LIBSTB_SRCS = container.c
LIBSTB_OBJS = $(LIBSTB_SRCS:%.c=%.o)
LIBSTB = $(LIBSTB_DIR)/built-in.o
-$(LIBSTB): $(LIBSTB_OBJS:%=$(LIBSTB_DIR)/%)
+include $(SRC)/$(LIBSTB_DIR)/tss/Makefile.inc
+
+$(LIBSTB): $(LIBSTB_OBJS:%=$(LIBSTB_DIR)/%) $(TSS)
diff --git a/libstb/tpm.h b/libstb/tpm.h
new file mode 100644
index 0000000..546458e
--- /dev/null
+++ b/libstb/tpm.h
@@ -0,0 +1,48 @@
+/* Copyright 2013-2016 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TPM_H
+#define __TPM_H
+
+#include <device.h>
+
+#include "tss/tpmLogMgr.H"
+#include "tss/trustedTypes.H"
+
+struct tpm_dev {
+ int bus_id;
+ int xscom_base;
+};
+
+struct tpm_driver {
+ const char* name;
+ int (*transmit)(struct tpm_dev *dev, uint8_t* buf, size_t cmdlen,
+ size_t *buflen);
+};
+
+struct tpm_chip {
+ int id;
+ bool enabled;
+ struct dt_node *node;
+ struct _TpmLogMgr logmgr;
+ struct tpm_dev *dev;
+ struct tpm_driver *driver;
+ struct list_node link;
+};
+
+typedef struct tpm_chip TpmTarget;
+
+#endif /* __TPM_H */
diff --git a/libstb/tss/Makefile.inc b/libstb/tss/Makefile.inc
new file mode 100644
index 0000000..2b5c3b9
--- /dev/null
+++ b/libstb/tss/Makefile.inc
@@ -0,0 +1,13 @@
+#-*-Makefile-*-
+
+TSS_DIR = libstb/tss
+
+SUBDIRS += $(TSS_DIR)
+
+TSS_SRCS = trustedbootCmds.C trustedTypes.C trustedbootUtils.C \
+ tpmLogMgr.C
+TSS_OBJS = $(TSS_SRCS:%.C=%.o)
+TSS = $(TSS_DIR)/built-in.o
+
+$(TSS): $(TSS_OBJS:%=$(TSS_DIR)/%)
+
diff --git a/libstb/tss/tpmLogMgr.C b/libstb/tss/tpmLogMgr.C
new file mode 100644
index 0000000..ed6e399
--- /dev/null
+++ b/libstb/tss/tpmLogMgr.C
@@ -0,0 +1,563 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/trusted/tpmLogMgr.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file TpmLogMgr.C
+ *
+ * @brief TPM Event log manager
+ */
+
+/////////////////////////////////////////////////////////////////
+// NOTE: This file is exportable as TSS-Lite for skiboot/PHYP //
+/////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include <string.h>
+#include "tpmLogMgr.H"
+#ifdef __HOSTBOOT_MODULE
+#include <sys/mm.h>
+#include <util/align.H>
+#include <secureboot/trustedboot_reasoncodes.H>
+#else
+#include "trustedboot_reasoncodes.H"
+#endif
+
+#ifdef __cplusplus
+namespace TRUSTEDBOOT
+{
+#endif
+
+ uint32_t TCG_EfiSpecIdEventStruct_size(TCG_EfiSpecIdEventStruct* val)
+ {
+ return (sizeof(TCG_EfiSpecIdEventStruct) + val->vendorInfoSize);
+ }
+
+#ifdef __HOSTBOOT_MODULE
+ errlHndl_t TpmLogMgr_initialize(TpmLogMgr* val)
+ {
+ errlHndl_t err = TB_SUCCESS;
+ const char vendorInfo[] = "IBM";
+ const char eventSignature[] = "Spec ID Event03";
+ TCG_EfiSpecIdEventStruct* eventData = NULL;
+
+ TCG_PCR_EVENT eventLogEntry;
+
+ TRACUCOMP( g_trac_trustedboot, ">>initialize()");
+
+ if (NULL == val)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM LOG INIT FAIL");
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPMLOGMGR_INIT_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPMLOGMGR_INITIALIZE
+ * @userdata1 0
+ * @userdata2 0
+ * @devdesc TPM log buffer init failure.
+ */
+ err = tpmCreateErrorLog( MOD_TPMLOGMGR_INITIALIZE,
+ RC_TPMLOGMGR_INIT_FAIL, 0, 0);
+
+ }
+ else
+ {
+
+ memset(val, 0, sizeof(TpmLogMgr));
+ val->logMaxSize = TPMLOG_BUFFER_SIZE;
+
+ mutex_init( &val->logMutex );
+ mutex_lock( &val->logMutex );
+
+ // Assign our new event pointer to the start
+ val->newEventPtr = val->eventLog;
+ memset(val->eventLog, 0, TPMLOG_BUFFER_SIZE);
+
+ eventData = (TCG_EfiSpecIdEventStruct*) eventLogEntry.event;
+
+ // Add the header event log
+ // Values here come from the PC ClientSpecificPlatformProfile spec
+ eventLogEntry.eventType = EV_NO_ACTION;
+ eventLogEntry.pcrIndex = 0;
+ eventLogEntry.eventSize = sizeof(TCG_EfiSpecIdEventStruct) +
+ sizeof(vendorInfo);
+
+ memcpy(eventData->signature, eventSignature,
+ sizeof(eventSignature));
+ eventData->platformClass = htole32(TPM_PLATFORM_SERVER);
+ eventData->specVersionMinor = TPM_SPEC_MINOR;
+ eventData->specVersionMajor = TPM_SPEC_MAJOR;
+ eventData->specErrata = TPM_SPEC_ERRATA;
+ eventData->uintnSize = 1;
+ eventData->numberOfAlgorithms = htole32(HASH_COUNT);
+ eventData->digestSizes[0].algorithmId = htole16(TPM_ALG_SHA256);
+ eventData->digestSizes[0].digestSize = htole16(TPM_ALG_SHA256_SIZE);
+ eventData->digestSizes[1].algorithmId = htole16(TPM_ALG_SHA1);
+ eventData->digestSizes[1].digestSize = htole16(TPM_ALG_SHA1_SIZE);
+ eventData->vendorInfoSize = sizeof(vendorInfo);
+ memcpy(eventData->vendorInfo, vendorInfo, sizeof(vendorInfo));
+ val->newEventPtr = TCG_PCR_EVENT_logMarshal(&eventLogEntry,
+ val->newEventPtr);
+
+ // Done, move our pointers
+ val->logSize += TCG_PCR_EVENT_marshalSize(&eventLogEntry);
+
+ mutex_unlock( &val->logMutex );
+
+ // Debug display of raw data
+ TRACUBIN(g_trac_trustedboot, "tpmInitialize: Header Entry",
+ val->eventLog, val->logSize);
+
+ TRACUCOMP( g_trac_trustedboot,
+ "<<initialize() LS:%d - %s",
+ val->logSize,
+ ((TB_SUCCESS == err) ? "No Error" : "With Error") );
+ }
+ return err;
+ }
+#endif
+
+ errlHndl_t TpmLogMgr_initializeUsingExistingLog(TpmLogMgr* val,
+ uint8_t* eventLogPtr,
+ uint32_t eventLogSize)
+ {
+ errlHndl_t err = TB_SUCCESS;
+ TRACUCOMP( g_trac_trustedboot,
+ ">>initializeUsingExistingLog()");
+
+ do
+ {
+
+ mutex_init( &val->logMutex );
+ mutex_lock( &val->logMutex );
+
+ val->logMaxSize = eventLogSize;
+ val->eventLogInMem = eventLogPtr;
+
+ // Ok, walk the log to figure out how big this is
+ val->logSize = TpmLogMgr_calcLogSize(val);
+
+ if (0 == val->logSize)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM LOG INIT WALK FAIL");
+ /*@
+ * @errortype
+ * @reasoncode RC_TPMLOGMGR_LOGWALKFAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPMLOGMGR_INITIALIZEEXISTLOG
+ * @userdata1 0
+ * @userdata2 0
+ * @devdesc TPM log header entry is missing.
+ */
+ err = tpmCreateErrorLog(MOD_TPMLOGMGR_INITIALIZEEXISTLOG,
+ RC_TPMLOGMGR_LOGWALKFAIL,
+ 0,
+ 0);
+ break;
+ }
+ // We are good, let's move the newEventLogPtr
+ val->newEventPtr = val->eventLogInMem + val->logSize;
+
+ }
+ while(0);
+
+ if (TB_SUCCESS != err)
+ {
+ val->eventLogInMem = NULL;
+ val->newEventPtr = NULL;
+ val->logMaxSize = 0;
+ val->logSize = 0;
+ }
+
+ mutex_unlock( &val->logMutex );
+
+ return err;
+ }
+
+ errlHndl_t TpmLogMgr_addEvent(TpmLogMgr* val,
+ TCG_PCR_EVENT2* logEvent)
+ {
+ errlHndl_t err = TB_SUCCESS;
+ size_t newLogSize = TCG_PCR_EVENT2_marshalSize(logEvent);
+
+ TRACUCOMP( g_trac_trustedboot,
+ ">>tpmAddEvent() PCR:%d Type:%d Size:%d",
+ logEvent->pcrIndex, logEvent->eventType, (int)newLogSize);
+
+ mutex_lock( &val->logMutex );
+
+ do
+ {
+
+ // Need to ensure we have room for the new event
+ // We have to leave room for the log full event as well
+ if (NULL == val->newEventPtr ||
+ val->logSize + newLogSize > val->logMaxSize)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM LOG ADD FAIL PNULL(%d) LS(%d) New LS(%d)"
+ " Max LS(%d)",
+ (NULL == val->newEventPtr ? 0 : 1),
+ (int)val->logSize, (int)newLogSize,
+ (int)val->logMaxSize);
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPMLOGMGR_ADDEVENT_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPMLOGMGR_ADDEVENT
+ * @userdata1 Log buffer NULL
+ * @userdata2[0:31] Current Log Size
+ * @userdata2[32:63] New entry size
+ * @devdesc TPM log buffer add failure.
+ */
+ err = tpmCreateErrorLog( MOD_TPMLOGMGR_ADDEVENT,
+ RC_TPMLOGMGR_ADDEVENT_FAIL,
+ (NULL == val->newEventPtr ? 0 : 1),
+ (uint64_t)val->logSize << 32 |
+ newLogSize);
+
+ break;
+ }
+
+ val->newEventPtr = TCG_PCR_EVENT2_logMarshal(logEvent,
+ val->newEventPtr);
+
+ if (NULL == val->newEventPtr)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM LOG MARSHAL Fail");
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPMLOGMGR_ADDEVENTMARSH_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPMLOGMGR_ADDEVENT
+ * @userdata1 0
+ * @userdata2 0
+ * @devdesc log buffer malloc failure.
+ */
+ err = tpmCreateErrorLog( MOD_TPMLOGMGR_ADDEVENT,
+ RC_TPMLOGMGR_ADDEVENTMARSH_FAIL,
+ 0,
+ 0);
+ break;
+ }
+
+ val->logSize += newLogSize;
+
+
+ } while ( 0 );
+
+ TRACUCOMP( g_trac_trustedboot,
+ "<<tpmAddEvent() LS:%d - %s",
+ (int)val->logSize,
+ ((TB_SUCCESS == err) ? "No Error" : "With Error") );
+
+ mutex_unlock( &val->logMutex );
+ return err;
+ }
+
+ uint32_t TpmLogMgr_getLogSize(TpmLogMgr* val)
+ {
+ return val->logSize;
+ }
+
+#ifdef __HOSTBOOT_MODULE
+ void TpmLogMgr_dumpLog(TpmLogMgr* val)
+ {
+
+ // Debug display of raw data
+ TRACUCOMP(g_trac_trustedboot, "tpmDumpLog Size : %d",
+ (int)val->logSize);
+
+ // Debug display of raw data
+ if (NULL == val->eventLogInMem)
+ {
+ TRACUBIN(g_trac_trustedboot, "tpmDumpLog",
+ val->eventLog, val->logSize);
+ }
+ else
+ {
+ TRACUBIN(g_trac_trustedboot, "tpmDumpLog From Memory",
+ val->eventLogInMem, val->logSize);
+ }
+ }
+#endif
+
+ uint32_t TpmLogMgr_calcLogSize(TpmLogMgr* val)
+ {
+ uint32_t logSize = 0;
+ TCG_PCR_EVENT event;
+ TCG_PCR_EVENT2 event2;
+ bool errorFound = false;
+ const uint8_t* prevLogHandle = NULL;
+ const uint8_t* nextLogHandle = NULL;
+
+ TRACUCOMP( g_trac_trustedboot, ">>calcLogSize");
+
+ // Start walking events
+ prevLogHandle = TpmLogMgr_getLogStartPtr(val);
+ do
+ {
+
+ // First need to deal with the header entry
+ nextLogHandle = TCG_PCR_EVENT_logUnmarshal(&event,
+ prevLogHandle,
+ sizeof(TCG_PCR_EVENT),
+ &errorFound);
+
+ if (NULL == nextLogHandle || errorFound ||
+ EV_NO_ACTION != event.eventType ||
+ 0 == event.eventSize)
+ {
+ TRACFCOMP( g_trac_trustedboot, "Header Marshal Failure");
+ prevLogHandle = NULL;
+ break;
+ }
+
+ if (( nextLogHandle - TpmLogMgr_getLogStartPtr(val)) >
+ val->logMaxSize)
+ {
+ TRACFCOMP( g_trac_trustedboot, "calcLogSize overflow");
+ prevLogHandle = NULL;
+ break;
+ }
+ prevLogHandle = nextLogHandle;
+
+ // Now iterate through all the other events
+ while (NULL != prevLogHandle)
+ {
+ nextLogHandle = TCG_PCR_EVENT2_logUnmarshal(
+ &event2,
+ prevLogHandle,
+ sizeof(TCG_PCR_EVENT2),
+ &errorFound);
+ if (NULL == nextLogHandle || errorFound)
+ {
+ // Failed parsing so we must have hit the end of log
+ break;
+ }
+ if (( nextLogHandle - TpmLogMgr_getLogStartPtr(val)) >
+ val->logMaxSize)
+ {
+ TRACFCOMP( g_trac_trustedboot, "calcLogSize overflow");
+ prevLogHandle = NULL;
+ break;
+ }
+ prevLogHandle = nextLogHandle;
+ }
+ }
+ while (0);
+
+ if (NULL == prevLogHandle)
+ {
+ logSize = 0;
+ }
+ else
+ {
+ logSize = (prevLogHandle - TpmLogMgr_getLogStartPtr(val));
+ }
+ TRACUCOMP( g_trac_trustedboot, "<<calcLogSize : %d", logSize);
+
+ return logSize;
+ }
+
+ const uint8_t* TpmLogMgr_getFirstEvent(TpmLogMgr* val)
+ {
+ TCG_PCR_EVENT event;
+ bool err = false;
+ const uint8_t* result = NULL;
+
+ // Header event in the log is always first, we skip over that
+ const uint8_t* firstEvent = TpmLogMgr_getLogStartPtr(val);
+ memset(&event, 0, sizeof(TCG_PCR_EVENT));
+
+ firstEvent = TCG_PCR_EVENT_logUnmarshal(&event, firstEvent,
+ sizeof(TCG_PCR_EVENT),
+ &err);
+ if (NULL != firstEvent && !err &&
+ firstEvent < val->newEventPtr)
+ {
+ result = firstEvent;
+ }
+
+ return result;
+ }
+
+ const uint8_t* TpmLogMgr_getNextEvent(TpmLogMgr* val,
+ const uint8_t* i_handle,
+ TCG_PCR_EVENT2* i_eventLog,
+ bool* o_err)
+ {
+ const uint8_t* l_resultPtr = NULL;
+ if (NULL == i_handle)
+ {
+ *o_err = true;
+ }
+ else
+ {
+ memset(i_eventLog, 0, sizeof(TCG_PCR_EVENT2));
+ TRACUCOMP( g_trac_trustedboot, "TPM getNextEvent 0x%p", i_handle);
+ l_resultPtr = TCG_PCR_EVENT2_logUnmarshal(i_eventLog, i_handle,
+ sizeof(TCG_PCR_EVENT2),
+ o_err);
+ if (NULL == l_resultPtr)
+ {
+ // An error was detected, ensure o_err is set
+ *o_err = true;
+ }
+ else if (l_resultPtr >= val->newEventPtr)
+ {
+ l_resultPtr = NULL;
+ }
+ }
+
+ return l_resultPtr;
+ }
+
+ TCG_PCR_EVENT2 TpmLogMgr_genLogEventPcrExtend(TPM_Pcr i_pcr,
+ TPM_Alg_Id i_algId_1,
+ const uint8_t* i_digest_1,
+ size_t i_digestSize_1,
+ TPM_Alg_Id i_algId_2,
+ const uint8_t* i_digest_2,
+ size_t i_digestSize_2,
+ uint32_t i_logType,
+ const char* i_logMsg)
+ {
+ TCG_PCR_EVENT2 eventLog;
+ size_t fullDigestSize_1 = 0;
+ size_t fullDigestSize_2 = 0;
+
+ fullDigestSize_1 = getDigestSize(i_algId_1);
+ if (NULL != i_digest_2)
+ {
+ fullDigestSize_2 = getDigestSize(i_algId_2);
+ }
+
+ memset(&eventLog, 0, sizeof(eventLog));
+ eventLog.pcrIndex = i_pcr;
+ eventLog.eventType = i_logType;
+
+ // Update digest information
+ eventLog.digests.count = 1;
+ eventLog.digests.digests[0].algorithmId = i_algId_1;
+ memcpy(&(eventLog.digests.digests[0].digest),
+ i_digest_1,
+ (i_digestSize_1 < fullDigestSize_1 ?
+ i_digestSize_1 : fullDigestSize_1));
+
+ if (NULL != i_digest_2)
+ {
+ eventLog.digests.count = 2;
+ eventLog.digests.digests[1].algorithmId = i_algId_2;
+ memcpy(&(eventLog.digests.digests[1].digest),
+ i_digest_2,
+ (i_digestSize_2 < fullDigestSize_2 ?
+ i_digestSize_2 : fullDigestSize_2));
+ }
+ // Event field data
+ eventLog.event.eventSize = strlen(i_logMsg);
+ memset(eventLog.event.event, 0, sizeof(eventLog.event.event));
+ memcpy(eventLog.event.event, i_logMsg,
+ (strlen(i_logMsg) > MAX_TPM_LOG_MSG ?
+ MAX_TPM_LOG_MSG - 1 // Leave room for NULL termination
+ : strlen(i_logMsg)) );
+
+ return eventLog;
+ }
+
+
+ uint8_t* TpmLogMgr_getLogStartPtr(TpmLogMgr* val)
+ {
+#ifdef __HOSTBOOT_MODULE
+ return (val->eventLogInMem == NULL ?
+ reinterpret_cast<uint8_t*>(&(val->eventLog)) : val->eventLogInMem);
+#else
+ return val->eventLogInMem;
+#endif
+ }
+
+#ifdef __HOSTBOOT_MODULE
+ errlHndl_t TpmLogMgr_getDevtreeInfo(TpmLogMgr* val,
+ uint64_t & io_logAddr,
+ size_t & o_allocationSize,
+ uint64_t & o_xscomAddr,
+ uint32_t & o_i2cMasterOffset)
+ {
+ errlHndl_t err = NULL;
+
+ mutex_lock( &val->logMutex );
+
+ assert(io_logAddr != 0, "Invalid starting log address");
+ assert(val->eventLogInMem == NULL,
+ "getDevtreeInfo can only be called once");
+
+ io_logAddr -= ALIGN_PAGE(TPMLOG_DEVTREE_SIZE);
+ // Align to 64KB for Opal
+ io_logAddr = ALIGN_DOWN_X(io_logAddr,64*KILOBYTE);
+
+ val->inMemlogBaseAddr = io_logAddr;
+ o_allocationSize = TPMLOG_DEVTREE_SIZE;
+ o_xscomAddr = val->devtreeXscomAddr;
+ o_i2cMasterOffset = val->devtreeI2cMasterOffset;
+
+ // Copy image.
+ val->eventLogInMem = (uint8_t*)(mm_block_map(
+ (void*)(io_logAddr),
+ ALIGN_PAGE(TPMLOG_DEVTREE_SIZE)));
+ // Copy log into new location
+ memset(val->eventLogInMem, 0, TPMLOG_DEVTREE_SIZE);
+ memcpy(val->eventLogInMem, val->eventLog, val->logSize);
+ val->newEventPtr = val->eventLogInMem + val->logSize;
+
+ mutex_unlock( &val->logMutex );
+
+ TRACUCOMP( g_trac_trustedboot,
+ "<<getDevtreeInfo() Addr:%lX - %s",
+ io_logAddr,
+ ((TB_SUCCESS == err) ? "No Error" : "With Error") );
+ return err;
+ }
+
+
+ void TpmLogMgr_setTpmDevtreeInfo(TpmLogMgr* val,
+ uint64_t i_xscomAddr,
+ uint32_t i_i2cMasterOffset)
+ {
+ val->devtreeXscomAddr = i_xscomAddr;
+ val->devtreeI2cMasterOffset = i_i2cMasterOffset;
+ }
+
+#endif
+
+#ifdef __cplusplus
+} // end TRUSTEDBOOT
+#endif
diff --git a/libstb/tss/tpmLogMgr.H b/libstb/tss/tpmLogMgr.H
new file mode 100644
index 0000000..eb2ef3d
--- /dev/null
+++ b/libstb/tss/tpmLogMgr.H
@@ -0,0 +1,248 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/trusted/tpmLogMgr.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file tpmLogMgr.H
+ *
+ * @brief Trustedboot TPM Event Log Manager
+ *
+ */
+
+/////////////////////////////////////////////////////////////////
+// NOTE: This file is exportable as TSS-Lite for skiboot/PHYP //
+/////////////////////////////////////////////////////////////////
+
+#ifndef __TPMLOGMGR_H
+#define __TPMLOGMGR_H
+// -----------------------------------------------
+// Includes
+// -----------------------------------------------
+
+#ifdef __HOSTBOOT_MODULE
+#include <sys/sync.h>
+#include "trustedboot.H"
+#endif
+#include "trustedbootUtils.H"
+#include "trustedTypes.H"
+
+#ifdef __cplusplus
+namespace TRUSTEDBOOT
+{
+#endif
+
+ /// Event log header algorithms
+ struct _TCG_EfiSpecIdEventAlgorithmSize
+ {
+ uint16_t algorithmId;
+ uint16_t digestSize;
+ } PACKED;
+ typedef struct _TCG_EfiSpecIdEventAlgorithmSize
+ TCG_EfiSpecIdEventAlgorithmSize;
+
+ /// Event log header event data
+ struct _TCG_EfiSpecIdEventStruct
+ {
+ char signature[16];
+ uint32_t platformClass;
+ uint8_t specVersionMinor;
+ uint8_t specVersionMajor;
+ uint8_t specErrata;
+ uint8_t uintnSize;
+ uint32_t numberOfAlgorithms;
+ TCG_EfiSpecIdEventAlgorithmSize digestSizes[HASH_COUNT];
+ uint8_t vendorInfoSize;
+ char vendorInfo[0];
+ } PACKED;
+ typedef struct _TCG_EfiSpecIdEventStruct TCG_EfiSpecIdEventStruct;
+ uint32_t TCG_EfiSpecIdEventStruct_size(TCG_EfiSpecIdEventStruct* val);
+
+ enum {
+ TPMLOG_BUFFER_SIZE = 2048, ///< Size of event log buffer in bytes
+ TPMLOG_DEVTREE_SIZE = 64*1024, ///< Size to allocate for OPAL
+ };
+
+ struct _TpmLogMgr
+ {
+ uint32_t logSize; ///< Current byte size of log
+ uint32_t logMaxSize; ///< Space allocated for log entries
+ uint8_t* newEventPtr; ///< Pointer to location to add new event
+ uint8_t* eventLogInMem; ///< Event log allocated from memory
+#ifdef __HOSTBOOT_MODULE
+ uint64_t inMemlogBaseAddr; ///< Base address of log for dev tree
+ uint64_t devtreeXscomAddr; ///< Devtree Xscom Address
+ uint32_t devtreeI2cMasterOffset; ///< Devtree I2c Master Offset
+ uint8_t eventLog[TPMLOG_BUFFER_SIZE]; ///< EventLog Buffer
+#endif
+ mutex_t logMutex; ///< Log mutex
+ };
+ typedef struct _TpmLogMgr TpmLogMgr;
+
+#ifdef __HOSTBOOT_MODULE
+ /**
+ * @brief Initialize the log manager
+ * @param[in/out] io_logMgr Return a pointer to the log manager
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+ errlHndl_t TpmLogMgr_initialize(TpmLogMgr * io_logMgr);
+#endif
+
+ /**
+ * @brief Initialize the log manager to use a pre-existing buffer
+ * @param[in] val TpmLogMgr structure
+ * @param[in] eventLogPtr Pointer to event log to use
+ * @param[in] eventLogSize Allocated log buffer size
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+ errlHndl_t TpmLogMgr_initializeUsingExistingLog(TpmLogMgr* val,
+ uint8_t* eventLogPtr,
+ uint32_t eventLogSize);
+
+ /**
+ * @brief Add a new event to the log
+ * @param[in] val TpmLogMgr structure
+ * @param[in] logEvent Event log entry to add
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+ errlHndl_t TpmLogMgr_addEvent(TpmLogMgr* val, TCG_PCR_EVENT2* logEvent);
+
+ /**
+ * @brief Get current log size in bytes
+ * @param[in] val TpmLogMgr structure
+ * @return uint32_t Byte size of log
+ */
+ uint32_t TpmLogMgr_getLogSize(TpmLogMgr* val);
+
+#ifdef __HOSTBOOT_MODULE
+ /**
+ * @brief Retrieve devtree information
+ * @param[in] val TpmLogMgr structure
+ * @param[in/out] io_logAddr TPM Log address
+ * @param[out] o_allocationSize Total memory allocated for log
+ * @param[out] o_xscomAddr Chip Xscom Address
+ * @param[out] o_i2cMasterOffset I2c Master Offset
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ * Function will allocate a new region in memory to store log
+ * for passing to opal
+ */
+ errlHndl_t TpmLogMgr_getDevtreeInfo(TpmLogMgr* val,
+ uint64_t & io_logAddr,
+ size_t & o_allocationSize,
+ uint64_t & o_xscomAddr,
+ uint32_t & o_i2cMasterOffset);
+
+ /**
+ * @brief Store TPM devtree node information
+ * @param[in] val TpmLogMgr structure
+ * @param[in] i_xscomAddr Chip Xscom Address
+ * @param[in] i_i2cMasterOffset i2c Master Offset
+ */
+ void TpmLogMgr_setTpmDevtreeInfo(TpmLogMgr* val,
+ uint64_t i_xscomAddr,
+ uint32_t i_i2cMasterOffset);
+#endif
+
+
+ /**
+ * @brief Calculate the log size in bytes by walking the log
+ * @param[in] val TpmLogMgr structure
+ * @return uint32_t Byte size of log
+ */
+ uint32_t TpmLogMgr_calcLogSize(TpmLogMgr* val);
+
+ /**
+ * @brief Get pointer to first event in eventLog past the header event
+ * @param[in] val TpmLogMgr structure
+ * @return uint8_t First event handle
+ * @retval NULL On empty log
+ * @retval !NULL First event handle
+ */
+ const uint8_t* TpmLogMgr_getFirstEvent(TpmLogMgr* val);
+
+ /**
+ * @brief Get pointer to next event in log and unmarshal log contents
+ * into i_eventLog
+ *
+ * @param[in] i_handle Current event to unmarshal
+ * @param[in] i_eventLog EVENT2 structure to populate
+ * @param[in] o_err Indicates if an error occurred during
+ * LogUnmarshal.
+ *
+ * @return uint8_t* Pointer to the next event after i_handle
+ * @retval NULL When val contains last entry in log
+ * @retval !NULL When addition log entries available
+ */
+ const uint8_t* TpmLogMgr_getNextEvent(TpmLogMgr* val,
+ const uint8_t* i_handle,
+ TCG_PCR_EVENT2* i_eventLog,
+ bool* o_err);
+
+ /**
+ * @brief Get a TCG_PCR_EVENT2 populated with required data
+ *
+ * @param[in] i_pcr PCR to write to
+ * @param[in] i_algId_1 Algorithm to use
+ * @param[in] i_digest_1 Digest value to write to PCR
+ * @param[in] i_digestSize_1 Byte size of i_digest array
+ * @param[in] i_algId_2 Algorithm to use
+ * @param[in] i_digest_2 Digest value to write to PCR, NULL if not used
+ * @param[in] i_digestSize_2 Byte size of i_digest array
+ * @param[in] i_logType Event type
+ * @param[in] i_logMsg Null terminated Log message
+ *
+ * @return TCG_PCR_EVENT2 PCR event log
+ */
+ TCG_PCR_EVENT2 TpmLogMgr_genLogEventPcrExtend(TPM_Pcr i_pcr,
+ TPM_Alg_Id i_algId_1,
+ const uint8_t* i_digest_1,
+ size_t i_digestSize_1,
+ TPM_Alg_Id i_algId_2,
+ const uint8_t* i_digest_2,
+ size_t i_digestSize_2,
+ uint32_t i_logType,
+ const char* i_logMsg);
+#ifdef __HOSTBOOT_MODULE
+ /**
+ * @brief Dump contents of log to a trace
+ * @param[in] val TpmLogMgr structure
+ */
+ void TpmLogMgr_dumpLog(TpmLogMgr* val);
+#endif
+
+ /**
+ * @brief Return a pointer to the start of the log
+ * @param[in] val TpmLogMgr structure
+ * @return uint8_t* Pointer to the start of the TPM log
+ */
+ uint8_t* TpmLogMgr_getLogStartPtr(TpmLogMgr* val);
+
+
+#ifdef __cplusplus
+} // end TRUSTEDBOOT namespace
+#endif
+
+#endif
diff --git a/libstb/tss/trustedTypes.C b/libstb/tss/trustedTypes.C
new file mode 100644
index 0000000..cc8c123
--- /dev/null
+++ b/libstb/tss/trustedTypes.C
@@ -0,0 +1,926 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/trusted/trustedTypes.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file trustedTypes.C
+ *
+ * @brief Trusted boot type inline functions
+ */
+
+/////////////////////////////////////////////////////////////////
+// NOTE: This file is exportable as TSS-Lite for skiboot/PHYP //
+/////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include <string.h>
+#include "trustedTypes.H"
+
+#ifdef __cplusplus
+namespace TRUSTEDBOOT
+{
+#endif
+
+ const uint8_t* unmarshalChunk(const uint8_t* i_tpmBuf,
+ size_t * io_tpmBufSize,
+ void* o_chunkPtr,
+ size_t i_chunkSize);
+
+ uint8_t* marshalChunk(uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t * io_cmdSize,
+ const void* i_chunkPtr,
+ size_t i_chunkSize);
+
+ const uint8_t* unmarshalChunk(const uint8_t* i_tpmBuf,
+ size_t * io_tpmBufSize,
+ void* o_chunkPtr,
+ size_t i_chunkSize)
+ {
+ if (NULL != i_tpmBuf)
+ {
+ if (i_chunkSize > *io_tpmBufSize)
+ {
+ return NULL;
+ }
+ memcpy(o_chunkPtr, i_tpmBuf, i_chunkSize);
+ i_tpmBuf += i_chunkSize;
+ *io_tpmBufSize -= i_chunkSize;
+ }
+ return i_tpmBuf;
+ }
+
+ uint8_t* marshalChunk(uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t * io_cmdSize,
+ const void* i_chunkPtr,
+ size_t i_chunkSize)
+ {
+ if (NULL != o_tpmBuf)
+ {
+ if ((*io_cmdSize + i_chunkSize) > i_tpmBufSize)
+ {
+ return NULL;
+ }
+ memcpy(o_tpmBuf, i_chunkPtr, i_chunkSize);
+ o_tpmBuf += i_chunkSize;
+ *io_cmdSize += i_chunkSize;
+ }
+ return o_tpmBuf;
+ }
+
+ uint32_t getDigestSize(const TPM_Alg_Id i_algId)
+ {
+ uint32_t ret = 0;
+ switch (i_algId)
+ {
+ case TPM_ALG_SHA1:
+ ret = TPM_ALG_SHA1_SIZE;
+ break;
+ case TPM_ALG_SHA256:
+ ret = TPM_ALG_SHA256_SIZE;
+ break;
+ default:
+ ret = 0;
+ break;
+ };
+ return ret;
+ }
+
+ const uint8_t* TPML_TAGGED_TPM_PROPERTY_unmarshal(
+ TPML_TAGGED_TPM_PROPERTY* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize)
+ {
+
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &(val->count), sizeof(val->count));
+
+ // Now we know the count as well
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &(val->tpmProperty[0]),
+ sizeof(TPMS_TAGGED_PROPERTY) * val->count);
+
+ return i_tpmBuf;
+ }
+
+ const uint8_t* TPMS_CAPABILITY_DATA_unmarshal(TPMS_CAPABILITY_DATA* val,
+ const uint8_t* i_tpmBuf,
+ size_t * io_tpmBufSize)
+ {
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &(val->capability),
+ sizeof(val->capability));
+
+ switch (val->capability)
+ {
+ case TPM_CAP_TPM_PROPERTIES:
+ {
+ return TPML_TAGGED_TPM_PROPERTY_unmarshal(
+ &(val->data.tpmProperties), i_tpmBuf,
+ io_tpmBufSize);
+ }
+ break;
+ default:
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPMS_CAPABILITY_DATA::unmarshal Unknown capability");
+ return NULL;
+ }
+ break;
+ }
+ return NULL;
+ }
+
+ uint8_t* TPMT_HA_marshal(const TPMT_HA* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t * io_cmdSize)
+ {
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->algorithmId), sizeof(val->algorithmId));
+ if (getDigestSize((TPM_Alg_Id)val->algorithmId) == 0)
+ {
+ return NULL;
+ }
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->digest),
+ getDigestSize((TPM_Alg_Id)val->algorithmId));
+ return o_tpmBuf;
+ }
+
+ uint8_t* TPML_DIGEST_VALUES_marshal(const TPML_DIGEST_VALUES* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t * io_cmdSize)
+ {
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->count), sizeof(val->count));
+ if (NULL != o_tpmBuf && HASH_COUNT < val->count)
+ {
+ o_tpmBuf = NULL;
+ }
+ else
+ {
+ for (size_t idx = 0; idx < val->count; idx++)
+ {
+ o_tpmBuf = TPMT_HA_marshal(&(val->digests[idx]),
+ o_tpmBuf,
+ i_tpmBufSize,
+ io_cmdSize);
+ if (NULL == o_tpmBuf)
+ {
+ break;
+ }
+ }
+ }
+ return o_tpmBuf;
+ }
+
+ uint8_t* TPM2_BaseIn_marshal(const TPM2_BaseIn* val, uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize, size_t* io_cmdSize)
+ {
+ return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ val, sizeof(TPM2_BaseIn));
+ }
+
+ const uint8_t* TPM2_BaseOut_unmarshal(TPM2_BaseOut* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize,
+ size_t i_outBufSize)
+ {
+ if (sizeof(TPM2_BaseOut) > i_outBufSize)
+ {
+ return NULL;
+ }
+ return unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ val, sizeof(TPM2_BaseOut));
+ }
+
+ uint8_t* TPM2_2ByteIn_marshal(const TPM2_2ByteIn* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize)
+ {
+ // Base has already been marshaled
+ return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->param), sizeof(val->param));
+ }
+
+ uint8_t* TPM2_4ByteIn_marshal(const TPM2_4ByteIn* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize)
+ {
+ // Base has already been marshaled
+ return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->param), sizeof(val->param));
+ }
+
+ uint8_t* TPM2_GetCapabilityIn_marshal(const TPM2_GetCapabilityIn* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize)
+ {
+ // Base has already been marshaled
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->capability),
+ sizeof(val->capability));
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->property),
+ sizeof(val->property));
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->propertyCount),
+ sizeof(val->propertyCount));
+ return o_tpmBuf;
+ }
+
+ const uint8_t* TPM2_GetCapabilityOut_unmarshal(TPM2_GetCapabilityOut* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize,
+ size_t i_outBufSize)
+ {
+ // Base has already been unmarshaled
+ if (sizeof(TPM2_GetCapabilityOut) > i_outBufSize)
+ {
+ return NULL;
+ }
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &(val->moreData), sizeof(val->moreData));
+
+ // Capability data block
+ return TPMS_CAPABILITY_DATA_unmarshal(&(val->capData), i_tpmBuf,
+ io_tpmBufSize);
+
+ }
+
+ uint8_t* TPM2_ExtendIn_marshalHandle(const TPM2_ExtendIn* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize)
+ {
+ // Base has already been marshaled
+ // only marshal the pcr handle in this stage
+ return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->pcrHandle), sizeof(val->pcrHandle));
+ }
+
+ uint8_t* TPM2_ExtendIn_marshalParms(const TPM2_ExtendIn* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize)
+ {
+ // Base and handle has already been marshaled
+ return (TPML_DIGEST_VALUES_marshal(&(val->digests), o_tpmBuf,
+ i_tpmBufSize, io_cmdSize));
+ }
+
+ uint8_t* TPMS_PCR_SELECTION_marshal(const TPMS_PCR_SELECTION* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize)
+ {
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->algorithmId), sizeof(val->algorithmId));
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->sizeOfSelect), sizeof(val->sizeOfSelect));
+
+ if (NULL != o_tpmBuf &&
+ PCR_SELECT_MAX < val->sizeOfSelect)
+ {
+ return NULL;
+ }
+
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ val->pcrSelect, val->sizeOfSelect);
+ return o_tpmBuf;
+ }
+
+ const uint8_t* TPMS_PCR_SELECTION_unmarshal(TPMS_PCR_SELECTION* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize)
+ {
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &(val->algorithmId),
+ sizeof(val->algorithmId));
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &(val->sizeOfSelect),
+ sizeof(val->sizeOfSelect));
+ if (NULL != i_tpmBuf &&
+ PCR_SELECT_MAX < val->sizeOfSelect)
+ {
+ return NULL;
+ }
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ val->pcrSelect, val->sizeOfSelect);
+
+ return i_tpmBuf;
+ }
+
+ const uint8_t* TPM2B_DIGEST_unmarshal(TPM2B_DIGEST* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize)
+ {
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &val->size, sizeof(val->size));
+ if (NULL != i_tpmBuf &&
+ sizeof(TPMU_HA) < val->size)
+ {
+ TRACUCOMP( g_trac_trustedboot,
+ "TPM2B_DIGEST::unmarshal invalid size");
+ return NULL;
+ }
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ val->buffer, val->size);
+ return i_tpmBuf;
+
+ }
+
+ const uint8_t* TPML_DIGEST_unmarshal(TPML_DIGEST* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize)
+ {
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &(val->count), sizeof(val->count));
+ if (NULL != i_tpmBuf && HASH_COUNT < val->count)
+ {
+ TRACUCOMP( g_trac_trustedboot,
+ "TPML_DIGEST::unmarshal invalid count %d", val->count);
+ i_tpmBuf = NULL;
+ }
+ else if (NULL != i_tpmBuf)
+ {
+ for (size_t idx = 0; idx < val->count; idx++)
+ {
+ i_tpmBuf = TPM2B_DIGEST_unmarshal(&(val->digests[idx]),
+ i_tpmBuf,
+ io_tpmBufSize);
+ if (NULL == i_tpmBuf)
+ {
+ break;
+ }
+ }
+ }
+ return i_tpmBuf;
+
+ }
+
+ uint8_t* TPML_PCR_SELECTION_marshal(const TPML_PCR_SELECTION* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize)
+ {
+ o_tpmBuf = marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ &(val->count), sizeof(val->count));
+ if (NULL != o_tpmBuf && HASH_COUNT < val->count)
+ {
+ TRACUCOMP( g_trac_trustedboot,
+ "TPML_PCR_SELECTION::marshal invalid count");
+ o_tpmBuf = NULL;
+ }
+ else if (NULL != o_tpmBuf)
+ {
+ for (size_t idx = 0; idx < val->count; idx++)
+ {
+ o_tpmBuf = TPMS_PCR_SELECTION_marshal(
+ &(val->pcrSelections[idx]),
+ o_tpmBuf,
+ i_tpmBufSize,
+ io_cmdSize);
+ if (NULL == o_tpmBuf)
+ {
+ break;
+ }
+ }
+ }
+ return o_tpmBuf;
+ }
+
+ const uint8_t* TPML_PCR_SELECTION_unmarshal(TPML_PCR_SELECTION* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize)
+ {
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &(val->count), sizeof(val->count));
+ if (NULL != i_tpmBuf && HASH_COUNT < val->count)
+ {
+ TRACUCOMP( g_trac_trustedboot,
+ "TPML_PCR_SELECTION::unmarshal invalid count");
+ i_tpmBuf = NULL;
+ }
+ else if (NULL != i_tpmBuf)
+ {
+ for (size_t idx = 0; idx < val->count; idx++)
+ {
+ i_tpmBuf = TPMS_PCR_SELECTION_unmarshal(
+ &(val->pcrSelections[idx]),
+ i_tpmBuf,
+ io_tpmBufSize);
+ if (NULL == i_tpmBuf)
+ {
+ break;
+ }
+ }
+ }
+ return i_tpmBuf;
+
+ }
+
+ uint8_t* TPM2_PcrReadIn_marshal(const TPM2_PcrReadIn* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize)
+ {
+ // Base and handle has already been marshaled
+ return (TPML_PCR_SELECTION_marshal(&(val->pcrSelectionIn), o_tpmBuf,
+ i_tpmBufSize, io_cmdSize));
+ }
+
+ const uint8_t* TPM2_PcrReadOut_unmarshal(TPM2_PcrReadOut* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize,
+ size_t i_outBufSize)
+ {
+ // Base and handle has already been marshaled
+ if (sizeof(TPM2_PcrReadOut) > i_outBufSize) return NULL;
+ i_tpmBuf = unmarshalChunk(i_tpmBuf, io_tpmBufSize,
+ &(val->pcrUpdateCounter),
+ sizeof(val->pcrUpdateCounter));
+
+ i_tpmBuf = TPML_PCR_SELECTION_unmarshal(&(val->pcrSelectionOut),
+ i_tpmBuf, io_tpmBufSize);
+ i_tpmBuf = TPML_DIGEST_unmarshal(&(val->pcrValues), i_tpmBuf,
+ io_tpmBufSize);
+ return i_tpmBuf;
+
+ }
+
+ uint8_t* TPMS_AUTH_COMMAND_marshal(const TPMS_AUTH_COMMAND* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize)
+ {
+ return marshalChunk(o_tpmBuf, i_tpmBufSize, io_cmdSize,
+ val, sizeof(TPMS_AUTH_COMMAND));
+ }
+
+
+ uint8_t* TPMT_HA_logMarshal(const TPMT_HA* val, uint8_t* i_logBuf)
+ {
+ uint16_t* field16 = (uint16_t*)i_logBuf;
+ *field16 = htole16(val->algorithmId);
+ i_logBuf += sizeof(uint16_t);
+ memcpy(i_logBuf, &(val->digest),
+ getDigestSize((TPM_Alg_Id)val->algorithmId));
+ i_logBuf += getDigestSize((TPM_Alg_Id)val->algorithmId);
+ return i_logBuf;
+ }
+
+ const uint8_t* TPMT_HA_logUnmarshal(TPMT_HA* val,
+ const uint8_t* i_tpmBuf, bool* o_err)
+ {
+ size_t size = 0;
+ uint16_t* field16 = NULL;
+
+ do {
+ *o_err = false;
+
+ // algorithmId
+ size = sizeof(val->algorithmId);
+ field16 = (uint16_t*)i_tpmBuf;
+ val->algorithmId = le16toh(*field16);
+ // Ensure a valid count
+ if (val->algorithmId >= TPM_ALG_INVALID_ID)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ TRACFCOMP(g_trac_trustedboot,"ERROR> TPMT_HA:logUnmarshal()"
+ " invalid algorithmId %d",
+ val->algorithmId);
+ break;
+ }
+ i_tpmBuf += size;
+
+ // digest
+ size = getDigestSize((TPM_Alg_Id)val->algorithmId);
+ // Ensure a valid count
+ if (size >= TPM_ALG_INVALID_SIZE)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ TRACFCOMP(g_trac_trustedboot,"ERROR> TPMT_HA:logUnmarshal() "
+ "invalid algorithm size of %d for algorithm id %d",
+ (int)size, val->algorithmId);
+ break;
+ }
+
+ memcpy(&(val->digest), i_tpmBuf, size);
+ i_tpmBuf += size;
+ } while(0);
+
+ return i_tpmBuf;
+ }
+
+ size_t TPMT_HA_marshalSize(const TPMT_HA* val)
+ {
+ return (sizeof(val->algorithmId) +
+ getDigestSize((TPM_Alg_Id)(val->algorithmId)));
+ }
+
+#ifdef __cplusplus
+ bool TPMT_HA::operator==(const TPMT_HA& i_rhs) const
+ {
+ size_t digestSize = getDigestSize((TPM_Alg_Id)algorithmId);
+ return (algorithmId == i_rhs.algorithmId) &&
+ (memcmp(&(digest), &(i_rhs.digest), digestSize) == 0);
+ }
+#endif
+
+ size_t TPML_DIGEST_VALUES_marshalSize(const TPML_DIGEST_VALUES* val)
+ {
+ size_t ret = sizeof(val->count);
+ for (size_t idx = 0; (idx < val->count && idx < HASH_COUNT); idx++)
+ {
+ ret += TPMT_HA_marshalSize(&(val->digests[idx]));
+ }
+ return ret;
+ }
+
+ uint8_t* TPML_DIGEST_VALUES_logMarshal(const TPML_DIGEST_VALUES* val,
+ uint8_t* i_logBuf)
+ {
+ uint32_t* field32 = (uint32_t*)i_logBuf;
+ if (HASH_COUNT < val->count)
+ {
+ i_logBuf = NULL;
+ }
+ else
+ {
+ *field32 = htole32(val->count);
+ i_logBuf += sizeof(uint32_t);
+ for (size_t idx = 0; idx < val->count; idx++)
+ {
+ i_logBuf = TPMT_HA_logMarshal(&(val->digests[idx]), i_logBuf);
+ if (NULL == i_logBuf) break;
+ }
+ }
+ return i_logBuf;
+ }
+
+ const uint8_t* TPML_DIGEST_VALUES_logUnmarshal(TPML_DIGEST_VALUES* val,
+ const uint8_t* i_tpmBuf,
+ bool* o_err)
+ {
+ size_t size = 0;
+ uint32_t* field32 = NULL;
+ do {
+ *o_err = false;
+
+ // count
+ size = sizeof(val->count);
+ field32 = (uint32_t*)(i_tpmBuf);
+ val->count = le32toh(*field32);
+ // Ensure a valid count
+ if (val->count > HASH_COUNT)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ TRACFCOMP(g_trac_trustedboot,"ERROR> "
+ "TPML_DIGEST_VALUES:logUnmarshal() "
+ "invalid digest count %d",
+ val->count);
+ break;
+ }
+ i_tpmBuf += size;
+
+ // Iterate all digests
+ for (size_t idx = 0; idx < val->count; idx++)
+ {
+ i_tpmBuf = TPMT_HA_logUnmarshal(&(val->digests[idx]),
+ i_tpmBuf, o_err);
+ if (NULL == i_tpmBuf)
+ {
+ break;
+ }
+ }
+ } while(0);
+
+ return i_tpmBuf;
+ }
+
+#ifdef __cplusplus
+ bool TPML_DIGEST_VALUES::operator==(const TPML_DIGEST_VALUES& i_rhs) const
+ {
+ bool result = (count == i_rhs.count);
+ // Iterate all digests
+ for (size_t idx = 0; idx < count; idx++)
+ {
+ result = (result && (digests[idx] == i_rhs.digests[idx]));
+ }
+
+ return result;
+ }
+#endif
+
+ const uint8_t* TCG_PCR_EVENT_logUnmarshal(TCG_PCR_EVENT* val,
+ const uint8_t* i_tpmBuf,
+ size_t i_bufSize,
+ bool* o_err)
+ {
+ size_t size = 0;
+ uint32_t* field32;
+
+ *o_err = false;
+ do {
+ // Ensure enough space for unmarshalled data
+ if (sizeof(TCG_PCR_EVENT) > i_bufSize)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ break;
+ }
+
+ // pcrIndex
+ size = sizeof(val->pcrIndex);
+ field32 = (uint32_t*)(i_tpmBuf);
+ val->pcrIndex = le32toh(*field32);
+ // Ensure a valid pcr index
+ if (val->pcrIndex >= IMPLEMENTATION_PCR)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ TRACFCOMP(g_trac_trustedboot,
+ "ERROR> TCG_PCR_EVENT:logUnmarshal() invalid pcrIndex %d",
+ val->pcrIndex);
+ break;
+ }
+ i_tpmBuf += size;
+
+ // eventType
+ size = sizeof(val->eventType);
+ field32 = (uint32_t*)(i_tpmBuf);
+ val->eventType = le32toh(*field32);
+ // Ensure a valid event type
+ if (val->eventType == 0 || val->eventType >= EV_INVALID)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ TRACFCOMP(g_trac_trustedboot,
+ "ERROR> TCG_PCR_EVENT:logUnmarshal() invalid eventType %d",
+ val->eventType);
+ break;
+ }
+ i_tpmBuf += size;
+
+ // digest
+ size = sizeof(val->digest);
+ memcpy(val->digest, i_tpmBuf, size);
+ i_tpmBuf += size;
+
+ // eventSize
+ size = sizeof(val->eventSize);
+ field32 = (uint32_t*)(i_tpmBuf);
+ val->eventSize = le32toh(*field32);
+ // Ensure a valid eventSize
+ if (val->eventSize >= MAX_TPM_LOG_MSG)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ TRACFCOMP(g_trac_trustedboot,
+ "ERROR> TCG_PCR_EVENT:logUnmarshal() invalid eventSize %d",
+ val->eventSize);
+ break;
+ }
+ i_tpmBuf += size;
+
+ memcpy(val->event, i_tpmBuf, val->eventSize);
+ i_tpmBuf += val->eventSize;
+
+ } while(0);
+
+ return i_tpmBuf;
+ }
+
+ uint8_t* TCG_PCR_EVENT_logMarshal(const TCG_PCR_EVENT* val,
+ uint8_t* i_logBuf)
+ {
+ uint32_t* field32 = (uint32_t*)(i_logBuf);
+ *field32 = htole32(val->pcrIndex);
+ i_logBuf += sizeof(uint32_t);
+
+ field32 = (uint32_t*)(i_logBuf);
+ *field32 = htole32(val->eventType);
+ i_logBuf += sizeof(uint32_t);
+
+ memcpy(i_logBuf, val->digest, sizeof(val->digest));
+ i_logBuf += sizeof(val->digest);
+
+ field32 = (uint32_t*)(i_logBuf);
+ *field32 = htole32(val->eventSize);
+ i_logBuf += sizeof(uint32_t);
+
+ if (val->eventSize > 0)
+ {
+ memcpy(i_logBuf, val->event, val->eventSize);
+ i_logBuf += val->eventSize;
+ }
+ return i_logBuf;
+ }
+
+ size_t TCG_PCR_EVENT_marshalSize(const TCG_PCR_EVENT* val)
+ {
+ return (sizeof(TCG_PCR_EVENT) + val->eventSize - MAX_TPM_LOG_MSG);
+ }
+
+ uint8_t* TPM_EVENT_FIELD_logMarshal(const TPM_EVENT_FIELD* val,
+ uint8_t* i_logBuf)
+ {
+ uint32_t* field32 = (uint32_t*)i_logBuf;
+ if (MAX_TPM_LOG_MSG < val->eventSize)
+ {
+ i_logBuf = NULL;
+ }
+ else
+ {
+ *field32 = htole32(val->eventSize);
+ i_logBuf += sizeof(uint32_t);
+
+ memcpy(i_logBuf, val->event, val->eventSize);
+ i_logBuf += val->eventSize;
+ }
+ return i_logBuf;
+ }
+
+ const uint8_t* TPM_EVENT_FIELD_logUnmarshal(TPM_EVENT_FIELD* val,
+ const uint8_t* i_tpmBuf,
+ bool* o_err)
+ {
+ size_t size = 0;
+ uint32_t* field32 = NULL;
+ do {
+ *o_err = false;
+
+ // Event size
+ size = sizeof(val->eventSize);
+ field32 = (uint32_t*)(i_tpmBuf);
+ val->eventSize = le32toh(*field32);
+ i_tpmBuf += size;
+
+ // Event
+ size = val->eventSize;
+ if (size > MAX_TPM_LOG_MSG)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ break;
+ }
+ memcpy(&val->event, i_tpmBuf, size);
+ i_tpmBuf += size;
+ } while(0);
+
+ return i_tpmBuf;
+ }
+ size_t TPM_EVENT_FIELD_marshalSize(const TPM_EVENT_FIELD* val)
+ {
+ return (sizeof(val->eventSize) + val->eventSize);
+ }
+
+
+#ifdef __cplusplus
+ bool TPM_EVENT_FIELD::operator==(const TPM_EVENT_FIELD& i_rhs) const
+ {
+ return (eventSize == i_rhs.eventSize) &&
+ (memcmp(event, i_rhs.event, eventSize) == 0);
+ }
+#endif
+
+
+ size_t TCG_PCR_EVENT2_marshalSize(const TCG_PCR_EVENT2* val)
+ {
+ return (sizeof(val->pcrIndex) + sizeof(val->eventType) +
+ TPML_DIGEST_VALUES_marshalSize(&(val->digests)) +
+ TPM_EVENT_FIELD_marshalSize(&(val->event)));
+ }
+
+ uint8_t* TCG_PCR_EVENT2_logMarshal(const TCG_PCR_EVENT2* val,
+ uint8_t* i_logBuf)
+ {
+ uint32_t* field32 = (uint32_t*)i_logBuf;
+ *field32 = htole32(val->pcrIndex);
+ i_logBuf += sizeof(uint32_t);
+ field32 = (uint32_t*)i_logBuf;
+ *field32 = htole32(val->eventType);
+ i_logBuf += sizeof(uint32_t);
+
+ i_logBuf = TPML_DIGEST_VALUES_logMarshal(&(val->digests),i_logBuf);
+ if (NULL != i_logBuf)
+ {
+ i_logBuf = TPM_EVENT_FIELD_logMarshal(&(val->event),i_logBuf);
+ }
+ return i_logBuf;
+ }
+
+ const uint8_t* TCG_PCR_EVENT2_logUnmarshal(TCG_PCR_EVENT2* val,
+ const uint8_t* i_tpmBuf,
+ size_t i_bufSize,
+ bool* o_err)
+ {
+ size_t size = 0;
+ uint32_t* field32 = NULL;
+
+ do {
+ *o_err = false;
+
+ // Ensure enough space for unmarshalled data
+ if (sizeof(TCG_PCR_EVENT2) > i_bufSize)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ break;
+ }
+
+ // pcrIndex
+ size = sizeof(val->pcrIndex);
+ field32 = (uint32_t*)(i_tpmBuf);
+ val->pcrIndex = le32toh(*field32);
+ // Ensure a valid pcr index
+ if (val->pcrIndex > IMPLEMENTATION_PCR)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ TRACUCOMP(g_trac_trustedboot,"ERROR> TCG_PCR_EVENT2:"
+ "logUnmarshal() invalid pcrIndex %d",
+ val->pcrIndex);
+ break;
+ }
+ i_tpmBuf += size;
+
+ // eventType
+ size = sizeof(val->eventType);
+ field32 = (uint32_t*)(i_tpmBuf);
+ val->eventType = le32toh(*field32);
+ // Ensure a valid event type
+ if (val->eventType == 0 ||
+ val->eventType >= EV_INVALID)
+ {
+ *o_err = true;
+ i_tpmBuf = NULL;
+ TRACUCOMP(g_trac_trustedboot,"ERROR> TCG_PCR_EVENT2:"
+ "logUnmarshal() invalid eventType %d",
+ val->eventType);
+ break;
+ }
+ i_tpmBuf += size;
+
+ // TPML_DIGEST_VALUES
+ i_tpmBuf = TPML_DIGEST_VALUES_logUnmarshal(&(val->digests),
+ i_tpmBuf, o_err);
+ if (i_tpmBuf == NULL)
+ {
+ break;
+ }
+
+ // TPM EVENT FIELD
+ i_tpmBuf = TPM_EVENT_FIELD_logUnmarshal(&(val->event),
+ i_tpmBuf, o_err);
+ if (i_tpmBuf == NULL)
+ {
+ break;
+ }
+ } while(0);
+
+ return i_tpmBuf;
+ }
+
+#ifdef __cplusplus
+ bool TCG_PCR_EVENT2::operator==(const TCG_PCR_EVENT2& i_rhs) const
+ {
+ return (pcrIndex == i_rhs.pcrIndex) &&
+ (eventType == i_rhs.eventType) &&
+ (digests == i_rhs.digests) &&
+ (event == i_rhs.event);
+ }
+} // end TRUSTEDBOOT
+#endif
diff --git a/libstb/tss/trustedTypes.H b/libstb/tss/trustedTypes.H
new file mode 100644
index 0000000..8269aff
--- /dev/null
+++ b/libstb/tss/trustedTypes.H
@@ -0,0 +1,470 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/trusted/trustedTypes.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file trustedTypes.H
+ *
+ * @brief Trustedboot TPM Types
+ *
+ */
+
+/////////////////////////////////////////////////////////////////
+// NOTE: This file is exportable as TSS-Lite for skiboot/PHYP //
+/////////////////////////////////////////////////////////////////
+
+#ifndef __TRUSTEDTYPES_H
+#define __TRUSTEDTYPES_H
+// -----------------------------------------------
+// Includes
+// -----------------------------------------------
+#include <stdint.h>
+#ifdef __HOSTBOOT_MODULE
+#include <builtins.h>
+#include <secureboot/trustedbootif.H>
+#else
+#include "trustedbootUtils.H"
+#define PACKED __attribute__((__packed__))
+#endif
+
+#ifdef __cplusplus
+namespace TRUSTEDBOOT
+{
+#endif
+
+ /// TPM Algorithm defines
+ typedef enum
+ {
+ TPM_ALG_SHA1 = 0x0004, ///< SHA1 Id
+ TPM_ALG_SHA256 = 0x000B, ///< SHA256 Id
+ TPM_ALG_INVALID_ID ///< Used for error checking
+ } TPM_Alg_Id;
+
+ typedef enum
+ {
+ TPM_ALG_NUM_SUPPORTED = 1, ///< Number of algorithms supported
+ TPM_ALG_SHA1_SIZE = 20, ///< SHA1 digest byte size
+ TPM_ALG_SHA256_SIZE = 32, ///< SHA256 digest byte size
+ TPM_ALG_INVALID_SIZE ///< Used for error checking
+ } TPM_Alg_Sizes;
+
+ /// Common static values
+ enum
+ {
+ MAX_SYSTEM_TPMS = 2,
+ TPM_MASTER_INDEX = 0, ///< Index into tpm array for master chip
+ TPM_BACKUP_INDEX = 1, ///< Index for backup TPM
+ MAX_TPM_LOG_MSG = 128, ///< Maximum log message size
+
+ HASH_COUNT = 2, ///< Maximum # of digests
+
+ PCR_SELECT_MAX = (IMPLEMENTATION_PCR+7)/8, ///< PCR selection octet max
+ };
+
+ typedef enum
+ {
+ EV_NO_ACTION = 0x3, ///< Event field contains info
+ EV_SEPARATOR = 0x4, ///< Used to indicate an error
+ EV_ACTION = 0x5, ///< Must extend a PCR
+ EV_INVALID ///< Used for error checking
+ } EventTypes;
+
+ /**
+ * @brief Get the digest size of the selected hash algorithm
+ * @param[in] i_algId Algorith ID to query
+ * @returns digest length in bytes, 0 on invalid algorithm
+ */
+ uint32_t getDigestSize(const TPM_Alg_Id i_algId) __attribute__ ((const));
+
+
+ /// Various static values
+ enum
+ {
+ // TPM Spec supported
+ TPM_SPEC_MAJOR = 2,
+ TPM_SPEC_MINOR = 0,
+ TPM_SPEC_ERRATA = 0,
+ TPM_PLATFORM_SERVER = 1,
+
+ // Command structure tags
+ TPM_ST_NO_SESSIONS = 0x8001, ///< A command with no sess/auth
+ TPM_ST_SESSIONS = 0x8002, ///< A command has sessions
+
+ // Command Codes
+ TPM_CC_Startup = 0x00000144,
+ TPM_CC_GetCapability = 0x0000017A,
+ TPM_CC_PCR_Read = 0x0000017E,
+ TPM_CC_PCR_Extend = 0x00000182,
+
+
+ // TPM Startup types
+ TPM_SU_CLEAR = 0x0000,///< TPM perform reset,restart
+ TPM_SU_STATE = 0x0001,///< TPM perform restore saved state
+
+ // Capability
+ MAX_TPM_PROPERTIES = 2,
+ TPM_CAP_TPM_PROPERTIES = 0x00000006, ///< Pull TPM Properties
+
+ // TPM Properties
+ TPM_PT_MANUFACTURER = 0x00000105,
+ TPM_PT_FIRMWARE_VERSION_1 = 0x0000010B,
+ TPM_PT_FIRMWARE_VERSION_2 = 0x0000010C,
+
+
+ // TPM Return Codes
+ TPM_SUCCESS = 0x000,
+
+ TPM_RC_INITIALIZE = 0x100,
+
+
+ // TPM Authorization types
+ TPM_RS_PW = 0x40000009,
+
+ };
+
+
+ // Command structures taken from Trusted Platform Module Library Part 3:
+ // Commands Family "2.0"
+
+ /// TPM capability response structure
+ struct _TPMS_TAGGED_PROPERTY
+ {
+ uint32_t property; ///< TPM_PT_xx identifier
+ uint32_t value; ///< value of the property
+ } PACKED;
+ typedef struct _TPMS_TAGGED_PROPERTY TPMS_TAGGED_PROPERTY;
+
+ struct _TPML_TAGGED_TPM_PROPERTY
+ {
+ uint32_t count; ///< Number of properties
+ TPMS_TAGGED_PROPERTY tpmProperty[MAX_TPM_PROPERTIES];
+ } PACKED;
+ typedef struct _TPML_TAGGED_TPM_PROPERTY TPML_TAGGED_TPM_PROPERTY;
+ const uint8_t* TPML_TAGGED_TPM_PROPERTY_unmarshal(
+ TPML_TAGGED_TPM_PROPERTY* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize);
+
+ union _TPMU_CAPABILITIES
+ {
+ // Currently only TPM properties supported
+ TPML_TAGGED_TPM_PROPERTY tpmProperties;
+ } PACKED;
+ typedef union _TPMU_CAPABILITIES TPMU_CAPABILITIES;
+
+ struct _TPMS_CAPABILITY_DATA
+ {
+ uint32_t capability; ///< The capability type
+ TPMU_CAPABILITIES data; ///< The capability data
+ } PACKED;
+ typedef struct _TPMS_CAPABILITY_DATA TPMS_CAPABILITY_DATA;
+ const uint8_t* TPMS_CAPABILITY_DATA_unmarshal(TPMS_CAPABILITY_DATA* val,
+ const uint8_t* i_tpmBuf,
+ size_t * io_tpmBufSize);
+
+
+ /// SHA1 Event log entry format
+ struct _TCG_PCR_EVENT
+ {
+ uint32_t pcrIndex; ///< PCRIndex event extended to
+ uint32_t eventType; ///< Type of event
+ uint8_t digest[20]; ///< Value extended into PCR index
+ uint32_t eventSize; ///< Size of event data
+ uint8_t event[MAX_TPM_LOG_MSG]; ///< The event data
+ } PACKED;
+ typedef struct _TCG_PCR_EVENT TCG_PCR_EVENT;
+ size_t TCG_PCR_EVENT_marshalSize(const TCG_PCR_EVENT* val);
+ const uint8_t* TCG_PCR_EVENT_logUnmarshal(TCG_PCR_EVENT* val,
+ const uint8_t* i_tpmBuf,
+ size_t i_bufSize, bool* o_err);
+ uint8_t* TCG_PCR_EVENT_logMarshal(const TCG_PCR_EVENT* val,
+ uint8_t* i_logBuf);
+
+ /// Digest union
+ union _TPMU_HA
+ {
+ uint8_t sha1[TPM_ALG_SHA1_SIZE];
+ uint8_t sha256[TPM_ALG_SHA256_SIZE];
+ } PACKED;
+ typedef union _TPMU_HA TPMU_HA;
+
+ /// Crypto agile digest
+ struct _TPMT_HA
+ {
+ uint16_t algorithmId; ///< ID of hashing algorithm
+ TPMU_HA digest; ///< Digest, depends on algorithmid
+#ifdef __cplusplus
+ bool operator==(const _TPMT_HA& i_rhs) const;
+#endif
+ } PACKED;
+ typedef struct _TPMT_HA TPMT_HA;
+ size_t TPMT_HA_marshalSize(const TPMT_HA* val);
+ uint8_t* TPMT_HA_logMarshal(const TPMT_HA* val, uint8_t* i_logBuf);
+ const uint8_t* TPMT_HA_logUnmarshal(TPMT_HA* val,
+ const uint8_t* i_tpmBuf, bool* o_err);
+ uint8_t* TPMT_HA_marshal(const TPMT_HA* val, uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize, size_t * io_cmdSize);
+
+
+ /// Crypto agile digests list
+ struct _TPML_DIGEST_VALUES
+ {
+ uint32_t count; ///< Number of digests
+ TPMT_HA digests[HASH_COUNT]; ///< Digests
+#ifdef __cplusplus
+ bool operator==(const _TPML_DIGEST_VALUES& i_rhs) const;
+#endif
+ } PACKED;
+ typedef struct _TPML_DIGEST_VALUES TPML_DIGEST_VALUES;
+ size_t TPML_DIGEST_VALUES_marshalSize(const TPML_DIGEST_VALUES* val);
+ uint8_t* TPML_DIGEST_VALUES_logMarshal(const TPML_DIGEST_VALUES* val,
+ uint8_t* i_logBuf);
+ const uint8_t* TPML_DIGEST_VALUES_logUnmarshal(TPML_DIGEST_VALUES* val,
+ const uint8_t* i_tpmBuf,
+ bool* o_err);
+ uint8_t* TPML_DIGEST_VALUES_marshal(const TPML_DIGEST_VALUES* val,
+ uint8_t* o_tpmBuf, size_t i_tpmBufSize,
+ size_t * io_cmdSize);
+
+ /// Event field structure
+ struct _TPM_EVENT_FIELD
+ {
+ uint32_t eventSize; ///< Size of event data
+ uint8_t event[MAX_TPM_LOG_MSG]; ///< The event data
+#ifdef __cplusplus
+ bool operator==(const _TPM_EVENT_FIELD& i_rhs) const;
+#endif
+ } PACKED;
+ typedef struct _TPM_EVENT_FIELD TPM_EVENT_FIELD;
+ size_t TPM_EVENT_FIELD_marshalSize(const TPM_EVENT_FIELD* val);
+ uint8_t* TPM_EVENT_FIELD_logMarshal(const TPM_EVENT_FIELD* val,
+ uint8_t* i_logBuf);
+ const uint8_t* TPM_EVENT_FIELD_logUnmarshal(TPM_EVENT_FIELD* val,
+ const uint8_t* i_tpmBuf,
+ bool* o_err);
+
+ /// Crypto agile log entry format
+ struct _TCG_PCR_EVENT2
+ {
+ uint32_t pcrIndex; ///< PCRIndex event extended to
+ uint32_t eventType; ///< Type of event
+ TPML_DIGEST_VALUES digests; ///< List of digests extended to PCRIndex
+ TPM_EVENT_FIELD event; ///< Event information
+#ifdef __cplusplus
+ bool operator==(const _TCG_PCR_EVENT2& i_rhs) const;
+#endif
+ } PACKED;
+ typedef struct _TCG_PCR_EVENT2 TCG_PCR_EVENT2;
+ uint8_t* TCG_PCR_EVENT2_logMarshal(const TCG_PCR_EVENT2* val,
+ uint8_t* i_logBuf);
+ const uint8_t* TCG_PCR_EVENT2_logUnmarshal(TCG_PCR_EVENT2* val,
+ const uint8_t* i_tpmBuf,
+ size_t i_bufSize, bool* o_err);
+ size_t TCG_PCR_EVENT2_marshalSize(const TCG_PCR_EVENT2* val);
+
+ struct _TPM2_BaseIn
+ {
+ uint16_t tag; ///< Type TPM_ST_xx
+ uint32_t commandSize; ///< Total # output bytes incl cmdSize & tag
+ uint32_t commandCode; ///< Type TPM_CC_xx
+ } PACKED;
+ typedef struct _TPM2_BaseIn TPM2_BaseIn;
+ uint8_t* TPM2_BaseIn_marshal(const TPM2_BaseIn* val, uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize, size_t* io_cmdSize);
+
+ /// Base of all outgoing messages
+ struct _TPM2_BaseOut
+ {
+ uint16_t tag; ///< Type TPM_ST_xx
+ uint32_t responseSize; ///< Total # out bytes incl paramSize & tag
+ uint32_t responseCode; ///< The return code of the operation
+ } PACKED;
+ typedef struct _TPM2_BaseOut TPM2_BaseOut;
+ const uint8_t* TPM2_BaseOut_unmarshal(TPM2_BaseOut* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize, size_t i_outBufSize);
+
+ /// Generic TPM Input Command structure with a 2 byte param
+ struct _TPM2_2ByteIn
+ {
+ TPM2_BaseIn base;
+ uint16_t param;
+ } PACKED;
+ typedef struct _TPM2_2ByteIn TPM2_2ByteIn;
+ uint8_t* TPM2_2ByteIn_marshal(const TPM2_2ByteIn* val, uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize, size_t* io_cmdSize);
+
+ /// Generic TPM Input Command structure with a 4 byte param
+ struct _TPM2_4ByteIn
+ {
+ TPM2_BaseIn base;
+ uint32_t param;
+ } PACKED;
+ typedef struct _TPM2_4ByteIn TPM2_4ByteIn;
+ uint8_t* TPM2_4ByteIn_marshal(const TPM2_4ByteIn* val, uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize, size_t* io_cmdSize);
+
+
+ /// Generic TPM Output Command structure with a 4 byte return data
+ struct _TPM2_4ByteOut
+ {
+ TPM2_BaseOut base;
+ uint32_t resp;
+ } PACKED;
+ typedef struct _TPM2_4ByteOut TPM2_4ByteOut;
+
+ /// Incoming TPM_GetCapability structure
+ struct _TPM2_GetCapabilityIn
+ {
+ TPM2_BaseIn base;
+ uint32_t capability; ///< group selection
+ uint32_t property; ///< Further definition
+ uint32_t propertyCount; ///< Number of properties to return
+ } PACKED;
+ typedef struct _TPM2_GetCapabilityIn TPM2_GetCapabilityIn;
+ uint8_t* TPM2_GetCapabilityIn_marshal(const TPM2_GetCapabilityIn* val,
+ uint8_t* o_tpmBuf,
+ size_t i_tpmBufSize,
+ size_t* io_cmdSize);
+
+ /// Outgoing TPM_GetCapability structure
+ struct _TPM2_GetCapabilityOut
+ {
+ TPM2_BaseOut base;
+ uint8_t moreData; ///< Flag to indicate if more values available
+ TPMS_CAPABILITY_DATA capData; ///< The capability response
+ } PACKED;
+ typedef struct _TPM2_GetCapabilityOut TPM2_GetCapabilityOut;
+ const uint8_t* TPM2_GetCapabilityOut_unmarshal(TPM2_GetCapabilityOut* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize,
+ size_t i_outBufSize);
+
+ /// Incoming TPM_EXTEND structure
+ struct _TPM2_ExtendIn
+ {
+ TPM2_BaseIn base;
+ uint32_t pcrHandle; ///< PCR number to extend
+ TPML_DIGEST_VALUES digests; ///< Values to be extended
+ } PACKED;
+ typedef struct _TPM2_ExtendIn TPM2_ExtendIn;
+ uint8_t* TPM2_ExtendIn_marshalHandle(const TPM2_ExtendIn* val,
+ uint8_t* o_tpmBuf, size_t i_tpmBufSize,
+ size_t* io_cmdSize);
+ uint8_t* TPM2_ExtendIn_marshalParms(const TPM2_ExtendIn* val,
+ uint8_t* o_tpmBuf, size_t i_tpmBufSize,
+ size_t* io_cmdSize);
+
+ struct _TPMS_PCR_SELECTION
+ {
+ uint16_t algorithmId; ///< ID of hashing algorithm
+ uint8_t sizeOfSelect; ///< Byte size of pcrSelect array
+ uint8_t pcrSelect[PCR_SELECT_MAX];
+ } PACKED;
+ typedef struct _TPMS_PCR_SELECTION TPMS_PCR_SELECTION;
+ uint8_t* TPMS_PCR_SELECTION_marshal(const TPMS_PCR_SELECTION* val,
+ uint8_t* o_tpmBuf, size_t i_tpmBufSize,
+ size_t* io_cmdSize);
+ const uint8_t* TPMS_PCR_SELECTION_unmarshal(TPMS_PCR_SELECTION* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize);
+
+
+ struct _TPM2B_DIGEST
+ {
+ uint16_t size;
+ uint8_t buffer[sizeof(TPMU_HA)];
+ } PACKED;
+ typedef struct _TPM2B_DIGEST TPM2B_DIGEST;
+ const uint8_t* TPM2B_DIGEST_unmarshal(TPM2B_DIGEST* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize);
+
+ struct _TPML_DIGEST
+ {
+ uint32_t count;
+ TPM2B_DIGEST digests[HASH_COUNT];
+ } PACKED;
+ typedef struct _TPML_DIGEST TPML_DIGEST;
+ const uint8_t* TPML_DIGEST_unmarshal(TPML_DIGEST* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize);
+
+ struct _TPML_PCR_SELECTION
+ {
+ uint32_t count;
+ TPMS_PCR_SELECTION pcrSelections[HASH_COUNT];
+ } PACKED;
+ typedef struct _TPML_PCR_SELECTION TPML_PCR_SELECTION;
+ uint8_t* TPML_PCR_SELECTION_marshal(const TPML_PCR_SELECTION* val,
+ uint8_t* o_tpmBuf, size_t i_tpmBufSize,
+ size_t* io_cmdSize);
+ const uint8_t* TPML_PCR_SELECTION_unmarshal(TPML_PCR_SELECTION* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize);
+
+ /// Incoming PCR_Read structure
+ struct _TPM2_PcrReadIn
+ {
+ TPM2_BaseIn base;
+ TPML_PCR_SELECTION pcrSelectionIn;
+ } PACKED;
+ typedef struct _TPM2_PcrReadIn TPM2_PcrReadIn;
+ uint8_t* TPM2_PcrReadIn_marshal(const TPM2_PcrReadIn* val,
+ uint8_t* o_tpmBuf, size_t i_tpmBufSize,
+ size_t* io_cmdSize);
+
+ /// Outgoing Pcr_Read structure
+ struct _TPM2_PcrReadOut
+ {
+ TPM2_BaseOut base;
+ uint32_t pcrUpdateCounter;
+ TPML_PCR_SELECTION pcrSelectionOut;
+ TPML_DIGEST pcrValues;
+ } PACKED;
+ typedef struct _TPM2_PcrReadOut TPM2_PcrReadOut;
+ const uint8_t* TPM2_PcrReadOut_unmarshal(TPM2_PcrReadOut* val,
+ const uint8_t* i_tpmBuf,
+ size_t* io_tpmBufSize,
+ size_t i_outBufSize);
+
+ /// TPM Authorization structure
+ /// This is not the full structure and only works for PW auth with NULL PW
+ struct _TPMS_AUTH_COMMAND
+ {
+ uint32_t sessionHandle;
+ uint16_t nonceSize; ///< Size of nonce structure, currently 0
+ uint8_t sessionAttributes; ///< Session attributes
+ uint16_t hmacSize; ///< Size of hmac structure, currently 0
+ } PACKED;
+ typedef struct _TPMS_AUTH_COMMAND TPMS_AUTH_COMMAND;
+ uint8_t* TPMS_AUTH_COMMAND_marshal(const TPMS_AUTH_COMMAND* val,
+ uint8_t* o_tpmBuf, size_t i_tpmBufSize,
+ size_t* io_cmdSize);
+
+#ifdef __cplusplus
+} // end TRUSTEDBOOT namespace
+#endif
+
+#endif
+
diff --git a/libstb/tss/trustedbootCmds.C b/libstb/tss/trustedbootCmds.C
new file mode 100644
index 0000000..796af16
--- /dev/null
+++ b/libstb/tss/trustedbootCmds.C
@@ -0,0 +1,1016 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/trusted/trustedbootCmds.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file trustedbootCmds.C
+ *
+ * @brief Trusted boot TPM command interfaces
+ */
+
+/////////////////////////////////////////////////////////////////
+// NOTE: This file is exportable as TSS-Lite for skiboot/PHYP //
+/////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include <string.h>
+#include <stdlib.h>
+#ifdef __HOSTBOOT_MODULE
+#include <secureboot/trustedboot_reasoncodes.H>
+#include "trustedboot.H"
+#else
+#include "trustedboot_reasoncodes.H"
+#endif
+#include "trustedbootCmds.H"
+#include "trustedbootUtils.H"
+#include "trustedTypes.H"
+
+#ifdef __cplusplus
+namespace TRUSTEDBOOT
+{
+#endif
+
+errlHndl_t tpmTransmitCommand(TpmTarget * io_target,
+ uint8_t* io_buffer,
+ size_t i_bufsize )
+{
+ errlHndl_t err = TB_SUCCESS;
+ uint8_t* transmitBuf = NULL;
+ size_t cmdSize = 0;
+ size_t dataSize = 0;
+ TPM2_BaseIn* cmd = (TPM2_BaseIn*)io_buffer;
+ TPM2_BaseOut* resp = (TPM2_BaseOut*)io_buffer;
+
+ TRACUCOMP( g_trac_trustedboot,
+ ">>TPM TRANSMIT CMD START : BufLen %d : %016llx",
+ (int)i_bufsize,
+ *((uint64_t*)io_buffer) );
+
+ do
+ {
+ transmitBuf = (uint8_t*)malloc(MAX_TRANSMIT_SIZE);
+
+ // Marshal the data into a byte array for transfer to the TPM
+ err = tpmMarshalCommandData(cmd,
+ transmitBuf,
+ MAX_TRANSMIT_SIZE,
+ &cmdSize);
+ if (TB_SUCCESS != err)
+ {
+ break;
+ }
+
+ // Send to the TPM
+ dataSize = MAX_TRANSMIT_SIZE;
+#ifdef __HOSTBOOT_MODULE
+ err = tpmTransmit(io_target,
+ transmitBuf,
+ cmdSize,
+ dataSize);
+#else
+ err = io_target->driver->transmit(io_target->dev,
+ transmitBuf,
+ cmdSize,
+ &dataSize);
+#endif
+
+ if (TB_SUCCESS != err)
+ {
+ break;
+ }
+
+ // Unmarshal the response
+ err = tpmUnmarshalResponseData(cmd->commandCode,
+ transmitBuf,
+ dataSize,
+ resp,
+ i_bufsize);
+
+
+ } while ( 0 );
+
+
+ free(transmitBuf);
+
+ TRACUCOMP( g_trac_trustedboot,
+ "<<tpmTransmitCommand() - %s",
+ ((TB_SUCCESS == err) ? "No Error" : "With Error") );
+ return err;
+}
+
+errlHndl_t tpmMarshalCommandData(TPM2_BaseIn* i_cmd,
+ uint8_t* o_outbuf,
+ size_t i_bufsize,
+ size_t* o_cmdSize)
+{
+ errlHndl_t err = TB_SUCCESS;
+ uint8_t* sBuf = o_outbuf;
+ uint32_t* sSizePtr = NULL;
+ size_t curSize = 0;
+ int stage = 0;
+ TPM2_BaseIn* baseCmd =
+ (TPM2_BaseIn*)o_outbuf;
+ TPMS_AUTH_COMMAND cmdAuth;
+
+ *o_cmdSize = 0;
+
+ TRACDCOMP( g_trac_trustedboot,
+ ">>tpmMarshalCommandData()" );
+ do
+ {
+
+ TRACUCOMP( g_trac_trustedboot,
+ "TPM MARSHAL START : BufLen %d : %016llx",
+ (int)i_bufsize,
+ *((uint64_t*)i_cmd) );
+
+ // Start with the command header
+ sBuf = TPM2_BaseIn_marshal(i_cmd, sBuf, i_bufsize, o_cmdSize);
+ if (NULL == sBuf)
+ {
+ break;
+ }
+
+ // Marshal the handles
+ stage = 1;
+ if (TPM_CC_PCR_Extend == i_cmd->commandCode)
+ {
+ TPM2_ExtendIn* cmdPtr = (TPM2_ExtendIn*)i_cmd;
+ sBuf = TPM2_ExtendIn_marshalHandle(cmdPtr,
+ sBuf,
+ i_bufsize,
+ o_cmdSize);
+ if (NULL == sBuf)
+ {
+ break;
+ }
+ }
+
+ // Marshal the authorizations
+ stage = 2;
+ if (TPM_CC_PCR_Extend == i_cmd->commandCode)
+ {
+ // Insert a password authorization with a null pw
+ // Make room for the 4 byte size field at the beginning
+ sSizePtr = (uint32_t*)sBuf;
+ sBuf += sizeof(uint32_t);
+ *o_cmdSize += sizeof(uint32_t);
+ i_bufsize -= sizeof(uint32_t);
+ curSize = *o_cmdSize;
+
+ cmdAuth.sessionHandle = TPM_RS_PW;
+ cmdAuth.nonceSize = 0;
+ cmdAuth.sessionAttributes = 0;
+ cmdAuth.hmacSize = 0;
+
+ sBuf = TPMS_AUTH_COMMAND_marshal(&cmdAuth, sBuf, i_bufsize,
+ o_cmdSize);
+
+ if (NULL == sBuf)
+ {
+ break;
+ }
+ // Put in the size of the auth area
+ *sSizePtr = (*o_cmdSize - curSize);
+
+ }
+
+ // Marshal the command parameters
+ stage = 3;
+ switch (i_cmd->commandCode)
+ {
+ // Two byte parm fields
+ case TPM_CC_Startup:
+ {
+ TPM2_2ByteIn* cmdPtr =
+ (TPM2_2ByteIn*)i_cmd;
+ sBuf = TPM2_2ByteIn_marshal(cmdPtr, sBuf,
+ i_bufsize, o_cmdSize);
+ }
+ break;
+
+ case TPM_CC_GetCapability:
+ {
+ TPM2_GetCapabilityIn* cmdPtr =
+ (TPM2_GetCapabilityIn*)i_cmd;
+ sBuf = TPM2_GetCapabilityIn_marshal(cmdPtr,sBuf,
+ i_bufsize, o_cmdSize);
+ }
+ break;
+ case TPM_CC_PCR_Read:
+ {
+ TPM2_PcrReadIn* cmdPtr = (TPM2_PcrReadIn*)i_cmd;
+ sBuf = TPM2_PcrReadIn_marshal(cmdPtr, sBuf,
+ i_bufsize - (sBuf - o_outbuf),
+ o_cmdSize);
+ }
+ break;
+
+ case TPM_CC_PCR_Extend:
+ {
+ TPM2_ExtendIn* cmdPtr = (TPM2_ExtendIn*)i_cmd;
+ sBuf = TPM2_ExtendIn_marshalParms(cmdPtr, sBuf,
+ i_bufsize, o_cmdSize);
+ }
+ break;
+
+ default:
+ {
+ // Command code not supported
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM MARSHAL INVALID COMMAND : %X",
+ i_cmd->commandCode );
+ sBuf = NULL;
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_MARSHAL_INVALID_CMD
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_MARSHALCMDDATA
+ * @userdata1 Command Code
+ * @userdata2 0
+ * @devdesc Unsupported command code during marshal
+ */
+ err = tpmCreateErrorLog(MOD_TPM_MARSHALCMDDATA,
+ RC_TPM_MARSHAL_INVALID_CMD,
+ i_cmd->commandCode,
+ 0);
+ }
+ break;
+ };
+
+ if (TB_SUCCESS != err || NULL == sBuf)
+ {
+ break;
+ }
+
+ // Do a verification that the cmdSize equals what we used
+ if (((size_t)(sBuf - o_outbuf)) != *o_cmdSize)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM MARSHAL MARSHAL SIZE MISMATCH : %d %d",
+ (int)(sBuf - o_outbuf), (int)(*o_cmdSize) );
+ sBuf = NULL;
+ }
+
+ // Lastly now that we know the size update the byte stream
+ baseCmd->commandSize = *o_cmdSize;
+
+ } while ( 0 );
+
+ if (NULL == sBuf && TB_SUCCESS == err)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM MARSHAL FAILURE : Stage %d", stage);
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_MARSHALING_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_MARSHALCMDDATA
+ * @userdata1 stage
+ * @userdata2 0
+ * @devdesc Marshaling error detected
+ */
+ err = tpmCreateErrorLog(MOD_TPM_MARSHALCMDDATA,
+ RC_TPM_MARSHALING_FAIL,
+ stage,
+ 0 );
+
+ }
+
+ TRACUBIN(g_trac_trustedboot, "Marshal Out",
+ o_outbuf, *o_cmdSize);
+
+ TRACUCOMP( g_trac_trustedboot,
+ "TPM MARSHAL END : CmdSize: %d : %016llx ",
+ (int)(*o_cmdSize),
+ *((uint64_t*)o_outbuf) );
+
+ TRACDCOMP( g_trac_trustedboot,
+ "<<tpmMarshalCommandData()" );
+
+ return err;
+}
+
+errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode,
+ uint8_t* i_respBuf,
+ size_t i_respBufSize,
+ TPM2_BaseOut* o_outBuf,
+ size_t i_outBufSize)
+{
+ errlHndl_t err = TB_SUCCESS;
+ const uint8_t* sBuf = i_respBuf;
+ int stage = 0;
+
+ TRACDCOMP( g_trac_trustedboot,
+ ">>tpmUnmarshalResponseData()" );
+
+ do {
+
+ TRACUCOMP( g_trac_trustedboot,
+ "TPM UNMARSHAL START : RespBufLen %d : OutBufLen %d",
+ (int)i_respBufSize, (int)i_outBufSize);
+ TRACUBIN(g_trac_trustedboot,"Unmarshal In",
+ i_respBuf, i_respBufSize);
+
+
+ // Start with the response header
+ stage = 1;
+ sBuf = TPM2_BaseOut_unmarshal(o_outBuf, sBuf,
+ &i_respBufSize, i_outBufSize);
+ if (NULL == sBuf)
+ {
+ break;
+ }
+
+ // If the TPM returned a failure it will not send the rest
+ // Let the caller deal with the RC
+ if (TPM_SUCCESS != o_outBuf->responseCode)
+ {
+ break;
+ }
+
+
+ // Unmarshal the parameters
+ stage = 2;
+ switch (i_commandCode)
+ {
+ // Empty response commands
+ case TPM_CC_Startup:
+ case TPM_CC_PCR_Extend:
+ // Nothing to do
+ break;
+
+ case TPM_CC_GetCapability:
+ {
+ TPM2_GetCapabilityOut* respPtr =
+ (TPM2_GetCapabilityOut*)o_outBuf;
+ sBuf = TPM2_GetCapabilityOut_unmarshal(respPtr, sBuf,
+ &i_respBufSize,
+ i_outBufSize);
+
+ }
+ break;
+
+ case TPM_CC_PCR_Read:
+ {
+ TPM2_PcrReadOut* respPtr = (TPM2_PcrReadOut*)o_outBuf;
+ sBuf = TPM2_PcrReadOut_unmarshal(respPtr, sBuf,
+ &i_respBufSize,
+ i_outBufSize);
+ }
+ break;
+
+ default:
+ {
+ // Command code not supported
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM UNMARSHAL INVALID COMMAND : %X",
+ i_commandCode );
+ sBuf = NULL;
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_UNMARSHAL_INVALID_CMD
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_UNMARSHALRESPDATA
+ * @userdata1 commandcode
+ * @userdata2 stage
+ * @devdesc Unsupported command code during unmarshal
+ */
+ err = tpmCreateErrorLog(MOD_TPM_UNMARSHALRESPDATA,
+ RC_TPM_UNMARSHAL_INVALID_CMD,
+ i_commandCode,
+ stage);
+ }
+ break;
+ }
+
+
+ } while ( 0 );
+
+ if (NULL == sBuf && TB_SUCCESS == err)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM UNMARSHAL FAILURE : Stage %d", stage);
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_UNMARSHALING_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_UNMARSHALRESPDATA
+ * @userdata1 Stage
+ * @userdata2 Remaining response buffer size
+ * @devdesc Unmarshaling error detected
+ */
+ err = tpmCreateErrorLog(MOD_TPM_UNMARSHALRESPDATA,
+ RC_TPM_UNMARSHALING_FAIL,
+ stage,
+ i_respBufSize);
+
+
+
+ }
+
+ TRACUCOMP( g_trac_trustedboot,
+ "TPM UNMARSHAL END : %016llx ",
+ *((uint64_t*)o_outBuf) );
+
+ TRACDCOMP( g_trac_trustedboot,
+ "<<tpmUnmarshalResponseData()" );
+
+ return err;
+}
+
+errlHndl_t tpmCmdStartup(TpmTarget* io_target)
+{
+ errlHndl_t err = TB_SUCCESS;
+ uint8_t dataBuf[BUFSIZE];
+
+ TPM2_BaseOut* resp =
+ (TPM2_BaseOut*)(dataBuf);
+
+ TPM2_2ByteIn* cmd =
+ (TPM2_2ByteIn*)(dataBuf);
+
+ TRACUCOMP( g_trac_trustedboot,
+ ">>tpmCmdStartup()" );
+
+ do
+ {
+ // Send the TPM startup command
+ // Build our command block for a startup
+ memset(dataBuf, 0, sizeof(dataBuf));
+
+
+ cmd->base.tag = TPM_ST_NO_SESSIONS;
+ cmd->base.commandCode = TPM_CC_Startup;
+ cmd->param = TPM_SU_CLEAR;
+
+ err = tpmTransmitCommand(io_target,
+ dataBuf,
+ sizeof(dataBuf));
+
+ if (TB_SUCCESS != err)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM STARTUP transmit Fail");
+ break;
+
+ }
+ else if (TPM_SUCCESS != resp->responseCode)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM STARTUP OP Fail %X : ",
+ resp->responseCode);
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_START_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_CMD_STARTUP
+ * @userdata1 responseCode
+ * @userdata2 0
+ * @devdesc Invalid operation type.
+ */
+ err = tpmCreateErrorLog(MOD_TPM_CMD_STARTUP,
+ RC_TPM_START_FAIL,
+ resp->responseCode,
+ 0);
+
+ break;
+ }
+
+
+ } while ( 0 );
+
+
+ TRACUCOMP( g_trac_trustedboot,
+ "<<tpmCmdStartup() - %s",
+ ((TB_SUCCESS == err) ? "No Error" : "With Error") );
+ return err;
+}
+
+errlHndl_t tpmCmdGetCapFwVersion(TpmTarget* io_target)
+{
+ errlHndl_t err = TB_SUCCESS;
+ uint8_t dataBuf[BUFSIZE];
+ size_t dataSize = BUFSIZE;
+ uint16_t fwVersion[4] = {0xFF, 0xFF, 0xFF, 0xFF};
+ TPM2_GetCapabilityOut* resp =
+ (TPM2_GetCapabilityOut*)dataBuf;
+ TPM2_GetCapabilityIn* cmd =
+ (TPM2_GetCapabilityIn*)dataBuf;
+
+
+ TRACUCOMP( g_trac_trustedboot,
+ ">>tpmCmdGetCapFwVersion()" );
+
+ do
+ {
+
+ // Build our command block for a get capability of the FW version
+ memset(dataBuf, 0, dataSize);
+
+ cmd->base.tag = TPM_ST_NO_SESSIONS;
+ cmd->base.commandCode = TPM_CC_GetCapability;
+ cmd->capability = TPM_CAP_TPM_PROPERTIES;
+ cmd->property = TPM_PT_FIRMWARE_VERSION_1;
+ cmd->propertyCount = 1;
+
+ err = tpmTransmitCommand(io_target,
+ dataBuf,
+ sizeof(dataBuf));
+
+ if (TB_SUCCESS != err)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM GETCAP Transmit Fail");
+ break;
+
+ }
+
+ if (TPM_SUCCESS != resp->base.responseCode)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM GETCAP OP Fail %X Size(%d) ",
+ resp->base.responseCode,
+ (int)dataSize);
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_GETCAP_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_CMD_GETCAPFWVERSION
+ * @userdata1 responseCode
+ * @userdata2 0
+ * @devdesc Command failure reading TPM FW version.
+ */
+ err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
+ RC_TPM_GETCAP_FAIL,
+ resp->base.responseCode,
+ 0);
+
+ break;
+ }
+ else
+ {
+ // Walk the reponse data to pull the high order bytes out
+
+ if (resp->capData.capability != TPM_CAP_TPM_PROPERTIES ||
+ resp->capData.data.tpmProperties.count != 1 ||
+ resp->capData.data.tpmProperties.tpmProperty[0].property !=
+ TPM_PT_FIRMWARE_VERSION_1) {
+
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM GETCAP FW INVALID DATA "
+ "Cap(%X) Cnt(%X) Prop(%X)",
+ resp->capData.capability,
+ resp->capData.data.tpmProperties.count,
+ resp->capData.data.tpmProperties.
+ tpmProperty[0].property);
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_GETCAP_FW_INVALID_RESP
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_CMD_GETCAPFWVERSION
+ * @userdata1 capability
+ * @userdata2 property
+ * @devdesc Command failure reading TPM FW version.
+ */
+ err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
+ RC_TPM_GETCAP_FW_INVALID_RESP,
+ resp->capData.capability,
+ resp->capData.data.tpmProperties.
+ tpmProperty[0].property);
+
+ break;
+ }
+ else
+ {
+ fwVersion[0] =
+ (resp->capData.data.
+ tpmProperties.tpmProperty[0].value >> 16);
+ fwVersion[1] =
+ (resp->capData.data.
+ tpmProperties.tpmProperty[0].value & 0xFFFF);
+ }
+
+ }
+
+ // Read part 2 of the version
+ dataSize = BUFSIZE;
+ memset(dataBuf, 0, dataSize);
+
+ cmd->base.tag = TPM_ST_NO_SESSIONS;
+ cmd->base.commandCode = TPM_CC_GetCapability;
+ cmd->capability = TPM_CAP_TPM_PROPERTIES;
+ cmd->property = TPM_PT_FIRMWARE_VERSION_2;
+ cmd->propertyCount = 1;
+
+
+ err = tpmTransmitCommand(io_target,
+ dataBuf,
+ sizeof(dataBuf));
+
+ if (TB_SUCCESS != err)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM GETCAP2 Transmit Fail");
+ break;
+
+ }
+
+ if ((sizeof(TPM2_GetCapabilityOut) > dataSize) ||
+ (TPM_SUCCESS != resp->base.responseCode))
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM GETCAP2 OP Fail %X Size(%d) ",
+ resp->base.responseCode,
+ (int)dataSize);
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_GETCAP2_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_CMD_GETCAPFWVERSION
+ * @userdata1 responseCode
+ * @userdata2 0
+ * @devdesc Command failure reading TPM FW version.
+ */
+ err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
+ RC_TPM_GETCAP2_FAIL,
+ resp->base.responseCode,
+ 0);
+
+ break;
+ }
+ else
+ {
+ // Walk the reponse data to pull the high order bytes out
+
+ if (resp->capData.capability != TPM_CAP_TPM_PROPERTIES ||
+ resp->capData.data.tpmProperties.count != 1 ||
+ resp->capData.data.tpmProperties.tpmProperty[0].property !=
+ TPM_PT_FIRMWARE_VERSION_2) {
+
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM GETCAP2 FW INVALID DATA "
+ "Cap(%X) Cnt(%X) Prop(%X)",
+ resp->capData.capability,
+ resp->capData.data.tpmProperties.count,
+ resp->capData.data.tpmProperties.
+ tpmProperty[0].property);
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_GETCAP2_FW_INVALID_RESP
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_CMD_GETCAPFWVERSION
+ * @userdata1 capability
+ * @userdata2 property
+ * @devdesc Command failure reading TPM FW version.
+ */
+ err = tpmCreateErrorLog(MOD_TPM_CMD_GETCAPFWVERSION,
+ RC_TPM_GETCAP2_FW_INVALID_RESP,
+ resp->capData.capability,
+ resp->capData.data.tpmProperties.
+ tpmProperty[0].property);
+ break;
+ }
+ else
+ {
+ fwVersion[2] =
+ (resp->capData.data.tpmProperties.
+ tpmProperty[0].value >> 16);
+ fwVersion[3] =
+ (resp->capData.data.tpmProperties.
+ tpmProperty[0].value & 0xFFFF);
+ }
+ // Trace the response
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM GETCAP FW Level %d.%d.%d.%d",
+ fwVersion[0],fwVersion[1],fwVersion[2],fwVersion[3]
+ );
+ }
+
+
+ } while ( 0 );
+
+
+ TRACDCOMP( g_trac_trustedboot,
+ "<<tpmCmdGetCapFwVersion() - %s",
+ ((TB_SUCCESS == err) ? "No Error" : "With Error") );
+ return err;
+}
+
+
+errlHndl_t tpmCmdPcrExtend(TpmTarget * io_target,
+ TPM_Pcr i_pcr,
+ TPM_Alg_Id i_algId,
+ const uint8_t* i_digest,
+ size_t i_digestSize)
+{
+ return tpmCmdPcrExtend2Hash(io_target, i_pcr,
+ i_algId, i_digest, i_digestSize,
+ TPM_ALG_INVALID_ID, NULL, 0);
+}
+
+errlHndl_t tpmCmdPcrExtend2Hash(TpmTarget * io_target,
+ TPM_Pcr i_pcr,
+ TPM_Alg_Id i_algId_1,
+ const uint8_t* i_digest_1,
+ size_t i_digestSize_1,
+ TPM_Alg_Id i_algId_2,
+ const uint8_t* i_digest_2,
+ size_t i_digestSize_2)
+{
+ errlHndl_t err = NULL;
+ uint8_t dataBuf[sizeof(TPM2_ExtendIn)];
+ size_t dataSize = sizeof(dataBuf);
+ size_t fullDigestSize_1 = 0;
+ size_t fullDigestSize_2 = 0;
+ TPM2_BaseOut* resp = (TPM2_BaseOut*)dataBuf;
+ TPM2_ExtendIn* cmd = (TPM2_ExtendIn*)dataBuf;
+
+
+ TRACDCOMP( g_trac_trustedboot,
+ ">>tpmCmdPcrExtend2Hash()" );
+ if (NULL == i_digest_2)
+ {
+ TRACUCOMP( g_trac_trustedboot,
+ ">>tpmCmdPcrExtend2Hash() Pcr(%d) Alg(%X) DS(%d)",
+ i_pcr, i_algId_1, (int)i_digestSize_1);
+ }
+ else
+ {
+ TRACUCOMP( g_trac_trustedboot,
+ ">>tpmCmdPcrExtend2Hash() Pcr(%d) Alg(%X:%X) DS(%d:%d)",
+ i_pcr, i_algId_1, i_algId_2,
+ (int)i_digestSize_1, (int)i_digestSize_2);
+ }
+
+ do
+ {
+
+ fullDigestSize_1 = getDigestSize(i_algId_1);
+ if (NULL != i_digest_2)
+ {
+ fullDigestSize_2 = getDigestSize(i_algId_2);
+ }
+
+ // Build our command block
+ memset(dataBuf, 0, sizeof(dataBuf));
+
+ // Argument verification
+ if (fullDigestSize_1 == 0 ||
+ NULL == i_digest_1 ||
+ IMPLEMENTATION_PCR < i_pcr ||
+ (NULL != i_digest_2 && fullDigestSize_2 == 0)
+ )
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM PCR EXTEND ARG FAILURE FDS(%d:%d) DS(%d:%d) "
+ "PCR(%d)",
+ (int)fullDigestSize_1, (int)fullDigestSize_2,
+ (int)i_digestSize_1, (int)i_digestSize_2, i_pcr);
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_INVALID_ARGS
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_CMD_PCREXTEND
+ * @userdata1 Digest Ptr
+ * @userdata2[0:15] Full Digest Size 1
+ * @userdata2[16:31] Full Digest Size 2
+ * @userdata2[32:63] PCR
+ * @devdesc Unmarshaling error detected
+ */
+ err = tpmCreateErrorLog(MOD_TPM_CMD_PCREXTEND,
+ RC_TPM_INVALID_ARGS,
+ (uint64_t)i_digest_1,
+ (fullDigestSize_1 << 48) |
+ (fullDigestSize_2 << 32) |
+ i_pcr);
+ break;
+ }
+
+ // Log the input PCR value
+ TRACUBIN(g_trac_trustedboot, "PCR In",
+ i_digest_1, fullDigestSize_1);
+
+ cmd->base.tag = TPM_ST_SESSIONS;
+ cmd->base.commandCode = TPM_CC_PCR_Extend;
+ cmd->pcrHandle = i_pcr;
+ cmd->digests.count = 1;
+ cmd->digests.digests[0].algorithmId = i_algId_1;
+ memcpy(&(cmd->digests.digests[0].digest), i_digest_1,
+ (i_digestSize_1 < fullDigestSize_1 ?
+ i_digestSize_1 : fullDigestSize_1) );
+ if (NULL != i_digest_2)
+ {
+ cmd->digests.count = 2;
+ cmd->digests.digests[1].algorithmId = i_algId_2;
+ memcpy(&(cmd->digests.digests[1].digest), i_digest_2,
+ (i_digestSize_2 < fullDigestSize_2 ?
+ i_digestSize_2 : fullDigestSize_2));
+ }
+
+ err = tpmTransmitCommand(io_target,
+ dataBuf,
+ sizeof(dataBuf));
+
+ if (TB_SUCCESS != err)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM PCRExtend Transmit Fail");
+ break;
+
+ }
+ else if ((sizeof(TPM2_BaseOut) > dataSize)
+ || (TPM_SUCCESS != resp->responseCode))
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM PCRExtend OP Fail Ret(%X) ExSize(%d) Size(%d) ",
+ resp->responseCode,
+ (int)sizeof(TPM2_BaseOut),
+ (int)dataSize);
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_COMMAND_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_CMD_PCREXTEND
+ * @userdata1 responseCode
+ * @userdata2 dataSize
+ * @devdesc Command failure reading TPM FW version.
+ */
+ err = tpmCreateErrorLog(MOD_TPM_CMD_PCREXTEND,
+ RC_TPM_COMMAND_FAIL,
+ resp->responseCode,
+ dataSize);
+ break;
+
+ }
+
+ } while ( 0 );
+
+
+ TRACUCOMP( g_trac_trustedboot,
+ "<<tpmCmdPcrExtend() - %s",
+ ((TB_SUCCESS == err) ? "No Error" : "With Error") );
+ return err;
+
+}
+
+errlHndl_t tpmCmdPcrRead(TpmTarget* io_target,
+ TPM_Pcr i_pcr,
+ TPM_Alg_Id i_algId,
+ uint8_t* o_digest,
+ size_t i_digestSize)
+{
+ errlHndl_t err = NULL;
+ uint8_t dataBuf[sizeof(TPM2_PcrReadOut)];
+ size_t dataSize = sizeof(dataBuf);
+ size_t fullDigestSize = 0;
+ TPM2_PcrReadOut* resp = (TPM2_PcrReadOut*)dataBuf;
+ TPM2_PcrReadIn* cmd = (TPM2_PcrReadIn*)dataBuf;
+
+
+ TRACDCOMP( g_trac_trustedboot,
+ ">>tpmCmdPcrRead()" );
+ TRACUCOMP( g_trac_trustedboot,
+ ">>tpmCmdPcrRead() Pcr(%d) DS(%d)",
+ i_pcr, (int)i_digestSize);
+
+ do
+ {
+
+ fullDigestSize = getDigestSize(i_algId);
+
+ // Build our command block
+ memset(dataBuf, 0, sizeof(dataBuf));
+
+ // Argument verification
+ if (fullDigestSize > i_digestSize ||
+ NULL == o_digest ||
+ IMPLEMENTATION_PCR < i_pcr
+ )
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM PCR READ ARG FAILURE FDS(%d) DS(%d) PCR(%d)",
+ (int)fullDigestSize, (int)i_digestSize, i_pcr);
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_INVALID_ARGS
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_CMD_PCRREAD
+ * @userdata1 Digest Ptr
+ * @userdata2[0:31] Full Digest Size
+ * @userdata2[32:63] PCR
+ * @devdesc Unmarshaling error detected
+ */
+ err = tpmCreateErrorLog(MOD_TPM_CMD_PCRREAD,
+ RC_TPM_INVALID_ARGS,
+ (uint64_t)o_digest,
+ (fullDigestSize << 32) |
+ i_pcr);
+
+ break;
+ }
+
+ cmd->base.tag = TPM_ST_NO_SESSIONS;
+ cmd->base.commandCode = TPM_CC_PCR_Read;
+ cmd->pcrSelectionIn.count = 1; // One algorithm
+ cmd->pcrSelectionIn.pcrSelections[0].algorithmId = i_algId;
+ cmd->pcrSelectionIn.pcrSelections[0].sizeOfSelect = PCR_SELECT_MAX;
+ memset(cmd->pcrSelectionIn.pcrSelections[0].pcrSelect, 0,
+ sizeof(cmd->pcrSelectionIn.pcrSelections[0].pcrSelect));
+ cmd->pcrSelectionIn.pcrSelections[0].pcrSelect[i_pcr / 8] =
+ 0x01 << (i_pcr % 8);
+
+ err = tpmTransmitCommand(io_target,
+ dataBuf,
+ sizeof(dataBuf));
+
+ if (TB_SUCCESS != err)
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM PCRRead Transmit Fail ");
+ break;
+
+ }
+ else if ((sizeof(TPM2_BaseOut) > dataSize) ||
+ (TPM_SUCCESS != resp->base.responseCode) ||
+ (resp->pcrValues.count != 1) ||
+ (resp->pcrValues.digests[0].size != fullDigestSize))
+ {
+ TRACFCOMP( g_trac_trustedboot,
+ "TPM PCRRead OP Fail Ret(%X) ExSize(%d) "
+ "Size(%d) Cnt(%d) DSize(%d)",
+ resp->base.responseCode,
+ (int)sizeof(TPM2_BaseOut),
+ (int)dataSize,
+ resp->pcrValues.count,
+ resp->pcrValues.digests[0].size);
+
+ /*@
+ * @errortype
+ * @reasoncode RC_TPM_COMMAND_FAIL
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_TPM_CMD_PCRREAD
+ * @userdata1 responseCode
+ * @userdata2 dataSize
+ * @devdesc Command failure reading TPM FW version.
+ */
+ err = tpmCreateErrorLog(MOD_TPM_CMD_PCRREAD,
+ RC_TPM_COMMAND_FAIL,
+ resp->base.responseCode,
+ dataSize);
+ break;
+ }
+ else
+ {
+
+ memcpy(o_digest, resp->pcrValues.digests[0].buffer, fullDigestSize);
+
+ // Log the PCR value
+ TRACUBIN(g_trac_trustedboot, "PCR Out",
+ o_digest, fullDigestSize);
+
+ }
+
+ } while ( 0 );
+
+
+ TRACUCOMP( g_trac_trustedboot,
+ "<<tpmCmdPcrRead() - %s",
+ ((TB_SUCCESS == err) ? "No Error" : "With Error") );
+ return err;
+
+}
+
+
+#ifdef __cplusplus
+} // end TRUSTEDBOOT
+#endif
diff --git a/libstb/tss/trustedbootCmds.H b/libstb/tss/trustedbootCmds.H
new file mode 100644
index 0000000..0a72c19
--- /dev/null
+++ b/libstb/tss/trustedbootCmds.H
@@ -0,0 +1,177 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/trusted/trustedbootCmds.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file trustedbootCmds.H
+ *
+ * @brief Trustedboot TPM command interfaces
+ */
+
+/////////////////////////////////////////////////////////////////
+// NOTE: This file is exportable as TSS-Lite for skiboot/PHYP //
+/////////////////////////////////////////////////////////////////
+
+#ifndef __TRUSTEDBOOTCMDS_H
+#define __TRUSTEDBOOTCMDS_H
+// -----------------------------------------------
+// Includes
+// -----------------------------------------------
+#ifdef __HOSTBOOT_MODULE
+#include <secureboot/trustedbootif.H>
+#include "trustedboot.H"
+#else
+#include "trustedbootUtils.H"
+#include "../tpm.h"
+#endif
+#include "trustedTypes.H"
+
+#ifdef __cplusplus
+namespace TRUSTEDBOOT
+{
+#endif
+
+enum
+{
+ BUFSIZE = 256,
+ MAX_TRANSMIT_SIZE = 1024, ///< Maximum send/receive transmit size
+};
+
+/**
+ * @brief Transmit the command to the TPM and perform marshaling
+ * @param[in/out] io_target Current TPM target structure
+ * @param[in/out] io_buffer Input the command buffer to send, response on exit
+ * @param[in] i_bufsize Size of io_buffer in bytes
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t tpmTransmitCommand(TpmTarget* io_target,
+ uint8_t* io_buffer,
+ size_t i_bufsize );
+
+/**
+ * @brief Take structure pointed to by cmd and format for input into TPM
+ * @param[in] i_cmd Prefilled command input structure
+ * @param[out] o_outbuf Buffer to place marshalled data
+ * @param[in] i_bufsize Size of o_outbuf in bytes
+ * @param[out] o_cmdSize Byte size of io_outbuf data after marshal
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t tpmMarshalCommandData(TPM2_BaseIn* i_cmd,
+ uint8_t* o_outbuf,
+ size_t i_bufsize,
+ size_t* o_cmdSize);
+
+/**
+ * @brief Take structure pointed to by cmd and format for input into TPM
+ * @param[in] i_commandCode Command code that was executed on the TPM
+ * @param[in] i_respBuf Buffer with response data from TPM
+ * @param[in] i_respBufSize Byte size of respBuf buffer from TPM
+ * @param[out] o_outBuf Buffer to place formatted response data
+ * @param[in] i_outBufSize Byte size of o_outBuf buffer
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t tpmUnmarshalResponseData(uint32_t i_commandCode,
+ uint8_t* i_respBuf,
+ size_t i_respBufSize,
+ TPM2_BaseOut* o_outBuf,
+ size_t i_outBufSize);
+/**
+ * @brief Send the TPM_STARTUP command to the targetted TPM
+ * @param[in/out] io_target Current TPM target structure
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+*/
+errlHndl_t tpmCmdStartup(TpmTarget* io_target);
+
+/**
+ * @brief Send the TPM_GETCAPABILITY command to read FW version from TPM
+ * @param[in/out] io_target Current TPM target structure
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+*/
+
+errlHndl_t tpmCmdGetCapFwVersion(TpmTarget* io_target);
+
+/**
+ * @brief Send the TPM_Extend command to the targeted TPM and log
+ * @param[in/out] io_target Current TPM target structure
+ * @param[in] i_pcr PCR to write to
+ * @param[in] i_algId Algorithm to use
+ * @param[in] i_digest Digest value to write to PCR, zeros appended as needed
+ * @param[in] i_digestSize Byte size of i_digest array
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t tpmCmdPcrExtend(TpmTarget * io_target,
+ TPM_Pcr i_pcr,
+ TPM_Alg_Id i_algId,
+ const uint8_t* i_digest,
+ size_t i_digestSize);
+
+/**
+ * @brief Send the TPM_Extend command to the targeted TPM and log
+ * @param[in/out] io_target Current TPM target structure
+ * @param[in] i_pcr PCR to write to
+ * @param[in] i_algId_1 Algorithm to use
+ * @param[in] i_digest_1 Digest value to write to PCR, zeros appended as needed
+ * @param[in] i_digestSize_1 Byte size of i_digest_1 array
+ * @param[in] i_algId_2 Algorithm to use
+ * @param[in] i_digest_2 Digest value to write to PCR, zeros appended as needed
+ * NULL if second digest not used
+ * @param[in] i_digestSize_2 Byte size of i_digest_2 array
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t tpmCmdPcrExtend2Hash(TpmTarget * io_target,
+ TPM_Pcr i_pcr,
+ TPM_Alg_Id i_algId_1,
+ const uint8_t* i_digest_1,
+ size_t i_digestSize_1,
+ TPM_Alg_Id i_algId_2,
+ const uint8_t* i_digest_2,
+ size_t i_digestSize_2);
+
+/**
+ * @brief Send the TPM_Read command to the targeted TPM and log
+ * @param[in/out] io_target Current TPM target structure
+ * @param[in] i_pcr PCR to read from
+ * @param[in] i_algId Algorithm back to read from
+ * @param[out] o_digest Array to store PCR contents
+ * @param[in] i_digestSize Byte size of i_digest array
+ * @return errlHndl_t NULL if successful, otherwise a pointer to the
+ * error log.
+ */
+errlHndl_t tpmCmdPcrRead(TpmTarget* io_target,
+ TPM_Pcr i_pcr,
+ TPM_Alg_Id i_algId,
+ uint8_t* o_digest,
+ size_t i_digestSize);
+
+#ifdef __cplusplus
+} // end TRUSTEDBOOT namespace
+#endif
+
+#endif
diff --git a/libstb/tss/trustedbootUtils.C b/libstb/tss/trustedbootUtils.C
new file mode 100644
index 0000000..24b949f
--- /dev/null
+++ b/libstb/tss/trustedbootUtils.C
@@ -0,0 +1,22 @@
+/**
+ * @file trustedbootUtils.C
+ *
+ * @brief Trusted boot utility functions for skiboot
+ */
+
+// ----------------------------------------------
+// Includes
+// ----------------------------------------------
+#include <stdio.h>
+#include "trustedbootUtils.H"
+
+errlHndl_t tpmCreateErrorLog(const uint8_t i_modId,
+ const uint16_t i_reasonCode,
+ const uint64_t i_user1,
+ const uint64_t i_user2)
+{
+ printf("Error Log %d %d %d %d\n", i_modId, i_reasonCode,
+ (int)i_user1, (int)i_user2);
+ return (i_modId << 16) | i_reasonCode;
+}
+
diff --git a/libstb/tss/trustedbootUtils.H b/libstb/tss/trustedbootUtils.H
new file mode 100644
index 0000000..78fb0ce
--- /dev/null
+++ b/libstb/tss/trustedbootUtils.H
@@ -0,0 +1,85 @@
+ /* Copyright 2013-2016 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/***************************************************************
+ * This file redefines some structures and functions so we can
+ * export the Hostboot TSS-Light code to skiboot
+ ***************************************************************/
+
+#ifndef __TRUSTEDBOOTUTILS_H
+#define __TRUSTEDBOOTUTILS_H
+
+#include <skiboot.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <lock.h>
+
+/* Failure trace routines */
+#define TRACFCOMP(TB, fmt, ...) prlog(PR_ERR, "STB: " fmt "\n", ##__VA_ARGS__);
+//#define TRACFCOMP(args...)
+
+/* Debug trace routines */
+//#define TRACDCOMP(TB, fmt, ...) prlog(PR_DEBUG, "STB: " fmt "\n", ##__VA_ARGS__)
+#define TRACDCOMP(args...)
+
+//#define TRACUCOMP(TB, fmt, ...) prlog(PR_DEBUG, "STB: " fmt "\n", ##__VA_ARGS__);
+#define TRACUCOMP(args...)
+
+//#define TRACUBIN(TB, fmt, ...) prlog(PR_DEBUG, "STB: " fmt "\n", ##__VA_ARGS__);
+#define TRACUBIN(args...)
+
+/* Define a few routines that are different in skiboot */
+#define g_trac_trustedboot NULL
+#define g_trac_tpmdd NULL
+typedef uint32_t errlHndl_t;
+#define TB_SUCCESS 0
+#define htole32 CPU_TO_LE32
+#define le32toh LE32_TO_CPU
+#define le16toh LE16_TO_CPU
+#define htole16 CPU_TO_LE16
+
+#define mutex_init(mutex) init_lock(mutex)
+#define mutex_lock(mutex) lock(mutex)
+#define mutex_unlock(mutex) unlock(mutex)
+#define mutex_t struct lock
+
+/* TPM PCR designations */
+typedef enum
+{
+ PCR_0 = 0,
+ PCR_1 = 1,
+ PCR_2 = 2,
+ PCR_3 = 3,
+ PCR_4 = 4,
+ PCR_5 = 5,
+ PCR_6 = 6,
+ PCR_7 = 7,
+ IMPLEMENTATION_PCR = 24 // Number of PCRs implemented by TPM
+} TPM_Pcr;
+
+/**
+ * @brief Create an error log entry for potential logging
+ * @param[in] i_modId Code Module ID
+ * @param[in] i_reasonCode Error Reason Code
+ * @param[in] i_user1 User data 1
+ * @param[in] i_user2 User data 2
+ */
+errlHndl_t tpmCreateErrorLog(const uint8_t i_modId,
+ const uint16_t i_reasonCode,
+ const uint64_t i_user1,
+ const uint64_t i_user2);
+#endif
+
diff --git a/libstb/tss/trustedboot_reasoncodes.H b/libstb/tss/trustedboot_reasoncodes.H
new file mode 100644
index 0000000..2c63488
--- /dev/null
+++ b/libstb/tss/trustedboot_reasoncodes.H
@@ -0,0 +1,88 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/secureboot/trustedboot_reasoncodes.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+/////////////////////////////////////////////////////////////////
+// NOTE: This file is exportable as TSS-Lite for skiboot/PHYP //
+/////////////////////////////////////////////////////////////////
+
+#ifndef __TRUSTEDBOOT_REASONCODES_H
+#define __TRUSTEDBOOT_REASONCODES_H
+
+#ifdef __HOSTBOOT_MODULE
+#include <hbotcompid.H>
+#else
+#define SECURE_COMP_ID 0x1E00
+#endif
+
+#ifdef __cplusplus
+namespace TRUSTEDBOOT
+{
+#endif
+
+ enum TRUSTEDModuleId
+ {
+ MOD_HOST_UPDATE_MASTER_TPM = 0x00,
+ MOD_TPM_INITIALIZE = 0x01,
+ MOD_TPM_CMD_STARTUP = 0x02,
+ MOD_TPM_CMD_GETCAPFWVERSION = 0x03,
+ MOD_TPM_MARSHALCMDDATA = 0x04,
+ MOD_TPM_UNMARSHALRESPDATA = 0x05,
+ MOD_TPM_VERIFYFUNCTIONAL = 0x06,
+ MOD_TPM_CMD_PCREXTEND = 0x07,
+ MOD_TPM_CMD_PCRREAD = 0x08,
+ MOD_TPM_REPLAY_LOG = 0x09,
+
+ MOD_TPMLOGMGR_INITIALIZE = 0x10,
+ MOD_TPMLOGMGR_ADDEVENT = 0x11,
+ MOD_TPMLOGMGR_INITIALIZEEXISTLOG = 0x012,
+ };
+
+ enum TRUSTEDReasonCode
+ {
+ // Reason codes 0x00 - 0x9F reserved for secure_reasoncodes.H
+
+ RC_TPM_START_FAIL = SECURE_COMP_ID | 0xA0,
+ RC_TPM_EXISTENCE_FAIL = SECURE_COMP_ID | 0xA1,
+ RC_TPM_GETCAP_FAIL = SECURE_COMP_ID | 0xA2,
+ RC_TPM_GETCAP_FW_INVALID_RESP = SECURE_COMP_ID | 0xA3,
+ RC_TPM_GETCAP2_FAIL = SECURE_COMP_ID | 0xA4,
+ RC_TPM_GETCAP2_FW_INVALID_RESP = SECURE_COMP_ID | 0xA5,
+ RC_TPM_MARSHAL_INVALID_CMD = SECURE_COMP_ID | 0xA6,
+ RC_TPM_MARSHALING_FAIL = SECURE_COMP_ID | 0xA7,
+ RC_TPM_UNMARSHAL_INVALID_CMD = SECURE_COMP_ID | 0xA8,
+ RC_TPM_UNMARSHALING_FAIL = SECURE_COMP_ID | 0xA9,
+ RC_TPMLOGMGR_ADDEVENT_FAIL = SECURE_COMP_ID | 0xAA,
+ RC_TPMLOGMGR_ADDEVENTMARSH_FAIL = SECURE_COMP_ID | 0xAB,
+ RC_TPMLOGMGR_INIT_FAIL = SECURE_COMP_ID | 0xAC,
+ RC_TPM_NOFUNCTIONALTPM_FAIL = SECURE_COMP_ID | 0xAD,
+ RC_TPM_COMMAND_FAIL = SECURE_COMP_ID | 0xAE,
+ RC_TPM_INVALID_ARGS = SECURE_COMP_ID | 0xAF,
+ RC_TPMLOGMGR_LOGWALKFAIL = SECURE_COMP_ID | 0xB0,
+ };
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--
1.9.1
More information about the Skiboot
mailing list