diff --git a/HIRS_Utils/src/main/java/hirs/utils/JsonUtils.java b/HIRS_Utils/src/main/java/hirs/utils/JsonUtils.java index 63140cf3..0bbbd9ee 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/JsonUtils.java +++ b/HIRS_Utils/src/main/java/hirs/utils/JsonUtils.java @@ -121,6 +121,7 @@ public final class JsonUtils { return new JsonObject(); } + public static JsonObject getJsonObject(final String jsonFilename) { return getJsonObject(jsonFilename, StandardCharsets.UTF_8); } @@ -131,7 +132,7 @@ public final class JsonUtils { try { InputStream jsonIs = UefiGuid.class - .getClassLoader().getResourceAsStream("vendor-table2.json"); + .getClassLoader().getResourceAsStream(jsonFilename); jsonObject = Json.parse(new InputStreamReader(jsonIs, charset)).asObject(); } catch (IOException e) { diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/TCGEventLog.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/TCGEventLog.java index 2b788c7c..e380bf4a 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/TCGEventLog.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/TCGEventLog.java @@ -20,8 +20,8 @@ import java.security.cert.CertificateException; import java.util.Collection; import java.util.LinkedHashMap; -import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILE_NORMAL; -import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILE_NOT_ACCESSIBLE; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE; /** * Class for handling different formats of TCG Event logs. @@ -80,14 +80,15 @@ public final class TCGEventLog { /** Event Output Flag use. */ @Getter private boolean bCryptoAgile = false; - /** Track if vendor-table file is inaccessible. - * If vendor-table file is not used, this remains false. + /** + * Track status of vendor-table.json + * This is only used if there is an event that uses a UefiVariable data structure. + * Default is normal status (normal status is from-filesystem). + * Status will only change IF there is a UefiVariable event in this log, + * and if that event causes a different status. * */ @Getter - private boolean bVendorTableFileInaccessbile = false; - /** Track status of vendor-table.json */ - @Getter - private String bVendorTableFileStatus = FILE_NORMAL; + private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM; /** * Default blank object constructor. @@ -158,11 +159,19 @@ public final class TCGEventLog { } else { eventList.put(eventNumber, new TpmPcrEvent1(is, eventNumber++)); } - if(eventList.get(eventNumber-1).isBVendorTableFileInaccessbile()) { - bVendorTableFileInaccessbile = true; - } - if(eventList.get(eventNumber-1).getBVendorTableFileStatus() == FILE_NOT_ACCESSIBLE) { - bVendorTableFileStatus = FILE_NOT_ACCESSIBLE; + // first check if any previous event has not been able to access vendor-table.json, + // and if that is the case, the first comparison in the if returns false and + // the if statement is not executed + // [previous event file status = vendorTableFileStatus] + // (ie. keep the file status to reflect that file was not accessible at some point) + // next, check if the new event has any status other than the default 'filesystem', + // and if that is the case, the 2nd comparison in the if returns true and + // the if statement is executed + // [new event file status = eventList.get(eventNumber-1).getVendorTableFileStatus()] + // (ie. if the new file status is not-accessible or from-code, then want to update) + if((vendorTableFileStatus != FILESTATUS_NOT_ACCESSIBLE) && + (eventList.get(eventNumber-1).getVendorTableFileStatus() != FILESTATUS_FROM_FILESYSTEM)) { + vendorTableFileStatus = eventList.get(eventNumber-1).getVendorTableFileStatus(); } } calculatePcrValues(); 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 89d4a12f..0b62726c 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 @@ -33,8 +33,8 @@ import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.Arrays; -import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILE_NORMAL; -import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILE_NOT_ACCESSIBLE; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE; /** * Class to process a TCG_PCR_EVENT. @@ -120,14 +120,15 @@ public class TpmPcrEvent { @Setter @Getter private boolean error = false; - /** Track if vendor-table file is inaccessible. - * If vendor-table file is not used, this remains false. + /** + * Track status of vendor-table.json + * This is only used for events that use a UefiVariable data structure. + * Default is normal status (normal status is from-filesystem). + * Status will only change IF this is an event that has a UefiVariable, + * and if that event causes a different status. * */ @Getter - private boolean bVendorTableFileInaccessbile = false; - /** Track status of vendor-table.json */ - @Getter - private String bVendorTableFileStatus = FILE_NORMAL; + private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM; /** * Constructor. @@ -520,22 +521,12 @@ public class TpmPcrEvent { String efiVarDescription = efiVar.toString().replace("\n", "\n "); description += "Event Content:\n " + efiVarDescription.substring(0, efiVarDescription.length() - INDENT_3); - if(efiVar.isBVendorTableFileInaccessbile()) { - bVendorTableFileInaccessbile = true; - } - if(efiVar.getBVendorTableFileStatus() == FILE_NOT_ACCESSIBLE) { - bVendorTableFileStatus = FILE_NOT_ACCESSIBLE; - } + vendorTableFileStatus = efiVar.getVendorTableFileStatus(); break; case EvConstants.EV_EFI_VARIABLE_BOOT: UefiVariable efiVarBoot = new UefiVariable(content); description += "Event Content:\n" + efiVarBoot.toString(); - if(efiVarBoot.isBVendorTableFileInaccessbile()) { - bVendorTableFileInaccessbile = true; - } - if(efiVarBoot.getBVendorTableFileStatus() == FILE_NOT_ACCESSIBLE) { - bVendorTableFileStatus = FILE_NOT_ACCESSIBLE; - } + vendorTableFileStatus = efiVarBoot.getVendorTableFileStatus(); break; case EvConstants.EV_EFI_BOOT_SERVICES_APPLICATION: EvEfiBootServicesApp bootServices = new EvEfiBootServicesApp(content); @@ -566,12 +557,7 @@ public class TpmPcrEvent { case EvConstants.EV_EFI_VARIABLE_AUTHORITY: UefiVariable efiVarAuth = new UefiVariable(content); description += "Event Content:\n" + efiVarAuth.toString(); - if(efiVarAuth.isBVendorTableFileInaccessbile()) { - bVendorTableFileInaccessbile = true; - } - if(efiVarAuth.getBVendorTableFileStatus() == FILE_NOT_ACCESSIBLE) { - bVendorTableFileStatus = FILE_NOT_ACCESSIBLE; - } + vendorTableFileStatus = efiVarAuth.getVendorTableFileStatus(); break; case EvConstants.EV_EFI_SPDM_FIRMWARE_BLOB: description += "Event Content:\n" + new EvEfiSpdmFirmwareBlob(content).toString(); diff --git a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiConstants.java b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiConstants.java index a30dc00a..d60bf67d 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiConstants.java +++ b/HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/uefi/UefiConstants.java @@ -272,18 +272,18 @@ public final class UefiConstants { */ public static final int UEFI_PT_LENGTH = 72; /** - * file status, where file was successfully found on local machine + * file status, where file was successfully found on local machine. */ - public static final String FILE_NORMAL = "fileNormal"; + public static final String FILESTATUS_FROM_FILESYSTEM = "fileFromFilesystem"; /** - * file status, where file is not accessible + * file status, where file was not found on local machine, so file from code was used. + * For instance, if vendor-table.json is not found in filesystem at location + * /etc/hirs/aca/default-properties/, it will be grabbed from code at + * HIRS_AttestationCA/src/main/resources/. */ - public static final String FILE_NOT_ACCESSIBLE = "fileNotAccessible"; + public static final String FILESTATUS_FROM_CODE = "fileFromCode"; /** - * file status, where file was not found on the local machine, - * and so file from the code was used. - * For instance, if vendor-table.json is not found in /etc/hirs/aca/default-properties/, - * it will be grabbed from code at HIRS_AttestationCA/src/main/resources/. + * file status, where file is not accessible (either not found, or no access permission). */ - public static final String FILE_FROM_CODE_USED = "fileFromCodeUsed"; + public static final String FILESTATUS_NOT_ACCESSIBLE = "fileNotAccessible"; } 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 00c22ce1..4e8fb969 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 @@ -1,9 +1,11 @@ package hirs.utils.tpm.eventlog.uefi; +import com.eclipsesource.json.Json; import com.eclipsesource.json.JsonObject; import hirs.utils.HexUtils; import hirs.utils.JsonUtils; import hirs.utils.rim.ReferenceManifestValidator; +import lombok.Getter; import org.apache.commons.io.IOUtils; import javax.xml.transform.Source; @@ -22,6 +24,10 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.UUID; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_CODE; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE; + /** * Class to process GUID per the UEFI specification * GUIDs are essentially UUID as defined by RFC-1422, however Microsoft refers to GUIDS. @@ -39,9 +45,13 @@ public class UefiGuid { private static final Path JSON_PATH = FileSystems.getDefault().getPath("/etc", "hirs", "aca", "default-properties", "vendor-table.json"); - private static final String vendorTableFilename = "vendor-table.json"; + private static final String JSON_FILENAME = "vendor-table3.json"; private JsonObject uefiVendorRef; + /** Track status of vendor-table.json */ + @Getter + private String vendorTableFileStatus = FILESTATUS_NOT_ACCESSIBLE; + /** * guid byte array. */ @@ -57,103 +67,7 @@ public class UefiGuid { * @param guidBytes byte array holding a valid guid. */ public UefiGuid(final byte[] guidBytes) { - guid = new byte[UefiConstants.SIZE_16]; - System.arraycopy(guidBytes, 0, guid, 0, UefiConstants.SIZE_16); - uuid = processGuid(guidBytes); -// uefiVendorRef = JsonUtils.getSpecificJsonObject(JSON_PATH, "VendorTable"); - - - Path bad = FileSystems.getDefault().getPath("/etc", - "hirs", "aca", "default-properties", "vendor-tableBAD.json"); - uefiVendorRef = JsonUtils.getSpecificJsonObject(bad, - "VendorTable"); - - if(isVendorTableReferenceHandleEmpty()) { - System.out.println("XXXX EMPTYYYYYYY, before trying to grab file from code"); - - -// uefiVendorRef = JsonUtils.getJsonObject("vendor-table2.json", -// StandardCharsets.UTF_8); - - uefiVendorRef = JsonUtils.getSpecificJsonObject("vendor-table2.json", "VendorTable", - StandardCharsets.UTF_8); - - -// System.out.println("XXXX getClass: " + getClass()); -// System.out.println("XXXX getClassResource: " + getClass().getResource("/vendor-table2.json")); -// -// -// InputStream inpStr = UefiGuid.class -// .getClassLoader().getResourceAsStream("vendor-table2.json"); -// System.out.println("XXXX InputStream: " + inpStr); -// -// Source inpSource = new StreamSource( -// ReferenceManifestValidator.class.getClassLoader() -// .getResourceAsStream("vendor-table2.json")); -// System.out.println("XXXX Source: " + inpSource); -// -// String path = this.getClass().getClassLoader().getResource("vendor-table2.json").toExternalForm(); -// System.out.println("XXXX External Form: " + path); - - -// JsonReader reader = new JsonReader(new InputStreamReader(inpStr, "UTF-8")); - -// try { -// BufferedReader streamReader = new BufferedReader(new InputStreamReader(inpStr, "UTF-8")); -// StringBuilder responseStrBuilder = new StringBuilder(); -// -// String inputStr; -// while ((inputStr = streamReader.readLine()) != null) -// responseStrBuilder.append(inputStr); -// -// String test = responseStrBuilder.toString(); -//// Gson gson = new Gson(); -// -// JsonObject testjj = parser. -// -// String temp = "hello"; -// -//// JsonObject jsonObject = new JsonObject(responseStrBuilder.toString()); -// -// } catch (UnsupportedEncodingException e) { -// throw new RuntimeException(e); -// } catch (IOException e) { -// throw new RuntimeException(e); -// } - -// byte[] rawLogBytes = IOUtils.toByteArray(inpStr); - - -// Path fPath2 = Paths.get(inpStr.toURI()); - -// try { -//// private static final String EK_PUBLIC_PATH = "/tpm2/ek.pub"; -// -//// Source source = new StreamSource( -//// getClass().getClassLoader().getResourceAsStream("identity_transform.xslt")); -// -// -// Path fPath = Paths.get(getClass().getResource("/vendor-table2.json").toURI()); -//// URL url = ClassLoader.getSystemResources("vendor-table.json").nextElement(); -//// URL url = ClassLoader.getSystemResources("vendor-table.json"); -//// Path fPath = Paths.get(url.toURI()); -// uefiVendorRef = JsonUtils.getSpecificJsonObject(fPath, -// "VendorTable"); -// -// } -//// catch (IOException e) { -//// System.out.print("XXXX IOException"); -//// throw new RuntimeException(e); -//// } -// catch (URISyntaxException e) { -// System.out.print("XXXX URISyntaxException"); -// throw new RuntimeException(e); -// } - } - - if(isVendorTableReferenceHandleEmpty()) { - System.out.println("YYYY EMPTY STILL, after trying to grab file from code"); - } + this(guidBytes, JSON_PATH); } /** @@ -168,6 +82,18 @@ public class UefiGuid { uuid = processGuid(guidBytes); uefiVendorRef = JsonUtils.getSpecificJsonObject(vendorPathString, "VendorTable"); + + if(!isVendorTableReferenceHandleEmpty()) { + vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM; + } + else { + // could not access vendor-table.json from filesystem, so attempt to access from code + uefiVendorRef = JsonUtils.getSpecificJsonObject(JSON_FILENAME, "VendorTable", + StandardCharsets.UTF_8); + if(!isVendorTableReferenceHandleEmpty()) { + vendorTableFileStatus = FILESTATUS_FROM_CODE; + } + } } /** 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 64fdf62d..bca52b15 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 @@ -9,8 +9,7 @@ import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.ArrayList; -import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILE_NORMAL; -import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILE_NOT_ACCESSIBLE; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE; /** * Class for processing the contents of a Secure Boot DB or DBX contents. @@ -72,14 +71,9 @@ public class UefiSignatureList { * Type of signature. */ private UefiGuid signatureType = null; - /** Track if vendor-table file is inaccessible. - * If vendor-table file is not used, this remains false. - * */ - @Getter - private boolean bVendorTableFileInaccessbile = false; /** Track status of vendor-table.json */ @Getter - private String bVendorTableFileStatus = FILE_NORMAL; + private String vendorTableFileStatus = FILESTATUS_NOT_ACCESSIBLE; /** * UefiSignatureList constructor. @@ -95,6 +89,7 @@ public class UefiSignatureList { byte[] guid = new byte[UefiConstants.SIZE_16]; System.arraycopy(list, 0, guid, 0, UefiConstants.SIZE_16); signatureType = new UefiGuid(guid); + vendorTableFileStatus = signatureType.getVendorTableFileStatus(); byte[] lSize = new byte[UefiConstants.SIZE_4]; System.arraycopy(list, UefiConstants.OFFSET_16, lSize, 0, UefiConstants.SIZE_4); @@ -125,10 +120,11 @@ public class UefiSignatureList { byte[] guid = new byte[UefiConstants.SIZE_16]; lists.read(guid); signatureType = new UefiGuid(guid); - if(signatureType.isVendorTableReferenceHandleEmpty()) { - bVendorTableFileInaccessbile = true; - bVendorTableFileStatus = FILE_NOT_ACCESSIBLE; - } + vendorTableFileStatus = signatureType.getVendorTableFileStatus(); +// if(signatureType.isVendorTableReferenceHandleEmpty()) { +// bVendorTableFileInaccessbile = true; +// vendorTableFileStatus = FILE_NOT_ACCESSIBLE; +// } // 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 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 05b4dd17..7aeeefc3 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 @@ -12,8 +12,9 @@ import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; -import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILE_NORMAL; -import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILE_NOT_ACCESSIBLE; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_CODE; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE; /** * Class to process a UEFI variable within a TPM Event. @@ -66,14 +67,14 @@ public class UefiVariable { */ private byte[] uefiVariableData = null; - /** Track if vendor-table file is inaccessible. - * If vendor-table file is not used, this remains false. + /** + * Track status of vendor-table.json. + * The default here is that each list correctly grabbed the file from file system. + * If any one list has issues, this overall status will change to reflect the + * problematic list's status. * */ @Getter - private boolean bVendorTableFileInaccessbile = false; - /** Track status of vendor-table.json */ - @Getter - private String bVendorTableFileStatus = FILE_NORMAL; + private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM; /** * EFIVariable constructor. @@ -158,13 +159,23 @@ public class UefiVariable { while (certData.available() > 0) { UefiSignatureList list; list = new UefiSignatureList(certData); + + // first check if any previous list has not been able to access vendor-table.json, + // and if that is the case, the first comparison in the if returns false and + // the if statement is not executed + // [previous event file status = vendorTableFileStatus] + // (ie. keep the file status to reflect that file was not accessible at some point) + // next, check if the new list has any status other than the default 'filesystem', + // and if that is the case, the 2nd comparison in the if returns true and + // the if statement is executed + // [new event file status = list.getVendorTableFileStatus()] + // (ie. if the new file status is not-accessible or from-code, then want to update) + if((vendorTableFileStatus != FILESTATUS_NOT_ACCESSIBLE) && + (list.getVendorTableFileStatus() != FILESTATUS_FROM_FILESYSTEM)) { + vendorTableFileStatus = list.getVendorTableFileStatus(); + } + // efiVariableSigListContents += list.toString(); - if(list.isBVendorTableFileInaccessbile()) { - bVendorTableFileInaccessbile = true; - } - if(list.getBVendorTableFileStatus() == FILE_NOT_ACCESSIBLE) { - bVendorTableFileStatus = FILE_NOT_ACCESSIBLE; - } if(!list.isSignatureTypeValid()) { invalidSignatureListEncountered = true; invalidSignatureListStatus = list.toString(); diff --git a/tools/tcg_eventlog_tool/src/main/java/hirs/tcg_eventlog/Main.java b/tools/tcg_eventlog_tool/src/main/java/hirs/tcg_eventlog/Main.java index 9b2f2fa7..e0c909a7 100644 --- a/tools/tcg_eventlog_tool/src/main/java/hirs/tcg_eventlog/Main.java +++ b/tools/tcg_eventlog_tool/src/main/java/hirs/tcg_eventlog/Main.java @@ -16,7 +16,8 @@ import hirs.utils.tpm.eventlog.TCGEventLog; import hirs.utils.tpm.eventlog.TpmPcrEvent; import hirs.utils.HexUtils; -import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILE_NOT_ACCESSIBLE; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_CODE; +import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE; /** * Command-line application for processing TCG Event Logs. @@ -129,13 +130,19 @@ final class Main { writeOut("\nEvent Log follows the \"SHA1\" format and has " + evLog.getEventList().size() + " events:\n\n"); } - if (evLog.isBVendorTableFileInaccessbile()) { - writeOut("*** remove this.\n\n"); - } - if (evLog.getBVendorTableFileStatus() == FILE_NOT_ACCESSIBLE) { + if (evLog.getVendorTableFileStatus() == FILESTATUS_NOT_ACCESSIBLE) { writeOut("*** WARNING: The file vendor-table.json file was not accessible so data " + "in some Secure Boot PCR 7 events cannot be processed.\n\n"); } + else if (evLog.getVendorTableFileStatus() == FILESTATUS_FROM_CODE) { + writeOut("*** NOTE: " + + "The file vendor-table.json file was not accessible from the filesystem,\n" + + " so the vendor-table.json from code was " + + "used. If updates were made in the\n" + + " filesystem file, they will not be reflected. " + + "This affects parsing in some\n" + + " Secure Boot PCR 7 events.\n\n"); + } } int eventCount = 0; for (TpmPcrEvent event : evLog.getEventList()) {