Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix pciids calls from windows machines #843

Merged
merged 14 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading