From 19aa3c27a1e889bdf36cf9fc41a220480c821560 Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Thu, 11 Mar 2021 10:55:22 -0500 Subject: [PATCH 1/4] initial commit with the structures that are to be set up --- .../src/main/java/hirs/persist/ReferenceManifestSelector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HIRS_Utils/src/main/java/hirs/persist/ReferenceManifestSelector.java b/HIRS_Utils/src/main/java/hirs/persist/ReferenceManifestSelector.java index 4b6ae6dd..3b363e35 100644 --- a/HIRS_Utils/src/main/java/hirs/persist/ReferenceManifestSelector.java +++ b/HIRS_Utils/src/main/java/hirs/persist/ReferenceManifestSelector.java @@ -22,7 +22,7 @@ import java.util.UUID; * with a {@link ReferenceManifestManager}. To make use of this object, * use (some ReferenceManifest).select(ReferenceManifestManager). * - * @param the type of Reference Integrity Manifest that will be retrived. + * @param the type of Reference Integrity Manifest that will be retrieved. */ public abstract class ReferenceManifestSelector { /** From accbc422e794c93d1673c3b8e28536b186dacb1e Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Thu, 11 Mar 2021 10:56:19 -0500 Subject: [PATCH 2/4] This adds the additional classes --- .../data/persist/ReferenceDigestRecord.java | 101 +++++++++ .../data/persist/ReferenceDigestValue.java | 79 +++++++ .../persist/DBReferenceDigestManager.java | 64 ++++++ .../hirs/persist/ReferenceDigestManager.java | 44 ++++ .../hirs/persist/ReferenceDigestSelector.java | 209 ++++++++++++++++++ 5 files changed, 497 insertions(+) create mode 100644 HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java create mode 100644 HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java create mode 100644 HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java create mode 100644 HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java create mode 100644 HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestSelector.java diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java new file mode 100644 index 00000000..3a2e4b1c --- /dev/null +++ b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java @@ -0,0 +1,101 @@ +package hirs.data.persist; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.ArrayList; +import java.util.List; + +/** + * This class will represent an entry a table that'll be associated + * with the manufacturer and model with all digest values, + * Event Type, index, RIM Tagid. + */ +@Entity +@Table(name = "ReferenceDigestRecord") +public class ReferenceDigestRecord extends ArchivableEntity { + + @Column(nullable = false) + private String manufacturer; + @Column(nullable = false) + private String model; + @Column(columnDefinition = "blob", nullable = false) + private byte[] valueBlob; + + // NOTE: when this works, and do a show tables to give to Lawrence + private List associatedDigests = new ArrayList<>(); + + /** + * Default Constructor. + */ + protected ReferenceDigestRecord() { + super(); + this.manufacturer = null; + this.model = null; + this.valueBlob = null; + } + + /** + * Default constructor with parameters. + * @param manufacturer device manufacturer + * @param model device model + * @param valueBlob the data values of the event. + */ + public ReferenceDigestRecord(final String manufacturer, + final String model, + final byte[] valueBlob) { + this.manufacturer = manufacturer; + this.model = model; + this.valueBlob = valueBlob.clone(); + } + + /** + * Getter for the manufacturer associated. + * @return the string of the manufacturer + */ + public String getManufacturer() { + return manufacturer; + } + + /** + * Setter for the manufacturer associated. + * @param manufacturer the string of the manufacturer + */ + public void setManufacturer(final String manufacturer) { + this.manufacturer = manufacturer; + } + + /** + * Getter for the model associated. + * @return the string of the model + */ + public String getModel() { + return model; + } + + /** + * Setter for the model associated. + * @param model the string of the model + */ + public void setModel(final String model) { + this.model = model; + } + + /** + * Getter for the byte array of event values. + * @return a clone of the byte array + */ + public byte[] getValueBlob() { + return valueBlob.clone(); + } + + /** + * Setter for the byte array of values. + * @param valueBlob non-null array. + */ + public void setValueBlob(final byte[] valueBlob) { + if (valueBlob != null) { + this.valueBlob = valueBlob.clone(); + } + } +} diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java new file mode 100644 index 00000000..aa095815 --- /dev/null +++ b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java @@ -0,0 +1,79 @@ +package hirs.data.persist; + +import java.util.Arrays; +import java.util.Objects; + +/** + * This class represents that actual entry in the Support RIM. + * Digest Value, Event Type, index, RIM Tagid + */ +public class ReferenceDigestValue { + + private int eventNumber; + private String digestValue; + private String eventType; + private String tagId; + private boolean matchFail; + private byte[] chunk; + + /** + * Default Constructor. + */ + public ReferenceDigestValue() { + + } + + /** + * Default Constructor with a parameter for the data. + * @param data event data + */ + public ReferenceDigestValue(final byte[] data) { + this.chunk = data.clone(); + int i = 0; + this.eventNumber = data[i]; + this.digestValue = String.valueOf(data[++i]); + this.eventType = String.valueOf(data[++i]); + this.tagId = String.valueOf(data[++i]); + this.matchFail = false; + } + + /** + * Default Constructor with parameters for all associated data. + * @param eventNumber the event number + * @param digestValue the key digest value + * @param eventType the event type + * @param tagId the tag id + * @param matchFail the status of the baseline check + */ + public ReferenceDigestValue(final int eventNumber, final String digestValue, + final String eventType, final String tagId, final boolean matchFail) { + this.eventNumber = eventNumber; + this.digestValue = digestValue; + this.eventType = eventType; + this.tagId = tagId; + this.matchFail = matchFail; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + ReferenceDigestValue that = (ReferenceDigestValue) obj; + return eventNumber == that.eventNumber && matchFail == that.matchFail + && Objects.equals(digestValue, that.digestValue) + && Objects.equals(eventType, that.eventType) + && Objects.equals(tagId, that.tagId) && Arrays.equals(chunk, that.chunk); + } + + @Override + @SuppressWarnings("MagicNumber") + public int hashCode() { + int result = Objects.hash(eventNumber, digestValue, eventType, tagId, matchFail); + result = 31 * result + Arrays.hashCode(chunk); + return result; + } +} diff --git a/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java b/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java new file mode 100644 index 00000000..057db95f --- /dev/null +++ b/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java @@ -0,0 +1,64 @@ +package hirs.persist; + +import hirs.data.persist.ReferenceDigestRecord; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.hibernate.SessionFactory; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * This class is used to persist and retrieve {@link hirs.data.persist.ReferenceDigestRecord}s into + * and from the database. + */ +public class DBReferenceDigestManager extends DBManager + implements ReferenceDigestManager { + + private static final Logger LOGGER = LogManager.getLogger(DBReferenceDigestManager.class); + + /** + * Default Constructor. + * + * @param sessionFactory session factory used to access database connections + */ + public DBReferenceDigestManager(final SessionFactory sessionFactory) { + super(ReferenceDigestRecord.class, sessionFactory); + } + + /** + * This method does not need to be used directly as it is used by + * {@link ReferenceManifestSelector}'s get* methods. Regardless, it may be + * used to retrieve ReferenceManifest by other code in this package, given a + * configured ReferenceManifestSelector. + * + * @param referenceDigestSelector a configured + * {@link ReferenceDigestSelector} to use for querying + * @return the resulting set of ReferenceManifest, possibly empty + */ + @Override + @SuppressWarnings("unchecked") + public Set get( + final ReferenceDigestSelector referenceDigestSelector) { + LOGGER.info("Getting the full set of Reference Digest Records."); + return new HashSet<>( + (List) getWithCriteria( + referenceDigestSelector.getReferenceDigestClass(), + Collections.singleton(referenceDigestSelector.getCriterion()) + ) + ); + } + + /** + * Remove a ReferenceDigestRecord from the database. + * + * @param referenceDigestRecord the referenceDigestRecord to delete + * @return true if deletion was successful, false otherwise + */ + public boolean deleteReferenceManifest(final ReferenceDigestRecord referenceDigestRecord) { + LOGGER.info(String.format("Deleting reference to %s/%s", + referenceDigestRecord.getManufacturer(), referenceDigestRecord.getModel())); + return delete(referenceDigestRecord); + } +} diff --git a/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java b/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java new file mode 100644 index 00000000..cbd0d03b --- /dev/null +++ b/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java @@ -0,0 +1,44 @@ + +package hirs.persist; + +import hirs.data.persist.ReferenceDigestRecord; + +import java.util.Set; + +/** + * This class facilitates the persistence of {@link hirs.data.persist.ReferenceDigestRecord}s + * including storage, retrieval, and deletion. + */ +public interface ReferenceDigestManager extends OrderedListQuerier { + + /** + * Persists a new Reference Digest. + * + * @param referenceDigestRecord the ReferenceDigestRecord + * @return the persisted ReferenceDigestRecord + */ + ReferenceDigestRecord save(ReferenceDigestRecord referenceDigestRecord); + + /** + * Updates an existing ReferenceDigestRecord. + * @param referenceDigestRecord the Reference Digest update + */ + void update(ReferenceDigestRecord referenceDigestRecord); + + /** + * Retrieve Reference Digest according to the given {@link ReferenceDigestSelector}. + * + * @param the type of reference digest that will be retrieved + * @param referenceDigestSelector a {@link ReferenceDigestSelector} to use for querying + * @return a Set of matching RIMs, which may be empty + */ + Set get(ReferenceDigestSelector referenceDigestSelector); + + /** + * Delete the given RIM. + * + * @param referenceDigestRecord the RIM to delete + * @return true if the deletion succeeded, false otherwise. + */ + boolean delete(ReferenceDigestRecord referenceDigestRecord); +} diff --git a/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestSelector.java b/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestSelector.java new file mode 100644 index 00000000..99e09891 --- /dev/null +++ b/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestSelector.java @@ -0,0 +1,209 @@ +package hirs.persist; + +import com.google.common.base.Preconditions; +import hirs.data.persist.ReferenceDigestRecord; +import hirs.data.persist.certificate.Certificate; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.criterion.Conjunction; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Restrictions; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * This class is used to select one or many RIMs in conjunction + * with a {@link ReferenceDigestManager}. To make use of this object, + * use (some ReferenceManifest).select(ReferenceManifestManager). + * + * @param the type of Reference Integrity Manifest that will be retrieved. + */ +public abstract class ReferenceDigestSelector { + /** + * String representing the database field for the manufacturer. + */ + public static final String PLATFORM_MANUFACTURER = "manufacturer"; + /** + * String representing the database field for the manufacturer id. + */ + public static final String PLATFORM_MODEL = "model"; + + private final ReferenceDigestManager referenceDigestManager; + private final Class referenceTypeClass; + + private final Map fieldValueSelections; + private boolean excludeArchivedRims; + + /** + * Default Constructor. + * + * @param referenceDigestManager the RIM manager to be used to retrieve RIMs + * @param referenceTypeClass the type of Reference Manifest to process. + */ + public ReferenceDigestSelector(final ReferenceDigestManager referenceDigestManager, + final Class referenceTypeClass) { + this(referenceDigestManager, referenceTypeClass, true); + } + + /** + * Standard Constructor for the Selector. + * + * @param referenceDigestManager the RIM manager to be used to retrieve RIMs + * @param referenceTypeClass the type of Reference Manifest to process. + * @param excludeArchivedRims true if excluding archived RIMs + */ + public ReferenceDigestSelector(final ReferenceDigestManager referenceDigestManager, + final Class referenceTypeClass, + final boolean excludeArchivedRims) { + Preconditions.checkArgument( + referenceDigestManager != null, + "reference manifest manager cannot be null" + ); + + Preconditions.checkArgument( + referenceTypeClass != null, + "type cannot be null" + ); + + this.referenceDigestManager = referenceDigestManager; + this.referenceTypeClass = referenceTypeClass; + this.excludeArchivedRims = excludeArchivedRims; + this.fieldValueSelections = new HashMap<>(); + } + + /** + * Specify the entity id that rims must have to be considered as matching. + * + * @param manufacturer the UUID to query + * @return this instance (for chaining further calls) + */ + public ReferenceDigestSelector byManufacturer(final String manufacturer) { + setFieldValue(PLATFORM_MANUFACTURER, manufacturer); + return this; + } + + /** + * Specify the hash code of the bytes that rim must match. + * + * @param model the hash code of the bytes to query for + * @return this instance (for chaining further calls) + */ + public ReferenceDigestSelector byModel(final String model) { + setFieldValue(PLATFORM_MODEL, model); + return this; + } + + /** + * Set a field name and value to match. + * + * @param name the field name to query + * @param value the value to query + */ + protected void setFieldValue(final String name, final Object value) { + Object valueToAssign = value; + + Preconditions.checkArgument( + value != null, + String.format("field value (%s) cannot be null.", name) + ); + + if (value instanceof String) { + Preconditions.checkArgument( + StringUtils.isNotEmpty((String) value), + "field value cannot be empty." + ); + } + + if (value instanceof byte[]) { + byte[] valueBytes = (byte[]) value; + + Preconditions.checkArgument( + ArrayUtils.isNotEmpty(valueBytes), + String.format("field value (%s) cannot be empty.", name) + ); + + valueToAssign = Arrays.copyOf(valueBytes, valueBytes.length); + } + + fieldValueSelections.put(name, valueToAssign); + } + + /** + * Retrieve the result set as a single + * {@link hirs.data.persist.ReferenceDigestRecord}. This method is best used + * when selecting on a unique attribute. If the result set contains more + * than one RIM, one is chosen arbitrarily and returned. If no matching RIMs + * are found, this method returns null. + * + * @return a matching digest record or null if none is found + */ + public T getDigestRecord() { + Set rims = execute(); + if (rims.isEmpty()) { + return null; + } + return rims.iterator().next(); + } + + /** + * Retrieve the result set as a set of + * {@link hirs.data.persist.ReferenceDigestRecord}s. This method is best used + * when selecting on non-unique attributes. ReferenceManifests are populated + * into the set in no specific order. If no matching certificates are found, + * the returned Set will be empty. + * + * @return a Set of matching RIMs, possibly empty + */ + public Set getDigestRecords() { + return Collections.unmodifiableSet(new HashSet<>(execute())); + } + + /** + * Construct the criterion that can be used to query for rims matching the + * configuration of this {@link hirs.persist.ReferenceDigestSelector}. + * + * @return a Criterion that can be used to query for rims matching the + * configuration of this instance + */ + Criterion getCriterion() { + Conjunction conj = new Conjunction(); + + for (Map.Entry fieldValueEntry : fieldValueSelections.entrySet()) { + conj.add(Restrictions.eq(fieldValueEntry.getKey(), fieldValueEntry.getValue())); + } + + if (this.excludeArchivedRims) { + conj.add(Restrictions.isNull(Certificate.ARCHIVE_FIELD)); + } + + return conj; + } + + /** + * @return the rim class that this instance will query + */ + public Class getReferenceDigestClass() { + return this.referenceTypeClass; + } + + // construct and execute query + private Set execute() { + Set results = this.referenceDigestManager.get(this); + return results; + } + + /** + * Configures the selector to query for archived and unarchived rims. + * + * @return the selector + */ + public ReferenceDigestSelector includeArchived() { + this.excludeArchivedRims = false; + return this; + } +} From 53cb300063041b9c04e7aa319699e73e39b788fe Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Wed, 17 Mar 2021 10:23:08 -0400 Subject: [PATCH 3/4] This is an initial commit with changes that add new classes for digest reference matching. --- ...stractAttestationCertificateAuthority.java | 17 +- ...tionCertificateAuthorityConfiguration.java | 12 + ...estfulAttestationCertificateAuthority.java | 5 +- ...ctAttestationCertificateAuthorityTest.java | 2 +- .../persistence/PersistenceConfiguration.java | 11 + .../data/persist/ReferenceDigestRecord.java | 82 ++++++- .../data/persist/ReferenceDigestValue.java | 5 + .../persist/DBReferenceDigestManager.java | 71 ++++-- .../persist/PersistenceConfiguration.java | 13 ++ .../hirs/persist/ReferenceDigestManager.java | 49 ++-- .../hirs/persist/ReferenceDigestSelector.java | 209 ------------------ 11 files changed, 214 insertions(+), 262 deletions(-) delete mode 100644 HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestSelector.java diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index d2366bee..c0be411f 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -12,6 +12,7 @@ import hirs.data.persist.BaseReferenceManifest; import hirs.data.persist.EventLogMeasurements; import hirs.data.persist.Device; import hirs.data.persist.DeviceInfoReport; +import hirs.data.persist.ReferenceDigestRecord; import hirs.data.persist.ReferenceManifest; import hirs.data.persist.SupplyChainPolicy; import hirs.data.persist.SupportReferenceManifest; @@ -28,6 +29,7 @@ import hirs.data.persist.certificate.IssuedAttestationCertificate; import hirs.data.persist.certificate.PlatformCredential; import hirs.data.service.DeviceRegister; import hirs.persist.CertificateManager; +import hirs.persist.ReferenceDigestManager; import hirs.persist.ReferenceManifestManager; import hirs.persist.DBManager; import hirs.persist.DeviceManager; @@ -169,6 +171,7 @@ public abstract class AbstractAttestationCertificateAuthority private final DeviceRegister deviceRegister; private final DeviceManager deviceManager; private final DBManager tpm2ProvisionerStateDBManager; + private final ReferenceDigestManager referenceDigestManager; private String tpmQuoteHash = ""; private String tpmQuoteSignature = ""; private String pcrValues; @@ -185,6 +188,7 @@ public abstract class AbstractAttestationCertificateAuthority * @param validDays the number of days issued certs are valid * @param deviceManager the device manager * @param tpm2ProvisionerStateDBManager the DBManager for persisting provisioner state + * @param referenceDigestManager the reference digest manager */ @SuppressWarnings("checkstyle:parameternumber") public AbstractAttestationCertificateAuthority( @@ -195,7 +199,8 @@ public abstract class AbstractAttestationCertificateAuthority final ReferenceManifestManager referenceManifestManager, final DeviceRegister deviceRegister, final int validDays, final DeviceManager deviceManager, - final DBManager tpm2ProvisionerStateDBManager) { + final DBManager tpm2ProvisionerStateDBManager, + final ReferenceDigestManager referenceDigestManager) { this.supplyChainValidationService = supplyChainValidationService; this.privateKey = privateKey; this.acaCertificate = acaCertificate; @@ -206,6 +211,7 @@ public abstract class AbstractAttestationCertificateAuthority this.validDays = validDays; this.deviceManager = deviceManager; this.tpm2ProvisionerStateDBManager = tpm2ProvisionerStateDBManager; + this.referenceDigestManager = referenceDigestManager; } /** @@ -841,6 +847,15 @@ public abstract class AbstractAttestationCertificateAuthority support.resetCreateTime(); this.referenceManifestManager.update(support); } + + // this is where we update or create the log + ReferenceDigestRecord rdr = new ReferenceDigestRecord(support, + hw.getManufacturer(), hw.getProductName()); + + + referenceDigestManager.saveRecord(rdr); + + } catch (IOException ioEx) { LOG.error(ioEx); } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/configuration/AttestationCertificateAuthorityConfiguration.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/configuration/AttestationCertificateAuthorityConfiguration.java index 48f07eea..f207eeb0 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/configuration/AttestationCertificateAuthorityConfiguration.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/configuration/AttestationCertificateAuthorityConfiguration.java @@ -1,5 +1,7 @@ package hirs.attestationca.configuration; +import hirs.persist.DBReferenceDigestManager; +import hirs.persist.ReferenceDigestManager; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bouncycastle.jce.provider.BouncyCastleProvider; @@ -252,6 +254,16 @@ public class AttestationCertificateAuthorityConfiguration extends WebMvcConfigur return new DBReferenceManifestManager(sessionFactory.getObject()); } + /** + * Creates a {@link ReferenceDigestManager} ready to use. + * + * @return {@link ReferenceDigestManager} + */ + @Bean + public ReferenceDigestManager referenceDigestManager() { + return new DBReferenceDigestManager(sessionFactory.getObject()); + } + @Override public void addResourceHandlers(final ResourceHandlerRegistry resourceHandlerRegistry) { resourceHandlerRegistry.addResourceHandler("/client-files/**") diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/rest/RestfulAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/rest/RestfulAttestationCertificateAuthority.java index 254cfd3a..6b48e8bd 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/rest/RestfulAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/rest/RestfulAttestationCertificateAuthority.java @@ -1,6 +1,7 @@ package hirs.attestationca.rest; import hirs.persist.DBManager; +import hirs.persist.ReferenceDigestManager; import hirs.persist.TPM2ProvisionerState; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -42,6 +43,7 @@ public class RestfulAttestationCertificateAuthority * @param validDays the number of days issued certs are valid * @param deviceManager the device manager * @param tpm2ProvisionerStateDBManager the DBManager for persisting provisioner state + * @param referenceDigestManager the reference digest manager */ @SuppressWarnings({ "checkstyle:parameternumber" }) @Autowired @@ -54,11 +56,12 @@ public class RestfulAttestationCertificateAuthority final DeviceRegister deviceRegister, final DeviceManager deviceManager, final DBManager tpm2ProvisionerStateDBManager, + final ReferenceDigestManager referenceDigestManager, @Value("${aca.certificates.validity}") final int validDays) { super(supplyChainValidationService, privateKey, acaCertificate, structConverter, certificateManager, referenceManifestManager, deviceRegister, validDays, deviceManager, - tpm2ProvisionerStateDBManager); + tpm2ProvisionerStateDBManager, referenceDigestManager); } /* diff --git a/HIRS_AttestationCA/src/test/java/hirs/attestationca/AbstractAttestationCertificateAuthorityTest.java b/HIRS_AttestationCA/src/test/java/hirs/attestationca/AbstractAttestationCertificateAuthorityTest.java index 5e5ade23..1ba111f1 100644 --- a/HIRS_AttestationCA/src/test/java/hirs/attestationca/AbstractAttestationCertificateAuthorityTest.java +++ b/HIRS_AttestationCA/src/test/java/hirs/attestationca/AbstractAttestationCertificateAuthorityTest.java @@ -133,7 +133,7 @@ public class AbstractAttestationCertificateAuthorityTest { public void setup() { aca = new AbstractAttestationCertificateAuthority(null, keyPair.getPrivate(), null, null, null, null, null, 1, - null, null) { + null, null, null) { }; } diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/persistence/PersistenceConfiguration.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/persistence/PersistenceConfiguration.java index 78caad4a..75556c06 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/persistence/PersistenceConfiguration.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/persistence/PersistenceConfiguration.java @@ -5,6 +5,7 @@ import hirs.persist.AppraiserManager; import hirs.persist.CrudManager; import hirs.persist.DBAppraiserManager; import hirs.persist.DBCertificateManager; +import hirs.persist.DBReferenceDigestManager; import hirs.persist.DBReferenceManifestManager; import hirs.persist.DBDeviceGroupManager; import hirs.persist.DBDeviceManager; @@ -71,6 +72,16 @@ public class PersistenceConfiguration { return new DBReferenceManifestManager(sessionFactory.getObject()); } + /** + * Creates a {@link DBReferenceDigestManager} ready to use. + * + * @return {@link DBReferenceDigestManager} + */ + @Bean + public DBReferenceDigestManager referenceDigestManager() { + return new DBReferenceDigestManager(sessionFactory.getObject()); + } + /** * Creates a {@link AppraiserManager} ready to use. * diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java index 3a2e4b1c..3a8a5286 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java @@ -1,10 +1,11 @@ package hirs.data.persist; +import org.bouncycastle.util.Arrays; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; -import java.util.ArrayList; -import java.util.List; +import java.util.UUID; /** * This class will represent an entry a table that'll be associated @@ -15,38 +16,89 @@ import java.util.List; @Table(name = "ReferenceDigestRecord") public class ReferenceDigestRecord extends ArchivableEntity { + @Column + private UUID supportRim; @Column(nullable = false) private String manufacturer; @Column(nullable = false) private String model; - @Column(columnDefinition = "blob", nullable = false) + @Column(columnDefinition = "blob", nullable = true) private byte[] valueBlob; - - // NOTE: when this works, and do a show tables to give to Lawrence - private List associatedDigests = new ArrayList<>(); + @Column + private boolean supportLoaded; /** * Default Constructor. */ protected ReferenceDigestRecord() { super(); - this.manufacturer = null; - this.model = null; + // I wonder if this will throw and error + this.supportRim = UUID.randomUUID(); + this.manufacturer = ""; + this.model = ""; this.valueBlob = null; + this.supportLoaded = false; } /** * Default constructor with parameters. + * @param supportRim link to the source of data * @param manufacturer device manufacturer * @param model device model * @param valueBlob the data values of the event. */ - public ReferenceDigestRecord(final String manufacturer, + public ReferenceDigestRecord(final UUID supportRim, + final String manufacturer, final String model, final byte[] valueBlob) { + super(); + // need to put up nullable entries + this.supportRim = supportRim; this.manufacturer = manufacturer; this.model = model; - this.valueBlob = valueBlob.clone(); + this.valueBlob = Arrays.clone(valueBlob); + } + + /** + * Default constructor with parameters specitic to a RIM object. + * @param referenceManifest rim object to use. + * @param manufacturer device manufacturer + * @param model device model + */ + public ReferenceDigestRecord(final ReferenceManifest referenceManifest, + final String manufacturer, + final String model) { + super(); + if (referenceManifest instanceof SupportReferenceManifest) { + this.supportRim = referenceManifest.getId(); + this.supportLoaded = true; + SupportReferenceManifest srm = (SupportReferenceManifest) referenceManifest; + this.valueBlob = Arrays.clone(srm.getRimBytes()); + } else if (referenceManifest != null) { + // the assumption is that there is a support RIM. + this.supportRim = referenceManifest.getAssociatedRim(); + // I will just test for loaded and if true but blob is empty, pull + // that information later and update the object + } + + this.manufacturer = manufacturer; + this.model = model; + } + + /** + * Getter for the linked source for the data. + * @return UUID of the source + */ + public UUID getSupportRim() { + return supportRim; + } + + /** + * Setter for the linked source for the data. + * @param supportRim UUID of the source + */ + public void setSupportRim(final UUID supportRim) { + this.supportRim = supportRim; } /** @@ -98,4 +150,14 @@ public class ReferenceDigestRecord extends ArchivableEntity { this.valueBlob = valueBlob.clone(); } } + + /** + * The string value representative of this class. + * @return manufacturer and model for this record + */ + @Override + public String toString() { + return String.format("%s%n%s -> %s", + super.toString(), this.manufacturer, this.model); + } } diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java index aa095815..322171ac 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java @@ -23,6 +23,10 @@ public class ReferenceDigestValue { } + /** + * Maybe add the match fail status to the device object: eventNumber, digest value + */ + /** * Default Constructor with a parameter for the data. * @param data event data @@ -31,6 +35,7 @@ public class ReferenceDigestValue { this.chunk = data.clone(); int i = 0; this.eventNumber = data[i]; + // look to using the Digest class this.digestValue = String.valueOf(data[++i]); this.eventType = String.valueOf(data[++i]); this.tagId = String.valueOf(data[++i]); diff --git a/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java b/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java index 057db95f..f692f2d3 100644 --- a/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java +++ b/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java @@ -4,10 +4,8 @@ import hirs.data.persist.ReferenceDigestRecord; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.hibernate.SessionFactory; -import java.util.Collections; -import java.util.HashSet; + import java.util.List; -import java.util.Set; /** * This class is used to persist and retrieve {@link hirs.data.persist.ReferenceDigestRecord}s into @@ -27,27 +25,51 @@ public class DBReferenceDigestManager extends DBManager super(ReferenceDigestRecord.class, sessionFactory); } - /** - * This method does not need to be used directly as it is used by - * {@link ReferenceManifestSelector}'s get* methods. Regardless, it may be - * used to retrieve ReferenceManifest by other code in this package, given a - * configured ReferenceManifestSelector. - * - * @param referenceDigestSelector a configured - * {@link ReferenceDigestSelector} to use for querying - * @return the resulting set of ReferenceManifest, possibly empty - */ @Override - @SuppressWarnings("unchecked") - public Set get( - final ReferenceDigestSelector referenceDigestSelector) { - LOGGER.info("Getting the full set of Reference Digest Records."); - return new HashSet<>( - (List) getWithCriteria( - referenceDigestSelector.getReferenceDigestClass(), - Collections.singleton(referenceDigestSelector.getCriterion()) - ) - ); + public ReferenceDigestRecord saveRecord(final ReferenceDigestRecord referenceDigestRecord) { + LOGGER.debug("saving state: {}", referenceDigestRecord); + try { + return save(referenceDigestRecord); + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } + } + + @Override + public ReferenceDigestRecord getRecord(final ReferenceDigestRecord referenceDigestRecord) { + LOGGER.debug("Getting record for {}", referenceDigestRecord); + if (referenceDigestRecord == null) { + LOGGER.error("null referenceDigestRecord argument"); + throw new NullPointerException("null referenceDigestRecord"); + } + return null; + } + + @Override + public List getRecordsByManufacturer( + final ReferenceDigestRecord referenceDigestRecord) { + LOGGER.debug("Getting records by manufacturer for {}", referenceDigestRecord); + if (referenceDigestRecord == null) { + LOGGER.error("null referenceDigestRecord argument"); + throw new NullPointerException("null referenceDigestRecord"); + } + return null; + } + + @Override + public List getRecordsByModel( + final ReferenceDigestRecord referenceDigestRecord) { + LOGGER.debug("Getting records by model for {}", referenceDigestRecord); + if (referenceDigestRecord == null) { + LOGGER.error("null referenceDigestRecord argument"); + throw new NullPointerException("null referenceDigestRecord"); + } + return null; + } + + @Override + public boolean updateRecord(final ReferenceDigestRecord referenceDigestRecord) { + return false; } /** @@ -56,7 +78,8 @@ public class DBReferenceDigestManager extends DBManager * @param referenceDigestRecord the referenceDigestRecord to delete * @return true if deletion was successful, false otherwise */ - public boolean deleteReferenceManifest(final ReferenceDigestRecord referenceDigestRecord) { + @Override + public boolean deleteRecord(final ReferenceDigestRecord referenceDigestRecord) { LOGGER.info(String.format("Deleting reference to %s/%s", referenceDigestRecord.getManufacturer(), referenceDigestRecord.getModel())); return delete(referenceDigestRecord); diff --git a/HIRS_Utils/src/main/java/hirs/persist/PersistenceConfiguration.java b/HIRS_Utils/src/main/java/hirs/persist/PersistenceConfiguration.java index 4c1da996..bd6f19f4 100644 --- a/HIRS_Utils/src/main/java/hirs/persist/PersistenceConfiguration.java +++ b/HIRS_Utils/src/main/java/hirs/persist/PersistenceConfiguration.java @@ -154,6 +154,19 @@ public class PersistenceConfiguration { return manager; } + /** + * Creates a {@link ReferenceDigestManager} ready to use. + * + * @return {@link ReferenceDigestManager} + */ + @Bean + public ReferenceDigestManager referenceDigestManager() { + DBReferenceDigestManager manager + = new DBReferenceDigestManager(sessionFactory.getObject()); + setDbManagerRetrySettings(manager); + return manager; + } + /** * Creates a {@link DeviceStateManager} ready to use. * diff --git a/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java b/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java index cbd0d03b..aef06272 100644 --- a/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java +++ b/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java @@ -3,13 +3,13 @@ package hirs.persist; import hirs.data.persist.ReferenceDigestRecord; -import java.util.Set; +import java.util.List; /** * This class facilitates the persistence of {@link hirs.data.persist.ReferenceDigestRecord}s * including storage, retrieval, and deletion. */ -public interface ReferenceDigestManager extends OrderedListQuerier { +public interface ReferenceDigestManager { /** * Persists a new Reference Digest. @@ -17,28 +17,45 @@ public interface ReferenceDigestManager extends OrderedListQuerier getRecordsByManufacturer( + ReferenceDigestRecord referenceDigestRecord); + + /** + * Persists a new Reference Digest. + * + * @param referenceDigestRecord the ReferenceDigestRecord + * @return the persisted ReferenceDigestRecord + */ + List getRecordsByModel(ReferenceDigestRecord referenceDigestRecord); /** * Updates an existing ReferenceDigestRecord. * @param referenceDigestRecord the Reference Digest update + * @return status of successful update */ - void update(ReferenceDigestRecord referenceDigestRecord); + boolean updateRecord(ReferenceDigestRecord referenceDigestRecord); /** - * Retrieve Reference Digest according to the given {@link ReferenceDigestSelector}. + * Delete the given record. * - * @param the type of reference digest that will be retrieved - * @param referenceDigestSelector a {@link ReferenceDigestSelector} to use for querying - * @return a Set of matching RIMs, which may be empty - */ - Set get(ReferenceDigestSelector referenceDigestSelector); - - /** - * Delete the given RIM. - * - * @param referenceDigestRecord the RIM to delete + * @param referenceDigestRecord the digest record delete * @return true if the deletion succeeded, false otherwise. */ - boolean delete(ReferenceDigestRecord referenceDigestRecord); + boolean deleteRecord(ReferenceDigestRecord referenceDigestRecord); } diff --git a/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestSelector.java b/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestSelector.java deleted file mode 100644 index 99e09891..00000000 --- a/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestSelector.java +++ /dev/null @@ -1,209 +0,0 @@ -package hirs.persist; - -import com.google.common.base.Preconditions; -import hirs.data.persist.ReferenceDigestRecord; -import hirs.data.persist.certificate.Certificate; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.StringUtils; -import org.hibernate.criterion.Conjunction; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Restrictions; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * This class is used to select one or many RIMs in conjunction - * with a {@link ReferenceDigestManager}. To make use of this object, - * use (some ReferenceManifest).select(ReferenceManifestManager). - * - * @param the type of Reference Integrity Manifest that will be retrieved. - */ -public abstract class ReferenceDigestSelector { - /** - * String representing the database field for the manufacturer. - */ - public static final String PLATFORM_MANUFACTURER = "manufacturer"; - /** - * String representing the database field for the manufacturer id. - */ - public static final String PLATFORM_MODEL = "model"; - - private final ReferenceDigestManager referenceDigestManager; - private final Class referenceTypeClass; - - private final Map fieldValueSelections; - private boolean excludeArchivedRims; - - /** - * Default Constructor. - * - * @param referenceDigestManager the RIM manager to be used to retrieve RIMs - * @param referenceTypeClass the type of Reference Manifest to process. - */ - public ReferenceDigestSelector(final ReferenceDigestManager referenceDigestManager, - final Class referenceTypeClass) { - this(referenceDigestManager, referenceTypeClass, true); - } - - /** - * Standard Constructor for the Selector. - * - * @param referenceDigestManager the RIM manager to be used to retrieve RIMs - * @param referenceTypeClass the type of Reference Manifest to process. - * @param excludeArchivedRims true if excluding archived RIMs - */ - public ReferenceDigestSelector(final ReferenceDigestManager referenceDigestManager, - final Class referenceTypeClass, - final boolean excludeArchivedRims) { - Preconditions.checkArgument( - referenceDigestManager != null, - "reference manifest manager cannot be null" - ); - - Preconditions.checkArgument( - referenceTypeClass != null, - "type cannot be null" - ); - - this.referenceDigestManager = referenceDigestManager; - this.referenceTypeClass = referenceTypeClass; - this.excludeArchivedRims = excludeArchivedRims; - this.fieldValueSelections = new HashMap<>(); - } - - /** - * Specify the entity id that rims must have to be considered as matching. - * - * @param manufacturer the UUID to query - * @return this instance (for chaining further calls) - */ - public ReferenceDigestSelector byManufacturer(final String manufacturer) { - setFieldValue(PLATFORM_MANUFACTURER, manufacturer); - return this; - } - - /** - * Specify the hash code of the bytes that rim must match. - * - * @param model the hash code of the bytes to query for - * @return this instance (for chaining further calls) - */ - public ReferenceDigestSelector byModel(final String model) { - setFieldValue(PLATFORM_MODEL, model); - return this; - } - - /** - * Set a field name and value to match. - * - * @param name the field name to query - * @param value the value to query - */ - protected void setFieldValue(final String name, final Object value) { - Object valueToAssign = value; - - Preconditions.checkArgument( - value != null, - String.format("field value (%s) cannot be null.", name) - ); - - if (value instanceof String) { - Preconditions.checkArgument( - StringUtils.isNotEmpty((String) value), - "field value cannot be empty." - ); - } - - if (value instanceof byte[]) { - byte[] valueBytes = (byte[]) value; - - Preconditions.checkArgument( - ArrayUtils.isNotEmpty(valueBytes), - String.format("field value (%s) cannot be empty.", name) - ); - - valueToAssign = Arrays.copyOf(valueBytes, valueBytes.length); - } - - fieldValueSelections.put(name, valueToAssign); - } - - /** - * Retrieve the result set as a single - * {@link hirs.data.persist.ReferenceDigestRecord}. This method is best used - * when selecting on a unique attribute. If the result set contains more - * than one RIM, one is chosen arbitrarily and returned. If no matching RIMs - * are found, this method returns null. - * - * @return a matching digest record or null if none is found - */ - public T getDigestRecord() { - Set rims = execute(); - if (rims.isEmpty()) { - return null; - } - return rims.iterator().next(); - } - - /** - * Retrieve the result set as a set of - * {@link hirs.data.persist.ReferenceDigestRecord}s. This method is best used - * when selecting on non-unique attributes. ReferenceManifests are populated - * into the set in no specific order. If no matching certificates are found, - * the returned Set will be empty. - * - * @return a Set of matching RIMs, possibly empty - */ - public Set getDigestRecords() { - return Collections.unmodifiableSet(new HashSet<>(execute())); - } - - /** - * Construct the criterion that can be used to query for rims matching the - * configuration of this {@link hirs.persist.ReferenceDigestSelector}. - * - * @return a Criterion that can be used to query for rims matching the - * configuration of this instance - */ - Criterion getCriterion() { - Conjunction conj = new Conjunction(); - - for (Map.Entry fieldValueEntry : fieldValueSelections.entrySet()) { - conj.add(Restrictions.eq(fieldValueEntry.getKey(), fieldValueEntry.getValue())); - } - - if (this.excludeArchivedRims) { - conj.add(Restrictions.isNull(Certificate.ARCHIVE_FIELD)); - } - - return conj; - } - - /** - * @return the rim class that this instance will query - */ - public Class getReferenceDigestClass() { - return this.referenceTypeClass; - } - - // construct and execute query - private Set execute() { - Set results = this.referenceDigestManager.get(this); - return results; - } - - /** - * Configures the selector to query for archived and unarchived rims. - * - * @return the selector - */ - public ReferenceDigestSelector includeArchived() { - this.excludeArchivedRims = false; - return this; - } -} From 108748fb2afe06ed98e39ed04bb11fa4924f668e Mon Sep 17 00:00:00 2001 From: Cyrus <24922493+cyrus-dev@users.noreply.github.com> Date: Fri, 19 Mar 2021 11:01:25 -0400 Subject: [PATCH 4/4] Undid some code and change the Digest Value class into a table in the database. This code then updates those values when a provision is initiated. At this time, that is all it does. --- ...stractAttestationCertificateAuthority.java | 57 ++++-- ...tionCertificateAuthorityConfiguration.java | 32 ++- ...estfulAttestationCertificateAuthority.java | 19 +- ...ctAttestationCertificateAuthorityTest.java | 25 ++- .../persistence/PersistenceConfiguration.java | 15 +- .../data/persist/ReferenceDigestRecord.java | 17 +- .../data/persist/ReferenceDigestValue.java | 152 +++++++++++--- .../persist/DBReferenceDigestManager.java | 156 +++++++++++++- .../hirs/persist/DBReferenceEventManager.java | 191 ++++++++++++++++++ .../persist/PersistenceConfiguration.java | 13 ++ .../hirs/persist/ReferenceDigestManager.java | 20 +- .../hirs/persist/ReferenceEventManager.java | 66 ++++++ 12 files changed, 664 insertions(+), 99 deletions(-) create mode 100644 HIRS_Utils/src/main/java/hirs/persist/DBReferenceEventManager.java create mode 100644 HIRS_Utils/src/main/java/hirs/persist/ReferenceEventManager.java diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java index c0be411f..8a3361b9 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/AbstractAttestationCertificateAuthority.java @@ -9,30 +9,32 @@ import hirs.attestationca.exceptions.UnexpectedServerException; import hirs.attestationca.service.SupplyChainValidationService; import hirs.data.persist.AppraisalStatus; import hirs.data.persist.BaseReferenceManifest; -import hirs.data.persist.EventLogMeasurements; import hirs.data.persist.Device; import hirs.data.persist.DeviceInfoReport; +import hirs.data.persist.EventLogMeasurements; import hirs.data.persist.ReferenceDigestRecord; +import hirs.data.persist.ReferenceDigestValue; import hirs.data.persist.ReferenceManifest; import hirs.data.persist.SupplyChainPolicy; +import hirs.data.persist.SupplyChainValidationSummary; import hirs.data.persist.SupportReferenceManifest; import hirs.data.persist.SwidResource; -import hirs.data.persist.info.FirmwareInfo; -import hirs.data.persist.info.HardwareInfo; -import hirs.data.persist.info.NetworkInfo; -import hirs.data.persist.info.OSInfo; -import hirs.data.persist.SupplyChainValidationSummary; -import hirs.data.persist.info.TPMInfo; import hirs.data.persist.certificate.Certificate; import hirs.data.persist.certificate.EndorsementCredential; import hirs.data.persist.certificate.IssuedAttestationCertificate; import hirs.data.persist.certificate.PlatformCredential; +import hirs.data.persist.info.FirmwareInfo; +import hirs.data.persist.info.HardwareInfo; +import hirs.data.persist.info.NetworkInfo; +import hirs.data.persist.info.OSInfo; +import hirs.data.persist.info.TPMInfo; import hirs.data.service.DeviceRegister; import hirs.persist.CertificateManager; -import hirs.persist.ReferenceDigestManager; -import hirs.persist.ReferenceManifestManager; import hirs.persist.DBManager; import hirs.persist.DeviceManager; +import hirs.persist.ReferenceDigestManager; +import hirs.persist.ReferenceEventManager; +import hirs.persist.ReferenceManifestManager; import hirs.persist.TPM2ProvisionerState; import hirs.structs.converters.SimpleStructBuilder; import hirs.structs.converters.StructConverter; @@ -44,6 +46,8 @@ import hirs.structs.elements.tpm.IdentityProof; import hirs.structs.elements.tpm.IdentityRequest; import hirs.structs.elements.tpm.SymmetricKey; import hirs.structs.elements.tpm.SymmetricKeyParams; +import hirs.tpm.eventlog.TCGEventLog; +import hirs.tpm.eventlog.TpmPcrEvent; import hirs.utils.HexUtils; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.ArrayUtils; @@ -172,6 +176,7 @@ public abstract class AbstractAttestationCertificateAuthority private final DeviceManager deviceManager; private final DBManager tpm2ProvisionerStateDBManager; private final ReferenceDigestManager referenceDigestManager; + private final ReferenceEventManager referenceEventManager; private String tpmQuoteHash = ""; private String tpmQuoteSignature = ""; private String pcrValues; @@ -189,6 +194,7 @@ public abstract class AbstractAttestationCertificateAuthority * @param deviceManager the device manager * @param tpm2ProvisionerStateDBManager the DBManager for persisting provisioner state * @param referenceDigestManager the reference digest manager + * @param referenceEventManager the reference event manager */ @SuppressWarnings("checkstyle:parameternumber") public AbstractAttestationCertificateAuthority( @@ -200,7 +206,8 @@ public abstract class AbstractAttestationCertificateAuthority final DeviceRegister deviceRegister, final int validDays, final DeviceManager deviceManager, final DBManager tpm2ProvisionerStateDBManager, - final ReferenceDigestManager referenceDigestManager) { + final ReferenceDigestManager referenceDigestManager, + final ReferenceEventManager referenceEventManager) { this.supplyChainValidationService = supplyChainValidationService; this.privateKey = privateKey; this.acaCertificate = acaCertificate; @@ -212,6 +219,7 @@ public abstract class AbstractAttestationCertificateAuthority this.deviceManager = deviceManager; this.tpm2ProvisionerStateDBManager = tpm2ProvisionerStateDBManager; this.referenceDigestManager = referenceDigestManager; + this.referenceEventManager = referenceEventManager; } /** @@ -848,14 +856,33 @@ public abstract class AbstractAttestationCertificateAuthority this.referenceManifestManager.update(support); } - // this is where we update or create the log - ReferenceDigestRecord rdr = new ReferenceDigestRecord(support, + ReferenceDigestRecord dbObj = new ReferenceDigestRecord(support, hw.getManufacturer(), hw.getProductName()); + // this is where we update or create the log + ReferenceDigestRecord rdr = this.referenceDigestManager.getRecord(dbObj); + // Handle baseline digest records + // is there already a baseline? + if (rdr == null) { + // doesn't exist, store + rdr = referenceDigestManager.saveRecord(dbObj); + } // right now this will not deal with updating - referenceDigestManager.saveRecord(rdr); - - + if (this.referenceEventManager.getValuesByRecordId(rdr).isEmpty()) { + try { + TCGEventLog logProcessor = new TCGEventLog(support.getRimBytes()); + ReferenceDigestValue rdv; + for (TpmPcrEvent tpe : logProcessor.getEventList()) { + rdv = new ReferenceDigestValue(rdr.getId(), tpe.getEventNumber(), + tpe.getEventDigestStr(), tpe.getEventTypeStr(), false); + this.referenceEventManager.saveValue(rdv); + } + } catch (CertificateException cEx) { + LOG.error(cEx); + } catch (NoSuchAlgorithmException noSaEx) { + LOG.error(noSaEx); + } + } } catch (IOException ioEx) { LOG.error(ioEx); } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/configuration/AttestationCertificateAuthorityConfiguration.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/configuration/AttestationCertificateAuthorityConfiguration.java index f207eeb0..3b604f71 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/configuration/AttestationCertificateAuthorityConfiguration.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/configuration/AttestationCertificateAuthorityConfiguration.java @@ -1,7 +1,19 @@ package hirs.attestationca.configuration; +import hirs.persist.DBDeviceGroupManager; +import hirs.persist.DBDeviceManager; import hirs.persist.DBReferenceDigestManager; +import hirs.persist.DBReferenceEventManager; +import hirs.persist.DBReferenceManifestManager; +import hirs.persist.DeviceGroupManager; +import hirs.persist.DeviceManager; +import hirs.persist.HibernateConfiguration; import hirs.persist.ReferenceDigestManager; +import hirs.persist.ReferenceEventManager; +import hirs.persist.ReferenceManifestManager; +import hirs.structs.converters.SimpleStructConverter; +import hirs.structs.converters.StructConverter; +import hirs.utils.LogConfigurationUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bouncycastle.jce.provider.BouncyCastleProvider; @@ -33,16 +45,6 @@ import java.security.KeyStoreException; import java.security.PrivateKey; import java.security.Security; import java.security.cert.X509Certificate; -import hirs.persist.DBDeviceGroupManager; -import hirs.persist.DBDeviceManager; -import hirs.persist.DeviceGroupManager; -import hirs.persist.DeviceManager; -import hirs.persist.ReferenceManifestManager; -import hirs.persist.DBReferenceManifestManager; -import hirs.persist.HibernateConfiguration; -import hirs.structs.converters.SimpleStructConverter; -import hirs.structs.converters.StructConverter; -import hirs.utils.LogConfigurationUtil; /** * Provides application context configuration for the Attestation Certificate @@ -264,6 +266,16 @@ public class AttestationCertificateAuthorityConfiguration extends WebMvcConfigur return new DBReferenceDigestManager(sessionFactory.getObject()); } + /** + * Creates a {@link ReferenceEventManager} ready to use. + * + * @return {@link ReferenceEventManager} + */ + @Bean + public ReferenceEventManager referenceEventManager() { + return new DBReferenceEventManager(sessionFactory.getObject()); + } + @Override public void addResourceHandlers(final ResourceHandlerRegistry resourceHandlerRegistry) { resourceHandlerRegistry.addResourceHandler("/client-files/**") diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/rest/RestfulAttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/rest/RestfulAttestationCertificateAuthority.java index 6b48e8bd..4e31119f 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/rest/RestfulAttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/rest/RestfulAttestationCertificateAuthority.java @@ -1,8 +1,16 @@ package hirs.attestationca.rest; +import hirs.attestationca.AbstractAttestationCertificateAuthority; +import hirs.attestationca.service.SupplyChainValidationService; +import hirs.data.service.DeviceRegister; +import hirs.persist.CertificateManager; import hirs.persist.DBManager; +import hirs.persist.DeviceManager; import hirs.persist.ReferenceDigestManager; +import hirs.persist.ReferenceEventManager; +import hirs.persist.ReferenceManifestManager; import hirs.persist.TPM2ProvisionerState; +import hirs.structs.converters.StructConverter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; @@ -14,13 +22,6 @@ import org.springframework.web.bind.annotation.RestController; import java.security.PrivateKey; import java.security.cert.X509Certificate; -import hirs.attestationca.AbstractAttestationCertificateAuthority; -import hirs.attestationca.service.SupplyChainValidationService; -import hirs.data.service.DeviceRegister; -import hirs.persist.CertificateManager; -import hirs.persist.ReferenceManifestManager; -import hirs.persist.DeviceManager; -import hirs.structs.converters.StructConverter; /** * Restful implementation of the {@link hirs.attestationca.AttestationCertificateAuthority}. @@ -44,6 +45,7 @@ public class RestfulAttestationCertificateAuthority * @param deviceManager the device manager * @param tpm2ProvisionerStateDBManager the DBManager for persisting provisioner state * @param referenceDigestManager the reference digest manager + * @param referenceEventManager the reference event manager */ @SuppressWarnings({ "checkstyle:parameternumber" }) @Autowired @@ -57,11 +59,12 @@ public class RestfulAttestationCertificateAuthority final DeviceManager deviceManager, final DBManager tpm2ProvisionerStateDBManager, final ReferenceDigestManager referenceDigestManager, + final ReferenceEventManager referenceEventManager, @Value("${aca.certificates.validity}") final int validDays) { super(supplyChainValidationService, privateKey, acaCertificate, structConverter, certificateManager, referenceManifestManager, deviceRegister, validDays, deviceManager, - tpm2ProvisionerStateDBManager, referenceDigestManager); + tpm2ProvisionerStateDBManager, referenceDigestManager, referenceEventManager); } /* diff --git a/HIRS_AttestationCA/src/test/java/hirs/attestationca/AbstractAttestationCertificateAuthorityTest.java b/HIRS_AttestationCA/src/test/java/hirs/attestationca/AbstractAttestationCertificateAuthorityTest.java index 1ba111f1..d51547a0 100644 --- a/HIRS_AttestationCA/src/test/java/hirs/attestationca/AbstractAttestationCertificateAuthorityTest.java +++ b/HIRS_AttestationCA/src/test/java/hirs/attestationca/AbstractAttestationCertificateAuthorityTest.java @@ -2,6 +2,17 @@ package hirs.attestationca; import com.google.protobuf.ByteString; import hirs.data.persist.certificate.PlatformCredential; +import hirs.structs.converters.StructConverter; +import hirs.structs.elements.aca.SymmetricAttestation; +import hirs.structs.elements.tpm.AsymmetricKeyParams; +import hirs.structs.elements.tpm.AsymmetricPublicKey; +import hirs.structs.elements.tpm.EncryptionScheme; +import hirs.structs.elements.tpm.IdentityProof; +import hirs.structs.elements.tpm.IdentityRequest; +import hirs.structs.elements.tpm.StorePubKey; +import hirs.structs.elements.tpm.SymmetricKey; +import hirs.structs.elements.tpm.SymmetricKeyParams; +import hirs.structs.elements.tpm.SymmetricSubParams; import hirs.utils.HexUtils; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.ArrayUtils; @@ -42,18 +53,6 @@ import java.security.spec.MGF1ParameterSpec; import java.util.Calendar; import java.util.HashSet; -import hirs.structs.converters.StructConverter; -import hirs.structs.elements.aca.SymmetricAttestation; -import hirs.structs.elements.tpm.AsymmetricKeyParams; -import hirs.structs.elements.tpm.AsymmetricPublicKey; -import hirs.structs.elements.tpm.EncryptionScheme; -import hirs.structs.elements.tpm.IdentityProof; -import hirs.structs.elements.tpm.IdentityRequest; -import hirs.structs.elements.tpm.StorePubKey; -import hirs.structs.elements.tpm.SymmetricKey; -import hirs.structs.elements.tpm.SymmetricKeyParams; -import hirs.structs.elements.tpm.SymmetricSubParams; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -133,7 +132,7 @@ public class AbstractAttestationCertificateAuthorityTest { public void setup() { aca = new AbstractAttestationCertificateAuthority(null, keyPair.getPrivate(), null, null, null, null, null, 1, - null, null, null) { + null, null, null, null) { }; } diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/persistence/PersistenceConfiguration.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/persistence/PersistenceConfiguration.java index 75556c06..f051b1a1 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/persistence/PersistenceConfiguration.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/persistence/PersistenceConfiguration.java @@ -5,12 +5,13 @@ import hirs.persist.AppraiserManager; import hirs.persist.CrudManager; import hirs.persist.DBAppraiserManager; import hirs.persist.DBCertificateManager; -import hirs.persist.DBReferenceDigestManager; -import hirs.persist.DBReferenceManifestManager; import hirs.persist.DBDeviceGroupManager; import hirs.persist.DBDeviceManager; import hirs.persist.DBManager; import hirs.persist.DBPolicyManager; +import hirs.persist.DBReferenceDigestManager; +import hirs.persist.DBReferenceEventManager; +import hirs.persist.DBReferenceManifestManager; import hirs.persist.DeviceGroupManager; import hirs.persist.DeviceManager; import hirs.persist.HibernateConfiguration; @@ -82,6 +83,16 @@ public class PersistenceConfiguration { return new DBReferenceDigestManager(sessionFactory.getObject()); } + /** + * Creates a {@link DBReferenceEventManager} ready to use. + * + * @return {@link DBReferenceEventManager} + */ + @Bean + public DBReferenceEventManager referenceEventManager() { + return new DBReferenceEventManager(sessionFactory.getObject()); + } + /** * Creates a {@link AppraiserManager} ready to use. * diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java index 3a8a5286..ee24e340 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestRecord.java @@ -1,6 +1,9 @@ package hirs.data.persist; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.bouncycastle.util.Arrays; +import org.hibernate.annotations.Type; import javax.persistence.Column; import javax.persistence.Entity; @@ -10,12 +13,15 @@ import java.util.UUID; /** * This class will represent an entry a table that'll be associated * with the manufacturer and model with all digest values, - * Event Type, index, RIM Tagid. + * Event Type, index, RIM TagId. */ @Entity @Table(name = "ReferenceDigestRecord") public class ReferenceDigestRecord extends ArchivableEntity { + private static final Logger LOGGER = LogManager.getLogger(ReferenceDigestRecord.class); + + @Type(type = "uuid-char") @Column private UUID supportRim; @Column(nullable = false) @@ -24,20 +30,16 @@ public class ReferenceDigestRecord extends ArchivableEntity { private String model; @Column(columnDefinition = "blob", nullable = true) private byte[] valueBlob; - @Column - private boolean supportLoaded; /** * Default Constructor. */ protected ReferenceDigestRecord() { super(); - // I wonder if this will throw and error this.supportRim = UUID.randomUUID(); this.manufacturer = ""; this.model = ""; this.valueBlob = null; - this.supportLoaded = false; } /** @@ -60,7 +62,7 @@ public class ReferenceDigestRecord extends ArchivableEntity { } /** - * Default constructor with parameters specitic to a RIM object. + * Default constructor with parameters specific to a RIM object. * @param referenceManifest rim object to use. * @param manufacturer device manufacturer * @param model device model @@ -71,7 +73,6 @@ public class ReferenceDigestRecord extends ArchivableEntity { super(); if (referenceManifest instanceof SupportReferenceManifest) { this.supportRim = referenceManifest.getId(); - this.supportLoaded = true; SupportReferenceManifest srm = (SupportReferenceManifest) referenceManifest; this.valueBlob = Arrays.clone(srm.getRimBytes()); } else if (referenceManifest != null) { @@ -157,7 +158,7 @@ public class ReferenceDigestRecord extends ArchivableEntity { */ @Override public String toString() { - return String.format("%s%n%s -> %s", + return String.format("ReferenceDigestRecord: %s%n%s -> %s", super.toString(), this.manufacturer, this.model); } } diff --git a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java index 322171ac..385a05c1 100644 --- a/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java +++ b/HIRS_Utils/src/main/java/hirs/data/persist/ReferenceDigestValue.java @@ -1,61 +1,141 @@ package hirs.data.persist; -import java.util.Arrays; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.hibernate.annotations.Type; + +import javax.persistence.Column; +import javax.persistence.Entity; import java.util.Objects; +import java.util.UUID; /** * This class represents that actual entry in the Support RIM. * Digest Value, Event Type, index, RIM Tagid */ -public class ReferenceDigestValue { +@Entity +public class ReferenceDigestValue extends AbstractEntity { + private static final Logger LOGGER = LogManager.getLogger(ReferenceDigestValue.class); + @Type(type = "uuid-char") + @Column + private UUID digestRecordId; + @Column(nullable = false) private int eventNumber; + @Column(nullable = false) private String digestValue; + @Column(nullable = false) private String eventType; - private String tagId; + @Column(nullable = false) private boolean matchFail; - private byte[] chunk; /** * Default Constructor. */ public ReferenceDigestValue() { - - } - - /** - * Maybe add the match fail status to the device object: eventNumber, digest value - */ - - /** - * Default Constructor with a parameter for the data. - * @param data event data - */ - public ReferenceDigestValue(final byte[] data) { - this.chunk = data.clone(); - int i = 0; - this.eventNumber = data[i]; - // look to using the Digest class - this.digestValue = String.valueOf(data[++i]); - this.eventType = String.valueOf(data[++i]); - this.tagId = String.valueOf(data[++i]); + super(); + this.digestRecordId = UUID.randomUUID(); + this.eventNumber = -1; + this.digestValue = ""; + this.eventType = ""; this.matchFail = false; } /** * Default Constructor with parameters for all associated data. + * @param digestRecordId the UUID of the associated record * @param eventNumber the event number * @param digestValue the key digest value - * @param eventType the event type - * @param tagId the tag id + * @param eventType the event type to store * @param matchFail the status of the baseline check */ - public ReferenceDigestValue(final int eventNumber, final String digestValue, - final String eventType, final String tagId, final boolean matchFail) { + public ReferenceDigestValue(final UUID digestRecordId, final int eventNumber, + final String digestValue, final String eventType, + final boolean matchFail) { + this.digestRecordId = digestRecordId; this.eventNumber = eventNumber; this.digestValue = digestValue; this.eventType = eventType; - this.tagId = tagId; + this.matchFail = matchFail; + } + + /** + * Getter for the digest record UUID. + * @return the string of the UUID + */ + public UUID getDigestRecordId() { + return digestRecordId; + } + + /** + * Setter for the digest record UUID. + * @param digestRecordId the value to store + */ + public void setDigestRecordId(final UUID digestRecordId) { + this.digestRecordId = digestRecordId; + } + + /** + * Getter for the event number. + * @return the stored value + */ + public int getEventNumber() { + return eventNumber; + } + + /** + * Setter for the event number. + * @param eventNumber the value to store + */ + public void setEventNumber(final int eventNumber) { + this.eventNumber = eventNumber; + } + + /** + * Getter for the digest value. + * @return the stored value + */ + public String getDigestValue() { + return digestValue; + } + + /** + * Setter for the digest value. + * @param digestValue the value to store + */ + public void setDigestValue(final String digestValue) { + this.digestValue = digestValue; + } + + /** + * Getter for the event type value. + * @return the stored value + */ + public String getEventType() { + return eventType; + } + + /** + * Setter for the event type. + * @param eventType the value to store + */ + public void setEventType(final String eventType) { + this.eventType = eventType; + } + + /** + * Getter for the status of the match fail. + * @return the value of the status + */ + public boolean isMatchFail() { + return matchFail; + } + + /** + * Setter for the status of a match fail. + * @param matchFail the value to store + */ + public void setMatchFail(final boolean matchFail) { this.matchFail = matchFail; } @@ -70,15 +150,21 @@ public class ReferenceDigestValue { ReferenceDigestValue that = (ReferenceDigestValue) obj; return eventNumber == that.eventNumber && matchFail == that.matchFail && Objects.equals(digestValue, that.digestValue) - && Objects.equals(eventType, that.eventType) - && Objects.equals(tagId, that.tagId) && Arrays.equals(chunk, that.chunk); + && Objects.equals(digestRecordId, that.digestRecordId) + && Objects.equals(eventType, that.eventType); } @Override - @SuppressWarnings("MagicNumber") public int hashCode() { - int result = Objects.hash(eventNumber, digestValue, eventType, tagId, matchFail); - result = 31 * result + Arrays.hashCode(chunk); + int result = Objects.hash(eventNumber, digestValue, digestRecordId, eventType, matchFail); return result; } + + /** + * Returns a string of the classes fields. + * @return a string + */ + public String toString() { + return String.format("ReferenceDigestValue: {%d, %b}", eventNumber, matchFail); + } } diff --git a/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java b/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java index f692f2d3..7ab13f5c 100644 --- a/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java +++ b/HIRS_Utils/src/main/java/hirs/persist/DBReferenceDigestManager.java @@ -3,9 +3,14 @@ package hirs.persist; import hirs.data.persist.ReferenceDigestRecord; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.criterion.Restrictions; +import java.util.ArrayList; import java.util.List; +import java.util.UUID; /** * This class is used to persist and retrieve {@link hirs.data.persist.ReferenceDigestRecord}s into @@ -27,7 +32,7 @@ public class DBReferenceDigestManager extends DBManager @Override public ReferenceDigestRecord saveRecord(final ReferenceDigestRecord referenceDigestRecord) { - LOGGER.debug("saving state: {}", referenceDigestRecord); + LOGGER.debug("saving digest record: {}", referenceDigestRecord); try { return save(referenceDigestRecord); } catch (DBManagerException dbMEx) { @@ -40,9 +45,100 @@ public class DBReferenceDigestManager extends DBManager LOGGER.debug("Getting record for {}", referenceDigestRecord); if (referenceDigestRecord == null) { LOGGER.error("null referenceDigestRecord argument"); - throw new NullPointerException("null referenceDigestRecord"); + return null; } - return null; + + if (referenceDigestRecord.getManufacturer() == null + || referenceDigestRecord.getModel() == null) { + LOGGER.error("No reference to get record from db {}", referenceDigestRecord); + return null; + } + + ReferenceDigestRecord dbRecord = null; + Transaction tx = null; + Session session = getFactory().getCurrentSession(); + try { + LOGGER.debug("retrieving referenceDigestRecord from db"); + tx = session.beginTransaction(); + dbRecord = (ReferenceDigestRecord) session.createCriteria(ReferenceDigestRecord.class) + .add(Restrictions.eq("manufacturer", + referenceDigestRecord.getManufacturer())).add(Restrictions.eq("model", + referenceDigestRecord.getModel())).uniqueResult(); + tx.commit(); + } catch (Exception ex) { + final String msg = "unable to retrieve object"; + LOGGER.error(msg, ex); + if (tx != null) { + LOGGER.debug("rolling back transaction"); + tx.rollback(); + } + throw new DBManagerException(msg, ex); + } + return dbRecord; + } + + @Override + public ReferenceDigestRecord getRecordById(final ReferenceDigestRecord referenceDigestRecord) { + LOGGER.debug("Getting record for {}", referenceDigestRecord); + if (referenceDigestRecord == null) { + LOGGER.error("null referenceDigestRecord argument"); + return null; + } + + if (referenceDigestRecord.getId() == null) { + LOGGER.error("No id to get record from db {}", referenceDigestRecord); + return null; + } + + ReferenceDigestRecord dbRecord; + Transaction tx = null; + Session session = getFactory().getCurrentSession(); + try { + LOGGER.debug("retrieving referenceDigestRecord from db"); + tx = session.beginTransaction(); + dbRecord = (ReferenceDigestRecord) session.createCriteria(ReferenceDigestRecord.class) + .add(Restrictions.eq("id", + referenceDigestRecord.getId())).uniqueResult(); + tx.commit(); + } catch (Exception ex) { + final String msg = "unable to retrieve object"; + LOGGER.error(msg, ex); + if (tx != null) { + LOGGER.debug("rolling back transaction"); + tx.rollback(); + } + throw new DBManagerException(msg, ex); + } + return dbRecord; + } + + @Override + public ReferenceDigestRecord getRecordBySupportId(final UUID supportId) { + LOGGER.debug("Getting record for {}", supportId); + if (supportId == null) { + LOGGER.error("null supportId argument"); + return null; + } + + ReferenceDigestRecord dbRecord; + Transaction tx = null; + Session session = getFactory().getCurrentSession(); + try { + LOGGER.debug("retrieving referenceDigestRecord from db"); + tx = session.beginTransaction(); + dbRecord = (ReferenceDigestRecord) session.createCriteria(ReferenceDigestRecord.class) + .add(Restrictions.eq("supportRim", supportId)).uniqueResult(); + tx.commit(); + } catch (Exception ex) { + final String msg = "unable to retrieve object"; + LOGGER.error(msg, ex); + if (tx != null) { + LOGGER.debug("rolling back transaction"); + tx.rollback(); + } + throw new DBManagerException(msg, ex); + } + return dbRecord; } @Override @@ -53,7 +149,24 @@ public class DBReferenceDigestManager extends DBManager LOGGER.error("null referenceDigestRecord argument"); throw new NullPointerException("null referenceDigestRecord"); } - return null; + if (referenceDigestRecord.getManufacturer() == null) { + LOGGER.error("null referenceDigestRecord manufacturer argument"); + throw new NullPointerException("null referenceDigestRecord manufacturer"); + } + + List dbRecords = new ArrayList<>(); + String manufacturer = referenceDigestRecord.getManufacturer(); + try { + List dbTempList = super.getList(ReferenceDigestRecord.class); + for (ReferenceDigestRecord rdr : dbTempList) { + if (rdr.getManufacturer().equals(manufacturer)) { + dbRecords.add(rdr); + } + } + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } + return dbRecords; } @Override @@ -64,12 +177,33 @@ public class DBReferenceDigestManager extends DBManager LOGGER.error("null referenceDigestRecord argument"); throw new NullPointerException("null referenceDigestRecord"); } - return null; + if (referenceDigestRecord.getModel() == null) { + LOGGER.error("null referenceDigestRecord model argument"); + throw new NullPointerException("null referenceDigestRecord model"); + } + + List dbRecords = new ArrayList<>(); + String model = referenceDigestRecord.getModel(); + try { + List dbTempList = super.getList(ReferenceDigestRecord.class); + for (ReferenceDigestRecord rdr : dbTempList) { + if (rdr.getModel().equals(model)) { + dbRecords.add(rdr); + } + } + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } + return dbRecords; } @Override - public boolean updateRecord(final ReferenceDigestRecord referenceDigestRecord) { - return false; + public void updateRecord(final ReferenceDigestRecord referenceDigestRecord) { + try { + super.update(referenceDigestRecord); + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } } /** @@ -80,8 +214,14 @@ public class DBReferenceDigestManager extends DBManager */ @Override public boolean deleteRecord(final ReferenceDigestRecord referenceDigestRecord) { + boolean result = false; LOGGER.info(String.format("Deleting reference to %s/%s", referenceDigestRecord.getManufacturer(), referenceDigestRecord.getModel())); - return delete(referenceDigestRecord); + try { + result = super.delete(referenceDigestRecord); + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } + return result; } } diff --git a/HIRS_Utils/src/main/java/hirs/persist/DBReferenceEventManager.java b/HIRS_Utils/src/main/java/hirs/persist/DBReferenceEventManager.java new file mode 100644 index 00000000..52b5d740 --- /dev/null +++ b/HIRS_Utils/src/main/java/hirs/persist/DBReferenceEventManager.java @@ -0,0 +1,191 @@ +package hirs.persist; + +import hirs.data.persist.ReferenceDigestRecord; +import hirs.data.persist.ReferenceDigestValue; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.criterion.Restrictions; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * This class is used to persist and retrieve {@link hirs.data.persist.ReferenceDigestValue}s into + * and from the database. + */ +public class DBReferenceEventManager extends DBManager + implements ReferenceEventManager { + + private static final Logger LOGGER = LogManager.getLogger(DBReferenceDigestManager.class); + + /** + * Default Constructor. + * + * @param sessionFactory session factory used to access database connections + */ + public DBReferenceEventManager(final SessionFactory sessionFactory) { + super(ReferenceDigestValue.class, sessionFactory); + } + @Override + public ReferenceDigestValue saveValue(final ReferenceDigestValue referenceDigestValue) { + LOGGER.debug("saving event digest value: {}", referenceDigestValue); + try { + return save(referenceDigestValue); + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } + } + + @Override + public ReferenceDigestValue getValue(final ReferenceDigestValue referenceDigestValue) { + LOGGER.debug("Getting record for {}", referenceDigestValue); + if (referenceDigestValue == null) { + LOGGER.error("null referenceDigestValue argument"); + return null; + } + + if (referenceDigestValue.getDigestRecordId() == null + || referenceDigestValue.getDigestValue() == null + || referenceDigestValue.getEventNumber() == -1) { + LOGGER.error("No reference to get record from db {}", referenceDigestValue); + return null; + } + + ReferenceDigestValue dbRecord; + Transaction tx = null; + Session session = getFactory().getCurrentSession(); + try { + LOGGER.debug("retrieving referenceDigestValue from db"); + tx = session.beginTransaction(); + dbRecord = (ReferenceDigestValue) session.createCriteria(ReferenceDigestValue.class) + .add(Restrictions.eq("digestRecordId", + referenceDigestValue.getDigestRecordId())) + .add(Restrictions.eq("digestValue", + referenceDigestValue.getDigestValue())) + .add(Restrictions.eq("eventNumber", + referenceDigestValue.getEventNumber())) + .uniqueResult(); + tx.commit(); + } catch (Exception ex) { + final String msg = "unable to retrieve object"; + LOGGER.error(msg, ex); + if (tx != null) { + LOGGER.debug("rolling back transaction"); + tx.rollback(); + } + throw new DBManagerException(msg, ex); + } + return dbRecord; + } + + @Override + public ReferenceDigestValue getValueById(final ReferenceDigestValue referenceDigestValue) { + LOGGER.debug("Getting record for {}", referenceDigestValue); + if (referenceDigestValue == null) { + LOGGER.error("null referenceDigestValue argument"); + return null; + } + + if (referenceDigestValue.getId() == null) { + LOGGER.error("No reference to get record from db {}", referenceDigestValue); + return null; + } + + ReferenceDigestValue dbRecord; + Transaction tx = null; + Session session = getFactory().getCurrentSession(); + try { + LOGGER.debug("retrieving referenceDigestValue from db"); + tx = session.beginTransaction(); + dbRecord = (ReferenceDigestValue) session.createCriteria(ReferenceDigestValue.class) + .add(Restrictions.eq("id", + referenceDigestValue.getId())).uniqueResult(); + tx.commit(); + } catch (Exception ex) { + final String msg = "unable to retrieve object"; + LOGGER.error(msg, ex); + if (tx != null) { + LOGGER.debug("rolling back transaction"); + tx.rollback(); + } + throw new DBManagerException(msg, ex); + } + return dbRecord; + } + + @Override + public List getValuesByRecordId( + final ReferenceDigestRecord referenceDigestRecord) { + LOGGER.debug("Getting digest values for {}", referenceDigestRecord); + if (referenceDigestRecord == null) { + LOGGER.error("null referenceDigestRecord argument"); + throw new NullPointerException("null referenceDigestRecord"); + } + if (referenceDigestRecord.getId() == null) { + LOGGER.error("null referenceDigestRecord ID argument"); + throw new NullPointerException("null referenceDigestRecord ID"); + } + + List dbDigestValues = new ArrayList<>(); + UUID uuid = referenceDigestRecord.getId(); + try { + List dbTempList = super.getList(ReferenceDigestValue.class); + for (ReferenceDigestValue rdv : dbTempList) { + if (rdv.getDigestRecordId().equals(uuid)) { + dbDigestValues.add(rdv); + } + } + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } + return dbDigestValues; + } + + @Override + public List getValueByEventType(final String eventType) { + LOGGER.debug("Getting digest values for event type: {}", eventType); + if (eventType == null) { + LOGGER.error("null event type argument"); + throw new NullPointerException("null event type"); + } + + List dbDigestValues = new ArrayList<>(); + try { + List dbTempList = super.getList(ReferenceDigestValue.class); + for (ReferenceDigestValue rdv : dbTempList) { + if (rdv.getEventType().equals(eventType)) { + dbDigestValues.add(rdv); + } + } + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } + return dbDigestValues; + } + + @Override + public void updateRecord(final ReferenceDigestValue referenceDigestValue) { + try { + super.update(referenceDigestValue); + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } + } + + @Override + public boolean deleteRecord(final ReferenceDigestValue referenceDigestValue) { + boolean result; + LOGGER.info(String.format("Deleting reference to %s", + referenceDigestValue.getId())); + try { + result = super.delete(referenceDigestValue); + } catch (DBManagerException dbMEx) { + throw new RuntimeException(dbMEx); + } + return result; + } +} diff --git a/HIRS_Utils/src/main/java/hirs/persist/PersistenceConfiguration.java b/HIRS_Utils/src/main/java/hirs/persist/PersistenceConfiguration.java index bd6f19f4..408687d1 100644 --- a/HIRS_Utils/src/main/java/hirs/persist/PersistenceConfiguration.java +++ b/HIRS_Utils/src/main/java/hirs/persist/PersistenceConfiguration.java @@ -167,6 +167,19 @@ public class PersistenceConfiguration { return manager; } + /** + * Creates a {@link ReferenceEventManager} ready to use. + * + * @return {@link ReferenceEventManager} + */ + @Bean + public ReferenceEventManager referenceEventManager() { + DBReferenceEventManager manager + = new DBReferenceEventManager(sessionFactory.getObject()); + setDbManagerRetrySettings(manager); + return manager; + } + /** * Creates a {@link DeviceStateManager} ready to use. * diff --git a/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java b/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java index aef06272..d858782c 100644 --- a/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java +++ b/HIRS_Utils/src/main/java/hirs/persist/ReferenceDigestManager.java @@ -4,6 +4,7 @@ package hirs.persist; import hirs.data.persist.ReferenceDigestRecord; import java.util.List; +import java.util.UUID; /** * This class facilitates the persistence of {@link hirs.data.persist.ReferenceDigestRecord}s @@ -27,6 +28,22 @@ public interface ReferenceDigestManager { */ ReferenceDigestRecord getRecord(ReferenceDigestRecord referenceDigestRecord); + /** + * Persists a new Reference Digest. + * + * @param referenceDigestRecord the ReferenceDigestRecord + * @return the persisted ReferenceDigestRecord + */ + ReferenceDigestRecord getRecordById(ReferenceDigestRecord referenceDigestRecord); + + /** + * Persists a new Reference Digest. + * + * @param supportId the support RIM UUID + * @return the persisted ReferenceDigestRecord + */ + ReferenceDigestRecord getRecordBySupportId(UUID supportId); + /** * Persists a new Reference Digest. * @@ -47,9 +64,8 @@ public interface ReferenceDigestManager { /** * Updates an existing ReferenceDigestRecord. * @param referenceDigestRecord the Reference Digest update - * @return status of successful update */ - boolean updateRecord(ReferenceDigestRecord referenceDigestRecord); + void updateRecord(ReferenceDigestRecord referenceDigestRecord); /** * Delete the given record. diff --git a/HIRS_Utils/src/main/java/hirs/persist/ReferenceEventManager.java b/HIRS_Utils/src/main/java/hirs/persist/ReferenceEventManager.java new file mode 100644 index 00000000..89c02ebc --- /dev/null +++ b/HIRS_Utils/src/main/java/hirs/persist/ReferenceEventManager.java @@ -0,0 +1,66 @@ +package hirs.persist; + +import hirs.data.persist.ReferenceDigestRecord; +import hirs.data.persist.ReferenceDigestValue; + +import java.util.List; + +/** + * This class facilitates the persistence of {@link hirs.data.persist.ReferenceDigestValue}s + * including storage, retrieval, and deletion. + */ +public interface ReferenceEventManager { + /** + * Persists a new Reference Digest value. + * + * @param referenceDigestValue the ReferenceDigestValue + * @return the persisted ReferenceDigestValue + */ + ReferenceDigestValue saveValue(ReferenceDigestValue referenceDigestValue); + + /** + * Persists a new Reference Digest value. + * + * @param referenceDigestValue the ReferenceDigestValue + * @return the persisted ReferenceDigestValue + */ + ReferenceDigestValue getValue(ReferenceDigestValue referenceDigestValue); + + /** + * Persists a new Reference Digest value. + * + * @param referenceDigestValue the ReferenceDigestValue + * @return the persisted ReferenceDigestValue + */ + ReferenceDigestValue getValueById(ReferenceDigestValue referenceDigestValue); + + /** + * Persists a new Reference Digest value. + * + * @param referenceDigestRecord the ReferenceDigestRecord + * @return the persisted list of ReferenceDigestValue + */ + List getValuesByRecordId(ReferenceDigestRecord referenceDigestRecord); + + /** + * Persists a new Reference Digest value. + * + * @param eventType the event type to look for + * @return the persisted list of ReferenceDigestValue + */ + List getValueByEventType(String eventType); + + /** + * Updates an existing ReferenceDigestRecord. + * @param referenceDigestValue the Reference Event update + */ + void updateRecord(ReferenceDigestValue referenceDigestValue); + + /** + * Delete the given value. + * + * @param referenceDigestValue the digest record delete + * @return true if the deletion succeeded, false otherwise. + */ + boolean deleteRecord(ReferenceDigestValue referenceDigestValue); +}