spdm processing - output is complete

This commit is contained in:
iadgovuser58 2024-04-22 14:35:58 -04:00 committed by chubtub
parent 03ce1b5763
commit 715e6599b9
8 changed files with 273 additions and 124 deletions

View File

@ -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) {

View File

@ -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);
}

View File

@ -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"
* <p>
* 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 {

View File

@ -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:
* <p>
* 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;
* <p>
* 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<SpdmMeasurementBlock> h1SpdmMeasurementBlockList;
private int length = 0;
/**
* Type Header 1 SPDM Measurement Block.
* SPDM hash algorithm.
*/
private SpdmMeasurementBlock h1SpdmMeasurementBlock;
@Getter
private int spdmHashAlgo = -1;
/**
* SPDM Measurement Block list. -implement this if there can be multiple SPDM blocks in one event
*/
//private List<SpdmMeasurementBlock> spdmMeasurementBlockList;
/**
* SPDM Measurement Block.
*/
private SpdmMeasurementBlock spdmMeasurementBlock;
public DeviceSecurityEventDataHeader(final byte[] dSEDbytes) {
public DeviceSecurityEventDataHeader(final byte[] dSEDbytes) throws UnsupportedEncodingException {
super(dSEDbytes);
byte[] lengthBytes = new byte[UefiConstants.SIZE_2];
System.arraycopy(dSEDbytes, 18, lengthBytes, 0,
UefiConstants.SIZE_2);
int h1Length = HexUtils.leReverseInt(lengthBytes);
length = HexUtils.leReverseInt(lengthBytes);
byte[] spdmHashAlgoBytes = new byte[UefiConstants.SIZE_4];
System.arraycopy(dSEDbytes, UefiConstants.OFFSET_20, spdmHashAlgoBytes, 0,
UefiConstants.SIZE_4);
int h1SpdmHashAlgoInt = HexUtils.leReverseInt(spdmHashAlgoBytes);
h1SpdmHashAlgo = SpdmHa.tcgAlgIdToString(h1SpdmHashAlgoInt);
spdmHashAlgo = HexUtils.leReverseInt(spdmHashAlgoBytes);
// byte[] deviceTypeBytes = new byte[UefiConstants.SIZE_4];
// System.arraycopy(dSEDbytes, UefiConstants.OFFSET_24, deviceTypeBytes, 0,
// UefiConstants.SIZE_4);
// int deviceTypeInt = HexUtils.leReverseInt(deviceTypeBytes);
// deviceType = deviceTypeToString(deviceTypeInt);
// For each measurement block, create a SpdmMeasurementBlock object (can there be many blocks ?)
extractDeviceType(dSEDbytes, 24);
// get the size of the SPDM Measurement Block
byte[] sizeOfSpdmMeasBlockBytes = new byte[UefiConstants.SIZE_2];
System.arraycopy(dSEDbytes, 30, sizeOfSpdmMeasBlockBytes, 0,
UefiConstants.SIZE_2);
int sizeOfSpdmMeas = HexUtils.leReverseInt(sizeOfSpdmMeasBlockBytes);
int sizeOfSpdmMeasBlock = sizeOfSpdmMeas + 4;
int sizeOfSpdmMeasBlock = sizeOfSpdmMeas + 4; // header is 4 bytes
// extract the bytes from the SPDM Measurement Block
byte[] spdmMeasBlockBytes = new byte[sizeOfSpdmMeasBlock];
System.arraycopy(dSEDbytes, 28, spdmMeasBlockBytes, 0,
sizeOfSpdmMeasBlock);
h1SpdmMeasurementBlock = new SpdmMeasurementBlock(spdmMeasBlockBytes);
spdmMeasurementBlock = new SpdmMeasurementBlock(spdmMeasBlockBytes);
// (can there be many >1 spdm block per event ?)
// byte[] algorithmIDBytes = new byte[UefiConstants.SIZE_2];
// int algLocation = UefiConstants.SIZE_28;
@ -72,11 +90,9 @@ public class DeviceSecurityEventDataHeader extends DeviceSecurityEventDataHeader
// String alg = TcgTpmtHa.tcgAlgIdToString(HexUtils.leReverseInt(algorithmIDBytes));
// algList.add(alg);
// }
// if ((algList.size() == 1) && (algList.get(0).compareTo("SHA1") == 0)) {
// cryptoAgile = false;
// } else {
// cryptoAgile = true;
// }
int devPathLenStartByte = 28 + sizeOfSpdmMeasBlock;
extractDevicePath(dSEDbytes, devPathLenStartByte);
}
@ -88,8 +104,12 @@ public class DeviceSecurityEventDataHeader extends DeviceSecurityEventDataHeader
*/
public String toString() {
String dsedHeaderInfo = "";
dsedHeaderInfo += "\n SPDM hash algorithm = " + h1SpdmHashAlgo;
dsedHeaderInfo += "\n SPDM Measurement Block " + h1SpdmMeasurementBlock.toString();
dsedHeaderInfo += headerBaseToString();
String spdmHashAlgoStr = SpdmHa.tcgAlgIdToString(spdmHashAlgo);
dsedHeaderInfo += "\n SPDM Hash Algorithm = " + spdmHashAlgoStr;
dsedHeaderInfo += "\n SPDM Measurement Block:";
dsedHeaderInfo += spdmMeasurementBlock.toString();
return dsedHeaderInfo;
}

View File

@ -4,70 +4,45 @@ import hirs.utils.HexUtils;
import hirs.utils.tpm.eventlog.spdm.SpdmHa;
import hirs.utils.tpm.eventlog.spdm.SpdmMeasurementBlock;
import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import hirs.utils.tpm.eventlog.uefi.UefiDevicePath;
import lombok.Getter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
/**
* Class to process the DEVICE_SECURITY_EVENT_DATA_HEADER or ..HEADER2 per PFP.
* Abstract class to process the DEVICE_SECURITY_EVENT_DATA_HEADER or ..HEADER2 per PFP.
* The first 16 bytes of the event data header MUST be a String based identifier (Signature),
* NUL-terminated, per PFP. The only currently defined Signature is "SPDM Device Sec",
* which implies the data is a DEVICE_SECURITY_EVENT_DATA or ..DATA2.
* 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:
* HEADERS defined by PFP v1.06 Rev 52.
* The ** indicates fields that are common to both ..HEADER and ..HEADER2.
* <p>
* 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;
* <p>
* 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:
* <p>
* Measurement block format {
* Index 1 byte;
* MeasurementSpec 1 byte;
* MeasurementSize 2 bytes;
* Measurement <MeasurementSize> bytes;
* }
* <p>
* DMTF measurement spec format {
* DMTFSpecMeasurementValueType 1 byte;
* DMTFSpecMeasurementValueSize 2 bytes;
* DMTFSpecMeasurementValue <DMTFSpecMeasurementValueSize> bytes;
* }
* <p>
* 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.
* <p>
*/
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;
}

View File

@ -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 {

View File

@ -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.
* <p>
* Measurement, defined by SPDM v1.03, Sect 10.11.1, Table 54:
* DMTF measurement spec format {
* DMTFSpecMeasurementValueType 1 byte;
* DMTFSpecMeasurementValueSize 2 bytes;
* DMTFSpecMeasurementValue <DMTFSpecMeasurementValueSize> bytes;
* }
* <p>
* 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.
* <p>
*/
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;
}
}

View File

@ -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.
* <p>
* 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 <MeasurementSize> bytes;
* }
* <p>
* 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;
}
}