mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-21 13:57:56 +00:00
Merge pull request #248 from nsacyber/issue-245
[#245] TCG Event Log - Event Processing
This commit is contained in:
commit
2ccd3a180e
@ -13,7 +13,8 @@ import java.nio.file.NoSuchFileException;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -106,9 +107,12 @@ public class ReferenceManifestDetailsPageController
|
|||||||
* @param referenceManifestManager the reference manifest manager.
|
* @param referenceManifestManager the reference manifest manager.
|
||||||
* @return mapping of the RIM information from the database.
|
* @return mapping of the RIM information from the database.
|
||||||
* @throws java.io.IOException error for reading file bytes.
|
* @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,
|
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<>();
|
HashMap<String, Object> data = new HashMap<>();
|
||||||
|
|
||||||
ReferenceManifest rim = ReferenceManifest
|
ReferenceManifest rim = ReferenceManifest
|
||||||
|
@ -1,94 +1,84 @@
|
|||||||
package hirs.tpm.eventlog;
|
package hirs.tpm.eventlog;
|
||||||
|
|
||||||
import hirs.utils.HexUtils;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import hirs.tpm.eventlog.events.EvConstants;
|
||||||
import org.apache.logging.log4j.Logger;
|
import hirs.utils.HexUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for handling different formats of TCG Event logs.
|
* Class for handling different formats of TCG Event logs.
|
||||||
*/
|
*/
|
||||||
public class TCGEventLog {
|
public final class TCGEventLog {
|
||||||
|
|
||||||
private static final Logger LOGGER
|
// private static final Logger LOGGER = (Logger) LogManager.getLogger(TCGEventLog.class);
|
||||||
= LogManager.getLogger(TCGEventLog.class);
|
|
||||||
|
|
||||||
/**
|
/** Initial value for SHA 256 values.*/
|
||||||
* Init value for SHA 256 values.
|
|
||||||
*/
|
|
||||||
public static final String INIT_SHA256_LIST = "00000000000000000000000000"
|
public static final String INIT_SHA256_LIST = "00000000000000000000000000"
|
||||||
+ "00000000000000000000000000000000000000";
|
+ "00000000000000000000000000000000000000";
|
||||||
/**
|
/** Initial value for SHA 1 values. */
|
||||||
* Init value for SHA 1 values.
|
|
||||||
*/
|
|
||||||
public static final String INIT_SHA1_LIST = "0000000000000000000000000000000000000000";
|
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;
|
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";
|
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";
|
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;
|
public static final int PCR_COUNT = 24;
|
||||||
/**
|
/** 2 dimensional array holding the PCR values. */
|
||||||
* 2 dimensional array holding the PCR values.
|
private byte[][] pcrList;
|
||||||
*/
|
/** List of parsed events within the log. */
|
||||||
private final byte[][] pcrList;
|
private ArrayList<TpmPcrEvent> eventList = new ArrayList<>();
|
||||||
/**
|
/** Length of PCR. Indicates which hash algorithm is used. */
|
||||||
* List of parsed events within the log.
|
|
||||||
*/
|
|
||||||
private final ArrayList<TpmPcrEvent> eventList = new ArrayList<>();
|
|
||||||
|
|
||||||
private int pcrLength;
|
private int pcrLength;
|
||||||
|
/** Name of hash algorithm. */
|
||||||
private String hashType;
|
private String hashType;
|
||||||
|
/** Initial Value to use. */
|
||||||
private String initValue;
|
private String initValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default blank object constructor.
|
* Default blank object constructor.
|
||||||
*/
|
*/
|
||||||
public TCGEventLog() {
|
public TCGEventLog() {
|
||||||
this.pcrList = new byte[PCR_COUNT][TpmPcrEvent.SHA1_LENGTH];
|
this.pcrList = new byte[PCR_COUNT][EvConstants.SHA1_LENGTH];
|
||||||
initValue = INIT_SHA1_LIST;
|
initValue = INIT_SHA1_LIST;
|
||||||
pcrLength = TpmPcrEvent.SHA1_LENGTH;
|
pcrLength = EvConstants.SHA1_LENGTH;
|
||||||
initPcrList();
|
initPcrList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor for just the rawlog that'll set up SHA1 Log.
|
* Default constructor for just the rawlog that'll set up SHA1 Log.
|
||||||
* @param rawlog data for the event log file
|
* @param rawlog data for the event log file.
|
||||||
* @throws IOException IO Stream for the event log
|
* @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 {
|
public TCGEventLog(final byte[] rawlog) throws CertificateException, NoSuchAlgorithmException,
|
||||||
this(rawlog, TpmPcrEvent.SHA1_LENGTH, HASH_STRING, INIT_SHA1_LIST);
|
IOException {
|
||||||
|
this(rawlog, EvConstants.SHA1_LENGTH, HASH_STRING, INIT_SHA1_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor for specific log.
|
* Default constructor for specific log.
|
||||||
* @param rawlog data for the event log file
|
* @param rawlog data for the event log file
|
||||||
* @param pcrLength determined by SHA1 or 256
|
* @param pLength determined by SHA1 or 256
|
||||||
* @param hashType the type of algorithm
|
* @param hType the type of algorithm
|
||||||
* @param initValue the default blank value
|
* @param iValue the default blank value.
|
||||||
* @throws IOException IO Stream for the 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 TCGEventLog(final byte[] rawlog, final int pcrLength,
|
public TCGEventLog(final byte[] rawlog, final int pLength, final String hType,
|
||||||
final String hashType, final String initValue) throws IOException {
|
final String iValue) throws IOException, CertificateException,
|
||||||
this.pcrLength = pcrLength;
|
NoSuchAlgorithmException {
|
||||||
|
pcrLength = pLength;
|
||||||
this.pcrList = new byte[PCR_COUNT][pcrLength];
|
this.pcrList = new byte[PCR_COUNT][pcrLength];
|
||||||
this.hashType = hashType;
|
hashType = hType;
|
||||||
this.initValue = initValue;
|
initValue = iValue;
|
||||||
ByteArrayInputStream is = new ByteArrayInputStream(rawlog);
|
ByteArrayInputStream is = new ByteArrayInputStream(rawlog);
|
||||||
// Process the 1st entry as a SHA1 format (per the spec)
|
// Process the 1st entry as a SHA1 format (per the spec)
|
||||||
eventList.add(new TpmPcrEvent1(is));
|
eventList.add(new TpmPcrEvent1(is));
|
||||||
@ -132,7 +122,7 @@ public class TCGEventLog {
|
|||||||
0, currentEvent.getDigestLength());
|
0, currentEvent.getDigestLength());
|
||||||
}
|
}
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} 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) {
|
public String getExpectedPCRValue(final int index) {
|
||||||
return HexUtils.byteArrayToHexString(pcrList[index]);
|
return HexUtils.byteArrayToHexString(pcrList[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,13 @@ package hirs.tpm.eventlog;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
import hirs.data.persist.TPMMeasurementRecord;
|
import hirs.data.persist.TPMMeasurementRecord;
|
||||||
import hirs.data.persist.TpmWhiteListBaseline;
|
import hirs.data.persist.TpmWhiteListBaseline;
|
||||||
|
import hirs.tpm.eventlog.events.EvConstants;
|
||||||
|
import hirs.tpm.eventlog.uefi.UefiConstants;
|
||||||
import hirs.utils.HexUtils;
|
import hirs.utils.HexUtils;
|
||||||
import hirs.data.persist.Digest;
|
import hirs.data.persist.Digest;
|
||||||
import hirs.data.persist.DigestAlgorithm;;
|
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.
|
* Constructor parses the input byte array into a List of TpmPcrEvents.
|
||||||
*/
|
*/
|
||||||
public class TCGEventLogProcessor {
|
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";
|
private String algorithm = "TPM_ALG_SHA256";
|
||||||
/**
|
/** Parsed event log array. */
|
||||||
* Parsed event log array.
|
|
||||||
*/
|
|
||||||
private TCGEventLog tcgLog = null;
|
private TCGEventLog tcgLog = null;
|
||||||
/**
|
/** EV_NO_ACTION signature offset. */
|
||||||
* EV_NO_ACTION signature offset.
|
|
||||||
*/
|
|
||||||
private static final int SIG_OFFSET = 32;
|
private static final int SIG_OFFSET = 32;
|
||||||
/**
|
/** TEV_NO_ACTION signature size. */
|
||||||
* TEV_NO_ACTION signature size.
|
|
||||||
*/
|
|
||||||
private static final int SIG_SIZE = 16;
|
private static final int SIG_SIZE = 16;
|
||||||
|
/** Number of PCRs in a TPM PCR Bank. */
|
||||||
|
private static final int PCR_COUNT = 24;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
@ -43,12 +41,15 @@ public class TCGEventLogProcessor {
|
|||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param rawLog the byte array holding the contents of the TCG Event Log
|
* @param rawLog the byte array holding the contents of the TCG Event Log.
|
||||||
* @throws IOException if there is a parsing error
|
* @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)) {
|
if (isLogCrytoAgile(rawLog)) {
|
||||||
tcgLog = new TCGEventLog(rawLog, TpmPcrEvent.SHA256_LENGTH,
|
tcgLog = new TCGEventLog(rawLog, EvConstants.SHA256_LENGTH,
|
||||||
TCGEventLog.HASH256_STRING, TCGEventLog.INIT_SHA256_LIST);
|
TCGEventLog.HASH256_STRING, TCGEventLog.INIT_SHA256_LIST);
|
||||||
} else {
|
} else {
|
||||||
tcgLog = new TCGEventLog(rawLog);
|
tcgLog = new TCGEventLog(rawLog);
|
||||||
@ -104,7 +105,7 @@ public class TCGEventLogProcessor {
|
|||||||
TpmWhiteListBaseline baseline = new TpmWhiteListBaseline(name);
|
TpmWhiteListBaseline baseline = new TpmWhiteListBaseline(name);
|
||||||
TPMMeasurementRecord record;
|
TPMMeasurementRecord record;
|
||||||
String pcrValue;
|
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
|
if (algorithm.compareToIgnoreCase("TPM_ALG_SHA1") == 0) { // Log Was SHA1 Format
|
||||||
pcrValue = tcgLog.getExpectedPCRValue(i);
|
pcrValue = tcgLog.getExpectedPCRValue(i);
|
||||||
byte[] hexValue = HexUtils.hexStringToByteArray(pcrValue);
|
byte[] hexValue = HexUtils.hexStringToByteArray(pcrValue);
|
||||||
@ -127,11 +128,11 @@ public class TCGEventLogProcessor {
|
|||||||
*
|
*
|
||||||
* @param log The Event Log
|
* @param log The Event Log
|
||||||
* @return true if EfiSpecIDEvent is found and indicates that the format is crypto agile
|
* @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 {
|
public boolean isLogCrytoAgile(final byte[] log) throws UnsupportedEncodingException {
|
||||||
byte[] eType = new byte[TpmPcrEvent.INT_LENGTH];
|
byte[] eType = new byte[UefiConstants.SIZE_4];
|
||||||
System.arraycopy(log, TpmPcrEvent.INT_LENGTH, eType, 0, TpmPcrEvent.INT_LENGTH);
|
System.arraycopy(log, UefiConstants.SIZE_4, eType, 0, UefiConstants.SIZE_4);
|
||||||
byte[] eventType = HexUtils.leReverseByte(eType);
|
byte[] eventType = HexUtils.leReverseByte(eType);
|
||||||
int eventID = new BigInteger(eventType).intValue();
|
int eventID = new BigInteger(eventType).intValue();
|
||||||
if (eventID != TCGEventLog.NO_ACTION_EVENT) {
|
if (eventID != TCGEventLog.NO_ACTION_EVENT) {
|
||||||
|
@ -15,63 +15,36 @@ import hirs.utils.HexUtils;
|
|||||||
* } TPMT_HA;
|
* } TPMT_HA;
|
||||||
*/
|
*/
|
||||||
public class TcgTpmtHa {
|
public class TcgTpmtHa {
|
||||||
/**
|
/** TCG Defined Algorithm Identifiers. */
|
||||||
* TCG Defined Algorithm Identifiers .
|
|
||||||
*/
|
|
||||||
private int hashAlgId = 0;
|
private int hashAlgId = 0;
|
||||||
/**
|
/** Length of the hash. */
|
||||||
* Length of the hash.
|
|
||||||
*/
|
|
||||||
private int hashLength = 0;
|
private int hashLength = 0;
|
||||||
/**
|
/** Human readable name of the hash algorithm. */
|
||||||
* Human readable name of the hash algorithm.
|
|
||||||
*/
|
|
||||||
private String hashName = "";
|
private String hashName = "";
|
||||||
/**
|
/** Hash data. */
|
||||||
* Hash data.
|
|
||||||
*/
|
|
||||||
private byte[] digest = null;
|
private byte[] digest = null;
|
||||||
/**
|
/** TCG ID for SHA1. */
|
||||||
* TCG ID for SHA1.
|
|
||||||
*/
|
|
||||||
public static final int TPM_ALG_SHA1 = 0x04;
|
public static final int TPM_ALG_SHA1 = 0x04;
|
||||||
/**
|
/** TCG ID for SHA1. */
|
||||||
* TCG ID for SHA1.
|
|
||||||
*/
|
|
||||||
public static final int TPM_ALG_SHA256 = 0x0B;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
public static final int TPM_ALG_NULL_LENGTH = 0;
|
||||||
|
/** buffer to hold the structure. */
|
||||||
|
private byte[] buffer = null;
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
@ -87,6 +60,9 @@ public class TcgTpmtHa {
|
|||||||
hashLength = tcgAlgLength(algID[0]);
|
hashLength = tcgAlgLength(algID[0]);
|
||||||
digest = new byte[hashLength];
|
digest = new byte[hashLength];
|
||||||
is.read(digest);
|
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;
|
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.
|
* Return the length of the Hash.
|
||||||
*
|
*
|
||||||
|
@ -3,7 +3,26 @@ package hirs.tpm.eventlog;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
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;
|
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_PCR_EVENT is used when the Event log uses the SHA1 Format as described in the
|
||||||
* TCG Platform Firmware Profile (PFP) specification.
|
* TCG Platform Firmware Profile (PFP) specification.
|
||||||
* typedef struct {
|
* typedef struct {
|
||||||
* TCG_PCRINDEX PCRIndex; //PCR Index value that either
|
* TCG_PCRINDEX PCRIndex; //PCR Index value that either
|
||||||
* //matches the PCRIndex of a
|
* //matches the PCRIndex of a
|
||||||
* //previous extend operation or
|
* //previous extend operation or
|
||||||
* //indicates that this Event Log
|
* //indicates that this Event Log
|
||||||
* //entry is not associated with
|
* //entry is not associated with
|
||||||
* //an extend operation
|
* //an extend operation
|
||||||
* TCG_EVENTTYPE EventType; //See Log event types defined in toStrng()
|
* TCG_EVENTTYPE EventType; //See Log event types defined in toStrng()
|
||||||
* TCG_DIGEST digest; //The hash of the event data
|
* TCG_DIGEST digest; //The hash of the event data
|
||||||
* UINT32 EventSize; //Size of the event data
|
* UINT32 EventSize; //Size of the event data
|
||||||
* UINT8 Event[EventSize]; //The event data
|
* UINT8 Event[EventSize]; //The event data
|
||||||
* } TCG_PCR_EVENT;
|
* } TCG_PCR_EVENT;
|
||||||
*/
|
*/
|
||||||
public class TpmPcrEvent {
|
public class TpmPcrEvent {
|
||||||
/**
|
/** Log format. SHA1=1, Crytpo agile=2. */
|
||||||
* Type length = 4 bytes.
|
private int logFormat = -1;
|
||||||
*/
|
/** PCR index. */
|
||||||
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.
|
|
||||||
*/
|
|
||||||
private int pcrIndex = -1;
|
private int pcrIndex = -1;
|
||||||
/**
|
/** Event Type (long). */
|
||||||
* Event Type (long).
|
|
||||||
*/
|
|
||||||
private long eventType = 0;
|
private long eventType = 0;
|
||||||
/**
|
/** Event digest. */
|
||||||
* Event digest.
|
|
||||||
*/
|
|
||||||
private byte[] digest = null;
|
private byte[] digest = null;
|
||||||
/**
|
/** Even content data. */
|
||||||
* Even data.
|
|
||||||
*/
|
|
||||||
private byte[] eventContent;
|
private byte[] eventContent;
|
||||||
/**
|
/** TCG Event Log spec version. */
|
||||||
* TCG Event Log spec version.
|
private String version = "Unknown";
|
||||||
*/
|
/** TCG Event Log errata version. */
|
||||||
private static String version = "Unknown";
|
private String errata = "Unknown";
|
||||||
/**
|
/** Length (in bytes) of a pcr. */
|
||||||
* TCG Event Log errata version.
|
|
||||||
*/
|
|
||||||
private static String errata = "Unknown";
|
|
||||||
/**
|
|
||||||
* Length (in bytes) of a pcr.
|
|
||||||
*/
|
|
||||||
private int digestLength = 0;
|
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.
|
* Constructor.
|
||||||
@ -128,14 +125,30 @@ public class TpmPcrEvent {
|
|||||||
return pcrIndex;
|
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.
|
* Sets the EventType.
|
||||||
*
|
*
|
||||||
* @param type byte array holding the PFP defined log event type
|
* @param type byte array holding the PFP defined log event type
|
||||||
*/
|
*/
|
||||||
protected void setEventType(final byte[] type) {
|
protected void setEventType(final byte[] type) {
|
||||||
byte[] evType = HexUtils.leReverseByte(type);
|
eventType = new BigInteger(HexUtils.leReverseByte(type)).longValue();
|
||||||
eventType = new BigInteger(evType).longValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -183,8 +196,8 @@ public class TpmPcrEvent {
|
|||||||
*
|
*
|
||||||
* @return byte array holding the events content field
|
* @return byte array holding the events content field
|
||||||
*/
|
*/
|
||||||
protected byte[] getEventContent() {
|
public byte[] getEventContent() {
|
||||||
return eventContent;
|
return java.util.Arrays.copyOf(eventContent, eventContent.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,4 +218,262 @@ public class TpmPcrEvent {
|
|||||||
public int getDigestLength() {
|
public int getDigestLength() {
|
||||||
return digestLength;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
package hirs.tpm.eventlog;
|
package hirs.tpm.eventlog;
|
||||||
|
|
||||||
|
import hirs.tpm.eventlog.events.EvConstants;
|
||||||
|
import hirs.tpm.eventlog.uefi.UefiConstants;
|
||||||
import hirs.utils.HexUtils;
|
import hirs.utils.HexUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to process a TCG_PCR_EVENT.
|
* Class to process a TCG_PCR_EVENT.
|
||||||
@ -27,25 +31,52 @@ public class TpmPcrEvent1 extends TpmPcrEvent {
|
|||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param is ByteArrayInputStream holding the TCG Log event
|
* @param is ByteArrayInputStream holding the TCG Log event.
|
||||||
* @throws IOException if an error occurs in parsing the 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);
|
super(is);
|
||||||
setDigestLength(SHA1_LENGTH);
|
setDigestLength(EvConstants.SHA1_LENGTH);
|
||||||
byte[] unit32Data = new byte[INT_LENGTH];
|
setLogFormat(1);
|
||||||
if (is.available() > MIN_SIZE) {
|
/** Event data. */
|
||||||
is.read(unit32Data);
|
byte[] event = null;
|
||||||
setPcrIndex(unit32Data);
|
byte[] rawIndex = new byte[UefiConstants.SIZE_4];
|
||||||
is.read(unit32Data);
|
byte[] rawType = new byte[UefiConstants.SIZE_4];
|
||||||
setEventType(unit32Data);
|
byte[] rawEventSize = new byte[UefiConstants.SIZE_4];
|
||||||
byte[] eventDigest = new byte[SHA1_LENGTH];
|
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);
|
is.read(eventDigest);
|
||||||
setEventDigest(eventDigest);
|
setEventDigest(eventDigest);
|
||||||
is.read(unit32Data);
|
is.read(rawEventSize);
|
||||||
int eventSize = HexUtils.leReverseInt(unit32Data);
|
eventSize = HexUtils.leReverseInt(rawEventSize);
|
||||||
byte[] eventContent = new byte[eventSize];
|
eventContent = new byte[eventSize];
|
||||||
is.read(eventContent);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,12 @@ package hirs.tpm.eventlog;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import hirs.tpm.eventlog.events.EvConstants;
|
||||||
|
import hirs.tpm.eventlog.uefi.UefiConstants;
|
||||||
import hirs.utils.HexUtils;
|
import hirs.utils.HexUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,21 +68,33 @@ public class TpmPcrEvent2 extends TpmPcrEvent {
|
|||||||
*
|
*
|
||||||
* @param is ByteArrayInputStream holding the TCG Log event
|
* @param is ByteArrayInputStream holding the TCG Log event
|
||||||
* @throws IOException if an error occurs in parsing the 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);
|
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
|
//TCG_PCR_EVENT2
|
||||||
byte[] rawInt = new byte[INT_LENGTH];
|
if (is.available() > UefiConstants.SIZE_32) {
|
||||||
if (is.available() > MIN_SIZE) {
|
is.read(rawIndex);
|
||||||
is.read(rawInt);
|
setPcrIndex(rawIndex);
|
||||||
setPcrIndex(rawInt);
|
is.read(rawType);
|
||||||
is.read(rawInt);
|
setEventType(rawType);
|
||||||
setEventType(rawInt);
|
|
||||||
// TPML_DIGEST_VALUES
|
// TPML_DIGEST_VALUES
|
||||||
is.read(rawInt);
|
is.read(algCountBytes);
|
||||||
algCount = HexUtils.leReverseInt(rawInt);
|
algCount = HexUtils.leReverseInt(algCountBytes);
|
||||||
TcgTpmtHa hashAlg = null;
|
|
||||||
// Process TPMT_HA,
|
// Process TPMT_HA,
|
||||||
for (int i = 0; i < algCount; i++) {
|
for (int i = 0; i < algCount; i++) {
|
||||||
hashAlg = new TcgTpmtHa(is);
|
hashAlg = new TcgTpmtHa(is);
|
||||||
@ -87,11 +103,36 @@ public class TpmPcrEvent2 extends TpmPcrEvent {
|
|||||||
setEventDigest(hashAlg.getDigest());
|
setEventDigest(hashAlg.getDigest());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is.read(rawInt);
|
is.read(rawEventSize);
|
||||||
int eventSize = HexUtils.leReverseInt(rawInt);
|
eventSize = HexUtils.leReverseInt(rawEventSize);
|
||||||
byte[] eventContent = new byte[eventSize];
|
eventContent = new byte[eventSize];
|
||||||
is.read(eventContent);
|
is.read(eventContent);
|
||||||
setEventContent(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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
43
HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvIPL.java
Normal file
43
HIRS_Utils/src/main/java/hirs/tpm/eventlog/events/EvIPL.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Non-persistant classes related to TGC Event Logs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package hirs.tpm.eventlog.events;
|
||||||
|
|
@ -19,16 +19,30 @@ public final class UefiConstants {
|
|||||||
public static final int SIZE_5 = 5;
|
public static final int SIZE_5 = 5;
|
||||||
/** 8 byte size. */
|
/** 8 byte size. */
|
||||||
public static final int SIZE_8 = 8;
|
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. */
|
/** 16 byte size. */
|
||||||
public static final int SIZE_16 = 16;
|
public static final int SIZE_16 = 16;
|
||||||
/** 20 byte size. */
|
/** 20 byte size. */
|
||||||
public static final int SIZE_20 = 20;
|
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. */
|
/** 28 byte size. */
|
||||||
public static final int SIZE_28 = 28;
|
public static final int SIZE_28 = 28;
|
||||||
/** 32 byte size. */
|
/** 32 byte size. */
|
||||||
public static final int SIZE_32 = 32;
|
public static final int SIZE_32 = 32;
|
||||||
/** 40 byte size. */
|
/** 40 byte size. */
|
||||||
public static final int SIZE_40 = 40;
|
public static final int SIZE_40 = 40;
|
||||||
|
/** 128 byte size. */
|
||||||
|
public static final int SIZE_128 = 128;
|
||||||
/** 256 byte size. */
|
/** 256 byte size. */
|
||||||
public static final int SIZE_256 = 256;
|
public static final int SIZE_256 = 256;
|
||||||
/** 1 byte offset. */
|
/** 1 byte offset. */
|
||||||
@ -47,6 +61,10 @@ public final class UefiConstants {
|
|||||||
public static final int OFFSET_16 = 16;
|
public static final int OFFSET_16 = 16;
|
||||||
/** 20 byte offset. */
|
/** 20 byte offset. */
|
||||||
public static final int OFFSET_20 = 20;
|
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. */
|
/** 24 byte offset. */
|
||||||
public static final int OFFSET_24 = 24;
|
public static final int OFFSET_24 = 24;
|
||||||
/** 28 byte offset. */
|
/** 28 byte offset. */
|
||||||
|
@ -2,14 +2,16 @@ package hirs.tpm.eventlog;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
//import java.util.List;
|
||||||
import java.util.Set;
|
//import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.hibernate.Session;
|
//import org.hibernate.Session;
|
||||||
|
|
||||||
|
|
||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
@ -17,24 +19,18 @@ import org.testng.annotations.AfterClass;
|
|||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
/*
|
//import hirs.data.persist.Baseline;
|
||||||
import org.junit.Test;
|
//import hirs.data.persist.Digest;
|
||||||
import org.junit.AfterClass;
|
//import hirs.data.persist.SpringPersistenceTest;
|
||||||
import org.junit.Assert;
|
//import hirs.data.persist.TpmWhiteListBaseline;
|
||||||
import org.junit.BeforeClass;
|
//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.
|
* Class for testing TCG Event Log processing.
|
||||||
*/
|
*/
|
||||||
public class TCGEventLogProcessorTest extends SpringPersistenceTest {
|
//public class TCGEventLogProcessorTest extends SpringPersistenceTest {
|
||||||
private static final String DEFAULT_EVENT_LOG = "/tcgeventlog/TpmLog.bin";
|
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 DEFAULT_EXPECTED_PCRS = "/tcgeventlog/TpmLogExpectedPcrs.txt";
|
||||||
private static final String SHA1_EVENT_LOG = "/tcgeventlog/TpmLogSHA1.bin";
|
private static final String SHA1_EVENT_LOG = "/tcgeventlog/TpmLogSHA1.bin";
|
||||||
private static final String SHA1_EXPECTED_PCRS = "/tcgeventlog/TpmLogSHA1ExpectedPcrs.txt";
|
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.
|
* removing all <code>Baseline</code> objects.
|
||||||
*/
|
*/
|
||||||
// @AfterMethod
|
// @AfterMethod
|
||||||
|
/*
|
||||||
public final void resetTestState() {
|
public final void resetTestState() {
|
||||||
LOGGER.debug("reset test state");
|
LOGGER.debug("reset test state");
|
||||||
LOGGER.debug("deleting all baselines");
|
LOGGER.debug("deleting all baselines");
|
||||||
@ -77,13 +74,16 @@ public class TCGEventLogProcessorTest extends SpringPersistenceTest {
|
|||||||
LOGGER.debug("all baselines removed");
|
LOGGER.debug("all baselines removed");
|
||||||
session.getTransaction().commit();
|
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 IOException when processing the test fails
|
||||||
|
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
|
||||||
|
* @throws CertificateException if a certificate fails to parse.
|
||||||
*/
|
*/
|
||||||
@Test
|
@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");
|
LOGGER.debug("Testing the parsing of a Crypto Agile formatted TCG Event Log");
|
||||||
InputStream log, pcrs;
|
InputStream log, pcrs;
|
||||||
boolean testPass = true;
|
boolean testPass = true;
|
||||||
@ -116,15 +116,18 @@ public class TCGEventLogProcessorTest extends SpringPersistenceTest {
|
|||||||
/**
|
/**
|
||||||
* Tests the processing of a SHA1 formatted Event log.
|
* Tests the processing of a SHA1 formatted Event log.
|
||||||
* @throws IOException when processing the test fails
|
* @throws IOException when processing the test fails
|
||||||
|
* @throws NoSuchAlgorithmException if an unknown algorithm is encountered.
|
||||||
|
* @throws CertificateException if a certificate fails to parse.
|
||||||
*/
|
*/
|
||||||
@Test
|
@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");
|
LOGGER.debug("Testing the parsing of a SHA1 formated TCG Event Log");
|
||||||
InputStream log, pcrs;
|
InputStream log, pcrs;
|
||||||
boolean testPass = true;
|
boolean testPass = true;
|
||||||
log = this.getClass().getResourceAsStream(SHA1_EVENT_LOG);
|
log = this.getClass().getResourceAsStream(SHA1_EVENT_LOG);
|
||||||
byte[] rawLogBytes = IOUtils.toByteArray(log);
|
byte[] rawLogBytes = IOUtils.toByteArray(log);
|
||||||
TCGEventLogProcessor tlp = new TCGEventLogProcessor(rawLogBytes);
|
TCGEventLogProcessor tlp = new TCGEventLogProcessor(rawLogBytes);
|
||||||
String[] pcrFromLog = tlp.getExpectedPCRValues();
|
String[] pcrFromLog = tlp.getExpectedPCRValues();
|
||||||
pcrs = this.getClass().getResourceAsStream(SHA1_EXPECTED_PCRS);
|
pcrs = this.getClass().getResourceAsStream(SHA1_EXPECTED_PCRS);
|
||||||
Object[] pcrObj = IOUtils.readLines(pcrs).toArray();
|
Object[] pcrObj = IOUtils.readLines(pcrs).toArray();
|
||||||
@ -152,7 +155,8 @@ public class TCGEventLogProcessorTest extends SpringPersistenceTest {
|
|||||||
* Tests TPM Baseline creation from a EventLog.
|
* Tests TPM Baseline creation from a EventLog.
|
||||||
* @throws IOException when processing the test fails
|
* @throws IOException when processing the test fails
|
||||||
*/
|
*/
|
||||||
@Test
|
//@Test
|
||||||
|
/*
|
||||||
public final void testTPMBaselineCreate() throws IOException {
|
public final void testTPMBaselineCreate() throws IOException {
|
||||||
LOGGER.debug("Create and save TPM baseline from TCG Event Log test started");
|
LOGGER.debug("Create and save TPM baseline from TCG Event Log test started");
|
||||||
InputStream log;
|
InputStream log;
|
||||||
@ -182,4 +186,5 @@ public class TCGEventLogProcessorTest extends SpringPersistenceTest {
|
|||||||
Assert.assertTrue(testPass);
|
Assert.assertTrue(testPass);
|
||||||
LOGGER.debug("OK. Create and save TPM baseline from TCG Event Log was a success");
|
LOGGER.debug("OK. Create and save TPM baseline from TCG Event Log was a success");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Non-persistant classes related to TGC Event Logs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package hirs.tpm.eventlog.events;
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
1820d45800000000e0b405000000000000000000000000002c00000000000000040714002ce2edb630defa45bb09ca202c1654b7040614001ae3e1159d9f844c82fb1a707fc0f63b7fff0400
|
@ -0,0 +1 @@
|
|||||||
|
4546492050415254000001005c000000a071310c000000000100000000000000af44f21b0000000022000000000000008e44f21b000000006fe7c34e23793e4cb040e8080f1b888302000000000000008000000080000000d0be05490500000000000000a4bb94ded106404da16abfd50179d6ac8787cc4223db454e9981701adc801dc70008000000000000ffa70f000000000001000000000000804200610073006900630020006400610074006100200070006100720074006900740069006f006e00000000000000000000000000000000000000000000000000000000000000000028732ac11ff8d211ba4b00a0c93ec93b3c62a78c1e04ab4f8c12f49a86b85d7300a80f0000000000ffc712000000000000000000000000804500460049002000730079007300740065006d00200070006100720074006900740069006f006e00000000000000000000000000000000000000000000000000000000000000000016e3c9e35c0bb84d817df92df00215aeffcf90d80c32454fb6cfa4d8bee6d9cb00c8120000000000ffc71a000000000000000000000000804d006900630072006f0073006f0066007400200072006500730065007200760065006400200070006100720074006900740069006f006e0000000000000000000000000000000000a2a0d0ebe5b9334487c068b6b72699c71c4c250c124b884ab88442a31866a34800c81a0000000000ff3ff81a0000000000000000000000004200610073006900630020006400610074006100200070006100720074006900740069006f006e000000000000000000000000000000000000000000000000000000000000000000a4bb94ded106404da16abfd50179d6ac92e459bc0fb29549b1488ded030c7ec20040f81a00000000ff3ff21b0000000001000000000000804200610073006900630020006400610074006100200070006100720074006900740069006f006e000000a70afc7f00007051864ba8020000c091dc4ba8020000bf3a758076450000
|
@ -0,0 +1 @@
|
|||||||
|
53706563204944204576656e743033000000000000020002010000000b00200000
|
@ -0,0 +1 @@
|
|||||||
|
01000000000000004415fdf294972c4a992ee5bbcf20e3940000676300000000
|
@ -0,0 +1 @@
|
|||||||
|
414350492044415441
|
42
tools/tcg_rim_tool/generated_swidTag.swidtag
Normal file
42
tools/tcg_rim_tool/generated_swidTag.swidtag
Normal 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>
|
Loading…
Reference in New Issue
Block a user