From 34aa54100e7402658ff08a4050bd1286f24ad657 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Fri, 30 Jun 2023 09:03:19 -0400 Subject: [PATCH] This push resolves the parsing issue of swidtags that may not meet the validation based on an attribute not matching the spec. --- .../rim/BaseReferenceManifest.java | 237 +++++------------- .../SupplyChainValidationServiceImpl.java | 3 +- .../portal/PersistenceJPAConfig.java | 7 + .../hirs/utils/swid/SwidTagConstants.java | 1 + 4 files changed, 78 insertions(+), 170 deletions(-) diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/rim/BaseReferenceManifest.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/rim/BaseReferenceManifest.java index 365fca10..391fe8ae 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/rim/BaseReferenceManifest.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/rim/BaseReferenceManifest.java @@ -4,13 +4,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import hirs.attestationca.persist.entity.userdefined.ReferenceManifest; import hirs.utils.SwidResource; import hirs.utils.swid.SwidTagConstants; -import hirs.utils.xjc.Link; -import hirs.utils.xjc.SoftwareIdentity; -import hirs.utils.xjc.SoftwareMeta; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.xml.bind.JAXBContext; -import jakarta.xml.bind.JAXBElement; import jakarta.xml.bind.JAXBException; import jakarta.xml.bind.UnmarshalException; import jakarta.xml.bind.Unmarshaller; @@ -24,7 +20,6 @@ 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; @@ -42,7 +37,6 @@ import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Base64; import java.util.List; -import java.util.Map; /** * @@ -100,28 +94,31 @@ public class BaseReferenceManifest extends ReferenceManifest { /** * Support constructor for the RIM object. * - * @param fileName - string representation of the uploaded file. * @param rimBytes - the file content of the uploaded file. * @throws IOException - thrown if the file is invalid. */ - public BaseReferenceManifest(final String fileName, final byte[] rimBytes) throws IOException { - this(rimBytes); - this.setFileName(fileName); + public BaseReferenceManifest(final byte[] rimBytes) throws IOException { + this("", rimBytes); } /** * Main constructor for the RIM object. This takes in a byte array of a * valid swidtag file and parses the information. * + * @param fileName - string representation of the uploaded file. * @param rimBytes byte array representation of the RIM * @throws IOException if unable to unmarshal the string */ @SuppressWarnings("checkstyle:AvoidInlineConditionals") - public BaseReferenceManifest(final byte[] rimBytes) throws IOException { + public BaseReferenceManifest(final String fileName, final byte[] rimBytes) throws IOException { super(rimBytes); this.setRimType(BASE_RIM); - this.setFileName(""); - SoftwareIdentity si = validateSwidTag(new ByteArrayInputStream(rimBytes)); + this.setFileName(fileName); + Document document = unmarshallSwidTag(new ByteArrayInputStream(rimBytes)); + Element softwareIdentity; + Element meta; + Element entity; + Element link; MessageDigest digest = null; this.base64Hash = ""; @@ -134,54 +131,22 @@ public class BaseReferenceManifest extends ReferenceManifest { } // begin parsing valid swid tag - if (si != null) { - setTagId(si.getTagId()); - this.swidName = si.getName(); - this.swidCorpus = si.isCorpus() ? 1 : 0; - this.setSwidPatch(si.isPatch()); - this.setSwidSupplemental(si.isSupplemental()); - this.setSwidVersion(si.getVersion()); - if (si.getTagVersion() != null) { - this.setSwidTagVersion(si.getTagVersion().toString()); - } + 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); + setTagId(softwareIdentity.getAttribute(SwidTagConstants.TAGID)); + this.swidName = softwareIdentity.getAttribute(SwidTagConstants.NAME); + this.swidCorpus = Boolean.parseBoolean(softwareIdentity.getAttribute(SwidTagConstants.CORPUS)) ? 1 : 0; + this.setSwidPatch(Boolean.parseBoolean(softwareIdentity.getAttribute(SwidTagConstants.PATCH))); + this.setSwidSupplemental(Boolean.parseBoolean(softwareIdentity.getAttribute(SwidTagConstants.SUPPLEMENTAL))); + this.setSwidVersion(softwareIdentity.getAttribute(SwidTagConstants.VERSION)); + this.setSwidTagVersion(softwareIdentity.getAttribute(SwidTagConstants.TAGVERSION)); - for (Object object : si.getEntityOrEvidenceOrLink()) { - if (object instanceof JAXBElement) { - JAXBElement element = (JAXBElement) object; - String elementName = element.getName().getLocalPart(); - switch (elementName) { - case "Meta": - parseSoftwareMeta((SoftwareMeta) element.getValue()); - break; - case "Entity": - hirs.utils.xjc.Entity entity - = (hirs.utils.xjc.Entity) element.getValue(); - if (entity != null) { - this.entityName = entity.getName(); - this.entityRegId = entity.getRegid(); - StringBuilder sb = new StringBuilder(); - for (String role : entity.getRole()) { - sb.append(String.format("%s%n", role)); - } - this.entityRole = sb.toString(); - this.entityThumbprint = entity.getThumbprint(); - } - break; - case "Link": - Link link - = (Link) element.getValue(); - if (link != null) { - this.linkHref = link.getHref(); - this.linkRel = link.getRel(); - } - break; - case "Payload": - case "Signature": - // left blank for a followup issue enhancement - default: - } - } - } + parseSoftwareMeta(meta); + parseEntity(entity); + parseLink(link); } } @@ -191,75 +156,57 @@ public class BaseReferenceManifest extends ReferenceManifest { * * @param softwareMeta The object to parse. */ - private void parseSoftwareMeta(final SoftwareMeta softwareMeta) { + private void parseSoftwareMeta(final Element softwareMeta) { if (softwareMeta != null) { - for (Map.Entry entry - : softwareMeta.getOtherAttributes().entrySet()) { - switch (entry.getKey().getLocalPart()) { - case "colloquialVersion": - this.colloquialVersion = entry.getValue(); - break; - case "product": - this.product = entry.getValue(); - break; - case "revision": - this.revision = entry.getValue(); - break; - case "edition": - this.edition = entry.getValue(); - break; - case "rimLinkHash": - this.rimLinkHash = entry.getValue(); - break; - case "bindingSpec": - this.bindingSpec = entry.getValue(); - break; - case "bindingSpecVersion": - this.bindingSpecVersion = entry.getValue(); - break; - case "platformManufacturerId": - this.setPlatformManufacturerId(entry.getValue()); - break; - case "platformModel": - this.setPlatformModel(entry.getValue()); - break; - case "platformManufacturerStr": - this.setPlatformManufacturer(entry.getValue()); - break; - case "platformVersion": - this.platformVersion = entry.getValue(); - break; - case "payloadType": - this.payloadType = entry.getValue(); - break; - case "pcURIGlobal": - this.pcURIGlobal = entry.getValue(); - break; - case "pcURILocal": - this.pcURILocal = entry.getValue(); - break; - default: - } - } + this.colloquialVersion = softwareMeta.getAttribute(SwidTagConstants._COLLOQUIAL_VERSION_STR); + this.product = softwareMeta.getAttribute(SwidTagConstants._PRODUCT_STR); + this.revision = softwareMeta.getAttribute(SwidTagConstants._REVISION_STR); + this.edition = softwareMeta.getAttribute(SwidTagConstants._EDITION_STR); + this.rimLinkHash = softwareMeta.getAttribute(SwidTagConstants._RIM_LINK_HASH_STR); + this.bindingSpec = softwareMeta.getAttribute(SwidTagConstants._BINDING_SPEC_STR); + this.bindingSpecVersion = softwareMeta.getAttribute(SwidTagConstants._BINDING_SPEC_VERSION_STR); + this.setPlatformManufacturerId(softwareMeta.getAttribute(SwidTagConstants._PLATFORM_MANUFACTURER_ID_STR)); + this.setPlatformManufacturer(softwareMeta.getAttribute(SwidTagConstants._PLATFORM_MANUFACTURER_STR)); + this.setPlatformModel(softwareMeta.getAttribute(SwidTagConstants._PLATFORM_MODEL_STR)); + this.platformVersion = softwareMeta.getAttribute(SwidTagConstants._PLATFORM_VERSION_STR); + this.payloadType = softwareMeta.getAttribute(SwidTagConstants._PAYLOAD_TYPE_STR); + this.pcURIGlobal = softwareMeta.getAttribute(SwidTagConstants._PC_URI_GLOBAL_STR); + this.pcURILocal = softwareMeta.getAttribute(SwidTagConstants._PC_URI_LOCAL_STR); + } else { + log.warn("SoftwareMeta Tag not found."); } } /** - * This method and code is pulled and adopted from the TCG Tool. Since this - * is taking in an file stored in memory through http, this was changed from - * a file to a stream as the input. + * This is a helper method that parses the Entity tag and stores the + * information in the class fields. * - * @param fileStream stream of the swidtag file. - * @return a {@link SoftwareIdentity} object - * @throws IOException Thrown by the unmarhsallSwidTag method. + * @param entity The object to parse. */ - private SoftwareIdentity validateSwidTag(final InputStream fileStream) throws IOException { - JAXBElement jaxbe = unmarshallSwidTag(fileStream); - SoftwareIdentity swidTag = (SoftwareIdentity) jaxbe.getValue(); + private void parseEntity(final Element entity) { + if (entity != null) { + this.entityName = entity.getAttribute(SwidTagConstants.NAME); + this.entityRegId = entity.getAttribute(SwidTagConstants.REGID); + this.entityRole = entity.getAttribute(SwidTagConstants.ROLE); + this.entityThumbprint = entity.getAttribute(SwidTagConstants.THUMBPRINT); + } else { + log.warn("Entity Tag not found."); + } + } - log.debug(String.format("SWID Tag found: %nname: %s;%ntagId: %s%n%s", - swidTag.getName(), swidTag.getTagId(), SCHEMA_STATEMENT)); - return swidTag; + /** + * This is a helper method that parses the Link tag and stores the + * information in the class fields. + * + * @param link The object to parse. + */ + private void parseLink(final Element link) { + if (link != null) { + this.linkHref = link.getAttribute(SwidTagConstants.HREF); + this.linkRel = link.getAttribute(SwidTagConstants.REL); + } else { + log.warn("Link Tag not found."); + } } /** @@ -326,58 +273,12 @@ public class BaseReferenceManifest extends ReferenceManifest { return validHashes; } - /** - * This method unmarshalls the swidtag found at [path] and validates it - * according to the schema. - * - * @param stream to the input swidtag - * @return the SoftwareIdentity element at the root of the swidtag - * @throws IOException if the swidtag cannot be unmarshalled or validated - */ - private JAXBElement unmarshallSwidTag(final InputStream stream) throws IOException { - JAXBElement jaxbe = null; - Schema schema; - Unmarshaller unmarshaller = null; - - try { - SchemaFactory schemaFactory = SchemaFactory.newInstance(SCHEMA_LANGUAGE); - schema = schemaFactory.newSchema(new StreamSource(stream)); - if (jaxbContext == null) { - jaxbContext = JAXBContext.newInstance(SCHEMA_PACKAGE); - } - unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setSchema(schema); - jaxbe = (JAXBElement) unmarshaller.unmarshal(stream); - } catch (UnmarshalException umEx) { - log.error(String.format("Error validating swidtag file!%n%s%n%s", - umEx.getMessage(), umEx.toString())); - 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) { - for (StackTraceElement ste : jaxEx.getStackTrace()) { - log.error(ste.toString()); - } - } - - if (jaxbe != null) { - return jaxbe; - } else { - throw new IOException("Invalid Base RIM, swidtag format expected."); - } - } - /** * This method unmarshalls the swidtag found at [path] into a Document object * and validates it according to the schema. * * @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 + * @return the Document element at the root of the swidtag */ private Document unmarshallSwidTag(final ByteArrayInputStream byteArrayInputStream) { InputStream is = null; diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/SupplyChainValidationServiceImpl.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/SupplyChainValidationServiceImpl.java index 30543763..d9785bb5 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/SupplyChainValidationServiceImpl.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/SupplyChainValidationServiceImpl.java @@ -117,8 +117,7 @@ public class SupplyChainValidationServiceImpl extends DefaultDbService caCreds = new HashSet<>(); for (CertificateAuthorityCredential cred : certAuthsWithMatchingIssuer) { caCreds.add(cred); - if ((cred.getHolderIssuer() != null && cred.getSubject() != null) - && !BouncyCastleUtils.x500NameCompare(cred.getHolderIssuer(), + if (!BouncyCastleUtils.x500NameCompare(cred.getHolderIssuer(), cred.getSubject())) { caCreds.addAll(getCaChainRec(cred, queriedOrganizations)); } diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/PersistenceJPAConfig.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/PersistenceJPAConfig.java index 15074321..f8b06efe 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/PersistenceJPAConfig.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/PersistenceJPAConfig.java @@ -26,6 +26,13 @@ import javax.sql.DataSource; import java.security.cert.X509Certificate; import java.util.Properties; +/** + * Provides application context configuration for the Attestation Certificate + * Authority application. The properties are processed in order and as such, the + * last property file read in will override properties that may had already been + * defined previously. In other words, the 'defaults.properties' file provides a + * basic standard of properties that can be overrode by the + */ @Log4j2 @Configuration @EnableWebMvc diff --git a/HIRS_Utils/src/main/java/hirs/utils/swid/SwidTagConstants.java b/HIRS_Utils/src/main/java/hirs/utils/swid/SwidTagConstants.java index dd6b2916..c259a56c 100644 --- a/HIRS_Utils/src/main/java/hirs/utils/swid/SwidTagConstants.java +++ b/HIRS_Utils/src/main/java/hirs/utils/swid/SwidTagConstants.java @@ -79,6 +79,7 @@ public class SwidTagConstants { public static final String N8060_PFX = "n8060"; public static final String RIM_PFX = "rim"; + public static final String FX_SEPARATOR = ":"; public static final String RFC3852_PFX = "rcf3852"; public static final String RFC3339_PFX = "rcf3339";