Merge pull request #248 from nsacyber/issue-245

[#245] TCG Event Log - Event Processing
This commit is contained in:
iadgovuser26 2020-05-15 11:39:12 -04:00 committed by GitHub
commit 2ccd3a180e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1874 additions and 228 deletions

View File

@ -13,7 +13,8 @@ import java.nio.file.NoSuchFileException;
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.Arrays;
import java.util.HashMap;
import java.util.List;
@ -106,9 +107,12 @@ public class ReferenceManifestDetailsPageController
* @param referenceManifestManager the reference manifest manager.
* @return mapping of the RIM information from the database.
* @throws java.io.IOException error for reading file bytes.
* @throws NoSuchAlgorithmException If an unknown Algorithm is encountered.
* @throws CertificateException if a certificate doesn't parse.
*/
public static HashMap<String, Object> getRimDetailInfo(final UUID uuid,
final ReferenceManifestManager referenceManifestManager) throws IOException {
final ReferenceManifestManager referenceManifestManager) throws IOException,
CertificateException, NoSuchAlgorithmException {
HashMap<String, Object> data = new HashMap<>();
ReferenceManifest rim = ReferenceManifest

View File

@ -1,94 +1,84 @@
package hirs.tpm.eventlog;
import hirs.utils.HexUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import hirs.tpm.eventlog.events.EvConstants;
import hirs.utils.HexUtils;
/**
* Class for handling different formats of TCG Event logs.
*/
public class TCGEventLog {
public final class TCGEventLog {
private static final Logger LOGGER
= LogManager.getLogger(TCGEventLog.class);
// private static final Logger LOGGER = (Logger) LogManager.getLogger(TCGEventLog.class);
/**
* Init value for SHA 256 values.
*/
/** Initial value for SHA 256 values.*/
public static final String INIT_SHA256_LIST = "00000000000000000000000000"
+ "00000000000000000000000000000000000000";
/**
* Init value for SHA 1 values.
*/
/** Initial value for SHA 1 values. */
public static final String INIT_SHA1_LIST = "0000000000000000000000000000000000000000";
/**
* PFP defined EV_NO_ACTION identifier.
*/
/** PFP defined EV_NO_ACTION identifier. */
public static final int NO_ACTION_EVENT = 0x00000003;
/**
* String value of SHA1 hash.
*/
/** String value of SHA1 hash.*/
public static final String HASH_STRING = "SHA1";
/**
* String value of SHA256 hash.
*/
/** String value of SHA256 hash. */
public static final String HASH256_STRING = "SHA-256";
/**
* Each PCR bank holds 24 registers.
*/
/** Each PCR bank holds 24 registers. */
public static final int PCR_COUNT = 24;
/**
* 2 dimensional array holding the PCR values.
*/
private final byte[][] pcrList;
/**
* List of parsed events within the log.
*/
private final ArrayList<TpmPcrEvent> eventList = new ArrayList<>();
/** 2 dimensional array holding the PCR values. */
private byte[][] pcrList;
/** List of parsed events within the log. */
private ArrayList<TpmPcrEvent> eventList = new ArrayList<>();
/** Length of PCR. Indicates which hash algorithm is used. */
private int pcrLength;
/** Name of hash algorithm. */
private String hashType;
/** Initial Value to use. */
private String initValue;
/**
* Default blank object constructor.
*/
public TCGEventLog() {
this.pcrList = new byte[PCR_COUNT][TpmPcrEvent.SHA1_LENGTH];
this.pcrList = new byte[PCR_COUNT][EvConstants.SHA1_LENGTH];
initValue = INIT_SHA1_LIST;
pcrLength = TpmPcrEvent.SHA1_LENGTH;
pcrLength = EvConstants.SHA1_LENGTH;
initPcrList();
}
/**
* Default constructor for just the rawlog that'll set up SHA1 Log.
* @param rawlog data for the event log file
* @throws IOException IO Stream for the event log
* @param rawlog data for the event log file.
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
* @throws CertificateException if a certificate in the log cannot be parsed.
* @throws IOException IO Stream if event cannot be parsed.
*/
public TCGEventLog(final byte[] rawlog) throws IOException {
this(rawlog, TpmPcrEvent.SHA1_LENGTH, HASH_STRING, INIT_SHA1_LIST);
public TCGEventLog(final byte[] rawlog) throws CertificateException, NoSuchAlgorithmException,
IOException {
this(rawlog, EvConstants.SHA1_LENGTH, HASH_STRING, INIT_SHA1_LIST);
}
/**
* Default constructor for specific log.
* @param rawlog data for the event log file
* @param pcrLength determined by SHA1 or 256
* @param hashType the type of algorithm
* @param initValue the default blank value
* @param pLength determined by SHA1 or 256
* @param hType the type of algorithm
* @param iValue the default blank value.
* @throws IOException IO Stream for the event log
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
* @throws CertificateException f a certificate in the log cannot be parsed.
*/
public TCGEventLog(final byte[] rawlog, final int pcrLength,
final String hashType, final String initValue) throws IOException {
this.pcrLength = pcrLength;
public TCGEventLog(final byte[] rawlog, final int pLength, final String hType,
final String iValue) throws IOException, CertificateException,
NoSuchAlgorithmException {
pcrLength = pLength;
this.pcrList = new byte[PCR_COUNT][pcrLength];
this.hashType = hashType;
this.initValue = initValue;
hashType = hType;
initValue = iValue;
ByteArrayInputStream is = new ByteArrayInputStream(rawlog);
// Process the 1st entry as a SHA1 format (per the spec)
eventList.add(new TpmPcrEvent1(is));
@ -132,7 +122,7 @@ public class TCGEventLog {
0, currentEvent.getDigestLength());
}
} catch (NoSuchAlgorithmException e) {
LOGGER.error(e);
// ((org.apache.logging.log4j.Logger) LOGGER).error(e);
}
}
}
@ -176,4 +166,5 @@ public class TCGEventLog {
public String getExpectedPCRValue(final int index) {
return HexUtils.byteArrayToHexString(pcrList[index]);
}
}

View File

@ -3,9 +3,13 @@ package hirs.tpm.eventlog;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import hirs.data.persist.TPMMeasurementRecord;
import hirs.data.persist.TpmWhiteListBaseline;
import hirs.tpm.eventlog.events.EvConstants;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.utils.HexUtils;
import hirs.data.persist.Digest;
import hirs.data.persist.DigestAlgorithm;;
@ -16,22 +20,16 @@ import hirs.data.persist.DigestAlgorithm;;
* Constructor parses the input byte array into a List of TpmPcrEvents.
*/
public class TCGEventLogProcessor {
/**
* Name of the hash algorithm used to process the Event Log, default is SHA256.
*/
/** Name of the hash algorithm used to process the Event Log, default is SHA256. */
private String algorithm = "TPM_ALG_SHA256";
/**
* Parsed event log array.
*/
/** Parsed event log array. */
private TCGEventLog tcgLog = null;
/**
* EV_NO_ACTION signature offset.
*/
/** EV_NO_ACTION signature offset. */
private static final int SIG_OFFSET = 32;
/**
* TEV_NO_ACTION signature size.
*/
/** TEV_NO_ACTION signature size. */
private static final int SIG_SIZE = 16;
/** Number of PCRs in a TPM PCR Bank. */
private static final int PCR_COUNT = 24;
/**
* Default Constructor.
@ -43,12 +41,15 @@ public class TCGEventLogProcessor {
/**
* Constructor.
*
* @param rawLog the byte array holding the contents of the TCG Event Log
* @throws IOException if there is a parsing error
* @param rawLog the byte array holding the contents of the TCG Event Log.
* @throws IOException IO Stream for the event log.
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
* @throws CertificateException f a certificate in the log cannot be parsed.
*/
public TCGEventLogProcessor(final byte[] rawLog) throws IOException {
public TCGEventLogProcessor(final byte[] rawLog) throws IOException, CertificateException,
NoSuchAlgorithmException {
if (isLogCrytoAgile(rawLog)) {
tcgLog = new TCGEventLog(rawLog, TpmPcrEvent.SHA256_LENGTH,
tcgLog = new TCGEventLog(rawLog, EvConstants.SHA256_LENGTH,
TCGEventLog.HASH256_STRING, TCGEventLog.INIT_SHA256_LIST);
} else {
tcgLog = new TCGEventLog(rawLog);
@ -104,7 +105,7 @@ public class TCGEventLogProcessor {
TpmWhiteListBaseline baseline = new TpmWhiteListBaseline(name);
TPMMeasurementRecord record;
String pcrValue;
for (int i = 0; i < TpmPcrEvent.PCR_COUNT; i++) {
for (int i = 0; i < PCR_COUNT; i++) {
if (algorithm.compareToIgnoreCase("TPM_ALG_SHA1") == 0) { // Log Was SHA1 Format
pcrValue = tcgLog.getExpectedPCRValue(i);
byte[] hexValue = HexUtils.hexStringToByteArray(pcrValue);
@ -127,11 +128,11 @@ public class TCGEventLogProcessor {
*
* @param log The Event Log
* @return true if EfiSpecIDEvent is found and indicates that the format is crypto agile
* @throws UnsupportedEncodingException
* @throws UnsupportedEncodingException if parsing error occurs.
*/
private boolean isLogCrytoAgile(final byte[] log) throws UnsupportedEncodingException {
byte[] eType = new byte[TpmPcrEvent.INT_LENGTH];
System.arraycopy(log, TpmPcrEvent.INT_LENGTH, eType, 0, TpmPcrEvent.INT_LENGTH);
public boolean isLogCrytoAgile(final byte[] log) throws UnsupportedEncodingException {
byte[] eType = new byte[UefiConstants.SIZE_4];
System.arraycopy(log, UefiConstants.SIZE_4, eType, 0, UefiConstants.SIZE_4);
byte[] eventType = HexUtils.leReverseByte(eType);
int eventID = new BigInteger(eventType).intValue();
if (eventID != TCGEventLog.NO_ACTION_EVENT) {

View File

@ -15,63 +15,36 @@ import hirs.utils.HexUtils;
* } TPMT_HA;
*/
public class TcgTpmtHa {
/**
* TCG Defined Algorithm Identifiers .
*/
/** TCG Defined Algorithm Identifiers. */
private int hashAlgId = 0;
/**
* Length of the hash.
*/
/** Length of the hash. */
private int hashLength = 0;
/**
* Human readable name of the hash algorithm.
*/
/** Human readable name of the hash algorithm. */
private String hashName = "";
/**
* Hash data.
*/
/** Hash data. */
private byte[] digest = null;
/**
* TCG ID for SHA1.
*/
/** TCG ID for SHA1. */
public static final int TPM_ALG_SHA1 = 0x04;
/**
* TCG ID for SHA1.
*/
/** TCG ID for SHA1. */
public static final int TPM_ALG_SHA256 = 0x0B;
/**
* TCG ID for SHA 384.
*/
/** * TCG ID for SHA 384. */
public static final int TPM_ALG_SHA384 = 0x0C;
/**
* TCG ID for SHA512.
*/
/** TCG ID for SHA512. */
public static final int TPM_ALG_SHA_512 = 0x0D;
/**
* TCG ID for Null algorithm.
*/
/** TCG ID for Null algorithm. */
public static final int TPM_ALG_NULL = 0x10;
/**
* TCG ID for SHA1.
*/
/** TCG ID for SHA1. */
public static final int TPM_ALG_SHA1_LENGTH = 20;
/**
* TCG ID for SHA1.
*/
/** TCG ID for SHA1. */
public static final int TPM_ALG_SHA256_LENGTH = 32;
/**
* TCG ID for SHA 384.
*/
/** TCG ID for SHA 384. */
public static final int TPM_ALG_SHA384_LENGTH = 48;
/**
* TCG ID for SHA512.
*/
/** TCG ID for SHA512. */
public static final int TPM_ALG_SHA512_LENGTH = 64;
/**
* TCG ID for Null algorithm.
*/
/** TCG ID for Null algorithm. */
public static final int TPM_ALG_NULL_LENGTH = 0;
/** buffer to hold the structure. */
private byte[] buffer = null;
/**
* Constructor.
*
@ -87,6 +60,9 @@ public class TcgTpmtHa {
hashLength = tcgAlgLength(algID[0]);
digest = new byte[hashLength];
is.read(digest);
buffer = new byte[algID.length + digest.length];
System.arraycopy(algID, 0, buffer, 0, algID.length);
System.arraycopy(digest, 0, buffer, algID.length, digest.length);
}
/**
@ -98,6 +74,14 @@ public class TcgTpmtHa {
return hashAlgId;
}
/**
* Returns the contents of the TPMT_HA structure buffer.
* @return contents of the TPMT_HA structure.
*/
public byte[] getBuffer() {
return java.util.Arrays.copyOf(buffer, buffer.length);
}
/**
* Return the length of the Hash.
*

View File

@ -3,7 +3,26 @@ package hirs.tpm.eventlog;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import hirs.tpm.eventlog.events.EvConstants;
import hirs.tpm.eventlog.events.EvCompactHash;
import hirs.tpm.eventlog.events.EvEfiBootServicesApp;
import hirs.tpm.eventlog.events.EvEfiGptPartition;
import hirs.tpm.eventlog.events.EvEfiHandoffTable;
import hirs.tpm.eventlog.events.EvEfiSpecIdEvent;
import hirs.tpm.eventlog.events.EvEventTag;
import hirs.tpm.eventlog.events.EvIPL;
import hirs.tpm.eventlog.events.EvNoAction;
import hirs.tpm.eventlog.events.EvPostCode;
import hirs.tpm.eventlog.events.EvSCrtmContents;
import hirs.tpm.eventlog.events.EvSCrtmVersion;
import hirs.tpm.eventlog.uefi.UefiFirmware;
import hirs.tpm.eventlog.uefi.UefiVariable;
import hirs.utils.HexUtils;
/**
@ -11,71 +30,49 @@ import hirs.utils.HexUtils;
* TCG_PCR_EVENT is used when the Event log uses the SHA1 Format as described in the
* TCG Platform Firmware Profile (PFP) specification.
* typedef struct {
* TCG_PCRINDEX PCRIndex; //PCR Index value that either
* //matches the PCRIndex of a
* //previous extend operation or
* //indicates that this Event Log
* //entry is not associated with
* //an extend operation
* TCG_EVENTTYPE EventType; //See Log event types defined in toStrng()
* TCG_DIGEST digest; //The hash of the event data
* UINT32 EventSize; //Size of the event data
* UINT8 Event[EventSize]; //The event data
* TCG_PCRINDEX PCRIndex; //PCR Index value that either
* //matches the PCRIndex of a
* //previous extend operation or
* //indicates that this Event Log
* //entry is not associated with
* //an extend operation
* TCG_EVENTTYPE EventType; //See Log event types defined in toStrng()
* TCG_DIGEST digest; //The hash of the event data
* UINT32 EventSize; //Size of the event data
* UINT8 Event[EventSize]; //The event data
* } TCG_PCR_EVENT;
*/
public class TpmPcrEvent {
/**
* Type length = 4 bytes.
*/
public static final int EV_TYPE_SIZE = 4;
/**
* Event Log spec version.
*/
public static final int MIN_SIZE = 32;
/**
* Event Type (byte array).
*/
public static final int INT_LENGTH = 4;
/**
* Event Type (byte array).
*/
public static final int SHA1_LENGTH = 20;
/**
* Event Type (byte array).
*/
public static final int SHA256_LENGTH = 32;
/**
* Each PCR bank holds 24 registers.
*/
public static final int PCR_COUNT = 24;
/**
* PCR index.
*/
/** Log format. SHA1=1, Crytpo agile=2. */
private int logFormat = -1;
/** PCR index. */
private int pcrIndex = -1;
/**
* Event Type (long).
*/
/** Event Type (long). */
private long eventType = 0;
/**
* Event digest.
*/
/** Event digest. */
private byte[] digest = null;
/**
* Even data.
*/
/** Even content data. */
private byte[] eventContent;
/**
* TCG Event Log spec version.
*/
private static String version = "Unknown";
/**
* TCG Event Log errata version.
*/
private static String errata = "Unknown";
/**
* Length (in bytes) of a pcr.
*/
/** TCG Event Log spec version. */
private String version = "Unknown";
/** TCG Event Log errata version. */
private String errata = "Unknown";
/** Length (in bytes) of a pcr. */
private int digestLength = 0;
/** Event Number. */
private int eventNumber = 1;
/** Index. */
private int index = -1;
/** Event Contents flag. */
private boolean bEvContent = false;
/** Event hash for SHA1 event logs. */
private byte[] eventDataSha1hash;
/** Event hash for Crypto Agile events. */
private byte[] eventDataSha256hash;
/** Signature extension mask.*/
private static final long SIGN_MASK = 0x00000000FFFFFFFFL;
/** Mask used to remove upper values from a long. */
private static final long INT_MASK = 0x000000007FFFFFFFL;
/**
* Constructor.
@ -128,14 +125,30 @@ public class TpmPcrEvent {
return pcrIndex;
}
/** Sets the Log Format for this TCG Event.
* 1 = SHA1 Format, 2 = Crypto Agile format.
* @param format indicates log format.
*/
protected void setLogFormat(final int format) {
logFormat = format;
}
/**
* Gets the Log Format for this TCG Event.
* 1 = SHA1 Format, 2 = Crypto Agile format.
* @return number representing the format.
*/
public int getLogFormat() {
return logFormat;
}
/**
* Sets the EventType.
*
* @param type byte array holding the PFP defined log event type
*/
protected void setEventType(final byte[] type) {
byte[] evType = HexUtils.leReverseByte(type);
eventType = new BigInteger(evType).longValue();
eventType = new BigInteger(HexUtils.leReverseByte(type)).longValue();
}
/**
@ -183,8 +196,8 @@ public class TpmPcrEvent {
*
* @return byte array holding the events content field
*/
protected byte[] getEventContent() {
return eventContent;
public byte[] getEventContent() {
return java.util.Arrays.copyOf(eventContent, eventContent.length);
}
/**
@ -205,4 +218,262 @@ public class TpmPcrEvent {
public int getDigestLength() {
return digestLength;
}
/**
* Parses the event content and creates a human readable description of each event.
* @param event the byte array holding the event data.
* @param eventContent the byte array holding the event content.
* @return String description of the event.
* @throws CertificateException if the event contains an event that cannot be processed.
* @throws NoSuchAlgorithmException if an event contains an unsupported algorithm.
* @throws IOException if the event cannot be parsed.
*/
public String processEvent(final byte[] event, final byte[] eventContent)
throws CertificateException, NoSuchAlgorithmException, IOException {
String description = "";
int eventID = (int) eventType;
description += "Event# " + eventNumber++ + ": ";
description += "Index PCR[" + this.index + "]\n";
description += "Event Type: 0x" + this.eventType + " " + eventString(eventID);
description += "\n";
if (logFormat == 1) { // Digest
description += "digest (SHA-1): " + HexUtils.byteArrayToHexString(this.digest) + "\n";
} else {
description += "digest (SHA256): " + HexUtils.byteArrayToHexString(this.digest) + "\n";
}
// Calculate both the SHA1 and SHA256 on the event since this will equal the digest
// field of about half the log messages.
MessageDigest md1 = MessageDigest.getInstance("SHA-1");
md1.update(event);
eventDataSha1hash = md1.digest();
MessageDigest md2 = MessageDigest.getInstance("SHA-256");
md2.update(event);
eventDataSha256hash = md2.digest();
switch (eventID) {
case EvConstants.EV_PREBOOT_CERT:
description += " EV_PREBOOT_CERT" + "\n";
break;
case EvConstants.EV_POST_CODE:
EvPostCode postCode = new EvPostCode(eventContent);
description += "Event Content:\n" + postCode.toString() + "\n";
break;
case EvConstants.EV_UNUSED:
break;
case EvConstants.EV_NO_ACTION:
EvNoAction noAction = new EvNoAction(eventContent);
description += "Event Content:\n" + noAction.toString();
if (noAction.isSpecIDEvent()) {
EvEfiSpecIdEvent specID = noAction.getEvEfiSpecIdEvent();
version = specID.getVersionMajor() + "." + specID.getVersionMinor();
errata = specID.getErrata();
}
break;
case EvConstants.EV_SEPARATOR:
if (EvPostCode.isAscii(eventContent)) {
String seperatorEventData = new String(eventContent, StandardCharsets.UTF_8);
if (!this.isEmpty(eventContent)) {
description += "Seperator event content = " + seperatorEventData + "\n";
}
}
description += eventHashCheck();
break;
case EvConstants.EV_ACTION:
description += "Event Content:\n"
+ new String(eventContent, StandardCharsets.UTF_8) + "\n";
description += eventHashCheck();
break;
case EvConstants.EV_EVENT_TAG:
EvEventTag eventTag = new EvEventTag(eventContent);
description += eventTag.toString() + "\n";
description += eventHashCheck();
break;
case EvConstants.EV_S_CRTM_CONTENTS:
EvSCrtmContents sCrtmContents = new EvSCrtmContents(eventContent);
description += "Event Content:\n " + sCrtmContents.toString() + "\n";
break;
case EvConstants.EV_S_CRTM_VERSION:
EvSCrtmVersion sCrtmVersion = new EvSCrtmVersion(eventContent);
description += "Event Content:\n" + sCrtmVersion.toString() + "\n";
description += eventHashCheck();
break;
case EvConstants.EV_CPU_MICROCODE:
break;
case EvConstants.EV_PLATFORM_CONFIG_FLAGS:
description += eventHashCheck();
break;
case EvConstants.EV_TABLE_OF_DEVICES:
break;
case EvConstants.EV_COMPACT_HASH:
EvCompactHash compactHash = new EvCompactHash(eventContent);
description += "Event Content:\n" + compactHash.toString() + "\n";
description += eventHashCheck();
break;
case EvConstants.EV_IPL:
EvIPL ipl = new EvIPL(eventContent);
description += "Event Content:\n" + ipl.toString() + "\n";
break;
case EvConstants.EV_IPL_PARTITION_DATA:
break;
case EvConstants.EV_NONHOST_CODE:
break;
case EvConstants.EV_NONHOST_CONFIG:
break;
case EvConstants.EV_NONHOST_INFO:
break;
case EvConstants.EV_EV_OMIT_BOOT_DEVICES_EVENTS:
break;
case EvConstants.EV_EFI_EVENT_BASE:
break;
case EvConstants.EV_EFI_VARIABLE_DRIVER_CONFIG:
UefiVariable efiVar = new UefiVariable(eventContent);
description += "Event Content:\n" + efiVar.toString();
description += eventHashCheck();
break;
case EvConstants.EV_EFI_VARIABLE_BOOT:
description += "Event Content:\n" + new UefiVariable(eventContent).toString();
description += eventHashCheck();
break;
case EvConstants.EV_EFI_BOOT_SERVICES_APPLICATION:
EvEfiBootServicesApp bootServices = new EvEfiBootServicesApp(eventContent);
description += "Event Content:\n" + bootServices.toString();
break;
case EvConstants.EV_EFI_BOOT_SERVICES_DRIVER: // same as EV_EFI_BOOT_SERVICES_APP
EvEfiBootServicesApp bootDriver = new EvEfiBootServicesApp(eventContent);
description += "Event Content:\n" + bootDriver.toString();
break;
case EvConstants.EV_EFI_RUNTIME_SERVICES_DRIVER:
break;
case EvConstants.EV_EFI_GPT_EVENT:
description += "Event Content:\n" + new EvEfiGptPartition(eventContent).toString();
description += eventHashCheck();
break;
case EvConstants.EV_EFI_ACTION:
description += new String(eventContent, StandardCharsets.UTF_8) + "\n";
description += eventHashCheck();
break;
case EvConstants.EV_EFI_PLATFORM_FIRMWARE_BLOB:
description += "Event Content:\n"
+ new UefiFirmware(eventContent).toString() + "\n";
break;
case EvConstants.EV_EFI_HANDOFF_TABLES:
EvEfiHandoffTable efiTable = new EvEfiHandoffTable(eventContent);
description += "Event Content:\n" + efiTable.toString();
break;
case EvConstants.EV_EFI_HCRTM_EVENT:
break;
case EvConstants.EV_EFI_VARIABLE_AUTHORITY:
description += "Event Content:\n" + new UefiVariable(eventContent).toString();
break;
default: description += " Unknown Event found" + "\n";
}
if (bEvContent) {
description += "Event content (Hex) (" + event.length + "): "
+ HexUtils.byteArrayToHexString(eventContent) + "\n\n";
}
return description;
}
/**
* Converts the Event ID into a String As defined in the TCG PC Client FW Profile.
* Event IDs have values larger than an integer,so a Long is used hold the value.
* @param event the event id.
* @return TCG defined String that represents the event id
*/
private static String eventString(final long event) {
String evString = "";
long tmpEvent = event;
Long longEvent = Long.valueOf(tmpEvent & SIGN_MASK); // Remove signed extension
Long intEvent = Long.valueOf(tmpEvent & INT_MASK); // truncate to an int value
// Check to see if value is larger than an int, if it is then truncate the value
if (longEvent.longValue() > (long) Integer.MAX_VALUE) {
switch (intEvent.intValue()) {
case EvConstants.EV_EFI_EVENT_BASE: evString = "EV_EFI_EVENT_BASE"; break;
case EvConstants.EV_EFI_VARIABLE_DRIVER_CONFIG:
evString = "EV_EFI_VARIABLE_DRIVER_CONFIG"; break;
case EvConstants.EV_EFI_VARIABLE_BOOT:
evString = "EV_EFI_VARIABLE_BOOT"; break;
case EvConstants.EV_EFI_BOOT_SERVICES_APPLICATION:
evString = "EV_EFI_BOOT_SERVICES_APPLICATION"; break;
case EvConstants.EV_EFI_BOOT_SERVICES_DRIVER:
evString = "EV_EFI_BOOT_SERVICES_DRIVER"; break;
case EvConstants.EV_EFI_RUNTIME_SERVICES_DRIVER:
evString = "EV_EFI_RUNTIME_SERVICES_DRIVER"; break;
case EvConstants.EV_EFI_GPT_EVENT: evString = "EV_EFI_GPT_EVENT"; break;
case EvConstants.EV_EFI_ACTION: evString = "EV_EFI_ACTION"; break;
case EvConstants.EV_EFI_PLATFORM_FIRMWARE_BLOB:
evString = "EV_EFI_PLATFORM_FIRMWARE_BLOB"; break;
case EvConstants.EV_EFI_HANDOFF_TABLES: evString = "EV_EFI_HANDOFF_TABLES"; break;
case EvConstants.EV_EFI_HCRTM_EVENT: evString = "EV_EFI_HCRTM_EVENT"; break;
case EvConstants.EV_EFI_VARIABLE_AUTHORITY:
evString = "EV_EFI_VARIABLE_AUTHORITY"; break;
default: evString = "Unknown Event ID " + event + " encountered";
}
} else {
switch (intEvent.intValue()) {
case EvConstants.EV_PREBOOT_CERT: evString = "EV_PREBOOT_CERT"; break;
case EvConstants.EV_POST_CODE: evString = "EV_POST_CODE"; break;
case EvConstants.EV_UNUSED: evString = "EV_Unused"; break;
case EvConstants.EV_NO_ACTION: evString = "EV_NO_ACTION"; break;
case EvConstants.EV_SEPARATOR: evString = "EV_SEPARATOR"; break;
case EvConstants.EV_ACTION: evString = "EV_ACTION"; break;
case EvConstants.EV_EVENT_TAG: evString = "EV_EVENT_TAG"; break;
case EvConstants.EV_S_CRTM_CONTENTS: evString = "EV_S_CRTM_CONTENTS"; break;
case EvConstants.EV_S_CRTM_VERSION: evString = "EV_S_CRTM_VERSION"; break;
case EvConstants.EV_CPU_MICROCODE: evString = "EV_CPU_MICROCODE"; break;
case EvConstants.EV_PLATFORM_CONFIG_FLAGS: evString = "EV_PLATFORM_CONFIG_FLAGS ";
break;
case EvConstants.EV_TABLE_OF_DEVICES: evString = "EV_TABLE_OF_DEVICES"; break;
case EvConstants.EV_COMPACT_HASH: evString = "EV_COMPACT_HASH"; break;
case EvConstants.EV_IPL: evString = "EV_IPL"; break;
case EvConstants.EV_IPL_PARTITION_DATA: evString = "EV_IPL_PARTITION_DATA"; break;
case EvConstants.EV_NONHOST_CODE: evString = "EV_NONHOST_CODE"; break;
case EvConstants.EV_NONHOST_CONFIG: evString = "EV_NONHOST_CONFIG"; break;
case EvConstants.EV_NONHOST_INFO: evString = "EV_NONHOST_INFO"; break;
case EvConstants.EV_EV_OMIT_BOOT_DEVICES_EVENTS:
evString = "EV_EV_OMIT_BOOT_DEVICES_EVENTS"; break;
default: evString = "Unknown Event ID " + event + " encountered";
}
}
return evString;
}
/**
* Human readable output of a check of input against the current event hash.
* @return human readable string.
*/
private String eventHashCheck() {
String result = "";
if (logFormat == 1) {
if (Arrays.equals(this.digest, eventDataSha1hash)) { result
+= "Event digest matched hash of the event data " + "\n";
} else {
result += "Event digest DID NOT match the hash of the event data :"
+ HexUtils.byteArrayToHexString(getEventDigest()) + "\n";
}
} else {
if (Arrays.equals(this.digest, eventDataSha256hash)) {
result += "Event digest matched hash of the event data " + "\n";
} else {
result += "Event digest DID NOT match the hash of the event data :"
+ HexUtils.byteArrayToHexString(getEventDigest()) + "\n";
}
}
return result;
}
/**
* Checks a byte array for all zeros.
* @param array holds data to check.
* @return true of all zeros are found.
*/
public boolean isEmpty(final byte[] array) {
for (int i = 0; i < array.length; i++) {
if (array[i] != 0) {
return false;
}
}
return true;
}
}

View File

@ -1,9 +1,13 @@
package hirs.tpm.eventlog;
import hirs.tpm.eventlog.events.EvConstants;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.utils.HexUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
/**
* Class to process a TCG_PCR_EVENT.
@ -27,25 +31,52 @@ public class TpmPcrEvent1 extends TpmPcrEvent {
/**
* Constructor.
*
* @param is ByteArrayInputStream holding the TCG Log event
* @throws IOException if an error occurs in parsing the event
* @param is ByteArrayInputStream holding the TCG Log event.
* @throws IOException if an error occurs in parsing the event.
* @throws NoSuchAlgorithmException if an undefined algorithm is encountered.
* @throws CertificateException If a certificate within an event can't be processed.
*/
public TpmPcrEvent1(final ByteArrayInputStream is) throws IOException {
public TpmPcrEvent1(final ByteArrayInputStream is) throws IOException, CertificateException,
NoSuchAlgorithmException {
super(is);
setDigestLength(SHA1_LENGTH);
byte[] unit32Data = new byte[INT_LENGTH];
if (is.available() > MIN_SIZE) {
is.read(unit32Data);
setPcrIndex(unit32Data);
is.read(unit32Data);
setEventType(unit32Data);
byte[] eventDigest = new byte[SHA1_LENGTH];
setDigestLength(EvConstants.SHA1_LENGTH);
setLogFormat(1);
/** Event data. */
byte[] event = null;
byte[] rawIndex = new byte[UefiConstants.SIZE_4];
byte[] rawType = new byte[UefiConstants.SIZE_4];
byte[] rawEventSize = new byte[UefiConstants.SIZE_4];
byte[] eventDigest = new byte[EvConstants.SHA1_LENGTH];
byte[] eventContent = null;
int eventSize = 0;
if (is.available() > UefiConstants.SIZE_32) {
is.read(rawIndex);
setPcrIndex(rawIndex);
is.read(rawType);
setEventType(rawType);
is.read(eventDigest);
setEventDigest(eventDigest);
is.read(unit32Data);
int eventSize = HexUtils.leReverseInt(unit32Data);
byte[] eventContent = new byte[eventSize];
is.read(rawEventSize);
eventSize = HexUtils.leReverseInt(rawEventSize);
eventContent = new byte[eventSize];
is.read(eventContent);
setEventContent(eventContent);
// copy entire event into a byte array for processing
int eventLength = rawIndex.length + rawType.length + eventDigest.length
+ rawEventSize.length;
int offset = 0;
event = new byte[eventLength];
System.arraycopy(rawIndex, 0, event, offset, rawIndex.length);
offset += rawIndex.length;
System.arraycopy(rawType, 0, event, offset, rawType.length);
offset += rawType.length;
System.arraycopy(eventDigest, 0, event, offset, eventDigest.length);
offset += eventDigest.length;
System.arraycopy(rawEventSize, 0, event, offset, rawEventSize.length);
offset += rawEventSize.length;
//System.arraycopy(eventContent, 0, event, offset, eventContent.length);
this.processEvent(event, eventContent);
}
}
}
}

View File

@ -2,8 +2,12 @@ package hirs.tpm.eventlog;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import hirs.tpm.eventlog.events.EvConstants;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.utils.HexUtils;
/**
@ -64,21 +68,33 @@ public class TpmPcrEvent2 extends TpmPcrEvent {
*
* @param is ByteArrayInputStream holding the TCG Log event
* @throws IOException if an error occurs in parsing the event
* @throws NoSuchAlgorithmException if an undefined algorithm is encountered.
* @throws CertificateException If a certificate within an event can't be processed.
*/
public TpmPcrEvent2(final ByteArrayInputStream is) throws IOException {
public TpmPcrEvent2(final ByteArrayInputStream is) throws IOException, CertificateException,
NoSuchAlgorithmException {
super(is);
setDigestLength(SHA256_LENGTH);
setDigestLength(EvConstants.SHA256_LENGTH);
setLogFormat(2);
/** Event data. */
byte[] event;
byte[] rawIndex = new byte[UefiConstants.SIZE_4];
byte[] algCountBytes = new byte[UefiConstants.SIZE_4];
byte[] rawType = new byte[UefiConstants.SIZE_4];
byte[] rawEventSize = new byte[UefiConstants.SIZE_4];
byte[] eventDigest = new byte[EvConstants.SHA256_LENGTH];
byte[] eventContent = null;
TcgTpmtHa hashAlg = null;
int eventSize = 0;
//TCG_PCR_EVENT2
byte[] rawInt = new byte[INT_LENGTH];
if (is.available() > MIN_SIZE) {
is.read(rawInt);
setPcrIndex(rawInt);
is.read(rawInt);
setEventType(rawInt);
if (is.available() > UefiConstants.SIZE_32) {
is.read(rawIndex);
setPcrIndex(rawIndex);
is.read(rawType);
setEventType(rawType);
// TPML_DIGEST_VALUES
is.read(rawInt);
algCount = HexUtils.leReverseInt(rawInt);
TcgTpmtHa hashAlg = null;
is.read(algCountBytes);
algCount = HexUtils.leReverseInt(algCountBytes);
// Process TPMT_HA,
for (int i = 0; i < algCount; i++) {
hashAlg = new TcgTpmtHa(is);
@ -87,11 +103,36 @@ public class TpmPcrEvent2 extends TpmPcrEvent {
setEventDigest(hashAlg.getDigest());
}
}
is.read(rawInt);
int eventSize = HexUtils.leReverseInt(rawInt);
byte[] eventContent = new byte[eventSize];
is.read(rawEventSize);
eventSize = HexUtils.leReverseInt(rawEventSize);
eventContent = new byte[eventSize];
is.read(eventContent);
setEventContent(eventContent);
int eventLength = rawIndex.length + rawType.length + eventDigest.length
+ rawEventSize.length;
int offset = 0;
for (TcgTpmtHa hash:hashlist) {
eventLength += hash.getBuffer().length;
}
event = new byte[eventLength];
System.arraycopy(rawIndex, 0, event, offset, rawIndex.length);
offset += rawIndex.length;
System.arraycopy(rawType, 0, event, offset, rawType.length);
offset += rawType.length;
System.arraycopy(eventDigest, 0, event, offset, eventDigest.length);
offset += eventDigest.length;
System.arraycopy(rawEventSize, 0, event, offset, rawEventSize.length);
offset += rawEventSize.length;
//System.arraycopy(eventContent, 0, event, offset, eventContent.length);
this.processEvent(event, eventContent);
}
}
/**
* Returns a list of digests within this event.
* @return a list of digests.
*/
public ArrayList<TcgTpmtHa> getHashList() {
return hashlist;
}
}

View File

@ -0,0 +1,53 @@
package hirs.tpm.eventlog.events;
import java.io.UnsupportedEncodingException;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.utils.HexUtils;
/**
* Class to process the EV_COMPACT_HASH event.
* The Old 2005 PFP description of EV_COMPACT_HASH which provides 4 byte ESI field (a pointer).
* The 2019 PFP description allow the vendor to create event data that is "specified by the caller"
* however the for PCR 6 there is a constraint that it contain
* "The Event Data field SHALL be a unique string".
*/
public class EvCompactHash {
/** Holds the Compact Hash description. */
private String eventInfo = "";
/**
* Constructor that takes in the event data (hex string) and passes to function below.
* @param event byte array of the Event Compact Hash.
* @throws UnsupportedEncodingException if compact hash has non utf-8 characters.
*/
public EvCompactHash(final byte[] event) throws UnsupportedEncodingException {
hashEvent(event);
}
/**
* Takes the event data (hex string) converts to readable output.
* This may be somewhat limited due to the unpublished nature of vendor specific data.
* @param event data to process.
* @return a human readable description.
* @throws UnsupportedEncodingException if compact hash has non utf-8 characters.
*/
public String hashEvent(final byte[] event) throws UnsupportedEncodingException {
// determine if old format is used
if (event.length == UefiConstants.SIZE_4) { // older PFP defines as 4 byte ESI pointer.
eventInfo = " ESI = " + HexUtils.byteArrayToHexString(event);
} else { // otherwise assume the event content is a string
eventInfo = " " + new String(event, "UTF-8");
}
return eventInfo;
}
/**
* Readable description of the Event Content, however limiting that may be.
* @return Event description.
*/
public String toString() {
return eventInfo;
}
}

View File

@ -0,0 +1,89 @@
package hirs.tpm.eventlog.events;
/**
* Class for defining constants referenced in the PC Client
* Platform Firmware Profile specification.
*
*/
public final class EvConstants {
/**
* EvConstants constructor.
*/
private EvConstants() {
}
/** Type length = 4 bytes. */
public static final int EV_TYPE_SIZE = 4;
/** Event Log spec version.*/
public static final int MIN_SIZE = 32;
/** Event Type (byte array). */
public static final int INT_LENGTH = 4;
/** Event Type (byte array). */
public static final int SHA1_LENGTH = 20;
/** Event Type (byte array). */
public static final int SHA256_LENGTH = 32;
/** Each PCR bank holds 24 registers. */
public static final int PCR_COUNT = 24;
// Event IDs
/** Pre boot cert Event ID. */
public static final int EV_PREBOOT_CERT = 0x00000000;
/** POST Code Event ID. */
public static final int EV_POST_CODE = 0x00000001;
/** Unused Event ID. */
public static final int EV_UNUSED = 0x00000002;
/** NoAction Event ID. */
public static final int EV_NO_ACTION = 0x00000003;
/** NoAction Event ID. */
public static final int EV_SEPARATOR = 0x00000004;
/** Action Event ID. */
public static final int EV_ACTION = 0x00000005;
/** Event ID. */
public static final int EV_EVENT_TAG = 0x00000006;
/** SCRTM Contents Event ID. */
public static final int EV_S_CRTM_CONTENTS = 0x00000007;
/** SCRTM Version Event ID. */
public static final int EV_S_CRTM_VERSION = 0x00000008;
/** CPU Microcode Event ID. */
public static final int EV_CPU_MICROCODE = 0x00000009;
/** Platform Config Flags Event ID. */
public static final int EV_PLATFORM_CONFIG_FLAGS = 0x0000000A;
/** Table of Devices Event ID. */
public static final int EV_TABLE_OF_DEVICES = 0x0000000B;
/** Compact Hash Event ID. */
public static final int EV_COMPACT_HASH = 0x0000000C;
/** IPL Event ID. */
public static final int EV_IPL = 0x0000000D;
/** Partition Data Event ID. */
public static final int EV_IPL_PARTITION_DATA = 0x0000000E;
/** Non Host Event ID. */
public static final int EV_NONHOST_CODE = 0x0000000F;
/** Non Host Config Event ID. */
public static final int EV_NONHOST_CONFIG = 0x00000010;
/** Non Host Info Event ID. */
public static final int EV_NONHOST_INFO = 0x00000011;
/** Omit Boot Device Event ID. */
public static final int EV_EV_OMIT_BOOT_DEVICES_EVENTS = 0x00000012;
/** EFI Event ID. */
public static final int EV_EFI_EVENT_BASE = 0x80000000;
/** EFI Variable Driver Event ID. */
public static final int EV_EFI_VARIABLE_DRIVER_CONFIG = 0x80000001;
/** EFI Variable Boot Driver Event ID. */
public static final int EV_EFI_VARIABLE_BOOT = 0x80000002;
/** EFI Boot Services Application Event ID. */
public static final int EV_EFI_BOOT_SERVICES_APPLICATION = 0x80000003;
/** EFI Boot Services Application Event ID. */
public static final int EV_EFI_BOOT_SERVICES_DRIVER = 0x80000004;
/** EFI Runtime Services Driver Event ID. */
public static final int EV_EFI_RUNTIME_SERVICES_DRIVER = 0x80000005;
/** EFI GPT Event ID. */
public static final int EV_EFI_GPT_EVENT = 0x80000006;
/** EFI GPT Event ID. */
public static final int EV_EFI_ACTION = 0x80000007;
/** Platform Firmware Blob Event ID. */
public static final int EV_EFI_PLATFORM_FIRMWARE_BLOB = 0x80000008;
/** EFI Handoff Tables Event ID. */
public static final int EV_EFI_HANDOFF_TABLES = 0x80000009;
/** HRCTM Event ID. */
public static final int EV_EFI_HCRTM_EVENT = 0x80000010;
/** EFI Variable Authority Event ID. */
public static final int EV_EFI_VARIABLE_AUTHORITY = 0x800000E0;
}

View File

@ -0,0 +1,133 @@
package hirs.tpm.eventlog.events;
import java.io.UnsupportedEncodingException;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.tpm.eventlog.uefi.UefiDevicePath;
import hirs.utils.HexUtils;
/**
* Class to process the PC Client Firmware profile defined EV_EFI_BOOT_SERVICES_APPLICATION event.
* The EV_EFI_BOOT_SERVICES_APPLICATION event data contains the UEFI_IMAGE_LOAD_EVENT structure:
* struct tdUEFI_IMAGE_LOAD_EVENT {
* UEFI_PHYSICAL_ADDRESS ImageLocationInMemory; // PE/COFF image same as UINT64
* UINT64 ImageLengthInMemory;
* UINT64 ImageLinkTimeAddress;
* UINT64 LengthOfDevicePath;
* UEFI_DEVICE_PATH DevicePath[LengthOfDevicePath]; // See UEFI spec for the encodings.
* } UEFI_IMAGE_LOAD_EVENT;
*
* DEVICE_PATH_PROTOCOL from the UEFI spec Section 10.1 page 284 of v2.8
*
* #define EFI_DEVICE_PATH_PROTOCOL_GUID \09576e91-6d3f-11d2-8e39-00a0c969723b
* typedef struct _EFI_DEVICE_PATH_PROTOCOL {
* UINT8 Type;
* UINT8 SubType;
* UINT8 Length[2];
* } EFI_DEVICE_PATH_PROTOCOL; // ref page of the UEFI spec
*
* Where Type and Subtype are defined the UEFI spec section 10.3.1
* Type 0x01 Hardware Device Path
* Type 0x02 ACPI Device Path
* Type 0x03 Messaging Device Path
* Type 0x04 Media Device Path
* Type 0x05 BIOS Boot Specification Device Path
* Type 0x7F End of Hardware Device Path
*/
public class EvEfiBootServicesApp {
/** UEFI Address. */
private byte[] physicalAddress = null;
/** UEFI Image Length. */
private int imageLength = 0;
/** UEFI Link Time image address. */
private byte[] linkTimeAddress = null;
/** UEFI Device Path Length. */
private int devicePathLength = 0;
/** UEFI Device path. */
private UefiDevicePath devPath = null;
/** Is the Device Path Valid. */
private boolean devicePathValid = false;
/**
* EvEFIBootServicesApp constructor.
* @param bootServices byte array holding the event data.
* @throws UnsupportedEncodingException if parsing issues exists.
*/
public EvEfiBootServicesApp(final byte[] bootServices) throws UnsupportedEncodingException {
physicalAddress = new byte[UefiConstants.SIZE_8];
System.arraycopy(bootServices, 0, physicalAddress, 0, UefiConstants.SIZE_8);
byte[] lengthBytes = new byte[UefiConstants.SIZE_8];
System.arraycopy(bootServices, UefiConstants.OFFSET_8, lengthBytes, 0, UefiConstants.SIZE_8);
imageLength = HexUtils.leReverseInt(lengthBytes);
linkTimeAddress = new byte[UefiConstants.SIZE_8];
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) {
devicePathLength = HexUtils.leReverseInt(lengthBytes);
byte[] devPathBytes = new byte[devicePathLength];
System.arraycopy(bootServices, UefiConstants.SIZE_32, devPathBytes,
0, devicePathLength);
devPath = new UefiDevicePath(devPathBytes);
devicePathValid = true;
}
}
/**
* Returns the address of the physical image of the boot services application.
* @return address of the physical image.
*/
public byte[] getImagePhysicalAddress() {
return java.util.Arrays.copyOf(physicalAddress, physicalAddress.length);
}
/**
* Returns the length of a link time image referenced by this event.
* @return length of the link time image.
*/
public byte[] getImageLinkTimeAddress() {
return java.util.Arrays.copyOf(linkTimeAddress, linkTimeAddress.length);
}
/**
* Returns the length of an image referenced by this event.
* @return length of the image.
*/
public int getImageLength() {
return imageLength;
}
/**
* Returns the length of the device path.
* @return device path length.
*/
public int getDevicePathLength() {
return devicePathLength;
}
/**
* Provide a uefi device path object contained in the event.
* @return UefiDevicePath object.
*/
public UefiDevicePath getDevicePath() {
return devPath;
}
/**
* Returns a human readable string of the Boot Service info.
* @return a human readable string.
*/
public String toString() {
String info = "Image info: ";
info += " Image physical address: " + HexUtils.byteArrayToHexString(physicalAddress);
info += " Image length = " + imageLength;
info += " Image link time address: " + HexUtils.byteArrayToHexString(physicalAddress);
info += " Device path length = " + devicePathLength + "\n";
if (devicePathValid) {
info += devPath.toString();
} else {
info += " Error processing device path" + "\n";
}
return info;
}
}

View File

@ -0,0 +1,138 @@
package hirs.tpm.eventlog.events;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.ArrayList;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.tpm.eventlog.uefi.UefiPartition;
import hirs.utils.HexUtils;
/**
* Class to process the PC Client Firmware profile defined EV_EFI_GPT_EVENT event.
* The EV_EFI_GPT_EVENT event data contains the UEFI_GPT_DATA structure as defined in the PFP
* line 2860:
*
* typedef struct {
* UEFI_PARTITION_TABLE_HEADER UEFIPartitionHeader; // same as UINT64 for current x86 devices
* UINT64 NumberOfPartitions;
* UEFI_PARTITION_ENTRY Partitions [NumberOfPartitions];
* }UEFI_GPT_DATA;
*
* The UEFI spec defines the EFI_TABLE_HEADER and EFI_PARTITION_ENTRY
*
* * typedef struct {
* UINT64 Signature; // A 64-bit signature that identifies the type of table that follows.
* UINT32 Revision;
* UINT32 HeaderSize;
* UINT32 CRC32;
* UINT32 Reserved;
* } EFI_TABLE_HEADER;
*
* typedef struct {
* EFI_GUID PartitionTypeGUID;
* EFI_GUID UniquePartitionGUID;
* EFI_LBA StartingLBA; // Same as UINT64.
* EFI_LBA EndingLBA;
* UINT64 Attributes;
* CHAR16 PartitionName[36]; // 36 CHAR16 = 72 Bytes
* } EFI_PARTITION_ENTRY;
*
* EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
* EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42
* EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552
*
* UEFI Table 23. Defined GPT Partition Entry - Partition Type GUIDs
* Unused Entry 00000000-0000-0000-0000-000000000000
* EFI System Partition C12A7328-F81F-11D2-BA4B-00A0C93EC93B
* Partition containing a legacy MBR 024DEE41-33E7-11D3-9D69-0008C781F39F
*
*/
public class EvEfiGptPartition {
/** Header Size. */
private int headerSize = 0;
/** Header bytes. */
private byte[] header = new byte[UefiConstants.SIZE_8];
/** Number of partitions in this event. */
private int numberOfPartitions;
/** Partition Length. */
private int partitonEntryLength = UefiConstants.SIZE_128;
/** List of Partitions. */
private ArrayList<UefiPartition> partitionList = new ArrayList<UefiPartition>();
/**
* GPT Partition Event Type constructor.
* @param eventDataBytes GPT Event to process
* @throws UnsupportedEncodingException if Event Data fails to parse
*/
public EvEfiGptPartition(final byte[] eventDataBytes) throws UnsupportedEncodingException {
//byte[] eventDataBytes = event.getEventContent();
// Process the partition header
System.arraycopy(eventDataBytes, 0, header, 0, UefiConstants.SIZE_8); // Signature
byte[] revision = new byte[UefiConstants.SIZE_4];
System.arraycopy(eventDataBytes, UefiConstants.SIZE_8, revision, 0, UefiConstants.SIZE_4);
byte[] hsize = new byte[UefiConstants.SIZE_4];
System.arraycopy(eventDataBytes, UefiConstants.SIZE_12, hsize, 0, UefiConstants.SIZE_4);
headerSize = getIntFromBytes(hsize);
byte[] partitions = new byte[UefiConstants.SIZE_8];
System.arraycopy(eventDataBytes, headerSize, partitions, 0, UefiConstants.SIZE_8);
numberOfPartitions = getIntFromBytes(partitions);
int partitionLength = numberOfPartitions * partitonEntryLength;
byte[] partitionEntries = new byte[partitionLength];
System.arraycopy(eventDataBytes, headerSize + UefiConstants.SIZE_8, partitionEntries,
0, partitionLength);
processesPartitions(partitionEntries, numberOfPartitions);
// Mystery Structure get processed here (skipped for now), still part of the header
}
/**
* Returns a list of partitions described in the Event Log.
* @return UefiPartition List.
*/
public ArrayList<UefiPartition> getPartitionList() {
return partitionList;
}
/**
* Processes an individual GPT partition entry.
* @param partitons byte array holding partition data.
* @param numberOfParititions number of partitions included in the data.
* @throws UnsupportedEncodingException if partition data fails to parse.
*/
private void processesPartitions(final byte[] partitons, final int numberOfParititions)
throws UnsupportedEncodingException {
byte[] partitionData = new byte[UefiConstants.SIZE_128];
for (int i = 0; i < numberOfParititions; i++) {
System.arraycopy(partitons, i * partitonEntryLength, partitionData, 0,
partitonEntryLength);
partitionList.add(new UefiPartition(partitionData));
}
}
/**
* Provides a human readable string describing the GPT Partition information.
* @return a human readable string holding the partition information.
*/
public String toString() {
String headerStr = HexUtils.byteArrayToHexString(header);
StringBuilder partitionInfo = new StringBuilder();
partitionInfo.append("GPT Header Signature = " + headerStr + " : Number of Paritions = "
+ numberOfPartitions + "\n");
for (int i = 0; i < numberOfPartitions; i++) {
partitionInfo.append("Partition " + i + " information\n");
partitionInfo.append(partitionList.get(i).toString());
}
return partitionInfo.toString();
}
/**
* Helper method for converting little Endian byte arrays into Big Endian integers.
* @param data data to convert.
* @return an integer.
*/
public int getIntFromBytes(final byte[] data) {
byte[] bigEndData = HexUtils.leReverseByte(data);
BigInteger bigInt = new BigInteger(bigEndData);
return bigInt.intValue();
}
}

View File

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

View File

@ -0,0 +1,179 @@
package hirs.tpm.eventlog.events;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import hirs.tpm.eventlog.TcgTpmtHa;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.utils.HexUtils;
/**
* Class to process the TCG_EfiSpecIDEvent.
* The first 16 bytes of a Event Data MUST be String based identifier (Signature).
* The only currently defined Signature is "Spec ID Event03" which implies the data is
* a TCG_EfiSpecIDEvent. TCG_EfiSpecIDEvent is the first event in a TPM Event Log
* and is used to determine the format of the Log (SHA1 vs Crypt Agile).
*
* typedef struct tdTCG_EfiSpecIdEvent {
* BYTE Signature[16];
* UINT32 platformClass;
* UINT8 specVersionMinor;
* UINT8 specVersionMajor;
* UINT8 specErrata;
* UINT8 uintnSize;
* UINT32 numberOfAlgorithms;
* TCG_EfiSpecIdEventAlgorithmSize digestSizes[numberOfAlgorithms];
* UINT8 vendorInfoSize;
* BYTE vendorInfo[VendorInfoSize];
* } TCG_EfiSpecIDEvent;
*
* typedef struct tdTCG_EfiSpecIdEventAlgorithmSize {
* UINT16 algorithmId;
* UINT16 digestSize;
* } TCG_EfiSpecIdEventAlgorithmSize;
*
* define TPM_ALG_SHA1 (TPM_ALG_ID)(0x0004)
* define TPM_ALG_SHA256 (TPM_ALG_ID)(0x000B)
* define TPM_ALG_SHA384 (TPM_ALG_ID)(0x000C)
* define TPM_ALG_SHA512 (TPM_ALG_ID)(0x000D)
*
* Notes: Parses event data for an EfiSpecID per Table 5 TCG_EfiSpecIdEvent Example.
* 1. Should be the first Structure in the log
* 2. Has an EventType of EV_NO_ACTION (0x00000003)
* 3. Digest of 20 bytes of all 0's
* 4. Event content defined as TCG_EfiSpecIDEvent Struct.
* 5. First 16 bytes of the structure is an ASCII "Spec ID Event03"
* 6. The version of the log is used to determine which format the Log
* is to use (sha1 or Crypto Agile)
*/
public class EvEfiSpecIdEvent {
/** Minor Version. */
private String vMin = "";
/** Major Version. */
private String vMaj = "";
/** Specification errata version. */
private String errata = "";
/** Signature (text) data. */
private String signature = "";
/** Platform class. */
private String platformClass = "";
/** Algorithm count. */
private int numberOfAlg = 0;
/** True if event log uses Crypto Agile format. */
private boolean cryptoAgile = false;
/** Algorithm list. */
private ArrayList<String> algList = new ArrayList<String>();
/**
* EvEfiSpecIdEvent Constructor.
* @param efiSpecId byte array holding the spec ID Event.
* @throws UnsupportedEncodingException if input fails to parse.
*/
public EvEfiSpecIdEvent(final byte[] efiSpecId) throws UnsupportedEncodingException {
byte[] signatureBytes = new byte[UefiConstants.SIZE_16];
System.arraycopy(efiSpecId, 0, signatureBytes, 0, UefiConstants.SIZE_16);
signature = HexUtils.byteArrayToHexString(signatureBytes);
signature = new String(signatureBytes, "UTF-8").substring(0, UefiConstants.SIZE_15);
byte[] platformClassBytes = new byte[UefiConstants.SIZE_4];
System.arraycopy(efiSpecId, UefiConstants.OFFSET_16, platformClassBytes, 0,
UefiConstants.SIZE_4);
platformClass = HexUtils.byteArrayToHexString(platformClassBytes);
byte[] specVersionMinorBytes = new byte[1];
System.arraycopy(efiSpecId, UefiConstants.OFFSET_20, specVersionMinorBytes, 0, 1);
vMin = HexUtils.byteArrayToHexString(specVersionMinorBytes);
byte[] specVersionMajorBytes = new byte[1];
System.arraycopy(efiSpecId, UefiConstants.OFFSET_21, specVersionMajorBytes, 0, 1);
vMaj = HexUtils.byteArrayToHexString(specVersionMajorBytes);
byte[] specErrataBytes = new byte[1];
System.arraycopy(efiSpecId, UefiConstants.OFFSET_22, specErrataBytes, 0, 1);
errata = HexUtils.byteArrayToHexString(specErrataBytes);
byte[] numberOfAlgBytes = new byte[UefiConstants.SIZE_4];
System.arraycopy(efiSpecId, UefiConstants.OFFSET_24, numberOfAlgBytes, 0,
UefiConstants.SIZE_4);
numberOfAlg = HexUtils.leReverseInt(numberOfAlgBytes);
byte[] algorithmIDBytes = new byte[UefiConstants.SIZE_2];
int algLocation = UefiConstants.SIZE_28;
for (int i = 0; i < numberOfAlg; i++) {
System.arraycopy(efiSpecId, algLocation + UefiConstants.OFFSET_4 * i, algorithmIDBytes,
0, UefiConstants.SIZE_2);
String alg = TcgTpmtHa.tcgAlgIdtoString(HexUtils.leReverseInt(algorithmIDBytes));
algList.add(alg);
}
if ((algList.size() == 1) && (algList.get(0).compareTo("SHA1") == 0)) {
cryptoAgile = false;
} else {
cryptoAgile = true;
}
}
/**
* Returns the specification major revision.
* @return major revision.
*/
public String getVersionMajor() {
return vMaj;
}
/**
* Returns the specification minor revision.
* @return minor revision.
*/
public String getVersionMinor() {
return vMin;
}
/**
* Returns the specification eratta version.
* @return major revision.
*/
public String getErrata() {
return errata;
}
/**
* Returns the contents of the events signature field.
* @return signature data.
*/
public String getSignature() {
return signature;
}
/**
* Returns the class of the platform.
* @return platform class.
*/
public String getPlatformClass() {
return platformClass;
}
/**
* Returns a list of hash algorithms used in the event log.
* @return ArrayList of TCG defined algorithm identifiers.
*/
public ArrayList<String> getAlgList() {
return algList;
}
/**
* Used to determine if the log uses the Crypto Agile format.
* @return boolean true if the algorithm is Crpyto Agile.
*/
public boolean isCryptoAgile() {
return cryptoAgile;
}
/**
* Returns a human readable description of the data within this event.
* @return a description of this event..
*/
public String toString() {
String specInfo = "";
if (signature == "Spec ID Event#") {
specInfo += "Platform Profile Specification version = " + vMaj + "." + vMin
+ " using errata version" + errata + "\n";
} else {
specInfo = "EV_NO_ACTION event named " + signature
+ " ecncountered but support for processing it has not been added to this application";
}
return specInfo;
}
}

View File

@ -0,0 +1,69 @@
package hirs.tpm.eventlog.events;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.utils.HexUtils;
/**
* Class for processing the EV_EVENT_TAG.
* The structure for the Event Data is defined as:
* structure tdTCG_PCClientTaggedEvent{
* UINT32 taggedEventID;
* UINT32 taggedEventDataSize;
* BYTE taggedEventData[taggedEventDataSize];
* } TCG_PCClientTaggedEvent;
* ToDo: Find lookup of taggedEventID and figure out how to process.
*/
public class EvEventTag {
/** Event Tag Information. */
private String eventTagInfo = "";
/** Event Tag ID. */
private int tagEventID = 0;
/** Event ID. */
private int eventID = 0;
/** Data size. */
private int dataSize = 0;
/**
* Processes event tag.
* @param eventTag byte array holding the eventTag data.
*/
public EvEventTag(final byte[] eventTag) {
if (eventTag.length < UefiConstants.SIZE_8) {
eventTagInfo = "Invalid EV Event Tag data";
} else {
byte[] tagEventIdBytes = new byte[UefiConstants.SIZE_4];
System.arraycopy(eventTag, 0, tagEventIdBytes, 0, UefiConstants.SIZE_4);
eventID = HexUtils.leReverseInt(tagEventIdBytes);
byte[] tagEventDataSize = new byte[UefiConstants.SIZE_4];
System.arraycopy(eventTag, UefiConstants.OFFSET_4, tagEventDataSize, 0,
UefiConstants.SIZE_4);
dataSize = HexUtils.leReverseInt(tagEventDataSize);
}
}
/**
* Returns the event ID & data size.
* @return eventID
*/
public int getTagEventID() {
return tagEventID;
}
/**
* Returns the size of the UEFI variable.
* @return size of the UEFI variable.
*/
public int getDataSize() {
return dataSize;
}
/**
* Returns a human readable string of the Event Tag.
* @return human readable string.
*/
public String toString() {
if (eventTagInfo.isEmpty()) {
eventTagInfo = " Tagged Event ID = " + eventID;
eventTagInfo += " Data Size = " + dataSize;
}
return eventTagInfo;
}
}

View File

@ -0,0 +1,43 @@
package hirs.tpm.eventlog.events;
import java.nio.charset.StandardCharsets;
/**
* Processes event type EV_IPL which is deprecated in the current spec,
* but defined in older version of the specification(1.0.0) as contain
* "informative information about the IPL code" (ascii strings).
*/
public class EvIPL {
private String description = "";
/**
*IPL Event Constructor.
* @param event byte array holding the IPL Event data.
*/
public EvIPL(final byte[] event) {
event(event);
}
/**
* Processes IPL event.
* @param event byte array holding the IPL Event data.
* @return a description of the IPl event.
*/
public String event(final byte[] event) {
if (event == null) {
description = "Invalid IPL event data";
} else {
description = " \"" + new String(event, StandardCharsets.UTF_8) + "\"";
}
return description;
}
/**
* Returns a human readable description of the IPL Event.
* @return human readable description.
*/
public String toString() {
return description;
}
}

View File

@ -0,0 +1,82 @@
package hirs.tpm.eventlog.events;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import hirs.tpm.eventlog.uefi.UefiConstants;
/**
* Class to process the EV_NO_ACTION event using a structure of TCG_EfiSpecIDEvent.
* The first 16 bytes of the event data MUST be a String based identifier (Signature).
* The only currently defined Signature is "Spec ID Event03"
* which implies the data is a TCG_EfiSpecIDEvent.
* TCG_EfiSpecIDEvent is the first event in a TPM Event Log and is used to determine
* if the format of the Log (SHA1 vs Crypto Agile).
*
* Notes:
* 1. First 16 bytes of the structure is an ASCII with a fixed Length of 16
* 2. Add processing of other NoEvent types when new ones get defined
*/
public class EvNoAction {
/** Signature (text) data. */
private String signature = "";
/** True of the event is a SpecIDEvent. */
private boolean bSpecIDEvent = false;
/** EvEfiSpecIdEvent Object. */
private EvEfiSpecIdEvent specIDEvent = null;
/**
* EvNoAction constructor.
* @param eventData byte array holding the event to process.
* @throws UnsupportedEncodingException if input fails to parse.
*/
public EvNoAction(final byte[] eventData) throws UnsupportedEncodingException {
byte[] signatureBytes = new byte[UefiConstants.SIZE_15];
System.arraycopy(eventData, 0, signatureBytes, 0, UefiConstants.SIZE_15);
signature = new String(signatureBytes, StandardCharsets.UTF_8);
signature = signature.replaceAll("[^\\P{C}\t\r\n]", ""); // remove null characters
if (signature.contains("Spec ID Event03")) { // implies CryptAgileFormat
specIDEvent = new EvEfiSpecIdEvent(eventData);
bSpecIDEvent = true;
}
}
/**
* Returns the EfiSpecIDEvent object (currently only NoAction event defined)
* or null if its not.
* @return EfiSpecIDEvent object or null.
*/
public EvEfiSpecIdEvent getEvEfiSpecIdEvent() {
return specIDEvent;
}
/**
* Determines if this event is a SpecIDEvent.
* @return true of the event is a SpecIDEvent.
*/
public boolean isSpecIDEvent() {
return bSpecIDEvent;
}
/**
* Returns a description of this event.
* @return Human readable description of this event.
*/
public String toString() {
String specInfo = "";
if (bSpecIDEvent) {
specInfo += " Signature = Spec ID Event03 : ";
if (specIDEvent.isCryptoAgile()) {
specInfo += "Log format is Crypto Agile \n";
} else {
specInfo += "Log format is SHA 1 (NOT Crypto Agile) \n";
specInfo += " Platform Profile Specification version = "
+ specIDEvent.getVersionMajor() + "." + specIDEvent.getVersionMinor()
+ " using errata version " + specIDEvent.getErrata() + "\n";
}
} else {
specInfo = "EV_NO_ACTION event named " + signature
+ " encountered but support for processing it has not been added to this application.\n";
}
return specInfo;
}
}

View File

@ -0,0 +1,86 @@
package hirs.tpm.eventlog.events;
import java.nio.charset.StandardCharsets;
import hirs.tpm.eventlog.uefi.UefiFirmware;
/**
* Class for processing EV_POST_CODE event types
*
* typedef struct tdUEFI_PLATFORM_FIRMWARE_BLOB {
* UEFI_PHYSICAL_ADDRESS BlobBase; // Same as UINT64 for most systems
* UINT64 BlobLength;
* } UEFI_PLATFORM_FIRMWARE_BLOB;
*
* However Table 9 of the PC Client Platform firmware profile states that even content is a string
* For POST code, the event data SHOULD be POST CODE.
* For embedded SMM code, the event data SHOULD be SMM CODE.
* For ACPI flash data, the event data SHOULD be ACPI DATA.
* For BIS code, the event data SHOULD be BIS CODE.
* For embedded option ROMs, the event data SHOULD be Embedded UEFI Driver.
*/
public class EvPostCode {
/** Event Description. */
private String codeInfo = "";
/** String type flag. */
private boolean bisString = false;
/** Firmware object. */
private UefiFirmware blob = null;
/**
* EcPostCode constructor.
* @param postCode byte array holding the post code content.
*/
public EvPostCode(final byte[] postCode) {
// 2 ways post code has been implemented, check for the ascii string first
if (isAscii(postCode)) {
String info = new String(postCode, StandardCharsets.UTF_8);
codeInfo = info;
bisString = true;
} else {
blob = new UefiFirmware(postCode);
}
}
/**
* Returns the UEFI Defined Firmware Blob information.
* @return UEFI Defined Firmware Blob information.
*/
public UefiFirmware getfirmwareBlob() {
return blob;
}
/**
* Flag set to true if Post Code is a string.
* @return true if Post Code is a string.
*/
public boolean isString() {
return bisString;
}
/**
* Returns a human readable string of the Post Code information.
* @return human readable string.
*/
public String toString() {
if (bisString) {
return codeInfo;
}
return blob.toString();
}
/**
* Determines if the byte array is a string.
* @param postCode byte array input.
* @return true if byte array is a string.
*/
public static boolean isAscii(final byte[] postCode) {
boolean bisAscii = true;
for (byte b : postCode) {
if (!Character.isDefined(b)) {
return false;
}
}
return bisAscii;
}
}

View File

@ -0,0 +1,41 @@
package hirs.tpm.eventlog.events;
import java.nio.charset.StandardCharsets;
/**
* Class to process the PC Client Firmware profile defined EV_S_CRTM_CONTENTS event.
*/
public class EvSCrtmContents {
private String description = "";
/**
* Constructor that takes in the event data and waits to be called.
* @param event byte array holding the event content data.
*/
public EvSCrtmContents(final byte[] event) {
scrtmContents(event);
}
/**
* Checks if event data is null and if not it converts to a String.
* @param event byte array holding the event data.
* @return String contents contained within the event.
*/
public String scrtmContents(final byte[] event) {
if (event == null) {
description = "invalid content event data";
} else {
description = new String(event, StandardCharsets.UTF_8);
}
return description;
}
/**
* Human readable string contained within the CRTM Contents event.
* @return Human readable string.
*/
public String toString() {
return description;
}
}

View File

@ -0,0 +1,60 @@
package hirs.tpm.eventlog.events;
import java.io.UnsupportedEncodingException;
import hirs.tpm.eventlog.uefi.UefiConstants;
import hirs.tpm.eventlog.uefi.UefiGuid;
import hirs.utils.HexUtils;
/**
* Class to process the PC Client Firmware profile defined EV_S_CRTM_VERSION event.
*/
public class EvSCrtmVersion {
private String description = "";
/**
* Constructor that takes in the event data and waits to be called.
* @param event byte array holding the event content data.
* @throws UnsupportedEncodingException if parsing issues exist.
*/
public EvSCrtmVersion(final byte[] event) throws UnsupportedEncodingException {
sCrtmVersion(event);
}
/**
* Checks if event data is null and if not it converts to a String.
* @param data byte array holding the vent content.
* @throws UnsupportedEncodingException if parsing issues exist.
* @return String representation of the version.
*/
public String sCrtmVersion(final byte[] data) throws UnsupportedEncodingException {
UefiGuid guid = null;
if (data == null) {
description = "invalid content event data";
} else {
if (data.length == UefiConstants.SIZE_16) {
if (UefiGuid.isValidUUID(data)) {
guid = new UefiGuid(data);
String guidInfo = guid.toStringNoLookup();
description = " SCRM Version = " + guidInfo;
}
} else if (data.length < UefiConstants.SIZE_4) {
description = HexUtils.byteArrayToHexString(data);
} else if (EvPostCode.isAscii(data)) {
description = new String(data, "UTF-8");
} else {
description = "Unknown Version format";
}
}
return (description);
}
/**
* Return function to send data to the toString.
* @return String representation of the version.
*/
public String toString() {
return description;
}
}

View File

@ -0,0 +1,6 @@
/**
* Non-persistant classes related to TGC Event Logs.
*/
package hirs.tpm.eventlog.events;

View File

@ -19,16 +19,30 @@ public final class UefiConstants {
public static final int SIZE_5 = 5;
/** 8 byte size. */
public static final int SIZE_8 = 8;
/** 12 byte size. */
public static final int SIZE_12 = 12;
/** 15 byte size. */
public static final int SIZE_15 = 15;
/** 16 byte size. */
public static final int SIZE_16 = 16;
/** 20 byte size. */
public static final int SIZE_20 = 20;
/** 21 byte size. */
public static final int SIZE_21 = 21;
/** 22 byte size. */
public static final int SIZE_22 = 22;
/** 23 byte size. */
public static final int SIZE_23 = 23;
/** 24 byte size. */
public static final int SIZE_24 = 24;
/** 28 byte size. */
public static final int SIZE_28 = 28;
/** 32 byte size. */
public static final int SIZE_32 = 32;
/** 40 byte size. */
public static final int SIZE_40 = 40;
/** 128 byte size. */
public static final int SIZE_128 = 128;
/** 256 byte size. */
public static final int SIZE_256 = 256;
/** 1 byte offset. */
@ -47,6 +61,10 @@ public final class UefiConstants {
public static final int OFFSET_16 = 16;
/** 20 byte offset. */
public static final int OFFSET_20 = 20;
/** 21 byte offset. */
public static final int OFFSET_21 = 21;
/** 22 byte offset. */
public static final int OFFSET_22 = 22;
/** 24 byte offset. */
public static final int OFFSET_24 = 24;
/** 28 byte offset. */

View File

@ -2,14 +2,16 @@ package hirs.tpm.eventlog;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
//import java.util.List;
//import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Session;
//import org.hibernate.Session;
import org.testng.Assert;
@ -17,24 +19,18 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/*
import org.junit.Test;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
*/
import hirs.data.persist.Baseline;
import hirs.data.persist.Digest;
import hirs.data.persist.SpringPersistenceTest;
import hirs.data.persist.TpmWhiteListBaseline;
import hirs.utils.HexUtils;
//import hirs.data.persist.Baseline;
//import hirs.data.persist.Digest;
//import hirs.data.persist.SpringPersistenceTest;
//import hirs.data.persist.TpmWhiteListBaseline;
//import hirs.utils.HexUtils;
/**
* Class for testing TCG Event Log processing.
*/
public class TCGEventLogProcessorTest extends SpringPersistenceTest {
private static final String DEFAULT_EVENT_LOG = "/tcgeventlog/TpmLog.bin";
//public class TCGEventLogProcessorTest extends SpringPersistenceTest {
public class TCGEventLogProcessorTest {
private static final String DEFAULT_EVENT_LOG = "/tcgeventlog/TpmLog.bin";
private static final String DEFAULT_EXPECTED_PCRS = "/tcgeventlog/TpmLogExpectedPcrs.txt";
private static final String SHA1_EVENT_LOG = "/tcgeventlog/TpmLogSHA1.bin";
private static final String SHA1_EXPECTED_PCRS = "/tcgeventlog/TpmLogSHA1ExpectedPcrs.txt";
@ -64,6 +60,7 @@ public class TCGEventLogProcessorTest extends SpringPersistenceTest {
* removing all <code>Baseline</code> objects.
*/
// @AfterMethod
/*
public final void resetTestState() {
LOGGER.debug("reset test state");
LOGGER.debug("deleting all baselines");
@ -77,13 +74,16 @@ public class TCGEventLogProcessorTest extends SpringPersistenceTest {
LOGGER.debug("all baselines removed");
session.getTransaction().commit();
}
*/
/**
* Tests the processing of a cryto agile event log.
* Tests the processing of a crypto agile event log.
* @throws IOException when processing the test fails
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
* @throws CertificateException if a certificate fails to parse.
*/
@Test
public final void testCryptoAgileTCGEventLog() throws IOException {
public final void testCryptoAgileTCGEventLog() throws IOException, CertificateException,
NoSuchAlgorithmException {
LOGGER.debug("Testing the parsing of a Crypto Agile formatted TCG Event Log");
InputStream log, pcrs;
boolean testPass = true;
@ -116,15 +116,18 @@ public class TCGEventLogProcessorTest extends SpringPersistenceTest {
/**
* Tests the processing of a SHA1 formatted Event log.
* @throws IOException when processing the test fails
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
* @throws CertificateException if a certificate fails to parse.
*/
@Test
public final void testSHA1TCGEventLog() throws IOException {
public final void testSHA1TCGEventLog() throws IOException, CertificateException,
NoSuchAlgorithmException {
LOGGER.debug("Testing the parsing of a SHA1 formated TCG Event Log");
InputStream log, pcrs;
boolean testPass = true;
log = this.getClass().getResourceAsStream(SHA1_EVENT_LOG);
byte[] rawLogBytes = IOUtils.toByteArray(log);
TCGEventLogProcessor tlp = new TCGEventLogProcessor(rawLogBytes);
TCGEventLogProcessor tlp = new TCGEventLogProcessor(rawLogBytes);
String[] pcrFromLog = tlp.getExpectedPCRValues();
pcrs = this.getClass().getResourceAsStream(SHA1_EXPECTED_PCRS);
Object[] pcrObj = IOUtils.readLines(pcrs).toArray();
@ -152,7 +155,8 @@ public class TCGEventLogProcessorTest extends SpringPersistenceTest {
* Tests TPM Baseline creation from a EventLog.
* @throws IOException when processing the test fails
*/
@Test
//@Test
/*
public final void testTPMBaselineCreate() throws IOException {
LOGGER.debug("Create and save TPM baseline from TCG Event Log test started");
InputStream log;
@ -182,4 +186,5 @@ public class TCGEventLogProcessorTest extends SpringPersistenceTest {
Assert.assertTrue(testPass);
LOGGER.debug("OK. Create and save TPM baseline from TCG Event Log was a success");
}
*/
}

View File

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

View File

@ -0,0 +1,6 @@
/**
* Non-persistant classes related to TGC Event Logs.
*/
package hirs.tpm.eventlog.events;

View File

@ -0,0 +1 @@
1820d45800000000e0b405000000000000000000000000002c00000000000000040714002ce2edb630defa45bb09ca202c1654b7040614001ae3e1159d9f844c82fb1a707fc0f63b7fff0400

View File

@ -0,0 +1 @@
4546492050415254000001005c000000a071310c000000000100000000000000af44f21b0000000022000000000000008e44f21b000000006fe7c34e23793e4cb040e8080f1b888302000000000000008000000080000000d0be05490500000000000000a4bb94ded106404da16abfd50179d6ac8787cc4223db454e9981701adc801dc70008000000000000ffa70f000000000001000000000000804200610073006900630020006400610074006100200070006100720074006900740069006f006e00000000000000000000000000000000000000000000000000000000000000000028732ac11ff8d211ba4b00a0c93ec93b3c62a78c1e04ab4f8c12f49a86b85d7300a80f0000000000ffc712000000000000000000000000804500460049002000730079007300740065006d00200070006100720074006900740069006f006e00000000000000000000000000000000000000000000000000000000000000000016e3c9e35c0bb84d817df92df00215aeffcf90d80c32454fb6cfa4d8bee6d9cb00c8120000000000ffc71a000000000000000000000000804d006900630072006f0073006f0066007400200072006500730065007200760065006400200070006100720074006900740069006f006e0000000000000000000000000000000000a2a0d0ebe5b9334487c068b6b72699c71c4c250c124b884ab88442a31866a34800c81a0000000000ff3ff81a0000000000000000000000004200610073006900630020006400610074006100200070006100720074006900740069006f006e000000000000000000000000000000000000000000000000000000000000000000a4bb94ded106404da16abfd50179d6ac92e459bc0fb29549b1488ded030c7ec20040f81a00000000ff3ff21b0000000001000000000000804200610073006900630020006400610074006100200070006100720074006900740069006f006e000000a70afc7f00007051864ba8020000c091dc4ba8020000bf3a758076450000

View File

@ -0,0 +1 @@
53706563204944204576656e743033000000000000020002010000000b00200000

View File

@ -0,0 +1 @@
01000000000000004415fdf294972c4a992ee5bbcf20e3940000676300000000

View File

@ -0,0 +1 @@
414350492044415441

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true">
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<DigestValue>jfwo1CF30jTNX7m/j85Avnt0EedV/QJIsRUZnaOY+Dg=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>VqUHbt1UqkxlLHVkTOlQs54KWjv5IPKzSCxrsPb8kGjaj5XjHkc1Z/h88znIIMTdCLcyrKgNEXS4
9EHI9nn9LmwXEd/ozKWd8adu6wLdxKj6uIfd0HaCLFrVlnf/b16xO9AW6wp5pLmXwoFi7zBXXJrn
F9MDKy55mXkxb/Z5RUC3IKqsoz+EuKjs6d+yhtb1EQtpJD2dZj23+VjMH4gXxEerDNR1PiPhma/i
QMFa1hwSO7AuasYPy0WCRIgrJ5ZL5x2ZoaSIdE2TsCqnStVL+KLZeMWNCqw4k89hsuELW7Azrl57
Vm2qzPok0svrB1K4QyZdyK2bnG1QY3Fip5Jdmg==</SignatureValue>
<KeyInfo>
<X509Data>
<X509SubjectName>CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US</X509SubjectName>
<X509Certificate>MIIDYTCCAkmgAwIBAgIJAPB+r6VBhBn4MA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAlVTMQsw
CQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxEjAQBgNVBAMM
CUV4YW1wbGVDQTAeFw0yMDAyMTAxODE1MzRaFw0yOTEyMTkxODE1MzRaMFwxCzAJBgNVBAYTAlVT
MQswCQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxGzAZBgNV
BAMMEmV4YW1wbGUuUklNLnNpZ25lcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKd1
lWGkSRuxAAY2wHag2GVxUk1dZx2PTpfQOflvLeccAVwa8mQhlsRERq+QK8ilj8Xfqs44/nBaccZD
OjdfIxIUCMfwhGXjxCaqZbgTucNsExDnu4arTGraoAwzHg0cVLiKT/Cxj9NL4dcMgxRXsPdHfXb0
923C7xYd2t2qfW05umgaj7qeQl6c68CFNsGX4JA8rWFQZvvGx5DGlK4KTcjPuQQINs5fxasNKqLY
2hq+z82x/rqwr2hmyizD6FpFSyIABPEMPfB036GEhRwu1WEMkq8yIp2jgRUoFYke9pB3ph9pVow0
Hh4mNFSKD4pP41VSKY1nus83mdkuukPy5o0CAwEAAaMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMC
BsAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAGuJ+dasb3/Mb7TBJ1Oe
al5ISq8d2LQD5ke5qnjgSQWKXfQ9fcUy3dWnt3Oked/i8B/Tyk3jCdTZJU3J3iRNgTqFfMLP8rU1
w2tPYBjjuPKiiK4YRBHPxtFxPdOL1BPmL4ZzNs33Lv6H0m4aff9p6QpMclX5b/CRjl+80JWRLiLj
U3B0CejZB9dJrPr9SBaC31cDoeTpja9Cl86ip7KkqrZZIYeMuNF6ucWyWtjrW2kr3UhmEy8x/6y4
KigsK8sBwmNv4N2Pu3RppeIcpjYj5NVA1hwRA4eeMgJp2u+urm3l1oo1UNX1HsSSBHp1Owc9zZLm
07Pl8T46kpIA4sroCAU=</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</SoftwareIdentity>