Added unit tests for Uefi processing.

This commit is contained in:
lareine 2020-03-27 08:20:04 -04:00
parent 828e6d4e65
commit fecc84a5be
12 changed files with 218 additions and 37 deletions

View File

@ -1,6 +1,5 @@
package hirs.tpm.eventlog.uefi;
import java.io.UnsupportedEncodingException;
import hirs.utils.HexUtils;
@ -63,7 +62,7 @@ public class UefiDevicePath {
* @return uefi sub-type
*/
public String getSubType() {
return subType;
return subType.trim();
}
/**
@ -124,41 +123,42 @@ public class UefiDevicePath {
String devInfo = " ";
int devPath = path[offset];
switch (path[0 + offset]) {
case UefiConstants.DEV_HW: devInfo += "Hardware Device Path: ";
case UefiConstants.DEV_HW: type = "Hardware Device Path";
if (devPath == UefiConstants.DEVPATH_HARWARE) {
devInfo += pciSubType(path, offset);
devInfo += type + ": " + pciSubType(path, offset);
}
break;
case UefiConstants.DEV_ACPI: devInfo += "ACPI Device Path: ";
devInfo += acpiSubType(path, offset);
case UefiConstants.DEV_ACPI: type = "ACPI Device Path";
devInfo += type + ": " + acpiSubType(path, offset);
break;
case UefiConstants.DEV_MSG: devInfo += "Messaging Device Path:";
case UefiConstants.DEV_MSG: type = "Messaging Device Path";
if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEV_SUB_SATA) {
devInfo += sataSubType(path, offset);
devInfo += type + ": " + sataSubType(path, offset);
}
if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEV_SUB_NVM) {
devInfo += nvmSubType(path, offset);
devInfo += type + ": " + nvmSubType(path, offset);
}
break;
case UefiConstants.DEV_MEDIA: devInfo += "Media Device Path: ";
case UefiConstants.DEV_MEDIA: type = "Media Device Path";
if (path[offset + UefiConstants.OFFSET_1] == 0x01) {
devInfo += hardDriveSubType(path, offset);
devInfo += type + ": " + hardDriveSubType(path, offset);
} else if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEVPATH_VENDOR) {
devInfo += vendorSubType(path, offset);
devInfo += type + ": " + vendorSubType(path, offset);
} else if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEVPATH_FILE) {
devInfo += filePathSubType(path, offset);
devInfo += type + ": " + filePathSubType(path, offset);
} else if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEVPATH_PWIG_FILE) {
devInfo += piwgFirmVolFile(path, offset);
devInfo += type + ": " + piwgFirmVolFile(path, offset);
} else if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEVPATH_PWIG_VOL) {
devInfo += piwgFirmVolPath(path, offset);
devInfo += type + ": " + piwgFirmVolPath(path, offset);
}
break;
case UefiConstants.DEV_BIOS: devInfo += "BIOS Device Path: ";
devInfo += biosDevicePath(path, offset);
case UefiConstants.DEV_BIOS: type = "BIOS Device Path";
devInfo += type + ": " + biosDevicePath(path, offset);
break;
case UefiConstants.TERMINATOR: devInfo += "End of Hardware Device Path: ";
case UefiConstants.TERMINATOR: devInfo += "End of Hardware Device Path";
break;
default: devInfo = " Unknown Device Path";
default: type = "Unknown Device Path";
devInfo = type;
}
devInfo += "\n";
return devInfo;
@ -176,9 +176,10 @@ private String acpiSubType(final byte[] path, final int offset) {
case 0x01: tmpType = "(Short): ";
tmpType += acpiShortSubType(path, offset);
break;
case 0x02: tmpType = "Expanded ACPI Device Path"; break;
case 0x02: tmpType = "Expanded ACPI Device Path"; break;
default: tmpType = "Invalid ACPI Device Path sub type";
}
subType = tmpType;
return tmpType;
}
@ -195,6 +196,7 @@ private String acpiShortSubType(final byte[] path, final int offset) {
tmpType += "_HID = " + HexUtils.byteArrayToHexString(hid);
System.arraycopy(path, 2 * UefiConstants.SIZE_4 + offset, hid, 0, UefiConstants.SIZE_4);
tmpType += "_UID = " + HexUtils.byteArrayToHexString(hid);
subType = tmpType;
return tmpType;
}
@ -209,6 +211,7 @@ private String pciSubType(final byte[] path, final int offset) {
tmpType += String.format("0x%x", path[offset + UefiConstants.SIZE_4]);
tmpType += " PCI Device Number = ";
tmpType += String.format("0x%x", path[offset + UefiConstants.SIZE_5]);
subType = tmpType;
return tmpType;
}
@ -227,6 +230,7 @@ private String sataSubType(final byte[] path, final int offset) {
tmpType += " Port Multiplier = " + HexUtils.byteArrayToHexString(data);
System.arraycopy(path, UefiConstants.OFFSET_8 + offset, data, 0, UefiConstants.SIZE_2);
tmpType += " Logical Unit Number = " + HexUtils.byteArrayToHexString(data);
subType = tmpType;
return tmpType;
}
@ -237,18 +241,18 @@ private String sataSubType(final byte[] path, final int offset) {
* @return hard drive info.
*/
private String hardDriveSubType(final byte[] path, final int offset) {
String tmpType = " Partition Number = ";
String tmpType = "Partition Number = ";
byte[] partnumber = new byte[UefiConstants.SIZE_4];
System.arraycopy(path, UefiConstants.OFFSET_4 + offset, partnumber, 0, UefiConstants.SIZE_4);
tmpType += HexUtils.byteArrayToHexString(partnumber);
byte[] data = new byte[UefiConstants.SIZE_8];
System.arraycopy(path, UefiConstants.OFFSET_8 + offset, data, 0, UefiConstants.SIZE_8);
tmpType += " Partition Start = " + HexUtils.byteArrayToHexString(data);
tmpType += "Partition Start = " + HexUtils.byteArrayToHexString(data);
System.arraycopy(path, UefiConstants.OFFSET_16 + offset, data, 0, UefiConstants.SIZE_8);
tmpType += " Partition Size = " + HexUtils.byteArrayToHexString(data);
tmpType += "Partition Size = " + HexUtils.byteArrayToHexString(data);
byte[] signature = new byte[UefiConstants.SIZE_16];
System.arraycopy(path, UefiConstants.OFFSET_24 + offset, signature, 0, UefiConstants.SIZE_16);
tmpType += " Partition Signature = ";
tmpType += "Partition Signature = ";
if (path[UefiConstants.OFFSET_41 + offset] == UefiConstants.DRIVE_SIG_NONE) {
tmpType += "None";
} else if (path[UefiConstants.OFFSET_41 + offset] == UefiConstants.DRIVE_SIG_32BIT) {
@ -259,7 +263,7 @@ private String hardDriveSubType(final byte[] path, final int offset) {
} else {
tmpType += "invalid partition signature type";
}
tmpType += " Partition Format = ";
tmpType += "Partition Format = ";
if (path[UefiConstants.OFFSET_40 + offset] == UefiConstants.DRIVE_TYPE_PC_AT) {
tmpType += "PC-AT compatible legacy MBR";
} else if (path[UefiConstants.OFFSET_40 + offset] == UefiConstants.DRIVE_TYPE_GPT) {
@ -267,6 +271,7 @@ private String hardDriveSubType(final byte[] path, final int offset) {
} else {
tmpType += "Invalid partition table type";
}
subType = tmpType;
return tmpType;
}
@ -279,7 +284,7 @@ private String hardDriveSubType(final byte[] path, final int offset) {
*/
private String filePathSubType(final byte[] path, final int offset)
throws UnsupportedEncodingException {
String tmpType = " File Path = ";
String tmpType = "File Path = ";
byte[] lengthBytes = new byte[UefiConstants.SIZE_2];
System.arraycopy(path, 2 + offset, lengthBytes, 0, UefiConstants.SIZE_2);
int subTypeLength = HexUtils.leReverseInt(lengthBytes);
@ -287,6 +292,7 @@ private String filePathSubType(final byte[] path, final int offset)
System.arraycopy(path, UefiConstants.OFFSET_4 + offset, filePath, 0, subTypeLength);
byte[] fileName = convertChar16tobyteArray(filePath);
tmpType += new String(fileName, "UTF-8");
subType = tmpType;
return tmpType;
}
@ -300,7 +306,7 @@ private String filePathSubType(final byte[] path, final int offset)
* @return vendor device info.
*/
private String vendorSubType(final byte[] path, final int offset) {
String tmpType = " Vendor Subtype GUID = ";
String tmpType = "Vendor Subtype GUID = ";
byte[] lengthBytes = new byte[UefiConstants.SIZE_2];
System.arraycopy(path, UefiConstants.OFFSET_2 + offset, lengthBytes, 0, UefiConstants.SIZE_2);
int subTypeLength = HexUtils.leReverseInt(lengthBytes);
@ -316,6 +322,7 @@ private String vendorSubType(final byte[] path, final int offset) {
} else {
tmpType += " : No Vendor Data pesent";
}
subType = tmpType;
return tmpType;
}
@ -330,13 +337,14 @@ private String vendorSubType(final byte[] path, final int offset) {
* @return NVM device info.
*/
private String nvmSubType(final byte[] path, final int offset) {
String tmpType = " NVM Express Namespace = ";
String tmpType = "NVM Express Namespace = ";
byte[] lengthBytes = new byte[UefiConstants.SIZE_2];
System.arraycopy(path, UefiConstants.OFFSET_2 + offset, lengthBytes, 0, UefiConstants.SIZE_2);
int subTypeLength = HexUtils.leReverseInt(lengthBytes);
byte[] nvmData = new byte[subTypeLength];
System.arraycopy(path, UefiConstants.OFFSET_4 + offset, nvmData, 0, subTypeLength);
tmpType += HexUtils.byteArrayToHexString(nvmData);
subType = tmpType;
return tmpType;
}
@ -349,7 +357,7 @@ private String nvmSubType(final byte[] path, final int offset) {
* @return String that represents the UEFI defined BIOS Device Type.
*/
private String biosDevicePath(final byte[] path, final int offset) {
String devPath = " Legacy BIOS : Type = ";
String devPath = "Legacy BIOS : Type = ";
byte devPathType = path[offset + 1];
Byte pathType = Byte.valueOf(devPathType);
switch (pathType.intValue()) {
@ -366,6 +374,7 @@ private String biosDevicePath(final byte[] path, final int offset) {
default: devPath += "Reserved";
break;
}
subType = devPath;
return devPath;
}
@ -379,11 +388,12 @@ private String biosDevicePath(final byte[] path, final int offset) {
* @return String that represents the PIWG Firmware Volume Path
*/
private String piwgFirmVolFile(final byte[] path, final int offset) {
String fWPath = " PIWG Firmware File ";
String fWPath = "PIWG Firmware File ";
byte[] guidData = new byte[UefiConstants.SIZE_16];
System.arraycopy(path, UefiConstants.OFFSET_4 + offset, guidData, 0, UefiConstants.SIZE_16);
UefiGuid guid = new UefiGuid(guidData);
fWPath += guid.toString();
subType = fWPath;
return fWPath;
}
@ -397,11 +407,12 @@ private String piwgFirmVolFile(final byte[] path, final int offset) {
* @return String that represents the PIWG Firmware Volume Path
*/
private String piwgFirmVolPath(final byte[] path, final int offset) {
String fWPath = " PIWG Firmware Volume ";
String fWPath = "PIWG Firmware Volume ";
byte[] guidData = new byte[UefiConstants.SIZE_16];
System.arraycopy(path, UefiConstants.OFFSET_4 + offset, guidData, 0, UefiConstants.SIZE_16);
UefiGuid guid = new UefiGuid(guidData);
fWPath += guid.toString();
subType = fWPath;
return fWPath;
}

View File

@ -37,7 +37,7 @@ public class UefiFirmware {
byte[] lelength = HexUtils.leReverseByte(addressLength);
BigInteger bigIntLength = new BigInteger(lelength);
blobLength = bigIntLength.intValue();
byte[]leAddress = HexUtils.leReverseByte(addressLength);
byte[]leAddress = HexUtils.leReverseByte(physicalAddress);
BigInteger bigIntAddress = new BigInteger(leAddress);
blobAddress = bigIntAddress.intValue();
}

View File

@ -1,5 +1,7 @@
package hirs.tpm.eventlog.uefi;
import java.io.UnsupportedEncodingException;
import hirs.utils.HexUtils;
/**
* Class to process EFI Partitions for EFI Partition tables defined in UEFI section 5.3.3
@ -37,8 +39,9 @@ public class UefiPartition {
/**
* Processes a UEFI defined partition entry.
* @param table byte array holding the partition table.
* @throws UnsupportedEncodingException if parsing of the data fails.
*/
public UefiPartition(final byte[] table) {
public UefiPartition(final byte[] table) throws UnsupportedEncodingException {
byte[] partitionGUID = new byte[UefiGuid.getGuidLength()];
System.arraycopy(table, 0, partitionGUID, 0, UefiGuid.getGuidLength());
partitionTypeGUID = new UefiGuid(partitionGUID);
@ -52,9 +55,7 @@ public class UefiPartition {
System.arraycopy(table, UefiConstants.PART_NAME_LENGTH, partitionname,
0, UefiConstants.UEFI_PT_LENGTH);
byte[] pName = convertChar16tobyteArray(partitionname);
partitionName = HexUtils.byteArrayToHexString(pName);
String[] parts = partitionName.split("[^\\x00-\\x7F]"); // remove any non ASCII
partitionName = parts[0];
partitionName = new String(pName, "UTF-8").trim();
}
/**

View File

@ -53,9 +53,9 @@ public UefiVariable(final byte[] varibaleData)
byte[] dataLength = new byte[UefiConstants.SIZE_8];
byte[] name = null;
int variableLength = 0;
uefiGuid = new UefiGuid(guid);
System.arraycopy(varibaleData, 0, guid, 0, UefiConstants.SIZE_16);
uefiGuid = new UefiGuid(guid);
System.arraycopy(varibaleData, UefiConstants.SIZE_16, nameLength, 0, UefiConstants.SIZE_8);
int nlength = HexUtils.leReverseInt(nameLength);
System.arraycopy(varibaleData, UefiConstants.OFFSET_24, dataLength, 0, UefiConstants.SIZE_8);

View File

@ -0,0 +1,158 @@
package hirs.tpm.eventlog.uefi;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import hirs.utils.HexUtils;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/*
import org.junit.Test;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
*/
/**
* Class for testing TCG Event Log processing of UEFI defined Data.
*/
public class UefiProcessingTest {
// Variable files collected using an Event Parsing tool
private static final String UEFI_VARIABLE_BOOT = "/tcgeventlog/uefi/EV_EFI_VARIABLE_BOOT.txt";
private static final String UEFI_VARIABLE_BOOT_SECURE_BOOT
= "/tcgeventlog/uefi/EV_EFI_VAR_SECURE_BOOT.txt";
private static final String UEFI_VARIABLE_BOOT_DRIVER_CONFIG_KEK
= "/tcgeventlog/uefi/EV_EFI_VARIABLE_DRIVER_CONFIG_KEK.txt";
private static final String UEFI_GPT_EVENT = "/tcgeventlog/uefi/EV_EFI_GPT_EVENT.txt";
private static final String UEFI_FW_BLOB = "/tcgeventlog/uefi/EFI_PLATFORM_FIRMWARE_BLOB.txt";
private static final String UEFI_DEVICE_PATH = "/tcgeventlog/uefi/EFI_DEVICE_PATH.txt";
private static final Logger LOGGER
= LogManager.getLogger(UefiProcessingTest.class);
/**
* Initializes a <code>SessionFactory</code>.
* The factory is used for an in-memory database that is used for testing.
*/
@BeforeClass
public static final void setup() {
LOGGER.debug("retrieving session factory");
}
/**
* Closes the <code>SessionFactory</code> from setup.
*/
@AfterClass
public static final void tearDown() {
LOGGER.debug("closing session factory");
}
/**
* Tests the processing of UEFI Variables.
* @throws IOException when processing the test fails.
* @throws NoSuchAlgorithmException if non TCG Algorithm is encountered.
* @throws CertificateException if parsing issue for X509 cert is encountered.
*/
@Test
public final void testUefiVariables() throws IOException,
CertificateException, NoSuchAlgorithmException {
LOGGER.debug("Testing the parsing of UEFI Variables");
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_VARIABLE_BOOT),
"UTF-8");
byte[] uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
UefiVariable uefiVariable = new UefiVariable(uefiVariableBytes);
UefiGuid guid = uefiVariable.getEfiVarGuid();
String varName = uefiVariable.getEfiVarName();
Assert.assertEquals(guid.toString(),
"8be4df61-93ca-11d2-aa0d-00e098032b8c : EFI_Global_Variable");
Assert.assertEquals(varName, "BootOrder");
uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_VARIABLE_BOOT_SECURE_BOOT),
"UTF-8");
uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
uefiVariable = new UefiVariable(uefiVariableBytes);
guid = uefiVariable.getEfiVarGuid();
varName = uefiVariable.getEfiVarName();
Assert.assertEquals(guid.toString(),
"8be4df61-93ca-11d2-aa0d-00e098032b8c : EFI_Global_Variable");
Assert.assertEquals(varName, "SecureBoot");
uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(
UEFI_VARIABLE_BOOT_DRIVER_CONFIG_KEK), "UTF-8");
uefiVariableBytes = HexUtils.hexStringToByteArray(uefiTxt);
uefiVariable = new UefiVariable(uefiVariableBytes);
varName = uefiVariable.getEfiVarName();
Assert.assertEquals(varName, "KEK");
}
/**
* Tests the processing of a UEFI defined GPT Partition event.
* @throws IOException when processing the test fails.
* @throws NoSuchAlgorithmException if non TCG Algorithm is encountered.
* @throws CertificateException if parsing issue for X509 cert is encountered.
*/
@Test
public final void testUefiPartiton() throws IOException,
CertificateException, NoSuchAlgorithmException {
LOGGER.debug("Testing the parsing of GPT Data");
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_GPT_EVENT),
"UTF-8");
byte[] uefiPartitionBytes = HexUtils.hexStringToByteArray(uefiTxt);
UefiPartition gptPart = new UefiPartition(uefiPartitionBytes);
String gptPartName = gptPart.getName();
UefiGuid gptTypeuid = gptPart.getPartitionTypeGUID();
UefiGuid gptUniqueGuid = gptPart.getUniquePartitionGUID();
Assert.assertEquals(gptTypeuid.toString(),
"c12a7328-f81f-11d2-ba4b-00a0c93ec93b : EFI System Partition");
Assert.assertEquals(gptUniqueGuid.toString(),
"8ca7623c-041e-4fab-8c12-f49a86b85d73 : Unknown GUID reference");
Assert.assertEquals(gptPartName, "EFI system partition");
}
/**
* Tests the processing of a UEFI defined GPT Partition event.
* @throws IOException when processing the test fails.
* @throws NoSuchAlgorithmException if non TCG Algorithm is encountered.
* @throws CertificateException if parsing issue for X509 cert is encountered.
*/
@Test
public final void testUefiFirmwareBlob() throws IOException,
CertificateException, NoSuchAlgorithmException {
LOGGER.debug("Testing the parsing of Uefi Firmware Blob");
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_FW_BLOB), "UTF-8");
byte[] uefiFwBlobBytes = HexUtils.hexStringToByteArray(uefiTxt);
UefiFirmware uefiFWBlob = new UefiFirmware(uefiFwBlobBytes);
int fwAddress = uefiFWBlob.getPhysicalAddress();
int fwLength = uefiFWBlob.getBlobLength();
Assert.assertEquals(fwAddress, 1797287936);
Assert.assertEquals(fwLength, 851968);
}
/**
* Tests the processing of a UEFI defined Device Path.
* @throws IOException when processing the test fails.
*/
@Test
public final void testUefiDevicePath() throws IOException {
LOGGER.debug("Testing the parsing of Uefi Device Path");
String uefiTxt = IOUtils.toString(this.getClass().getResourceAsStream(UEFI_DEVICE_PATH),
"UTF-8");
byte[] uefiFwBlobBytes = HexUtils.hexStringToByteArray(uefiTxt);
UefiDevicePath uefiDevPath = new UefiDevicePath(uefiFwBlobBytes);
String devPathType = uefiDevPath.getType();
String devPathSubType = uefiDevPath.getSubType();
Assert.assertEquals(devPathType, "Media Device Path");
Assert.assertEquals(devPathSubType,
"PIWG Firmware File 15e1e31a-9f9d-4c84-82fb-1a707fc0f63b : RSTeSATAEFI");
}
}

View File

@ -0,0 +1,5 @@
/**
* Test classes for the hirs.tpm package.
*/
package hirs.tpm.eventlog.uefi;

View File

@ -0,0 +1 @@
040714002ce2edb630defa45bb09ca202c1654b7040614001ae3e1159d9f844c82fb1a707fc0f63b7fff0400

View File

@ -0,0 +1 @@
0070206b0000000000000d0000000000

View File

@ -0,0 +1 @@
28732ac11ff8d211ba4b00a0c93ec93b3c62a78c1e04ab4f8c12f49a86b85d7300a80f0000000000ffc712000000000000000000000000804500460049002000730079007300740065006d00200070006100720074006900740069006f006e000000000000000000000000000000000000000000000000000000000000000000

View File

@ -0,0 +1 @@
61dfe48bca93d211aa0d00e098032b8c09000000000000000c0000000000000042006f006f0074004f007200640065007200040003000200000001000500

View File

@ -0,0 +1 @@
61dfe48bca93d211aa0d00e098032b8c030000000000000000000000000000004b0045004b00

View File

@ -0,0 +1 @@
61dfe48bca93d211aa0d00e098032b8c0a00000000000000010000000000000053006500630075007200650042006f006f00740000