diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/FirmwareScvValidator.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/FirmwareScvValidator.java index e4af66867..c7ac85ec3 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/FirmwareScvValidator.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/FirmwareScvValidator.java @@ -38,6 +38,7 @@ public class FirmwareScvValidator extends SupplyChainCredentialValidator { private static PcrValidator pcrValidator; + private static ReferenceManifest supportReferenceManifest; /** * @param device device @@ -54,17 +55,11 @@ public static AppraisalStatus validateFirmware( final ReferenceDigestValueRepository referenceDigestValueRepository, final CACredentialRepository caCredentialRepository) { boolean passed = true; - String[] baseline = new String[Integer.SIZE]; AppraisalStatus fwStatus = null; String hostName = device.getDeviceInfo().getNetworkInfo().getHostname(); -// ReferenceManifest validationObject; - List baseReferenceManifests = null; BaseReferenceManifest baseReferenceManifest = null; - ReferenceManifest supportReferenceManifest = null; EventLogMeasurements measurement = null; - //baseReferenceManifests = referenceManifestRepository.findAllBaseRims(); - // This block was looking for a base RIM matching the device name // The base rim might not have a device name associated with it- i.e. if it's uploaded to the ACA // prior to provisioning In this case, try to look up the event log associated with the device, @@ -108,190 +103,230 @@ public static AppraisalStatus validateFirmware( } if (passed) { - List resources = - baseReferenceManifest.getFileResources(); - fwStatus = new AppraisalStatus(PASS, - SupplyChainCredentialValidator.FIRMWARE_VALID); - - // verify signatures - ReferenceManifestValidator referenceManifestValidator = - new ReferenceManifestValidator(); - referenceManifestValidator.setRim(baseReferenceManifest.getRimBytes()); - - //Validate signing cert - List allCerts = caCredentialRepository.findAll(); - CertificateAuthorityCredential signingCert = null; - for (CertificateAuthorityCredential cert : allCerts) { - signingCert = cert; - KeyStore keyStore = null; - Set set = ValidationService.getCaChainRec(signingCert, - Collections.emptySet(), - caCredentialRepository); - try { - keyStore = ValidationService.caCertSetToKeystore(set); - } catch (Exception e) { - log.error("Error building CA chain for {}: {}", signingCert.getSubjectKeyIdentifier(), - e.getMessage()); + AppraisalStatus rimSignatureStatus = validateRimSignature(baseReferenceManifest, + caCredentialRepository, referenceManifestRepository); + if (rimSignatureStatus.getAppStatus() == PASS) { + AppraisalStatus pcrStatus = validatePcrValues(device, hostName, baseReferenceManifest, + measurement, referenceDigestValueRepository, policySettings); + if (pcrStatus.getAppStatus() == PASS) { + EventLogMeasurements eventLog = measurement; + eventLog.setOverallValidationResult(PASS); + referenceManifestRepository.save(eventLog); + fwStatus = new AppraisalStatus(PASS, SupplyChainCredentialValidator.FIRMWARE_VALID); + } else { + passed = false; } + } else { + passed = false; + } + } + if (!passed) { + fwStatus = new AppraisalStatus(FAIL, String.format("Firmware Validation failed: " + + "%s for %s can not be found", failedString, hostName)); + if (measurement != null) { + measurement.setOverallValidationResult(fwStatus.getAppStatus()); + referenceManifestRepository.save(measurement); + } + } + return fwStatus; + } - ArrayList certs = new ArrayList<>(set.size()); - for (CertificateAuthorityCredential cac : set) { - try { - certs.add(cac.getX509Certificate()); - } catch (IOException e) { - log.error("Error building CA chain for {}: {}", signingCert.getSubjectKeyIdentifier(), - e.getMessage()); - } - } - referenceManifestValidator.setTrustStore(certs); + private static AppraisalStatus validateRimSignature( + final BaseReferenceManifest baseReferenceManifest, + final CACredentialRepository caCredentialRepository, + final ReferenceManifestRepository referenceManifestRepository) { + List resources = + baseReferenceManifest.getFileResources(); + AppraisalStatus rimSignatureStatus = new AppraisalStatus(PASS, "RIM signature valid."); + boolean passed = true; + + // verify signatures + ReferenceManifestValidator referenceManifestValidator = + new ReferenceManifestValidator(); + referenceManifestValidator.setRim(baseReferenceManifest.getRimBytes()); + + //Validate signing cert + List allCerts = caCredentialRepository.findAll(); + CertificateAuthorityCredential signingCert = null; + for (CertificateAuthorityCredential cert : allCerts) { + signingCert = cert; + KeyStore keyStore = null; + Set set = ValidationService.getCaChainRec(signingCert, + Collections.emptySet(), + caCredentialRepository); + try { + keyStore = ValidationService.caCertSetToKeystore(set); + } catch (Exception e) { + log.error("Error building CA chain for " + signingCert.getSubjectKeyIdentifier() + ": " + + e.getMessage()); + } + + ArrayList certs = new ArrayList<>(set.size()); + for (CertificateAuthorityCredential cac : set) { try { - if (referenceManifestValidator.validateXmlSignature( - signingCert.getX509Certificate().getPublicKey(), - signingCert.getSubjectKeyIdString(), signingCert.getEncodedPublicKey())) { - try { - if (!SupplyChainCredentialValidator.verifyCertificate( - signingCert.getX509Certificate(), keyStore)) { - passed = false; - fwStatus = new AppraisalStatus(FAIL, - "Firmware validation failed: invalid certificate path."); - } - } catch (IOException ioEx) { - log.error("Error getting X509 cert from manager: {}", ioEx.getMessage()); - } catch (SupplyChainValidatorException scvEx) { - log.error("Error validating cert against keystore: {}", scvEx.getMessage()); - fwStatus = new AppraisalStatus(FAIL, - "Firmware validation failed: invalid certificate path."); + certs.add(cac.getX509Certificate()); + } catch (IOException e) { + log.error( + "Error building CA chain for " + signingCert.getSubjectKeyIdentifier() + ": " + + e.getMessage()); + } + } + referenceManifestValidator.setTrustStore(certs); + try { + if (referenceManifestValidator.validateXmlSignature( + signingCert.getX509Certificate().getPublicKey(), + signingCert.getSubjectKeyIdString(), signingCert.getEncodedPublicKey())) { + try { + if (!SupplyChainCredentialValidator.verifyCertificate( + signingCert.getX509Certificate(), keyStore)) { + passed = false; + rimSignatureStatus = new AppraisalStatus(FAIL, + "RIM signature validation failed: invalid certificate path."); } - break; + } catch (IOException ioEx) { + log.error("Error getting X509 cert from manager: " + ioEx.getMessage()); + } catch (SupplyChainValidatorException scvEx) { + log.error("Error validating cert against keystore: " + scvEx.getMessage()); + rimSignatureStatus = new AppraisalStatus(FAIL, + "RIM signature validation failed: invalid certificate path."); } - } catch (IOException ioEx) { - log.error("Error getting X509 cert from manager: {}", ioEx.getMessage()); + break; } + } catch (IOException ioEx) { + log.error("Error getting X509 cert from manager: " + ioEx.getMessage()); } + } - for (SwidResource swidRes : resources) { - supportReferenceManifest = referenceManifestRepository.findByHexDecHashAndRimType( - swidRes.getHashValue(), ReferenceManifest.SUPPORT_RIM); - if (supportReferenceManifest != null) { - // Removed the filename check from this if statement - referenceManifestValidator.validateSupportRimHash( - supportReferenceManifest.getRimBytes(), swidRes.getHashValue()); - } + for (SwidResource swidRes : resources) { + supportReferenceManifest = referenceManifestRepository.findByHexDecHashAndRimType( + swidRes.getHashValue(), ReferenceManifest.SUPPORT_RIM); + if (supportReferenceManifest != null) { + // Removed the filename check from this if statement + referenceManifestValidator.validateSupportRimHash( + supportReferenceManifest.getRimBytes(), swidRes.getHashValue()); } + } - if (passed && signingCert == null) { - passed = false; - fwStatus = new AppraisalStatus(FAIL, - "Firmware validation failed: signing cert not found."); - } + if (passed && signingCert == null) { + passed = false; + rimSignatureStatus = new AppraisalStatus(FAIL, + "RIM signature validation failed: signing cert not found."); + } - if (passed && supportReferenceManifest == null) { - fwStatus = new AppraisalStatus(FAIL, - "Support Reference Integrity Manifest can not be found"); - passed = false; - } + if (passed && supportReferenceManifest == null) { + rimSignatureStatus = new AppraisalStatus(FAIL, + "Support Reference Integrity Manifest can not be found"); + passed = false; + } - if (passed && !referenceManifestValidator.isSignatureValid()) { - passed = false; - fwStatus = new AppraisalStatus(FAIL, - "Firmware validation failed: Signature validation " - + "failed for Base RIM."); - } + if (passed && !referenceManifestValidator.isSignatureValid()) { + passed = false; + rimSignatureStatus = new AppraisalStatus(FAIL, + "RIM signature validation failed: Signature validation " + + "failed for Base RIM."); + } - if (passed && !referenceManifestValidator.isSupportRimValid()) { - passed = false; - fwStatus = new AppraisalStatus(FAIL, - "Firmware validation failed: Hash validation " - + "failed for Support RIM."); - } + if (passed && !referenceManifestValidator.isSupportRimValid()) { + rimSignatureStatus = new AppraisalStatus(FAIL, + "RIM signature validation failed: Hash validation " + + "failed for Support RIM."); + } - if (passed) { - TCGEventLog expectedEventLog; - try { - expectedEventLog = new TCGEventLog(supportReferenceManifest.getRimBytes()); - baseline = expectedEventLog.getExpectedPCRValues(); - } catch (CertificateException | IOException | NoSuchAlgorithmException cEx) { - log.error(cEx); - } + return rimSignatureStatus; + } - // part 1 of firmware validation check: PCR baseline match - pcrValidator = new PcrValidator(baseline); + private static AppraisalStatus validatePcrValues( + final Device device, + final String hostName, + final ReferenceManifest baseReferenceManifest, + final EventLogMeasurements measurement, + final ReferenceDigestValueRepository referenceDigestValueRepository, + final PolicySettings policySettings) { - if (baseline.length > 0) { - String pcrContent = ""; - pcrContent = new String(device.getDeviceInfo().getTpmInfo().getPcrValues(), - StandardCharsets.UTF_8); + String[] baseline = new String[Integer.SIZE]; + TCGEventLog logProcessor; + AppraisalStatus pcrAppraisalStatus = new AppraisalStatus(PASS, "PCR values validated."); + try { + logProcessor = new TCGEventLog(supportReferenceManifest.getRimBytes()); + baseline = logProcessor.getExpectedPCRValues(); + } catch (CertificateException cEx) { + log.error(cEx); + } catch (NoSuchAlgorithmException noSaEx) { + log.error(noSaEx); + } catch (IOException ioEx) { + log.error(ioEx); + } - if (pcrContent.isEmpty()) { - fwStatus = new AppraisalStatus(FAIL, - "Firmware validation failed: Client did not " - + "provide pcr values."); - log.warn("Firmware validation failed: Client ({}) did not " - + "provide pcr values.", device.getName()); - } else { - // we have a full set of PCR values - //int algorithmLength = baseline[0].length(); - //String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength); - //pcrPolicy.validatePcrs(storedPcrs); - - // part 2 of firmware validation check: bios measurements - // vs baseline tcg event log - // find the measurement - TCGEventLog actualEventLog; - LinkedList failedPcrValues = new LinkedList<>(); - List rimIntegrityMeasurements; - HashMap expectedEventLogRecords = new HashMap<>(); - try { - if (measurement.getDeviceName().equals(hostName)) { - actualEventLog = new TCGEventLog(measurement.getRimBytes()); - rimIntegrityMeasurements = referenceDigestValueRepository - .findValuesByBaseRimId(baseReferenceManifest.getId()); - for (ReferenceDigestValue rdv : rimIntegrityMeasurements) { - expectedEventLogRecords.put(rdv.getDigestValue(), rdv); - } - - failedPcrValues.addAll(pcrValidator.validateTpmEvents( - actualEventLog, expectedEventLogRecords, policySettings)); - } - } catch (CertificateException | NoSuchAlgorithmException | IOException exception) { - log.error(exception); - } + // part 1 of firmware validation check: PCR baseline match + pcrValidator = new PcrValidator(baseline); + + if (baseline.length > 0) { + String pcrContent = ""; + pcrContent = new String(device.getDeviceInfo().getTpmInfo().getPcrValues(), + StandardCharsets.UTF_8); - if (!failedPcrValues.isEmpty()) { - StringBuilder sb = new StringBuilder(); - sb.append(String.format("%d digest(s) were not found:%n", - failedPcrValues.size())); - for (TpmPcrEvent tpe : failedPcrValues) { - sb.append(String.format("PCR Index %d - %s%n", - tpe.getPcrIndex(), - tpe.getEventTypeStr())); - } - if (fwStatus.getAppStatus().equals(FAIL)) { - fwStatus = new AppraisalStatus(FAIL, String.format("%s%n%s", - fwStatus.getMessage(), sb)); - } else { - fwStatus = new AppraisalStatus(FAIL, - sb.toString(), ReferenceManifest.MEASUREMENT_RIM); - } + if (pcrContent.isEmpty()) { + pcrAppraisalStatus = new AppraisalStatus(FAIL, + "Firmware validation failed: Client did not " + + "provide pcr values."); + log.warn(String.format( + "Firmware validation failed: Client (%s) did not " + + "provide pcr values.", device.getName())); + } else { + // we have a full set of PCR values + //int algorithmLength = baseline[0].length(); + //String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength); + //pcrPolicy.validatePcrs(storedPcrs); + + // part 2 of firmware validation check: bios measurements + // vs baseline tcg event log + // find the measurement + TCGEventLog tcgMeasurementLog; + LinkedList tpmPcrEvents = new LinkedList<>(); + List eventValue; + HashMap eventValueMap = new HashMap<>(); + try { + if (measurement.getDeviceName().equals(hostName)) { + tcgMeasurementLog = new TCGEventLog(measurement.getRimBytes()); + eventValue = referenceDigestValueRepository + .findValuesByBaseRimId(baseReferenceManifest.getId()); + for (ReferenceDigestValue rdv : eventValue) { + eventValueMap.put(rdv.getDigestValue(), rdv); } + + tpmPcrEvents.addAll(pcrValidator.validateTpmEvents( + tcgMeasurementLog, eventValueMap, policySettings)); } - } else { - fwStatus = new AppraisalStatus(FAIL, "The RIM baseline could not be found."); + } catch (NoSuchAlgorithmException e) { + log.error(e); + } catch (CertificateException cEx) { + log.error(cEx); + } catch (IOException e) { + log.error(e); } - } - EventLogMeasurements eventLog = measurement; - eventLog.setOverallValidationResult(fwStatus.getAppStatus()); - referenceManifestRepository.save(eventLog); - } else { - fwStatus = new AppraisalStatus(FAIL, String.format("Firmware Validation failed: " - + "%s for %s can not be found", failedString, hostName)); - if (measurement != null) { - measurement.setOverallValidationResult(fwStatus.getAppStatus()); - referenceManifestRepository.save(measurement); + if (!tpmPcrEvents.isEmpty()) { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("%d digest(s) were not found:%n", + tpmPcrEvents.size())); + for (TpmPcrEvent tpe : tpmPcrEvents) { + sb.append(String.format("PCR Index %d - %s%n", + tpe.getPcrIndex(), + tpe.getEventTypeStr())); + } + if (pcrAppraisalStatus.getAppStatus().equals(FAIL)) { + pcrAppraisalStatus = new AppraisalStatus(FAIL, String.format("%s%n%s", + pcrAppraisalStatus.getMessage(), sb.toString())); + } else { + pcrAppraisalStatus = new AppraisalStatus(FAIL, + sb.toString(), ReferenceManifest.MEASUREMENT_RIM); + } + } } + } else { + pcrAppraisalStatus = new AppraisalStatus(FAIL, "The RIM baseline could not be found."); } - return fwStatus; + return pcrAppraisalStatus; } }