mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-19 13:08:05 +00:00
Merge pull request #369 from nsacyber/issue-345
[#345] Add cert path validation to ACA
This commit is contained in:
commit
28ccbfe679
@ -38,6 +38,7 @@ import hirs.utils.ReferenceManifestValidator;
|
||||
import hirs.validation.CredentialValidator;
|
||||
import hirs.validation.SupplyChainCredentialValidator;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import hirs.validation.SupplyChainValidatorException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
@ -51,7 +52,9 @@ import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -89,6 +92,15 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
private static final Logger LOGGER
|
||||
= LogManager.getLogger(SupplyChainValidationServiceImpl.class);
|
||||
|
||||
/**
|
||||
* Constructor to set just the CertificateManager, so that cert chain validating
|
||||
* methods can be called from outside classes.
|
||||
* @param certificateManager the cert manager
|
||||
*/
|
||||
public SupplyChainValidationServiceImpl(final CertificateManager certificateManager) {
|
||||
this.certificateManager = certificateManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@ -415,6 +427,38 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
}
|
||||
}
|
||||
|
||||
//Validate signing cert
|
||||
Set<CertificateAuthorityCredential> allCerts =
|
||||
CertificateAuthorityCredential.select(certificateManager).getCertificates();
|
||||
CertificateAuthorityCredential signingCert = null;
|
||||
for (CertificateAuthorityCredential cert : allCerts) {
|
||||
if (Arrays.equals(cert.getEncodedPublicKey(),
|
||||
referenceManifestValidator.getPublicKey().getEncoded())) {
|
||||
signingCert = cert;
|
||||
KeyStore keyStore = getCaChain(signingCert);
|
||||
try {
|
||||
X509Certificate x509Cert = signingCert.getX509Certificate();
|
||||
if (!SupplyChainCredentialValidator.verifyCertificate(x509Cert, keyStore)) {
|
||||
passed = false;
|
||||
fwStatus = new AppraisalStatus(FAIL,
|
||||
"Firmware validation failed: invalid certificate path.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Error getting X509 cert from manager: " + e.getMessage());
|
||||
} catch (SupplyChainValidatorException e) {
|
||||
LOGGER.error("Error validating cert against keystore: " + e.getMessage());
|
||||
fwStatus = new AppraisalStatus(FAIL,
|
||||
"Firmware validation failed: invalid certificate path.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (signingCert == null) {
|
||||
passed = false;
|
||||
fwStatus = new AppraisalStatus(FAIL,
|
||||
"Firmware validation failed: signing cert not found.");
|
||||
}
|
||||
|
||||
if (!referenceManifestValidator.isSignatureValid()) {
|
||||
passed = false;
|
||||
fwStatus = new AppraisalStatus(FAIL,
|
||||
|
@ -4,6 +4,7 @@ import hirs.attestationca.portal.page.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.PageMessages;
|
||||
import hirs.attestationca.portal.page.params.ReferenceManifestDetailsPageParams;
|
||||
import hirs.attestationca.service.SupplyChainValidationServiceImpl;
|
||||
import hirs.data.persist.BaseReferenceManifest;
|
||||
import hirs.data.persist.EventLogMeasurements;
|
||||
import hirs.data.persist.ReferenceManifest;
|
||||
@ -16,6 +17,8 @@ import hirs.persist.ReferenceManifestManager;
|
||||
import hirs.tpm.eventlog.TCGEventLog;
|
||||
import hirs.tpm.eventlog.TpmPcrEvent;
|
||||
import hirs.utils.ReferenceManifestValidator;
|
||||
import hirs.validation.SupplyChainCredentialValidator;
|
||||
import hirs.validation.SupplyChainValidatorException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -26,8 +29,10 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
@ -277,12 +282,33 @@ public class ReferenceManifestDetailsPageController
|
||||
}
|
||||
|
||||
RIM_VALIDATOR.validateXmlSignature(new ByteArrayInputStream(baseRim.getRimBytes()));
|
||||
data.put("signatureValid", RIM_VALIDATOR.isSignatureValid());
|
||||
Set<CertificateAuthorityCredential> certificates =
|
||||
CertificateAuthorityCredential.select(certificateManager)
|
||||
.getCertificates();
|
||||
//Report invalid signature unless RIM_VALIDATOR validates it and cert path is valid
|
||||
data.put("signatureValid", false);
|
||||
if (RIM_VALIDATOR.isSignatureValid()) {
|
||||
for (CertificateAuthorityCredential cert : certificates) {
|
||||
if (Arrays.equals(cert.getEncodedPublicKey(),
|
||||
RIM_VALIDATOR.getPublicKey().getEncoded())) {
|
||||
SupplyChainValidationServiceImpl scvsImpl =
|
||||
new SupplyChainValidationServiceImpl(certificateManager);
|
||||
KeyStore keystore = scvsImpl.getCaChain(cert);
|
||||
X509Certificate signingCert = cert.getX509Certificate();
|
||||
try {
|
||||
if (SupplyChainCredentialValidator.verifyCertificate(signingCert,
|
||||
keystore)) {
|
||||
data.replace("signatureValid", true);
|
||||
}
|
||||
} catch (SupplyChainValidatorException e) {
|
||||
LOGGER.error("Error verifying cert chain: " + e.getMessage());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
data.put("skID", RIM_VALIDATOR.getSubjectKeyIdentifier());
|
||||
try {
|
||||
Set<CertificateAuthorityCredential> certificates =
|
||||
CertificateAuthorityCredential.select(certificateManager)
|
||||
.getCertificates();
|
||||
for (CertificateAuthorityCredential cert : certificates) {
|
||||
if (Arrays.equals(cert.getEncodedPublicKey(),
|
||||
RIM_VALIDATOR.getPublicKey().getEncoded())) {
|
||||
|
@ -1249,8 +1249,14 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
*/
|
||||
public static String verifyCertificate(final X509AttributeCertificateHolder cert,
|
||||
final KeyStore trustStore) throws SupplyChainValidatorException {
|
||||
if (cert == null || trustStore == null) {
|
||||
throw new SupplyChainValidatorException("Certificate or trust store is null");
|
||||
try {
|
||||
if (cert == null || trustStore == null) {
|
||||
throw new SupplyChainValidatorException("Certificate or trust store is null");
|
||||
} else if (trustStore.size() == 0) {
|
||||
throw new SupplyChainValidatorException("Truststore is empty");
|
||||
}
|
||||
} catch (KeyStoreException e) {
|
||||
LOGGER.error("Error accessing trust store: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
@ -1289,9 +1295,16 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
*/
|
||||
public static boolean verifyCertificate(final X509Certificate cert,
|
||||
final KeyStore trustStore) throws SupplyChainValidatorException {
|
||||
if (cert == null || trustStore == null) {
|
||||
throw new SupplyChainValidatorException("Certificate or trust store is null");
|
||||
try {
|
||||
if (cert == null || trustStore == null) {
|
||||
throw new SupplyChainValidatorException("Certificate or trust store is null");
|
||||
} else if (trustStore.size() == 0) {
|
||||
throw new SupplyChainValidatorException("Truststore is empty");
|
||||
}
|
||||
} catch (KeyStoreException e) {
|
||||
LOGGER.error("Error accessing trust store: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
Set<X509Certificate> trustedCerts = new HashSet<>();
|
||||
|
||||
@ -1320,7 +1333,8 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
* certificate to validate
|
||||
* @param additionalCerts
|
||||
* Set of certs to validate against
|
||||
* @return boolean indicating if the validation was successful
|
||||
* @return String status of the cert chain validation -
|
||||
* blank if successful, error message otherwise
|
||||
* @throws SupplyChainValidatorException tried to validate using null certificates
|
||||
*/
|
||||
public static String validateCertChain(final X509AttributeCertificateHolder cert,
|
||||
@ -1341,14 +1355,12 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
signatureMatchesPublicKey = signatureMatchesPublicKey(cert, trustedCert);
|
||||
if (issuerMatchesSubject && signatureMatchesPublicKey) {
|
||||
if (isSelfSigned(trustedCert)) {
|
||||
foundRootOfCertChain = "";
|
||||
LOGGER.info("CA Root found.");
|
||||
break;
|
||||
} else {
|
||||
foundRootOfCertChain = validateCertChain(trustedCert, additionalCerts);
|
||||
|
||||
if (!foundRootOfCertChain.isEmpty()) {
|
||||
LOGGER.error("Root of certificate chain not found. Check for CA Cert: "
|
||||
+ cert.getIssuer().getNames()[0]);
|
||||
}
|
||||
foundRootOfCertChain = "Intermediate signing cert found. Check for CA Cert: "
|
||||
+ cert.getIssuer().getNames()[0];
|
||||
}
|
||||
} else {
|
||||
if (!issuerMatchesSubject) {
|
||||
@ -1360,6 +1372,9 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundRootOfCertChain.isEmpty()) {
|
||||
LOGGER.error(foundRootOfCertChain);
|
||||
}
|
||||
return foundRootOfCertChain;
|
||||
}
|
||||
|
||||
@ -1374,7 +1389,8 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
* certificate to validate
|
||||
* @param additionalCerts
|
||||
* Set of certs to validate against
|
||||
* @return boolean indicating if the validation was successful
|
||||
* @return String status of the cert chain validation -
|
||||
* blank if successful, error message otherwise
|
||||
* @throws SupplyChainValidatorException tried to validate using null certificates
|
||||
*/
|
||||
public static String validateCertChain(final X509Certificate cert,
|
||||
@ -1395,14 +1411,12 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
signatureMatchesPublicKey = signatureMatchesPublicKey(cert, trustedCert);
|
||||
if (issuerMatchesSubject && signatureMatchesPublicKey) {
|
||||
if (isSelfSigned(trustedCert)) {
|
||||
foundRootOfCertChain = "";
|
||||
LOGGER.info("CA Root found.");
|
||||
break;
|
||||
} else if (!cert.equals(trustedCert)) {
|
||||
foundRootOfCertChain = validateCertChain(trustedCert, additionalCerts);
|
||||
|
||||
if (!foundRootOfCertChain.isEmpty()) {
|
||||
LOGGER.error("Root of certificate chain not found. Check for CA Cert: "
|
||||
+ cert.getIssuerDN().getName());
|
||||
}
|
||||
foundRootOfCertChain = "Intermediate signing cert found, check for CA cert "
|
||||
+ cert.getIssuerDN().getName();
|
||||
}
|
||||
} else {
|
||||
if (!issuerMatchesSubject) {
|
||||
@ -1414,6 +1428,9 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundRootOfCertChain.isEmpty()) {
|
||||
LOGGER.error(foundRootOfCertChain);
|
||||
}
|
||||
return foundRootOfCertChain;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user