Skip to content

Commit

Permalink
Merge pull request #843 from nsacyber/v3_issue_836-spdm
Browse files Browse the repository at this point in the history
fix pciids calls from windows machines
  • Loading branch information
iadgovuser58 authored Oct 24, 2024
2 parents d908fda + 99e0c84 commit b163691
Show file tree
Hide file tree
Showing 14 changed files with 38,637 additions and 97 deletions.
4 changes: 3 additions & 1 deletion HIRS_AttestationCAPortal/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,9 @@ ospackage {
requires('mariadb-server' , '10.3' , GREATER | EQUAL)
requires('procps-ng', '3.3.15', GREATER | EQUAL)
requires('alternatives', '1.19', GREATER | EQUAL)
requires('hwdata', '0.314', GREATER | EQUAL)
// Post Trans stage (Occurs after required app and postInstall stage)
// Note postInstall wont wait forrequired apps
// Note postInstall wont wait for required apps
postTrans 'update-alternatives --set java java-17-openjdk.x86_64'
postTrans 'firewall-cmd --add-port=8443/tcp --permanent'
postTrans 'firewall-cmd --reload'
Expand All @@ -181,6 +182,7 @@ ospackage {
requires('openjdk-17-jdk', '17.0', GREATER | EQUAL)
requires('mariadb-server' , '10.3' , GREATER | EQUAL)
requires('curl')
requires('hwdata', '0.314', GREATER | EQUAL)
// Install after required packages
postInstall 'bash /opt/hirs/aca/scripts/aca/aca_setup.sh -u'
postInstall 'bash /opt/hirs/aca/scripts/systemd/aca_enable_service.sh'
Expand Down
119 changes: 75 additions & 44 deletions HIRS_Utils/src/main/java/hirs/utils/PciIds.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.github.marandus.pciid.model.Vendor;
import com.github.marandus.pciid.service.PciIdsDatabase;
import com.google.common.base.Strings;
import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.bouncycastle.asn1.ASN1UTF8String;
import org.bouncycastle.asn1.DERUTF8String;
Expand All @@ -25,30 +27,46 @@
@Log4j2
public final class PciIds {

/**
* Track status of pciids file.
*/
@Getter
private static String pciidsFileStatus = UefiConstants.FILESTATUS_NOT_ACCESSIBLE;

/**
* Name of pciids file in code.
*/
private static final String PCIIDS_FILENAME = "/pci.ids";

/**
* This pci ids file can be in different places on different distributions.
* Fedora/RHEL/Rocky/CentOS: /usr/share/hwdata/pci.ids
* Debian/Ubuntu: /usr/share/misc/pci.ids
* If the file is not found on the system (such as with Windows systems),
* the file will have to be accessed from code.
*/
public static final List<String> PCI_IDS_PATH =
Collections.unmodifiableList(new ArrayList<>() {
private static final long serialVersionUID = 1L;

{
add("/usr/share/hwdata/pci.ids");
add("/usr/share/misc/pci.ids");
add("/tmp/pci.ids");
}
});

/**
* The PCI IDs Database object.
* <p>
* This only needs to be loaded one time.
* <p>
* The pci ids library protects the data inside the object by making it immutable.
*/
public static final PciIdsDatabase DB = new PciIdsDatabase();

//Configure the PCI IDs Database object.
static {
if (!DB.isReady()) {

// if pciids file is found on the system, then process using this file
String dbFile = null;
for (final String path : PCI_IDS_PATH) {
if ((new File(path)).exists()) {
Expand All @@ -57,11 +75,13 @@ public final class PciIds {
break;
}
}
if (dbFile != null) {

if(dbFile != null) {
InputStream is = null;
try {
is = new FileInputStream(dbFile);
DB.loadStream(is);
pciidsFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
} catch (IOException e) {
// DB will not be ready, hardware IDs will not be translated
dbFile = null;
Expand All @@ -75,25 +95,48 @@ public final class PciIds {
}
}
}

// if pciids file is not found on the system or not accessible, then attempt to grab it from code
if(pciidsFileStatus == UefiConstants.FILESTATUS_NOT_ACCESSIBLE) {
InputStream isFromCode = PciIds.class.getResourceAsStream(PCIIDS_FILENAME);
if(isFromCode != null) {
try {
DB.loadStream(isFromCode);
pciidsFileStatus = UefiConstants.FILESTATUS_FROM_CODE;
} catch (IOException e) {
// DB will not be ready, hardware IDs will not be translated
} finally {
try {
isFromCode.close();
} catch (IOException e) {
}
}
}
}

// if pciids file is not accessible on system or from within code, then log error
if(pciidsFileStatus == UefiConstants.FILESTATUS_NOT_ACCESSIBLE) {
log.info("PCI IDs file was NOT accessible from within the system or within the code");
}
}
}

/**
* Default private constructor so checkstyles doesn't complain.
* Default private constructor so checkstyles doesn't complain
*/
private PciIds() {
}
private PciIds() { }

/**
* Look up the vendor name from the PCI IDs list, if the input string contains an ID.
* If any part of this fails, return the original manufacturer value.
*
* @param refManufacturer DERUTF8String, likely from a ComponentIdentifier
* @return DERUTF8String with the discovered vendor name, or the original manufacturer value.
*/
public static ASN1UTF8String translateVendor(final ASN1UTF8String refManufacturer) {
ASN1UTF8String manufacturer = refManufacturer;
if (manufacturer != null && manufacturer.getString().trim().matches("^[0-9A-Fa-f]{4}$")) {
if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& manufacturer != null
&& manufacturer.getString().trim().matches("^[0-9A-Fa-f]{4}$")) {
Vendor ven = DB.findVendor(manufacturer.getString().toLowerCase());
if (ven != null && !Strings.isNullOrEmpty(ven.getName())) {
manufacturer = new DERUTF8String(ven.getName());
Expand All @@ -105,13 +148,14 @@ public static ASN1UTF8String translateVendor(final ASN1UTF8String refManufacture
/**
* Look up the vendor name from the PCI IDs list, if the input string contains an ID.
* If any part of this fails, return the original manufacturer value.
*
* @param refManufacturer String, likely from a ComponentResult
* @return String with the discovered vendor name, or the original manufacturer value.
*/
public static String translateVendor(final String refManufacturer) {
String manufacturer = refManufacturer;
if (manufacturer != null && manufacturer.trim().matches("^[0-9A-Fa-f]{4}$")) {
if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& manufacturer != null
&& manufacturer.trim().matches("^[0-9A-Fa-f]{4}$")) {
Vendor ven = DB.findVendor(manufacturer.toLowerCase());
if (ven != null && !Strings.isNullOrEmpty(ven.getName())) {
manufacturer = ven.getName();
Expand All @@ -124,16 +168,16 @@ public static String translateVendor(final String refManufacturer) {
* Look up the device name from the PCI IDs list, if the input strings contain IDs.
* The Device lookup requires the Vendor ID AND the Device ID to be valid values.
* If any part of this fails, return the original model value.
*
* @param refManufacturer ASN1UTF8String, likely from a ComponentIdentifier
* @param refModel ASN1UTF8String, likely from a ComponentIdentifier
* @param refModel ASN1UTF8String, likely from a ComponentIdentifier
* @return ASN1UTF8String with the discovered device name, or the original model value.
*/
public static ASN1UTF8String translateDevice(final ASN1UTF8String refManufacturer,
final ASN1UTF8String refModel) {
ASN1UTF8String manufacturer = refManufacturer;
ASN1UTF8String model = refModel;
if (manufacturer != null
if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& manufacturer != null
&& model != null
&& manufacturer.getString().trim().matches("^[0-9A-Fa-f]{4}$")
&& model.getString().trim().matches("^[0-9A-Fa-f]{4}$")) {
Expand All @@ -150,15 +194,15 @@ public static ASN1UTF8String translateDevice(final ASN1UTF8String refManufacture
* Look up the device name from the PCI IDs list, if the input strings contain IDs.
* The Device lookup requires the Vendor ID AND the Device ID to be valid values.
* If any part of this fails, return the original model value.
*
* @param refManufacturer String, likely from a ComponentResult
* @param refModel String, likely from a ComponentResult
* @param refModel String, likely from a ComponentResult
* @return String with the discovered device name, or the original model value.
*/
public static String translateDevice(final String refManufacturer,
final String refModel) {
String model = refModel;
if (refManufacturer != null
if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& refManufacturer != null
&& model != null
&& refManufacturer.trim().matches("^[0-9A-Fa-f]{4}$")
&& model.trim().matches("^[0-9A-Fa-f]{4}$")) {
Expand All @@ -174,39 +218,26 @@ public static String translateDevice(final String refManufacturer,
/**
* Look up the device class name from the PCI IDs list, if the input string contains an ID.
* If any part of this fails, return the original manufacturer value.
*
* @param refClassCode String, formatted as 2 characters (1 byte) for each of the 3 categories
* Example "010802":
* Class: "01"
* Subclass: "08"
* Programming Interface: "02"
* Example "010802":
* Class: "01"
* Subclass: "08"
* Programming Interface: "02"
* @return List<String> 3-element list with the class code
* 1st element: human-readable description of Class
* 2nd element: human-readable description of Subclass
* 3rd element: human-readable description of Programming Interface
* 1st element: human-readable description of Class
* 2nd element: human-readable description of Subclass
* 3rd element: human-readable description of Programming Interface
*/
public static List<String> translateDeviceClass(final String refClassCode) {
List<String> translatedClassCode = new ArrayList<>();

String classCode = refClassCode;
if (classCode != null && classCode.trim().matches("^[0-9A-Fa-f]{6}$")) {
final int startIndexOfDeviceClass = 0;
final int endIndexOfDeviceClass = 2;
String deviceClass =
classCode.substring(startIndexOfDeviceClass, endIndexOfDeviceClass).toLowerCase();

final int startIndexOfDeviceSubclass = 2;
final int endIndexOfDeviceSubclass = 4;
String deviceSubclass =
classCode.substring(startIndexOfDeviceSubclass, endIndexOfDeviceSubclass)
.toLowerCase();

final int startIndexOfProgramInterface = 4;
final int endIndexOfProgramInterface = 6;
final String programInterface =
classCode.substring(startIndexOfProgramInterface, endIndexOfProgramInterface)
.toLowerCase();

if (!pciidsFileStatus.equals(UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& classCode != null
&& classCode.trim().matches("^[0-9A-Fa-f]{6}$")) {
String deviceClass = classCode.substring(0, 2).toLowerCase();
String deviceSubclass = classCode.substring(2, 4).toLowerCase();
String programInterface = classCode.substring(4, 6).toLowerCase();
translatedClassCode.add(deviceClass);
translatedClassCode.add(deviceSubclass);
translatedClassCode.add(programInterface);
Expand All @@ -225,4 +256,4 @@ public static List<String> translateDeviceClass(final String refClassCode) {
}
return translatedClassCode;
}
}
}
24 changes: 18 additions & 6 deletions HIRS_Utils/src/main/java/hirs/utils/tpm/eventlog/TCGEventLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
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.
*/
Expand Down Expand Up @@ -88,7 +85,16 @@ public final class TCGEventLog {
* and if that event causes a different status.
*/
@Getter
private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM;
private String vendorTableFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;
/**
* Track status of pci.ids
* This is only used if there is an event that uses functions from the pciids class.
* Default is normal status (normal status is from-filesystem).
* Status will only change IF there is an event that uses pciids file, and the file
* causes a different status.
*/
@Getter
private String pciidsFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;

/**
* Default blank object constructor.
Expand Down Expand Up @@ -169,11 +175,17 @@ public TCGEventLog(final byte[] rawlog, final boolean bEventFlag,
// 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)
if ((vendorTableFileStatus != UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& (eventList.get(eventNumber - 1).getVendorTableFileStatus()
!= FILESTATUS_FROM_FILESYSTEM)) {
!= UefiConstants.FILESTATUS_FROM_FILESYSTEM)) {
vendorTableFileStatus = eventList.get(eventNumber - 1).getVendorTableFileStatus();
}
//similar to above with vendor-table.json file, but here with pci.ids file
if ((pciidsFileStatus != UefiConstants.FILESTATUS_NOT_ACCESSIBLE)
&& (eventList.get(eventNumber - 1).getPciidsFileStatus()
!= UefiConstants.FILESTATUS_FROM_FILESYSTEM)) {
pciidsFileStatus = eventList.get(eventNumber - 1).getPciidsFileStatus();
}
}
calculatePcrValues();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ public class TpmPcrEvent {
@Getter
private String vendorTableFileStatus = FILESTATUS_FROM_FILESYSTEM;

/**
* Track status of pci.ids
* This is only used for events that access the pci.ids file.
* Default is normal status (normal status is from-filesystem).
* Status will only change IF this is an event that uses this file,
* and if that event causes a different status.
*/
@Getter
private String pciidsFileStatus = FILESTATUS_FROM_FILESYSTEM;

/**
* Constructor.
*
Expand Down Expand Up @@ -438,6 +448,7 @@ public String processEvent(final byte[] eventData, final byte[] content,
specVersion = noAction.getSpecVersion();
specErrataVersion = noAction.getSpecErrataVersion();
}
pciidsFileStatus = noAction.getPciidsFileStatus();
break;
case EvConstants.EV_SEPARATOR:
if (EvPostCode.isAscii(content)) {
Expand Down Expand Up @@ -523,7 +534,9 @@ public String processEvent(final byte[] eventData, final byte[] content,
break;
case EvConstants.EV_EFI_SPDM_FIRMWARE_BLOB:
case EvConstants.EV_EFI_SPDM_FIRMWARE_CONFIG:
description += "Event Content:\n" + new EvEfiSpdmDeviceSecurityEvent(content).toString();
EvEfiSpdmDeviceSecurityEvent efiSpdmDse = new EvEfiSpdmDeviceSecurityEvent(content);
description += "Event Content:\n" + efiSpdmDse.toString();
pciidsFileStatus = efiSpdmDse.getPciidsFileStatus();
break;
default:
description += " Unknown Event found" + "\n";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package hirs.utils.tpm.eventlog.events;

import hirs.utils.tpm.eventlog.uefi.UefiConstants;
import lombok.Getter;
import lombok.Setter;

Expand Down Expand Up @@ -44,7 +45,7 @@ public abstract class DeviceSecurityEvent {
* DeviceSecurityEventDataContext Object.
*/
@Getter
private DeviceSecurityEventDataDeviceContext dsedDevContext = null;
private DeviceSecurityEventDataPciContext dsedPciContext = null;

/**
* Device type.
Expand All @@ -60,6 +61,17 @@ public abstract class DeviceSecurityEvent {
@Getter
private String deviceContextInfo = "";

/**
* Track status of pci.ids
* This is only used for events that access the pci.ids file.
* (In this class, this is only needed if DeviceSecurityEvent includes a DeviceSecurityEventDataPciContext)
* Default is normal status (normal status is from-filesystem).
* Status will only change IF this is an event that uses this file,
* and if that event causes a different status.
*/
@Getter
private String pciidsFileStatus = UefiConstants.FILESTATUS_FROM_FILESYSTEM;

/**
* DeviceSecurityEventData Default Constructor.
*
Expand All @@ -82,8 +94,11 @@ public void instantiateDeviceContext(final byte[] dsedDeviceContextBytes) {
if (deviceType == DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_NONE) {
deviceContextInfo = "\n No Device Context (indicated by device type value of 0)";
} else if (deviceType == DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_PCI) {
dsedDevContext = new DeviceSecurityEventDataPciContext(dsedDeviceContextBytes);
deviceContextInfo = dsedDevContext.toString();
dsedPciContext = new DeviceSecurityEventDataPciContext(dsedDeviceContextBytes);
deviceContextInfo = dsedPciContext.toString();
// getPciidsFileStatus() must be called after DeviceSecurityEventDataPciContext.toString(),
// because the toString function is where the pciids db gets set up and used
pciidsFileStatus = dsedPciContext.getPciidsFileStatus();
} else if (deviceType == DeviceSecurityEventDataDeviceContext.DEVICE_TYPE_USB) {
deviceContextInfo = " Device Type: USB - To be implemented";
} else {
Expand Down
Loading

0 comments on commit b163691

Please sign in to comment.