Modify BaseReferenceManifest to handle namespace prefixes in the swidtag XML. Modify the rimtool and ReferenceManifestValidator to properly prefix Directory and File under Payload and handle them for validation.

This commit is contained in:
chubtub 2024-04-11 09:14:09 -04:00
parent 594870ca14
commit cfbd8f2e38
6 changed files with 98 additions and 37 deletions

View File

@ -116,10 +116,14 @@ public class BaseReferenceManifest extends ReferenceManifest {
// begin parsing valid swid tag // begin parsing valid swid tag
if (document != null) { if (document != null) {
softwareIdentity = (Element) document.getElementsByTagName(SwidTagConstants.SOFTWARE_IDENTITY).item(0); softwareIdentity = (Element) document.getElementsByTagNameNS(
entity = (Element) document.getElementsByTagName(SwidTagConstants.ENTITY).item(0); SwidTagConstants.SWIDTAG_NAMESPACE, SwidTagConstants.SOFTWARE_IDENTITY).item(0);
link = (Element) document.getElementsByTagName(SwidTagConstants.LINK).item(0); entity = (Element) document.getElementsByTagNameNS(
meta = (Element) document.getElementsByTagName(SwidTagConstants.META).item(0); SwidTagConstants.SWIDTAG_NAMESPACE, SwidTagConstants.ENTITY).item(0);
link = (Element) document.getElementsByTagNameNS(
SwidTagConstants.SWIDTAG_NAMESPACE, SwidTagConstants.LINK).item(0);
meta = (Element) document.getElementsByTagNameNS(
SwidTagConstants.SWIDTAG_NAMESPACE, SwidTagConstants.META).item(0);
setTagId(softwareIdentity.getAttribute(SwidTagConstants.TAGID)); setTagId(softwareIdentity.getAttribute(SwidTagConstants.TAGID));
this.swidName = softwareIdentity.getAttribute(SwidTagConstants.NAME); this.swidName = softwareIdentity.getAttribute(SwidTagConstants.NAME);
this.swidCorpus = Boolean.parseBoolean(softwareIdentity.getAttribute(SwidTagConstants.CORPUS)) ? 1 : 0; this.swidCorpus = Boolean.parseBoolean(softwareIdentity.getAttribute(SwidTagConstants.CORPUS)) ? 1 : 0;
@ -217,7 +221,8 @@ public class BaseReferenceManifest extends ReferenceManifest {
private Element getDirectoryTag(final ByteArrayInputStream byteArrayInputStream) { private Element getDirectoryTag(final ByteArrayInputStream byteArrayInputStream) {
Document document = unmarshallSwidTag(byteArrayInputStream); Document document = unmarshallSwidTag(byteArrayInputStream);
Element softwareIdentity = Element softwareIdentity =
(Element) document.getElementsByTagName("SoftwareIdentity").item(0); (Element) document.getElementsByTagNameNS(
SwidTagConstants.SWIDTAG_NAMESPACE,"SoftwareIdentity").item(0);
if (softwareIdentity != null) { if (softwareIdentity != null) {
Element directory = (Element) document.getElementsByTagName("Directory").item(0); Element directory = (Element) document.getElementsByTagName("Directory").item(0);

View File

@ -261,7 +261,8 @@ public class ReferenceManifestValidator {
* @return true if both the file element and signature are valid, false otherwise * @return true if both the file element and signature are valid, false otherwise
*/ */
public boolean validateRim(String signingCertPath) { public boolean validateRim(String signingCertPath) {
Element fileElement = (Element) rim.getElementsByTagName("File").item(0); Element fileElement = (Element) rim.getElementsByTagNameNS(
SwidTagConstants.SWIDTAG_NAMESPACE, "File").item(0);
X509Certificate signingCert = parseCertificatesFromPem(signingCertPath).get(0); X509Certificate signingCert = parseCertificatesFromPem(signingCertPath).get(0);
if (signingCert == null) { if (signingCert == null) {
return failWithError("Unable to parse the signing cert from " + signingCertPath); return failWithError("Unable to parse the signing cert from " + signingCertPath);

View File

@ -22,6 +22,7 @@ public class SwidTagConstants {
public static final String SCHEMA_PACKAGE = "hirs.swid.xjc"; 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_LANGUAGE = XMLConstants.W3C_XML_SCHEMA_NS_URI;
public static final String SCHEMA_URL = "swid_schema.xsd"; public static final String SCHEMA_URL = "swid_schema.xsd";
public static final String SWIDTAG_NAMESPACE = "http://standards.iso.org/iso/19770/-2/2015/schema.xsd";
public static final String SOFTWARE_IDENTITY = "SoftwareIdentity"; public static final String SOFTWARE_IDENTITY = "SoftwareIdentity";
public static final String ENTITY = "Entity"; public static final String ENTITY = "Entity";

View File

@ -66,6 +66,8 @@ public class ObjectFactory {
private final static QName _SoftwareIdentityLink_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Link"); private final static QName _SoftwareIdentityLink_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Link");
private final static QName _SoftwareIdentityEvidence_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Evidence"); private final static QName _SoftwareIdentityEvidence_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Evidence");
private final static QName _SoftwareIdentityPayload_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Payload"); private final static QName _SoftwareIdentityPayload_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Payload");
private final static QName _PayloadDirectory_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Directory");
private final static QName _DirectoryFile_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "File");
private final static QName _SoftwareIdentityEntity_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Entity"); private final static QName _SoftwareIdentityEntity_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Entity");
private final static QName _SoftwareIdentityMeta_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Meta"); private final static QName _SoftwareIdentityMeta_QNAME = new QName("http://standards.iso.org/iso/19770/-2/2015/schema.xsd", "Meta");
private final static QName _SignatureMethodTypeHMACOutputLength_QNAME = new QName("http://www.w3.org/2000/09/xmldsig#", "HMACOutputLength"); private final static QName _SignatureMethodTypeHMACOutputLength_QNAME = new QName("http://www.w3.org/2000/09/xmldsig#", "HMACOutputLength");
@ -666,6 +668,24 @@ public class ObjectFactory {
return new JAXBElement<ResourceCollection>(_SoftwareIdentityPayload_QNAME, ResourceCollection.class, SoftwareIdentity.class, value); return new JAXBElement<ResourceCollection>(_SoftwareIdentityPayload_QNAME, ResourceCollection.class, SoftwareIdentity.class, value);
} }
/**
* Create an instance of {@link JAXBElement }{@code <}{@link FilesystemItem }{@code >}}
*
*/
@XmlElementDecl(namespace = "http://standards.iso.org/iso/19770/-2/2015/schema.xsd", name = "Directory", scope = ResourceCollection.class)
public JAXBElement<FilesystemItem> createPayloadDirectory(FilesystemItem value) {
return new JAXBElement<FilesystemItem>(_PayloadDirectory_QNAME, FilesystemItem.class, ResourceCollection.class, value);
}
/**
* Create an instance of {@link JAXBElement }{@code <}{@link FilesystemItem }{@code >}}
*
*/
@XmlElementDecl(namespace = "http://standards.iso.org/iso/19770/-2/2015/schema.xsd", name = "File", scope = ResourceCollection.class)
public JAXBElement<FilesystemItem> createDirectoryFile(FilesystemItem value) {
return new JAXBElement<FilesystemItem>(_DirectoryFile_QNAME, FilesystemItem.class, ResourceCollection.class, value);
}
/** /**
* Create an instance of {@link JAXBElement }{@code <}{@link Entity }{@code >}} * Create an instance of {@link JAXBElement }{@code <}{@link Entity }{@code >}}
* *

View File

@ -28,6 +28,7 @@ public class SwidTagConstants {
public static final String SCHEMA_PACKAGE = "hirs.utils.xjc"; public static final String SCHEMA_PACKAGE = "hirs.utils.xjc";
public static final String SCHEMA_LANGUAGE = XMLConstants.W3C_XML_SCHEMA_NS_URI; 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 SCHEMA_URL = "swid_schema.xsd";
public static final String SWIDTAG_NAMESPACE = "http://standards.iso.org/iso/19770/-2/2015/schema.xsd";
public static final String SOFTWARE_IDENTITY = "SoftwareIdentity"; public static final String SOFTWARE_IDENTITY = "SoftwareIdentity";
public static final String ENTITY = "Entity"; public static final String ENTITY = "Entity";

View File

@ -3,22 +3,24 @@ package hirs.swid;
import hirs.swid.utils.HashSwid; import hirs.swid.utils.HashSwid;
import hirs.utils.xjc.Directory; import hirs.utils.xjc.Directory;
import hirs.utils.xjc.Entity; import hirs.utils.xjc.Entity;
import hirs.utils.xjc.FilesystemItem;
import hirs.utils.xjc.Link; import hirs.utils.xjc.Link;
import hirs.utils.xjc.ObjectFactory; import hirs.utils.xjc.ObjectFactory;
import hirs.utils.xjc.ResourceCollection; import hirs.utils.xjc.ResourceCollection;
import hirs.utils.xjc.SoftwareIdentity; import hirs.utils.xjc.SoftwareIdentity;
import hirs.utils.xjc.SoftwareMeta; import hirs.utils.xjc.SoftwareMeta;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.json.Json; import javax.json.Json;
import javax.json.JsonException; import javax.json.JsonException;
import javax.json.JsonObject; import javax.json.JsonObject;
import javax.json.JsonReader; import javax.json.JsonReader;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import javax.xml.crypto.MarshalException; import javax.xml.crypto.MarshalException;
import javax.xml.crypto.XMLStructure; import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.dom.DOMStructure; import javax.xml.crypto.dom.DOMStructure;
@ -41,6 +43,7 @@ import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec; import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys; import javax.xml.transform.OutputKeys;
@ -91,6 +94,8 @@ public class SwidTagGateway {
private String timestampFormat; private String timestampFormat;
private String timestampArgument; private String timestampArgument;
private String errorRequiredFields; private String errorRequiredFields;
private DocumentBuilderFactory dbf;
private DocumentBuilder builder;
/** /**
* Default constructor initializes jaxbcontext, marshaller, and unmarshaller * Default constructor initializes jaxbcontext, marshaller, and unmarshaller
@ -107,8 +112,15 @@ public class SwidTagGateway {
timestampFormat = ""; timestampFormat = "";
timestampArgument = ""; timestampArgument = "";
errorRequiredFields = ""; errorRequiredFields = "";
dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
builder = dbf.newDocumentBuilder();
} catch (JAXBException e) { } catch (JAXBException e) {
System.out.println("Error initializing jaxbcontext: " + e.getMessage()); System.out.println("Error initializing jaxbcontext: " + e.getMessage());
} catch (ParserConfigurationException e) {
System.out.println("Error instantiating Document object for parsing swidtag: "
+ e.getMessage());
System.exit(1);
} }
} }
@ -198,49 +210,62 @@ public class SwidTagGateway {
* @param filename * @param filename
*/ */
public void generateSwidTag(final String filename) { public void generateSwidTag(final String filename) {
SoftwareIdentity swidTag = null; Document swidtag = builder.newDocument();
SoftwareIdentity softwareIdentity = null;
try { try {
InputStream is = new FileInputStream(attributesFile); InputStream is = new FileInputStream(attributesFile);
JsonReader reader = Json.createReader(is); JsonReader reader = Json.createReader(is);
JsonObject configProperties = reader.readObject(); JsonObject configProperties = reader.readObject();
reader.close(); reader.close();
//SoftwareIdentity //SoftwareIdentity
swidTag = createSwidTag( softwareIdentity = createSwidTag(
configProperties.getJsonObject(SwidTagConstants.SOFTWARE_IDENTITY)); configProperties.getJsonObject(SwidTagConstants.SOFTWARE_IDENTITY));
//Entity //Entity
JAXBElement<Entity> entity = objectFactory.createSoftwareIdentityEntity( JAXBElement<Entity> entity = objectFactory.createSoftwareIdentityEntity(
createEntity(configProperties.getJsonObject(SwidTagConstants.ENTITY))); createEntity(configProperties.getJsonObject(SwidTagConstants.ENTITY)));
swidTag.getEntityOrEvidenceOrLink().add(entity); softwareIdentity.getEntityOrEvidenceOrLink().add(entity);
//Link //Link
JAXBElement<Link> link = objectFactory.createSoftwareIdentityLink( JAXBElement<Link> link = objectFactory.createSoftwareIdentityLink(
createLink(configProperties.getJsonObject(SwidTagConstants.LINK))); createLink(configProperties.getJsonObject(SwidTagConstants.LINK)));
swidTag.getEntityOrEvidenceOrLink().add(link); softwareIdentity.getEntityOrEvidenceOrLink().add(link);
//Meta //Meta
JAXBElement<SoftwareMeta> meta = objectFactory.createSoftwareIdentityMeta( JAXBElement<SoftwareMeta> meta = objectFactory.createSoftwareIdentityMeta(
createSoftwareMeta(configProperties.getJsonObject(SwidTagConstants.META))); createSoftwareMeta(configProperties.getJsonObject(SwidTagConstants.META)));
swidTag.getEntityOrEvidenceOrLink().add(meta); softwareIdentity.getEntityOrEvidenceOrLink().add(meta);
//Payload
ResourceCollection payload = createPayload( swidtag = convertToDocument(objectFactory.createSoftwareIdentity(softwareIdentity));
configProperties.getJsonObject(SwidTagConstants.PAYLOAD)); Element rootElement = swidtag.getDocumentElement();
//Directory
Directory directory = createDirectory(
configProperties.getJsonObject(SwidTagConstants.PAYLOAD)
.getJsonObject(SwidTagConstants.DIRECTORY));
//File //File
hirs.utils.xjc.File file = createFile( hirs.utils.xjc.File file = createFile(
configProperties.getJsonObject(SwidTagConstants.PAYLOAD) configProperties.getJsonObject(SwidTagConstants.PAYLOAD)
.getJsonObject(SwidTagConstants.DIRECTORY) .getJsonObject(SwidTagConstants.DIRECTORY)
.getJsonObject(SwidTagConstants.FILE)); .getJsonObject(SwidTagConstants.FILE));
//Nest File in Directory in Payload JAXBElement<FilesystemItem> jaxbFile = objectFactory.createDirectoryFile(file);
directory.getDirectoryOrFile().add(file); Document fileDoc = convertToDocument(jaxbFile);
payload.getDirectoryOrFileOrProcess().add(directory); //Directory
Directory directory = createDirectory(
configProperties.getJsonObject(SwidTagConstants.PAYLOAD)
.getJsonObject(SwidTagConstants.DIRECTORY));
JAXBElement<FilesystemItem> jaxbDirectory = objectFactory.createPayloadDirectory(directory);
Document dirDoc = convertToDocument(jaxbDirectory);
Node fileNode = dirDoc.importNode(fileDoc.getDocumentElement(), true);
dirDoc.getDocumentElement().appendChild(fileNode);
//Payload
ResourceCollection payload = createPayload(
configProperties.getJsonObject(SwidTagConstants.PAYLOAD));
JAXBElement<ResourceCollection> jaxbPayload = JAXBElement<ResourceCollection> jaxbPayload =
objectFactory.createSoftwareIdentityPayload(payload); objectFactory.createSoftwareIdentityPayload(payload);
swidTag.getEntityOrEvidenceOrLink().add(jaxbPayload); Document payloadDoc = convertToDocument(jaxbPayload);
Node dirNode = payloadDoc.importNode(dirDoc.getDocumentElement(), true);
payloadDoc.getDocumentElement().appendChild(dirNode);
Node payloadNode = swidtag.importNode(payloadDoc.getDocumentElement(), true);
rootElement.appendChild(payloadNode);
//Signature //Signature
if (errorRequiredFields.isEmpty()) { if (errorRequiredFields.isEmpty()) {
Document signedSoftwareIdentity = signXMLDocument( Document signedSoftwareIdentity = signXMLDocument(swidtag);
objectFactory.createSoftwareIdentity(swidTag));
writeSwidTagFile(signedSoftwareIdentity, filename); writeSwidTagFile(signedSoftwareIdentity, filename);
} else { } else {
System.out.println("The following fields cannot be empty or null: " System.out.println("The following fields cannot be empty or null: "
@ -545,23 +570,31 @@ public class SwidTagGateway {
} }
/** /**
* This method signs a SoftwareIdentity with an xmldsig in compatibility mode. * This method converts a JAXBElement object generated from the hirs.utils.xjc package into
* Current assumptions: digest method SHA256, signature method SHA256, enveloped signature * a Document object.
*
* @param element to convert
* @return a Document object
*/ */
private Document signXMLDocument(JAXBElement<SoftwareIdentity> swidTag) { private Document convertToDocument(JAXBElement element) {
Document doc = null; Document doc = null;
try { try {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); doc = builder.newDocument();
marshaller.marshal(swidTag, doc); marshaller.marshal(element, doc);
} catch (ParserConfigurationException e) {
System.out.println("Error instantiating Document object for parsing swidtag: "
+ e.getMessage());
System.exit(1);
} catch (JAXBException e) { } catch (JAXBException e) {
System.out.println("Error while marshaling swidtag: " + e.getMessage()); System.out.println("Error while marshaling swidtag: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
System.exit(1); System.exit(1);
} }
return doc;
}
/**
* This method signs a SoftwareIdentity with an xmldsig in compatibility mode.
* Current assumptions: digest method SHA256, signature method SHA256, enveloped signature
*/
private Document signXMLDocument(Document doc) {
XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM"); XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
List xmlObjectList = null; List xmlObjectList = null;
String signatureId = null; String signatureId = null;