mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-02-20 17:52:47 +00:00
Merge pull request #289 from nsacyber/aca-test-validation
[#282] ACA Firmware Validation 500 External error resolution
This commit is contained in:
commit
3353ec5f47
@ -66,6 +66,10 @@ import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
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.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
@ -103,6 +107,11 @@ public abstract class AbstractAttestationCertificateAuthority
|
||||
*/
|
||||
private static final BigInteger EXPONENT = new BigInteger("010001",
|
||||
AttestationCertificateAuthority.DEFAULT_IV_SIZE);
|
||||
private static final String CATALINA_HOME = System.getProperty("catalina.base");
|
||||
private static final String TOMCAT_UPLOAD_DIRECTORY
|
||||
= "/webapps/HIRS_AttestationCA/upload/";
|
||||
private static final String PCR_UPLOAD_FOLDER
|
||||
= CATALINA_HOME + TOMCAT_UPLOAD_DIRECTORY;
|
||||
|
||||
/**
|
||||
* Number of bytes to include in the TPM2.0 nonce.
|
||||
@ -1468,7 +1477,7 @@ public abstract class AbstractAttestationCertificateAuthority
|
||||
IssuedAttestationCertificate attCert = new IssuedAttestationCertificate(
|
||||
derEncodedAttestationCertificate, endorsementCredential, platformCredentials);
|
||||
attCert.setDevice(device);
|
||||
attCert.setPcrValues(pcrValues);
|
||||
attCert.setPcrValues(savePcrValues(pcrValues, device.getName()));
|
||||
certificateManager.save(attCert);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error saving generated Attestation Certificate to database.", e);
|
||||
@ -1477,4 +1486,29 @@ public abstract class AbstractAttestationCertificateAuthority
|
||||
+ 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";
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package hirs.attestationca.service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@ -330,6 +333,8 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
.byManufacturer(manufacturer)
|
||||
.getRIM();
|
||||
|
||||
fwStatus = new AppraisalStatus(PASS,
|
||||
SupplyChainCredentialValidator.FIRMWARE_VALID);
|
||||
if (rim == null) {
|
||||
fwStatus = new AppraisalStatus(FAIL,
|
||||
String.format("Firmware validation failed: "
|
||||
@ -344,43 +349,67 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
pcrPolicy.setBaselinePcrs(baseline);
|
||||
|
||||
if (attCert != null) {
|
||||
String[] pcrsSet = attCert.getPcrValues().split("\\+");
|
||||
String[] pcrs1 = pcrsSet[0].split("\\n");
|
||||
String[] pcrs256 = pcrsSet[1].split("\\n");
|
||||
String[] quote = new String[TPMMeasurementRecord.MAX_PCR_ID + 1];
|
||||
int offset = 0;
|
||||
|
||||
fwStatus = new AppraisalStatus(PASS,
|
||||
SupplyChainCredentialValidator.FIRMWARE_VALID);
|
||||
|
||||
if (baseline[0].length() == TPMMeasurementRecord.SHA_BYTE_LENGTH) {
|
||||
// quote from provisioner is formated to indicate the encryption
|
||||
if (pcrs1[0].split(":")[0].contains("sha")) {
|
||||
offset = 1;
|
||||
}
|
||||
for (int i = 0; i <= TPMMeasurementRecord.MAX_PCR_ID; i++) {
|
||||
//update quote with the pcr only, based on offset
|
||||
quote[i] = pcrs1[i + offset].split(":")[1].trim();
|
||||
}
|
||||
} else if (baseline[0].length() == TPMMeasurementRecord.SHA_256_BYTE_LENGTH) {
|
||||
// quote from provisioner is formated to indicate the encryption
|
||||
if (pcrs256[0].split(":")[0].contains("sha")) {
|
||||
offset = 1;
|
||||
}
|
||||
for (int i = 0; i <= TPMMeasurementRecord.MAX_PCR_ID; i++) {
|
||||
//update quote with the pcr only, based on offset
|
||||
quote[i] = pcrs256[i + offset].split(":")[1].trim();
|
||||
Path pcrPath = Paths.get(attCert.getPcrValues());
|
||||
String pcrContent = "";
|
||||
if (Files.exists(pcrPath)) {
|
||||
try {
|
||||
pcrContent = new String(Files.readAllBytes(pcrPath), "UTF8");
|
||||
} catch (IOException ioEx) {
|
||||
LOGGER.error(ioEx);
|
||||
}
|
||||
}
|
||||
String[] pcrSet = null;
|
||||
String[] quote = null;
|
||||
int algorithmLength = baseline[0].length();
|
||||
|
||||
StringBuilder sb = pcrPolicy.validatePcrs(quote);
|
||||
if (sb.length() > 0) {
|
||||
level = Level.ERROR;
|
||||
fwStatus = new AppraisalStatus(FAIL, sb.toString());
|
||||
if (pcrContent.isEmpty()) {
|
||||
fwStatus = new AppraisalStatus(FAIL,
|
||||
"Firmware validation failed: Client did not "
|
||||
+ "provide pcr values.");
|
||||
LOGGER.warn(String.format(
|
||||
"Firmware validation failed: Client (%s) did not "
|
||||
+ "provide pcr values.", attCert.getDevice().getName()));
|
||||
} else {
|
||||
level = Level.INFO;
|
||||
// we have a full set of PCR values
|
||||
pcrSet = pcrContent.split("\\n");
|
||||
quote = 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++) {
|
||||
quote[j] = pcrSet[++i].split(":")[1].trim();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (quote[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(quote);
|
||||
if (sb.length() > 0) {
|
||||
level = Level.ERROR;
|
||||
fwStatus = new AppraisalStatus(FAIL, sb.toString());
|
||||
} else {
|
||||
level = Level.INFO;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (fwStatus != null) {
|
||||
} else {
|
||||
fwStatus = new AppraisalStatus(FAIL, "Associated Issued Attestation"
|
||||
+ " Certificate can not be found.");
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ public class IssuedCertificatesPageControllerTest extends PageControllerTest {
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Tests downloading the certificate.
|
||||
* @throws java.lang.Exception when getting raw report
|
||||
*/
|
||||
|
@ -61,7 +61,6 @@ class CommandTpm2 {
|
||||
static const char* const kTpm2ToolsGetQuoteCommand;
|
||||
static const char* const kTpm2DefaultQuoteFilename;
|
||||
static const char* const kTpm2DefaultSigFilename;
|
||||
static const char* const kTpm2Sha1SigAlgorithm;
|
||||
static const char* const kTpm2Sha256SigAlgorithm;
|
||||
static const char* const kTpm2ToolsPcrListCommand;
|
||||
|
||||
@ -139,7 +138,6 @@ class CommandTpm2 {
|
||||
const std::string& nonce);
|
||||
|
||||
std::string getPcrsList();
|
||||
std::string getPcrs256List();
|
||||
};
|
||||
|
||||
} // namespace tpm2
|
||||
|
@ -123,7 +123,6 @@ const char* const CommandTpm2::kDefaultActivatedIdentityFilename
|
||||
= "activatedIdentity.secret";
|
||||
const char* const CommandTpm2::kTpm2DefaultQuoteFilename = "/tmp/quote.bin";
|
||||
const char* const CommandTpm2::kTpm2DefaultSigFilename = "/tmp/sig.bin";
|
||||
const char* const CommandTpm2::kTpm2Sha1SigAlgorithm = "sha1";
|
||||
const char* const CommandTpm2::kTpm2Sha256SigAlgorithm = "sha256";
|
||||
|
||||
/**
|
||||
@ -563,33 +562,13 @@ string CommandTpm2::getPcrsList() {
|
||||
string pcrslist;
|
||||
stringstream argsStream;
|
||||
|
||||
argsStream << " -g " << kTpm2Sha1SigAlgorithm
|
||||
<< endl;
|
||||
argsStream << endl;
|
||||
|
||||
LOGGER.info("Running tpm2_pcrlist with arguments: " + argsStream.str());
|
||||
pcrslist = runTpm2CommandWithRetry(kTpm2ToolsPcrListCommand,
|
||||
argsStream.str(),
|
||||
__LINE__);
|
||||
LOGGER.info("TPM PCRS List successful");
|
||||
|
||||
return pcrslist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the full list of pcrs from the TPM as SHA256. *
|
||||
*/
|
||||
string CommandTpm2::getPcrs256List() {
|
||||
string pcrslist;
|
||||
stringstream argsStream;
|
||||
|
||||
argsStream << " -g " << kTpm2Sha256SigAlgorithm
|
||||
<< endl;
|
||||
|
||||
LOGGER.info("Running tpm2_pcrlist with arguments: " + argsStream.str());
|
||||
pcrslist = runTpm2CommandWithRetry(kTpm2ToolsPcrListCommand,
|
||||
argsStream.str(),
|
||||
__LINE__);
|
||||
LOGGER.info("TPM PCRS (SHA 256) List successful");
|
||||
LOGGER.info("TPM PCR List successful");
|
||||
|
||||
return pcrslist;
|
||||
}
|
||||
|
@ -106,9 +106,7 @@ int provision() {
|
||||
"14,15,16,17,18,19,20,21,22,23",
|
||||
decryptedNonce));
|
||||
|
||||
stringstream pcrStream;
|
||||
pcrStream << tpm2.getPcrsList() << "\n+\n" << tpm2.getPcrs256List();
|
||||
certificateRequest.set_pcrslist(pcrStream.str());
|
||||
certificateRequest.set_pcrslist(tpm2.getPcrsList());
|
||||
const string& akCertificateByteString
|
||||
= provisioner.sendAttestationCertificateRequest(certificateRequest);
|
||||
|
||||
|
@ -21,7 +21,7 @@ import javax.persistence.ManyToOne;
|
||||
@Entity
|
||||
public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
|
||||
|
||||
private static final int MAX_CERT_LENGTH_BYTES = 4096;
|
||||
private static final int MAX_CERT_LENGTH_BYTES = 1024;
|
||||
|
||||
/**
|
||||
* AIC label that must be used.
|
||||
|
Loading…
x
Reference in New Issue
Block a user