mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-18 20:47:58 +00:00
Merge pull request #778 from nsacyber/v3_issue_768_Part2-eventProcessing
Event processing when no access to vendor-table.json Part 2
This commit is contained in:
commit
78d85bddfd
@ -124,7 +124,7 @@ ospackage {
|
||||
// copy json tables
|
||||
into ('/etc/hirs/aca/default-properties') {
|
||||
from '../HIRS_AttestationCA/src/main/resources/component-class.json'
|
||||
from '../HIRS_AttestationCA/src/main/resources/vendor-table.json'
|
||||
from '../HIRS_Utils/src/main/resources/vendor-table.json'
|
||||
}
|
||||
// copy springboot property file
|
||||
into ('/etc/hirs/aca/') {
|
||||
|
@ -97,4 +97,75 @@ public final class JsonUtils {
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the JSON Object that is associated with the elementName value
|
||||
* mapped in the associated JSON file.
|
||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||
*
|
||||
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
||||
* @param elementName the specific object to pull from the file
|
||||
* @return a JSON object
|
||||
*/
|
||||
public static JsonObject getSpecificJsonObject(final String jsonFilename, final String elementName) {
|
||||
// find the file and load it
|
||||
return getSpecificJsonObject(jsonFilename, elementName, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the JSON Object that is associated with the elementName value
|
||||
* mapped in the associated JSON file.
|
||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||
*
|
||||
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
||||
* @param elementName the specific object to pull from the file
|
||||
* @param charset the character set to use
|
||||
* @return a JSON object
|
||||
*/
|
||||
public static JsonObject getSpecificJsonObject(final String jsonFilename,
|
||||
final String elementName,
|
||||
final Charset charset) {
|
||||
// find the file and load it
|
||||
JsonObject jsonObject = getJsonObject(jsonFilename, charset);
|
||||
|
||||
if (jsonObject != null && jsonObject.get(elementName) != null) {
|
||||
return jsonObject.get(elementName).asObject();
|
||||
}
|
||||
|
||||
return new JsonObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the JSON Object that is mapped in the associated JSON file.
|
||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||
*
|
||||
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
||||
* @return a JSON object
|
||||
*/
|
||||
public static JsonObject getJsonObject(final String jsonFilename) {
|
||||
return getJsonObject(jsonFilename, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the JSON Object that is mapped in the associated JSON file.
|
||||
*
|
||||
* @param jsonFilename the object holding the name of the file in classpath to parse.
|
||||
* @param charset the character set to use
|
||||
* @return a JSON object
|
||||
*/
|
||||
public static JsonObject getJsonObject(final String jsonFilename, final Charset charset) {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
|
||||
InputStream jsonIs = JsonUtils.class.getClassLoader().getResourceAsStream(jsonFilename);
|
||||
if (jsonIs != null) {
|
||||
try {
|
||||
jsonObject = Json.parse(new InputStreamReader(jsonIs,
|
||||
charset)).asObject();
|
||||
} catch (IOException ex) {
|
||||
jsonObject = new JsonObject();
|
||||
}
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ import java.security.cert.CertificateException;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM;
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
|
||||
|
||||
/**
|
||||
* Class for handling different formats of TCG Event logs.
|
||||
*/
|
||||
@ -77,6 +80,15 @@ public final class TCGEventLog {
|
||||
/** Event Output Flag use. */
|
||||
@Getter
|
||||
private boolean bCryptoAgile = false;
|
||||
/**
|
||||
* Track status of vendor-table.json
|
||||
* This is only used if there is an event that uses a UefiVariable data structure.
|
||||
* Default is normal status (normal status is from-filesystem).
|
||||
* Status will only change IF there is a UefiVariable event in this log,
|
||||
* and if that event causes a different status.
|
||||
*/
|
||||
@Getter
|
||||
private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM;
|
||||
|
||||
/**
|
||||
* Default blank object constructor.
|
||||
@ -147,6 +159,20 @@ public final class TCGEventLog {
|
||||
} else {
|
||||
eventList.put(eventNumber, new TpmPcrEvent1(is, eventNumber++));
|
||||
}
|
||||
// first check if any previous event has not been able to access vendor-table.json,
|
||||
// and if that is the case, the first comparison in the if returns false and
|
||||
// the if statement is not executed
|
||||
// [previous event file status = vendorTableFileStatus]
|
||||
// (ie. keep the file status to reflect that file was not accessible at some point)
|
||||
// next, check if the new event has any status other than the default 'filesystem',
|
||||
// and if that is the case, the 2nd comparison in the if returns true and
|
||||
// the if statement is executed
|
||||
// [new event file status = eventList.get(eventNumber-1).getVendorTableFileStatus()]
|
||||
// (ie. if the new file status is not-accessible or from-code, then want to update)
|
||||
if((vendorTableFileStatus != FILESTATUS_NOT_ACCESSIBLE) &&
|
||||
(eventList.get(eventNumber-1).getVendorTableFileStatus() != FILESTATUS_FROM_FILESYSTEM)) {
|
||||
vendorTableFileStatus = eventList.get(eventNumber-1).getVendorTableFileStatus();
|
||||
}
|
||||
}
|
||||
calculatePcrValues();
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM;
|
||||
|
||||
/**
|
||||
* Class to process a TCG_PCR_EVENT.
|
||||
* TCG_PCR_EVENT is used when the Event log uses the SHA1 Format as described in the
|
||||
@ -117,6 +119,16 @@ public class TpmPcrEvent {
|
||||
@Setter @Getter
|
||||
private boolean error = false;
|
||||
|
||||
/**
|
||||
* Track status of vendor-table.json
|
||||
* This is only used for events that use a UefiVariable data structure.
|
||||
* Default is normal status (normal status is from-filesystem).
|
||||
* Status will only change IF this is an event that has a UefiVariable,
|
||||
* and if that event causes a different status.
|
||||
*/
|
||||
@Getter
|
||||
private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@ -508,9 +520,12 @@ public class TpmPcrEvent {
|
||||
String efiVarDescription = efiVar.toString().replace("\n", "\n ");
|
||||
description += "Event Content:\n " + efiVarDescription.substring(0,
|
||||
efiVarDescription.length() - INDENT_3);
|
||||
vendorTableFileStatus = efiVar.getVendorTableFileStatus();
|
||||
break;
|
||||
case EvConstants.EV_EFI_VARIABLE_BOOT:
|
||||
description += "Event Content:\n" + new UefiVariable(content).toString();
|
||||
UefiVariable efiVarBoot = new UefiVariable(content);
|
||||
description += "Event Content:\n" + efiVarBoot.toString();
|
||||
vendorTableFileStatus = efiVarBoot.getVendorTableFileStatus();
|
||||
break;
|
||||
case EvConstants.EV_EFI_BOOT_SERVICES_APPLICATION:
|
||||
EvEfiBootServicesApp bootServices = new EvEfiBootServicesApp(content);
|
||||
@ -539,7 +554,9 @@ public class TpmPcrEvent {
|
||||
case EvConstants.EV_EFI_HCRTM_EVENT:
|
||||
break;
|
||||
case EvConstants.EV_EFI_VARIABLE_AUTHORITY:
|
||||
description += "Event Content:\n" + new UefiVariable(content).toString();
|
||||
UefiVariable efiVarAuth = new UefiVariable(content);
|
||||
description += "Event Content:\n" + efiVarAuth.toString();
|
||||
vendorTableFileStatus = efiVarAuth.getVendorTableFileStatus();
|
||||
break;
|
||||
case EvConstants.EV_EFI_SPDM_FIRMWARE_BLOB:
|
||||
description += "Event Content:\n" + new EvEfiSpdmFirmwareBlob(content).toString();
|
||||
|
@ -23,7 +23,7 @@ import java.nio.charset.StandardCharsets;
|
||||
* NUL-terminated, per PFP. The only currently defined Signature is "SPDM Device Sec",
|
||||
* which implies the data is a DEVICE_SECURITY_EVENT_DATA or ..DATA2.
|
||||
* The EV_EFI_SPDM_FIRMWARE_BLOB event is used to record an extended digest for the firmware of
|
||||
* an embedded component or an add-in device that supports SPDM “GET_MEASUREMENTS” functionality.
|
||||
* an embedded component or an add-in device that supports SPDM "GET_MEASUREMENTS" functionality.
|
||||
* This event records extended digests of SPDM GET_MEASUREMENT responses that correspond to
|
||||
* firmware, such as immutable ROM, mutable firmware, firmware version, firmware secure version
|
||||
* number, etc.
|
||||
|
@ -271,4 +271,19 @@ public final class UefiConstants {
|
||||
* standard UEFI partition table lengh.
|
||||
*/
|
||||
public static final int UEFI_PT_LENGTH = 72;
|
||||
/**
|
||||
* file status, where file was successfully found on local machine.
|
||||
*/
|
||||
public static final String FILESTATUS_FROM_FILESYSTEM = "fileFromFilesystem";
|
||||
/**
|
||||
* file status, where file was not found on local machine, so file from code was used.
|
||||
* For instance, if vendor-table.json is not found in filesystem at location
|
||||
* /etc/hirs/aca/default-properties/, it will be grabbed from code at
|
||||
* HIRS_AttestationCA/src/main/resources/.
|
||||
*/
|
||||
public static final String FILESTATUS_FROM_CODE = "fileFromCode";
|
||||
/**
|
||||
* file status, where file is not accessible (either not found, or no access permission).
|
||||
*/
|
||||
public static final String FILESTATUS_NOT_ACCESSIBLE = "fileNotAccessible";
|
||||
}
|
||||
|
@ -3,12 +3,17 @@ package hirs.utils.tpm.eventlog.uefi;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import hirs.utils.HexUtils;
|
||||
import hirs.utils.JsonUtils;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.util.UUID;
|
||||
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_CODE;
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM;
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
|
||||
|
||||
/**
|
||||
* Class to process GUID per the UEFI specification
|
||||
* GUIDs are essentially UUID as defined by RFC-1422, however Microsoft refers to GUIDS.
|
||||
@ -22,10 +27,25 @@ public class UefiGuid {
|
||||
* used for conversion to uuid time.
|
||||
*/
|
||||
private static final int UUID_EPOCH_DIVISOR = 10000;
|
||||
|
||||
/**
|
||||
* Filesystem path of vendor-table.json
|
||||
*/
|
||||
private static final Path JSON_PATH = FileSystems.getDefault().getPath("/etc",
|
||||
"hirs", "aca", "default-properties", "vendor-table.json");
|
||||
/**
|
||||
* Name of vendor-table file in code
|
||||
*/
|
||||
private static final String JSON_FILENAME = "vendor-table.json";
|
||||
/**
|
||||
* Reference to the vendor-table json object
|
||||
*/
|
||||
private JsonObject uefiVendorRef;
|
||||
/**
|
||||
* Track status of vendor-table.json
|
||||
*/
|
||||
@Getter
|
||||
private String vendorTableFileStatus = FILESTATUS_NOT_ACCESSIBLE;
|
||||
|
||||
/**
|
||||
* guid byte array.
|
||||
*/
|
||||
@ -41,10 +61,7 @@ public class UefiGuid {
|
||||
* @param guidBytes byte array holding a valid guid.
|
||||
*/
|
||||
public UefiGuid(final byte[] guidBytes) {
|
||||
guid = new byte[UefiConstants.SIZE_16];
|
||||
System.arraycopy(guidBytes, 0, guid, 0, UefiConstants.SIZE_16);
|
||||
uuid = processGuid(guidBytes);
|
||||
uefiVendorRef = JsonUtils.getSpecificJsonObject(JSON_PATH, "VendorTable");
|
||||
this(guidBytes, JSON_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,6 +76,17 @@ public class UefiGuid {
|
||||
uuid = processGuid(guidBytes);
|
||||
uefiVendorRef = JsonUtils.getSpecificJsonObject(vendorPathString,
|
||||
"VendorTable");
|
||||
|
||||
if(!isVendorTableReferenceHandleEmpty()) {
|
||||
vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM;
|
||||
}
|
||||
else {
|
||||
// could not access vendor-table.json from filesystem, so attempt to access from code
|
||||
uefiVendorRef = JsonUtils.getSpecificJsonObject(JSON_FILENAME, "VendorTable");
|
||||
if(!isVendorTableReferenceHandleEmpty()) {
|
||||
vendorTableFileStatus = FILESTATUS_FROM_CODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,6 +125,16 @@ public class UefiGuid {
|
||||
return UefiConstants.SIZE_16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the handle to the file needed to look up the UUID is valid. If empty,
|
||||
* this likely means the file was not accessible to due to existence or permissions.
|
||||
*
|
||||
* @return true if the reference to the file handle needed to look up the UUID is empty
|
||||
*/
|
||||
public boolean isVendorTableReferenceHandleEmpty() {
|
||||
return uefiVendorRef.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String that represents a specification name referenced by the
|
||||
* EFI_CONFIGURATION_TABLE VendorGUID field. For structure of
|
||||
|
@ -9,6 +9,8 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
|
||||
|
||||
/**
|
||||
* Class for processing the contents of a Secure Boot DB or DBX contents.
|
||||
* used for EFIVariables associated with Secure Boot
|
||||
@ -69,6 +71,11 @@ public class UefiSignatureList {
|
||||
* Type of signature.
|
||||
*/
|
||||
private UefiGuid signatureType = null;
|
||||
/**
|
||||
* Track status of vendor-table.json
|
||||
*/
|
||||
@Getter
|
||||
private String vendorTableFileStatus = FILESTATUS_NOT_ACCESSIBLE;
|
||||
|
||||
/**
|
||||
* UefiSignatureList constructor.
|
||||
@ -84,6 +91,7 @@ public class UefiSignatureList {
|
||||
byte[] guid = new byte[UefiConstants.SIZE_16];
|
||||
System.arraycopy(list, 0, guid, 0, UefiConstants.SIZE_16);
|
||||
signatureType = new UefiGuid(guid);
|
||||
vendorTableFileStatus = signatureType.getVendorTableFileStatus();
|
||||
|
||||
byte[] lSize = new byte[UefiConstants.SIZE_4];
|
||||
System.arraycopy(list, UefiConstants.OFFSET_16, lSize, 0, UefiConstants.SIZE_4);
|
||||
@ -114,6 +122,7 @@ public class UefiSignatureList {
|
||||
byte[] guid = new byte[UefiConstants.SIZE_16];
|
||||
lists.read(guid);
|
||||
signatureType = new UefiGuid(guid);
|
||||
vendorTableFileStatus = signatureType.getVendorTableFileStatus();
|
||||
|
||||
// if signatureType is invalid, don't even process any of the data
|
||||
// however, if signatureTYpe is valid, but some of the data later on is invalid, that will
|
||||
|
@ -12,6 +12,9 @@ import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_FILESYSTEM;
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
|
||||
|
||||
/**
|
||||
* Class to process a UEFI variable within a TPM Event.
|
||||
* typedef struct tdUEFI_VARIABLE_DATA{
|
||||
@ -63,6 +66,15 @@ public class UefiVariable {
|
||||
*/
|
||||
private byte[] uefiVariableData = null;
|
||||
|
||||
/**
|
||||
* Track status of vendor-table.json.
|
||||
* The default here is that each list correctly grabbed the file from file system.
|
||||
* If any one list has issues, this overall status will change to reflect the
|
||||
* problematic list's status.
|
||||
*/
|
||||
@Getter
|
||||
private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM;
|
||||
|
||||
/**
|
||||
* EFIVariable constructor.
|
||||
* The UEFI_VARIABLE_DATA contains a "VariableName" field which is used to determine
|
||||
@ -146,6 +158,22 @@ public class UefiVariable {
|
||||
while (certData.available() > 0) {
|
||||
UefiSignatureList list;
|
||||
list = new UefiSignatureList(certData);
|
||||
|
||||
// first check if any previous list has not been able to access vendor-table.json,
|
||||
// and if that is the case, the first comparison in the if returns false and
|
||||
// the if statement is not executed
|
||||
// [previous event file status = vendorTableFileStatus]
|
||||
// (ie. keep the file status to reflect that file was not accessible at some point)
|
||||
// next, check if the new list has any status other than the default 'filesystem',
|
||||
// and if that is the case, the 2nd comparison in the if returns true and
|
||||
// the if statement is executed
|
||||
// [new event file status = list.getVendorTableFileStatus()]
|
||||
// (ie. if the new file status is not-accessible or from-code, then want to update)
|
||||
if((vendorTableFileStatus != FILESTATUS_NOT_ACCESSIBLE) &&
|
||||
(list.getVendorTableFileStatus() != FILESTATUS_FROM_FILESYSTEM)) {
|
||||
vendorTableFileStatus = list.getVendorTableFileStatus();
|
||||
}
|
||||
|
||||
// efiVariableSigListContents += list.toString();
|
||||
if(!list.isSignatureTypeValid()) {
|
||||
invalidSignatureListEncountered = true;
|
||||
@ -163,6 +191,7 @@ public class UefiVariable {
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder efiVariable = new StringBuilder();
|
||||
|
||||
efiVariable.append("UEFI Variable Name: " + efiVarName + "\n");
|
||||
efiVariable.append("UEFI Variable GUID: " + uefiVarGuid.toString() + "\n");
|
||||
if (efiVarName != "") {
|
||||
|
@ -17,7 +17,7 @@ ACA_VERSION_FILE="/opt/hirs/aca/VERSION"
|
||||
SPRING_PROP_FILE="/etc/hirs/aca/application.properties"
|
||||
PROP_FILE='../../../HIRS_AttestationCAPortal/src/main/resources/application.properties'
|
||||
COMP_JSON='../../../HIRS_AttestationCA/src/main/resources/component-class.json'
|
||||
VENDOR_TABLE='../../../HIRS_AttestationCA/src/main/resources/vendor-table.json'
|
||||
VENDOR_TABLE='../../../HIRS_Utils/src/main/resources/vendor-table.json'
|
||||
|
||||
help () {
|
||||
echo " Setup script for the HIRS ACA"
|
||||
|
@ -8,7 +8,7 @@ param (
|
||||
$APP_HOME=(Split-Path -parent $PSCommandPath)
|
||||
$ACA_COMMON_SCRIPT=(Join-Path $APP_HOME 'aca_common.ps1')
|
||||
$COMP_JSON=(Join-Path $APP_HOME '..' '..' '..' 'HIRS_AttestationCA' 'src' 'main' 'resources' 'component-class.json')
|
||||
$VENDOR_TABLE=(Join-Path $APP_HOME '..' '..' '..' 'HIRS_AttestationCA' 'src' 'main' 'resources' 'vendor-table.json')
|
||||
$VENDOR_TABLE=(Join-Path $APP_HOME '..' '..' '..' 'HIRS_Utils' 'src' 'main' 'resources' 'vendor-table.json')
|
||||
|
||||
# Load other scripts
|
||||
. $ACA_COMMON_SCRIPT
|
||||
|
@ -16,6 +16,9 @@ import hirs.utils.tpm.eventlog.TCGEventLog;
|
||||
import hirs.utils.tpm.eventlog.TpmPcrEvent;
|
||||
import hirs.utils.HexUtils;
|
||||
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_FROM_CODE;
|
||||
import static hirs.utils.tpm.eventlog.uefi.UefiConstants.FILESTATUS_NOT_ACCESSIBLE;
|
||||
|
||||
/**
|
||||
* Command-line application for processing TCG Event Logs.
|
||||
* Input arg: path to *.tcglp file
|
||||
@ -127,6 +130,19 @@ final class Main {
|
||||
writeOut("\nEvent Log follows the \"SHA1\" format and has "
|
||||
+ evLog.getEventList().size() + " events:\n\n");
|
||||
}
|
||||
if (evLog.getVendorTableFileStatus() == FILESTATUS_NOT_ACCESSIBLE) {
|
||||
writeOut("*** WARNING: The file vendor-table.json file was not accessible so data " +
|
||||
"in some Secure Boot PCR 7 events cannot be processed.\n\n");
|
||||
}
|
||||
else if (evLog.getVendorTableFileStatus() == FILESTATUS_FROM_CODE) {
|
||||
writeOut("*** NOTE: " +
|
||||
"The file vendor-table.json file was not accessible from the filesystem,\n" +
|
||||
" so the vendor-table.json from code was " +
|
||||
"used. If updates were made in the\n" +
|
||||
" filesystem file, they will not be reflected. " +
|
||||
"This affects parsing in some\n" +
|
||||
" Secure Boot PCR 7 events.\n\n");
|
||||
}
|
||||
}
|
||||
int eventCount = 0;
|
||||
for (TpmPcrEvent event : evLog.getEventList()) {
|
||||
|
Loading…
Reference in New Issue
Block a user