mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-02-21 18:06:42 +00:00
All bugs are fixed. The SupplyChainValidationSummary wasn't getting pulled from the DB.
This commit is contained in:
parent
0f3eb1b5d0
commit
0ab91b9b41
@ -62,14 +62,11 @@ import javax.crypto.spec.OAEPParameterSpec;
|
|||||||
import javax.crypto.spec.PSource;
|
import javax.crypto.spec.PSource;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.NoSuchFileException;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
@ -167,8 +164,9 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
private final DeviceManager deviceManager;
|
private final DeviceManager deviceManager;
|
||||||
private final DBManager<TPM2ProvisionerState> tpm2ProvisionerStateDBManager;
|
private final DBManager<TPM2ProvisionerState> tpm2ProvisionerStateDBManager;
|
||||||
private String tpmQuoteHash = "";
|
private String tpmQuoteHash = "";
|
||||||
private String tpmSignatureHash = "";
|
private String tpmQuoteSignature = "";
|
||||||
private String pcrValues;
|
private String pcrValues;
|
||||||
|
private SupplyChainValidationSummary savedSummary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -455,7 +453,7 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
// perform supply chain validation
|
// perform supply chain validation
|
||||||
SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain(
|
SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain(
|
||||||
endorsementCredential, platformCredentials, device);
|
endorsementCredential, platformCredentials, device);
|
||||||
|
savedSummary = summary;
|
||||||
// update the validation result in the device
|
// update the validation result in the device
|
||||||
AppraisalStatus.Status validationResult = summary.getOverallValidationResult();
|
AppraisalStatus.Status validationResult = summary.getOverallValidationResult();
|
||||||
device.setSupplyChainStatus(validationResult);
|
device.setSupplyChainStatus(validationResult);
|
||||||
@ -472,7 +470,8 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
*/
|
*/
|
||||||
private AppraisalStatus.Status doQuoteValidation(final Device device) {
|
private AppraisalStatus.Status doQuoteValidation(final Device device) {
|
||||||
// perform supply chain validation
|
// perform supply chain validation
|
||||||
SupplyChainValidationSummary scvs = supplyChainValidationService.validateQuote(device);
|
SupplyChainValidationSummary scvs = supplyChainValidationService.validateQuote(
|
||||||
|
device, savedSummary);
|
||||||
AppraisalStatus.Status validationResult;
|
AppraisalStatus.Status validationResult;
|
||||||
|
|
||||||
// either validation wasn't enabled or device already failed
|
// either validation wasn't enabled or device already failed
|
||||||
@ -536,37 +535,63 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
Set<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,
|
Set<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,
|
||||||
endorsementCredential);
|
endorsementCredential);
|
||||||
|
|
||||||
// Parse through the Provisioner supplied TPM Quote and pcr values
|
|
||||||
// these fields are optional
|
|
||||||
if (request.getQuote() != null && !request.getQuote().isEmpty()) {
|
|
||||||
parseTPMQuote(request.getQuote().toStringUtf8());
|
|
||||||
}
|
|
||||||
// if (request.getPcrslist() != null && !request.getPcrslist().isEmpty()) {
|
|
||||||
// this.pcrValues = request.getPcrslist().toStringUtf8();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Get device name and device
|
// Get device name and device
|
||||||
String deviceName = claim.getDv().getNw().getHostname();
|
String deviceName = claim.getDv().getNw().getHostname();
|
||||||
Device device = deviceManager.getDevice(deviceName);
|
Device device = deviceManager.getDevice(deviceName);
|
||||||
|
|
||||||
// Create signed, attestation certificate
|
// Parse through the Provisioner supplied TPM Quote and pcr values
|
||||||
X509Certificate attestationCertificate = generateCredential(akPub,
|
// these fields are optional
|
||||||
endorsementCredential, platformCredentials, deviceName);
|
if (request.getQuote() != null && !request.getQuote().isEmpty()) {
|
||||||
byte[] derEncodedAttestationCertificate = getDerEncodedCertificate(
|
parseTPMQuote(request.getQuote().toStringUtf8());
|
||||||
attestationCertificate);
|
TPMInfo savedInfo = device.getDeviceInfo().getTPMInfo();
|
||||||
|
TPMInfo tpmInfo = null;
|
||||||
|
try {
|
||||||
|
tpmInfo = new TPMInfo(savedInfo.getTPMMake(),
|
||||||
|
savedInfo.getTPMVersionMajor(),
|
||||||
|
savedInfo.getTPMVersionMinor(),
|
||||||
|
savedInfo.getTPMVersionRevMajor(),
|
||||||
|
savedInfo.getTPMVersionRevMinor(),
|
||||||
|
savedInfo.getPcrValues(),
|
||||||
|
this.tpmQuoteHash.getBytes("UTF-8"),
|
||||||
|
this.tpmQuoteSignature.getBytes("UTF-8"));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
LOG.error(e);
|
||||||
|
}
|
||||||
|
DeviceInfoReport dvReport = new DeviceInfoReport(
|
||||||
|
device.getDeviceInfo().getNetworkInfo(),
|
||||||
|
device.getDeviceInfo().getOSInfo(),
|
||||||
|
device.getDeviceInfo().getFirmwareInfo(),
|
||||||
|
device.getDeviceInfo().getHardwareInfo(), tpmInfo,
|
||||||
|
claim.getClientVersion());
|
||||||
|
device = this.deviceRegister.saveOrUpdateDevice(dvReport);
|
||||||
|
}
|
||||||
|
|
||||||
// We validated the nonce and made use of the identity claim so state can be deleted
|
AppraisalStatus.Status validationResult = doQuoteValidation(device);
|
||||||
tpm2ProvisionerStateDBManager.delete(tpm2ProvisionerState);
|
if (validationResult == AppraisalStatus.Status.PASS) {
|
||||||
|
// Create signed, attestation certificate
|
||||||
|
X509Certificate attestationCertificate = generateCredential(akPub,
|
||||||
|
endorsementCredential, platformCredentials, deviceName);
|
||||||
|
byte[] derEncodedAttestationCertificate = getDerEncodedCertificate(
|
||||||
|
attestationCertificate);
|
||||||
|
|
||||||
// Package the signed certificate into a response
|
// We validated the nonce and made use of the identity claim so state can be deleted
|
||||||
ByteString certificateBytes = ByteString.copyFrom(derEncodedAttestationCertificate);
|
tpm2ProvisionerStateDBManager.delete(tpm2ProvisionerState);
|
||||||
ProvisionerTpm2.CertificateResponse response = ProvisionerTpm2.CertificateResponse
|
|
||||||
.newBuilder().setCertificate(certificateBytes).build();
|
|
||||||
|
|
||||||
saveAttestationCertificate(derEncodedAttestationCertificate, endorsementCredential,
|
// Package the signed certificate into a response
|
||||||
platformCredentials, device);
|
ByteString certificateBytes = ByteString.copyFrom(derEncodedAttestationCertificate);
|
||||||
|
ProvisionerTpm2.CertificateResponse response = ProvisionerTpm2.CertificateResponse
|
||||||
|
.newBuilder().setCertificate(certificateBytes).build();
|
||||||
|
|
||||||
return response.toByteArray();
|
saveAttestationCertificate(derEncodedAttestationCertificate, endorsementCredential,
|
||||||
|
platformCredentials, device);
|
||||||
|
|
||||||
|
return response.toByteArray();
|
||||||
|
} else {
|
||||||
|
LOG.error("Supply chain validation did not succeed. "
|
||||||
|
+ "Firmware Quote Validation failed. Result is: "
|
||||||
|
+ validationResult);
|
||||||
|
return new byte[]{};
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error("Could not process credential request. Invalid nonce provided: "
|
LOG.error("Could not process credential request. Invalid nonce provided: "
|
||||||
+ request.getNonce().toString());
|
+ request.getNonce().toString());
|
||||||
@ -579,7 +604,8 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
* quote and the signature hash.
|
* quote and the signature hash.
|
||||||
* @param tpmQuote contains hash values for the quote and the signature
|
* @param tpmQuote contains hash values for the quote and the signature
|
||||||
*/
|
*/
|
||||||
private void parseTPMQuote(final String tpmQuote) {
|
private boolean parseTPMQuote(final String tpmQuote) {
|
||||||
|
boolean success = false;
|
||||||
if (tpmQuote != null) {
|
if (tpmQuote != null) {
|
||||||
String[] lines = tpmQuote.split(":");
|
String[] lines = tpmQuote.split(":");
|
||||||
if (lines[1].contains("signature")) {
|
if (lines[1].contains("signature")) {
|
||||||
@ -587,8 +613,11 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
} else {
|
} else {
|
||||||
this.tpmQuoteHash = lines[1].trim();
|
this.tpmQuoteHash = lines[1].trim();
|
||||||
}
|
}
|
||||||
this.tpmSignatureHash = lines[2].trim();
|
this.tpmQuoteSignature = lines[2].trim();
|
||||||
|
success = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -689,9 +718,24 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
hwProto.getProductVersion(), hwProto.getSystemSerialNumber(),
|
hwProto.getProductVersion(), hwProto.getSystemSerialNumber(),
|
||||||
firstChassisSerialNumber, firstBaseboardSerialNumber);
|
firstChassisSerialNumber, firstBaseboardSerialNumber);
|
||||||
|
|
||||||
|
if (dv.getPcrslist() != null && !dv.getPcrslist().isEmpty()) {
|
||||||
|
this.pcrValues = dv.getPcrslist().toStringUtf8();
|
||||||
|
}
|
||||||
|
|
||||||
// Get TPM info, currently unimplemented
|
// Get TPM info, currently unimplemented
|
||||||
TPMInfo tpm = new TPMInfo();
|
TPMInfo tpm = new TPMInfo();
|
||||||
|
try {
|
||||||
|
tpm = new TPMInfo(DeviceInfoReport.NOT_SPECIFIED,
|
||||||
|
(short) 0,
|
||||||
|
(short) 0,
|
||||||
|
(short) 0,
|
||||||
|
(short) 0,
|
||||||
|
this.pcrValues.getBytes("UTF-8"),
|
||||||
|
this.tpmQuoteHash.getBytes("UTF-8"),
|
||||||
|
this.tpmQuoteSignature.getBytes("UTF-8"));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
tpm = new TPMInfo();
|
||||||
|
}
|
||||||
|
|
||||||
// Create final report
|
// Create final report
|
||||||
DeviceInfoReport dvReport = new DeviceInfoReport(nw, os, fw, hw, tpm,
|
DeviceInfoReport dvReport = new DeviceInfoReport(nw, os, fw, hw, tpm,
|
||||||
@ -1511,29 +1555,4 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
+ e.getMessage(), e);
|
+ e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String savePcrValues(final String pcrValues, final String deviceName) {
|
|
||||||
if (pcrValues != null && !pcrValues.isEmpty()) {
|
|
||||||
try {
|
|
||||||
if (Files.notExists(Paths.get(PCR_UPLOAD_FOLDER))) {
|
|
||||||
Files.createDirectory(Paths.get(PCR_UPLOAD_FOLDER));
|
|
||||||
}
|
|
||||||
Path pcrPath = Paths.get(String.format("%s/%s",
|
|
||||||
PCR_UPLOAD_FOLDER, deviceName));
|
|
||||||
if (Files.notExists(pcrPath)) {
|
|
||||||
Files.createFile(pcrPath);
|
|
||||||
}
|
|
||||||
Files.write(pcrPath, pcrValues.getBytes("UTF8"));
|
|
||||||
return pcrPath.toString();
|
|
||||||
} catch (NoSuchFileException nsfEx) {
|
|
||||||
LOG.error(String.format("File Not found!: %s",
|
|
||||||
deviceName));
|
|
||||||
LOG.error(nsfEx);
|
|
||||||
} catch (IOException ioEx) {
|
|
||||||
LOG.error(ioEx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "empty";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,9 @@ public interface SupplyChainValidationService {
|
|||||||
* A supplemental method that handles validating just the quote post main validation.
|
* A supplemental method that handles validating just the quote post main validation.
|
||||||
*
|
*
|
||||||
* @param device the associated device.
|
* @param device the associated device.
|
||||||
|
* @param summary the associated device summary
|
||||||
* @return True if validation is successful, false otherwise.
|
* @return True if validation is successful, false otherwise.
|
||||||
*/
|
*/
|
||||||
SupplyChainValidationSummary validateQuote(Device device);
|
SupplyChainValidationSummary validateQuote(Device device,
|
||||||
|
SupplyChainValidationSummary summary);
|
||||||
}
|
}
|
||||||
|
@ -257,79 +257,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
|||||||
return summary;
|
return summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A supplemental method that handles validating just the quote post main validation.
|
|
||||||
*
|
|
||||||
* @param device the associated device.
|
|
||||||
* @return True if validation is successful, false otherwise.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public SupplyChainValidationSummary validateQuote(final Device device) {
|
|
||||||
final Appraiser supplyChainAppraiser = appraiserManager.getAppraiser(
|
|
||||||
SupplyChainAppraiser.NAME);
|
|
||||||
SupplyChainPolicy policy = (SupplyChainPolicy) policyManager.getDefaultPolicy(
|
|
||||||
supplyChainAppraiser);
|
|
||||||
SupplyChainValidation quoteScv = null;
|
|
||||||
SupplyChainValidationSummary summary = supplyChainValidatorSummaryManager
|
|
||||||
.get(device.getId());
|
|
||||||
Level level = Level.ERROR;
|
|
||||||
AppraisalStatus fwStatus = new AppraisalStatus(FAIL,
|
|
||||||
SupplyChainCredentialValidator.FIRMWARE_VALID);
|
|
||||||
|
|
||||||
// If the device already failed, then ignore
|
|
||||||
if (summary.getOverallValidationResult() == PASS) {
|
|
||||||
// check if the policy is enabled
|
|
||||||
if (policy.isFirmwareValidationEnabled()) {
|
|
||||||
String[] baseline = new String[Integer.SIZE];
|
|
||||||
String manufacturer = device.getDeviceInfo()
|
|
||||||
.getHardwareInfo().getManufacturer();
|
|
||||||
|
|
||||||
// need to get pcrs
|
|
||||||
ReferenceManifest rim = ReferenceManifest.select(
|
|
||||||
this.referenceManifestManager)
|
|
||||||
.byManufacturer(manufacturer)
|
|
||||||
.getRIM();
|
|
||||||
|
|
||||||
if (rim == null) {
|
|
||||||
fwStatus = new AppraisalStatus(FAIL,
|
|
||||||
String.format("Firmware Quote validation failed: "
|
|
||||||
+ "No associated RIM file could be found for %s",
|
|
||||||
manufacturer));
|
|
||||||
} else {
|
|
||||||
List<SwidResource> swids = rim.parseResource();
|
|
||||||
for (SwidResource swid : swids) {
|
|
||||||
baseline = swid.getPcrValues()
|
|
||||||
.toArray(new String[swid.getPcrValues().size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
PCRPolicy pcrPolicy = policy.getPcrPolicy();
|
|
||||||
|
|
||||||
pcrPolicy.setBaselinePcrs(baseline);
|
|
||||||
// grab the quote
|
|
||||||
// byte[] hash = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash();
|
|
||||||
// byte[] signature = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash();
|
|
||||||
//
|
|
||||||
// if (!pcrPolicy.validateQuote(hash)) {
|
|
||||||
// quoteScv = buildValidationRecord(SupplyChainValidation
|
|
||||||
// .ValidationType.FIRMWARE,
|
|
||||||
// fwStatus.getAppStatus(),
|
|
||||||
// "Firmware validation of TPM Quote failed.", rim, level);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate validation summary, save it, and return it.
|
|
||||||
summary.getValidations().add(quoteScv); //verify
|
|
||||||
try {
|
|
||||||
supplyChainValidatorSummaryManager.save(summary);
|
|
||||||
} catch (DBManagerException ex) {
|
|
||||||
LOGGER.error("Failed to save Supply Chain summary", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return summary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is a sub set of the validate supply chain method and focuses
|
* This method is a sub set of the validate supply chain method and focuses
|
||||||
* on the specific multibase validation check for a delta chain. This method
|
* on the specific multibase validation check for a delta chain. This method
|
||||||
@ -422,9 +349,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
|||||||
} catch (NullPointerException npEx) {
|
} catch (NullPointerException npEx) {
|
||||||
LOGGER.error(npEx);
|
LOGGER.error(npEx);
|
||||||
}
|
}
|
||||||
String[] pcrSet = null;
|
|
||||||
String[] storedPcrs = null;
|
|
||||||
int algorithmLength = baseline[0].length();
|
|
||||||
|
|
||||||
if (pcrContent.isEmpty()) {
|
if (pcrContent.isEmpty()) {
|
||||||
fwStatus = new AppraisalStatus(FAIL,
|
fwStatus = new AppraisalStatus(FAIL,
|
||||||
@ -435,26 +359,8 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
|||||||
+ "provide pcr values.", device.getName()));
|
+ "provide pcr values.", device.getName()));
|
||||||
} else {
|
} else {
|
||||||
// we have a full set of PCR values
|
// we have a full set of PCR values
|
||||||
pcrSet = pcrContent.split("\\n");
|
int algorithmLength = baseline[0].length();
|
||||||
storedPcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1];
|
String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength);
|
||||||
|
|
||||||
// we need to scroll through the entire list until we find
|
|
||||||
// a matching hash length
|
|
||||||
int offset = 1;
|
|
||||||
|
|
||||||
for (int i = 0; i < pcrSet.length; i++) {
|
|
||||||
if (pcrSet[i].contains("sha")) {
|
|
||||||
// entered a new set, check size
|
|
||||||
if (pcrSet[i + offset].split(":")[1].trim().length()
|
|
||||||
== algorithmLength) {
|
|
||||||
// found the matching set
|
|
||||||
for (int j = 0; j <= TPMMeasurementRecord.MAX_PCR_ID; j++) {
|
|
||||||
storedPcrs[j] = pcrSet[++i].split(":")[1].trim();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (storedPcrs[0].isEmpty()) {
|
if (storedPcrs[0].isEmpty()) {
|
||||||
// validation fail
|
// validation fail
|
||||||
@ -483,6 +389,81 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
|||||||
fwStatus.getAppStatus(), fwStatus.getMessage(), rim, level);
|
fwStatus.getAppStatus(), fwStatus.getMessage(), rim, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A supplemental method that handles validating just the quote post main validation.
|
||||||
|
*
|
||||||
|
* @param device the associated device.
|
||||||
|
* @param summary the associated device summary
|
||||||
|
* @return True if validation is successful, false otherwise.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SupplyChainValidationSummary validateQuote(final Device device,
|
||||||
|
final SupplyChainValidationSummary summary) {
|
||||||
|
final Appraiser supplyChainAppraiser = appraiserManager.getAppraiser(
|
||||||
|
SupplyChainAppraiser.NAME);
|
||||||
|
SupplyChainPolicy policy = (SupplyChainPolicy) policyManager.getDefaultPolicy(
|
||||||
|
supplyChainAppraiser);
|
||||||
|
SupplyChainValidation quoteScv = null;
|
||||||
|
SupplyChainValidationSummary newSummary = null;
|
||||||
|
Level level = Level.ERROR;
|
||||||
|
AppraisalStatus fwStatus = new AppraisalStatus(FAIL,
|
||||||
|
SupplyChainCredentialValidator.FIRMWARE_VALID);
|
||||||
|
|
||||||
|
// check if the policy is enabled
|
||||||
|
if (policy.isFirmwareValidationEnabled()) {
|
||||||
|
String[] baseline = new String[Integer.SIZE];
|
||||||
|
String manufacturer = device.getDeviceInfo()
|
||||||
|
.getHardwareInfo().getManufacturer();
|
||||||
|
|
||||||
|
// need to get pcrs
|
||||||
|
ReferenceManifest rim = ReferenceManifest.select(
|
||||||
|
this.referenceManifestManager)
|
||||||
|
.byManufacturer(manufacturer)
|
||||||
|
.getRIM();
|
||||||
|
if (rim == null) {
|
||||||
|
fwStatus = new AppraisalStatus(FAIL,
|
||||||
|
String.format("Firmware Quote validation failed: "
|
||||||
|
+ "No associated RIM file could be found for %s",
|
||||||
|
manufacturer));
|
||||||
|
} else {
|
||||||
|
List<SwidResource> swids = rim.parseResource();
|
||||||
|
for (SwidResource swid : swids) {
|
||||||
|
baseline = swid.getPcrValues()
|
||||||
|
.toArray(new String[swid.getPcrValues().size()]);
|
||||||
|
}
|
||||||
|
int algorithmLength = baseline[0].length();
|
||||||
|
String pcrContent = new String(device.getDeviceInfo().getTPMInfo().getPcrValues());
|
||||||
|
String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength);
|
||||||
|
PCRPolicy pcrPolicy = policy.getPcrPolicy();
|
||||||
|
pcrPolicy.setBaselinePcrs(baseline);
|
||||||
|
// grab the quote
|
||||||
|
byte[] hash = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash();
|
||||||
|
byte[] signature = device.getDeviceInfo().getTPMInfo().getTpmQuoteHash();
|
||||||
|
if (!pcrPolicy.validateQuote(hash, storedPcrs)) {
|
||||||
|
quoteScv = buildValidationRecord(SupplyChainValidation
|
||||||
|
.ValidationType.FIRMWARE,
|
||||||
|
fwStatus.getAppStatus(),
|
||||||
|
"Firmware validation of TPM Quote failed.", rim, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate validation summary, save it, and return it.
|
||||||
|
|
||||||
|
List<SupplyChainValidation> validations = new ArrayList<>();
|
||||||
|
validations.addAll(summary.getValidations());
|
||||||
|
validations.add(quoteScv);
|
||||||
|
newSummary = new SupplyChainValidationSummary(device, validations);
|
||||||
|
|
||||||
|
try {
|
||||||
|
supplyChainValidatorSummaryManager.update(newSummary);
|
||||||
|
} catch (DBManagerException ex) {
|
||||||
|
LOGGER.error("Failed to save Supply Chain summary", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newSummary;
|
||||||
|
}
|
||||||
|
|
||||||
private SupplyChainValidation validateEndorsementCredential(final EndorsementCredential ec,
|
private SupplyChainValidation validateEndorsementCredential(final EndorsementCredential ec,
|
||||||
final boolean acceptExpiredCerts) {
|
final boolean acceptExpiredCerts) {
|
||||||
final SupplyChainValidation.ValidationType validationType
|
final SupplyChainValidation.ValidationType validationType
|
||||||
@ -617,7 +598,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
|||||||
final SupplyChainValidation.ValidationType validationType,
|
final SupplyChainValidation.ValidationType validationType,
|
||||||
final AppraisalStatus.Status result, final String message,
|
final AppraisalStatus.Status result, final String message,
|
||||||
final ArchivableEntity archivableEntity, final Level logLevel) {
|
final ArchivableEntity archivableEntity, final Level logLevel) {
|
||||||
|
|
||||||
List<ArchivableEntity> aeList = new ArrayList<>();
|
List<ArchivableEntity> aeList = new ArrayList<>();
|
||||||
if (archivableEntity != null) {
|
if (archivableEntity != null) {
|
||||||
aeList.add(archivableEntity);
|
aeList.add(archivableEntity);
|
||||||
@ -735,4 +715,30 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
|||||||
|
|
||||||
return multiple;
|
return multiple;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String[] buildStoredPcrs(final String pcrContent, final int algorithmLength) {
|
||||||
|
// we have a full set of PCR values
|
||||||
|
String[] pcrSet = pcrContent.split("\\n");
|
||||||
|
String[] storedPcrs = new String[TPMMeasurementRecord.MAX_PCR_ID + 1];
|
||||||
|
|
||||||
|
// we need to scroll through the entire list until we find
|
||||||
|
// a matching hash length
|
||||||
|
int offset = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < pcrSet.length; i++) {
|
||||||
|
if (pcrSet[i].contains("sha")) {
|
||||||
|
// entered a new set, check size
|
||||||
|
if (pcrSet[i + offset].split(":")[1].trim().length()
|
||||||
|
== algorithmLength) {
|
||||||
|
// found the matching set
|
||||||
|
for (int j = 0; j <= TPMMeasurementRecord.MAX_PCR_ID; j++) {
|
||||||
|
storedPcrs[j] = pcrSet[++i].split(":")[1].trim();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return storedPcrs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,19 @@ package hirs.data.persist;
|
|||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||||
|
|
||||||
import hirs.data.persist.tpm.PcrComposite;
|
import hirs.data.persist.tpm.PcrComposite;
|
||||||
import hirs.data.persist.tpm.PcrInfoShort;
|
import hirs.data.persist.tpm.PcrInfoShort;
|
||||||
import hirs.data.persist.tpm.PcrSelection;
|
import hirs.data.persist.tpm.PcrSelection;
|
||||||
|
import org.apache.commons.codec.DecoderException;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class handles the flags that ignore certain PCRs for validation.
|
* The class handles the flags that ignore certain PCRs for validation.
|
||||||
@ -90,13 +93,22 @@ public final class PCRPolicy extends Policy {
|
|||||||
* Compares hashs to validate the quote from the client.
|
* Compares hashs to validate the quote from the client.
|
||||||
*
|
*
|
||||||
* @param tpmQuote the provided quote
|
* @param tpmQuote the provided quote
|
||||||
|
* @param storedPcrs values from the RIM file
|
||||||
* @return true if validated, false if not
|
* @return true if validated, false if not
|
||||||
*/
|
*/
|
||||||
public boolean validateQuote(final byte[] tpmQuote) {
|
public boolean validateQuote(final byte[] tpmQuote, final String[] storedPcrs) {
|
||||||
|
LOGGER.info("Validating quote from associated device.");
|
||||||
boolean validated = false;
|
boolean validated = false;
|
||||||
short localityAtRelease = 0;
|
short localityAtRelease = 0;
|
||||||
|
|
||||||
TPMMeasurementRecord[] measurements = new TPMMeasurementRecord[baselinePcrs.length];
|
TPMMeasurementRecord[] measurements = new TPMMeasurementRecord[baselinePcrs.length];
|
||||||
|
try {
|
||||||
|
for (int i = 0; i <= TPMMeasurementRecord.MAX_PCR_ID; i++) {
|
||||||
|
measurements[i] = new TPMMeasurementRecord(i, storedPcrs[i]);
|
||||||
|
}
|
||||||
|
} catch (DecoderException deEx) {
|
||||||
|
LOGGER.error(deEx);
|
||||||
|
}
|
||||||
PcrSelection pcrSelection = new PcrSelection(PcrSelection.ALL_PCRS_ON);
|
PcrSelection pcrSelection = new PcrSelection(PcrSelection.ALL_PCRS_ON);
|
||||||
PcrComposite pcrComposite = new PcrComposite(
|
PcrComposite pcrComposite = new PcrComposite(
|
||||||
pcrSelection,
|
pcrSelection,
|
||||||
@ -106,20 +118,25 @@ public final class PCRPolicy extends Policy {
|
|||||||
tpmQuote, pcrComposite);
|
tpmQuote, pcrComposite);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!Arrays.equals(pcrInfoShort.getCalculatedDigest(),
|
validated = Arrays.equals(pcrInfoShort.getCalculatedDigest(),
|
||||||
pcrInfoShort.getCompositeHash())) {
|
pcrInfoShort.getCompositeHash());
|
||||||
LOGGER.error("This is NOT matching: ");
|
if (validated) {
|
||||||
LOGGER.error(new String(pcrInfoShort.getCalculatedDigest(), "UTF-8"));
|
LOGGER.error("This is matching: ");
|
||||||
|
String value = Base64.getEncoder().encodeToString(pcrInfoShort
|
||||||
|
.getCalculatedDigest());
|
||||||
|
LOGGER.error(value);
|
||||||
LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8"));
|
LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8"));
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error("This is matching: ");
|
LOGGER.error("This is NOT matching: ");
|
||||||
LOGGER.error(new String(pcrInfoShort.getCalculatedDigest(), "UTF-8"));
|
String value = new String(pcrInfoShort
|
||||||
|
.getCalculatedDigest(), "UTF-8");
|
||||||
|
LOGGER.error(value);
|
||||||
LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8"));
|
LOGGER.error(new String(pcrInfoShort.getCompositeHash(), "UTF-8"));
|
||||||
}
|
}
|
||||||
} catch (NoSuchAlgorithmException naEx) {
|
} catch (NoSuchAlgorithmException naEx) {
|
||||||
LOGGER.error(naEx);
|
LOGGER.error(naEx);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException ueEx) {
|
||||||
e.printStackTrace();
|
LOGGER.error(ueEx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return validated;
|
return validated;
|
||||||
|
@ -270,6 +270,7 @@ public class PcrInfoShort {
|
|||||||
|
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
TPMMeasurementRecord record = (TPMMeasurementRecord) iter.next();
|
TPMMeasurementRecord record = (TPMMeasurementRecord) iter.next();
|
||||||
|
LOGGER.error(record.getHash());
|
||||||
byteBuffer.put(record.getHash().getDigest());
|
byteBuffer.put(record.getHash().getDigest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user