aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/eventlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/libstb/tss2/ibmtpm20tss/utils/eventlib.c')
-rw-r--r--roms/skiboot/libstb/tss2/ibmtpm20tss/utils/eventlib.c1095
1 files changed, 1095 insertions, 0 deletions
diff --git a/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/eventlib.c b/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/eventlib.c
new file mode 100644
index 000000000..b887e1122
--- /dev/null
+++ b/roms/skiboot/libstb/tss2/ibmtpm20tss/utils/eventlib.c
@@ -0,0 +1,1095 @@
+/********************************************************************************/
+/* */
+/* TPM2 Measurement Log Common Routines */
+/* Written by Ken Goldman */
+/* IBM Thomas J. Watson Research Center */
+/* */
+/* (c) Copyright IBM Corporation 2016 - 2020. */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following conditions are */
+/* met: */
+/* */
+/* Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the following disclaimer. */
+/* */
+/* Redistributions in binary form must reproduce the above copyright */
+/* notice, this list of conditions and the following disclaimer in the */
+/* documentation and/or other materials provided with the distribution. */
+/* */
+/* Neither the names of the IBM Corporation nor the names of its */
+/* contributors may be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
+/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
+/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
+/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
+/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
+/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
+/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
+/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
+/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
+/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/********************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ibmtss/tssprint.h>
+#include <ibmtss/Unmarshal_fp.h>
+#include <ibmtss/tssmarshal.h>
+#include <ibmtss/tsserror.h>
+#ifndef TPM_TSS_NOCRYPTO
+#include <ibmtss/tsscryptoh.h>
+#include <ibmtss/tsscrypto.h>
+#endif /* TPM_TSS_NOCRYPTO */
+#include <ibmtss/tssutils.h>
+
+#include "eventlib.h"
+
+#ifndef TPM_TSS_NOFILE
+#ifdef TPM_TPM20
+static uint16_t Uint16_Convert(uint16_t in);
+#endif
+static uint32_t Uint32_Convert(uint32_t in);
+#endif /* TPM_TSS_NOFILE */
+static TPM_RC UINT16LE_Unmarshal(uint16_t *target, BYTE **buffer, uint32_t *size);
+static TPM_RC UINT32LE_Unmarshal(uint32_t *target, BYTE **buffer, uint32_t *size);
+
+static void TSS_EVENT_EventType_Trace(uint32_t eventType);
+static TPM_RC TSS_SpecIdEventAlgorithmSize_Unmarshal(TCG_EfiSpecIdEventAlgorithmSize *algSize,
+ uint8_t **buffer,
+ uint32_t *size);
+static void TSS_SpecIdEventAlgorithmSize_Trace(TCG_EfiSpecIdEventAlgorithmSize *algSize);
+static TPM_RC TSS_TPML_DIGEST_VALUES_LE_Unmarshalu(TPML_DIGEST_VALUES *target,
+ BYTE **buffer,
+ uint32_t *size);
+static TPM_RC TSS_TPMT_HA_LE_Unmarshalu(TPMT_HA *target, BYTE **buffer,
+ uint32_t *size, BOOL allowNull);
+static TPM_RC TSS_TPMI_ALG_HASH_LE_Unmarshalu(TPMI_ALG_HASH *target,
+ BYTE **buffer, uint32_t *size,
+ BOOL allowNull);
+static TPM_RC TSS_TPM_ALG_ID_LE_Unmarshalu(TPM_ALG_ID *target,
+ BYTE **buffer, uint32_t *size);
+static TPM_RC TSS_TPMT_HA_LE_Marshalu(const TPMT_HA *source, uint16_t *written,
+ BYTE **buffer, uint32_t *size);
+static TPM_RC TSS_TPML_DIGEST_VALUES_LE_Marshalu(const TPML_DIGEST_VALUES *source,
+ uint16_t *written, BYTE **buffer,
+ uint32_t *size);
+
+/* TSS_EVENT_Line_Read() reads a TPM 1.2 SHA-1 event line from a binary file inFile.
+
+ */
+
+#ifndef TPM_TSS_NOFILE
+int TSS_EVENT_Line_Read(TCG_PCR_EVENT *event,
+ int *endOfFile,
+ FILE *inFile)
+{
+ int rc = 0;
+ size_t readSize;
+ *endOfFile = FALSE;
+
+ /* read the PCR index */
+ if (rc == 0) {
+ readSize = fread(&(event->pcrIndex),
+ sizeof(((TCG_PCR_EVENT *)NULL)->pcrIndex), 1, inFile);
+ if (readSize != 1) {
+ if (feof(inFile)) {
+ *endOfFile = TRUE;
+ }
+ else {
+ printf("TSS_EVENT_Line_Read: Error, could not read pcrIndex, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ }
+ /* do the endian conversion from stream to uint32_t */
+ if (!*endOfFile && (rc == 0)) {
+ event->pcrIndex = Uint32_Convert(event->pcrIndex);
+ }
+ /* read the event type */
+ if (!*endOfFile && (rc == 0)) {
+ readSize = fread(&(event->eventType),
+ sizeof(((TCG_PCR_EVENT *)NULL)->eventType), 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT_Line_Read: Error, could not read eventType, returned %lu\n",
+ (unsigned long) readSize);
+ rc = TSS_RC_BAD_PROPERTY_VALUE;
+ }
+ }
+ /* do the endian conversion from stream to uint32_t */
+ if (!*endOfFile && (rc == 0)) {
+ event->eventType = Uint32_Convert(event->eventType);
+ }
+ /* read the digest */
+ if (!*endOfFile && (rc == 0)) {
+ readSize = fread(&(event->digest),
+ sizeof(((TCG_PCR_EVENT *)NULL)->digest), 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT_Line_Read: Error, could not read digest, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* read the event data size */
+ if (!*endOfFile && (rc == 0)) {
+ readSize = fread(&(event->eventDataSize),
+ sizeof(((TCG_PCR_EVENT *)NULL)->eventDataSize), 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT_Line_Read: Error, could not read event data size, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* do the endian conversion from stream to uint32_t */
+ if (!*endOfFile && (rc == 0)) {
+ event->eventDataSize = Uint32_Convert(event->eventDataSize);
+ }
+ /* bounds check the event data length */
+ if (!*endOfFile && (rc == 0)) {
+ if (event->eventDataSize > sizeof(((TCG_PCR_EVENT *)NULL)->event)) {
+ printf("TSS_EVENT_Line_Read: Error, event data length too big: %u\n",
+ event->eventDataSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* read the event */
+ if (!*endOfFile && (rc == 0)) {
+ memset(event->event , 0, sizeof(((TCG_PCR_EVENT *)NULL)->event));
+ readSize = fread(&(event->event),
+ event->eventDataSize, 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT_Line_Read: Error, could not read event, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ return rc;
+}
+
+#endif /* TPM_TSS_NOFILE */
+
+/* TSS_EVENT_Line_Marshal() marshals a TCG_PCR_EVENT structure */
+
+TPM_RC TSS_EVENT_Line_Marshal(TCG_PCR_EVENT *source,
+ uint16_t *written, uint8_t **buffer, uint32_t *size)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ rc = TSS_UINT32_Marshalu(&source->pcrIndex, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32_Marshalu(&source->eventType, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Marshalu(source->digest, SHA1_DIGEST_SIZE, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32_Marshalu(&source->eventDataSize, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Marshalu(source->event, source->eventDataSize, written, buffer, size);
+ }
+ return rc;
+}
+
+/* TSS_EVENT_Line_Unmarshal() unmarshals a TCG_PCR_EVENT2 structure
+
+ */
+
+TPM_RC TSS_EVENT_Line_Unmarshal(TCG_PCR_EVENT *target, BYTE **buffer, uint32_t *size)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ rc = TSS_UINT32_Unmarshalu(&target->pcrIndex, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32_Unmarshalu(&target->eventType, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Unmarshalu((uint8_t *)target->digest, SHA1_DIGEST_SIZE, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32_Unmarshalu(&target->eventDataSize, buffer, size);
+ }
+ if (rc == 0) {
+ if (target->eventDataSize > sizeof(target->event)) {
+ rc = TPM_RC_SIZE;
+ }
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Unmarshalu((uint8_t *)target->event, target->eventDataSize, buffer, size);
+ }
+ return rc;
+}
+
+/*
+ * TSS_EVENT_Line_LE_Unmarshal() Unmarshal LE buffer into a target TCG_PCR_EVENT
+*/
+TPM_RC TSS_EVENT_Line_LE_Unmarshal(TCG_PCR_EVENT *target, BYTE **buffer, uint32_t *size)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ rc = UINT32LE_Unmarshal(&target->pcrIndex, buffer, size);
+ }
+ if (rc == 0) {
+ rc = UINT32LE_Unmarshal(&target->eventType, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Unmarshalu((uint8_t *)target->digest, SHA1_DIGEST_SIZE, buffer, size);
+ }
+ if (rc == 0) {
+ rc = UINT32LE_Unmarshal(&target->eventDataSize, buffer, size);
+ }
+ if (rc == 0) {
+ if (target->eventDataSize > sizeof(target->event)) {
+ rc = TPM_RC_SIZE;
+ }
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Unmarshalu((uint8_t *)target->event, target->eventDataSize, buffer, size);
+ }
+ return rc;
+}
+
+#ifndef TPM_TSS_NOCRYPTO
+/* TSS_EVENT_PCR_Extend() extends PCR digest with the digest from the TCG_PCR_EVENT event log
+ entry.
+*/
+
+TPM_RC TSS_EVENT_PCR_Extend(TPMT_HA pcrs[IMPLEMENTATION_PCR],
+ TCG_PCR_EVENT *event)
+{
+ TPM_RC rc = 0;
+
+ /* validate PCR number */
+ if (rc == 0) {
+ if (event->pcrIndex >= IMPLEMENTATION_PCR) {
+ printf("ERROR: TSS_EVENT_PCR_Extend: PCR number %u out of range\n", event->pcrIndex);
+ rc = TSS_RC_BAD_PROPERTY_VALUE;
+ }
+ }
+ /* process each event hash algorithm */
+ if (rc == 0) {
+ pcrs[event->pcrIndex].hashAlg = TPM_ALG_SHA1; /* should already be initialized */
+ if (rc == 0) {
+ rc = TSS_Hash_Generate(&pcrs[event->pcrIndex],
+ SHA1_DIGEST_SIZE, (uint8_t *)&pcrs[event->pcrIndex].digest,
+ SHA1_DIGEST_SIZE, &event->digest,
+ 0, NULL);
+ }
+ }
+ return rc;
+}
+#endif /* TPM_TSS_NOCRYPTO */
+
+void TSS_EVENT_Line_Trace(TCG_PCR_EVENT *event)
+{
+ printf("TSS_EVENT_Line_Trace: PCR index %u\n", event->pcrIndex);
+ TSS_EVENT_EventType_Trace(event->eventType);
+ TSS_PrintAll("TSS_EVENT_Line_Trace: PCR",
+ event->digest, sizeof(((TCG_PCR_EVENT *)NULL)->digest));
+ TSS_PrintAll("TSS_EVENT_Line_Trace: event",
+ event->event, event->eventDataSize);
+ if (event->eventType == EV_IPL) { /* this event appears to be printable strings */
+ printf(" %.*s\n", event->eventDataSize, event->event);
+ }
+ return;
+}
+
+/* TSS_SpecIdEvent_Unmarshal() unmarshals the TCG_EfiSpecIDEvent structure.
+
+ The size and buffer are not moved, since this is the only structure in the event.
+*/
+
+TPM_RC TSS_SpecIdEvent_Unmarshal(TCG_EfiSpecIDEvent *specIdEvent,
+ uint32_t eventSize,
+ uint8_t *event)
+{
+ TPM_RC rc = 0;
+ uint32_t size = eventSize; /* copy, because size and buffer are not moved */
+ uint8_t *buffer = event;
+ uint32_t i;
+
+ if (rc == 0) {
+ rc = TSS_Array_Unmarshalu(specIdEvent->signature, sizeof(specIdEvent->signature),
+ &buffer, &size);
+ }
+ if (rc == 0) {
+ rc = UINT32LE_Unmarshal(&(specIdEvent->platformClass), &buffer, &size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT8_Unmarshalu(&(specIdEvent->specVersionMinor), &buffer, &size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT8_Unmarshalu(&(specIdEvent->specVersionMajor), &buffer, &size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT8_Unmarshalu(&(specIdEvent->specErrata), &buffer, &size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT8_Unmarshalu(&(specIdEvent->uintnSize), &buffer, &size);
+ }
+ if (rc == 0) {
+ rc = UINT32LE_Unmarshal(&(specIdEvent->numberOfAlgorithms), &buffer, &size);
+ }
+ for (i = 0 ; (rc == 0) && (i < specIdEvent->numberOfAlgorithms) ; i++) {
+ rc = TSS_SpecIdEventAlgorithmSize_Unmarshal(&(specIdEvent->digestSizes[i]),
+ &buffer, &size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT8_Unmarshalu(&(specIdEvent->vendorInfoSize), &buffer, &size);
+ }
+#if 0 /* NOTE: Can never fail because vendorInfoSize is uint8_t and vendorInfo is 0xff bytes */
+ if (rc == 0) {
+ if (specIdEvent->vendorInfoSize > sizeof(specIdEvent->vendorInfo)) {
+ rc = TPM_RC_SIZE;
+ }
+ }
+#endif
+ if (rc == 0) {
+ rc = TSS_Array_Unmarshalu(specIdEvent->vendorInfo, specIdEvent->vendorInfoSize,
+ &buffer, &size);
+ }
+ return rc;
+}
+
+/* TSS_SpecIdEventAlgorithmSize_Unmarshal() unmarshals the TCG_EfiSpecIdEventAlgorithmSize
+ structure */
+
+static TPM_RC TSS_SpecIdEventAlgorithmSize_Unmarshal(TCG_EfiSpecIdEventAlgorithmSize *algSize,
+ uint8_t **buffer,
+ uint32_t *size)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ rc = UINT16LE_Unmarshal(&(algSize->algorithmId), buffer, size);
+ }
+ if (rc == 0) {
+ rc = UINT16LE_Unmarshal(&(algSize->digestSize), buffer, size);
+ }
+ if (rc == 0) {
+ uint16_t mappedDigestSize = TSS_GetDigestSize(algSize->algorithmId);
+ if (mappedDigestSize != 0) {
+ if (mappedDigestSize != algSize->digestSize) {
+ printf("TSS_SpecIdEventAlgorithmSize_Unmarshal: "
+ "Error, inconsistent digest size, algorithm %04x size %u\n",
+ algSize->algorithmId, algSize->digestSize);
+ rc = TSS_RC_BAD_PROPERTY_VALUE;
+ }
+ }
+ }
+ return rc;
+}
+
+void TSS_SpecIdEvent_Trace(TCG_EfiSpecIDEvent *specIdEvent)
+{
+ uint32_t i;
+
+ /* normal case */
+ if (specIdEvent->signature[15] == '\0') {
+ printf("TSS_SpecIdEvent_Trace: signature: %s\n", specIdEvent->signature);
+ }
+ /* error case */
+ else {
+ TSS_PrintAll("TSS_SpecIdEvent_Trace: signature",
+ specIdEvent->signature, sizeof(specIdEvent->signature));
+ }
+ printf("TSS_SpecIdEvent_Trace: platformClass %08x\n", specIdEvent->platformClass);
+ printf("TSS_SpecIdEvent_Trace: specVersionMinor %02x\n", specIdEvent->specVersionMinor);
+ printf("TSS_SpecIdEvent_Trace: specVersionMajor %02x\n", specIdEvent->specVersionMajor);
+ printf("TSS_SpecIdEvent_Trace: specErrata %02x\n", specIdEvent->specErrata);
+ printf("TSS_SpecIdEvent_Trace: uintnSize %02x\n", specIdEvent->uintnSize);
+ printf("TSS_SpecIdEvent_Trace: numberOfAlgorithms %u\n", specIdEvent->numberOfAlgorithms);
+ for (i = 0 ; (i < specIdEvent->numberOfAlgorithms) ; i++) {
+ TSS_SpecIdEventAlgorithmSize_Trace(&(specIdEvent->digestSizes[i]));
+ }
+ /* try for a printable string */
+ if (specIdEvent->vendorInfo[specIdEvent->vendorInfoSize-1] == '\0') {
+ printf("TSS_SpecIdEvent_Trace: vendorInfo: %s\n", specIdEvent->vendorInfo);
+ }
+ /* if not, trace the bytes */
+ else {
+ TSS_PrintAll("TSS_SpecIdEvent_Trace: vendorInfo",
+ specIdEvent->vendorInfo, specIdEvent->vendorInfoSize);
+ }
+ return;
+}
+
+static void TSS_SpecIdEventAlgorithmSize_Trace(TCG_EfiSpecIdEventAlgorithmSize *algSize)
+{
+ printf("TSS_SpecIdEventAlgorithmSize_Trace: algorithmId %04x\n", algSize->algorithmId);
+ printf("TSS_SpecIdEventAlgorithmSize_Trace: digestSize %u\n", algSize->digestSize);
+ return;
+}
+
+#ifdef TPM_TPM20
+#ifndef TPM_TSS_NOFILE
+
+/* TSS_EVENT2_Line_Read() reads a TPM2 event line from a binary file inFile.
+
+*/
+
+int TSS_EVENT2_Line_Read(TCG_PCR_EVENT2 *event,
+ int *endOfFile,
+ FILE *inFile)
+{
+ int rc = 0;
+ size_t readSize;
+ uint32_t maxCount;
+ uint32_t count;
+
+ *endOfFile = FALSE;
+ /* read the PCR index */
+ if (rc == 0) {
+ readSize = fread(&(event->pcrIndex),
+ sizeof(((TCG_PCR_EVENT2 *)NULL)->pcrIndex), 1, inFile);
+ if (readSize != 1) {
+ if (feof(inFile)) {
+ *endOfFile = TRUE;
+ }
+ else {
+ printf("TSS_EVENT2_Line_Read: Error, could not read pcrIndex, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ }
+ /* do the endian conversion from stream to uint32_t */
+ if (!*endOfFile && (rc == 0)) {
+ event->pcrIndex = Uint32_Convert(event->pcrIndex);
+ }
+ /* read the event type */
+ if (!*endOfFile && (rc == 0)) {
+ readSize = fread(&(event->eventType),
+ sizeof(((TCG_PCR_EVENT2 *)NULL)->eventType), 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT2_Line_Read: Error, could not read eventType, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* do the endian conversion from stream to uint32_t */
+ if (!*endOfFile && (rc == 0)) {
+ event->eventType = Uint32_Convert(event->eventType);
+ }
+ /* read the TPML_DIGEST_VALUES count */
+ if (!*endOfFile && (rc == 0)) {
+ maxCount = sizeof((TPML_DIGEST_VALUES *)NULL)->digests / sizeof(TPMT_HA);
+ readSize = fread(&(event->digests.count),
+ sizeof(((TPML_DIGEST_VALUES *)NULL)->count), 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT2_Line_Read: Error, could not read digest count, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* do the endian conversion from stream to uint32_t */
+ if (!*endOfFile && (rc == 0)) {
+ event->digests.count = Uint32_Convert(event->digests.count);
+ }
+ /* range check the digest count */
+ if (!*endOfFile && (rc == 0)) {
+ if (event->digests.count > maxCount) {
+ printf("TSS_EVENT2_Line_Read: Error, digest count %u is greater than structure %u\n",
+ event->digests.count, maxCount);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ else if (event->digests.count == 0) {
+ printf("TSS_EVENT2_Line_Read: Error, digest count is zero\n");
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* read all the TPMT_HA, loop through all the digest algorithms */
+ for (count = 0 ; !*endOfFile && (count < event->digests.count) ; count++) {
+ uint16_t digestSize;
+ /* read the digest algorithm */
+ if (rc == 0) {
+ readSize = fread(&(event->digests.digests[count].hashAlg),
+ sizeof((TPMT_HA *)NULL)->hashAlg, 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT2_Line_Read: "
+ "Error, could not read digest algorithm, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* do the endian conversion of the hash algorithm from stream to uint16_t */
+ if (rc == 0) {
+ event->digests.digests[count].hashAlg =
+ Uint16_Convert(event->digests.digests[count].hashAlg);
+ }
+ /* map from the digest algorithm to the digest length */
+ if (rc == 0) {
+ digestSize = TSS_GetDigestSize(event->digests.digests[count].hashAlg);
+ if (digestSize == 0) {
+ printf("TSS_EVENT2_Line_Read: Error, unknown digest algorithm %04x*\n",
+ event->digests.digests[count].hashAlg);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* read the digest */
+ if (rc == 0) {
+ readSize = fread((uint8_t *)&(event->digests.digests[count].digest),
+ digestSize, 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT2_Line_Read: Error, could not read digest, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ }
+ /* read the event size */
+ if (!*endOfFile && (rc == 0)) {
+ readSize = fread(&(event->eventSize),
+ sizeof(((TCG_PCR_EVENT2 *)NULL)->eventSize), 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT2_Line_Read: Error, could not read event size, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* do the endian conversion from stream to uint32_t */
+ if (!*endOfFile && (rc == 0)) {
+ event->eventSize = Uint32_Convert(event->eventSize);
+ }
+ /* bounds check the event size */
+ if (!*endOfFile && (rc == 0)) {
+ if (event->eventSize > sizeof(((TCG_PCR_EVENT2 *)NULL)->event)) {
+ printf("TSS_EVENT2_Line_Read: Error, event size too big: %u\n",
+ event->eventSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ /* read the event */
+ if (!*endOfFile && (event->eventSize > 0) && (rc == 0)) {
+ memset(event->event , 0, sizeof(((TCG_PCR_EVENT2 *)NULL)->event));
+ readSize = fread(&(event->event),
+ event->eventSize, 1, inFile);
+ if (readSize != 1) {
+ printf("TSS_EVENT2_Line_Read: Error, could not read event, returned %lu\n",
+ (unsigned long)readSize);
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ return rc;
+}
+#endif /* TPM_TSS_NOFILE */
+
+/* TSS_EVENT2_Line_Marshal() marshals a TCG_PCR_EVENT2 structure */
+
+TPM_RC TSS_EVENT2_Line_Marshal(TCG_PCR_EVENT2 *source,
+ uint16_t *written, uint8_t **buffer, uint32_t *size)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ rc = TSS_UINT32_Marshalu(&source->pcrIndex, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32_Marshalu(&source->eventType, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_TPML_DIGEST_VALUES_Marshalu(&source->digests, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32_Marshalu(&source->eventSize, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Marshalu((uint8_t *)source->event, source->eventSize, written, buffer, size);
+ }
+ return rc;
+}
+
+/*
+ * TSS_EVENT2_Line_LE_Marshal() Marshals a TSS_EVENT2 structure from HBO into LE
+ * and saves to buffer.
+ */
+TPM_RC TSS_EVENT2_Line_LE_Marshal(TCG_PCR_EVENT2 *source, uint16_t *written,
+ uint8_t **buffer, uint32_t *size)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ rc = TSS_UINT32LE_Marshal(&source->pcrIndex, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32LE_Marshal(&source->eventType, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_TPML_DIGEST_VALUES_LE_Marshalu(&source->digests, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32LE_Marshal(&source->eventSize, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Marshalu((uint8_t *)source->event, source->eventSize, written, buffer, size);
+ }
+ return rc;
+}
+
+/* TSS_EVENT2_Line_Unmarshal() unmarshals a TCG_PCR_EVENT2 structure */
+
+
+TPM_RC TSS_EVENT2_Line_Unmarshal(TCG_PCR_EVENT2 *target, BYTE **buffer, uint32_t *size)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ rc = TSS_UINT32_Unmarshalu(&target->pcrIndex, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32_Unmarshalu(&target->eventType, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_TPML_DIGEST_VALUES_Unmarshalu(&target->digests, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_UINT32_Unmarshalu(&target->eventSize, buffer, size);
+ }
+ if (rc == 0) {
+ if (target->eventSize > sizeof(target->event)) {
+ rc = TPM_RC_SIZE;
+ }
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Unmarshalu((uint8_t *)target->event, target->eventSize, buffer, size);
+ }
+ return rc;
+}
+
+/*
+ * TSS_EVENT2_Line_LE_Unmarshal() Unmarshals an LE eventlog buffer and save to
+ * the target TCG_PCR_EVENT2
+ */
+TPM_RC TSS_EVENT2_Line_LE_Unmarshal(TCG_PCR_EVENT2 *target, BYTE **buffer, uint32_t *size)
+{
+ TPM_RC rc = 0;
+
+ if (rc == 0) {
+ rc = UINT32LE_Unmarshal(&target->pcrIndex, buffer, size);
+ }
+ if (rc == 0) {
+ rc = UINT32LE_Unmarshal(&target->eventType, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_TPML_DIGEST_VALUES_LE_Unmarshalu(&target->digests, buffer, size);
+ }
+ if (rc == 0) {
+ rc = UINT32LE_Unmarshal(&target->eventSize, buffer, size);
+ }
+ if (rc == 0) {
+ if (target->eventSize > sizeof(target->event)) {
+ rc = TPM_RC_SIZE;
+ }
+ }
+ if (rc == 0) {
+ rc = TSS_Array_Unmarshalu((uint8_t *)target->event, target->eventSize, buffer, size);
+ }
+ return rc;
+}
+
+#ifndef TPM_TSS_NOCRYPTO
+/* TSS_EVENT2_PCR_Extend() extends PCR digests with the digest from the TCG_PCR_EVENT2 event log
+ entry.
+*/
+
+TPM_RC TSS_EVENT2_PCR_Extend(TPMT_HA pcrs[HASH_COUNT][IMPLEMENTATION_PCR],
+ TCG_PCR_EVENT2 *event2)
+{
+ TPM_RC rc = 0;
+ uint32_t i; /* iterator though hash algorithms */
+ uint32_t bankNum = 0; /* iterator though PCR hash banks */
+
+ /* validate PCR number */
+ if (rc == 0) {
+ if (event2->pcrIndex >= IMPLEMENTATION_PCR) {
+ printf("ERROR: TSS_EVENT2_PCR_Extend: PCR number %u out of range\n", event2->pcrIndex);
+ rc = 1;
+ }
+ }
+ /* validate event count */
+ if (rc == 0) {
+ uint32_t maxCount = sizeof(((TPML_DIGEST_VALUES *)NULL)->digests) / sizeof(TPMT_HA);
+ if (event2->digests.count > maxCount) {
+ printf("ERROR: TSS_EVENT2_PCR_Extend: PCR count %u out of range, max %u\n",
+ event2->digests.count, maxCount);
+ rc = 1;
+ }
+ }
+ /* process each event hash algorithm */
+ for (i = 0; (rc == 0) && (i < event2->digests.count) ; i++) {
+ /* find the matching PCR bank */
+ for (bankNum = 0 ; (rc == 0) && (bankNum < event2->digests.count) ; bankNum++) {
+ if (pcrs[bankNum][0].hashAlg == event2->digests.digests[i].hashAlg) {
+
+ uint16_t digestSize;
+ if (rc == 0) {
+ digestSize = TSS_GetDigestSize(event2->digests.digests[i].hashAlg);
+ if (digestSize == 0) {
+ printf("ERROR: TSS_EVENT2_PCR_Extend: hash algorithm %04hx unknown\n",
+ event2->digests.digests[i].hashAlg);
+ rc = 1;
+ }
+ }
+ if (rc == 0) {
+ rc = TSS_Hash_Generate(&pcrs[bankNum][event2->pcrIndex],
+ digestSize,
+ (uint8_t *)&pcrs[bankNum][event2->pcrIndex].digest,
+ digestSize,
+ &event2->digests.digests[i].digest,
+ 0, NULL);
+ }
+ }
+ }
+ }
+ return rc;
+}
+#endif /* TPM_TSS_NOCRYPTO */
+#endif /* TPM_TPM20 */
+
+#ifndef TPM_TSS_NOFILE
+#ifdef TPM_TPM20
+
+/* Uint16_Convert() converts a little endian uint16_t (from an input stream) to host byte order
+ */
+
+static uint16_t Uint16_Convert(uint16_t in)
+{
+ uint16_t out = 0;
+ unsigned char *inb = (unsigned char *)&in;
+
+ /* little endian input */
+ out = (inb[0] << 0) |
+ (inb[1] << 8);
+ return out;
+}
+
+#endif
+
+/* Uint32_Convert() converts a little endian uint32_t (from an input stream) to host byte order
+ */
+
+static uint32_t Uint32_Convert(uint32_t in)
+{
+ uint32_t out = 0;
+ unsigned char *inb = (unsigned char *)&in;
+
+ /* little endian input */
+ out = (inb[0] << 0) |
+ (inb[1] << 8) |
+ (inb[2] << 16) |
+ (inb[3] << 24);
+ return out;
+}
+#endif /* TPM_TSS_NOFILE */
+
+/* UINT16LE_Unmarshal() unmarshals a little endian 2-byte array from buffer into a HBO uint16_t */
+
+static TPM_RC
+UINT16LE_Unmarshal(uint16_t *target, BYTE **buffer, uint32_t *size)
+{
+ if (*size < sizeof(uint16_t)) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ *target = ((uint16_t)((*buffer)[0]) << 0) |
+ ((uint16_t)((*buffer)[1]) << 8);
+ *buffer += sizeof(uint16_t);
+ *size -= sizeof(uint16_t);
+ return TPM_RC_SUCCESS;
+}
+
+/* UINT32LE_Unmarshal() unmarshals a little endian 4-byte array from buffer into a HBO uint32_t */
+
+static TPM_RC
+UINT32LE_Unmarshal(uint32_t *target, BYTE **buffer, uint32_t *size)
+{
+ if (*size < sizeof(uint32_t)) {
+ return TPM_RC_INSUFFICIENT;
+ }
+ *target = ((uint32_t)((*buffer)[0]) << 0) |
+ ((uint32_t)((*buffer)[1]) << 8) |
+ ((uint32_t)((*buffer)[2]) << 16) |
+ ((uint32_t)((*buffer)[3]) << 24);
+ *buffer += sizeof(uint32_t);
+ *size -= sizeof(uint32_t);
+ return TPM_RC_SUCCESS;
+}
+
+
+void TSS_EVENT2_Line_Trace(TCG_PCR_EVENT2 *event)
+{
+ uint32_t count;
+ uint16_t digestSize;
+ printf("TSS_EVENT2_Line_Trace: PCR index %u\n", event->pcrIndex);
+ TSS_EVENT_EventType_Trace(event->eventType);
+ printf("TSS_EVENT2_Line_Trace: digest count %u\n", event->digests.count);
+ for (count = 0 ; count < event->digests.count ; count++) {
+ printf("TSS_EVENT2_Line_Trace: digest %u algorithm %04x\n",
+ count, event->digests.digests[count].hashAlg);
+ digestSize = TSS_GetDigestSize(event->digests.digests[count].hashAlg);
+ TSS_PrintAll("TSS_EVENT2_Line_Trace: PCR",
+ (uint8_t *)&event->digests.digests[count].digest, digestSize);
+ }
+ TSS_PrintAll("TSS_EVENT2_Line_Trace: event",
+ event->event, event->eventSize);
+ return;
+}
+
+/* tables to map eventType to text */
+
+typedef struct {
+ uint32_t eventType;
+ const char *text;
+} EVENT_TYPE_TABLE;
+
+const EVENT_TYPE_TABLE eventTypeTable [] = {
+ {EV_PREBOOT_CERT, "EV_PREBOOT_CERT"},
+ {EV_POST_CODE, "EV_POST_CODE"},
+ {EV_UNUSED, "EV_UNUSED"},
+ {EV_NO_ACTION, "EV_NO_ACTION"},
+ {EV_SEPARATOR, "EV_SEPARATOR"},
+ {EV_ACTION, "EV_ACTION"},
+ {EV_EVENT_TAG, "EV_EVENT_TAG"},
+ {EV_S_CRTM_CONTENTS, "EV_S_CRTM_CONTENTS"},
+ {EV_S_CRTM_VERSION, "EV_S_CRTM_VERSION"},
+ {EV_CPU_MICROCODE, "EV_CPU_MICROCODE"},
+ {EV_PLATFORM_CONFIG_FLAGS, "EV_PLATFORM_CONFIG_FLAGS"},
+ {EV_TABLE_OF_DEVICES, "EV_TABLE_OF_DEVICES"},
+ {EV_COMPACT_HASH, "EV_COMPACT_HASH"},
+ {EV_IPL, "EV_IPL"},
+ {EV_IPL_PARTITION_DATA, "EV_IPL_PARTITION_DATA"},
+ {EV_NONHOST_CODE, "EV_NONHOST_CODE"},
+ {EV_NONHOST_CONFIG, "EV_NONHOST_CONFIG"},
+ {EV_NONHOST_INFO, "EV_NONHOST_INFO"},
+ {EV_OMIT_BOOT_DEVICE_EVENTS, "EV_OMIT_BOOT_DEVICE_EVENTS"},
+ {EV_EFI_EVENT_BASE, "EV_EFI_EVENT_BASE"},
+ {EV_EFI_VARIABLE_DRIVER_CONFIG, "EV_EFI_VARIABLE_DRIVER_CONFIG"},
+ {EV_EFI_VARIABLE_BOOT, "EV_EFI_VARIABLE_BOOT"},
+ {EV_EFI_BOOT_SERVICES_APPLICATION, "EV_EFI_BOOT_SERVICES_APPLICATION"},
+ {EV_EFI_BOOT_SERVICES_DRIVER, "EV_EFI_BOOT_SERVICES_DRIVER"},
+ {EV_EFI_RUNTIME_SERVICES_DRIVER, "EV_EFI_RUNTIME_SERVICES_DRIVER"},
+ {EV_EFI_GPT_EVENT, "EV_EFI_GPT_EVENT"},
+ {EV_EFI_ACTION, "EV_EFI_ACTION"},
+ {EV_EFI_PLATFORM_FIRMWARE_BLOB, "EV_EFI_PLATFORM_FIRMWARE_BLOB"},
+ {EV_EFI_HANDOFF_TABLES, "EV_EFI_HANDOFF_TABLES"},
+ {EV_EFI_HCRTM_EVENT, "EV_EFI_HCRTM_EVENT"},
+ {EV_EFI_VARIABLE_AUTHORITY, "EV_EFI_VARIABLE_AUTHORITY"}
+};
+
+static void TSS_EVENT_EventType_Trace(uint32_t eventType)
+{
+ size_t i;
+
+ for (i = 0 ; i < sizeof(eventTypeTable) / sizeof(EVENT_TYPE_TABLE) ; i++) {
+ if (eventTypeTable[i].eventType == eventType) {
+ printf("TSS_EVENT_EventType_Trace: %08x %s\n",
+ eventTypeTable[i].eventType, eventTypeTable[i].text);
+ return;
+ }
+ }
+ printf("TSS_EVENT_EventType_Trace: %08x Unknown\n", eventType);
+ return;
+}
+
+const char *TSS_EVENT_EventTypeToString(uint32_t eventType)
+{
+ const char *crc = NULL;
+ size_t i;
+
+ for (i = 0 ; i < sizeof(eventTypeTable) / sizeof(EVENT_TYPE_TABLE) ; i++) {
+ if (eventTypeTable[i].eventType == eventType) {
+ crc = eventTypeTable[i].text;
+ }
+ }
+ if (crc == NULL) {
+ crc = "Unknown event type";
+ }
+ return crc;
+}
+
+/*
+ * TSS_TPML_DIGEST_VALUES_LE_Unmarshalu() Unmarshals TPML_DIGEST_VALUES struct
+ * from a LE buffer into HBO data structure. This is similar to
+ * TSS_TPML_DIGEST_VALUES_Unmarshalu but it unrmarshals TPML_DIGEST_VALUES's
+ * count and the digests array members from LE instead of HBO.
+ */
+
+static TPM_RC
+TSS_TPML_DIGEST_VALUES_LE_Unmarshalu(TPML_DIGEST_VALUES *target, BYTE **buffer, uint32_t *size)
+{
+ TPM_RC rc = TPM_RC_SUCCESS;
+
+ uint32_t i;
+ if (rc == TPM_RC_SUCCESS) {
+ rc = UINT32LE_Unmarshal(&target->count, buffer, size);
+ }
+ if (rc == TPM_RC_SUCCESS) {
+ if (target->count > HASH_COUNT) {
+ rc = TPM_RC_SIZE;
+ }
+ }
+ for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) {
+ rc = TSS_TPMT_HA_LE_Unmarshalu(&target->digests[i], buffer, size, NO);
+ }
+ return rc;
+}
+
+/*
+ * TSS_TPMT_HA_LE_Unmarshalu() Unmarshals a TPMT_HA data from LE to HBO. This is
+ * similar to TSS_TPMT_HA_Unmarshalu but differs specificaly for unmarshalling
+ * hashAlg member from LE instead of from HBO.
+ */
+static TPM_RC
+TSS_TPMT_HA_LE_Unmarshalu(TPMT_HA *target, BYTE **buffer, uint32_t *size, BOOL allowNull)
+{
+ TPM_RC rc = TPM_RC_SUCCESS;
+
+ if (rc == TPM_RC_SUCCESS) {
+ rc = TSS_TPMI_ALG_HASH_LE_Unmarshalu(&target->hashAlg, buffer, size, allowNull);
+ }
+ if (rc == TPM_RC_SUCCESS) {
+ rc = TSS_TPMU_HA_Unmarshalu(&target->digest, buffer, size, target->hashAlg);
+ }
+ return rc;
+}
+
+/*
+ * TSS_TPMI_ALG_HASH_LE_Unmarshalu() Unmarshals TPMI_ALG_HASH from a LE buffer
+ * into HBO data structure. This is similar to TSS_TPMI_ALG_HASH_Unmarshalu but
+ * unmarshals TPMI_ALG_HASH from LE instead of HBO.
+ */
+static TPM_RC
+TSS_TPMI_ALG_HASH_LE_Unmarshalu(TPMI_ALG_HASH *target, BYTE **buffer, uint32_t *size, BOOL allowNull)
+{
+ TPM_RC rc = TPM_RC_SUCCESS;
+ allowNull = allowNull;
+
+ if (rc == TPM_RC_SUCCESS) {
+ rc = TSS_TPM_ALG_ID_LE_Unmarshalu(target, buffer, size);
+ }
+ return rc;
+}
+
+/*
+ * TSS_TPM_ALG_ID_LE_Unmarshalu() Unrmarshals TPM_ALG_ID from LE buffer. This is
+ * simlar to TSS_TPM_ALG_ID_Unmarshalu but unmarshals from LE instead of HBO.
+ */
+static TPM_RC
+TSS_TPM_ALG_ID_LE_Unmarshalu(TPM_ALG_ID *target, BYTE **buffer,
+ uint32_t *size)
+{
+ TPM_RC rc = TPM_RC_SUCCESS;
+
+ if (rc == TPM_RC_SUCCESS) {
+ rc = UINT16LE_Unmarshal(target, buffer, size);
+ }
+ return rc;
+}
+
+/* TSS_TPML_DIGEST_VALUES_LE_Marshalu() Similar to TSS_TPML_DIGEST_VALUES_Marshalu
+ * for TSS EVENT2 this marshals count to buffer in LE endianess.
+ */
+static TPM_RC
+TSS_TPML_DIGEST_VALUES_LE_Marshalu(const TPML_DIGEST_VALUES *source,
+ uint16_t *written, BYTE **buffer,
+ uint32_t *size)
+{
+ TPM_RC rc = 0;
+ uint32_t i;
+
+ if (rc == 0) {
+ rc = TSS_UINT32LE_Marshal(&source->count, written, buffer, size);
+ }
+ for (i = 0 ; i < source->count ; i++) {
+ if (rc == 0) {
+ rc = TSS_TPMT_HA_LE_Marshalu(&source->digests[i], written, buffer, size);
+ }
+ }
+ return rc;
+}
+
+/* TSS_TPMT_HA_LE_Marshalu() Similar to TSS_TPMT_HA_Marshalu for TSS EVENT2,
+ * this saves hashAlg attr as little endian into buffer.
+ */
+static TPM_RC
+TSS_TPMT_HA_LE_Marshalu(const TPMT_HA *source, uint16_t *written,
+ BYTE **buffer, uint32_t *size)
+{
+ TPM_RC rc = 0;
+ if (rc == 0) {
+ rc = TSS_UINT16LE_Marshalu(&source->hashAlg, written, buffer, size);
+ }
+ if (rc == 0) {
+ rc = TSS_TPMU_HA_Marshalu(&source->digest, written, buffer, size,
+ source->hashAlg);
+ }
+ return rc;
+}
+
+/*
+ * TSS_UINT32LE_Marshal() Marshals uint32_t from HBO into LE in the given buffer.
+ */
+TPM_RC
+TSS_UINT32LE_Marshal(const UINT32 *source, uint16_t *written, BYTE **buffer,
+ uint32_t *size)
+{
+ TPM_RC rc = 0;
+ if (buffer != NULL) {
+ if ((size == NULL) || (*size >= sizeof(uint32_t))) {
+ (*buffer)[0] = (BYTE)((*source >> 0) & 0xff);
+ (*buffer)[1] = (BYTE)((*source >> 8) & 0xff);
+ (*buffer)[2] = (BYTE)((*source >> 16) & 0xff);
+ (*buffer)[3] = (BYTE)((*source >> 24) & 0xff);
+
+ *buffer += sizeof(uint32_t);
+ if (size != NULL) {
+ *size -= sizeof(uint32_t);
+ }
+ }
+ else {
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ *written += sizeof(uint32_t);
+ return rc;
+}
+
+/*
+ * UINT16LE_Marshal() Marshals uint16_t from HBO into LE in the given buffer.
+ */
+
+TPM_RC
+TSS_UINT16LE_Marshalu(const UINT16 *source, uint16_t *written, BYTE **buffer,
+ uint32_t *size)
+{
+ TPM_RC rc = 0;
+ if (buffer != NULL) {
+ if ((size == NULL) || (*size >= sizeof(uint16_t))) {
+ (*buffer)[0] = (BYTE)((*source >> 0) & 0xff);
+ (*buffer)[1] = (BYTE)((*source >> 8) & 0xff);
+
+ *buffer += sizeof(uint16_t);
+
+ if (size != NULL) {
+ *size -= sizeof(uint16_t);
+ }
+ }
+ else {
+ rc = TSS_RC_INSUFFICIENT_BUFFER;
+ }
+ }
+ *written += sizeof(uint16_t);
+ return rc;
+}