added a eventcheck script to check and event log against a signed RIM

This commit is contained in:
iadgovuser26 2020-05-27 17:31:15 -04:00
parent 1cf1d4ec92
commit ff955bd499
19 changed files with 598 additions and 539 deletions

View File

@ -58,6 +58,8 @@ public final class TCGEventLog {
private boolean bHexEvent = false; private boolean bHexEvent = false;
/** Event Output Flag use. */ /** Event Output Flag use. */
private boolean bEvent = false; private boolean bEvent = false;
/** Event Output Flag use. */
private boolean bCryptoAgile = false;
/** /**
* Default blank object constructor. * Default blank object constructor.
*/ */
@ -96,7 +98,7 @@ public final class TCGEventLog {
final boolean bContentFlag, final boolean bHexEventFlag) final boolean bContentFlag, final boolean bHexEventFlag)
throws CertificateException, NoSuchAlgorithmException, IOException { throws CertificateException, NoSuchAlgorithmException, IOException {
boolean bCryptoAgile = isLogCrytoAgile(rawlog); bCryptoAgile = isLogCrytoAgile(rawlog);
if (bCryptoAgile) { if (bCryptoAgile) {
initValue = INIT_SHA256_LIST; initValue = INIT_SHA256_LIST;
algorithm = "TPM_ALG_SHA256"; algorithm = "TPM_ALG_SHA256";
@ -219,7 +221,14 @@ public final class TCGEventLog {
} }
return pcrs; return pcrs;
} }
/**
* Returns a flag which is set if the event log follows the "Crypto Agile" Format Type.
* A false implies the type is SHA1 format.
* @return true if log follows the Crypto Agile format.
*/
public boolean isCryptoAgile() {
return bCryptoAgile;
}
/** /**
* Returns a list of event found in the Event Log. * Returns a list of event found in the Event Log.
* @return an arraylist of event. * @return an arraylist of event.

View File

@ -7,4 +7,5 @@ include 'TPM_Utils',
'HIRS_AttestationCA', 'HIRS_AttestationCA',
'HIRS_AttestationCAPortal', 'HIRS_AttestationCAPortal',
'tpm_module', 'tpm_module',
'tools/tcg_rim_tool' 'tools/tcg_rim_tool',
'tools/tcg_eventlog_tool'

View File

@ -0,0 +1,79 @@
#!bin/bash
# outline:
# 1. Run the tcg_rim_tool to check the validity of the rim using cmd line
# 2. Run the event_log_tool diff cmdline
# 3. Output results
function eventcheck_help() {
echo "Event Check: Checks a TCG defined Event Log agianst a Integrity Reference Manifest for a Linux Device with a TPM 2.0"
echo "usage: eventcheck -r [file] - p [file] -s [file] -l [file]";
echo "Options"
echo "-r --rim <path> : Reference Integrity Manifest (RIM) <path> Reference Integrity Manifest (RIM) Base RIM file holding OEM product information.";
echo "-p --publicCertificate <path> : Public key certificate path used to validate the rim file.";
echo "-s --supportRim <path> : PC Client defined support RIM file holding the reference data provided by the OEM of the product.";
echo "-l --log <path> : Event Log of the device being tested. Will default to latest event log if parameter is not supplied.";
echo "-h --help : help listing";
}
while [[ "$#" -gt 0 ]]; do
case $1 in
-p|--publicCertificate) oem_cert="$2"; shift ;;
-r|--rim) oem_rim=$2; shift ;;
-s|--supportRim) support_rim=$2; shift ;;
-l|--log) event_log=$2; shift ;;
-h|--help) eventcheck_help; exit 0 ;;
*) echo "Unknown parameter passed: $1"; eventcheck_help; exit 1 ;;
esac
shift
done
# Check for required parameters
if ${oem_rim+"false"}; then
echo "Error: Base RIM file needs to be specified using the -r parameter";
echo "Exiting without processing.";
exit 1;
fi
if ${support_rim+"false"}; then
echo "Error: Support RIM file needs to be specified using the -s parameter";
echo "Exiting without processing.";
exit 1;
fi
if ${oem_cert+"false"}; then
echo "Error: OEM Public Key Certificate Chain file needs to be specified using the -p parameter";
echo "Exiting without processing.";
exit 1;
fi
# If event log not specified, then use the local devices log (if present)
if ${event_log+"false"}; then
ech0 "Event log not specified attempting to use local devices event log...";
event_log="/sys/kernel/security/tpm0/binary_bios_measurements";
if [ ! -f $event_log ]; then
kver=$(uname -r);
echo "Error opening default event log file, sudo may be required.";
echo " Note kernel version must be greater than 4.18 to produce an Event log. Current verion is $kver.";
echo "Exiting without processing.";
exit 1;
fi
fi
echo "OEM Certificate Chain = $oem_cert";
echo "Base RIM = $oem_rim";
echo "Support RIM = $support_rim";
echo "eventlog = $event_log";
echo "Checking the RIM signature and OEM Certificate Chain";
java -jar ../tcg_rim_tool/build/libs/tools/tcg_rim_tool-1.0.jar -v $oem_rim -p $oem_cert
if [ $? -ne 0 ]; then
exit 1;
fi
echo "Comparing RIM against the specified Event Log";
java -jar ../tcg_eventlog_tool/build/libs/tools/tcg_eventlog_tool-1.0.jar -d $support_rim $event_log
echo " ";
echo "Event Check against RIM complete"

View File

@ -0,0 +1,7 @@
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,55 @@
apply plugin: 'java'
apply plugin: 'findbugs'
apply plugin: 'checkstyle'
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
compile project(':HIRS_Utils')
compile libs.jcommander
compileOnly libs.checkstyle
compileOnly libs.findbugs
testCompile libs.testng
}
ext.configDir = new File(projectDir, 'config')
ext.checkstyleConfigDir = "$configDir/checkstyle"
checkstyle {
toolVersion = '5.7'
configFile = checkstyleConfigFile
configProperties.put('basedir', checkstyleConfigDir)
ignoreFailures = false
showViolations = true
}
ext.findbugsConfigDir = "$configDir/findbugs"
findbugs {
toolVersion = '3.0.0'
ignoreFailures = false
effort = 'max'
}
jar {
manifest {
attributes("Main-Class": "hirs.tcg_eventlog.Main",
"Class-Path": configurations.runtime.files.collect { "lib/$it.name" }.join(' ')
)
}
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {}
exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
}
uploadArchives {
repositories {
flatDir {
dirs "${buildDir}"
}
}
}

View File

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
<suppress files="Main.java" checks="HideUtilityClassConstructor" />
<suppress checks="MagicNumber" files=".*[/\\]src[/\\]test[/\\]+" />
<suppress checks="FinalParameters" files=".*[/\\]src[/\\]test[/\\]+" />
<suppress checks="JavadocPackage" files=".*[/\\]src[/\\]test[/\\]+" />
</suppressions>

Binary file not shown.

View File

@ -1,4 +1,4 @@
package hirs.tcg_eventlog_tool; package hirs.tcg_eventlog;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -12,7 +12,6 @@ public class Commander {
private static final String COMMAND_PREFIX = "-"; private static final String COMMAND_PREFIX = "-";
private static final String FULL_COMMAND_PREFIX = "--"; private static final String FULL_COMMAND_PREFIX = "--";
private static final String ALL_STRING = "all";
private static final String CONTENT_STRING = "contenthex"; private static final String CONTENT_STRING = "contenthex";
private static final String DIFF_STRING = "diff"; private static final String DIFF_STRING = "diff";
private static final String EVENTIDS_STRING = "event"; private static final String EVENTIDS_STRING = "event";
@ -27,7 +26,7 @@ public class Commander {
private static final String VERSION_NUMBER = "1.0"; private static final String VERSION_NUMBER = "1.0";
private boolean hasArguments = false; private boolean hasArguments = false;
private boolean bAll = false; private boolean bValidArgs = true;
private boolean bContentHex = false; private boolean bContentHex = false;
private boolean bDiff = false; private boolean bDiff = false;
private boolean bEventIds = false; private boolean bEventIds = false;
@ -37,6 +36,7 @@ public class Commander {
private boolean bOutput = false; private boolean bOutput = false;
private boolean bPCRs = false; private boolean bPCRs = false;
private boolean bVerify = false; private boolean bVerify = false;
private boolean bHelp = false;
private String inFile = ""; private String inFile = "";
private String inFile2 = ""; private String inFile2 = "";
@ -47,9 +47,9 @@ public class Commander {
private int eventNumber = -1; private int eventNumber = -1;
/** /**
* The main constructor for the Commander class * The main constructor for the Commander class.
* *
* @param args * @param args inout parameters
*/ */
public Commander(final String[] args) { public Commander(final String[] args) {
hasArguments = args.length > 0; hasArguments = args.length > 0;
@ -62,10 +62,10 @@ public class Commander {
} }
/** /**
* This method is called if an empty Commander was created, and later gets * This method is called if an empty Commander was created, and later gets args.
* args. Will be used by the main constructor. * Will be used by the main constructor.
* *
* @param args * @param args input parameters
*/ */
public final void parseArguments(final String[] args) { public final void parseArguments(final String[] args) {
String tempValue; String tempValue;
@ -74,17 +74,13 @@ public class Commander {
tempValue = args[i]; tempValue = args[i];
switch (tempValue) { switch (tempValue) {
case FULL_COMMAND_PREFIX + ALL_STRING:
case COMMAND_PREFIX + "a":
bAll = true;
break;
case FULL_COMMAND_PREFIX + CONTENT_STRING: case FULL_COMMAND_PREFIX + CONTENT_STRING:
case FULL_COMMAND_PREFIX + EVENTIDS_STRING: case FULL_COMMAND_PREFIX + EVENTIDS_STRING:
case COMMAND_PREFIX + "e": case COMMAND_PREFIX + "e":
if (i<args.length-1) { // Check for a filter following the -e on the command line if (i < args.length - 1) { // Check for a filter following the -e
if (!args[i + 1].startsWith("-")) { if (!args[i + 1].startsWith("-")) {
eventFilter = args[i++ + 1]; eventFilter = args[i++ + 1];
eventNumber = new Integer(eventFilter).intValue(); eventNumber = Integer.parseInt(eventFilter);
} }
} }
bEventIds = true; bEventIds = true;
@ -98,17 +94,19 @@ public class Commander {
break; break;
case FULL_COMMAND_PREFIX + DIFF_STRING: case FULL_COMMAND_PREFIX + DIFF_STRING:
case COMMAND_PREFIX + "d": case COMMAND_PREFIX + "d":
if ((args.length < i+3)||(args[i+1].charAt(0)=='-')||(args[i+2].charAt(0)=='-')){ if ((args.length < i + 2 + 1) || (args[i + 1].charAt(0) == '-')
System.out.print("tcg_eventlog_tool command line error: 2 or 3 parameters needed for -diff.\n"); || (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.out.print("usage: elt -d logFile1 logFile2 pcr#");
System.exit(0); bValidArgs = false;
} else { } else {
inFile = args[i++ + 1]; inFile = args[i++ + 1];
inFile2 = args[i++ + 1]; inFile2 = args[i++ + 1];
if (args.length > i + 1) { if (args.length > i + 1) {
if (!args[i + 1].contains("-")) { // pcr filter provided if (!args[i + 1].contains("-")) { // pcr filter provided
eventFilter = args[i++ + 1]; eventFilter = args[i++ + 1];
eventNumber = new Integer(eventFilter).intValue(); eventNumber = Integer.parseInt(eventFilter);
} }
} }
bDiff = true; bDiff = true;
@ -121,22 +119,22 @@ public class Commander {
break; break;
case FULL_COMMAND_PREFIX + OUTPUT_STRING: case FULL_COMMAND_PREFIX + OUTPUT_STRING:
case COMMAND_PREFIX + "o": case COMMAND_PREFIX + "o":
if (i<args.length-1) { // Check for a filter following the -p on the command line if (i < args.length - 1) { // Check for a filter following the -o
if (!args[i + 1].startsWith("-")) { if (!args[i + 1].startsWith("-")) {
outFile = args[i++ + 1]; outFile = args[i++ + 1];
} else { } else {
System.out.print("no output file specified with -o option"); System.out.print("no output file specified with -o option");
System.exit (1); bValidArgs = false;
} }
} }
bOutput = true; bOutput = true;
break; break;
case FULL_COMMAND_PREFIX + PCR_STRING: case FULL_COMMAND_PREFIX + PCR_STRING:
case COMMAND_PREFIX + "p": case COMMAND_PREFIX + "p":
if (i<args.length-1) { // Check for a filter following the -p on the command line if (i < args.length - 1) { // Check for a filter following the -p
if (!args[i + 1].startsWith("-")) { if (!args[i + 1].startsWith("-")) {
pcrFilter = args[i++ + 1 ]; pcrFilter = args[i++ + 1 ];
pcrNumber = new Integer(pcrFilter).intValue(); pcrNumber = Integer.parseInt(pcrFilter);
} }
} }
bPCRs = true; bPCRs = true;
@ -144,7 +142,7 @@ public class Commander {
case FULL_COMMAND_PREFIX + VERSION_STRING: case FULL_COMMAND_PREFIX + VERSION_STRING:
case COMMAND_PREFIX + "v": case COMMAND_PREFIX + "v":
System.out.print("TCG Event Log Parser version " + VERSION_NUMBER); System.out.print("TCG Event Log Parser version " + VERSION_NUMBER);
System.exit (0); bValidArgs = false;
break; break;
case FULL_COMMAND_PREFIX + VERIFY_STRING: case FULL_COMMAND_PREFIX + VERIFY_STRING:
case COMMAND_PREFIX + "V": case COMMAND_PREFIX + "V":
@ -155,9 +153,12 @@ public class Commander {
bHex = true; bHex = true;
break; break;
case FULL_COMMAND_PREFIX + HELP_STRING: case FULL_COMMAND_PREFIX + HELP_STRING:
bHelp = true;
break;
case COMMAND_PREFIX + "h": case COMMAND_PREFIX + "h":
default: default:
printHelp(""); printHelp("");
bValidArgs = false;
} }
} }
} }
@ -175,10 +176,16 @@ public class Commander {
* Getter for the input All flag. * Getter for the input All flag.
* @return true if the All flag was set. * @return true if the All flag was set.
*/ */
public final boolean getAllFlag() { public final boolean getValidityFlag() {
return bAll; return bValidArgs;
}
/**
* Getter for the help flag.
* @return true if the Help flag was set.
*/
public final boolean getHelpFlag() {
return bHelp;
} }
/** /**
* Getter for the input associated with the PCR flag. * Getter for the input associated with the PCR flag.
* @return true if the PCR Flag was set. * @return true if the PCR Flag was set.
@ -212,7 +219,7 @@ public class Commander {
/** /**
* Getter for the input associated with the EventIds flag. * Getter for the input associated with the EventIds flag.
* @return true of EventIds Falg was set. * @return true of EventIds Flag was set.
*/ */
public final boolean getEventIdsFlag() { public final boolean getEventIdsFlag() {
return bEventIds; return bEventIds;
@ -220,14 +227,14 @@ public class Commander {
/** /**
* Getter for the input associated with the File flag. * Getter for the input associated with the File flag.
* @return true if File Flage was set. * @return true if File Flag was set.
*/ */
public final boolean getFileFlag() { public final boolean getFileFlag() {
return bFile; return bFile;
} }
/** /**
* Getter for the input associated with the diff flag. * Getter for the input associated with the diff flag.
* @return * @return true if the diff flag was set
*/ */
public final boolean getDiffFlag() { public final boolean getDiffFlag() {
return bDiff; return bDiff;
@ -235,7 +242,7 @@ public class Commander {
/** /**
* Getter for the input associated with the Verify flag. * Getter for the input associated with the Verify flag.
* @return * @return true if the verify flag was set
*/ */
public final boolean getVerifyFile() { public final boolean getVerifyFile() {
return bVerify; return bVerify;
@ -297,14 +304,14 @@ public class Commander {
return pcrNumber; return pcrNumber;
} }
/** /**
* This method is used to inform the user of the allowed functionality of * This method is used to inform the user of the allowed functionality of the program.
* the program. * @param message message caller specific message to print before listing the help.
*/ */
private void printHelp(String message) { public final void printHelp(final String message) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String os = System.getProperty("os.name").toLowerCase(); String os = System.getProperty("os.name").toLowerCase();
if (message != null && !message.isEmpty()) { if ((message != null) && (!message.isEmpty())) {
sb.append(String.format("ERROR: %s\n\n", message)); sb.append("\n\n" + message);
} }
sb.append("\nTCG Log Parser "); sb.append("\nTCG Log Parser ");
if (os.compareToIgnoreCase("linux") == 0) { if (os.compareToIgnoreCase("linux") == 0) {
@ -317,10 +324,12 @@ public class Commander {
+ "\n\t\t\t Following parameter MUST be a path and file name." + "\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 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" + "\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. " + " -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" + "\n\t\t\t Following optional parameter is a single pcr id used to filter"
+ " the output." + " the output."
+ "\n\t\t\t All events will be displayed if the optional parameter is not provided.\n" + "\n\t\t\t All events will be displayed if the optional parameter is not +"
+ "provided.\n"
+ " -ec\t--contenthex\t Displays event content" + " -ec\t--contenthex\t Displays event content"
+ " in eventhex format when -event is used.\n" + " in eventhex format when -event is used.\n"
+ " -ex\t--eventhex\t Displays event in hex format when -event is used" + " -ex\t--eventhex\t Displays event in hex format when -event is used"
@ -334,20 +343,22 @@ public class Commander {
+ "\n\t\t\t Following parameter MAY be a PCR number used to specify a single pcr." + "\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" + "\n\t\t\t No following parameters will display all PCRs.\n"
+ " -v\t--version\t Parser Version.\n" + " -v\t--version\t Parser Version.\n"
// + " -V\t--Verify\t Attempts to verify the log file against values on the local device." // + " -V\t--Verify\t Attempts to verify the log file against values."
+ " -x\t--hex\t\t Displays output in hex format." + " -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 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\t\t\t All output will be human readble form if not present."
+ "\n"); + "\n\n");
if (os.compareToIgnoreCase("linux") == 0) { if (os.compareToIgnoreCase("linux") == 0) {
sb.append("\nIf no FILE parameter is provided then the standard Linux TCGEventLog path " 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(/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" + "\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" + "All OPTIONS must be seperated by a space delimiter, no concatenation"
+ " of OPTIONS is currently supported.\n" + " of OPTIONS is currently supported.\n"
+ "\nExamples: (run from the script directory)\n" + "\nExamples: (run from the script directory)\n"
+ "1. Display all events from the binary_bios_measurements.bin test pattern:\n" + "1. Display all events from the binary_bios_measurements.bin test pattern:\n"
+" sh elt.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" + "2. Display only the event with an index of 0 (e.g event that extend PCR 0):\n"
+ " sh scripts/elt.sh -f " + " sh scripts/elt.sh -f "
+ "../test/testdata/binary_bios_measurements_Dell_Fedora30.bin -p 0\n" + "../test/testdata/binary_bios_measurements_Dell_Fedora30.bin -p 0\n"
@ -368,19 +379,21 @@ public class Commander {
); );
} }
System.out.println(sb.toString()); System.out.println(sb.toString());
System.exit(1);
} }
/** /**
* Checks that the file given to create a new swidtag is a valid path. * Checks that the file path is a valid.
* @param filepath * @param filepath file path of file to check
* @return * @return true if path is valid
*/ */
public static boolean isValidPath(String filepath) { public static boolean isValidPath(final String filepath) {
try { try {
System.out.println("Checking for a valid creation path..."); System.out.println("Checking for a valid creation path...");
File file = new File(filepath); File file = new File(filepath);
file.createNewFile(); boolean test = file.createNewFile();
if (!test) {
return false;
}
} catch (IOException | InvalidPathException | NullPointerException ex) { } catch (IOException | InvalidPathException | NullPointerException ex) {
return false; return false;
} }

View File

@ -0,0 +1,313 @@
package hirs.tcg_eventlog;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
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
*/
final class Main {
private static Commander commander = null;
private static FileOutputStream outputStream = null;
private static byte[] eventLog = null;
private static boolean bContentFlag, bEventFlag, bHexEvent, bHexFlag, bPcrFlag = false;
/**
* Main Constructor.
* @param args command line parameters.
*/
public static void main(final String[] args) {
commander = new Commander(args);
if (!commander.getValidityFlag()) {
System.out.print("Program exiting wihtout processs due to issues with"
+ " parameters provided.");
System.exit(1);
}
if (commander.hasArguments()) {
if (commander.getHelpFlag()) {
commander.printHelp("");
System.exit(1);
}
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.getContentFlag()) {
bContentFlag = true;
}
if (commander.getDiffFlag()) {
bEventFlag = 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);
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) {
if (!bHexFlag) {
if (evLog.isCryptoAgile()) {
writeOut("\nEvent Log follows the \"Crypto Agile\" format and has "
+ evLog.getEventList().size() + " events:\n\n");
} else {
writeOut("\nEvent Log follows the \"SHA1\" format and has "
+ evLog.getEventList().size() + " events:\n\n");
}
}
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 (IOException i) {
System.out.print("IO error processing Event Log " + commander.getInFileName()
+ "\nError was " + i.toString());
System.exit(1);
} catch (CertificateException c) {
System.out.print("Certificate error processing Event Log " + commander.getInFileName()
+ "\nError was " + c.toString());
System.exit(1);
} catch (NoSuchAlgorithmException a) {
System.out.print("Algorithm error processing Event Log " + commander.getInFileName()
+ "\nError was " + a.toString());
System.exit(1);
}
}
/**
* Opens a TCG Event log file.
* @param fileName Name of the log file. Will use a OS specific default.
* @return a byte array holding the entire log
*/
public static byte[] openLog(final String fileName) {
String os = System.getProperty("os.name").toLowerCase(), fName = fileName;
byte[] rawLog = null;
boolean bDefault = false;
try {
if (fileName.isEmpty()) {
if (os.compareToIgnoreCase("linux") == 0) { // need to find Windows path
fName = "/sys/kernel/security/tpm0/binary_bios_measurements";
bDefault = true;
writeOut("Local Event Log being used: " + fileName + "\n");
}
}
Path path = Paths.get(fName);
rawLog = Files.readAllBytes(path);
if (!commander.getHexFlag()) {
writeOut("tcg_eventlog_tool is opening file:" + path + "\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(final String data) {
try {
String dataNoNull = data.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
if (commander.getOutputFlag()) {
outputStream.write(dataNoNull.getBytes(Charset.forName("UTF-8")));
} else {
System.out.print(dataNoNull); // 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 reference.
* @return A sting containing human readable results.
*/
public static String compareLogs(final String logFileName1, final String logFileName2) {
TCGEventLog eventLog1 = null, eventLog2 = null;
byte[] evLog = openLog(logFileName1);
byte[] evLog2 = openLog(logFileName2);
StringBuilder sb = new StringBuilder();
try {
eventLog1 = new TCGEventLog(evLog);
} catch (Exception e) {
sb.append("\nError processing event log " + logFileName1 + " : " + e.getMessage());
return sb.toString();
}
try {
eventLog2 = new TCGEventLog(evLog2);
ArrayList<TpmPcrEvent> errors = diffEventLogs(eventLog1.getEventList(),
eventLog2.getEventList(), commander.getPcrNumber());
if (errors.isEmpty() && !bHexFlag) {
sb.append("\nEvent Log " + logFileName1 + " MATCHED EventLog " + logFileName2);
} else {
if (!errors.isEmpty() && !bHexFlag) {
sb.append("\nEvent 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) {
sb.append(HexUtils.byteArrayToHexString(error.getEvent()) + "\n");
}
if (bContentFlag) {
sb.append(HexUtils.byteArrayToHexString(error.getEventContent())
+ "\n");
}
} else {
sb.append(error.toString(bEventFlag, bContentFlag, bHexEvent) + "\n");
}
}
}
} catch (IOException i) {
System.out.print("IO error processing Event Log " + commander.getInFileName()
+ "\nError was " + i.toString());
System.exit(1);
} catch (CertificateException c) {
System.out.print("Certificate error processing Event Log " + commander.getInFileName()
+ "\nError was " + c.toString());
System.exit(1);
} catch (NoSuchAlgorithmException a) {
System.out.print("Algorithm error processing Event Log " + commander.getInFileName()
+ "\nError was " + a.toString());
System.exit(1);
}
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(final ArrayList<TpmPcrEvent> eventList,
final ArrayList<TpmPcrEvent> eventList2, final 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

@ -0,0 +1,5 @@
/**
* Base package that includes common exceptions, interfaces and base implementations for and related
* to the ACA.
*/
package hirs.tcg_eventlog;

View File

@ -18,25 +18,17 @@ F9MDKy55mXkxb/Z5RUC3IKqsoz+EuKjs6d+yhtb1EQtpJD2dZj23+VjMH4gXxEerDNR1PiPhma/i
QMFa1hwSO7AuasYPy0WCRIgrJ5ZL5x2ZoaSIdE2TsCqnStVL+KLZeMWNCqw4k89hsuELW7Azrl57 QMFa1hwSO7AuasYPy0WCRIgrJ5ZL5x2ZoaSIdE2TsCqnStVL+KLZeMWNCqw4k89hsuELW7Azrl57
Vm2qzPok0svrB1K4QyZdyK2bnG1QY3Fip5Jdmg==</SignatureValue> Vm2qzPok0svrB1K4QyZdyK2bnG1QY3Fip5Jdmg==</SignatureValue>
<KeyInfo> <KeyInfo>
<X509Data> <KeyName>2fdeb8e7d030a2209daa01861a964fedecf2bcc1</KeyName>
<X509SubjectName>CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US</X509SubjectName> <KeyValue>
<X509Certificate>MIIDYTCCAkmgAwIBAgIJAPB+r6VBhBn4MA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAlVTMQsw <RSAKeyValue>
CQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxEjAQBgNVBAMM <Modulus>p3WVYaRJG7EABjbAdqDYZXFSTV1nHY9Ol9A5+W8t5xwBXBryZCGWxERGr5AryKWPxd+qzjj+cFpx
CUV4YW1wbGVDQTAeFw0yMDAyMTAxODE1MzRaFw0yOTEyMTkxODE1MzRaMFwxCzAJBgNVBAYTAlVT xkM6N18jEhQIx/CEZePEJqpluBO5w2wTEOe7hqtMatqgDDMeDRxUuIpP8LGP00vh1wyDFFew90d9
MQswCQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxGzAZBgNV dvT3bcLvFh3a3ap9bTm6aBqPup5CXpzrwIU2wZfgkDytYVBm+8bHkMaUrgpNyM+5BAg2zl/Fqw0q
BAMMEmV4YW1wbGUuUklNLnNpZ25lcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKd1 otjaGr7PzbH+urCvaGbKLMPoWkVLIgAE8Qw98HTfoYSFHC7VYQySrzIinaOBFSgViR72kHemH2lW
lWGkSRuxAAY2wHag2GVxUk1dZx2PTpfQOflvLeccAVwa8mQhlsRERq+QK8ilj8Xfqs44/nBaccZD jDQeHiY0VIoPik/jVVIpjWe6zzeZ2S66Q/LmjQ==</Modulus>
OjdfIxIUCMfwhGXjxCaqZbgTucNsExDnu4arTGraoAwzHg0cVLiKT/Cxj9NL4dcMgxRXsPdHfXb0 <Exponent>AQAB</Exponent>
923C7xYd2t2qfW05umgaj7qeQl6c68CFNsGX4JA8rWFQZvvGx5DGlK4KTcjPuQQINs5fxasNKqLY </RSAKeyValue>
2hq+z82x/rqwr2hmyizD6FpFSyIABPEMPfB036GEhRwu1WEMkq8yIp2jgRUoFYke9pB3ph9pVow0 </KeyValue>
Hh4mNFSKD4pP41VSKY1nus83mdkuukPy5o0CAwEAAaMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMC
BsAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAGuJ+dasb3/Mb7TBJ1Oe
al5ISq8d2LQD5ke5qnjgSQWKXfQ9fcUy3dWnt3Oked/i8B/Tyk3jCdTZJU3J3iRNgTqFfMLP8rU1
w2tPYBjjuPKiiK4YRBHPxtFxPdOL1BPmL4ZzNs33Lv6H0m4aff9p6QpMclX5b/CRjl+80JWRLiLj
U3B0CejZB9dJrPr9SBaC31cDoeTpja9Cl86ip7KkqrZZIYeMuNF6ucWyWtjrW2kr3UhmEy8x/6y4
KigsK8sBwmNv4N2Pu3RppeIcpjYj5NVA1hwRA4eeMgJp2u+urm3l1oo1UNX1HsSSBHp1Owc9zZLm
07Pl8T46kpIA4sroCAU=</X509Certificate>
</X509Data>
</KeyInfo> </KeyInfo>
</Signature> </Signature>
</SoftwareIdentity> </SoftwareIdentity>

View File

@ -0,0 +1,7 @@
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,157 +0,0 @@
task wrapper(type: Wrapper) {
gradleVersion = '2.10'
}
allprojects {
task addPlugins << {
delete './build/plugins'
mkdir './build/plugins'
if (project.hasProperty('pluginDir')) {
if (pluginDir?.trim()) {
copy {
from "$pluginDir"
into 'build/plugins'
include '*.jar'
include '**/*.jar'
}
}
}
}
task copyVersion() {
doLast {
if (project.hasProperty('displayVersion')) {
String resourceDir="${buildDir}/resources/main"
println "setting app version file contents of: ${displayVersion} to ${resourceDir}"
new File(resourceDir, "VERSION").write("$displayVersion")
}
}
}
group = 'hirs'
version = file("$rootDir/VERSION").text.trim() + "-SNAPSHOT"
}
subprojects {
apply plugin: 'java'
apply plugin: 'maven-publish'
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-Werror"
}
repositories {
mavenCentral()
}
test {
testLogging {
exceptionFormat = 'full'
}
}
tasks.withType(Test) {
useTestNG() {
includeGroups = project.ext.includeGroups.split()
excludeGroups = project.ext.excludeGroups.split()
}
afterSuite { desc, result ->
if (desc.parent == null) {
logger.lifecycle("${result.successfulTestCount}/${result.testCount} tests passed")
}
}
}
tasks.withType(FindBugs) {
reports {
xml.enabled = false
html.enabled = true
}
}
tasks.withType(Pmd) {
reports {
xml.enabled = false
html.enabled = true
}
}
publishing {
repositories {
if(findProperty("env") != null && findProperty("env") == "CI") {
maven {
url "$rootDir/librepo"
}
} else {
mavenLocal()
}
}
}
// Global checkstyle file
ext.checkstyleConfigFile = new File(rootDir, "/config/checkstyle/sun_checks.xml")
// Version definitions of all of the libraries we're using. They're defined
// here to ensure that all projects are using the same versions of common
// dependencies:
ext.libs = [
bouncy_castle: 'org.bouncycastle:bcmail-jdk15on:1.59',
checkstyle: 'com.puppycrawl.tools:checkstyle:8.10.1',
commons_cli: 'commons-cli:commons-cli:1.2',
commons_codec: 'commons-codec:commons-codec:1.9',
commons_csv: 'org.apache.commons:commons-csv:1.4',
commons_exec: 'org.apache.commons:commons-exec:1.3',
commons_http: 'commons-httpclient:commons-httpclient:3.1',
commons_io: 'commons-io:commons-io:2.4',
commons_lang: 'org.apache.commons:commons-lang3:3.3.2',
commons_upload:'commons-fileupload:commons-fileupload:1.3.1',
commons_valid: 'commons-validator:commons-validator:1.4.0',
findbugs: 'com.google.code.findbugs:findbugs:3.0.0',
gson: 'com.google.code.gson:gson:2.2.4',
guava: 'com.google.guava:guava:18.0',
hibernate: [ 'org.hibernate.common:hibernate-commons-annotations:4.0.4.Final',
'org.hibernate:hibernate-core:4.3.11.Final',
'org.hibernate:hibernate-hikaricp:4.3.11.Final'],
hikari: 'com.zaxxer:HikariCP:2.4.1',
hsqldb: 'org.hsqldb:hsqldb:2.3.2',
http: 'org.apache.httpcomponents:httpclient:4.5',
jackson: [ 'com.fasterxml.jackson.core:jackson-core:2.6.3',
'com.fasterxml.jackson.core:jackson-databind:2.6.3',
'com.fasterxml.jackson.core:jackson-annotations:2.6.3'],
jadira_usertype: 'org.jadira.usertype:usertype.core:4.0.0.GA',
jcommander: 'com.beust:jcommander:1.35',
joda_time: 'joda-time:joda-time:2.9.4',
jstl: [ 'org.apache.taglibs:taglibs-standard-impl:1.2.5',
'org.apache.taglibs:taglibs-standard-spec:1.2.5'],
log4j2: [ 'org.apache.logging.log4j:log4j-api:2.8.1',
'org.apache.logging.log4j:log4j-core:2.8.1',
'org.apache.logging.log4j:log4j-slf4j-impl:2.8.1'],
log4j2_web: 'org.apache.logging.log4j:log4j-web:2.8.1',
log_bridge: 'org.apache.logging.log4j:log4j-jcl:2.8.1',
mockito: 'org.mockito:mockito-all:1.10.19',
mariadb: 'org.mariadb.jdbc:mariadb-java-client:2.2.1',
minimal_json: 'com.eclipsesource.minimal-json:minimal-json:0.9.5',
pci_ids: 'com.github.marandus:pci-ids:0.3',
pmd: 'net.sourceforge.pmd:pmd:5.1.1',
powermock: [ 'org.powermock:powermock-core:1.6.3',
'org.powermock:powermock-api-mockito:1.6.3',
'org.powermock:powermock-module-testng:1.6.3' ],
protobuf_java: 'com.google.protobuf:protobuf-java:3.4.0',
reflections: 'org.reflections:reflections:0.9.9-RC1',
servlet_api: 'javax.servlet:servlet-api:2.5',
slf4j: 'org.slf4j:slf4j-api:1.7.13',
spring_core: ['org.springframework:spring-aop:4.2.3.RELEASE',
'org.springframework:spring-beans:4.2.3.RELEASE',
'org.springframework:spring-context:4.2.3.RELEASE',
'org.springframework:spring-expression:4.2.3.RELEASE',
'org.springframework:spring-orm:4.2.3.RELEASE'],
spring_msg: 'org.springframework:spring-messaging:4.2.3.RELEASE',
spring_plugin: 'org.springframework.plugin:spring-plugin-core:1.2.0.RELEASE',
spring_retry: 'org.springframework.retry:spring-retry:1.2.0.RELEASE',
spring_test: 'org.springframework:spring-test:4.2.3.RELEASE',
spring_web: 'org.springframework:spring-web:4.2.3.RELEASE',
spring_webmvc: 'org.springframework:spring-webmvc:4.2.3.RELEASE',
testng: 'org.testng:testng:6.8.8',
xml_rpc_client: 'org.apache.xmlrpc:xmlrpc-client:3.1.3',
]
}

View File

@ -1,277 +0,0 @@
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;
}
}