This push fixes the issues with parsing the file tag and getting the

hash value for the support rim and as well for getting the collapsible
file link on the details page to operate. [no ci]
This commit is contained in:
Cyrus 2023-06-29 07:49:32 -04:00
parent 27e55ab2c7
commit 67681c0227
6 changed files with 291 additions and 73 deletions

View File

@ -2,15 +2,9 @@ package hirs.attestationca.persist.entity.userdefined.rim;
import com.fasterxml.jackson.annotation.JsonIgnore;
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
import hirs.attestationca.persist.service.ReferenceManifestServiceImpl;
import hirs.utils.SwidResource;
import hirs.utils.xjc.BaseElement;
import hirs.utils.xjc.Directory;
import hirs.utils.xjc.File;
import hirs.utils.xjc.FilesystemItem;
import hirs.utils.swid.SwidTagConstants;
import hirs.utils.xjc.Link;
import hirs.utils.xjc.Meta;
import hirs.utils.xjc.ResourceCollection;
import hirs.utils.xjc.SoftwareIdentity;
import hirs.utils.xjc.SoftwareMeta;
import jakarta.persistence.Column;
@ -25,9 +19,21 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@ -170,8 +176,6 @@ public class BaseReferenceManifest extends ReferenceManifest {
}
break;
case "Payload":
parseResource((ResourceCollection) element.getValue());
break;
case "Signature":
// left blank for a followup issue enhancement
default:
@ -259,35 +263,67 @@ public class BaseReferenceManifest extends ReferenceManifest {
}
/**
* Helper method that is used to parse a specific element of the SwidTag
* based on an already established and stored byte array.
* 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.
*
* @param elementName string of an xml tag in the file.
* @return the object value of the element, if it exists
*/
private BaseElement getBaseElementFromBytes(final String elementName) {
BaseElement baseElement = null;
private Element getDirectoryTag() {
return getDirectoryTag(new ByteArrayInputStream(getRimBytes()));
}
if (getRimBytes() != null && elementName != null) {
try {
SoftwareIdentity si = validateSwidTag(new ByteArrayInputStream(getRimBytes()));
JAXBElement element;
for (Object object : si.getEntityOrEvidenceOrLink()) {
if (object instanceof JAXBElement) {
element = (JAXBElement) object;
if (element.getName().getLocalPart().equals(elementName)) {
// found the element
baseElement = (BaseElement) element.getValue();
}
}
}
/**
* 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.
*
* @param byteArrayInputStream the location of the file to be validated
*/
private Element getDirectoryTag(final ByteArrayInputStream byteArrayInputStream) {
Document document = unmarshallSwidTag(byteArrayInputStream);
Element softwareIdentity =
(Element) document.getElementsByTagName("SoftwareIdentity").item(0);
if (softwareIdentity != null) {
Element directory = (Element) document.getElementsByTagName("Directory").item(0);
} catch (IOException ioEx) {
log.error("Failed to parse Swid Tag bytes.", ioEx);
}
return directory;
} else {
log.error("Invalid xml for validation, please verify ");
}
return baseElement;
return null;
}
/**
* This method iterates over the list of File elements under the directory. *
*/
public List<SwidResource> getFileResources() {
return getFileResources(getRimBytes());
}
/**
* This method iterates over the list of File elements under the directory.
*
* @param rimBytes the bytes to find the files
*
*/
public List<SwidResource> getFileResources(final byte[] rimBytes) {
Element directoryTag = getDirectoryTag(new ByteArrayInputStream(rimBytes));
List<SwidResource> validHashes = new ArrayList<>();
NodeList fileNodeList = directoryTag.getChildNodes();
Element file = null;
SwidResource swidResource = null;
for (int i = 0; i < fileNodeList.getLength(); i++) {
file = (Element) fileNodeList.item(i);
swidResource = new SwidResource();
swidResource.setName(file.getAttribute(SwidTagConstants.NAME));
swidResource.setSize(file.getAttribute(SwidTagConstants.SIZE));
swidResource.setHashValue(file.getAttribute(SwidTagConstants._SHA256_HASH.getPrefix() + ":"
+ SwidTagConstants._SHA256_HASH.getLocalPart()));
validHashes.add(swidResource);
}
return validHashes;
}
/**
@ -301,13 +337,15 @@ public class BaseReferenceManifest extends ReferenceManifest {
private JAXBElement unmarshallSwidTag(final InputStream stream) throws IOException {
JAXBElement jaxbe = null;
Schema schema;
Unmarshaller unmarshaller = null;
try {
schema = ReferenceManifestServiceImpl.getSchemaObject();
SchemaFactory schemaFactory = SchemaFactory.newInstance(SCHEMA_LANGUAGE);
schema = schemaFactory.newSchema(new StreamSource(stream));
if (jaxbContext == null) {
jaxbContext = JAXBContext.newInstance(SCHEMA_PACKAGE);
}
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(schema);
jaxbe = (JAXBElement) unmarshaller.unmarshal(stream);
} catch (UnmarshalException umEx) {
@ -316,6 +354,8 @@ public class BaseReferenceManifest extends ReferenceManifest {
for (StackTraceElement ste : umEx.getStackTrace()) {
log.error(ste.toString());
}
} catch (SAXException e) {
System.out.println("Error setting schema for validation!");
} catch (IllegalArgumentException iaEx) {
log.error("Input file empty.");
} catch (JAXBException jaxEx) {
@ -332,51 +372,79 @@ public class BaseReferenceManifest extends ReferenceManifest {
}
/**
* Default method for parsing the payload element.
* This method unmarshalls the swidtag found at [path] into a Document object
* and validates it according to the schema.
*
* @return a collection of payload objects.
* @param byteArrayInputStream to the input swidtag
* @return the SoftwareIdentity element at the root of the swidtag
* @throws IOException if the swidtag cannot be unmarshalled or validated
*/
public final List<SwidResource> parseResource() {
return parseResource((ResourceCollection) this.getBaseElementFromBytes("Payload"));
private Document unmarshallSwidTag(final ByteArrayInputStream byteArrayInputStream) {
InputStream is = null;
Document document = null;
Unmarshaller unmarshaller = null;
try {
document = removeXMLWhitespace(byteArrayInputStream);
SchemaFactory schemaFactory = SchemaFactory.newInstance(SCHEMA_LANGUAGE);
is = getClass().getClassLoader().getResourceAsStream(SwidTagConstants.SCHEMA_URL);
Schema schema = schemaFactory.newSchema(new StreamSource(is));
if (jaxbContext == null) {
jaxbContext = JAXBContext.newInstance(SCHEMA_PACKAGE);
}
unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(schema);
unmarshaller.unmarshal(document);
} catch (IOException e) {
log.error(e.getMessage());
} catch (SAXException e) {
log.error("Error setting schema for validation!");
} catch (UnmarshalException e) {
log.error("Error validating swidtag file!");
} catch (IllegalArgumentException e) {
log.error("Input file empty.");
} catch (JAXBException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
System.out.println("Error closing input stream");
}
}
}
return document;
}
/**
* This method parses the payload method of a {@link ResourceCollection}.
* This method strips all whitespace from an xml file, including indents and spaces
* added for human-readability.
*
* @param rc Resource Collection object.
* @return a collection of payload objects.
* @param byteArrayInputStream to the xml file
* @return Document object without whitespace
*/
public final List<SwidResource> parseResource(final ResourceCollection rc) {
List<SwidResource> resources = new ArrayList<>();
log.error("Parsing stuff");
try {
if (rc != null) {
for (Meta meta : rc.getDirectoryOrFileOrProcess()) {
if (meta instanceof Directory) {
Directory directory = (Directory) meta;
for (FilesystemItem fsi : directory.getDirectoryOrFile()) {
if (fsi != null) {
resources.add(new SwidResource(
(File) fsi, null));
} else {
log.error("fsi is negative");
}
}
} else if (meta instanceof File) {
resources.add(new SwidResource((File) meta, null));
}
}
} else {
log.error("ResourceCollection is negative");
private Document removeXMLWhitespace(final ByteArrayInputStream byteArrayInputStream) throws IOException {
TransformerFactory tf = TransformerFactory.newInstance();
Source source = new StreamSource(
getClass().getClassLoader().getResourceAsStream("identity_transform.xslt"));
Document document = null;
if (byteArrayInputStream.available() > 0) {
try {
Transformer transformer = tf.newTransformer(source);
DOMResult result = new DOMResult();
transformer.transform(new StreamSource(byteArrayInputStream), result);
document = (Document) result.getNode();
} catch (TransformerConfigurationException tcEx) {
log.error("Error configuring transformer!");
} catch (TransformerException tEx) {
log.error("Error transforming input!");
}
} catch (ClassCastException ccEx) {
log.error(ccEx);
log.error("At this time, the code does not support the "
+ "particular formatting of this SwidTag's Payload.");
} else {
throw new IOException("Input file is empty!");
}
return resources;
return document;
}
@Override

View File

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="no" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

View File

@ -245,7 +245,7 @@ public class ReferenceManifestDetailsPageController extends PageController<Refer
}
data.put("rimType", baseRim.getRimType());
List<SwidResource> resources = baseRim.parseResource();
List<SwidResource> resources = baseRim.getFileResources();
TCGEventLog logProcessor = null;
List<ReferenceManifest> subManifests;
SupportReferenceManifest support = null;

View File

@ -27,7 +27,8 @@ public final class BouncyCastleUtils {
*/
public static boolean x500NameCompare(final String nameValue1, final String nameValue2) {
if (nameValue1 == null || nameValue2 == null) {
throw new IllegalArgumentException("Provided DN string is null.");
log.error("Provided DN string is null.");
return true;
}
boolean result = false;

View File

@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import hirs.utils.digest.DigestAlgorithm;
import hirs.utils.xjc.File;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.xml.namespace.QName;
@ -18,9 +19,10 @@ import java.util.Map;
public class SwidResource {
@Getter
private String name, size;
@Setter
private String name, size, hashValue;
@Getter
private String rimFormat, rimType, rimUriGlobal, hashValue;
private String rimFormat, rimType, rimUriGlobal;
// private TpmWhiteListBaseline tpmWhiteList;
private DigestAlgorithm digest = DigestAlgorithm.SHA1;
@Getter

View File

@ -0,0 +1,137 @@
package hirs.utils.swid;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
/**
* This class contains the String constants that are referenced by the gateway
* class. It is expected that member properties of this class will expand as
* more functionality is added to SwidTagGateway.
*/
public class SwidTagConstants {
public static final String DEFAULT_KEYSTORE_FILE = "keystore.jks";//"/opt/hirs/rimtool/keystore.jks";
public static final String DEFAULT_KEYSTORE_PASSWORD = "password";
public static final String DEFAULT_PRIVATE_KEY_ALIAS = "1";
public static final String DEFAULT_ATTRIBUTES_FILE = "/opt/hirs/rimtool/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_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 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 TCG_EVENTLOG_ASSERTION = "TCG_EventLog_Assertion";
public static final String TPM_PCR_ASSERTION = "TPM_PCR_Assertion";
public static final String SUPPORT_RIM_FORMAT_MISSING = "supportRIMFormat missing";
public static final String SUPPORT_RIM_URI_GLOBAL = "supportRIMURIGlobal";
public static final String DATETIME = "dateTime";
public static final String NIST_NS = "http://csrc.nist.gov/ns/swid/2015-extensions/1.0";
public static final String TCG_NS = "https://trustedcomputinggroup.org/wp-content/uploads/TCG_RIM_Model";
public static final String RFC3852_NS = "https://www.ietf.org/rfc/rfc3852.txt";
public static final String RFC3339_NS = "https://www.ietf.org/rfc/rfc3339.txt";
public static final String N8060_PFX = "n8060";
public static final String RIM_PFX = "rim";
public static final String RFC3852_PFX = "rcf3852";
public static final String RFC3339_PFX = "rcf3339";
public static final QName _SHA256_HASH = new QName(
"http://www.w3.org/2001/04/xmlenc#sha256", HASH, "SHA256");
public static final QName _COLLOQUIAL_VERSION = new QName(
NIST_NS, COLLOQUIAL_VERSION, N8060_PFX);
public static final QName _EDITION = new QName(
NIST_NS, EDITION, N8060_PFX);
public static final QName _PRODUCT = new QName(
NIST_NS, PRODUCT, N8060_PFX);
public static final QName _REVISION = new QName(
NIST_NS, REVISION, N8060_PFX);
public static final QName _PAYLOAD_TYPE = new QName(
TCG_NS, PAYLOAD_TYPE, RIM_PFX);
public static final QName _PLATFORM_MANUFACTURER_STR = new QName(
TCG_NS, PLATFORM_MANUFACTURER_STR, RIM_PFX);
public static final QName _PLATFORM_MANUFACTURER_ID = new QName(
TCG_NS, PLATFORM_MANUFACTURER_ID, RIM_PFX);
public static final QName _PLATFORM_MODEL = new QName(
TCG_NS, PLATFORM_MODEL, RIM_PFX);
public static final QName _PLATFORM_VERSION = new QName(
TCG_NS, PLATFORM_VERSION, RIM_PFX);
public static final QName _FIRMWARE_MANUFACTURER_STR = new QName(
TCG_NS, FIRMWARE_MANUFACTURER_STR, RIM_PFX);
public static final QName _FIRMWARE_MANUFACTURER_ID = new QName(
TCG_NS, FIRMWARE_MANUFACTURER_ID, RIM_PFX);
public static final QName _FIRMWARE_MODEL = new QName(
TCG_NS, FIRMWARE_MODEL, RIM_PFX);
public static final QName _FIRMWARE_VERSION = new QName(
TCG_NS, FIRMWARE_VERSION, RIM_PFX);
public static final QName _BINDING_SPEC = new QName(
TCG_NS, BINDING_SPEC, RIM_PFX);
public static final QName _BINDING_SPEC_VERSION = new QName(
TCG_NS, BINDING_SPEC_VERSION, RIM_PFX);
public static final QName _PC_URI_LOCAL = new QName(
TCG_NS, PC_URI_LOCAL, RIM_PFX);
public static final QName _PC_URI_GLOBAL = new QName(
TCG_NS, PC_URI_GLOBAL, RIM_PFX);
public static final QName _RIM_LINK_HASH = new QName(
TCG_NS, RIM_LINK_HASH, RIM_PFX);
public static final QName _SUPPORT_RIM_TYPE = new QName(
TCG_NS, SUPPORT_RIM_TYPE, RIM_PFX);
public static final QName _SUPPORT_RIM_FORMAT = new QName(
TCG_NS, SUPPORT_RIM_FORMAT, RIM_PFX);
public static final QName _SUPPORT_RIM_URI_GLOBAL = new QName(
TCG_NS, SUPPORT_RIM_URI_GLOBAL, RIM_PFX);
public static final QName _N8060_ENVVARPREFIX = new QName(
NIST_NS, "envVarPrefix", N8060_PFX);
public static final QName _N8060_ENVVARSUFFIX = new QName(
NIST_NS, "envVarSuffix", N8060_PFX);
public static final QName _N8060_PATHSEPARATOR = new QName(
NIST_NS, "pathSeparator", N8060_PFX);
public static final String CA_ISSUERS = "1.3.6.1.5.5.7.48.2";
}