Merge pull request #439 from nsacyber/rim-blob-size-update

Variety of Firmware RIM modifications
This commit is contained in:
iadgovuser26 2022-02-15 15:26:39 -05:00 committed by GitHub
commit b136159d17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 79 additions and 342 deletions

View File

@ -840,7 +840,8 @@ public abstract class AbstractAttestationCertificateAuthority
}
}
} else {
LOG.warn("Device did not send support RIM file...");
LOG.warn(String.format("%s did not send support RIM file...",
dv.getNw().getHostname()));
}
if (dv.getSwidfileCount() > 0) {
@ -876,7 +877,8 @@ public abstract class AbstractAttestationCertificateAuthority
}
}
} else {
LOG.warn("Device did not send swid tag file...");
LOG.warn(String.format("%s did not send swid tag file...",
dv.getNw().getHostname()));
}
//update Support RIMs and Base RIMs.
@ -948,11 +950,21 @@ public abstract class AbstractAttestationCertificateAuthority
this.referenceManifestManager.update(rim);
}
}
for (BaseReferenceManifest baseRim : BaseReferenceManifest
.select(referenceManifestManager).getRIMs()) {
if (baseRim.getPlatformManufacturer().equals(dv.getHw().getManufacturer())
&& baseRim.getPlatformModel().equals(dv.getHw().getProductName())) {
baseRim.setEventLogHash(temp.getHexDecHash());
this.referenceManifestManager.update(baseRim);
}
}
} catch (IOException ioEx) {
LOG.error(ioEx);
}
} else {
LOG.warn("Device did not send bios measurement log...");
LOG.warn(String.format("%s did not send bios measurement log...",
dv.getNw().getHostname()));
}
// Get TPM info, currently unimplemented
@ -1885,7 +1897,7 @@ public abstract class AbstractAttestationCertificateAuthority
generateCertificate = scp.isIssueAttestationCertificate();
if (issuedAc != null && scp.isGenerateOnExpiration()) {
if (issuedAc.getEndValidity().after(currentDate)) {
// so the issued AC is expired
// so the issued AC is not expired
// however are we within the threshold
days = daysBetween(currentDate, issuedAc.getEndValidity());
if (days < Integer.parseInt(scp.getReissueThreshold())) {

View File

@ -389,14 +389,15 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
Set<BaseReferenceManifest> baseReferenceManifests = null;
BaseReferenceManifest baseReferenceManifest = null;
ReferenceManifest supportReferenceManifest = null;
ReferenceManifest measurement = null;
EventLogMeasurements measurement = null;
ReferenceDigestRecord digestRecord = null;
baseReferenceManifests = BaseReferenceManifest.select(referenceManifestManager)
.byDeviceName(device.getDeviceInfo().getNetworkInfo().getHostname()).getRIMs();
.byModel(model).getRIMs();
for (BaseReferenceManifest bRim : baseReferenceManifests) {
if (!bRim.isSwidSupplemental() && !bRim.isSwidPatch()) {
if (bRim.getPlatformManufacturer().equals(manufacturer)
&& !bRim.isSwidSupplemental() && !bRim.isSwidPatch()) {
baseReferenceManifest = bRim;
}
}
@ -408,6 +409,11 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
} else {
measurement = EventLogMeasurements.select(referenceManifestManager)
.byHexDecHash(baseReferenceManifest.getEventLogHash()).getRIM();
if (measurement == null) {
measurement = EventLogMeasurements.select(referenceManifestManager)
.byModel(baseReferenceManifest.getPlatformModel()).getRIM();
}
}
if (measurement == null) {
@ -456,12 +462,10 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
for (SwidResource swidRes : resources) {
supportReferenceManifest = SupportReferenceManifest.select(referenceManifestManager)
.byHexDecHash(swidRes.getHashValue()).getRIM();
if (supportReferenceManifest != null
&& swidRes.getName().equals(supportReferenceManifest.getFileName())) {
if (supportReferenceManifest != null) {
// Removed the filename check from this if statement
referenceManifestValidator.validateSupportRimHash(
supportReferenceManifest.getRimBytes(), swidRes.getHashValue());
} else {
supportReferenceManifest = null;
}
}
@ -473,7 +477,7 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
if (passed && supportReferenceManifest == null) {
fwStatus = new AppraisalStatus(FAIL,
"Support Reference Integrity Manifest can not be found\n");
"Support Reference Integrity Manifest can not be found");
passed = false;
}
@ -581,9 +585,10 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
} else {
fwStatus = new AppraisalStatus(FAIL, String.format("Firmware Validation failed: "
+ "%s for %s can not be found", failedString, manufacturer));
EventLogMeasurements eventLog = (EventLogMeasurements) measurement;
eventLog.setOverallValidationResult(fwStatus.getAppStatus());
this.referenceManifestManager.update(eventLog);
if (measurement != null) {
measurement.setOverallValidationResult(fwStatus.getAppStatus());
this.referenceManifestManager.update(measurement);
}
}
return buildValidationRecord(SupplyChainValidation.ValidationType.FIRMWARE,

View File

@ -473,13 +473,14 @@ public class PolicyPageController extends PageController<NoPageParams> {
if (generateCertificateEnabled) {
threshold = ppModel.getThresholdValue();
if (threshold == null) {
threshold = SupplyChainPolicy.YEAR;
}
} else {
threshold = ppModel.getReissueThreshold();
}
if (threshold == null || threshold.isEmpty()) {
threshold = SupplyChainPolicy.YEAR;
}
policy.setReissueThreshold(threshold);
} else {
generateCertificateEnabled = false;
@ -542,13 +543,14 @@ public class PolicyPageController extends PageController<NoPageParams> {
if (generateDevIdCertificateEnabled) {
threshold = ppModel.getDevIdThresholdValue();
if (threshold == null) {
threshold = SupplyChainPolicy.YEAR;
}
} else {
threshold = ppModel.getDevIdReissueThreshold();
}
if (threshold == null || threshold.isEmpty()) {
threshold = SupplyChainPolicy.YEAR;
}
policy.setDevIdReissueThreshold(threshold);
} else {
generateDevIdCertificateEnabled = false;

View File

@ -10,6 +10,7 @@ import hirs.attestationca.portal.page.PageController;
import hirs.attestationca.portal.page.PageMessages;
import hirs.attestationca.portal.page.params.NoPageParams;
import hirs.data.persist.BaseReferenceManifest;
import hirs.data.persist.EventLogMeasurements;
import hirs.data.persist.ReferenceManifest;
import hirs.data.persist.SupportReferenceManifest;
import hirs.data.persist.SwidResource;
@ -257,6 +258,15 @@ public class ReferenceManifestPageController
}
}
}
for (EventLogMeasurements liveLog : EventLogMeasurements
.select(referenceManifestManager).getRIMs()) {
if (liveLog.getPlatformManufacturer().equals(base.getPlatformManufacturer())
&& liveLog.getPlatformModel().equals(base.getPlatformModel())) {
rim.setEventLogHash(liveLog.getEventLogHash());
break;
}
}
}
storeManifest(file.getOriginalFilename(),

View File

@ -1,108 +0,0 @@
package hirs.attestationca.portal.page.controllers;
import hirs.data.persist.BaseReferenceManifest;
import hirs.data.persist.ReferenceManifest;
import hirs.persist.DBReferenceManifestManager;
import hirs.attestationca.portal.page.Page;
import hirs.attestationca.portal.page.PageController;
import hirs.attestationca.portal.page.PageControllerTest;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.util.Map;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Integration tests that test the URL End Points of
* EndorsementKeyCredentialsPageController.
*/
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class ReferenceManifestDetailsPageControllerTest extends PageControllerTest {
private static final String GOOD_RIM_FILE = "/rims/generated_good.swidtag";
private static final String ID = "046b6c7f-0b8a-43b9-b35d-6489e6daee91";
@Autowired
private DBReferenceManifestManager referenceManifestManager;
private ReferenceManifest referenceManifest;
/**
* Prepares tests.
*
* @throws IOException if test resources are not found
*/
@BeforeClass
public void prepareTests() throws IOException {
Path fPath;
try {
fPath = Paths.get(this.getClass().getResource(GOOD_RIM_FILE).toURI());
} catch (URISyntaxException e) {
throw new IOException("Could not resolve path URI", e);
}
referenceManifest = new BaseReferenceManifest(Files.readAllBytes(fPath));
referenceManifestManager.save(referenceManifest);
}
/**
* Constructor.
*/
public ReferenceManifestDetailsPageControllerTest() {
super(Page.RIM_DETAILS);
}
/**
* Tests initial page when the Reference Integrity Manifest
* was not found.
* @throws Exception if an exception occurs
*/
@Test
public void testInitPage() throws Exception {
// Get error message
getMockMvc()
.perform(MockMvcRequestBuilders.get("/" + getPage().getViewName())
.param("id", ID))
.andExpect(status().isOk())
.andExpect(model().attribute(PageController.MESSAGES_ATTRIBUTE,
hasProperty("error", hasItem("Unable to find RIM with ID: " + ID))))
.andReturn();
}
/**
* Tests initial page for an Reference Integrity Manifest.
*
* @throws Exception if an exception occurs
*/
@Test
@Rollback
@SuppressWarnings("unchecked")
public void testInitPageRim() throws Exception {
MvcResult result = getMockMvc()
.perform(MockMvcRequestBuilders.get("/" + getPage().getViewName())
.param("id", referenceManifest.getId().toString())
.param("swidTagId", referenceManifest.getTagId()))
.andExpect(status().isOk())
.andExpect(model().attributeExists(PolicyPageController.INITIAL_DATA))
.andReturn();
// Obtain initialData HashMap
Map<String, String> initialData = (Map<String, String>) result
.getModelAndView()
.getModel()
.get(PolicyPageController.INITIAL_DATA);
Assert.assertEquals(initialData.get("swidTagId"), referenceManifest.getTagId());
}
}

View File

@ -1,191 +0,0 @@
package hirs.attestationca.portal.page.controllers;
import hirs.data.persist.BaseReferenceManifest;
import hirs.data.persist.ReferenceManifest;
import hirs.persist.ReferenceManifestManager;
import hirs.attestationca.portal.page.Page;
import hirs.attestationca.portal.page.PageControllerTest;
import hirs.attestationca.portal.page.PageMessages;
import java.io.IOException;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.web.servlet.FlashMap;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Integration tests that test the URL End Points of
* ReferenceManifestPageController.
*/
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class ReferenceManifestPageControllerTest extends PageControllerTest {
private static final String GOOD_RIM_FILE = "generated_good.swidtag";
private static final String BAD_RIM_FILE = "generated_bad.swidtag";
@Autowired
private ReferenceManifestManager referenceManifestManager;
private MockMultipartFile validRimFile;
private MockMultipartFile nonValidRimFile;
/**
* Constructor.
*/
public ReferenceManifestPageControllerTest() {
super(Page.REFERENCE_MANIFESTS);
}
/**
* Prepares tests.
*
* @throws IOException if test resources are not found
*/
@BeforeMethod
public void prepareTests() throws IOException {
// create a multi part file for the controller upload
validRimFile = new MockMultipartFile("file", GOOD_RIM_FILE, "",
new ClassPathResource("rims/" + GOOD_RIM_FILE).getInputStream());
nonValidRimFile = new MockMultipartFile("file", BAD_RIM_FILE, "",
new ClassPathResource("rims/" + BAD_RIM_FILE).getInputStream());
}
private void archiveTestCert(final ReferenceManifest referenceManifest) throws Exception {
// now, archive the record
getMockMvc().perform(MockMvcRequestBuilders
.post("/reference-manifests/delete")
.param("id", referenceManifest.getId().toString()))
.andExpect(status().is3xxRedirection())
.andReturn();
Set<ReferenceManifest> records
= referenceManifestManager.get(BaseReferenceManifest
.select(referenceManifestManager).includeArchived());
Assert.assertEquals(records.size(), 1);
Assert.assertTrue(records.iterator().next().isArchived());
}
/**
* Tests uploading a RIM that is a Reference Integrity Manifest, and
* archiving it.
*
* @throws Exception if an exception occurs
*/
@Test
@Rollback
public void uploadAndArchiveValidRim() throws Exception {
ReferenceManifest rim = uploadTestRim();
archiveTestRim(rim);
}
/**
* Tests uploading a rim that is not a valid Reference Integrity Manifest,
* which results in failure.
*
* @throws Exception if an exception occurs
*/
@Test
@Rollback
public void uploadNonValidRim() throws Exception {
MvcResult result = getMockMvc().perform(MockMvcRequestBuilders
.fileUpload("/reference-manifests/upload")
.file(nonValidRimFile))
.andExpect(status().is3xxRedirection())
.andReturn();
// verify redirection messages
FlashMap flashMap = result.getFlashMap();
PageMessages pageMessages = (PageMessages) flashMap.get("messages");
Assert.assertEquals(pageMessages.getSuccess().size(), 0);
Assert.assertEquals(pageMessages.getError().size(), 1);
}
/**
* Tests that uploading a RIM when an identical RIM is archived will cause
* the existing RIM to be unarchived and updated.
*
* @throws Exception if an exception occurs
*/
@Test
@Rollback
public void uploadCausesUnarchive() throws Exception {
ReferenceManifest rim = uploadTestRim();
archiveTestCert(rim);
// upload the same cert again
MvcResult result = getMockMvc().perform(MockMvcRequestBuilders
.fileUpload("/reference-manifests/upload")
.file(validRimFile))
.andExpect(status().is3xxRedirection())
.andReturn();
// verify redirection messages
FlashMap flashMap = result.getFlashMap();
PageMessages pageMessages = (PageMessages) flashMap.get("messages");
Assert.assertEquals(pageMessages.getSuccess().size(), 1);
Assert.assertEquals(pageMessages.getError().size(), 0);
Assert.assertEquals(pageMessages.getSuccess().get(0),
"Pre-existing RIM found and unarchived (generated_good.swidtag): ");
// verify the cert was actually stored
Set<ReferenceManifest> records = referenceManifestManager.get(BaseReferenceManifest.select(
referenceManifestManager));
Assert.assertEquals(records.size(), 1);
ReferenceManifest newRim = records.iterator().next();
// verify that the rim was unarchived
Assert.assertFalse(newRim.isArchived());
// verify that the createTime was updated
Assert.assertTrue(newRim.getCreateTime().getTime() > rim.getCreateTime().getTime());
}
private ReferenceManifest uploadTestRim() throws Exception {
MvcResult result = getMockMvc().perform(MockMvcRequestBuilders
.fileUpload("/reference-manifests/upload")
.file(validRimFile))
.andExpect(status().is3xxRedirection())
.andReturn();
// verify redirection messages
FlashMap flashMap = result.getFlashMap();
PageMessages pageMessages = (PageMessages) flashMap.get("messages");
Assert.assertEquals(pageMessages.getSuccess().size(), 1);
Assert.assertEquals(pageMessages.getError().size(), 0);
// verify the cert was actually stored
Set<ReferenceManifest> records
= referenceManifestManager.get(BaseReferenceManifest
.select(referenceManifestManager));
Assert.assertEquals(records.size(), 1);
ReferenceManifest rim = records.iterator().next();
Assert.assertFalse(rim.isArchived());
return rim;
}
private void archiveTestRim(final ReferenceManifest rim) throws Exception {
// now, archive the record
getMockMvc().perform(MockMvcRequestBuilders
.post("/reference-manifests/delete")
.param("id", rim.getId().toString()))
.andExpect(status().is3xxRedirection())
.andReturn();
Set<ReferenceManifest> records
= referenceManifestManager.get(BaseReferenceManifest
.select(referenceManifestManager).includeArchived());
Assert.assertEquals(records.size(), 1);
Assert.assertTrue(records.iterator().next().isArchived());
}
}

View File

@ -48,27 +48,12 @@ SWIDTAG_FILE_LOCATION="$TCG_DIRECTORY/manifest/swidtag/"
CREDENTIALS_LOCATION="$TCG_DIRECTORY/cert/platform/"
BINARY_BIOS_MEASUREMENTS="/sys/kernel/security/tpm0/binary_bios_measurements"
touch "$TCG_TEMP_FILE"
if [ -d "$RIM_FILE_LOCATION" ]; then
echo "tcg.rim.dir=$RIM_FILE_LOCATION" > "$TCG_TEMP_FILE"
fi
if [ -d "$SWIDTAG_FILE_LOCATION" ]; then
echo "tcg.swidtag.dir=$SWIDTAG_FILE_LOCATION" >> "$TCG_TEMP_FILE"
fi
if [ -d "$CREDENTIALS_LOCATION" ]; then
echo "tcg.cert.dir=$CREDENTIALS_LOCATION" >> "$TCG_TEMP_FILE"
fi
if [ -f "$BINARY_BIOS_MEASUREMENTS" ]; then
echo "tcg.event.file=$BINARY_BIOS_MEASUREMENTS" >> "$TCG_TEMP_FILE"
fi
if [ ! -f "$TCG_BOOT_FILE" ]; then
touch "$TCG_TEMP_FILE"
echo "tcg.rim.dir=$RIM_FILE_LOCATION" > "$TCG_TEMP_FILE"
echo "tcg.swidtag.dir=$SWIDTAG_FILE_LOCATION" >> "$TCG_TEMP_FILE"
echo "tcg.cert.dir=$CREDENTIALS_LOCATION" >> "$TCG_TEMP_FILE"
echo "tcg.event.file=$BINARY_BIOS_MEASUREMENTS" >> "$TCG_TEMP_FILE"
install -m 644 $TCG_TEMP_FILE $TCG_BOOT_FILE
else
echo $TCG_TEMP_FILE > $TCG_BOOT_FILE
fi

View File

@ -110,6 +110,17 @@ public class BaseReferenceManifest extends ReferenceManifest {
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);
return this;
}
/**
* Specify the device name that rims must have to be considered
* as matching.

View File

@ -61,6 +61,17 @@ public class EventLogMeasurements extends ReferenceManifest {
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);
return this;
}
/**
* Specify the device name that rims must have to be considered
* as matching.

View File

@ -30,7 +30,7 @@ public class ReferenceDigestRecord extends ArchivableEntity {
private String model;
@Column(nullable = false)
private String deviceName;
@Column(columnDefinition = "blob", nullable = true)
@Column(columnDefinition = "mediumblob", nullable = true)
private byte[] valueBlob;
/**

View File

@ -68,7 +68,7 @@ public abstract class ReferenceManifest extends ArchivableEntity {
private static final Logger LOGGER = LogManager.getLogger(ReferenceManifest.class);
@Column(columnDefinition = "blob", nullable = false)
@Column(columnDefinition = "mediumblob", nullable = false)
@JsonIgnore
private byte[] rimBytes;
@Column(nullable = false)