mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-21 13:57:56 +00:00
Merge pull request #253 from nsacyber/issue-252
[#252] eventcheck script
This commit is contained in:
commit
7597fc8717
@ -64,6 +64,8 @@ public final class TCGEventLog {
|
||||
private boolean bHexEvent = false;
|
||||
/** Event Output Flag use. */
|
||||
private boolean bEvent = false;
|
||||
/** Event Output Flag use. */
|
||||
private boolean bCryptoAgile = false;
|
||||
/**
|
||||
* Default blank object constructor.
|
||||
*/
|
||||
@ -102,7 +104,7 @@ public final class TCGEventLog {
|
||||
final boolean bContentFlag, final boolean bHexEventFlag)
|
||||
throws CertificateException, NoSuchAlgorithmException, IOException {
|
||||
|
||||
boolean bCryptoAgile = isLogCrytoAgile(rawlog);
|
||||
bCryptoAgile = isLogCrytoAgile(rawlog);
|
||||
if (bCryptoAgile) {
|
||||
initValue = INIT_SHA256_LIST;
|
||||
algorithm = "TPM_ALG_SHA256";
|
||||
@ -236,7 +238,14 @@ public final class TCGEventLog {
|
||||
}
|
||||
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.
|
||||
* @return an arraylist of event.
|
||||
|
@ -63,8 +63,9 @@ public class EvEfiBootServicesApp {
|
||||
System.arraycopy(bootServices, UefiConstants.OFFSET_16, linkTimeAddress, 0,
|
||||
UefiConstants.SIZE_8);
|
||||
System.arraycopy(bootServices, UefiConstants.SIZE_24, lengthBytes, 0, UefiConstants.SIZE_8);
|
||||
if (imageLength != 0) {
|
||||
// if (imageLength != 0) {
|
||||
devicePathLength = HexUtils.leReverseInt(lengthBytes);
|
||||
if (devicePathLength != 0) {
|
||||
byte[] devPathBytes = new byte[devicePathLength];
|
||||
System.arraycopy(bootServices, UefiConstants.SIZE_32, devPathBytes,
|
||||
0, devicePathLength);
|
||||
@ -126,7 +127,7 @@ public class EvEfiBootServicesApp {
|
||||
if (devicePathValid) {
|
||||
info += "\n" + devPath.toString();
|
||||
} else {
|
||||
info += "\n Error processing device path" + "\n";
|
||||
info += "\n No uefi device paths were specified";
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
@ -7,4 +7,5 @@ include 'TPM_Utils',
|
||||
'HIRS_AttestationCA',
|
||||
'HIRS_AttestationCAPortal',
|
||||
'tpm_module',
|
||||
'tools/tcg_rim_tool'
|
||||
'tools/tcg_rim_tool',
|
||||
'tools/tcg_eventlog_tool'
|
79
tools/scripts/eventcheck.sh
Normal file
79
tools/scripts/eventcheck.sh
Normal 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"
|
7
tools/scripts/identity_transform.xslt
Normal file
7
tools/scripts/identity_transform.xslt
Normal 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>
|
55
tools/tcg_eventlog_tool/build.gradle
Normal file
55
tools/tcg_eventlog_tool/build.gradle
Normal 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}"
|
||||
}
|
||||
}
|
||||
}
|
12
tools/tcg_eventlog_tool/config/checkstyle/suppressions.xml
Normal file
12
tools/tcg_eventlog_tool/config/checkstyle/suppressions.xml
Normal 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>
|
BIN
tools/tcg_eventlog_tool/libs/HIRS_Utils-1.1.1.jar
Normal file
BIN
tools/tcg_eventlog_tool/libs/HIRS_Utils-1.1.1.jar
Normal file
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
package hirs.tcg_eventlog_tool;
|
||||
package hirs.tcg_eventlog;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -12,7 +12,6 @@ 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 = "contenthex";
|
||||
private static final String DIFF_STRING = "diff";
|
||||
private static final String EVENTIDS_STRING = "event";
|
||||
@ -27,7 +26,7 @@ public class Commander {
|
||||
private static final String VERSION_NUMBER = "1.0";
|
||||
|
||||
private boolean hasArguments = false;
|
||||
private boolean bAll = false;
|
||||
private boolean bValidArgs = true;
|
||||
private boolean bContentHex = false;
|
||||
private boolean bDiff = false;
|
||||
private boolean bEventIds = false;
|
||||
@ -37,6 +36,7 @@ public class Commander {
|
||||
private boolean bOutput = false;
|
||||
private boolean bPCRs = false;
|
||||
private boolean bVerify = false;
|
||||
private boolean bHelp = false;
|
||||
|
||||
private String inFile = "";
|
||||
private String inFile2 = "";
|
||||
@ -47,9 +47,9 @@ public class Commander {
|
||||
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) {
|
||||
hasArguments = args.length > 0;
|
||||
@ -62,10 +62,10 @@ public class Commander {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called if an empty Commander was created, and later gets
|
||||
* args. Will be used by the main constructor.
|
||||
* This method is called if an empty Commander was created, and later gets args.
|
||||
* Will be used by the main constructor.
|
||||
*
|
||||
* @param args
|
||||
* @param args input parameters
|
||||
*/
|
||||
public final void parseArguments(final String[] args) {
|
||||
String tempValue;
|
||||
@ -74,17 +74,13 @@ public class Commander {
|
||||
tempValue = args[i];
|
||||
|
||||
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 + 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();
|
||||
if (i < args.length - 1) { // Check for a filter following the -e
|
||||
if (!args[i + 1].startsWith("-")) {
|
||||
eventFilter = args[i++ + 1];
|
||||
eventNumber = Integer.parseInt(eventFilter);
|
||||
}
|
||||
}
|
||||
bEventIds = true;
|
||||
@ -98,17 +94,19 @@ public class Commander {
|
||||
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");
|
||||
if ((args.length < i + 2 + 1) || (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);
|
||||
bValidArgs = false;
|
||||
} 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();
|
||||
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 = Integer.parseInt(eventFilter);
|
||||
}
|
||||
}
|
||||
bDiff = true;
|
||||
@ -121,22 +119,22 @@ public class Commander {
|
||||
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];
|
||||
if (i < args.length - 1) { // Check for a filter following the -o
|
||||
if (!args[i + 1].startsWith("-")) {
|
||||
outFile = args[i++ + 1];
|
||||
} else {
|
||||
System.out.print("no output file specified with -o option");
|
||||
System.exit (1);
|
||||
bValidArgs = false;
|
||||
}
|
||||
}
|
||||
bOutput = true;
|
||||
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();
|
||||
if (i < args.length - 1) { // Check for a filter following the -p
|
||||
if (!args[i + 1].startsWith("-")) {
|
||||
pcrFilter = args[i++ + 1 ];
|
||||
pcrNumber = Integer.parseInt(pcrFilter);
|
||||
}
|
||||
}
|
||||
bPCRs = true;
|
||||
@ -144,7 +142,7 @@ public class Commander {
|
||||
case FULL_COMMAND_PREFIX + VERSION_STRING:
|
||||
case COMMAND_PREFIX + "v":
|
||||
System.out.print("TCG Event Log Parser version " + VERSION_NUMBER);
|
||||
System.exit (0);
|
||||
bValidArgs = false;
|
||||
break;
|
||||
case FULL_COMMAND_PREFIX + VERIFY_STRING:
|
||||
case COMMAND_PREFIX + "V":
|
||||
@ -155,15 +153,18 @@ public class Commander {
|
||||
bHex = true;
|
||||
break;
|
||||
case FULL_COMMAND_PREFIX + HELP_STRING:
|
||||
bHelp = true;
|
||||
break;
|
||||
case COMMAND_PREFIX + "h":
|
||||
default:
|
||||
printHelp("");
|
||||
bValidArgs = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 command line.
|
||||
*
|
||||
* @return true if any arguments were passed in.
|
||||
*/
|
||||
@ -175,10 +176,16 @@ public class Commander {
|
||||
* Getter for the input All flag.
|
||||
* @return true if the All flag was set.
|
||||
*/
|
||||
public final boolean getAllFlag() {
|
||||
return bAll;
|
||||
public final boolean getValidityFlag() {
|
||||
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.
|
||||
* @return true if the PCR Flag was set.
|
||||
@ -212,7 +219,7 @@ public class Commander {
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
return bEventIds;
|
||||
@ -220,14 +227,14 @@ public class Commander {
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
return bFile;
|
||||
}
|
||||
/**
|
||||
* Getter for the input associated with the diff flag.
|
||||
* @return
|
||||
* @return true if the diff flag was set
|
||||
*/
|
||||
public final boolean getDiffFlag() {
|
||||
return bDiff;
|
||||
@ -235,7 +242,7 @@ public class Commander {
|
||||
|
||||
/**
|
||||
* Getter for the input associated with the Verify flag.
|
||||
* @return
|
||||
* @return true if the verify flag was set
|
||||
*/
|
||||
public final boolean getVerifyFile() {
|
||||
return bVerify;
|
||||
@ -297,17 +304,17 @@ public class Commander {
|
||||
return pcrNumber;
|
||||
}
|
||||
/**
|
||||
* This method is used to inform the user of the allowed functionality of
|
||||
* the program.
|
||||
* This method is used to inform the user of the allowed functionality of 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();
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (message != null && !message.isEmpty()) {
|
||||
sb.append(String.format("ERROR: %s\n\n", message));
|
||||
if ((message != null) && (!message.isEmpty())) {
|
||||
sb.append("\n\n" + message);
|
||||
}
|
||||
sb.append("\nTCG Log Parser ");
|
||||
if (os.compareToIgnoreCase("linux")==0) {
|
||||
if (os.compareToIgnoreCase("linux") == 0) {
|
||||
sb.append("Usage: sh elt.sh [OPTION]...-f [FILE]...\n");
|
||||
} else {
|
||||
sb.append("Usage: ./elt.ps1 [OPTION]...-f [FILE]...\n");
|
||||
@ -317,10 +324,12 @@ public class Commander {
|
||||
+ "\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. "
|
||||
+ " -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"
|
||||
+ "\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"
|
||||
@ -334,53 +343,57 @@ public class Commander {
|
||||
+ "\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."
|
||||
// + " -V\t--Verify\t Attempts to verify the log file against values."
|
||||
+ " -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) {
|
||||
+ "\n\t\t\t All output will be human readble form if not present."
|
||||
+ "\n\n");
|
||||
if (os.compareToIgnoreCase("linux") == 0) {
|
||||
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"
|
||||
+ "\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"
|
||||
+"\nExamples: (run from the script directory)\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"
|
||||
+"2. Display only the event with an index of 0 (e.g event that extend PCR 0):\n"
|
||||
+" sh scripts/elt.sh -f "
|
||||
+ "\nExamples: (run from the script directory)\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"
|
||||
+ "2. Display only the event with an index of 0 (e.g event that extend PCR 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"
|
||||
+"\n Note admin privileges may be required (e.g. run as Administrator).\n"
|
||||
+"All OPTIONS must be seperated by a space delimiter, "
|
||||
+ "\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"
|
||||
+"\nExamples:(run from the script directory)\n"
|
||||
+"1. Display all events from the binary_bios_measurements.bin test pattern:\n"
|
||||
+" ./elt.ps1 -f "
|
||||
+ "\nExamples:(run from the script directory)\n"
|
||||
+ "1. Display all events from the binary_bios_measurements.bin test pattern:\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"
|
||||
+" ./elt.ps1 -f "
|
||||
+ "2. Display only the event with an index of 0 (e.g event that extend PCR 0):\n"
|
||||
+ " ./elt.ps1 -f "
|
||||
+ "..\\test\\testdata\\binary_bios_measurements_Dell_Fedora30.bin -p 0\n"
|
||||
);
|
||||
}
|
||||
System.out.println(sb.toString());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the file given to create a new swidtag is a valid path.
|
||||
* @param filepath
|
||||
* @return
|
||||
* Checks that the file path is a valid.
|
||||
* @param filepath file path of file to check
|
||||
* @return true if path is valid
|
||||
*/
|
||||
public static boolean isValidPath(String filepath) {
|
||||
public static boolean isValidPath(final String filepath) {
|
||||
try {
|
||||
System.out.println("Checking for a valid creation path...");
|
||||
File file = new File(filepath);
|
||||
file.createNewFile();
|
||||
boolean test = file.createNewFile();
|
||||
if (!test) {
|
||||
return false;
|
||||
}
|
||||
} catch (IOException | InvalidPathException | NullPointerException ex) {
|
||||
return false;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Base package that includes common exceptions, interfaces and base implementations for and related
|
||||
* to the ACA.
|
||||
*/
|
||||
package hirs.tcg_eventlog;
|
@ -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',
|
||||
]
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user