parsing SPDM cert chain

This commit is contained in:
iadgovuser58 2024-07-19 18:18:06 -04:00
parent 602fd88e53
commit 0266b5293e
2 changed files with 80 additions and 41 deletions

View File

@ -45,8 +45,6 @@ public class DeviceSecurityEventDataSubHeaderCertChain extends DeviceSecurityEve
*/
public DeviceSecurityEventDataSubHeaderCertChain(final byte[] dsedSubHBytes) {
spdmMeasurementBlockList = new ArrayList<>();
byte[] spdmVersionBytes = new byte[2];
System.arraycopy(dsedSubHBytes, 0, spdmVersionBytes, 0, 2);
spdmVersion = HexUtils.leReverseInt(spdmVersionBytes);
@ -69,12 +67,12 @@ 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);
}
// ByteArrayInputStream spdmMeasurementBlockListData =
// new ByteArrayInputStream(spdmMeasurementBlockListBytes);
// while (spdmMeasurementBlockListData.available() > 0) {
// SpdmMeasurementBlock spdmMeasurementBlock;
// spdmMeasurementBlock = new SpdmMeasurementBlock(spdmMeasurementBlockListData);
// spdmMeasurementBlockList.add(spdmMeasurementBlock);
// }
}
}

View File

@ -1,17 +1,25 @@
package hirs.utils.tpm.eventlog.spdm;
import hirs.utils.HexUtils;
import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import hirs.utils.tpm.eventlog.uefi.UefiSignatureData;
import hirs.utils.tpm.eventlog.uefi.UefiX509Cert;
import lombok.Getter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
/**
* Class to process the SpdmCertificateChain.
* <p>
* Certificate chain format, defined by SPDM v1.03, Sect 10.6.1, Table 33:
* Certificate chain format {
* Length 1 byte;
* Length 2 bytes;
* Reserved 2 bytes;
* RootHash <H> bytes;
* Certificates <Length> - (4 + <H>) bytes;
@ -31,47 +39,80 @@ public class SpdmCertificateChain {
/**
* Length of the certificate chain to include all fields in this structure.
*/
@Getter
private int length = 0;
/**
* Root hash.
*/
private byte[] rootHash = null;
/**
* Certificates.
*/
// private SpdmMeasurement spdmMeasurement;
/**
* Error reading SPDM Cert Chain.
*/
private boolean spdmCertificateChainReadError = false;
/**
* SpdmMeasurementBlock Constructor.
* Number of certs in the SPDM cert chain.
*/
@Getter
private int numberOfCerts = 0;
/**
* Array List of certs found in the chain.
*/
// private ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
private ArrayList<UefiX509Cert> certList = new ArrayList<UefiX509Cert>();
/**
* SpdmCertificateChain Constructor.
*
* @param spdmMeasBlocks byte array holding the SPDM Measurement Block bytes.
* @param spdmCertChainBytes byte array holding the SPDM Cert Chain bytes.
*/
public SpdmCertificateChain(final ByteArrayInputStream spdmMeasBlocks) {
public SpdmCertificateChain(final byte[] spdmCertChainBytes, final int rootHashLength) throws CertificateException, NoSuchAlgorithmException, IOException {
try {
byte[] indexBytes = new byte[1];
spdmMeasBlocks.read(indexBytes);
index = HexUtils.leReverseInt(indexBytes);
byte[] lengthBytes = new byte[2];
System.arraycopy(spdmCertChainBytes, 0, lengthBytes, 0, 2);
length = HexUtils.leReverseInt(lengthBytes);
byte[] measurementSpecBytes = new byte[1];
spdmMeasBlocks.read(measurementSpecBytes);
measurementSpec = HexUtils.leReverseInt(measurementSpecBytes);
// Reserved: 2 bytes
// in future, can crosscheck this measurement size with the MeasurementSpec hash alg size
byte[] measurementSizeBytes = new byte[2];
spdmMeasBlocks.read(measurementSizeBytes);
int measurementSize = HexUtils.leReverseInt(measurementSizeBytes);
rootHash = new byte[rootHashLength];
System.arraycopy(spdmCertChainBytes, 4, rootHash, 0, rootHashLength);
byte[] measurementBytes = new byte[measurementSize];
spdmMeasBlocks.read(measurementBytes);
spdmMeasurement = new SpdmMeasurement(measurementBytes);
} catch (IOException ioEx) {
spdmMeasurementBlockReadError = true;
int certChainStartPos = 4 + rootHashLength;
int certChainLength = spdmCertChainBytes.length - certChainStartPos;
byte[] certChainBytes = new byte[certChainLength];
System.arraycopy(spdmCertChainBytes, certChainStartPos, certChainBytes, 0, certChainLength);
processCertChain(certChainBytes);
}
//TODO possily get rid of exceptions
/**
* Method for processing the data in an EFI SignatureList (ex. can be one or more X509 certs)
*
* @param certChainData Byte array holding the cert chain data
* @throws java.security.cert.CertificateException If there's a problem parsing the X509 certificate.
* @throws java.security.NoSuchAlgorithmException if there's a problem hashing the certificate.
* @throws java.io.IOException If there's a problem parsing the signature data.
*/
private void processCertChain(final byte[] certChainData)
throws CertificateException, NoSuchAlgorithmException, IOException {
UefiX509Cert cert = null;
ByteArrayInputStream certChainDataIS = new ByteArrayInputStream(certChainData);
while (certChainDataIS.available() > 0) {
byte[] certType = new byte[UefiConstants.SIZE_2];
certChainDataIS.read(certType);
byte[] certLength = new byte[UefiConstants.SIZE_2];
certChainDataIS.read(certLength);
int cLength = new BigInteger(certLength).intValue() + UefiConstants.SIZE_4;
byte[] certData = new byte[cLength];
certChainDataIS.read(certData);
// put the cert back together
byte[] certBlob = new byte[cLength + UefiConstants.SIZE_4];
System.arraycopy(certType, 0, certBlob, 0, 2);
System.arraycopy(certLength, 0, certBlob, 2, 2);
System.arraycopy(certData, 0, certBlob, UefiConstants.OFFSET_4, cLength);
cert = new UefiX509Cert(certBlob);
// cert = new X509Certificate(certBlob);
certList.add(cert);
numberOfCerts++;
}
}
@ -82,7 +123,7 @@ public class SpdmCertificateChain {
*/
public String toString() {
// String spdmMeasBlockInfo = "";
String spdmMeasBlockInfo = "";
//
// if(spdmMeasurementBlockReadError) {
// spdmMeasBlockInfo += "\n Error reading SPDM Measurement Block";
@ -93,6 +134,6 @@ public class SpdmCertificateChain {
// spdmMeasBlockInfo += spdmMeasurement.toString();
// }
//
// return spdmMeasBlockInfo;
// }
return spdmMeasBlockInfo;
}
}