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 228e25717..029460ecb 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 @@ -440,7 +440,7 @@ public String getEventContentStr() { case EvConstants.EV_EFI_SPDM_DEVICE_AUTHORITY: try { sb.append(new UefiVariable(eventContent)); - } catch (CertificateException | NoSuchAlgorithmException | IOException exception) { + } catch (NoSuchAlgorithmException | IOException exception) { log.error(exception); sb.append(exception); } diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiGuid.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiGuid.java index 9cce277eb..bb7dbc9aa 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiGuid.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiGuid.java @@ -166,6 +166,7 @@ public String getVendorTableReference() { * published that represent standards that one can find further * information on the configuration table being referenced. * Refer to section 4.6 of UEFI spec v 2.8, page 101. + * defaultValue – the value to be returned if the requested member is missing * * @param lookupValue specific value to look up * @return A String of major UUID parameters diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiSignatureData.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiSignatureData.java index 64fa45f0c..2208d7ea5 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiSignatureData.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiSignatureData.java @@ -2,6 +2,7 @@ import hirs.utils.HexUtils; import lombok.Getter; +import lombok.extern.log4j.Log4j2; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -11,14 +12,16 @@ /** * 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 or Device Authority, whose data is an EFIVariable - * EFIVariable data for SPDM Device Policy: UefiSignatureList - * EFIVariable data for SPDM Device: UefiSignatureData only - * as defined by PFP v1.06 Rev52, Section 10.4 + * 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 + * EV_EFI_VARIABLE_DRIVER_CONFIG + * EV_EFI_VARIABLE_AUTHORITY + * 2) the contents of an SPDM devdb, + * used for SPDM Device Policy or Device Authority, whose data is an EFIVariable + * EFIVariable data for EV_EFI_SPDM_DEVICE_POLICY: UefiSignatureList + * EFIVariable data for EV_EFI_SPDM_DEVICE_AUTHORITY : UefiSignatureData only + * as defined by PFP v1.06 Rev52, Section 10.4 *

* typedef struct _EFI_SIGNATURE_DATA { * EFI_GUID SignatureOwner; @@ -29,6 +32,7 @@ * will contain the "the SHA-256 hash of the binary". * So the Signature Data depends upon the Signature Type from the EFI Signature List. */ +@Log4j2 public class UefiSignatureData { /** * UEFI Certificate GUID. @@ -63,10 +67,10 @@ public class UefiSignatureData { */ private final byte[] binaryHash = new byte[UefiConstants.SIZE_32]; /** - * UEFI Signature data status. + * UEFI Signature data error status. */ @Getter - private String status = "Signature Data contains a valid Certificate"; + private String errorStatus = ""; /** * UefiSignatureData constructor. @@ -78,7 +82,7 @@ public class UefiSignatureData { * @throws java.security.NoSuchAlgorithmException if there's a problem hashing the certificate. */ UefiSignatureData(final ByteArrayInputStream inputStream, final UefiGuid sigType) - throws IOException, CertificateException, NoSuchAlgorithmException { + throws IOException, NoSuchAlgorithmException { signatureType = sigType; // UEFI spec section 32.5.3.3 states that SignatureListType of EFI_CERT_SHA256_GUID // only contains a hash, not a cert @@ -90,28 +94,20 @@ public class UefiSignatureData { } else if (sigType.getVendorTableReference().equals("EFI_CERT_X509_GUID")) { inputStream.read(guid); efiVarGuid = new UefiGuid(guid); - // Read in Type and Length separately so we calculate the rest of the cert size - byte[] certType = new byte[UefiConstants.SIZE_2]; - inputStream.read(certType); - byte[] certLength = new byte[UefiConstants.SIZE_2]; - inputStream.read(certLength); - int cLength = new BigInteger(certLength).intValue() + UefiConstants.SIZE_4; - byte[] certData = new byte[cLength]; - inputStream.read(certData); - // put the cert back together - byte[] certBlob = new byte[cLength + UefiConstants.SIZE_4]; - System.arraycopy(certType, 0, certBlob, 0, UefiConstants.SIZE_2); - System.arraycopy(certLength, 0, certBlob, UefiConstants.OFFSET_2, UefiConstants.SIZE_2); - System.arraycopy(certData, 0, certBlob, UefiConstants.OFFSET_4, cLength); - cert = new UefiX509Cert(certBlob); - } else if (sigType.isUnknownUUID()) { - //status = "Signature List Type has an unknown GUID: " + efiGuid.toString(); - status = "Signature List Type has an unknown GUID"; - return; - } else { // else process as a cert (RH SHIM does this) processC509Cert(inputStream); - efiVarGuid = sigType; + } else { + errorStatus = "Signature List Type has either an unknown GUID or a type that hasn't been implemented yet"; + return; } +// else if (sigType.isUnknownUUID()) { +// //status = "Signature List Type has an unknown GUID: " + efiGuid.toString(); +// status = "Signature List Type has an unknown GUID"; +// return; +// } else { // else process as a cert (RH SHIM does this) +// processC509Cert(inputStream); +// efiVarGuid = sigType; +// } + valid = true; } @@ -140,20 +136,26 @@ public class UefiSignatureData { * @throws java.security.NoSuchAlgorithmException if there's a problem creating a hash. */ private void processC509Cert(final ByteArrayInputStream inputStream) - throws IOException, CertificateException, NoSuchAlgorithmException { + throws IOException, NoSuchAlgorithmException { + + // Read in Type and Length separately so we calculate the rest of the cert size byte[] certType = new byte[UefiConstants.SIZE_2]; inputStream.read(certType); byte[] certLength = new byte[UefiConstants.SIZE_2]; inputStream.read(certLength); - int cLength = new BigInteger(certLength).intValue() + UefiConstants.SIZE_4; - byte[] certData = new byte[cLength]; + int certDataLength = new BigInteger(certLength).intValue(); + byte[] certData = new byte[certDataLength]; inputStream.read(certData); - // put the cert back together - byte[] certBlob = new byte[cLength + UefiConstants.SIZE_4]; + byte[] certBlob = new byte[certDataLength + 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); + System.arraycopy(certData, 0, certBlob, UefiConstants.OFFSET_4, certDataLength); + try { + cert = new UefiX509Cert(certBlob); + } catch (CertificateException e) { + errorStatus = "\n **** UefiSignatureData Certificate Issue ****: " + e.getMessage(); + log.warn("UefiSignatureData Certificate Issue: {}", e.getMessage()); + } } /** @@ -164,14 +166,18 @@ private void processC509Cert(final ByteArrayInputStream inputStream) public String toString() { String sigInfo = ""; if (!valid) { - sigInfo = status; + sigInfo = errorStatus; } else { if (signatureType.getVendorTableReference().equals("EFI_CERT_SHA256_GUID")) { sigInfo += " UEFI Signature Owner = " + efiVarGuid.toString() + "\n"; sigInfo += " Binary Hash = " + HexUtils.byteArrayToHexString(binaryHash) + "\n"; } else { sigInfo += " UEFI Signature Owner = " + efiVarGuid.toString() + "\n"; - sigInfo += cert.toString(); + if (errorStatus.isEmpty()) { + sigInfo += cert.toString(); + } else { + sigInfo += errorStatus; + } } } return sigInfo; 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 836566295..7b1324e43 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 @@ -5,22 +5,21 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; import java.util.ArrayList; /** * 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 + * 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 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). + * - 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; @@ -32,18 +31,18 @@ * } EFI_SIGNATURE_LIST; *

* SignatureListHeader (contents common to any Signature Type) - * - SignatureType - * - SignatureListSize - * - SignatureHeaderSize - * - SignatureSize + * - SignatureType (SHA256, X509) + * - SignatureListSize + * - SignatureHeaderSize + * - SignatureSize * SignatureHeader (contents depend on the SignatureType) - * - The format of this header is specified by the SignatureType (SHA256, X509). + * - The format of this header is specified by the SignatureType (SHA256, X509). * Signatures[][] is an array of signatures. - * - Each signature is SignatureSize bytes in length. - * - The format of the signature is defined by SignatureType (SHA256, X509). + * - Each signature is SignatureSize bytes in length. + * - The format of the signature is defined by SignatureType (SHA256, X509). *

- * / |-------------------------| ------- SignatureType - * / | Signature List Header | SignatureListSize + * / / |-------------------------| ------- SignatureType + * / / | Signature List Header | SignatureListSize * |---------------------| / |-------------------------|\ SignatureHeaderSize * | Signature List #0 | / | Signature Header | \ _____ SignatureSize * | | / |-------------------------| @@ -54,10 +53,10 @@ * | | | Signature #2 | (1 cert or hash) * | | |-------------------------| * |---------------------| | ... | - * \ | | - * \ |-------------------------| - * \ | Signature #n | - * \ |-------------------------| + * | | \ | | + * | | \ |-------------------------| + * | | \ | Signature #n | + * | | \ |-------------------------| */ public class UefiSignatureList { /** @@ -151,7 +150,7 @@ public class UefiSignatureList { * @throws java.security.NoSuchAlgorithmException if there's a problem hashing the certificate. */ UefiSignatureList(final ByteArrayInputStream lists) - throws IOException, CertificateException, NoSuchAlgorithmException { + throws IOException, NoSuchAlgorithmException { byte[] guid = new byte[UefiConstants.SIZE_16]; lists.read(guid); signatureType = new UefiGuid(guid); @@ -190,13 +189,13 @@ public class UefiSignatureList { * @throws java.io.IOException If there's a problem parsing the signature data. */ private void processSignatureList(final byte[] efiSigData) - throws CertificateException, NoSuchAlgorithmException, IOException { + throws NoSuchAlgorithmException, IOException { efiSigDataIS = new ByteArrayInputStream(efiSigData); while (efiSigDataIS.available() > 0) { UefiSignatureData tmpSigData = new UefiSignatureData(efiSigDataIS, signatureType); if (!tmpSigData.isValid()) { dataValid = false; - dataInvalidStatus = tmpSigData.getStatus(); + dataInvalidStatus = tmpSigData.getErrorStatus(); break; } sigList.add(tmpSigData); diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiVariable.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiVariable.java index e8e2c8917..ab7f2badf 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiVariable.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiVariable.java @@ -7,7 +7,6 @@ import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; @@ -82,15 +81,13 @@ public class UefiVariable { * the class used to parse the data within the "VariableData". * * @param variableData byte array holding the UEFI Variable. - * @throws java.security.cert.CertificateException If there 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. */ public UefiVariable(final byte[] variableData) - throws CertificateException, NoSuchAlgorithmException, IOException { + throws NoSuchAlgorithmException, IOException { certSuperList = new ArrayList<>(); byte[] guid = new byte[UefiConstants.SIZE_16]; byte[] nameLength = new byte[UefiConstants.SIZE_8]; @@ -164,7 +161,7 @@ public UefiVariable(final byte[] variableData) * parsing the signature data. */ private void processSigList(final byte[] data) - throws CertificateException, NoSuchAlgorithmException, IOException { + throws NoSuchAlgorithmException, IOException { ByteArrayInputStream certData = new ByteArrayInputStream(data); while (certData.available() > 0) { UefiSignatureList list; @@ -204,7 +201,7 @@ private void processSigList(final byte[] data) * @throws java.io.IOException If there's a problem parsing the signature data. */ private void processSigDataX509(final byte[] efiSigData) - throws CertificateException, NoSuchAlgorithmException, IOException { + throws NoSuchAlgorithmException, IOException { ByteArrayInputStream efiSigDataIS = new ByteArrayInputStream(efiSigData); ArrayList sigList = new ArrayList(); @@ -222,7 +219,7 @@ private void processSigDataX509(final byte[] efiSigData) UefiSignatureData tmpSigData = new UefiSignatureData(efiSigDataIS, signatureType); if (!tmpSigData.isValid()) { dataValid = false; - dataInvalidStatus = tmpSigData.getStatus(); + dataInvalidStatus = tmpSigData.getErrorStatus(); break; } sigList.add(tmpSigData); diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiX509Cert.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiX509Cert.java index 6258757f4..7eceadf93 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiX509Cert.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiX509Cert.java @@ -30,10 +30,14 @@ public class UefiX509Cert { */ public UefiX509Cert(final byte[] certData) throws CertificateException, NoSuchAlgorithmException { - CertificateFactory cf; - cf = CertificateFactory.getInstance("X.509"); - InputStream targetStream = new ByteArrayInputStream(certData); - cert = cf.generateCertificate(targetStream); + try { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + InputStream targetStream = new ByteArrayInputStream(certData); + cert = cf.generateCertificate(targetStream); + } catch (CertificateException e) { + throw new CertificateException("\n Error parsing UEFI X509 certificate: " + e.getMessage()); + } + MessageDigest md = MessageDigest.getInstance("SHA1"); md.update(certData); }