Merge pull request #289 from nsacyber/aca-test-validation

[#282] ACA Firmware Validation 500 External error resolution
This commit is contained in:
Cyrus 2020-07-29 14:37:28 -04:00 committed by GitHub
commit 3353ec5f47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 101 additions and 63 deletions

View File

@ -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";
}
}

View File

@ -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.");
}

View File

@ -144,7 +144,7 @@ public class IssuedCertificatesPageControllerTest extends PageControllerTest {
.andReturn();
}
/**
/**
* Tests downloading the certificate.
* @throws java.lang.Exception when getting raw report
*/

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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.