Merge pull request #392 from nsacyber/uefi-test-update

UEFI Unit Test Update
This commit is contained in:
iadgovuser26 2021-08-20 12:16:35 -04:00 committed by GitHub
commit 71666542c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 234 additions and 167 deletions

View File

@ -1,43 +1,53 @@
package hirs.tpm.eventlog.events;
import java.util.ArrayList;
package hirs.tpm.eventlog.events;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.tpm.eventlog.uefi.UefiGuid;
import hirs.utils.HexUtils;
import java.math.BigInteger;
import java.nio.file.Path;
import java.util.ArrayList;
/** Class to process the PC Client Firmware profile defined EV_EFI_HANDOFF_TABLES event.
/**
* Class to process the PC Client Firmware profile defined EV_EFI_HANDOFF_TABLES event.
* The Event data holds a structure called UEFI_HANDOFF_TABLE_POINTERS:
*
* tdUEFI_HANDOFF_TABLE_POINTERS {
* UINT64 NumberOfTables;
* UEFI_CONFIGURATION_TABLE TableEntry[NumberOfTables];
* }UEFI_HANDOFF_TABLE_POINTERS;
*
* <p>
* tdUEFI_HANDOFF_TABLE_POINTERS {
* UINT64 NumberOfTables;
* UEFI_CONFIGURATION_TABLE TableEntry[NumberOfTables];
* }UEFI_HANDOFF_TABLE_POINTERS;
* <p>
* The UEFI_CONFIGURATION_TABLE id defined in the UEFI spec as:
*
* typedef struct{
* EFI_GUID VendorGuid;
* VOID *VendorTable;
* } EFI_CONFIGURATION_TABLE;
* <p>
* typedef struct{
* EFI_GUID VendorGuid;
* VOID *VendorTable;
* } EFI_CONFIGURATION_TABLE;
* Where the defines
* VendorGuid: The 128-bit GUID value that uniquely identifies the system configuration table.
* VendorTable: A pointer to the table associated with VendorGuid.
* Section 4.6 of the UEFI spec has a listing of some of the industry defined
* standard that define the particular table.
* Section 4.6 of the UEFI spec has a listing of some of the industry defined
* standard that define the particular table.
*/
public class EvEfiHandoffTable {
/** Number of Tables. */
/**
* Number of Tables.
*/
private int tableCount = 0;
/** List of Vendor GUIDs. */
/**
* List of Vendor GUIDs.
*/
private ArrayList<UefiGuid> vendorGuids = new ArrayList<UefiGuid>();
/** List of Vendors. */
/**
* List of Vendors.
*/
private ArrayList<byte[]> vendorTables = new ArrayList<byte[]>();
private Path vendorPathString;
/**
* EvEFIHandoffTable constructor.
*
* @param tpmEventData byte array holding the Handoff table data.
*/
public EvEfiHandoffTable(final byte[] tpmEventData) {
@ -53,56 +63,87 @@ public class EvEfiHandoffTable {
vendorGuids.add(getNextGUID(tpmEventData, offset));
vendorTables.add(getNextTable(tpmEventData, offset + UefiConstants.OFFSET_16));
offset += UefiConstants.OFFSET_24;
}
}
}
/**
* Return the number of EFI configuration tables covered in this event.
* @return number of EFI configuration tables.
/**
* EvEFIHandoffTable constructor.
*
* @param tpmEventData byte array holding the Handoff table data.
* @param vendorPathString the string for the vendor file
*/
public EvEfiHandoffTable(final byte[] tpmEventData, final Path vendorPathString) {
// Get NumberOfTables from the EventData
byte[] count = new byte[UefiConstants.SIZE_8];
System.arraycopy(tpmEventData, 0, count, 0, UefiConstants.SIZE_8);
byte[] bigEndCount = HexUtils.leReverseByte(count);
BigInteger countInt = new BigInteger(bigEndCount);
tableCount = countInt.intValue();
this.vendorPathString = vendorPathString;
// process each UEFI_CONFIGURATION_TABLE table
int offset = UefiConstants.OFFSET_8;
for (int tables = 0; tables < tableCount; tables++) {
vendorGuids.add(getNextGUID(tpmEventData, offset));
vendorTables.add(getNextTable(tpmEventData, offset + UefiConstants.OFFSET_16));
offset += UefiConstants.OFFSET_24;
}
}
/**
* Return the number of EFI configuration tables covered in this event.
*
* @return number of EFI configuration tables.
*/
public int getNumberOfTables() {
return tableCount;
return tableCount;
}
/**
* Returns the next GUI in the table.
*
* @param eventData byte array holding the guids.
* @param offset offset to the guid.
* @param offset offset to the guid.
* @return Vendor Guid
*/
private UefiGuid getNextGUID(final byte[] eventData, final int offset) {
byte[] guid = new byte[UefiConstants.SIZE_16];
System.arraycopy(eventData, offset, guid, 0, UefiConstants.SIZE_16);
return new UefiGuid(guid);
if (vendorPathString == null || vendorPathString.toString().isEmpty()) {
return new UefiGuid(guid);
} else {
return new UefiGuid(guid, vendorPathString);
}
}
/**
* Copies the next table to a new array.
*
* @param eventData byte array holding the next table.
* @param offset offset within the table to fond the data.
* @param offset offset within the table to fond the data.
* @return a byte array holding the new table.
*/
private byte[] getNextTable(final byte[] eventData, final int offset) {
private byte[] getNextTable(final byte[] eventData, final int offset) {
byte[] table = new byte[UefiConstants.SIZE_8];
System.arraycopy(eventData, offset, table, 0, UefiConstants.SIZE_8);
return table;
}
}
/**
* Returns a human readable description of the hand off tables.
* @return a human readable description.
*/
public String toString() {
StringBuilder tableInfo = new StringBuilder();
tableInfo.append("Number of UEFI_CONFIGURATION_TABLEs = " + tableCount + "\n");
for (int i = 0; i < tableCount; i++) {
UefiGuid currentGuid = vendorGuids.get(i);
tableInfo.append(" Table " + i + ": " + currentGuid.toString());
tableInfo.append(" UEFI industry standard table type = "
+ currentGuid.getVendorTableReference() + "\n");
tableInfo.append(" VendorTable " + i + " address: "
+ HexUtils.byteArrayToHexString(vendorTables.get(i)));
}
return tableInfo.toString();
/**
* Returns a human readable description of the hand off tables.
*
* @return a human readable description.
*/
public String toString() {
StringBuilder tableInfo = new StringBuilder();
tableInfo.append("Number of UEFI_CONFIGURATION_TABLEs = " + tableCount + "\n");
for (int i = 0; i < tableCount; i++) {
UefiGuid currentGuid = vendorGuids.get(i);
tableInfo.append(" Table " + i + ": " + currentGuid.toString());
tableInfo.append(" UEFI industry standard table type = "
+ currentGuid.getVendorTableReference() + "\n");
tableInfo.append(" VendorTable " + i + " address: "
+ HexUtils.byteArrayToHexString(vendorTables.get(i)));
}
return tableInfo.toString();
}
}

View File

@ -1,14 +1,14 @@
package hirs.tpm.eventlog.uefi;
import com.eclipsesource.json.JsonObject;
import hirs.utils.HexUtils;
import hirs.utils.JsonUtils;
import java.math.BigInteger;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.UUID;
import com.eclipsesource.json.JsonObject;
import hirs.utils.HexUtils;
import hirs.utils.JsonUtils;
/**
* Class to process GUID per the UEFI specification
* GUIDs are essentially UUID as defined by RFC-1422, however Microsoft refers to GUIDS.
@ -47,6 +47,20 @@ public class UefiGuid {
uefiVendorRef = JsonUtils.getSpecificJsonObject(JSON_PATH, "VendorTable");
}
/**
* UefiGUID constructor.
*
* @param guidBytes byte array holding a valid guid.
* @param vendorPathString string path for vendor
*/
public UefiGuid(final byte[] guidBytes, final Path vendorPathString) {
guid = new byte[UefiConstants.SIZE_16];
System.arraycopy(guidBytes, 0, guid, 0, UefiConstants.SIZE_16);
uuid = processGuid(guidBytes);
uefiVendorRef = JsonUtils.getSpecificJsonObject(vendorPathString,
"VendorTable");
}
/**
* Converts a GUID with a byte array to a RFC-1422 UUID object.
* Assumes a MS format and converts to Big Endian format used by most others , including Linux

View File

@ -20,8 +20,9 @@ public class ComponentClassTest {
@Test
public void testGetComponentNoneUNK() throws URISyntaxException {
String componentIdentifier = "00000001";
ComponentClass instance = new ComponentClass("TCG", Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
ComponentClass instance = new ComponentClass("TCG",
Paths.get(this.getClass().getResource(JSON_FILE).toURI()),
componentIdentifier);
String resultCategory = instance.getCategory();
String resultComponent = instance.getComponent();
Assert.assertEquals(resultComponent, "Unknown");

View File

@ -1,10 +1,9 @@
package hirs.tpm.eventlog.events;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import hirs.tpm.eventlog.TCGEventLogTest;
import hirs.tpm.eventlog.uefi.UefiGuid;
import hirs.tpm.eventlog.uefi.UefiPartition;
import hirs.utils.HexUtils;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -13,25 +12,28 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import hirs.tpm.eventlog.TCGEventLogTest;
import hirs.utils.HexUtils;
import hirs.tpm.eventlog.uefi.UefiGuid;
import hirs.tpm.eventlog.uefi.UefiPartition;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
/**
* Class for testing TCG Event Log Event processing.
* Class for testing TCG Event Log Event processing.
*/
public class TCGEventLogEventsTest {
// Variable files collected using an Event Parsing tool
// Variable files collected using an Event Parsing tool
private static final String EVENT_SPECID = "/tcgeventlog/events/EvEfiSpecId.txt";
private static final String EVENT_BOOTSERVICES
= "/tcgeventlog/events/EvBootServicesApplication.txt";
= "/tcgeventlog/events/EvBootServicesApplication.txt";
private static final String EVENT_GPT_PARTITION
= "/tcgeventlog/events/EvEfiGptPartition.txt";
= "/tcgeventlog/events/EvEfiGptPartition.txt";
private static final String EVENT_HANDOFF_TABLES = "/tcgeventlog/events/EvHandoffTables.txt";
private static final String UEFI_POST_CODE = "/tcgeventlog/events/EvPostCode.txt";
private static final Logger LOGGER
= LogManager.getLogger(TCGEventLogTest.class);
= LogManager.getLogger(TCGEventLogTest.class);
private static final String JSON_FILE = "/tcgeventlog/uefi/vendor-table.json";
/**
* Initializes a <code>SessionFactory</code>.
@ -50,111 +52,120 @@ public class TCGEventLogEventsTest {
LOGGER.debug("closing session factory");
}
/**
* Tests the processing of a SpecIDEvent event.
* @throws IOException when processing the test fails
*/
@Test
public final void testSpecIDEvent() throws IOException {
LOGGER.debug("Testing the SpecID Event Processing");
String event = IOUtils.toString(this.getClass().getResourceAsStream(EVENT_SPECID), "UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvEfiSpecIdEvent specEvent = new EvEfiSpecIdEvent(eventBytes);
Assert.assertTrue(specEvent.isCryptoAgile());
Assert.assertEquals(specEvent.getSignature(), "Spec ID Event03");
}
/**
* Tests the processing of a SpecIDEvent event.
*
* @throws IOException when processing the test fails
*/
@Test
public final void testSpecIDEvent() throws IOException {
LOGGER.debug("Testing the SpecID Event Processing");
String event = IOUtils.toString(this.getClass().getResourceAsStream(EVENT_SPECID), "UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvEfiSpecIdEvent specEvent = new EvEfiSpecIdEvent(eventBytes);
Assert.assertTrue(specEvent.isCryptoAgile());
Assert.assertEquals(specEvent.getSignature(), "Spec ID Event03");
}
/**
* Tests the processing of a Boot Services App event.
* @throws IOException when processing the test fails
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
* @throws CertificateException if a certificate fails to parse.
*/
@Test
public final void testEvBootServicesApp() throws IOException {
LOGGER.debug("Testing the parsing of Boot Services Application Event");
String event = IOUtils.toString(this.getClass().getResourceAsStream(EVENT_BOOTSERVICES),
"UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvEfiBootServicesApp bootService = new EvEfiBootServicesApp(eventBytes);
String address = HexUtils.byteArrayToHexString(bootService.getImagePhysicalAddress());
Assert.assertEquals(address, "1820d45800000000");
String path = bootService.getDevicePath().toString();
Assert.assertTrue(path.contains("PIWG Firmware Volume b6ede22c-de30-45fa-bb09-ca202c1654b7"));
}
/**
* Tests the processing of a Boot Services App event.
*
* @throws IOException when processing the test fails
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
* @throws CertificateException if a certificate fails to parse.
*/
@Test
public final void testEvBootServicesApp() throws IOException {
LOGGER.debug("Testing the parsing of Boot Services Application Event");
String event = IOUtils.toString(this.getClass().getResourceAsStream(EVENT_BOOTSERVICES),
"UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvEfiBootServicesApp bootService = new EvEfiBootServicesApp(eventBytes);
String address = HexUtils.byteArrayToHexString(bootService.getImagePhysicalAddress());
Assert.assertEquals(address, "1820d45800000000");
String path = bootService.getDevicePath().toString();
Assert.assertTrue(path.contains("PIWG Firmware Volume "
+ "b6ede22c-de30-45fa-bb09-ca202c1654b7"));
}
/**
* Tests the processing of a Boot Services App event.
* @throws IOException when processing the test fails
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
* @throws CertificateException if a certificate fails to parse.
*/
@Test
public final void testEvGptPartiton() throws IOException {
LOGGER.debug("Testing the parsing of Boot Services Application Event");
String event = IOUtils.toString(this.getClass().getResourceAsStream(EVENT_GPT_PARTITION),
"UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvEfiGptPartition partition = new EvEfiGptPartition(eventBytes);
ArrayList<UefiPartition> partitonList = partition.getPartitionList();
int partNumber = 1;
for (UefiPartition parition:partitonList) {
UefiGuid guidPart = parition.getPartitionTypeGUID();
UefiGuid guidUnique = parition.getUniquePartitionGUID();
String name = parition.getName();
if (partNumber == 1) {
Assert.assertTrue(guidPart.toString().
contains("de94bba4-06d1-4d40-a16a-bfd50179d6a"));
Assert.assertTrue(guidUnique.toString().
contains("42cc8787-db23-4e45-9981-701adc801dc7"));
Assert.assertEquals(name, "Basic data partition");
}
if (partNumber == 2) {
Assert.assertTrue(guidPart.toString().
contains("c12a7328-f81f-11d2-ba4b-00a0c93ec93b"));
Assert.assertTrue(guidUnique.toString().
contains("8ca7623c-041e-4fab-8c12-f49a86b85d73"));
Assert.assertEquals(name, "EFI system partition");
}
if (partNumber++ == 3) {
Assert.assertTrue(guidPart.toString().
contains("e3c9e316-0b5c-4db8-817d-f92df00215ae"));
Assert.assertTrue(guidUnique.toString().
contains("d890cfff-320c-4f45-b6cf-a4d8bee6d9cb"));
Assert.assertEquals(name, "Microsoft reserved partition");
/**
* Tests the processing of a Boot Services App event.
*
* @throws IOException when processing the test fails
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
* @throws CertificateException if a certificate fails to parse.
*/
@Test
public final void testEvGptPartiton() throws IOException {
LOGGER.debug("Testing the parsing of Boot Services Application Event");
String event = IOUtils.toString(this.getClass().getResourceAsStream(EVENT_GPT_PARTITION),
"UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvEfiGptPartition partition = new EvEfiGptPartition(eventBytes);
ArrayList<UefiPartition> partitonList = partition.getPartitionList();
int partNumber = 1;
for (UefiPartition parition : partitonList) {
UefiGuid guidPart = parition.getPartitionTypeGUID();
UefiGuid guidUnique = parition.getUniquePartitionGUID();
String name = parition.getName();
if (partNumber == 1) {
Assert.assertTrue(guidPart.toString().
contains("de94bba4-06d1-4d40-a16a-bfd50179d6a"));
Assert.assertTrue(guidUnique.toString().
contains("42cc8787-db23-4e45-9981-701adc801dc7"));
Assert.assertEquals(name, "Basic data partition");
}
if (partNumber == 2) {
Assert.assertTrue(guidPart.toString().
contains("c12a7328-f81f-11d2-ba4b-00a0c93ec93b"));
Assert.assertTrue(guidUnique.toString().
contains("8ca7623c-041e-4fab-8c12-f49a86b85d73"));
Assert.assertEquals(name, "EFI system partition");
}
if (partNumber++ == 3) {
Assert.assertTrue(guidPart.toString().
contains("e3c9e316-0b5c-4db8-817d-f92df00215ae"));
Assert.assertTrue(guidUnique.toString().
contains("d890cfff-320c-4f45-b6cf-a4d8bee6d9cb"));
Assert.assertEquals(name, "Microsoft reserved partition");
}
}
}
}
/**
* Tests the processing of a Hand off Table event.
* @throws IOException when processing the test fails
*/
@Test
public final void testHandOffTables() throws IOException {
LOGGER.debug("Testing the Hand Off Tables Event Processing");
String event = IOUtils.toString(this.getClass().
getResourceAsStream(EVENT_HANDOFF_TABLES), "UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvEfiHandoffTable hTable = new EvEfiHandoffTable(eventBytes);
Assert.assertEquals(hTable.getNumberOfTables(), 1);
String tableInfo = hTable.toString();
Assert.assertTrue(tableInfo.toString().
contains("UEFI industry standard table type = SMBIOS3_TABLE_GUID"));
}
/**
* Tests the processing of a Hand off Table event.
*
* @throws IOException when processing the test fails
*/
@Test
public final void testHandOffTables() throws IOException, URISyntaxException {
LOGGER.debug("Testing the Hand Off Tables Event Processing");
String event = IOUtils.toString(this.getClass().
getResourceAsStream(EVENT_HANDOFF_TABLES), "UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvEfiHandoffTable hTable = new EvEfiHandoffTable(eventBytes,
Paths.get(this.getClass().getResource(JSON_FILE).toURI()));
Assert.assertEquals(hTable.getNumberOfTables(), 1);
String tableInfo = hTable.toString();
LOGGER.error(tableInfo);
Assert.assertTrue(tableInfo.
contains("UEFI industry standard table type = SMBIOS3_TABLE_GUID"));
}
/**
* Tests the processing of a Post Code event.
* @throws IOException when processing the test fails
*/
@Test
public final void testPostCode() throws IOException {
LOGGER.debug("Testing the Post Code Event Processing");
String event = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_POST_CODE), "UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvPostCode pCode = new EvPostCode(eventBytes);
Assert.assertTrue(pCode.isString());
String postCode = pCode.toString();
Assert.assertEquals(postCode, "ACPI DATA");
}
/**
* Tests the processing of a Post Code event.
*
* @throws IOException when processing the test fails
*/
@Test
public final void testPostCode() throws IOException {
LOGGER.debug("Testing the Post Code Event Processing");
String event = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_POST_CODE),
"UTF-8");
byte[] eventBytes = HexUtils.hexStringToByteArray(event);
EvPostCode pCode = new EvPostCode(eventBytes);
Assert.assertTrue(pCode.isString());
String postCode = pCode.toString();
Assert.assertEquals(postCode, "ACPI DATA");
}
}