[#109] Delta Chain Validation (#151)

* This code adds functionality to check the delta certificates in a chain. The main operation validates that the delta belongs in that chain and then that the chain establishes correct component modification. No removes before an add, no add to a component that exists, no remove to a component that doesn't exist. The unit test was updated to not use any flat file certificate.

Closes #109

* Changes were made to the validation of a delta certificate based on newer information.  There can be multiple bases and multiple leaves in a tree of associated certificates.  However currently we don't have certificates to validate the entirety of the code to test.

* Updated the code to treat the platform attributes policy, if v2, against all in the chain rather than one at a time.
This commit is contained in:
Cyrus 2019-06-04 14:07:35 -04:00 committed by GitHub
parent 75b84c8801
commit 157dcb649d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 525 additions and 54 deletions

View File

@ -16,6 +16,10 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.HashMap;
import org.apache.logging.log4j.Level;
import hirs.appraiser.Appraiser;
@ -101,8 +105,8 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
boolean acceptExpiredCerts = policy.isExpiredCertificateValidationEnabled();
HashMap<PlatformCredential, SupplyChainValidation> credentialMap = new HashMap<>();
PlatformCredential baseCredential = null;
List<SupplyChainValidation> validations = new ArrayList<>();
List<SupplyChainValidation> validations = new LinkedList<>();
Map<String, Boolean> multiBaseCheckMap = new HashMap<>();
// validate all supply chain pieces. Potentially, a policy setting could be made
// to dictate stopping after the first validation failure.
@ -133,19 +137,39 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
KeyStore trustedCa = getCaChain(pc);
SupplyChainValidation platformScv = validatePlatformCredential(
pc, trustedCa, acceptExpiredCerts);
// check if this cert has been verified for multiple base associated
// with the serial number
if (pc != null) {
boolean checked = multiBaseCheckMap.containsKey(pc.getPlatformSerial());
if (!checked) {
// if not checked, update the map
boolean result = checkForMultipleBaseCredentials(
pc.getPlatformSerial());
multiBaseCheckMap.put(pc.getPlatformSerial(), result);
// if it is, then update the SupplyChainValidation message and result
if (result) {
String message = "Multiple Base certificates found in chain.";
if (!platformScv.getResult()
.equals(AppraisalStatus.Status.PASS)) {
message = String.format("%s,%n%s",
platformScv.getMessage(), message);
}
platformScv = buildValidationRecord(
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
AppraisalStatus.Status.FAIL,
message, pc, Level.ERROR);
}
}
}
validations.add(platformScv);
if (null != pc) {
if (pc != null) {
pc.setDevice(device);
this.certificateManager.update(pc);
credentialMap.put(pc, platformScv);
/*
* This method will be added to PlatformCredential to return whether a given
* object is a base or a delta credential.
*/
/* if (pc.isBase()) {
if (pc.isBase()) {
baseCredential = pc;
}
*/
}
}
}
@ -165,13 +189,27 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
Iterator<PlatformCredential> it = pcs.iterator();
while (it.hasNext()) {
PlatformCredential pc = it.next();
SupplyChainValidation attributeScv = null;
if (pc == baseCredential || baseCredential == null) {
SupplyChainValidation attributeScv;
if (baseCredential == null || pc == baseCredential && !pc.isDeltaChain()) {
attributeScv = validatePlatformCredentialAttributes(
pc, device.getDeviceInfo(), ec);
} else {
List<PlatformCredential> chainCertificates = PlatformCredential
.select(certificateManager)
.byBoardSerialNumber(pc.getPlatformSerial())
.getCertificates().stream().collect(Collectors.toList());
Collections.sort(chainCertificates,
new Comparator<PlatformCredential>() {
@Override
public int compare(final PlatformCredential obj1,
final PlatformCredential obj2) {
return obj1.getBeginValidity()
.compareTo(obj2.getBeginValidity());
}
});
attributeScv = validateDeltaPlatformCredentialAttributes(
pc, device.getDeviceInfo(), baseCredential);
pc, device.getDeviceInfo(), baseCredential, chainCertificates);
}
SupplyChainValidation platformScv = credentialMap.get(pc);
@ -191,7 +229,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
}
}
if (null != pc) {
if (pc != null) {
pc.setDevice(device);
this.certificateManager.update(pc);
}
@ -306,22 +344,21 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
private SupplyChainValidation validateDeltaPlatformCredentialAttributes(
final PlatformCredential delta,
final DeviceInfoReport deviceInfoReport,
final PlatformCredential base) {
/*
* Do we need a new ValidationType for deltas?
*/
final PlatformCredential base,
final List<PlatformCredential> chainCertificates) {
final SupplyChainValidation.ValidationType validationType =
SupplyChainValidation.ValidationType.DELTA_PLATFORM_CREDENTIAL_ATTRIBUTES;
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
if (delta == null) {
LOGGER.error("No delta credential to validate");
LOGGER.error("No delta certificate to validate");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Platform credential is missing",
AppraisalStatus.Status.FAIL, "Delta platform certificate is missing",
null, Level.ERROR);
}
LOGGER.info("Validating platform credential attributes");
LOGGER.info("Validating delta platform certificate attributes");
AppraisalStatus result = supplyChainCredentialValidator.
validateDeltaPlatformCredentialAttributes(delta, deviceInfoReport, base);
validateDeltaPlatformCredentialAttributes(delta, deviceInfoReport,
base, chainCertificates);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
@ -354,7 +391,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
final Certificate certificate, final Level logLevel) {
List<Certificate> certificateList = new ArrayList<>();
if (null != certificate) {
if (certificate != null) {
certificateList.add(certificate);
}
@ -373,7 +410,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
* Returns the certificate authority credentials in a KeyStore.
*
* @param credential the credential whose CA chain should be retrieved
* @return A keystore ontaining all relevant CA credentials to the given certificate's
* @return A keystore containing all relevant CA credentials to the given certificate's
* organization or null if the keystore can't be assembled
*/
public KeyStore getCaChain(final Certificate credential) {
@ -443,4 +480,26 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
return keyStore;
}
private boolean checkForMultipleBaseCredentials(final String platformSerialNumber) {
boolean multiple = false;
PlatformCredential baseCredential = null;
if (platformSerialNumber != null) {
List<PlatformCredential> chainCertificates = PlatformCredential
.select(certificateManager)
.byBoardSerialNumber(platformSerialNumber)
.getCertificates().stream().collect(Collectors.toList());
for (PlatformCredential pc : chainCertificates) {
if (baseCredential != null && pc.isBase()) {
multiple = true;
} else if (pc.isBase()) {
baseCredential = pc;
}
}
}
return multiple;
}
}

View File

@ -93,7 +93,7 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest
// mocked
private SupplyChainPolicy policy;
private PlatformCredential pc;
// private PlatformCredential delta;
private PlatformCredential delta;
private EndorsementCredential ec;
private HashSet<PlatformCredential> pcs;
private Device device;
@ -135,9 +135,15 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest
pcs = new HashSet<PlatformCredential>();
pcs.add(pc);
/*
* Mock delta platform credential here
*/
//Mock delta platform credential
X509Certificate deltaCert = mock(X509Certificate.class);
delta = mock(PlatformCredential.class);
when(delta.getId()).thenReturn(UUID.randomUUID());
when(delta.getX509Certificate()).thenReturn(deltaCert);
//when(delta.getSerialNumber()).thenReturn(BigInteger.ONE);
when(delta.getIssuerOrganization()).thenReturn("STMicroelectronics NV");
when(delta.getSubjectOrganization()).thenReturn("STMicroelectronics NV");
//pcs.add(delta);
Set<Certificate> resultPcs = new HashSet<>();
resultPcs.add(pc);
@ -182,11 +188,6 @@ public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
.validatePlatformCredentialAttributes(eq(pc), any(DeviceInfoReport.class),
any(EndorsementCredential.class));
/*
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
.validateDeltaPlatformCredentialAttributes(eq(delta), any(DeviceInfoReport.class),
any(PlatformCredential.class));
*/
Assert.assertEquals(service.validateSupplyChain(ec, pcs,
device).getOverallValidationResult(), PASS);

View File

@ -877,4 +877,4 @@
</script>
</jsp:body>
</my:page>
</my:page>

View File

@ -34,12 +34,7 @@ public class SupplyChainValidation extends ArchivableEntity {
/**
* Validation of a platform credential's attributes.
*/
PLATFORM_CREDENTIAL_ATTRIBUTES,
/**
* Validation of a delta platform credential's attributes.
*/
DELTA_PLATFORM_CREDENTIAL_ATTRIBUTES
PLATFORM_CREDENTIAL_ATTRIBUTES
}
@Column

View File

@ -234,6 +234,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
private EndorsementCredential endorsementCredential = null;
private String platformChainType = Strings.EMPTY;
private boolean isDeltaChain = false;
/**
* Get a Selector for use in retrieving PlatformCredentials.
@ -371,6 +372,15 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
return platformBase;
}
/**
* Flag that indicates this PC has or can have a chain of delta
* certificates.
* @return status of the chain
*/
public boolean isDeltaChain() {
return isDeltaChain;
}
/**
* Getter for the string representation of the platform type.
*
@ -522,9 +532,11 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
if (platformOid.getId().equals(PLATFORM_BASE_CERT)) {
this.platformBase = true;
this.platformChainType = "Base";
this.isDeltaChain = true;
} else if (platformOid.getId().equals(PLATFORM_DELTA_CERT)) {
this.platformBase = false;
this.platformChainType = "Delta";
this.isDeltaChain = true;
}
}
}

View File

@ -214,6 +214,13 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
this.attributeStatus = attributeStatus;
}
/**
* @return true if the component has been modified.
*/
public final boolean isAdded() {
return getAttributeStatus() == AttributeStatus.ADDED;
}
/**
* @return true if the component has been modified.
*/

View File

@ -6,6 +6,7 @@ import hirs.data.persist.certificate.EndorsementCredential;
import hirs.data.persist.certificate.PlatformCredential;
import java.security.KeyStore;
import java.util.List;
/**
* A class used to support supply chain validation by performing the actual
@ -43,11 +44,14 @@ public interface CredentialValidator {
* serial number of the platform to be validated.
* @param base the base credential from the same identity request
* as the delta credential.
* @param chainCertificates base and delta certificates associated with the
* delta being validated.
* @return the result of the validation.
*/
AppraisalStatus validateDeltaPlatformCredentialAttributes(PlatformCredential delta,
DeviceInfoReport deviceInfoReport,
PlatformCredential base);
DeviceInfoReport deviceInfoReport,
PlatformCredential base,
List<PlatformCredential> chainCertificates);
/**
* Checks if the endorsement credential is valid.
*

View File

@ -55,6 +55,9 @@ import java.util.stream.Collectors;
import static hirs.data.persist.AppraisalStatus.Status.ERROR;
import static hirs.data.persist.AppraisalStatus.Status.FAIL;
import static hirs.data.persist.AppraisalStatus.Status.PASS;
import hirs.data.persist.certificate.attributes.V2.ComponentIdentifierV2;
import java.util.Collections;
import java.util.LinkedList;
import org.apache.logging.log4j.util.Strings;
@ -258,26 +261,99 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
* serial number of the platform to be validated.
* @param basePlatformCredential the base credential from the same identity request
* as the delta credential.
* @param chainCertificates base and delta certificates associated with the
* delta being validated.
* @return the result of the validation.
*/
@Override
public AppraisalStatus validateDeltaPlatformCredentialAttributes(
final PlatformCredential deltaPlatformCredential,
final DeviceInfoReport deviceInfoReport,
final PlatformCredential basePlatformCredential) {
final PlatformCredential basePlatformCredential,
final List<PlatformCredential> chainCertificates) {
final String baseErrorMessage = "Can't validate delta platform"
+ "certificate attributes without ";
String message;
if (deltaPlatformCredential == null) {
message = baseErrorMessage + "a delta platform certificate";
LOGGER.error(message);
return new AppraisalStatus(FAIL, message);
}
if (deviceInfoReport == null) {
message = baseErrorMessage + "a device info report";
LOGGER.error(message);
return new AppraisalStatus(FAIL, message);
}
if (basePlatformCredential == null) {
message = baseErrorMessage + "a base platform credential";
LOGGER.error(message);
return new AppraisalStatus(FAIL, message);
}
/*
* Code here to check the holder and attribute status fields
*/
return validatePlatformCredentialAttributesV2p0(deltaPlatformCredential, deviceInfoReport);
if (!basePlatformCredential.getPlatformSerial()
.equals(deltaPlatformCredential.getPlatformSerial())) {
message = String.format("Delta platform certificate "
+ "platform serial number (%s) does not match "
+ "the base certificate's platform serial number (%s)",
deltaPlatformCredential.getPlatformSerial(),
basePlatformCredential.getPlatformSerial());
LOGGER.error(message);
return new AppraisalStatus(FAIL, message);
}
// parse out the provided delta and its specific chain.
Collections.reverse(chainCertificates);
List<PlatformCredential> leafChain = new LinkedList<>();
PlatformCredential dc;
List<ComponentIdentifier> origPcComponents = new LinkedList<>();
for (PlatformCredential pc : chainCertificates) {
if (pc.isBase()) {
if (basePlatformCredential.getSerialNumber()
.equals(pc.getSerialNumber())) {
// get original component list
origPcComponents.addAll(pc.getComponentIdentifiers());
}
} else {
dc = pc;
leafChain.add(dc);
}
}
// map the deltas to their holder serial numbers
Map<String, PlatformCredential> leafMap = new HashMap<>();
leafChain.stream().forEach((delta) -> {
leafMap.put(delta.getHolderSerialNumber().toString(), delta);
});
leafChain.clear();
String serialNumber = basePlatformCredential.getSerialNumber().toString();
PlatformCredential tempCred;
// Start with the base serial number, find the delta pointing to it
// and put that first in the list
for (int i = 0; i < leafMap.size(); i++) {
tempCred = leafMap.get(serialNumber);
// this should never be null
if (tempCred != null) {
leafChain.add(i, tempCred);
serialNumber = tempCred.getSerialNumber().toString();
} else {
return new AppraisalStatus(ERROR, String.format("Delta platform search "
+ "for mapping returned null for %s", serialNumber));
}
}
return validateDeltaAttributesChainV2p0(deviceInfoReport,
leafChain, origPcComponents);
}
private static AppraisalStatus validatePlatformCredentialAttributesV1p2(
final PlatformCredential platformCredential,
final DeviceInfoReport deviceInfoReport) {
// check the device's board serial number, and compare against this platform credential's
// board serial number.
// check the device's board serial number, and compare against this
// platform credential's board serial number.
// Retrieve the various device serial numbers.
String credentialBoardSerialNumber = platformCredential.getPlatformSerial();
String credentialChassisSerialNumber = platformCredential.getChassisSerialNumber();
@ -379,8 +455,7 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
final PlatformCredential platformCredential,
final DeviceInfoReport deviceInfoReport) {
boolean passesValidation = true;
StringBuffer resultMessage = new StringBuffer();
StringBuilder resultMessage = new StringBuilder();
HardwareInfo hardwareInfo = deviceInfoReport.getHardwareInfo();
@ -500,6 +575,115 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
}
}
/**
* The main purpose of this method, the in process of validation, is to
* pick out the changes that lead to the delta cert and make sure the changes
* are valid.
*
* @param deviceInfoReport The paccor profile of device being validated against.
* @param leafChain The specific chain associated with delta cert being
* validated.
* @param origPcComponents The component identifier list associated with the
* base cert for this specific chain
* @return Appraisal Status of delta being validated.
*/
static AppraisalStatus validateDeltaAttributesChainV2p0(
final DeviceInfoReport deviceInfoReport,
final List<PlatformCredential> leafChain,
final List<ComponentIdentifier> origPcComponents) {
boolean fieldValidation = true;
StringBuilder resultMessage = new StringBuilder();
List<ComponentIdentifier> validOrigPcComponents = origPcComponents.stream()
.filter(identifier -> identifier.getComponentManufacturer() != null
&& identifier.getComponentModel() != null)
.collect(Collectors.toList());
// map the components throughout the chain
Map<String, ComponentIdentifier> chainCiMapping = new HashMap<>();
List<ComponentIdentifier> deltaBuildList = new LinkedList<>(validOrigPcComponents);
deltaBuildList.stream().forEach((ci) -> {
chainCiMapping.put(ci.getComponentSerial().toString(), ci);
});
String ciSerial;
// go through the leaf and check the changes against the valid components
// forget modifying validOrigPcComponents
for (PlatformCredential delta : leafChain) {
for (ComponentIdentifier ci : delta.getComponentIdentifiers()) {
if (ci.isVersion2()) {
ciSerial = ci.getComponentSerial().toString();
ComponentIdentifierV2 ciV2 = (ComponentIdentifierV2) ci;
if (ciV2.isModified()) {
// this won't match
// check it is there
if (!chainCiMapping.containsKey(ciSerial)) {
fieldValidation = false;
resultMessage.append(String.format(
"%s attempted MODIFIED with no prior instance.%n",
ciSerial));
} else {
chainCiMapping.put(ci.getComponentSerial().toString(), ci);
}
} else if (ciV2.isRemoved()) {
if (!chainCiMapping.containsKey(ciSerial)) {
// error thrown, can't remove if it doesn't exist
fieldValidation = false;
resultMessage.append(String.format(
"%s attempted REMOVED with no prior instance.%n",
ciSerial));
} else {
chainCiMapping.remove(ci.getComponentSerial().toString());
}
} else if (ciV2.isAdded()) {
// ADDED
if (chainCiMapping.containsKey(ciSerial)) {
// error, shouldn't exist
fieldValidation = false;
resultMessage.append(String.format(
"%s was ADDED, the serial already exists.%n",
ciSerial));
} else {
// have to add incase later it is removed
chainCiMapping.put(ciSerial, ci);
}
}
}
}
}
if (!fieldValidation) {
resultMessage.append("There are errors with Delta "
+ "Component Statuses components:\n");
return new AppraisalStatus(FAIL, resultMessage.toString());
}
String paccorOutputString = deviceInfoReport.getPaccorOutputString();
String unmatchedComponents;
try {
List<ComponentInfo> componentInfoList
= getComponentInfoFromPaccorOutput(paccorOutputString);
unmatchedComponents = validateV2p0PlatformCredentialComponentsExpectingExactMatch(
new LinkedList<>(chainCiMapping.values()), componentInfoList);
fieldValidation &= unmatchedComponents.isEmpty();
} catch (IOException e) {
final String baseErrorMessage = "Error parsing JSON output from PACCOR: ";
LOGGER.error(baseErrorMessage + e.toString());
LOGGER.error("PACCOR output string:\n" + paccorOutputString);
return new AppraisalStatus(ERROR, baseErrorMessage + e.getMessage());
}
if (!fieldValidation) {
resultMessage.append("There are unmatched components:\n");
resultMessage.append(unmatchedComponents);
return new AppraisalStatus(FAIL, resultMessage.toString());
}
return new AppraisalStatus(PASS, PLATFORM_ATTRIBUTES_VALID);
}
/**
* Compares the component information from the device info report against those of the
* platform credential. All components in the platform credential should exactly match one
@ -545,7 +729,6 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
pcComponents.forEach(component -> LOGGER.info(component.toString()));
LOGGER.info("...against the the following DeviceInfoReport components:");
allDeviceInfoComponents.forEach(component -> LOGGER.info(component.toString()));
Set<DERUTF8String> manufacturerSet = new HashSet<>();
pcComponents.forEach(component -> manufacturerSet.add(
component.getComponentManufacturer()));
@ -577,7 +760,8 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
// Now match up the components from the device info that are from the same
// manufacturer and have a serial number. As matches are found, remove them from
// both lists.
for (ComponentIdentifier pcComponent : pcComponentsFromManufacturerWithSerialNumber) {
for (ComponentIdentifier pcComponent
: pcComponentsFromManufacturerWithSerialNumber) {
Optional<ComponentInfo> first
= deviceInfoComponentsFromManufacturer.stream()
.filter(componentInfo
@ -607,7 +791,8 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
// Now match up the components from the device info that are from the same
// manufacturer and specify a value for the revision field. As matches are found,
// remove them from both lists.
for (ComponentIdentifier pcComponent : pcComponentsFromManufacturerWithRevision) {
for (ComponentIdentifier pcComponent
: pcComponentsFromManufacturerWithRevision) {
Optional<ComponentInfo> first
= deviceInfoComponentsFromManufacturer.stream()
.filter(info -> StringUtils.isNotEmpty(info.getComponentRevision()))

View File

@ -15,7 +15,10 @@ import hirs.data.persist.certificate.CertificateAuthorityCredential;
import hirs.data.persist.certificate.CertificateTest;
import hirs.data.persist.certificate.EndorsementCredential;
import hirs.data.persist.certificate.PlatformCredential;
import hirs.data.persist.certificate.attributes.ComponentClass;
import hirs.data.persist.certificate.attributes.ComponentIdentifier;
import hirs.data.persist.certificate.attributes.V2.AttributeStatus;
import hirs.data.persist.certificate.attributes.V2.ComponentIdentifierV2;
import org.apache.commons.io.IOUtils;
import org.bouncycastle.asn1.ASN1Boolean;
import org.bouncycastle.asn1.DERUTF8String;
@ -1992,6 +1995,211 @@ public class SupplyChainCredentialValidatorTest {
SupplyChainCredentialValidator.PLATFORM_ATTRIBUTES_VALID);
}
/**
* Tests that SupplyChainCredentialValidator passes with a base and delta certificate where
* the base serial number and delta holder serial number match.
* @throws java.io.IOException Reading file for the certificates
* @throws java.net.URISyntaxException when loading certificates bytes
*/
@Test
public final void testValidateDeltaPlatformCredentialAttributes()
throws IOException, URISyntaxException {
DeviceInfoReport deviceInfoReport = setupDeviceInfoReportWithComponents(
SAMPLE_PACCOR_OUTPUT_TXT);
PlatformCredential base = mock(PlatformCredential.class);
PlatformCredential delta1 = mock(PlatformCredential.class);
PlatformCredential delta2 = mock(PlatformCredential.class);
ComponentIdentifier compId1 = new ComponentIdentifier(new DERUTF8String("Intel"),
new DERUTF8String("Core i7"), new DERUTF8String("Not Specified"),
new DERUTF8String("Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz"), null,
ASN1Boolean.TRUE, new ArrayList<>(0));
ComponentIdentifier compId2 = new ComponentIdentifier(
new DERUTF8String("Intel Corporation"),
new DERUTF8String("Ethernet Connection I217-V-faulty"),
new DERUTF8String("23:94:17:ba:86:5e"), new DERUTF8String("00"), null,
ASN1Boolean.FALSE, new ArrayList<>(0));
ComponentIdentifier compId3 = new ComponentIdentifier(
new DERUTF8String("Intel Corporation"),
new DERUTF8String("82580 Gigabit Network Connection-faulty"),
new DERUTF8String("90:e2:ba:31:83:10"), new DERUTF8String(""), null,
ASN1Boolean.FALSE, new ArrayList<>(0));
ComponentIdentifierV2 deltaCompId2 = new ComponentIdentifierV2(
new ComponentClass(),
new DERUTF8String("Intel Corporation"),
new DERUTF8String("Ethernet Connection I217-V"),
new DERUTF8String("23:94:17:ba:86:5e"), new DERUTF8String("00"), null,
ASN1Boolean.FALSE, new ArrayList<>(0), null, null,
AttributeStatus.ADDED);
ComponentIdentifierV2 deltaCompId3 = new ComponentIdentifierV2(
new ComponentClass(),
new DERUTF8String("Intel Corporation"),
new DERUTF8String("82580 Gigabit Network Connection"),
new DERUTF8String("90:e2:ba:31:83:10"), new DERUTF8String(""), null,
ASN1Boolean.FALSE, new ArrayList<>(0), null, null,
AttributeStatus.ADDED);
ComponentIdentifierV2 ciV21Faulty = new ComponentIdentifierV2();
ComponentIdentifierV2 ciV22Faulty = new ComponentIdentifierV2();
ciV21Faulty.setComponentManufacturer(compId2.getComponentManufacturer());
ciV21Faulty.setComponentModel(compId2.getComponentModel());
ciV21Faulty.setComponentSerial(compId2.getComponentSerial());
ciV21Faulty.setComponentRevision(compId2.getComponentRevision());
ciV21Faulty.setComponentManufacturerId(compId2.getComponentManufacturerId());
ciV21Faulty.setFieldReplaceable(compId2.getFieldReplaceable());
ciV21Faulty.setComponentAddress(compId2.getComponentAddress());
ciV21Faulty.setAttributeStatus(AttributeStatus.REMOVED);
ciV22Faulty.setComponentManufacturer(compId3.getComponentManufacturer());
ciV22Faulty.setComponentModel(compId3.getComponentModel());
ciV22Faulty.setComponentSerial(compId3.getComponentSerial());
ciV22Faulty.setComponentRevision(compId3.getComponentRevision());
ciV22Faulty.setComponentManufacturerId(compId3.getComponentManufacturerId());
ciV22Faulty.setFieldReplaceable(compId3.getFieldReplaceable());
ciV22Faulty.setComponentAddress(compId3.getComponentAddress());
ciV22Faulty.setAttributeStatus(AttributeStatus.REMOVED);
List<ComponentIdentifier> compList = new ArrayList<>(3);
compList.add(compId1);
compList.add(compId2);
compList.add(compId3);
List<ComponentIdentifier> delta1List = new ArrayList<>(2);
delta1List.add(ciV21Faulty);
delta1List.add(deltaCompId2);
List<ComponentIdentifier> delta2List = new ArrayList<>(2);
delta1List.add(ciV22Faulty);
delta1List.add(deltaCompId3);
when(base.isBase()).thenReturn(true);
when(delta1.isBase()).thenReturn(false);
when(delta2.isBase()).thenReturn(false);
when(base.getManufacturer()).thenReturn("innotek GmbH");
when(base.getModel()).thenReturn("VirtualBox");
when(base.getVersion()).thenReturn("1.2");
when(base.getPlatformSerial()).thenReturn("0");
when(delta1.getPlatformSerial()).thenReturn("0");
when(delta2.getPlatformSerial()).thenReturn("0");
when(base.getPlatformType()).thenReturn("base");
when(delta1.getPlatformType()).thenReturn("delta");
when(delta2.getPlatformType()).thenReturn("delta");
when(base.getSerialNumber()).thenReturn(BigInteger.ZERO);
when(delta1.getSerialNumber()).thenReturn(BigInteger.ONE);
when(delta2.getSerialNumber()).thenReturn(BigInteger.TEN);
when(delta1.getHolderSerialNumber()).thenReturn(BigInteger.ZERO);
when(delta2.getHolderSerialNumber()).thenReturn(BigInteger.ONE);
when(base.getComponentIdentifiers()).thenReturn(compList);
when(delta1.getComponentIdentifiers()).thenReturn(delta1List);
when(delta2.getComponentIdentifiers()).thenReturn(delta2List);
List<PlatformCredential> chainCredentials = new ArrayList<>(0);
chainCredentials.add(base);
chainCredentials.add(delta1);
chainCredentials.add(delta2);
AppraisalStatus result = supplyChainCredentialValidator
.validateDeltaPlatformCredentialAttributes(delta2,
deviceInfoReport, base, chainCredentials);
Assert.assertEquals(result.getAppStatus(), AppraisalStatus.Status.PASS);
Assert.assertEquals(result.getMessage(),
SupplyChainCredentialValidator.PLATFORM_ATTRIBUTES_VALID);
}
/**
* Tests that SupplyChainCredentialValidator fails when a component needs to
* be replaced but hasn't been by a delta certificate.
* @throws java.io.IOException Reading file for the certificates
* @throws java.net.URISyntaxException when loading certificates bytes
*/
@Test
public final void testValidateChainFailure()
throws IOException, URISyntaxException {
DeviceInfoReport deviceInfoReport = setupDeviceInfoReportWithComponents(
SAMPLE_PACCOR_OUTPUT_TXT);
PlatformCredential base = mock(PlatformCredential.class);
PlatformCredential delta1 = mock(PlatformCredential.class);
ComponentIdentifier compId1 = new ComponentIdentifier(new DERUTF8String("Intel"),
new DERUTF8String("Core i7"), new DERUTF8String("Not Specified"),
new DERUTF8String("Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz"), null,
ASN1Boolean.TRUE, new ArrayList<>(0));
ComponentIdentifier compId2 = new ComponentIdentifier(
new DERUTF8String("Intel Corporation"),
new DERUTF8String("Ethernet Connection I217-V-faulty"),
new DERUTF8String("23:94:17:ba:86:5e"), new DERUTF8String("00"), null,
ASN1Boolean.FALSE, new ArrayList<>(0));
ComponentIdentifier compId3 = new ComponentIdentifier(
new DERUTF8String("Intel Corporation"),
new DERUTF8String("82580 Gigabit Network Connection-faulty"),
new DERUTF8String("90:e2:ba:31:83:10"), new DERUTF8String(""), null,
ASN1Boolean.FALSE, new ArrayList<>(0));
ComponentIdentifierV2 deltaCompId2 = new ComponentIdentifierV2(
new ComponentClass(),
new DERUTF8String("Intel Corporation"),
new DERUTF8String("Ethernet Connection I217-V"),
new DERUTF8String("23:94:17:ba:86:5e"), new DERUTF8String("00"), null,
ASN1Boolean.FALSE, new ArrayList<>(0), null, null,
AttributeStatus.ADDED);
ComponentIdentifierV2 ciV21Faulty = new ComponentIdentifierV2();
ComponentIdentifierV2 ciV22Faulty = new ComponentIdentifierV2();
ciV21Faulty.setComponentManufacturer(compId2.getComponentManufacturer());
ciV21Faulty.setComponentModel(compId2.getComponentModel());
ciV21Faulty.setComponentSerial(compId2.getComponentSerial());
ciV21Faulty.setComponentRevision(compId2.getComponentRevision());
ciV21Faulty.setComponentManufacturerId(compId2.getComponentManufacturerId());
ciV21Faulty.setFieldReplaceable(compId2.getFieldReplaceable());
ciV21Faulty.setComponentAddress(compId2.getComponentAddress());
ciV21Faulty.setAttributeStatus(AttributeStatus.REMOVED);
ciV22Faulty.setComponentManufacturer(compId3.getComponentManufacturer());
ciV22Faulty.setComponentModel(compId3.getComponentModel());
ciV22Faulty.setComponentSerial(compId3.getComponentSerial());
ciV22Faulty.setComponentRevision(compId3.getComponentRevision());
ciV22Faulty.setComponentManufacturerId(compId3.getComponentManufacturerId());
ciV22Faulty.setFieldReplaceable(compId3.getFieldReplaceable());
ciV22Faulty.setComponentAddress(compId3.getComponentAddress());
ciV22Faulty.setAttributeStatus(AttributeStatus.REMOVED);
List<ComponentIdentifier> compList = new ArrayList<>(3);
compList.add(compId1);
compList.add(compId2);
compList.add(compId3);
List<ComponentIdentifier> delta1List = new ArrayList<>(2);
delta1List.add(ciV21Faulty);
delta1List.add(deltaCompId2);
when(base.isBase()).thenReturn(true);
when(delta1.isBase()).thenReturn(false);
when(base.getManufacturer()).thenReturn("innotek GmbH");
when(base.getModel()).thenReturn("VirtualBox");
when(base.getVersion()).thenReturn("1.2");
when(base.getPlatformSerial()).thenReturn("0");
when(delta1.getPlatformSerial()).thenReturn("0");
when(base.getPlatformType()).thenReturn("base");
when(delta1.getPlatformType()).thenReturn("delta");
when(base.getSerialNumber()).thenReturn(BigInteger.ZERO);
when(delta1.getSerialNumber()).thenReturn(BigInteger.ONE);
when(delta1.getHolderSerialNumber()).thenReturn(BigInteger.ZERO);
when(base.getComponentIdentifiers()).thenReturn(compList);
when(delta1.getComponentIdentifiers()).thenReturn(delta1List);
List<PlatformCredential> chainCredentials = new ArrayList<>(0);
chainCredentials.add(base);
chainCredentials.add(delta1);
AppraisalStatus result = supplyChainCredentialValidator
.validateDeltaPlatformCredentialAttributes(delta1,
deviceInfoReport, base, chainCredentials);
Assert.assertEquals(result.getAppStatus(), AppraisalStatus.Status.FAIL);
Assert.assertEquals(result.getMessage(),
"There are unmatched components:\n"
+ "Manufacturer=Intel Corporation, Model=82580 "
+ "Gigabit Network Connection-faulty, "
+ "Serial=90:e2:ba:31:83:10, Revision=\n");
}
/**
* Creates a new RSA 1024-bit KeyPair using a Bouncy Castle Provider.
*