diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagValidator.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagValidator.java index e1313f0f..494e16a3 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagValidator.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagValidator.java @@ -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 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 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!"); diff --git a/tools/tcg_rim_tool/src/test/java/hirs/swid/TestSwidTagGateway.java b/tools/tcg_rim_tool/src/test/java/hirs/swid/TestSwidTagGateway.java index 2723ff25..09b75977 100644 --- a/tools/tcg_rim_tool/src/test/java/hirs/swid/TestSwidTagGateway.java +++ b/tools/tcg_rim_tool/src/test/java/hirs/swid/TestSwidTagGateway.java @@ -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 */ - @Test + public void testValidateSwidTag() { String filepath = TestSwidTagGateway.class.getClassLoader() .getResource(BASE_USER_CERT).getPath(); diff --git a/tools/tcg_rim_tool/src/test/resources/RimCertChain.pem b/tools/tcg_rim_tool/src/test/resources/RimCertChain.pem new file mode 100644 index 00000000..1580a790 --- /dev/null +++ b/tools/tcg_rim_tool/src/test/resources/RimCertChain.pem @@ -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-----