mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-21 05:53:27 +00:00
Merge branch 'issue-504'
This commit is contained in:
commit
610e1f316c
Binary file not shown.
@ -12,22 +12,43 @@ import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
|||||||
import org.bouncycastle.util.encoders.Base64;
|
import org.bouncycastle.util.encoders.Base64;
|
||||||
import org.bouncycastle.util.encoders.DecoderException;
|
import org.bouncycastle.util.encoders.DecoderException;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedInputStream;
|
||||||
import java.security.*;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
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.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class parses private key, public key, and certificate for use in their respective java.security objects.
|
* This class parses private key, public key, and certificates for use in
|
||||||
|
* their respective java.security objects.
|
||||||
*/
|
*/
|
||||||
public class CredentialParser {
|
public class CredentialParser {
|
||||||
private static final String X509 = "X.509";
|
private static final String X509 = "X.509";
|
||||||
private static final String JKS = "JKS";
|
private static final String DEFAULT_ALGORITHM = "RSA";
|
||||||
private static final String PEM = "PEM";
|
|
||||||
private static final String PKCS1_HEADER = "-----BEGIN RSA PRIVATE KEY-----";
|
private static final String PKCS1_HEADER = "-----BEGIN RSA PRIVATE KEY-----";
|
||||||
private static final String PKCS1_FOOTER = "-----END RSA PRIVATE KEY-----";
|
private static final String PKCS1_FOOTER = "-----END RSA PRIVATE KEY-----";
|
||||||
private static final String PKCS8_HEADER = "-----BEGIN PRIVATE KEY-----";
|
private static final String PKCS8_HEADER = "-----BEGIN PRIVATE KEY-----";
|
||||||
@ -54,14 +75,94 @@ public class CredentialParser {
|
|||||||
return publicKey;
|
return publicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parseJKSCredentials(String jksKeystore) {
|
/**
|
||||||
KeyStore.PrivateKeyEntry privateKeyEntry =
|
* This method parses the CA cert chain, private key, and public key from
|
||||||
parseKeystorePrivateKey(jksKeystore,
|
* a JKS truststore.
|
||||||
SwidTagConstants.DEFAULT_PRIVATE_KEY_ALIAS,
|
*
|
||||||
SwidTagConstants.DEFAULT_KEYSTORE_PASSWORD);
|
* @param jksKeystore the truststore file
|
||||||
certificate = (X509Certificate) privateKeyEntry.getCertificate();
|
*/
|
||||||
privateKey = privateKeyEntry.getPrivateKey();
|
public List<X509Certificate> parseJKSCredentials(String jksKeystore,
|
||||||
publicKey = certificate.getPublicKey();
|
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 default JKS.
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
public List<X509Certificate> parseCertsFromPEM(String truststore) {
|
||||||
|
return parsePEMCertificates(truststore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parsePEMCredentials(List<X509Certificate> truststore, String privateKeyFile)
|
||||||
|
throws Exception {
|
||||||
|
byte[] challengeString = new byte[15];
|
||||||
|
for (X509Certificate cert : truststore) {
|
||||||
|
certificate = cert;
|
||||||
|
privateKey = parsePEMPrivateKey(privateKeyFile, DEFAULT_ALGORITHM);
|
||||||
|
publicKey = certificate.getPublicKey();
|
||||||
|
SecureRandom.getInstanceStrong().nextBytes(challengeString);
|
||||||
|
Signature signature = Signature.getInstance("SHA256withRSA");
|
||||||
|
signature.initSign(privateKey);
|
||||||
|
signature.update(challengeString);
|
||||||
|
byte[] signedChallenge = signature.sign();
|
||||||
|
signature.initVerify(publicKey);
|
||||||
|
signature.update(challengeString);
|
||||||
|
if (signature.verify(signedChallenge)) {
|
||||||
|
System.out.println("Matched private key to truststore certificate");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
publicKey = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parsePEMCredentials(String certificateFile, String privateKeyFile)
|
public void parsePEMCredentials(String certificateFile, String privateKeyFile)
|
||||||
@ -70,7 +171,7 @@ public class CredentialParser {
|
|||||||
if (certificate.getIssuerX500Principal().equals(certificate.getSubjectX500Principal())) {
|
if (certificate.getIssuerX500Principal().equals(certificate.getSubjectX500Principal())) {
|
||||||
throw new CertificateException("Signing certificate cannot be self-signed!");
|
throw new CertificateException("Signing certificate cannot be self-signed!");
|
||||||
}
|
}
|
||||||
privateKey = parsePEMPrivateKey(privateKeyFile, "RSA");
|
privateKey = parsePEMPrivateKey(privateKeyFile, DEFAULT_ALGORITHM);
|
||||||
publicKey = certificate.getPublicKey();
|
publicKey = certificate.getPublicKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +179,7 @@ public class CredentialParser {
|
|||||||
* This method extracts certificate bytes from a string. The bytes are assumed to be
|
* 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
|
* PEM format, and a header and footer are concatenated with the input string to
|
||||||
* facilitate proper parsing.
|
* facilitate proper parsing.
|
||||||
|
*
|
||||||
* @param pemString the input string
|
* @param pemString the input string
|
||||||
* @return an X509Certificate created from the string
|
* @return an X509Certificate created from the string
|
||||||
* @throws CertificateException if instantiating the CertificateFactory errors
|
* @throws CertificateException if instantiating the CertificateFactory errors
|
||||||
@ -86,31 +188,21 @@ public class CredentialParser {
|
|||||||
try {
|
try {
|
||||||
CertificateFactory factory = CertificateFactory.getInstance(X509);
|
CertificateFactory factory = CertificateFactory.getInstance(X509);
|
||||||
InputStream inputStream = new ByteArrayInputStream((CERTIFICATE_HEADER
|
InputStream inputStream = new ByteArrayInputStream((CERTIFICATE_HEADER
|
||||||
+ System.lineSeparator()
|
+ System.lineSeparator()
|
||||||
+ pemString
|
+ pemString
|
||||||
+ System.lineSeparator()
|
+ System.lineSeparator()
|
||||||
+ CERTIFICATE_FOOTER).getBytes());
|
+ CERTIFICATE_FOOTER).getBytes());
|
||||||
return (X509Certificate) factory.generateCertificate(inputStream);
|
return (X509Certificate) factory.generateCertificate(inputStream);
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the X509Certificate object from a PEM certificate file.
|
|
||||||
* @param certificateFile
|
|
||||||
* @return
|
|
||||||
* @throws FileNotFoundException
|
|
||||||
*/
|
|
||||||
public List<X509Certificate> parseCertsFromPEM(String certificateFile)
|
|
||||||
throws FileNotFoundException {
|
|
||||||
return parsePEMCertificates(certificateFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the X509Certificate found in a PEM file.
|
* This method returns the X509Certificate found in a PEM file.
|
||||||
* Unchecked typcase warnings are suppressed because the CertificateFactory
|
* Unchecked typcase warnings are suppressed because the CertificateFactory
|
||||||
* implements X509Certificate objects explicitly.
|
* implements X509Certificate objects explicitly.
|
||||||
|
*
|
||||||
* @param filename pem file
|
* @param filename pem file
|
||||||
* @return a list containing all X509Certificates extracted
|
* @return a list containing all X509Certificates extracted
|
||||||
*/
|
*/
|
||||||
@ -136,7 +228,8 @@ public class CredentialParser {
|
|||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
System.out.println("Error in certificate factory: " + e.getMessage());
|
System.out.println("Error in certificate factory: " + e.getMessage());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("Error reading from input stream: " + e.getMessage());
|
System.out.println("Error reading from input stream: " + filename);
|
||||||
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (fis != null) {
|
if (fis != null) {
|
||||||
@ -158,6 +251,7 @@ public class CredentialParser {
|
|||||||
* Both PKCS1 and PKCS8 formats are handled.
|
* Both PKCS1 and PKCS8 formats are handled.
|
||||||
* Algorithm argument is present to allow handling of multiple encryption algorithms,
|
* Algorithm argument is present to allow handling of multiple encryption algorithms,
|
||||||
* but for now it is always RSA.
|
* but for now it is always RSA.
|
||||||
|
*
|
||||||
* @param filename
|
* @param filename
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -218,6 +312,7 @@ public class CredentialParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method reads a PKCS1 keypair from a PEM file.
|
* This method reads a PKCS1 keypair from a PEM file.
|
||||||
|
*
|
||||||
* @param filename
|
* @param filename
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -232,12 +327,15 @@ public class CredentialParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the private key from a JKS keystore.
|
* This method returns the private key from a JKS keystore.
|
||||||
|
*
|
||||||
* @param keystoreFile
|
* @param keystoreFile
|
||||||
* @param alias
|
* @param alias
|
||||||
* @param password
|
* @param password
|
||||||
* @return KeyStore.PrivateKeyEntry
|
* @return KeyStore.PrivateKeyEntry
|
||||||
*/
|
*/
|
||||||
private KeyStore.PrivateKeyEntry parseKeystorePrivateKey(String keystoreFile, String alias, String password) {
|
private KeyStore.PrivateKeyEntry parseKeystorePrivateKey(String keystoreFile,
|
||||||
|
String alias,
|
||||||
|
String password) {
|
||||||
KeyStore keystore = null;
|
KeyStore keystore = null;
|
||||||
KeyStore.PrivateKeyEntry privateKey = null;
|
KeyStore.PrivateKeyEntry privateKey = null;
|
||||||
try {
|
try {
|
||||||
@ -247,7 +345,8 @@ public class CredentialParser {
|
|||||||
new KeyStore.PasswordProtection(password.toCharArray()));
|
new KeyStore.PasswordProtection(password.toCharArray()));
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
System.out.println("Cannot locate keystore " + keystoreFile);
|
System.out.println("Cannot locate keystore " + keystoreFile);
|
||||||
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableEntryException | CertificateException | IOException e) {
|
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableEntryException |
|
||||||
|
CertificateException | IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,6 +355,7 @@ public class CredentialParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the authorityInfoAccess from an X509Certificate.
|
* This method returns the authorityInfoAccess from an X509Certificate.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@ -264,7 +364,7 @@ public class CredentialParser {
|
|||||||
byte[] extension = certificate.getExtensionValue(Extension.authorityInfoAccess.getId());
|
byte[] extension = certificate.getExtensionValue(Extension.authorityInfoAccess.getId());
|
||||||
if (extension != null && extension.length > 0) {
|
if (extension != null && extension.length > 0) {
|
||||||
AuthorityInformationAccess aia = AuthorityInformationAccess.getInstance(
|
AuthorityInformationAccess aia = AuthorityInformationAccess.getInstance(
|
||||||
JcaX509ExtensionUtils.parseExtensionValue(extension));
|
JcaX509ExtensionUtils.parseExtensionValue(extension));
|
||||||
for (AccessDescription ad : aia.getAccessDescriptions()) {
|
for (AccessDescription ad : aia.getAccessDescriptions()) {
|
||||||
if (ad.getAccessMethod().toString().equals(SwidTagConstants.CA_ISSUERS)) {
|
if (ad.getAccessMethod().toString().equals(SwidTagConstants.CA_ISSUERS)) {
|
||||||
sb.append("CA issuers - ");
|
sb.append("CA issuers - ");
|
||||||
@ -279,6 +379,7 @@ public class CredentialParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the subjectKeyIdentifier from the local X509Certificate.
|
* This method returns the subjectKeyIdentifier from the local X509Certificate.
|
||||||
|
*
|
||||||
* @return the String representation of the subjectKeyIdentifier
|
* @return the String representation of the subjectKeyIdentifier
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@ -293,6 +394,7 @@ public class CredentialParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the subjectKeyIdentifier from a given X509Certificate.
|
* This method returns the subjectKeyIdentifier from a given X509Certificate.
|
||||||
|
*
|
||||||
* @param certificate the cert to pull the subjectKeyIdentifier from
|
* @param certificate the cert to pull the subjectKeyIdentifier from
|
||||||
* @return the String representation of the subjectKeyIdentifier
|
* @return the String representation of the subjectKeyIdentifier
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package hirs.swid;
|
package hirs.swid;
|
||||||
|
|
||||||
import hirs.swid.utils.Commander;
|
|
||||||
import com.beust.jcommander.JCommander;
|
import com.beust.jcommander.JCommander;
|
||||||
|
import hirs.swid.utils.Commander;
|
||||||
|
import hirs.swid.utils.CredentialArgumentValidator;
|
||||||
import hirs.swid.utils.TimestampArgumentValidator;
|
import hirs.swid.utils.TimestampArgumentValidator;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -14,6 +15,7 @@ public class Main {
|
|||||||
jc.parse(args);
|
jc.parse(args);
|
||||||
SwidTagGateway gateway;
|
SwidTagGateway gateway;
|
||||||
SwidTagValidator validator;
|
SwidTagValidator validator;
|
||||||
|
CredentialArgumentValidator caValidator;
|
||||||
|
|
||||||
if (commander.isHelp()) {
|
if (commander.isHelp()) {
|
||||||
jc.usage();
|
jc.usage();
|
||||||
@ -26,28 +28,28 @@ public class Main {
|
|||||||
String rimel = commander.getRimEventLog();
|
String rimel = commander.getRimEventLog();
|
||||||
String certificateFile = commander.getPublicCertificate();
|
String certificateFile = commander.getPublicCertificate();
|
||||||
String trustStore = commander.getTruststoreFile();
|
String trustStore = commander.getTruststoreFile();
|
||||||
if (!verifyFile.isEmpty()) {
|
boolean defaultKey = commander.isDefaultKey();
|
||||||
if (!rimel.isEmpty()) {
|
validator.setRimEventLog(rimel);
|
||||||
validator.setRimEventLog(rimel);
|
if (defaultKey) {
|
||||||
}
|
validator.validateSwidTag(verifyFile, "DEFAULT");
|
||||||
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);
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Need a RIM file to validate!");
|
caValidator = new CredentialArgumentValidator(trustStore,
|
||||||
System.exit(1);
|
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 {
|
} else {
|
||||||
gateway = new SwidTagGateway();
|
gateway = new SwidTagGateway();
|
||||||
System.out.println(commander.toString());
|
System.out.println(commander.toString());
|
||||||
String createType = commander.getCreateType().toUpperCase();
|
String createType = commander.getCreateType().toUpperCase();
|
||||||
String attributesFile = commander.getAttributesFile();
|
String attributesFile = commander.getAttributesFile();
|
||||||
String jksTruststoreFile = commander.getTruststoreFile();
|
String truststoreFile = commander.getTruststoreFile();
|
||||||
String certificateFile = commander.getPublicCertificate();
|
String certificateFile = commander.getPublicCertificate();
|
||||||
String privateKeyFile = commander.getPrivateKeyFile();
|
String privateKeyFile = commander.getPrivateKeyFile();
|
||||||
boolean embeddedCert = commander.isEmbedded();
|
boolean embeddedCert = commander.isEmbedded();
|
||||||
@ -58,30 +60,27 @@ public class Main {
|
|||||||
if (!attributesFile.isEmpty()) {
|
if (!attributesFile.isEmpty()) {
|
||||||
gateway.setAttributesFile(attributesFile);
|
gateway.setAttributesFile(attributesFile);
|
||||||
}
|
}
|
||||||
if (!jksTruststoreFile.isEmpty()) {
|
if (defaultKey) {
|
||||||
gateway.setDefaultCredentials(true);
|
gateway.setDefaultCredentials(true);
|
||||||
gateway.setJksTruststoreFile(jksTruststoreFile);
|
gateway.setTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
|
||||||
} else if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) {
|
} else {
|
||||||
gateway.setDefaultCredentials(false);
|
gateway.setDefaultCredentials(false);
|
||||||
gateway.setPemCertificateFile(certificateFile);
|
caValidator = new CredentialArgumentValidator(truststoreFile,
|
||||||
gateway.setPemPrivateKeyFile(privateKeyFile);
|
certificateFile, privateKeyFile, "", "", false);
|
||||||
|
if (caValidator.isValid()) {
|
||||||
|
gateway.setTruststoreFile(truststoreFile);
|
||||||
|
gateway.setPemCertificateFile(certificateFile);
|
||||||
|
gateway.setPemPrivateKeyFile(privateKeyFile);
|
||||||
|
} else {
|
||||||
|
System.out.println("Invalid combination of credentials given: "
|
||||||
|
+ caValidator.getErrorMessage());
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
if (embeddedCert) {
|
if (embeddedCert) {
|
||||||
gateway.setEmbeddedCert(true);
|
gateway.setEmbeddedCert(true);
|
||||||
}
|
}
|
||||||
} else if (defaultKey){
|
|
||||||
gateway.setDefaultCredentials(true);
|
|
||||||
gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
|
|
||||||
} else {
|
|
||||||
System.out.println("A private key (-k) and public certificate (-p) " +
|
|
||||||
"are required, or the default key (-d) must be indicated.");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
if (rimEventLog.isEmpty()) {
|
|
||||||
System.out.println("Error: a support RIM is required!");
|
|
||||||
System.exit(1);
|
|
||||||
} else {
|
|
||||||
gateway.setRimEventLog(rimEventLog);
|
|
||||||
}
|
}
|
||||||
|
gateway.setRimEventLog(rimEventLog);
|
||||||
List<String> timestampArguments = commander.getTimestampArguments();
|
List<String> timestampArguments = commander.getTimestampArguments();
|
||||||
if (timestampArguments.size() > 0) {
|
if (timestampArguments.size() > 0) {
|
||||||
if (new TimestampArgumentValidator(timestampArguments).isValid()) {
|
if (new TimestampArgumentValidator(timestampArguments).isValid()) {
|
||||||
|
@ -8,13 +8,12 @@ import javax.xml.namespace.QName;
|
|||||||
* This class contains the String constants that are referenced by the gateway
|
* 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
|
* class. It is expected that member properties of this class will expand as
|
||||||
* more functionality is added to SwidTagGateway.
|
* more functionality is added to SwidTagGateway.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class SwidTagConstants {
|
public class SwidTagConstants {
|
||||||
|
|
||||||
public static final String DEFAULT_KEYSTORE_FILE = "/opt/hirs/rimtool/keystore.jks";
|
public static final String DEFAULT_KEYSTORE_FILE = "keystore.jks";//"/opt/hirs/rimtool/keystore.jks";
|
||||||
public static final String DEFAULT_KEYSTORE_PASSWORD = "password";
|
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_ATTRIBUTES_FILE = "/opt/hirs/rimtool/rim_fields.json";
|
||||||
public static final String DEFAULT_ENGLISH = "en";
|
public static final String DEFAULT_ENGLISH = "en";
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ public class SwidTagConstants {
|
|||||||
public static final String ROLE = "role";
|
public static final String ROLE = "role";
|
||||||
public static final String THUMBPRINT = "thumbprint";
|
public static final String THUMBPRINT = "thumbprint";
|
||||||
public static final String HREF = "href";
|
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 COLLOQUIAL_VERSION = "colloquialVersion";
|
||||||
public static final String EDITION = "edition";
|
public static final String EDITION = "edition";
|
||||||
public static final String PRODUCT = "product";
|
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_FORMAT_MISSING = "supportRIMFormat missing";
|
||||||
public static final String SUPPORT_RIM_URI_GLOBAL = "supportRIMURIGlobal";
|
public static final String SUPPORT_RIM_URI_GLOBAL = "supportRIMURIGlobal";
|
||||||
public static final String DATETIME = "dateTime";
|
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 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 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 RFC3339_NS = "https://www.ietf.org/rfc/rfc3339.txt";
|
||||||
|
|
||||||
public static final String N8060_PFX = "n8060";
|
public static final String N8060_PFX = "n8060";
|
||||||
public static final String RIM_PFX = "rim";
|
public static final String RIM_PFX = "rim";
|
||||||
public static final String RFC3852_PFX = "rcf3852";
|
public static final String RFC3852_PFX = "rcf3852";
|
||||||
@ -119,7 +118,7 @@ public class SwidTagConstants {
|
|||||||
TCG_NS, PC_URI_LOCAL, RIM_PFX);
|
TCG_NS, PC_URI_LOCAL, RIM_PFX);
|
||||||
public static final QName _PC_URI_GLOBAL = new QName(
|
public static final QName _PC_URI_GLOBAL = new QName(
|
||||||
TCG_NS, PC_URI_GLOBAL, RIM_PFX);
|
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);
|
TCG_NS, RIM_LINK_HASH, RIM_PFX);
|
||||||
public static final QName _SUPPORT_RIM_TYPE = new QName(
|
public static final QName _SUPPORT_RIM_TYPE = new QName(
|
||||||
TCG_NS, SUPPORT_RIM_TYPE, RIM_PFX);
|
TCG_NS, SUPPORT_RIM_TYPE, RIM_PFX);
|
||||||
|
@ -84,7 +84,7 @@ public class SwidTagGateway {
|
|||||||
private Marshaller marshaller;
|
private Marshaller marshaller;
|
||||||
private String attributesFile;
|
private String attributesFile;
|
||||||
private boolean defaultCredentials;
|
private boolean defaultCredentials;
|
||||||
private String jksTruststoreFile;
|
private String truststoreFile;
|
||||||
private String pemPrivateKeyFile;
|
private String pemPrivateKeyFile;
|
||||||
private String pemCertificateFile;
|
private String pemCertificateFile;
|
||||||
private boolean embeddedCert;
|
private boolean embeddedCert;
|
||||||
@ -102,6 +102,7 @@ public class SwidTagGateway {
|
|||||||
marshaller = jaxbContext.createMarshaller();
|
marshaller = jaxbContext.createMarshaller();
|
||||||
attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE;
|
attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE;
|
||||||
defaultCredentials = true;
|
defaultCredentials = true;
|
||||||
|
truststoreFile = "";
|
||||||
pemCertificateFile = "";
|
pemCertificateFile = "";
|
||||||
embeddedCert = false;
|
embeddedCert = false;
|
||||||
rimEventLog = "";
|
rimEventLog = "";
|
||||||
@ -133,12 +134,12 @@ public class SwidTagGateway {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for JKS keystore file
|
* Setter for keystore file
|
||||||
*
|
*
|
||||||
* @param jksTruststoreFile
|
* @param truststoreFile
|
||||||
*/
|
*/
|
||||||
public void setJksTruststoreFile(final String jksTruststoreFile) {
|
public void setTruststoreFile(final String truststoreFile) {
|
||||||
this.jksTruststoreFile = jksTruststoreFile;
|
this.truststoreFile = truststoreFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,6 +180,7 @@ public class SwidTagGateway {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for timestamp format in XML signature
|
* Setter for timestamp format in XML signature
|
||||||
|
*
|
||||||
* @param timestampFormat
|
* @param timestampFormat
|
||||||
*/
|
*/
|
||||||
public void setTimestampFormat(String timestampFormat) {
|
public void setTimestampFormat(String timestampFormat) {
|
||||||
@ -187,6 +189,7 @@ public class SwidTagGateway {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for timestamp input - RFC3852 + file or RFC3339 + value
|
* Setter for timestamp input - RFC3852 + file or RFC3339 + value
|
||||||
|
*
|
||||||
* @param timestampArgument
|
* @param timestampArgument
|
||||||
*/
|
*/
|
||||||
public void setTimestampArgument(String timestampArgument) {
|
public void setTimestampArgument(String timestampArgument) {
|
||||||
@ -245,7 +248,7 @@ public class SwidTagGateway {
|
|||||||
writeSwidTagFile(signedSoftwareIdentity, filename);
|
writeSwidTagFile(signedSoftwareIdentity, filename);
|
||||||
} else {
|
} else {
|
||||||
System.out.println("The following fields cannot be empty or null: "
|
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);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
} catch (JsonException e) {
|
} catch (JsonException e) {
|
||||||
@ -531,6 +534,7 @@ public class SwidTagGateway {
|
|||||||
addNonNullAttribute(attributes, key, value);
|
addNonNullAttribute(attributes, key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This utility method checks if an attribute value is empty before adding it to the map.
|
* This utility method checks if an attribute value is empty before adding it to the map.
|
||||||
*
|
*
|
||||||
@ -593,14 +597,19 @@ public class SwidTagGateway {
|
|||||||
PrivateKey privateKey;
|
PrivateKey privateKey;
|
||||||
CredentialParser cp = new CredentialParser();
|
CredentialParser cp = new CredentialParser();
|
||||||
if (defaultCredentials) {
|
if (defaultCredentials) {
|
||||||
cp.parseJKSCredentials(jksTruststoreFile);
|
cp.parseDefaultCredentials();
|
||||||
privateKey = cp.getPrivateKey();
|
privateKey = cp.getPrivateKey();
|
||||||
KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier());
|
KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier());
|
||||||
keyInfoElements.add(keyName);
|
keyInfoElements.add(keyName);
|
||||||
} else {
|
} else {
|
||||||
cp.parsePEMCredentials(pemCertificateFile, pemPrivateKeyFile);
|
if (!truststoreFile.isEmpty()) {
|
||||||
X509Certificate certificate = cp.getCertificate();
|
List<X509Certificate> truststore = cp.parseCertsFromPEM(truststoreFile);
|
||||||
|
cp.parsePEMCredentials(truststore, pemPrivateKeyFile);
|
||||||
|
} else {
|
||||||
|
cp.parsePEMCredentials(pemCertificateFile, pemPrivateKeyFile);
|
||||||
|
}
|
||||||
privateKey = cp.getPrivateKey();
|
privateKey = cp.getPrivateKey();
|
||||||
|
X509Certificate certificate = cp.getCertificate();
|
||||||
if (embeddedCert) {
|
if (embeddedCert) {
|
||||||
ArrayList<Object> x509Content = new ArrayList<Object>();
|
ArrayList<Object> x509Content = new ArrayList<Object>();
|
||||||
x509Content.add(certificate.getSubjectX500Principal().getName());
|
x509Content.add(certificate.getSubjectX500Principal().getName());
|
||||||
@ -608,6 +617,8 @@ public class SwidTagGateway {
|
|||||||
X509Data data = kiFactory.newX509Data(x509Content);
|
X509Data data = kiFactory.newX509Data(x509Content);
|
||||||
keyInfoElements.add(data);
|
keyInfoElements.add(data);
|
||||||
} else {
|
} else {
|
||||||
|
KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier());
|
||||||
|
keyInfoElements.add(keyName);
|
||||||
keyInfoElements.add(kiFactory.newKeyValue(certificate.getPublicKey()));
|
keyInfoElements.add(kiFactory.newKeyValue(certificate.getPublicKey()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -646,7 +657,8 @@ public class SwidTagGateway {
|
|||||||
/**
|
/**
|
||||||
* This method creates a timestamp element and populates it with data according to
|
* 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.
|
* 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
|
* @param sigFactory the SignatureFactory object
|
||||||
* @return an XMLObject containing the timestamp element
|
* @return an XMLObject containing the timestamp element
|
||||||
*/
|
*/
|
||||||
@ -687,7 +699,7 @@ public class SwidTagGateway {
|
|||||||
SignatureProperties signatureProperties = sigFactory.newSignatureProperties(
|
SignatureProperties signatureProperties = sigFactory.newSignatureProperties(
|
||||||
Collections.singletonList(signatureProperty), null);
|
Collections.singletonList(signatureProperty), null);
|
||||||
XMLObject xmlObject = sigFactory.newXMLObject(
|
XMLObject xmlObject = sigFactory.newXMLObject(
|
||||||
Collections.singletonList(signatureProperties), null,null,null);
|
Collections.singletonList(signatureProperties), null, null, null);
|
||||||
|
|
||||||
return xmlObject;
|
return xmlObject;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ import javax.xml.transform.stream.StreamSource;
|
|||||||
import javax.xml.validation.Schema;
|
import javax.xml.validation.Schema;
|
||||||
import javax.xml.validation.SchemaFactory;
|
import javax.xml.validation.SchemaFactory;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
@ -74,6 +73,7 @@ public class SwidTagValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for rimel file path.
|
* Setter for rimel file path.
|
||||||
|
*
|
||||||
* @param rimEventLog the rimel file
|
* @param rimEventLog the rimel file
|
||||||
*/
|
*/
|
||||||
public void setRimEventLog(String rimEventLog) {
|
public void setRimEventLog(String rimEventLog) {
|
||||||
@ -82,6 +82,7 @@ public class SwidTagValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for the truststore file path.
|
* Setter for the truststore file path.
|
||||||
|
*
|
||||||
* @param trustStoreFile the truststore
|
* @param trustStoreFile the truststore
|
||||||
*/
|
*/
|
||||||
public void setTrustStoreFile(String trustStoreFile) {
|
public void setTrustStoreFile(String trustStoreFile) {
|
||||||
@ -99,6 +100,7 @@ public class SwidTagValidator {
|
|||||||
System.out.println("Error initializing JAXBContext: " + e.getMessage());
|
System.out.println("Error initializing JAXBContext: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method validates the .swidtag file at the given filepath against the
|
* 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
|
* 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
|
* @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);
|
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");
|
StringBuilder si = new StringBuilder("Base RIM detected:\n");
|
||||||
si.append("SoftwareIdentity name: " + softwareIdentity.getAttribute("name") + "\n");
|
si.append("SoftwareIdentity name: " + softwareIdentity.getAttribute("name") + "\n");
|
||||||
si.append("SoftwareIdentity tagId: " + softwareIdentity.getAttribute("tagId") + "\n");
|
si.append("SoftwareIdentity tagId: " + softwareIdentity.getAttribute("tagId") + "\n");
|
||||||
@ -120,8 +123,14 @@ public class SwidTagValidator {
|
|||||||
System.out.println(e.getMessage());
|
System.out.println(e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
System.out.println("Signature core validity: " + validateSignedXMLDocument(document));
|
boolean swidtagValidity = validateSignedXMLDocument(document, format);
|
||||||
return true;
|
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:
|
* Next, the signature is inspected for two things:
|
||||||
* 1. valid signature
|
* 1. valid signature
|
||||||
* 2. valid certificate chain
|
* 2. valid certificate chain
|
||||||
|
*
|
||||||
* @param doc XML document
|
* @param doc XML document
|
||||||
* @return true if both the signature and cert chain are valid; false otherwise
|
* @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 {
|
try {
|
||||||
DOMValidateContext context;
|
DOMValidateContext context;
|
||||||
CredentialParser cp = new CredentialParser();
|
CredentialParser cp = new CredentialParser();
|
||||||
X509Certificate signingCert = null;
|
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();
|
X509KeySelector keySelector = new X509KeySelector();
|
||||||
NodeList nodes = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
|
NodeList nodes = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
|
||||||
if (nodes.getLength() == 0) {
|
if (nodes.getLength() == 0) {
|
||||||
@ -190,7 +206,7 @@ public class SwidTagValidator {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Base RIM must have a non-empty, non-null " +
|
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);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,8 +220,6 @@ public class SwidTagValidator {
|
|||||||
cp.setCertificate(signingCert);
|
cp.setCertificate(signingCert);
|
||||||
System.out.println(System.lineSeparator() + cp.getCertificateAuthorityInfoAccess());
|
System.out.println(System.lineSeparator() + cp.getCertificateAuthorityInfoAccess());
|
||||||
return signatureIsValid;
|
return signatureIsValid;
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
System.out.println("Error parsing truststore: " + e.getMessage());
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
System.out.println("Error instantiating a KeyFactory to generate pk: "
|
System.out.println("Error instantiating a KeyFactory to generate pk: "
|
||||||
+ e.getMessage());
|
+ e.getMessage());
|
||||||
@ -214,7 +228,7 @@ public class SwidTagValidator {
|
|||||||
} catch (MarshalException | XMLSignatureException e) {
|
} catch (MarshalException | XMLSignatureException e) {
|
||||||
System.out.println(e.getMessage());
|
System.out.println(e.getMessage());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println(e.getMessage());
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -239,7 +253,8 @@ public class SwidTagValidator {
|
|||||||
* This method extracts a public key from either an X509Certificate element
|
* This method extracts a public key from either an X509Certificate element
|
||||||
* or a KeyValue element. If the public key's algorithm matches the declared
|
* or a KeyValue element. If the public key's algorithm matches the declared
|
||||||
* algorithm it is returned in a KeySelecctorResult.
|
* algorithm it is returned in a KeySelecctorResult.
|
||||||
* @param keyinfo the KeyInfo element
|
*
|
||||||
|
* @param keyinfo the KeyInfo element
|
||||||
* @param purpose
|
* @param purpose
|
||||||
* @param algorithm the encapsulating signature's declared signing algorithm
|
* @param algorithm the encapsulating signature's declared signing algorithm
|
||||||
* @param context
|
* @param context
|
||||||
@ -250,9 +265,9 @@ public class SwidTagValidator {
|
|||||||
final KeySelector.Purpose purpose,
|
final KeySelector.Purpose purpose,
|
||||||
final AlgorithmMethod algorithm,
|
final AlgorithmMethod algorithm,
|
||||||
final XMLCryptoContext context)
|
final XMLCryptoContext context)
|
||||||
throws KeySelectorException {
|
throws KeySelectorException {
|
||||||
Iterator keyinfoItr = keyinfo.getContent().iterator();
|
Iterator keyinfoItr = keyinfo.getContent().iterator();
|
||||||
while(keyinfoItr.hasNext()) {
|
while (keyinfoItr.hasNext()) {
|
||||||
XMLStructure element = (XMLStructure) keyinfoItr.next();
|
XMLStructure element = (XMLStructure) keyinfoItr.next();
|
||||||
if (element instanceof X509Data) {
|
if (element instanceof X509Data) {
|
||||||
X509Data data = (X509Data) element;
|
X509Data data = (X509Data) element;
|
||||||
@ -302,7 +317,8 @@ public class SwidTagValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks that the signature and public key algorithms match.
|
* 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
|
* @param name to match the public key algorithm
|
||||||
* @return true if both match, false otherwise
|
* @return true if both match, false otherwise
|
||||||
*/
|
*/
|
||||||
@ -314,6 +330,7 @@ public class SwidTagValidator {
|
|||||||
/**
|
/**
|
||||||
* This method validates the cert chain for a given certificate. The truststore is iterated
|
* 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.
|
* over until a root CA is found, otherwise an error is returned.
|
||||||
|
*
|
||||||
* @param cert the certificate at the start of the chain
|
* @param cert the certificate at the start of the chain
|
||||||
* @return true if the chain is valid
|
* @return true if the chain is valid
|
||||||
* @throws Exception if a valid chain is not found in the truststore
|
* @throws Exception if a valid chain is not found in the truststore
|
||||||
@ -356,7 +373,8 @@ public class SwidTagValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks if cert's issuerDN matches issuer's subjectDN.
|
* 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
|
* @param issuer the signing certificate
|
||||||
* @return true if they match, false if not
|
* @return true if they match, false if not
|
||||||
* @throws Exception if either argument is null
|
* @throws Exception if either argument is null
|
||||||
@ -372,7 +390,8 @@ public class SwidTagValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks if cert's signature matches signer's public key.
|
* 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
|
* @param signer the signing certificate
|
||||||
* @return true if they match
|
* @return true if they match
|
||||||
* @throws Exception if an error occurs or there is no match
|
* @throws Exception if an error occurs or there is no match
|
||||||
@ -404,6 +423,7 @@ public class SwidTagValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks if a given certificate is self signed or not.
|
* This method checks if a given certificate is self signed or not.
|
||||||
|
*
|
||||||
* @param cert the cert to check
|
* @param cert the cert to check
|
||||||
* @return true if self signed, false if not
|
* @return true if self signed, false if not
|
||||||
*/
|
*/
|
||||||
@ -413,6 +433,7 @@ public class SwidTagValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method compares a public key against those in the truststore.
|
* This method compares a public key against those in the truststore.
|
||||||
|
*
|
||||||
* @param pk a public key
|
* @param pk a public key
|
||||||
* @return true if pk is found in the trust store, false otherwise
|
* @return true if pk is found in the trust store, false otherwise
|
||||||
*/
|
*/
|
||||||
@ -485,6 +506,7 @@ public class SwidTagValidator {
|
|||||||
/**
|
/**
|
||||||
* This method strips all whitespace from an xml file, including indents and spaces
|
* This method strips all whitespace from an xml file, including indents and spaces
|
||||||
* added for human-readability.
|
* added for human-readability.
|
||||||
|
*
|
||||||
* @param path to the xml file
|
* @param path to the xml file
|
||||||
* @return Document object without whitespace
|
* @return Document object without whitespace
|
||||||
*/
|
*/
|
||||||
|
@ -19,33 +19,33 @@ public class Commander {
|
|||||||
private String createType = "";
|
private String createType = "";
|
||||||
@Parameter(names = {"-a", "--attributes <path>"}, order = 1,
|
@Parameter(names = {"-a", "--attributes <path>"}, order = 1,
|
||||||
description = "The configuration file holding attributes "
|
description = "The configuration file holding attributes "
|
||||||
+ "to populate the base RIM with.")
|
+ "to populate the base RIM with.")
|
||||||
private String attributesFile = "";
|
private String attributesFile = "";
|
||||||
@Parameter(names = {"-o", "--out <path>"}, order = 2,
|
@Parameter(names = {"-o", "--out <path>"}, order = 2,
|
||||||
description = "The file to write the RIM out to. "
|
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 = "";
|
private String outFile = "";
|
||||||
@Parameter(names = {"-v", "--verify <path>"}, order = 3,
|
@Parameter(names = {"-v", "--verify <path>"}, order = 3,
|
||||||
description = "Specify a RIM file to verify.")
|
description = "Specify a RIM file to verify.")
|
||||||
private String verifyFile = "";
|
private String verifyFile = "";
|
||||||
@Parameter(names = {"-t", "--truststore <path>"}, order = 4,
|
@Parameter(names = {"-t", "--truststore <path>"}, order = 4,
|
||||||
description = "The truststore to sign the base RIM created "
|
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 = "";
|
private String truststoreFile = "";
|
||||||
@Parameter(names = {"-k", "--privateKeyFile <path>"}, order = 5,
|
@Parameter(names = {"-k", "--privateKeyFile <path>"}, order = 5,
|
||||||
description = "The private key used to sign the base RIM created by this tool.")
|
description = "The private key used to sign the base RIM created by this tool.")
|
||||||
private String privateKeyFile = "";
|
private String privateKeyFile = "";
|
||||||
@Parameter(names = {"-p", "--publicCertificate <path>"}, order = 6,
|
@Parameter(names = {"-p", "--publicCertificate <path>"}, order = 6,
|
||||||
description = "The public key certificate to embed in the base RIM created by "
|
description = "The public key certificate to embed in the base RIM created by "
|
||||||
+ "this tool.")
|
+ "this tool.")
|
||||||
private String publicCertificate = "";
|
private String publicCertificate = "";
|
||||||
@Parameter(names = {"-e", "--embed-cert"}, order = 7,
|
@Parameter(names = {"-e", "--embed-cert"}, order = 7,
|
||||||
description = "Embed the provided certificate in the signed swidtag.")
|
description = "Embed the provided certificate in the signed swidtag.")
|
||||||
private boolean embedded = false;
|
private boolean embedded = false;
|
||||||
@Parameter(names = {"-d", "--default-key"}, order = 8,
|
@Parameter(names = {"-d", "--default-key"}, order = 8,
|
||||||
description = "Use default signing credentials.")
|
description = "Use keystore.jks from the rimtool installation to sign.")
|
||||||
private boolean defaultKey = false;
|
private boolean defaultKey = false;
|
||||||
@Parameter(names = {"-l", "--rimel <path>"}, order = 9,
|
@Parameter(names = {"-l", "--rimel <path>"}, order = 9, required = true,
|
||||||
description = "The TCG eventlog file to use as a support RIM.")
|
description = "The TCG eventlog file to use as a support RIM.")
|
||||||
private String rimEventLog = "";
|
private String rimEventLog = "";
|
||||||
@Parameter(names = {"--timestamp"}, order = 10, variableArity = true,
|
@Parameter(names = {"--timestamp"}, order = 10, variableArity = true,
|
||||||
@ -74,7 +74,9 @@ public class Commander {
|
|||||||
return verifyFile;
|
return verifyFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTruststoreFile() { return truststoreFile; }
|
public String getTruststoreFile() {
|
||||||
|
return truststoreFile;
|
||||||
|
}
|
||||||
|
|
||||||
public String getPrivateKeyFile() {
|
public String getPrivateKeyFile() {
|
||||||
return privateKeyFile;
|
return privateKeyFile;
|
||||||
@ -84,11 +86,17 @@ public class Commander {
|
|||||||
return publicCertificate;
|
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() {
|
public List<String> getTimestampArguments() {
|
||||||
return timestampArguments;
|
return timestampArguments;
|
||||||
@ -119,25 +127,22 @@ public class Commander {
|
|||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Creating: " + this.getCreateType() + System.lineSeparator());
|
sb.append("Creating: " + this.getCreateType() + System.lineSeparator());
|
||||||
sb.append("Using attributes file: " + this.getAttributesFile() + System.lineSeparator());
|
sb.append("Using attributes file: " + this.getAttributesFile() + System.lineSeparator());
|
||||||
sb.append("Write to: " + this.getOutFile() + System.lineSeparator());
|
sb.append("Write to: " + this.getOutFile() + System.lineSeparator());
|
||||||
sb.append("Verify file: " + this.getVerifyFile() + System.lineSeparator());
|
sb.append("Verify file: " + this.getVerifyFile() + System.lineSeparator());
|
||||||
if (!this.getTruststoreFile().isEmpty()) {
|
if (this.isDefaultKey()) {
|
||||||
|
sb.append("Truststore file: default (" + SwidTagConstants.DEFAULT_KEYSTORE_FILE + ")"
|
||||||
|
+ System.lineSeparator());
|
||||||
|
} else {
|
||||||
sb.append("Truststore file: " + this.getTruststoreFile() + System.lineSeparator());
|
sb.append("Truststore file: " + this.getTruststoreFile() + System.lineSeparator());
|
||||||
} else if (!this.getPrivateKeyFile().isEmpty() &&
|
|
||||||
!this.getPublicCertificate().isEmpty()) {
|
|
||||||
sb.append("Private key file: " + this.getPrivateKeyFile() + System.lineSeparator());
|
sb.append("Private key file: " + this.getPrivateKeyFile() + System.lineSeparator());
|
||||||
sb.append("Public certificate: " + this.getPublicCertificate()
|
sb.append("Public certificate: " + this.getPublicCertificate()
|
||||||
+ System.lineSeparator());
|
+ System.lineSeparator());
|
||||||
sb.append("Embedded certificate: " + this.isEmbedded() + System.lineSeparator());
|
sb.append("Embedded certificate: " + this.isEmbedded() + System.lineSeparator());
|
||||||
} else if (this.isDefaultKey()){
|
|
||||||
sb.append("Truststore file: default (" + SwidTagConstants.DEFAULT_KEYSTORE_FILE + ")"
|
|
||||||
+ System.lineSeparator());
|
|
||||||
} else {
|
|
||||||
sb.append("Signing credential: (none given)" + System.lineSeparator());
|
|
||||||
}
|
}
|
||||||
sb.append("Event log support RIM: " + this.getRimEventLog() + System.lineSeparator());
|
sb.append("Event log support RIM: " + this.getRimEventLog() + System.lineSeparator());
|
||||||
List<String> timestampArguments = this.getTimestampArguments();
|
List<String> timestampArguments = this.getTimestampArguments();
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
package hirs.swid.utils;
|
||||||
|
|
||||||
|
public class CredentialArgumentValidator {
|
||||||
|
private String truststoreFile;
|
||||||
|
private String certificateFile;
|
||||||
|
private String privateKeyFile;
|
||||||
|
private String password;
|
||||||
|
private String alias;
|
||||||
|
private String format;
|
||||||
|
private boolean isValidating;
|
||||||
|
private String errorMessage;
|
||||||
|
private static final String JKS = "JKS";
|
||||||
|
private static final String PEM = "PEM";
|
||||||
|
|
||||||
|
public CredentialArgumentValidator(String truststoreFile,
|
||||||
|
String certificateFile,
|
||||||
|
String privateKeyFile,
|
||||||
|
String password,
|
||||||
|
String alias,
|
||||||
|
boolean isValidating) {
|
||||||
|
this.truststoreFile = truststoreFile;
|
||||||
|
this.certificateFile = certificateFile;
|
||||||
|
this.privateKeyFile = privateKeyFile;
|
||||||
|
this.password = password;
|
||||||
|
this.alias = alias;
|
||||||
|
this.isValidating = isValidating;
|
||||||
|
errorMessage = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for format property
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public String getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for error message
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks for the following valid configurations of input arguments:
|
||||||
|
* 1. truststore + password + alias (JKS format)
|
||||||
|
* 2. truststore + private key (PEM format)
|
||||||
|
* 3. truststore only for validating (PEM format)
|
||||||
|
* 4. certificate + private key (PEM format)
|
||||||
|
* 5. certificate only for validating (PEM format)
|
||||||
|
*
|
||||||
|
* @return true if the above are found, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isValid() {
|
||||||
|
if (!truststoreFile.isEmpty()) {
|
||||||
|
if (!password.isEmpty() && !alias.isEmpty()) {
|
||||||
|
format = JKS;
|
||||||
|
return true;
|
||||||
|
} else if (!privateKeyFile.isEmpty() || isValidating) {
|
||||||
|
format = PEM;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
errorMessage = "A JKS truststore needs a password and alias; " +
|
||||||
|
"a PEM truststore needs a private key file.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) {
|
||||||
|
format = PEM;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
errorMessage = "A public certificate must be accompanied by a private key file.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
public class TimestampArgumentValidator {
|
public class TimestampArgumentValidator {
|
||||||
List<String> args;
|
List<String> args;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles validation of the --timestamp commandline parameter.
|
* This class handles validation of the --timestamp commandline parameter.
|
||||||
* Currently only RFC3339 and RFC3852 formats are supported.
|
* Currently only RFC3339 and RFC3852 formats are supported.
|
||||||
@ -35,7 +36,7 @@ public class TimestampArgumentValidator {
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (args.size() == 1){
|
} else if (args.size() == 1) {
|
||||||
System.out.println("Countersignature file is required for RFC3852 timestamps");
|
System.out.println("Countersignature file is required for RFC3852 timestamps");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,200 +1,213 @@
|
|||||||
package hirs.swid;
|
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.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
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 {
|
public class TestSwidTagGateway {
|
||||||
private SwidTagGateway gateway;
|
private SwidTagGateway gateway;
|
||||||
private SwidTagValidator validator;
|
private SwidTagValidator validator;
|
||||||
private final String DEFAULT_OUTPUT = "generated_swidTag.swidtag";
|
private final String JKS = "JKS";
|
||||||
private final String BASE_USER_CERT = "generated_user_cert.swidtag";
|
private final String PEM = "PEM";
|
||||||
private final String BASE_USER_CERT_EMBED = "generated_user_cert_embed.swidtag";
|
private final String DEFAULT_OUTPUT = "generated_swidTag.swidtag";
|
||||||
private final String BASE_DEFAULT_CERT = "generated_default_cert.swidtag";
|
private final String BASE_USER_CERT = "generated_user_cert.swidtag";
|
||||||
private final String BASE_RFC3339_TIMESTAMP = "generated_timestamp_rfc3339.swidtag";
|
private final String BASE_USER_CERT_EMBED = "generated_user_cert_embed.swidtag";
|
||||||
private final String BASE_RFC3852_TIMESTAMP = "generated_timestamp_rfc3852.swidtag";
|
private final String BASE_TRUSTSTORE_EMBED = "generated_truststore_embed.swidtag";
|
||||||
private final String ATTRIBUTES_FILE = TestSwidTagGateway.class.getClassLoader()
|
private final String BASE_DEFAULT_CERT = "generated_default_cert.swidtag";
|
||||||
.getResource("rim_fields.json").getPath();
|
private final String BASE_RFC3339_TIMESTAMP = "generated_timestamp_rfc3339.swidtag";
|
||||||
private final String JKS_KEYSTORE_FILE = TestSwidTagGateway.class.getClassLoader()
|
private final String BASE_RFC3852_TIMESTAMP = "generated_timestamp_rfc3852.swidtag";
|
||||||
.getResource("keystore.jks").getPath();
|
private final String ATTRIBUTES_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
private final String SIGNING_CERT_FILE = TestSwidTagGateway.class.getClassLoader()
|
.getResource("rim_fields.json").getPath();
|
||||||
.getResource("RimSignCert.pem").getPath();
|
private final String JKS_KEYSTORE_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
private final String PRIVATE_KEY_FILE = TestSwidTagGateway.class.getClassLoader()
|
.getResource("keystore.jks").getPath();
|
||||||
.getResource("privateRimKey.pem").getPath();
|
private final String SIGNING_CERT_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
private final String CA_CHAIN_FILE = TestSwidTagGateway.class.getClassLoader()
|
.getResource("RimSignCert.pem").getPath();
|
||||||
.getResource("RimCertChain.pem").getPath();
|
private final String PRIVATE_KEY_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
private final String SUPPORT_RIM_FILE = TestSwidTagGateway.class.getClassLoader()
|
.getResource("privateRimKey.pem").getPath();
|
||||||
.getResource("TpmLog.bin").getPath();
|
private final String CA_CHAIN_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
private final String RFC3852_COUNTERSIGNATURE_FILE = TestSwidTagGateway.class.getClassLoader()
|
.getResource("RimCertChain.pem").getPath();
|
||||||
.getResource("counterSignature.file").getPath();
|
private final String SUPPORT_RIM_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
private InputStream expectedFile;
|
.getResource("TpmLog.bin").getPath();
|
||||||
|
private final String RFC3852_COUNTERSIGNATURE_FILE = TestSwidTagGateway.class.getClassLoader()
|
||||||
|
.getResource("counterSignature.file").getPath();
|
||||||
|
private InputStream expectedFile;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
gateway = new SwidTagGateway();
|
gateway = new SwidTagGateway();
|
||||||
gateway.setRimEventLog(SUPPORT_RIM_FILE);
|
gateway.setRimEventLog(SUPPORT_RIM_FILE);
|
||||||
gateway.setAttributesFile(ATTRIBUTES_FILE);
|
gateway.setAttributesFile(ATTRIBUTES_FILE);
|
||||||
validator = new SwidTagValidator();
|
validator = new SwidTagValidator();
|
||||||
validator.setRimEventLog(SUPPORT_RIM_FILE);
|
validator.setRimEventLog(SUPPORT_RIM_FILE);
|
||||||
validator.setTrustStoreFile(CA_CHAIN_FILE);
|
validator.setTrustStoreFile(CA_CHAIN_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
if (expectedFile != null) {
|
if (expectedFile != null) {
|
||||||
expectedFile.close();
|
expectedFile.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test corresponds to the arguments:
|
* This test corresponds to the arguments:
|
||||||
* -c base -l TpmLog.bin -k privateRimKey.pem -p RimSignCert.pem
|
* -c base -l TpmLog.bin -k privateRimKey.pem -p RimSignCert.pem
|
||||||
* where RimSignCert.pem has the AIA extension.
|
* where RimSignCert.pem has the AIA extension.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreateBaseUserCertNotEmbedded() {
|
public void testCreateBasePemCertNotEmbedded() {
|
||||||
gateway.setDefaultCredentials(false);
|
gateway.setDefaultCredentials(false);
|
||||||
gateway.setPemCertificateFile(SIGNING_CERT_FILE);
|
gateway.setPemCertificateFile(SIGNING_CERT_FILE);
|
||||||
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
|
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
|
||||||
gateway.setEmbeddedCert(false);
|
gateway.setEmbeddedCert(false);
|
||||||
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
||||||
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
||||||
.getResourceAsStream(BASE_USER_CERT);
|
.getResourceAsStream(BASE_USER_CERT);
|
||||||
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
||||||
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
|
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, PEM));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test creates the following base RIM:
|
* This test creates the following base RIM:
|
||||||
* -c base -l TpmLog.bin -k privateRimKey.pem -p RimSignCert.pem -e
|
* -c base -l TpmLog.bin -k privateRimKey.pem -p RimSignCert.pem -e
|
||||||
* And then validates it:
|
* And then validates it:
|
||||||
* -v [base RIM] -l TpmLog.bin -t RimCertChain.pem
|
* -v [base RIM] -l TpmLog.bin -t RimCertChain.pem
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreateBaseUserCertEmbedded() {
|
public void testCreateBasePemCertEmbedded() {
|
||||||
gateway.setDefaultCredentials(false);
|
gateway.setDefaultCredentials(false);
|
||||||
gateway.setPemCertificateFile(SIGNING_CERT_FILE);
|
gateway.setTruststoreFile("");
|
||||||
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
|
gateway.setPemCertificateFile(SIGNING_CERT_FILE);
|
||||||
gateway.setEmbeddedCert(true);
|
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
|
||||||
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
gateway.setEmbeddedCert(true);
|
||||||
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
||||||
.getResourceAsStream(BASE_USER_CERT_EMBED);
|
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
||||||
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
.getResourceAsStream(BASE_USER_CERT_EMBED);
|
||||||
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
|
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
||||||
}
|
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, PEM));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test corresponds to the arguments:
|
* This test corresponds to:
|
||||||
* -c base -l TpmLog.bin -d
|
* -c base -l TpmLog.bin -t RimCertChain.pem -k privateRimKey.pem -e
|
||||||
*/
|
* And then validates it:
|
||||||
@Test
|
* -v [base RIM] -l TpmLog.bin -t RimCertChain.pem
|
||||||
public void testCreateBaseDefaultCert() {
|
*/
|
||||||
gateway.setDefaultCredentials(true);
|
@Test
|
||||||
gateway.setJksTruststoreFile(JKS_KEYSTORE_FILE);
|
public void testCreateBasePemTruststoreEmbedded() {
|
||||||
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
gateway.setDefaultCredentials(false);
|
||||||
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
gateway.setTruststoreFile(CA_CHAIN_FILE);
|
||||||
.getResourceAsStream(BASE_DEFAULT_CERT);
|
gateway.setPemCertificateFile("");
|
||||||
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
|
||||||
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
|
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:
|
* This test corresponds to the arguments:
|
||||||
* -c base -l TpmLog.bin -d --timestamp rfc3339 2023-01-01T00:00:00Z
|
* -c base -l TpmLog.bin -d
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreateTimestampRfc3339() {
|
public void testCreateBaseDefaultCert() {
|
||||||
gateway.setDefaultCredentials(true);
|
gateway.setDefaultCredentials(true);
|
||||||
gateway.setJksTruststoreFile(JKS_KEYSTORE_FILE);
|
gateway.setTruststoreFile(JKS_KEYSTORE_FILE);
|
||||||
gateway.setTimestampFormat("RFC3339");
|
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
||||||
gateway.setTimestampArgument("2023-01-01T00:00:00Z");
|
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
||||||
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
.getResourceAsStream(BASE_DEFAULT_CERT);
|
||||||
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
||||||
.getResourceAsStream(BASE_RFC3339_TIMESTAMP);
|
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, "DEFAULT"));
|
||||||
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
}
|
||||||
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test corresponds to the arguments:
|
* This test corresponds to the arguments:
|
||||||
* -c base -l TpmLog.bin -d --timestamp rfc3852 countersignature.file
|
* -c base -l TpmLog.bin -d --timestamp rfc3339 2023-01-01T00:00:00Z
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreateTimestampRfc3852() {
|
public void testCreateTimestampRfc3339() {
|
||||||
gateway.setDefaultCredentials(true);
|
gateway.setDefaultCredentials(true);
|
||||||
gateway.setJksTruststoreFile(JKS_KEYSTORE_FILE);
|
gateway.setTruststoreFile(JKS_KEYSTORE_FILE);
|
||||||
gateway.setTimestampFormat("RFC3852");
|
gateway.setTimestampFormat("RFC3339");
|
||||||
gateway.setTimestampArgument(RFC3852_COUNTERSIGNATURE_FILE);
|
gateway.setTimestampArgument("2023-01-01T00:00:00Z");
|
||||||
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
||||||
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
expectedFile = TestSwidTagGateway.class.getClassLoader()
|
||||||
.getResourceAsStream(BASE_RFC3852_TIMESTAMP);
|
.getResourceAsStream(BASE_RFC3339_TIMESTAMP);
|
||||||
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
||||||
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT));
|
Assert.assertTrue(validator.validateSwidTag(DEFAULT_OUTPUT, "DEFAULT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test corresponds to the arguments:
|
* This test corresponds to the arguments:
|
||||||
* -v <path>
|
* -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, "DEFAULT"));
|
||||||
|
}
|
||||||
|
|
||||||
public void testValidateSwidTag() {
|
/**
|
||||||
String filepath = TestSwidTagGateway.class.getClassLoader()
|
* This method compares two files by bytes to determine if they are the same or not.
|
||||||
.getResource(BASE_USER_CERT).getPath();
|
*
|
||||||
System.out.println("Validating file at " + filepath);
|
* @param file to be compared to the expected value.
|
||||||
Assert.assertTrue(validator.validateSwidTag(filepath));
|
* @return true if they are equal, false if not.
|
||||||
}
|
*/
|
||||||
|
private boolean compareFileBytesToExpectedFile(String file) {
|
||||||
/**
|
FileInputStream testFile = null;
|
||||||
* This method compares two files by bytes to determine if they are the same or not.
|
try {
|
||||||
* @param file to be compared to the expected value.
|
int data;
|
||||||
* @return true if they are equal, false if not.
|
testFile = new FileInputStream(file);
|
||||||
*/
|
while ((data = testFile.read()) != -1) {
|
||||||
private boolean compareFileBytesToExpectedFile(String file) {
|
int expected = expectedFile.read();
|
||||||
FileInputStream testFile = null;
|
if (data != expected) {
|
||||||
try {
|
System.out.println("Expected: " + expected);
|
||||||
int data;
|
System.out.println("Got: " + data);
|
||||||
testFile = new FileInputStream(file);
|
return false;
|
||||||
while ((data = testFile.read()) != -1) {
|
}
|
||||||
int expected = expectedFile.read();
|
}
|
||||||
if (data != expected) {
|
} catch (FileNotFoundException e) {
|
||||||
System.out.println("Expected: " + expected);
|
e.printStackTrace();
|
||||||
System.out.println("Got: " + data);
|
return false;
|
||||||
return false;
|
} catch (IOException e) {
|
||||||
}
|
e.printStackTrace();
|
||||||
}
|
return false;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (NullPointerException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
} catch (IOException e) {
|
} finally {
|
||||||
e.printStackTrace();
|
if (testFile != null) {
|
||||||
return false;
|
try {
|
||||||
} catch (NullPointerException e) {
|
testFile.close();
|
||||||
e.printStackTrace();
|
} catch (IOException e) {
|
||||||
return false;
|
e.printStackTrace();
|
||||||
} finally {
|
return false;
|
||||||
if (testFile != null) {
|
}
|
||||||
try {
|
}
|
||||||
testFile.close();
|
if (expectedFile != null) {
|
||||||
} catch (IOException e) {
|
try {
|
||||||
e.printStackTrace();
|
expectedFile.close();
|
||||||
return false;
|
} catch (IOException e) {
|
||||||
}
|
e.printStackTrace();
|
||||||
}
|
return false;
|
||||||
if (expectedFile != null) {
|
}
|
||||||
try {
|
}
|
||||||
expectedFile.close();
|
}
|
||||||
} catch (IOException e) {
|
return true;
|
||||||
e.printStackTrace();
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<SoftwareIdentity xmlns="http://standards.iso.org/iso/19770/-2/2015/schema.xsd" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" corpus="false" name="Example.com BIOS" patch="false" supplemental="false" tagId="94f6b457-9ac9-4d35-9b3f-78804173b65as" tagVersion="0" version="01" versionScheme="multipartnumeric" xml:lang="en">
|
||||||
|
<Entity name="Example Inc" regid="http://Example.com" role="softwareCreator tagCreator"/>
|
||||||
|
<Link href="https://Example.com/support/ProductA/firmware/installfiles" rel="installationmedia"/>
|
||||||
|
<Meta xmlns:n8060="http://csrc.nist.gov/ns/swid/2015-extensions/1.0" xmlns:rim="https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model" n8060:colloquialVersion="Firmware_2019" n8060:edition="12" n8060:product="ProductA" n8060:revision="r2" rim:PayloadType="direct" rim:bindingSpec="PC Client RIM" rim:bindingSpecVersion="1.2" rim:firmwareManufacturerId="00213022" rim:firmwareManufacturerStr="BIOSVendorA" rim:firmwareModel="A0" rim:firmwareVersion="12" rim:pcURIGlobal="https://Example.com/support/ProductA/" rim:pcURIlocal="/boot/tcg/manifest/switag/" rim:platformManufacturerId="00201234" rim:platformManufacturerStr="Example.com" rim:platformModel="ProductA" rim:platformVersion="01"/>
|
||||||
|
<Payload>
|
||||||
|
<Directory name="rim">
|
||||||
|
<File xmlns:SHA256="http://www.w3.org/2001/04/xmlenc#sha256" SHA256:hash="4479ca722623f8c47b703996ced3cbd981b06b1ae8a897db70137e0b7c546848" name="Example.com.BIOS.01.rimel" size="7549"/>
|
||||||
|
</Directory>
|
||||||
|
</Payload>
|
||||||
|
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||||
|
<SignedInfo>
|
||||||
|
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||||
|
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
|
||||||
|
<Reference URI="">
|
||||||
|
<Transforms>
|
||||||
|
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||||
|
</Transforms>
|
||||||
|
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||||
|
<DigestValue>DJMc0n3VHHwU+F3HNpiY/l3EMcjRZAQOYlrjhD5v9qE=</DigestValue>
|
||||||
|
</Reference>
|
||||||
|
</SignedInfo>
|
||||||
|
<SignatureValue>ojJ6v8ToxLWWekCKmBoZ+Yg2V4MYMPbKB9FjDs/QG/AMP+LKjnb55Z7FSLhC8+CvvShKPAoS9mv1
|
||||||
|
QepwI17NEqbfnC1U4WH0u578A3J6wiHMXIDnIQqKAAXb8v2c/wjMDArzFl8CXmDA7HUDIt+3C4VC
|
||||||
|
tA598YY7o0Hf6hK5qO8oWGQxXUKfpUwvtGLxHpbDWYFuVSPa+uk6OTzutt/QyzTERzxyO9Le1i6K
|
||||||
|
nrpzh4lgHn6EfGs6HR1ffdHQ069q0bE61zDx0VC18nK9DmszW6p6FlMzApiTVW/4PiVt+dSFeVGR
|
||||||
|
9///OdtxcoBCeofDDFPRyO+s+kY1pXd92Q3nfg==</SignatureValue>
|
||||||
|
<KeyInfo>
|
||||||
|
<X509Data>
|
||||||
|
<X509SubjectName>CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US</X509SubjectName>
|
||||||
|
<X509Certificate>MIIDoTCCAomgAwIBAgIJAIKly+6bklZlMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAlVTMQsw
|
||||||
|
CQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxEjAQBgNVBAMM
|
||||||
|
CUV4YW1wbGVDQTAeFw0yMDA2MTExNjUzMDFaFw0zMDA0MjAxNjUzMDFaMFwxCzAJBgNVBAYTAlVT
|
||||||
|
MQswCQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxGzAZBgNV
|
||||||
|
BAMMEmV4YW1wbGUuUklNLnNpZ25lcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKd1
|
||||||
|
lWGkSRuxAAY2wHag2GVxUk1dZx2PTpfQOflvLeccAVwa8mQhlsRERq+QK8ilj8Xfqs44/nBaccZD
|
||||||
|
OjdfIxIUCMfwhGXjxCaqZbgTucNsExDnu4arTGraoAwzHg0cVLiKT/Cxj9NL4dcMgxRXsPdHfXb0
|
||||||
|
923C7xYd2t2qfW05umgaj7qeQl6c68CFNsGX4JA8rWFQZvvGx5DGlK4KTcjPuQQINs5fxasNKqLY
|
||||||
|
2hq+z82x/rqwr2hmyizD6FpFSyIABPEMPfB036GEhRwu1WEMkq8yIp2jgRUoFYke9pB3ph9pVow0
|
||||||
|
Hh4mNFSKD4pP41VSKY1nus83mdkuukPy5o0CAwEAAaNvMG0wHQYDVR0OBBYEFC/euOfQMKIgnaoB
|
||||||
|
hhqWT+3s8rzBMB8GA1UdIwQYMBaAFEahuO3bpnFf0NLneoo8XW6aw5Y4MAkGA1UdEwQCMAAwCwYD
|
||||||
|
VR0PBAQDAgbAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQC1mG0naE0W
|
||||||
|
4E9vujPhygf7LXHMFkMPs5uWyvkxe4zWgTg0RHTClbOFJQJ+pGLOcthSG6vIC6xYJxT5EKtB9rzR
|
||||||
|
lEYHOi4MxuwXz9rLWQhA2zdbSo54Fb/BPoca5K9kxvAanRltEfqEFhCcRmqIX1i6mpOWiZsrdMs7
|
||||||
|
IflHKBsylUTn+v636BAz3p2H8/lpJbF4LUFUxFU5FWB3tLuasxYTsbeE6YyNAnQIS95ML7c5H8z2
|
||||||
|
aEQs5TCNHZJDyc0PZT2aPOuEj5lGv9oyBHbYDitszUWSVxF7z86uVGmYR/2oTIj6tqb+IwuvFtnO
|
||||||
|
wiXFRS5ctLCdESr3SjdQF5wmIN4n</X509Certificate>
|
||||||
|
</X509Data>
|
||||||
|
</KeyInfo>
|
||||||
|
</Signature>
|
||||||
|
</SoftwareIdentity>
|
@ -26,6 +26,7 @@ tA598YY7o0Hf6hK5qO8oWGQxXUKfpUwvtGLxHpbDWYFuVSPa+uk6OTzutt/QyzTERzxyO9Le1i6K
|
|||||||
nrpzh4lgHn6EfGs6HR1ffdHQ069q0bE61zDx0VC18nK9DmszW6p6FlMzApiTVW/4PiVt+dSFeVGR
|
nrpzh4lgHn6EfGs6HR1ffdHQ069q0bE61zDx0VC18nK9DmszW6p6FlMzApiTVW/4PiVt+dSFeVGR
|
||||||
9///OdtxcoBCeofDDFPRyO+s+kY1pXd92Q3nfg==</SignatureValue>
|
9///OdtxcoBCeofDDFPRyO+s+kY1pXd92Q3nfg==</SignatureValue>
|
||||||
<KeyInfo>
|
<KeyInfo>
|
||||||
|
<KeyName>2fdeb8e7d030a2209daa01861a964fedecf2bcc1</KeyName>
|
||||||
<KeyValue>
|
<KeyValue>
|
||||||
<RSAKeyValue>
|
<RSAKeyValue>
|
||||||
<Modulus>p3WVYaRJG7EABjbAdqDYZXFSTV1nHY9Ol9A5+W8t5xwBXBryZCGWxERGr5AryKWPxd+qzjj+cFpx
|
<Modulus>p3WVYaRJG7EABjbAdqDYZXFSTV1nHY9Ol9A5+W8t5xwBXBryZCGWxERGr5AryKWPxd+qzjj+cFpx
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user