mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-06-13 12:48:26 +00:00
Added Pci IDs translate to the HIRS_Util module for the supply chain validator process so that the hash can match up for highlighting failed components.
This commit is contained in:
@ -39,6 +39,7 @@ dependencies {
|
|||||||
compile libs.joda_time
|
compile libs.joda_time
|
||||||
compile libs.log4j2
|
compile libs.log4j2
|
||||||
compile libs.mariadb
|
compile libs.mariadb
|
||||||
|
compile libs.pci_ids
|
||||||
compile libs.reflections
|
compile libs.reflections
|
||||||
compile libs.guava
|
compile libs.guava
|
||||||
compile libs.spring_core
|
compile libs.spring_core
|
||||||
@ -48,6 +49,7 @@ dependencies {
|
|||||||
exclude group: 'junit'
|
exclude group: 'junit'
|
||||||
}
|
}
|
||||||
compile 'org.jboss.logging:jboss-logging:3.2.0.Final'
|
compile 'org.jboss.logging:jboss-logging:3.2.0.Final'
|
||||||
|
compile 'org.apache.commons:commons-text:1.9'
|
||||||
|
|
||||||
// add spring plugin, but do not pull transitive dependencies (causes conflicts)
|
// add spring plugin, but do not pull transitive dependencies (causes conflicts)
|
||||||
compile(libs.spring_plugin) {
|
compile(libs.spring_plugin) {
|
||||||
|
@ -15,7 +15,7 @@ import hirs.data.persist.TPMReport;
|
|||||||
import hirs.data.persist.baseline.TpmBlackListBaseline;
|
import hirs.data.persist.baseline.TpmBlackListBaseline;
|
||||||
import hirs.data.persist.baseline.TpmWhiteListBaseline;
|
import hirs.data.persist.baseline.TpmWhiteListBaseline;
|
||||||
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.codec.binary.Hex;
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
import org.apache.commons.text.StringEscapeUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
194
HIRS_Utils/src/main/java/hirs/utils/PciIds.java
Normal file
194
HIRS_Utils/src/main/java/hirs/utils/PciIds.java
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
package hirs.utils;
|
||||||
|
|
||||||
|
import com.github.marandus.pciid.model.Device;
|
||||||
|
import com.github.marandus.pciid.model.Vendor;
|
||||||
|
import com.github.marandus.pciid.service.PciIdsDatabase;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import hirs.data.persist.certificate.attributes.ComponentIdentifier;
|
||||||
|
import hirs.data.persist.certificate.attributes.V2.ComponentIdentifierV2;
|
||||||
|
import org.bouncycastle.asn1.DERUTF8String;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide Java access to PCI IDs.
|
||||||
|
*/
|
||||||
|
public final class PciIds {
|
||||||
|
/**
|
||||||
|
* This pci ids file can be in different places on different distributions.
|
||||||
|
*/
|
||||||
|
public static final List<String> PCI_IDS_PATH =
|
||||||
|
Collections.unmodifiableList(new Vector<String>() {
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* This only needs to be loaded one time.
|
||||||
|
*
|
||||||
|
* The pci ids library protects the data inside the object by making it immutable.
|
||||||
|
*/
|
||||||
|
public static final PciIdsDatabase DB = new PciIdsDatabase();
|
||||||
|
|
||||||
|
static {
|
||||||
|
if (!DB.isReady()) {
|
||||||
|
String dbFile = null;
|
||||||
|
for (final String path : PCI_IDS_PATH) {
|
||||||
|
if ((new File(path)).exists()) {
|
||||||
|
dbFile = path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dbFile != null) {
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
is = new FileInputStream(new File(dbFile));
|
||||||
|
DB.loadStream(is);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// DB will not be ready, hardware IDs will not be translated
|
||||||
|
dbFile = null;
|
||||||
|
} finally {
|
||||||
|
if (is != null) {
|
||||||
|
try {
|
||||||
|
is.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
dbFile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class.
|
||||||
|
*/
|
||||||
|
private PciIds() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Component Class TCG Registry OID.
|
||||||
|
*/
|
||||||
|
public static final String COMPCLASS_TCG_OID = "2.23.133.18.3.1";
|
||||||
|
/**
|
||||||
|
* The Component Class Value mask for NICs.
|
||||||
|
*/
|
||||||
|
public static final String COMPCLASS_TCG_CAT_NIC = "00090000";
|
||||||
|
/**
|
||||||
|
* The Component Class Value mask for GFX cards.
|
||||||
|
*/
|
||||||
|
public static final String COMPCLASS_TCG_CAT_GFX = "00050000";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate through all components and translate PCI hardware IDs as necessary. It will only
|
||||||
|
* translate ComponentIdentifierV2+ objects as it relies on Component Class information.
|
||||||
|
* @param components List of ComponentIdentifiers.
|
||||||
|
* @return the translated list of ComponentIdentifiers.
|
||||||
|
*/
|
||||||
|
public static List<ComponentIdentifier> translate(
|
||||||
|
final List<ComponentIdentifier> components) {
|
||||||
|
Vector<ComponentIdentifier> newList = new Vector<ComponentIdentifier>();
|
||||||
|
if (components != null && !components.isEmpty()) {
|
||||||
|
for (final ComponentIdentifier component : components) {
|
||||||
|
// V2 components should not be found alongside V1 components
|
||||||
|
// they pass through just in case
|
||||||
|
if (component.isVersion2()) {
|
||||||
|
newList.add(translate((ComponentIdentifierV2) component));
|
||||||
|
} else {
|
||||||
|
newList.add(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate Vendor and Device IDs, if found, in ComponentIdentifierV2 objects.
|
||||||
|
* It will only translate ID values, any other value will pass through.
|
||||||
|
* @param component ComponentIdentifierV2 object.
|
||||||
|
* @return the translated ComponentIdentifierV2 object.
|
||||||
|
*/
|
||||||
|
public static ComponentIdentifierV2 translate(final ComponentIdentifierV2 component) {
|
||||||
|
ComponentIdentifierV2 newComponent = null;
|
||||||
|
if (component != null) {
|
||||||
|
newComponent = component;
|
||||||
|
// This can be updated as we get more accurate component class registries and values
|
||||||
|
// Component Class Registry not accessible: TCG assumed
|
||||||
|
final String compClassValue = component.getComponentClass().getCategoryValue();
|
||||||
|
if (compClassValue.equals(COMPCLASS_TCG_CAT_NIC)
|
||||||
|
|| compClassValue.equals(COMPCLASS_TCG_CAT_GFX)) {
|
||||||
|
DERUTF8String manufacturer = translateVendor(component.getComponentManufacturer());
|
||||||
|
DERUTF8String model = translateDevice(component.getComponentManufacturer(),
|
||||||
|
component.getComponentModel());
|
||||||
|
|
||||||
|
newComponent = new ComponentIdentifierV2(component.getComponentClass(),
|
||||||
|
manufacturer,
|
||||||
|
model,
|
||||||
|
component.getComponentSerial(),
|
||||||
|
component.getComponentRevision(),
|
||||||
|
component.getComponentManufacturerId(),
|
||||||
|
component.getFieldReplaceable(),
|
||||||
|
component.getComponentAddress(),
|
||||||
|
component.getCertificateIdentifier(),
|
||||||
|
component.getComponentPlatformUri(),
|
||||||
|
component.getAttributeStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return newComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 DERUTF8String translateVendor(final DERUTF8String refManufacturer) {
|
||||||
|
DERUTF8String manufacturer = refManufacturer;
|
||||||
|
if (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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return manufacturer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 DERUTF8String, likely from a ComponentIdentifier
|
||||||
|
* @param refModel DERUTF8String, likely from a ComponentIdentifier
|
||||||
|
* @return DERUTF8String with the discovered device name, or the original model value.
|
||||||
|
*/
|
||||||
|
public static DERUTF8String translateDevice(final DERUTF8String refManufacturer,
|
||||||
|
final DERUTF8String refModel) {
|
||||||
|
DERUTF8String manufacturer = refManufacturer;
|
||||||
|
DERUTF8String model = refModel;
|
||||||
|
if (manufacturer != null
|
||||||
|
&& model != null
|
||||||
|
&& manufacturer.getString().trim().matches("^[0-9A-Fa-f]{4}$")
|
||||||
|
&& model.getString().trim().matches("^[0-9A-Fa-f]{4}$")) {
|
||||||
|
Device dev = DB.findDevice(manufacturer.getString().toLowerCase(),
|
||||||
|
model.getString().toLowerCase());
|
||||||
|
if (dev != null && !Strings.isNullOrEmpty(dev.getName())) {
|
||||||
|
model = new DERUTF8String(dev.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ import hirs.data.persist.certificate.attributes.ComponentIdentifier;
|
|||||||
import hirs.data.persist.certificate.attributes.V2.ComponentIdentifierV2;
|
import hirs.data.persist.certificate.attributes.V2.ComponentIdentifierV2;
|
||||||
import hirs.data.persist.info.ComponentInfo;
|
import hirs.data.persist.info.ComponentInfo;
|
||||||
import hirs.data.persist.info.HardwareInfo;
|
import hirs.data.persist.info.HardwareInfo;
|
||||||
|
import hirs.utils.PciIds;
|
||||||
import org.apache.commons.codec.Charsets;
|
import org.apache.commons.codec.Charsets;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@ -565,7 +566,11 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
|||||||
|
|
||||||
// pass information of which ones failed in additionInfo
|
// pass information of which ones failed in additionInfo
|
||||||
for (ComponentIdentifier ci : validPcComponents) {
|
for (ComponentIdentifier ci : validPcComponents) {
|
||||||
additionalInfo.append(String.format("%d;", ci.hashCode()));
|
ComponentIdentifierV2 pciCi = (ComponentIdentifierV2) ci;
|
||||||
|
if (PciIds.DB.isReady()) {
|
||||||
|
pciCi = PciIds.translate((ComponentIdentifierV2) ci);
|
||||||
|
}
|
||||||
|
additionalInfo.append(String.format("%d;", pciCi.hashCode()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user