mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-23 23:02:32 +00:00
Merge branch 'issue-237' into issue-252
This commit is contained in:
commit
1cf1d4ec92
build.gradle
tools/tcg_rim_tool
@ -119,7 +119,7 @@ subprojects {
|
||||
'com.fasterxml.jackson.core:jackson-databind:2.6.3',
|
||||
'com.fasterxml.jackson.core:jackson-annotations:2.6.3'],
|
||||
jadira_usertype: 'org.jadira.usertype:usertype.core:4.0.0.GA',
|
||||
jcommander: 'com.beust:jcommander:1.35',
|
||||
jcommander: 'com.beust:jcommander:1.72',
|
||||
joda_time: 'joda-time:joda-time:2.9.4',
|
||||
jstl: [ 'org.apache.taglibs:taglibs-standard-impl:1.2.5',
|
||||
'org.apache.taglibs:taglibs-standard-spec:1.2.5'],
|
||||
|
22
tools/tcg_rim_tool/RimSignCert.pem
Normal file
22
tools/tcg_rim_tool/RimSignCert.pem
Normal file
@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDoTCCAomgAwIBAgIJAPB+r6VBhBn5MA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV
|
||||
BAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwI
|
||||
UENDbGllbnQxEjAQBgNVBAMMCUV4YW1wbGVDQTAeFw0yMDAzMTExODExMjJaFw0z
|
||||
MDAxMTgxODExMjJaMFwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJWQTEQMA4GA1UE
|
||||
CgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxGzAZBgNVBAMMEmV4YW1wbGUu
|
||||
UklNLnNpZ25lcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKd1lWGk
|
||||
SRuxAAY2wHag2GVxUk1dZx2PTpfQOflvLeccAVwa8mQhlsRERq+QK8ilj8Xfqs44
|
||||
/nBaccZDOjdfIxIUCMfwhGXjxCaqZbgTucNsExDnu4arTGraoAwzHg0cVLiKT/Cx
|
||||
j9NL4dcMgxRXsPdHfXb0923C7xYd2t2qfW05umgaj7qeQl6c68CFNsGX4JA8rWFQ
|
||||
ZvvGx5DGlK4KTcjPuQQINs5fxasNKqLY2hq+z82x/rqwr2hmyizD6FpFSyIABPEM
|
||||
PfB036GEhRwu1WEMkq8yIp2jgRUoFYke9pB3ph9pVow0Hh4mNFSKD4pP41VSKY1n
|
||||
us83mdkuukPy5o0CAwEAAaNvMG0wHQYDVR0OBBYEFC/euOfQMKIgnaoBhhqWT+3s
|
||||
8rzBMB8GA1UdIwQYMBaAFEahuO3bpnFf0NLneoo8XW6aw5Y4MAkGA1UdEwQCMAAw
|
||||
CwYDVR0PBAQDAgbAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUA
|
||||
A4IBAQBl2Bu9xpnHCCeeebjx+ILQXJXBd6q5+NQlV3zzBrf0bleZRtsOmsuFvWQo
|
||||
KQxsfZuk7QcSvVd/1v8mqwJ0PwbFKQmrhIPWP+iowiBNqpG5PH9YxhpHQ1osOfib
|
||||
NLOXMhudIQRY0yAgqQf+MOlXYa0stX8gkgftVBDRutuMKyOTf4a6d8TUcbG2Rnyz
|
||||
O/6S9bq4cPDYLqWRBM+aGN8e00UWTKpBl6/1EU8wkJA6WdllK2e8mVkXUPWYyHTZ
|
||||
0qQnrYiuLr36ycAznABDzEAoj4tMZbjIAfuscty6Ggzxl1WbyZLI6YzyXALwaYvr
|
||||
crTLeyFynlKxuCfDnr1SAHDM65BY
|
||||
-----END CERTIFICATE-----
|
@ -7,6 +7,8 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
compile libs.minimal_json
|
||||
compile libs.jcommander
|
||||
compile libs.bouncy_castle
|
||||
testCompile libs.testng
|
||||
}
|
||||
|
||||
@ -17,6 +19,7 @@ jar {
|
||||
)
|
||||
}
|
||||
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {}
|
||||
exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
|
Binary file not shown.
28
tools/tcg_rim_tool/privateRimKey.pem
Normal file
28
tools/tcg_rim_tool/privateRimKey.pem
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCndZVhpEkbsQAG
|
||||
NsB2oNhlcVJNXWcdj06X0Dn5by3nHAFcGvJkIZbEREavkCvIpY/F36rOOP5wWnHG
|
||||
Qzo3XyMSFAjH8IRl48QmqmW4E7nDbBMQ57uGq0xq2qAMMx4NHFS4ik/wsY/TS+HX
|
||||
DIMUV7D3R3129Pdtwu8WHdrdqn1tObpoGo+6nkJenOvAhTbBl+CQPK1hUGb7xseQ
|
||||
xpSuCk3Iz7kECDbOX8WrDSqi2Noavs/Nsf66sK9oZsosw+haRUsiAATxDD3wdN+h
|
||||
hIUcLtVhDJKvMiKdo4EVKBWJHvaQd6YfaVaMNB4eJjRUig+KT+NVUimNZ7rPN5nZ
|
||||
LrpD8uaNAgMBAAECggEAcnG8npd9U0x7HMQMcsZoPaPdwHvF/gCzkLNA+8RM1bZh
|
||||
A4ZzA5WlCQs0V8Wq9pyXjn7Wp8txsG1PdlT5k2AUgsVoXuR0R4IKyvYHQG9StEjH
|
||||
GvWURmwJdLlnSg8hSYqEJ/52taNUDO6+MI8fgiaQDd8w0ryF4OCpLy9GJdnfkGYZ
|
||||
Ayemb3USFUdj/S67NVqxnvAfFMM5FqkKGhkoy7wBRgO6eOeJvoTq8LMiPiponwwF
|
||||
DW409ZStbrk1f1Oszst/UvFUWA9BdDfeoPmFR61y3eB5zlMQG8Mhr2v5hvkj9TPX
|
||||
FU4Fm4EzZ1h/60cdWoP6XYCP7F2NqZ8N8u4UBQNAIQKBgQDcGIw5GJEvRF+FFTTR
|
||||
hYatMRn80DGTVjdT32MgajdKx05OWxBmQsFob34fiSnr0wAXPJeDXG4ruMBE2bSk
|
||||
EC8rCO08G8ihQoH8x0cvuERe1fpVWk3RWNucVGIiJSEXAIwWrlYZLTfYd5GqBkPE
|
||||
OQxxo4MtOyqeHmVH1mOywk9ABQKBgQDCxt95luzqQZV9Xl78QQvOIbjOdHLjY23Z
|
||||
yp8sGt9birL/WZ33TCRgmH1e61BdrSqO7Om/ail2Y59XM5UU6kLbDj0IgmOPTsrJ
|
||||
JmIVf8r3bKltVUaLePgr4yex7dmtHRH8OkLXKnE0RCO0kCi9kJMB12yE3pWxk+Pu
|
||||
zztQd3a66QKBgBNJd2g9deONe01fOVyu9clRhzR3ThDaOkj4R2h8xlGgO4V0R3Ce
|
||||
ovIy6vt6epj2yYg/wAs720+rhfXCmijSXj/ILXnZ+W/gMyHimKNe42boG2LFYhJZ
|
||||
Vg1R+7OAS3EHlD8ckeDs7Hrkp3gdymx0j1mZ+ZHKIIbwpPFxoRT2IBm9AoGBAI0Z
|
||||
bIK0puP8psKvPrgWluq42xwUl7XKLaX8dtqIjQ3PqGP7E8g2TJP9Y7UDWrDB5Xas
|
||||
gZi821R8Ts3o/DKukcgGxIgJjP4f4h9dwug4L1yWRxaBFB2tgHqqj/MBjxMtX/4M
|
||||
Zqdgg6mNQyBm3lyVAynuWRrX9DE0JYa2cQ2VvVkhAoGBAMBv/oT813w00759PmkO
|
||||
Uxv3LXTJuYBbq0Rmga25jN3ow8LrGQdSVg7F/af3I5KUF7mLiegDy1pkRfauyXH7
|
||||
+WhEqnf86vDrzPpytDMxinWOQZusCqeWHb+nuVTuL3Fv+GxEdwVGYI/7lFJ7B//h
|
||||
P5rU93ZoYY7sWcGVqaaEkMRU
|
||||
-----END PRIVATE KEY-----
|
190
tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java
Normal file
190
tools/tcg_rim_tool/src/main/java/hirs/swid/CredentialParser.java
Normal file
@ -0,0 +1,190 @@
|
||||
package hirs.swid;
|
||||
|
||||
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMKeyPair;
|
||||
import org.bouncycastle.openssl.PEMParser;
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
|
||||
/**
|
||||
* This class parses private key, public key, and certificate for use in their respective java.security objects.
|
||||
*/
|
||||
public class CredentialParser {
|
||||
private static final String X509 = "X.509";
|
||||
private static final String JKS = "JKS";
|
||||
private static final String PEM = "PEM";
|
||||
private static final String PKCS1_HEADER = "-----BEGIN 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_FOOTER = "-----END PRIVATE KEY-----";
|
||||
private X509Certificate certificate;
|
||||
private PrivateKey privateKey;
|
||||
private PublicKey publicKey;
|
||||
|
||||
public X509Certificate getCertificate() {
|
||||
return certificate;
|
||||
}
|
||||
|
||||
public PrivateKey getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public PublicKey getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public void parseJKSCredentials() {
|
||||
KeyStore.PrivateKeyEntry privateKeyEntry =
|
||||
parseKeystorePrivateKey(SwidTagConstants.DEFAULT_KEYSTORE_PATH,
|
||||
SwidTagConstants.DEFAULT_PRIVATE_KEY_ALIAS,
|
||||
SwidTagConstants.DEFAULT_KEYSTORE_PASSWORD);
|
||||
certificate = (X509Certificate) privateKeyEntry.getCertificate();
|
||||
privateKey = privateKeyEntry.getPrivateKey();
|
||||
publicKey = certificate.getPublicKey();
|
||||
}
|
||||
|
||||
public void parsePEMCredentials(String certificateFile, String privateKeyFile) throws FileNotFoundException {
|
||||
certificate = parsePEMCertificate(certificateFile);
|
||||
|
||||
/*User input on algorithm???*/
|
||||
privateKey = parsePEMPrivateKey(privateKeyFile, "RSA");
|
||||
|
||||
publicKey = certificate.getPublicKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the X509Certificate found in a PEM file.
|
||||
* @param filename
|
||||
* @return
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
private X509Certificate parsePEMCertificate(String filename) throws FileNotFoundException {
|
||||
X509Certificate certificate = null;
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(filename);
|
||||
BufferedInputStream bis = new BufferedInputStream(fis);
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
|
||||
|
||||
while (bis.available() > 0) {
|
||||
certificate = (X509Certificate) certificateFactory.generateCertificate(bis);
|
||||
}
|
||||
|
||||
|
||||
} catch (CertificateException e) {
|
||||
System.out.println("Error in certificate factory: " + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error reading from input stream: " + e.getMessage());
|
||||
}
|
||||
|
||||
return certificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method extracts the private key from a PEM file.
|
||||
* Both PKCS1 and PKCS8 formats are handled.
|
||||
* Algorithm argument is present to allow handling of multiple encryption algorithms,
|
||||
* but for now it is always RSA.
|
||||
* @param filename
|
||||
* @return
|
||||
*/
|
||||
private PrivateKey parsePEMPrivateKey(String filename, String algorithm) {
|
||||
PrivateKey privateKey = null;
|
||||
try {
|
||||
File file = new File(filename);
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
DataInputStream dis = new DataInputStream(fis);
|
||||
byte[] key = new byte[(int) file.length()];
|
||||
dis.readFully(key);
|
||||
dis.close();
|
||||
|
||||
String privateKeyStr = new String(key);
|
||||
if (privateKeyStr.contains(PKCS1_HEADER)) {
|
||||
privateKey = getPKCS1KeyPair(filename).getPrivate();
|
||||
} else if (privateKeyStr.contains(PKCS8_HEADER)) {
|
||||
privateKeyStr = privateKeyStr.replace(PKCS8_HEADER, "");
|
||||
privateKeyStr = privateKeyStr.replace(PKCS8_FOOTER, "");
|
||||
|
||||
byte[] decodedKey = Base64.decode(privateKeyStr);
|
||||
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decodedKey);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
|
||||
privateKey = keyFactory.generatePrivate(spec);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println("Unable to locate private key file: " + filename);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
System.out.println("Unable to instantiate KeyFactory with algorithm: " + algorithm);
|
||||
} catch (IOException e) {
|
||||
System.out.println("IOException: " + e.getMessage());
|
||||
} catch (InvalidKeySpecException e) {
|
||||
System.out.println("Error instantiating PKCS8EncodedKeySpec object: " + e.getMessage());
|
||||
}
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method reads a PKCS1 keypair from a PEM file.
|
||||
* @param filename
|
||||
* @return
|
||||
*/
|
||||
private KeyPair getPKCS1KeyPair(String filename) throws IOException {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
PEMParser pemParser = new PEMParser(new FileReader(filename));
|
||||
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
|
||||
KeyPair keyPair = converter.getKeyPair((PEMKeyPair) pemParser.readObject());
|
||||
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the private key from a JKS keystore.
|
||||
* @param keystoreFile
|
||||
* @param alias
|
||||
* @param password
|
||||
* @return KeyStore.PrivateKeyEntry
|
||||
*/
|
||||
private KeyStore.PrivateKeyEntry parseKeystorePrivateKey(String keystoreFile, String alias, String password) {
|
||||
KeyStore keystore = null;
|
||||
KeyStore.PrivateKeyEntry privateKey = null;
|
||||
try {
|
||||
keystore = KeyStore.getInstance("JKS");
|
||||
keystore.load(new FileInputStream(keystoreFile), password.toCharArray());
|
||||
privateKey = (KeyStore.PrivateKeyEntry) keystore.getEntry(alias,
|
||||
new KeyStore.PasswordProtection(password.toCharArray()));
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println("Cannot locate keystore " + keystoreFile);
|
||||
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableEntryException | CertificateException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for extracting the subjectKeyIdentifier from an X509Certificate.
|
||||
* The subjectKeyIdentifier is stored as a DER-encoded octet and will be converted to a String.
|
||||
* @return
|
||||
*/
|
||||
public String getCertificateSubjectKeyIdentifier() throws IOException {
|
||||
String decodedValue = null;
|
||||
byte[] extension = certificate.getExtensionValue(SwidTagConstants.CERTIFICATE_SUBJECT_KEY_IDENTIFIER);
|
||||
if (extension != null) {
|
||||
decodedValue = JcaX509ExtensionUtils.parseExtensionValue(extension).toString();
|
||||
}
|
||||
//If there is a # symbol at the beginning of the string, remove it
|
||||
if (decodedValue.startsWith("#")) {
|
||||
decodedValue = decodedValue.substring(1);
|
||||
}
|
||||
return decodedValue;
|
||||
}
|
||||
}
|
@ -1,50 +1,58 @@
|
||||
package hirs.swid;
|
||||
|
||||
import hirs.swid.utils.Commander;
|
||||
import com.beust.jcommander.JCommander;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
* Command-line application for generating and validating SWID tags.
|
||||
* Input arg: path to *.swidtag file
|
||||
*
|
||||
* If an argument is given it will be validated against the schema at http://standards.iso.org/iso/19770/-2/2015/schema.xsd
|
||||
* If an argument is not given a SWID tag file will be generated.
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Commander commander = new Commander(args);
|
||||
Commander commander = new Commander();
|
||||
JCommander jc = JCommander.newBuilder().addObject(commander).build();
|
||||
jc.parse(args);
|
||||
SwidTagGateway gateway = new SwidTagGateway();
|
||||
|
||||
if (commander.hasArguments()) {
|
||||
// we have arguments to work with
|
||||
if (commander.isAttributesGiven()) {
|
||||
gateway.setAttributesFile(commander.getAttributesFile());
|
||||
}
|
||||
if (commander.isKeystoreGiven()) {
|
||||
gateway.setKeystoreFile(commander.getKeystore());
|
||||
}
|
||||
if (commander.isShowCert()) {
|
||||
gateway.setShowCert(true);
|
||||
}
|
||||
|
||||
if (commander.create()) {
|
||||
// parsing the arguments detected a create parameter (-c)
|
||||
gateway.generateSwidTag(commander.getCreateOutFile());
|
||||
}
|
||||
if (commander.validate()) {
|
||||
// parsing the arguments detected a validation parameter (-v)
|
||||
try {
|
||||
gateway.validateSwidTag(commander.getValidateFile());
|
||||
} catch (IOException e) {
|
||||
System.out.println("Unable to validate file: " + e.getMessage());
|
||||
if (commander.isHelp()) {
|
||||
jc.usage();
|
||||
System.out.println(commander.printHelpExamples());
|
||||
} else {
|
||||
if (!commander.getVerifyFile().isEmpty()) {
|
||||
System.out.println(commander.toString());
|
||||
String verifyFile = commander.getVerifyFile();
|
||||
String publicCertificate = commander.getPublicCertificate();
|
||||
if (!verifyFile.isEmpty() && !publicCertificate.isEmpty()) {
|
||||
try {
|
||||
gateway.validateSwidTag(verifyFile);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error validating RIM file: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
System.out.println("Need both a RIM file to validate and a public certificate to validate with!");
|
||||
}
|
||||
}
|
||||
if (commander.parse()) {
|
||||
try {
|
||||
gateway.parsePayload(commander.getParseFile());
|
||||
} catch (IOException e) {
|
||||
System.out.println("Unable to parse file: " + e.getMessage());
|
||||
} else {
|
||||
System.out.println(commander.toString());
|
||||
String createType = commander.getCreateType().toUpperCase();
|
||||
String attributesFile = commander.getAttributesFile();
|
||||
String certificateFile = commander.getPublicCertificate();
|
||||
String privateKeyFile = commander.getPrivateKeyFile();
|
||||
switch (createType) {
|
||||
case "BASE":
|
||||
if (!attributesFile.isEmpty()) {
|
||||
gateway.setAttributesFile(attributesFile);
|
||||
}
|
||||
if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) {
|
||||
gateway.setDefaultCredentials(false);
|
||||
gateway.setPemCertificateFile(certificateFile);
|
||||
gateway.setPemPrivateKeyFile(privateKeyFile);
|
||||
}
|
||||
gateway.generateSwidTag(commander.getOutFile());
|
||||
break;
|
||||
case "EVENTLOG":
|
||||
break;
|
||||
case "PCR":
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,15 +20,10 @@ public class SwidTagConstants {
|
||||
|
||||
public static final String SIGNATURE_ALGORITHM_RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
|
||||
|
||||
public static final String SCHEMA_STATEMENT = "ISO/IEC 19770-2:2015 Schema (XSD 1.0) "
|
||||
+ "- September 2015, see http://standards.iso.org/iso/19770/-2/2015/schema.xsd";
|
||||
public static final String SCHEMA_PACKAGE = "hirs.swid.xjc";
|
||||
public static final String SCHEMA_LANGUAGE = XMLConstants.W3C_XML_SCHEMA_NS_URI;
|
||||
public static final String SCHEMA_URL = "swid_schema.xsd";
|
||||
|
||||
public static final String HIRS_SWIDTAG_HEADERS = "hirsSwidTagHeader.properties";
|
||||
public static final String EXAMPLE_PROPERTIES = "swidExample.properties";
|
||||
|
||||
public static final String SOFTWARE_IDENTITY = "SoftwareIdentity";
|
||||
public static final String ENTITY = "Entity";
|
||||
public static final String LINK = "Link";
|
||||
@ -147,48 +142,5 @@ public class SwidTagConstants {
|
||||
"http://csrc.nist.gov/ns/swid/2015-extensions/1.0",
|
||||
"pathSeparator", "n8060");
|
||||
|
||||
//Below properties can probably be deleted
|
||||
public static final String SOFTWARE_IDENTITY_NAME = "softwareIdentity.name";
|
||||
public static final String SOFTWARE_IDENTITY_TAGID = "softwareIdentity.tagId";
|
||||
public static final String SOFTWARE_IDENTITY_VERSION = "softwareIdentity.version";
|
||||
public static final String SOFTWARE_IDENTITY_CORPUS = "softwareIdentity.corpus";
|
||||
public static final String SOFTWARE_IDENTITY_PATCH = "softwareIdentity.patch";
|
||||
public static final String SOFTWARE_IDENTITY_SUPPLEMENTAL = "softwareIdentity.supplemental";
|
||||
|
||||
public static final String ENTITY_NAME = "entity.name";
|
||||
public static final String ENTITY_REGID = "entity.regid";
|
||||
public static final String ENTITY_ROLE = "entity.role";
|
||||
public static final String ENTITY_THUMBPRINT = "entity.thumbprint";
|
||||
|
||||
public static final String LINK_HREF = "link.href";
|
||||
public static final String LINK_REL = "link.rel";
|
||||
|
||||
public static final String META_PCURILOCAL = "softwareMeta.pcUriLocal";
|
||||
public static final String META_BINDINGSPEC = "softwareMeta.bindingSpec";
|
||||
public static final String META_BINDINGSPECVERSION = "softwareMeta.bindingSpecVersion";
|
||||
public static final String META_PLATFORMMANUFACTURERID = "softwareMeta.platformManufacturerId";
|
||||
public static final String META_PLATFORMMANUFACTURERSTR = "softwareMeta.platformManufacturerStr";
|
||||
public static final String META_PLATFORMMODEL = "softwareMeta.platformModel";
|
||||
public static final String META_COMPONENTCLASS = "softwareMeta.componentClass";
|
||||
public static final String META_COMPONENTMANUFACTURER = "softwareMeta.componentManufacturer";
|
||||
public static final String META_COMPONENTMANUFACTURERID = "softwareMeta.componentManufacturerId";
|
||||
public static final String META_RIMLINKHASH = "softwareMeta.rimLinkHash";
|
||||
|
||||
public static final String PAYLOAD_ENVVARPREFIX = "n8060.envvarprefix";
|
||||
public static final String PAYLOAD_ENVVARSUFFIX = "n8060.envvarsuffix";
|
||||
public static final String PAYLOAD_PATHSEPARATOR = "n8060.pathseparator";
|
||||
|
||||
public static final String DIRECTORY_KEY = "directory.key";
|
||||
public static final String DIRECTORY_LOCATION = "directory.location";
|
||||
public static final String DIRECTORY_NAME = "directory.name";
|
||||
public static final String DIRECTORY_ROOT = "directory.root";
|
||||
public static final String FILE_KEY = "file.key";
|
||||
public static final String FILE_LOCATION = "file.location";
|
||||
public static final String FILE_NAME = "file.name";
|
||||
public static final String FILE_ROOT = "file.root";
|
||||
public static final String FILE_SIZE = "file.size";
|
||||
public static final String FILE_VERSION = "file.version";
|
||||
|
||||
public static final int PCR_NUMBER = 0;
|
||||
public static final int PCR_VALUE = 1;
|
||||
public static final String CERTIFICATE_SUBJECT_KEY_IDENTIFIER = "2.5.29.14";
|
||||
}
|
||||
|
@ -1,18 +1,19 @@
|
||||
package hirs.swid;
|
||||
|
||||
import javax.xml.bind.JAXB;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.UnmarshalException;
|
||||
import javax.xml.crypto.dsig.keyinfo.*;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
@ -29,7 +30,6 @@ import javax.xml.crypto.XMLStructure;
|
||||
import javax.xml.crypto.dsig.CanonicalizationMethod;
|
||||
import javax.xml.crypto.dsig.DigestMethod;
|
||||
import javax.xml.crypto.dsig.Reference;
|
||||
import javax.xml.crypto.dsig.SignatureMethod;
|
||||
import javax.xml.crypto.dsig.SignedInfo;
|
||||
import javax.xml.crypto.dsig.Transform;
|
||||
import javax.xml.crypto.dsig.XMLSignature;
|
||||
@ -37,78 +37,48 @@ import javax.xml.crypto.dsig.XMLSignatureException;
|
||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||
import javax.xml.crypto.dsig.dom.DOMSignContext;
|
||||
import javax.xml.crypto.dsig.dom.DOMValidateContext;
|
||||
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
|
||||
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
|
||||
import javax.xml.crypto.dsig.keyinfo.X509Data;
|
||||
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
|
||||
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.UnrecoverableEntryException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.*;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import hirs.swid.utils.CsvParser;
|
||||
import hirs.swid.utils.HashSwid;
|
||||
import hirs.swid.xjc.BaseElement;
|
||||
import hirs.swid.xjc.CanonicalizationMethodType;
|
||||
import hirs.swid.xjc.DigestMethodType;
|
||||
import hirs.swid.xjc.Directory;
|
||||
import hirs.swid.xjc.Entity;
|
||||
import hirs.swid.xjc.Link;
|
||||
import hirs.swid.xjc.ObjectFactory;
|
||||
import hirs.swid.xjc.ResourceCollection;
|
||||
import hirs.swid.xjc.ReferenceType;
|
||||
import hirs.swid.xjc.SignatureType;
|
||||
import hirs.swid.xjc.SignatureValueType;
|
||||
import hirs.swid.xjc.SignatureMethodType;
|
||||
import hirs.swid.xjc.SignedInfoType;
|
||||
import hirs.swid.xjc.SoftwareIdentity;
|
||||
import hirs.swid.xjc.SoftwareMeta;
|
||||
import hirs.swid.xjc.TransformType;
|
||||
import hirs.swid.xjc.TransformsType;
|
||||
|
||||
import com.eclipsesource.json.Json;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import com.eclipsesource.json.JsonObject.Member;
|
||||
import com.eclipsesource.json.JsonValue;
|
||||
import com.eclipsesource.json.Location;
|
||||
import com.eclipsesource.json.ParseException;
|
||||
|
||||
|
||||
@ -120,32 +90,16 @@ import com.eclipsesource.json.ParseException;
|
||||
*/
|
||||
public class SwidTagGateway {
|
||||
|
||||
private static final QName _DEFAULT_QNAME = new QName(
|
||||
"http://www.w3.org/2000/09/xmldsig#", "SHA256", "ds");
|
||||
private static final QName _SHA1Value_QNAME = new QName(
|
||||
"http://www.w3.org/2000/09/xmldsig#", "SHA1", "ds");
|
||||
private static final QName _SHA384Value_QNAME = new QName(
|
||||
"http://www.w3.org/2000/09/xmldsig#", "SHA384", "ds");
|
||||
private static final QName _SHA512Value_QNAME = new QName(
|
||||
"http://www.w3.org/2000/09/xmldsig#", "SHA512", "ds");
|
||||
private static final QName _SHA256_HASH = new QName(
|
||||
"http://www.w3.org/2001/04/xmlenc#sha256", "hash", "SHA256");
|
||||
|
||||
private final ObjectFactory objectFactory = new ObjectFactory();
|
||||
private final File generatedFile = new File("generated_swidTag.swidtag");
|
||||
private QName hashValue = null;
|
||||
|
||||
private JAXBContext jaxbContext;
|
||||
private Marshaller marshaller;
|
||||
private Unmarshaller unmarshaller;
|
||||
private String attributesFile;
|
||||
/**
|
||||
* The keystoreFile is used in signXMLDocument() to pass in the keystore path.
|
||||
* The same method requires the keystore password and the alias of the private key,
|
||||
* which would need to be passed in if not using the default keystore.
|
||||
*/
|
||||
private String keystoreFile;
|
||||
private boolean showCert;
|
||||
private boolean defaultCredentials;
|
||||
private String pemPrivateKeyFile;
|
||||
private String pemCertificateFile;
|
||||
|
||||
/**
|
||||
* Default constructor initializes jaxbcontext, marshaller, and unmarshaller
|
||||
@ -156,8 +110,8 @@ public class SwidTagGateway {
|
||||
marshaller = jaxbContext.createMarshaller();
|
||||
unmarshaller = jaxbContext.createUnmarshaller();
|
||||
attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE;
|
||||
keystoreFile = SwidTagConstants.DEFAULT_KEYSTORE_PATH;
|
||||
showCert = false;
|
||||
defaultCredentials = true;
|
||||
pemCertificateFile = "";
|
||||
} catch (JAXBException e) {
|
||||
System.out.println("Error initializing jaxbcontext: " + e.getMessage());
|
||||
}
|
||||
@ -172,107 +126,37 @@ public class SwidTagGateway {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for String holding keystore path
|
||||
* @param keystore
|
||||
* Setter for boolean governing signing credentials
|
||||
* @param defaultCredentials
|
||||
* @return
|
||||
*/
|
||||
public void setKeystoreFile(String keystoreFile) {
|
||||
this.keystoreFile = keystoreFile;
|
||||
public void setDefaultCredentials(boolean defaultCredentials) {
|
||||
this.defaultCredentials = defaultCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for boolean to display certificate block in xml signature
|
||||
* @param showCert
|
||||
* Setter for private key file in PEM format
|
||||
* @param pemPrivateKeyFile
|
||||
*/
|
||||
public void setShowCert(boolean showCert) {
|
||||
this.showCert = showCert;
|
||||
public void setPemPrivateKeyFile(String pemPrivateKeyFile) {
|
||||
this.pemPrivateKeyFile = pemPrivateKeyFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* default generator method that has no parameters
|
||||
/** Setter for certificate file in PEM format
|
||||
* @param pemCertificateFile
|
||||
*/
|
||||
public void generateSwidTag() {
|
||||
generateSwidTag("");
|
||||
}
|
||||
|
||||
/**
|
||||
* This generator method is used by the create method.
|
||||
*
|
||||
* This method should be updated to incorporate the RIM fields that are implemented
|
||||
* in generateSwidTag(final File outputFile) below.
|
||||
*
|
||||
* @param inputFile - the file in csv format that is used as data
|
||||
* @param outputFile - output specific to the given file
|
||||
* @param hashType - the optional labeling of the hash type
|
||||
*/
|
||||
public void generateSwidTag(final String inputFile,
|
||||
final String outputFile, final String hashType) {
|
||||
// create file instances
|
||||
File input = new File(inputFile);
|
||||
File output = new File(outputFile);
|
||||
List<String> tempList = new LinkedList<>();
|
||||
|
||||
// I need to go over this again about which needs to be checked.
|
||||
if (input.exists()) {
|
||||
// parse the csv file
|
||||
CsvParser parser = new CsvParser(input);
|
||||
for (String line : parser.getContent()) {
|
||||
tempList.add(line);
|
||||
}
|
||||
|
||||
if (hashType.contains("256")) {
|
||||
hashValue = _DEFAULT_QNAME;
|
||||
} else if (hashType.contains("384")) {
|
||||
hashValue = _SHA384Value_QNAME;
|
||||
} else if (hashType.contains("512")) {
|
||||
hashValue = _SHA512Value_QNAME;
|
||||
} else if (hashType.contains("1")) {
|
||||
hashValue = _SHA1Value_QNAME;
|
||||
} else {
|
||||
hashValue = _DEFAULT_QNAME;
|
||||
}
|
||||
|
||||
// generate a swid tag
|
||||
Properties properties = new Properties();
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = SwidTagGateway.class.getClassLoader().getResourceAsStream(SwidTagConstants.HIRS_SWIDTAG_HEADERS);
|
||||
properties.load(is);
|
||||
|
||||
SoftwareIdentity swidTag = createSwidTag(new JsonObject());
|
||||
|
||||
JAXBElement<Entity> entity = objectFactory.createSoftwareIdentityEntity(createEntity(new JsonObject()));
|
||||
swidTag.getEntityOrEvidenceOrLink().add(entity);
|
||||
|
||||
// we should have resources, there for we need a collection
|
||||
JAXBElement<ResourceCollection> resources = objectFactory.createSoftwareIdentityPayload(createPayload(tempList, hashValue));
|
||||
swidTag.getEntityOrEvidenceOrLink().add(resources);
|
||||
|
||||
JAXBElement<SoftwareIdentity> jaxbe = objectFactory.createSoftwareIdentity(swidTag);
|
||||
writeSwidTagFile(jaxbe, output);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error reading properties file: ");
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setPemCertificateFile(String pemCertificateFile) {
|
||||
this.pemCertificateFile = pemCertificateFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method generates a base RIM from the values in a JSON file.
|
||||
*
|
||||
* @param outputFile
|
||||
* @param filename
|
||||
*/
|
||||
public void generateSwidTag(final String filename) {
|
||||
SoftwareIdentity swidTag = null;
|
||||
try {
|
||||
System.out.println("Reading base rim values from " + attributesFile);
|
||||
BufferedReader jsonIn = Files.newBufferedReader(Paths.get(attributesFile), StandardCharsets.UTF_8);
|
||||
JsonObject configProperties = Json.parse(jsonIn).asObject();
|
||||
//SoftwareIdentity
|
||||
@ -318,12 +202,7 @@ public class SwidTagGateway {
|
||||
}
|
||||
|
||||
Document signedSoftwareIdentity = signXMLDocument(objectFactory.createSoftwareIdentity(swidTag));
|
||||
System.out.println("Signature core validity: " + validateSignedXMLDocument(signedSoftwareIdentity));
|
||||
if (!filename.isEmpty()) {
|
||||
writeSwidTagFile(signedSoftwareIdentity, new File(filename));
|
||||
} else {
|
||||
writeSwidTagFile(signedSoftwareIdentity, generatedFile);
|
||||
}
|
||||
writeSwidTagFile(signedSoftwareIdentity, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -334,51 +213,33 @@ public class SwidTagGateway {
|
||||
* @param path the location of the file to be validated
|
||||
*/
|
||||
public boolean validateSwidTag(String path) throws IOException {
|
||||
JAXBElement jaxbe = unmarshallSwidTag(path);
|
||||
SoftwareIdentity swidTag = (SoftwareIdentity) jaxbe.getValue();
|
||||
String output = String.format("name: %s;\ntagId: %s\n%s",
|
||||
swidTag.getName(), swidTag.getTagId(),
|
||||
SwidTagConstants.SCHEMA_STATEMENT);
|
||||
System.out.println("SWID Tag found: ");
|
||||
System.out.println(output);
|
||||
Document document = unmarshallSwidTag(path);
|
||||
Element softwareIdentity = (Element) document.getElementsByTagName("SoftwareIdentity").item(0);
|
||||
StringBuilder si = new StringBuilder("Base RIM detected:\n");
|
||||
si.append("SoftwareIdentity name: " + softwareIdentity.getAttribute("name") + "\n");
|
||||
si.append("SoftwareIdentity tagId: " + softwareIdentity.getAttribute("tagId") + "\n");
|
||||
System.out.println(si.toString());
|
||||
System.out.println("Signature core validity: " + validateSignedXMLDocument(document));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method calls the marshal() method that writes the swidtag data to the output file.
|
||||
*
|
||||
* @param jaxbe
|
||||
* @param outputFile
|
||||
*/
|
||||
public void writeSwidTagFile(JAXBElement<SoftwareIdentity> jaxbe, File outputFile) {
|
||||
JAXBContext jaxbContext;
|
||||
try {
|
||||
jaxbContext = JAXBContext.newInstance(SwidTagConstants.SCHEMA_PACKAGE);
|
||||
Marshaller marshaller = jaxbContext.createMarshaller();
|
||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
|
||||
marshaller.marshal(jaxbe, outputFile);
|
||||
} catch (JAXBException e) {
|
||||
System.out.println("Error generating xml: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method writes a Document object out to the file specified by generatedFile.
|
||||
*
|
||||
* @param swidTag
|
||||
*/
|
||||
public void writeSwidTagFile(Document swidTag, File outputFile) {
|
||||
public void writeSwidTagFile(Document swidTag, String output) {
|
||||
try {
|
||||
OutputStream outStream = new FileOutputStream(outputFile);
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Transformer transformer = tf.newTransformer();
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
||||
Source source = new DOMSource(swidTag);
|
||||
System.out.println("Writing to file: " + outputFile.getName());
|
||||
transformer.transform(source, new StreamResult(outStream));
|
||||
transformer.transform(source, new StreamResult(System.out));
|
||||
if (output.isEmpty()) {
|
||||
transformer.transform(source, new StreamResult(System.out));
|
||||
} else {
|
||||
transformer.transform(source, new StreamResult(new FileOutputStream(output)));
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println("Unable to write to file: " + e.getMessage());
|
||||
} catch (TransformerConfigurationException e) {
|
||||
@ -392,7 +253,7 @@ public class SwidTagGateway {
|
||||
* This method creates SoftwareIdentity element based on the parameters read in from
|
||||
* a properties file.
|
||||
*
|
||||
* @param properties the Properties object containing parameters from file
|
||||
* @param jsonObject the Properties object containing parameters from file
|
||||
* @return SoftwareIdentity object created from the properties
|
||||
*/
|
||||
private SoftwareIdentity createSwidTag(JsonObject jsonObject) {
|
||||
@ -426,7 +287,7 @@ public class SwidTagGateway {
|
||||
* This method creates an Entity object based on the parameters read in from
|
||||
* a properties file.
|
||||
*
|
||||
* @param properties the Properties object containing parameters from file
|
||||
* @param jsonObject the Properties object containing parameters from file
|
||||
* @return Entity object created from the properties
|
||||
*/
|
||||
private Entity createEntity(JsonObject jsonObject) {
|
||||
@ -463,7 +324,7 @@ public class SwidTagGateway {
|
||||
/**
|
||||
* Thsi method creates a Link element based on the parameters read in from a properties
|
||||
* file.
|
||||
* @param properties the Properties object containing parameters from file
|
||||
* @param jsonObject the Properties object containing parameters from file
|
||||
* @return Link element created from the properties
|
||||
*/
|
||||
private Link createLink(JsonObject jsonObject) {
|
||||
@ -483,7 +344,7 @@ public class SwidTagGateway {
|
||||
/**
|
||||
* This method creates a Meta element based on the parameters read in from a properties
|
||||
* file.
|
||||
* @param properties the Properties object containing parameters from file
|
||||
* @param jsonObject the Properties object containing parameters from file
|
||||
* @return the Meta element created from the properties
|
||||
*/
|
||||
private SoftwareMeta createSoftwareMeta(JsonObject jsonObject) {
|
||||
@ -514,15 +375,15 @@ public class SwidTagGateway {
|
||||
/**
|
||||
* This method creates a Payload from the parameters read in from a properties file.
|
||||
*
|
||||
* @param properties the Properties object containing parameters from file
|
||||
* @param jsonObject the Properties object containing parameters from file
|
||||
* @return the Payload object created
|
||||
*/
|
||||
private ResourceCollection createPayload(JsonObject jsonObject) {
|
||||
ResourceCollection payload = objectFactory.createResourceCollection();
|
||||
Map<QName, String> attributes = payload.getOtherAttributes();
|
||||
addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARPREFIX, jsonObject.getString(SwidTagConstants.PAYLOAD_ENVVARPREFIX, ""));
|
||||
addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARSUFFIX, jsonObject.getString(SwidTagConstants.PAYLOAD_ENVVARSUFFIX, ""));
|
||||
addNonNullAttribute(attributes, SwidTagConstants._N8060_PATHSEPARATOR, jsonObject.getString(SwidTagConstants.PAYLOAD_PATHSEPARATOR, ""));
|
||||
addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARPREFIX, jsonObject.getString(SwidTagConstants._N8060_ENVVARPREFIX.getLocalPart(), ""));
|
||||
addNonNullAttribute(attributes, SwidTagConstants._N8060_ENVVARSUFFIX, jsonObject.getString(SwidTagConstants._N8060_ENVVARSUFFIX.getLocalPart(), ""));
|
||||
addNonNullAttribute(attributes, SwidTagConstants._N8060_PATHSEPARATOR, jsonObject.getString(SwidTagConstants._N8060_PATHSEPARATOR.getLocalPart(), ""));
|
||||
|
||||
return payload;
|
||||
}
|
||||
@ -530,7 +391,7 @@ public class SwidTagGateway {
|
||||
/**
|
||||
* This method creates a Directory from the parameters read in from a properties file.
|
||||
*
|
||||
* @param properties the Properties object containing parameters from file
|
||||
* @param jsonObject the Properties object containing parameters from file
|
||||
* @return Directory object created from the properties
|
||||
*/
|
||||
private Directory createDirectory(JsonObject jsonObject) {
|
||||
@ -540,13 +401,7 @@ public class SwidTagGateway {
|
||||
addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_TYPE, jsonObject.getString(SwidTagConstants.SUPPORT_RIM_TYPE, ""));
|
||||
addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_FORMAT, jsonObject.getString(SwidTagConstants.SUPPORT_RIM_FORMAT, ""));
|
||||
addNonNullAttribute(attributes, SwidTagConstants._SUPPORT_RIM_URI_GLOBAL, jsonObject.getString(SwidTagConstants.SUPPORT_RIM_URI_GLOBAL, ""));
|
||||
/*
|
||||
directory.setLocation(jsonObject.getString(SwidTagConstants.DIRECTORY_LOCATION));
|
||||
String directoryRoot = jsonObject.getString(SwidTagConstants.DIRECTORY_ROOT);
|
||||
if (!directoryRoot.isEmpty()) {
|
||||
directory.setRoot(directoryRoot);
|
||||
}
|
||||
*/
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
@ -554,8 +409,7 @@ public class SwidTagGateway {
|
||||
* This method creates a hirs.swid.xjc.File from three arguments, then calculates
|
||||
* and stores its hash as an attribute in itself.
|
||||
*
|
||||
* @param filename
|
||||
* @param location
|
||||
* @param jsonObject
|
||||
* @return hirs.swid.xjc.File object from File object
|
||||
*/
|
||||
private hirs.swid.xjc.File createFile(JsonObject jsonObject) {
|
||||
@ -577,32 +431,6 @@ public class SwidTagGateway {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a Payload from a list of Strings and a hash algorithm.
|
||||
* The Strings in the list are expected to be in the form of "[PCR_NUMBER],[PCR_VALUE]"
|
||||
* and the hash algorithm is attached as the file's xml namespace identifier.
|
||||
*
|
||||
* @param populate
|
||||
* @return
|
||||
*/
|
||||
private ResourceCollection createPayload(List<String> populate, QName hashStr) {
|
||||
ResourceCollection rc = objectFactory.createResourceCollection();
|
||||
hirs.swid.xjc.File xjcFile = null;
|
||||
String[] tempArray = null;
|
||||
|
||||
for (String item : populate) {
|
||||
xjcFile = objectFactory.createFile();
|
||||
|
||||
tempArray = item.split(",");
|
||||
|
||||
xjcFile.setName(tempArray[SwidTagConstants.PCR_NUMBER]);
|
||||
xjcFile.getOtherAttributes().put(hashStr, tempArray[SwidTagConstants.PCR_VALUE]);
|
||||
rc.getDirectoryOrFileOrProcess().add(xjcFile);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method signs a SoftwareIdentity with an xmldsig in compatibility mode.
|
||||
* Current assumptions: digest method SHA256, signature method SHA256, enveloped signature
|
||||
@ -623,34 +451,47 @@ public class SwidTagGateway {
|
||||
sigFactory.newSignatureMethod(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256, null),
|
||||
Collections.singletonList(reference)
|
||||
);
|
||||
KeyStore keystore = KeyStore.getInstance("JKS");
|
||||
keystore.load(new FileInputStream(keystoreFile), SwidTagConstants.DEFAULT_KEYSTORE_PASSWORD.toCharArray());
|
||||
KeyStore.PrivateKeyEntry privateKey = (KeyStore.PrivateKeyEntry) keystore.getEntry(SwidTagConstants.DEFAULT_PRIVATE_KEY_ALIAS,
|
||||
new KeyStore.PasswordProtection(SwidTagConstants.DEFAULT_KEYSTORE_PASSWORD.toCharArray()));
|
||||
X509Certificate certificate = (X509Certificate) privateKey.getCertificate();
|
||||
List<XMLStructure> keyInfoElements = new ArrayList<XMLStructure>();
|
||||
|
||||
KeyInfoFactory kiFactory = sigFactory.getKeyInfoFactory();
|
||||
ArrayList<Object> x509Content = new ArrayList<Object>();
|
||||
x509Content.add(certificate.getSubjectX500Principal().getName());
|
||||
if (showCert) {
|
||||
PrivateKey privateKey;
|
||||
PublicKey publicKey;
|
||||
CredentialParser cp = new CredentialParser();
|
||||
if (defaultCredentials) {
|
||||
cp.parseJKSCredentials();
|
||||
privateKey = cp.getPrivateKey();
|
||||
publicKey = cp.getPublicKey();
|
||||
} else {
|
||||
cp.parsePEMCredentials(pemCertificateFile, pemPrivateKeyFile);
|
||||
X509Certificate certificate = cp.getCertificate();
|
||||
privateKey = cp.getPrivateKey();
|
||||
publicKey = cp.getPublicKey();
|
||||
ArrayList<Object> x509Content = new ArrayList<Object>();
|
||||
x509Content.add(certificate.getSubjectX500Principal().getName());
|
||||
x509Content.add(certificate);
|
||||
X509Data data = kiFactory.newX509Data(x509Content);
|
||||
keyInfoElements.add(data);
|
||||
}
|
||||
X509Data data = kiFactory.newX509Data(x509Content);
|
||||
KeyInfo keyinfo = kiFactory.newKeyInfo(Collections.singletonList(data));
|
||||
KeyName keyName = kiFactory.newKeyName(cp.getCertificateSubjectKeyIdentifier());
|
||||
keyInfoElements.add(keyName);
|
||||
KeyValue keyValue = kiFactory.newKeyValue(publicKey);
|
||||
keyInfoElements.add(keyValue);
|
||||
KeyInfo keyinfo = kiFactory.newKeyInfo(keyInfoElements);
|
||||
|
||||
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
||||
marshaller.marshal(swidTag, doc);
|
||||
DOMSignContext context = new DOMSignContext(privateKey.getPrivateKey(), doc.getDocumentElement());
|
||||
DOMSignContext context = new DOMSignContext(privateKey, doc.getDocumentElement());
|
||||
XMLSignature signature = sigFactory.newXMLSignature(signedInfo, keyinfo);
|
||||
signature.sign(context);
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println("Keystore not found! " + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error loading keystore: " + e.getMessage());
|
||||
} catch (NoSuchAlgorithmException | KeyStoreException | InvalidAlgorithmParameterException |
|
||||
ParserConfigurationException | UnrecoverableEntryException e) {
|
||||
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException |
|
||||
ParserConfigurationException e) {
|
||||
System.out.println(e.getMessage());
|
||||
} catch (CertificateException e) {
|
||||
System.out.println("Certificate error: " + e.getMessage());
|
||||
} catch (KeyException e) {
|
||||
System.out.println("Error setting public key in KeyValue: " + e.getMessage());
|
||||
} catch (JAXBException e) {
|
||||
System.out.println("Error marshaling signed swidtag: " + e.getMessage());
|
||||
} catch (MarshalException | XMLSignatureException e) {
|
||||
@ -733,92 +574,26 @@ public class SwidTagGateway {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an input swidtag at [path] parse any PCRs in the payload into an InputStream object.
|
||||
* This method will be used in a following pull request.
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public ByteArrayInputStream parsePayload(String path) throws IOException {
|
||||
JAXBElement jaxbe = unmarshallSwidTag(path);
|
||||
SoftwareIdentity softwareIdentity = (SoftwareIdentity) jaxbe.getValue();
|
||||
String pcrs = "";
|
||||
if (!softwareIdentity.getEntityOrEvidenceOrLink().isEmpty()) {
|
||||
List<Object> swidtag = softwareIdentity.getEntityOrEvidenceOrLink();
|
||||
for (Object obj : swidtag) {
|
||||
try {
|
||||
JAXBElement element = (JAXBElement) obj;
|
||||
String elementName = element.getName().getLocalPart();
|
||||
if (elementName.equals(SwidTagConstants.PAYLOAD)) {
|
||||
ResourceCollection rc = (ResourceCollection) element.getValue();
|
||||
if (!rc.getDirectoryOrFileOrProcess().isEmpty()) {
|
||||
pcrs = parsePCRs(rc.getDirectoryOrFileOrProcess());
|
||||
}
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
System.out.println("Found a non-JAXBElement object!" + e.getMessage());
|
||||
throw new IOException("Found an invalid element in the swidtag file!");
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ByteArrayInputStream(pcrs.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method traverses a hirs.swid.xjc.Directory recursively until it finds at
|
||||
* least one hirs.swid.xjc.File. This File is expected to have an attribute of the form
|
||||
* "[hash algorithm]=[hash value]."
|
||||
*
|
||||
* @param list of swidtag elements
|
||||
* @return the hash value(s) parsed from the File object(s)
|
||||
*/
|
||||
private String parsePCRs(List list) {
|
||||
final String newline = System.lineSeparator();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Object listItem : list) {
|
||||
if (listItem instanceof Directory) {
|
||||
Directory dir = (Directory) listItem;
|
||||
if (!dir.getDirectoryOrFile().isEmpty()) {
|
||||
parsePCRs(dir.getDirectoryOrFile());
|
||||
}
|
||||
} else if (listItem instanceof hirs.swid.xjc.File){
|
||||
hirs.swid.xjc.File pcr = (hirs.swid.xjc.File) listItem;
|
||||
String pcrHash = "";
|
||||
if (!pcr.getOtherAttributes().isEmpty()) {
|
||||
Object[] fileAttributes = pcr.getOtherAttributes().values().toArray();
|
||||
pcrHash = (String) fileAttributes[0];
|
||||
}
|
||||
if (pcrHash.isEmpty()) {
|
||||
pcrHash = "null";
|
||||
}
|
||||
sb.append(pcr.getName() + "," + pcrHash);
|
||||
}
|
||||
}
|
||||
System.out.println(sb.toString());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method unmarshalls the swidtag found at [path] into a JAXBElement object
|
||||
* This method unmarshalls the swidtag found at [path] into a Document object
|
||||
* and validates it according to the schema.
|
||||
*
|
||||
* @param path to the input swidtag
|
||||
* @return the SoftwareIdentity element at the root of the swidtag
|
||||
* @throws IOException if the swidtag cannot be unmarshalled or validated
|
||||
*/
|
||||
private JAXBElement unmarshallSwidTag(String path) throws IOException {
|
||||
File input = null;
|
||||
InputStream is = null;
|
||||
JAXBElement swidtag = null;
|
||||
try {
|
||||
input = new File(path);
|
||||
is = SwidTagGateway.class.getClassLoader().getResourceAsStream(SwidTagConstants.SCHEMA_URL);
|
||||
SchemaFactory schemaFactory = SchemaFactory.newInstance(SwidTagConstants.SCHEMA_LANGUAGE);
|
||||
Schema schema = schemaFactory.newSchema(new StreamSource(is));
|
||||
unmarshaller.setSchema(schema);
|
||||
swidtag = (JAXBElement) unmarshaller.unmarshal(input);
|
||||
} catch (SAXException e) {
|
||||
private Document unmarshallSwidTag(String path) {
|
||||
InputStream is = null;
|
||||
Document document = null;
|
||||
try {
|
||||
document = removeXMLWhitespace(path);
|
||||
is = SwidTagGateway.class.getClassLoader().getResourceAsStream(SwidTagConstants.SCHEMA_URL);
|
||||
SchemaFactory schemaFactory = SchemaFactory.newInstance(SwidTagConstants.SCHEMA_LANGUAGE);
|
||||
Schema schema = schemaFactory.newSchema(new StreamSource(is));
|
||||
unmarshaller.setSchema(schema);
|
||||
unmarshaller.unmarshal(document);
|
||||
} catch (IOException e) {
|
||||
System.out.println(e.getMessage());
|
||||
} catch (SAXException e) {
|
||||
System.out.println("Error setting schema for validation!");
|
||||
} catch (UnmarshalException e) {
|
||||
System.out.println("Error validating swidtag file!");
|
||||
@ -827,18 +602,46 @@ public class SwidTagGateway {
|
||||
} catch (JAXBException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error closing input stream");
|
||||
}
|
||||
}
|
||||
if (swidtag != null) {
|
||||
return swidtag;
|
||||
} else {
|
||||
throw new IOException("Invalid swidtag file!");
|
||||
}
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error closing input stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method strips all whitespace from an xml file, including indents and spaces
|
||||
* added for human-readability.
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
private Document removeXMLWhitespace(String path) throws IOException {
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Source source = new StreamSource(new File("identity_transform.xslt"));
|
||||
Document document = null;
|
||||
File input = new File(path);
|
||||
if (input.length() > 0) {
|
||||
try {
|
||||
Transformer transformer = tf.newTransformer(source);
|
||||
DOMResult result = new DOMResult();
|
||||
transformer.transform(new StreamSource(input), result);
|
||||
document = (Document) result.getNode();
|
||||
} catch (TransformerConfigurationException e) {
|
||||
System.out.println("Error configuring transformer!");
|
||||
e.printStackTrace();
|
||||
} catch (TransformerException e) {
|
||||
System.out.println("Error transforming input!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
throw new IOException("Input file is empty!");
|
||||
}
|
||||
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
@ -6,292 +6,119 @@ import java.nio.file.Files;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
|
||||
/**
|
||||
* Commander is a class that handles the command line arguments for the SWID
|
||||
* Tags gateway.
|
||||
* Tags gateway by implementing the JCommander package.
|
||||
*/
|
||||
public class Commander {
|
||||
|
||||
private static final String COMMAND_PREFIX = "-";
|
||||
private static final String FULL_COMMAND_PREFIX = "--";
|
||||
private static final String CREATE_STRING = "create";
|
||||
private static final String VERIFY_STRING = "verify";
|
||||
private static final String HELP_STRING = "help";
|
||||
private static final String PARSE_STRING = "parse";
|
||||
private static final String ATTRIBUTES_STRING = "attributes";
|
||||
private static final String KEYSTORE_STRING = "keystore";
|
||||
private static final String SHOW_CERT_STRING = "show-cert";
|
||||
|
||||
private boolean hasArguments = false;
|
||||
private boolean validate = false;
|
||||
private boolean create = false;
|
||||
private boolean parse = false;
|
||||
private boolean attributesGiven = false;
|
||||
private boolean keystoreGiven = false;
|
||||
private boolean showCert = false;
|
||||
|
||||
private String validateFile;
|
||||
private String createOutFile = "";
|
||||
private String parseFile;
|
||||
@Parameter(names = {"-h", "--help"}, help = true, description = "Print this help text.")
|
||||
private boolean help;
|
||||
@Parameter(names = {"-c", "--create \"base\""}, order = 0,
|
||||
description = "The type of RIM to create. A base RIM will be created by default.")
|
||||
private String createType = "";//other possible values: "eventlog" and "pcr"
|
||||
@Parameter(names = {"-a", "--attributes <path>"}, order = 1,
|
||||
description = "The configuration file holding attributes to populate the base RIM with.")
|
||||
private String attributesFile = "";
|
||||
private String keystore = "";
|
||||
private String hashAlg = null;
|
||||
|
||||
/**
|
||||
* The main constructor for the Commander class
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public Commander(final String[] args) {
|
||||
hasArguments = args.length > 0;
|
||||
|
||||
if (hasArguments) {
|
||||
parseArguments(args);
|
||||
} else {
|
||||
printHelp();
|
||||
}
|
||||
|
||||
if (create) {
|
||||
if (hashAlg == null) {
|
||||
hashAlg = "256";
|
||||
}
|
||||
|
||||
if (!getCreateOutFile().isEmpty() && !isValidPath(getCreateOutFile())) {
|
||||
printHelp(String.format("Invalid file path %s!", getCreateOutFile()));
|
||||
}
|
||||
}
|
||||
@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.")
|
||||
private String outFile = "";
|
||||
@Parameter(names = {"-v", "--verify <path>"}, order = 3,
|
||||
description = "Specify a RIM file to verify.")
|
||||
private String verifyFile = "";
|
||||
@Parameter(names = {"-k", "--privateKeyFile <path>"}, order = 4,
|
||||
description = "File containing the private key used to sign the base RIM created by the create function.")
|
||||
private String privateKeyFile = "";
|
||||
@Parameter(names = {"-p", "--publicCertificate <path>"}, order = 5,
|
||||
description = "The public key certificate used to verify a RIM file or to embed in a signed RIM. " +
|
||||
"A signed RIM generated by this tool by default will not show the signing certificate without this parameter present.")
|
||||
private String publicCertificate = "";
|
||||
/*
|
||||
@Parameter(names = {"-l", "--rimel <path>"}, order = 6,
|
||||
description = "The TCG eventlog file to use as a support RIM. By default the last system eventlog will be used.")
|
||||
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() {
|
||||
return help;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default blank constructor
|
||||
*/
|
||||
public Commander() {
|
||||
|
||||
public String getCreateType() {
|
||||
return createType;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called if an empty Commander was created, and later gets
|
||||
* args. Will be used by the main constructor.
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public final void parseArguments(final String[] args) {
|
||||
String tempValue;
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
tempValue = args[i];
|
||||
|
||||
switch (tempValue) {
|
||||
case FULL_COMMAND_PREFIX + CREATE_STRING:
|
||||
case COMMAND_PREFIX + "c":
|
||||
create = true;
|
||||
if (i+1 < args.length && !args[i+1].substring(0,1).equals(COMMAND_PREFIX)) {
|
||||
createOutFile = args[++i];
|
||||
}
|
||||
break;
|
||||
case FULL_COMMAND_PREFIX + ATTRIBUTES_STRING:
|
||||
case COMMAND_PREFIX + "a":
|
||||
attributesGiven = true;
|
||||
if (i+1 < args.length && !args[i+1].substring(0,1).equals(COMMAND_PREFIX)) {
|
||||
attributesFile = args[++i];
|
||||
}
|
||||
break;
|
||||
case FULL_COMMAND_PREFIX + VERIFY_STRING:
|
||||
case COMMAND_PREFIX + "v":
|
||||
validate = true;
|
||||
validateFile = args[++i];
|
||||
break;
|
||||
case FULL_COMMAND_PREFIX + PARSE_STRING:
|
||||
case COMMAND_PREFIX + "p":
|
||||
parse = true;
|
||||
parseFile = args[++i];
|
||||
break;
|
||||
case FULL_COMMAND_PREFIX + SHOW_CERT_STRING:
|
||||
showCert = true;
|
||||
break;
|
||||
case FULL_COMMAND_PREFIX + HELP_STRING:
|
||||
case COMMAND_PREFIX + "h":
|
||||
default:
|
||||
printHelp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the input validate file associated with the validate flag
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final String getValidateFile() {
|
||||
return validateFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the output file for the create flag
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final String getCreateOutFile() {
|
||||
return createOutFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the property that indicates if something was given at the
|
||||
* commandline.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final boolean hasArguments() {
|
||||
return hasArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the validate command flag.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final boolean validate() {
|
||||
return validate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the create command flag.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final boolean create() {
|
||||
return create;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the hash algorithm to be used for hash functions.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final String getHashAlg() {
|
||||
return hashAlg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the parse command flag
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final boolean parse() {
|
||||
return parse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the file to be parsed by the parse command flag
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final String getParseFile() {
|
||||
return parseFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the attributes file given flag
|
||||
* @return
|
||||
*/
|
||||
public boolean isAttributesGiven() {
|
||||
return attributesGiven;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the file containing attribute key-value pairs
|
||||
* @return
|
||||
*/
|
||||
public String getAttributesFile() {
|
||||
return attributesFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the keystore given flag
|
||||
* @return
|
||||
*/
|
||||
public boolean isKeystoreGiven() {
|
||||
return keystoreGiven;
|
||||
public String getOutFile() {
|
||||
return outFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the keystore used for digital signatures
|
||||
* @return
|
||||
*/
|
||||
public String getKeystore() {
|
||||
return keystore;
|
||||
public String getVerifyFile() {
|
||||
return verifyFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for boolean to show certificate data or not
|
||||
* @return
|
||||
*/
|
||||
public boolean isShowCert() {
|
||||
return showCert;
|
||||
public String getPrivateKeyFile() {
|
||||
return privateKeyFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default no parameter help method.
|
||||
*/
|
||||
private void printHelp() {
|
||||
printHelp(null);
|
||||
public String getPublicCertificate() {
|
||||
return publicCertificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to inform the user of the allowed functionality of
|
||||
* the program.
|
||||
*/
|
||||
private void printHelp(String message) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (message != null && !message.isEmpty()) {
|
||||
sb.append(String.format("ERROR: %s\n\n", message));
|
||||
}
|
||||
sb.append("Usage: HIRS_SwidTag\n");
|
||||
sb.append(" -c, --create <file>\t\tCreate a base rim and write to\n"
|
||||
+ " \t\t\t\tthe given file. If no file is given the default is\n"
|
||||
+ " \t\t\t\tgenerated_swidTag.swidtag\n\n");
|
||||
sb.append(" -a, --attributes <file>\tSpecify the JSON file that contains\n"
|
||||
+ " \t\t\t\tthe xml attributes to add to the RIM\n\n");
|
||||
sb.append(" -v, --verify\t\t\tTakes the provided input file and\n"
|
||||
+ " \t\t\t\tvalidates it against the schema at\n"
|
||||
+ " \t\t\t\thttp://standards.iso.org/iso/19770/-2/2015/schema.xsd\n\n");
|
||||
sb.append(" -p, --parse <file>\t\tParse the given swidtag's payload\n\n");
|
||||
/*
|
||||
sb.append(" -k, --keystore <file>\tSpecify the keystore and its location to use\n"
|
||||
+ " \t\t\t\tfor digital signatures\n");
|
||||
*/
|
||||
sb.append(" --show-cert\t\t\tPrint the certificate in the signature block of\n"
|
||||
+ " \t\t\t\tthe base RIM\n\n");
|
||||
sb.append(" -h, --help, <no args>\tPrints this command help information.\n");
|
||||
sb.append(" \t\t\t\tListing no command arguments will also\n"
|
||||
+ " \t\t\t\tprint this help text.\n\n");
|
||||
sb.append("Example commands: \n"
|
||||
+ " Create a base rim from the default attribute file and write the rim\n"
|
||||
+ " to generated_swidTag.swidtag:\n\n"
|
||||
+ " \t\tjava -jar tcg_rim_tool-1.0.jar -c\n\n"
|
||||
+ " Create a base rim from the values in config.json and write the rim\n"
|
||||
+ " to base_rim.swidtag:\n\n"
|
||||
+ " \t\tjava -jar tcg_rim_tool-1.0.jar -c base_rim.swidtag -a config.json\n\n"
|
||||
+ " ");
|
||||
|
||||
System.out.println(sb.toString());
|
||||
System.exit(1);
|
||||
public String getRimEventLog() {
|
||||
return rimEventLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the file given to create a new swidtag is a valid path.
|
||||
* @param filepath
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidPath(String filepath) {
|
||||
try {
|
||||
System.out.println("Checking for a valid creation path...");
|
||||
File file = new File(filepath);
|
||||
file.createNewFile();
|
||||
} catch (IOException | InvalidPathException | NullPointerException ex) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
public String getRimPcrs() {
|
||||
return rimPcrs;
|
||||
}
|
||||
|
||||
public String getToBeSigned() {
|
||||
return toBeSigned;
|
||||
}
|
||||
|
||||
public String getSignatureData() {
|
||||
return signatureData;
|
||||
}
|
||||
*/
|
||||
public String printHelpExamples() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Create a base RIM using the values in attributes.json; " +
|
||||
"sign it with the default keystore, alias, and password;\n");
|
||||
sb.append("and write the data to base_rim.swidtag:\n\n");
|
||||
sb.append("\t\t-c base -a attributes.json -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("and write the data to console output, to include cert.pem in the signature block:\n\n");
|
||||
sb.append("\t\t-c base -k privateKey.pem -p cert.pem\n\n\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Creating: " + getCreateType() + System.lineSeparator());
|
||||
sb.append("Using attributes file: " + getAttributesFile() + System.lineSeparator());
|
||||
sb.append("Write to: " + getOutFile() + System.lineSeparator());
|
||||
sb.append("Verify file: " + getVerifyFile() + System.lineSeparator());
|
||||
sb.append("Private key file: " + getPrivateKeyFile() + System.lineSeparator());
|
||||
sb.append("Public certificate: " + getPublicCertificate() + System.lineSeparator());
|
||||
/*
|
||||
sb.append("Event log support RIM: " + 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();
|
||||
}
|
||||
}
|
||||
|
@ -14,17 +14,16 @@ import org.testng.annotations.Test;
|
||||
|
||||
public class TestSwidTagGateway {
|
||||
private SwidTagGateway gateway;
|
||||
private String inputFile, outputFile, hashType;
|
||||
private final String DEFAULT_OUTPUT = "generated_swidTag.swidtag";
|
||||
private final String DEFAULT_WITH_CERT = "generated_with_cert.swidtag";
|
||||
private final String DEFAULT_NO_CERT = "generated_no_cert.swidtag";
|
||||
private final String certificateFile = "RimSignCert.pem";
|
||||
private final String privateKeyFile = "privateRimKey.pem";
|
||||
private InputStream expectedFile;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() throws Exception {
|
||||
gateway = new SwidTagGateway();
|
||||
inputFile = TestSwidTagGateway.class.getClassLoader().getResource("examplecsv.csv").getFile();
|
||||
hashType = "SHA256";
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@ -35,29 +34,35 @@ public class TestSwidTagGateway {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creating a base RIM with default attributes with an X509Certificate element.
|
||||
* This test corresponds to the arguments:
|
||||
* -c base -k privateRimKey.pem -p RimSignCert.pem
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateDefaultWithCert() {
|
||||
gateway.setShowCert(true);
|
||||
gateway.generateSwidTag();
|
||||
public void testCreateBaseWithCert() {
|
||||
gateway.setDefaultCredentials(false);
|
||||
gateway.setPemCertificateFile(certificateFile);
|
||||
gateway.setPemPrivateKeyFile(privateKeyFile);
|
||||
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
||||
expectedFile = (InputStream) TestSwidTagGateway.class.getClassLoader().getResourceAsStream(DEFAULT_WITH_CERT);
|
||||
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a base RIM with default attributes without an X509Certificate element.
|
||||
* This test corresponds to the arguments:
|
||||
* -c base
|
||||
* -c base -a <path>
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateDefaultNoCert() {
|
||||
gateway.setShowCert(false);
|
||||
gateway.generateSwidTag();
|
||||
public void testCreateBaseWithoutCert() {
|
||||
gateway.setDefaultCredentials(true);
|
||||
gateway.generateSwidTag(DEFAULT_OUTPUT);
|
||||
expectedFile = (InputStream) TestSwidTagGateway.class.getClassLoader().getResourceAsStream(DEFAULT_NO_CERT);
|
||||
Assert.assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a base RIM with default attributes with an X509Certificate element.
|
||||
* This test corresponds to the arguments:
|
||||
* -v <path> -p RimSignCert.pem
|
||||
*/
|
||||
@Test
|
||||
public void testValidateSwidTag() {
|
||||
@ -68,35 +73,6 @@ public class TestSwidTagGateway {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify expected values of a File element in a Payload element.
|
||||
*/
|
||||
@Test
|
||||
public void testParsePayload() {
|
||||
InputStream is = null;
|
||||
outputFile = TestSwidTagGateway.class.getClassLoader().getResource(DEFAULT_WITH_CERT).getPath();
|
||||
try {
|
||||
is = gateway.parsePayload(outputFile);
|
||||
Scanner scanner = new Scanner(is, "UTF-8");
|
||||
String test = "Example.com.iotBase.bin,688e293e3ccb522f6cf8a027c9ade7960f84bd0bf3a0b99812bc1fa498a2db8d";
|
||||
String temp = "";
|
||||
while (scanner.hasNext()) {
|
||||
temp = scanner.next();
|
||||
Assert.assertEquals(temp, test, "temp: " + temp + ", test: " + test);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Assert.fail("Error parsing test file!");
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
Assert.fail("Failed to close input stream!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method compares two files by bytes to determine if they are the same or not.
|
||||
* @param file to be compared to the expected value.
|
||||
|
@ -26,9 +26,17 @@ zu3HTmQfeRYs/c6Ck1k3bL1jnyWoNzhBqCuPYrZtPbv9opVP0YOxM5IjRkRgkZIDgYbh1k4WXw8O
|
||||
/iIMZuVJDfKQJSNCTAZsIbUatGDQc/nOihLHdI90wG8zu9amgrl1AEKzH8z864Fan5uuXolfAaak
|
||||
sLJl6RPCNcp+JNCXMMZiS8bmYPQnVJc1ze0I1A==</SignatureValue>
|
||||
<KeyInfo>
|
||||
<X509Data>
|
||||
<X509SubjectName>CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US</X509SubjectName>
|
||||
</X509Data>
|
||||
<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>
|
||||
</Signature>
|
||||
</SoftwareIdentity>
|
||||
|
@ -28,23 +28,35 @@ sLJl6RPCNcp+JNCXMMZiS8bmYPQnVJc1ze0I1A==</SignatureValue>
|
||||
<KeyInfo>
|
||||
<X509Data>
|
||||
<X509SubjectName>CN=example.RIM.signer,OU=PCClient,O=Example,ST=VA,C=US</X509SubjectName>
|
||||
<X509Certificate>MIIDYTCCAkmgAwIBAgIJAPB+r6VBhBn4MA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAlVTMQsw
|
||||
<X509Certificate>MIIDoTCCAomgAwIBAgIJAPB+r6VBhBn5MA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAlVTMQsw
|
||||
CQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxEjAQBgNVBAMM
|
||||
CUV4YW1wbGVDQTAeFw0yMDAyMTAxODE1MzRaFw0yOTEyMTkxODE1MzRaMFwxCzAJBgNVBAYTAlVT
|
||||
CUV4YW1wbGVDQTAeFw0yMDAzMTExODExMjJaFw0zMDAxMTgxODExMjJaMFwxCzAJBgNVBAYTAlVT
|
||||
MQswCQYDVQQIDAJWQTEQMA4GA1UECgwHRXhhbXBsZTERMA8GA1UECwwIUENDbGllbnQxGzAZBgNV
|
||||
BAMMEmV4YW1wbGUuUklNLnNpZ25lcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKd1
|
||||
lWGkSRuxAAY2wHag2GVxUk1dZx2PTpfQOflvLeccAVwa8mQhlsRERq+QK8ilj8Xfqs44/nBaccZD
|
||||
OjdfIxIUCMfwhGXjxCaqZbgTucNsExDnu4arTGraoAwzHg0cVLiKT/Cxj9NL4dcMgxRXsPdHfXb0
|
||||
923C7xYd2t2qfW05umgaj7qeQl6c68CFNsGX4JA8rWFQZvvGx5DGlK4KTcjPuQQINs5fxasNKqLY
|
||||
2hq+z82x/rqwr2hmyizD6FpFSyIABPEMPfB036GEhRwu1WEMkq8yIp2jgRUoFYke9pB3ph9pVow0
|
||||
Hh4mNFSKD4pP41VSKY1nus83mdkuukPy5o0CAwEAAaMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMC
|
||||
BsAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAGuJ+dasb3/Mb7TBJ1Oe
|
||||
al5ISq8d2LQD5ke5qnjgSQWKXfQ9fcUy3dWnt3Oked/i8B/Tyk3jCdTZJU3J3iRNgTqFfMLP8rU1
|
||||
w2tPYBjjuPKiiK4YRBHPxtFxPdOL1BPmL4ZzNs33Lv6H0m4aff9p6QpMclX5b/CRjl+80JWRLiLj
|
||||
U3B0CejZB9dJrPr9SBaC31cDoeTpja9Cl86ip7KkqrZZIYeMuNF6ucWyWtjrW2kr3UhmEy8x/6y4
|
||||
KigsK8sBwmNv4N2Pu3RppeIcpjYj5NVA1hwRA4eeMgJp2u+urm3l1oo1UNX1HsSSBHp1Owc9zZLm
|
||||
07Pl8T46kpIA4sroCAU=</X509Certificate>
|
||||
Hh4mNFSKD4pP41VSKY1nus83mdkuukPy5o0CAwEAAaNvMG0wHQYDVR0OBBYEFC/euOfQMKIgnaoB
|
||||
hhqWT+3s8rzBMB8GA1UdIwQYMBaAFEahuO3bpnFf0NLneoo8XW6aw5Y4MAkGA1UdEwQCMAAwCwYD
|
||||
VR0PBAQDAgbAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQBl2Bu9xpnH
|
||||
CCeeebjx+ILQXJXBd6q5+NQlV3zzBrf0bleZRtsOmsuFvWQoKQxsfZuk7QcSvVd/1v8mqwJ0PwbF
|
||||
KQmrhIPWP+iowiBNqpG5PH9YxhpHQ1osOfibNLOXMhudIQRY0yAgqQf+MOlXYa0stX8gkgftVBDR
|
||||
utuMKyOTf4a6d8TUcbG2RnyzO/6S9bq4cPDYLqWRBM+aGN8e00UWTKpBl6/1EU8wkJA6WdllK2e8
|
||||
mVkXUPWYyHTZ0qQnrYiuLr36ycAznABDzEAoj4tMZbjIAfuscty6Ggzxl1WbyZLI6YzyXALwaYvr
|
||||
crTLeyFynlKxuCfDnr1SAHDM65BY</X509Certificate>
|
||||
</X509Data>
|
||||
<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>
|
||||
</Signature>
|
||||
</SoftwareIdentity>
|
||||
|
Loading…
Reference in New Issue
Block a user