mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-05-02 08:43:00 +00:00
Merge pull request #380 from nsacyber/issue-375
[#375] WIP: Add cert path validation to tcg_rim_tool
This commit is contained in:
commit
be155ef89c
@ -1,5 +1,5 @@
|
|||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
version = '2.0.0'
|
version = '2.1.0'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
# Calls the the_tcg_rim_tool and passes in parameters
|
# Calls the the_tcg_rim_tool and passes in parameters
|
||||||
scriptDir=$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")
|
scriptDir=$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")
|
||||||
baseDir=${scriptDir%/*}
|
baseDir=${scriptDir%/*}
|
||||||
jar="tcg_rim_tool-2.0.0.jar";
|
jar="tcg_rim_tool-2.1.0.jar";
|
||||||
java -jar $baseDir/$jar "$@"
|
java -jar $baseDir/$jar "$@"
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ 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.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 certificate for use in their respective java.security objects.
|
||||||
@ -31,6 +32,8 @@ public class CredentialParser {
|
|||||||
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-----";
|
||||||
private static final String PKCS8_FOOTER = "-----END PRIVATE KEY-----";
|
private static final String PKCS8_FOOTER = "-----END PRIVATE KEY-----";
|
||||||
|
private static final String CERTIFICATE_HEADER = "-----BEGIN CERTIFICATE-----";
|
||||||
|
private static final String CERTIFICATE_FOOTER = "-----END CERTIFICATE-----";
|
||||||
private X509Certificate certificate;
|
private X509Certificate certificate;
|
||||||
private PrivateKey privateKey;
|
private PrivateKey privateKey;
|
||||||
private PublicKey publicKey;
|
private PublicKey publicKey;
|
||||||
@ -61,8 +64,9 @@ public class CredentialParser {
|
|||||||
publicKey = certificate.getPublicKey();
|
publicKey = certificate.getPublicKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parsePEMCredentials(String certificateFile, String privateKeyFile) throws CertificateException, FileNotFoundException {
|
public void parsePEMCredentials(String certificateFile, String privateKeyFile)
|
||||||
certificate = parsePEMCertificate(certificateFile);
|
throws CertificateException, FileNotFoundException {
|
||||||
|
certificate = parsePEMCertificates(certificateFile).get(0);
|
||||||
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!");
|
||||||
}
|
}
|
||||||
@ -70,24 +74,49 @@ public class CredentialParser {
|
|||||||
publicKey = certificate.getPublicKey();
|
publicKey = certificate.getPublicKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public X509Certificate parseCertFromPEMString(String pemString) throws CertificateException {
|
||||||
|
try {
|
||||||
|
CertificateFactory factory = CertificateFactory.getInstance(X509);
|
||||||
|
InputStream inputStream = new ByteArrayInputStream((CERTIFICATE_HEADER
|
||||||
|
+ System.lineSeparator()
|
||||||
|
+ pemString
|
||||||
|
+ System.lineSeparator()
|
||||||
|
+ CERTIFICATE_FOOTER).getBytes());
|
||||||
|
return (X509Certificate) factory.generateCertificate(inputStream);
|
||||||
|
} catch (CertificateException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the X509Certificate object from a PEM certificate file.
|
* This method returns the X509Certificate object from a PEM certificate file.
|
||||||
* @param certificateFile
|
* @param certificateFile
|
||||||
* @return
|
* @return
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
*/
|
*/
|
||||||
public X509Certificate parseCertFromPEM(String certificateFile) throws FileNotFoundException {
|
public List<X509Certificate> parseCertsFromPEM(String certificateFile)
|
||||||
return parsePEMCertificate(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.
|
||||||
* @param filename
|
* Unchecked typcase warnings are suppressed because the CertificateFactory
|
||||||
* @return
|
* implements X509Certificate objects explicitly.
|
||||||
* @throws FileNotFoundException
|
* @param filename pem file
|
||||||
|
* @return a list containing all X509Certificates extracted
|
||||||
*/
|
*/
|
||||||
private X509Certificate parsePEMCertificate(String filename) throws FileNotFoundException {
|
@SuppressWarnings("unchecked")
|
||||||
X509Certificate certificate = null;
|
private List<X509Certificate> parsePEMCertificates(String filename) {
|
||||||
|
List<X509Certificate> certificates = null;
|
||||||
FileInputStream fis = null;
|
FileInputStream fis = null;
|
||||||
BufferedInputStream bis = null;
|
BufferedInputStream bis = null;
|
||||||
try {
|
try {
|
||||||
@ -96,9 +125,12 @@ public class CredentialParser {
|
|||||||
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
|
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
|
||||||
|
|
||||||
while (bis.available() > 0) {
|
while (bis.available() > 0) {
|
||||||
certificate = (X509Certificate) certificateFactory.generateCertificate(bis);
|
certificates = (List<X509Certificate>) certificateFactory.generateCertificates(bis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (certificates.size() < 1) {
|
||||||
|
System.out.println("ERROR: No certificates parsed from " + filename);
|
||||||
|
}
|
||||||
bis.close();
|
bis.close();
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
System.out.println("Error in certificate factory: " + e.getMessage());
|
System.out.println("Error in certificate factory: " + e.getMessage());
|
||||||
@ -117,7 +149,7 @@ public class CredentialParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return certificate;
|
return certificates;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -241,8 +273,8 @@ public class CredentialParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the subjectKeyIdentifier from an X509Certificate.
|
* This method returns the subjectKeyIdentifier from the local X509Certificate.
|
||||||
* @return
|
* @return the String representation of the subjectKeyIdentifier
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public String getCertificateSubjectKeyIdentifier() throws IOException {
|
public String getCertificateSubjectKeyIdentifier() throws IOException {
|
||||||
@ -253,4 +285,19 @@ public class CredentialParser {
|
|||||||
}
|
}
|
||||||
return decodedValue.substring(1);//Drop the # at the beginning of the string
|
return decodedValue.substring(1);//Drop the # at the beginning of the string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public String getCertificateSubjectKeyIdentifier(X509Certificate certificate) throws IOException {
|
||||||
|
String decodedValue = null;
|
||||||
|
byte[] extension = certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId());
|
||||||
|
if (extension != null && extension.length > 0) {
|
||||||
|
decodedValue = JcaX509ExtensionUtils.parseExtensionValue(extension).toString();
|
||||||
|
}
|
||||||
|
return decodedValue.substring(1);//Drop the # at the beginning of the string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package hirs.swid;
|
|||||||
import hirs.swid.utils.Commander;
|
import hirs.swid.utils.Commander;
|
||||||
import com.beust.jcommander.JCommander;
|
import com.beust.jcommander.JCommander;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
@ -25,19 +24,19 @@ public class Main {
|
|||||||
String verifyFile = commander.getVerifyFile();
|
String verifyFile = commander.getVerifyFile();
|
||||||
String rimel = commander.getRimEventLog();
|
String rimel = commander.getRimEventLog();
|
||||||
String certificateFile = commander.getPublicCertificate();
|
String certificateFile = commander.getPublicCertificate();
|
||||||
|
String trustStore = commander.getTruststoreFile();
|
||||||
if (!verifyFile.isEmpty()) {
|
if (!verifyFile.isEmpty()) {
|
||||||
if (!rimel.isEmpty()) {
|
if (!rimel.isEmpty()) {
|
||||||
validator.setRimEventLog(rimel);
|
validator.setRimEventLog(rimel);
|
||||||
}
|
}
|
||||||
|
if (!trustStore.isEmpty()) {
|
||||||
|
validator.setTrustStoreFile(trustStore);
|
||||||
|
}
|
||||||
if (!certificateFile.isEmpty()) {
|
if (!certificateFile.isEmpty()) {
|
||||||
validator.setCertificateFile(certificateFile);
|
System.out.println("A single cert cannot be used for verification. " +
|
||||||
}
|
"The signing cert will be searched for in the trust store.");
|
||||||
try {
|
|
||||||
validator.validateSwidTag(verifyFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("Error validating RIM file: " + e.getMessage());
|
|
||||||
System.exit(1);
|
|
||||||
}
|
}
|
||||||
|
validator.validateSwidTag(verifyFile);
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Need a RIM file to validate!");
|
System.out.println("Need a RIM file to validate!");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
@ -47,7 +46,7 @@ public class Main {
|
|||||||
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 jksKeystoreFile = commander.getKeystoreFile();
|
String jksTruststoreFile = commander.getTruststoreFile();
|
||||||
String certificateFile = commander.getPublicCertificate();
|
String certificateFile = commander.getPublicCertificate();
|
||||||
String privateKeyFile = commander.getPrivateKeyFile();
|
String privateKeyFile = commander.getPrivateKeyFile();
|
||||||
String rimEventLog = commander.getRimEventLog();
|
String rimEventLog = commander.getRimEventLog();
|
||||||
@ -56,16 +55,16 @@ public class Main {
|
|||||||
if (!attributesFile.isEmpty()) {
|
if (!attributesFile.isEmpty()) {
|
||||||
gateway.setAttributesFile(attributesFile);
|
gateway.setAttributesFile(attributesFile);
|
||||||
}
|
}
|
||||||
if (!jksKeystoreFile.isEmpty()) {
|
if (!jksTruststoreFile.isEmpty()) {
|
||||||
gateway.setDefaultCredentials(true);
|
gateway.setDefaultCredentials(true);
|
||||||
gateway.setJksKeystoreFile(jksKeystoreFile);
|
gateway.setJksTruststoreFile(jksTruststoreFile);
|
||||||
} else if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) {
|
} else if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) {
|
||||||
gateway.setDefaultCredentials(false);
|
gateway.setDefaultCredentials(false);
|
||||||
gateway.setPemCertificateFile(certificateFile);
|
gateway.setPemCertificateFile(certificateFile);
|
||||||
gateway.setPemPrivateKeyFile(privateKeyFile);
|
gateway.setPemPrivateKeyFile(privateKeyFile);
|
||||||
} else {
|
} else {
|
||||||
gateway.setDefaultCredentials(true);
|
gateway.setDefaultCredentials(true);
|
||||||
gateway.setJksKeystoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
|
gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
|
||||||
}
|
}
|
||||||
if (rimEventLog.isEmpty()) {
|
if (rimEventLog.isEmpty()) {
|
||||||
System.out.println("Error: a support RIM is required!");
|
System.out.println("Error: a support RIM is required!");
|
||||||
@ -75,6 +74,8 @@ public class Main {
|
|||||||
}
|
}
|
||||||
gateway.generateSwidTag(commander.getOutFile());
|
gateway.generateSwidTag(commander.getOutFile());
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
System.out.println("No create type given, nothing to do");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ public class SwidTagGateway {
|
|||||||
private Marshaller marshaller;
|
private Marshaller marshaller;
|
||||||
private String attributesFile;
|
private String attributesFile;
|
||||||
private boolean defaultCredentials;
|
private boolean defaultCredentials;
|
||||||
private String jksKeystoreFile;
|
private String jksTruststoreFile;
|
||||||
private String pemPrivateKeyFile;
|
private String pemPrivateKeyFile;
|
||||||
private String pemCertificateFile;
|
private String pemCertificateFile;
|
||||||
private String rimEventLog;
|
private String rimEventLog;
|
||||||
@ -120,9 +120,9 @@ public class SwidTagGateway {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for JKS keystore file
|
* Setter for JKS keystore file
|
||||||
* @param jksKeystoreFile
|
* @param jksTruststoreFile
|
||||||
*/
|
*/
|
||||||
public void setJksKeystoreFile(String jksKeystoreFile) { this.jksKeystoreFile = jksKeystoreFile; }
|
public void setJksTruststoreFile(String jksTruststoreFile) { this.jksTruststoreFile = jksTruststoreFile; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for private key file in PEM format
|
* Setter for private key file in PEM format
|
||||||
@ -437,27 +437,22 @@ public class SwidTagGateway {
|
|||||||
|
|
||||||
KeyInfoFactory kiFactory = sigFactory.getKeyInfoFactory();
|
KeyInfoFactory kiFactory = sigFactory.getKeyInfoFactory();
|
||||||
PrivateKey privateKey;
|
PrivateKey privateKey;
|
||||||
PublicKey publicKey;
|
|
||||||
CredentialParser cp = new CredentialParser();
|
CredentialParser cp = new CredentialParser();
|
||||||
if (defaultCredentials) {
|
if (defaultCredentials) {
|
||||||
cp.parseJKSCredentials(jksKeystoreFile);
|
cp.parseJKSCredentials(jksTruststoreFile);
|
||||||
privateKey = cp.getPrivateKey();
|
privateKey = cp.getPrivateKey();
|
||||||
publicKey = cp.getPublicKey();
|
|
||||||
KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier());
|
KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier());
|
||||||
keyInfoElements.add(keyName);
|
keyInfoElements.add(keyName);
|
||||||
} else {
|
} else {
|
||||||
cp.parsePEMCredentials(pemCertificateFile, pemPrivateKeyFile);
|
cp.parsePEMCredentials(pemCertificateFile, pemPrivateKeyFile);
|
||||||
X509Certificate certificate = cp.getCertificate();
|
X509Certificate certificate = cp.getCertificate();
|
||||||
privateKey = cp.getPrivateKey();
|
privateKey = cp.getPrivateKey();
|
||||||
publicKey = cp.getPublicKey();
|
|
||||||
ArrayList<Object> x509Content = new ArrayList<Object>();
|
ArrayList<Object> x509Content = new ArrayList<Object>();
|
||||||
x509Content.add(certificate.getSubjectX500Principal().getName());
|
x509Content.add(certificate.getSubjectX500Principal().getName());
|
||||||
x509Content.add(certificate);
|
x509Content.add(certificate);
|
||||||
X509Data data = kiFactory.newX509Data(x509Content);
|
X509Data data = kiFactory.newX509Data(x509Content);
|
||||||
keyInfoElements.add(data);
|
keyInfoElements.add(data);
|
||||||
}
|
}
|
||||||
KeyValue keyValue = kiFactory.newKeyValue(publicKey);
|
|
||||||
keyInfoElements.add(keyValue);
|
|
||||||
KeyInfo keyinfo = kiFactory.newKeyInfo(keyInfoElements);
|
KeyInfo keyinfo = kiFactory.newKeyInfo(keyInfoElements);
|
||||||
|
|
||||||
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
||||||
@ -472,8 +467,6 @@ public class SwidTagGateway {
|
|||||||
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException |
|
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException |
|
||||||
ParserConfigurationException e) {
|
ParserConfigurationException e) {
|
||||||
System.out.println(e.getMessage());
|
System.out.println(e.getMessage());
|
||||||
} catch (KeyException e) {
|
|
||||||
System.out.println("Error setting public key in KeyValue: " + e.getMessage());
|
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
System.out.println(e.getMessage());
|
System.out.println(e.getMessage());
|
||||||
} catch (JAXBException e) {
|
} catch (JAXBException e) {
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package hirs.swid;
|
package hirs.swid;
|
||||||
|
|
||||||
import hirs.swid.utils.HashSwid;
|
import hirs.swid.utils.HashSwid;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import javax.security.auth.x500.X500Principal;
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.JAXBContext;
|
||||||
import javax.xml.bind.JAXBException;
|
import javax.xml.bind.JAXBException;
|
||||||
import javax.xml.bind.UnmarshalException;
|
import javax.xml.bind.UnmarshalException;
|
||||||
@ -33,12 +36,26 @@ 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.math.BigInteger;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.NoSuchProviderException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
import java.security.Security;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.RSAPublicKeySpec;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles validating base Reference Integrity Manifest files.
|
* This class handles validating base Reference Integrity Manifest files.
|
||||||
@ -47,17 +64,30 @@ public class SwidTagValidator {
|
|||||||
private Unmarshaller unmarshaller;
|
private Unmarshaller unmarshaller;
|
||||||
private String rimEventLog;
|
private String rimEventLog;
|
||||||
private String certificateFile;
|
private String certificateFile;
|
||||||
|
private String trustStoreFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that BouncyCastle is configured as a javax.security.Security provider, as this
|
||||||
|
* class expects it to be available.
|
||||||
|
*/
|
||||||
|
static {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setter for rimel file path.
|
* Setter for rimel file path.
|
||||||
* @param rimEventLog
|
* @param rimEventLog the rimel file
|
||||||
*/
|
*/
|
||||||
public void setRimEventLog(String rimEventLog) {
|
public void setRimEventLog(String rimEventLog) {
|
||||||
this.rimEventLog = rimEventLog;
|
this.rimEventLog = rimEventLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCertificateFile(String certificateFile) {
|
/**
|
||||||
this.certificateFile = certificateFile;
|
* Setter for the truststore file path.
|
||||||
|
* @param trustStoreFile the truststore
|
||||||
|
*/
|
||||||
|
public void setTrustStoreFile(String trustStoreFile) {
|
||||||
|
this.trustStoreFile = trustStoreFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SwidTagValidator() {
|
public SwidTagValidator() {
|
||||||
@ -66,6 +96,7 @@ public class SwidTagValidator {
|
|||||||
unmarshaller = jaxbContext.createUnmarshaller();
|
unmarshaller = jaxbContext.createUnmarshaller();
|
||||||
rimEventLog = "";
|
rimEventLog = "";
|
||||||
certificateFile = "";
|
certificateFile = "";
|
||||||
|
trustStoreFile = SwidTagConstants.DEFAULT_KEYSTORE_FILE;
|
||||||
} catch (JAXBException e) {
|
} catch (JAXBException e) {
|
||||||
System.out.println("Error initializing JAXBContext: " + e.getMessage());
|
System.out.println("Error initializing JAXBContext: " + e.getMessage());
|
||||||
}
|
}
|
||||||
@ -77,7 +108,7 @@ 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) throws IOException {
|
public boolean validateSwidTag(String path) {
|
||||||
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");
|
||||||
@ -113,50 +144,192 @@ public class SwidTagValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method validates a Document with a signature element.
|
* This method validates a signed XML document.
|
||||||
*
|
* First, the signing certificate is either parsed from the embedded X509Certificate element or
|
||||||
* @param doc
|
* generated from the Modulus and Exponent elements.
|
||||||
|
* 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) {
|
||||||
DOMValidateContext context = null;
|
|
||||||
boolean isValid = false;
|
|
||||||
try {
|
try {
|
||||||
|
DOMValidateContext context;
|
||||||
|
CredentialParser cp = new CredentialParser();
|
||||||
|
X509Certificate signingCert = null;
|
||||||
|
List<X509Certificate> trustStore = cp.parseCertsFromPEM(trustStoreFile);
|
||||||
NodeList nodes = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
|
NodeList nodes = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
|
||||||
if (nodes.getLength() == 0) {
|
if (nodes.getLength() == 0) {
|
||||||
throw new Exception("Signature element not found!");
|
throw new Exception("Signature element not found!");
|
||||||
}
|
}
|
||||||
NodeList embeddedCert = doc.getElementsByTagName("X509Data");
|
NodeList embeddedCert = doc.getElementsByTagName("X509Certificate");
|
||||||
if (embeddedCert.getLength() > 0) {
|
if (embeddedCert.getLength() > 0) {
|
||||||
context = new DOMValidateContext(new SwidTagValidator.X509KeySelector(), nodes.item(0));
|
context = new DOMValidateContext(new X509KeySelector(), nodes.item(0));
|
||||||
|
signingCert = cp.parseCertFromPEMString(embeddedCert.item(0).getTextContent());
|
||||||
} else {
|
} else {
|
||||||
CredentialParser cp = new CredentialParser();
|
String skId = doc.getElementsByTagName("KeyName").item(0).getTextContent();
|
||||||
if (!certificateFile.isEmpty()) {
|
for (X509Certificate trustedCert : trustStore) {
|
||||||
X509Certificate certificate = cp.parseCertFromPEM(certificateFile);
|
String trustedSkId = cp.getCertificateSubjectKeyIdentifier(trustedCert);
|
||||||
cp.setCertificate(certificate);
|
if (skId.equals(trustedSkId)) {
|
||||||
System.out.println(cp.getCertificateAuthorityInfoAccess());
|
signingCert = trustedCert;
|
||||||
context = new DOMValidateContext(certificate.getPublicKey(), nodes.item(0));
|
break;
|
||||||
} else {
|
}
|
||||||
System.out.println("Signing certificate not found for validation!");
|
}
|
||||||
|
if (signingCert == null) {
|
||||||
|
System.out.println("Issuer certificate with subject key identifier = "
|
||||||
|
+ skId + " not found");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
context = new DOMValidateContext(signingCert.getPublicKey(), nodes.item(0));
|
||||||
}
|
}
|
||||||
|
cp.setCertificate(signingCert);
|
||||||
|
System.out.println(cp.getCertificateAuthorityInfoAccess());
|
||||||
XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
|
XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
|
||||||
XMLSignature signature = sigFactory.unmarshalXMLSignature(context);
|
XMLSignature signature = sigFactory.unmarshalXMLSignature(context);
|
||||||
isValid = signature.validate(context);
|
boolean signatureIsValid = signature.validate(context);
|
||||||
|
boolean certChainIsValid = validateCertChain(signingCert, trustStore);
|
||||||
|
System.out.println("Signature validity: " + signatureIsValid);
|
||||||
|
System.out.println("Cert chain validity: " + certChainIsValid);
|
||||||
|
return signatureIsValid && certChainIsValid;
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
System.out.println("Error parsing truststore: " + e.getMessage());
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
System.out.println("Error instantiating a KeyFactory to generate pk: "
|
||||||
|
+ e.getMessage());
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
System.out.println("Failed to generate a pk from swidtag: " + e.getMessage());
|
||||||
} 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());
|
System.out.println(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return isValid;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @param trustStore from which to find the chain of intermediate and root CAs
|
||||||
|
* @return true if the chain is valid
|
||||||
|
* @throws Exception if a valid chain is not found in the truststore
|
||||||
|
*/
|
||||||
|
private boolean validateCertChain(final X509Certificate cert,
|
||||||
|
final List<X509Certificate> trustStore)
|
||||||
|
throws Exception {
|
||||||
|
if (cert == null || trustStore == null) {
|
||||||
|
throw new Exception("Null certificate or truststore received");
|
||||||
|
} else if (trustStore.size() == 0) {
|
||||||
|
throw new Exception("Truststore is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String INT_CA_ERROR = "Intermediate CA found, searching for root CA";
|
||||||
|
String errorMessage = "";
|
||||||
|
X509Certificate startOfChain = cert;
|
||||||
|
do {
|
||||||
|
for (X509Certificate trustedCert : trustStore) {
|
||||||
|
boolean isIssuer = areYouMyIssuer(startOfChain, trustedCert);
|
||||||
|
boolean isSigner = areYouMySigner(startOfChain, trustedCert);
|
||||||
|
if (isIssuer && isSigner) {
|
||||||
|
if (isSelfSigned(trustedCert)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
startOfChain = trustedCert;
|
||||||
|
errorMessage = INT_CA_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!isIssuer) {
|
||||||
|
errorMessage = "Issuer cert not found";
|
||||||
|
} else if (!isSigner) {
|
||||||
|
errorMessage = "Signing cert not found";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (errorMessage.equals(INT_CA_ERROR));
|
||||||
|
|
||||||
|
throw new Exception("Error while validating cert chain: " + errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks if cert's issuerDN matches issuer's subjectDN.
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
private boolean areYouMyIssuer(final X509Certificate cert, final X509Certificate issuer)
|
||||||
|
throws Exception {
|
||||||
|
if (cert == null || issuer == null) {
|
||||||
|
throw new Exception("Cannot verify issuer, null certificate received");
|
||||||
|
}
|
||||||
|
X500Principal issuerDN = new X500Principal(cert.getIssuerX500Principal().getName());
|
||||||
|
return issuer.getSubjectX500Principal().equals(issuerDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks if cert's signature matches signer's public key.
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
private boolean areYouMySigner(final X509Certificate cert, final X509Certificate signer)
|
||||||
|
throws Exception {
|
||||||
|
if (cert == null || signer == null) {
|
||||||
|
throw new Exception("Cannot verify signature, null certificate received");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
cert.verify(signer.getPublicKey(), BouncyCastleProvider.PROVIDER_NAME);
|
||||||
|
return true;
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new Exception("Signing algorithm in signing cert not supported");
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new Exception("Signing certificate key does not match signature");
|
||||||
|
} catch (NoSuchProviderException e) {
|
||||||
|
throw new Exception("Error with BouncyCastleProvider: " + e.getMessage());
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
String error = "Error with signature: " + e.getMessage()
|
||||||
|
+ System.lineSeparator()
|
||||||
|
+ "Certificate needed for verification is missing: "
|
||||||
|
+ signer.getSubjectX500Principal().getName();
|
||||||
|
throw new Exception(error);
|
||||||
|
} catch (CertificateException e) {
|
||||||
|
throw new Exception("Encoding error: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
private boolean isSelfSigned(final X509Certificate cert) {
|
||||||
|
return cert.getIssuerX500Principal().equals(cert.getSubjectX500Principal());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This internal class handles parsing the public key from a KeyInfo element.
|
||||||
|
*/
|
||||||
public class X509KeySelector extends KeySelector {
|
public class X509KeySelector extends KeySelector {
|
||||||
public KeySelectorResult select(KeyInfo keyinfo,
|
/**
|
||||||
KeySelector.Purpose purpose,
|
* This method extracts a public key from either an X509Certificate element
|
||||||
AlgorithmMethod algorithm,
|
* or a KeyValue element. If the public key's algorithm matches the declared
|
||||||
XMLCryptoContext context) throws KeySelectorException {
|
* algorithm it is returned in a KeySelecctorResult.
|
||||||
|
* @param keyinfo the KeyInfo element
|
||||||
|
* @param purpose
|
||||||
|
* @param algorithm the encapsulating signature's declared signing algorithm
|
||||||
|
* @param context
|
||||||
|
* @return a KeySelectorResult if the public key's algorithm matches the declared algorithm
|
||||||
|
* @throws KeySelectorException if the algorithms do not match
|
||||||
|
*/
|
||||||
|
public KeySelectorResult select(final KeyInfo keyinfo,
|
||||||
|
final KeySelector.Purpose purpose,
|
||||||
|
final AlgorithmMethod algorithm,
|
||||||
|
final XMLCryptoContext context)
|
||||||
|
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();
|
||||||
@ -174,16 +347,18 @@ public class SwidTagValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new KeySelectorException("No key found!");
|
throw new KeySelectorException("No key found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks that the signature and public key algorithms match.
|
||||||
|
* @param uri to match the signature algorithm
|
||||||
|
* @param name to match the public key algorithm
|
||||||
|
* @return true if both match, false otherwise
|
||||||
|
*/
|
||||||
public boolean areAlgorithmsEqual(String uri, String name) {
|
public boolean areAlgorithmsEqual(String uri, String name) {
|
||||||
if (uri.equals(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256) && name.equalsIgnoreCase("RSA")) {
|
return uri.equals(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256)
|
||||||
return true;
|
&& name.equalsIgnoreCase("RSA");
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RIMKeySelectorResult implements KeySelectorResult {
|
private class RIMKeySelectorResult implements KeySelectorResult {
|
||||||
@ -243,8 +418,8 @@ 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
|
* @param path to the xml file
|
||||||
* @return
|
* @return Document object without whitespace
|
||||||
*/
|
*/
|
||||||
private Document removeXMLWhitespace(String path) throws IOException {
|
private Document removeXMLWhitespace(String path) throws IOException {
|
||||||
TransformerFactory tf = TransformerFactory.newInstance();
|
TransformerFactory tf = TransformerFactory.newInstance();
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
package hirs.swid.utils;
|
package hirs.swid.utils;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.InvalidPathException;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
import com.beust.jcommander.Parameter;
|
import com.beust.jcommander.Parameter;
|
||||||
import hirs.swid.SwidTagConstants;
|
import hirs.swid.SwidTagConstants;
|
||||||
|
|
||||||
@ -19,40 +13,33 @@ public class Commander {
|
|||||||
private boolean help;
|
private boolean help;
|
||||||
@Parameter(names = {"-c", "--create \"base\""}, order = 0,
|
@Parameter(names = {"-c", "--create \"base\""}, order = 0,
|
||||||
description = "The type of RIM to create. A base RIM will be created by default.")
|
description = "The type of RIM to create. A base RIM will be created by default.")
|
||||||
private String createType = "";//other possible values: "eventlog" and "pcr"
|
private String createType = "";
|
||||||
@Parameter(names = {"-a", "--attributes <path>"}, order = 1,
|
@Parameter(names = {"-a", "--attributes <path>"}, order = 1,
|
||||||
description = "The configuration file holding attributes to populate the base RIM with.")
|
description = "The configuration file holding attributes "
|
||||||
|
+ "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. The RIM will be written to stdout by default.")
|
description = "The file to write the RIM out to. "
|
||||||
|
+ "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 = {"--keystore <path>"}, order = 4,
|
@Parameter(names = {"-t", "--truststore <path>"}, order = 4,
|
||||||
description = "JKS keystore containing a private key to sign the base RIM created by the create function.")
|
description = "The truststore to sign the base RIM created "
|
||||||
private String keystoreFile = "";
|
+ "or to validate the signed base RIM.")
|
||||||
|
private String truststoreFile = "";
|
||||||
@Parameter(names = {"-k", "--privateKeyFile <path>"}, order = 5,
|
@Parameter(names = {"-k", "--privateKeyFile <path>"}, order = 5,
|
||||||
description = "File containing the private key used to sign the base RIM created by the create function.")
|
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 used to verify a RIM file or to embed in a signed RIM. " +
|
description = "The public key certificate to embed in the base RIM created by "
|
||||||
"A signed RIM generated by this tool by default will not show the signing certificate without this parameter present.")
|
+ "this tool.")
|
||||||
private String publicCertificate = "";
|
private String publicCertificate = "";
|
||||||
@Parameter(names = {"-l", "--rimel <path>"}, order = 7,
|
@Parameter(names = {"-l", "--rimel <path>"}, order = 7,
|
||||||
description = "The TCG eventlog file to use as a support RIM. By default the last system eventlog will be used.")
|
description = "The TCG eventlog file to use as a support RIM.")
|
||||||
private String rimEventLog = "";
|
private String rimEventLog = "";
|
||||||
/*
|
|
||||||
@Parameter(names = {"-t", "--rimpcr <path>"}, order = 7,
|
|
||||||
description = "The file containing TPM PCR values to use as a support RIM. By default the current platform TPM will be used.")
|
|
||||||
private String rimPcrs = "";
|
|
||||||
//@Parameter(names = {}, order = 8, description = "")
|
|
||||||
private String toBeSigned = "";
|
|
||||||
@Parameter(names = {"-s", "--addSignatureData <originalBaseRIM> <signatureFile> <outputFile>"}, order = 8,
|
|
||||||
description = "The signature data in <signatureFile> will be combined with the data in <originalBaseRIM>" +
|
|
||||||
"and written to <outputFile>, or will overwrite <originalBaseRIM> if <outputFile> is not given.")
|
|
||||||
private String signatureData = "";
|
|
||||||
*/
|
|
||||||
public boolean isHelp() {
|
public boolean isHelp() {
|
||||||
return help;
|
return help;
|
||||||
}
|
}
|
||||||
@ -73,7 +60,7 @@ public class Commander {
|
|||||||
return verifyFile;
|
return verifyFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKeystoreFile() { return keystoreFile; }
|
public String getTruststoreFile() { return truststoreFile; }
|
||||||
|
|
||||||
public String getPrivateKeyFile() {
|
public String getPrivateKeyFile() {
|
||||||
return privateKeyFile;
|
return privateKeyFile;
|
||||||
@ -84,33 +71,23 @@ public class Commander {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getRimEventLog() { return rimEventLog; }
|
public String getRimEventLog() { return rimEventLog; }
|
||||||
/*
|
|
||||||
public String getRimPcrs() {
|
|
||||||
return rimPcrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToBeSigned() {
|
|
||||||
return toBeSigned;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignatureData() {
|
|
||||||
return signatureData;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
public String printHelpExamples() {
|
public String printHelpExamples() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Create a base RIM using the values in attributes.json; " +
|
sb.append("Create a base RIM using the values in attributes.json; " +
|
||||||
"sign it with the default keystore, alias, and password;\n");
|
"sign it with the default keystore, alias, and password;\n");
|
||||||
sb.append("and write the data to base_rim.swidtag:\n\n");
|
sb.append("and write the data to base_rim.swidtag:\n\n");
|
||||||
sb.append("\t\t-c base -a attributes.json -l support_rim.bin -o base_rim.swidtag\n\n\n");
|
sb.append("\t\t-c base -a attributes.json -l support_rim.bin -o base_rim.swidtag\n\n\n");
|
||||||
sb.append("Create a base RIM using the default attribute values; sign it using privateKey.pem;\n");
|
sb.append("Create a base RIM using the default attribute values; ");
|
||||||
sb.append("and write the data to console output, to embed cert.pem in the signature block:\n\n");
|
sb.append("sign it using privateKey.pem; embed cert.pem in the signature block; ");
|
||||||
|
sb.append("and write the data to console output:\n\n");
|
||||||
sb.append("\t\t-c base -l support_rim.bin -k privateKey.pem -p cert.pem\n\n\n");
|
sb.append("\t\t-c base -l support_rim.bin -k privateKey.pem -p cert.pem\n\n\n");
|
||||||
sb.append("Validate a base RIM using an external support RIM to override the payload file:\n\n");
|
sb.append("Validate a base RIM using an external support RIM to override the ");
|
||||||
|
sb.append("payload file:\n\n");
|
||||||
sb.append("\t\t-v base_rim.swidtag -l support_rim.bin\n\n\n");
|
sb.append("\t\t-v base_rim.swidtag -l support_rim.bin\n\n\n");
|
||||||
sb.append("Validate a base RIM with an external cert:\n\n");
|
sb.append("Validate a base RIM with its own payload file and a PEM truststore ");
|
||||||
sb.append("\t\t-v base_rim.swidtag -p signing_cert.pem\n\n\n");
|
sb.append("containing the signing cert:\n\n");
|
||||||
|
sb.append("\t\t-v base_rim.swidtag -t ca.crt\n\n\n");
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
@ -120,22 +97,17 @@ public class Commander {
|
|||||||
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.getKeystoreFile().isEmpty()) {
|
if (!this.getTruststoreFile().isEmpty()) {
|
||||||
sb.append("Keystore file: " + this.getKeystoreFile() + System.lineSeparator());
|
sb.append("Truststore file: " + this.getTruststoreFile() + System.lineSeparator());
|
||||||
} else if (!this.getPrivateKeyFile().isEmpty() &&
|
} else if (!this.getPrivateKeyFile().isEmpty() &&
|
||||||
!this.getPublicCertificate().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() + System.lineSeparator());
|
sb.append("Public certificate: " + this.getPublicCertificate() + System.lineSeparator());
|
||||||
} else {
|
} else {
|
||||||
sb.append("Keystore file: default (" + SwidTagConstants.DEFAULT_KEYSTORE_FILE + ")"
|
sb.append("Truststore file: default (" + SwidTagConstants.DEFAULT_KEYSTORE_FILE + ")"
|
||||||
+ System.lineSeparator());
|
+ System.lineSeparator());
|
||||||
}
|
}
|
||||||
sb.append("Event log support RIM: " + this.getRimEventLog() + System.lineSeparator());
|
sb.append("Event log support RIM: " + this.getRimEventLog() + System.lineSeparator());
|
||||||
/*
|
|
||||||
sb.append("TPM PCRs support RIM: " + getRimPcrs() + System.lineSeparator());
|
|
||||||
sb.append("Base RIM to be signed: " + getToBeSigned() + System.lineSeparator());
|
|
||||||
sb.append("External signature file: " + getSignatureData() + System.lineSeparator());
|
|
||||||
*/
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
package hirs.swid;
|
package hirs.swid;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
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 java.nio.file.Paths;
|
|
||||||
import java.util.Scanner;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
|
|
||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
@ -65,7 +61,7 @@ public class TestSwidTagGateway {
|
|||||||
@Test
|
@Test
|
||||||
public void testCreateBaseWithoutCert() {
|
public void testCreateBaseWithoutCert() {
|
||||||
gateway.setDefaultCredentials(true);
|
gateway.setDefaultCredentials(true);
|
||||||
gateway.setJksKeystoreFile(JKS_KEYSTORE_FILE);
|
gateway.setJksTruststoreFile(JKS_KEYSTORE_FILE);
|
||||||
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
||||||
expectedFile = TestSwidTagGateway.class.getClassLoader().getResourceAsStream(DEFAULT_NO_CERT);
|
expectedFile = TestSwidTagGateway.class.getClassLoader().getResourceAsStream(DEFAULT_NO_CERT);
|
||||||
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
||||||
@ -79,13 +75,7 @@ public class TestSwidTagGateway {
|
|||||||
public void testValidateSwidTag() {
|
public void testValidateSwidTag() {
|
||||||
String filepath = TestSwidTagGateway.class.getClassLoader().getResource(DEFAULT_WITH_CERT).getPath();
|
String filepath = TestSwidTagGateway.class.getClassLoader().getResource(DEFAULT_WITH_CERT).getPath();
|
||||||
System.out.println("Validating file at " + filepath);
|
System.out.println("Validating file at " + filepath);
|
||||||
try {
|
Assert.assertTrue(validator.validateSwidTag(filepath));
|
||||||
Assert.assertTrue(validator.validateSwidTag(filepath));
|
|
||||||
} catch (IOException e) {
|
|
||||||
Assert.fail("Invalid swidtag!");
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
Assert.fail("Cannot find file: " + filepath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,23 +20,13 @@
|
|||||||
<DigestValue>97uWB7zSsO5WaGbrcQrlKd1Bju0aDTjK1/ktUYBje8A=</DigestValue>
|
<DigestValue>97uWB7zSsO5WaGbrcQrlKd1Bju0aDTjK1/ktUYBje8A=</DigestValue>
|
||||||
</Reference>
|
</Reference>
|
||||||
</SignedInfo>
|
</SignedInfo>
|
||||||
<SignatureValue>N1YtTeo2Ryuj+CtlXIpICEay+ni7vt8+4J7tAsYpa3efnLwtea69PIqEylPWm9LdA8Eo8XDdpgxV
|
<SignatureValue>N1YtTeo2Ryuj+CtlXIpICEay+ni7vt8+4J7tAsYpa3efnLwtea69PIqEylPWm9LdA8Eo8XDdpgxV
|
||||||
7h3hi2LTOU+Wxq3bLiLamo99T1EtIwl+ZPcOv8bsfEkmShHdMC0dlfcj6r7x4tc0XkNAhhJgfRNz
|
7h3hi2LTOU+Wxq3bLiLamo99T1EtIwl+ZPcOv8bsfEkmShHdMC0dlfcj6r7x4tc0XkNAhhJgfRNz
|
||||||
FsmPWKJb6FYcsHFbHO/Uw1hSokbAGcWWTshEOqvKHMa8UVkrFMUPnrnMtdyJqZlhDBrZHNi4rWth
|
FsmPWKJb6FYcsHFbHO/Uw1hSokbAGcWWTshEOqvKHMa8UVkrFMUPnrnMtdyJqZlhDBrZHNi4rWth
|
||||||
8TjlUnQVSCF9s9I04FxJ1cUAdeVMHtXKM8Pvjv68PaJMJK73dW5Yd3SbcgoKLesf/HPWeeZL0rr4
|
8TjlUnQVSCF9s9I04FxJ1cUAdeVMHtXKM8Pvjv68PaJMJK73dW5Yd3SbcgoKLesf/HPWeeZL0rr4
|
||||||
TNjlqJ/wq61Ons45MFG9bIscVbnd+XxFHx8Skw==</SignatureValue>
|
TNjlqJ/wq61Ons45MFG9bIscVbnd+XxFHx8Skw==</SignatureValue>
|
||||||
<KeyInfo>
|
<KeyInfo>
|
||||||
<KeyName>2fdeb8e7d030a2209daa01861a964fedecf2bcc1</KeyName>
|
<KeyName>2fdeb8e7d030a2209daa01861a964fedecf2bcc1</KeyName>
|
||||||
<KeyValue>
|
|
||||||
<RSAKeyValue>
|
|
||||||
<Modulus>p3WVYaRJG7EABjbAdqDYZXFSTV1nHY9Ol9A5+W8t5xwBXBryZCGWxERGr5AryKWPxd+qzjj+cFpx
|
|
||||||
xkM6N18jEhQIx/CEZePEJqpluBO5w2wTEOe7hqtMatqgDDMeDRxUuIpP8LGP00vh1wyDFFew90d9
|
|
||||||
dvT3bcLvFh3a3ap9bTm6aBqPup5CXpzrwIU2wZfgkDytYVBm+8bHkMaUrgpNyM+5BAg2zl/Fqw0q
|
|
||||||
otjaGr7PzbH+urCvaGbKLMPoWkVLIgAE8Qw98HTfoYSFHC7VYQySrzIinaOBFSgViR72kHemH2lW
|
|
||||||
jDQeHiY0VIoPik/jVVIpjWe6zzeZ2S66Q/LmjQ==</Modulus>
|
|
||||||
<Exponent>AQAB</Exponent>
|
|
||||||
</RSAKeyValue>
|
|
||||||
</KeyValue>
|
|
||||||
</KeyInfo>
|
</KeyInfo>
|
||||||
</Signature>
|
</Signature>
|
||||||
</SoftwareIdentity>
|
</SoftwareIdentity>
|
||||||
|
@ -20,43 +20,33 @@
|
|||||||
<DigestValue>97uWB7zSsO5WaGbrcQrlKd1Bju0aDTjK1/ktUYBje8A=</DigestValue>
|
<DigestValue>97uWB7zSsO5WaGbrcQrlKd1Bju0aDTjK1/ktUYBje8A=</DigestValue>
|
||||||
</Reference>
|
</Reference>
|
||||||
</SignedInfo>
|
</SignedInfo>
|
||||||
<SignatureValue>N1YtTeo2Ryuj+CtlXIpICEay+ni7vt8+4J7tAsYpa3efnLwtea69PIqEylPWm9LdA8Eo8XDdpgxV
|
<SignatureValue>N1YtTeo2Ryuj+CtlXIpICEay+ni7vt8+4J7tAsYpa3efnLwtea69PIqEylPWm9LdA8Eo8XDdpgxV
|
||||||
7h3hi2LTOU+Wxq3bLiLamo99T1EtIwl+ZPcOv8bsfEkmShHdMC0dlfcj6r7x4tc0XkNAhhJgfRNz
|
7h3hi2LTOU+Wxq3bLiLamo99T1EtIwl+ZPcOv8bsfEkmShHdMC0dlfcj6r7x4tc0XkNAhhJgfRNz
|
||||||
FsmPWKJb6FYcsHFbHO/Uw1hSokbAGcWWTshEOqvKHMa8UVkrFMUPnrnMtdyJqZlhDBrZHNi4rWth
|
FsmPWKJb6FYcsHFbHO/Uw1hSokbAGcWWTshEOqvKHMa8UVkrFMUPnrnMtdyJqZlhDBrZHNi4rWth
|
||||||
8TjlUnQVSCF9s9I04FxJ1cUAdeVMHtXKM8Pvjv68PaJMJK73dW5Yd3SbcgoKLesf/HPWeeZL0rr4
|
8TjlUnQVSCF9s9I04FxJ1cUAdeVMHtXKM8Pvjv68PaJMJK73dW5Yd3SbcgoKLesf/HPWeeZL0rr4
|
||||||
TNjlqJ/wq61Ons45MFG9bIscVbnd+XxFHx8Skw==</SignatureValue>
|
TNjlqJ/wq61Ons45MFG9bIscVbnd+XxFHx8Skw==</SignatureValue>
|
||||||
<KeyInfo>
|
<KeyInfo>
|
||||||
<X509Data>
|
<X509Data>
|
||||||
<X509SubjectName>CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US</X509SubjectName>
|
<X509SubjectName>CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US</X509SubjectName>
|
||||||
<X509Certificate>MIID2jCCAsKgAwIBAgIJAP0uwoNdwZDFMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAlVTMQsw
|
<X509Certificate>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
|
||||||
5VGvm0npLO394ZihtsI1sRAR8ORJ</X509Certificate>
|
5VGvm0npLO394ZihtsI1sRAR8ORJ</X509Certificate>
|
||||||
</X509Data>
|
</X509Data>
|
||||||
<KeyValue>
|
|
||||||
<RSAKeyValue>
|
|
||||||
<Modulus>p3WVYaRJG7EABjbAdqDYZXFSTV1nHY9Ol9A5+W8t5xwBXBryZCGWxERGr5AryKWPxd+qzjj+cFpx
|
|
||||||
xkM6N18jEhQIx/CEZePEJqpluBO5w2wTEOe7hqtMatqgDDMeDRxUuIpP8LGP00vh1wyDFFew90d9
|
|
||||||
dvT3bcLvFh3a3ap9bTm6aBqPup5CXpzrwIU2wZfgkDytYVBm+8bHkMaUrgpNyM+5BAg2zl/Fqw0q
|
|
||||||
otjaGr7PzbH+urCvaGbKLMPoWkVLIgAE8Qw98HTfoYSFHC7VYQySrzIinaOBFSgViR72kHemH2lW
|
|
||||||
jDQeHiY0VIoPik/jVVIpjWe6zzeZ2S66Q/LmjQ==</Modulus>
|
|
||||||
<Exponent>AQAB</Exponent>
|
|
||||||
</RSAKeyValue>
|
|
||||||
</KeyValue>
|
|
||||||
</KeyInfo>
|
</KeyInfo>
|
||||||
</Signature>
|
</Signature>
|
||||||
</SoftwareIdentity>
|
</SoftwareIdentity>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Name: tcg_rim_tool
|
Name: tcg_rim_tool
|
||||||
Version: 2.0.0
|
Version: 2.1.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: A java command-line tool to create PC client root RIM
|
Summary: A java command-line tool to create PC client root RIM
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user