Modify validator class to handle JKS and PEM truststores appropriately.

This commit is contained in:
chubtub 2023-03-01 20:03:20 -05:00
parent 53a4816dec
commit 401fb404f0
11 changed files with 366 additions and 274 deletions

Binary file not shown.

View File

@ -32,11 +32,14 @@ import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.UnrecoverableEntryException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.List;
/**
@ -73,29 +76,65 @@ public class CredentialParser {
}
/**
* This method parses the X509 signing cert, private key, and public key from
* This method parses the CA cert chain, private key, and public key from
* a JKS truststore.
*
* @param jksKeystore the truststore file
*/
public void parseJKSCredentials(String jksKeystore, String alias, String password) {
KeyStore.PrivateKeyEntry privateKeyEntry =
parseKeystorePrivateKey(jksKeystore, alias, password);
certificate = (X509Certificate) privateKeyEntry.getCertificate();
privateKey = privateKeyEntry.getPrivateKey();
publicKey = certificate.getPublicKey();
public List<X509Certificate> parseJKSCredentials(String jksKeystore,
String alias,
String password) {
ArrayList<X509Certificate> keystoreAsList = new ArrayList<>();
try {
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream(jksKeystore), password.toCharArray());
for (Certificate cert : keystore.getCertificateChain(alias)) {
keystoreAsList.add((X509Certificate) cert);
}
KeyStore.PrivateKeyEntry privateKeyEntry =
(KeyStore.PrivateKeyEntry) keystore.getEntry(alias,
new KeyStore.PasswordProtection(password.toCharArray()));
certificate = (X509Certificate) privateKeyEntry.getCertificate();
privateKey = privateKeyEntry.getPrivateKey();
publicKey = certificate.getPublicKey();
} catch (KeyStoreException e) {
System.out.println("JKS keystore type not supported");
} catch (FileNotFoundException e) {
System.out.println("Unable to locate " + jksKeystore);
} catch (IOException e) {
if (e.getCause() instanceof UnrecoverableKeyException) {
System.out.println("Password is incorrect, please resubmit");
} else if (password.isEmpty()) {
System.out.println("No password given, please resubmit");
} else {
System.out.println("Error importing keystore data:");
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e) {
System.out.println("Unable to verify keystore integrity");
e.printStackTrace();
} catch (CertificateException e) {
System.out.println("Error loading certificates from keystore:");
e.printStackTrace();
} catch (UnrecoverableEntryException e) {
e.printStackTrace();
}
return keystoreAsList;
}
/**
* Convenience method for parsing the cert and keys of the default JKS.
* Convenience method for parsing the default JKS.
*/
public void parseDefaultCredentials() {
parseJKSCredentials(SwidTagConstants.DEFAULT_KEYSTORE_FILE,
SwidTagConstants.DEFAULT_PRIVATE_KEY_ALIAS,
SwidTagConstants.DEFAULT_KEYSTORE_PASSWORD);
public List<X509Certificate> parseDefaultCredentials() {
return parseJKSCredentials(SwidTagConstants.DEFAULT_KEYSTORE_FILE,
SwidTagConstants.DEFAULT_PRIVATE_KEY_ALIAS,
SwidTagConstants.DEFAULT_KEYSTORE_PASSWORD);
}
/**
* This method returns the X509Certificate object from a PEM truststore.
*
* @param truststore the PEM truststore
* @return a list of X509 certs
*/
@ -103,9 +142,8 @@ public class CredentialParser {
return parsePEMCertificates(truststore);
}
public void parsePEMCredentials(List<X509Certificate> truststore,
String privateKeyFile)
throws Exception {
public void parsePEMCredentials(List<X509Certificate> truststore, String privateKeyFile)
throws Exception {
byte[] challengeString = new byte[15];
for (X509Certificate cert : truststore) {
certificate = cert;
@ -141,6 +179,7 @@ public class CredentialParser {
* This method extracts certificate bytes from a string. The bytes are assumed to be
* PEM format, and a header and footer are concatenated with the input string to
* facilitate proper parsing.
*
* @param pemString the input string
* @return an X509Certificate created from the string
* @throws CertificateException if instantiating the CertificateFactory errors
@ -149,10 +188,10 @@ public class CredentialParser {
try {
CertificateFactory factory = CertificateFactory.getInstance(X509);
InputStream inputStream = new ByteArrayInputStream((CERTIFICATE_HEADER
+ System.lineSeparator()
+ pemString
+ System.lineSeparator()
+ CERTIFICATE_FOOTER).getBytes());
+ System.lineSeparator()
+ pemString
+ System.lineSeparator()
+ CERTIFICATE_FOOTER).getBytes());
return (X509Certificate) factory.generateCertificate(inputStream);
} catch (CertificateException e) {
throw e;
@ -163,6 +202,7 @@ public class CredentialParser {
* This method returns the X509Certificate found in a PEM file.
* Unchecked typcase warnings are suppressed because the CertificateFactory
* implements X509Certificate objects explicitly.
*
* @param filename pem file
* @return a list containing all X509Certificates extracted
*/
@ -211,6 +251,7 @@ public class CredentialParser {
* Both PKCS1 and PKCS8 formats are handled.
* Algorithm argument is present to allow handling of multiple encryption algorithms,
* but for now it is always RSA.
*
* @param filename
* @return
*/
@ -271,6 +312,7 @@ public class CredentialParser {
/**
* This method reads a PKCS1 keypair from a PEM file.
*
* @param filename
* @return
*/
@ -285,6 +327,7 @@ public class CredentialParser {
/**
* This method returns the private key from a JKS keystore.
*
* @param keystoreFile
* @param alias
* @param password
@ -312,6 +355,7 @@ public class CredentialParser {
/**
* This method returns the authorityInfoAccess from an X509Certificate.
*
* @return
* @throws IOException
*/
@ -320,7 +364,7 @@ public class CredentialParser {
byte[] extension = certificate.getExtensionValue(Extension.authorityInfoAccess.getId());
if (extension != null && extension.length > 0) {
AuthorityInformationAccess aia = AuthorityInformationAccess.getInstance(
JcaX509ExtensionUtils.parseExtensionValue(extension));
JcaX509ExtensionUtils.parseExtensionValue(extension));
for (AccessDescription ad : aia.getAccessDescriptions()) {
if (ad.getAccessMethod().toString().equals(SwidTagConstants.CA_ISSUERS)) {
sb.append("CA issuers - ");
@ -335,6 +379,7 @@ public class CredentialParser {
/**
* This method returns the subjectKeyIdentifier from the local X509Certificate.
*
* @return the String representation of the subjectKeyIdentifier
* @throws IOException
*/
@ -349,6 +394,7 @@ public class CredentialParser {
/**
* This method returns the subjectKeyIdentifier from a given X509Certificate.
*
* @param certificate the cert to pull the subjectKeyIdentifier from
* @return the String representation of the subjectKeyIdentifier
* @throws IOException

View File

@ -1,7 +1,7 @@
package hirs.swid;
import hirs.swid.utils.Commander;
import com.beust.jcommander.JCommander;
import hirs.swid.utils.Commander;
import hirs.swid.utils.CredentialArgumentValidator;
import hirs.swid.utils.TimestampArgumentValidator;
@ -28,21 +28,21 @@ public class Main {
String rimel = commander.getRimEventLog();
String certificateFile = commander.getPublicCertificate();
String trustStore = commander.getTruststoreFile();
if (!verifyFile.isEmpty()) {
if (!rimel.isEmpty()) {
validator.setRimEventLog(rimel);
}
if (!trustStore.isEmpty()) {
validator.setTrustStoreFile(trustStore);
}
if (!certificateFile.isEmpty()) {
System.out.println("A single cert cannot be used for verification. " +
"The signing cert will be searched for in the trust store.");
}
validator.validateSwidTag(verifyFile);
boolean defaultKey = commander.isDefaultKey();
validator.setRimEventLog(rimel);
if (defaultKey) {
validator.validateSwidTag(verifyFile, "DEFAULT");
} else {
System.out.println("Need a RIM file to validate!");
System.exit(1);
caValidator = new CredentialArgumentValidator(trustStore,
certificateFile, "", "", "", true);
if (caValidator.isValid()) {
validator.setTrustStoreFile(trustStore);
validator.validateSwidTag(verifyFile, caValidator.getFormat());
} else {
System.out.println("Invalid combination of credentials given: "
+ caValidator.getErrorMessage());
System.exit(1);
}
}
} else {
gateway = new SwidTagGateway();
@ -66,7 +66,7 @@ public class Main {
} else {
gateway.setDefaultCredentials(false);
caValidator = new CredentialArgumentValidator(truststoreFile,
certificateFile, privateKeyFile,"","", false);
certificateFile, privateKeyFile, "", "", false);
if (caValidator.isValid()) {
gateway.setTruststoreFile(truststoreFile);
gateway.setPemCertificateFile(certificateFile);

View File

@ -8,13 +8,12 @@ import javax.xml.namespace.QName;
* This class contains the String constants that are referenced by the gateway
* class. It is expected that member properties of this class will expand as
* more functionality is added to SwidTagGateway.
*
*/
public class SwidTagConstants {
public static final String DEFAULT_KEYSTORE_FILE = "/opt/hirs/rimtool/keystore.jks";
public static final String DEFAULT_KEYSTORE_PASSWORD = "password";
public static final String DEFAULT_PRIVATE_KEY_ALIAS = "selfsigned";
public static final String DEFAULT_PRIVATE_KEY_ALIAS = "1";
public static final String DEFAULT_ATTRIBUTES_FILE = "/opt/hirs/rimtool/rim_fields.json";
public static final String DEFAULT_ENGLISH = "en";
@ -43,7 +42,7 @@ public class SwidTagConstants {
public static final String ROLE = "role";
public static final String THUMBPRINT = "thumbprint";
public static final String HREF = "href";
public static final String REL = "rel";
public static final String REL = "rel";
public static final String COLLOQUIAL_VERSION = "colloquialVersion";
public static final String EDITION = "edition";
public static final String PRODUCT = "product";
@ -72,12 +71,12 @@ public class SwidTagConstants {
public static final String SUPPORT_RIM_FORMAT_MISSING = "supportRIMFormat missing";
public static final String SUPPORT_RIM_URI_GLOBAL = "supportRIMURIGlobal";
public static final String DATETIME = "dateTime";
public static final String NIST_NS = "http://csrc.nist.gov/ns/swid/2015-extensions/1.0";
public static final String TCG_NS = "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model";
public static final String TCG_NS = "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model";
public static final String RFC3852_NS = "https://www.ietf.org/rfc/rfc3852.txt";
public static final String RFC3339_NS = "https://www.ietf.org/rfc/rfc3339.txt";
public static final String N8060_PFX = "n8060";
public static final String RIM_PFX = "rim";
public static final String RFC3852_PFX = "rcf3852";
@ -119,7 +118,7 @@ public class SwidTagConstants {
TCG_NS, PC_URI_LOCAL, RIM_PFX);
public static final QName _PC_URI_GLOBAL = new QName(
TCG_NS, PC_URI_GLOBAL, RIM_PFX);
public static final QName _RIM_LINK_HASH = new QName(
public static final QName _RIM_LINK_HASH = new QName(
TCG_NS, RIM_LINK_HASH, RIM_PFX);
public static final QName _SUPPORT_RIM_TYPE = new QName(
TCG_NS, SUPPORT_RIM_TYPE, RIM_PFX);

View File

@ -180,6 +180,7 @@ public class SwidTagGateway {
/**
* Setter for timestamp format in XML signature
*
* @param timestampFormat
*/
public void setTimestampFormat(String timestampFormat) {
@ -188,6 +189,7 @@ public class SwidTagGateway {
/**
* Setter for timestamp input - RFC3852 + file or RFC3339 + value
*
* @param timestampArgument
*/
public void setTimestampArgument(String timestampArgument) {
@ -246,7 +248,7 @@ public class SwidTagGateway {
writeSwidTagFile(signedSoftwareIdentity, filename);
} else {
System.out.println("The following fields cannot be empty or null: "
+ errorRequiredFields.substring(0, errorRequiredFields.length()-2));
+ errorRequiredFields.substring(0, errorRequiredFields.length() - 2));
System.exit(1);
}
} catch (JsonException e) {
@ -532,6 +534,7 @@ public class SwidTagGateway {
addNonNullAttribute(attributes, key, value);
}
}
/**
* This utility method checks if an attribute value is empty before adding it to the map.
*
@ -652,7 +655,8 @@ public class SwidTagGateway {
/**
* This method creates a timestamp element and populates it with data according to
* the RFC format set in timestampFormat. The element is returned within an XMLObject.
* @param doc the Document representing the XML to be signed
*
* @param doc the Document representing the XML to be signed
* @param sigFactory the SignatureFactory object
* @return an XMLObject containing the timestamp element
*/
@ -693,7 +697,7 @@ public class SwidTagGateway {
SignatureProperties signatureProperties = sigFactory.newSignatureProperties(
Collections.singletonList(signatureProperty), null);
XMLObject xmlObject = sigFactory.newXMLObject(
Collections.singletonList(signatureProperties), null,null,null);
Collections.singletonList(signatureProperties), null, null, null);
return xmlObject;
}

View File

@ -36,7 +36,6 @@ import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
@ -74,6 +73,7 @@ public class SwidTagValidator {
/**
* Setter for rimel file path.
*
* @param rimEventLog the rimel file
*/
public void setRimEventLog(String rimEventLog) {
@ -82,6 +82,7 @@ public class SwidTagValidator {
/**
* Setter for the truststore file path.
*
* @param trustStoreFile the truststore
*/
public void setTrustStoreFile(String trustStoreFile) {
@ -99,6 +100,7 @@ public class SwidTagValidator {
System.out.println("Error initializing JAXBContext: " + e.getMessage());
}
}
/**
* This method validates the .swidtag file at the given filepath against the
* schema. A successful validation results in the output of the tag's name
@ -106,9 +108,10 @@ public class SwidTagValidator {
*
* @param path the location of the file to be validated
*/
public boolean validateSwidTag(String path) {
public boolean validateSwidTag(String path, String format) {
Document document = unmarshallSwidTag(path);
Element softwareIdentity = (Element) document.getElementsByTagName("SoftwareIdentity").item(0);
Element softwareIdentity =
(Element) document.getElementsByTagName("SoftwareIdentity").item(0);
StringBuilder si = new StringBuilder("Base RIM detected:\n");
si.append("SoftwareIdentity name: " + softwareIdentity.getAttribute("name") + "\n");
si.append("SoftwareIdentity tagId: " + softwareIdentity.getAttribute("tagId") + "\n");
@ -120,8 +123,14 @@ public class SwidTagValidator {
System.out.println(e.getMessage());
return false;
}
System.out.println("Signature core validity: " + validateSignedXMLDocument(document));
return true;
boolean swidtagValidity = validateSignedXMLDocument(document, format);
if (swidtagValidity) {
System.out.println("Signature core validity: true");
return true;
} else {
System.out.println("Signature core validity: false");
return false;
}
}
/**
@ -153,15 +162,22 @@ public class SwidTagValidator {
* Next, the signature is inspected for two things:
* 1. valid signature
* 2. valid certificate chain
*
* @param doc XML document
* @return true if both the signature and cert chain are valid; false otherwise
*/
private boolean validateSignedXMLDocument(Document doc) {
private boolean validateSignedXMLDocument(Document doc, String credentialFormat) {
try {
DOMValidateContext context;
CredentialParser cp = new CredentialParser();
X509Certificate signingCert = null;
trustStore = cp.parseCertsFromPEM(trustStoreFile);
switch (credentialFormat) {
case "DEFAULT":
trustStore = cp.parseDefaultCredentials();
break;
case "PEM":
trustStore = cp.parseCertsFromPEM(trustStoreFile);
}
X509KeySelector keySelector = new X509KeySelector();
NodeList nodes = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nodes.getLength() == 0) {
@ -190,7 +206,7 @@ public class SwidTagValidator {
}
} else {
System.out.println("Base RIM must have a non-empty, non-null " +
"Subject Key Identifier (SKID) in the <KeyName> element");
"Subject Key Identifier (SKID) in the <KeyName> element");
System.exit(1);
}
}
@ -212,7 +228,7 @@ public class SwidTagValidator {
} catch (MarshalException | XMLSignatureException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
return false;
@ -237,7 +253,8 @@ public class SwidTagValidator {
* This method extracts a public key from either an X509Certificate element
* or a KeyValue element. If the public key's algorithm matches the declared
* algorithm it is returned in a KeySelecctorResult.
* @param keyinfo the KeyInfo element
*
* @param keyinfo the KeyInfo element
* @param purpose
* @param algorithm the encapsulating signature's declared signing algorithm
* @param context
@ -248,9 +265,9 @@ public class SwidTagValidator {
final KeySelector.Purpose purpose,
final AlgorithmMethod algorithm,
final XMLCryptoContext context)
throws KeySelectorException {
throws KeySelectorException {
Iterator keyinfoItr = keyinfo.getContent().iterator();
while(keyinfoItr.hasNext()) {
while (keyinfoItr.hasNext()) {
XMLStructure element = (XMLStructure) keyinfoItr.next();
if (element instanceof X509Data) {
X509Data data = (X509Data) element;
@ -300,7 +317,8 @@ public class SwidTagValidator {
/**
* This method checks that the signature and public key algorithms match.
* @param uri to match the signature algorithm
*
* @param uri to match the signature algorithm
* @param name to match the public key algorithm
* @return true if both match, false otherwise
*/
@ -312,6 +330,7 @@ public class SwidTagValidator {
/**
* 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.
*
* @param cert the certificate at the start of the chain
* @return true if the chain is valid
* @throws Exception if a valid chain is not found in the truststore
@ -354,7 +373,8 @@ public class SwidTagValidator {
/**
* This method checks if cert's issuerDN matches issuer's subjectDN.
* @param cert the signed certificate
*
* @param cert the signed certificate
* @param issuer the signing certificate
* @return true if they match, false if not
* @throws Exception if either argument is null
@ -370,7 +390,8 @@ public class SwidTagValidator {
/**
* This method checks if cert's signature matches signer's public key.
* @param cert the signed certificate
*
* @param cert the signed certificate
* @param signer the signing certificate
* @return true if they match
* @throws Exception if an error occurs or there is no match
@ -402,6 +423,7 @@ public class SwidTagValidator {
/**
* This method checks if a given certificate is self signed or not.
*
* @param cert the cert to check
* @return true if self signed, false if not
*/
@ -411,6 +433,7 @@ public class SwidTagValidator {
/**
* This method compares a public key against those in the truststore.
*
* @param pk a public key
* @return true if pk is found in the trust store, false otherwise
*/
@ -483,6 +506,7 @@ public class SwidTagValidator {
/**
* This method strips all whitespace from an xml file, including indents and spaces
* added for human-readability.
*
* @param path to the xml file
* @return Document object without whitespace
*/

View File

@ -19,25 +19,25 @@ public class Commander {
private String createType = "";
@Parameter(names = {"-a", "--attributes <path>"}, order = 1,
description = "The configuration file holding attributes "
+ "to populate the base RIM with.")
+ "to populate the base RIM with.")
private String attributesFile = "";
@Parameter(names = {"-o", "--out <path>"}, order = 2,
description = "The file to write the RIM out to. "
+ "The RIM will be written to stdout by default.")
+ "The RIM will be written to stdout by default.")
private String outFile = "";
@Parameter(names = {"-v", "--verify <path>"}, order = 3,
description = "Specify a RIM file to verify.")
private String verifyFile = "";
@Parameter(names = {"-t", "--truststore <path>"}, order = 4,
description = "The truststore to sign the base RIM created "
+ "or to validate the signed base RIM.")
+ "or to validate the signed base RIM.")
private String truststoreFile = "";
@Parameter(names = {"-k", "--privateKeyFile <path>"}, order = 5,
description = "The private key used to sign the base RIM created by this tool.")
private String privateKeyFile = "";
@Parameter(names = {"-p", "--publicCertificate <path>"}, order = 6,
description = "The public key certificate to embed in the base RIM created by "
+ "this tool.")
+ "this tool.")
private String publicCertificate = "";
@Parameter(names = {"-e", "--embed-cert"}, order = 7,
description = "Embed the provided certificate in the signed swidtag.")
@ -74,7 +74,9 @@ public class Commander {
return verifyFile;
}
public String getTruststoreFile() { return truststoreFile; }
public String getTruststoreFile() {
return truststoreFile;
}
public String getPrivateKeyFile() {
return privateKeyFile;
@ -84,11 +86,17 @@ public class Commander {
return publicCertificate;
}
public boolean isEmbedded() { return embedded; }
public boolean isEmbedded() {
return embedded;
}
public boolean isDefaultKey() { return defaultKey; }
public boolean isDefaultKey() {
return defaultKey;
}
public String getRimEventLog() { return rimEventLog; }
public String getRimEventLog() {
return rimEventLog;
}
public List<String> getTimestampArguments() {
return timestampArguments;
@ -119,6 +127,7 @@ public class Commander {
return sb.toString();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Creating: " + this.getCreateType() + System.lineSeparator());

View File

@ -29,15 +29,21 @@ public class CredentialArgumentValidator {
/**
* Getter for format property
*
* @return string
*/
public String getFormat() { return format; }
public String getFormat() {
return format;
}
/**
* Getter for error message
*
* @return string
*/
public String getErrorMessage() { return errorMessage; }
public String getErrorMessage() {
return errorMessage;
}
/**
* This method checks for the following valid configurations of input arguments:

View File

@ -11,6 +11,7 @@ import java.util.regex.Pattern;
public class TimestampArgumentValidator {
List<String> args;
/**
* This class handles validation of the --timestamp commandline parameter.
* Currently only RFC3339 and RFC3852 formats are supported.
@ -35,7 +36,7 @@ public class TimestampArgumentValidator {
} else {
return false;
}
} else if (args.size() == 1){
} else if (args.size() == 1) {
System.out.println("Countersignature file is required for RFC3852 timestamps");
return false;
}

View File

@ -1,222 +1,225 @@
package hirs.swid;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
public class TestSwidTagGateway {
private SwidTagGateway gateway;
private SwidTagValidator validator;
private final String DEFAULT_OUTPUT = "generated_swidTag.swidtag";
private final String BASE_USER_CERT = "generated_user_cert.swidtag";
private final String BASE_USER_CERT_EMBED = "generated_user_cert_embed.swidtag";
private final String BASE_TRUSTSTORE_EMBED = "generated_truststore_embed.swidtag";
private final String BASE_DEFAULT_CERT = "generated_default_cert.swidtag";
private final String BASE_RFC3339_TIMESTAMP = "generated_timestamp_rfc3339.swidtag";
private final String BASE_RFC3852_TIMESTAMP = "generated_timestamp_rfc3852.swidtag";
private final String ATTRIBUTES_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("rim_fields.json").getPath();
private final String JKS_KEYSTORE_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("keystore.jks").getPath();
private final String SIGNING_CERT_FILE = TestSwidTagGateway.class.getClassLoader()
.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 final String RFC3852_COUNTERSIGNATURE_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("counterSignature.file").getPath();
private InputStream expectedFile;
private SwidTagGateway gateway;
private SwidTagValidator validator;
private final String JKS = "JKS";
private final String PEM = "PEM";
private final String DEFAULT_OUTPUT = "generated_swidTag.swidtag";
private final String BASE_USER_CERT = "generated_user_cert.swidtag";
private final String BASE_USER_CERT_EMBED = "generated_user_cert_embed.swidtag";
private final String BASE_TRUSTSTORE_EMBED = "generated_truststore_embed.swidtag";
private final String BASE_DEFAULT_CERT = "generated_default_cert.swidtag";
private final String BASE_RFC3339_TIMESTAMP = "generated_timestamp_rfc3339.swidtag";
private final String BASE_RFC3852_TIMESTAMP = "generated_timestamp_rfc3852.swidtag";
private final String ATTRIBUTES_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("rim_fields.json").getPath();
private final String JKS_KEYSTORE_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("keystore.jks").getPath();
private final String SIGNING_CERT_FILE = TestSwidTagGateway.class.getClassLoader()
.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 final String RFC3852_COUNTERSIGNATURE_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("counterSignature.file").getPath();
private InputStream expectedFile;
@BeforeClass
public void setUp() throws Exception {
gateway = new SwidTagGateway();
gateway.setRimEventLog(SUPPORT_RIM_FILE);
gateway.setAttributesFile(ATTRIBUTES_FILE);
validator = new SwidTagValidator();
validator.setRimEventLog(SUPPORT_RIM_FILE);
validator.setTrustStoreFile(CA_CHAIN_FILE);
}
@BeforeClass
public void setUp() throws Exception {
gateway = new SwidTagGateway();
gateway.setRimEventLog(SUPPORT_RIM_FILE);
gateway.setAttributesFile(ATTRIBUTES_FILE);
validator = new SwidTagValidator();
validator.setRimEventLog(SUPPORT_RIM_FILE);
validator.setTrustStoreFile(CA_CHAIN_FILE);
}
@AfterClass
public void tearDown() throws Exception {
if (expectedFile != null) {
expectedFile.close();
}
}
@AfterClass
public void tearDown() throws Exception {
if (expectedFile != null) {
expectedFile.close();
}
}
/**
* This test corresponds to the arguments:
* -c base -l TpmLog.bin -k privateRimKey.pem -p RimSignCert.pem
* where RimSignCert.pem has the AIA extension.
*/
@Test
public void testCreateBasePemCertNotEmbedded() {
gateway.setDefaultCredentials(false);
gateway.setPemCertificateFile(SIGNING_CERT_FILE);
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
gateway.setEmbeddedCert(false);
gateway.generateSwidTag(DEFAULT_OUTPUT);
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:
* -c base -l TpmLog.bin -k privateRimKey.pem -p RimSignCert.pem
* where RimSignCert.pem has the AIA extension.
*/
@Test
public void testCreateBasePemCertNotEmbedded() {
gateway.setDefaultCredentials(false);
gateway.setPemCertificateFile(SIGNING_CERT_FILE);
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
gateway.setEmbeddedCert(false);
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_USER_CERT);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, PEM));
}
/**
* This test creates the following base RIM:
* -c base -l TpmLog.bin -k privateRimKey.pem -p RimSignCert.pem -e
* And then validates it:
* -v [base RIM] -l TpmLog.bin -t RimCertChain.pem
*/
@Test
public void testCreateBasePemCertEmbedded() {
gateway.setDefaultCredentials(false);
gateway.setTruststoreFile("");
gateway.setPemCertificateFile(SIGNING_CERT_FILE);
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
gateway.setEmbeddedCert(true);
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_USER_CERT_EMBED);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
}
/**
* This test creates the following base RIM:
* -c base -l TpmLog.bin -k privateRimKey.pem -p RimSignCert.pem -e
* And then validates it:
* -v [base RIM] -l TpmLog.bin -t RimCertChain.pem
*/
@Test
public void testCreateBasePemCertEmbedded() {
gateway.setDefaultCredentials(false);
gateway.setTruststoreFile("");
gateway.setPemCertificateFile(SIGNING_CERT_FILE);
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
gateway.setEmbeddedCert(true);
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_USER_CERT_EMBED);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, PEM));
}
/**
* This test corresponds to:
* -c base -l TpmLog.bin -t RimCertChain.pem -k privateRimKey.pem -e
* And then validates it:
* -v [base RIM] -l TpmLog.bin -t RimCertChain.pem
*/
@Test
public void testCreateBasePemTruststoreEmbedded() {
gateway.setDefaultCredentials(false);
gateway.setTruststoreFile(CA_CHAIN_FILE);
gateway.setPemCertificateFile("");
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
gateway.setEmbeddedCert(true);
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_TRUSTSTORE_EMBED);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
}
/**
* This test corresponds to:
* -c base -l TpmLog.bin -t RimCertChain.pem -k privateRimKey.pem -e
* And then validates it:
* -v [base RIM] -l TpmLog.bin -t RimCertChain.pem
*/
@Test
public void testCreateBasePemTruststoreEmbedded() {
gateway.setDefaultCredentials(false);
gateway.setTruststoreFile(CA_CHAIN_FILE);
gateway.setPemCertificateFile("");
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
gateway.setEmbeddedCert(true);
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_TRUSTSTORE_EMBED);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, PEM));
}
/**
* This test corresponds to the arguments:
* -c base -l TpmLog.bin -d
*/
@Test
public void testCreateBaseDefaultCert() {
gateway.setDefaultCredentials(true);
gateway.setTruststoreFile(JKS_KEYSTORE_FILE);
gateway.generateSwidTag(DEFAULT_OUTPUT);
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:
* -c base -l TpmLog.bin -d
*/
@Test
public void testCreateBaseDefaultCert() {
gateway.setDefaultCredentials(true);
gateway.setTruststoreFile(JKS_KEYSTORE_FILE);
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_DEFAULT_CERT);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, "DEFAULT"));
}
/**
* This test corresponds to the arguments:
* -c base -l TpmLog.bin -d --timestamp rfc3339 2023-01-01T00:00:00Z
*/
@Test
public void testCreateTimestampRfc3339() {
gateway.setDefaultCredentials(true);
gateway.setTruststoreFile(JKS_KEYSTORE_FILE);
gateway.setTimestampFormat("RFC3339");
gateway.setTimestampArgument("2023-01-01T00:00:00Z");
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_RFC3339_TIMESTAMP);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
}
/**
* This test corresponds to the arguments:
* -c base -l TpmLog.bin -d --timestamp rfc3339 2023-01-01T00:00:00Z
*/
@Test
public void testCreateTimestampRfc3339() {
gateway.setDefaultCredentials(true);
gateway.setTruststoreFile(JKS_KEYSTORE_FILE);
gateway.setTimestampFormat("RFC3339");
gateway.setTimestampArgument("2023-01-01T00:00:00Z");
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_RFC3339_TIMESTAMP);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, JKS));
}
/**
* This test corresponds to the arguments:
* -c base -l TpmLog.bin -d --timestamp rfc3852 countersignature.file
*/
@Test
public void testCreateTimestampRfc3852() {
gateway.setDefaultCredentials(true);
gateway.setTruststoreFile(JKS_KEYSTORE_FILE);
gateway.setTimestampFormat("RFC3852");
gateway.setTimestampArgument(RFC3852_COUNTERSIGNATURE_FILE);
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_RFC3852_TIMESTAMP);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
}
/**
* This test corresponds to the arguments:
* -c base -l TpmLog.bin -d --timestamp rfc3852 countersignature.file
*/
@Test
public void testCreateTimestampRfc3852() {
gateway.setDefaultCredentials(true);
gateway.setTruststoreFile(JKS_KEYSTORE_FILE);
gateway.setTimestampFormat("RFC3852");
gateway.setTimestampArgument(RFC3852_COUNTERSIGNATURE_FILE);
gateway.generateSwidTag(DEFAULT_OUTPUT);
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_RFC3852_TIMESTAMP);
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, JKS));
}
/**
* This test corresponds to the arguments:
* -v <path>
*/
/**
* This test corresponds to the arguments:
* -v <path>
*/
public void testValidateSwidTag() {
String filepath = TestSwidTagGateway.class.getClassLoader()
.getResource(BASE_USER_CERT).getPath();
System.out.println("Validating file at " + filepath);
Assert.assertTrue(validator.validateSwidTag(filepath));
}
public void testValidateSwidTag() {
String filepath = TestSwidTagGateway.class.getClassLoader()
.getResource(BASE_USER_CERT).getPath();
System.out.println("Validating file at " + filepath);
Assert.assertTrue(validator.validateSwidTag(filepath, PEM));
}
/**
* This method compares two files by bytes to determine if they are the same or not.
* @param file to be compared to the expected value.
* @return true if they are equal, false if not.
*/
private boolean compareFileBytesToExpectedFile(String file) {
FileInputStream testFile = null;
try {
int data;
testFile = new FileInputStream(file);
while ((data = testFile.read()) != -1) {
int expected = expectedFile.read();
if (data != expected) {
System.out.println("Expected: " + expected);
System.out.println("Got: " + data);
return false;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (NullPointerException e) {
e.printStackTrace();
return false;
} finally {
if (testFile != null) {
try {
testFile.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
if (expectedFile != null) {
try {
expectedFile.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
return true;
}
/**
* This method compares two files by bytes to determine if they are the same or not.
*
* @param file to be compared to the expected value.
* @return true if they are equal, false if not.
*/
private boolean compareFileBytesToExpectedFile(String file) {
FileInputStream testFile = null;
try {
int data;
testFile = new FileInputStream(file);
while ((data = testFile.read()) != -1) {
int expected = expectedFile.read();
if (data != expected) {
System.out.println("Expected: " + expected);
System.out.println("Got: " + data);
return false;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (NullPointerException e) {
e.printStackTrace();
return false;
} finally {
if (testFile != null) {
try {
testFile.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
if (expectedFile != null) {
try {
expectedFile.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
return true;
}
}