diff --git a/settings.gradle b/settings.gradle index 30f5655b..a996fc2d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,4 @@ include 'TPM_Utils', 'HIRS_AttestationCA', 'HIRS_AttestationCAPortal', 'tpm_module', - 'tools' + 'tools/tcg_rim_tool' diff --git a/tools/tcg_rim_tool/build.gradle b/tools/tcg_rim_tool/build.gradle index b83bedbf..fd331228 100644 --- a/tools/tcg_rim_tool/build.gradle +++ b/tools/tcg_rim_tool/build.gradle @@ -6,13 +6,17 @@ repositories { } dependencies { - testCompile 'org.testng:testng:6.8.8' + compile libs.minimal_json + testCompile libs.testng } jar { manifest { - attributes("Main-Class": "hirs.swid.Main") + attributes("Main-Class": "hirs.swid.Main", + "Class-Path": configurations.runtime.files.collect { "lib/$it.name" }.join(' ') + ) } + from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {} } uploadArchives { diff --git a/tools/tcg_rim_tool/keystore.jks b/tools/tcg_rim_tool/keystore.jks new file mode 100644 index 00000000..0c5bc1d7 Binary files /dev/null and b/tools/tcg_rim_tool/keystore.jks differ diff --git a/tools/tcg_rim_tool/rim_fields.json b/tools/tcg_rim_tool/rim_fields.json new file mode 100644 index 00000000..179cdd63 --- /dev/null +++ b/tools/tcg_rim_tool/rim_fields.json @@ -0,0 +1,41 @@ +{ + "SoftwareIdentity": { + "name": "TCG RIM example", + "version": "0.1", + "tagId": "hirs.swid.SwidTags.example", + "tagVersion": "1", + "patch": false + }, + "Entity": { + "name": "HIRS", + "role": "softwareCreator,tagCreator", + "regid": "www.example.com", + "thumbprint": "" + }, + "Link": { + "href": "https://Example.com/support/ProductA/firmware/installfiles", + "rel": "installationmedia" + }, + "Meta": { + "colloquialVersion": "", + "edition": "", + "product": "", + "revision": "", + "platformManufacturerStr": "Example.com", + "platformManufacturerId": "00201234", + "platformModel": "ProductA", + "bindingSpec": "IOT RIM", + "bindingSpecVersion": "1.2", + "rimLinkHash": "88f21d8e44d4271149297404df91caf207130bfa116582408abd04ede6db7f51" + }, + "Payload": { + "Directory": { + "name": "iotBase", + "File": { + "name": "Example.com.iotBase.bin", + "size": "15400", + "hash": "688e293e3ccb522f6cf8a027c9ade7960f84bd0bf3a0b99812bc1fa498a2db8d" + } + } + } +} diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java index 6c2e0d50..6c549cd5 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/Main.java @@ -14,31 +14,40 @@ public class Main { public static void main(String[] args) { Commander commander = new Commander(args); + SwidTagGateway gateway = new SwidTagGateway(); if (commander.hasArguments()) { // we have arguments to work with + if (commander.isAttributesGiven()) { + gateway.setAttributesFile(commander.getAttributesFile()); + } +/* if (commander.isKeystoreGiven()) { + + } +*/ if (commander.create()) { + String keystore = commander.getKeystore(); + if (!keystore.isEmpty()) { + //set keystore for gateway if given + } // parsing the arguments detected a create parameter (-c) - (new SwidTagGateway()).generateSwidTag(commander.getCreateInFile(), - commander.getCreateOutFile(), commander.getHashAlg()); - } else if (commander.validate()) { + gateway.generateSwidTag(commander.getCreateOutFile()); + } + if (commander.validate()) { // parsing the arguments detected a validation parameter (-v) try { - (new SwidTagGateway()).validateSwidTag(commander.getValidateFile()); + gateway.validateSwidTag(commander.getValidateFile()); } catch (IOException e) { System.out.println("Unable to validate file: " + e.getMessage()); } - } else if (commander.parse()) { + } + if (commander.parse()) { try { - (new SwidTagGateway()).parsePayload(commander.getParseFile()); + gateway.parsePayload(commander.getParseFile()); } catch (IOException e) { System.out.println("Unable to parse file: " + e.getMessage()); } } - } else { - // development stage in which no valid arguments were given - // therefore generate a mock tag file - (new SwidTagGateway()).generateSwidTag(); } } } diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagConstants.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagConstants.java index 35a61ecc..bad1a213 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagConstants.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagConstants.java @@ -1,6 +1,8 @@ package hirs.swid; import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + /** * This class contains the String constants that are referenced by the gateway @@ -10,6 +12,14 @@ import javax.xml.XMLConstants; */ public class SwidTagConstants { + public static final String DEFAULT_KEYSTORE_PATH = "keystore.jks"; + public static final String DEFAULT_KEYSTORE_PASSWORD = "password"; + public static final String DEFAULT_PRIVATE_KEY_ALIAS = "selfsigned"; + public static final String DEFAULT_ATTRIBUTES_FILE = "/etc/hirs/rim_fields.json"; + public static final String DEFAULT_ENGLISH = "en"; + + 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"; @@ -19,6 +29,125 @@ public class SwidTagConstants { 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"; + public static final String META = "Meta"; + public static final String PAYLOAD = "Payload"; + public static final String DIRECTORY = "Directory"; + public static final String FILE = "File"; + public static final String NAME = "name"; + public static final String VERSION = "version"; + public static final String VERSION_SCHEME = "versionScheme"; + public static final String TAGID = "tagId"; + public static final String TAGVERSION = "tagVersion"; + public static final String CORPUS = "corpus"; + public static final String PATCH = "patch"; + public static final String SUPPLEMENTAL = "supplemental"; + public static final String REGID = "regid"; + public static final String ROLE = "role"; + public static final String THUMBPRINT = "thumbprint"; + public static final String HREF = "href"; + public static final String REL = "rel"; + public static final String COLLOQUIAL_VERSION = "colloquialVersion"; + public static final String EDITION = "edition"; + public static final String PRODUCT = "product"; + public static final String REVISION = "revision"; + public static final String PAYLOAD_TYPE = "payloadType"; + public static final String HYBRID = "hybrid"; + public static final String PLATFORM_MANUFACTURER_STR = "platformManufacturerStr"; + public static final String PLATFORM_MANUFACTURER_ID = "platformManufacturerId"; + public static final String PLATFORM_MODEL = "platformModel"; + public static final String PLATFORM_VERSION = "platformVersion"; + public static final String FIRMWARE_MANUFACTURER_STR = "firmwareManufacturerStr"; + public static final String FIRMWARE_MANUFACTURER_ID = "firmwareManufacturerId"; + public static final String FIRMWARE_MODEL = "firmwareModel"; + public static final String FIRMWARE_VERSION = "firmwareVersion"; + public static final String BINDING_SPEC = "bindingSpec"; + public static final String BINDING_SPEC_VERSION = "bindingSpecVersion"; + public static final String PC_URI_LOCAL = "pcURILocal"; + public static final String PC_URI_GLOBAL = "pcURIGlobal"; + public static final String RIM_LINK_HASH = "rimLinkHash"; + public static final String SIZE = "size"; + public static final String HASH = "hash"; + public static final String SUPPORT_RIM_TYPE = "supportRIMType"; + public static final String SUPPORT_RIM_FORMAT = "supportRIMFormat"; + public static final String SUPPORT_RIM_URI_GLOBAL = "supportRIMURIGlobal"; + + public static final QName _COLLOQUIAL_VERSION = new QName( + "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", + "colloquialVersion", "n8060"); + public static final QName _EDITION = new QName( + "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", + "edition", "n8060"); + public static final QName _PRODUCT = new QName( + "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", + "product", "n8060"); + public static final QName _REVISION = new QName( + "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", + "revision", "n8060"); + public static final QName _PAYLOAD_TYPE = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "payloadType", "rim"); + public static final QName _PLATFORM_MANUFACTURER_STR = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "platformManufacturerStr", "rim"); + public static final QName _PLATFORM_MANUFACTURER_ID = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "platformManufacturerId", "rim"); + public static final QName _PLATFORM_MODEL = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "platformModel", "rim"); + public static final QName _PLATFORM_VERSION = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "platformVersion", "rim"); + public static final QName _FIRMWARE_MANUFACTURER_STR = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "platformManufacturerStr", "rim"); + public static final QName _FIRMWARE_MANUFACTURER_ID = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "platformManufacturerId", "rim"); + public static final QName _FIRMWARE_MODEL = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "platformModel", "rim"); + public static final QName _FIRMWARE_VERSION = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "platformVersion", "rim"); + public static final QName _BINDING_SPEC = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "bindingSpec", "rim"); + public static final QName _BINDING_SPEC_VERSION = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "bindingSpecVersion", "rim"); + public static final QName _PC_URI_LOCAL = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "pcURILocal", "rim"); + public static final QName _PC_URI_GLOBAL = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "pcURIGlobal", "rim"); + public static final QName _RIM_LINK_HASH = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "rimLinkHash", "rim"); + public static final QName _SUPPORT_RIM_TYPE = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "supportRIMType", "rim"); + public static final QName _SUPPORT_RIM_FORMAT = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "supportRIMFormat", "rim"); + public static final QName _SUPPORT_RIM_URI_GLOBAL = new QName( + "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", + "supportRIMURIGlobal", "rim"); + public static final QName _N8060_ENVVARPREFIX = new QName( + "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", + "envVarPrefix", "n8060"); + public static final QName _N8060_ENVVARSUFFIX = new QName( + "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", + "envVarSuffix", "n8060"); + public static final QName _N8060_PATHSEPARATOR = new QName( + "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"; diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java index 0f48178b..e5aa48fa 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/SwidTagGateway.java @@ -1,27 +1,92 @@ 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.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.DOMSource; +import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.namespace.QName; +import javax.xml.crypto.AlgorithmMethod; +import javax.xml.crypto.KeySelector; +import javax.xml.crypto.KeySelectorException; +import javax.xml.crypto.KeySelectorResult; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.XMLCryptoContext; +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; +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.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.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; @@ -39,15 +104,14 @@ import hirs.swid.xjc.SoftwareMeta; import hirs.swid.xjc.TransformType; import hirs.swid.xjc.TransformsType; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; +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; + -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; /** * This class provides interaction with the SWID Tag schema as defined in @@ -66,58 +130,39 @@ public class SwidTagGateway { "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 static final QName _RIM_PCURILOCAL = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "pcURILocal", "rim"); - private static final QName _RIM_BINDINGSPEC = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "bindingSpec", "rim"); - private static final QName _RIM_BINDINGSPECVERSION = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "bindingSpecVersion", "rim"); - private static final QName _RIM_PLATFORMMANUFACTURERID = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "platformManufacturerId", "rim"); - private static final QName _RIM_PLATFORMMANUFACTURERSTR = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "platformManufacturerStr", "rim"); - private static final QName _RIM_PLATFORMMODEL = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "platformModel", "rim"); - private static final QName _RIM_COMPONENTCLASS = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "componentClass", "rim"); - private static final QName _RIM_COMPONENTMANUFACTURER = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "componentManufacturer", "rim"); - private static final QName _RIM_COMPONENTMANUFACTURERID = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "componentManufacturerId", "rim"); - private static final QName _RIM_RIMLINKHASH = new QName( - "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model", - "rimLinkHash", "rim"); - private static final QName _N8060_ENVVARPREFIX = new QName( - "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", - "envVarPrefix", "n8060"); - private static final QName _N8060_ENVVARSUFFIX = new QName( - "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", - "envVarSuffix", "n8060"); - private static final QName _N8060_PATHSEPARATOR = new QName( - "http://csrc.nist.gov/ns/swid/2015-extensions/1.0", - "pathSeparator", "n8060"); private final ObjectFactory objectFactory = new ObjectFactory(); private final File generatedFile = new File("generated_swidTag.swidtag"); private QName hashValue = null; - - private static final String ENTITY = "Entity"; - private static final String PAYLOAD = "Payload"; + + private JAXBContext jaxbContext; + private Marshaller marshaller; + private Unmarshaller unmarshaller; + private String attributesFile; + + /** + * Default constructor initializes jaxbcontext, marshaller, and unmarshaller + */ + public SwidTagGateway() { + try { + jaxbContext = JAXBContext.newInstance(SwidTagConstants.SCHEMA_PACKAGE); + marshaller = jaxbContext.createMarshaller(); + unmarshaller = jaxbContext.createUnmarshaller(); + attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE; + } catch (JAXBException e) { + System.out.println("Error initializing jaxbcontext: " + e.getMessage()); + } + } + + public void setAttributesFile(String attributesFile) { + this.attributesFile = attributesFile; + } /** * default generator method that has no parameters */ public void generateSwidTag() { - generateSwidTag(generatedFile); + generateSwidTag(""); } /** @@ -164,9 +209,9 @@ public class SwidTagGateway { is = SwidTagGateway.class.getClassLoader().getResourceAsStream(SwidTagConstants.HIRS_SWIDTAG_HEADERS); properties.load(is); - SoftwareIdentity swidTag = createSwidTag(properties); + SoftwareIdentity swidTag = createSwidTag(new JsonObject()); - JAXBElement entity = objectFactory.createSoftwareIdentityEntity(createEntity(properties)); + JAXBElement entity = objectFactory.createSoftwareIdentityEntity(createEntity(new JsonObject())); swidTag.getEntityOrEvidenceOrLink().add(entity); // we should have resources, there for we need a collection @@ -191,59 +236,68 @@ public class SwidTagGateway { } /** - * This method generates a primary SWID tag from the values in - * resources/swidExamples.properties. + * This method generates a base RIM from the values in a JSON file. * * @param outputFile */ - public void generateSwidTag(final File outputFile) { - Properties properties = new Properties(); - InputStream is = null; + public void generateSwidTag(final String filename) { + SoftwareIdentity swidTag = null; try { - is = SwidTagGateway.class.getClassLoader().getResourceAsStream(SwidTagConstants.EXAMPLE_PROPERTIES); - properties.load(is); - - SoftwareIdentity swidTag = createSwidTag(properties); - - JAXBElement entity = objectFactory.createSoftwareIdentityEntity(createEntity(properties)); + 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 + swidTag = createSwidTag(configProperties.get(SwidTagConstants.SOFTWARE_IDENTITY).asObject()); + //Entity + JAXBElement entity = objectFactory.createSoftwareIdentityEntity( + createEntity(configProperties.get(SwidTagConstants.ENTITY).asObject())); swidTag.getEntityOrEvidenceOrLink().add(entity); - - JAXBElement link = objectFactory.createSoftwareIdentityLink(createLink(properties)); + //Link + JAXBElement link = objectFactory.createSoftwareIdentityLink( + createLink(configProperties.get(SwidTagConstants.LINK).asObject())); swidTag.getEntityOrEvidenceOrLink().add(link); - - JAXBElement meta = objectFactory.createSoftwareIdentityMeta(createSoftwareMeta(properties)); + //Meta + JAXBElement meta = objectFactory.createSoftwareIdentityMeta( + createSoftwareMeta(configProperties.get(SwidTagConstants.META).asObject())); swidTag.getEntityOrEvidenceOrLink().add(meta); - - ResourceCollection payload = createPayload(properties); - Directory directory = createDirectory(properties); - hirs.swid.xjc.File file1 = createFile("Example.com.iotBase.bin", "01.00", "15400"); - hirs.swid.xjc.File file2 = createFile("iotExec.bin", "01.00", "1024"); - directory.getDirectoryOrFile().add(file1); - directory.getDirectoryOrFile().add(file2); + //File + hirs.swid.xjc.File file = createFile( + configProperties.get(SwidTagConstants.PAYLOAD).asObject() + .get(SwidTagConstants.DIRECTORY).asObject() + .get(SwidTagConstants.FILE).asObject()); + //Directory + Directory directory = createDirectory( + configProperties.get(SwidTagConstants.PAYLOAD).asObject() + .get(SwidTagConstants.DIRECTORY).asObject()); + directory.getDirectoryOrFile().add(file); + //Payload + ResourceCollection payload = createPayload( + configProperties.get(SwidTagConstants.PAYLOAD).asObject()); payload.getDirectoryOrFileOrProcess().add(directory); - JAXBElement jaxbPayload = objectFactory.createSoftwareIdentityPayload(payload); + JAXBElement jaxbPayload = + objectFactory.createSoftwareIdentityPayload(payload); swidTag.getEntityOrEvidenceOrLink().add(jaxbPayload); -// JAXBElement swidtagSignature = objectFactory.createSignature(createSignature()); -// swidTag.getEntityOrEvidenceOrLink().add(swidtagSignature); - - JAXBElement jaxbe = objectFactory.createSoftwareIdentity(swidTag); - writeSwidTagFile(jaxbe, outputFile); + } catch (FileNotFoundException e) { + System.out.println("File does not exist or cannot be read: " + e.getMessage()); } catch (IOException e) { - System.out.println("Error reading properties file: "); - e.printStackTrace(); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException ex) { - // ignore - } - } + System.out.println("Error in file reader: " + e.getMessage()); + } catch (ParseException e) { + System.out.println("Invalid JSON detected at " + e.getLocation().toString()); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + 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); } } - /** + /** * This method validates the .swidtag file at the given filepath against the * schema. A successful validation results in the output of the tag's name * and tagId attributes, otherwise a generic error message is printed. @@ -279,6 +333,31 @@ public class SwidTagGateway { e.printStackTrace(); } } + + /** + * This method writes a Document object out to the file specified by generatedFile. + * + * @param swidTag + */ + public void writeSwidTagFile(Document swidTag, File outputFile) { + 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)); + } catch (FileNotFoundException e) { + System.out.println("Unable to write to file: " + e.getMessage()); + } catch (TransformerConfigurationException e) { + System.out.println("Error instantiating TransformerFactory class: " + e.getMessage()); + } catch (TransformerException e) { + System.out.println("Error instantiating Transformer class: " + e.getMessage()); + } + } /** * Given an input swidtag at [path] parse any PCRs in the payload into an InputStream object. @@ -298,7 +377,7 @@ public class SwidTagGateway { try { JAXBElement element = (JAXBElement) obj; String elementName = element.getName().getLocalPart(); - if (elementName.equals(PAYLOAD)) { + if (elementName.equals(SwidTagConstants.PAYLOAD)) { ResourceCollection rc = (ResourceCollection) element.getValue(); if (!rc.getDirectoryOrFileOrProcess().isEmpty()) { pcrs = parsePCRs(rc.getDirectoryOrFileOrProcess()); @@ -320,14 +399,29 @@ public class SwidTagGateway { * @param properties the Properties object containing parameters from file * @return SoftwareIdentity object created from the properties */ - private SoftwareIdentity createSwidTag(Properties properties) { + private SoftwareIdentity createSwidTag(JsonObject jsonObject) { SoftwareIdentity swidTag = objectFactory.createSoftwareIdentity(); - swidTag.setName(properties.getProperty(SwidTagConstants.SOFTWARE_IDENTITY_NAME)); - swidTag.setTagId(properties.getProperty(SwidTagConstants.SOFTWARE_IDENTITY_TAGID)); - swidTag.setVersion(properties.getProperty(SwidTagConstants.SOFTWARE_IDENTITY_VERSION)); - swidTag.setCorpus(Boolean.parseBoolean(properties.getProperty(SwidTagConstants.SOFTWARE_IDENTITY_CORPUS))); - swidTag.setPatch(Boolean.parseBoolean(properties.getProperty(SwidTagConstants.SOFTWARE_IDENTITY_PATCH))); - swidTag.setSupplemental(Boolean.parseBoolean(properties.getProperty(SwidTagConstants.SOFTWARE_IDENTITY_SUPPLEMENTAL))); + swidTag.setLang(SwidTagConstants.DEFAULT_ENGLISH); + String name = jsonObject.getString(SwidTagConstants.NAME, ""); + if (!name.isEmpty()) { + swidTag.setName(name); + } + String tagId = jsonObject.getString(SwidTagConstants.TAGID, ""); + if (!tagId.isEmpty()) { + swidTag.setTagId(tagId); + } + swidTag.setTagVersion(new BigInteger(jsonObject.getString(SwidTagConstants.TAGVERSION, "0"))); + String version = jsonObject.getString(SwidTagConstants.VERSION, ""); + if (!version.isEmpty()) { + swidTag.setVersion(version); + } + swidTag.setCorpus(jsonObject.getBoolean(SwidTagConstants.CORPUS, false)); + swidTag.setPatch(jsonObject.getBoolean(SwidTagConstants.PATCH, false)); + swidTag.setSupplemental(jsonObject.getBoolean(SwidTagConstants.SUPPLEMENTAL, false)); + if (!swidTag.isCorpus() && !swidTag.isPatch() + && !swidTag.isSupplemental() && swidTag.getVersion() != "0.0") { + swidTag.setVersionScheme(jsonObject.getString(SwidTagConstants.VERSION_SCHEME, "multipartnumeric")); + } return swidTag; } @@ -339,16 +433,34 @@ public class SwidTagGateway { * @param properties the Properties object containing parameters from file * @return Entity object created from the properties */ - private Entity createEntity(Properties properties) { + private Entity createEntity(JsonObject jsonObject) { + boolean isTagCreator = false; Entity entity = objectFactory.createEntity(); - entity.setName(properties.getProperty(SwidTagConstants.ENTITY_NAME)); - entity.setRegid(properties.getProperty(SwidTagConstants.ENTITY_REGID)); - String[] roles = properties.getProperty(SwidTagConstants.ENTITY_ROLE).split(","); + String name = jsonObject.getString(SwidTagConstants.NAME, ""); + if (!name.isEmpty()) { + entity.setName(name); + } + String[] roles = jsonObject.getString(SwidTagConstants.ROLE, "").split(","); for (int i = 0; i < roles.length; i++) { entity.getRole().add(roles[i]); + if (roles[i].equals("tagCreator")) { + isTagCreator = true; + } + } + if (isTagCreator) { + String regid = jsonObject.getString(SwidTagConstants.REGID, ""); + if (regid.isEmpty()) { + //throw exception that regid is required + } else { + entity.setRegid(regid); + } + } else { + entity.setRegid(jsonObject.getString(SwidTagConstants.REGID, "invalid.unavailable")); + } + String thumbprint = jsonObject.getString(SwidTagConstants.THUMBPRINT, ""); + if (!thumbprint.isEmpty()) { + entity.setThumbprint(thumbprint); } - entity.setThumbprint(properties.getProperty(SwidTagConstants.ENTITY_THUMBPRINT)); - return entity; } @@ -358,10 +470,16 @@ public class SwidTagGateway { * @param properties the Properties object containing parameters from file * @return Link element created from the properties */ - private Link createLink(Properties properties) { + private Link createLink(JsonObject jsonObject) { Link link = objectFactory.createLink(); - link.setHref(properties.getProperty(SwidTagConstants.LINK_HREF)); - link.setRel(properties.getProperty(SwidTagConstants.LINK_REL)); + String href = jsonObject.getString(SwidTagConstants.HREF, ""); + if (!href.isEmpty()) { + link.setHref(href); + } + String rel = jsonObject.getString(SwidTagConstants.REL, ""); + if (!rel.isEmpty()) { + link.setRel(rel); + } return link; } @@ -372,85 +490,95 @@ public class SwidTagGateway { * @param properties the Properties object containing parameters from file * @return the Meta element created from the properties */ - private SoftwareMeta createSoftwareMeta(Properties properties) { + private SoftwareMeta createSoftwareMeta(JsonObject jsonObject) { SoftwareMeta softwareMeta = objectFactory.createSoftwareMeta(); Map attributes = softwareMeta.getOtherAttributes(); - attributes.put(_RIM_PCURILOCAL, properties.getProperty(SwidTagConstants.META_PCURILOCAL)); - attributes.put(_RIM_BINDINGSPEC, properties.getProperty(SwidTagConstants.META_BINDINGSPEC)); - attributes.put(_RIM_BINDINGSPECVERSION, properties.getProperty(SwidTagConstants.META_BINDINGSPECVERSION)); - attributes.put(_RIM_PLATFORMMANUFACTURERID, properties.getProperty(SwidTagConstants.META_PLATFORMMANUFACTURERID)); - attributes.put(_RIM_PLATFORMMANUFACTURERSTR, properties.getProperty(SwidTagConstants.META_PLATFORMMANUFACTURERSTR)); - attributes.put(_RIM_PLATFORMMODEL, properties.getProperty(SwidTagConstants.META_PLATFORMMODEL)); - attributes.put(_RIM_COMPONENTCLASS, properties.getProperty(SwidTagConstants.META_COMPONENTCLASS)); - attributes.put(_RIM_COMPONENTMANUFACTURER, properties.getProperty(SwidTagConstants.META_COMPONENTMANUFACTURER)); - attributes.put(_RIM_COMPONENTMANUFACTURERID, properties.getProperty(SwidTagConstants.META_COMPONENTMANUFACTURERID)); - attributes.put(_RIM_RIMLINKHASH, properties.getProperty(SwidTagConstants.META_RIMLINKHASH)); + addNonNullAttribute(attributes, SwidTagConstants._COLLOQUIAL_VERSION, jsonObject.getString(SwidTagConstants.COLLOQUIAL_VERSION, "")); + addNonNullAttribute(attributes, SwidTagConstants._EDITION, jsonObject.getString(SwidTagConstants.EDITION, "")); + addNonNullAttribute(attributes, SwidTagConstants._PRODUCT, jsonObject.getString(SwidTagConstants.PRODUCT, "")); + addNonNullAttribute(attributes, SwidTagConstants._REVISION, jsonObject.getString(SwidTagConstants.REVISION, "")); + addNonNullAttribute(attributes, SwidTagConstants._PAYLOAD_TYPE, jsonObject.getString(SwidTagConstants.PAYLOAD_TYPE, "")); + addNonNullAttribute(attributes, SwidTagConstants._PLATFORM_MANUFACTURER_STR, jsonObject.getString(SwidTagConstants.PLATFORM_MANUFACTURER_STR, "")); + addNonNullAttribute(attributes, SwidTagConstants._PLATFORM_MANUFACTURER_ID, jsonObject.getString(SwidTagConstants.PLATFORM_MANUFACTURER_ID, "")); + addNonNullAttribute(attributes, SwidTagConstants._PLATFORM_MODEL, jsonObject.getString(SwidTagConstants.PLATFORM_MODEL, "")); + addNonNullAttribute(attributes, SwidTagConstants._PLATFORM_VERSION, jsonObject.getString(SwidTagConstants.PLATFORM_VERSION, "")); + addNonNullAttribute(attributes, SwidTagConstants._FIRMWARE_MANUFACTURER_STR, jsonObject.getString(SwidTagConstants.FIRMWARE_MANUFACTURER_STR, "")); + addNonNullAttribute(attributes, SwidTagConstants._FIRMWARE_MANUFACTURER_ID, jsonObject.getString(SwidTagConstants.FIRMWARE_MANUFACTURER_ID, "")); + addNonNullAttribute(attributes, SwidTagConstants._FIRMWARE_MODEL, jsonObject.getString(SwidTagConstants.FIRMWARE_MODEL, "")); + addNonNullAttribute(attributes, SwidTagConstants._FIRMWARE_VERSION, jsonObject.getString(SwidTagConstants.FIRMWARE_VERSION, "")); + addNonNullAttribute(attributes, SwidTagConstants._BINDING_SPEC, jsonObject.getString(SwidTagConstants.BINDING_SPEC, "")); + addNonNullAttribute(attributes, SwidTagConstants._BINDING_SPEC_VERSION, jsonObject.getString(SwidTagConstants.BINDING_SPEC_VERSION, "")); + addNonNullAttribute(attributes, SwidTagConstants._PC_URI_LOCAL, jsonObject.getString(SwidTagConstants.PC_URI_LOCAL, "")); + addNonNullAttribute(attributes, SwidTagConstants._PC_URI_GLOBAL, jsonObject.getString(SwidTagConstants.PC_URI_GLOBAL, "")); + addNonNullAttribute(attributes, SwidTagConstants._RIM_LINK_HASH, jsonObject.getString(SwidTagConstants.RIM_LINK_HASH, "")); return softwareMeta; } - /** - * This method creates a Directory from the parameters read in from a properties file. - * - * @param properties the Properties object containing parameters from file - * @return Directory object created from the properties - */ - private Directory createDirectory(Properties properties) { - Directory directory = objectFactory.createDirectory(); - directory.setLocation(properties.getProperty(SwidTagConstants.DIRECTORY_LOCATION)); - directory.setName(properties.getProperty(SwidTagConstants.DIRECTORY_NAME)); - String directoryRoot = properties.getProperty(SwidTagConstants.DIRECTORY_ROOT); - if (!directoryRoot.isEmpty()) { - directory.setRoot(directoryRoot); - } - - return directory; - } - - /** - * This method creates a hirs.swid.xjc.File from a java.nio.File object. - * This method signature is not currently used and may be removed later. - * - * @param file - * @return hirs.swid.xjc.File object from File object - */ - private hirs.swid.xjc.File createFile(File file) { - return createFile(file.getName(), "01.00", Long.toString(file.length())); - } - - /** - * 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 - * @return hirs.swid.xjc.File object from File object - */ - private hirs.swid.xjc.File createFile(String filename, String version, String size) { - hirs.swid.xjc.File file = objectFactory.createFile(); - file.setName(filename); - file.setVersion(version); - file.setSize(new BigInteger(size)); - String hash = HashSwid.get256Hash(file.getName()); - file.getOtherAttributes().put(_SHA256_HASH, hash); - - return file; - } - /** * This method creates a Payload from the parameters read in from a properties file. * * @param properties the Properties object containing parameters from file * @return the Payload object created */ - private ResourceCollection createPayload(Properties properties) { - ResourceCollection rc = objectFactory.createResourceCollection(); + private ResourceCollection createPayload(JsonObject jsonObject) { + ResourceCollection payload = objectFactory.createResourceCollection(); + Map 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, "")); - rc.getOtherAttributes().put(_N8060_ENVVARPREFIX, properties.getProperty(SwidTagConstants.PAYLOAD_ENVVARPREFIX)); - rc.getOtherAttributes().put(_N8060_ENVVARSUFFIX, properties.getProperty(SwidTagConstants.PAYLOAD_ENVVARSUFFIX)); - rc.getOtherAttributes().put(_N8060_PATHSEPARATOR, properties.getProperty(SwidTagConstants.PAYLOAD_PATHSEPARATOR)); + return payload; + } - return rc; + /** + * This method creates a Directory from the parameters read in from a properties file. + * + * @param properties the Properties object containing parameters from file + * @return Directory object created from the properties + */ + private Directory createDirectory(JsonObject jsonObject) { + Directory directory = objectFactory.createDirectory(); + directory.setName(jsonObject.getString(SwidTagConstants.NAME, "")); + Map attributes = directory.getOtherAttributes(); + 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; + } + + /** + * 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 + * @return hirs.swid.xjc.File object from File object + */ + private hirs.swid.xjc.File createFile(JsonObject jsonObject) { + hirs.swid.xjc.File file = objectFactory.createFile(); + file.setName(jsonObject.getString(SwidTagConstants.NAME, "")); + file.setSize(new BigInteger(jsonObject.getString(SwidTagConstants.SIZE, "0"))); + Map attributes = file.getOtherAttributes(); + addNonNullAttribute(attributes, _SHA256_HASH, jsonObject.getString(SwidTagConstants.HASH, "")); + 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, "")); + + return file; + } + + private void addNonNullAttribute(Map attributes, QName key, String value) { + if (!value.isEmpty()) { + attributes.put(key, value); + } } /** @@ -480,45 +608,130 @@ public class SwidTagGateway { } /** - * This method creates an xml signature based on the xmldsig schema. - * This method is incomplete and not yet implemented. - * - * @return the Signature object created + * This method signs a SoftwareIdentity with an xmldsig in compatibility mode. + * Current assumptions: digest method SHA256, signature method SHA256, enveloped signature */ - private SignatureType createSignature() { - SignatureType signature = objectFactory.createSignatureType(); - SignedInfoType signedInfo = objectFactory.createSignedInfoType(); + private Document signXMLDocument(JAXBElement swidTag) { + Document doc = null; + try { + XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM"); + Reference reference = sigFactory.newReference( + "", + sigFactory.newDigestMethod(DigestMethod.SHA256, null), + Collections.singletonList(sigFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), + null, + null + ); + SignedInfo signedInfo = sigFactory.newSignedInfo( + sigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null), + sigFactory.newSignatureMethod(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256, null), + Collections.singletonList(reference) + ); + KeyStore keystore = KeyStore.getInstance("JKS"); + keystore.load(new FileInputStream(SwidTagConstants.DEFAULT_KEYSTORE_PATH), 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(); + KeyInfoFactory kiFactory = sigFactory.getKeyInfoFactory(); + ArrayList x509Content = new ArrayList(); + x509Content.add(certificate.getSubjectX500Principal().getName()); + x509Content.add(certificate); + X509Data data = kiFactory.newX509Data(x509Content); + KeyInfo keyinfo = kiFactory.newKeyInfo(Collections.singletonList(data)); - CanonicalizationMethodType canonicalizationMethod = objectFactory.createCanonicalizationMethodType(); - canonicalizationMethod.setAlgorithm("http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); + doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + marshaller.marshal(swidTag, doc); + DOMSignContext context = new DOMSignContext(privateKey.getPrivateKey(), 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) { + System.out.println(e.getMessage()); + } catch (CertificateException e) { + System.out.println("Certificate error: " + e.getMessage()); + } catch (JAXBException e) { + System.out.println("Error marshaling signed swidtag: " + e.getMessage()); + } catch (MarshalException | XMLSignatureException e) { + System.out.println("Error while signing SoftwareIdentity: " + e.getMessage()); + } - SignatureMethodType signatureMethod = objectFactory.createSignatureMethodType(); - signatureMethod.setAlgorithm("http://www.w3.org/2000/09/xmldsig#rsa-sha512"); + return doc; + } - ReferenceType reference = objectFactory.createReferenceType(); - TransformsType transforms = objectFactory.createTransformsType(); + /** + * This method validates a Document with a signature element. + * + * @param doc + */ + private boolean validateSignedXMLDocument(Document doc) { + boolean isValid = false; + try { + NodeList nodes = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); + if (nodes.getLength() == 0) { + throw new Exception("Signature element not found!"); + } + DOMValidateContext context = new DOMValidateContext(new X509KeySelector(), nodes.item(0)); + XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM"); + XMLSignature signature = sigFactory.unmarshalXMLSignature(context); + isValid = signature.validate(context); + } catch (MarshalException | XMLSignatureException e) { + System.out.println(e.getMessage()); + } catch (Exception e) { + System.out.println(e.getMessage()); + } - TransformType transform = objectFactory.createTransformType(); - transform.setAlgorithm("http://www.w3.org/2000/09/xmldsig#enveloped-signature"); - transforms.getTransform().add(transform); + return isValid; + } - DigestMethodType digestMethod = objectFactory.createDigestMethodType(); - digestMethod.setAlgorithm("http://www.w3.org/2000/09/xmldsig#sha256"); + public class X509KeySelector extends KeySelector { + public KeySelectorResult select(KeyInfo keyinfo, + KeySelector.Purpose purpose, + AlgorithmMethod algorithm, + XMLCryptoContext context) throws KeySelectorException { + Iterator keyinfoItr = keyinfo.getContent().iterator(); + while(keyinfoItr.hasNext()) { + XMLStructure element = (XMLStructure) keyinfoItr.next(); + if (element instanceof X509Data) { + X509Data data = (X509Data) element; + Iterator dataItr = data.getContent().iterator(); + while (dataItr.hasNext()) { + Object object = dataItr.next(); + if (object instanceof X509Certificate) { + final PublicKey publicKey = ((X509Certificate) object).getPublicKey(); + if (areAlgorithmsEqual(algorithm.getAlgorithm(), publicKey.getAlgorithm())) { + return new RIMKeySelectorResult(publicKey); + } + } + } + } + } - reference.setTransforms(transforms); - reference.setDigestMethod(digestMethod); - reference.setDigestValue(new byte[10]); + throw new KeySelectorException("No key found!"); + } - signedInfo.setCanonicalizationMethod(canonicalizationMethod); - signedInfo.setSignatureMethod(signatureMethod); - signedInfo.getReference().add(reference); + public boolean areAlgorithmsEqual(String uri, String name) { + if (uri.equals(SwidTagConstants.SIGNATURE_ALGORITHM_RSA_SHA256) && name.equalsIgnoreCase("RSA")) { + return true; + } else { + return false; + } + } - SignatureValueType signatureValue = objectFactory.createSignatureValueType(); - signatureValue.setValue(new byte[10]); + private class RIMKeySelectorResult implements KeySelectorResult { + private Key key; - signature.setSignedInfo(signedInfo); + public RIMKeySelectorResult(Key key) { + this.key = key; + } - return signature; + public Key getKey() { + return key; + } + } } /** @@ -572,8 +785,6 @@ public class SwidTagGateway { is = SwidTagGateway.class.getClassLoader().getResourceAsStream(SwidTagConstants.SCHEMA_URL); SchemaFactory schemaFactory = SchemaFactory.newInstance(SwidTagConstants.SCHEMA_LANGUAGE); Schema schema = schemaFactory.newSchema(new StreamSource(is)); - JAXBContext jaxbContext = JAXBContext.newInstance(SwidTagConstants.SCHEMA_PACKAGE); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); unmarshaller.setSchema(schema); jaxbe = (JAXBElement) unmarshaller.unmarshal(input); } catch (SAXException e) { diff --git a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java index 3a5fc006..3b155e65 100644 --- a/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java +++ b/tools/tcg_rim_tool/src/main/java/hirs/swid/utils/Commander.java @@ -17,21 +17,24 @@ public class Commander { 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 EXAMPLE_STRING = "example"; private static final String PARSE_STRING = "parse"; - private static final String IN_STRING = "in"; - private static final String OUT_STRING = "out"; - private static final String HASH_STRING = "hash"; + private static final String ATTRIBUTES_STRING = "attributes"; + private static final String KEY_STRING = "key"; + private static final String PRIVATE_KEY_STRING = "privatekey"; + private static final String CERT_STRING = "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 String validateFile; - private String createInFile; - private String createOutFile; + private String createOutFile = ""; private String parseFile; + private String attributesFile = ""; + private String keystore = ""; private String hashAlg = null; /** @@ -45,31 +48,18 @@ public class Commander { if (hasArguments) { parseArguments(args); } else { - //printHelp(); + printHelp(); } if (create) { - if (!Files.exists(Paths.get(getCreateInFile()))) { - create = false; - printHelp("Input file doesn't exist..."); - } - if (hashAlg == null) { hashAlg = "256"; } - if (!isValidPath(getCreateOutFile())) { - printHelp(String.format("Invalid file path on creation file...(%s)", - getCreateOutFile())); + if (!getCreateOutFile().isEmpty() && !isValidPath(getCreateOutFile())) { + printHelp(String.format("Invalid file path %s!", getCreateOutFile())); } } - - if (validate && create) { - // there maybe a time in which you could validate what you created - // but not right now - // print the help information - printHelp(); - } } /** @@ -95,15 +85,15 @@ public class Commander { case FULL_COMMAND_PREFIX + CREATE_STRING: case COMMAND_PREFIX + "c": create = true; - break; - case COMMAND_PREFIX + IN_STRING: - if (create) { - createInFile = args[++i]; + if (i+1 < args.length && !args[i+1].substring(0,1).equals(COMMAND_PREFIX)) { + createOutFile = args[++i]; } break; - case COMMAND_PREFIX + OUT_STRING: - if (create) { - createOutFile = args[++i]; + 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: @@ -111,27 +101,18 @@ public class Commander { validate = true; validateFile = args[++i]; break; - case FULL_COMMAND_PREFIX + EXAMPLE_STRING: - case COMMAND_PREFIX + "e": - hasArguments = false; - return; // default is generate - case COMMAND_PREFIX + HASH_STRING: - hashAlg = args[++i]; - break; case FULL_COMMAND_PREFIX + PARSE_STRING: case COMMAND_PREFIX + "p": parse = true; parseFile = args[++i]; break; + case FULL_COMMAND_PREFIX + KEY_STRING: + case COMMAND_PREFIX + "k": + keystore = args[++i]; + break; case FULL_COMMAND_PREFIX + HELP_STRING: case COMMAND_PREFIX + "h": default: - if (Files.exists(Paths.get(args[i]))) { - validate = true; - validateFile = args[i]; - break; - } - printHelp(); } } @@ -146,15 +127,6 @@ public class Commander { return validateFile; } - /** - * Getter for the input create file associated with the create flag - * - * @return - */ - public final String getCreateInFile() { - return createInFile; - } - /** * Getter for the output file for the create flag * @@ -218,7 +190,39 @@ public class Commander { 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; + } + + /** + * Getter for the keystore used for digital signatures + * @return + */ + public String getKeystore() { + return keystore; + } + /** * Default no parameter help method. */ @@ -237,20 +241,29 @@ public class Commander { sb.append(String.format("ERROR: %s\n\n", message)); } sb.append("Usage: HIRS_SwidTag\n"); - sb.append(" -c, --create \tTakes given input in the csv format\n" - + " \t-in \tand produces swidtag payloads.\n" - + " \t-out \tThe -hash argument is optional.\n" - + " \t-hash \n"); - sb.append(" -v, --verify\t\tTakes the provided input file and\n" - + " \t\t\tvalidates it against the schema at\n" - + " \t\t\thttp://standards.iso.org/iso/19770/-2/2015/schema.xsd\n"); - sb.append(" -e, --example\tCreate example swid tag file (generated_swidTag.swidtag)\n"); - sb.append(" -h, --help\t\tPrints the command help information\n"); - sb.append(" \t\tListing no command with no argument will\n" - + " \t\t\tcreate an example tag file\n"); - sb.append(" \t\tValidate the given file argument\n"); - sb.append(" -p, --parse\t\tParse a swidtag's payload\n" - + " \t\tInput swidtag"); + sb.append(" -c, --create \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 \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 \t\tParse the given swidtag's payload\n\n"); +/* sb.append(" -k, --key\t\t\tSpecify the credential and its location to use\n" + + " \t-privatekey \tfor digital signatures\n" + + " \t-cert \n\n"); +*/ sb.append(" -h, --help, \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);