added tcg_eventlog_tool

This commit is contained in:
iadgovuser26 2020-05-15 10:46:47 -04:00
parent f24c53f6c6
commit b8f4182415
16 changed files with 571 additions and 267 deletions

View File

@ -244,24 +244,9 @@ public final class TCGEventLog {
public String toString() {
StringBuilder sb = new StringBuilder();
for (TpmPcrEvent event:eventList) {
if (bEvent) {
sb.append(event.toString());
}
if (bHexEvent) {
byte[] eventData = event.getEvent();
sb.append("Event (Hex no Content) (" + eventData.length + " bytes): "
+ HexUtils.byteArrayToHexString(eventData) + "\n");
}
if (bContent) {
byte[] eventContent = event.getEventContent();
sb.append("Event content (Hex) (" + eventContent.length + " bytes): "
+ HexUtils.byteArrayToHexString(eventContent) + "\n");
}
if (bEvent || bHexEvent || bContent) {
sb.append("\n");
}
sb.append(event.toString(bEvent, bHexEvent, bContent));
}
sb.append("Event Log proessing completed.\n");
sb.append("Event Log processing completed.\n");
return sb.toString();
}
/**

View File

@ -21,6 +21,7 @@ import hirs.tpm.eventlog.events.EvNoAction;
import hirs.tpm.eventlog.events.EvPostCode;
import hirs.tpm.eventlog.events.EvSCrtmContents;
import hirs.tpm.eventlog.events.EvSCrtmVersion;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.tpm.eventlog.uefi.UefiFirmware;
import hirs.tpm.eventlog.uefi.UefiVariable;
import hirs.utils.HexUtils;
@ -248,9 +249,12 @@ public class TpmPcrEvent {
description += "Event Type: 0x" + Long.toHexString(eventType) + " " + eventString(eventID);
description += "\n";
if (logFormat == 1) { // Digest
description += "digest (SHA-1): " + HexUtils.byteArrayToHexString(this.digest) + "\n";
description += "digest (SHA-1): " + HexUtils.byteArrayToHexString(this.digest);
} else {
description += "digest (SHA256): " + HexUtils.byteArrayToHexString(this.digest) + "\n";
description += "digest (SHA256): " + HexUtils.byteArrayToHexString(this.digest);
}
if (eventID != UefiConstants.SIZE_4) {
description += "\n";
}
// Calculate both the SHA1 and SHA256 on the event since this will equal the digest
// field of about half the log messages.
@ -267,7 +271,7 @@ public class TpmPcrEvent {
break;
case EvConstants.EV_POST_CODE:
EvPostCode postCode = new EvPostCode(eventContent);
description += "Event Content:\n" + postCode.toString() + "\n";
description += "Event Content:\n" + postCode.toString();
break;
case EvConstants.EV_UNUSED:
break;
@ -284,25 +288,25 @@ public class TpmPcrEvent {
if (EvPostCode.isAscii(eventContent)) {
String seperatorEventData = new String(eventContent, StandardCharsets.UTF_8);
if (!this.isEmpty(eventContent)) {
description += "Seperator event content = " + seperatorEventData + "\n";
description += "Seperator event content = " + seperatorEventData;
}
}
break;
case EvConstants.EV_ACTION:
description += "Event Content:\n"
+ new String(eventContent, StandardCharsets.UTF_8) + "\n";
+ new String(eventContent, StandardCharsets.UTF_8);
break;
case EvConstants.EV_EVENT_TAG:
EvEventTag eventTag = new EvEventTag(eventContent);
description += eventTag.toString() + "\n";
description += eventTag.toString();
break;
case EvConstants.EV_S_CRTM_CONTENTS:
EvSCrtmContents sCrtmContents = new EvSCrtmContents(eventContent);
description += "Event Content:\n " + sCrtmContents.toString() + "\n";
description += "Event Content:\n " + sCrtmContents.toString();
break;
case EvConstants.EV_S_CRTM_VERSION:
EvSCrtmVersion sCrtmVersion = new EvSCrtmVersion(eventContent);
description += "Event Content:\n" + sCrtmVersion.toString() + "\n";
description += "Event Content:\n" + sCrtmVersion.toString();
break;
case EvConstants.EV_CPU_MICROCODE:
break;
@ -312,11 +316,11 @@ public class TpmPcrEvent {
break;
case EvConstants.EV_COMPACT_HASH:
EvCompactHash compactHash = new EvCompactHash(eventContent);
description += "Event Content:\n" + compactHash.toString() + "\n";
description += "Event Content:\n" + compactHash.toString();
break;
case EvConstants.EV_IPL:
EvIPL ipl = new EvIPL(eventContent);
description += "Event Content:\n" + ipl.toString() + "\n";
description += "Event Content:\n" + ipl.toString();
break;
case EvConstants.EV_IPL_PARTITION_DATA:
break;
@ -353,11 +357,11 @@ public class TpmPcrEvent {
description += "Event Content:\n" + new EvEfiGptPartition(eventContent).toString();
break;
case EvConstants.EV_EFI_ACTION:
description += new String(eventContent, StandardCharsets.UTF_8) + "\n";
description += new String(eventContent, StandardCharsets.UTF_8);
break;
case EvConstants.EV_EFI_PLATFORM_FIRMWARE_BLOB:
description += "Event Content:\n"
+ new UefiFirmware(eventContent).toString() + "\n";
+ new UefiFirmware(eventContent).toString();
break;
case EvConstants.EV_EFI_HANDOFF_TABLES:
EvEfiHandoffTable efiTable = new EvEfiHandoffTable(eventContent);
@ -491,6 +495,37 @@ public class TpmPcrEvent {
* @return Description of the log.
*/
public String toString() {
return description;
return description + "\n";
}
/**
* Human readable string representing the contents of the Event Log.
* @param bEvent event Flag.
* @param bContent content flag.
* @param bHexEvent hex event flag.
* @return Description of the log.
*/
public String toString(final boolean bEvent, final boolean bContent, final boolean bHexEvent) {
StringBuilder sb = new StringBuilder();
if (bEvent) {
sb.append(description);
}
if (bHexEvent) {
if (bEvent || bContent) {
sb.append("\n");
}
byte[] eventData = getEvent();
sb.append("Event (Hex no Content) (" + eventData.length + " bytes): "
+ HexUtils.byteArrayToHexString(eventData));
}
if (bContent) {
byte[] evContent = getEventContent();
if (bEvent) {
sb.append("\n");
}
sb.append("Event content (Hex) (" + evContent.length + " bytes): "
+ HexUtils.byteArrayToHexString(evContent));
}
return sb.toString() + "\n";
}
}

View File

@ -122,11 +122,11 @@ public class EvEfiBootServicesApp {
info += " Image physical address: " + HexUtils.byteArrayToHexString(physicalAddress);
info += " Image length = " + imageLength;
info += " Image link time address: " + HexUtils.byteArrayToHexString(physicalAddress);
info += " Device path length = " + devicePathLength + "\n";
info += " Device path length = " + devicePathLength;
if (devicePathValid) {
info += devPath.toString();
info += "\n" + devPath.toString();
} else {
info += " Error processing device path" + "\n";
info += "\n Error processing device path" + "\n";
}
return info;
}

View File

@ -119,7 +119,10 @@ public class EvEfiGptPartition {
partitionInfo.append("GPT Header Signature = " + headerStr + " : Number of Paritions = "
+ numberOfPartitions + "\n");
for (int i = 0; i < numberOfPartitions; i++) {
partitionInfo.append("Partition " + i + " information\n");
if (i > 0) {
partitionInfo.append("\n");
}
partitionInfo.append(" Partition " + i + " information\n");
partitionInfo.append(partitionList.get(i).toString());
}
return partitionInfo.toString();

View File

@ -101,7 +101,7 @@ public class EvEfiHandoffTable {
tableInfo.append(" UEFI industry standard table type = "
+ currentGuid.getVendorTableReference() + "\n");
tableInfo.append(" VendorTable " + i + " address: "
+ HexUtils.byteArrayToHexString(vendorTables.get(i)) + "\n");
+ HexUtils.byteArrayToHexString(vendorTables.get(i)));
}
return tableInfo.toString();
}

View File

@ -169,7 +169,7 @@ public class EvEfiSpecIdEvent {
String specInfo = "";
if (signature == "Spec ID Event#") {
specInfo += "Platform Profile Specification version = " + vMaj + "." + vMin
+ " using errata version" + errata + "\n";
+ " using errata version" + errata;
} else {
specInfo = "EV_NO_ACTION event named " + signature
+ " ecncountered but support for processing it has not been added to this application";

View File

@ -66,13 +66,13 @@ public class EvNoAction {
if (bSpecIDEvent) {
specInfo += " Signature = Spec ID Event03 : ";
if (specIDEvent.isCryptoAgile()) {
specInfo += "Log format is Crypto Agile \n";
specInfo += "Log format is Crypto Agile\n";
} else {
specInfo += "Log format is SHA 1 (NOT Crypto Agile) \n";
specInfo += "Log format is SHA 1 (NOT Crypto Agile)\n";
}
specInfo += " Platform Profile Specification version = "
+ specIDEvent.getVersionMajor() + "." + specIDEvent.getVersionMinor()
+ " using errata version " + specIDEvent.getErrata() + "\n";
}
+ " using errata version " + specIDEvent.getErrata();
} else {
specInfo = "EV_NO_ACTION event named " + signature
+ " encountered but support for processing it has not been added to this application.\n";

View File

@ -31,7 +31,7 @@ public String toString() {
for (int i = 0; i < bootOrder.length; i++) {
orderList.append(String.format("Boot %04d", (int) bootOrder[i]));
}
orderList.append("\n");
//orderList.append("\n");
return orderList.toString();
}
}

View File

@ -53,6 +53,8 @@ public final class UefiConstants {
public static final int OFFSET_3 = 3;
/** 4 byte offset. */
public static final int OFFSET_4 = 4;
/** 5 byte offset. */
public static final int OFFSET_5 = 5;
/** 6 byte offset. */
public static final int OFFSET_6 = 4;
/** 8 byte offset. */
@ -89,6 +91,8 @@ public final class UefiConstants {
public static final int DEV_MEDIA = 0x04;
/** Device Type Hardware. */
public static final int DEV_BIOS = 0x05;
/** Device Sub-Type USV. */
public static final int DEV_SUB_USB = 0x05;
/** Device Sub-Type Sata. */
public static final int DEV_SUB_SATA = 0x12;
/** Device Sub-Type nvm. */

View File

@ -84,26 +84,24 @@ public class UefiDevicePath {
*/
private String processDevPath(final byte[] path) throws UnsupportedEncodingException {
StringBuilder pInfo = new StringBuilder();
String devicePathInfo = "";
int devLength = 0, pathOffset = 0;
int devLength = 0, pathOffset = 0, devCount = 0;
while (true) {
Byte devPath = Byte.valueOf(path[pathOffset]);
if ((devPath.intValue() == UefiConstants.TERMINATOR)
|| (devPath.intValue() == UefiConstants.END_FLAG)) {
break;
}
devicePathInfo = processDev(path, pathOffset);
if (devicePathInfo.contains("Unknown Device Path")) {
if (devCount++ > 0) {
pInfo.append("\n");
}
pInfo.append(processDev(path, pathOffset));
devLength = path[pathOffset + UefiConstants.OFFSET_3] * UefiConstants.SIZE_256
+ path[pathOffset + UefiConstants.OFFSET_2];
pathOffset = pathOffset + devLength;
if (pathOffset >= path.length) {
break;
}
pInfo.append(devicePathInfo);
devLength = path[pathOffset + UefiConstants.OFFSET_3] * UefiConstants.SIZE_256
+ path[pathOffset + UefiConstants.OFFSET_2];
pathOffset = pathOffset + devLength;
if (pathOffset >= path.length) {
break;
}
}
}
}
return pInfo.toString();
}
@ -120,6 +118,7 @@ public class UefiDevicePath {
throws UnsupportedEncodingException {
String devInfo = " ";
int devPath = path[offset];
byte unknownSubType = path[offset + UefiConstants.OFFSET_1];
switch (path[0 + offset]) {
case UefiConstants.DEV_HW: type = "Hardware Device Path";
if (devPath == UefiConstants.DEVPATH_HARWARE) {
@ -132,9 +131,12 @@ public class UefiDevicePath {
case UefiConstants.DEV_MSG: type = "Messaging Device Path";
if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEV_SUB_SATA) {
devInfo += type + ": " + sataSubType(path, offset);
}
if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEV_SUB_NVM) {
} else if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEV_SUB_NVM) {
devInfo += type + ": " + nvmSubType(path, offset);
} else if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEV_SUB_USB) {
devInfo += type + ": " + usbSubType(path, offset);
} else {
devInfo += "UEFI Messaging Device Path Type " + Integer.valueOf(unknownSubType);
}
break;
case UefiConstants.DEV_MEDIA: type = "Media Device Path";
@ -148,6 +150,8 @@ public class UefiDevicePath {
devInfo += type + ": " + piwgFirmVolFile(path, offset);
} else if (path[offset + UefiConstants.OFFSET_1] == UefiConstants.DEVPATH_PWIG_VOL) {
devInfo += type + ": " + piwgFirmVolPath(path, offset);
} else {
devInfo += "UEFI Media Device Path Type " + Integer.valueOf(unknownSubType);
}
break;
case UefiConstants.DEV_BIOS: type = "BIOS Device Path";
@ -155,11 +159,10 @@ public class UefiDevicePath {
break;
case UefiConstants.TERMINATOR: devInfo += "End of Hardware Device Path";
break;
default: type = "Unknown Device Path";
devInfo = type;
default:
devInfo += "UEFI Device Path Type " + Integer.valueOf(unknownSubType);
}
devInfo += "\n";
return devInfo;
return devInfo;
}
/**
@ -318,7 +321,27 @@ private String vendorSubType(final byte[] path, final int offset) {
}
/**
* Returns nvm device info.
* Returns USB device info.
* UEFI Specification, Version 2.8.
* @param path
* @param offset
* @return USB device info.
*/
private String usbSubType(final byte[] path, final int offset) {
subType = " USB ";
subType += " port = " + Integer.valueOf(path[offset + UefiConstants.OFFSET_4]);
subType += " interface = " + Integer.valueOf(path[offset + UefiConstants.OFFSET_5]);
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[] usbData = new byte[subTypeLength];
System.arraycopy(path, UefiConstants.OFFSET_4 + offset, usbData, 0, subTypeLength);
// Todo add further USB processing ...
return subType;
}
/**
* Returns NVM device info.
* UEFI Specification, Version 2.8.
* Name space Identifier (NSID) and IEEE Extended Unique Identifier (EUI-64):
* See Links to UEFI Related Documents

View File

@ -91,7 +91,7 @@ public String toString() {
partitionInfo += " Partition Name : " + partitionName + "\n";
partitionInfo += " Partition Type GUID : " + partitionTypeGUID.toString() + "\n";
partitionInfo += " Unique Partition GUID : " + uniquePartitionGUID.toStringNoLookup() + "\n";
partitionInfo += " Attributes : " + attributes + "\n";
partitionInfo += " Attributes : " + attributes;
return partitionInfo;
}

View File

@ -43,11 +43,11 @@ public int getSecurBootVariable() {
public String toString() {
if (!berror) {
if (secureBootVar == 1) {
info += " Secure Boot is enabled \n";
info += " Secure Boot is enabled ";
} else if (secureBootVar == 0) {
info += " Secure Boot is NOT enabled \n";
info += " Secure Boot is NOT enabled ";
} else {
info += " Unkown State: Secure Variable is undefined \n";
info += " Unkown State: Secure Variable is undefined ";
}
}
return info;

View File

@ -143,6 +143,8 @@ public String toString() {
String tmpName = varName;
if (varName.contains("Boot00")) {
tmpName = "Boot00";
} else {
tmpName = varName;
}
switch (tmpName) {
case "Shim": efiVariable.append(printCert(uefiVaribelData, 0)); break;
@ -150,7 +152,12 @@ public String toString() {
case "Boot00": efiVariable.append(bootv.toString()); break;
case "BootOrder": efiVariable.append(booto.toString()); break;
case "SecureBoot": efiVariable.append(sb.toString()); break;
default: efiVariable.append("Data not provided for UEFI var named " + tmpName + "\n");
default:
if (!tmpName.isEmpty()) {
efiVariable.append("Data not provided for UEFI variable named " + tmpName + " ");
} else {
efiVariable.append("Data not provided ");
}
}
for (int i = 0; i < certSuperList.size(); i++) {
efiVariable.append(certSuperList.get(i).toString());
@ -175,7 +182,7 @@ public String printCert(final byte[] data, final int offset) {
UefiX509Cert cert = new UefiX509Cert(certData);
certInfo = cert.toString();
} catch (Exception e) {
certInfo = "Error Processing Certificate : " + e.getMessage() + "\n";
certInfo = "Error Processing Certificate : " + e.getMessage();
}
return (certInfo);
}

View File

@ -1,4 +1,4 @@
package hirs.tcglp.utils;
package hirs.tcg_eventlog_tool;
import java.io.File;
import java.io.IOException;
@ -6,36 +6,45 @@ import java.nio.file.InvalidPathException;
/**
* Commander is a class that handles the command line arguments for the
* TCG Log Parser (tcglp).
* TCG Log Parser (tcg_eventlotool).
*/
public class Commander {
private static final String COMMAND_PREFIX = "-";
private static final String FULL_COMMAND_PREFIX = "--";
private static final String ALL_STRING = "all";
private static final String CONTENT_STRING = "eventcontent";
private static final String CONTENT_STRING = "contenthex";
private static final String DIFF_STRING = "diff";
private static final String EVENTIDS_STRING = "eventids";
private static final String EVENTIDS_STRING = "event";
private static final String FILE_STRING = "file";
private static final String HELP_STRING = "help";
private static final String EVENTHEX_STRING = "eventhex";
private static final String HEX_STRING = "hex";
private static final String OUTPUT_STRING = "output";
private static final String PCR_STRING = "tpmpcrs";
private static final String PCR_STRING = "pcr";
private static final String VERIFY_STRING = "Verify";
private static final String VERSION_STRING = "version";
private static final String VERSION_NUMBER = "1.0";
private boolean hasArguments = false;
private boolean bAll = false;
private boolean bContent = false;
private boolean bContentHex = false;
private boolean bDiff = false;
private boolean bEventIds = false;
private boolean bFile = false;
private boolean bEventHex = false;
private boolean bHex = false;
private boolean bOutput = false;
private boolean bPCRs = false;
private boolean bVerify = false;
private String inFile = "";
private String outFile = "";
private String inFile2 = "";
private String outFile = "";
private String eventFilter = "";
private String pcrFilter = "";
private int pcrNumber = -1;
private int eventNumber = -1;
/**
* The main constructor for the Commander class
@ -70,39 +79,81 @@ public class Commander {
bAll = true;
break;
case FULL_COMMAND_PREFIX + CONTENT_STRING:
case COMMAND_PREFIX + "c":
bContent = true;
break;
case FULL_COMMAND_PREFIX + DIFF_STRING:
case COMMAND_PREFIX + "d":
bDiff = true;
break;
case FULL_COMMAND_PREFIX + EVENTIDS_STRING:
case COMMAND_PREFIX + "e":
if (i<args.length-1) { // Check for a filter following the -e on the command line
if (!args[i+1].startsWith("-")) {
eventFilter=args[i+++1];
eventNumber = new Integer(eventFilter).intValue();
}
}
bEventIds = true;
break;
case COMMAND_PREFIX + "ec":
bContentHex = true;
break;
case FULL_COMMAND_PREFIX + EVENTHEX_STRING:
case COMMAND_PREFIX + "ex":
bEventHex = true;
break;
case FULL_COMMAND_PREFIX + DIFF_STRING:
case COMMAND_PREFIX + "d":
if ((args.length < i+3)||(args[i+1].charAt(0)=='-')||(args[i+2].charAt(0)=='-')){
System.out.print("tcg_eventlog_tool command line error: 2 or 3 parameters needed for -diff.\n");
System.out.print("usage: elt -d logFile1 logFile2 pcr#");
System.exit(0);
} else {
inFile = args[i+++1];
inFile2 = args[i+++1];
if (args.length>i+1) {
if (!args[i+1].contains("-")) { // pcr filter provided
eventFilter = args[i+++1];
eventNumber = new Integer(eventFilter).intValue();
}
}
bDiff = true;
}
break;
case FULL_COMMAND_PREFIX + FILE_STRING:
case COMMAND_PREFIX + "f":
bFile = true;
inFile = args[++i];
break;
case FULL_COMMAND_PREFIX + HEX_STRING:
case COMMAND_PREFIX + "x":
bHex = true;
break;
case FULL_COMMAND_PREFIX + OUTPUT_STRING:
case COMMAND_PREFIX + "o":
if (i<args.length-1) { // Check for a filter following the -p on the command line
if (!args[i+1].startsWith("-")) {
outFile=args[i+++1];
} else {
System.out.print("no output file specified with -o option");
System.exit (1);
}
}
bOutput = true;
outFile = args[++i];
break;
case FULL_COMMAND_PREFIX + PCR_STRING:
case COMMAND_PREFIX + "p":
if (i<args.length-1) { // Check for a filter following the -p on the command line
if (!args[i+1].startsWith("-")) {
pcrFilter=args[i+++1];
pcrNumber = new Integer(pcrFilter).intValue();
}
}
bPCRs = true;
break;
case FULL_COMMAND_PREFIX + VERSION_STRING:
case COMMAND_PREFIX + "v":
System.out.print("TCG Event Log Parser version " + VERSION_NUMBER);
System.exit (0);
break;
case FULL_COMMAND_PREFIX + VERIFY_STRING:
case COMMAND_PREFIX + "V":
bVerify = true;
break;
case FULL_COMMAND_PREFIX + HEX_STRING:
case COMMAND_PREFIX + "x":
bHex = true;
break;
case FULL_COMMAND_PREFIX + HELP_STRING:
case COMMAND_PREFIX + "h":
default:
@ -112,8 +163,8 @@ public class Commander {
}
/**
* Getter for the property that indicates if something was given at the
* commandline.
* Getter for the property that indicates if something was given at the commandline.
*
* @return true if any arguments were passed in.
*/
public final boolean hasArguments() {
@ -141,9 +192,16 @@ public class Commander {
* @return true if the Event Flag was set.
*/
public final boolean getContentFlag() {
return bContent;
return bContentHex;
}
/**
* Getter for the input associated with the Event Hex flag.
* @return true if the Hex Flag was set.
*/
public final boolean getEventHexFlag() {
return bEventHex;
}
/**
* Getter for the input associated with the Hex flag.
* @return true if the Hex Flag was set.
@ -167,15 +225,6 @@ public class Commander {
public final boolean getFileFlag() {
return bFile;
}
/**
* Getter for the input associated with the Output flag.
* @return true if the Output flag was set.
*/
public final boolean getOutputFile() {
return bOutput;
}
/**
* Getter for the input associated with the diff flag.
* @return
@ -191,7 +240,41 @@ public class Commander {
public final boolean getVerifyFile() {
return bVerify;
}
/**
* Returns the name of the input file, if provided.
* @return name of the input file.
*/
public final String getInFileName() {
return inFile;
}
/**
* Returns the name of the 2nd input file, if provided.
* @return name of the 2nd input file.
*/
public final String getInFile2Name() {
return inFile2;
}
/**
* Returns the name of the 2nd input file, if provided.
* @return name of the 2nd input file.
*/
public final String getEventFilter() {
return eventFilter;
}
/**
* Returns the name of the 2nd input file, if provided.
* @return name of the 2nd input file.
*/
public final int getEventNumber() {
return eventNumber;
}
/**
* Getter for the input associated with the Output flag.
* @return true if the Output flag was set.
*/
public final boolean getOutputFlag() {
return bOutput;
}
/**
* Returns the name of the output file, if provided.
* @return name of the output file.
@ -199,13 +282,19 @@ public class Commander {
public final String getOutputFileName() {
return outFile;
}
/**
* Returns the name of the input file, if provided.
* @return name of the input file.
* Returns the name of the 2nd input file, if provided.
* @return name of the 2nd input file.
*/
public final String getInFileName() {
return inFile;
public final String getPcrFilter() {
return pcrFilter;
}
/**
* Returns the name of the 2nd input file, if provided.
* @return name of the 2nd input file.
*/
public final int getPcrNumber() {
return pcrNumber;
}
/**
* This method is used to inform the user of the allowed functionality of
@ -219,39 +308,63 @@ public class Commander {
}
sb.append("\nTCG Log Parser ");
if (os.compareToIgnoreCase("linux")==0) {
sb.append("Usage: sh tcglp.sh [OPTION]...-f [FILE]...\n");
sb.append("Usage: sh elt.sh [OPTION]...-f [FILE]...\n");
} else {
sb.append("Usage: .tcglp.ps1 [OPTION]...-f [FILE]...\n");
sb.append("Usage: ./elt.ps1 [OPTION]...-f [FILE]...\n");
}
sb.append("Options:\n -a\t--all\t\t Displays everything; overrides other options.\n"
+ " -c\t--eventcontent\t Displays event content (hex). \n\t\t\t Following paramter MAY be a event id or event id label. \n\t\t\t No following parameters will read All Events.\n"
+ " -d\t--diff\t\t Compares two TCG Event Logs and outputs a list of events that differred.\n"
+ " -e\t--eventids\t Filters the output to only display events using ID's provided.\n\t\t\t ID is single work mask of the event ID's. \n\t\t\t No EventID will output all events.\n"
+ " -f\t--file\t\t Use specific input file. \n\t\t\t Following parameter MUST be a relative path and file name.\n"
+ " -o\t--output\t Output to a file. \n\t\t\t Following parameter MUST be a relative path and file name.\n"
+ " -p\t--tpmpcrs\t Output PCR contents calculated from the TCG Log. \n\t\t\t Following parameter MAY be a PCR number or Text PCR[] string.\n\t\t\t No following parameters will display ALl PCRs.\n"
+ " -v\t--Version\t Parser Version.\n"
+ " -V\t--Verify\t Attempts to verify the log file against values on the local device.\n"
+ " -x\t--hex\t\t Displays event structure of each log event in hexdecimal.\n");
sb.append("Options:\n"
+ " -f\t--file\t\t Use specific Event Log file. "
+ "\n\t\t\t Following parameter MUST be a path and file name."
+ "\n\t\t\t The local Event Log file will be used if this option is not present."
+ "\n\t\t\t Note: Access to the local Event Log may require admin privileges.\n"
+ " -e\t--event\t\t Display event descriptions (including event content) in human readable form. "
+ "\n\t\t\t Following optional parameter is a single pcr id used to filter"
+ " the output."
+ "\n\t\t\t All events will be displayed if the optional parameter is not provided.\n"
+ " -ec\t--contenthex\t Displays event content"
+ " in eventhex format when -event is used.\n"
+ " -ex\t--eventhex\t Displays event in hex format when -event is used"
+ " when -event is used.\n"
+ " -d\t--diff\t\t Compares two TCG Event Logs and outputs a list of events"
+ " of the second log that differred.\n"
+ " -o\t--output\t Output to a file. "
+ "\n\t\t\t Following parameter MUST be a relative path and file name.\n"
+ " -p\t--pcr\t\t Output expected PCR value calculated from the "
+ "TCG Log (for PCR Replay)."
+ "\n\t\t\t Following parameter MAY be a PCR number used to specify a single pcr."
+ "\n\t\t\t No following parameters will display all PCRs.\n"
+ " -v\t--version\t Parser Version.\n"
// + " -V\t--Verify\t Attempts to verify the log file against values on the local device."
+ " -x\t--hex\t\t Displays output in hex format."
+ "\n\t\t\t Use -e -ec and -ex options to filter output."
+ "\n\t\t\t All output will be human readble form if this parameter is not present.\n"
+ "\n");
if (os.compareToIgnoreCase("linux")==0) {
sb.append("\nIf no FILE parameter is provided then the standard Linux TCGEventLog path (/sys/kernel/security/tpm0/binary_bios_measurements) is used."
sb.append("\nIf no FILE parameter is provided then the standard Linux TCGEventLog path "
+ "\n(/sys/kernel/security/tpm0/binary_bios_measurements) is used."
+"\n Note admin privileges may be required (e.g. use sudo when running the script).\n"
+"All OPTIONS must be seperated by a space delimiter, no concatenation of OPTIONS is currently supported.\n"
+"All OPTIONS must be seperated by a space delimiter, no concatenation"
+ " of OPTIONS is currently supported.\n"
+"\nExamples: (run from the script directory)\n"
+"1. Display all events from the binary_bios_measurements.bin test pattern:\n"
+" sh tcglp.sh -f ../test/testdata/binary_bios_measurements_Dell_Fedora30.bin -e\n"
+" sh elt.sh -f ../test/testdata/binary_bios_measurements_Dell_Fedora30.bin -e\n"
+"2. Display only the event with an index of 0 (e.g event that extend PCR 0):\n"
+" sh scripts/tcglp.sh -f ../test/testdata/binary_bios_measurements_Dell_Fedora30.bin -p 0\n"
+" sh scripts/elt.sh -f "
+ "../test/testdata/binary_bios_measurements_Dell_Fedora30.bin -p 0\n"
);
} else { //windows
sb.append("\nIf no FILE parameter is provided then the standard Windows TCGEventLog path (C:\\Windows\\Logs\\MeasuredBoot) is used"
sb.append("\nIf no FILE parameter is provided then the "
+ "standard Windows TCGEventLog path (C:\\Windows\\Logs\\MeasuredBoot) is used"
+"\n Note admin privileges may be required (e.g. run as Administrator).\n"
+"All OPTIONS must be seperated by a space delimiter, no concatenation of OPTIONS is currently supported.\n"
+"All OPTIONS must be seperated by a space delimiter, "
+ "no concatenation of OPTIONS is currently supported.\n"
+"\nExamples:(run from the script directory)\n"
+"1. Display all events from the binary_bios_measurements.bin test pattern:\n"
+" ./tcglp.ps1 -f ..\\test\\testdata\\binary_bios_measurements_Dell_Fedora30.bin -e\n"
+" ./elt.ps1 -f "
+ "..\\test\\testdata\\binary_bios_measurements_Dell_Fedora30.bin -e\n"
+"2. Display only the event with an index of 0 (e.g event that extend PCR 0):\n"
+" ./tcglp.ps1 -f ..\\test\\testdata\\binary_bios_measurements_Dell_Fedora30.bin -p 0\n"
+" ./elt.ps1 -f "
+ "..\\test\\testdata\\binary_bios_measurements_Dell_Fedora30.bin -p 0\n"
);
}
System.out.println(sb.toString());

View File

@ -0,0 +1,277 @@
package hirs.tcg_eventlog_tool;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import hirs.tpm.eventlog.TCGEventLog;
import hirs.tpm.eventlog.TpmPcrEvent;
import hirs.utils.HexUtils;
/**
* Command-line application for processing TCG Event Logs.
* Input arg: path to *.tcglp file
*
*/
public class Main {
private static Commander commander = null;
static FileOutputStream outputStream = null;
static byte[] eventLog = null;
static boolean bContentFlag, bEventFlag, bHexEvent, bHexFlag, bPcrFlag, bOutFile = false;
public static void main(String[] args) {
commander = new Commander(args);
if (commander.hasArguments()) {
if (commander.getOutputFlag()) {
try {
outputStream = new FileOutputStream(commander.getOutputFileName());
} catch (FileNotFoundException e) {
System.out.print("Error opening output file" + commander.getOutputFileName()
+ "\nError was "+ e.getMessage());
System.exit(1);
}
}
if (commander.getFileFlag()) {
eventLog = openLog(commander.getInFileName());
}
if (commander.getAllFlag()) {
System.out.print("All option is not yet implemented");
System.exit(1);
}
if (commander.getContentFlag()) {
bContentFlag = true;
}
if (commander.getDiffFlag()) {
bEventFlag = true;
if(commander.getHexFlag()) {
bHexFlag=bHexEvent = bContentFlag = true;
}
String results = compareLogs (commander.getInFileName(),commander.getInFile2Name());
writeOut(results);
System.exit(0);
}
if (commander.getEventIdsFlag()) {
bEventFlag = true;
}
if (commander.getEventHexFlag()) {
bHexEvent = true;
}
if (commander.getPCRFlag()) {
bPcrFlag = true;
}
if (commander.getVerifyFile()) {
System.out.print("Verify option is not yet implemented");
System.exit(1);
}
if (commander.getHexFlag()) {
bHexFlag = true;
}
} else {
System.out.print("Nothing to do: No Parameters provided.");
System.exit(1);
} // End commander processing
try {
if (eventLog == null) {
eventLog = openLog("");
}
// Main Event processing
TCGEventLog evLog = new TCGEventLog(eventLog, bEventFlag, bContentFlag, bHexEvent);
// Check for pcr flag
if (bPcrFlag) {
String[] pcrs = evLog.getExpectedPCRValues();
int count = 0;
if(!commander.getHexFlag()) {
writeOut("Expected Platform Configuration Register (PCR) values"
+ " derived from the Event Log: \n\n");
}
for (String pcr: pcrs) {
if(count++ == commander.getPcrNumber() || (commander.getPcrNumber() == -1)) {
if(bHexFlag) {
writeOut(pcr.toString()+"\n");
} else {
writeOut(" pcr " + (count-1) + " = " + pcr.toString() + "\n");
}
}
}
if(!bHexFlag) {
writeOut("\n----------------- End PCR Values ----------------- \n\n");
}
}
// General event log output
if (bEventFlag) {
for (TpmPcrEvent event: evLog.getEventList()) {
if ((commander.getEventNumber() == event.getPcrIndex())|| commander.getEventNumber() == -1) {
if(bHexFlag) {
if(bEventFlag || bHexEvent) {
writeOut(HexUtils.byteArrayToHexString(event.getEvent())+ "\n");
}
if(bContentFlag) {
writeOut(HexUtils.byteArrayToHexString(event.getEventContent())+ "\n");
}
}
else {
writeOut(event.toString(bEventFlag, bContentFlag, bHexEvent) + "\n");
}
}
}
}
} catch (Exception e) {
System.out.print("Error processing Event Log " + commander.getInFileName()
+ "\nError was "+ e.toString());
System.exit(1);
}
}
/**
* Opens a TCG Event log file
* @param fileName Name of the log file. Will use a OS specific default file if none is supplied.
* @param os the name os of the current system
* @return a byte array holding the entire log
*/
public static byte[] openLog(String fileName) {
String os = System.getProperty("os.name").toLowerCase();
byte[] rawLog=null;
boolean bDefault = false;
try {
if (fileName == "") {
if (os.compareToIgnoreCase("linux")==0) { // need to find Windows path
fileName = "/sys/kernel/security/tpm0/binary_bios_measurements";
bDefault = true;
writeOut("Local Event Log being used: "+fileName +"\n");
}
}
Path path = Paths.get(fileName);
rawLog = Files.readAllBytes(path);
if(!commander.getHexFlag()) {
writeOut("TPM Event Log parser opening file:"+ path +"\n\n");
}
} catch (Exception e) {
String error = "Error reading event Log File: " + e.toString();
if (bDefault) {
error += "\nTry using the -f option to specify an Event Log File";
}
writeOut(error);
System.exit(1);
}
return rawLog;
}
/**
* Write data out to the system and/or a file.
* @param data
*/
private static void writeOut(String data) {
try {
data = data.replaceAll("[^\\P{C}\t\r\n]", ""); // remove any null characters that seem to upset text editors
if(commander.getOutputFlag()) {
outputStream.write(data.getBytes()); // Write to an output file
} else {
System.out.print(data); // output to the console
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Compares 2 Event Logs and returns a string based upon the results.
* Uses the Events digest field for comparisons.
* @param LogFileName1 Log file to use as a reference.
* @param LogFileName2 Log file to compare to the refernce.
* @return A sting containing human readable results.
*/
public static String compareLogs (String LogFileName1, String LogFileName2) {
TCGEventLog eventLog = null, eventLog2 = null;
byte[] evLog = openLog(LogFileName1);
byte[] evLog2 = openLog(LogFileName2);
StringBuilder sb = new StringBuilder();
try {
eventLog = new TCGEventLog(evLog);
} catch (Exception e) {
sb.append("Error processing event log " + LogFileName1 + " : " + e.getMessage());
return sb.toString();
} try {
eventLog2 = new TCGEventLog(evLog2);
ArrayList<TpmPcrEvent> errors = diffEventLogs(eventLog.getEventList(),
eventLog2.getEventList(), commander.getPcrNumber() );
if (errors.isEmpty() && !bHexFlag) {
sb.append("Event Log " + LogFileName1 + " MATCHED EventLog "+ LogFileName2);
} else {
if (!errors.isEmpty() && !bHexFlag) {
sb.append("Event Log " + LogFileName1
+ " did NOT match EventLog " + LogFileName2 + "\n");
sb.append("There were " + errors.size() + " event mismatches: \n\n");
}
for (TpmPcrEvent error : errors ) {
if(bHexFlag) {
if(bEventFlag || bHexEvent) {
writeOut(HexUtils.byteArrayToHexString(error.getEvent())+ "\n");
}
if(bContentFlag) {
writeOut(HexUtils.byteArrayToHexString(error.getEventContent())+ "\n");
}
}
else {
writeOut(error.toString(bEventFlag, bContentFlag, bHexEvent) + "\n");
}
}
}
} catch (Exception e) {
writeOut("Error processing event log " + LogFileName2 + " : " + e.getMessage());
}
return sb.toString();
}
/**
* Compare this event log against a second event log.
* Returns a String Array of event descriptions in which the digests from the first
* did no match the second. Return value is null if all events matched.
* @param eventList initial events
* @param eventList2 events to compare against
* @param pcr used as a filter. Use -1 to check all pcrs.
* @return array list of strings. Null of no events mismatched.
*/
public static ArrayList<TpmPcrEvent> diffEventLogs(ArrayList<TpmPcrEvent> eventList,
ArrayList<TpmPcrEvent> eventList2, int pcr) {
ArrayList<TpmPcrEvent> results= new ArrayList<TpmPcrEvent>();
for (TpmPcrEvent event2 : eventList2) {
if(pcr >= 0) {
if (event2.getPcrIndex() == pcr) {
if(!digestMatch(eventList,event2)) {
results.add(event2);
}
}
} else {
if(!digestMatch(eventList,event2)) {
results.add(event2);
}
}
}
return results;
}
/**
* Checks a digest from a single event against all digests with the same index in an Event Log.
* @param eventLog The Reference Event log.
* @param event single event to match.
* @return
*/
private static boolean digestMatch(final ArrayList<TpmPcrEvent> eventLog, final TpmPcrEvent event) {
boolean matchFound = false;
for (TpmPcrEvent event2 : eventLog) {
if((event.getPcrIndex() == event2.getPcrIndex())
&& (Arrays.equals(event.getEventDigest(), event2.getEventDigest()))) {
matchFound = true;
}
}
return matchFound;
}
}

View File

@ -1,143 +0,0 @@
package hirs.tcglp.utils;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import hirs.tpm.eventlog.TCGEventLog;
/**
* Command-line application for processing TCG Event Logs.
* Input arg: path to *.tcglp file
*
* If an argument is given it will be validated against the schema at http://standards.iso.org/iso/19770/-2/2015/schema.xsd
* If an argument is not given a SWID tag file will be generated.
*/
public class Main {
private static Commander commander = null;
static FileOutputStream outputStream = null;
static byte[] eventLlog = null;
static boolean bContentFlag, bEventFlag, bHexEvent, bOutFile = false;
public static void main(String[] args) {
commander = new Commander(args);
String os = System.getProperty("os.name").toLowerCase();
if (commander.hasArguments()) {
// we have arguments to work with
if (commander.getFileFlag()) {
eventLlog = openLog(commander.getInFileName());
} else {
eventLlog = openLog("");
}
if (commander.getAllFlag()) {
System.out.print("All option is not yet implemented");
System.exit(1);
}
if (commander.getPCRFlag()) {
try {
TCGEventLog tlp = new TCGEventLog(eventLlog, bEventFlag, bContentFlag, bHexEvent);
String[] pcrs = tlp.getExpectedPCRValues();
int i=0;
System.out.print("Platform Configuration Register (PCR) values: \n\n");
for (String pcr: pcrs) {
System.out.print(" pcr "+ i++ + " = " + pcr.toString() + "\n");
}
} catch (Exception e) {
System.out.print("Error processing Event Log " + commander.getInFileName()
+ "\nError was "+ e.toString());
System.exit(1);
}
System.out.print("\n----------------- End PCR Values ----------------- \n\n");
}
if (commander.getContentFlag()) {
bContentFlag = true;
}
if (commander.getHexFlag()) {
bHexEvent = true;
}
if (commander.getEventIdsFlag()) {
bEventFlag = true;
}
if (commander.getOutputFile()) {
try {
outputStream = new FileOutputStream(commander.getOutputFileName());
} catch (FileNotFoundException e) {
System.out.print("Error opening output file" + commander.getOutputFileName()
+ "\nError was "+ e.getMessage());
System.exit(1);
}
}
if (commander.getVerifyFile()) {
System.out.print("Verify option is not yet implemented");
System.exit(1);
}
} else {
System.out.print("Nothing to do: No Parameters provided.");
System.exit(1);
}
try {
TCGEventLog tlp = new TCGEventLog(eventLlog, bEventFlag, bContentFlag, bHexEvent);
writeOut(tlp.toString());
} catch (Exception e) {
System.out.print("Error processing Event Log " + commander.getInFileName()
+ "\nError was "+ e.toString());
System.exit(1);
}
}
/**
* Opens a TCG Event log file
* @param fileName Name of the log file. Will use a OS specific default file if none is supplied.
* @param os the name os of the current system
* @return a byte array holding the entire log
*/
public static byte[] openLog(String fileName) {
String os = System.getProperty("os.name").toLowerCase();
byte[] rawLog=null;
boolean bDefault = false;
try {
if (fileName == "") {
if (os.compareToIgnoreCase("linux")==0) { // need to find Windows path
fileName = "/sys/kernel/security/tpm0/binary_bios_measurements";
bDefault = true;
writeOut("Local Event Log being used: "+fileName +"\n");
}
}
Path path = Paths.get(fileName);
rawLog = Files.readAllBytes(path);
writeOut("TPM Event Log parser using file:"+ path +"\n\n");
} catch (Exception e) {
String error = "Error reading event Log File: " + e.toString();
if (bDefault) {
error += "\nTry using the -f option to specify an Event Log File";
}
writeOut(error);
System.exit(1);
}
return rawLog;
}
/**
* Write data out to the system and/or a file.
* @param data
*/
private static void writeOut(String data) {
try {
data = data.replaceAll("[^\\P{C}\t\r\n]", ""); // remove any null characters that seem to upset text editors
if(commander.getOutputFile()) outputStream.write(data.getBytes()); // Write to an output file
System.out.print(data); // output to the console
} catch (IOException e) {
e.printStackTrace();
}
}
}