Merge pull request #795 from nsacyber/v3_issue_793-spdm

Add SPDM Events Part 3
This commit is contained in:
D2B8CA1B27286366A8607B6858C0565962613D18D0546480078B520CD7AD705A 2024-07-03 10:41:48 -04:00 committed by GitHub
commit b4225f152f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 522 additions and 138 deletions

View File

@ -391,12 +391,7 @@ public class TpmPcrEvent {
break; break;
case EvConstants.EV_EFI_SPDM_FIRMWARE_BLOB: case EvConstants.EV_EFI_SPDM_FIRMWARE_BLOB:
case EvConstants.EV_EFI_SPDM_FIRMWARE_CONFIG: case EvConstants.EV_EFI_SPDM_FIRMWARE_CONFIG:
try {
sb.append(new EvEfiSpdmDeviceSecurityEvent(eventContent).toString()); sb.append(new EvEfiSpdmDeviceSecurityEvent(eventContent).toString());
} catch (UnsupportedEncodingException ueEx) {
log.error(ueEx);
sb.append(ueEx.toString());
}
break; break;
default: default:
sb.append("Unknown Event found\n"); sb.append("Unknown Event found\n");
@ -560,7 +555,9 @@ public class TpmPcrEvent {
case EvConstants.EV_EFI_HCRTM_EVENT: case EvConstants.EV_EFI_HCRTM_EVENT:
break; break;
case EvConstants.EV_EFI_SPDM_FIRMWARE_BLOB: case EvConstants.EV_EFI_SPDM_FIRMWARE_BLOB:
description += "Event Content:\n" + new EvEfiSpdmDeviceSecurityEvent(content).toString(); EvEfiSpdmDeviceSecurityEvent tempp = new EvEfiSpdmDeviceSecurityEvent(content);
description += "Event Content:\n" + tempp.toString();
// description += "Event Content:\n" + new EvEfiSpdmDeviceSecurityEvent(content).toString();
break; break;
case EvConstants.EV_EFI_SPDM_FIRMWARE_CONFIG: case EvConstants.EV_EFI_SPDM_FIRMWARE_CONFIG:
description += "Event Content:\n" + new EvEfiSpdmDeviceSecurityEvent(content).toString(); description += "Event Content:\n" + new EvEfiSpdmDeviceSecurityEvent(content).toString();

View File

@ -1,6 +1,11 @@
package hirs.utils.tpm.eventlog.events; package hirs.utils.tpm.eventlog.events;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import static hirs.utils.tpm.eventlog.events.DeviceSecurityEventHeader.DEVICE_TYPE_NONE;
import static hirs.utils.tpm.eventlog.events.DeviceSecurityEventHeader.DEVICE_TYPE_PCI;
import static hirs.utils.tpm.eventlog.events.DeviceSecurityEventHeader.DEVICE_TYPE_USB;
/** /**
@ -51,7 +56,20 @@ import lombok.Getter;
public abstract class DeviceSecurityEvent { public abstract class DeviceSecurityEvent {
/** /**
* Human readable description of the data within the * DeviceSecurityEventDataContext Object.
*/
@Getter
private DeviceSecurityEventDataDeviceContext dsedDevContext = null;
/**
* Device type.
*/
@Getter
@Setter
private int deviceType = -1;
/**
* Human-readable description of the data within the
* DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT. DEVICE can be either PCI or USB. * DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT. DEVICE can be either PCI or USB.
*/ */
@Getter @Getter
@ -68,34 +86,25 @@ public abstract class DeviceSecurityEvent {
/** /**
* Parse the Device Context structure, can be PCI or USB based on device type field. * Parse the Device Context structure, can be PCI or USB based on device type field.
* *
* @param dSEDbytes byte array holding the DeviceSecurityEventData. * @param dsedDeviceContextBytes byte array holding the DeviceSecurityEventData.
* @param startByte starting byte of the device structure (depends on length of header).
* @param deviceType device type either PCI or USB.
* *
*/ */
public void parseDeviceContext(final byte[] dSEDbytes, int startByte, int deviceType) { public void instantiateDeviceContext(final byte[] dsedDeviceContextBytes) {
int deviceContextLength = dSEDbytes.length - startByte; if (deviceType == DEVICE_TYPE_NONE) {
deviceContextInfo = "\n No Device Context (indicated by device type value of 0";
// get the device context bytes
byte[] deviceContextBytes = new byte[deviceContextLength];
System.arraycopy(dSEDbytes, startByte, deviceContextBytes, 0,
deviceContextLength);
if (deviceType == 0) {
deviceContextInfo = "No Device Context (indicated by device type value of 0";
} }
else if (deviceType == 1) { else if (deviceType == DEVICE_TYPE_PCI) {
DeviceSecurityEventDataPciContext dSEDpciContext dsedDevContext
= new DeviceSecurityEventDataPciContext(deviceContextBytes); = new DeviceSecurityEventDataPciContext(dsedDeviceContextBytes);
deviceContextInfo = dSEDpciContext.toString(); deviceContextInfo = dsedDevContext.toString();
}
else if (deviceType == DEVICE_TYPE_USB) {
// dsedDevContext
// = new DeviceSecurityEventDataUsbContext(dsedDeviceContextBytes);
// deviceContextInfo = dsedDevContext.toString();
deviceContextInfo = " Device Type: USB - To be implemented";
} }
//else if (deviceType == 2) {
//DeviceSecurityEventDataUsbContext dSEDusbContext
// = new DeviceSecurityEventDataUsbContext(deviceContextBytes);
//deviceContextInfo = dSEDusbContext.toString();
//deviceContextInfo = "Device type is USB - to be implemented in future";
//}
else { else {
deviceContextInfo = " Unknown device type; cannot process device context"; deviceContextInfo = " Unknown device type; cannot process device context";
} }

View File

@ -1,6 +1,8 @@
package hirs.utils.tpm.eventlog.events; package hirs.utils.tpm.eventlog.events;
import lombok.Getter; import lombok.Getter;
import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
/** /**
@ -24,15 +26,23 @@ public class DeviceSecurityEventData extends DeviceSecurityEvent {
/** /**
* DeviceSecurityEventData Constructor. * DeviceSecurityEventData Constructor.
* *
* @param dSEDbytes byte array holding the DeviceSecurityEventData. * @param dsedBytes byte array holding the DeviceSecurityEventData.
*/ */
public DeviceSecurityEventData(final byte[] dSEDbytes) throws UnsupportedEncodingException { public DeviceSecurityEventData(final byte[] dsedBytes) {
dsedHeader = new DeviceSecurityEventDataHeader(dSEDbytes); dsedHeader = new DeviceSecurityEventDataHeader(dsedBytes);
parseDeviceContext(dSEDbytes, dsedHeader.getDSEDheaderByteSize(), dsedHeader.getDeviceType()); setDeviceType(dsedHeader.getDeviceType());
int dsedHeaderLength = dsedHeader.getDsedHeaderLength();
int dsedDevContextLength = dsedBytes.length - dsedHeaderLength;
byte[] dsedDevContextBytes = new byte[dsedDevContextLength];
System.arraycopy(dsedBytes, dsedHeaderLength, dsedDevContextBytes, 0,
dsedDevContextLength);
instantiateDeviceContext(dsedDevContextBytes);
} }
/** /**
* Returns a human readable description of the data within this structure. * Returns a human-readable description of the data within this structure.
* *
* @return a description of this structure. * @return a description of this structure.
*/ */

View File

@ -2,7 +2,12 @@ package hirs.utils.tpm.eventlog.events;
import lombok.Getter; import lombok.Getter;
// TODO Placeholder class to be implemented upon getting test pattern import java.io.IOException;
import java.io.UnsupportedEncodingException;
import static hirs.utils.tpm.eventlog.events.DeviceSecurityEventDataHeader2.SUBHEADERTYPE_CERT_CHAIN;
import static hirs.utils.tpm.eventlog.events.DeviceSecurityEventDataHeader2.SUBHEADERTYPE_MEAS_BLOCK;
/** /**
* Class to process DEVICE_SECURITY_EVENT_DATA2. * Class to process DEVICE_SECURITY_EVENT_DATA2.
* Parses event data per PFP v1.06 Rev52 Table 26. * Parses event data per PFP v1.06 Rev52 Table 26.
@ -22,25 +27,70 @@ public class DeviceSecurityEventData2 extends DeviceSecurityEvent {
@Getter @Getter
private DeviceSecurityEventDataHeader2 dsedHeader2 = null; private DeviceSecurityEventDataHeader2 dsedHeader2 = null;
/**
* DeviceSecurityEventDataSubHeader Object.
*/
@Getter
private DeviceSecurityEventDataSubHeader dsedSubHeader = null;
/**
* Human readable description of the data within the
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER. SUB_HEADER can be either
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK or
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN
*/
@Getter
String subHeaderInfo = "";
/** /**
* DeviceSecurityEventData2 Constructor. * DeviceSecurityEventData2 Constructor.
* *
* @param dSEDbytes byte array holding the DeviceSecurityEventData2. * @param dsedBytes byte array holding the DeviceSecurityEventData2.
*/ */
public DeviceSecurityEventData2(final byte[] dSEDbytes) { public DeviceSecurityEventData2(final byte[] dsedBytes) {
dsedHeader2 = new DeviceSecurityEventDataHeader2(dSEDbytes); dsedHeader2 = new DeviceSecurityEventDataHeader2(dsedBytes);
// get subheader setDeviceType(dsedHeader2.getDeviceType());
parseDeviceContext(dSEDbytes, dsedHeader2.getDSEDheaderByteSize(), dsedHeader2.getDeviceType()); int dsedHeaderLength = dsedHeader2.getDsedHeaderLength();
int subHeaderType = dsedHeader2.getSubHeaderType();
int subHeaderLength = dsedHeader2.getSubHeaderLength();
subHeaderInfo = "\nSub header type: " + subHeaderType;
byte[] dsedSubHeaderBytes = new byte[subHeaderLength];
System.arraycopy(dsedBytes, dsedHeaderLength, dsedSubHeaderBytes, 0, subHeaderLength);
if (subHeaderType == SUBHEADERTYPE_MEAS_BLOCK) {
dsedSubHeader = new DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock(dsedSubHeaderBytes);
subHeaderInfo += dsedSubHeader.toString();
}
else if (subHeaderType == SUBHEADERTYPE_CERT_CHAIN) {
// dsedSubHeader = new DeviceSecurityEventDataSubHeaderCertChain();
subHeaderInfo += " Cert chain to be implemented ";
}
else {
subHeaderInfo += "Sub header type unknown";
}
int dsedDevContextStartByte = dsedHeaderLength + subHeaderLength;
int dsedDevContextLength = dsedBytes.length - dsedDevContextStartByte;
byte[] dsedDevContextBytes = new byte[dsedDevContextLength];
System.arraycopy(dsedBytes, dsedDevContextStartByte, dsedDevContextBytes, 0,
dsedDevContextLength);
instantiateDeviceContext(dsedDevContextBytes);
} }
/** /**
* Returns a human readable description of the data within this structure. * Returns a human-readable description of the data within this structure.
* *
* @return a description of this structure. * @return a description of this structure.
*/ */
public String toString() { public String toString() {
String dsedInfo = ""; String dsedInfo = "";
dsedInfo += dsedHeader2.toString();
dsedInfo += dsedSubHeader.toString();
dsedInfo += getDeviceContextInfo();
return dsedInfo; return dsedInfo;
} }
} }

View File

@ -31,17 +31,17 @@ public abstract class DeviceSecurityEventDataDeviceContext {
/** /**
* DeviceSecurityEventDataDeviceContext Constructor. * DeviceSecurityEventDataDeviceContext Constructor.
* *
* @param dSEDdeviceContextBytes byte array holding the DeviceSecurityEventData. * @param dsedDeviceContextBytes byte array holding the DeviceSecurityEventData.
*/ */
public DeviceSecurityEventDataDeviceContext(final byte[] dSEDdeviceContextBytes) { public DeviceSecurityEventDataDeviceContext(final byte[] dsedDeviceContextBytes) {
byte[] pciVersionBytes = new byte[2]; byte[] versionBytes = new byte[2];
System.arraycopy(dSEDdeviceContextBytes, 0, pciVersionBytes, 0, 2); System.arraycopy(dsedDeviceContextBytes, 0, versionBytes, 0, 2);
version = HexUtils.leReverseInt(pciVersionBytes); version = HexUtils.leReverseInt(versionBytes);
byte[] pciLengthBytes = new byte[2]; byte[] lengthBytes = new byte[2];
System.arraycopy(dSEDdeviceContextBytes, 2, pciLengthBytes, 0, 2); System.arraycopy(dsedDeviceContextBytes, 2, lengthBytes, 0, 2);
length = HexUtils.leReverseInt(pciLengthBytes); length = HexUtils.leReverseInt(lengthBytes);
} }
/** /**
@ -52,8 +52,7 @@ public abstract class DeviceSecurityEventDataDeviceContext {
public String toString() { public String toString() {
String dSEDdeviceContextCommonInfo = ""; String dSEDdeviceContextCommonInfo = "";
dSEDdeviceContextCommonInfo += "\n DeviceSecurityEventData Device Info:"; dSEDdeviceContextCommonInfo += "\n DeviceSecurityEventData Device Context:";
dSEDdeviceContextCommonInfo += "\n Device Structure Version = " + version;
return dSEDdeviceContextCommonInfo; return dSEDdeviceContextCommonInfo;
} }

View File

@ -6,6 +6,8 @@ import hirs.utils.tpm.eventlog.spdm.SpdmMeasurementBlock;
import hirs.utils.tpm.eventlog.uefi.UefiConstants; import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter; import lombok.Getter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
/** /**
@ -49,43 +51,46 @@ public class DeviceSecurityEventDataHeader extends DeviceSecurityEventHeader {
/** /**
* DeviceSecurityEventDataHeader Constructor. * DeviceSecurityEventDataHeader Constructor.
* *
* @param dSEDbytes byte array holding the DeviceSecurityEventData. * @param dsedBytes byte array holding the DeviceSecurityEventData.
*/ */
public DeviceSecurityEventDataHeader(final byte[] dSEDbytes) throws UnsupportedEncodingException { public DeviceSecurityEventDataHeader(final byte[] dsedBytes) {
super(dSEDbytes); super(dsedBytes);
byte[] lengthBytes = new byte[UefiConstants.SIZE_2]; byte[] lengthBytes = new byte[UefiConstants.SIZE_2];
System.arraycopy(dSEDbytes, 18, lengthBytes, 0, System.arraycopy(dsedBytes, 18, lengthBytes, 0,
UefiConstants.SIZE_2); UefiConstants.SIZE_2);
length = HexUtils.leReverseInt(lengthBytes); length = HexUtils.leReverseInt(lengthBytes);
byte[] spdmHashAlgoBytes = new byte[UefiConstants.SIZE_4]; byte[] spdmHashAlgoBytes = new byte[UefiConstants.SIZE_4];
System.arraycopy(dSEDbytes, UefiConstants.OFFSET_20, spdmHashAlgoBytes, 0, System.arraycopy(dsedBytes, UefiConstants.OFFSET_20, spdmHashAlgoBytes, 0,
UefiConstants.SIZE_4); UefiConstants.SIZE_4);
spdmHashAlgo = HexUtils.leReverseInt(spdmHashAlgoBytes); spdmHashAlgo = HexUtils.leReverseInt(spdmHashAlgoBytes);
extractDeviceType(dSEDbytes, 24); extractDeviceType(dsedBytes, 24);
// get the size of the SPDM Measurement Block // get the size of the SPDM Measurement Block
byte[] sizeOfSpdmMeasBlockBytes = new byte[UefiConstants.SIZE_2]; byte[] sizeOfSpdmMeasBlockBytes = new byte[UefiConstants.SIZE_2];
System.arraycopy(dSEDbytes, 30, sizeOfSpdmMeasBlockBytes, 0, System.arraycopy(dsedBytes, 30, sizeOfSpdmMeasBlockBytes, 0,
UefiConstants.SIZE_2); UefiConstants.SIZE_2);
int sizeOfSpdmMeas = HexUtils.leReverseInt(sizeOfSpdmMeasBlockBytes); int sizeOfSpdmMeas = HexUtils.leReverseInt(sizeOfSpdmMeasBlockBytes);
int sizeOfSpdmMeasBlock = sizeOfSpdmMeas + 4; // header is 4 bytes int sizeOfSpdmMeasBlock = sizeOfSpdmMeas + 4; // header is 4 bytes
// extract the bytes from the SPDM Measurement Block // extract the bytes that comprise the SPDM Measurement Block
byte[] spdmMeasBlockBytes = new byte[sizeOfSpdmMeasBlock]; byte[] spdmMeasBlockBytes = new byte[sizeOfSpdmMeasBlock];
System.arraycopy(dSEDbytes, 28, spdmMeasBlockBytes, 0, System.arraycopy(dsedBytes, 28, spdmMeasBlockBytes, 0,
sizeOfSpdmMeasBlock); sizeOfSpdmMeasBlock);
spdmMeasurementBlock = new SpdmMeasurementBlock(spdmMeasBlockBytes);
ByteArrayInputStream spdmMeasurementBlockData =
new ByteArrayInputStream(spdmMeasBlockBytes);
spdmMeasurementBlock = new SpdmMeasurementBlock(spdmMeasurementBlockData);
int devPathLenStartByte = 28 + sizeOfSpdmMeasBlock; int devPathLenStartByte = 28 + sizeOfSpdmMeasBlock;
extractDevicePathAndFinalSize(dSEDbytes, devPathLenStartByte); extractDevicePathAndFinalSize(dsedBytes, devPathLenStartByte);
} }
/** /**
* Returns a human readable description of the data within this structure. * Returns a human-readable description of the data within this structure.
* *
* @return a description of this structure. * @return a description of this structure.
*/ */

View File

@ -1,22 +1,161 @@
package hirs.utils.tpm.eventlog.events; package hirs.utils.tpm.eventlog.events;
import hirs.utils.tpm.eventlog.spdm.SpdmHa; import hirs.utils.HexUtils;
import lombok.Getter;
// Placeholder for Header2 data structure. import java.io.UnsupportedEncodingException;
/**
* Class to process the DEVICE_SECURITY_EVENT_DATA_HEADER2.
* DEVICE_SECURITY_EVENT_DATA_HEADER2 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_HEADER2 {
* UINT8 Signature[16];
* UINT16 Version;
* UINT8 AuthState;
* UINT8 Reserved
* UINT32 Length;
* UINT32 DeviceType;
* UINT32 SubHeaderType;
* UINT32 SubHeaderLength;
* UINT64 SubHeaderUID;
* UINT64 DevicePathLength;
* UNIT8 DevicePath[DevicePathLength]
* } DEVICE_SECURITY_EVENT_DATA_HEADER2;
* <p>
*/
public class DeviceSecurityEventDataHeader2 extends DeviceSecurityEventHeader { public class DeviceSecurityEventDataHeader2 extends DeviceSecurityEventHeader {
public DeviceSecurityEventDataHeader2(final byte[] dSEDbytes) { /**
* Event auth state
*/
@Getter
private int authState = 0;
/**
* Event data length.
*/
@Getter
private int length = 0;
/**
* Event sub headerType
*/
@Getter
private int subHeaderType = 0;
/**
* Event sub header length.
*/
@Getter
private int subHeaderLength = 0;
/**
* Event sub header UID.
*/
@Getter
private String subHeaderUid = "";
/**
* Auth state - success
*/
public static final int AUTH_SUCCESS = 0;
/**
* Auth state - digital signature of the data is valid, but the public key certificate chain is not
* validated with the entry in in the UEFI device signature variable
*/
public static final int AUTH_NO_AUTHORITY = 1;
/**
* Auth state - digital signature of the measurement data is valid, but the reported device capabilities,
* negotiated parameters or certificate chains were not validated by a transcript.
*/
public static final int AUTH_NO_BINDING = 2;
/**
* Auth state - data has no digital signature
*/
public static final int AUTH_FAIL_NO_SIG = 3;
/**
* Auth state - data is invalid
*/
public static final int AUTH_FAIL_INVALID = 4;
/**
* Auth state - device is not an SPDM-capable device
*/
public static final int AUTH_NO_SPDM = 0xFF;
/**
* Sub header type - SPDM measurement block
*/
public static final int SUBHEADERTYPE_MEAS_BLOCK = 0;
/**
* Sub header type - SPDM cert chain
*/
public static final int SUBHEADERTYPE_CERT_CHAIN = 1;
public DeviceSecurityEventDataHeader2(final byte[] dsedBytes) {
super(dsedBytes);
byte[] authStateBytes = new byte[1];
System.arraycopy(dsedBytes, 18, authStateBytes, 0, 1);
authState = HexUtils.leReverseInt(authStateBytes);
// byte[] reserved[Bytes]: 1 byte
byte[] lengthBytes = new byte[4];
System.arraycopy(dsedBytes, 20, lengthBytes, 0, 4);
length = HexUtils.leReverseInt(lengthBytes);
extractDeviceType(dsedBytes, 24);
byte[] subHeaderTypeBytes = new byte[4];
System.arraycopy(dsedBytes, 28, subHeaderTypeBytes, 0, 4);
subHeaderType = HexUtils.leReverseInt(subHeaderTypeBytes);
byte[] subHeaderLengthBytes = new byte[4];
System.arraycopy(dsedBytes, 32, subHeaderLengthBytes, 0, 4);
subHeaderLength = HexUtils.leReverseInt(subHeaderLengthBytes);
byte[] subHeaderUidBytes = new byte[8];
System.arraycopy(dsedBytes, 36, subHeaderUidBytes, 0, 8);
subHeaderUidBytes = HexUtils.leReverseByte(subHeaderUidBytes);
subHeaderUid = HexUtils.byteArrayToHexString(subHeaderUidBytes);
int devPathLenStartByte = 44;
extractDevicePathAndFinalSize(dsedBytes, devPathLenStartByte);
} }
/** /**
* Returns a human readable description of the data within this structure. * Returns a human-readable description of the data within this structure.
* *
* @return a description of this structure. * @return a description of this structure.
*/ */
public String toString() { public String toString() {
String dsedHeader2Info = ""; String dsedHeader2Info = "";
dsedHeader2Info += super.toString();
dsedHeader2Info += "\n AuthState: " + getAuthStateString();
dsedHeader2Info += "\n Sub header UID: " + subHeaderUid;
return dsedHeader2Info; return dsedHeader2Info;
} }
public String getAuthStateString() {
switch (authState) {
case AUTH_SUCCESS:
return ("AUTH_SUCCESS");
case AUTH_NO_AUTHORITY:
return ("AUTH_NO_AUTHORITY");
case AUTH_NO_BINDING:
return ("AUTH_NO_BINDING");
case AUTH_FAIL_NO_SIG:
return ("AUTH_FAIL_NO_SIG");
case AUTH_FAIL_INVALID:
return ("AUTH_FAIL_INVALID");
case AUTH_NO_SPDM:
return ("AUTH_NO_SPDM");
default:
return ("Auth State unknown");
}
}
} }

View File

@ -0,0 +1,20 @@
package hirs.utils.tpm.eventlog.events;
/**
* Class to process the DEVICE_SECURITY_EVENT_DATA_SUB_HEADER event per PFP.
*
* <p>
* typedef union tdDEVICE_SECURITY_EVENT_DATA_SUB_HEADER {
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN SpdmCertChain;
* DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_OEM_MEASUREMENT OemMeasurement;
* } DEVICE_SECURITY_EVENT_DATA_SUB_HEADER;
* <p>
*/
public abstract class DeviceSecurityEventDataSubHeader {
public DeviceSecurityEventDataSubHeader() {
}
}

View File

@ -0,0 +1,111 @@
package hirs.utils.tpm.eventlog.events;
import hirs.utils.HexUtils;
import hirs.utils.tpm.eventlog.spdm.SpdmHa;
import hirs.utils.tpm.eventlog.spdm.SpdmMeasurementBlock;
import lombok.Getter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Class to process the DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK event per PFP.
*
* <p>
* typedef union tdDEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK {
* UINT16 SpdmVersion;
* UINT8 SpdmMeasurementBlockCount;
* UINT8 Reserved;
* UINT32 SpdmMeasurementHashAlgo;
* SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock[SpdmMeasurementBlockCount];
* } DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK;
* <p>
*/
public class DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock extends DeviceSecurityEventDataSubHeader {
/**
* SPDM version.
*/
@Getter
private int spdmVersion = 0;
/**
* SPDM measurement block count.
*/
@Getter
private int spdmMeasurementBlockCount = 0;
/**
* SPDM measurement hash algorithm.
*/
@Getter
private int spdmMeasurementHashAlgo = -1;
/**
* List of SPDM Measurement Blocks.
*/
private List<SpdmMeasurementBlock> spdmMeasurementBlockList;
/**
* DeviceSecurityEventDataHeader Constructor.
*
* @param dsedSubHBytes byte array holding the DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock.
*/
public DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock(final byte[] dsedSubHBytes) {
spdmMeasurementBlockList = new ArrayList<>();
byte[] spdmVersionBytes = new byte[2];
System.arraycopy(dsedSubHBytes, 0, spdmVersionBytes, 0, 2);
spdmVersion = HexUtils.leReverseInt(spdmVersionBytes);
byte[] spdmMeasurementBlockCountBytes = new byte[1];
System.arraycopy(dsedSubHBytes, 2, spdmMeasurementBlockCountBytes, 0, 1);
spdmMeasurementBlockCount = HexUtils.leReverseInt(spdmMeasurementBlockCountBytes);
// byte[] reserved[Bytes]: 1 byte
byte[] spdmMeasurementHashAlgoBytes = new byte[4];
System.arraycopy(dsedSubHBytes, 4, spdmMeasurementHashAlgoBytes, 0, 4);
spdmMeasurementHashAlgo = HexUtils.leReverseInt(spdmMeasurementHashAlgoBytes);
// get the size of the SPDM Measurement Block List
int spdmMeasurementBlockListSize = dsedSubHBytes.length - 8;
// extract the bytes that comprise the SPDM Measurement Block List
byte[] spdmMeasurementBlockListBytes = new byte[spdmMeasurementBlockListSize];
System.arraycopy(dsedSubHBytes, 8, spdmMeasurementBlockListBytes, 0,
spdmMeasurementBlockListSize);
ByteArrayInputStream spdmMeasurementBlockListData =
new ByteArrayInputStream(spdmMeasurementBlockListBytes);
while (spdmMeasurementBlockListData.available() > 0) {
SpdmMeasurementBlock spdmMeasurementBlock;
spdmMeasurementBlock = new SpdmMeasurementBlock(spdmMeasurementBlockListData);
spdmMeasurementBlockList.add(spdmMeasurementBlock);
}
}
/**
* Returns a human-readable description of the data within this structure.
*
* @return a description of this structure.
*/
public String toString() {
String dsedSubHeaderInfo = "";
dsedSubHeaderInfo += "\n SPDM Version: " + spdmVersion;
String spdmHashAlgoStr = SpdmHa.tcgAlgIdToString(spdmMeasurementHashAlgo);
dsedSubHeaderInfo += "\n SPDM Hash Algorithm = " + spdmHashAlgoStr;
// SPDM Measurement Block List output
dsedSubHeaderInfo += "\n Number of SPDM Measurement Blocks = " + spdmMeasurementBlockList.size();
int spdmMeasBlockCnt = 1;
for (SpdmMeasurementBlock spdmMeasBlock : spdmMeasurementBlockList) {
dsedSubHeaderInfo += "\n SPDM Measurement Block # " + spdmMeasBlockCnt++ + " of " +
spdmMeasurementBlockList.size();
dsedSubHeaderInfo += spdmMeasBlock.toString();
}
return dsedSubHeaderInfo;
}
}

View File

@ -56,7 +56,8 @@ public abstract class DeviceSecurityEventHeader {
* Contains the size (in bytes) of the header. * Contains the size (in bytes) of the header.
*/ */
@Getter @Getter
private Integer dSEDheaderByteSize = 0; private Integer dsedHeaderLength = 0;
/** /**
* Signature (text) data. * Signature (text) data.
*/ */
@ -118,8 +119,8 @@ public abstract class DeviceSecurityEventHeader {
byte[] signatureBytes = new byte[UefiConstants.SIZE_16]; byte[] signatureBytes = new byte[UefiConstants.SIZE_16];
System.arraycopy(dSEDbytes, 0, signatureBytes, 0, UefiConstants.SIZE_16); System.arraycopy(dSEDbytes, 0, signatureBytes, 0, UefiConstants.SIZE_16);
signature = new String(signatureBytes, StandardCharsets.UTF_8) signature = new String(signatureBytes, StandardCharsets.UTF_8);
.substring(0, UefiConstants.SIZE_15); signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
byte[] versionBytes = new byte[UefiConstants.SIZE_2]; byte[] versionBytes = new byte[UefiConstants.SIZE_2];
System.arraycopy(dSEDbytes, UefiConstants.OFFSET_16, versionBytes, 0, System.arraycopy(dSEDbytes, UefiConstants.OFFSET_16, versionBytes, 0,
@ -131,14 +132,14 @@ public abstract class DeviceSecurityEventHeader {
/** /**
* Parse the device type from the Device Security Event Data Header/Header2. * Parse the device type from the Device Security Event Data Header/Header2.
* *
* @param dSEDbytes byte array holding the DeviceSecurityEventData/Data2. * @param dsedBytes byte array holding the DeviceSecurityEventData/Data2.
* @param startByte starting byte of device type (depends on header fields before it). * @param startByte starting byte of device type (depends on header fields before it).
*/ */
public void extractDeviceType(final byte[] dSEDbytes, int startByte) { public void extractDeviceType(final byte[] dsedBytes, int startByte) {
// get the device type ID // get the device type ID
byte[] deviceTypeBytes = new byte[UefiConstants.SIZE_4]; byte[] deviceTypeBytes = new byte[UefiConstants.SIZE_4];
System.arraycopy(dSEDbytes, startByte, deviceTypeBytes, 0, System.arraycopy(dsedBytes, startByte, deviceTypeBytes, 0,
UefiConstants.SIZE_4); UefiConstants.SIZE_4);
deviceType = HexUtils.leReverseInt(deviceTypeBytes); deviceType = HexUtils.leReverseInt(deviceTypeBytes);
} }
@ -147,15 +148,14 @@ public abstract class DeviceSecurityEventHeader {
* Parse the device path from the Device Security Event Data Header/Header2. * Parse the device path from the Device Security Event Data Header/Header2.
* Also, determine final length of header (will be used to extract the next data structure). * Also, determine final length of header (will be used to extract the next data structure).
* *
* @param dSEDbytes byte array holding the DeviceSecurityEventData/Data2. * @param dsedBytes byte array holding the DeviceSecurityEventData/Data2.
* @param startByte starting byte of device path (depends on header fields before it). * @param startByte starting byte of device path (depends on header fields before it).
*/ */
public void extractDevicePathAndFinalSize(final byte[] dSEDbytes, int startByte) public void extractDevicePathAndFinalSize(final byte[] dsedBytes, int startByte) {
throws UnsupportedEncodingException {
// get the device path length // get the device path length
byte[] devicePathLengthBytes = new byte[UefiConstants.SIZE_8]; byte[] devicePathLengthBytes = new byte[UefiConstants.SIZE_8];
System.arraycopy(dSEDbytes, startByte, devicePathLengthBytes, 0, System.arraycopy(dsedBytes, startByte, devicePathLengthBytes, 0,
UefiConstants.SIZE_8); UefiConstants.SIZE_8);
int devicePathLength = HexUtils.leReverseInt(devicePathLengthBytes); int devicePathLength = HexUtils.leReverseInt(devicePathLengthBytes);
@ -163,14 +163,19 @@ public abstract class DeviceSecurityEventHeader {
if (devicePathLength != 0) { if (devicePathLength != 0) {
startByte = startByte + UefiConstants.SIZE_8; startByte = startByte + UefiConstants.SIZE_8;
byte[] devPathBytes = new byte[devicePathLength]; byte[] devPathBytes = new byte[devicePathLength];
System.arraycopy(dSEDbytes, startByte, devPathBytes, System.arraycopy(dsedBytes, startByte, devPathBytes,
0, devicePathLength); 0, devicePathLength);
try {
devicePath = new UefiDevicePath(devPathBytes); devicePath = new UefiDevicePath(devPathBytes);
devicePathValid = true; devicePathValid = true;
} }
catch (UnsupportedEncodingException e) {
devicePathValid = false;
}
}
// header total size // header total size
dSEDheaderByteSize = startByte + devicePathLength; dsedHeaderLength = startByte + devicePathLength;
} }
/** /**
@ -181,25 +186,20 @@ public abstract class DeviceSecurityEventHeader {
* @return name of the device type * @return name of the device type
*/ */
public String deviceTypeToString(final int deviceTypeInt) { public String deviceTypeToString(final int deviceTypeInt) {
String deviceTypeStr;
switch (deviceTypeInt) { switch (deviceTypeInt) {
case DEVICE_TYPE_NONE: case DEVICE_TYPE_NONE:
deviceTypeStr = "No device type"; return "No device type";
break;
case DEVICE_TYPE_PCI: case DEVICE_TYPE_PCI:
deviceTypeStr = "PCI"; return "PCI";
break;
case DEVICE_TYPE_USB: case DEVICE_TYPE_USB:
deviceTypeStr = "USB"; return "USB";
break;
default: default:
deviceTypeStr = "Unknown or invalid Device Type"; return "Unknown or invalid Device Type";
} }
return deviceTypeStr;
} }
/** /**
* Returns a human readable description of the data common to header structures. * Returns a human-readable description of the data common to header structures.
* *
* @return a description of this structure. * @return a description of this structure.
*/ */

View File

@ -2,7 +2,9 @@ package hirs.utils.tpm.eventlog.events;
import hirs.utils.HexUtils; import hirs.utils.HexUtils;
import hirs.utils.tpm.eventlog.uefi.UefiConstants; import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter;
import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -31,10 +33,16 @@ import java.nio.charset.StandardCharsets;
*/ */
public class EvEfiSpdmDeviceSecurityEvent { public class EvEfiSpdmDeviceSecurityEvent {
/**
* DeviceSecurityEvent Object.
*/
private DeviceSecurityEvent dsed = null;
/** /**
* Signature (text) data. * Signature (text) data.
*/ */
private String signature = ""; private String signature = "";
/** /**
* Human readable description of the data within this DEVICE_SECURITY_EVENT_DATA/..DATA2 event. * Human readable description of the data within this DEVICE_SECURITY_EVENT_DATA/..DATA2 event.
*/ */
@ -46,32 +54,43 @@ public class EvEfiSpdmDeviceSecurityEvent {
* @param eventData byte array holding the event to process. * @param eventData byte array holding the event to process.
* @throws java.io.UnsupportedEncodingException if input fails to parse. * @throws java.io.UnsupportedEncodingException if input fails to parse.
*/ */
public EvEfiSpdmDeviceSecurityEvent(final byte[] eventData) throws UnsupportedEncodingException { public EvEfiSpdmDeviceSecurityEvent(final byte[] eventData) {
byte[] signatureBytes = new byte[UefiConstants.SIZE_15]; byte[] signatureBytes = new byte[UefiConstants.SIZE_16];
System.arraycopy(eventData, 0, signatureBytes, 0, UefiConstants.SIZE_15); System.arraycopy(eventData, 0, signatureBytes, 0, UefiConstants.SIZE_16);
signature = new String(signatureBytes, StandardCharsets.UTF_8); signature = new String(signatureBytes, StandardCharsets.UTF_8);
signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
if (signature.contains("SPDM Device Sec")) { // implies Device Security event
spdmInfo = " Signature = SPDM Device Sec";
byte[] versionBytes = new byte[UefiConstants.SIZE_2]; byte[] versionBytes = new byte[UefiConstants.SIZE_2];
System.arraycopy(eventData, UefiConstants.OFFSET_16, versionBytes, 0, System.arraycopy(eventData, UefiConstants.OFFSET_16, versionBytes, 0,
UefiConstants.SIZE_2); UefiConstants.SIZE_2);
String version = HexUtils.byteArrayToHexString(versionBytes); String version = HexUtils.byteArrayToHexString(versionBytes);
if (version == "") {
if (version.equals("0100")) { version = "version not readable";
DeviceSecurityEventData dSED = new DeviceSecurityEventData(eventData);
spdmInfo += dSED.toString();
} }
else if (version.equals("0200")) {
DeviceSecurityEventData2 dSED2 = new DeviceSecurityEventData2(eventData); if (signature.contains("SPDM Device Sec2")) {
spdmInfo += dSED2.toString();
spdmInfo = " Signature = SPDM Device Sec2";
if (version.equals("0200")) {
dsed = new DeviceSecurityEventData2(eventData);
spdmInfo += dsed.toString();
} }
else { else {
spdmInfo += " Unknown version of DeviceSecurityEventData structure"; spdmInfo += " Incompatible version for DeviceSecurityEventData2: " + version;
}
}
else if (signature.contains("SPDM Device Sec")) { // implies Device Security event
spdmInfo = " Signature = SPDM Device Sec";
if (version.equals("0100")) {
dsed = new DeviceSecurityEventData(eventData);
spdmInfo += dsed.toString();
}
else {
spdmInfo += " Incompatible version for DeviceSecurityEventData: " + version;
} }
} }
else { else {
@ -82,7 +101,7 @@ public class EvEfiSpdmDeviceSecurityEvent {
/** /**
* Returns a description of this event. * Returns a description of this event.
* *
* @return Human readable description of this event. * @return Human-readable description of this event.
*/ */
public String toString() { public String toString() {
return spdmInfo; return spdmInfo;

View File

@ -62,9 +62,11 @@ public class SpdmMeasurement {
} }
/** /**
* Returns a human readable description of the data within this structure. * Lookup for SPDM measurement value type
* *
* @return a description of this structure.. * @param measValType the numerical representation of the measurement value type.
*
* @return a description of the measurement value type.
*/ */
public String dmtfSpecMeasurementValueTypeToString(final int measValType) { public String dmtfSpecMeasurementValueTypeToString(final int measValType) {
@ -92,7 +94,7 @@ public class SpdmMeasurement {
measValTypeStr = "Mutable firmware's version number"; measValTypeStr = "Mutable firmware's version number";
break; break;
case 7: case 7:
measValTypeStr = "Mutable firmware's security verison number"; measValTypeStr = "Mutable firmware's security version number";
break; break;
case 8: case 8:
measValTypeStr = "Hash-extended measurement"; measValTypeStr = "Hash-extended measurement";
@ -109,6 +111,11 @@ public class SpdmMeasurement {
return measValTypeStr; return measValTypeStr;
} }
/**
* Returns a human-readable description of the data within this structure.
*
* @return a description of this structure.
*/
public String toString() { public String toString() {
String spdmMeasInfo = ""; String spdmMeasInfo = "";

View File

@ -4,6 +4,14 @@ import hirs.utils.HexUtils;
import hirs.utils.tpm.eventlog.uefi.UefiConstants; import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter; import lombok.Getter;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/** /**
* Class to process the SpdmMeasurementBlock. * Class to process the SpdmMeasurementBlock.
* <p> * <p>
@ -38,49 +46,58 @@ public class SpdmMeasurementBlock {
* SPDM Measurement. * SPDM Measurement.
*/ */
private SpdmMeasurement spdmMeasurement; private SpdmMeasurement spdmMeasurement;
/**
* Error reading SPDM Measurement Block.
*/
private boolean spdmMeasurementBlockReadError = false;
/** /**
* SpdmMeasurementBlock Constructor. * SpdmMeasurementBlock Constructor.
* *
* @param spdmMeasBlockBytes byte array holding the SPDM Measurement Block bytes. * @param spdmMeasBlocks byte array holding the SPDM Measurement Block bytes.
*/ */
public SpdmMeasurementBlock(final byte[] spdmMeasBlockBytes) { public SpdmMeasurementBlock(final ByteArrayInputStream spdmMeasBlocks) {
try {
byte[] indexBytes = new byte[1]; byte[] indexBytes = new byte[1];
System.arraycopy(spdmMeasBlockBytes, 0, indexBytes, 0, spdmMeasBlocks.read(indexBytes);
1);
index = HexUtils.leReverseInt(indexBytes); index = HexUtils.leReverseInt(indexBytes);
byte[] measurementSpecBytes = new byte[1]; byte[] measurementSpecBytes = new byte[1];
System.arraycopy(spdmMeasBlockBytes, 1, measurementSpecBytes, 0, spdmMeasBlocks.read(measurementSpecBytes);
1);
measurementSpec = HexUtils.leReverseInt(measurementSpecBytes); measurementSpec = HexUtils.leReverseInt(measurementSpecBytes);
// in future, can crosscheck this measurement size with the MeasurementSpec hash alg size // in future, can crosscheck this measurement size with the MeasurementSpec hash alg size
byte[] measurementSizeBytes = new byte[2]; byte[] measurementSizeBytes = new byte[2];
System.arraycopy(spdmMeasBlockBytes, 2, measurementSizeBytes, 0, spdmMeasBlocks.read(measurementSizeBytes);
2);
int measurementSize = HexUtils.leReverseInt(measurementSizeBytes); int measurementSize = HexUtils.leReverseInt(measurementSizeBytes);
byte[] measurementBytes = new byte[measurementSize]; byte[] measurementBytes = new byte[measurementSize];
System.arraycopy(spdmMeasBlockBytes, 4, measurementBytes, 0, spdmMeasBlocks.read(measurementBytes);
measurementSize);
spdmMeasurement = new SpdmMeasurement(measurementBytes); spdmMeasurement = new SpdmMeasurement(measurementBytes);
} catch (IOException ioEx) {
spdmMeasurementBlockReadError = true;
}
} }
/** /**
* Returns a human readable description of the data within this structure. * Returns a human-readable description of the data within this structure.
* *
* @return a description of this structure.. * @return a description of this structure..
*/ */
public String toString() { public String toString() {
String spdmMeasBlockInfo = ""; String spdmMeasBlockInfo = "";
if(spdmMeasurementBlockReadError) {
spdmMeasBlockInfo += "\n Error reading SPDM Measurement Block";
}
else {
spdmMeasBlockInfo += "\n Index = " + index; spdmMeasBlockInfo += "\n Index = " + index;
spdmMeasBlockInfo += "\n MeasurementSpec = " + measurementSpec; spdmMeasBlockInfo += "\n MeasurementSpec = " + measurementSpec;
spdmMeasBlockInfo += spdmMeasurement.toString(); spdmMeasBlockInfo += spdmMeasurement.toString();
}
return spdmMeasBlockInfo; return spdmMeasBlockInfo;
} }
} }

View File

@ -216,10 +216,11 @@ public class UefiVariable {
case "KEK": case "KEK":
case "db": case "db":
case "dbx": case "dbx":
break;
case "devdb": // SPDM_DEVICE_POLICY and SPDM_DEVICE_AUTHORITY case "devdb": // SPDM_DEVICE_POLICY and SPDM_DEVICE_AUTHORITY
// (update when test patterns exist) // (update when test patterns exist)
efiVariable.append(" EV_EFI_SPDM_DEVICE_POLICY and EV_EFI_SPDM_DEVICE_AUTHORITY: " + efiVariable.append(" EV_EFI_SPDM_DEVICE_POLICY and EV_EFI_SPDM_DEVICE_AUTHORITY: " +
"To be processed once more test patterns exist\n"); "To be processed once more test patterns exist");
break; break;
case "Boot00": case "Boot00":
efiVariable.append(bootv.toString()); efiVariable.append(bootv.toString());