From ee294e456299ced4c51f4efdf8b9324a370b8025 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Tue, 25 Aug 2020 11:36:37 -0400 Subject: [PATCH 01/12] SupplyCahinValidationService did not like the additions of a method returning a SupplyChainValidation, switched to Summary and it worked. This was the cause of the DB crashing. --- ...stractAttestationCertificateAuthority.java | 7 +- .../service/SupplyChainValidationService.java | 8 ++ .../SupplyChainValidationServiceImpl.java | 74 ++++++++++++++++++- HIRS_ProvisionerTPM2/src/CommandTpm2.cpp | 2 +- .../src/ProvisionerTpm2.proto | 2 +- .../src/RestfulClientProvisioner.cpp | 2 +- HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp | 7 +- .../IssuedAttestationCertificate.java | 22 ------ 8 files changed, 93 insertions(+), 31 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index 46686746..3d57dab2 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -515,9 +515,9 @@ public abstract class AbstractAttestationCertificateAuthority if (request.getQuote() != null && !request.getQuote().isEmpty()) { parseTPMQuote(request.getQuote().toStringUtf8()); } - if (request.getPcrslist() != null && !request.getPcrslist().isEmpty()) { - this.pcrValues = request.getPcrslist().toStringUtf8(); - } +// if (request.getPcrslist() != null && !request.getPcrslist().isEmpty()) { +// this.pcrValues = request.getPcrslist().toStringUtf8(); +// } // Get device name and device String deviceName = claim.getDv().getNw().getHostname(); @@ -1477,7 +1477,6 @@ public abstract class AbstractAttestationCertificateAuthority IssuedAttestationCertificate attCert = new IssuedAttestationCertificate( derEncodedAttestationCertificate, endorsementCredential, platformCredentials); attCert.setDevice(device); - attCert.setPcrValues(savePcrValues(pcrValues, device.getName())); certificateManager.save(attCert); } catch (Exception e) { LOG.error("Error saving generated Attestation Certificate to database.", e); diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java index f3d6de85..f3007bab 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java @@ -25,4 +25,12 @@ public interface SupplyChainValidationService { SupplyChainValidationSummary validateSupplyChain(EndorsementCredential ec, Set pc, Device device); + + /** + * A supplemental method that handles validating just the quote post main validation. + * + * @param device the associated device. + * @return True if validation is successful, false otherwise. + */ + SupplyChainValidationSummary validateQuote(Device device); } 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 b6ffbcc1..86516e1f 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java @@ -127,6 +127,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe List validations = new LinkedList<>(); Map deltaMapping = new HashMap<>(); SupplyChainValidation platformScv = null; + LOGGER.info("Validating supply chain."); // Validate the Endorsement Credential if (policy.isEcValidationEnabled()) { @@ -260,6 +261,77 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe return summary; } + /** + * A supplemental method that handles validating just the quote post main validation. + * + * @param device the associated device. + * @return True if validation is successful, false otherwise. + */ + @Override + public SupplyChainValidationSummary validateQuote(final Device device) { + final Appraiser supplyChainAppraiser = appraiserManager.getAppraiser( + SupplyChainAppraiser.NAME); + SupplyChainPolicy policy = (SupplyChainPolicy) policyManager.getDefaultPolicy( + supplyChainAppraiser); + SupplyChainValidation quoteScv = null; + SupplyChainValidationSummary summary = supplyChainValidatorSummaryManager.get(device.getId()); + Level level = Level.ERROR; + AppraisalStatus fwStatus = new AppraisalStatus(FAIL, + SupplyChainCredentialValidator.FIRMWARE_VALID); + + // If the device already failed, then ignore + if (summary.getOverallValidationResult() == PASS) { + // check if the policy is enabled + if (policy.isFirmwareValidationEnabled()) { + String[] baseline = new String[Integer.SIZE]; + String manufacturer = device.getDeviceInfo() + .getHardwareInfo().getManufacturer(); + + // need to get pcrs + ReferenceManifest rim = ReferenceManifest.select( + this.referenceManifestManager) + .byManufacturer(manufacturer) + .getRIM(); + + if (rim == null) { + fwStatus = new AppraisalStatus(FAIL, + String.format("Firmware Quote validation failed: " + + "No associated RIM file could be found for %s", + manufacturer)); + } else { + List swids = rim.parseResource(); + for (SwidResource swid : swids) { + baseline = swid.getPcrValues() + .toArray(new String[swid.getPcrValues().size()]); + } + + PCRPolicy pcrPolicy = policy.getPcrPolicy(); + + pcrPolicy.setBaselinePcrs(baseline); + // grab the quote +// byte[] hash = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash(); +// byte[] signature = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash(); +// +// if (!pcrPolicy.validateQuote(hash)) { +// quoteScv = buildValidationRecord(SupplyChainValidation.ValidationType.FIRMWARE, +// fwStatus.getAppStatus(), +// "Firmware validation of TPM Quote failed.", rim, level); +// } + } + } + } + + // Generate validation summary, save it, and return it. + summary.getValidations().add(quoteScv); //verify + try { + supplyChainValidatorSummaryManager.save(summary); + } catch (DBManagerException ex) { + LOGGER.error("Failed to save Supply Chain summary", ex); + } + + return summary; + } + /** * This method is a sub set of the validate supply chain method and focuses * on the specific multibase validation check for a delta chain. This method @@ -349,7 +421,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe pcrPolicy.setBaselinePcrs(baseline); if (attCert != null) { - Path pcrPath = Paths.get(attCert.getPcrValues()); + Path pcrPath = Paths.get(""); String pcrContent = ""; if (Files.exists(pcrPath)) { try { diff --git a/HIRS_ProvisionerTPM2/src/CommandTpm2.cpp b/HIRS_ProvisionerTPM2/src/CommandTpm2.cpp index f2976299..226e42a4 100644 --- a/HIRS_ProvisionerTPM2/src/CommandTpm2.cpp +++ b/HIRS_ProvisionerTPM2/src/CommandTpm2.cpp @@ -558,7 +558,7 @@ string CommandTpm2::getQuote(const string& pcr_selection, * Method to get the full list of pcrs from the TPM. * */ -string CommandTpm2::getPcrsList() { +string CommandTpm2::getPcrList() { string pcrslist; stringstream argsStream; diff --git a/HIRS_ProvisionerTPM2/src/ProvisionerTpm2.proto b/HIRS_ProvisionerTPM2/src/ProvisionerTpm2.proto index f0bb5868..9f34d2a2 100644 --- a/HIRS_ProvisionerTPM2/src/ProvisionerTpm2.proto +++ b/HIRS_ProvisionerTPM2/src/ProvisionerTpm2.proto @@ -57,6 +57,7 @@ message DeviceInfo { required HardwareInfo hw = 2; required NetworkInfo nw = 3; required OsInfo os = 4; + optional bytes pcrslist = 5; } message IdentityClaim { @@ -80,7 +81,6 @@ message IdentityClaimResponse { message CertificateRequest { required bytes nonce = 1; optional bytes quote = 2; - optional bytes pcrslist = 3; } message CertificateResponse { diff --git a/HIRS_ProvisionerTPM2/src/RestfulClientProvisioner.cpp b/HIRS_ProvisionerTPM2/src/RestfulClientProvisioner.cpp index 4969d146..e734f588 100644 --- a/HIRS_ProvisionerTPM2/src/RestfulClientProvisioner.cpp +++ b/HIRS_ProvisionerTPM2/src/RestfulClientProvisioner.cpp @@ -98,7 +98,7 @@ string RestfulClientProvisioner::sendIdentityClaim( stringstream errormsg; errormsg << "Error communicating with ACA server. " << "Received response code: " << to_string(r.status_code) - << "\n\nError message fom ACA was: " + << "\n\nError message from ACA was: " << JSONFieldParser::parseJsonStringField(r.text, ACA_ERROR_FIELDNAME); throw HirsRuntimeException(errormsg.str(), diff --git a/HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp b/HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp index c8e78851..835e4be2 100644 --- a/HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp +++ b/HIRS_ProvisionerTPM2/src/TPM2_Provisioner.cpp @@ -64,6 +64,7 @@ int provision() { // collect device info cout << "----> Collecting device information" << endl; hirs::pb::DeviceInfo dv = DeviceInfoCollector::collectDeviceInfo(); + dv.set_pcrslist(tpm2.getPcrList()); // send identity claim cout << "----> Sending identity claim to Attestation CA" << endl; @@ -106,10 +107,14 @@ int provision() { "14,15,16,17,18,19,20,21,22,23", decryptedNonce)); - certificateRequest.set_pcrslist(tpm2.getPcrsList()); const string& akCertificateByteString = provisioner.sendAttestationCertificateRequest(certificateRequest); + if (akCertificateByteString == "") { + cout << "----> Provisioning failed."; + cout << "Please refer to the Attestation CA for details." << endl; + return 0; + } cout << "----> Storing attestation key certificate" << endl; tpm2.storeAKCertificate(akCertificateByteString); return 1; diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/IssuedAttestationCertificate.java b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/IssuedAttestationCertificate.java index b24eafa0..3782daee 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/certificate/IssuedAttestationCertificate.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/certificate/IssuedAttestationCertificate.java @@ -10,7 +10,6 @@ import java.util.Set; import java.util.UUID; import javax.persistence.Entity; import javax.persistence.FetchType; -import javax.persistence.Column; import javax.persistence.JoinColumn; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; @@ -21,8 +20,6 @@ import javax.persistence.ManyToOne; @Entity public class IssuedAttestationCertificate extends DeviceAssociatedCertificate { - private static final int MAX_CERT_LENGTH_BYTES = 1024; - /** * AIC label that must be used. */ @@ -36,9 +33,6 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate { @JoinColumn(name = "pc_id") private Set platformCredentials; - @Column(nullable = true, length = MAX_CERT_LENGTH_BYTES) - private String pcrValues; - /** * This class enables the retrieval of IssuedAttestationCertificate by their attributes. */ @@ -129,20 +123,4 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate { public Set getPlatformCredentials() { return Collections.unmodifiableSet(platformCredentials); } - - /** - * Getter for the pcrValues passed up by the client. - * @return a string blob of pcrs - */ - public String getPcrValues() { - return pcrValues; - } - - /** - * Setter for the pcrValues passed up by the client. - * @param pcrValues to be stored. - */ - public void setPcrValues(final String pcrValues) { - this.pcrValues = pcrValues; - } } From 905f12052d342314940d34b0cd5d909ab4943b16 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Wed, 26 Aug 2020 07:54:39 -0400 Subject: [PATCH 02/12] This is the next stage of changes that doesn't cause a 404 error. This has a compile error because the PCRPolicy class references PCRComposite and PCRInfoShort. Both of the later classes had changes to add new constructors, and these new constructors are the source of the problem. --- ...stractAttestationCertificateAuthority.java | 30 +++- .../SupplyChainValidationServiceImpl.java | 38 ++--- .../java/hirs/data/persist/PCRPolicy.java | 57 ++++++- .../java/hirs/data/persist/info/TPMInfo.java | 158 ++++++++++++++++-- .../hirs/data/persist/tpm/PcrComposite.java | 2 +- 5 files changed, 243 insertions(+), 42 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index 3d57dab2..28144970 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -166,8 +166,8 @@ public abstract class AbstractAttestationCertificateAuthority private final DeviceRegister deviceRegister; private final DeviceManager deviceManager; private final DBManager tpm2ProvisionerStateDBManager; - private String tpmQuoteHash; - private String tpmSignatureHash; + private String tpmQuoteHash = ""; + private String tpmSignatureHash = ""; private String pcrValues; /** @@ -463,6 +463,32 @@ public abstract class AbstractAttestationCertificateAuthority return validationResult; } + /** + * Performs supply chain validation for just the quote under Firmware validation. + * Performed after main supply chain validation and a certificate request. + * + * @param device associated device to validate. + * @return the {@link AppraisalStatus} of the supply chain validation + */ + private AppraisalStatus.Status doQuoteValidation(final Device device) { + // perform supply chain validation + SupplyChainValidationSummary scvs = supplyChainValidationService.validateQuote(device); + AppraisalStatus.Status validationResult; + + // either validation wasn't enabled or device already failed + if (scvs == null) { + // this will just allow for the certificate to be saved. + validationResult = AppraisalStatus.Status.PASS; + } else { + // update the validation result in the device + validationResult = scvs.getOverallValidationResult(); + device.setSupplyChainStatus(validationResult); + deviceManager.updateDevice(device); + } + + return validationResult; + } + /** * Basic implementation of the ACA processCertificateRequest method. * Parses the nonce, validates its correctness, generates the signed, 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 86516e1f..d7b5c84c 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java @@ -1,9 +1,6 @@ package hirs.attestationca.service; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; @@ -40,7 +37,6 @@ import hirs.data.persist.certificate.Certificate; import hirs.data.persist.certificate.CertificateAuthorityCredential; import hirs.data.persist.certificate.EndorsementCredential; import hirs.data.persist.certificate.PlatformCredential; -import hirs.data.persist.certificate.IssuedAttestationCertificate; import hirs.data.persist.ReferenceManifest; import hirs.persist.AppraiserManager; import hirs.persist.CertificateManager; @@ -274,7 +270,8 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe SupplyChainPolicy policy = (SupplyChainPolicy) policyManager.getDefaultPolicy( supplyChainAppraiser); SupplyChainValidation quoteScv = null; - SupplyChainValidationSummary summary = supplyChainValidatorSummaryManager.get(device.getId()); + SupplyChainValidationSummary summary = supplyChainValidatorSummaryManager + .get(device.getId()); Level level = Level.ERROR; AppraisalStatus fwStatus = new AppraisalStatus(FAIL, SupplyChainCredentialValidator.FIRMWARE_VALID); @@ -313,7 +310,8 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe // byte[] signature = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash(); // // if (!pcrPolicy.validateQuote(hash)) { -// quoteScv = buildValidationRecord(SupplyChainValidation.ValidationType.FIRMWARE, +// quoteScv = buildValidationRecord(SupplyChainValidation +// .ValidationType.FIRMWARE, // fwStatus.getAppStatus(), // "Firmware validation of TPM Quote failed.", rim, level); // } @@ -397,9 +395,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe String manufacturer = device.getDeviceInfo() .getHardwareInfo().getManufacturer(); - IssuedAttestationCertificate attCert = IssuedAttestationCertificate - .select(this.certificateManager) - .byDeviceId(device.getId()).getCertificate(); ReferenceManifest rim = ReferenceManifest.select( this.referenceManifestManager) .byManufacturer(manufacturer) @@ -420,18 +415,15 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe } pcrPolicy.setBaselinePcrs(baseline); - if (attCert != null) { - Path pcrPath = Paths.get(""); + if (device != null) { String pcrContent = ""; - if (Files.exists(pcrPath)) { - try { - pcrContent = new String(Files.readAllBytes(pcrPath), "UTF8"); - } catch (IOException ioEx) { - LOGGER.error(ioEx); - } + try { + pcrContent = new String(device.getDeviceInfo().getTPMInfo().getPcrValues()); + } catch (NullPointerException npEx) { + LOGGER.error(npEx); } String[] pcrSet = null; - String[] quote = null; + String[] storedPcrs = null; int algorithmLength = baseline[0].length(); if (pcrContent.isEmpty()) { @@ -440,11 +432,11 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe + "provide pcr values."); LOGGER.warn(String.format( "Firmware validation failed: Client (%s) did not " - + "provide pcr values.", attCert.getDevice().getName())); + + "provide pcr values.", device.getName())); } else { // we have a full set of PCR values pcrSet = pcrContent.split("\\n"); - quote = new String[TPMMeasurementRecord.MAX_PCR_ID + 1]; + storedPcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1]; // we need to scroll through the entire list until we find // a matching hash length @@ -457,14 +449,14 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe == algorithmLength) { // found the matching set for (int j = 0; j <= TPMMeasurementRecord.MAX_PCR_ID; j++) { - quote[j] = pcrSet[++i].split(":")[1].trim(); + storedPcrs[j] = pcrSet[++i].split(":")[1].trim(); } break; } } } - if (quote[0].isEmpty()) { + if (storedPcrs[0].isEmpty()) { // validation fail fwStatus = new AppraisalStatus(FAIL, "Firmware validation failed: " @@ -472,7 +464,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe + "values are not the same algorithm " + "as associated RIM."); } else { - StringBuilder sb = pcrPolicy.validatePcrs(quote); + StringBuilder sb = pcrPolicy.validatePcrs(storedPcrs); if (sb.length() > 0) { level = Level.ERROR; fwStatus = new AppraisalStatus(FAIL, sb.toString()); diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java index e6a1a463..e2062d69 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java @@ -3,8 +3,18 @@ package hirs.data.persist; import javax.persistence.Column; import javax.persistence.Entity; import static org.apache.logging.log4j.LogManager.getLogger; + +import hirs.data.persist.tpm.PcrComposite; +import hirs.data.persist.tpm.PcrInfoShort; +import org.apache.commons.codec.DecoderException; import org.apache.logging.log4j.Logger; +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * The class handles the flags that ignore certain PCRs for validation. */ @@ -28,23 +38,28 @@ public final class PCRPolicy extends Policy { private boolean linuxOs = false; private String[] baselinePcrs; + private List measurements; /** * Default constructor. */ public PCRPolicy() { baselinePcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1]; + measurements = new ArrayList<>(baselinePcrs.length); } /** * Constructor to parse PCR values. * * @param pcrValues RIM provided baseline PCRs + * @throws DecoderException if byte array could not be decoded. */ - public PCRPolicy(final String[] pcrValues) { + public PCRPolicy(final String[] pcrValues) throws DecoderException { baselinePcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1]; + measurements = new ArrayList<>(baselinePcrs.length); for (int i = 0; i <= TPMMeasurementRecord.MAX_PCR_ID; i++) { baselinePcrs[i] = pcrValues[i]; + measurements.add(new TPMMeasurementRecord(i, pcrValues[i])); } } @@ -52,10 +67,10 @@ public final class PCRPolicy extends Policy { * Compares the baseline pcr list and the quote pcr list. If the * ignore flags are set, 10 and 17-19 will be skipped for comparison. * - * @param quotePcrs non-baseline pcr list + * @param storedPcrs non-baseline pcr list * @return a StringBuilder that is empty if everything passes. */ - public StringBuilder validatePcrs(final String[] quotePcrs) { + public StringBuilder validatePcrs(final String[] storedPcrs) { StringBuilder sb = new StringBuilder(); String failureMsg = "PCR %d does not match%n"; @@ -70,7 +85,7 @@ public final class PCRPolicy extends Policy { i += NUM_OF_TBOOT_PCR; } - if (!baselinePcrs[i].equals(quotePcrs[i])) { + if (!baselinePcrs[i].equals(storedPcrs[i])) { sb.append(String.format(failureMsg, i)); } } @@ -78,6 +93,40 @@ public final class PCRPolicy extends Policy { return sb; } + /** + * Compares hashs to validate the quote from the client. + * + * @param tpmQuote the provided quote + * @return true if validated, false if not + */ + public boolean validateQuote(final byte[] tpmQuote) { + boolean validated = false; + + short localityAtRelease = 0; + PcrComposite pcrComposite = new PcrComposite(this.measurements); + PcrInfoShort pcrInfoShort = new PcrInfoShort(localityAtRelease, + tpmQuote, pcrComposite); + + try { + if (!Arrays.equals(pcrInfoShort.getCalculatedDigest(), + pcrInfoShort.getCompositeHash())) { + LOGGER.error("This is NOT matching: "); + LOGGER.error(new String(pcrInfoShort.getCalculatedDigest(), "UTF-8")); + LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8")); + } else { + LOGGER.error("This is matching: "); + LOGGER.error(new String(pcrInfoShort.getCalculatedDigest(), "UTF-8")); + LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8")); + } + } catch (NoSuchAlgorithmException naEx) { + LOGGER.error(naEx); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + return validated; + } + /** * Getter for the array of baseline PCRs. * @return instance of the PCRs. diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/info/TPMInfo.java b/HIRS_Utils/src/main/java/hirs/data/persist/info/TPMInfo.java index 5e672956..dcb17814 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/info/TPMInfo.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/info/TPMInfo.java @@ -24,6 +24,7 @@ import org.hibernate.annotations.Type; @Embeddable public class TPMInfo implements Serializable { private static final Logger LOGGER = LogManager.getLogger(TPMInfo.class); + private static final int MAX_BLOB_SIZE = 65535; @XmlElement @Column(length = DeviceInfoReport.MED_STRING_LENGTH, nullable = true) @@ -52,6 +53,15 @@ public class TPMInfo implements Serializable { @JsonIgnore private X509Certificate identityCertificate; + @Column(nullable = true, length = MAX_BLOB_SIZE) + private byte[] pcrValues; + + @Column(nullable = true, length = MAX_BLOB_SIZE) + private byte[] tpmQuoteHash; + + @Column(nullable = true, length = MAX_BLOB_SIZE) + private byte[] tpmQuoteSignature; + /** * Constructor used to create a TPMInfo object. * @@ -68,17 +78,65 @@ public class TPMInfo implements Serializable { * short representing the minor revision number for the TPM * @param identityCertificate * byte array with the value of the identity certificate + * @param pcrValues + * short representing the major revision number for the TPM + * @param tpmQuoteHash + * short representing the minor revision number for the TPM + * @param tpmQuoteSignature + * byte array with the value of the identity certificate */ + @SuppressWarnings("parameternumber") public TPMInfo(final String tpmMake, final short tpmVersionMajor, final short tpmVersionMinor, final short tpmVersionRevMajor, final short tpmVersionRevMinor, - final X509Certificate identityCertificate) { + final X509Certificate identityCertificate, final byte[] pcrValues, + final byte[] tpmQuoteHash, final byte[] tpmQuoteSignature) { setTPMMake(tpmMake); setTPMVersionMajor(tpmVersionMajor); setTPMVersionMinor(tpmVersionMinor); setTPMVersionRevMajor(tpmVersionRevMajor); setTPMVersionRevMinor(tpmVersionRevMinor); setIdentityCertificate(identityCertificate); + setPcrValues(pcrValues); + setTpmQuoteHash(tpmQuoteHash); + setTpmQuoteSignature(tpmQuoteSignature); + } + + /** + * Constructor used to create a TPMInfo object without an identity + * certificate. + * + * @param tpmMake + * String representing the make information for the TPM, + * NullPointerException thrown if null + * @param tpmVersionMajor + * short representing the major version number for the TPM + * @param tpmVersionMinor + * short representing the minor version number for the TPM + * @param tpmVersionRevMajor + * short representing the major revision number for the TPM + * @param tpmVersionRevMinor + * short representing the minor revision number for the TPM + * @param pcrValues + * short representing the major revision number for the TPM + * @param tpmQuoteHash + * short representing the minor revision number for the TPM + * @param tpmQuoteSignature + * byte array with the value of the identity certificate + */ + @SuppressWarnings("parameternumber") + public TPMInfo(final String tpmMake, final short tpmVersionMajor, + final short tpmVersionMinor, final short tpmVersionRevMajor, + final short tpmVersionRevMinor, final byte[] pcrValues, + final byte[] tpmQuoteHash, final byte[] tpmQuoteSignature) { + setTPMMake(tpmMake); + setTPMVersionMajor(tpmVersionMajor); + setTPMVersionMinor(tpmVersionMinor); + setTPMVersionRevMajor(tpmVersionRevMajor); + setTPMVersionRevMinor(tpmVersionRevMinor); + setPcrValues(pcrValues); + setTpmQuoteHash(tpmQuoteHash); + setTpmQuoteSignature(tpmQuoteSignature); } /** @@ -98,13 +156,38 @@ public class TPMInfo implements Serializable { * short representing the minor revision number for the TPM */ public TPMInfo(final String tpmMake, final short tpmVersionMajor, - final short tpmVersionMinor, final short tpmVersionRevMajor, - final short tpmVersionRevMinor) { - setTPMMake(tpmMake); - setTPMVersionMajor(tpmVersionMajor); - setTPMVersionMinor(tpmVersionMinor); - setTPMVersionRevMajor(tpmVersionRevMajor); - setTPMVersionRevMinor(tpmVersionRevMinor); + final short tpmVersionMinor, final short tpmVersionRevMajor, + final short tpmVersionRevMinor) { + this(tpmMake, tpmVersionMajor, tpmVersionMinor, tpmVersionRevMajor, + tpmVersionRevMinor, null, + new byte[0], new byte[0], new byte[0]); + } + + /** + * Constructor used to create a TPMInfo object without an identity + * certificate. + * + * @param tpmMake + * String representing the make information for the TPM, + * NullPointerException thrown if null + * @param tpmVersionMajor + * short representing the major version number for the TPM + * @param tpmVersionMinor + * short representing the minor version number for the TPM + * @param tpmVersionRevMajor + * short representing the major revision number for the TPM + * @param tpmVersionRevMinor + * short representing the minor revision number for the TPM + * @param identityCertificate + * byte array with the value of the identity certificate + */ + public TPMInfo(final String tpmMake, final short tpmVersionMajor, + final short tpmVersionMinor, final short tpmVersionRevMajor, + final short tpmVersionRevMinor, + final X509Certificate identityCertificate) { + this(tpmMake, tpmVersionMajor, tpmVersionMinor, tpmVersionRevMajor, + tpmVersionRevMinor, identityCertificate, + new byte[0], new byte[0], new byte[0]); } /** @@ -112,10 +195,13 @@ public class TPMInfo implements Serializable { */ public TPMInfo() { this(DeviceInfoReport.NOT_SPECIFIED, - (short) 0, - (short) 0, - (short) 0, - (short) 0); + (short) 0, + (short) 0, + (short) 0, + (short) 0, + new byte[0], + new byte[0], + new byte[0]); identityCertificate = null; } @@ -175,6 +261,30 @@ public class TPMInfo implements Serializable { return identityCertificate; } + /** + * Getter for the tpmQuote passed up by the client. + * @return a byte blob of quote + */ + public final byte[] getTpmQuoteHash() { + return tpmQuoteHash.clone(); + } + + /** + * Getter for the quote signature. + * @return a byte blob. + */ + public final byte[] getTpmQuoteSignature() { + return tpmQuoteSignature.clone(); + } + + /** + * Getter for the pcr values. + * @return a byte blob for the pcrValues. + */ + public final byte[] getPcrValues() { + return pcrValues.clone(); + } + @Override public final int hashCode() { final int prime = 31; @@ -285,4 +395,28 @@ public class TPMInfo implements Serializable { LOGGER.debug("setting identity certificate"); this.identityCertificate = identityCertificate; } + + private void setPcrValues(final byte[] pcrValues) { + if (pcrValues == null) { + this.pcrValues = new byte[0]; + } else { + this.pcrValues = pcrValues.clone(); + } + } + + private void setTpmQuoteHash(final byte[] tpmQuoteHash) { + if (tpmQuoteHash == null) { + this.tpmQuoteHash = new byte[0]; + } else { + this.tpmQuoteHash = tpmQuoteHash.clone(); + } + } + + private void setTpmQuoteSignature(final byte[] tpmQuoteSignature) { + if (tpmQuoteSignature == null) { + this.tpmQuoteSignature = new byte[0]; + } else { + this.tpmQuoteSignature = tpmQuoteSignature.clone(); + } + } } diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrComposite.java b/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrComposite.java index 0bf0f4fa..65dfd3f8 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrComposite.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrComposite.java @@ -115,7 +115,7 @@ public class PcrComposite { @XmlElement(name = "ValueSize", required = true) public final int getValueSize() { int valueSize = 0; - for (TPMMeasurementRecord record: this.pcrValueList) { + for (TPMMeasurementRecord record : this.pcrValueList) { valueSize += record.getHash().getDigest().length; } return valueSize; From 0f3eb1b5d05160b74b88abc3c2466f4f1d15ce86 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Wed, 26 Aug 2020 11:13:00 -0400 Subject: [PATCH 03/12] Took out initalizing TPMMeasurementRecord in PCRPolicy's constructor. This was likely throwing the DecoderException which caused the 404 error in the ACA. --- .../java/hirs/data/persist/PCRPolicy.java | 22 +++++++++---------- .../hirs/data/persist/tpm/PcrSelection.java | 7 ++++-- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java index e2062d69..0501d586 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java @@ -6,14 +6,12 @@ import static org.apache.logging.log4j.LogManager.getLogger; import hirs.data.persist.tpm.PcrComposite; import hirs.data.persist.tpm.PcrInfoShort; -import org.apache.commons.codec.DecoderException; +import hirs.data.persist.tpm.PcrSelection; import org.apache.logging.log4j.Logger; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; /** * The class handles the flags that ignore certain PCRs for validation. @@ -38,28 +36,23 @@ public final class PCRPolicy extends Policy { private boolean linuxOs = false; private String[] baselinePcrs; - private List measurements; /** * Default constructor. */ public PCRPolicy() { baselinePcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1]; - measurements = new ArrayList<>(baselinePcrs.length); } /** * Constructor to parse PCR values. * * @param pcrValues RIM provided baseline PCRs - * @throws DecoderException if byte array could not be decoded. */ - public PCRPolicy(final String[] pcrValues) throws DecoderException { + public PCRPolicy(final String[] pcrValues) { baselinePcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1]; - measurements = new ArrayList<>(baselinePcrs.length); for (int i = 0; i <= TPMMeasurementRecord.MAX_PCR_ID; i++) { baselinePcrs[i] = pcrValues[i]; - measurements.add(new TPMMeasurementRecord(i, pcrValues[i])); } } @@ -101,10 +94,15 @@ public final class PCRPolicy extends Policy { */ public boolean validateQuote(final byte[] tpmQuote) { boolean validated = false; - short localityAtRelease = 0; - PcrComposite pcrComposite = new PcrComposite(this.measurements); - PcrInfoShort pcrInfoShort = new PcrInfoShort(localityAtRelease, + + TPMMeasurementRecord[] measurements = new TPMMeasurementRecord[baselinePcrs.length]; + PcrSelection pcrSelection = new PcrSelection(PcrSelection.ALL_PCRS_ON); + PcrComposite pcrComposite = new PcrComposite( + pcrSelection, + Arrays.asList(measurements)); + PcrInfoShort pcrInfoShort = new PcrInfoShort(pcrSelection, + localityAtRelease, tpmQuote, pcrComposite); try { diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrSelection.java b/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrSelection.java index 8d31739b..a17e411d 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrSelection.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrSelection.java @@ -30,6 +30,10 @@ public class PcrSelection { private static final Logger LOGGER = LogManager .getLogger(PcrSelection.class); private static final int MAX_SIZE_PCR_ARRAY = 3; + /** + * All PCRs are on. + */ + public static final int ALL_PCRS_ON = 0xffffff; @XmlAttribute(name = "PcrSelect", required = true) private final byte[] pcrSelect; @@ -76,8 +80,7 @@ public class PcrSelection { * long value representing the bits to be selected */ public PcrSelection(final long pcrSelectLong) { - final int allPCRsOn = 0xffffff; - if (pcrSelectLong > allPCRsOn) { + if (pcrSelectLong > ALL_PCRS_ON) { LOGGER.error("pcrSelect long value must be less than 3 bytes"); throw new InvalidParameterException("pcrSelect"); } From 0ab91b9b4141c36fe94d8703b3058f6c837f2f3c Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Thu, 27 Aug 2020 12:11:12 -0400 Subject: [PATCH 04/12] All bugs are fixed. The SupplyChainValidationSummary wasn't getting pulled from the DB. --- ...stractAttestationCertificateAuthority.java | 133 +++++++----- .../service/SupplyChainValidationService.java | 4 +- .../SupplyChainValidationServiceImpl.java | 200 +++++++++--------- .../java/hirs/data/persist/PCRPolicy.java | 35 ++- .../hirs/data/persist/tpm/PcrInfoShort.java | 1 + 5 files changed, 209 insertions(+), 164 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index 28144970..20274d15 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -62,14 +62,11 @@ import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.nio.file.Paths; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyFactory; @@ -167,8 +164,9 @@ public abstract class AbstractAttestationCertificateAuthority private final DeviceManager deviceManager; private final DBManager tpm2ProvisionerStateDBManager; private String tpmQuoteHash = ""; - private String tpmSignatureHash = ""; + private String tpmQuoteSignature = ""; private String pcrValues; + private SupplyChainValidationSummary savedSummary; /** * Constructor. @@ -455,7 +453,7 @@ public abstract class AbstractAttestationCertificateAuthority // perform supply chain validation SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain( endorsementCredential, platformCredentials, device); - + savedSummary = summary; // update the validation result in the device AppraisalStatus.Status validationResult = summary.getOverallValidationResult(); device.setSupplyChainStatus(validationResult); @@ -472,7 +470,8 @@ public abstract class AbstractAttestationCertificateAuthority */ private AppraisalStatus.Status doQuoteValidation(final Device device) { // perform supply chain validation - SupplyChainValidationSummary scvs = supplyChainValidationService.validateQuote(device); + SupplyChainValidationSummary scvs = supplyChainValidationService.validateQuote( + device, savedSummary); AppraisalStatus.Status validationResult; // either validation wasn't enabled or device already failed @@ -536,37 +535,63 @@ public abstract class AbstractAttestationCertificateAuthority Set platformCredentials = parsePcsFromIdentityClaim(claim, endorsementCredential); - // Parse through the Provisioner supplied TPM Quote and pcr values - // these fields are optional - if (request.getQuote() != null && !request.getQuote().isEmpty()) { - parseTPMQuote(request.getQuote().toStringUtf8()); - } -// if (request.getPcrslist() != null && !request.getPcrslist().isEmpty()) { -// this.pcrValues = request.getPcrslist().toStringUtf8(); -// } - // Get device name and device String deviceName = claim.getDv().getNw().getHostname(); Device device = deviceManager.getDevice(deviceName); - // Create signed, attestation certificate - X509Certificate attestationCertificate = generateCredential(akPub, - endorsementCredential, platformCredentials, deviceName); - byte[] derEncodedAttestationCertificate = getDerEncodedCertificate( - attestationCertificate); + // Parse through the Provisioner supplied TPM Quote and pcr values + // these fields are optional + if (request.getQuote() != null && !request.getQuote().isEmpty()) { + parseTPMQuote(request.getQuote().toStringUtf8()); + TPMInfo savedInfo = device.getDeviceInfo().getTPMInfo(); + TPMInfo tpmInfo = null; + try { + tpmInfo = new TPMInfo(savedInfo.getTPMMake(), + savedInfo.getTPMVersionMajor(), + savedInfo.getTPMVersionMinor(), + savedInfo.getTPMVersionRevMajor(), + savedInfo.getTPMVersionRevMinor(), + savedInfo.getPcrValues(), + this.tpmQuoteHash.getBytes("UTF-8"), + this.tpmQuoteSignature.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + LOG.error(e); + } + DeviceInfoReport dvReport = new DeviceInfoReport( + device.getDeviceInfo().getNetworkInfo(), + device.getDeviceInfo().getOSInfo(), + device.getDeviceInfo().getFirmwareInfo(), + device.getDeviceInfo().getHardwareInfo(), tpmInfo, + claim.getClientVersion()); + device = this.deviceRegister.saveOrUpdateDevice(dvReport); + } - // We validated the nonce and made use of the identity claim so state can be deleted - tpm2ProvisionerStateDBManager.delete(tpm2ProvisionerState); + AppraisalStatus.Status validationResult = doQuoteValidation(device); + if (validationResult == AppraisalStatus.Status.PASS) { + // Create signed, attestation certificate + X509Certificate attestationCertificate = generateCredential(akPub, + endorsementCredential, platformCredentials, deviceName); + byte[] derEncodedAttestationCertificate = getDerEncodedCertificate( + attestationCertificate); - // Package the signed certificate into a response - ByteString certificateBytes = ByteString.copyFrom(derEncodedAttestationCertificate); - ProvisionerTpm2.CertificateResponse response = ProvisionerTpm2.CertificateResponse - .newBuilder().setCertificate(certificateBytes).build(); + // We validated the nonce and made use of the identity claim so state can be deleted + tpm2ProvisionerStateDBManager.delete(tpm2ProvisionerState); - saveAttestationCertificate(derEncodedAttestationCertificate, endorsementCredential, - platformCredentials, device); + // Package the signed certificate into a response + ByteString certificateBytes = ByteString.copyFrom(derEncodedAttestationCertificate); + ProvisionerTpm2.CertificateResponse response = ProvisionerTpm2.CertificateResponse + .newBuilder().setCertificate(certificateBytes).build(); - return response.toByteArray(); + saveAttestationCertificate(derEncodedAttestationCertificate, endorsementCredential, + platformCredentials, device); + + return response.toByteArray(); + } else { + LOG.error("Supply chain validation did not succeed. " + + "Firmware Quote Validation failed. Result is: " + + validationResult); + return new byte[]{}; + } } else { LOG.error("Could not process credential request. Invalid nonce provided: " + request.getNonce().toString()); @@ -579,7 +604,8 @@ public abstract class AbstractAttestationCertificateAuthority * quote and the signature hash. * @param tpmQuote contains hash values for the quote and the signature */ - private void parseTPMQuote(final String tpmQuote) { + private boolean parseTPMQuote(final String tpmQuote) { + boolean success = false; if (tpmQuote != null) { String[] lines = tpmQuote.split(":"); if (lines[1].contains("signature")) { @@ -587,8 +613,11 @@ public abstract class AbstractAttestationCertificateAuthority } else { this.tpmQuoteHash = lines[1].trim(); } - this.tpmSignatureHash = lines[2].trim(); + this.tpmQuoteSignature = lines[2].trim(); + success = true; } + + return success; } /** @@ -689,9 +718,24 @@ public abstract class AbstractAttestationCertificateAuthority hwProto.getProductVersion(), hwProto.getSystemSerialNumber(), firstChassisSerialNumber, firstBaseboardSerialNumber); + if (dv.getPcrslist() != null && !dv.getPcrslist().isEmpty()) { + this.pcrValues = dv.getPcrslist().toStringUtf8(); + } // Get TPM info, currently unimplemented TPMInfo tpm = new TPMInfo(); + try { + tpm = new TPMInfo(DeviceInfoReport.NOT_SPECIFIED, + (short) 0, + (short) 0, + (short) 0, + (short) 0, + this.pcrValues.getBytes("UTF-8"), + this.tpmQuoteHash.getBytes("UTF-8"), + this.tpmQuoteSignature.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + tpm = new TPMInfo(); + } // Create final report DeviceInfoReport dvReport = new DeviceInfoReport(nw, os, fw, hw, tpm, @@ -1511,29 +1555,4 @@ public abstract class AbstractAttestationCertificateAuthority + e.getMessage(), e); } } - - private String savePcrValues(final String pcrValues, final String deviceName) { - if (pcrValues != null && !pcrValues.isEmpty()) { - try { - if (Files.notExists(Paths.get(PCR_UPLOAD_FOLDER))) { - Files.createDirectory(Paths.get(PCR_UPLOAD_FOLDER)); - } - Path pcrPath = Paths.get(String.format("%s/%s", - PCR_UPLOAD_FOLDER, deviceName)); - if (Files.notExists(pcrPath)) { - Files.createFile(pcrPath); - } - Files.write(pcrPath, pcrValues.getBytes("UTF8")); - return pcrPath.toString(); - } catch (NoSuchFileException nsfEx) { - LOG.error(String.format("File Not found!: %s", - deviceName)); - LOG.error(nsfEx); - } catch (IOException ioEx) { - LOG.error(ioEx); - } - } - - return "empty"; - } } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java index f3007bab..98f2191f 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java @@ -30,7 +30,9 @@ public interface SupplyChainValidationService { * A supplemental method that handles validating just the quote post main validation. * * @param device the associated device. + * @param summary the associated device summary * @return True if validation is successful, false otherwise. */ - SupplyChainValidationSummary validateQuote(Device device); + SupplyChainValidationSummary validateQuote(Device device, + SupplyChainValidationSummary summary); } 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 d7b5c84c..d08fb4b7 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java @@ -257,79 +257,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe return summary; } - /** - * A supplemental method that handles validating just the quote post main validation. - * - * @param device the associated device. - * @return True if validation is successful, false otherwise. - */ - @Override - public SupplyChainValidationSummary validateQuote(final Device device) { - final Appraiser supplyChainAppraiser = appraiserManager.getAppraiser( - SupplyChainAppraiser.NAME); - SupplyChainPolicy policy = (SupplyChainPolicy) policyManager.getDefaultPolicy( - supplyChainAppraiser); - SupplyChainValidation quoteScv = null; - SupplyChainValidationSummary summary = supplyChainValidatorSummaryManager - .get(device.getId()); - Level level = Level.ERROR; - AppraisalStatus fwStatus = new AppraisalStatus(FAIL, - SupplyChainCredentialValidator.FIRMWARE_VALID); - - // If the device already failed, then ignore - if (summary.getOverallValidationResult() == PASS) { - // check if the policy is enabled - if (policy.isFirmwareValidationEnabled()) { - String[] baseline = new String[Integer.SIZE]; - String manufacturer = device.getDeviceInfo() - .getHardwareInfo().getManufacturer(); - - // need to get pcrs - ReferenceManifest rim = ReferenceManifest.select( - this.referenceManifestManager) - .byManufacturer(manufacturer) - .getRIM(); - - if (rim == null) { - fwStatus = new AppraisalStatus(FAIL, - String.format("Firmware Quote validation failed: " - + "No associated RIM file could be found for %s", - manufacturer)); - } else { - List swids = rim.parseResource(); - for (SwidResource swid : swids) { - baseline = swid.getPcrValues() - .toArray(new String[swid.getPcrValues().size()]); - } - - PCRPolicy pcrPolicy = policy.getPcrPolicy(); - - pcrPolicy.setBaselinePcrs(baseline); - // grab the quote -// byte[] hash = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash(); -// byte[] signature = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash(); -// -// if (!pcrPolicy.validateQuote(hash)) { -// quoteScv = buildValidationRecord(SupplyChainValidation -// .ValidationType.FIRMWARE, -// fwStatus.getAppStatus(), -// "Firmware validation of TPM Quote failed.", rim, level); -// } - } - } - } - - // Generate validation summary, save it, and return it. - summary.getValidations().add(quoteScv); //verify - try { - supplyChainValidatorSummaryManager.save(summary); - } catch (DBManagerException ex) { - LOGGER.error("Failed to save Supply Chain summary", ex); - } - - return summary; - } - /** * This method is a sub set of the validate supply chain method and focuses * on the specific multibase validation check for a delta chain. This method @@ -422,9 +349,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe } catch (NullPointerException npEx) { LOGGER.error(npEx); } - String[] pcrSet = null; - String[] storedPcrs = null; - int algorithmLength = baseline[0].length(); if (pcrContent.isEmpty()) { fwStatus = new AppraisalStatus(FAIL, @@ -435,26 +359,8 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe + "provide pcr values.", device.getName())); } else { // we have a full set of PCR values - pcrSet = pcrContent.split("\\n"); - storedPcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1]; - - // we need to scroll through the entire list until we find - // a matching hash length - int offset = 1; - - for (int i = 0; i < pcrSet.length; i++) { - if (pcrSet[i].contains("sha")) { - // entered a new set, check size - if (pcrSet[i + offset].split(":")[1].trim().length() - == algorithmLength) { - // found the matching set - for (int j = 0; j <= TPMMeasurementRecord.MAX_PCR_ID; j++) { - storedPcrs[j] = pcrSet[++i].split(":")[1].trim(); - } - break; - } - } - } + int algorithmLength = baseline[0].length(); + String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength); if (storedPcrs[0].isEmpty()) { // validation fail @@ -483,6 +389,81 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe fwStatus.getAppStatus(), fwStatus.getMessage(), rim, level); } + /** + * A supplemental method that handles validating just the quote post main validation. + * + * @param device the associated device. + * @param summary the associated device summary + * @return True if validation is successful, false otherwise. + */ + @Override + public SupplyChainValidationSummary validateQuote(final Device device, + final SupplyChainValidationSummary summary) { + final Appraiser supplyChainAppraiser = appraiserManager.getAppraiser( + SupplyChainAppraiser.NAME); + SupplyChainPolicy policy = (SupplyChainPolicy) policyManager.getDefaultPolicy( + supplyChainAppraiser); + SupplyChainValidation quoteScv = null; + SupplyChainValidationSummary newSummary = null; + Level level = Level.ERROR; + AppraisalStatus fwStatus = new AppraisalStatus(FAIL, + SupplyChainCredentialValidator.FIRMWARE_VALID); + + // check if the policy is enabled + if (policy.isFirmwareValidationEnabled()) { + String[] baseline = new String[Integer.SIZE]; + String manufacturer = device.getDeviceInfo() + .getHardwareInfo().getManufacturer(); + + // need to get pcrs + ReferenceManifest rim = ReferenceManifest.select( + this.referenceManifestManager) + .byManufacturer(manufacturer) + .getRIM(); + if (rim == null) { + fwStatus = new AppraisalStatus(FAIL, + String.format("Firmware Quote validation failed: " + + "No associated RIM file could be found for %s", + manufacturer)); + } else { + List swids = rim.parseResource(); + for (SwidResource swid : swids) { + baseline = swid.getPcrValues() + .toArray(new String[swid.getPcrValues().size()]); + } + int algorithmLength = baseline[0].length(); + String pcrContent = new String(device.getDeviceInfo().getTPMInfo().getPcrValues()); + String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength); + PCRPolicy pcrPolicy = policy.getPcrPolicy(); + pcrPolicy.setBaselinePcrs(baseline); + // grab the quote + byte[] hash = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash(); + byte[] signature = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash(); + if (!pcrPolicy.validateQuote(hash, storedPcrs)) { + quoteScv = buildValidationRecord(SupplyChainValidation + .ValidationType.FIRMWARE, + fwStatus.getAppStatus(), + "Firmware validation of TPM Quote failed.", rim, level); + } + } + + // Generate validation summary, save it, and return it. + + List validations = new ArrayList<>(); + validations.addAll(summary.getValidations()); + validations.add(quoteScv); + newSummary = new SupplyChainValidationSummary(device, validations); + + try { + supplyChainValidatorSummaryManager.update(newSummary); + } catch (DBManagerException ex) { + LOGGER.error("Failed to save Supply Chain summary", ex); + } + } + + return newSummary; + } + private SupplyChainValidation validateEndorsementCredential(final EndorsementCredential ec, final boolean acceptExpiredCerts) { final SupplyChainValidation.ValidationType validationType @@ -617,7 +598,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe final SupplyChainValidation.ValidationType validationType, final AppraisalStatus.Status result, final String message, final ArchivableEntity archivableEntity, final Level logLevel) { - List aeList = new ArrayList<>(); if (archivableEntity != null) { aeList.add(archivableEntity); @@ -735,4 +715,30 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe return multiple; } + + private String[] buildStoredPcrs(final String pcrContent, final int algorithmLength) { + // we have a full set of PCR values + String[] pcrSet = pcrContent.split("\\n"); + String[] storedPcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1]; + + // we need to scroll through the entire list until we find + // a matching hash length + int offset = 1; + + for (int i = 0; i < pcrSet.length; i++) { + if (pcrSet[i].contains("sha")) { + // entered a new set, check size + if (pcrSet[i + offset].split(":")[1].trim().length() + == algorithmLength) { + // found the matching set + for (int j = 0; j <= TPMMeasurementRecord.MAX_PCR_ID; j++) { + storedPcrs[j] = pcrSet[++i].split(":")[1].trim(); + } + break; + } + } + } + + return storedPcrs; + } } diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java index 0501d586..0f9f5b0b 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java @@ -2,16 +2,19 @@ package hirs.data.persist; import javax.persistence.Column; import javax.persistence.Entity; + import static org.apache.logging.log4j.LogManager.getLogger; import hirs.data.persist.tpm.PcrComposite; import hirs.data.persist.tpm.PcrInfoShort; import hirs.data.persist.tpm.PcrSelection; +import org.apache.commons.codec.DecoderException; import org.apache.logging.log4j.Logger; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; +import java.util.Base64; /** * The class handles the flags that ignore certain PCRs for validation. @@ -90,13 +93,22 @@ public final class PCRPolicy extends Policy { * Compares hashs to validate the quote from the client. * * @param tpmQuote the provided quote + * @param storedPcrs values from the RIM file * @return true if validated, false if not */ - public boolean validateQuote(final byte[] tpmQuote) { + public boolean validateQuote(final byte[] tpmQuote, final String[] storedPcrs) { + LOGGER.info("Validating quote from associated device."); boolean validated = false; short localityAtRelease = 0; TPMMeasurementRecord[] measurements = new TPMMeasurementRecord[baselinePcrs.length]; + try { + for (int i = 0; i <= TPMMeasurementRecord.MAX_PCR_ID; i++) { + measurements[i] = new TPMMeasurementRecord(i, storedPcrs[i]); + } + } catch (DecoderException deEx) { + LOGGER.error(deEx); + } PcrSelection pcrSelection = new PcrSelection(PcrSelection.ALL_PCRS_ON); PcrComposite pcrComposite = new PcrComposite( pcrSelection, @@ -106,20 +118,25 @@ public final class PCRPolicy extends Policy { tpmQuote, pcrComposite); try { - if (!Arrays.equals(pcrInfoShort.getCalculatedDigest(), - pcrInfoShort.getCompositeHash())) { - LOGGER.error("This is NOT matching: "); - LOGGER.error(new String(pcrInfoShort.getCalculatedDigest(), "UTF-8")); + validated = Arrays.equals(pcrInfoShort.getCalculatedDigest(), + pcrInfoShort.getCompositeHash()); + if (validated) { + LOGGER.error("This is matching: "); + String value = Base64.getEncoder().encodeToString(pcrInfoShort + .getCalculatedDigest()); + LOGGER.error(value); LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8")); } else { - LOGGER.error("This is matching: "); - LOGGER.error(new String(pcrInfoShort.getCalculatedDigest(), "UTF-8")); + LOGGER.error("This is NOT matching: "); + String value = new String(pcrInfoShort + .getCalculatedDigest(), "UTF-8"); + LOGGER.error(value); LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8")); } } catch (NoSuchAlgorithmException naEx) { LOGGER.error(naEx); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); + } catch (UnsupportedEncodingException ueEx) { + LOGGER.error(ueEx); } return validated; diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrInfoShort.java b/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrInfoShort.java index f551350d..1837ba84 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrInfoShort.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrInfoShort.java @@ -270,6 +270,7 @@ public class PcrInfoShort { while (iter.hasNext()) { TPMMeasurementRecord record = (TPMMeasurementRecord) iter.next(); + LOGGER.error(record.getHash()); byteBuffer.put(record.getHash().getDigest()); } From 5fe19c590436c638816e52973780d3afee74712d Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Fri, 28 Aug 2020 07:14:27 -0400 Subject: [PATCH 05/12] Updated the code to compare the composite hash and the calculated value. --- .../SupplyChainValidationServiceImpl.java | 5 ++--- .../java/hirs/data/persist/PCRPolicy.java | 22 +++++++------------ .../hirs/data/persist/tpm/PcrInfoShort.java | 2 -- 3 files changed, 10 insertions(+), 19 deletions(-) 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 d08fb4b7..f93ed01f 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java @@ -448,20 +448,19 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe } // Generate validation summary, save it, and return it. - List validations = new ArrayList<>(); validations.addAll(summary.getValidations()); validations.add(quoteScv); newSummary = new SupplyChainValidationSummary(device, validations); try { - supplyChainValidatorSummaryManager.update(newSummary); + supplyChainValidatorSummaryManager.save(summary); } catch (DBManagerException ex) { LOGGER.error("Failed to save Supply Chain summary", ex); } } - return newSummary; + return summary; } private SupplyChainValidation validateEndorsementCredential(final EndorsementCredential ec, diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java index 0f9f5b0b..86ba27e9 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java @@ -9,12 +9,12 @@ import hirs.data.persist.tpm.PcrComposite; import hirs.data.persist.tpm.PcrInfoShort; import hirs.data.persist.tpm.PcrSelection; import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; import org.apache.logging.log4j.Logger; -import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; import java.security.NoSuchAlgorithmException; import java.util.Arrays; -import java.util.Base64; /** * The class handles the flags that ignore certain PCRs for validation. @@ -100,6 +100,8 @@ public final class PCRPolicy extends Policy { LOGGER.info("Validating quote from associated device."); boolean validated = false; short localityAtRelease = 0; + Charset charset = Charset.forName("UTF-8"); + String quoteString = new String(tpmQuote, charset); TPMMeasurementRecord[] measurements = new TPMMeasurementRecord[baselinePcrs.length]; try { @@ -118,25 +120,17 @@ public final class PCRPolicy extends Policy { tpmQuote, pcrComposite); try { - validated = Arrays.equals(pcrInfoShort.getCalculatedDigest(), - pcrInfoShort.getCompositeHash()); + String calculatedString = Hex.encodeHexString( + pcrInfoShort.getCalculatedDigest()); + validated = quoteString.contains(calculatedString); if (validated) { LOGGER.error("This is matching: "); - String value = Base64.getEncoder().encodeToString(pcrInfoShort - .getCalculatedDigest()); - LOGGER.error(value); - LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8")); + } else { LOGGER.error("This is NOT matching: "); - String value = new String(pcrInfoShort - .getCalculatedDigest(), "UTF-8"); - LOGGER.error(value); - LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8")); } } catch (NoSuchAlgorithmException naEx) { LOGGER.error(naEx); - } catch (UnsupportedEncodingException ueEx) { - LOGGER.error(ueEx); } return validated; diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrInfoShort.java b/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrInfoShort.java index 1837ba84..5d2ff1ae 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrInfoShort.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/tpm/PcrInfoShort.java @@ -270,7 +270,6 @@ public class PcrInfoShort { while (iter.hasNext()) { TPMMeasurementRecord record = (TPMMeasurementRecord) iter.next(); - LOGGER.error(record.getHash()); byteBuffer.put(record.getHash().getDigest()); } @@ -288,7 +287,6 @@ public class PcrInfoShort { * @return byte array representing the PcrInfoShort object */ public final byte[] getValue() { - ByteBuffer byteBuffer = ByteBuffer.allocate(getLength()); byteBuffer.put(pcrSelection.getValue()); byteBuffer.put((byte) localityAtRelease); From 792a248ba0c5b7696a38dd96e12132c6dc4b11a3 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Fri, 28 Aug 2020 12:24:02 -0400 Subject: [PATCH 06/12] This code finishes up validating the pcrs against the provided tpm quote. However this will cause a second summary object to display if firmware validation is enabled. This is because the summary manager isn't able to get or update the previously saved summary. --- ...stractAttestationCertificateAuthority.java | 4 +- .../service/SupplyChainValidationService.java | 4 +- .../SupplyChainValidationServiceImpl.java | 38 +++++++++---------- .../java/hirs/data/persist/PCRPolicy.java | 6 --- 4 files changed, 20 insertions(+), 32 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index 20274d15..7fa97644 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -166,7 +166,6 @@ public abstract class AbstractAttestationCertificateAuthority private String tpmQuoteHash = ""; private String tpmQuoteSignature = ""; private String pcrValues; - private SupplyChainValidationSummary savedSummary; /** * Constructor. @@ -453,7 +452,6 @@ public abstract class AbstractAttestationCertificateAuthority // perform supply chain validation SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain( endorsementCredential, platformCredentials, device); - savedSummary = summary; // update the validation result in the device AppraisalStatus.Status validationResult = summary.getOverallValidationResult(); device.setSupplyChainStatus(validationResult); @@ -471,7 +469,7 @@ public abstract class AbstractAttestationCertificateAuthority private AppraisalStatus.Status doQuoteValidation(final Device device) { // perform supply chain validation SupplyChainValidationSummary scvs = supplyChainValidationService.validateQuote( - device, savedSummary); + device); AppraisalStatus.Status validationResult; // either validation wasn't enabled or device already failed diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java index 98f2191f..f3007bab 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java @@ -30,9 +30,7 @@ public interface SupplyChainValidationService { * A supplemental method that handles validating just the quote post main validation. * * @param device the associated device. - * @param summary the associated device summary * @return True if validation is successful, false otherwise. */ - SupplyChainValidationSummary validateQuote(Device device, - SupplyChainValidationSummary summary); + SupplyChainValidationSummary validateQuote(Device device); } 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 f93ed01f..34e224cb 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java @@ -393,18 +393,16 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe * A supplemental method that handles validating just the quote post main validation. * * @param device the associated device. - * @param summary the associated device summary * @return True if validation is successful, false otherwise. */ @Override - public SupplyChainValidationSummary validateQuote(final Device device, - final SupplyChainValidationSummary summary) { + public SupplyChainValidationSummary validateQuote(final Device device) { final Appraiser supplyChainAppraiser = appraiserManager.getAppraiser( SupplyChainAppraiser.NAME); SupplyChainPolicy policy = (SupplyChainPolicy) policyManager.getDefaultPolicy( supplyChainAppraiser); SupplyChainValidation quoteScv = null; - SupplyChainValidationSummary newSummary = null; + SupplyChainValidationSummary summary = null; Level level = Level.ERROR; AppraisalStatus fwStatus = new AppraisalStatus(FAIL, SupplyChainCredentialValidator.FIRMWARE_VALID); @@ -431,33 +429,33 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe baseline = swid.getPcrValues() .toArray(new String[swid.getPcrValues().size()]); } - int algorithmLength = baseline[0].length(); + String pcrContent = new String(device.getDeviceInfo().getTPMInfo().getPcrValues()); - String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength); + String[] storedPcrs = buildStoredPcrs(pcrContent, baseline[0].length()); PCRPolicy pcrPolicy = policy.getPcrPolicy(); pcrPolicy.setBaselinePcrs(baseline); // grab the quote byte[] hash = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash(); - byte[] signature = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash(); - if (!pcrPolicy.validateQuote(hash, storedPcrs)) { - quoteScv = buildValidationRecord(SupplyChainValidation - .ValidationType.FIRMWARE, - fwStatus.getAppStatus(), - "Firmware validation of TPM Quote failed.", rim, level); + if (pcrPolicy.validateQuote(hash, storedPcrs)) { + level = Level.INFO; + fwStatus = new AppraisalStatus(PASS, + SupplyChainCredentialValidator.FIRMWARE_VALID); + fwStatus.setMessage("Firmware validation of TPM Quote successful."); + + } else { + fwStatus.setMessage("Firmware validation of TPM Quote failed."); } } + quoteScv = buildValidationRecord(SupplyChainValidation + .ValidationType.FIRMWARE, + fwStatus.getAppStatus(), fwStatus.getMessage(), rim, level); + // Generate validation summary, save it, and return it. List validations = new ArrayList<>(); - validations.addAll(summary.getValidations()); validations.add(quoteScv); - newSummary = new SupplyChainValidationSummary(device, validations); - - try { - supplyChainValidatorSummaryManager.save(summary); - } catch (DBManagerException ex) { - LOGGER.error("Failed to save Supply Chain summary", ex); - } + summary = new SupplyChainValidationSummary(device, validations); + supplyChainValidatorSummaryManager.save(summary); } return summary; diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java index 86ba27e9..0c8eeafe 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/PCRPolicy.java @@ -123,12 +123,6 @@ public final class PCRPolicy extends Policy { String calculatedString = Hex.encodeHexString( pcrInfoShort.getCalculatedDigest()); validated = quoteString.contains(calculatedString); - if (validated) { - LOGGER.error("This is matching: "); - - } else { - LOGGER.error("This is NOT matching: "); - } } catch (NoSuchAlgorithmException naEx) { LOGGER.error(naEx); } From 0291b96ca82a42183f7f3db7c52d8e0d09fc2dfc Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Fri, 28 Aug 2020 14:02:40 -0400 Subject: [PATCH 07/12] Updated code should be able to print one summary --- ...stractAttestationCertificateAuthority.java | 3 ++- .../service/SupplyChainValidationService.java | 1 + .../SupplyChainValidationServiceImpl.java | 9 +++++++++ .../main/java/hirs/data/persist/Device.java | 19 +++++++++++++++++++ .../java/hirs/data/persist/SwidResource.java | 10 ++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index 7fa97644..79b14e70 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -302,7 +302,7 @@ public abstract class AbstractAttestationCertificateAuthority // update the validation result in the device device.setSupplyChainStatus(summary.getOverallValidationResult()); deviceManager.updateDevice(device); - + LOG.error("This is the device id? {} ", device.getId()); // check if supply chain validation succeeded. // If it did not, do not provide the IdentityResponseEnvelope if (summary.getOverallValidationResult() == AppraisalStatus.Status.PASS) { @@ -452,6 +452,7 @@ public abstract class AbstractAttestationCertificateAuthority // perform supply chain validation SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain( endorsementCredential, platformCredentials, device); + device.setSummaryId(summary.getId().toString()); // update the validation result in the device AppraisalStatus.Status validationResult = summary.getOverallValidationResult(); device.setSupplyChainStatus(validationResult); diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java index f3007bab..00e98b8e 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationService.java @@ -1,6 +1,7 @@ package hirs.attestationca.service; import java.util.Set; + import hirs.data.persist.Device; import hirs.data.persist.SupplyChainValidationSummary; import hirs.data.persist.certificate.EndorsementCredential; 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 34e224cb..ef2044f3 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.LinkedList; +import java.util.UUID; import java.util.stream.Collectors; import org.apache.logging.log4j.Level; import hirs.appraiser.Appraiser; @@ -47,6 +48,7 @@ import hirs.persist.DBManagerException; import hirs.persist.PersistenceConfiguration; import hirs.persist.PolicyManager; import hirs.validation.CredentialValidator; + import java.util.HashMap; import java.util.Map; @@ -254,6 +256,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe } catch (DBManagerException ex) { LOGGER.error("Failed to save Supply Chain summary", ex); } + return summary; } @@ -339,6 +342,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe for (SwidResource swid : swids) { baseline = swid.getPcrValues() .toArray(new String[swid.getPcrValues().size()]); + LOGGER.error("is file size valid {}", swid.isValidFileSize()); } pcrPolicy.setBaselinePcrs(baseline); @@ -453,9 +457,14 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe // Generate validation summary, save it, and return it. List validations = new ArrayList<>(); + SupplyChainValidationSummary previous + = this.supplyChainValidatorSummaryManager.get( + UUID.fromString(device.getSummaryId())); + validations.addAll(previous.getValidations()); validations.add(quoteScv); summary = new SupplyChainValidationSummary(device, validations); supplyChainValidatorSummaryManager.save(summary); + supplyChainValidatorSummaryManager.delete(previous.getId()); } return summary; diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/Device.java b/HIRS_Utils/src/main/java/hirs/data/persist/Device.java index 8a5a9c26..54084725 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/Device.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/Device.java @@ -95,6 +95,9 @@ public class Device extends AbstractEntity { @Column(name = "state_override_reason") private String overrideReason; + @Column(name = "summary_id") + private String summaryId; + /** * Default constructor required by Hibernate. */ @@ -358,6 +361,22 @@ public class Device extends AbstractEntity { this.supplyChainValidationStatus = supplyChainValidationStatus; } + /** + * Getter for the last summary id. + * @return UUID for the summary + */ + public String getSummaryId() { + return summaryId; + } + + /** + * Setter for the last summary id. + * @param summaryId UUID + */ + public void setSummaryId(final String summaryId) { + this.summaryId = summaryId; + } + /** * Returns a hash code for this Device. The hash code is * determined from the name of the Device. diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/SwidResource.java b/HIRS_Utils/src/main/java/hirs/data/persist/SwidResource.java index 0db88fe5..f9849676 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/SwidResource.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/SwidResource.java @@ -48,6 +48,7 @@ public class SwidResource { private List pcrValues; private TpmWhiteListBaseline tpmWhiteList; private DigestAlgorithm digest = DigestAlgorithm.SHA1; + private boolean validFileSize = false; /** * Default constructor. @@ -192,6 +193,14 @@ public class SwidResource { this.pcrValues = pcrValues; } + /** + * flag for if the file sizes match with the swidtag. + * @return true if they match + */ + public boolean isValidFileSize() { + return validFileSize; + } + /** * Getter for a generated map of the PCR values. * @@ -223,6 +232,7 @@ public class SwidResource { if (Files.exists(logPath)) { logProcessor = new TCGEventLog( Files.readAllBytes(logPath)); +// this.validFileSize = Files.size(logPath) == Long.getLong(this.size); } this.setPcrValues(Arrays.asList( logProcessor.getExpectedPCRValues())); From 325feffd9032b6d9201cd2c7f79f1a74eeed4985 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Tue, 8 Sep 2020 08:08:23 -0400 Subject: [PATCH 08/12] Update h file that was changed with the method change in the cpp class file. --- HIRS_ProvisionerTPM2/include/CommandTpm2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HIRS_ProvisionerTPM2/include/CommandTpm2.h b/HIRS_ProvisionerTPM2/include/CommandTpm2.h index b22c7f8b..986f2fa3 100644 --- a/HIRS_ProvisionerTPM2/include/CommandTpm2.h +++ b/HIRS_ProvisionerTPM2/include/CommandTpm2.h @@ -137,7 +137,7 @@ class CommandTpm2 { std::string getQuote(const std::string& pcr_selection, const std::string& nonce); - std::string getPcrsList(); + std::string getPcrList(); }; } // namespace tpm2 From 1ed02e72b2932836b60263d2c78f3a6372d8f9e6 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Wed, 9 Sep 2020 07:03:31 -0400 Subject: [PATCH 09/12] This last commit corrects the database error. The code attempts to save a new supplychainvalidationsummary it needs to be a supplychainvalidation recreation to create new primary keys. --- ...stractAttestationCertificateAuthority.java | 1 + .../SupplyChainValidationServiceImpl.java | 20 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index 79b14e70..f98b0569 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -478,6 +478,7 @@ public abstract class AbstractAttestationCertificateAuthority // this will just allow for the certificate to be saved. validationResult = AppraisalStatus.Status.PASS; } else { + device.setSummaryId(scvs.getId().toString()); // update the validation result in the device validationResult = scvs.getOverallValidationResult(); device.setSupplyChainStatus(validationResult); 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 ef2044f3..784a06fc 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/service/SupplyChainValidationServiceImpl.java @@ -342,7 +342,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe for (SwidResource swid : swids) { baseline = swid.getPcrValues() .toArray(new String[swid.getPcrValues().size()]); - LOGGER.error("is file size valid {}", swid.isValidFileSize()); } pcrPolicy.setBaselinePcrs(baseline); @@ -460,11 +459,24 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe SupplyChainValidationSummary previous = this.supplyChainValidatorSummaryManager.get( UUID.fromString(device.getSummaryId())); - validations.addAll(previous.getValidations()); + for (SupplyChainValidation scv : previous.getValidations()) { + if (scv.getValidationType() != SupplyChainValidation.ValidationType.FIRMWARE) { + validations.add(buildValidationRecord(scv.getValidationType(), + scv.getResult(), scv.getMessage(), + scv.getCertificatesUsed().get(0), Level.INFO)); + } + } validations.add(quoteScv); + previous.archive(); + supplyChainValidatorSummaryManager.update(previous); summary = new SupplyChainValidationSummary(device, validations); - supplyChainValidatorSummaryManager.save(summary); - supplyChainValidatorSummaryManager.delete(previous.getId()); + + // try removing the supply chain validation as well and resaving that + try { + supplyChainValidatorSummaryManager.save(summary); + } catch (DBManagerException ex) { + LOGGER.error("Failed to save Supply Chain Summary", ex); + } } return summary; From 4167696e1358ffd3d00f9ba25f4e1eedcb8ab0bc Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Wed, 9 Sep 2020 07:12:29 -0400 Subject: [PATCH 10/12] Removed commented line --- HIRS_Utils/src/main/java/hirs/data/persist/SwidResource.java | 1 - 1 file changed, 1 deletion(-) diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/SwidResource.java b/HIRS_Utils/src/main/java/hirs/data/persist/SwidResource.java index f9849676..8679ae53 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/SwidResource.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/SwidResource.java @@ -232,7 +232,6 @@ public class SwidResource { if (Files.exists(logPath)) { logProcessor = new TCGEventLog( Files.readAllBytes(logPath)); -// this.validFileSize = Files.size(logPath) == Long.getLong(this.size); } this.setPcrValues(Arrays.asList( logProcessor.getExpectedPCRValues())); From c18124e5acca9691a3e9ab7113297f36d5561eef Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Mon, 21 Sep 2020 08:19:39 -0400 Subject: [PATCH 11/12] Firmware validation produces 2 summaries. However, they both shouldn't be displayed. Added the restriction on the page controller to not display archived summaries. --- .../page/controllers/ValidationReportsPageController.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java index a95609a9..d05cce14 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java @@ -5,9 +5,11 @@ import hirs.attestationca.portal.datatables.DataTableResponse; import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter; import hirs.attestationca.portal.page.PageController; import hirs.attestationca.portal.page.params.NoPageParams; +import hirs.data.persist.certificate.Certificate; import org.apache.logging.log4j.Logger; import static org.apache.logging.log4j.LogManager.getLogger; import org.hibernate.Criteria; +import org.hibernate.criterion.Restrictions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; @@ -79,16 +81,17 @@ public class ValidationReportsPageController extends PageController records = OrderedListQueryDataTableAdapter.getOrderedList(SupplyChainValidationSummary.class, - supplyChainValidatorSummaryManager, input, orderColumnName, modifier); + supplyChainValidatorSummaryManager, input, orderColumnName, criteriaModifier); return new DataTableResponse<>(records, input); } From be4d4adb84b85e69736925fd75bc6a0ac83bc023 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Mon, 21 Sep 2020 08:35:39 -0400 Subject: [PATCH 12/12] Updated line length over 100 characters --- .../page/controllers/ValidationReportsPageController.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java index d05cce14..e95d4ca3 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java @@ -90,8 +90,10 @@ public class ValidationReportsPageController extends PageController records = - OrderedListQueryDataTableAdapter.getOrderedList(SupplyChainValidationSummary.class, - supplyChainValidatorSummaryManager, input, orderColumnName, criteriaModifier); + OrderedListQueryDataTableAdapter.getOrderedList( + SupplyChainValidationSummary.class, + supplyChainValidatorSummaryManager, input, orderColumnName, + criteriaModifier); return new DataTableResponse<>(records, input); }