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 a903b0e448
commit 4da6020260
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
if (document != null) {
softwareIdentity = (Element) document.getElementsByTagName(SwidTagConstants.SOFTWARE_IDENTITY).item(0);
entity = (Element) document.getElementsByTagName(SwidTagConstants.ENTITY).item(0);
link = (Element) document.getElementsByTagName(SwidTagConstants.LINK).item(0);
meta = (Element) document.getElementsByTagName(SwidTagConstants.META).item(0);
softwareIdentity = (Element) document.getElementsByTagNameNS(
SwidTagConstants.SWIDTAG_NAMESPACE, SwidTagConstants.SOFTWARE_IDENTITY).item(0);
entity = (Element) document.getElementsByTagNameNS(
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));
this.swidName = softwareIdentity.getAttribute(SwidTagConstants.NAME);
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) {
Document document = unmarshallSwidTag(byteArrayInputStream);
Element softwareIdentity =
(Element) document.getElementsByTagName("SoftwareIdentity").item(0);
(Element) document.getElementsByTagNameNS(
SwidTagConstants.SWIDTAG_NAMESPACE,"SoftwareIdentity").item(0);
if (softwareIdentity != null) {
Element directory = (Element) document.getElementsByTagName("Directory").item(0);

View File

@ -252,7 +252,8 @@ public class ReferenceManifestValidator {
* @return true if both the file element and signature are valid, false otherwise
*/
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);
if (signingCert == null) {
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_LANGUAGE = XMLConstants.W3C_XML_SCHEMA_NS_URI;
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 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 _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 _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 _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");
@ -666,6 +668,24 @@ public class ObjectFactory {
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 >}}
*

View File

@ -28,6 +28,7 @@ public class SwidTagConstants {
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_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 ENTITY = "Entity";

View File

@ -3,22 +3,24 @@ package hirs.swid;
import hirs.swid.utils.HashSwid;
import hirs.utils.xjc.Directory;
import hirs.utils.xjc.Entity;
import hirs.utils.xjc.FilesystemItem;
import hirs.utils.xjc.Link;
import hirs.utils.xjc.ObjectFactory;
import hirs.utils.xjc.ResourceCollection;
import hirs.utils.xjc.SoftwareIdentity;
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.Element;
import org.w3c.dom.Node;
import javax.json.Json;
import javax.json.JsonException;
import javax.json.JsonObject;
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.XMLStructure;
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.TransformParameterSpec;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
@ -91,6 +94,8 @@ public class SwidTagGateway {
private String timestampFormat;
private String timestampArgument;
private String errorRequiredFields;
private DocumentBuilderFactory dbf;
private DocumentBuilder builder;
/**
* Default constructor initializes jaxbcontext, marshaller, and unmarshaller
@ -107,8 +112,15 @@ public class SwidTagGateway {
timestampFormat = "";
timestampArgument = "";
errorRequiredFields = "";
dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
builder = dbf.newDocumentBuilder();
} catch (JAXBException e) {
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
*/
public void generateSwidTag(final String filename) {
SoftwareIdentity swidTag = null;
Document swidtag = builder.newDocument();
SoftwareIdentity softwareIdentity = null;
try {
InputStream is = new FileInputStream(attributesFile);
JsonReader reader = Json.createReader(is);
JsonObject configProperties = reader.readObject();
reader.close();
//SoftwareIdentity
swidTag = createSwidTag(
softwareIdentity = createSwidTag(
configProperties.getJsonObject(SwidTagConstants.SOFTWARE_IDENTITY));
//Entity
JAXBElement<Entity> entity = objectFactory.createSoftwareIdentityEntity(
createEntity(configProperties.getJsonObject(SwidTagConstants.ENTITY)));
swidTag.getEntityOrEvidenceOrLink().add(entity);
softwareIdentity.getEntityOrEvidenceOrLink().add(entity);
//Link
JAXBElement<Link> link = objectFactory.createSoftwareIdentityLink(
createLink(configProperties.getJsonObject(SwidTagConstants.LINK)));
swidTag.getEntityOrEvidenceOrLink().add(link);
softwareIdentity.getEntityOrEvidenceOrLink().add(link);
//Meta
JAXBElement<SoftwareMeta> meta = objectFactory.createSoftwareIdentityMeta(
createSoftwareMeta(configProperties.getJsonObject(SwidTagConstants.META)));
swidTag.getEntityOrEvidenceOrLink().add(meta);
//Payload
ResourceCollection payload = createPayload(
configProperties.getJsonObject(SwidTagConstants.PAYLOAD));
//Directory
Directory directory = createDirectory(
configProperties.getJsonObject(SwidTagConstants.PAYLOAD)
.getJsonObject(SwidTagConstants.DIRECTORY));
softwareIdentity.getEntityOrEvidenceOrLink().add(meta);
swidtag = convertToDocument(objectFactory.createSoftwareIdentity(softwareIdentity));
Element rootElement = swidtag.getDocumentElement();
//File
hirs.utils.xjc.File file = createFile(
configProperties.getJsonObject(SwidTagConstants.PAYLOAD)
.getJsonObject(SwidTagConstants.DIRECTORY)
.getJsonObject(SwidTagConstants.FILE));
//Nest File in Directory in Payload
directory.getDirectoryOrFile().add(file);
payload.getDirectoryOrFileOrProcess().add(directory);
JAXBElement<FilesystemItem> jaxbFile = objectFactory.createDirectoryFile(file);
Document fileDoc = convertToDocument(jaxbFile);
//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 =
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
if (errorRequiredFields.isEmpty()) {
Document signedSoftwareIdentity = signXMLDocument(
objectFactory.createSoftwareIdentity(swidTag));
Document signedSoftwareIdentity = signXMLDocument(swidtag);
writeSwidTagFile(signedSoftwareIdentity, filename);
} else {
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.
* Current assumptions: digest method SHA256, signature method SHA256, enveloped signature
* This method converts a JAXBElement object generated from the hirs.utils.xjc package into
* 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;
try {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
marshaller.marshal(swidTag, doc);
} catch (ParserConfigurationException e) {
System.out.println("Error instantiating Document object for parsing swidtag: "
+ e.getMessage());
System.exit(1);
doc = builder.newDocument();
marshaller.marshal(element, doc);
} catch (JAXBException e) {
System.out.println("Error while marshaling swidtag: " + e.getMessage());
e.printStackTrace();
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");
List xmlObjectList = null;
String signatureId = null;