diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index eb178210..9566ff9b 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -90,7 +90,9 @@ import java.security.spec.RSAPublicKeySpec; import java.util.Arrays; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -101,7 +103,6 @@ import java.util.regex.Pattern; */ public abstract class AbstractAttestationCertificateAuthority implements AttestationCertificateAuthority { - /** * Logger instance for for subclass instances. */ @@ -122,7 +123,6 @@ public abstract class AbstractAttestationCertificateAuthority * Number of bytes to include in the TPM2.0 nonce. */ public static final int NONCE_LENGTH = 20; - private static final int SEED_LENGTH = 32; private static final int MAX_SECRET_LENGTH = 32; private static final int RSA_MODULUS_LENGTH = 256; @@ -130,13 +130,11 @@ public abstract class AbstractAttestationCertificateAuthority private static final int HMAC_KEY_LENGTH_BYTES = 32; private static final int HMAC_SIZE_LENGTH_BYTES = 2; private static final int TPM2_CREDENTIAL_BLOB_SIZE = 392; - // Constants used to parse out the ak name from the ak public data. Used in generateAkName private static final String AK_NAME_PREFIX = "000b"; private static final String AK_NAME_HASH_PREFIX = "0001000b00050072000000100014000b0800000000000100"; private static final String TPM_SIGNATURE_ALG = "sha"; - private static final int MAC_BYTES = 6; /** @@ -165,7 +163,6 @@ public abstract class AbstractAttestationCertificateAuthority * certificates issued by this ACA are valid for. */ private final Integer validDays; - private final CertificateManager certificateManager; private final ReferenceManifestManager referenceManifestManager; private final DeviceRegister deviceRegister; @@ -456,6 +453,12 @@ public abstract class AbstractAttestationCertificateAuthority // attempt to find platform credentials to validate Set platformCredentials = parsePcsFromIdentityClaim(claim, endorsementCredential); + Map correctedMap = new HashMap<>(); + for (PlatformCredential pc : platformCredentials) { + correctedMap.put(pc.getSerialNumber(), pc); + } + platformCredentials.clear(); + platformCredentials.addAll(correctedMap.values()); // Parse and save device info Device device = processDeviceInfo(claim); diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java index 8aa5cf2b..0883a239 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java @@ -135,6 +135,12 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe List validations = new LinkedList<>(); Map deltaMapping = new HashMap<>(); SupplyChainValidation platformScv = null; + SupplyChainValidation.ValidationType platformType = SupplyChainValidation + .ValidationType.PLATFORM_CREDENTIAL; + SupplyChainValidation.ValidationType platformAttrType = SupplyChainValidation + .ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES; + Map validationTypeMap + = new HashMap<>(); LOGGER.info("Validating supply chain."); // Validate the Endorsement Credential @@ -153,7 +159,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe if (pcs == null || pcs.isEmpty()) { LOGGER.error("There were no Platform Credentials to validate."); validations.add(buildValidationRecord( - SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL, + platformType, AppraisalStatus.Status.FAIL, "Platform credential(s) missing", null, Level.ERROR)); } else { @@ -170,16 +176,63 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe platformScv = validatePcPolicy(pc, platformScv, deltaMapping, acceptExpiredCerts); - validations.add(platformScv); - validations.addAll(deltaMapping.values()); + /** + * Alright, this should work but because the test material is bad + * I can't finish it. Currently the delta certificate has the same + * serial number as the base, the same validity and so on. I will + * attempt to generate my own but for right now, I'm going to move + * on to something else. + */ + if (validationTypeMap.containsKey( + platformType)) { + SupplyChainValidation tmpScv = validationTypeMap.get(platformType); + if (tmpScv.getResult() == PASS && platformScv.getResult() == FAIL) { + validationTypeMap.put(platformType, platformScv); + } + } else { + validationTypeMap.put(platformType, platformScv); + } if (pc.isBase()) { baseCredential = pc; + LOGGER.error("Found the base Certificate"); } pc.setDevice(device); this.certificateManager.update(pc); } } + + // check that the delta certificates validity date is after + // the base + if (baseCredential != null) { + for (PlatformCredential pc : pcs) { + int result = pc.getBeginValidity() + .compareTo(baseCredential.getBeginValidity()); + if (!pc.isBase() && (result <= 0)) { + LOGGER.error("You are not crazy"); + validationTypeMap.put(platformType, + buildValidationRecord( + platformType, + AppraisalStatus.Status.FAIL, + "Delta Certificate's validity " + + "date is not after Base", + null, Level.ERROR)); + break; + } + } + } else { + // we don't have a base cert, fail + validationTypeMap.put(platformType, + buildValidationRecord( + platformType, + AppraisalStatus.Status.FAIL, + "Base Platform credential missing", + null, + Level.ERROR)); + } + + validations.add(validationTypeMap.get( + platformType)); } } @@ -189,17 +242,23 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe if (pcs == null || pcs.isEmpty()) { LOGGER.error("There were no Platform Credentials to validate attributes."); validations.add(buildValidationRecord( - SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL, + platformAttrType, AppraisalStatus.Status.FAIL, "Platform credential(s) missing." + " Cannot validate attributes", null, Level.ERROR)); } else { + platformScv = validationTypeMap.get( + platformType); + SupplyChainValidation attributeScv = null; + + List aes = new ArrayList<>(); + if (platformScv != null) { + aes.addAll(platformScv.getCertificatesUsed()); + } Iterator it = pcs.iterator(); while (it.hasNext()) { PlatformCredential pc = it.next(); - SupplyChainValidation attributeScv = null; - if (pc != null) { if (pc.isDeltaChain()) { // this check validates the delta changes and re-compares @@ -211,38 +270,69 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe attributeScv = validatePlatformCredentialAttributes( pc, device.getDeviceInfo(), ec); } - if (platformScv != null) { - // have to make sure the attribute validation isn't ignored and - // doesn't override general validation status - if (platformScv.getResult() == PASS - && attributeScv.getResult() != PASS) { - // if the platform trust store validated but the attribute didn't - // replace - validations.remove(platformScv); - validations.add(attributeScv); - } else if ((platformScv.getResult() == PASS - && attributeScv.getResult() == PASS) - || (platformScv.getResult() != PASS - && attributeScv.getResult() != PASS)) { - // if both trust store and attributes validated or failed - // combine messages - validations.remove(platformScv); - List aes = new ArrayList<>(); - for (Certificate cert : platformScv.getCertificatesUsed()) { - aes.add(cert); - } - validations.add(new SupplyChainValidation( - platformScv.getValidationType(), - platformScv.getResult(), aes, - String.format("%s%n%s", platformScv.getMessage(), + + // update the attribute SCV + if (validationTypeMap.containsKey(platformAttrType)) { + SupplyChainValidation tmpScv = validationTypeMap.get( + platformAttrType); + if (tmpScv.getResult() == PASS && attributeScv.getResult() == FAIL) { + validationTypeMap.put(platformAttrType, attributeScv); + } else if (tmpScv.getResult() == FAIL + && attributeScv.getResult() == FAIL) { + validationTypeMap.put(platformAttrType, new SupplyChainValidation( + attributeScv.getValidationType(), + attributeScv.getResult(), aes, + String.format("%s%n%s", tmpScv.getMessage(), attributeScv.getMessage()))); } + } else { + validationTypeMap.put(platformAttrType, attributeScv); } +// if (platformScv != null) { +// // have to make sure the attribute validation isn't ignored and +// // doesn't override general validation status +// if (platformScv.getResult() == PASS +// && attributeScv.getResult() != PASS) { +// // if the platform trust store validated but the attribute didn't +// // replace +// validationTypeMap.put( +// SupplyChainValidation.ValidationType +// .PLATFORM_CREDENTIAL_ATTRIBUTES, +// attributeScv); +// } else if ((platformScv.getResult() == PASS +// && attributeScv.getResult() == PASS) +// || (platformScv.getResult() != PASS +// && attributeScv.getResult() != PASS)) { +// // if both trust store and attributes validated or failed +// // combine messages +// validations.add(new SupplyChainValidation( +// platformScv.getValidationType(), +// platformScv.getResult(), aes, +// String.format("%s%n%s", platformScv.getMessage(), +// attributeScv.getMessage()))); +// } +// } + pc.setDevice(device); this.certificateManager.update(pc); } } + //combine platform and platform attributes + validations.remove(platformScv); + attributeScv = validationTypeMap.get( + platformAttrType); + if (platformScv.getResult() == PASS && attributeScv.getResult() == FAIL) { + validations.add(new SupplyChainValidation( + platformScv.getValidationType(), + attributeScv.getResult(), aes, attributeScv.getMessage())); + } else if (platformScv.getResult() == FAIL && attributeScv.getResult() == FAIL) { + validations.add(new SupplyChainValidation( + platformScv.getValidationType(), + platformScv.getResult(), aes, + String.format("%s%n%s", platformScv.getMessage(), + attributeScv.getMessage()))); + } } } @@ -645,7 +735,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe final PlatformCredential pc, final DeviceInfoReport deviceInfoReport, final EndorsementCredential ec) { final SupplyChainValidation.ValidationType validationType - = SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL; + = SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES; if (pc == null) { LOGGER.error("No platform credential to validate"); @@ -676,7 +766,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe final PlatformCredential base, final Map deltaMapping) { final SupplyChainValidation.ValidationType validationType - = SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL; + = SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES; if (delta == null) { LOGGER.error("No delta certificate to validate"); diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/AppraisalStatus.java b/HIRS_Utils/src/main/java/hirs/data/persist/AppraisalStatus.java index dd5ddfc5..87491887 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/AppraisalStatus.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/AppraisalStatus.java @@ -40,8 +40,7 @@ public class AppraisalStatus { * @param message description of result */ public AppraisalStatus(final Status appStatus, final String message) { - this.appStatus = appStatus; - this.message = message; + this(appStatus, message, ""); } /** diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/attributes/V2/ComponentIdentifierV2.java b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/attributes/V2/ComponentIdentifierV2.java index a9e5fdb0..00ebf805 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/attributes/V2/ComponentIdentifierV2.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/attributes/V2/ComponentIdentifierV2.java @@ -235,6 +235,14 @@ public class ComponentIdentifierV2 extends ComponentIdentifier { return getAttributeStatus() == AttributeStatus.REMOVED; } + /** + * @return true if the component status wasn't set. + */ + public final boolean isEmpty() { + return (getAttributeStatus() == AttributeStatus.EMPTY_STATUS) + || (getAttributeStatus() == null); + } + /** * @return indicates the type of platform certificate. */ diff --git a/HIRS_Utils/src/main/java/hirs/validation/SupplyChainCredentialValidator.java b/HIRS_Utils/src/main/java/hirs/validation/SupplyChainCredentialValidator.java index 6ce019d4..5e65b1f1 100644 --- a/HIRS_Utils/src/main/java/hirs/validation/SupplyChainCredentialValidator.java +++ b/HIRS_Utils/src/main/java/hirs/validation/SupplyChainCredentialValidator.java @@ -633,7 +633,7 @@ public final class SupplyChainCredentialValidator implements CredentialValidator List certificateList = null; SupplyChainValidation scv = null; resultMessage.append("There are errors with Delta " - + "Component Statuses components:\n"); + + "Component Statuses:\n"); // go through the leaf and check the changes against the valid components // forget modifying validOrigPcComponents for (PlatformCredential delta : chainCertificates) { @@ -744,12 +744,24 @@ public final class SupplyChainCredentialValidator implements CredentialValidator } else { builtMatchList.add(ci); } + } else if (ciV2.isEmpty()) { + fieldValidation = false; + LOGGER.warn(String.format("%s for delta %s has empty status", + ciV2.getComponentClass().toString(), + delta.getSerialNumber().toString())); + failureMsg.append(String.format("Empty component status " + + "in delta certificate. (%s)%n", + delta.getSerialNumber().toString())); + deltaMapping.put(delta, new SupplyChainValidation( + SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL, + FAIL, certificateList, + failureMsg.toString() + )); } } } // each delta has a change to change or modify what was just modified modifiedClassValues.clear(); - resultMessage.append(failureMsg.toString()); } @@ -809,11 +821,10 @@ public final class SupplyChainCredentialValidator implements CredentialValidator for (ComponentIdentifier cId : fullDeltaChainComponents) { ciV2 = (ComponentIdentifierV2) cId; if (ciV2.getComponentClass().getClassValueString() - .contains(cInfo.getComponentClass())) { - if (isMatch(cId, cInfo)) { + .contains(cInfo.getComponentClass()) + && isMatch(cId, cInfo)) { subCompIdList.remove(cId); subCompInfoList.remove(cInfo); - } } } }