From e91517c77cd8be8851c25dbf7acea8d5dd1023bd Mon Sep 17 00:00:00 2001 From: iadgovuser58 <124906646+iadgovuser58@users.noreply.github.com> Date: Fri, 2 Aug 2024 18:35:08 -0400 Subject: [PATCH] parsing SPDM cert chain --- .../events/DeviceSecurityEventData2.java | 4 +- ...ceSecurityEventDataSubHeaderCertChain.java | 56 ++++---- ...ventDataSubHeaderSpdmMeasurementBlock.java | 12 +- .../eventlog/spdm/SpdmCertificateChain.java | 135 ++++++++++++------ .../hirs/utils/tpm/eventlog/spdm/SpdmHa.java | 38 +++++ .../tpm/eventlog/uefi/UefiSignatureData.java | 12 +- .../tpm/eventlog/uefi/UefiSignatureList.java | 42 +++++- 7 files changed, 214 insertions(+), 85 deletions(-) diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventData2.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventData2.java index b2f63ba4..7a2c2479 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventData2.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventData2.java @@ -76,14 +76,14 @@ public class DeviceSecurityEventData2 extends DeviceSecurityEvent { } } else if (subHeaderType == DeviceSecurityEventDataSubHeader.SUBHEADERTYPE_CERT_CHAIN) { - subHeaderInfo += "\n Cert chain to be implemented "; +// subHeaderInfo += "\n Cert chain to be implemented "; try { dsedSubHeader = new DeviceSecurityEventDataSubHeaderCertChain(dsedSubHeaderBytes); subHeaderInfo += dsedSubHeader.toString(); } catch(NullPointerException e) { - subHeaderInfo = "\n Could not interpret Sub header info for SPDM measurement block"; + subHeaderInfo = "\n Could not interpret Sub header info for SPDM cert chain"; } } else { diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataSubHeaderCertChain.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataSubHeaderCertChain.java index eac5bc8a..dc7c22c3 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataSubHeaderCertChain.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataSubHeaderCertChain.java @@ -1,8 +1,8 @@ package hirs.utils.tpm.eventlog.events; import hirs.utils.HexUtils; +import hirs.utils.tpm.eventlog.spdm.SpdmCertificateChain; import hirs.utils.tpm.eventlog.spdm.SpdmHa; -import hirs.utils.tpm.eventlog.spdm.SpdmMeasurementBlock; import lombok.Getter; import java.io.ByteArrayInputStream; @@ -20,24 +20,33 @@ import java.util.ArrayList; * SPDM_CERT_CHAIN SpdmCertChain; * } DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN; *
+ * SpdmVersion: SpdmBaseHashAlgo + * SpdmSlotId: SlotId associated with this SPDM Certificate Chain + * SpdmBaseHashAlgo: SPDM Base Hash Algorithm for the root certificate in the SPDM Certificate chain + * SpdmCertChain: SPDM Certificate Chain */ public class DeviceSecurityEventDataSubHeaderCertChain extends DeviceSecurityEventDataSubHeader{ /** * SPDM version. */ - @Getter private int spdmVersion = 0; /** * SPDM slot ID. */ - @Getter - private int spdmLotId = 0; + private int spdmSlotId = 0; /** * SPDM base hash algorithm. */ - @Getter private int spdmBaseHashAlgo = -1; + /** + * SPDM cert chain. + */ + private SpdmCertificateChain spdmCertChain = null; + /** + * Human-readable description of any error associated with SPDM base hash alg. + */ + String spdmBaseHashAlgoError = ""; /** * DeviceSecurityEventDataSubHeaderCertChain Constructor. @@ -52,7 +61,7 @@ public class DeviceSecurityEventDataSubHeaderCertChain extends DeviceSecurityEve byte[] spdmLotIdBytes = new byte[1]; System.arraycopy(dsedSubHBytes, 2, spdmLotIdBytes, 0, 1); - spdmLotId = HexUtils.leReverseInt(spdmLotIdBytes); + spdmSlotId = HexUtils.leReverseInt(spdmLotIdBytes); // byte[] reserved[Bytes]: 1 byte @@ -68,13 +77,15 @@ public class DeviceSecurityEventDataSubHeaderCertChain extends DeviceSecurityEve System.arraycopy(dsedSubHBytes, 8, spdmCertChainBytes, 0, spdmCertChainSize); -// ByteArrayInputStream spdmMeasurementBlockListData = -// new ByteArrayInputStream(spdmMeasurementBlockListBytes); -// while (spdmMeasurementBlockListData.available() > 0) { -// SpdmMeasurementBlock spdmMeasurementBlock; -// spdmMeasurementBlock = new SpdmMeasurementBlock(spdmMeasurementBlockListData); -// spdmMeasurementBlockList.add(spdmMeasurementBlock); -// } + int spdmBaseHashAlgoSize = SpdmHa.tcgAlgIdToByteSize(spdmBaseHashAlgo); + + if(spdmBaseHashAlgoSize > 0) { + spdmCertChain = new SpdmCertificateChain(spdmCertChainBytes, spdmBaseHashAlgoSize); + } + else { + spdmBaseHashAlgoError += "SPDM base hash algorithm size is not >0"; + } + } @@ -85,18 +96,13 @@ public class DeviceSecurityEventDataSubHeaderCertChain extends DeviceSecurityEve */ 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(); -// } + dsedSubHeaderInfo += "\n SPDM Version = " + spdmVersion; + dsedSubHeaderInfo += "\n SPDM Slot ID = " + spdmSlotId; + String spdmBaseHashAlgoStr = SpdmHa.tcgAlgIdToString(spdmBaseHashAlgo); + dsedSubHeaderInfo += "\n SPDM Base Hash Algorithm = " + spdmBaseHashAlgoStr; + + // SPDM Certificate Chain output + dsedSubHeaderInfo += spdmCertChain.toString(); return dsedSubHeaderInfo; } diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock.java index 9df680ac..19c5d42a 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/events/DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock.java @@ -21,6 +21,14 @@ import java.util.List; * SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock[SpdmMeasurementBlockCount]; * } DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK; *
+ *
+ * SpdmMeasurementBlock is an array of SPDM_MEASUREMENT_BLOCKs
+ * The size of each block is the same and can be found by either:
+ * 1) 4 + SpdmMeasurementBlock MeasurementSize
+ * OR
+ * 2) 4 + hash length of the hash algorithm found in
+ * DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK SpdmMeasurementHashAlgo
+ * where 4 is the size of the SpdmMeasurementBlock header
*/
public class DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock extends DeviceSecurityEventDataSubHeader {
@@ -68,7 +76,7 @@ public class DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock extends Device
System.arraycopy(dsedSubHBytes, 4, spdmMeasurementHashAlgoBytes, 0, 4);
spdmMeasurementHashAlgo = HexUtils.leReverseInt(spdmMeasurementHashAlgoBytes);
- // get the size of the SPDM Measurement Block List
+ // get the total size of the SPDM Measurement Block List
int spdmMeasurementBlockListSize = dsedSubHBytes.length - 8;
// extract the bytes that comprise the SPDM Measurement Block List
@@ -92,7 +100,7 @@ public class DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock extends Device
*/
public String toString() {
String dsedSubHeaderInfo = "";
- dsedSubHeaderInfo += "\n SPDM Version: " + spdmVersion;
+ dsedSubHeaderInfo += "\n SPDM Version = " + spdmVersion;
String spdmHashAlgoStr = SpdmHa.tcgAlgIdToString(spdmMeasurementHashAlgo);
dsedSubHeaderInfo += "\n SPDM Hash Algorithm = " + spdmHashAlgoStr;
diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmCertificateChain.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmCertificateChain.java
index ad6fb351..7aaf1cb2 100644
--- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmCertificateChain.java
+++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/spdm/SpdmCertificateChain.java
@@ -1,8 +1,10 @@
package hirs.utils.tpm.eventlog.spdm;
import hirs.utils.HexUtils;
+import hirs.utils.tpm.eventlog.events.DeviceSecurityEventDataSubHeaderSpdmMeasurementBlock;
import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import hirs.utils.tpm.eventlog.uefi.UefiSignatureData;
+import hirs.utils.tpm.eventlog.uefi.UefiSignatureList;
import hirs.utils.tpm.eventlog.uefi.UefiX509Cert;
import lombok.Getter;
@@ -31,6 +33,8 @@ import java.util.ArrayList;
* hash algorithm is included in the DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN
* structure as the member "SpdmBaseHashAlg"
* RootHash: the digest of the Root Certificate.
+ * size is determined by hash algorithm selected by the most recent SPDM ALGORITHMS response;
+ * the hash algorithm is the DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN SpdmBaseHashAlgo
* Certificates: Complete cert chain consisting of 1 or more ASN.1 DER-encoded X.509 v3 certs
* this field shall be in Encoded ASN.1 byte order
*/
@@ -44,75 +48,99 @@ public class SpdmCertificateChain {
* Root hash.
*/
private byte[] rootHash = null;
-
/**
* Number of certs in the SPDM cert chain.
*/
- @Getter
private int numberOfCerts = 0;
/**
* Array List of certs found in the chain.
*/
// private ArrayList
* typedef struct _EFI_SIGNATURE_DATA {
* EFI_GUID SignatureOwner;
diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiSignatureList.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiSignatureList.java
index b2a682d1..ec780cdb 100644
--- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiSignatureList.java
+++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiSignatureList.java
@@ -12,12 +12,18 @@ import java.util.ArrayList;
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
/**
- * Class for processing the contents of a Secure Boot DB or DBX contents.
- * used for EFIVariables associated with Secure Boot
- * as defined by Section 32.4.1 Signature Database from the UEFI 2.8 specification.
+ * Class for processing either
+ * 1) the contents of a Secure Boot PK, KEK, DB or DBX contents,
+ * used for EFIVariables associated with Secure Boot,
+ * as defined by Section 32.4.1 Signature Database from the UEFI 2.8 specification
+ * 2) the contents of an SPDM devdb,
+ * used for SPDM Device Policy, whose data is an EFIVariable
+ * as defined by PFP v1.06 Rev52, Section 10.4
*
- * An EFI Signature List is actual a list of Certificates used to verify a Signature.
- * This is mainly found in PCR[7] UEFI variables for the Secure Boot PK, KEK, Db and DBx variables.
+ * An EFI Signature List is actually a list of Certificates used to verify a Signature.
+ * This is mainly found in PCR[7] UEFI variables for either the
+ * Secure Boot PK, KEK, Db and DBx variables
+ * or the SPDM devdb variable (under EV_EFI_SPDM_DEVICE_POLICY).
*
* typedef struct _EFI_SIGNATURE_LIST {
* EFI_GUID SignatureType;
@@ -27,6 +33,27 @@ import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIB
* // UINT8 SignatureHeader[SignatureHeaderSize];
* // EFI_SIGNATURE_DATA Signatures[...][SignatureSize];
* } EFI_SIGNATURE_LIST;
+ *
+ * Signatures[][] is an array of signatures.
+ * - Each signature is SignatureSize bytes in length.
+ * - The format of the signature is defined by SignatureType (SHA256, X509)
+ *
+ * / |-------------------------| ------- SignatureType
+ * / | Signature List Header | SignatureListSize
+ * |---------------------| / |-------------------------|\ SignatureHeaderSize
+ * | Signature List #0 | / | Signature Header | \ _____ SignatureSize
+ * | | / |-------------------------|
+ * |---------------------| / | Signature #0 |
+ * | Signature List #1 | / |-------------------------|
+ * |---------------------|/ | Signature #1 | --> each Signature is
+ * | Signature List #2 | |-------------------------| 1 UefiSignatureData
+ * | | | Signature #2 | (1 cert or hash)
+ * | | |-------------------------|
+ * |---------------------| | ... |
+ * \ | |
+ * \ |-------------------------|
+ * \ | Signature #n |
+ * \ |-------------------------|
*/
public class UefiSignatureList {
/**
@@ -125,7 +152,7 @@ public class UefiSignatureList {
vendorTableFileStatus = signatureType.getVendorTableFileStatus();
// if signatureType is invalid, don't even process any of the data
- // however, if signatureTYpe is valid, but some of the data later on is invalid, that will
+ // however, if signatureType is valid, but some of the data later on is invalid, that will
// be caught when UefiSignatureData is processed
if (!isValidSigListGUID(signatureType)) {
//processSignatureData(lists);
@@ -230,7 +257,10 @@ public class UefiSignatureList {
sigInfo.append(" UEFI Signature List Type = " + signatureType.toString() + "\n");
sigInfo.append(" Number of Certs or Hashes in UEFI Signature List = " + numberOfCerts + "\n");
+ int certOrHashCnt = 1;
for (int i = 0; i < sigList.size(); i++) {
+ sigInfo.append(" Cert or Hash # " + certOrHashCnt++ + " of " +
+ numberOfCerts + ": ------------------\n");
UefiSignatureData certData = sigList.get(i);
sigInfo.append(certData.toString());
}