Merge pull request #374 from nsacyber/fm-validation-pass-link

[#371] Reference Validation Pass Link
This commit is contained in:
Cyrus 2021-06-28 12:15:58 -04:00 committed by GitHub
commit 347a030c1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 711 additions and 356 deletions

View File

@ -94,9 +94,11 @@ import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
@ -680,7 +682,6 @@ public abstract class AbstractAttestationCertificateAuthority
for (String line : lines) {
if (!line.isEmpty()
&& !line.contains(TPM_SIGNATURE_ALG)) {
LOG.error(line);
pcrs[counter++] = line.split(":")[1].trim();
}
}
@ -776,23 +777,22 @@ public abstract class AbstractAttestationCertificateAuthority
dv.getHw().getManufacturer(),
dv.getHw().getProductName());
BaseReferenceManifest dbBaseRim = null;
ReferenceManifest support;
SupportReferenceManifest support;
EventLogMeasurements measurements;
String tagId = "";
String fileName = "";
Pattern pattern = Pattern.compile("([^\\s]+(\\.(?i)(rimpcr|rimel|bin|log))$)");
Matcher matcher;
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
List<ReferenceManifest> listOfSavedRims = new LinkedList<>();
if (dv.getLogfileCount() > 0) {
for (ByteString logFile : dv.getLogfileList()) {
try {
support = SupportReferenceManifest.select(referenceManifestManager)
.includeArchived()
.byHashCode(Hex.encodeHexString(messageDigest.digest(
logFile.toByteArray())))
.byHexDecHash(Hex.encodeHexString(messageDigest.digest(
logFile.toByteArray()))).includeArchived()
.getRIM();
if (support == null) {
support = new SupportReferenceManifest(
String.format("%s.rimel",
@ -804,8 +804,9 @@ public abstract class AbstractAttestationCertificateAuthority
support.setPlatformManufacturer(dv.getHw().getManufacturer());
support.setPlatformModel(dv.getHw().getProductName());
support.setFileName(String.format("%s_[%s].rimel", defaultClientName,
support.getRimHash().substring(
support.getRimHash().length() - NUM_OF_VARIABLES)));
support.getHexDecHash().substring(
support.getHexDecHash().length() - NUM_OF_VARIABLES)));
support.setDeviceName(dv.getNw().getHostname());
this.referenceManifestManager.save(support);
} else {
LOG.info("Client provided Support RIM already loaded in database.");
@ -828,53 +829,19 @@ public abstract class AbstractAttestationCertificateAuthority
if (dv.getSwidfileCount() > 0) {
for (ByteString swidFile : dv.getSwidfileList()) {
fileName = "";
try {
dbBaseRim = BaseReferenceManifest.select(referenceManifestManager)
.byBase64Hash(Base64.getEncoder()
.encodeToString(messageDigest
.digest(swidFile.toByteArray())))
.includeArchived()
.byHashCode(Hex.encodeHexString(messageDigest.digest(
swidFile.toByteArray())))
.getRIM();
if (dbBaseRim == null) {
dbBaseRim = new BaseReferenceManifest(
String.format("%s.swidtag",
defaultClientName),
swidFile.toByteArray());
// get file name to use
for (SwidResource swid : dbBaseRim.parseResource()) {
matcher = pattern.matcher(swid.getName());
if (matcher.matches()) {
//found the file name
int dotIndex = swid.getName().lastIndexOf(".");
fileName = swid.getName().substring(0, dotIndex);
dbBaseRim = new BaseReferenceManifest(
String.format("%s.swidtag",
fileName),
swidFile.toByteArray());
}
// now update support rim
SupportReferenceManifest dbSupport = SupportReferenceManifest
.select(referenceManifestManager)
.byRimHash(swid.getHashValue()).getRIM();
if (dbSupport != null && !dbSupport.isUpdated()) {
dbSupport.setFileName(swid.getName());
dbSupport.setSwidTagVersion(dbBaseRim.getSwidTagVersion());
// I might create a get for the bytes of the swidtag file
// so that I can set that instead of the rim ID
dbSupport.setTagId(dbBaseRim.getTagId());
dbSupport.setSwidTagVersion(dbBaseRim.getSwidTagVersion());
dbSupport.setSwidVersion(dbBaseRim.getSwidVersion());
dbSupport.setSwidPatch(dbBaseRim.isSwidPatch());
dbSupport.setSwidSupplemental(dbBaseRim.isSwidSupplemental());
dbBaseRim.setAssociatedRim(dbSupport.getId());
dbSupport.setUpdated(true);
this.referenceManifestManager.update(dbSupport);
break;
}
}
dbBaseRim.setDeviceName(dv.getNw().getHostname());
this.referenceManifestManager.save(dbBaseRim);
} else {
LOG.info("Client provided Base RIM already loaded in database.");
@ -888,7 +855,6 @@ public abstract class AbstractAttestationCertificateAuthority
this.referenceManifestManager.update(dbBaseRim);
}
}
} catch (IOException ioEx) {
LOG.error(ioEx);
}
@ -897,27 +863,75 @@ public abstract class AbstractAttestationCertificateAuthority
LOG.warn("Device did not send swid tag file...");
}
generateDigestRecords(hw.getManufacturer(), hw.getProductName());
//update Support RIMs and Base RIMs.
for (ByteString swidFile : dv.getSwidfileList()) {
dbBaseRim = BaseReferenceManifest.select(referenceManifestManager)
.byBase64Hash(Base64.getEncoder().encodeToString(messageDigest.digest(
swidFile.toByteArray()))).includeArchived()
.getRIM();
// get file name to use
for (SwidResource swid : dbBaseRim.parseResource()) {
matcher = pattern.matcher(swid.getName());
if (matcher.matches()) {
//found the file name
int dotIndex = swid.getName().lastIndexOf(".");
fileName = swid.getName().substring(0, dotIndex);
dbBaseRim.setFileName(String.format("%s.swidtag",
fileName));
}
// now update support rim
SupportReferenceManifest dbSupport = SupportReferenceManifest
.select(referenceManifestManager)
.byHexDecHash(swid.getHashValue()).getRIM();
if (dbSupport != null) {
dbSupport.setFileName(swid.getName());
dbSupport.setSwidTagVersion(dbBaseRim.getSwidTagVersion());
dbSupport.setTagId(dbBaseRim.getTagId());
dbSupport.setSwidTagVersion(dbBaseRim.getSwidTagVersion());
dbSupport.setSwidVersion(dbBaseRim.getSwidVersion());
dbSupport.setSwidPatch(dbBaseRim.isSwidPatch());
dbSupport.setSwidSupplemental(dbBaseRim.isSwidSupplemental());
dbBaseRim.setAssociatedRim(dbSupport.getId());
dbSupport.setUpdated(true);
dbSupport.setAssociatedRim(dbBaseRim.getId());
this.referenceManifestManager.update(dbSupport);
listOfSavedRims.add(dbSupport);
}
}
this.referenceManifestManager.update(dbBaseRim);
listOfSavedRims.add(dbBaseRim);
}
generateDigestRecords(hw.getManufacturer(), hw.getProductName(),
dv.getNw().getHostname());
if (dv.hasLivelog()) {
LOG.info("Device sent bios measurement log...");
fileName = String.format("%s.measurement",
defaultClientName);
dv.getNw().getHostname());
try {
// find previous version. If it exists, delete it
measurements = EventLogMeasurements.select(referenceManifestManager)
.byManufacturer(dv.getHw().getManufacturer())
.includeArchived().getRIM();
if (measurements != null) {
LOG.info("Previous bios measurement log found and being replaced...");
this.referenceManifestManager.delete(measurements);
}
measurements = new EventLogMeasurements(fileName,
EventLogMeasurements temp = new EventLogMeasurements(fileName,
dv.getLivelog().toByteArray());
measurements.setPlatformManufacturer(dv.getHw().getManufacturer());
measurements.setPlatformModel(dv.getHw().getProductName());
measurements.setTagId(tagId);
this.referenceManifestManager.save(measurements);
// find previous version.
measurements = EventLogMeasurements.select(referenceManifestManager)
.byHexDecHash(temp.getHexDecHash()).includeArchived().getRIM();
if (measurements == null) {
measurements = temp;
measurements.setPlatformManufacturer(dv.getHw().getManufacturer());
measurements.setPlatformModel(dv.getHw().getProductName());
measurements.setTagId(tagId);
measurements.setDeviceName(dv.getNw().getHostname());
this.referenceManifestManager.save(measurements);
}
// now save the hash to the base and support rims associated
for (ReferenceManifest rim : listOfSavedRims) {
if (rim != null) {
rim.setEventLogHash(temp.getHexDecHash());
this.referenceManifestManager.update(rim);
}
}
} catch (IOException ioEx) {
LOG.error(ioEx);
}
@ -944,7 +958,8 @@ public abstract class AbstractAttestationCertificateAuthority
return dvReport;
}
private boolean generateDigestRecords(final String manufacturer, final String model) {
private boolean generateDigestRecords(final String manufacturer, final String model,
final String deviceName) {
List<ReferenceDigestValue> rdValues;
Set<SupportReferenceManifest> dbSupportRims = SupportReferenceManifest
.select(referenceManifestManager).byManufacturer(manufacturer).getRIMs();
@ -953,6 +968,7 @@ public abstract class AbstractAttestationCertificateAuthority
if (dbSupport.getPlatformModel().equals(model)) {
ReferenceDigestRecord dbObj = new ReferenceDigestRecord(dbSupport,
manufacturer, model);
dbObj.setDeviceName(deviceName);
// this is where we update or create the log
ReferenceDigestRecord rdr = this.referenceDigestManager.getRecord(dbObj);
if (dbSupport.isBaseSupport()) {

View File

@ -37,6 +37,7 @@ import hirs.utils.BouncyCastleUtils;
import hirs.utils.ReferenceManifestValidator;
import hirs.validation.CredentialValidator;
import hirs.validation.SupplyChainCredentialValidator;
import hirs.validation.SupplyChainValidatorException;
import org.apache.logging.log4j.Level;
import hirs.validation.SupplyChainValidatorException;
import org.apache.logging.log4j.LogManager;
@ -381,33 +382,36 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
.getHardwareInfo().getManufacturer();
String model = device.getDeviceInfo()
.getHardwareInfo().getProductName();
ReferenceManifest validationObject = null;
ReferenceManifest baseReferenceManifest = null;
ReferenceManifest validationObject;
Set<BaseReferenceManifest> baseReferenceManifests = null;
BaseReferenceManifest baseReferenceManifest = null;
ReferenceManifest supportReferenceManifest = null;
ReferenceManifest measurement = null;
ReferenceDigestRecord digestRecord = null;
baseReferenceManifest = BaseReferenceManifest.select(referenceManifestManager)
.byManufacturer(manufacturer).getRIM();
supportReferenceManifest = SupportReferenceManifest.select(referenceManifestManager)
.byManufacturer(manufacturer).getRIM();
measurement = EventLogMeasurements.select(referenceManifestManager)
.byManufacturer(manufacturer).includeArchived().getRIM();
baseReferenceManifests = BaseReferenceManifest.select(referenceManifestManager)
.byDeviceName(device.getDeviceInfo().getNetworkInfo().getHostname()).getRIMs();
for (BaseReferenceManifest bRim : baseReferenceManifests) {
if (!bRim.isSwidSupplemental() && !bRim.isSwidPatch()) {
baseReferenceManifest = bRim;
}
}
validationObject = baseReferenceManifest;
String failedString = "";
if (baseReferenceManifest == null) {
failedString = "Base Reference Integrity Manifest\n";
passed = false;
} else {
measurement = EventLogMeasurements.select(referenceManifestManager)
.byHexDecHash(baseReferenceManifest.getEventLogHash()).getRIM();
}
if (supportReferenceManifest == null) {
failedString += "Support Reference Integrity Manifest\n";
passed = false;
}
if (measurement == null) {
failedString += "Bios measurement";
passed = false;
}
validationObject = measurement;
if (passed) {
List<SwidResource> resources =
@ -420,13 +424,18 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
new ReferenceManifestValidator(
new ByteArrayInputStream(baseReferenceManifest.getRimBytes()));
for (SwidResource swidRes : resources) {
if (swidRes.getName().equals(supportReferenceManifest.getFileName())) {
supportReferenceManifest = SupportReferenceManifest.select(referenceManifestManager)
.byHexDecHash(swidRes.getHashValue()).getRIM();
if (supportReferenceManifest != null
&& swidRes.getName().equals(supportReferenceManifest.getFileName())) {
referenceManifestValidator.validateSupportRimHash(
supportReferenceManifest.getRimBytes(), swidRes.getHashValue());
} else {
supportReferenceManifest = null;
}
}
//Validate signing cert
Set<CertificateAuthorityCredential> allCerts =
CertificateAuthorityCredential.select(certificateManager).getCertificates();
@ -453,13 +462,46 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
break;
}
}
//Validate signing cert
Set<CertificateAuthorityCredential> allCerts =
CertificateAuthorityCredential.select(certificateManager).getCertificates();
CertificateAuthorityCredential signingCert = null;
for (CertificateAuthorityCredential cert : allCerts) {
if (Arrays.equals(cert.getEncodedPublicKey(),
referenceManifestValidator.getPublicKey().getEncoded())) {
signingCert = cert;
KeyStore keyStore = getCaChain(signingCert);
try {
X509Certificate x509Cert = signingCert.getX509Certificate();
if (!SupplyChainCredentialValidator.verifyCertificate(x509Cert, keyStore)) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: invalid certificate path.");
}
} catch (IOException e) {
LOGGER.error("Error getting X509 cert from manager: " + e.getMessage());
} catch (SupplyChainValidatorException e) {
LOGGER.error("Error validating cert against keystore: " + e.getMessage());
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: invalid certificate path.");
}
break;
}
}
if (signingCert == null) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: signing cert not found.");
}
if (!referenceManifestValidator.isSignatureValid()) {
if (passed && supportReferenceManifest == null) {
fwStatus = new AppraisalStatus(FAIL,
"Support Reference Integrity Manifest can not be found\n");
passed = false;
}
if (passed && !referenceManifestValidator.isSignatureValid()) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: Signature validation "
@ -504,24 +546,8 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
// we have a full set of PCR values
int algorithmLength = baseline[0].length();
String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength);
pcrPolicy.validatePcrs(storedPcrs);
if (storedPcrs[0] == null || storedPcrs[0].isEmpty()) {
// validation fail
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: "
+ "Client provided PCR "
+ "values are not the same algorithm "
+ "as associated RIM.");
} else {
StringBuilder sb = pcrPolicy.validatePcrs(storedPcrs);
if (sb.length() > 0) {
validationObject = supportReferenceManifest;
level = Level.ERROR;
fwStatus = new AppraisalStatus(FAIL, sb.toString());
} else {
level = Level.INFO;
}
}
// part 2 of firmware validation check: bios measurements
// vs baseline tcg event log
// find the measurement
@ -556,9 +582,11 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
if (!tpmPcrEvents.isEmpty()) {
StringBuilder sb = new StringBuilder();
validationObject = measurement;
sb.append(String.format("%d digest(s) were not found:%n",
tpmPcrEvents.size()));
for (TpmPcrEvent tpe : tpmPcrEvents) {
sb.append(String.format("Event %s - %s%n",
tpe.getEventNumber(),
sb.append(String.format("PCR Index %d - %s%n",
tpe.getPcrIndex(),
tpe.getEventTypeStr()));
}
if (fwStatus.getAppStatus().equals(FAIL)) {
@ -578,6 +606,9 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
+ "%s for %s can not be found", failedString, manufacturer));
}
EventLogMeasurements eventLog = (EventLogMeasurements) measurement;
eventLog.setOverallValidationResult(fwStatus.getAppStatus());
this.referenceManifestManager.update(eventLog);
return buildValidationRecord(SupplyChainValidation.ValidationType.FIRMWARE,
fwStatus.getAppStatus(), fwStatus.getMessage(), validationObject, level);
}
@ -605,29 +636,34 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
// check if the policy is enabled
if (policy.isFirmwareValidationEnabled()) {
String[] baseline = new String[Integer.SIZE];
String manufacturer = device.getDeviceInfo()
.getHardwareInfo().getManufacturer();
String deviceName = device.getDeviceInfo()
.getNetworkInfo().getHostname();
try {
sRim = SupportReferenceManifest.select(
this.referenceManifestManager)
.byManufacturer(manufacturer).getRIM();
Set<SupportReferenceManifest> supportRims = SupportReferenceManifest
.select(this.referenceManifestManager)
.byDeviceName(deviceName).getRIMs();
for (SupportReferenceManifest support : supportRims) {
if (support.isBaseSupport()) {
sRim = support;
}
}
eventLog = EventLogMeasurements
.select(this.referenceManifestManager)
.byManufacturer(manufacturer).getRIM();
.byHexDecHash(sRim.getEventLogHash()).getRIM();
if (sRim == null) {
fwStatus = new AppraisalStatus(FAIL,
String.format("Firmware Quote validation failed: "
+ "No associated Support RIM file "
+ "could be found for %s",
manufacturer));
deviceName));
} else if (eventLog == null) {
fwStatus = new AppraisalStatus(FAIL,
String.format("Firmware Quote validation failed: "
+ "No associated Client Log file "
+ "could be found for %s",
manufacturer));
deviceName));
} else {
baseline = sRim.getExpectedPCRList();
String[] storedPcrs = eventLog.getExpectedPCRList();
@ -640,11 +676,12 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
fwStatus = new AppraisalStatus(PASS,
SupplyChainCredentialValidator.FIRMWARE_VALID);
fwStatus.setMessage("Firmware validation of TPM Quote successful.");
} else {
fwStatus.setMessage("Firmware validation of TPM Quote failed."
+ "\nPCR hash and Quote hash do not match.");
}
eventLog.setOverallValidationResult(fwStatus.getAppStatus());
this.referenceManifestManager.update(eventLog);
}
} catch (Exception ex) {
LOGGER.error(ex);
@ -652,7 +689,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
quoteScv = buildValidationRecord(SupplyChainValidation
.ValidationType.FIRMWARE,
fwStatus.getAppStatus(), fwStatus.getMessage(), sRim, level);
fwStatus.getAppStatus(), fwStatus.getMessage(), eventLog, level);
// Generate validation summary, save it, and return it.
List<SupplyChainValidation> validations = new ArrayList<>();

View File

@ -7,12 +7,16 @@ import hirs.attestationca.portal.page.params.ReferenceManifestDetailsPageParams;
import hirs.attestationca.service.SupplyChainValidationServiceImpl;
import hirs.data.persist.BaseReferenceManifest;
import hirs.data.persist.EventLogMeasurements;
import hirs.data.persist.ReferenceDigestRecord;
import hirs.data.persist.ReferenceDigestValue;
import hirs.data.persist.ReferenceManifest;
import hirs.data.persist.SupportReferenceManifest;
import hirs.data.persist.SwidResource;
import hirs.data.persist.certificate.CertificateAuthorityCredential;
import hirs.persist.CertificateManager;
import hirs.persist.DBManagerException;
import hirs.persist.ReferenceDigestManager;
import hirs.persist.ReferenceEventManager;
import hirs.persist.ReferenceManifestManager;
import hirs.tpm.eventlog.TCGEventLog;
import hirs.tpm.eventlog.TpmPcrEvent;
@ -33,10 +37,13 @@ import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@ -49,6 +56,8 @@ public class ReferenceManifestDetailsPageController
extends PageController<ReferenceManifestDetailsPageParams> {
private final ReferenceManifestManager referenceManifestManager;
private final ReferenceDigestManager referenceDigestManager;
private final ReferenceEventManager referenceEventManager;
private final CertificateManager certificateManager;
private static final ReferenceManifestValidator RIM_VALIDATOR
= new ReferenceManifestValidator();
@ -59,14 +68,20 @@ public class ReferenceManifestDetailsPageController
* Constructor providing the Page's display and routing specification.
*
* @param referenceManifestManager the reference manifest manager.
* @param referenceDigestManager the reference digest manager.
* @param referenceEventManager the reference event manager.
* @param certificateManager the certificate manager.
*/
@Autowired
public ReferenceManifestDetailsPageController(
final ReferenceManifestManager referenceManifestManager,
final ReferenceDigestManager referenceDigestManager,
final ReferenceEventManager referenceEventManager,
final CertificateManager certificateManager) {
super(Page.RIM_DETAILS);
this.referenceManifestManager = referenceManifestManager;
this.referenceDigestManager = referenceDigestManager;
this.referenceEventManager = referenceEventManager;
this.certificateManager = certificateManager;
}
@ -92,12 +107,13 @@ public class ReferenceManifestDetailsPageController
if (params.getId() == null) {
String typeError = "ID was not provided";
messages.addError(typeError);
LOGGER.error(typeError);
LOGGER.debug(typeError);
mav.addObject(MESSAGES_ATTRIBUTE, messages);
} else {
try {
UUID uuid = UUID.fromString(params.getId());
data.putAll(getRimDetailInfo(uuid, referenceManifestManager, certificateManager));
data.putAll(getRimDetailInfo(uuid, referenceManifestManager,
referenceDigestManager, referenceEventManager, certificateManager));
} catch (IllegalArgumentException iaEx) {
String uuidError = "Failed to parse ID from: " + params.getId();
messages.addError(uuidError);
@ -105,7 +121,7 @@ public class ReferenceManifestDetailsPageController
} catch (Exception ioEx) {
LOGGER.error(ioEx);
for (StackTraceElement ste : ioEx.getStackTrace()) {
LOGGER.debug(ste.toString());
LOGGER.error(ste.toString());
}
}
if (data.isEmpty()) {
@ -128,6 +144,8 @@ public class ReferenceManifestDetailsPageController
*
* @param uuid database reference for the requested RIM.
* @param referenceManifestManager the reference manifest manager.
* @param referenceDigestManager the reference digest manager.
* @param referenceEventManager the reference event manager.
* @param certificateManager the certificate manager.
* @return mapping of the RIM information from the database.
* @throws java.io.IOException error for reading file bytes.
@ -136,6 +154,8 @@ public class ReferenceManifestDetailsPageController
*/
public static HashMap<String, Object> getRimDetailInfo(final UUID uuid,
final ReferenceManifestManager referenceManifestManager,
final ReferenceDigestManager referenceDigestManager,
final ReferenceEventManager referenceEventManager,
final CertificateManager certificateManager) throws IOException,
CertificateException, NoSuchAlgorithmException {
HashMap<String, Object> data = new HashMap<>();
@ -158,7 +178,8 @@ public class ReferenceManifestDetailsPageController
.byEntityId(uuid).getRIM();
if (bios != null) {
data.putAll(getMeasurementsRimInfo(bios, referenceManifestManager));
data.putAll(getMeasurementsRimInfo(bios, referenceManifestManager,
referenceDigestManager, referenceEventManager));
}
return data;
@ -237,8 +258,11 @@ public class ReferenceManifestDetailsPageController
boolean hashLinked = false;
if (baseRim.getRimLinkHash() != null) {
ReferenceManifest rim = BaseReferenceManifest.select(referenceManifestManager)
.byHashCode(baseRim.getRimLinkHash()).getRIM();
.byBase64Hash(baseRim.getRimLinkHash()).getRIM();
hashLinked = (rim != null);
if (hashLinked) {
data.put("rimLinkId", rim.getId());
}
}
data.put("linkHashValid", hashLinked);
data.put("rimType", baseRim.getRimType());
@ -297,7 +321,7 @@ public class ReferenceManifestDetailsPageController
X509Certificate signingCert = cert.getX509Certificate();
try {
if (SupplyChainCredentialValidator.verifyCertificate(signingCert,
keystore)) {
keystore)) {
data.replace("signatureValid", true);
}
} catch (SupplyChainValidatorException e) {
@ -344,7 +368,8 @@ public class ReferenceManifestDetailsPageController
.select(referenceManifestManager)
.byRimType(ReferenceManifest.BASE_RIM).getRIMs();
for (BaseReferenceManifest baseRim : baseRims) {
if (baseRim != null && baseRim.getAssociatedRim().equals(support.getId())) {
if (baseRim != null && baseRim.getAssociatedRim() != null
&& baseRim.getAssociatedRim().equals(support.getId())) {
support.setAssociatedRim(baseRim.getId());
try {
referenceManifestManager.update(support);
@ -359,10 +384,8 @@ public class ReferenceManifestDetailsPageController
// testing this independent of the above if statement because the above
// starts off checking if associated rim is null; that is irrelevant for
// this statement.
if (support.getPlatformManufacturer() != null) {
measurements = EventLogMeasurements.select(referenceManifestManager)
.byManufacturer(support.getPlatformManufacturer()).getRIM();
}
measurements = EventLogMeasurements.select(referenceManifestManager)
.byHexDecHash(support.getEventLogHash()).getRIM();
if (support.isSwidPatch()) {
data.put("swidPatch", "True");
@ -380,20 +403,6 @@ public class ReferenceManifestDetailsPageController
data.put("associatedRim", support.getAssociatedRim());
data.put("rimType", support.getRimType());
data.put("tagId", support.getTagId());
boolean crtm = false;
boolean bootManager = false;
boolean osLoader = false;
boolean osKernel = false;
boolean acpiTables = false;
boolean smbiosTables = false;
boolean gptTable = false;
boolean bootOrder = false;
boolean defaultBootDevice = false;
boolean secureBoot = false;
boolean pk = false;
boolean kek = false;
boolean sigDb = false;
boolean forbiddenDbx = false;
TCGEventLog logProcessor = new TCGEventLog(support.getRimBytes());
LinkedList<TpmPcrEvent> tpmPcrEvents = new LinkedList<>();
@ -419,8 +428,29 @@ public class ReferenceManifestDetailsPageController
data.put("events", logProcessor.getEventList());
}
getEventSummary(data, logProcessor.getEventList());
return data;
}
private static void getEventSummary(final HashMap<String, Object> data,
final Collection<TpmPcrEvent> eventList) {
boolean crtm = false;
boolean bootManager = false;
boolean osLoader = false;
boolean osKernel = false;
boolean acpiTables = false;
boolean smbiosTables = false;
boolean gptTable = false;
boolean bootOrder = false;
boolean defaultBootDevice = false;
boolean secureBoot = false;
boolean pk = false;
boolean kek = false;
boolean sigDb = false;
boolean forbiddenDbx = false;
String contentStr;
for (TpmPcrEvent tpe : logProcessor.getEventList()) {
for (TpmPcrEvent tpe : eventList) {
contentStr = tpe.getEventContentStr();
// check for specific events
if (contentStr.contains("CRTM")) {
@ -473,8 +503,6 @@ public class ReferenceManifestDetailsPageController
data.put("kek", kek);
data.put("sigDb", sigDb);
data.put("forbiddenDbx", forbiddenDbx);
return data;
}
/**
@ -483,6 +511,8 @@ public class ReferenceManifestDetailsPageController
*
* @param measurements established ReferenceManifest Type.
* @param referenceManifestManager the reference manifest manager.
* @param referenceDigestManager the reference digest manager.
* @param referenceEventManager the reference event manager.
* @return mapping of the RIM information from the database.
* @throws java.io.IOException error for reading file bytes.
* @throws NoSuchAlgorithmException If an unknown Algorithm is encountered.
@ -490,57 +520,108 @@ public class ReferenceManifestDetailsPageController
*/
private static HashMap<String, Object> getMeasurementsRimInfo(
final EventLogMeasurements measurements,
final ReferenceManifestManager referenceManifestManager)
final ReferenceManifestManager referenceManifestManager,
final ReferenceDigestManager referenceDigestManager,
final ReferenceEventManager referenceEventManager)
throws IOException, CertificateException, NoSuchAlgorithmException {
HashMap<String, Object> data = new HashMap<>();
LinkedList<TpmPcrEvent> supportEvents = new LinkedList<>();
LinkedList<TpmPcrEvent> livelogEvents = new LinkedList<>();
BaseReferenceManifest base = null;
SupportReferenceManifest support = null;
TCGEventLog supportLog = null;
List<SupportReferenceManifest> supports = new ArrayList<>();
SupportReferenceManifest baseSupport = null;
List<ReferenceDigestRecord> digestRecords = new LinkedList<>();
data.put("supportFilename", "Blank");
data.put("supportId", "");
data.put("tagId", measurements.getTagId());
data.put("baseId", "");
data.put("associatedRim", "");
data.put("rimType", measurements.getRimType());
data.put("hostName", measurements.getDeviceName());
data.put("validationResult", measurements.getOverallValidationResult());
data.put("swidBase", true);
if (measurements.getPlatformManufacturer() != null) {
support = SupportReferenceManifest
if (measurements.getDeviceName() != null) {
digestRecords = referenceDigestManager
.getRecordsByDeviceName(measurements.getDeviceName());
supports.addAll(SupportReferenceManifest
.select(referenceManifestManager)
.byManufacturer(measurements
.getPlatformManufacturer()).getRIM();
if (support != null) {
supportLog = new TCGEventLog(support.getRimBytes());
data.put("supportFilename", support.getFileName());
data.put("supportId", support.getId());
.byDeviceName(measurements
.getDeviceName()).getRIMs());
for (SupportReferenceManifest support : supports) {
if (support.isBaseSupport()) {
baseSupport = support;
}
}
base = BaseReferenceManifest
.select(referenceManifestManager)
.byManufacturer(measurements
.getPlatformManufacturer()).getRIM();
if (baseSupport != null) {
data.put("supportFilename", baseSupport.getFileName());
data.put("supportId", baseSupport.getId());
if (base != null) {
data.put("baseId", base.getId());
base = BaseReferenceManifest
.select(referenceManifestManager)
.byEntityId(baseSupport.getAssociatedRim())
.getRIM();
data.put("tagId", baseSupport.getTagId());
if (base != null) {
data.put("associatedRim", base.getId());
}
}
}
TCGEventLog measurementLog = new TCGEventLog(measurements.getRimBytes());
if (supportLog != null) {
TpmPcrEvent measurementEvent;
for (TpmPcrEvent tpe : supportLog.getEventList()) {
measurementEvent = measurementLog.getEventByNumber(tpe.getEventNumber());
if (!tpe.eventCompare(measurementEvent)) {
supportEvents.add(tpe);
List<ReferenceDigestValue> eventValue = new ArrayList<>();
Map<String, ReferenceDigestValue> eventValueMap = new HashMap<>();
if (!digestRecords.isEmpty()) {
for (ReferenceDigestRecord rdr : digestRecords) {
eventValue.addAll(referenceEventManager
.getValuesByRecordId(rdr));
}
for (ReferenceDigestValue rdv : eventValue) {
eventValueMap.put(rdv.getDigestValue(), rdv);
}
for (TpmPcrEvent measurementEvent : measurementLog.getEventList()) {
if (!eventValueMap.containsKey(measurementEvent.getEventDigestStr())) {
livelogEvents.add(measurementEvent);
}
}
}
data.put("supportEvents", supportEvents);
if (!supports.isEmpty()) {
Map<String, List<TpmPcrEvent>> baselineLogEvents = new HashMap<>();
List<TpmPcrEvent> matchedEvents = null;
List<TpmPcrEvent> combinedBaselines = new LinkedList<>();
for (SupportReferenceManifest support : supports) {
combinedBaselines.addAll(support.getEventLog());
}
String bootVariable;
String variablePrefix = "Variable Name:";
String variableSuffix = "UEFI_GUID";
for (TpmPcrEvent tpe : livelogEvents) {
matchedEvents = new ArrayList<>();
for (TpmPcrEvent tpmPcrEvent : combinedBaselines) {
if (tpmPcrEvent.getEventType() == tpe.getEventType()) {
if (tpe.getEventContentStr().contains(variablePrefix)) {
bootVariable = tpe.getEventContentStr().substring((
tpe.getEventContentStr().indexOf(variablePrefix)
+ variablePrefix.length()),
tpe.getEventContentStr().indexOf(variableSuffix));
if (tpmPcrEvent.getEventContentStr().contains(bootVariable)) {
matchedEvents.add(tpmPcrEvent);
}
} else {
matchedEvents.add(tpmPcrEvent);
}
}
}
baselineLogEvents.put(tpe.getEventDigestStr(), matchedEvents);
}
data.put("eventTypeMap", baselineLogEvents);
}
TCGEventLog logProcessor = new TCGEventLog(measurements.getRimBytes());
data.put("livelogEvents", livelogEvents);
data.put("events", logProcessor.getEventList());
getEventSummary(data, logProcessor.getEventList());
return data;
}

View File

@ -1,40 +1,26 @@
package hirs.attestationca.portal.page.controllers;
import hirs.FilteredRecordsList;
import hirs.attestationca.portal.datatables.DataTableInput;
import hirs.attestationca.portal.datatables.DataTableResponse;
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
import hirs.attestationca.portal.page.Page;
import hirs.attestationca.portal.page.PageController;
import hirs.FilteredRecordsList;
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
import hirs.attestationca.portal.page.PageMessages;
import hirs.attestationca.portal.page.params.NoPageParams;
import hirs.data.persist.BaseReferenceManifest;
import hirs.data.persist.SupportReferenceManifest;
import hirs.persist.DBManagerException;
import hirs.persist.ReferenceManifestManager;
import hirs.persist.CriteriaModifier;
import hirs.data.persist.ReferenceManifest;
import hirs.data.persist.SupportReferenceManifest;
import hirs.data.persist.SwidResource;
import hirs.data.persist.certificate.Certificate;
import java.io.IOException;
import java.net.URISyntaxException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletResponse;
import hirs.persist.CriteriaModifier;
import hirs.persist.DBManagerException;
import hirs.persist.ReferenceManifestManager;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
@ -50,6 +36,21 @@ import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.view.RedirectView;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Controller for the Reference Manifest page.
*/
@ -437,19 +438,34 @@ public class ReferenceManifestPageController
ReferenceManifest existingManifest;
MessageDigest digest = null;
String rimHash = "";
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException noSaEx) {
LOGGER.error(noSaEx);
}
// look for existing manifest in the database
try {
if (supportRim) {
if (digest != null) {
rimHash = Hex.encodeHexString(
digest.digest(referenceManifest.getRimBytes()));
}
existingManifest = SupportReferenceManifest
.select(referenceManifestManager)
.byHexDecHash(rimHash)
.includeArchived()
.byHashCode(referenceManifest.getRimHash())
.getRIM();
} else {
if (digest != null) {
rimHash = Base64.encodeBase64String(
digest.digest(referenceManifest.getRimBytes()));
}
existingManifest = BaseReferenceManifest
.select(referenceManifestManager)
.select(referenceManifestManager).byBase64Hash(rimHash)
.includeArchived()
.byHashCode(referenceManifest.getRimHash())
.getRIM();
}
} catch (DBManagerException e) {

View File

@ -114,7 +114,7 @@
<div>Not Before:&nbsp;<span>${initialData.beginValidity}</span></div>
<div>Not After:&nbsp;<span>${initialData.endValidity}</span></div>
</div>
</div>
</div>
</c:if>
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Signature</span></div><div id="signatureSection" class="col col-md-8">
@ -736,7 +736,7 @@
<span class="fieldHeader">Name:</span>
<span class="fieldValue">${property.getPropertyName()}</span><br/>
<span class="fieldHeader">Value:</span>
<span class="fieldValue">${property.getPropertyValue()}</span><br/>
<span class="fieldValue" style="word-wrap: break-word">${property.getPropertyValue()}</span><br/>
</div>
</div>
</div>

View File

@ -52,7 +52,7 @@
{
data: 'id',
orderable: false,
searchable:false,
searchable: false,
render: function(data, type, full, meta) {
// Set up a delete icon with link to handleDeleteRequest().
// sets up a hidden input field containing the ID which is

View File

@ -11,10 +11,20 @@
<link type="text/css" rel="stylesheet" href="${common}/rim_details.css"/>
</jsp:attribute>
<jsp:attribute name="pageHeaderTitle">
${initialData.rimType} Reference Integrity Manifest
<a href="${portal}/reference-manifests/download?id=${param.id}">
<img src="${icons}/ic_file_download_black_24dp.png" title="Download ${initialData.rimType} RIM">
</a>
<c:choose>
<c:when test="${initialData.rimType=='Measurement'}">
TCG Event Log
<a href="${portal}/reference-manifests/download?id=${param.id}">
<img src="${icons}/ic_file_download_black_24dp.png" title="Download ${initialData.rimType} RIM">
</a>
</c:when>
<c:otherwise>
${initialData.rimType} Reference Integrity Manifest
<a href="${portal}/reference-manifests/download?id=${param.id}">
<img src="${icons}/ic_file_download_black_24dp.png" title="Download ${initialData.rimType} RIM">
</a>
</c:otherwise>
</c:choose>
</jsp:attribute>
<jsp:body>
<c:set var="passIcon" value="${icons}/ic_checkbox_marked_circle_black_green_24dp.png"/>
@ -25,18 +35,25 @@
<c:set var="supportRimHashInvalidText" value="Support RIM hash not valid!"/>
<div id="certificate-details-page" class="container-fluid">
<c:choose>
<c:when test="${initialData.rimType=='Support'}">
<c:when test="${initialData.rimType=='Support' || (initialData.rimType=='Measurement' && initialData.validationResult=='PASS')}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Base RIM</span></div>
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Additional<br />RIM Info</span></div>
<div id="baseRim" class="col col-md-8">
<c:choose>
<c:when test="${not empty initialData.associatedRim}">
<a href="${portal}/rim-details?id=${initialData.associatedRim}">
${initialData.tagId}
</a>
<c:if test="${not empty initialData.hostName}">
<div>Device:&nbsp;<span>${initialData.hostName}</span></div>
</c:if>
<c:if test="${not empty initialData.supportId}">
<div>Support:&nbsp;<span><a href="${portal}/rim-details?id=${initialData.supportId}">${initialData.supportFilename}</a></span>
</div>
</c:if>
</c:when>
<c:otherwise>
<div class="component col col-md-10" style="color: red; padding-left: 20px">Base RIM not uploaded from the ACA RIM Page</div>
<div class="component col col-md-10" style="color: red; padding-left: 20px">RIM not uploaded from the ACA RIM Page</div>
</c:otherwise>
</c:choose>
</div>
@ -71,7 +88,14 @@
<div id="eventsCol" class="col col-md-8">
<div id="eventOptions" class="collapse" class="collapsed" aria-expanded="false">
<ul>
<li>This Support RIM file covers the following critical items:</li>
<c:choose>
<c:when test="${initialData.rimType=='Support'}">
<li>This Support RIM file covers the following critical items:</li>
</c:when>
<c:otherwise>
<li>This Event Log file covers the following critical items:</li>
</c:otherwise>
</c:choose>
<ul>
<c:if test="${initialData.crtm || initialData.bootManager || initialData.osLoader || initialData.osKernel}">
<li>PC Client Boot path</li>
@ -133,7 +157,14 @@
</ul>
</ul>
<ul>
<li>The Support RIM file does NOT covers the following critical items:</li>
<c:choose>
<c:when test="${initialData.rimType=='Support'}">
<li>This Support RIM file covers the following critical items:</li>
</c:when>
<c:otherwise>
<li>This Event Log file covers the following critical items:</li>
</c:otherwise>
</c:choose>
<ul>
<c:if test="${not initialData.crtm || not initialData.bootManager || not initialData.osLoader || not initialData.osKernel}">
<li>PC Client Boot path</li>
@ -236,13 +267,17 @@
</div>
<div class="col-md-a col-md-offset-1"><span class="colHeader">${initialData.events.size()} entries</span></div>
</c:when>
<c:when test="${initialData.rimType=='Measurement'}">
<c:when test="${initialData.rimType=='Measurement' && initialData.validationResult=='FAIL'}">
<div style="display: inline">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Base/Support</span></div>
<div id="measurements" class="col col-md-8">
<c:if test="${not empty initialData.hostName}">
<div>Device:&nbsp;<span>${initialData.hostName}</span>
</div>
</c:if>
<c:if test="${not empty initialData.tagId}">
<div>Base:&nbsp;<span><a href="${portal}/rim-details?id=${initialData.baseId}">${initialData.tagId}</a></span>
<div>Base:&nbsp;<span><a href="${portal}/rim-details?id=${initialData.associatedRim}">${initialData.tagId}</a></span>
</div>
</c:if>
<c:if test="${not empty initialData.supportId}">
@ -253,60 +288,50 @@
</div>
<br />
<div class="row" style="margin: auto 260px auto 125px">
<div class="panel panel-default" style="flex: 1">
<div class="panel-heading">Support</div>
<c:if test="${not empty initialData.supportEvents}">
<c:forEach items="${initialData.supportEvents}" var="sEvent">
<div class="event-element">
<div class="event-data">
<div class="data-label">Event#:</div>
<div class="data-value">${sEvent.getEventNumber()+1}</div>
</div>
<div class="event-data">
<div class="data-label">PCR Index:</div>
<div class="data-value">${sEvent.getPcrIndex()}</div>
</div>
<div class="event-data">
<div class="data-label">Digest:</div>
<div class="data-value">${sEvent.getEventDigestStr()}</div>
</div>
<div class="event-data">
<div class="data-label">Content:</div>
<div class="data-value">${sEvent.getEventContentStr()}</div>
</div>
</div>
</c:forEach>
</c:if>
</div>
<div class="panel panel-default" style="flex: 1">
<div class="panel-heading">Client Log</div>
<c:if test="${not empty initialData.livelogEvents}">
<c:set var="iterator" value="0" scope="page"/>
<c:forEach items="${initialData.livelogEvents}" var="lEvent">
<div class="event-element">
<div class="event-data">
<div class="data-label">Event#:</div>
<div class="data-value">${lEvent.getEventNumber()+1}</div>
</div>
<div class="event-data">
<div class="data-label">PCR Index:</div>
<div class="data-value">${lEvent.getPcrIndex()}</div>
</div>
<div class="event-data">
<div class="data-label">Digest:</div>
<div class="data-value">${lEvent.getEventDigestStr()}</div>
</div>
<div class="event-data">
<div class="data-label">Content:</div>
<div class="data-value">${lEvent.getEventContentStr()}</div>
<div>
<div style="display: flex; background: lightgray;">
<div style="display: flex 1; font-weight: bold; margin: auto 1rem auto 1rem">Failed Event Digest:<br />
</div>
<div style="display: flex 2; margin: 2px auto 2px 25px">
<span class="mappedData">PCR Index:</span> ${lEvent.getPcrIndex()}<br />
<span class="mappedData">Digest:</span> ${lEvent.getEventDigestStr()}<br />
<span class="mappedData">Event Content:</span> ${lEvent.getEventContentStr()}
</div>
</div>
</div>
<div style="display: flex;">
<div class="mappedButton">
Baseline Events of Type:<br />
<span style="word-wrap: break-word"><a role="button" data-toggle="collapse" href="#eventContent${iterator}">${lEvent.getEventTypeString()}</a></span>
</div>
<div id="eventContent${iterator}" class="panel-collapse collapse in" style="flex: 2">
<c:forEach items="${initialData.eventTypeMap}" var="mappedDigest">
<c:if test="${mappedDigest.key == lEvent.getEventDigestStr()}">
<c:set var="event" value="${mappedDigest.value}" scope="page"/>
<c:forEach items="${mappedDigest.value}" var="event">
<div class="mappedOverhead">
<div><span class="mappedData">PCR Index:</span> ${event.getPcrIndex()}</div>
<div><span class="mappedData">Digest:</span> ${event.getEventDigestStr()}</div>
<div><span class="mappedData">Event Content:</span> ${event.getEventContentStr()}</div>
</div>
</c:forEach>
</c:if>
</c:forEach>
</div>
</div>
<c:set var="iterator" value="${iterator+1}" scope="page"/>
</c:forEach>
</c:if>
</div>
</div>
</div>
</c:when>
<c:otherwise>
<c:when test="${initialData.rimType=='Base'}">
<div class="row">
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Software Identity</span></div>
<div id="softwareIdentity" class="col col-md-8">
@ -343,7 +368,17 @@
<div class="col-md-1 col-md-offset-1"><span class="colHeader">Link</span></div>
<div id="link" class="col col-md-8">
<c:if test="${not empty initialData.linkHref}">
<div><span><a href="${portal}/rim-details?id=${initialData.linkHrefLink}" rel="${initialData.linkRel}">${initialData.linkHref}</a></span>
<div>
<span>
<c:choose>
<c:when test="${initialData.linkRel=='requires'}">
<a href="${portal}/rim-details?id=${initialData.linkHrefLink}" rel="${initialData.linkRel}">${initialData.linkHref}</a>
</c:when>
<c:otherwise>
<a href="${initialData.linkHref}" rel="${initialData.linkRel}">${initialData.linkHref}</a>
</c:otherwise>
</c:choose>
</span>
</div>
<div>Rel:&nbsp;<span>${initialData.linkRel}</span>
</div>
@ -375,7 +410,15 @@
<c:if test="${not empty initialData.pcUriLocal}">
<div>PC URI Local:&nbsp;<span>${initialData.pcUriLocal}</span></div>
</c:if>
<div>Rim Link Hash:&nbsp;<span>${initialData.rimLinkHash}</span>
<c:choose>
<c:when test="${not empty initialData.rimLinkId}">
<div>Rim Link Hash:&nbsp;<span><a href="${portal}/rim-details?id=${initialData.rimLinkId}">${initialData.rimLinkHash}</a></span>
</c:when>
<c:otherwise>
<div>Rim Link Hash:&nbsp;<span>${initialData.rimLinkHash}</span>
</c:otherwise>
</c:choose>
<c:if test="${not empty initialData.rimLinkHash}">
<span>
<c:choose>
<c:when test="${initialData.linkHashValid}">
@ -386,6 +429,7 @@
</c:otherwise>
</c:choose>
</span>
</c:if>
</div>
</div>
</div>
@ -531,6 +575,8 @@
</div>
</div>
</div>
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>
</div>

View File

@ -81,4 +81,28 @@
.data-value {
flex: 5
}
.mappedType {
display: flex 1;
padding: 1rem;
width: 20rem;
font-weight: bold
}
.mappedOverhead {
display: flex;
flex-direction: column;
padding: 1rem;
}
.mappedData {
font-weight: bold;
}
.mappedButton {
display: flex 1;
padding: 1rem;
width: 20rem;
font-weight: bold;
}

View File

@ -1,5 +1,6 @@
package hirs.data.persist;
import com.fasterxml.jackson.annotation.JsonIgnore;
import hirs.persist.DBReferenceManifestManager;
import hirs.persist.ReferenceManifestManager;
import hirs.persist.ReferenceManifestSelector;
@ -25,7 +26,10 @@ import javax.xml.validation.Schema;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
@ -35,9 +39,16 @@ import java.util.Map;
@Entity
public class BaseReferenceManifest extends ReferenceManifest {
private static final Logger LOGGER = LogManager.getLogger(BaseReferenceManifest.class);
/**
* Holds the name of the 'base64Hash' field.
*/
public static final String BASE_64_HASH_FIELD = "base64Hash";
private static JAXBContext jaxbContext;
@Column
@JsonIgnore
private String base64Hash = "";
@Column
private String swidName = null;
@Column
@ -100,24 +111,23 @@ public class BaseReferenceManifest extends ReferenceManifest {
}
/**
* Specify the platform manufacturer id that rims must have to be considered
* Specify the device name that rims must have to be considered
* as matching.
* @param manufacturerId string for the id of the manufacturer
* @param deviceName string for the deviceName
* @return this instance
*/
public Selector byManufacturerId(final String manufacturerId) {
setFieldValue(PLATFORM_MANUFACTURER_ID, manufacturerId);
public Selector byDeviceName(final String deviceName) {
setFieldValue("deviceName", deviceName);
return this;
}
/**
* Specify the platform model that rims must have to be considered
* as matching.
* @param model string for the model
* Specify the RIM hash associated with the base RIM.
* @param base64Hash the hash of the file associated with the rim
* @return this instance
*/
public Selector byModel(final String model) {
setFieldValue(PLATFORM_MODEL, model);
public Selector byBase64Hash(final String base64Hash) {
setFieldValue(BASE_64_HASH_FIELD, base64Hash);
return this;
}
}
@ -148,6 +158,16 @@ public class BaseReferenceManifest extends ReferenceManifest {
this.setFileName("");
SoftwareIdentity si = validateSwidTag(new ByteArrayInputStream(rimBytes));
MessageDigest digest = null;
this.base64Hash = "";
try {
digest = MessageDigest.getInstance("SHA-256");
this.base64Hash = Base64.getEncoder().encodeToString(
digest.digest(rimBytes));
} catch (NoSuchAlgorithmException noSaEx) {
LOGGER.error(noSaEx);
}
// begin parsing valid swid tag
if (si != null) {
setTagId(si.getTagId());
@ -757,6 +777,15 @@ public class BaseReferenceManifest extends ReferenceManifest {
this.pcURILocal = pcURILocal;
}
/**
* Getter for the Reference Integrity Manifest hash value.
*
* @return int representation of the hash value
*/
public String getBase64Hash() {
return base64Hash;
}
@Override
public String toString() {
return String.format("ReferenceManifest{swidName=%s,"
@ -764,6 +793,6 @@ public class BaseReferenceManifest extends ReferenceManifest {
+ " platformModel=%s,"
+ "tagId=%s, rimHash=%s}",
swidName, this.getPlatformManufacturer(),
this.getPlatformModel(), getTagId(), this.getRimHash());
this.getPlatformModel(), getTagId(), this.getBase64Hash());
}
}

View File

@ -10,6 +10,8 @@ import org.apache.logging.log4j.Logger;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
@ -29,6 +31,8 @@ public class EventLogMeasurements extends ReferenceManifest {
@Column
@JsonIgnore
private int pcrHash = 0;
@Enumerated(EnumType.STRING)
private AppraisalStatus.Status overallValidationResult = AppraisalStatus.Status.FAIL;
/**
* This class enables the retrieval of SupportReferenceManifest by their attributes.
@ -58,24 +62,23 @@ public class EventLogMeasurements extends ReferenceManifest {
}
/**
* Specify the platform manufacturer id that rims must have to be considered
* Specify the device name that rims must have to be considered
* as matching.
* @param manufacturerId string for the id of the manufacturer
* @param deviceName string for the deviceName
* @return this instance
*/
public Selector byManufacturerId(final String manufacturerId) {
setFieldValue(PLATFORM_MANUFACTURER_ID, manufacturerId);
public Selector byDeviceName(final String deviceName) {
setFieldValue("deviceName", deviceName);
return this;
}
/**
* Specify the platform model that rims must have to be considered
* as matching.
* @param model string for the model
* Specify the RIM hash associated with the Event Log.
* @param hexDecHash the hash of the file associated with the rim
* @return this instance
*/
public Selector byModel(final String model) {
setFieldValue(PLATFORM_MODEL, model);
public Selector byHexDecHash(final String hexDecHash) {
setFieldValue(HEX_DEC_HASH_FIELD, hexDecHash);
return this;
}
}
@ -101,8 +104,8 @@ public class EventLogMeasurements extends ReferenceManifest {
) throws IOException {
super(rimBytes);
this.setFileName(fileName);
this.archive("Event Log Measurement");
this.setRimType(MEASUREMENT_RIM);
this.archive("Measurement event log");
this.pcrHash = 0;
}
@ -182,4 +185,38 @@ public class EventLogMeasurements extends ReferenceManifest {
public void setPcrHash(final int pcrHash) {
this.pcrHash = pcrHash;
}
/**
* Getter for the overall validation result for display purposes.
* @return the result status
*/
public AppraisalStatus.Status getOverallValidationResult() {
return overallValidationResult;
}
/**
* Setter for the overall validation result for display purposes.
* @param overallValidationResult the current status for this validation.
*/
public void setOverallValidationResult(final AppraisalStatus.Status overallValidationResult) {
this.overallValidationResult = overallValidationResult;
}
@Override
public boolean equals(final Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
EventLogMeasurements that = (EventLogMeasurements) object;
return this.getHexDecHash().equals(that.getHexDecHash());
}
@Override
public int hashCode() {
return super.hashCode();
}
}

View File

@ -72,25 +72,29 @@ public final class PCRPolicy extends Policy {
public StringBuilder validatePcrs(final String[] storedPcrs) {
StringBuilder sb = new StringBuilder();
String failureMsg = "PCR %d does not match%n";
if (storedPcrs[0] == null || storedPcrs[0].isEmpty()) {
sb.append("failureMsg");
} else {
for (int i = 0; i <= TPMMeasurementRecord.MAX_PCR_ID; i++) {
if (enableIgnoreIma && i == IMA_PCR) {
LOGGER.info("PCR Policy IMA Ignore enabled.");
i += NUM_TO_SKIP;
}
for (int i = 0; i <= TPMMeasurementRecord.MAX_PCR_ID; i++) {
if (enableIgnoreIma && i == IMA_PCR) {
LOGGER.info("PCR Policy IMA Ignore enabled.");
i += NUM_TO_SKIP;
}
if (enableIgnoretBoot && i == TBOOT_PCR) {
LOGGER.info("PCR Policy TBoot Ignore enabled.");
i += NUM_OF_TBOOT_PCR;
}
if (enableIgnoretBoot && i == TBOOT_PCR) {
LOGGER.info("PCR Policy TBoot Ignore enabled.");
i += NUM_OF_TBOOT_PCR;
}
if (enableIgnoreGpt && i == GPT_PCR) {
LOGGER.info("PCR Policy GPT Ignore enabled.");
i += NUM_TO_SKIP;
}
if (enableIgnoreGpt && i == GPT_PCR) {
LOGGER.info("PCR Policy GPT Ignore enabled.");
i += NUM_TO_SKIP;
}
if (!baselinePcrs[i].equals(storedPcrs[i])) {
sb.append(String.format(failureMsg, i));
if (!baselinePcrs[i].equals(storedPcrs[i])) {
LOGGER.error(String.format("%s =/= %s", baselinePcrs[i], storedPcrs[i]));
sb.append(String.format(failureMsg, i));
}
}
}

View File

@ -28,6 +28,8 @@ public class ReferenceDigestRecord extends ArchivableEntity {
private String manufacturer;
@Column(nullable = false)
private String model;
@Column(nullable = false)
private String deviceName;
@Column(columnDefinition = "blob", nullable = true)
private byte[] valueBlob;
@ -134,6 +136,22 @@ public class ReferenceDigestRecord extends ArchivableEntity {
this.model = model;
}
/**
* Getter for the deviceName associated.
* @return the string of the deviceName
*/
public String getDeviceName() {
return deviceName;
}
/**
* Setter for the deviceName associated.
* @param deviceName the string of the model
*/
public void setDeviceName(final String deviceName) {
this.deviceName = deviceName;
}
/**
* Getter for the byte array of event values.
* @return a clone of the byte array
@ -158,7 +176,7 @@ public class ReferenceDigestRecord extends ArchivableEntity {
*/
@Override
public String toString() {
return String.format("ReferenceDigestRecord: %s%n%s -> %s",
super.toString(), this.manufacturer, this.model);
return String.format("ReferenceDigestRecord: %s%n%s::%s::%s",
super.toString(), this.manufacturer, this.model, this.deviceName);
}
}

View File

@ -31,6 +31,10 @@ import java.util.UUID;
@XmlAccessorType(XmlAccessType.FIELD)
@Access(AccessType.FIELD)
public abstract class ReferenceManifest extends ArchivableEntity {
/**
* Holds the name of the 'hexDecHash' field.
*/
public static final String HEX_DEC_HASH_FIELD = "hexDecHash";
/**
* String for display of a Base RIM.
*/
@ -64,13 +68,6 @@ public abstract class ReferenceManifest extends ArchivableEntity {
private static final Logger LOGGER = LogManager.getLogger(ReferenceManifest.class);
/**
* Holds the name of the 'rimHash' field.
*/
public static final String RIM_HASH_FIELD = "rimHash";
@Column(nullable = false)
@JsonIgnore
private final String rimHash;
@Column(columnDefinition = "blob", nullable = false)
@JsonIgnore
private byte[] rimBytes;
@ -97,6 +94,15 @@ public abstract class ReferenceManifest extends ArchivableEntity {
@Type(type = "uuid-char")
@Column
private UUID associatedRim;
@Column
@JsonIgnore
private String deviceName;
@Column
@JsonIgnore
private String hexDecHash = "";
@Column
@JsonIgnore
private String eventLogHash = "";
/**
* Default constructor necessary for Hibernate.
@ -104,7 +110,6 @@ public abstract class ReferenceManifest extends ArchivableEntity {
protected ReferenceManifest() {
super();
this.rimBytes = null;
this.rimHash = "";
this.rimType = null;
this.platformManufacturer = null;
this.platformManufacturerId = null;
@ -126,19 +131,15 @@ public abstract class ReferenceManifest extends ArchivableEntity {
"Cannot construct a RIM from an empty byte array");
this.rimBytes = rimBytes.clone();
MessageDigest digest = null;
this.hexDecHash = "";
try {
digest = MessageDigest.getInstance("SHA-256");
this.hexDecHash = Hex.encodeHexString(
digest.digest(rimBytes));
} catch (NoSuchAlgorithmException noSaEx) {
LOGGER.error(noSaEx);
}
if (digest == null) {
this.rimHash = "";
} else {
this.rimHash = Hex.encodeHexString(
digest.digest(rimBytes));
}
}
/**
@ -212,7 +213,7 @@ public abstract class ReferenceManifest extends ArchivableEntity {
}
/**
* Getter for the RIM Type (Primary, Supplemental, Patch).
* Getter for the RIM Type (Base, Support, Measurement).
*
* @return string for the RIM Type
*/
@ -335,6 +336,48 @@ public abstract class ReferenceManifest extends ArchivableEntity {
this.associatedRim = associatedRim;
}
/**
* Getter for the Device Name.
* @return string value of the device associated with this log.
*/
public String getDeviceName() {
return deviceName;
}
/**
* Setter for the Device Name.
* @param deviceName new value to assign.
*/
public void setDeviceName(final String deviceName) {
this.deviceName = deviceName;
}
/**
* Getter for the Reference Integrity Manifest hash value.
*
* @return int representation of the hash value
*/
public String getHexDecHash() {
return hexDecHash;
}
/**
* Getter for the event log hash.
* @param eventLogHash hash value to store
*/
public void setEventLogHash(final String eventLogHash) {
this.eventLogHash = eventLogHash;
}
/**
* Getter for the event log hash.
*
* @return int representation of the hash value
*/
public String getEventLogHash() {
return eventLogHash;
}
/**
* Getter for the Reference Integrity Manifest as a byte array.
*
@ -348,15 +391,6 @@ public abstract class ReferenceManifest extends ArchivableEntity {
return null;
}
/**
* Getter for the Reference Integrity Manifest hash value.
*
* @return int representation of the hash value
*/
public String getRimHash() {
return rimHash;
}
@Override
public int hashCode() {
return Arrays.hashCode(this.rimBytes);
@ -374,8 +408,7 @@ public abstract class ReferenceManifest extends ArchivableEntity {
return false;
}
ReferenceManifest that = (ReferenceManifest) object;
return rimHash == that.rimHash
&& Arrays.equals(rimBytes, that.rimBytes)
return Arrays.equals(rimBytes, that.rimBytes)
&& rimType.equals(that.rimType)
&& tagId.equals(that.tagId)
&& platformManufacturer.equals(that.platformManufacturer)
@ -387,8 +420,7 @@ public abstract class ReferenceManifest extends ArchivableEntity {
@Override
public String toString() {
return String.format("Filename->%s%nPlatform Manufacturer->%s%n"
+ "Platform Model->%s%nRIM Type->%s%nRIM Hash->%s", this.getFileName(),
this.platformManufacturer, this.platformModel, this.getRimType(),
this.getRimHash());
+ "Platform Model->%s%nRIM Type->%s%nRIM", this.getFileName(),
this.platformManufacturer, this.platformModel, this.getRimType());
}
}

View File

@ -23,7 +23,6 @@ import java.util.Collection;
@Entity
public class SupportReferenceManifest extends ReferenceManifest {
private static final Logger LOGGER = LogManager.getLogger(SupportReferenceManifest.class);
@Column
@JsonIgnore
private int pcrHash = 0;
@ -60,24 +59,13 @@ public class SupportReferenceManifest extends ReferenceManifest {
}
/**
* Specify the platform manufacturer id that rims must have to be considered
* Specify the device name that rims must have to be considered
* as matching.
* @param manufacturerId string for the id of the manufacturer
* @param deviceName string for the deviceName
* @return this instance
*/
public Selector byManufacturerId(final String manufacturerId) {
setFieldValue(PLATFORM_MANUFACTURER_ID, manufacturerId);
return this;
}
/**
* Specify the platform model that rims must have to be considered
* as matching.
* @param model string for the model
* @return this instance
*/
public Selector byModel(final String model) {
setFieldValue(PLATFORM_MODEL, model);
public Selector byDeviceName(final String deviceName) {
setFieldValue("deviceName", deviceName);
return this;
}
@ -93,11 +81,11 @@ public class SupportReferenceManifest extends ReferenceManifest {
/**
* Specify the RIM hash associated with the support RIM.
* @param rimHash the hash of the file associated with the rim
* @param hexDecHash the hash of the file associated with the rim
* @return this instance
*/
public Selector byRimHash(final String rimHash) {
setFieldValue(RIM_HASH_FIELD, rimHash);
public Selector byHexDecHash(final String hexDecHash) {
setFieldValue(HEX_DEC_HASH_FIELD, hexDecHash);
return this;
}
}

View File

@ -108,6 +108,28 @@ public class DBReferenceDigestManager extends DBManager<ReferenceDigestRecord>
return dbRecord;
}
@Override
public List<ReferenceDigestRecord> getRecordsByDeviceName(final String deviceName) {
LOGGER.debug("Getting record for {}", deviceName);
if (deviceName == null) {
LOGGER.error("No deviceName to get record from db");
return null;
}
List<ReferenceDigestRecord> dbRecords = new ArrayList<>();
try {
List<ReferenceDigestRecord> dbTempList = super.getList(ReferenceDigestRecord.class);
for (ReferenceDigestRecord rdr : dbTempList) {
if (rdr.getDeviceName().equals(deviceName)) {
dbRecords.add(rdr);
}
}
} catch (DBManagerException dbMEx) {
throw new RuntimeException(dbMEx);
}
return dbRecords;
}
@Override
public ReferenceDigestRecord getRecordById(final ReferenceDigestRecord referenceDigestRecord) {
LOGGER.debug("Getting record for {}", referenceDigestRecord);

View File

@ -37,6 +37,14 @@ public interface ReferenceDigestManager {
*/
ReferenceDigestRecord getRecord(String manufacturer, String model);
/**
* Persists a new Reference Digest.
*
* @param deviceName the string of the network hostname
* @return the persisted ReferenceDigestRecord list
*/
List<ReferenceDigestRecord> getRecordsByDeviceName(String deviceName);
/**
* Persists a new Reference Digest.
*

View File

@ -97,17 +97,6 @@ public abstract class ReferenceManifestSelector<T extends ReferenceManifest> {
return this;
}
/**
* Specify the hash code of the bytes that rim must match.
*
* @param rimHash the hash code of the bytes to query for
* @return this instance (for chaining further calls)
*/
public ReferenceManifestSelector<T> byHashCode(final String rimHash) {
setFieldValue(hirs.data.persist.ReferenceManifest.RIM_HASH_FIELD, rimHash);
return this;
}
/**
* Specify the file name of the object to grab.
* @param fileName the name of the file associated with the rim

View File

@ -1,17 +1,7 @@
package hirs.tpm.eventlog;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import hirs.tpm.eventlog.events.EvConstants;
import hirs.tpm.eventlog.events.EvCompactHash;
import hirs.tpm.eventlog.events.EvConstants;
import hirs.tpm.eventlog.events.EvEfiBootServicesApp;
import hirs.tpm.eventlog.events.EvEfiGptPartition;
import hirs.tpm.eventlog.events.EvEfiHandoffTable;
@ -30,6 +20,16 @@ import org.apache.commons.codec.binary.Hex;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Arrays;
/**
* Class to process a TCG_PCR_EVENT.
* TCG_PCR_EVENT is used when the Event log uses the SHA1 Format as described in the
@ -211,6 +211,14 @@ public class TpmPcrEvent {
return String.format("0x%s %s", Long.toHexString(eventType), eventString((int) eventType));
}
/**
* Returns a formatted string of the type for the event minus the byte code.
* @return a string formatted to be human readable
*/
public String getEventTypeString() {
return eventString((int) eventType);
}
/**
* Returns the version of the TCG Log Event specification pertaining to the log.
* only updated if the event is a TCG_EfiSpecIdEvent.