WIP: Modify validation code and unit tests to account for embedded public key.

This commit is contained in:
chubtub 2022-04-04 14:38:38 -04:00
parent 0a618b3796
commit e5e6db75f4
3 changed files with 132 additions and 21 deletions

View File

@ -4,7 +4,6 @@ import hirs.swid.utils.HashSwid;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
@ -25,6 +24,7 @@ import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
@ -42,6 +42,7 @@ import java.io.InputStream;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@ -117,7 +118,7 @@ public class SwidTagValidator {
System.out.println(si.toString());
Element file = (Element) document.getElementsByTagName("File").item(0);
validateFile(file);
System.out.println("Signature core validity: " + validateSignedXMLDocument(document));
validateSignedXMLDocument(document);
return true;
}
@ -159,29 +160,56 @@ public class SwidTagValidator {
CredentialParser cp = new CredentialParser();
X509Certificate signingCert = null;
List<X509Certificate> trustStore = cp.parseCertsFromPEM(trustStoreFile);
X509KeySelector keySelector = new X509KeySelector();
NodeList nodes = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nodes.getLength() == 0) {
throw new Exception("Signature element not found!");
} else {
context = new DOMValidateContext(keySelector, nodes.item(0));
}
NodeList embeddedCert = doc.getElementsByTagName("X509Certificate");
if (embeddedCert.getLength() > 0) {
context = new DOMValidateContext(new X509KeySelector(), nodes.item(0));
signingCert = cp.parseCertFromPEMString(embeddedCert.item(0).getTextContent());
} else {
String skId = doc.getElementsByTagName("KeyName").item(0).getTextContent();
for (X509Certificate trustedCert : trustStore) {
String trustedSkId = cp.getCertificateSubjectKeyIdentifier(trustedCert);
if (skId.equals(trustedSkId)) {
signingCert = trustedCert;
break;
NodeList keyValue = doc.getElementsByTagName("KeyValue");
if (keyValue.getLength() > 0) {
String modulus = doc.getElementsByTagName("Modulus").item(0).getTextContent();
String exponent =
doc.getElementsByTagName("Exponent").item(0).getTextContent();
PublicKey signingKey = calculatePublicKey(modulus, exponent);
for (X509Certificate trustedCert : trustStore) {
System.out.println(trustedCert.getPublicKey().toString());
if (Arrays.equals(trustedCert.getPublicKey().getEncoded(),
signingKey.getEncoded())) {
signingCert = trustedCert;
break;
}
}
}
if (signingCert == null) {
System.out.println("Issuer certificate with subject key identifier = "
if (signingCert == null) {
System.out.println("Calculated public key not found: " + signingKey.toString());
System.exit(1);
}
} else {
String skId = doc.getElementsByTagName("KeyName").item(0).getTextContent();
if (skId != null && !skId.isEmpty()) {
for (X509Certificate trustedCert : trustStore) {
String trustedSkId = cp.getCertificateSubjectKeyIdentifier(trustedCert);
if (skId.equals(trustedSkId)) {
signingCert = trustedCert;
break;
}
}
if (signingCert == null) {
System.out.println("Issuer certificate with subject key identifier = "
+ skId + " not found");
System.exit(1);
System.exit(1);
}
} else {
System.out.println("No credentials found with which to validate this swidtag");
System.exit(1);
}
context = new DOMValidateContext(signingCert.getPublicKey(), nodes.item(0));
}
context = new DOMValidateContext(signingCert.getPublicKey(), nodes.item(0));
}
cp.setCertificate(signingCert);
System.out.println(cp.getCertificateAuthorityInfoAccess());
@ -208,6 +236,28 @@ public class SwidTagValidator {
return false;
}
/**
* This method calculates an RSA public key from the <KeyValue> element of an XML
* signature block.
*
* @param mod the modulus string
* @param exp the exponent string
* @return the calculated public key
*/
private PublicKey calculatePublicKey(final String mod, final String exp)
throws NoSuchAlgorithmException, InvalidKeySpecException{
System.out.println("Decoding " + exp);
BigInteger exponent = new BigInteger(Base64.getMimeDecoder().decode(exp));
System.out.println("MIME: " + exponent);
System.out.println("Decoding " + mod);
BigInteger modulus = new BigInteger(Base64.getMimeDecoder().decode(mod));
System.out.println("MIME: " + modulus);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(new RSAPublicKeySpec(modulus, exponent));
}
/**
* This method validates the cert chain for a given certificate. The truststore is iterated
* over until a root CA is found, otherwise an error is returned.
@ -331,6 +381,8 @@ public class SwidTagValidator {
final XMLCryptoContext context)
throws KeySelectorException {
Iterator keyinfoItr = keyinfo.getContent().iterator();
PublicKey publicKey = null;
System.out.println("Parsing KeyInfo");
while(keyinfoItr.hasNext()) {
XMLStructure element = (XMLStructure) keyinfoItr.next();
if (element instanceof X509Data) {
@ -339,12 +391,21 @@ public class SwidTagValidator {
while (dataItr.hasNext()) {
Object object = dataItr.next();
if (object instanceof X509Certificate) {
final PublicKey publicKey = ((X509Certificate) object).getPublicKey();
if (areAlgorithmsEqual(algorithm.getAlgorithm(), publicKey.getAlgorithm())) {
return new SwidTagValidator.X509KeySelector.RIMKeySelectorResult(publicKey);
}
publicKey = ((X509Certificate) object).getPublicKey();
}
}
} else if (element instanceof KeyValue) {
try {
publicKey = ((KeyValue) element).getPublicKey();
System.out.println("PK parsed from KeyValue: " + publicKey.toString());
} catch (KeyException e) {
System.out.println("Unable to convert KeyValue data to PK.");
}
}
if (publicKey != null) {
if (areAlgorithmsEqual(algorithm.getAlgorithm(), publicKey.getAlgorithm())) {
return new SwidTagValidator.X509KeySelector.RIMKeySelectorResult(publicKey);
}
}
}
throw new KeySelectorException("No key found!");

View File

@ -25,6 +25,8 @@ public class TestSwidTagGateway {
.getResource("RimSignCert.pem").getPath();
private final String PRIVATE_KEY_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("privateRimKey.pem").getPath();
private final String CA_CHAIN_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("RimCertChain.pem").getPath();
private final String SUPPORT_RIM_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("TpmLog.bin").getPath();
private InputStream expectedFile;
@ -36,6 +38,7 @@ public class TestSwidTagGateway {
gateway.setAttributesFile(ATTRIBUTES_FILE);
validator = new SwidTagValidator();
validator.setRimEventLog(SUPPORT_RIM_FILE);
validator.setTrustStoreFile(CA_CHAIN_FILE);
}
@AfterClass
@ -60,12 +63,14 @@ public class TestSwidTagGateway {
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_USER_CERT);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
}
/**
* This test corresponds to the arguments:
* This test creates the following base RIM:
* -c base -l TpmLog.bin -k privateRimKey.pem -p RimSignCert.pem -e
* where RimSignCert.pem has the AIA extension.
* And then validates it:
* -v [base RIM] -l TpmLog.bin -t RimCertChain.pem
*/
@Test
public void testCreateBaseUserCertEmbedded() {
@ -77,6 +82,7 @@ public class TestSwidTagGateway {
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_USER_CERT_EMBED);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
}
/**
@ -91,13 +97,14 @@ public class TestSwidTagGateway {
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_DEFAULT_CERT);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
}
/**
* This test corresponds to the arguments:
* -v <path>
*/
@Test
public void testValidateSwidTag() {
String filepath = TestSwidTagGateway.class.getClassLoader()
.getResource(BASE_USER_CERT).getPath();

View File

@ -0,0 +1,43 @@
-----BEGIN CERTIFICATE-----
MIIDjDCCAnSgAwIBAgIJALEA1Q472tZoMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV
BAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwI
UENDbGllbnQxEjAQBgNVBAMMCUV4YW1wbGVDQTAeFw0yMDAyMTAxNzI2MDdaFw0y
OTEyMTkxNzI2MDdaMFMxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UE
CgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxEjAQBgNVBAMMCUV4YW1wbGVD
QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPN0k+ULqFxdHZ14CCio
HAvn56T1Ca4t3ClmZoHSAiKsqzLV+rErk5SbMTIdi0vHQ+3sPYf9Opy0EeUXzh4J
g6CeGdDn247has1k135KBD9iJCaErJfZPnJ22CjKey8rvJM8fH3CAR7M/5uwYcPH
yRICwGAJMA/Qss4nsMRQpfZg4ReKVW+kAoa9eekG3q1sLu/QlCb0NC766X0ANP+8
AuGuHJmNV22fjvwSNfWbsJElcMrLbK4kliPyy05YVs19p+cBM1ADxGw2fJqsNsUy
34SXL1ATqOp7VCslRR5TJBzhxfM56xZbszry7BaqTSFDRGn1FuMw/4+qtPMAB88u
eXECAwEAAaNjMGEwHQYDVR0OBBYEFEahuO3bpnFf0NLneoo8XW6aw5Y4MB8GA1Ud
IwQYMBaAFEahuO3bpnFf0NLneoo8XW6aw5Y4MA8GA1UdEwEB/wQFMAMBAf8wDgYD
VR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQCwCUSV6VjOR+v85z18q5UX
bla0gEsfbc2mx0kGtNqi2im2Xt8UoSJDnfMXzfQq3IP3en943mqgIeYUl3f9UQBT
KgGfyHNbEfa0FzqfKpxJdT37C9ilSQ85GtThffc4I50QgBHaRXOvwBdrGpU2O11V
x35VLyYoycIlg+CizVywEX53aoMil1hEbv0TPtbNnFZGwM/fxvere65GeQld9gEP
9krGtSXYlMktvr66cqPzmG0ciA6dMBZN8dpTgUopmYNz8HVoHDq/KBmXYA7CMzrX
pVNx4kMW/KxA+XAHT82xE7PCiLIJx4z9uPn0O4PBDw0tQ0mxuDpeoi1i9PuBfe6Y
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDoTCCAomgAwIBAgIJAIKly+6bklZlMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV
BAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwI
UENDbGllbnQxEjAQBgNVBAMMCUV4YW1wbGVDQTAeFw0yMDA2MTExNjUzMDFaFw0z
MDA0MjAxNjUzMDFaMFwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UE
CgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxGzAZBgNVBAMMEmV4YW1wbGUu
UklNLnNpZ25lcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKd1lWGk
SRuxAAY2wHag2GVxUk1dZx2PTpfQOflvLeccAVwa8mQhlsRERq+QK8ilj8Xfqs44
/nBaccZDOjdfIxIUCMfwhGXjxCaqZbgTucNsExDnu4arTGraoAwzHg0cVLiKT/Cx
j9NL4dcMgxRXsPdHfXb0923C7xYd2t2qfW05umgaj7qeQl6c68CFNsGX4JA8rWFQ
ZvvGx5DGlK4KTcjPuQQINs5fxasNKqLY2hq+z82x/rqwr2hmyizD6FpFSyIABPEM
PfB036GEhRwu1WEMkq8yIp2jgRUoFYke9pB3ph9pVow0Hh4mNFSKD4pP41VSKY1n
us83mdkuukPy5o0CAwEAAaNvMG0wHQYDVR0OBBYEFC/euOfQMKIgnaoBhhqWT+3s
8rzBMB8GA1UdIwQYMBaAFEahuO3bpnFf0NLneoo8XW6aw5Y4MAkGA1UdEwQCMAAw
CwYDVR0PBAQDAgbAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA
A4IBAQC1mG0naE0W4E9vujPhygf7LXHMFkMPs5uWyvkxe4zWgTg0RHTClbOFJQJ+
pGLOcthSG6vIC6xYJxT5EKtB9rzRlEYHOi4MxuwXz9rLWQhA2zdbSo54Fb/BPoca
5K9kxvAanRltEfqEFhCcRmqIX1i6mpOWiZsrdMs7IflHKBsylUTn+v636BAz3p2H
8/lpJbF4LUFUxFU5FWB3tLuasxYTsbeE6YyNAnQIS95ML7c5H8z2aEQs5TCNHZJD
yc0PZT2aPOuEj5lGv9oyBHbYDitszUWSVxF7z86uVGmYR/2oTIj6tqb+IwuvFtnO
wiXFRS5ctLCdESr3SjdQF5wmIN4n
-----END CERTIFICATE-----