mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-02-21 18:06:42 +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.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;
|
||||||
@ -103,6 +107,11 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
*/
|
*/
|
||||||
private static final BigInteger EXPONENT = new BigInteger("010001",
|
private static final BigInteger EXPONENT = new BigInteger("010001",
|
||||||
AttestationCertificateAuthority.DEFAULT_IV_SIZE);
|
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.
|
* Number of bytes to include in the TPM2.0 nonce.
|
||||||
@ -1468,7 +1477,7 @@ public abstract class AbstractAttestationCertificateAuthority
|
|||||||
IssuedAttestationCertificate attCert = new IssuedAttestationCertificate(
|
IssuedAttestationCertificate attCert = new IssuedAttestationCertificate(
|
||||||
derEncodedAttestationCertificate, endorsementCredential, platformCredentials);
|
derEncodedAttestationCertificate, endorsementCredential, platformCredentials);
|
||||||
attCert.setDevice(device);
|
attCert.setDevice(device);
|
||||||
attCert.setPcrValues(pcrValues);
|
attCert.setPcrValues(savePcrValues(pcrValues, device.getName()));
|
||||||
certificateManager.save(attCert);
|
certificateManager.save(attCert);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error saving generated Attestation Certificate to database.", e);
|
LOG.error("Error saving generated Attestation Certificate to database.", e);
|
||||||
@ -1477,4 +1486,29 @@ 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";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package hirs.attestationca.service;
|
package hirs.attestationca.service;
|
||||||
|
|
||||||
import java.io.IOException;
|
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.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
@ -330,6 +333,8 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
|||||||
.byManufacturer(manufacturer)
|
.byManufacturer(manufacturer)
|
||||||
.getRIM();
|
.getRIM();
|
||||||
|
|
||||||
|
fwStatus = new AppraisalStatus(PASS,
|
||||||
|
SupplyChainCredentialValidator.FIRMWARE_VALID);
|
||||||
if (rim == null) {
|
if (rim == null) {
|
||||||
fwStatus = new AppraisalStatus(FAIL,
|
fwStatus = new AppraisalStatus(FAIL,
|
||||||
String.format("Firmware validation failed: "
|
String.format("Firmware validation failed: "
|
||||||
@ -344,43 +349,67 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
|||||||
pcrPolicy.setBaselinePcrs(baseline);
|
pcrPolicy.setBaselinePcrs(baseline);
|
||||||
|
|
||||||
if (attCert != null) {
|
if (attCert != null) {
|
||||||
String[] pcrsSet = attCert.getPcrValues().split("\\+");
|
Path pcrPath = Paths.get(attCert.getPcrValues());
|
||||||
String[] pcrs1 = pcrsSet[0].split("\\n");
|
String pcrContent = "";
|
||||||
String[] pcrs256 = pcrsSet[1].split("\\n");
|
if (Files.exists(pcrPath)) {
|
||||||
String[] quote = new String[TPMMeasurementRecord.MAX_PCR_ID + 1];
|
try {
|
||||||
int offset = 0;
|
pcrContent = new String(Files.readAllBytes(pcrPath), "UTF8");
|
||||||
|
} catch (IOException ioEx) {
|
||||||
fwStatus = new AppraisalStatus(PASS,
|
LOGGER.error(ioEx);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
String[] pcrSet = null;
|
||||||
|
String[] quote = null;
|
||||||
|
int algorithmLength = baseline[0].length();
|
||||||
|
|
||||||
StringBuilder sb = pcrPolicy.validatePcrs(quote);
|
if (pcrContent.isEmpty()) {
|
||||||
if (sb.length() > 0) {
|
fwStatus = new AppraisalStatus(FAIL,
|
||||||
level = Level.ERROR;
|
"Firmware validation failed: Client did not "
|
||||||
fwStatus = new AppraisalStatus(FAIL, sb.toString());
|
+ "provide pcr values.");
|
||||||
|
LOGGER.warn(String.format(
|
||||||
|
"Firmware validation failed: Client (%s) did not "
|
||||||
|
+ "provide pcr values.", attCert.getDevice().getName()));
|
||||||
} else {
|
} 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"
|
fwStatus = new AppraisalStatus(FAIL, "Associated Issued Attestation"
|
||||||
+ " Certificate can not be found.");
|
+ " Certificate can not be found.");
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ public class IssuedCertificatesPageControllerTest extends PageControllerTest {
|
|||||||
.andReturn();
|
.andReturn();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests downloading the certificate.
|
* Tests downloading the certificate.
|
||||||
* @throws java.lang.Exception when getting raw report
|
* @throws java.lang.Exception when getting raw report
|
||||||
*/
|
*/
|
||||||
|
@ -61,7 +61,6 @@ class CommandTpm2 {
|
|||||||
static const char* const kTpm2ToolsGetQuoteCommand;
|
static const char* const kTpm2ToolsGetQuoteCommand;
|
||||||
static const char* const kTpm2DefaultQuoteFilename;
|
static const char* const kTpm2DefaultQuoteFilename;
|
||||||
static const char* const kTpm2DefaultSigFilename;
|
static const char* const kTpm2DefaultSigFilename;
|
||||||
static const char* const kTpm2Sha1SigAlgorithm;
|
|
||||||
static const char* const kTpm2Sha256SigAlgorithm;
|
static const char* const kTpm2Sha256SigAlgorithm;
|
||||||
static const char* const kTpm2ToolsPcrListCommand;
|
static const char* const kTpm2ToolsPcrListCommand;
|
||||||
|
|
||||||
@ -139,7 +138,6 @@ class CommandTpm2 {
|
|||||||
const std::string& nonce);
|
const std::string& nonce);
|
||||||
|
|
||||||
std::string getPcrsList();
|
std::string getPcrsList();
|
||||||
std::string getPcrs256List();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tpm2
|
} // namespace tpm2
|
||||||
|
@ -123,7 +123,6 @@ const char* const CommandTpm2::kDefaultActivatedIdentityFilename
|
|||||||
= "activatedIdentity.secret";
|
= "activatedIdentity.secret";
|
||||||
const char* const CommandTpm2::kTpm2DefaultQuoteFilename = "/tmp/quote.bin";
|
const char* const CommandTpm2::kTpm2DefaultQuoteFilename = "/tmp/quote.bin";
|
||||||
const char* const CommandTpm2::kTpm2DefaultSigFilename = "/tmp/sig.bin";
|
const char* const CommandTpm2::kTpm2DefaultSigFilename = "/tmp/sig.bin";
|
||||||
const char* const CommandTpm2::kTpm2Sha1SigAlgorithm = "sha1";
|
|
||||||
const char* const CommandTpm2::kTpm2Sha256SigAlgorithm = "sha256";
|
const char* const CommandTpm2::kTpm2Sha256SigAlgorithm = "sha256";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -563,33 +562,13 @@ string CommandTpm2::getPcrsList() {
|
|||||||
string pcrslist;
|
string pcrslist;
|
||||||
stringstream argsStream;
|
stringstream argsStream;
|
||||||
|
|
||||||
argsStream << " -g " << kTpm2Sha1SigAlgorithm
|
argsStream << endl;
|
||||||
<< endl;
|
|
||||||
|
|
||||||
LOGGER.info("Running tpm2_pcrlist with arguments: " + argsStream.str());
|
LOGGER.info("Running tpm2_pcrlist with arguments: " + argsStream.str());
|
||||||
pcrslist = runTpm2CommandWithRetry(kTpm2ToolsPcrListCommand,
|
pcrslist = runTpm2CommandWithRetry(kTpm2ToolsPcrListCommand,
|
||||||
argsStream.str(),
|
argsStream.str(),
|
||||||
__LINE__);
|
__LINE__);
|
||||||
LOGGER.info("TPM PCRS List successful");
|
LOGGER.info("TPM PCR 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");
|
|
||||||
|
|
||||||
return pcrslist;
|
return pcrslist;
|
||||||
}
|
}
|
||||||
|
@ -106,9 +106,7 @@ int provision() {
|
|||||||
"14,15,16,17,18,19,20,21,22,23",
|
"14,15,16,17,18,19,20,21,22,23",
|
||||||
decryptedNonce));
|
decryptedNonce));
|
||||||
|
|
||||||
stringstream pcrStream;
|
certificateRequest.set_pcrslist(tpm2.getPcrsList());
|
||||||
pcrStream << tpm2.getPcrsList() << "\n+\n" << tpm2.getPcrs256List();
|
|
||||||
certificateRequest.set_pcrslist(pcrStream.str());
|
|
||||||
const string& akCertificateByteString
|
const string& akCertificateByteString
|
||||||
= provisioner.sendAttestationCertificateRequest(certificateRequest);
|
= provisioner.sendAttestationCertificateRequest(certificateRequest);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import javax.persistence.ManyToOne;
|
|||||||
@Entity
|
@Entity
|
||||||
public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
|
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.
|
* AIC label that must be used.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user