/*
* Copyright (C) 2012 Intel Corporation
* All rights reserved.
*/
package com.intel.mtwilson.policy.rule;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.intel.mtwilson.model.Measurement;
import com.intel.mtwilson.model.PcrEventLog;
import com.intel.mtwilson.policy.BaseRule;
import com.intel.mtwilson.policy.HostReport;
import com.intel.mtwilson.policy.RuleResult;
import com.intel.mtwilson.policy.fault.PcrEventLogContainsUnexpectedEntries;
import com.intel.mtwilson.policy.fault.PcrEventLogMissing;
import com.intel.mtwilson.policy.fault.PcrEventLogMissingExpectedEntries;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A TrustPolicy implementation that checks whether the HostReport contains
* a ModuleManifest for a given PCR that equals the expected ModuleManifest.
* The expected ModuleManifest in this case is a complete manifest and any
* change (less modules, more modules, different modules) in the actual
* ModuleManifest will trigger a fault.
*
* @author jbuhacoff
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(ignoreUnknown=true)
public class PcrEventLogEquals extends BaseRule {
private Logger log = LoggerFactory.getLogger(getClass());
private PcrEventLog expected;
protected PcrEventLogEquals() { } // for desearializing jackson
public PcrEventLogEquals(PcrEventLog expected) {
this.expected = expected;
}
public PcrEventLog getPcrModuleManifest() { return expected; }
@Override
public RuleResult apply(HostReport hostReport) {
RuleResult report = new RuleResult(this);
// report.check(this);
// report.check(getClass().getSimpleName()); // the minimum... show that the host was evaluated by this policy
if( hostReport.pcrManifest == null ) {
log.debug("PcrManifest null fault is being raised.");
report.fault(new PcrEventLogMissing());
}
else {
PcrEventLog pcrEventLog = getPcrEventLog(hostReport);
if( pcrEventLog == null ) {
log.debug("PcrEventLog missing fault is being raised.");
report.fault(new PcrEventLogMissing(expected.getPcrIndex()));
}
else {
List<Measurement> moduleManifest = pcrEventLog.getEventLog();
log.debug("About to apply the PcrEventLogEquals policy for {} entries.", moduleManifest.size());
if( moduleManifest == null || moduleManifest.isEmpty() ) {
report.fault(new PcrEventLogMissing(expected.getPcrIndex()));
}
else {
// we check that for the PCR defined in the policy, the HostReport's PcrModuleManifest contains the exact set of expected modules
ArrayList<Measurement> hostActualUnexpected = new ArrayList<Measurement>(moduleManifest);
hostActualUnexpected.removeAll(expected.getEventLog()); // hostActualUnexpected = actual modules - expected modules = only extra modules that shouldn't be there; comparison is done BY HASH VALUE, not by name or any "other info"
if( !hostActualUnexpected.isEmpty() ) {
log.debug("PcrEventLogEquals : Host is having #{} additional modules compared to the white list.", hostActualUnexpected.size());
report.fault(new PcrEventLogContainsUnexpectedEntries(expected.getPcrIndex(), hostActualUnexpected));
}
ArrayList<Measurement> hostActualMissing = new ArrayList<Measurement>(expected.getEventLog());
hostActualMissing.removeAll(moduleManifest); // hostActualMissing = expected modules - actual modules = only modules that should be there but aren't
if( !hostActualMissing.isEmpty() ) {
log.debug("PcrEventLogEquals : Host is missing #{} modules compared to the white list.", hostActualMissing.size());
report.fault(new PcrEventLogMissingExpectedEntries(expected.getPcrIndex(), new HashSet<Measurement>(hostActualMissing)));
}
}
}
}
return report;
}
protected PcrEventLog getPcrEventLog(HostReport hostReport) {
return hostReport.pcrManifest.getPcrEventLog(expected.getPcrIndex());
}
}