From 715e6599b9b0cf0c281148821b67723a2d405eaf Mon Sep 17 00:00:00 2001 From: iadgovuser58 <124906646+iadgovuser58@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:35:58 -0400 Subject: [PATCH] spdm processing - output is complete --- .../hirs/utils/tpm/eventlog/TpmPcrEvent.java | 8 +- .../events/DeviceSecurityEventData.java | 4 +- .../events/DeviceSecurityEventDataBase.java | 4 + .../events/DeviceSecurityEventDataHeader.java | 88 ++++++++----- .../DeviceSecurityEventDataHeaderBase.java | 121 +++++++----------- .../hirs/utils/tpm/eventlog/spdm/SpdmHa.java | 3 +- .../tpm/eventlog/spdm/SpdmMeasurement.java | 105 ++++++++++++++- .../eventlog/spdm/SpdmMeasurementBlock.java | 64 +++++++-- 8 files changed, 273 insertions(+), 124 deletions(-) diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/TpmPcrEvent.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/TpmPcrEvent.java index f921ee4d..c6027fbf 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/TpmPcrEvent.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/TpmPcrEvent.java @@ -376,6 +376,13 @@ public class TpmPcrEvent { case EvConstants.EV_EFI_HCRTM_EVENT: break; case EvConstants.EV_EFI_SPDM_FIRMWARE_BLOB: + try { + sb.append(new EvEfiSpdmFirmwareBlob(eventContent).toString()); + } catch (UnsupportedEncodingException ueEx) { + log.error(ueEx); + sb.append(ueEx.toString()); + } + break; default: sb.append("Unknown Event found\n"); } @@ -552,7 +559,6 @@ public class TpmPcrEvent { */ private static String eventString(final long event) { - System.out.println("XXXX " + event); if (event == EvConstants.EV_PREBOOT_CERT) { return "EV_PREBOOT_CERT"; } else if (event == EvConstants.EV_POST_CODE) { diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventData.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventData.java index 9e3098ab..f7c4d8b6 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventData.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventData.java @@ -3,6 +3,8 @@ package hirs.utils.tpm.eventlog.events; import lombok.Getter; +import java.io.UnsupportedEncodingException; + public class DeviceSecurityEventData extends DeviceSecurityEventDataBase { /** @@ -16,7 +18,7 @@ public class DeviceSecurityEventData extends DeviceSecurityEventDataBase { * * @param dSEDbytes byte array holding the DeviceSecurityEventData. */ - public DeviceSecurityEventData(final byte[] dSEDbytes) { + public DeviceSecurityEventData(final byte[] dSEDbytes) throws UnsupportedEncodingException { super(dSEDbytes); dsedHeader = new DeviceSecurityEventDataHeader(dSEDbytes); } diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataBase.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataBase.java index 3e7b8a1f..46f3bdba 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataBase.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataBase.java @@ -44,6 +44,10 @@ import java.nio.charset.StandardCharsets; * 2. Digest of 48 bytes * 3. Event content defined as DEVICE_SECURITY_EVENT_DATA Struct. * 4. First 16 bytes of the structure header is an ASCII "SPDM Device Sec" + *
+ * Only a few of the Device Security Event Data events have been implemented as there are many, + * but only those that were reported using the test devices at hand. + * Without test patterns, the processing may lead to an un-handled exception. */ public abstract class DeviceSecurityEventDataBase { diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataHeader.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataHeader.java index 5073a1d2..955a353c 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataHeader.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataHeader.java @@ -6,63 +6,81 @@ import hirs.utils.tpm.eventlog.spdm.SpdmMeasurementBlock; import hirs.utils.tpm.eventlog.uefi.UefiConstants; import lombok.Getter; +import java.io.UnsupportedEncodingException; + + +/** + * Class to process the DEVICE_SECURITY_EVENT_DATA_HEADER. + * DEVICE_SECURITY_EVENT_DATA_HEADER contains the measurement(s) and hash algorithm identifier + * returned by the SPDM "GET_MEASUREMENTS" function. + * + * HEADERS defined by PFP v1.06 Rev 52: + *
+ * typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER { + * UINT8 Signature[16]; + * UINT16 Version; + * UINT16 Length; + * UINT32 SpdmHashAlg; + * UINT32 DeviceType; + * SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock; + * UINT64 DevicePathLength; + * UNIT8 DevicePath[DevicePathLength] + * } DEVICE_SECURITY_EVENT_DATA_HEADER; + *
+ * Assumption: there is only 1 SpdmMeasurementBlock per event. Need more test patterns to verify.
+ */
public class DeviceSecurityEventDataHeader extends DeviceSecurityEventDataHeaderBase {
- /** ----------- Variables specific to Header Type 1 -----------
- // /**
- // * Type Header 1 event data length.
- // */
-// @Getter
-// private String h1Length = "";
/**
- * Type Header 1 SPDM hash algorithm.
+ * Event data length.
*/
@Getter
- private String h1SpdmHashAlgo = "";
-// /**
-// * Type Header 1 SPDM Measurement Block list.
-// */
-// private List
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER {
- * UINT8 Signature[16];
- * UINT16 Version;
+ * UINT8 ** Signature[16];
+ * UINT16 ** Version;
* UINT16 Length;
* UINT32 SpdmHashAlg;
- * UINT32 DeviceType;
+ * UINT32 ** DeviceType;
* SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
- * UINT64 DevicePathLength;
- * UNIT8 DevicePath[DevicePathLength]
+ * UINT64 ** DevicePathLength;
+ * UNIT8 ** DevicePath[DevicePathLength]
* } DEVICE_SECURITY_EVENT_DATA_HEADER;
*
* typedef struct tdDEVICE_SECURITY_EVENT_DATA_HEADER2 { - NOT IMPLEMENTED YET
- * UINT8 Signature[16];
- * UINT16 Version;
+ * UINT8 ** Signature[16];
+ * UINT16 ** Version;
* UINT8 AuthState;
* UINT8 Reserved;
* UINT32 Length;
- * UINT32 DeviceType;
+ * UINT32 ** DeviceType;
* UINT32 SubHeaderType;
* UINT32 SubHeaderLength;
* UINT32 SubHeaderUID;
- * UINT64 DevicePathLength;
- * UNIT8 DevicePath[DevicePathLength]
+ * UINT64 ** DevicePathLength;
+ * UNIT8 ** DevicePath[DevicePathLength]
* } DEVICE_SECURITY_EVENT_DATA_HEADER2;
- *
- * SPDM_MEASUREMENT_BLOCK and contents defined by SPDM v1.03, Sect 10.11.1, Table 53 and 54:
- *
- * Measurement block format {
- * Index 1 byte;
- * MeasurementSpec 1 byte;
- * MeasurementSize 2 bytes;
- * Measurement
- * DMTF measurement spec format {
- * DMTFSpecMeasurementValueType 1 byte;
- * DMTFSpecMeasurementValueSize 2 bytes;
- * DMTFSpecMeasurementValue
- * DMTFSpecMeasurementValueType[7]
- * Indicates how bits [0:6] are represented
- * Bit = 0: Digest
- * Bit = 1: Raw bit stream
- * DMTFSpecMeasurementValueType[6:0]
- * Immutable ROM 0x0
- * Mutable firmware 0x1
- * Hardware configuration 0x2
- * Firmware configuration 0x3
- * etc.
*
*/
public abstract class DeviceSecurityEventDataHeaderBase {
@@ -98,22 +73,21 @@ public abstract class DeviceSecurityEventDataHeaderBase {
* Device type.
*/
@Getter
- private int deviceTypeId = -1;
-// /**
-// * Device type.
-// */
-// @Getter
-// private String deviceType = "";
+ private int deviceType = -1;
/**
- * Device path length.
+ * UEFI Device Path Length.
*/
@Getter
- private String devicePathLength = "";
+ private int devicePathLength = 0;
/**
- * Device path.
+ * UEFI Device path.
*/
@Getter
- private String devicePath = "";
+ private UefiDevicePath devicePath = null;
+ /**
+ * Is the Device Path Valid.
+ */
+ private boolean devicePathValid = false;
/**
* Device Security Event Data Device Type = no device type.
@@ -155,32 +129,33 @@ public abstract class DeviceSecurityEventDataHeaderBase {
}
- public void extractDeviceTypeId(final byte[] dSEDbytes, int startByte) {
+ public void extractDeviceType(final byte[] dSEDbytes, int startByte) {
// get the device type ID
byte[] deviceTypeBytes = new byte[UefiConstants.SIZE_4];
System.arraycopy(dSEDbytes, startByte, deviceTypeBytes, 0,
UefiConstants.SIZE_4);
- deviceTypeId = HexUtils.leReverseInt(deviceTypeBytes);
+ deviceType = HexUtils.leReverseInt(deviceTypeBytes);
}
- public void extractDevicePathString(final byte[] dSEDbytes, int startByte) {
+ public void extractDevicePath(final byte[] dSEDbytes, int startByte)
+ throws UnsupportedEncodingException {
// get the device path length
byte[] devicePathLengthBytes = new byte[UefiConstants.SIZE_8];
System.arraycopy(dSEDbytes, startByte, devicePathLengthBytes, 0,
UefiConstants.SIZE_8);
- int deviceTypeLength = HexUtils.leReverseInt(devicePathLengthBytes);
-
- // TODO: how to interpret this?? i'ts not ascii
+ int devicePathLength = HexUtils.leReverseInt(devicePathLengthBytes);
// get the device path
- startByte = startByte + UefiConstants.SIZE_8;
- byte[] devicePathBytes = new byte[UefiConstants.SIZE_16];
- System.arraycopy(dSEDbytes, startByte, devicePathBytes, 0,
- deviceTypeLength);
-
- // TODO: store device path length
+ if (devicePathLength != 0) {
+ startByte = startByte + UefiConstants.SIZE_8;
+ byte[] devPathBytes = new byte[devicePathLength];
+ System.arraycopy(dSEDbytes, startByte, devPathBytes,
+ 0, devicePathLength);
+ devicePath = new UefiDevicePath(devPathBytes);
+ devicePathValid = true;
+ }
}
/**
@@ -213,22 +188,18 @@ public abstract class DeviceSecurityEventDataHeaderBase {
*
* @return a description of this event..
*/
- public String toString() {
+ public String headerBaseToString() {
String dsedHeaderInfo = "";
- dsedHeaderInfo += "\n SPDM Device";
- dsedHeaderInfo += "\n Device Type: " + deviceTypeToString(deviceTypeId);
- dsedHeaderInfo += "\n Device Path: " + devicePath;
+ dsedHeaderInfo += "\n SPDM Device Type = " + deviceTypeToString(deviceType);
+ if (devicePathValid) {
+ dsedHeaderInfo += "\n SPDM Device Path =\n";
+ dsedHeaderInfo += devicePath;
+ }
+ else {
+ dsedHeaderInfo += "\n SPDM Device Path = Uknown or invalid";
+ }
-// if (version.equals("0100")) {
-// dsedHeaderInfo += "\n SPDM hash algorithm = " + h1SpdmHashAlgo;
-// dsedHeaderInfo += "\n SPDM Device";
-// dsedHeaderInfo += "\n Device Type: " + deviceType;
-// dsedHeaderInfo += "\n Device Path: " + devicePath;
-// dsedHeaderInfo += "\n SPDM Measurement Block " + h1SpdmMeasurementBlock.toString();
-// } else if(version.equals("0200")) {
-// dsedHeaderInfo = "tbd";
-// }
return dsedHeaderInfo;
}
diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmHa.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmHa.java
index ce6a2fb1..3195896f 100644
--- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmHa.java
+++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmHa.java
@@ -5,8 +5,7 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
- * Class for defining constants referenced in the DMTF
- * SPDM specification.
+ * Class for defining constants referenced in the DMTF SPDM specification.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SpdmHa {
diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmMeasurement.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmMeasurement.java
index 4dd82a4e..1555d4aa 100644
--- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmMeasurement.java
+++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmMeasurement.java
@@ -1,13 +1,116 @@
package hirs.utils.tpm.eventlog.spdm;
+import hirs.utils.HexUtils;
+import lombok.AccessLevel;
+import lombok.Getter;
+
+/**
+ * Class to process the SpdmMeasurement.
+ *
+ * Measurement, defined by SPDM v1.03, Sect 10.11.1, Table 54:
+ * DMTF measurement spec format {
+ * DMTFSpecMeasurementValueType 1 byte;
+ * DMTFSpecMeasurementValueSize 2 bytes;
+ * DMTFSpecMeasurementValue
+ * DMTFSpecMeasurementValueType[7]
+ * Indicates how bits [0:6] are represented
+ * Bit = 0: Digest
+ * Bit = 1: Raw bit stream
+ * DMTFSpecMeasurementValueType[6:0] (see SPDM Spec, Table 55 "DMTFSpecMeasurementValueType[6:0]")
+ * Immutable ROM 0x0
+ * Mutable firmware 0x1
+ * Hardware configuration 0x2
+ * Firmware configuration 0x3
+ * etc.
+ *
+ */
public class SpdmMeasurement {
+ /**
+ * Measurement value type (such as mutable firmware, etc).
+ */
+ @Getter
+ private int dmtfSpecMeasurementValueType = 0;
+ /**
+ * Measurement value (digest).
+ */
+ @Getter
+ private byte[] dmtfSpecMeasurementValue = null;
+
+ @Getter(value = AccessLevel.PROTECTED)
+ private byte[] digest = null;
+
public SpdmMeasurement(final byte[] spdmMeasBytes) {
+ byte[] dmtfSpecMeasurementValueTypeBytes = new byte[1];
+ System.arraycopy(spdmMeasBytes, 0, dmtfSpecMeasurementValueTypeBytes, 0,
+ 1);
+ dmtfSpecMeasurementValueType = HexUtils.leReverseInt(dmtfSpecMeasurementValueTypeBytes);
+
+ // in future, can crosscheck this value size + 3 with the spdm block MeasurementSize size
+ byte[] dmtfSpecMeasurementValueSizeBytes = new byte[2];
+ System.arraycopy(spdmMeasBytes, 1, dmtfSpecMeasurementValueSizeBytes, 0,
+ 2);
+ int dmtfSpecMeasurementValueSize = HexUtils.leReverseInt(dmtfSpecMeasurementValueSizeBytes);
+
+ dmtfSpecMeasurementValue = new byte[dmtfSpecMeasurementValueSize];
+ System.arraycopy(spdmMeasBytes, 3, dmtfSpecMeasurementValue, 0,
+ dmtfSpecMeasurementValueSize);
}
+ public String dmtfSpecMeasurementValueTypeToString(final int measValType) {
+
+ String measValTypeStr;
+ switch (measValType) {
+ case 0:
+ measValTypeStr = "Immutable ROM";
+ break;
+ case 1:
+ measValTypeStr = "Mutable firmware";
+ break;
+ case 2:
+ measValTypeStr = "Hardware configuration";
+ break;
+ case 3:
+ measValTypeStr = "Firmware configuration";
+ break;
+ case 4:
+ measValTypeStr = "Freeform measurement manifest";
+ break;
+ case 5:
+ measValTypeStr = "Structured representation of debug and device mode";
+ break;
+ case 6:
+ measValTypeStr = "Mutable firmware's version number";
+ break;
+ case 7:
+ measValTypeStr = "Mutable firmware's security verison number";
+ break;
+ case 8:
+ measValTypeStr = "Hash-extended measurement";
+ break;
+ case 9:
+ measValTypeStr = "Informational";
+ break;
+ case 10:
+ measValTypeStr = "Structured measurement manifest";
+ break;
+ default:
+ measValTypeStr = "Unknown or invalid DMTF Spec Measurement Value Type";
+ }
+ return measValTypeStr;
+ }
public String toString() {
- return "TEMP TEST SpdmMeasurement";
+ String spdmMeasInfo = "";
+
+ spdmMeasInfo += "\n SPDM Measurement Value Type = " +
+ dmtfSpecMeasurementValueTypeToString(dmtfSpecMeasurementValueType);
+ spdmMeasInfo += "\n SPDM Measurement Value = " +
+ HexUtils.byteArrayToHexString(dmtfSpecMeasurementValue);
+
+ return spdmMeasInfo;
}
}
diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmMeasurementBlock.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmMeasurementBlock.java
index af8c95a4..ff2ac9ea 100644
--- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmMeasurementBlock.java
+++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmMeasurementBlock.java
@@ -1,32 +1,76 @@
package hirs.utils.tpm.eventlog.spdm;
+import hirs.utils.HexUtils;
+import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter;
+/**
+ * Class to process the SpdmMeasurementBlock.
+ *
+ * Measurement block format, defined by SPDM v1.03, Sect 10.11.1, Table 53:
+ * Measurement block format {
+ * Index 1 byte;
+ * MeasurementSpec 1 byte;
+ * MeasurementSize 2 bytes;
+ * Measurement
+ * Index: index of the measurement block, as there can be more than one
+ * MeasurementSpec: bit mask; the measurement specification that the requested Measurement follows
+ * See "MeasurementSpecificationSel" in Table 21. See Tables 29, 53, 54
+ * Bit 0: DMTFmeasSpec, per Table 54
+ * Bit 1-7: Reserved
+ * Measurement: the digest
+ */
public class SpdmMeasurementBlock {
+ /**
+ * Measurement block index, as an SPDM measurement exchange can contain several measurements.
+ */
+ @Getter
+ private int index = 0;
/**
* Measurement Spec.
*/
@Getter
- private String measurementSpec = "";
+ private int measurementSpec = 0;
/**
- * Measurement value type (such as mutable firmware, etc).
+ * SPDM Measurement.
*/
- @Getter
- private String dmtfSpecMeasurementValueType = "";
- /**
- * Measurement value (digest).
- */
- @Getter
- private String dmtfSpecMeasurementValue = "";
+ private SpdmMeasurement spdmMeasurement;
public SpdmMeasurementBlock(final byte[] spdmMeasBlockBytes) {
+ byte[] indexBytes = new byte[1];
+ System.arraycopy(spdmMeasBlockBytes, 0, indexBytes, 0,
+ 1);
+ index = HexUtils.leReverseInt(indexBytes);
+ byte[] measurementSpecBytes = new byte[1];
+ System.arraycopy(spdmMeasBlockBytes, 1, measurementSpecBytes, 0,
+ 1);
+ measurementSpec = HexUtils.leReverseInt(measurementSpecBytes);
+
+ // in future, can crosscheck this measurement size with the MeasurementSpec hash alg size
+ byte[] measurementSizeBytes = new byte[2];
+ System.arraycopy(spdmMeasBlockBytes, 2, measurementSizeBytes, 0,
+ 2);
+ int measurementSize = HexUtils.leReverseInt(measurementSizeBytes);
+
+ byte[] measurementBytes = new byte[measurementSize];
+ System.arraycopy(spdmMeasBlockBytes, 4, measurementBytes, 0,
+ measurementSize);
+ spdmMeasurement = new SpdmMeasurement(measurementBytes);
}
public String toString() {
- return "TEMP TEST spdmMeasBlockBytes";
+ String spdmMeasBlockInfo = "";
+
+ spdmMeasBlockInfo += "\n Index = " + index;
+ spdmMeasBlockInfo += "\n MeasurementSpec = " + measurementSpec;
+ spdmMeasBlockInfo += spdmMeasurement.toString();
+
+ return spdmMeasBlockInfo;
}
}