mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-03-25 13:27:38 +00:00
Finished up the rest of it
This commit is contained in:
parent
86ef7d9356
commit
468cbc0797
@ -25,29 +25,19 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
jaxb "org.glassfish.jaxb:jaxb-xjc:4.0.1"
|
||||
jaxb "org.glassfish.jaxb:jaxb-runtime:4.0.1"
|
||||
implementation project(':HIRS_Utils')
|
||||
implementation project(':HIRS_AttestationCA')
|
||||
|
||||
implementation 'com.github.marandus:pci-ids:0.3'
|
||||
implementation 'org.bouncycastle:bcmail-jdk15on:1.70'
|
||||
implementation 'com.google.guava:guava:31.1-jre'
|
||||
implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.0'
|
||||
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'org.projectlombok:lombok'
|
||||
implementation 'org.bouncycastle:bcmail-jdk15on:1.70'
|
||||
implementation 'org.springframework.plugin:spring-plugin-core:3.0.0'
|
||||
implementation 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||
implementation 'com.google.guava:guava:31.1-jre'
|
||||
implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.0'
|
||||
implementation 'org.apache.httpcomponents.client5:httpclient5:5.2.1'
|
||||
implementation 'commons-codec:commons-codec:1.15'
|
||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
||||
implementation 'org.apache.logging.log4j:log4j-core:2.19.0'
|
||||
implementation 'org.apache.logging.log4j:log4j-api:2.19.0'
|
||||
implementation 'com.eclipsesource.minimal-json:minimal-json:0.9.5'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-core:2.14.2'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.14.2'
|
||||
implementation "org.glassfish.jaxb:jaxb-runtime:4.0.1"
|
||||
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0'
|
||||
// implementation 'com.sun.xml.bind:jaxb-impl:4.0.2' //creates duplicate error
|
||||
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
@ -63,34 +53,3 @@ war {
|
||||
}
|
||||
archiveFileName = 'HIRS_AttestationCAPortal.war'
|
||||
}
|
||||
|
||||
task generateXjcLibrary(type:Exec) {
|
||||
workingDir 'config'
|
||||
|
||||
commandLine './genXjcLibrary.sh'
|
||||
}
|
||||
compileJava.dependsOn generateXjcLibrary
|
||||
|
||||
//ospackage {
|
||||
// packageName = 'HIRS_AttestationCA'
|
||||
// os = LINUX
|
||||
// arch = NOARCH
|
||||
// release = '1'
|
||||
//
|
||||
// user 'root'
|
||||
// fileMode = 0755
|
||||
//
|
||||
// addParentDirs = true
|
||||
// createDirectoryEntry true
|
||||
//
|
||||
// into ("/opt/tomcat/webapps") {
|
||||
// from war.outputs.files
|
||||
// from '../HIRS_AttestationCAPortal/build/libs/HIRS_AttestationCAPortal.war'
|
||||
// user 'root'
|
||||
// fileMode = 0755
|
||||
// }
|
||||
//
|
||||
// buildRpm {
|
||||
// arch = X86_64
|
||||
// }
|
||||
//}
|
||||
|
@ -1,100 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* An abstract database entity.
|
||||
*/
|
||||
@ToString
|
||||
@MappedSuperclass
|
||||
public abstract class AbstractEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* static value for the length of a status message for objects that
|
||||
* can have extremely long values, potentially.
|
||||
*/
|
||||
protected static final int RESULT_MESSAGE_LENGTH = 1000000;
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2", strategy=GenerationType.AUTO)
|
||||
@JdbcTypeCode(java.sql.Types.VARCHAR)
|
||||
@Getter
|
||||
private UUID id;
|
||||
|
||||
@Column (name = "create_time")
|
||||
@ColumnDefault(value = "CURRENT_TIMESTAMP")
|
||||
@Generated(GenerationTime.INSERT)
|
||||
private Date createTime;// = new Date();
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected AbstractEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the UUID that can not be null
|
||||
* and can not be overridden.
|
||||
* @param id - primary able key
|
||||
*/
|
||||
public void setId(UUID id) {
|
||||
if (id != null) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the creation time of this entity.
|
||||
*
|
||||
* @return creation time
|
||||
*/
|
||||
public Date getCreateTime() {
|
||||
return (Date) createTime.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the creation time to the current time.
|
||||
*/
|
||||
public void resetCreateTime() {
|
||||
createTime.setTime(new Date().getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (id != null) {
|
||||
return id.hashCode();
|
||||
}
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(this.getClass().equals(obj.getClass()))) {
|
||||
return false;
|
||||
}
|
||||
return this.hashCode() == obj.hashCode();
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* The <code>Appraiser</code> class represents an appraiser that can appraise a <code>Report</code>.
|
||||
* <code>Appraiser</code>s are invoked to validate the integrity of client's platform. An
|
||||
* <code>Appraiser</code> does this by examining a <code>Report</code> sent from the client's
|
||||
* machine.
|
||||
* <p>
|
||||
* Supported <code>Report</code> types are kept track of in three ways: <ul> <li>The type of report
|
||||
* received for appraisal is getAppraiseReportType() (e.g. the <code>DeviceInfoAppraiser</code>
|
||||
* takes in a <code>DeviceInfoReport</code> and the <code>TPMAppraiser</code> takes in an
|
||||
* <code>IntegrityReport</code>)</li> <li>The type requested in getReportRequest is
|
||||
* getRequestReportType(). This tends to be the specific report type for that type of appraiser
|
||||
* (e.g. the <code>IMAAppraiser</code> requests an <code>IMAReport</code> and the
|
||||
* <code>TPMAppraiser</code> requests a <code>TPMReport</code>)</li> <li>The set of types this
|
||||
* appraiser relies on extracting from the top-level report is getRequiredReportTypes() (e.g. if the
|
||||
* top-level report is <code>IntegrityReport</code> then the <code>IMAAppraiser</code> needs to
|
||||
* extract both a <code>DeviceInfoReport</code> and a <code>IMAReport</code> from the
|
||||
* <code>IntegrityReport</code>)</li> </ul>
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "Appraiser")
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Appraiser {
|
||||
/**
|
||||
* Name set for every instance of <code>TPMAppraiser</code>.
|
||||
*/
|
||||
public static final String TPM_NAME = "TPM Appraiser";
|
||||
/**
|
||||
* Name set for every instance of <code>SupplyChainAppraiser</code>.
|
||||
*/
|
||||
public static final String SC_NAME = "Supply Chain Appraiser";
|
||||
/**
|
||||
* Name set for every instance of <code>IMAAppraiser</code>.
|
||||
*/
|
||||
public static final String IMA_NAME = "IMA Appraiser";
|
||||
/**
|
||||
* Name set for every instance of <code>HIRSAppraiser</code>.
|
||||
*/
|
||||
public static final String HIRS_NAME = "HIRS Appraiser";
|
||||
/**
|
||||
* Name set for every instance of <code>DeviceInfoAppraiser</code>.
|
||||
*/
|
||||
public static final String DI_NAME = "Device Info Appraiser";
|
||||
|
||||
@Getter
|
||||
@ToString.Exclude
|
||||
@EqualsAndHashCode.Exclude
|
||||
@Id
|
||||
@Column(name = "Appraiser_ID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Column(nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Appraiser</code> with the specified name. The name should be universally
|
||||
* unique as this is how other components will identify <code>Appraiser</code>s. Web portals,
|
||||
* for instance, could display a list of <code>Appraiser</code> names to display which
|
||||
* <code>Appraiser</code>s are available.
|
||||
* <p>
|
||||
* The name will be tested for uniqueness when it is added to a repository. It is not tested for
|
||||
* uniqueness in the class.
|
||||
*
|
||||
* @param name unique name
|
||||
*/
|
||||
public Appraiser(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An abstract archivable entity that can be deleted.
|
||||
*/
|
||||
@ToString
|
||||
@Getter
|
||||
@MappedSuperclass
|
||||
public abstract class ArchivableEntity extends AbstractEntity {
|
||||
|
||||
/**
|
||||
* Defining the size of a message field for error display.
|
||||
*/
|
||||
public static final int MAX_MESSAGE_LENGTH = 2400;
|
||||
|
||||
@Column(name = "archived_time")
|
||||
private Date archivedTime;
|
||||
|
||||
@Column(name = "archived_description")
|
||||
private String archivedDescription;
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected ArchivableEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the boolean representing whether or not this entity has been soft-deleted.
|
||||
*
|
||||
* @return true if this entity has been soft-deleted, false otherwise
|
||||
*/
|
||||
public final boolean isArchived() {
|
||||
return archivedTime != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that this entity has been archived, by setting the archivedTime to the current date
|
||||
* and time.
|
||||
*
|
||||
* @return
|
||||
* true if time was null and date was set.
|
||||
* false is archived time is already set, signifying the entity has been archived.
|
||||
*/
|
||||
public final boolean archive() {
|
||||
if (this.archivedTime == null) {
|
||||
this.archivedTime = new Date();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a description for the resolution if one is provided. This is done for accounting
|
||||
* purposes so the reason for action taken can be referenced.
|
||||
*
|
||||
* @param description - description of the action taken for resolution
|
||||
* @return
|
||||
* boolean result is dependent on the return value of the archive() method
|
||||
*/
|
||||
public final boolean archive(final String description) {
|
||||
if (archive()) {
|
||||
this.archivedDescription = description;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the archivedTime to null. The archivedTime being null signifies that the entity has
|
||||
* not been archived. If the time is already null then this call was unnecessary.
|
||||
*
|
||||
* @return
|
||||
* true if the time is changed to null.
|
||||
* false if time was already set to null.
|
||||
*/
|
||||
public final boolean restore() {
|
||||
if (this.archivedTime != null) {
|
||||
this.archivedTime = null;
|
||||
this.archivedDescription = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity;
|
||||
|
||||
import jakarta.persistence.Access;
|
||||
import jakarta.persistence.AccessType;
|
||||
import jakarta.persistence.Inheritance;
|
||||
import jakarta.persistence.InheritanceType;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
/**
|
||||
* The <code>Policy</code> class represents a policy. This is an abstract class
|
||||
* for representing the rules for which an <code>Appraiser</code> should
|
||||
* evaluate a <code>Report</code>. A typical <code>Policy</code> will contain a
|
||||
* <code>Baseline</code> at the very least. A <code>Policy</code> is identified
|
||||
* by its name, so the name for a <code>Policy</code> must be unique.
|
||||
*/
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@Access(AccessType.FIELD)
|
||||
@MappedSuperclass
|
||||
public abstract class Policy extends UserDefinedEntity {
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected Policy() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>Policy</code> with the specified name.
|
||||
*
|
||||
* @param name
|
||||
* name
|
||||
*/
|
||||
public Policy(final String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>Policy</code> with the specified name and
|
||||
* description.
|
||||
*
|
||||
* @param name
|
||||
* name (required)
|
||||
* @param description
|
||||
* description (may be null)
|
||||
*/
|
||||
public Policy(final String name, final String description) {
|
||||
super(name, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this object has been persisted. Used in determining whether
|
||||
* an Appraiser should request the full Policy (and baselines) for appraisal
|
||||
*
|
||||
* @return true if this object has been persisted; false otherwise
|
||||
*/
|
||||
public final boolean isPersisted() {
|
||||
return getId() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link hirs.attestationca.portal.persist.entity.Policy} are serialized to be sent to the browser, this can be used
|
||||
* to determine the type of {@link hirs.attestationca.portal.persist.entity.Policy}.
|
||||
*
|
||||
* @return The class name for the {@link hirs.attestationca.portal.persist.entity.Policy}
|
||||
*/
|
||||
public String getType() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity;
|
||||
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* An abstract archivable entity that can be given a user-defined name and description.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@AllArgsConstructor
|
||||
@MappedSuperclass
|
||||
public abstract class UserDefinedEntity extends ArchivableEntity {
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
@ToString.Exclude
|
||||
@EqualsAndHashCode.Exclude
|
||||
@Column(nullable = false, unique = false)
|
||||
private String description = "";
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected UserDefinedEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new entity with the specified name.
|
||||
*
|
||||
* @param name name
|
||||
*/
|
||||
public UserDefinedEntity(final String name) {
|
||||
this(name, "");
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.manager;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.Device;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface DeviceRepository extends JpaRepository<Device, UUID> {
|
||||
List<Device> findByName(String deviceName);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.manager;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ReferenceManifestRepository extends JpaRepository<ReferenceManifest, UUID> {
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.manager;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainSettings;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface SettingsRepository extends JpaRepository<SupplyChainSettings, UUID> {
|
||||
SupplyChainSettings findByName(String name);
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* This package has objects for hibernate entity.
|
||||
*/
|
||||
package hirs.attestationca.portal.persist.entity;
|
File diff suppressed because it is too large
Load Diff
@ -1,63 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.persist.entity.AbstractEntity;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import hirs.attestationca.persist.enums.HealthStatus;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Entity
|
||||
@Table(name = "Device")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@AllArgsConstructor
|
||||
public class Device extends AbstractEntity {
|
||||
|
||||
@Column(name = "name", unique = true)
|
||||
private String name;
|
||||
|
||||
// @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
|
||||
// optional = true, orphanRemoval = true)
|
||||
// private DeviceInfoReport deviceInfo;
|
||||
|
||||
@Column
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
private HealthStatus healthStatus;
|
||||
|
||||
@Column
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
private AppraisalStatus.Status supplyChainValidationStatus;
|
||||
|
||||
/**
|
||||
* Time stamp for the report.
|
||||
*/
|
||||
@Column(name = "last_report_timestamp")
|
||||
private Timestamp lastReportTimestamp;
|
||||
|
||||
@Column(name = "is_state_overridden")
|
||||
private boolean isStateOverridden;
|
||||
|
||||
@Column(name = "state_override_reason")
|
||||
private String overrideReason;
|
||||
|
||||
@Column(name = "summary_id")
|
||||
private String summaryId;
|
||||
|
||||
public String toString() {
|
||||
return String.format("Device Name: %s%nStatus: %s%nSummary: %s",
|
||||
name, healthStatus.getStatus(),
|
||||
// supplyChainValidationStatus.toString(),
|
||||
summaryId);
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import jakarta.persistence.Access;
|
||||
import jakarta.persistence.AccessType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This class represents that actual entry in the Support RIM.
|
||||
* Digest Value, Event Type, index, RIM Tagid
|
||||
*/
|
||||
@ToString @EqualsAndHashCode(callSuper = false)
|
||||
@Setter @Getter
|
||||
@Entity
|
||||
@Table(name = "ReferenceDigestValue")
|
||||
@Access(AccessType.FIELD)
|
||||
public class ReferenceDigestValue extends ArchivableEntity {
|
||||
|
||||
// @Type(type = "uuid-char")
|
||||
@JdbcTypeCode(java.sql.Types.VARCHAR)
|
||||
@Column
|
||||
private UUID baseRimId;
|
||||
// @Type(type = "uuid-char")
|
||||
@JdbcTypeCode(java.sql.Types.VARCHAR)
|
||||
@Column
|
||||
private UUID supportRimId;
|
||||
@Column(nullable = false)
|
||||
private String manufacturer;
|
||||
@Column(nullable = false)
|
||||
private String model;
|
||||
@Column(nullable = false)
|
||||
private int pcrIndex;
|
||||
@Column(nullable = false)
|
||||
private String digestValue;
|
||||
@Column(nullable = false)
|
||||
private String eventType;
|
||||
@Column(columnDefinition = "blob", nullable = true)
|
||||
private byte[] contentBlob;
|
||||
@Column(nullable = false)
|
||||
private boolean matchFail;
|
||||
@Column(nullable = false)
|
||||
private boolean patched = false;
|
||||
@Column(nullable = false)
|
||||
private boolean updated = false;
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected ReferenceDigestValue() {
|
||||
super();
|
||||
this.baseRimId = null;
|
||||
this.supportRimId = null;
|
||||
this.manufacturer = "";
|
||||
this.model = "";
|
||||
this.pcrIndex = -1;
|
||||
this.digestValue = "";
|
||||
this.eventType = "";
|
||||
this.matchFail = false;
|
||||
this.patched = false;
|
||||
this.updated = false;
|
||||
this.contentBlob = null;
|
||||
}
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import jakarta.persistence.Access;
|
||||
import jakarta.persistence.AccessType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This class represents the Reference Integrity Manifest object that will be
|
||||
* loaded into the DB and displayed in the ACA.
|
||||
*/
|
||||
@Getter @Setter @ToString
|
||||
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
|
||||
@Entity
|
||||
@Table(name = "ReferenceManifest")
|
||||
@Access(AccessType.FIELD)
|
||||
public class ReferenceManifest extends ArchivableEntity {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(ReferenceManifest.class);
|
||||
/**
|
||||
* Holds the name of the 'hexDecHash' field.
|
||||
*/
|
||||
public static final String HEX_DEC_HASH_FIELD = "hexDecHash";
|
||||
/**
|
||||
* String for display of a Base RIM.
|
||||
*/
|
||||
public static final String BASE_RIM = "Base";
|
||||
/**
|
||||
* String for display of a Support RIM.
|
||||
*/
|
||||
public static final String SUPPORT_RIM = "Support";
|
||||
/**
|
||||
* String for display of a Support RIM.
|
||||
*/
|
||||
public static final String MEASUREMENT_RIM = "Measurement";
|
||||
|
||||
/**
|
||||
* String for the xml schema ios standard.
|
||||
*/
|
||||
public static final String SCHEMA_STATEMENT = "ISO/IEC 19770-2:2015 Schema (XSD 1.0) "
|
||||
+ "- September 2015, see http://standards.iso.org/iso/19770/-2/2015/schema.xsd";
|
||||
/**
|
||||
* String for the xml schema URL file name.
|
||||
*/
|
||||
public static final String SCHEMA_URL = "swid_schema.xsd";
|
||||
/**
|
||||
* String for the language type for the xml schema.
|
||||
*/
|
||||
public static final String SCHEMA_LANGUAGE = XMLConstants.W3C_XML_SCHEMA_NS_URI;
|
||||
/**
|
||||
* String for the package location of the xml generated java files.
|
||||
*/
|
||||
public static final String SCHEMA_PACKAGE = "hirs.utils.xjc";
|
||||
|
||||
@EqualsAndHashCode.Include
|
||||
@Column(columnDefinition = "mediumblob", nullable = false)
|
||||
private byte[] rimBytes;
|
||||
@EqualsAndHashCode.Include
|
||||
@Column(nullable = false)
|
||||
private String rimType = "Base";
|
||||
@Column
|
||||
private String tagId = null;
|
||||
@Column
|
||||
private boolean swidPatch = false;
|
||||
@Column
|
||||
private boolean swidSupplemental = false;
|
||||
@Column
|
||||
private String platformManufacturer = null;
|
||||
@Column
|
||||
private String platformManufacturerId = null;
|
||||
@Column
|
||||
private String swidTagVersion = null;
|
||||
@Column
|
||||
private String swidVersion = null;
|
||||
@Column
|
||||
private String platformModel = null;
|
||||
@Column(nullable = false)
|
||||
private String fileName = null;
|
||||
// @Type(type="uuid-char")
|
||||
@JdbcTypeCode(java.sql.Types.VARCHAR)
|
||||
@Column
|
||||
private UUID associatedRim;
|
||||
@Column
|
||||
private String deviceName;
|
||||
@Column
|
||||
private String hexDecHash = "";
|
||||
@Column
|
||||
private String eventLogHash = "";
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected ReferenceManifest() {
|
||||
super();
|
||||
this.rimBytes = null;
|
||||
this.rimType = null;
|
||||
this.platformManufacturer = null;
|
||||
this.platformManufacturerId = null;
|
||||
this.platformModel = null;
|
||||
this.fileName = BASE_RIM;
|
||||
this.tagId = null;
|
||||
this.associatedRim = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor for ingesting the bytes of the file content.
|
||||
* @param rimBytes - file contents.
|
||||
*/
|
||||
public ReferenceManifest(final byte[] rimBytes) {
|
||||
Preconditions.checkArgument(rimBytes != null,
|
||||
"Cannot construct a RIM from a null byte array");
|
||||
|
||||
Preconditions.checkArgument(rimBytes.length > 0,
|
||||
"Cannot construct a RIM from an empty byte array");
|
||||
|
||||
this.rimBytes = rimBytes.clone();
|
||||
MessageDigest digest = null;
|
||||
this.hexDecHash = "";
|
||||
try {
|
||||
digest = MessageDigest.getInstance("SHA-256");
|
||||
this.hexDecHash = Hex.encodeHexString(
|
||||
digest.digest(rimBytes));
|
||||
} catch (NoSuchAlgorithmException noSaEx) {
|
||||
LOGGER.error(noSaEx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the Reference Integrity Manifest as a byte array.
|
||||
*
|
||||
* @return array of bytes
|
||||
*/
|
||||
@JsonIgnore
|
||||
public byte[] getRimBytes() {
|
||||
if (this.rimBytes != null) {
|
||||
return this.rimBytes.clone();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.persist.entity.AbstractEntity;
|
||||
import jakarta.persistence.Access;
|
||||
import jakarta.persistence.AccessType;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Inheritance;
|
||||
import jakarta.persistence.InheritanceType;
|
||||
|
||||
/**
|
||||
* A <code>Report</code> represents an integrity report to be appraised by an
|
||||
* <code>Appraiser</code>. An <code>Appraiser</code> validates the integrity of
|
||||
* a client's platform with an integrity report. Example reports include an IMA
|
||||
* report and TPM report.
|
||||
* <p>
|
||||
* This <code>Report</code> class contains minimal information because each
|
||||
* report is vastly different. There is an identification number in case the
|
||||
* <code>Report</code> is stored in a database, and there is a report type. The
|
||||
* report type is used to determine which <code>Appraiser</code>s can appraise
|
||||
* the report.
|
||||
*/
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
public abstract class Report extends AbstractEntity {
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
protected Report() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> that indicates this report type. The report
|
||||
* type is used to find an <code>Appraiser</code> that can appraise this
|
||||
* <code>Report</code>.
|
||||
*
|
||||
* @return report type
|
||||
*/
|
||||
public abstract String getReportType();
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.persist.entity.UserDefinedEntity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* Class represents Supply Chain policy. Supply Chain Policy identifies the methods in
|
||||
* SupplyChainValidator that should be used in order to validate a supply chain.
|
||||
* By default, the policy does not enable any validations.
|
||||
*/
|
||||
@Table(name = "SupplyChainSettings")
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@ToString(callSuper = true)
|
||||
public class SupplyChainSettings extends UserDefinedEntity {
|
||||
/**
|
||||
* Name of the default Supply Chain Policy.
|
||||
*/
|
||||
public static final String DEFAULT_POLICY = "Default Supply Chain Policy";
|
||||
/**
|
||||
* Number of days in 10 years.
|
||||
*/
|
||||
public static final String TEN_YEARS = "3651";
|
||||
/**
|
||||
* Number of days in 1 year.
|
||||
*/
|
||||
public static final String YEAR = "365";
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean ecValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean pcValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean pcAttributeValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean firmwareValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean utcValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean expiredCertificateValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean replaceEC = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default true")
|
||||
private boolean issueAttestationCertificate = true;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default true")
|
||||
private boolean issueDevIdCertificate = true;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String validityDays = TEN_YEARS;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String devIdValidityDays = TEN_YEARS;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String reissueThreshold = YEAR;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String devIdReissueThreshold = YEAR;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean generateOnExpiration = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean devIdExpirationFlag = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean ignoreImaEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean ignoretBootEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean linuxOs = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default true")
|
||||
private boolean ignoreGptEnabled = true;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean ignoreOsEvtEnabled = false;
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected SupplyChainSettings() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to initialize SupplyChainSettings object.
|
||||
*
|
||||
* @param name
|
||||
* A name used to uniquely identify and reference the Supply Chain policy.
|
||||
*/
|
||||
public SupplyChainSettings(final String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to initialize SupplyChainSettings object.
|
||||
*
|
||||
* @param name
|
||||
* A name used to uniquely identify and reference the supply chain policy.
|
||||
* @param description
|
||||
* Optional description of the policy that can be added by the user
|
||||
*/
|
||||
public SupplyChainSettings(final String name, final String description) {
|
||||
super(name, description);
|
||||
}
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.Certificate;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class persists Certificate Authority credentials by extending the base Certificate
|
||||
* class with fields unique to CA credentials.
|
||||
*/
|
||||
@Entity
|
||||
public class CertificateAuthorityCredential extends Certificate {
|
||||
|
||||
|
||||
@SuppressWarnings("PMD.AvoidUsingHardCodedIP")
|
||||
private static final String SUBJECT_KEY_IDENTIFIER_EXTENSION = "2.5.29.14";
|
||||
|
||||
/**
|
||||
* Holds the name of the 'subjectKeyIdentifier' field.
|
||||
*/
|
||||
public static final String SUBJECT_KEY_IDENTIFIER_FIELD = "subjectKeyIdentifier";
|
||||
|
||||
private static final int CA_BYTE_SIZE = 20;
|
||||
private static final int PREFIX_BYTE_SIZE = 4;
|
||||
|
||||
@Column
|
||||
private final byte[] subjectKeyIdentifier;
|
||||
|
||||
@Getter
|
||||
@Column
|
||||
private String subjectKeyIdString;
|
||||
|
||||
/**
|
||||
* this field is part of the TCG CA specification, but has not yet been found in
|
||||
* manufacturer-provided CAs, and is therefore not currently parsed.
|
||||
*/
|
||||
@Getter
|
||||
@Column
|
||||
private final String credentialType = "TCPA Trusted Platform Module Endorsement";
|
||||
|
||||
/**
|
||||
* Construct a new CertificateAuthorityCredential given its binary contents. The given
|
||||
* certificate should represent either an X509 certificate or X509 attribute certificate.
|
||||
*
|
||||
* @param certificateBytes the contents of a certificate file
|
||||
* @throws java.io.IOException if there is a problem extracting information from the certificate
|
||||
*/
|
||||
public CertificateAuthorityCredential(final byte[] certificateBytes)
|
||||
throws IOException {
|
||||
super(certificateBytes);
|
||||
byte[] tempBytes = getX509Certificate()
|
||||
.getExtensionValue(SUBJECT_KEY_IDENTIFIER_EXTENSION);
|
||||
|
||||
if (tempBytes != null && tempBytes.length > CA_BYTE_SIZE) {
|
||||
this.subjectKeyIdentifier = truncatePrefixBytes(tempBytes);
|
||||
} else {
|
||||
this.subjectKeyIdentifier =
|
||||
getX509Certificate().getExtensionValue(SUBJECT_KEY_IDENTIFIER_EXTENSION);
|
||||
}
|
||||
|
||||
if (this.subjectKeyIdentifier != null) {
|
||||
this.subjectKeyIdString = Hex.encodeHexString(this.subjectKeyIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new CertificateAuthorityCredential by parsing the file at the given path.
|
||||
* The given certificate should represent either an X509 certificate or X509 attribute
|
||||
* certificate.
|
||||
*
|
||||
* @param certificatePath the path on disk to a certificate
|
||||
* @throws java.io.IOException if there is a problem reading the file
|
||||
*/
|
||||
public CertificateAuthorityCredential(final Path certificatePath)
|
||||
throws IOException {
|
||||
super(certificatePath);
|
||||
byte[] tempBytes = getX509Certificate()
|
||||
.getExtensionValue(SUBJECT_KEY_IDENTIFIER_EXTENSION);
|
||||
|
||||
if (tempBytes.length > CA_BYTE_SIZE) {
|
||||
this.subjectKeyIdentifier = truncatePrefixBytes(tempBytes);
|
||||
} else {
|
||||
this.subjectKeyIdentifier =
|
||||
getX509Certificate().getExtensionValue(SUBJECT_KEY_IDENTIFIER_EXTENSION);
|
||||
}
|
||||
if (this.subjectKeyIdentifier != null) {
|
||||
this.subjectKeyIdString = Hex.encodeHexString(this.subjectKeyIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor for Hibernate.
|
||||
*/
|
||||
protected CertificateAuthorityCredential() {
|
||||
subjectKeyIdentifier = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return this certificate's subject key identifier.
|
||||
*/
|
||||
public byte[] getSubjectKeyIdentifier() {
|
||||
if (subjectKeyIdentifier != null) {
|
||||
return subjectKeyIdentifier.clone();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private byte[] truncatePrefixBytes(final byte[] certificateBytes) {
|
||||
byte[] temp = new byte[CA_BYTE_SIZE];
|
||||
System.arraycopy(certificateBytes, PREFIX_BYTE_SIZE, temp, 0, CA_BYTE_SIZE);
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("checkstyle:avoidinlineconditionals")
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CertificateAuthorityCredential that = (CertificateAuthorityCredential) o;
|
||||
|
||||
// if (!Objects.equals(credentialType, that.credentialType)) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return Arrays.equals(subjectKeyIdentifier, that.subjectKeyIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"checkstyle:magicnumber", "checkstyle:avoidinlineconditionals"})
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (credentialType != null ? credentialType.hashCode() : 0);
|
||||
result = 31 * result + Arrays.hashCode(subjectKeyIdentifier);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate;
|
||||
|
||||
public class CertificateVariables {
|
||||
|
||||
public static final String PEM_HEADER = "-----BEGIN CERTIFICATE-----";
|
||||
public static final String PEM_FOOTER = "-----END CERTIFICATE-----";
|
||||
public static final String PEM_ATTRIBUTE_HEADER = "-----BEGIN ATTRIBUTE CERTIFICATE-----";
|
||||
public static final String PEM_ATTRIBUTE_FOOTER = "-----END ATTRIBUTE CERTIFICATE-----";
|
||||
public static final String MALFORMED_CERT_MESSAGE = "Malformed certificate detected.";
|
||||
public static final int MAX_CERT_LENGTH_BYTES = 2048;
|
||||
public static final int MAX_NUMERIC_PRECISION = 49; // Can store up to 160 bit values
|
||||
public static final int MAX_PUB_KEY_MODULUS_HEX_LENGTH = 1024;
|
||||
public static final int KEY_USAGE_BIT0 = 0;
|
||||
public static final int KEY_USAGE_BIT1 = 1;
|
||||
public static final int KEY_USAGE_BIT2 = 2;
|
||||
public static final int KEY_USAGE_BIT3 = 3;
|
||||
public static final int KEY_USAGE_BIT4 = 4;
|
||||
public static final int KEY_USAGE_BIT5 = 5;
|
||||
public static final int KEY_USAGE_BIT6 = 6;
|
||||
public static final int KEY_USAGE_BIT7 = 7;
|
||||
public static final int KEY_USAGE_BIT8 = 8;
|
||||
public static final String KEY_USAGE_DS = "DIGITAL SIGNATURE";
|
||||
public static final String KEY_USAGE_NR = "NON-REPUDIATION";
|
||||
public static final String KEY_USAGE_KE = "KEY ENCIPHERMENT";
|
||||
public static final String KEY_USAGE_DE = "DATA ENCIPHERMENT";
|
||||
public static final String KEY_USAGE_KA = "KEY AGREEMENT";
|
||||
public static final String KEY_USAGE_KC = "KEY CERT SIGN";
|
||||
public static final String KEY_USAGE_CS = "CRL SIGN";
|
||||
public static final String KEY_USAGE_EO = "ENCIPHER ONLY";
|
||||
public static final String KEY_USAGE_DO = "DECIPHER ONLY";
|
||||
public static final String ECDSA_OID = "1.2.840.10045.4.3.2";
|
||||
public static final String ECDSA_SHA224_OID = "1.2.840.10045.4.1";
|
||||
public static final String RSA256_OID = "1.2.840.113549.1.1.11";
|
||||
public static final String RSA384_OID = "1.2.840.113549.1.1.12";
|
||||
public static final String RSA512_OID = "1.2.840.113549.1.1.13";
|
||||
public static final String RSA224_OID = "1.2.840.113549.1.1.14";
|
||||
public static final String RSA512_224_OID = "1.2.840.113549.1.1.15";
|
||||
public static final String RSA512_256_OID = "1.2.840.113549.1.1.16";
|
||||
public static final String RSA256_STRING = "SHA256WithRSA";
|
||||
public static final String RSA384_STRING = "SHA384WithRSA";
|
||||
public static final String RSA224_STRING = "SHA224WithRSA";
|
||||
public static final String RSA512_STRING = "SHA512WithRSA";
|
||||
public static final String RSA512_224_STRING = "SHA512-224WithRSA";
|
||||
public static final String RSA512_256_STRING = "SHA512-256WithRSA";
|
||||
public static final String ECDSA_STRING = "SHA256WithECDSA";
|
||||
public static final String ECDSA_SHA224_STRING = "SHA224WithECDSA";
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.Certificate;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* This class persists Conformance credentials by extending the base Certificate
|
||||
* class with fields unique to Conformance credentials.
|
||||
*/
|
||||
@NoArgsConstructor(access= AccessLevel.PROTECTED)
|
||||
@Entity
|
||||
public class ConformanceCredential extends Certificate {
|
||||
/**
|
||||
* This class enables the retrieval of ConformanceCredentials by their attributes.
|
||||
*/
|
||||
// public static class Selector extends CertificateSelector<ConformanceCredential> {
|
||||
// /**
|
||||
// * Construct a new CertificateSelector that will use the given {@link CertificateManager} to
|
||||
// * retrieve one or many ConformanceCredentials.
|
||||
// *
|
||||
// * @param certificateManager the certificate manager to be used to retrieve certificates
|
||||
// */
|
||||
// public Selector(final CertificateManager certificateManager) {
|
||||
// super(certificateManager, ConformanceCredential.class);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get a Selector for use in retrieving ConformanceCredentials.
|
||||
*
|
||||
* @param certMan the CertificateManager to be used to retrieve persisted certificates
|
||||
* @return a ConformanceCredential.Selector instance to use for retrieving certificates
|
||||
*/
|
||||
// public static Selector select(final CertificateManager certMan) {
|
||||
// return new Selector(certMan);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Construct a new ConformanceCredential given its binary contents. The given certificate
|
||||
* should represent either an X509 certificate or X509 attribute certificate.
|
||||
*
|
||||
* @param certificateBytes the contents of a certificate file
|
||||
* @throws java.io.IOException if there is a problem extracting information from the certificate
|
||||
*/
|
||||
public ConformanceCredential(final byte[] certificateBytes) throws IOException {
|
||||
super(certificateBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new ConformanceCredential by parsing the file at the given path. The given
|
||||
* certificate should represent either an X509 certificate or X509 attribute certificate.
|
||||
*
|
||||
* @param certificatePath the path on disk to a certificate
|
||||
* @throws java.io.IOException if there is a problem reading the file
|
||||
*/
|
||||
public ConformanceCredential(final Path certificatePath) throws IOException {
|
||||
super(certificatePath);
|
||||
}
|
||||
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.Certificate;
|
||||
import hirs.attestationca.persist.entity.userdefined.Device;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* A Certificate that is associated with a single device.
|
||||
*
|
||||
* @see Certificate
|
||||
*/
|
||||
@NoArgsConstructor(access= AccessLevel.PACKAGE)
|
||||
@MappedSuperclass
|
||||
public abstract class DeviceAssociatedCertificate extends Certificate {
|
||||
|
||||
// a device can have multiple certs of this type.
|
||||
@Getter
|
||||
@Setter
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "device_id")
|
||||
private Device device;
|
||||
|
||||
/**
|
||||
* Holds the name of the entity 'DEVICE_ID' field.
|
||||
*/
|
||||
protected static final String DEVICE_ID_FIELD = "device.id";
|
||||
|
||||
/**
|
||||
* Construct a new Certificate by parsing the file at the given path. The given certificate
|
||||
* should represent either an X509 certificate or X509 attribute certificate.
|
||||
*
|
||||
* @param certificatePath the path on disk to a certificate
|
||||
* @throws java.io.IOException if there is a problem reading the file
|
||||
*/
|
||||
DeviceAssociatedCertificate(final Path certificatePath) throws IOException {
|
||||
super(certificatePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new Certificate given its binary contents. The given certificate should
|
||||
* represent either an X509 certificate or X509 attribute certificate.
|
||||
*
|
||||
* @param certificateBytes the contents of a certificate file
|
||||
* @throws java.io.IOException if there is a problem extracting information from the certificate
|
||||
*/
|
||||
DeviceAssociatedCertificate(final byte[] certificateBytes) throws IOException {
|
||||
super(certificateBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(super.toString());
|
||||
if (device != null) {
|
||||
sb.append(String.format("%nDevice -> %s", getDevice().toString()));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,716 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.TPMSecurityAssertions;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.TPMSpecification;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embedded;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Transient;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.asn1.ASN1ApplicationSpecific;
|
||||
import org.bouncycastle.asn1.ASN1BitString;
|
||||
import org.bouncycastle.asn1.ASN1Boolean;
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1Enumerated;
|
||||
import org.bouncycastle.asn1.ASN1GeneralizedTime;
|
||||
import org.bouncycastle.asn1.ASN1InputStream;
|
||||
import org.bouncycastle.asn1.ASN1Integer;
|
||||
import org.bouncycastle.asn1.ASN1Null;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.ASN1Primitive;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1Set;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.ASN1UTCTime;
|
||||
import org.bouncycastle.asn1.DERBMPString;
|
||||
import org.bouncycastle.asn1.DERExternal;
|
||||
import org.bouncycastle.asn1.DERGeneralString;
|
||||
import org.bouncycastle.asn1.DERIA5String;
|
||||
import org.bouncycastle.asn1.DERNumericString;
|
||||
import org.bouncycastle.asn1.DERPrintableString;
|
||||
import org.bouncycastle.asn1.DERT61String;
|
||||
import org.bouncycastle.asn1.DERTaggedObject;
|
||||
import org.bouncycastle.asn1.DERUTF8String;
|
||||
import org.bouncycastle.asn1.DERUniversalString;
|
||||
import org.bouncycastle.asn1.DERVisibleString;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.file.Path;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.text.ParseException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* This class persists Certificate Authority credentials by extending the base Certificate
|
||||
* class with fields unique to Endorsement credentials, as defined in the Trusted
|
||||
* Computing Group Credential Profiles, specification v.1.2.
|
||||
*
|
||||
* trustedcomputinggroup.org/wp-content/uploads/Credential_Profiles_V1.2_Level2_Revision8.pdf
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
@NoArgsConstructor(access= AccessLevel.PROTECTED)
|
||||
@Entity
|
||||
public class EndorsementCredential extends DeviceAssociatedCertificate {
|
||||
|
||||
// Indices for ASN1 OBJ items needed for parsing information
|
||||
private static final int ASN1_OBJ_ID = 0;
|
||||
private static final int ASN1_OBJ_PRIMITIVE = 1;
|
||||
private static final int ASN1_FAMILY_INDEX = 0;
|
||||
private static final int ASN1_LEVEL_INDEX = 1;
|
||||
private static final int ASN1_REV_INDEX = 2;
|
||||
private static final int ASN1_VER_INDEX = 0;
|
||||
private static final int ASN1_UPGRADEABLE_INDEX = 1;
|
||||
|
||||
private static final int EK_LOC_VAL_MIN = 0;
|
||||
private static final int EK_LOC_VAL_MAX = 2;
|
||||
private static final int EK_TYPE_VAL_MIN = 0;
|
||||
private static final int EK_TYPE_VAL_MAX = 3;
|
||||
|
||||
// EK Tag index values
|
||||
private static final int EK_TYPE_TAG = 0;
|
||||
private static final int EK_LOC_TAG = 1;
|
||||
private static final int EK_CERT_LOC_TAG = 2;
|
||||
|
||||
private static final int ASN1_SEQ_UNKNOWN_SIZE = 2;
|
||||
private static final int ASN1_SEQ_KNOWN_SIZE = 3;
|
||||
|
||||
private static final String TPM_MODEL = "2.23.133.2.2";
|
||||
|
||||
private static final String TPM_VERSION = "2.23.133.2.3";
|
||||
|
||||
private static final String TPM_MANUFACTURER = "2.23.133.2.1";
|
||||
|
||||
private static final String TPM_SPECIFICATION = "2.23.133.2.16";
|
||||
|
||||
private static final String TPM_SECURITY_ASSERTIONS = "2.23.133.2.18";
|
||||
|
||||
private static final String CREDENTIAL_TYPE_LABEL = "1.3.6.1.5.5.7.2.2";
|
||||
|
||||
// number of extra bytes potentially present in a cert header.
|
||||
private static final int EK_CERT_HEADER_BYTE_COUNT = 7;
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(EndorsementCredential.class);
|
||||
|
||||
/**
|
||||
* This class enables the retrieval of EndorsementCredential by their attributes.
|
||||
*/
|
||||
// public static class Selector extends CertificateSelector<EndorsementCredential> {
|
||||
// /**
|
||||
// * Construct a new CertificateSelector that will use the given {@link CertificateManager} to
|
||||
// * retrieve one or many EndorsementCredentials.
|
||||
// *
|
||||
// * @param certificateManager the certificate manager to be used to retrieve certificates
|
||||
// */
|
||||
// public Selector(final CertificateManager certificateManager) {
|
||||
// super(certificateManager, EndorsementCredential.class);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a manufacturer that certificates must have to be considered as matching.
|
||||
// * @param manufacturer the manufacturer to query, not empty or null
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byManufacturer(final String manufacturer) {
|
||||
// setFieldValue(MANUFACTURER_FIELD, manufacturer);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a model that certificates must have to be considered as matching.
|
||||
// * @param model the model to query, not empty or null
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byModel(final String model) {
|
||||
// setFieldValue(MODEL_FIELD, model);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a version that certificates must have to be considered as matching.
|
||||
// * @param version the version to query, not empty or null
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byVersion(final String version) {
|
||||
// setFieldValue(VERSION_FIELD, version);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a device id that certificates must have to be considered
|
||||
// * as matching.
|
||||
// *
|
||||
// * @param device the device id to query
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byDeviceId(final UUID device) {
|
||||
// setFieldValue(DEVICE_ID_FIELD, device);
|
||||
// return this;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Get a Selector for use in retrieving EndorsementCredentials.
|
||||
// *
|
||||
// * @param certMan the CertificateManager to be used to retrieve persisted certificates
|
||||
// * @return a EndorsementCredential.Selector instance to use for retrieving certificates
|
||||
// */
|
||||
// public static Selector select(final CertificateManager certMan) {
|
||||
// return new Selector(certMan);
|
||||
// }
|
||||
|
||||
/**
|
||||
* this field is part of the TCG EC specification, but has not yet been found in
|
||||
* manufacturer-provided ECs, and is therefore not currently parsed
|
||||
*/
|
||||
@Getter
|
||||
@Column
|
||||
private String credentialType = "TCPA Trusted Platform Module Endorsement";
|
||||
|
||||
private static final String MANUFACTURER_FIELD = "manufacturer";
|
||||
@Getter
|
||||
@Column
|
||||
private String manufacturer = null;
|
||||
|
||||
private static final String MODEL_FIELD = "model";
|
||||
@Getter
|
||||
@Column
|
||||
private String model = null;
|
||||
|
||||
private static final String VERSION_FIELD = "version";
|
||||
@Getter
|
||||
@Column
|
||||
private String version = null;
|
||||
|
||||
@Getter
|
||||
@Embedded
|
||||
private TPMSpecification tpmSpecification = null;
|
||||
|
||||
@Getter
|
||||
@Embedded
|
||||
private TPMSecurityAssertions tpmSecurityAssertions = null; //optional
|
||||
|
||||
/*
|
||||
* this field is part of the TCG EC specification, but has not yet been found in
|
||||
* manufacturer-provided ECs, and is therefore not currently parsed
|
||||
*/
|
||||
@Getter
|
||||
@Column(nullable = true)
|
||||
private String policyReference = null; // optional
|
||||
|
||||
/*
|
||||
* this field is part of the TCG EC specification, but has not yet been found in
|
||||
* manufacturer-provided ECs, and is therefore not currently parsed
|
||||
*/
|
||||
@Getter
|
||||
@Column(nullable = true)
|
||||
private String revocationLocator = null; // optional
|
||||
|
||||
@Transient
|
||||
private Set<String> expectedOids;
|
||||
|
||||
@Transient
|
||||
private Map<String, Object> parsedFields;
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(EndorsementCredential.class);
|
||||
|
||||
/**
|
||||
* Construct a new EndorsementCredential given its binary contents. The given
|
||||
* certificate should represent either an X509 certificate or X509 attribute certificate.
|
||||
*
|
||||
* @param certificateBytes the contents of a certificate file
|
||||
* @throws java.io.IOException if there is a problem extracting information from the certificate
|
||||
*/
|
||||
public EndorsementCredential(final byte[] certificateBytes) throws IOException {
|
||||
super(certificateBytes);
|
||||
parseCertificate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new EndorsementCredential by parsing the file at the given path. The given
|
||||
* certificate should represent either an X509 certificate or X509 attribute certificate.
|
||||
*
|
||||
* @param certificatePath the path on disk to a certificate
|
||||
* @throws java.io.IOException if there is a problem reading the file
|
||||
*/
|
||||
public EndorsementCredential(final Path certificatePath) throws IOException {
|
||||
this(readBytes(certificatePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the bytes as an EK. If parsing fails initially, the optionally present header
|
||||
* is removed and tried again. The cert header, if present, contains some certificate length
|
||||
* information which isn't needed for parsing.
|
||||
* @param certificateBytes the bytes of the EC
|
||||
* @return the EC if a valid credential, null otherwise
|
||||
*/
|
||||
public static EndorsementCredential parseWithPossibleHeader(final byte[] certificateBytes) {
|
||||
|
||||
try {
|
||||
// first, attempt parsing as is
|
||||
return new EndorsementCredential(certificateBytes);
|
||||
} catch (Exception e) {
|
||||
// attempt parsing again after removing extra header bytes.
|
||||
if (certificateBytes.length <= EK_CERT_HEADER_BYTE_COUNT) {
|
||||
throw new IllegalArgumentException("EK parsing failed (only one attempt "
|
||||
+ "possible", e);
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug("Attempting parse after removing extra header bytes");
|
||||
try {
|
||||
byte[] truncatedBytes = ArrayUtils.subarray(
|
||||
certificateBytes, EK_CERT_HEADER_BYTE_COUNT,
|
||||
certificateBytes.length);
|
||||
return new EndorsementCredential(truncatedBytes);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Failed to parse EK after multiple attempts", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the OID fields for the parser to search for and prepares a
|
||||
* hashmap field to hold the discovered values. Must be called once before
|
||||
* an ASN1Primitive can be parsed.
|
||||
*/
|
||||
private void prepareParser() {
|
||||
expectedOids = new HashSet<>();
|
||||
expectedOids.add(TPM_MODEL);
|
||||
expectedOids.add(TPM_VERSION);
|
||||
expectedOids.add(TPM_MANUFACTURER);
|
||||
expectedOids.add(TPM_SPECIFICATION);
|
||||
expectedOids.add(TPM_SECURITY_ASSERTIONS);
|
||||
expectedOids.add(CREDENTIAL_TYPE_LABEL);
|
||||
parsedFields = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the bytes of an X509 certificate and parses them to extract the relevant fields of an
|
||||
* Endorsement Credential Certificate. This works by making a single pass through all of the
|
||||
* ASN1Primitives in the certificate and searches for matching OID keys of specific values. If
|
||||
* matching OID keys are found, their values are encoded in the fields of the current
|
||||
* EndorsementCredential object.
|
||||
* @throws java.io.IOException the input certificate bytes were not readable into an X509
|
||||
* certificate format
|
||||
*/
|
||||
private void parseCertificate() throws IOException {
|
||||
prepareParser();
|
||||
// although we start with a byte representation, we need to change the encoding to
|
||||
// make it parseable
|
||||
ASN1InputStream asn1In = null;
|
||||
try {
|
||||
X509Certificate ec = super.getX509Certificate();
|
||||
asn1In = new ASN1InputStream(ec.getEncoded());
|
||||
|
||||
ASN1Primitive obj = asn1In.readObject();
|
||||
ASN1Sequence seq;
|
||||
|
||||
while (obj != null) {
|
||||
seq = ASN1Sequence.getInstance(obj);
|
||||
parseSequence(seq, false, null);
|
||||
obj = asn1In.readObject();
|
||||
}
|
||||
} catch (CertificateException e) {
|
||||
throw new IOException("Couldn't read certificate bytes");
|
||||
} finally {
|
||||
if (asn1In != null) {
|
||||
asn1In.close();
|
||||
}
|
||||
}
|
||||
|
||||
String oid;
|
||||
Object value;
|
||||
// unpack fields from parsedFields and set field values
|
||||
for (Map.Entry<String, Object> entry : parsedFields.entrySet()) {
|
||||
oid = entry.getKey();
|
||||
value = entry.getValue();
|
||||
if (oid.equals(TPM_MODEL)) {
|
||||
model = value.toString();
|
||||
LOGGER.debug("Found TPM Model: " + model);
|
||||
} else if (oid.equals(TPM_VERSION)) {
|
||||
version = value.toString();
|
||||
LOGGER.debug("Found TPM Version: " + version);
|
||||
} else if (oid.equals(TPM_MANUFACTURER)) {
|
||||
manufacturer = value.toString();
|
||||
LOGGER.debug("Found TPM Manufacturer: " + manufacturer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the ASN1Sequence type by iteratively unpacking each successive element. If,
|
||||
* however, the method is set to add the sequence to the OID mapping, it may search for
|
||||
* patterns that correspond to the TPM Security Assertions and TPM Specification and set
|
||||
* those fields appropriately.
|
||||
* @param seq the sequence to parse
|
||||
* @param addToMapping whether or not to store the sequence value as an OID key/value value
|
||||
* @param key the associated OID key with this value necessary if addToMapping is true
|
||||
* @throws java.io.IOException parsing individual subcomponents failed
|
||||
*/
|
||||
private void parseSequence(final ASN1Sequence seq, final boolean addToMapping,
|
||||
final String key) throws IOException {
|
||||
// need to check if an OID/Value pair
|
||||
// it is possible these pairs could be in a larger sequence of size != 2
|
||||
// but it appears that all expected TPM related fields are of size 2.
|
||||
// The other larger ones are only used for generic X509 fields, which we
|
||||
// don't need to extract here.
|
||||
if (seq.size() == ASN1_SEQ_UNKNOWN_SIZE) {
|
||||
ASN1Encodable obj1 = seq.getObjectAt(ASN1_OBJ_ID);
|
||||
ASN1Encodable obj2 = seq.getObjectAt(ASN1_OBJ_PRIMITIVE);
|
||||
if (obj1 instanceof ASN1ObjectIdentifier) {
|
||||
String oid = ((ASN1ObjectIdentifier) obj1).getId();
|
||||
if (expectedOids.contains(oid)) {
|
||||
// parse and put object 2
|
||||
parseSingle((ASN1Primitive) obj2, true, oid);
|
||||
} else {
|
||||
// there may be subfields that are expected, so continue parsing
|
||||
parseSingle((ASN1Primitive) obj2, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
// The next two are special sequences that have already been matched with an OID.
|
||||
} else if (addToMapping && key.equals(TPM_SPECIFICATION)
|
||||
&& seq.size() == ASN1_SEQ_KNOWN_SIZE) {
|
||||
// Parse TPM Specification
|
||||
DERUTF8String family = (DERUTF8String) seq.getObjectAt(ASN1_FAMILY_INDEX);
|
||||
ASN1Integer level = (ASN1Integer) seq.getObjectAt(ASN1_LEVEL_INDEX);
|
||||
ASN1Integer revision = (ASN1Integer) seq.getObjectAt(ASN1_REV_INDEX);
|
||||
tpmSpecification = new TPMSpecification(family.getString(), level.getValue(),
|
||||
revision.getValue());
|
||||
LOGGER.debug("Found TPM Spec:" + tpmSpecification.toString());
|
||||
} else if (addToMapping && key.equals(TPM_SECURITY_ASSERTIONS)) {
|
||||
// Parse TPM Security Assertions
|
||||
int seqPosition = 0;
|
||||
|
||||
ASN1Integer ver;
|
||||
// Parse Security Assertions Version
|
||||
if (seq.getObjectAt(seqPosition) instanceof ASN1Integer) {
|
||||
ver = (ASN1Integer) seq.getObjectAt(seqPosition);
|
||||
seqPosition++;
|
||||
} else {
|
||||
// Default value of 1 if field not found
|
||||
ver = new ASN1Integer(BigInteger.ONE);
|
||||
}
|
||||
|
||||
ASN1Boolean fieldUpgradeable;
|
||||
// Parse Security Assertions Field Upgradeable
|
||||
if (seq.getObjectAt(seqPosition) instanceof ASN1Boolean) {
|
||||
fieldUpgradeable = (ASN1Boolean) seq.getObjectAt(seqPosition);
|
||||
seqPosition++;
|
||||
} else {
|
||||
// Default value of false if field not found
|
||||
fieldUpgradeable = ASN1Boolean.getInstance(false);
|
||||
}
|
||||
|
||||
tpmSecurityAssertions = new TPMSecurityAssertions(ver.getValue(),
|
||||
fieldUpgradeable.isTrue());
|
||||
|
||||
LOGGER.debug("Found TPM Assertions: " + tpmSecurityAssertions.toString());
|
||||
// Iterate through remaining fields to set optional attributes
|
||||
int tag;
|
||||
DERTaggedObject obj;
|
||||
for (int i = seqPosition; i < seq.size(); i++) {
|
||||
if (seq.getObjectAt(i) instanceof DERTaggedObject) {
|
||||
obj = (DERTaggedObject) seq.getObjectAt(i);
|
||||
tag = obj.getTagNo();
|
||||
if (tag == EK_TYPE_TAG) {
|
||||
int ekGenTypeVal = ((ASN1Enumerated) obj.getObject()).getValue().intValue();
|
||||
if (ekGenTypeVal >= EK_TYPE_VAL_MIN && ekGenTypeVal <= EK_TYPE_VAL_MAX) {
|
||||
TPMSecurityAssertions.EkGenerationType ekGenType
|
||||
= TPMSecurityAssertions.EkGenerationType.values()[ekGenTypeVal];
|
||||
tpmSecurityAssertions.setEkGenType(ekGenType);
|
||||
}
|
||||
} else if (tag == EK_LOC_TAG) {
|
||||
int ekGenLocVal = ((ASN1Enumerated) obj.getObject()).getValue().intValue();
|
||||
if (ekGenLocVal >= EK_LOC_VAL_MIN && ekGenLocVal <= EK_LOC_VAL_MAX) {
|
||||
TPMSecurityAssertions.EkGenerationLocation ekGenLocation
|
||||
= TPMSecurityAssertions.EkGenerationLocation.values()[ekGenLocVal];
|
||||
tpmSecurityAssertions.setEkGenerationLocation(ekGenLocation);
|
||||
}
|
||||
} else if (tag == EK_CERT_LOC_TAG) {
|
||||
int ekCertGenLocVal = ((ASN1Enumerated) obj.getObject())
|
||||
.getValue().intValue();
|
||||
if (ekCertGenLocVal >= EK_LOC_VAL_MIN
|
||||
&& ekCertGenLocVal <= EK_LOC_VAL_MAX) {
|
||||
TPMSecurityAssertions.EkGenerationLocation ekCertGenLoc
|
||||
= TPMSecurityAssertions.EkGenerationLocation.
|
||||
values()[ekCertGenLocVal];
|
||||
tpmSecurityAssertions.setEkGenerationLocation(ekCertGenLoc);
|
||||
}
|
||||
}
|
||||
// ccInfo, fipsLevel, iso9000Certified, and iso9000Uri still to be implemented
|
||||
}
|
||||
// Will need additional else if case in the future for instanceof ASN1Boolean when
|
||||
// supporting TPMSecurityAssertions iso9000Certified field, which could be either
|
||||
// DERTaggedObject or ASN1Boolean
|
||||
}
|
||||
} else {
|
||||
//parse the elements of the sequence individually
|
||||
for (ASN1Encodable component : seq) {
|
||||
parseSingle((ASN1Primitive) component, false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the many different types of ASN1Primitives and searches for specific OID
|
||||
* key/value pairs. Works by traversing the entire ASN1Primitive tree with a single
|
||||
* pass and populates relevant fields in the EndorsementCredential object.
|
||||
* @param component the ASN1Primitive to parse
|
||||
* @param addToMapping whether or not the current component has been matched as the
|
||||
* value in an expected TPM OID key/value pair
|
||||
* @param key if addToMapping is true, the key in the OID key/value pair
|
||||
* @throws java.io.IOException parsing of subcomponents in the tree failed.
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:methodlength")
|
||||
private void parseSingle(final ASN1Primitive component, final boolean addToMapping,
|
||||
final String key) throws IOException {
|
||||
// null check the key if addToMapping is true
|
||||
if (addToMapping && StringUtils.isEmpty(key)) {
|
||||
throw new IllegalArgumentException("Key cannot be empty if adding to field mapping");
|
||||
}
|
||||
|
||||
if (component instanceof ASN1Sequence) {
|
||||
parseSequence((ASN1Sequence) component, addToMapping, key);
|
||||
|
||||
} else if (component instanceof DERUTF8String) {
|
||||
if (addToMapping) {
|
||||
DERUTF8String nameData = (DERUTF8String) component;
|
||||
parsedFields.put(key, nameData.getString());
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1ObjectIdentifier) {
|
||||
if (addToMapping) {
|
||||
// shouldn't ever be reached, but just in case
|
||||
parsedFields.put(key, ((ASN1ObjectIdentifier) component).getId());
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1TaggedObject) {
|
||||
ASN1TaggedObject taggedObj = (ASN1TaggedObject) component;
|
||||
parseSingle(taggedObj.getObject(), addToMapping, key);
|
||||
|
||||
} else if (component instanceof ASN1OctetString) {
|
||||
// this may contain parseable data or may just be a OID key-pair value
|
||||
ASN1OctetString octStr = (ASN1OctetString) component;
|
||||
byte[] bytes = octStr.getOctets();
|
||||
ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
|
||||
ASN1InputStream octIn = new ASN1InputStream(inStream);
|
||||
try {
|
||||
ASN1Encodable newComp = octIn.readObject();
|
||||
parseSingle((ASN1Primitive) newComp, false, null);
|
||||
} catch (IOException e) {
|
||||
// this means octet string didn't contain parsable data, so store the
|
||||
// value as is
|
||||
if (addToMapping) {
|
||||
parsedFields.put(key, bytes);
|
||||
}
|
||||
} finally {
|
||||
if (octIn != null) {
|
||||
octIn.close();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1Set) {
|
||||
// all ECs seen to this point use sets differently than sequences and their sets
|
||||
// don't contain top level OIDs, so we can parse everything term by term, if that
|
||||
// ceases to be the case, we need to switch to this parsing to be more like
|
||||
// parseSequences in the future
|
||||
ASN1Set set = (ASN1Set) component;
|
||||
Enumeration setContents = set.getObjects();
|
||||
ASN1Encodable subComp;
|
||||
while (setContents.hasMoreElements()) {
|
||||
subComp = (ASN1Encodable) setContents.nextElement();
|
||||
if (subComp instanceof ASN1ObjectIdentifier) {
|
||||
LOGGER.warn("OID in top level of ASN1Set");
|
||||
}
|
||||
parseSingle((ASN1Primitive) subComp, addToMapping, key);
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1Boolean) {
|
||||
if (addToMapping) {
|
||||
boolean fieldVal = ((ASN1Boolean) component).isTrue();
|
||||
parsedFields.put(key, fieldVal);
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1BitString) {
|
||||
// I don't think this contains more fields and needs to be reparsed,
|
||||
// though not 100% sure
|
||||
if (addToMapping) {
|
||||
byte[] bytes = ((ASN1BitString) component).getBytes();
|
||||
parsedFields.put(key, bytes);
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1Integer) {
|
||||
if (addToMapping) {
|
||||
BigInteger bigInt = ((ASN1Integer) component).getValue();
|
||||
parsedFields.put(key, bigInt);
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1Null) {
|
||||
if (addToMapping) {
|
||||
parsedFields.put(key, null);
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1UTCTime) {
|
||||
if (addToMapping) {
|
||||
try {
|
||||
parsedFields.put(key, ((ASN1UTCTime) component).getDate());
|
||||
} catch (ParseException pe) {
|
||||
pe.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (component instanceof DERPrintableString) {
|
||||
if (addToMapping) {
|
||||
parsedFields.put(key, ((DERPrintableString) component).getString());
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1Enumerated) {
|
||||
if (addToMapping) {
|
||||
BigInteger value = ((ASN1Enumerated) component).getValue();
|
||||
parsedFields.put(key, value);
|
||||
}
|
||||
// after about this point, I doubt we'll see any of the following field types, but
|
||||
// in the interest of completeness and robustness, they are still parsed
|
||||
} else if (component instanceof DERIA5String) {
|
||||
if (addToMapping) {
|
||||
String ia5Str = ((DERIA5String) component).getString();
|
||||
parsedFields.put(key, ia5Str);
|
||||
}
|
||||
|
||||
} else if (component instanceof DERNumericString) {
|
||||
if (addToMapping) {
|
||||
String numStr = ((DERNumericString) component).getString();
|
||||
parsedFields.put(key, numStr);
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1GeneralizedTime) {
|
||||
if (addToMapping) {
|
||||
try {
|
||||
parsedFields.put(key, ((ASN1GeneralizedTime) component).getDate());
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (component instanceof ASN1ApplicationSpecific) {
|
||||
parseSingle(((ASN1ApplicationSpecific) component).getObject(), addToMapping, key);
|
||||
|
||||
} else if (component instanceof DERBMPString) {
|
||||
if (addToMapping) {
|
||||
String bmpStr = ((DERBMPString) component).getString();
|
||||
parsedFields.put(key, bmpStr);
|
||||
}
|
||||
|
||||
} else if (component instanceof DERExternal) {
|
||||
parseSingle(((DERExternal) component).getExternalContent(), addToMapping, key);
|
||||
|
||||
} else if (component instanceof DERGeneralString) {
|
||||
if (addToMapping) {
|
||||
String generalStr = ((DERGeneralString) component).getString();
|
||||
parsedFields.put(key, generalStr);
|
||||
}
|
||||
|
||||
} else if (component instanceof DERT61String) {
|
||||
if (addToMapping) {
|
||||
String t61Str = ((DERT61String) component).getString();
|
||||
parsedFields.put(key, t61Str);
|
||||
}
|
||||
|
||||
} else if (component instanceof DERUniversalString) {
|
||||
if (addToMapping) {
|
||||
String univStr = ((DERUniversalString) component).getString();
|
||||
parsedFields.put(key, univStr);
|
||||
}
|
||||
|
||||
} else if (component instanceof DERVisibleString) {
|
||||
if (addToMapping) {
|
||||
String visStr = ((DERVisibleString) component).getString();
|
||||
parsedFields.put(key, visStr);
|
||||
}
|
||||
|
||||
} else {
|
||||
// there are some deprecated types that we don't parse
|
||||
LOGGER.error("Unparsed type: " + component.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the credential type label.
|
||||
* @return the credential type label.
|
||||
*/
|
||||
public String getCredentialType() {
|
||||
return credentialType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TPM Manufacturer.
|
||||
* @return the TPM Manufacturer.
|
||||
*/
|
||||
public String getManufacturer() {
|
||||
return manufacturer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TPM model.
|
||||
* @return the TPM model.
|
||||
*/
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TPM version.
|
||||
* @return the TPM version.
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TPM specification.
|
||||
* @return the TPM specification.
|
||||
*/
|
||||
public TPMSpecification getTpmSpecification() {
|
||||
return tpmSpecification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TPM security assertions.
|
||||
* @return the TPM security assertions.
|
||||
*/
|
||||
public TPMSecurityAssertions getTpmSecurityAssertions() {
|
||||
return tpmSecurityAssertions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the policy reference.
|
||||
* @return the policy reference.
|
||||
*/
|
||||
public String getPolicyReference() {
|
||||
return policyReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the revocation locator.
|
||||
* @return the revocation locator.
|
||||
*/
|
||||
public String getRevocationLocator() {
|
||||
return revocationLocator;
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents an issued attestation certificate to a HIRS Client.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@Getter
|
||||
@Entity
|
||||
public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
|
||||
|
||||
/**
|
||||
* AIC label that must be used.
|
||||
*/
|
||||
public static final String AIC_TYPE_LABEL = "TCPA Trusted Platform Identity";
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "ek_id")
|
||||
private EndorsementCredential endorsementCredential;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "pc_id")
|
||||
private Set<PlatformCredential> platformCredentials;
|
||||
|
||||
/**
|
||||
* This class enables the retrieval of IssuedAttestationCertificate by their attributes.
|
||||
*/
|
||||
// public static class Selector extends CertificateSelector<IssuedAttestationCertificate> {
|
||||
// /**
|
||||
// * Construct a new CertificateSelector that will use the given {@link CertificateManager} to
|
||||
// * retrieve one or many IssuedAttestationCertificate.
|
||||
// *
|
||||
// * @param certificateManager the certificate manager to be used to retrieve certificates
|
||||
// */
|
||||
// public Selector(final CertificateManager certificateManager) {
|
||||
// super(certificateManager, IssuedAttestationCertificate.class);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a device id that certificates must have to be considered
|
||||
// * as matching.
|
||||
// *
|
||||
// * @param device the device id to query
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byDeviceId(final UUID device) {
|
||||
// setFieldValue(DEVICE_ID_FIELD, device);
|
||||
// return this;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Get a Selector for use in retrieving IssuedAttestationCertificate.
|
||||
// *
|
||||
// * @param certMan the CertificateManager to be used to retrieve persisted certificates
|
||||
// * @return a IssuedAttestationCertificate.Selector instance to use for retrieving certificates
|
||||
// */
|
||||
// public static IssuedAttestationCertificate.Selector select(final CertificateManager certMan) {
|
||||
// return new IssuedAttestationCertificate.Selector(certMan);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param certificateBytes the issued certificate bytes
|
||||
* @param endorsementCredential the endorsement credential
|
||||
* @param platformCredentials the platform credentials
|
||||
* @throws java.io.IOException if there is a problem extracting information from the certificate
|
||||
*/
|
||||
public IssuedAttestationCertificate(final byte[] certificateBytes,
|
||||
final EndorsementCredential endorsementCredential,
|
||||
final Set<PlatformCredential> platformCredentials)
|
||||
throws IOException {
|
||||
super(certificateBytes);
|
||||
this.endorsementCredential = endorsementCredential;
|
||||
this.platformCredentials = platformCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param certificatePath path to certificate
|
||||
* @param endorsementCredential the endorsement credential
|
||||
* @param platformCredentials the platform credentials
|
||||
* @throws java.io.IOException if there is a problem extracting information from the certificate
|
||||
*/
|
||||
public IssuedAttestationCertificate(final Path certificatePath,
|
||||
final EndorsementCredential endorsementCredential,
|
||||
final Set<PlatformCredential> platformCredentials)
|
||||
throws IOException {
|
||||
this(readBytes(certificatePath), endorsementCredential, platformCredentials);
|
||||
}
|
||||
|
||||
}
|
@ -1,796 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfigurationV1;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.TBBSecurityAssertion;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.PlatformConfigurationV2;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Transient;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERIA5String;
|
||||
import org.bouncycastle.asn1.DERNull;
|
||||
import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
|
||||
import org.bouncycastle.asn1.x500.RDN;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||
import org.bouncycastle.asn1.x509.Attribute;
|
||||
import org.bouncycastle.asn1.x509.AttributeCertificate;
|
||||
import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
|
||||
import org.bouncycastle.asn1.x509.CertificatePolicies;
|
||||
import org.bouncycastle.asn1.x509.Extension;
|
||||
import org.bouncycastle.asn1.x509.GeneralName;
|
||||
import org.bouncycastle.asn1.x509.GeneralNames;
|
||||
import org.bouncycastle.asn1.x509.PolicyInformation;
|
||||
import org.bouncycastle.asn1.x509.PolicyQualifierInfo;
|
||||
import org.bouncycastle.asn1.x509.UserNotice;
|
||||
import org.bouncycastle.operator.ContentVerifier;
|
||||
import org.bouncycastle.operator.ContentVerifierProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class persists Platform credentials by extending the base Certificate
|
||||
* class with fields unique to a Platform credentials, as defined in the Trusted
|
||||
* Computing Group Credential Profiles, specification v.1.2.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@Entity
|
||||
public class PlatformCredential extends DeviceAssociatedCertificate {
|
||||
private static final Logger LOGGER = LogManager.getLogger(PlatformCredential.class);
|
||||
private static final int TCG_SPECIFICATION_LENGTH = 3;
|
||||
// These are Object Identifiers (OIDs) for sections in the credentials
|
||||
private static final String POLICY_QUALIFIER_CPSURI = "1.3.6.1.5.5.7.2.1";
|
||||
private static final String POLICY_QUALIFIER_USER_NOTICE = "1.3.6.1.5.5.7.2.2";
|
||||
|
||||
// OID for TCG Attributes
|
||||
private static final String PLATFORM_MANUFACTURER = "2.23.133.2.4";
|
||||
private static final String PLATFORM_MODEL = "2.23.133.2.5";
|
||||
private static final String PLATFORM_VERSION = "2.23.133.2.6";
|
||||
private static final String PLATFORM_SERIAL = "2.23.133.2.23";
|
||||
private static final String PLATFORM_BASEBOARD_CHASSIS_COMBINED = "2.23.133.5.1.6";
|
||||
|
||||
// OID for TCG Platform Class Common Attributes
|
||||
private static final String PLATFORM_MANUFACTURER_2_0 = "2.23.133.5.1.1";
|
||||
private static final String PLATFORM_MODEL_2_0 = "2.23.133.5.1.4";
|
||||
private static final String PLATFORM_VERSION_2_0 = "2.23.133.5.1.5";
|
||||
private static final String PLATFORM_SERIAL_2_0 = "2.23.133.5.1.6";
|
||||
|
||||
// OID for Certificate Attributes
|
||||
private static final String TCG_PLATFORM_SPECIFICATION = "2.23.133.2.17";
|
||||
private static final String TPM_SECURITY_ASSERTION = "2.23.133.2.18";
|
||||
private static final String TBB_SECURITY_ASSERTION = "2.23.133.2.19";
|
||||
private static final String TCG_CREDENTIAL_SPECIFICATION = "2.23.133.2.23";
|
||||
private static final String PLATFORM_CONFIGURATION_URI = "2.23.133.5.1.3";
|
||||
private static final String PLATFORM_CONFIGURATION = "2.23.133.5.1.7.1";
|
||||
private static final String PLATFORM_CONFIGURATION_V2 = "2.23.133.5.1.7.2";
|
||||
private static final String PLATFORM_CREDENTIAL_TYPE = "2.23.133.2.25";
|
||||
private static final String PLATFORM_BASE_CERT = "2.23.133.8.2";
|
||||
private static final String PLATFORM_DELTA_CERT = "2.23.133.8.5";
|
||||
|
||||
/**
|
||||
* TCG Platform Specification values
|
||||
* At this time these are placeholder values.
|
||||
*/
|
||||
private static final Map<String, String> TCG_PLATFORM_MAP = new HashMap<String, String>() {{
|
||||
put("#00000000", "Unclassified");
|
||||
put("#00000001", "PC Client");
|
||||
put("#00000002", "PDA");
|
||||
put("#00000003", "CELLPHONE");
|
||||
put("#00000004", "SERVER");
|
||||
put("#00000005", "PERIPHERAL");
|
||||
put("#00000006", "TSS");
|
||||
put("#00000007", "STORAGE");
|
||||
put("#00000008", "AUTHENTICATION");
|
||||
put("#00000009", "EMBEDDED");
|
||||
put("#00000010", "HARD COPY");
|
||||
put("#00000011", "INFRASTRUCTURE");
|
||||
put("#00000012", "VIRTUALIZATION");
|
||||
put("#00000013", "TNC");
|
||||
put("#00000014", "MULTI-TENANT");
|
||||
}};
|
||||
|
||||
// number of extra bytes potentially present in a cert header.
|
||||
private static final int PC_CERT_HEADER_BYTE_COUNT = 8;
|
||||
|
||||
/**
|
||||
* TCPA Trusted Platform Endorsement.
|
||||
*/
|
||||
public static final String CERTIFICATE_TYPE_1_2 = "TCPA Trusted Platform Endorsement";
|
||||
|
||||
/**
|
||||
* TCG Trusted Platform Endorsement.
|
||||
*/
|
||||
public static final String CERTIFICATE_TYPE_2_0 = "TCG Trusted Platform Endorsement";
|
||||
|
||||
/**
|
||||
* This class enables the retrieval of PlatformCredentials by their attributes.
|
||||
*/
|
||||
// public static class Selector extends CertificateSelector<PlatformCredential> {
|
||||
// /**
|
||||
// * Construct a new CertificateSelector that will use the given {@link CertificateManager} to
|
||||
// * retrieve one or many PlatformCredentials.
|
||||
// *
|
||||
// * @param certificateManager the certificate manager to be used to retrieve certificates
|
||||
// */
|
||||
// public Selector(final CertificateManager certificateManager) {
|
||||
// super(certificateManager, PlatformCredential.class);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a manufacturer that certificates must have to be considered as matching.
|
||||
// * @param manufacturer the manufacturer to query, not empty or null
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byManufacturer(final String manufacturer) {
|
||||
// setFieldValue(MANUFACTURER_FIELD, manufacturer);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a model that certificates must have to be considered as matching.
|
||||
// * @param model the model to query, not empty or null
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byModel(final String model) {
|
||||
// setFieldValue(MODEL_FIELD, model);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a version that certificates must have to be considered as matching.
|
||||
// * @param version the version to query, not empty or null
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byVersion(final String version) {
|
||||
// setFieldValue(VERSION_FIELD, version);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a serial number that certificates must have to be considered as matching.
|
||||
// * @param serialNumber the serial number to query, not empty or null
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector bySerialNumber(final String serialNumber) {
|
||||
// setFieldValue(SERIAL_NUMBER_FIELD, serialNumber);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a board serial number that certificates must have to be considered as matching.
|
||||
// * @param boardSerialNumber the board serial number to query, not empty or null
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byBoardSerialNumber(final String boardSerialNumber) {
|
||||
// setFieldValue(PLATFORM_SERIAL_FIELD, boardSerialNumber);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a chassis serial number that certificates must have to be considered as matching.
|
||||
// * @param chassisSerialNumber the board serial number to query, not empty or null
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byChassisSerialNumber(final String chassisSerialNumber) {
|
||||
// setFieldValue(CHASSIS_SERIAL_NUMBER_FIELD, chassisSerialNumber);
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Specify a device id that certificates must have to be considered
|
||||
// * as matching.
|
||||
// *
|
||||
// * @param device the device id to query
|
||||
// * @return this instance (for chaining further calls)
|
||||
// */
|
||||
// public Selector byDeviceId(final UUID device) {
|
||||
// setFieldValue(DEVICE_ID_FIELD, device);
|
||||
// return this;
|
||||
// }
|
||||
// }
|
||||
|
||||
@Column
|
||||
private String credentialType = null;
|
||||
|
||||
@Column
|
||||
private boolean platformBase = false;
|
||||
|
||||
private static final String MANUFACTURER_FIELD = "manufacturer";
|
||||
@Column
|
||||
private String manufacturer = null;
|
||||
|
||||
private static final String MODEL_FIELD = "model";
|
||||
@Column
|
||||
private String model = null;
|
||||
|
||||
private static final String VERSION_FIELD = "version";
|
||||
@Column
|
||||
private String version = null;
|
||||
|
||||
private static final String PLATFORM_SERIAL_FIELD = "platformSerial";
|
||||
@Column
|
||||
private String platformSerial = null;
|
||||
|
||||
private static final String CHASSIS_SERIAL_NUMBER_FIELD = "chassisSerialNumber";
|
||||
@Column
|
||||
private String chassisSerialNumber;
|
||||
|
||||
@Column
|
||||
private int majorVersion = 0;
|
||||
|
||||
@Column
|
||||
private int minorVersion = 0;
|
||||
|
||||
@Column
|
||||
private int revisionLevel = 0;
|
||||
|
||||
@Column
|
||||
private int tcgCredentialMajorVersion = 0;
|
||||
|
||||
@Column
|
||||
private int tcgCredentialMinorVersion = 0;
|
||||
|
||||
@Column
|
||||
private int tcgCredentialRevisionLevel = 0;
|
||||
|
||||
@Column
|
||||
private String platformClass = null;
|
||||
|
||||
@Column(length = MAX_MESSAGE_LENGTH)
|
||||
private String componentFailures = Strings.EMPTY;
|
||||
|
||||
@Transient
|
||||
private EndorsementCredential endorsementCredential = null;
|
||||
|
||||
private String platformChainType = Strings.EMPTY;
|
||||
private boolean isDeltaChain = false;
|
||||
|
||||
|
||||
/**
|
||||
* Get a Selector for use in retrieving PlatformCredentials.
|
||||
*
|
||||
* @param certMan the CertificateManager to be used to retrieve persisted certificates
|
||||
* @return a PlatformCredential.Selector instance to use for retrieving certificates
|
||||
*/
|
||||
// public static Selector select(final CertificateManager certMan) {
|
||||
// return new Selector(certMan);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Construct a new PlatformCredential given its binary contents. ParseFields is
|
||||
* optionally run. The given certificate should represent either an X509 certificate
|
||||
* or X509 attribute certificate.
|
||||
*
|
||||
* @param certificateBytes the contents of a certificate file
|
||||
* @param parseFields boolean True to parse fields
|
||||
* @throws java.io.IOException if there is a problem extracting information from the certificate\
|
||||
*/
|
||||
public PlatformCredential(final byte[] certificateBytes,
|
||||
final boolean parseFields) throws IOException {
|
||||
super(certificateBytes);
|
||||
if (parseFields) {
|
||||
parseFields();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new PlatformCredential given its binary contents. The given
|
||||
* certificate should represent either an X509 certificate or X509 attribute certificate.
|
||||
*
|
||||
* @param certificateBytes the contents of a certificate file
|
||||
* @throws java.io.IOException if there is a problem extracting information from the certificate
|
||||
*/
|
||||
public PlatformCredential(final byte[] certificateBytes) throws IOException {
|
||||
this(certificateBytes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new PlatformCredential by parsing the file at the given path. The given
|
||||
* certificate should represent either an X509 certificate or X509 attribute certificate.
|
||||
*
|
||||
* @param certificatePath the path on disk to a certificate
|
||||
* @throws java.io.IOException if there is a problem reading the file
|
||||
*/
|
||||
public PlatformCredential(final Path certificatePath) throws IOException {
|
||||
this(readBytes(certificatePath), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the signature on the attribute certificate in this holder.
|
||||
*
|
||||
* @param verifierProvider a ContentVerifierProvider that can generate a
|
||||
* verifier for the signature.
|
||||
* @return true if the signature is valid, false otherwise.
|
||||
* @throws java.io.IOException if the signature cannot be processed or is inappropriate.
|
||||
*/
|
||||
public boolean isSignatureValid(final ContentVerifierProvider verifierProvider)
|
||||
throws IOException {
|
||||
AttributeCertificate attCert = getAttributeCertificate();
|
||||
AttributeCertificateInfo acinfo = getAttributeCertificate().getAcinfo();
|
||||
|
||||
// Check if the algorithm identifier is the same
|
||||
if (!isAlgIdEqual(acinfo.getSignature(), attCert.getSignatureAlgorithm())) {
|
||||
throw new IOException("signature invalid - algorithm identifier mismatch");
|
||||
}
|
||||
|
||||
ContentVerifier verifier;
|
||||
|
||||
try {
|
||||
// Set ContentVerifier with the signature that will verify
|
||||
verifier = verifierProvider.get((acinfo.getSignature()));
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new IOException("unable to process signature: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return verifier.verify(attCert.getSignatureValue().getOctets());
|
||||
}
|
||||
/**
|
||||
* Parses the bytes as an PC. If parsing fails initially, the optionally present header
|
||||
* is removed and tried again. The cert header, if present, contains some certificate length
|
||||
* information which isn't needed for parsing.
|
||||
* @param certificateBytes the bytes of the PC
|
||||
* @return the PC if a valid credential, null otherwise
|
||||
*/
|
||||
public static PlatformCredential parseWithPossibleHeader(final byte[] certificateBytes) {
|
||||
PlatformCredential credential = null;
|
||||
|
||||
try {
|
||||
// first, attempt parsing as is
|
||||
credential = new PlatformCredential(certificateBytes);
|
||||
} catch (Exception e) {
|
||||
// attempt parsing again after removing extra header bytes.
|
||||
if (certificateBytes.length > PC_CERT_HEADER_BYTE_COUNT) {
|
||||
LOGGER.debug("Attempting parse after removing extra header bytes");
|
||||
try {
|
||||
byte[] truncatedBytes = ArrayUtils.subarray(
|
||||
certificateBytes, PC_CERT_HEADER_BYTE_COUNT,
|
||||
certificateBytes.length);
|
||||
credential = new PlatformCredential(truncatedBytes);
|
||||
} catch (Exception e1) {
|
||||
LOGGER.warn("Failed to parse PC after multiple attempts", e1);
|
||||
}
|
||||
} else {
|
||||
LOGGER.warn("EK parsing failed (only one attempt possible)", e);
|
||||
}
|
||||
}
|
||||
return credential;
|
||||
}
|
||||
|
||||
private void parseFields() throws IOException {
|
||||
AttributeCertificateInfo certificate = getAttributeCertificate().getAcinfo();
|
||||
Map<String, String> policyQualifier = getPolicyQualifier(certificate);
|
||||
credentialType = policyQualifier.get("userNotice");
|
||||
|
||||
// Parse data based on certificate type (1.2 vs 2.0)
|
||||
switch (credentialType) {
|
||||
case CERTIFICATE_TYPE_1_2:
|
||||
parseAttributeCert(certificate);
|
||||
break;
|
||||
case CERTIFICATE_TYPE_2_0:
|
||||
parseAttributeCert2(certificate);
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Invalid Attribute Credential Type: " + credentialType);
|
||||
}
|
||||
|
||||
// Get TCG Platform Specification Information
|
||||
for (ASN1Encodable enc : certificate.getAttributes().toArray()) {
|
||||
Attribute attr = Attribute.getInstance(enc);
|
||||
if (attr.getAttrType().toString().equals(TCG_PLATFORM_SPECIFICATION)) {
|
||||
ASN1Sequence tcgPlatformSpecification
|
||||
= ASN1Sequence.getInstance(attr.getAttrValues().getObjectAt(0));
|
||||
ASN1Sequence tcgSpecificationVersion
|
||||
= ASN1Sequence.getInstance(tcgPlatformSpecification.getObjectAt(0));
|
||||
|
||||
this.majorVersion = Integer.parseInt(
|
||||
tcgSpecificationVersion.getObjectAt(0).toString());
|
||||
this.minorVersion = Integer.parseInt(
|
||||
tcgSpecificationVersion.getObjectAt(1).toString());
|
||||
this.revisionLevel = Integer.parseInt(
|
||||
tcgSpecificationVersion.getObjectAt(2).toString());
|
||||
|
||||
this.platformClass = tcgPlatformSpecification.getObjectAt(1).toString();
|
||||
} else if (attr.getAttrType().toString().equals(PLATFORM_CREDENTIAL_TYPE)) {
|
||||
ASN1Sequence tcgPlatformType = ASN1Sequence.getInstance(
|
||||
attr.getAttrValues().getObjectAt(0));
|
||||
ASN1ObjectIdentifier platformOid = ASN1ObjectIdentifier.getInstance(
|
||||
tcgPlatformType.getObjectAt(0));
|
||||
|
||||
if (platformOid.getId().equals(PLATFORM_BASE_CERT)) {
|
||||
this.platformBase = true;
|
||||
this.platformChainType = "Base";
|
||||
this.isDeltaChain = true;
|
||||
} else if (platformOid.getId().equals(PLATFORM_DELTA_CERT)) {
|
||||
this.platformBase = false;
|
||||
this.platformChainType = "Delta";
|
||||
this.isDeltaChain = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a 1.2 Platform Certificate (Attribute Certificate).
|
||||
* @param certificate Attribute Certificate
|
||||
*/
|
||||
private void parseAttributeCert(final AttributeCertificateInfo certificate) {
|
||||
Extension subjectAlternativeNameExtension
|
||||
= certificate.getExtensions().getExtension(Extension.subjectAlternativeName);
|
||||
// It contains a Subject Alternative Name Extension
|
||||
if (subjectAlternativeNameExtension != null) {
|
||||
GeneralNames gnames = GeneralNames.getInstance(
|
||||
subjectAlternativeNameExtension.getParsedValue());
|
||||
for (GeneralName gname : gnames.getNames()) {
|
||||
// Check if it's a directoryName [4] Name type
|
||||
if (gname.getTagNo() == GeneralName.directoryName) {
|
||||
X500Name name = X500Name.getInstance(gname.getName());
|
||||
for (RDN rdn: name.getRDNs()) {
|
||||
for (AttributeTypeAndValue attTV: rdn.getTypesAndValues()) {
|
||||
switch (attTV.getType().toString()) {
|
||||
case PLATFORM_MANUFACTURER:
|
||||
this.manufacturer = attTV.getValue().toString();
|
||||
break;
|
||||
case PLATFORM_MODEL:
|
||||
this.model = attTV.getValue().toString();
|
||||
break;
|
||||
case PLATFORM_VERSION:
|
||||
this.version = attTV.getValue().toString();
|
||||
break;
|
||||
case PLATFORM_SERIAL:
|
||||
this.platformSerial = attTV.getValue().toString();
|
||||
break;
|
||||
case PLATFORM_BASEBOARD_CHASSIS_COMBINED:
|
||||
String[] combinedValues = attTV.getValue()
|
||||
.toString()
|
||||
.split(",");
|
||||
if (combinedValues.length != 2) {
|
||||
LOGGER.warn("Unable to parse combined "
|
||||
+ "baseboard/chassis SN field");
|
||||
} else {
|
||||
this.chassisSerialNumber = combinedValues[0];
|
||||
this.platformSerial = combinedValues[1];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a 2.0 Platform Certificate (Attribute Certificate).
|
||||
* @param certificate Attribute Certificate
|
||||
*/
|
||||
private void parseAttributeCert2(final AttributeCertificateInfo certificate)
|
||||
throws IOException {
|
||||
Extension subjectAlternativeNameExtension
|
||||
= certificate.getExtensions().getExtension(Extension.subjectAlternativeName);
|
||||
|
||||
// It contains a Subject Alternative Name Extension
|
||||
if (subjectAlternativeNameExtension != null) {
|
||||
GeneralNames gnames = GeneralNames.getInstance(
|
||||
subjectAlternativeNameExtension.getParsedValue());
|
||||
for (GeneralName gname : gnames.getNames()) {
|
||||
// Check if it's a directoryName [4] Name type
|
||||
if (gname.getTagNo() == GeneralName.directoryName) {
|
||||
X500Name name = X500Name.getInstance(gname.getName());
|
||||
for (RDN rdn: name.getRDNs()) {
|
||||
for (AttributeTypeAndValue attTV: rdn.getTypesAndValues()) {
|
||||
switch (attTV.getType().toString()) {
|
||||
case PLATFORM_MANUFACTURER_2_0:
|
||||
this.manufacturer = attTV.getValue().toString();
|
||||
break;
|
||||
case PLATFORM_MODEL_2_0:
|
||||
this.model = attTV.getValue().toString();
|
||||
break;
|
||||
case PLATFORM_VERSION_2_0:
|
||||
this.version = attTV.getValue().toString();
|
||||
break;
|
||||
case PLATFORM_SERIAL_2_0:
|
||||
this.platformSerial = attTV.getValue().toString();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get all the attributes map to check for validity
|
||||
try {
|
||||
getAllAttributes();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new IOException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the x509 Platform Certificate version.
|
||||
* @return a big integer representing the certificate version.
|
||||
*/
|
||||
@Override
|
||||
public int getX509CredentialVersion() {
|
||||
try {
|
||||
return getAttributeCertificate()
|
||||
.getAcinfo()
|
||||
.getVersion()
|
||||
.getValue().intValue();
|
||||
} catch (IOException ex) {
|
||||
LOGGER.warn("X509 Credential Version not found.");
|
||||
LOGGER.error(ex);
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cPSuri from the Certificate Policies.
|
||||
* @return cPSuri from the CertificatePolicies.
|
||||
* @throws java.io.IOException when reading the certificate.
|
||||
*/
|
||||
public String getCPSuri() throws IOException {
|
||||
Map<String, String> policyQualifier
|
||||
= getPolicyQualifier(getAttributeCertificate().getAcinfo());
|
||||
if (policyQualifier.get("cpsURI") != null && !policyQualifier.get("cpsURI").isEmpty()) {
|
||||
return policyQualifier.get("cpsURI");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Platform Configuration Attribute from the Platform Certificate.
|
||||
* @return a map with all the attributes
|
||||
* @throws IllegalArgumentException when there is a parsing error
|
||||
* @throws java.io.IOException when reading the certificate.
|
||||
*/
|
||||
public Map<String, Object> getAllAttributes()
|
||||
throws IllegalArgumentException, IOException {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
ASN1Sequence attributeSequence;
|
||||
// Check all attributes for Platform Configuration
|
||||
for (ASN1Encodable enc: getAttributeCertificate().getAcinfo().getAttributes().toArray()) {
|
||||
Attribute attr = Attribute.getInstance(enc);
|
||||
attributeSequence
|
||||
= ASN1Sequence.getInstance(attr.getAttrValues().getObjectAt(0));
|
||||
// Parse sequence based on the attribute OID
|
||||
switch (attr.getAttrType().getId()) {
|
||||
case TBB_SECURITY_ASSERTION:
|
||||
attributes.put("tbbSecurityAssertion",
|
||||
new TBBSecurityAssertion(attributeSequence));
|
||||
break;
|
||||
case PLATFORM_CONFIGURATION_URI:
|
||||
attributes.put("platformConfigurationURI",
|
||||
new URIReference(attributeSequence));
|
||||
break;
|
||||
case PLATFORM_CONFIGURATION:
|
||||
attributes.put("platformConfiguration",
|
||||
new PlatformConfigurationV1(attributeSequence));
|
||||
break;
|
||||
case PLATFORM_CONFIGURATION_V2:
|
||||
attributes.put("platformConfiguration",
|
||||
new PlatformConfigurationV2(attributeSequence));
|
||||
break;
|
||||
case TCG_PLATFORM_SPECIFICATION:
|
||||
case PLATFORM_CREDENTIAL_TYPE:
|
||||
// handled in parseFields
|
||||
break;
|
||||
case TCG_CREDENTIAL_SPECIFICATION:
|
||||
getTCGCredentialSpecification(attributeSequence);
|
||||
break;
|
||||
default:
|
||||
// No class defined for this attribute
|
||||
LOGGER.warn("No class defined for attribute with OID: "
|
||||
+ attr.getAttrType().getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified attribute from the Platform Certificate.
|
||||
* @param attributeName to retrieve from the map.
|
||||
* @return an Object with the attribute.
|
||||
* @throws IllegalArgumentException when there is a parsing error
|
||||
* @throws java.io.IOException when reading the certificate.
|
||||
*/
|
||||
public Object getAttribute(final String attributeName)
|
||||
throws IllegalArgumentException, IOException {
|
||||
return getAllAttributes().get(attributeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Platform Configuration Attribute from the Platform Certificate.
|
||||
* @return a map with the Platform Configuration information.
|
||||
* @throws IllegalArgumentException when there is a parsing error
|
||||
* @throws java.io.IOException when reading the certificate.
|
||||
*/
|
||||
public PlatformConfiguration getPlatformConfiguration()
|
||||
throws IllegalArgumentException, IOException {
|
||||
|
||||
if (getAttribute("platformConfiguration") != null
|
||||
&& getAttribute("platformConfiguration") instanceof PlatformConfiguration) {
|
||||
return (PlatformConfiguration) getAttribute("platformConfiguration");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Platform Configuration URI Attribute from the Platform Certificate.
|
||||
* @return an URIReference object to the Platform Configuration URI.
|
||||
* @throws IllegalArgumentException when there is a parsing error
|
||||
* @throws java.io.IOException when reading the certificate.
|
||||
*/
|
||||
public URIReference getPlatformConfigurationURI()
|
||||
throws IllegalArgumentException, IOException {
|
||||
if (getAttribute("platformConfigurationURI") != null
|
||||
&& getAttribute("platformConfigurationURI") instanceof URIReference) {
|
||||
return (URIReference) getAttribute("platformConfigurationURI");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TBB Security Assertion from the Platform Certificate.
|
||||
* @return a TBBSecurityAssertion object.
|
||||
* @throws IllegalArgumentException when there is a parsing error
|
||||
* @throws java.io.IOException when reading the certificate.
|
||||
*/
|
||||
public TBBSecurityAssertion getTBBSecurityAssertion()
|
||||
throws IllegalArgumentException, IOException {
|
||||
if (getAttribute("tbbSecurityAssertion") != null
|
||||
&& getAttribute("tbbSecurityAssertion") instanceof TBBSecurityAssertion) {
|
||||
return (TBBSecurityAssertion) getAttribute("tbbSecurityAssertion");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the TCG Credential fields from a certificate, if provided.
|
||||
*
|
||||
* @param attributeSequence The sequence associated with 2.23.133.2.23
|
||||
*/
|
||||
private void getTCGCredentialSpecification(final ASN1Sequence attributeSequence) {
|
||||
try {
|
||||
this.tcgCredentialMajorVersion = Integer.parseInt(
|
||||
attributeSequence.getObjectAt(0).toString());
|
||||
this.tcgCredentialMinorVersion = Integer.parseInt(
|
||||
attributeSequence.getObjectAt(1).toString());
|
||||
this.tcgCredentialRevisionLevel = Integer.parseInt(
|
||||
attributeSequence.getObjectAt(2).toString());
|
||||
} catch (NumberFormatException nfEx) {
|
||||
// ill-formed ASN1
|
||||
String fieldContents = attributeSequence.toString();
|
||||
|
||||
if (fieldContents != null && fieldContents.contains(",")) {
|
||||
fieldContents = fieldContents.replaceAll("[^a-zA-Z0-9,]", "");
|
||||
String[] fields = fieldContents.split(",");
|
||||
|
||||
if (fields.length == TCG_SPECIFICATION_LENGTH) {
|
||||
this.tcgCredentialMajorVersion = Integer.parseInt(fields[0]);
|
||||
this.tcgCredentialMinorVersion = Integer.parseInt(fields[1]);
|
||||
this.tcgCredentialRevisionLevel = Integer.parseInt(fields[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of component identifiers if there are any.
|
||||
* @return the list of component identifiers if there are any
|
||||
*/
|
||||
public List<ComponentIdentifier> getComponentIdentifiers() {
|
||||
try {
|
||||
PlatformConfiguration platformConfig = getPlatformConfiguration();
|
||||
if (platformConfig != null) {
|
||||
return platformConfig.getComponentIdentifier();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Unable to parse Platform Configuration from Credential or find"
|
||||
+ "component identifiers");
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if the AlgorithmIdentifiers are equal.
|
||||
*
|
||||
* @param id1 AlgorithIdentifier one
|
||||
* @param id2 AlgorithIdentifier two
|
||||
* @return True if are the same, False if not
|
||||
*/
|
||||
public static boolean isAlgIdEqual(final AlgorithmIdentifier id1,
|
||||
final AlgorithmIdentifier id2) {
|
||||
if (!id1.getAlgorithm().equals(id2.getAlgorithm())) {
|
||||
return false;
|
||||
}
|
||||
if (id1.getParameters() == null) {
|
||||
if (id2.getParameters() != null && !id2.getParameters().equals(DERNull.INSTANCE)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (id2.getParameters() == null) {
|
||||
if (id1.getParameters() != null && !id1.getParameters().equals(DERNull.INSTANCE)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return id1.getParameters().equals(id2.getParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PolicyQualifier from the Certificate Policies Extension.
|
||||
*
|
||||
* @param certificate Attribute Certificate information
|
||||
* @return Policy Qualifier from the Certificate Policies Extension
|
||||
*/
|
||||
public static Map<String, String> getPolicyQualifier(
|
||||
final AttributeCertificateInfo certificate) {
|
||||
Preconditions.checkArgument(certificate.getExtensions() != null,
|
||||
"Platform certificate should have extensions.");
|
||||
|
||||
CertificatePolicies certPolicies
|
||||
= CertificatePolicies.fromExtensions(certificate.getExtensions());
|
||||
Map<String, String> policyQualifiers = new HashMap<>();
|
||||
String userNoticeQualifier = "";
|
||||
String cpsURI = "";
|
||||
|
||||
if (certPolicies != null) {
|
||||
// Must contain at least one Policy
|
||||
for (PolicyInformation policy : certPolicies.getPolicyInformation()) {
|
||||
for (ASN1Encodable pQualifierInfo: policy.getPolicyQualifiers().toArray()) {
|
||||
PolicyQualifierInfo info = PolicyQualifierInfo.getInstance(pQualifierInfo);
|
||||
// Subtract the data based on the OID
|
||||
switch (info.getPolicyQualifierId().getId()) {
|
||||
case POLICY_QUALIFIER_CPSURI:
|
||||
cpsURI = DERIA5String.getInstance(info.getQualifier()).getString();
|
||||
break;
|
||||
case POLICY_QUALIFIER_USER_NOTICE:
|
||||
UserNotice userNotice = UserNotice.getInstance(info.getQualifier());
|
||||
userNoticeQualifier = userNotice.getExplicitText().getString();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to map
|
||||
policyQualifiers.put("userNotice", userNoticeQualifier);
|
||||
policyQualifiers.put("cpsURI", cpsURI);
|
||||
|
||||
return policyQualifiers;
|
||||
}
|
||||
}
|
@ -1,300 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bouncycastle.asn1.ASN1Boolean;
|
||||
import org.bouncycastle.asn1.ASN1Enumerated;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.DERIA5String;
|
||||
|
||||
/**
|
||||
* Basic class that handle CommonCriteriaMeasures for the Platform Certificate
|
||||
* Attribute.
|
||||
* <pre>
|
||||
* CommonCriteriaMeasures ::= SEQUENCE {
|
||||
* version IA5STRING (SIZE (1..STRMAX)), "2.2" or "3.1";
|
||||
* assurancelevel EvaluationAssuranceLevel,
|
||||
* evaluationStatus EvaluationStatus,
|
||||
* plus BOOLEAN DEFAULT FALSE,
|
||||
* strengthOfFunction [0] IMPLICIT StrengthOfFunction OPTIONAL,
|
||||
* profileOid [1] IMPLICIT OBJECT IDENTIFIER OPTIONAL,
|
||||
* profileUri [2] IMPLICIT URIReference OPTIONAL,
|
||||
* targetOid [3] IMPLICIT OBJECT IDENTIFIER OPTIONAL,
|
||||
* targetUri [4] IMPLICIT URIReference OPTIONAL }
|
||||
* </pre>
|
||||
*/
|
||||
@Getter @Setter
|
||||
public class CommonCriteriaMeasures {
|
||||
|
||||
private static final int STRENGTH_OF_FUNCTION = 0;
|
||||
private static final int PROFILE_OID = 1;
|
||||
private static final int PROFILE_URI = 2;
|
||||
private static final int TARGET_OID = 3;
|
||||
private static final int TARGET_URI = 4;
|
||||
|
||||
/**
|
||||
* A type to handle the evaluation status used in the Common Criteria Measurement.
|
||||
* Ordering of enum types is intentional and their ordinal values correspond to enum
|
||||
* values in the TCG spec.
|
||||
*
|
||||
* <pre>
|
||||
* EvaluationStatus ::= ENUMERATED {
|
||||
* designedToMeet (0),
|
||||
* evaluationInProgress (1),
|
||||
* evaluationCompleted (2) }
|
||||
* </pre>
|
||||
*/
|
||||
public enum EvaluationStatus {
|
||||
/**
|
||||
* Evaluation designed to meet.
|
||||
*/
|
||||
DESIGNEDTOMEET("designed To Meet"),
|
||||
/**
|
||||
* Evaluation in progress.
|
||||
*/
|
||||
EVALUATIONINPROGRESS("evaluation In Progress"),
|
||||
/**
|
||||
* Evaluation completed.
|
||||
*/
|
||||
EVALUATIONCOMPLETED("evaluation Completed");
|
||||
|
||||
@Getter
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Basic constructor.
|
||||
* @param value string containing the value.
|
||||
*/
|
||||
EvaluationStatus(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A type to handle the strength of function used in the Common Criteria Measurement.
|
||||
* Ordering of enum types is intentional and their ordinal values correspond to enum
|
||||
* values in the TCG spec.
|
||||
*
|
||||
* <pre>
|
||||
* StrengthOfFunction ::= ENUMERATED {
|
||||
* basic (0),
|
||||
* medium (1),
|
||||
* high (2) }
|
||||
* </pre>
|
||||
*/
|
||||
public enum StrengthOfFunction {
|
||||
/**
|
||||
* Basic function.
|
||||
*/
|
||||
BASIC("basic"),
|
||||
/**
|
||||
* Medium function.
|
||||
*/
|
||||
MEDIUM("medium"),
|
||||
/**
|
||||
* Hight function.
|
||||
*/
|
||||
HIGH("high");
|
||||
|
||||
@Getter
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Basic constructor.
|
||||
* @param value string containing the value.
|
||||
*/
|
||||
StrengthOfFunction(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A type to handle the evaluation assurance aevel used in the Common Criteria Measurement.
|
||||
* Ordering of enum types is intentional and their ordinal values correspond to enum
|
||||
* values in the TCG spec.
|
||||
*
|
||||
* <pre>
|
||||
* EvaluationAssuranceLevel ::= ENUMERATED {
|
||||
* levell (1),
|
||||
* level2 (2),
|
||||
* level3 (3),
|
||||
* level4 (4),
|
||||
* level5 (5),
|
||||
* level6 (6),
|
||||
* level7 (7) }
|
||||
* </pre>
|
||||
*/
|
||||
public enum EvaluationAssuranceLevel {
|
||||
/**
|
||||
* Evaluation Assurance Level 1.
|
||||
*/
|
||||
LEVEL1("level 1"),
|
||||
/**
|
||||
* Evaluation Assurance Level 2.
|
||||
*/
|
||||
LEVEL2("level 2"),
|
||||
/**
|
||||
* Evaluation Assurance Level 3.
|
||||
*/
|
||||
LEVEL3("level 3"),
|
||||
/**
|
||||
* Evaluation Assurance Level 4.
|
||||
*/
|
||||
LEVEL4("level 4"),
|
||||
/**
|
||||
* Evaluation Assurance Level 5.
|
||||
*/
|
||||
LEVEL5("level 5"),
|
||||
/**
|
||||
* Evaluation Assurance Level 6.
|
||||
*/
|
||||
LEVEL6("level 6"),
|
||||
/**
|
||||
* Evaluation Assurance Level 7.
|
||||
*/
|
||||
LEVEL7("level 7");
|
||||
|
||||
@Getter
|
||||
private final String value;
|
||||
/**
|
||||
* Basic constructor.
|
||||
* @param value string containing the value.
|
||||
*/
|
||||
EvaluationAssuranceLevel(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private DERIA5String version;
|
||||
private EvaluationAssuranceLevel assuranceLevel;
|
||||
private EvaluationStatus evaluationStatus;
|
||||
private ASN1Boolean plus;
|
||||
private StrengthOfFunction strengthOfFunction;
|
||||
private ASN1ObjectIdentifier profileOid;
|
||||
private URIReference profileUri;
|
||||
private ASN1ObjectIdentifier targetOid;
|
||||
private URIReference targetUri;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public CommonCriteriaMeasures() {
|
||||
this.version = null;
|
||||
this.assuranceLevel = null;
|
||||
this.evaluationStatus = null;
|
||||
this.plus = ASN1Boolean.FALSE;
|
||||
this.strengthOfFunction = null;
|
||||
this.profileOid = null;
|
||||
this.profileUri = null;
|
||||
this.targetOid = null;
|
||||
this.targetUri = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains Common Criteria Measures.
|
||||
* @param sequence containing the the common criteria measures
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public CommonCriteriaMeasures(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
|
||||
//Get all the mandatory values
|
||||
int index = 0;
|
||||
version = DERIA5String.getInstance(sequence.getObjectAt(index));
|
||||
++index;
|
||||
ASN1Enumerated enumarated = ASN1Enumerated.getInstance(sequence.getObjectAt(index));
|
||||
++index;
|
||||
//Throw exception when is not between 1 and 7
|
||||
if (enumarated.getValue().intValue() <= 0
|
||||
|| enumarated.getValue().intValue() > EvaluationAssuranceLevel.values().length) {
|
||||
throw new IllegalArgumentException("Invalid assurance level.");
|
||||
}
|
||||
assuranceLevel = EvaluationAssuranceLevel.values()[enumarated.getValue().intValue() - 1];
|
||||
enumarated = ASN1Enumerated.getInstance(sequence.getObjectAt(index));
|
||||
++index;
|
||||
evaluationStatus = EvaluationStatus.values()[enumarated.getValue().intValue()];
|
||||
//Default plus value
|
||||
plus = ASN1Boolean.FALSE;
|
||||
|
||||
//Current sequence index
|
||||
if (sequence.getObjectAt(index).toASN1Primitive() instanceof ASN1Boolean) {
|
||||
plus = ASN1Boolean.getInstance(sequence.getObjectAt(index));
|
||||
index++;
|
||||
}
|
||||
|
||||
//Optional values (default to null or empty)
|
||||
strengthOfFunction = null;
|
||||
profileOid = null;
|
||||
profileUri = null;
|
||||
targetOid = null;
|
||||
targetUri = null;
|
||||
|
||||
//Sequence for the URIReference
|
||||
ASN1Sequence uriSequence;
|
||||
|
||||
//Continue reading the sequence
|
||||
for (; index < sequence.size(); index++) {
|
||||
ASN1TaggedObject taggedObj = ASN1TaggedObject.getInstance(sequence.getObjectAt(index));
|
||||
switch (taggedObj.getTagNo()) {
|
||||
case STRENGTH_OF_FUNCTION:
|
||||
enumarated = ASN1Enumerated.getInstance(taggedObj, false);
|
||||
strengthOfFunction
|
||||
= StrengthOfFunction.values()[enumarated.getValue().intValue()];
|
||||
break;
|
||||
case PROFILE_OID:
|
||||
profileOid = ASN1ObjectIdentifier.getInstance(taggedObj, false);
|
||||
break;
|
||||
case PROFILE_URI:
|
||||
uriSequence = ASN1Sequence.getInstance(taggedObj, false);
|
||||
profileUri = new URIReference(uriSequence);
|
||||
break;
|
||||
case TARGET_OID:
|
||||
targetOid = ASN1ObjectIdentifier.getInstance(taggedObj, false);
|
||||
break;
|
||||
case TARGET_URI:
|
||||
uriSequence = ASN1Sequence.getInstance(taggedObj, false);
|
||||
targetUri = new URIReference(uriSequence);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Common criteria measures contains "
|
||||
+ "invalid tagged object.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("ComponentIdentifier{");
|
||||
sb.append("version=").append(version.toString());
|
||||
sb.append(", assuranceLevel=").append(assuranceLevel.getValue());
|
||||
sb.append(", evaluationStatus=").append(evaluationStatus.getValue());
|
||||
sb.append(", plus=").append(plus.toString());
|
||||
//Not null optional objects
|
||||
sb.append(", strengthOfFunction=");
|
||||
if (strengthOfFunction != null) {
|
||||
sb.append(strengthOfFunction.getValue());
|
||||
}
|
||||
sb.append(", profileOid=");
|
||||
if (profileOid != null) {
|
||||
sb.append(profileOid.getId());
|
||||
}
|
||||
sb.append(", profileUri=");
|
||||
if (profileUri != null) {
|
||||
sb.append(profileUri.toString());
|
||||
}
|
||||
sb.append(", targetOid=");
|
||||
if (targetOid != null) {
|
||||
sb.append(targetOid.getId());
|
||||
}
|
||||
sb.append(", targetUri=");
|
||||
if (targetUri != null) {
|
||||
sb.append(targetUri.toString());
|
||||
}
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERUTF8String;
|
||||
|
||||
/**
|
||||
* Basic class that handle component addresses from the component identifier.
|
||||
* <pre>
|
||||
* componentAddress ::= SEQUENCE {
|
||||
* addressType AddressType,
|
||||
* addressValue UTF8String (SIZE (1..STRMAX)) }
|
||||
* where STRMAX is 256
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class ComponentAddress {
|
||||
|
||||
/**
|
||||
* Number of identifiers that a component address must have.
|
||||
*/
|
||||
public static final int IDENTIFIER_NUMBER = 2;
|
||||
|
||||
private static final String ETHERNET_MAC = "2.23.133.17.1";
|
||||
private static final String WLAN_MAC = "2.23.133.17.2";
|
||||
private static final String BLUETOOTH_MAC = "2.23.133.17.3";
|
||||
|
||||
private ASN1ObjectIdentifier addressType;
|
||||
private DERUTF8String addressValue;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public ComponentAddress() {
|
||||
addressType = null;
|
||||
addressValue = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains the type and value for the
|
||||
* component address.
|
||||
*
|
||||
* @param sequence containing the type and value for the component address
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public ComponentAddress(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
//Check if the sequence contains the two values required
|
||||
if (sequence.size() != IDENTIFIER_NUMBER) {
|
||||
throw new IllegalArgumentException("Component address does not contain "
|
||||
+ "all the required fields.");
|
||||
}
|
||||
addressType = ASN1ObjectIdentifier.getInstance(sequence.getObjectAt(0));
|
||||
addressValue = DERUTF8String.getInstance(sequence.getObjectAt(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string value for the address type.
|
||||
* @return the string value for the address type
|
||||
*/
|
||||
public String getAddressTypeValue() {
|
||||
String typeValue;
|
||||
switch (this.addressType.getId()) {
|
||||
case ETHERNET_MAC:
|
||||
typeValue = "ethernet mac";
|
||||
break;
|
||||
case WLAN_MAC:
|
||||
typeValue = "wlan mac";
|
||||
break;
|
||||
case BLUETOOTH_MAC:
|
||||
typeValue = "bluetooth mac";
|
||||
break;
|
||||
default:
|
||||
typeValue = "unknown mac";
|
||||
break;
|
||||
}
|
||||
return typeValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ComponentAddress{"
|
||||
+ "addressType=" + addressType.getId()
|
||||
+ ", addressValue=" + addressValue.getString()
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,248 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import com.eclipsesource.json.JsonObject.Member;
|
||||
import hirs.attestationca.utils.JsonUtils;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class parses the associated component identifier located in Platform
|
||||
* Certificates and maps them to the corresponding string representation found
|
||||
* in the associated JSON file. If the value can not be found, either because
|
||||
* the provided value is malformed or doesn't exist in the mapping, then values
|
||||
* returned will not match what is expected. This class will return Unknown as a
|
||||
* category and None as the component which is not a valid mapping. This is
|
||||
* because None is a category and Unknown is a component identifier.
|
||||
* </p>
|
||||
* <pre>
|
||||
* componentClass ::= SEQUENCE {
|
||||
* componentClassRegistry ComponentClassRegistry,
|
||||
* componentClassValue OCTET STRING SIZE(4) ) }
|
||||
* </pre>
|
||||
*
|
||||
* A note for the future.
|
||||
*/
|
||||
public class ComponentClass {
|
||||
private static final String TCG_COMPONENT_REGISTRY = "2.23.133.18.3.1";
|
||||
private static final String SMBIOS_COMPONENT_REGISTRY = "2.23.133.18.3.3";
|
||||
private static final Path JSON_PATH = FileSystems.getDefault()
|
||||
.getPath("/opt", "hirs", "default-properties", "component-class.json");
|
||||
|
||||
// private static final Path JSON_PATH = FileSystems.getDefault()
|
||||
// .getPath("/opt", "hirs", "default-properties", "component-class.json");
|
||||
private static final String OTHER_STRING = "Other";
|
||||
private static final String UNKNOWN_STRING = "Unknown";
|
||||
private static final String NONE_STRING = "None";
|
||||
|
||||
// Used to indicate that the component string value provided is erroneous
|
||||
private static final String ERROR = "-1";
|
||||
private static final int MID_INDEX = 4;
|
||||
/**
|
||||
* All TCG categories have Other and Unknown as the first 2 values.
|
||||
*/
|
||||
private static final String OTHER = "0000";
|
||||
private static final String UNKNOWN = "0001";
|
||||
|
||||
@Getter
|
||||
private String category, categoryStr;
|
||||
@Getter
|
||||
private String component, componentStr;
|
||||
private String registryType;
|
||||
private String componentIdentifier;
|
||||
|
||||
/**
|
||||
* Default class constructor.
|
||||
*/
|
||||
public ComponentClass() {
|
||||
this("TCG", JSON_PATH, UNKNOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Constructor that takes a String representation of the component
|
||||
* value.
|
||||
*
|
||||
* @param registryOid the decimal notation for the type of registry
|
||||
* @param componentIdentifier component value
|
||||
*/
|
||||
public ComponentClass(final String registryOid, final String componentIdentifier) {
|
||||
this(registryOid, JSON_PATH, componentIdentifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Constructor that takes a String representation of the component
|
||||
* value.
|
||||
*
|
||||
* @param componentClassPath file path for the json
|
||||
* @param componentIdentifier component value
|
||||
*/
|
||||
public ComponentClass(final Path componentClassPath, final String componentIdentifier) {
|
||||
this(TCG_COMPONENT_REGISTRY, componentClassPath, componentIdentifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main Class Constructor that takes in an integer representation of the
|
||||
* component value. Sets main class variables to default values and then
|
||||
* matches the value against defined values in the associated JSON file.
|
||||
*
|
||||
* @param registryOid the decimal notation for the type of registry
|
||||
* @param componentClassPath file path for the json
|
||||
* @param componentIdentifier component value
|
||||
*/
|
||||
public ComponentClass(final String registryOid,
|
||||
final Path componentClassPath,
|
||||
final String componentIdentifier) {
|
||||
this.category = OTHER;
|
||||
this.component = NONE_STRING;
|
||||
if (componentIdentifier == null || componentIdentifier.isEmpty()) {
|
||||
this.componentIdentifier = "";
|
||||
} else {
|
||||
this.componentIdentifier = verifyComponentValue(componentIdentifier);
|
||||
}
|
||||
|
||||
switch (registryOid) {
|
||||
case TCG_COMPONENT_REGISTRY -> registryType = "TCG";
|
||||
case SMBIOS_COMPONENT_REGISTRY -> registryType = "SMBIOS";
|
||||
default -> registryType = UNKNOWN_STRING;
|
||||
}
|
||||
|
||||
switch (this.componentIdentifier) {
|
||||
case OTHER:
|
||||
this.categoryStr = NONE_STRING;
|
||||
this.component = OTHER;
|
||||
this.componentStr = OTHER_STRING;
|
||||
break;
|
||||
case UNKNOWN:
|
||||
case "":
|
||||
this.categoryStr = NONE_STRING;
|
||||
this.component = UNKNOWN;
|
||||
this.componentStr = UNKNOWN_STRING;
|
||||
break;
|
||||
case ERROR:
|
||||
// Number Format Exception
|
||||
break;
|
||||
default:
|
||||
this.category = this.componentIdentifier.substring(0, MID_INDEX) + this.category;
|
||||
this.component = OTHER + this.componentIdentifier.substring(MID_INDEX);
|
||||
findStringValues(JsonUtils.getSpecificJsonObject(componentClassPath, registryType));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main way this class will be referenced and how it
|
||||
* will be displayed on the portal.
|
||||
* @return String combination of category and component.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
String resultString;
|
||||
if (componentStr.equals(UNKNOWN_STRING) || component.equals(OTHER_STRING)) {
|
||||
resultString = String.format("%s%n%s", registryType, categoryStr);
|
||||
} else {
|
||||
resultString = String.format("%s%n%s - %s", registryType, categoryStr, componentStr);
|
||||
}
|
||||
return resultString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the Category mapped to the associated value in.
|
||||
*
|
||||
* @param categories a JSON object associated with mapped categories in file
|
||||
* {}@link componentIdentifier}.
|
||||
*/
|
||||
private void findStringValues(final JsonObject categories) {
|
||||
String categoryID;
|
||||
String componentMask;
|
||||
boolean found = false;
|
||||
|
||||
if (categories != null) {
|
||||
for (String name : categories.names()) {
|
||||
categoryID = verifyComponentValue(categories.get(name)
|
||||
.asObject().get("ID").asString());
|
||||
componentMask = componentIdentifier.substring(MID_INDEX);
|
||||
// check for the correct flag
|
||||
if (categoryMatch(componentIdentifier.substring(0, MID_INDEX),
|
||||
categoryID.substring(0, MID_INDEX))) {
|
||||
found = true;
|
||||
JsonObject componentTypes = categories.get(name)
|
||||
.asObject().get("Types").asObject();
|
||||
categoryStr = name;
|
||||
|
||||
switch (componentMask) {
|
||||
case OTHER -> componentStr = OTHER_STRING;
|
||||
case UNKNOWN -> componentStr = UNKNOWN_STRING;
|
||||
default -> getComponent(componentTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
this.categoryStr = NONE_STRING;
|
||||
this.componentStr = UNKNOWN_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the comparison between a category and the what's in the id.
|
||||
* @param category the category to compare
|
||||
* @param componentId the id value to compare
|
||||
* @return true if they match
|
||||
*/
|
||||
public boolean categoryMatch(final String category, final String componentId) {
|
||||
return category.equals(componentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the component associated with the component JSON Object mapped
|
||||
* in the JSON file.
|
||||
*
|
||||
* @param components JSON Object for the categories components
|
||||
*/
|
||||
private void getComponent(final JsonObject components) {
|
||||
String typeID;
|
||||
|
||||
if (components != null) {
|
||||
for (Member member : components) {
|
||||
typeID = verifyComponentValue(member.getName());
|
||||
|
||||
if (component.equals(typeID)) {
|
||||
componentStr = member.getValue().asString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts the string representation of the component ID into
|
||||
* an integer. Or throws and error if the format is in error.
|
||||
*
|
||||
* @param component string representation of the component ID
|
||||
* @return the int representation of the component
|
||||
*/
|
||||
private static String verifyComponentValue(final String component) {
|
||||
String componentValue = ERROR;
|
||||
|
||||
if (component != null) {
|
||||
try {
|
||||
if (component.contains("x")) {
|
||||
componentValue = component.substring(component.indexOf("x") + 1);
|
||||
} else {
|
||||
if (component.contains("#")) {
|
||||
componentValue = component.replace("#", "");
|
||||
} else {
|
||||
return component;
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException nfEx) {
|
||||
//invalid entry
|
||||
}
|
||||
}
|
||||
|
||||
return componentValue;
|
||||
}
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.bouncycastle.asn1.ASN1Boolean;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.DERUTF8String;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Basic class that handle component identifiers from the Platform Configuration
|
||||
* Attribute.
|
||||
* <pre>
|
||||
* ComponentIdentifier ::= SEQUENCE {
|
||||
* componentManufacturer UTF8String (SIZE (1..STRMAX)),
|
||||
* componentModel UTF8String (SIZE (1..STRMAX)),
|
||||
* componentSerial[0] IMPLICIT UTF8String (SIZE (1..STRMAX)) OPTIONAL,
|
||||
* componentRevision [1] IMPLICIT UTF8String (SIZE (1..STRMAX)) OPTIONAL,
|
||||
* componentManufacturerId [2] IMPLICIT PrivateEnterpriseNumber OPTIONAL,
|
||||
* fieldReplaceable [3] IMPLICIT BOOLEAN OPTIONAL,
|
||||
* componentAddress [4] IMPLICIT
|
||||
* SEQUENCE(SIZE(1..CONFIGMAX)) OF ComponentAddress OPTIONAL}
|
||||
* where STRMAX is 256, CONFIGMAX is 32
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class ComponentIdentifier {
|
||||
|
||||
/**
|
||||
* Variable for components that aren't set.
|
||||
*/
|
||||
public static final String EMPTY_COMPONENT = "[Empty]";
|
||||
/**
|
||||
* Variable for components that aren't set.
|
||||
*/
|
||||
public static final String NOT_SPECIFIED_COMPONENT = "Not Specified";
|
||||
/**
|
||||
* Maximum number of configurations.
|
||||
*/
|
||||
public static final int CONFIGMAX = 32;
|
||||
|
||||
private static final int MANDATORY_ELEMENTS = 2;
|
||||
// optional sequence objects
|
||||
/**
|
||||
* Static variable indicated array position for the serial number.
|
||||
*/
|
||||
protected static final int COMPONENT_SERIAL = 0;
|
||||
/**
|
||||
* Static variable indicated array position for the revision info.
|
||||
*/
|
||||
protected static final int COMPONENT_REVISION = 1;
|
||||
/**
|
||||
* Static variable indicated array position for the manufacturer id.
|
||||
*/
|
||||
protected static final int COMPONENT_MANUFACTURER_ID = 2;
|
||||
/**
|
||||
* Static variable indicated array position for the field replaceable value.
|
||||
*/
|
||||
protected static final int FIELD_REPLACEABLE = 3;
|
||||
/**
|
||||
* Static variable indicated array position for the component address.
|
||||
*/
|
||||
protected static final int COMPONENT_ADDRESS = 4;
|
||||
|
||||
private DERUTF8String componentManufacturer;
|
||||
private DERUTF8String componentModel;
|
||||
private DERUTF8String componentSerial;
|
||||
private DERUTF8String componentRevision;
|
||||
private ASN1ObjectIdentifier componentManufacturerId;
|
||||
private ASN1Boolean fieldReplaceable;
|
||||
private List<ComponentAddress> componentAddress;
|
||||
private boolean validationResult = true;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public ComponentIdentifier() {
|
||||
componentManufacturer = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||
componentModel = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||
componentSerial = new DERUTF8String(StringUtils.EMPTY);
|
||||
componentRevision = new DERUTF8String(StringUtils.EMPTY);
|
||||
componentManufacturerId = null;
|
||||
fieldReplaceable = null;
|
||||
componentAddress = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the components values.
|
||||
*
|
||||
* @param componentManufacturer represents the component manufacturer
|
||||
* @param componentModel represents the component model
|
||||
* @param componentSerial represents the component serial number
|
||||
* @param componentRevision represents the component revision
|
||||
* @param componentManufacturerId represents the component manufacturer ID
|
||||
* @param fieldReplaceable represents if the component is replaceable
|
||||
* @param componentAddress represents a list of addresses
|
||||
*/
|
||||
public ComponentIdentifier(final DERUTF8String componentManufacturer,
|
||||
final DERUTF8String componentModel,
|
||||
final DERUTF8String componentSerial,
|
||||
final DERUTF8String componentRevision,
|
||||
final ASN1ObjectIdentifier componentManufacturerId,
|
||||
final ASN1Boolean fieldReplaceable,
|
||||
final List<ComponentAddress> componentAddress) {
|
||||
this.componentManufacturer = componentManufacturer;
|
||||
this.componentModel = componentModel;
|
||||
this.componentSerial = componentSerial;
|
||||
this.componentRevision = componentRevision;
|
||||
this.componentManufacturerId = componentManufacturerId;
|
||||
this.fieldReplaceable = fieldReplaceable;
|
||||
this.componentAddress = componentAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains Component Identifier.
|
||||
* @param sequence containing the the component identifier
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public ComponentIdentifier(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
// set all optional values to default in case they aren't set.
|
||||
this();
|
||||
//Check if it have a valid number of identifiers
|
||||
if (sequence.size() < MANDATORY_ELEMENTS) {
|
||||
throw new IllegalArgumentException("Component identifier do not have required values.");
|
||||
}
|
||||
|
||||
//Mandatory values
|
||||
componentManufacturer = DERUTF8String.getInstance(sequence.getObjectAt(0));
|
||||
componentModel = DERUTF8String.getInstance(sequence.getObjectAt(1));
|
||||
|
||||
//Continue reading the sequence if it does contain more than 2 values
|
||||
for (int i = 2; i < sequence.size(); i++) {
|
||||
ASN1TaggedObject taggedObj = ASN1TaggedObject.getInstance(sequence.getObjectAt(i));
|
||||
switch (taggedObj.getTagNo()) {
|
||||
case COMPONENT_SERIAL:
|
||||
componentSerial = DERUTF8String.getInstance(taggedObj, false);
|
||||
break;
|
||||
case COMPONENT_REVISION:
|
||||
componentRevision = DERUTF8String.getInstance(taggedObj, false);
|
||||
break;
|
||||
case COMPONENT_MANUFACTURER_ID:
|
||||
componentManufacturerId = ASN1ObjectIdentifier.getInstance(taggedObj, false);
|
||||
break;
|
||||
case FIELD_REPLACEABLE:
|
||||
fieldReplaceable = ASN1Boolean.getInstance(taggedObj, false);
|
||||
break;
|
||||
case COMPONENT_ADDRESS:
|
||||
ASN1Sequence addressesSequence = ASN1Sequence.getInstance(taggedObj, false);
|
||||
componentAddress = retrieveComponentAddress(addressesSequence);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Component identifier contains "
|
||||
+ "invalid tagged object.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the component addresses inside the sequence.
|
||||
*
|
||||
* @param sequence that contains the component addresses.
|
||||
* @return list of component addresses inside the sequence
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public static List<ComponentAddress> retrieveComponentAddress(final ASN1Sequence sequence)
|
||||
throws IllegalArgumentException {
|
||||
List<ComponentAddress> addresses;
|
||||
addresses = new ArrayList<>();
|
||||
|
||||
if (sequence.size() > CONFIGMAX) {
|
||||
throw new IllegalArgumentException("Component identifier contains invalid number "
|
||||
+ "of component addresses.");
|
||||
}
|
||||
//Get the components
|
||||
for (int i = 0; i < sequence.size(); i++) {
|
||||
ASN1Sequence address = ASN1Sequence.getInstance(sequence.getObjectAt(i));
|
||||
addresses.add(new ComponentAddress(address));
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(addresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("ComponentIdentifier{");
|
||||
sb.append("componentManufacturer=").append(componentManufacturer.getString());
|
||||
sb.append(", componentModel=").append(componentModel.getString());
|
||||
//Optional not null values
|
||||
sb.append(", componentSerial=");
|
||||
if (componentSerial != null) {
|
||||
sb.append(componentSerial.getString());
|
||||
}
|
||||
sb.append(", componentRevision=");
|
||||
if (componentRevision != null) {
|
||||
sb.append(componentRevision.getString());
|
||||
}
|
||||
sb.append(", componentManufacturerId=");
|
||||
if (componentManufacturerId != null) {
|
||||
sb.append(componentManufacturerId.getId());
|
||||
}
|
||||
sb.append(", fieldReplaceable=");
|
||||
if (fieldReplaceable != null) {
|
||||
sb.append(fieldReplaceable.toString());
|
||||
}
|
||||
sb.append(", componentAddress=");
|
||||
if (componentAddress.size() > 0) {
|
||||
sb.append(componentAddress
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(",")));
|
||||
}
|
||||
sb.append(", certificateIdentifier=");
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bouncycastle.asn1.ASN1Boolean;
|
||||
import org.bouncycastle.asn1.ASN1Enumerated;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERIA5String;
|
||||
|
||||
/**
|
||||
* Basic class that handle FIPS Level.
|
||||
* <pre>
|
||||
* FIPSLevel ::= SEQUENCE {
|
||||
* version IA5STRING (SIZE (1..STRMAX)), -- "140-1" or "140-2"
|
||||
* level SecurityLevel,
|
||||
* plus BOOLEAN DEFAULT FALSE }
|
||||
* </pre>
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class FIPSLevel {
|
||||
|
||||
private static final int MAX_SEQUENCE_SIZE = 3;
|
||||
/**
|
||||
* A type to handle the security Level used in the FIPS Level.
|
||||
* Ordering of enum types is intentional and their ordinal values correspond to enum
|
||||
* values in the TCG spec.
|
||||
*
|
||||
* <pre>
|
||||
* SecurityLevel ::= ENUMERATED {
|
||||
* level1 (1),
|
||||
* level2 (2),
|
||||
* level3 (3),
|
||||
* level4 (4) }
|
||||
* </pre>
|
||||
*/
|
||||
public enum SecurityLevel {
|
||||
/**
|
||||
* Security Level 1.
|
||||
*/
|
||||
LEVEL1("level 1"),
|
||||
/**
|
||||
* Security Level 2.
|
||||
*/
|
||||
LEVEL2("level 2"),
|
||||
/**
|
||||
* Security Level 3.
|
||||
*/
|
||||
LEVEL3("level 3"),
|
||||
/**
|
||||
* Security Level 4.
|
||||
*/
|
||||
LEVEL4("level 4");
|
||||
|
||||
private final String value;
|
||||
/**
|
||||
* Basic constructor.
|
||||
* @param value string containing the value.
|
||||
*/
|
||||
SecurityLevel(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string value from the StrengthOfFunction.
|
||||
* @return the string containing the value.
|
||||
*/
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter @Setter
|
||||
private DERIA5String version;
|
||||
@Getter @Setter
|
||||
private SecurityLevel level;
|
||||
@Getter @Setter
|
||||
private ASN1Boolean plus;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public FIPSLevel() {
|
||||
version = null;
|
||||
level = null;
|
||||
plus = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains the FIPLevel Object.
|
||||
*
|
||||
* @param sequence containing the FIPS Level Object
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public FIPSLevel(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
//Get version
|
||||
version = DERIA5String.getInstance(sequence.getObjectAt(0));
|
||||
//Get and validate level
|
||||
ASN1Enumerated enumarated = ASN1Enumerated.getInstance(sequence.getObjectAt(1));
|
||||
//Throw exception when is not between 1 and 7
|
||||
if (enumarated.getValue().intValue() <= 0
|
||||
|| enumarated.getValue().intValue() > SecurityLevel.values().length) {
|
||||
throw new IllegalArgumentException("Invalid security level on FIPSLevel.");
|
||||
}
|
||||
level = SecurityLevel.values()[enumarated.getValue().intValue() - 1];
|
||||
|
||||
//Check if there is another value on the sequence for the plus
|
||||
plus = ASN1Boolean.FALSE; //Default to false
|
||||
if (sequence.size() == MAX_SEQUENCE_SIZE) {
|
||||
plus = ASN1Boolean.getInstance(sequence.getObjectAt(2));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FIPSLevel{"
|
||||
+ "version=" + version.getString()
|
||||
+ ", level=" + level.getValue()
|
||||
+ ", plus=" + plus.toString()
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstract class that provides base info for Platform Configuration of
|
||||
* the Platform Certificate Attribute.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public abstract class PlatformConfiguration {
|
||||
private List<ComponentIdentifier> componentIdentifier;
|
||||
@Getter @Setter
|
||||
private URIReference componentIdentifierUri;
|
||||
private List<PlatformProperty> platformProperties;
|
||||
@Getter @Setter
|
||||
private URIReference platformPropertiesUri;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public PlatformConfiguration() {
|
||||
this.componentIdentifier = new ArrayList<>();
|
||||
this.componentIdentifierUri = null;
|
||||
this.platformProperties = new ArrayList<>();
|
||||
this.platformPropertiesUri = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the Platform Configuration values.
|
||||
*
|
||||
* @param componentIdentifier list containing all the components inside the
|
||||
* Platform Configuration.
|
||||
* @param platformProperties list containing all the properties inside the
|
||||
* Platform Configuration.
|
||||
* @param platformPropertiesUri object containing the URI Reference
|
||||
*/
|
||||
public PlatformConfiguration(final List<ComponentIdentifier> componentIdentifier,
|
||||
final List<PlatformProperty> platformProperties,
|
||||
final URIReference platformPropertiesUri) {
|
||||
this.componentIdentifier = componentIdentifier;
|
||||
this.platformProperties = platformProperties;
|
||||
this.platformPropertiesUri = platformPropertiesUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the componentIdentifier
|
||||
*/
|
||||
public List<ComponentIdentifier> getComponentIdentifier() {
|
||||
return Collections.unmodifiableList(componentIdentifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add function for the component identifier array.
|
||||
* @param componentIdentifier object to add
|
||||
* @return status of the add, if successful or not
|
||||
*/
|
||||
protected boolean add(final ComponentIdentifier componentIdentifier) {
|
||||
if (this.componentIdentifier != null) {
|
||||
return this.componentIdentifier.add(componentIdentifier);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param componentIdentifier the componentIdentifier to set
|
||||
*/
|
||||
public void setComponentIdentifier(final List<ComponentIdentifier> componentIdentifier) {
|
||||
this.componentIdentifier = componentIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the platformProperties
|
||||
*/
|
||||
public List<PlatformProperty> getPlatformProperties() {
|
||||
return Collections.unmodifiableList(platformProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add function for the platform property array.
|
||||
* @param platformProperty property object to add
|
||||
* @return status of the add, if successful or not
|
||||
*/
|
||||
protected boolean add(final PlatformProperty platformProperty) {
|
||||
if (this.platformProperties != null) {
|
||||
return this.platformProperties.add(platformProperty);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param platformProperties the platformProperties to set
|
||||
*/
|
||||
public void setPlatformProperties(final List<PlatformProperty> platformProperties) {
|
||||
this.platformProperties = platformProperties;
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Basic class that handle Platform Configuration for the Platform Certificate
|
||||
* Attribute.
|
||||
* <pre>
|
||||
* PlatformConfiguration ::= SEQUENCE {
|
||||
* componentIdentifier [0] IMPLICIT SEQUENCE(SIZE(1..CONFIGMAX)) OF
|
||||
* ComponentIdentifier OPTIONAL,
|
||||
* platformProperties [1] IMPLICIT SEQUENCE(SIZE(1..CONFIGMAX)) OF Properties OPTIONAL,
|
||||
* platformPropertiesUri [2] IMPLICIT URIReference OPTIONAL }
|
||||
* </pre>
|
||||
*/
|
||||
public class PlatformConfigurationV1 extends PlatformConfiguration {
|
||||
|
||||
private static final int COMPONENT_IDENTIFIER = 0;
|
||||
private static final int PLATFORM_PROPERTIES = 1;
|
||||
private static final int PLATFORM_PROPERTIES_URI = 2;
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains Platform Configuration.
|
||||
* @param sequence containing the the Platform Configuration.
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public PlatformConfigurationV1(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
|
||||
//Default values
|
||||
setComponentIdentifier(new ArrayList<>());
|
||||
setPlatformProperties(new ArrayList<>());
|
||||
setPlatformPropertiesUri(null);
|
||||
|
||||
for (int i = 0; i < sequence.size(); i++) {
|
||||
ASN1TaggedObject taggedSequence
|
||||
= ASN1TaggedObject.getInstance(sequence.getObjectAt(i));
|
||||
//Set information based on the set tagged
|
||||
switch (taggedSequence.getTagNo()) {
|
||||
case COMPONENT_IDENTIFIER:
|
||||
//Get componentIdentifier
|
||||
ASN1Sequence componentConfiguration
|
||||
= ASN1Sequence.getInstance(taggedSequence, false);
|
||||
|
||||
//Get and set all the component values
|
||||
for (int j = 0; j < componentConfiguration.size(); j++) {
|
||||
//DERSequence with the components
|
||||
ASN1Sequence component
|
||||
= ASN1Sequence.getInstance(componentConfiguration.getObjectAt(j));
|
||||
add(new ComponentIdentifier(component));
|
||||
}
|
||||
break;
|
||||
case PLATFORM_PROPERTIES:
|
||||
//Get platformProperties
|
||||
ASN1Sequence properties = ASN1Sequence.getInstance(taggedSequence, false);
|
||||
|
||||
//Get and set all the properties values
|
||||
for (int j = 0; j < properties.size(); j++) {
|
||||
//DERSequence with the components
|
||||
ASN1Sequence property = ASN1Sequence.getInstance(properties.getObjectAt(j));
|
||||
add(new PlatformProperty(property));
|
||||
}
|
||||
break;
|
||||
case PLATFORM_PROPERTIES_URI:
|
||||
//Get platformPropertiesURI
|
||||
ASN1Sequence propertiesUri = ASN1Sequence.getInstance(taggedSequence, false);
|
||||
//Save properties URI
|
||||
setPlatformPropertiesUri(new URIReference(propertiesUri));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("PlatformConfiguration{");
|
||||
sb.append("componentIdentifier=");
|
||||
if (getComponentIdentifier().size() > 0) {
|
||||
sb.append(getComponentIdentifier()
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(",")));
|
||||
}
|
||||
sb.append(", platformProperties=");
|
||||
if (getPlatformProperties().size() > 0) {
|
||||
sb.append(getPlatformProperties()
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(",")));
|
||||
}
|
||||
sb.append(", platformPropertiesUri=");
|
||||
if (getPlatformPropertiesUri() != null) {
|
||||
sb.append(getPlatformPropertiesUri().toString());
|
||||
}
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERUTF8String;
|
||||
|
||||
/**
|
||||
*
|
||||
* Basic class that handles a single property for the platform configuration.
|
||||
* <pre>
|
||||
* Properties ::= SEQUENCE {
|
||||
* propertyName UTF8String (SIZE (1..STRMAX)),
|
||||
* propertyValue UTF8String (SIZE (1..STRMAX) }
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class PlatformProperty {
|
||||
|
||||
private static final String NOT_SPECIFIED = "Not Specified";
|
||||
|
||||
/**
|
||||
* Number of identifiers for version 1.
|
||||
*/
|
||||
protected static final int IDENTIFIER_NUMBER = 2;
|
||||
|
||||
private DERUTF8String propertyName;
|
||||
private DERUTF8String propertyValue;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public PlatformProperty() {
|
||||
this.propertyName = new DERUTF8String(NOT_SPECIFIED);
|
||||
this.propertyValue = new DERUTF8String(NOT_SPECIFIED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains the name and value for the
|
||||
* platform property.
|
||||
*
|
||||
* @param sequence containing the name and value of the platform property
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public PlatformProperty(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
// Check if the sequence contains the two values required
|
||||
if (sequence.size() != IDENTIFIER_NUMBER) {
|
||||
throw new IllegalArgumentException("Platform properties does not contain all "
|
||||
+ "the required fields.");
|
||||
}
|
||||
|
||||
this.propertyName = DERUTF8String.getInstance(sequence.getObjectAt(0));
|
||||
this.propertyValue = DERUTF8String.getInstance(sequence.getObjectAt(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlatformProperty{"
|
||||
+ "propertyName=" + propertyName.getString()
|
||||
+ ", propertyValue=" + propertyValue.getString()
|
||||
+ "}";
|
||||
}
|
||||
}
|
@ -1,282 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.bouncycastle.asn1.ASN1Boolean;
|
||||
import org.bouncycastle.asn1.ASN1Enumerated;
|
||||
import org.bouncycastle.asn1.ASN1Integer;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.DERIA5String;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Basic class that handle component identifiers from the Platform Configuration
|
||||
* Attribute.
|
||||
* <pre>
|
||||
* TBBSecurityAssertions ::= SEQUENCE {
|
||||
* version Version DEFAULT v1,
|
||||
* ccInfo [0] IMPLICIT CommonCriteriaMeasures OPTIONAL,
|
||||
* fipsLevel [1] IMPLICIT FIPSLevel OPTIONAL,
|
||||
* rtmType [2] IMPLICIT MeasurementRootType OPTIONAL,
|
||||
* iso9000Certified BOOLEAN DEFAULT FALSE,
|
||||
* iso9000Uri IA5STRING (SIZE (1..URIMAX)) OPTIONAL }
|
||||
* </pre>
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class TBBSecurityAssertion {
|
||||
|
||||
private static final int CCINFO = 0;
|
||||
private static final int FIPSLEVEL = 1;
|
||||
private static final int RTMTYPE = 2;
|
||||
|
||||
/**
|
||||
* A type to handle the evaluation status used in the Common Criteria Measurement.
|
||||
* Ordering of enum types is intentional and their ordinal values correspond to enum
|
||||
* values in the TCG spec.
|
||||
*
|
||||
* <pre>
|
||||
* MeasurementRootType ::= ENUMERATED {
|
||||
* static (0),
|
||||
* dynamic (1),
|
||||
* nonHost (2),
|
||||
* hybrid (3),
|
||||
* physical (4),
|
||||
* virtual (5) }
|
||||
* </pre>
|
||||
*/
|
||||
public enum MeasurementRootType {
|
||||
/**
|
||||
* Static measurement root type.
|
||||
*/
|
||||
STATIC("static"),
|
||||
/**
|
||||
* Dynamic measurement root type.
|
||||
*/
|
||||
DYNAMIC("dynamic"),
|
||||
/**
|
||||
* Non-Host measurement root type.
|
||||
*/
|
||||
NONHOST("nonHost"),
|
||||
/**
|
||||
* Hybrid measurement root type.
|
||||
*/
|
||||
HYBRID("hybrid"),
|
||||
/**
|
||||
* Physical measurement root type.
|
||||
*/
|
||||
PHYSICAL("physical"),
|
||||
/**
|
||||
* Virtual measurement root type.
|
||||
*/
|
||||
VIRTUAL("virtual");
|
||||
|
||||
@Getter
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Basic constructor.
|
||||
* @param value string containing the value.
|
||||
*/
|
||||
MeasurementRootType(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private ASN1Integer version;
|
||||
private CommonCriteriaMeasures ccInfo;
|
||||
private FIPSLevel fipsLevel;
|
||||
private MeasurementRootType rtmType;
|
||||
private ASN1Boolean iso9000Certified;
|
||||
private DERIA5String iso9000Uri;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public TBBSecurityAssertion() {
|
||||
version = null;
|
||||
ccInfo = null;
|
||||
fipsLevel = null;
|
||||
rtmType = null;
|
||||
iso9000Certified = null;
|
||||
iso9000Uri = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains a TBBSecurityAssertion Object.
|
||||
* @param sequence containing the the TBB Security Assertion
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public TBBSecurityAssertion(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
int index = 0;
|
||||
//sequence size
|
||||
int sequenceSize = sequence.size();
|
||||
|
||||
//Default values
|
||||
version = new ASN1Integer(BigInteger.valueOf(0)); //Default v1 (0)
|
||||
ccInfo = null;
|
||||
fipsLevel = null;
|
||||
rtmType = null;
|
||||
iso9000Certified = ASN1Boolean.FALSE;
|
||||
iso9000Uri = null;
|
||||
|
||||
// Only contains defaults
|
||||
if (sequence.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get version if present
|
||||
if (sequence.getObjectAt(index).toASN1Primitive() instanceof ASN1Integer) {
|
||||
version = ASN1Integer.getInstance(sequence.getObjectAt(index));
|
||||
index++;
|
||||
}
|
||||
|
||||
// Check if it's a tag value
|
||||
while (index < sequenceSize
|
||||
&& sequence.getObjectAt(index).toASN1Primitive() instanceof ASN1TaggedObject) {
|
||||
ASN1TaggedObject taggedObj = ASN1TaggedObject.getInstance(sequence.getObjectAt(index));
|
||||
switch (taggedObj.getTagNo()) {
|
||||
case CCINFO:
|
||||
ASN1Sequence cciSequence = ASN1Sequence.getInstance(taggedObj, false);
|
||||
ccInfo = new CommonCriteriaMeasures(cciSequence);
|
||||
break;
|
||||
case FIPSLEVEL:
|
||||
ASN1Sequence fipsSequence = ASN1Sequence.getInstance(taggedObj, false);
|
||||
fipsLevel = new FIPSLevel(fipsSequence);
|
||||
break;
|
||||
case RTMTYPE:
|
||||
ASN1Enumerated enumerated = ASN1Enumerated.getInstance(taggedObj, false);
|
||||
rtmType = MeasurementRootType.values()[enumerated.getValue().intValue()];
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("TBB Security Assertion contains "
|
||||
+ "invalid tagged object.");
|
||||
}
|
||||
index++;
|
||||
}
|
||||
// Check if it's a boolean
|
||||
if (index < sequenceSize
|
||||
&& sequence.getObjectAt(index).toASN1Primitive() instanceof ASN1Boolean) {
|
||||
iso9000Certified = ASN1Boolean.getInstance(sequence.getObjectAt(index));
|
||||
index++;
|
||||
}
|
||||
// Check if it's a IA5String
|
||||
if (index < sequenceSize
|
||||
&& sequence.getObjectAt(index).toASN1Primitive() instanceof DERIA5String) {
|
||||
iso9000Uri = DERIA5String.getInstance(sequence.getObjectAt(index));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the version
|
||||
*/
|
||||
public ASN1Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version the version to set
|
||||
*/
|
||||
public void setVersion(final ASN1Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ccInfo
|
||||
*/
|
||||
public CommonCriteriaMeasures getCcInfo() {
|
||||
return ccInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ccInfo the ccInfo to set
|
||||
*/
|
||||
public void setCcInfo(final CommonCriteriaMeasures ccInfo) {
|
||||
this.ccInfo = ccInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fipsLevel
|
||||
*/
|
||||
public FIPSLevel getFipsLevel() {
|
||||
return fipsLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fipsLevel the fipsLevel to set
|
||||
*/
|
||||
public void setFipsLevel(final FIPSLevel fipsLevel) {
|
||||
this.fipsLevel = fipsLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the rtmType
|
||||
*/
|
||||
public MeasurementRootType getRtmType() {
|
||||
return rtmType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rtmType the rtmType to set
|
||||
*/
|
||||
public void setRtmType(final MeasurementRootType rtmType) {
|
||||
this.rtmType = rtmType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the iso9000Certified
|
||||
*/
|
||||
public ASN1Boolean getIso9000Certified() {
|
||||
return iso9000Certified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iso9000Certified the iso9000Certified to set
|
||||
*/
|
||||
public void setIso9000Certified(final ASN1Boolean iso9000Certified) {
|
||||
this.iso9000Certified = iso9000Certified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the iso9000Uri
|
||||
*/
|
||||
public DERIA5String getIso9000Uri() {
|
||||
return iso9000Uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param iso9000Uri the iso9000Uri to set
|
||||
*/
|
||||
public void setIso9000Uri(final DERIA5String iso9000Uri) {
|
||||
this.iso9000Uri = iso9000Uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("TBBSecurityAssertion{");
|
||||
sb.append("version=").append(version.toString());
|
||||
//Optional values not null
|
||||
sb.append(", ccInfo=");
|
||||
if (ccInfo != null) {
|
||||
sb.append(ccInfo.toString());
|
||||
}
|
||||
sb.append(", fipsLevel=");
|
||||
if (fipsLevel != null) {
|
||||
sb.append(fipsLevel.toString());
|
||||
}
|
||||
sb.append(", rtmType=");
|
||||
if (rtmType != null) {
|
||||
sb.append(rtmType.getValue());
|
||||
}
|
||||
sb.append(", iso9000Certified=").append(iso9000Certified.toString());
|
||||
sb.append(", iso9000Uri=");
|
||||
if (iso9000Uri != null) {
|
||||
sb.append(iso9000Uri.getString());
|
||||
}
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* A class to represent the TPM Security Assertions in an Endorsement Credential as
|
||||
* defined by the TCG spec for TPM 1.2.
|
||||
*
|
||||
* https://www.trustedcomputinggroup.org/wp-content/uploads/IWG-Credential_Profiles_V1_R0.pdf
|
||||
*
|
||||
* Future iterations of this code may want to reference
|
||||
* www.trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf
|
||||
* for specifications for TPM 2.0 (pg. 19).
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@Getter @Setter
|
||||
@Embeddable
|
||||
public class TPMSecurityAssertions {
|
||||
|
||||
/**
|
||||
* A type to handle the different endorsement key generation types used in the TPM
|
||||
* Assertions field of an endorsement credential. Ordering of enum types is intentional
|
||||
* and their ordinal values correspond to enum values in the TCG spec.
|
||||
*/
|
||||
|
||||
public enum EkGenerationType {
|
||||
/**
|
||||
* Generated internally within the TPM and cannot be revoked. Enum value of 0.
|
||||
*/
|
||||
INTERNAL,
|
||||
/**
|
||||
* Generated externally and then inserted under a controlled environment during
|
||||
* manufacturing. Cannot be revoked. Enum value of 1.
|
||||
*/
|
||||
INJECTED,
|
||||
/**
|
||||
* Generated internally within the TPM and can be revoked. Enum value of 2.
|
||||
*/
|
||||
INTERNAL_REVOCABLE,
|
||||
/**
|
||||
* Generated externally and then inserted under a controlled environment during
|
||||
* manufacturing. Can be revoked. Enum value of 3.
|
||||
*/
|
||||
INJECTED_REVOCABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* A type to handle the different endorsement key generation locations used in
|
||||
* specifying the endorsement key generation location and the endorsement key
|
||||
* certificate generation location in the TPM Assertions field of an endorsement
|
||||
* credential. Ordering of enum types is intentional and their ordinal values
|
||||
* correspond to enum values in the TCG spec.
|
||||
*/
|
||||
public enum EkGenerationLocation {
|
||||
/**
|
||||
* Generated by the TPM Manufacturer. Enum value of 0.
|
||||
*/
|
||||
TPM_MANUFACTURER,
|
||||
/**
|
||||
* Generated by the Platform Manufacturer. Enum value of 1.
|
||||
*/
|
||||
PLATFORM_MANUFACTURER,
|
||||
/**
|
||||
* Generated by the endorsement key certificate signer. Enum value of 2.
|
||||
*/
|
||||
EK_CERT_SIGNER;
|
||||
}
|
||||
|
||||
@Column
|
||||
private BigInteger tpmSecAssertsVersion; //default v1
|
||||
|
||||
@Column
|
||||
private boolean fieldUpgradeable; //default false
|
||||
|
||||
@Column(nullable = true)
|
||||
private EkGenerationType ekGenType; //optional
|
||||
|
||||
@Column(nullable = true)
|
||||
private EkGenerationLocation ekGenerationLocation; //optional
|
||||
|
||||
@Column(nullable = true)
|
||||
private EkGenerationLocation ekCertificateGenerationLocation; //optional
|
||||
|
||||
// Future work (may need to create other classes):
|
||||
//private CommonCriteriaMeasures commCritMeasures; //optional
|
||||
//private FIPSLevel fipsLevel; //optional
|
||||
//private boolean iso9000Certified; //default false
|
||||
//private IA5String iso9000Uri; //optional
|
||||
|
||||
/**
|
||||
* Standard constructor that sets required fields. Use accessor methods
|
||||
* to set optional fields.
|
||||
* @param version the version of the security assertions
|
||||
* @param fieldUpgradeable whether or not the security assertions are
|
||||
* field upgradeable.
|
||||
*/
|
||||
public TPMSecurityAssertions(final BigInteger version, final boolean fieldUpgradeable) {
|
||||
this.tpmSecAssertsVersion = version;
|
||||
this.fieldUpgradeable = fieldUpgradeable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TPMSecurityAssertions{"
|
||||
+ "version=" + tpmSecAssertsVersion
|
||||
+ ", fieldUpgradeable=" + fieldUpgradeable
|
||||
+ ", ekGenType=" + ekGenType
|
||||
+ ", ekGenLoc=" + ekGenerationLocation
|
||||
+ ", ekCertGenLoc=" + ekCertificateGenerationLocation
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* A class to represent the TPM Specification in an Endorsement Credential as
|
||||
* defined by the TCG spec for TPM 1.2.
|
||||
*
|
||||
* https://www.trustedcomputinggroup.org/wp-content/uploads/IWG-Credential_Profiles_V1_R0.pdf
|
||||
*
|
||||
* Future iterations of this code may want to reference
|
||||
* www.trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf
|
||||
* for specifications for TPM 2.0.
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
@NoArgsConstructor(access= AccessLevel.PROTECTED)
|
||||
@Getter
|
||||
@Embeddable
|
||||
public class TPMSpecification {
|
||||
|
||||
@Column
|
||||
private String family;
|
||||
|
||||
@Column
|
||||
private BigInteger level;
|
||||
|
||||
@Column
|
||||
private BigInteger revision;
|
||||
|
||||
/**
|
||||
* Standard constructor.
|
||||
* @param family the specification family.
|
||||
* @param level the specification level.
|
||||
* @param revision the specification revision.
|
||||
*/
|
||||
public TPMSpecification(final String family, final BigInteger level,
|
||||
final BigInteger revision) {
|
||||
this.family = family;
|
||||
this.level = level;
|
||||
this.revision = revision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TPMSpecification{"
|
||||
+ "family='" + family + '\''
|
||||
+ ", level=" + level
|
||||
+ ", revision=" + revision
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERBitString;
|
||||
import org.bouncycastle.asn1.DERIA5String;
|
||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||
|
||||
/**
|
||||
*
|
||||
* Basic class that handle a URIReference object.
|
||||
* <pre>
|
||||
* URIReference ::= SEQUENCE {
|
||||
* uniformResourceIdentifier IA5String (SIZE (1..URIMAX)),
|
||||
* hashAlgorithm AlgorithmIdentifier OPTIONAL,
|
||||
* hashValue BIT STRING OPTIONAL
|
||||
}
|
||||
* </pre>
|
||||
*/
|
||||
@Getter @Setter
|
||||
@AllArgsConstructor
|
||||
public class URIReference {
|
||||
private DERIA5String uniformResourceIdentifier;
|
||||
private AlgorithmIdentifier hashAlgorithm;
|
||||
@JsonIgnore
|
||||
private DERBitString hashValue;
|
||||
|
||||
private static final int PLATFORM_PROPERTIES_URI_MAX = 3;
|
||||
private static final int PLATFORM_PROPERTIES_URI_MIN = 1;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public URIReference() {
|
||||
this.uniformResourceIdentifier = null;
|
||||
this.hashAlgorithm = null;
|
||||
this.hashValue = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains the URIReference values.
|
||||
*
|
||||
* @param sequence containing the name and value of the platform property
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public URIReference(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
//Check if the sequence contains the two values required
|
||||
if (sequence.size() > PLATFORM_PROPERTIES_URI_MAX
|
||||
|| sequence.size() < PLATFORM_PROPERTIES_URI_MIN) {
|
||||
throw new IllegalArgumentException("PlatformPropertiesURI contains invalid "
|
||||
+ "number of fields.");
|
||||
}
|
||||
|
||||
//Get the Platform Configuration URI values
|
||||
for (int j = 0; j < sequence.size(); j++) {
|
||||
if (sequence.getObjectAt(j) instanceof DERIA5String) {
|
||||
this.uniformResourceIdentifier = DERIA5String.getInstance(sequence.getObjectAt(j));
|
||||
} else if ((sequence.getObjectAt(j) instanceof AlgorithmIdentifier)
|
||||
|| (sequence.getObjectAt(j) instanceof ASN1Sequence)) {
|
||||
this.hashAlgorithm =
|
||||
AlgorithmIdentifier.getInstance(sequence.getObjectAt(j));
|
||||
} else if (sequence.getObjectAt(j) instanceof DERBitString) {
|
||||
this.hashValue = DERBitString.getInstance(sequence.getObjectAt(j));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected DER type found. "
|
||||
+ sequence.getObjectAt(j).getClass().getName() + " found at index " + j + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("URIReference{");
|
||||
sb.append("uniformResourceIdentifier=").append(uniformResourceIdentifier.getString());
|
||||
//Check of optional values are not null
|
||||
sb.append(", hashAlgorithm=");
|
||||
if (hashAlgorithm != null) {
|
||||
sb.append(hashAlgorithm.getAlgorithm().getId());
|
||||
}
|
||||
sb.append(", hashValue=");
|
||||
if (hashValue != null) {
|
||||
sb.append(hashValue.getString());
|
||||
}
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes.V2;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* A type to handle the security Level used in the FIPS Level.
|
||||
* Ordering of enum types is intentional and their ordinal values correspond to enum
|
||||
* values in the TCG spec.
|
||||
*
|
||||
* <pre>
|
||||
* AttributeStatus ::= ENUMERATED {
|
||||
* added (0),
|
||||
* modified (1),
|
||||
* removed (2) }
|
||||
* </pre>
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public enum AttributeStatus {
|
||||
/**
|
||||
* Attribute Status for ADDED.
|
||||
*/
|
||||
ADDED("added"),
|
||||
/**
|
||||
* Attribute Status for MODIFIED.
|
||||
*/
|
||||
MODIFIED("modified"),
|
||||
/**
|
||||
* Attribute Status for REMOVED.
|
||||
*/
|
||||
REMOVED("removed"),
|
||||
/**
|
||||
* Attribute Status for EMPTY.
|
||||
*/
|
||||
EMPTY_STATUS(StringUtils.EMPTY);
|
||||
|
||||
@Getter
|
||||
private final String value;
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes.V2;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.bouncycastle.asn1.ASN1Integer;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.x509.GeneralName;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Basic class that handles a the attribute associate with a Certificate
|
||||
* Identifier for the component.
|
||||
* <pre>
|
||||
* CertificateIdentifier::= SEQUENCE {
|
||||
* attributeCertIdentifier [0] IMPLICIT AttributeCertificateIdentifier OPTIONAL
|
||||
* genericCertIdentifier [1] IMPLICIT IssuerSerial OPTIONAL }
|
||||
*
|
||||
* AttributeCertificateIdentifier ::= SEQUENCE {
|
||||
* hashAlgorithm AlgorithmIdentifier,
|
||||
* hashOverSignatureValue OCTET STRING }
|
||||
*
|
||||
* IssuerSerial ::= SEQUENCE {
|
||||
* issuer GeneralNames,
|
||||
* serial CertificateSerialNumber }
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
public class CertificateIdentifier {
|
||||
private static final String NOT_SPECIFIED = "Not Specified";
|
||||
|
||||
private static final int SEQUENCE_NUMBER = 2;
|
||||
private static final int ATTRIBUTE_ID_INDEX = 0;
|
||||
private static final int GENERIC_ID_INDEX = 1;
|
||||
|
||||
private String hashAlgorithm;
|
||||
private String hashSigValue;
|
||||
private GeneralName issuerDN;
|
||||
private BigInteger certificateSerialNumber;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public CertificateIdentifier() {
|
||||
hashAlgorithm = NOT_SPECIFIED;
|
||||
hashSigValue = null;
|
||||
issuerDN = null;
|
||||
certificateSerialNumber = BigInteger.ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary constructor for the parsing of the sequence.
|
||||
* @param sequence containing the name and value of the Certificate Identifier
|
||||
*/
|
||||
public CertificateIdentifier(final ASN1Sequence sequence) {
|
||||
this();
|
||||
|
||||
ASN1TaggedObject taggedObj;
|
||||
for (int i = 0; i < sequence.size(); i++) {
|
||||
taggedObj = ASN1TaggedObject.getInstance(sequence.getObjectAt(i));
|
||||
|
||||
switch (taggedObj.getTagNo()) {
|
||||
case ATTRIBUTE_ID_INDEX:
|
||||
// attributecertificateidentifier
|
||||
parseAttributeCertId(ASN1Sequence.getInstance(taggedObj, false));
|
||||
break;
|
||||
case GENERIC_ID_INDEX:
|
||||
// issuerserial
|
||||
parseGenericCertId(ASN1Sequence.getInstance(taggedObj, false));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseAttributeCertId(final ASN1Sequence attrCertSeq) {
|
||||
//Check if it have a valid number of identifiers
|
||||
if (attrCertSeq.size() != SEQUENCE_NUMBER) {
|
||||
throw new IllegalArgumentException("CertificateIdentifier"
|
||||
+ ".AttributeCertificateIdentifier does not have required values.");
|
||||
}
|
||||
|
||||
hashAlgorithm = attrCertSeq.getObjectAt(0).toString();
|
||||
hashSigValue = attrCertSeq.getObjectAt(1).toString();
|
||||
}
|
||||
|
||||
private void parseGenericCertId(final ASN1Sequence issuerSerialSeq) {
|
||||
//Check if it have a valid number of identifiers
|
||||
if (issuerSerialSeq.size() != SEQUENCE_NUMBER) {
|
||||
throw new IllegalArgumentException("CertificateIdentifier"
|
||||
+ ".GenericCertificateIdentifier does not have required values.");
|
||||
}
|
||||
|
||||
ASN1Sequence derSequence = DERSequence.getInstance(issuerSerialSeq.getObjectAt(0));
|
||||
ASN1TaggedObject taggedObj = ASN1TaggedObject.getInstance(derSequence.getObjectAt(0));
|
||||
|
||||
issuerDN = GeneralName.getInstance(taggedObj);
|
||||
certificateSerialNumber = ASN1Integer.getInstance(issuerSerialSeq
|
||||
.getObjectAt(1)).getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* String for the internal data stored.
|
||||
* @return String representation of the data.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("CertificateIdentifier{");
|
||||
sb.append("hashAlgorithm=").append(hashAlgorithm);
|
||||
sb.append(", hashSigValue").append(hashSigValue);
|
||||
sb.append(", issuerDN=");
|
||||
if (issuerDN != null) {
|
||||
sb.append(issuerDN.toString());
|
||||
}
|
||||
sb.append(", certificateSerialNumber=");
|
||||
if (certificateSerialNumber != null) {
|
||||
sb.append(certificateSerialNumber.toString());
|
||||
}
|
||||
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,251 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes.V2;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentAddress;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentClass;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bouncycastle.asn1.ASN1Boolean;
|
||||
import org.bouncycastle.asn1.ASN1Enumerated;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
import org.bouncycastle.asn1.DERUTF8String;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Basic class that handle component identifiers from the Platform Configuration
|
||||
* Attribute.
|
||||
* <pre>
|
||||
* ComponentIdentifier ::= SEQUENCE {
|
||||
* componentManufacturer UTF8String (SIZE (1..STRMAX)),
|
||||
* componentModel UTF8String (SIZE (1..STRMAX)),
|
||||
* componentSerial[0] IMPLICIT UTF8String (SIZE (1..STRMAX)) OPTIONAL,
|
||||
* componentRevision [1] IMPLICIT UTF8String (SIZE (1..STRMAX)) OPTIONAL,
|
||||
* componentManufacturerId [2] IMPLICIT PrivateEnterpriseNumber OPTIONAL,
|
||||
* fieldReplaceable [3] IMPLICIT BOOLEAN OPTIONAL,
|
||||
* componentAddress [4] IMPLICIT
|
||||
* SEQUENCE(SIZE(1..CONFIGMAX)) OF ComponentAddress OPTIONAL
|
||||
* componentPlatformCert [5] IMPLICIT CertificateIdentifier OPTIONAL,
|
||||
* componentPlatformCertUri [6] IMPLICIT URIReference OPTIONAL,
|
||||
* status [7] IMPLICIT AttributeStatus OPTIONAL }
|
||||
* where STRMAX is 256, CONFIGMAX is 32
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class ComponentIdentifierV2 extends ComponentIdentifier {
|
||||
|
||||
private static final int MANDATORY_ELEMENTS = 3;
|
||||
// Additional optional identifiers for version 2
|
||||
private static final int COMPONENT_PLATFORM_CERT = 5;
|
||||
private static final int COMPONENT_PLATFORM_URI = 6;
|
||||
private static final int ATTRIBUTE_STATUS = 7;
|
||||
|
||||
private ComponentClass componentClass;
|
||||
private CertificateIdentifier certificateIdentifier;
|
||||
private URIReference componentPlatformUri;
|
||||
private AttributeStatus attributeStatus;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public ComponentIdentifierV2() {
|
||||
super();
|
||||
componentClass = new ComponentClass();
|
||||
certificateIdentifier = null;
|
||||
componentPlatformUri = null;
|
||||
attributeStatus = AttributeStatus.EMPTY_STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the components values.
|
||||
*
|
||||
* @param componentClass represent the component type
|
||||
* @param componentManufacturer represents the component manufacturer
|
||||
* @param componentModel represents the component model
|
||||
* @param componentSerial represents the component serial number
|
||||
* @param componentRevision represents the component revision
|
||||
* @param componentManufacturerId represents the component manufacturer ID
|
||||
* @param fieldReplaceable represents if the component is replaceable
|
||||
* @param componentAddress represents a list of addresses
|
||||
* @param certificateIdentifier object representing certificate Id
|
||||
* @param componentPlatformUri object containing the URI Reference
|
||||
* @param attributeStatus object containing enumerated status
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
public ComponentIdentifierV2(final ComponentClass componentClass,
|
||||
final DERUTF8String componentManufacturer,
|
||||
final DERUTF8String componentModel,
|
||||
final DERUTF8String componentSerial,
|
||||
final DERUTF8String componentRevision,
|
||||
final ASN1ObjectIdentifier componentManufacturerId,
|
||||
final ASN1Boolean fieldReplaceable,
|
||||
final List<ComponentAddress> componentAddress,
|
||||
final CertificateIdentifier certificateIdentifier,
|
||||
final URIReference componentPlatformUri,
|
||||
final AttributeStatus attributeStatus) {
|
||||
super(componentManufacturer, componentModel, componentSerial,
|
||||
componentRevision, componentManufacturerId, fieldReplaceable,
|
||||
componentAddress);
|
||||
this.componentClass = componentClass;
|
||||
// additional optional component identifiers
|
||||
this.certificateIdentifier = certificateIdentifier;
|
||||
this.componentPlatformUri = componentPlatformUri;
|
||||
this.attributeStatus = attributeStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains Component Identifier.
|
||||
* @param sequence containing the the component identifier
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public ComponentIdentifierV2(final ASN1Sequence sequence)
|
||||
throws IllegalArgumentException {
|
||||
super();
|
||||
// Check if it have a valid number of identifiers
|
||||
if (sequence.size() < MANDATORY_ELEMENTS) {
|
||||
throw new IllegalArgumentException("Component identifier do not have required values.");
|
||||
}
|
||||
|
||||
int tag = 0;
|
||||
ASN1Sequence componentIdSeq = ASN1Sequence.getInstance(sequence.getObjectAt(tag));
|
||||
componentClass = new ComponentClass(componentIdSeq.getObjectAt(tag++).toString(),
|
||||
DEROctetString.getInstance(componentIdSeq.getObjectAt(tag)).toString());
|
||||
|
||||
// Mandatory values
|
||||
this.setComponentManufacturer(DERUTF8String.getInstance(sequence.getObjectAt(tag++)));
|
||||
this.setComponentModel(DERUTF8String.getInstance(sequence.getObjectAt(tag++)));
|
||||
|
||||
// Continue reading the sequence if it does contain more than 2 values
|
||||
for (int i = tag; i < sequence.size(); i++) {
|
||||
ASN1TaggedObject taggedObj = ASN1TaggedObject.getInstance(sequence.getObjectAt(i));
|
||||
switch (taggedObj.getTagNo()) {
|
||||
case COMPONENT_SERIAL:
|
||||
this.setComponentSerial(DERUTF8String.getInstance(taggedObj, false));
|
||||
break;
|
||||
case COMPONENT_REVISION:
|
||||
this.setComponentRevision(DERUTF8String.getInstance(taggedObj, false));
|
||||
break;
|
||||
case COMPONENT_MANUFACTURER_ID:
|
||||
this.setComponentManufacturerId(ASN1ObjectIdentifier
|
||||
.getInstance(taggedObj, false));
|
||||
break;
|
||||
case FIELD_REPLACEABLE:
|
||||
this.setFieldReplaceable(ASN1Boolean.getInstance(taggedObj, false));
|
||||
break;
|
||||
case COMPONENT_ADDRESS:
|
||||
ASN1Sequence addressesSequence = ASN1Sequence.getInstance(taggedObj, false);
|
||||
this.setComponentAddress(retrieveComponentAddress(addressesSequence));
|
||||
break;
|
||||
case COMPONENT_PLATFORM_CERT:
|
||||
ASN1Sequence ciSequence = ASN1Sequence.getInstance(taggedObj, false);
|
||||
certificateIdentifier = new CertificateIdentifier(ciSequence);
|
||||
break;
|
||||
case COMPONENT_PLATFORM_URI:
|
||||
ASN1Sequence uriSequence = ASN1Sequence.getInstance(taggedObj, false);
|
||||
this.componentPlatformUri = new URIReference(uriSequence);
|
||||
break;
|
||||
case ATTRIBUTE_STATUS:
|
||||
ASN1Enumerated enumerated = ASN1Enumerated.getInstance(taggedObj, false);
|
||||
this.attributeStatus = AttributeStatus.values()[
|
||||
enumerated.getValue().intValue()];
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Component identifier contains "
|
||||
+ "invalid tagged object.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the component has been modified.
|
||||
*/
|
||||
public final boolean isAdded() {
|
||||
return getAttributeStatus() == AttributeStatus.ADDED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the component has been modified.
|
||||
*/
|
||||
public final boolean isModified() {
|
||||
return getAttributeStatus() == AttributeStatus.MODIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the component has been removed.
|
||||
*/
|
||||
public final boolean isRemoved() {
|
||||
return getAttributeStatus() == AttributeStatus.REMOVED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the component status wasn't set.
|
||||
*/
|
||||
public final boolean isEmpty() {
|
||||
return (getAttributeStatus() == AttributeStatus.EMPTY_STATUS)
|
||||
|| (getAttributeStatus() == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return indicates the type of platform certificate.
|
||||
*/
|
||||
public boolean isVersion2() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("ComponentIdentifierV2{");
|
||||
sb.append("componentClass=").append(componentClass);
|
||||
sb.append(", componentManufacturer=").append(getComponentManufacturer()
|
||||
.getString());
|
||||
sb.append(", componentModel=").append(getComponentModel().getString());
|
||||
// Optional not null values
|
||||
sb.append(", componentSerial=");
|
||||
if (getComponentSerial() != null) {
|
||||
sb.append(getComponentSerial().getString());
|
||||
}
|
||||
sb.append(", componentRevision=");
|
||||
if (getComponentRevision() != null) {
|
||||
sb.append(getComponentRevision().getString());
|
||||
}
|
||||
sb.append(", componentManufacturerId=");
|
||||
if (getComponentManufacturerId() != null) {
|
||||
sb.append(getComponentManufacturerId().getId());
|
||||
}
|
||||
sb.append(", fieldReplaceable=");
|
||||
if (getFieldReplaceable() != null) {
|
||||
sb.append(getFieldReplaceable().toString());
|
||||
}
|
||||
sb.append(", componentAddress=");
|
||||
if (getComponentAddress().size() > 0) {
|
||||
sb.append(getComponentAddress()
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(",")));
|
||||
}
|
||||
sb.append(", certificateIdentifier=");
|
||||
if (certificateIdentifier != null) {
|
||||
sb.append(certificateIdentifier.toString());
|
||||
}
|
||||
sb.append(", componentPlatformUri=");
|
||||
if (componentPlatformUri != null) {
|
||||
sb.append(componentPlatformUri.toString());
|
||||
}
|
||||
sb.append(", status=");
|
||||
if (attributeStatus != null) {
|
||||
sb.append(attributeStatus.getValue());
|
||||
}
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes.V2;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.ASN1TaggedObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Basic class that handle Platform Configuration for the Platform Certificate
|
||||
* Attribute.
|
||||
* <pre>
|
||||
* PlatformConfiguration ::= SEQUENCE {
|
||||
* componentIdentifier [0] IMPLICIT SEQUENCE(SIZE(1..CONFIGMAX)) OF
|
||||
* ComponentIdentifier OPTIONAL,
|
||||
* componentIdentifiersUri [1] IMPLICIT URIReference OPTIONAL
|
||||
* platformProperties [2] IMPLICIT SEQUENCE(SIZE(1..CONFIGMAX)) OF Properties OPTIONAL,
|
||||
* platformPropertiesUri [3] IMPLICIT URIReference OPTIONAL }
|
||||
* </pre>
|
||||
*/
|
||||
public class PlatformConfigurationV2 extends PlatformConfiguration {
|
||||
|
||||
private static final int COMPONENT_IDENTIFIER = 0;
|
||||
private static final int COMPONENT_IDENTIFIER_URI = 1;
|
||||
private static final int PLATFORM_PROPERTIES = 2;
|
||||
private static final int PLATFORM_PROPERTIES_URI = 3;
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains Platform Configuration.
|
||||
* @param sequence containing the the Platform Configuration.
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public PlatformConfigurationV2(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
//Default values
|
||||
setComponentIdentifier(new ArrayList<>());
|
||||
setComponentIdentifierUri(null);
|
||||
setPlatformProperties(new ArrayList<>());
|
||||
setPlatformPropertiesUri(null);
|
||||
|
||||
for (int i = 0; i < sequence.size(); i++) {
|
||||
ASN1TaggedObject taggedSequence
|
||||
= ASN1TaggedObject.getInstance(sequence.getObjectAt(i));
|
||||
//Set information based on the set tagged
|
||||
switch (taggedSequence.getTagNo()) {
|
||||
case COMPONENT_IDENTIFIER:
|
||||
//Get componentIdentifier
|
||||
ASN1Sequence componentConfiguration
|
||||
= ASN1Sequence.getInstance(taggedSequence, false);
|
||||
|
||||
//Get and set all the component values
|
||||
for (int j = 0; j < componentConfiguration.size(); j++) {
|
||||
//DERSequence with the components
|
||||
ASN1Sequence component
|
||||
= ASN1Sequence.getInstance(componentConfiguration.getObjectAt(j));
|
||||
add(new ComponentIdentifierV2(component));
|
||||
}
|
||||
break;
|
||||
case COMPONENT_IDENTIFIER_URI:
|
||||
//Get componentIdentifierURI
|
||||
ASN1Sequence componentUri = ASN1Sequence.getInstance(taggedSequence, false);
|
||||
//Save Component Identifier URI
|
||||
setComponentIdentifierUri(new URIReference(componentUri));
|
||||
break;
|
||||
case PLATFORM_PROPERTIES:
|
||||
//Get platformProperties
|
||||
ASN1Sequence properties = ASN1Sequence.getInstance(taggedSequence, false);
|
||||
|
||||
//Get and set all the properties values
|
||||
for (int j = 0; j < properties.size(); j++) {
|
||||
//DERSequence with the components
|
||||
ASN1Sequence property = ASN1Sequence.getInstance(properties.getObjectAt(j));
|
||||
add(new PlatformPropertyV2(property));
|
||||
}
|
||||
break;
|
||||
case PLATFORM_PROPERTIES_URI:
|
||||
//Get platformPropertiesURI
|
||||
ASN1Sequence propertiesUri = ASN1Sequence.getInstance(taggedSequence, false);
|
||||
//Save properties URI
|
||||
setPlatformPropertiesUri(new URIReference(propertiesUri));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("PlatformConfiguration{");
|
||||
sb.append("componentIdentifier=");
|
||||
if (getComponentIdentifier().size() > 0) {
|
||||
sb.append(getComponentIdentifier()
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(",")));
|
||||
}
|
||||
sb.append(", componentIdentifierUri=");
|
||||
if (getComponentIdentifierUri() != null) {
|
||||
sb.append(getComponentIdentifierUri().toString());
|
||||
}
|
||||
sb.append(", platformProperties=");
|
||||
if (getPlatformProperties().size() > 0) {
|
||||
sb.append(getPlatformProperties()
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(",")));
|
||||
}
|
||||
sb.append(", platformPropertiesUri=");
|
||||
if (getPlatformPropertiesUri() != null) {
|
||||
sb.append(getPlatformPropertiesUri().toString());
|
||||
}
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes.V2;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bouncycastle.asn1.ASN1Enumerated;
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERUTF8String;
|
||||
|
||||
/**
|
||||
*
|
||||
* Basic class that handles a single property for the platform configuration.
|
||||
* <pre>
|
||||
* Properties ::= SEQUENCE {
|
||||
* propertyName UTF8String (SIZE (1..STRMAX)),
|
||||
* propertyValue UTF8String (SIZE (1..STRMAX),
|
||||
* status [0] IMPLICIT AttributeStatus OPTIONAL }
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public class PlatformPropertyV2 extends PlatformProperty {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private AttributeStatus attributeStatus;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public PlatformPropertyV2() {
|
||||
super();
|
||||
this.attributeStatus = AttributeStatus.EMPTY_STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the name and value for the platform property.
|
||||
*
|
||||
* @param propertyName string containing the property name
|
||||
* @param propertyValue string containing the property value
|
||||
* @param attributeStatus enumerated object with the status of the property
|
||||
*/
|
||||
public PlatformPropertyV2(final DERUTF8String propertyName, final DERUTF8String propertyValue,
|
||||
final AttributeStatus attributeStatus) {
|
||||
super(propertyName, propertyValue);
|
||||
this.attributeStatus = attributeStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains the name and value for the
|
||||
* platform property.
|
||||
*
|
||||
* @param sequence containing the name and value of the platform property
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public PlatformPropertyV2(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
// Check if the sequence contains the two values required
|
||||
if (sequence.size() < IDENTIFIER_NUMBER) {
|
||||
throw new IllegalArgumentException("Platform properties does not contain all "
|
||||
+ "the required fields.");
|
||||
}
|
||||
|
||||
setPropertyName(DERUTF8String.getInstance(sequence.getObjectAt(0)));
|
||||
setPropertyValue(DERUTF8String.getInstance(sequence.getObjectAt(1)));
|
||||
|
||||
// optional value which is a placeholder for now
|
||||
if (sequence.size() > IDENTIFIER_NUMBER
|
||||
&& sequence.getObjectAt(2) instanceof ASN1Enumerated) {
|
||||
ASN1Enumerated enumerated = ASN1Enumerated.getInstance(sequence.getObjectAt(2));
|
||||
this.attributeStatus = AttributeStatus.values()[enumerated.getValue().intValue()];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the property has been modified.
|
||||
*/
|
||||
public final boolean isModified() {
|
||||
return getAttributeStatus() == AttributeStatus.MODIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the property has been removed.
|
||||
*/
|
||||
public final boolean isRemoved() {
|
||||
return getAttributeStatus() != AttributeStatus.REMOVED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("PlatformPropertyV2{");
|
||||
sb.append("PropertyName=").append(getPropertyName().getString());
|
||||
sb.append(", propertyValue=").append(getPropertyValue().getString());
|
||||
if (attributeStatus != null) {
|
||||
sb.append(", attributeStatus=").append(attributeStatus.toString());
|
||||
}
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes.V2;
|
@ -1 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate.attributes;
|
@ -1 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.certificate;
|
@ -1,60 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.info;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import hirs.attestationca.utils.StringValidator;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Used for representing the firmware info of a device, such as the BIOS information.
|
||||
*/
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@Getter
|
||||
public class FirmwareInfo implements Serializable {
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = false)
|
||||
private final String biosVendor;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = false)
|
||||
private final String biosVersion;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.SHORT_STRING_LENGTH, nullable = false)
|
||||
private final String biosReleaseDate;
|
||||
|
||||
/**
|
||||
* Constructor used to create a populated firmware info object.
|
||||
*
|
||||
* @param biosVendor String bios vendor name, i.e. Dell Inc.
|
||||
* @param biosVersion String bios version info, i.e. A11
|
||||
* @param biosReleaseDate String bios release date info, i.e. 03/12/2013
|
||||
*/
|
||||
public FirmwareInfo(final String biosVendor, final String biosVersion,
|
||||
final String biosReleaseDate) {
|
||||
this.biosVendor = StringValidator.check(biosVendor, "biosVendor")
|
||||
.notBlank().maxLength(DeviceInfoReport.LONG_STRING_LENGTH).getValue();
|
||||
|
||||
this.biosVersion = StringValidator.check(biosVersion, "biosVersion")
|
||||
.notBlank().maxLength(DeviceInfoReport.LONG_STRING_LENGTH).getValue();
|
||||
|
||||
this.biosReleaseDate = StringValidator.check(biosReleaseDate, "biosReleaseDate")
|
||||
.notBlank().maxLength(DeviceInfoReport.SHORT_STRING_LENGTH).getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor, useful for hibernate and marshalling and unmarshalling.
|
||||
*/
|
||||
public FirmwareInfo() {
|
||||
this(DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED);
|
||||
}
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.info;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import hirs.attestationca.utils.StringValidator;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Used for representing the hardware info of a device.
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
@Getter
|
||||
@Embeddable
|
||||
public class HardwareInfo implements Serializable {
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = false)
|
||||
private String manufacturer = DeviceInfoReport.NOT_SPECIFIED;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = false)
|
||||
private String productName = DeviceInfoReport.NOT_SPECIFIED;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.MED_STRING_LENGTH, nullable = false)
|
||||
private String version = DeviceInfoReport.NOT_SPECIFIED;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = false)
|
||||
private String systemSerialNumber = DeviceInfoReport.NOT_SPECIFIED;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = false)
|
||||
private String chassisSerialNumber = DeviceInfoReport.NOT_SPECIFIED;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = false)
|
||||
private String baseboardSerialNumber = DeviceInfoReport.NOT_SPECIFIED;
|
||||
|
||||
/**
|
||||
* Constructor used to create a populated firmware info object.
|
||||
*
|
||||
* @param manufacturer String manufacturer name
|
||||
* @param productName String product name info
|
||||
* @param version String bios release date info
|
||||
* @param systemSerialNumber String device serial number
|
||||
* @param chassisSerialNumber String device chassis serial number
|
||||
* @param baseboardSerialNumber String device baseboard serial number
|
||||
*/
|
||||
public HardwareInfo(
|
||||
final String manufacturer,
|
||||
final String productName,
|
||||
final String version,
|
||||
final String systemSerialNumber,
|
||||
final String chassisSerialNumber,
|
||||
final String baseboardSerialNumber) {
|
||||
if (!StringUtils.isBlank(manufacturer)) {
|
||||
this.manufacturer = StringValidator.check(manufacturer, "manufacturer")
|
||||
.maxLength(DeviceInfoReport.LONG_STRING_LENGTH).getValue();
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(productName)) {
|
||||
this.productName = StringValidator.check(productName, "productName")
|
||||
.maxLength(DeviceInfoReport.LONG_STRING_LENGTH).getValue();
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(version)) {
|
||||
this.version = StringValidator.check(version, "version")
|
||||
.maxLength(DeviceInfoReport.MED_STRING_LENGTH).getValue();
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(systemSerialNumber)) {
|
||||
this.systemSerialNumber = StringValidator.check(systemSerialNumber,
|
||||
"systemSerialNumber")
|
||||
.maxLength(DeviceInfoReport.LONG_STRING_LENGTH).getValue();
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(chassisSerialNumber)) {
|
||||
this.chassisSerialNumber = StringValidator.check(chassisSerialNumber,
|
||||
"chassisSerialNumber")
|
||||
.maxLength(DeviceInfoReport.LONG_STRING_LENGTH).getValue();
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(baseboardSerialNumber)) {
|
||||
this.baseboardSerialNumber = StringValidator.check(
|
||||
baseboardSerialNumber, "baseboardSerialNumber")
|
||||
.maxLength(DeviceInfoReport.LONG_STRING_LENGTH).getValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor, useful for hibernate and marshalling and unmarshalling.
|
||||
*/
|
||||
public HardwareInfo() {
|
||||
this(
|
||||
DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HardwareInfo{"
|
||||
+ "manufacturer='" + manufacturer + '\''
|
||||
+ ", productName='" + productName + '\''
|
||||
+ ", version='" + version + '\''
|
||||
+ ", systemSerialNumber='" + systemSerialNumber + '\''
|
||||
+ ", chassisSerialNumber='" + chassisSerialNumber + '\''
|
||||
+ ", baseboardSerialNumber='" + baseboardSerialNumber + '\''
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.info;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* This class is used to represent the network info of a device.
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
@Embeddable
|
||||
public class NetworkInfo implements Serializable {
|
||||
|
||||
private static final Logger LOGGER = LogManager
|
||||
.getLogger(NetworkInfo.class);
|
||||
|
||||
private static final int NUM_MAC_ADDRESS_BYTES = 6;
|
||||
|
||||
@XmlElement
|
||||
@Setter
|
||||
@Getter
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = true)
|
||||
private String hostname;
|
||||
|
||||
@XmlElement
|
||||
@XmlJavaTypeAdapter(value = InetAddressXmlAdapter.class)
|
||||
@Setter
|
||||
@Getter
|
||||
@Column(length = DeviceInfoReport.SHORT_STRING_LENGTH, nullable = true)
|
||||
@Type(type = "hirs.attestationca.persist.type.InetAddressType")
|
||||
private InetAddress ipAddress;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = NUM_MAC_ADDRESS_BYTES, nullable = true)
|
||||
@SuppressWarnings("checkstyle:magicnumber")
|
||||
private byte[] macAddress;
|
||||
|
||||
/**
|
||||
* Constructor used to create a NetworkInfo object.
|
||||
*
|
||||
* @param hostname
|
||||
* String representing the hostname information for the device,
|
||||
* can be null if hostname unknown
|
||||
* @param ipAddress
|
||||
* InetAddress object representing the IP address for the device,
|
||||
* can be null if IP address unknown
|
||||
* @param macAddress
|
||||
* byte array representing the MAC address for the device, can be
|
||||
* null if MAC address is unknown
|
||||
*/
|
||||
public NetworkInfo(final String hostname, final InetAddress ipAddress,
|
||||
final byte[] macAddress) {
|
||||
setHostname(hostname);
|
||||
setIpAddress(ipAddress);
|
||||
setMacAddress(macAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for marshalling/unmarshalling XML objects.
|
||||
*/
|
||||
protected NetworkInfo() {
|
||||
this.hostname = null;
|
||||
this.ipAddress = null;
|
||||
this.macAddress = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to retrieve the MAC address of the device.
|
||||
*
|
||||
* @return a String representing the MAC address, may return null if no
|
||||
* value is set
|
||||
*/
|
||||
public final byte[] getMacAddress() {
|
||||
if (macAddress == null) {
|
||||
return null;
|
||||
} else {
|
||||
return macAddress.clone();
|
||||
}
|
||||
}
|
||||
|
||||
private void setMacAddress(final byte[] macAddress) {
|
||||
StringBuilder sb;
|
||||
if (macAddress == null) {
|
||||
sb = null;
|
||||
} else {
|
||||
if (macAddress.length != NUM_MAC_ADDRESS_BYTES) {
|
||||
LOGGER.error(
|
||||
"MAC address is only {} bytes, must be {} bytes or "
|
||||
+ "null", macAddress.length,
|
||||
NUM_MAC_ADDRESS_BYTES);
|
||||
throw new IllegalArgumentException(
|
||||
"MAC address is invalid size");
|
||||
}
|
||||
sb = new StringBuilder();
|
||||
for (byte b : macAddress) {
|
||||
sb.append(String.format("%02X ", b));
|
||||
}
|
||||
}
|
||||
LOGGER.debug("setting MAC address to: {}", sb);
|
||||
this.macAddress = macAddress;
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.info;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import hirs.attestationca.utils.StringValidator;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* This class is used to represent the OS info of a device.
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
@ToString
|
||||
@Getter
|
||||
@Embeddable
|
||||
public class OSInfo implements Serializable {
|
||||
private static final Logger LOGGER = LogManager.getLogger(OSInfo.class);
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = false)
|
||||
private final String osName;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.LONG_STRING_LENGTH, nullable = false)
|
||||
private final String osVersion;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.SHORT_STRING_LENGTH, nullable = false)
|
||||
private final String osArch;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.SHORT_STRING_LENGTH, nullable = true)
|
||||
private final String distribution;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.SHORT_STRING_LENGTH, nullable = true)
|
||||
private final String distributionRelease;
|
||||
|
||||
/**
|
||||
* Constructor used to create an OSInfo object. This constructor takes an OS
|
||||
* name (Linux | Mac OS X | Windows 7), an OS version (i.e.
|
||||
* 3.10.0-123.el7.x86_64), OS architecture (x86_64), distribution (CentOS |
|
||||
* Fedora), and distribution release (7.0.1406). Distribution only makes
|
||||
* sense for Linux, so distribution and distributionRelease may be null.
|
||||
*
|
||||
* @param osName
|
||||
* String OS name (Linux | Mac OS X | Windows 7)
|
||||
* @param osVersion
|
||||
* String OS version (i.e. 3.10.0-123.el7.x86_64)
|
||||
* @param osArch
|
||||
* String OS architecture (x86_64)
|
||||
* @param distribution
|
||||
* String distribution (CentOS | Fedora)
|
||||
* @param distributionRelease
|
||||
* String distribution release (7.0.1406)
|
||||
*/
|
||||
public OSInfo(final String osName, final String osVersion,
|
||||
final String osArch, final String distribution,
|
||||
final String distributionRelease) {
|
||||
LOGGER.debug("setting OS name information to: {}", osName);
|
||||
this.osName = StringValidator.check(osName, "osName")
|
||||
.notNull().maxLength(DeviceInfoReport.LONG_STRING_LENGTH).getValue();
|
||||
|
||||
LOGGER.debug("setting OS version information to: {}", osVersion);
|
||||
this.osVersion = StringValidator.check(osVersion, "osVersion")
|
||||
.notNull().maxLength(DeviceInfoReport.LONG_STRING_LENGTH).getValue();
|
||||
|
||||
LOGGER.debug("setting OS arch information to: {}", osArch);
|
||||
this.osArch = StringValidator.check(osArch, "osArch")
|
||||
.notNull().maxLength(DeviceInfoReport.SHORT_STRING_LENGTH).getValue();
|
||||
|
||||
LOGGER.debug("setting OS distribution information to: {}", distribution);
|
||||
this.distribution = StringValidator.check(distribution, "distribution")
|
||||
.maxLength(DeviceInfoReport.SHORT_STRING_LENGTH).getValue();
|
||||
|
||||
LOGGER.debug("setting OS distribution release information to: {}",
|
||||
distributionRelease);
|
||||
this.distributionRelease = StringValidator.check(distributionRelease, "distributionRelease")
|
||||
.maxLength(DeviceInfoReport.SHORT_STRING_LENGTH).getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for marshalling/unmarshalling XML objects.
|
||||
*/
|
||||
public OSInfo() {
|
||||
this(DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED);
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.info;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import hirs.attestationca.utils.StringValidator;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@Embeddable
|
||||
public class RIMInfo implements Serializable {
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.MED_STRING_LENGTH, nullable = false)
|
||||
private final String rimManufacturer;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.MED_STRING_LENGTH, nullable = false)
|
||||
private final String model;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.MED_STRING_LENGTH, nullable = false)
|
||||
private final String fileHash;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.MED_STRING_LENGTH, nullable = false)
|
||||
private final String pcrHash;
|
||||
|
||||
/**
|
||||
* Constructor for the initial values of the class.
|
||||
* @param rimManufacturer string of the rimManufacturer
|
||||
* @param model string of the model
|
||||
* @param fileHash string of the file hash
|
||||
* @param pcrHash string of the pcr hash
|
||||
*/
|
||||
public RIMInfo(final String rimManufacturer, final String model,
|
||||
final String fileHash, final String pcrHash) {
|
||||
this.rimManufacturer = StringValidator.check(rimManufacturer, "rimManufacturer")
|
||||
.notBlank().maxLength(DeviceInfoReport.MED_STRING_LENGTH).getValue();
|
||||
this.model = StringValidator.check(model, "model")
|
||||
.notBlank().maxLength(DeviceInfoReport.MED_STRING_LENGTH).getValue();
|
||||
this.fileHash = StringValidator.check(fileHash, "fileHash")
|
||||
.notBlank().maxLength(DeviceInfoReport.MED_STRING_LENGTH).getValue();
|
||||
this.pcrHash = StringValidator.check(pcrHash, "pcrHash")
|
||||
.notBlank().maxLength(DeviceInfoReport.MED_STRING_LENGTH).getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default no parameter constructor.
|
||||
*/
|
||||
public RIMInfo() {
|
||||
this(DeviceInfoReport.NOT_SPECIFIED, DeviceInfoReport.NOT_SPECIFIED,
|
||||
DeviceInfoReport.NOT_SPECIFIED, DeviceInfoReport.NOT_SPECIFIED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s, %s, %s, %s", rimManufacturer, model,
|
||||
fileHash, pcrHash);
|
||||
}
|
||||
}
|
@ -1,316 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.info;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import hirs.attestationca.utils.StringValidator;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* This class is used to represent the TPM information for a device.
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@Embeddable
|
||||
public class TPMInfo implements Serializable {
|
||||
private static final Logger LOGGER = LogManager.getLogger(TPMInfo.class);
|
||||
private static final int MAX_BLOB_SIZE = 65535;
|
||||
|
||||
@XmlElement
|
||||
@Column(length = DeviceInfoReport.MED_STRING_LENGTH, nullable = true)
|
||||
private String tpmMake;
|
||||
|
||||
@XmlElement
|
||||
@Column(nullable = true)
|
||||
private short tpmVersionMajor;
|
||||
|
||||
@XmlElement
|
||||
@Column(nullable = true)
|
||||
private short tpmVersionMinor;
|
||||
|
||||
@XmlElement
|
||||
@Column(nullable = true)
|
||||
private short tpmVersionRevMajor;
|
||||
|
||||
@XmlElement
|
||||
@Column(nullable = true)
|
||||
private short tpmVersionRevMinor;
|
||||
|
||||
@XmlElement
|
||||
// @XmlJavaTypeAdapter(X509CertificateAdapter.class)
|
||||
@Lob
|
||||
// @Type(type = "hirs.attestationca.persist.type.X509CertificateType")
|
||||
@JsonIgnore
|
||||
private X509Certificate identityCertificate;
|
||||
|
||||
@Column(nullable = true, length = MAX_BLOB_SIZE)
|
||||
private byte[] pcrValues;
|
||||
|
||||
@Column(nullable = true, length = MAX_BLOB_SIZE)
|
||||
private byte[] tpmQuoteHash;
|
||||
|
||||
@Column(nullable = true, length = MAX_BLOB_SIZE)
|
||||
private byte[] tpmQuoteSignature;
|
||||
|
||||
/**
|
||||
* Constructor used to create a TPMInfo object.
|
||||
*
|
||||
* @param tpmMake
|
||||
* String representing the make information for the TPM,
|
||||
* NullPointerException thrown if null
|
||||
* @param tpmVersionMajor
|
||||
* short representing the major version number for the TPM
|
||||
* @param tpmVersionMinor
|
||||
* short representing the minor version number for the TPM
|
||||
* @param tpmVersionRevMajor
|
||||
* short representing the major revision number for the TPM
|
||||
* @param tpmVersionRevMinor
|
||||
* short representing the minor revision number for the TPM
|
||||
* @param identityCertificate
|
||||
* byte array with the value of the identity certificate
|
||||
* @param pcrValues
|
||||
* short representing the major revision number for the TPM
|
||||
* @param tpmQuoteHash
|
||||
* short representing the minor revision number for the TPM
|
||||
* @param tpmQuoteSignature
|
||||
* byte array with the value of the identity certificate
|
||||
*/
|
||||
@SuppressWarnings("parameternumber")
|
||||
public TPMInfo(final String tpmMake, final short tpmVersionMajor,
|
||||
final short tpmVersionMinor, final short tpmVersionRevMajor,
|
||||
final short tpmVersionRevMinor,
|
||||
final X509Certificate identityCertificate, final byte[] pcrValues,
|
||||
final byte[] tpmQuoteHash, final byte[] tpmQuoteSignature) {
|
||||
setTPMMake(tpmMake);
|
||||
setTPMVersionMajor(tpmVersionMajor);
|
||||
setTPMVersionMinor(tpmVersionMinor);
|
||||
setTPMVersionRevMajor(tpmVersionRevMajor);
|
||||
setTPMVersionRevMinor(tpmVersionRevMinor);
|
||||
setIdentityCertificate(identityCertificate);
|
||||
setPcrValues(pcrValues);
|
||||
setTpmQuoteHash(tpmQuoteHash);
|
||||
setTpmQuoteSignature(tpmQuoteSignature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to create a TPMInfo object without an identity
|
||||
* certificate.
|
||||
*
|
||||
* @param tpmMake
|
||||
* String representing the make information for the TPM,
|
||||
* NullPointerException thrown if null
|
||||
* @param tpmVersionMajor
|
||||
* short representing the major version number for the TPM
|
||||
* @param tpmVersionMinor
|
||||
* short representing the minor version number for the TPM
|
||||
* @param tpmVersionRevMajor
|
||||
* short representing the major revision number for the TPM
|
||||
* @param tpmVersionRevMinor
|
||||
* short representing the minor revision number for the TPM
|
||||
* @param pcrValues
|
||||
* short representing the major revision number for the TPM
|
||||
* @param tpmQuoteHash
|
||||
* short representing the minor revision number for the TPM
|
||||
* @param tpmQuoteSignature
|
||||
* byte array with the value of the identity certificate
|
||||
*/
|
||||
@SuppressWarnings("parameternumber")
|
||||
public TPMInfo(final String tpmMake, final short tpmVersionMajor,
|
||||
final short tpmVersionMinor, final short tpmVersionRevMajor,
|
||||
final short tpmVersionRevMinor, final byte[] pcrValues,
|
||||
final byte[] tpmQuoteHash, final byte[] tpmQuoteSignature) {
|
||||
setTPMMake(tpmMake);
|
||||
setTPMVersionMajor(tpmVersionMajor);
|
||||
setTPMVersionMinor(tpmVersionMinor);
|
||||
setTPMVersionRevMajor(tpmVersionRevMajor);
|
||||
setTPMVersionRevMinor(tpmVersionRevMinor);
|
||||
setPcrValues(pcrValues);
|
||||
setTpmQuoteHash(tpmQuoteHash);
|
||||
setTpmQuoteSignature(tpmQuoteSignature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to create a TPMInfo object without an identity
|
||||
* certificate.
|
||||
*
|
||||
* @param tpmMake
|
||||
* String representing the make information for the TPM,
|
||||
* NullPointerException thrown if null
|
||||
* @param tpmVersionMajor
|
||||
* short representing the major version number for the TPM
|
||||
* @param tpmVersionMinor
|
||||
* short representing the minor version number for the TPM
|
||||
* @param tpmVersionRevMajor
|
||||
* short representing the major revision number for the TPM
|
||||
* @param tpmVersionRevMinor
|
||||
* short representing the minor revision number for the TPM
|
||||
*/
|
||||
public TPMInfo(final String tpmMake, final short tpmVersionMajor,
|
||||
final short tpmVersionMinor, final short tpmVersionRevMajor,
|
||||
final short tpmVersionRevMinor) {
|
||||
this(tpmMake, tpmVersionMajor, tpmVersionMinor, tpmVersionRevMajor,
|
||||
tpmVersionRevMinor, null,
|
||||
new byte[0], new byte[0], new byte[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to create a TPMInfo object without an identity
|
||||
* certificate.
|
||||
*
|
||||
* @param tpmMake
|
||||
* String representing the make information for the TPM,
|
||||
* NullPointerException thrown if null
|
||||
* @param tpmVersionMajor
|
||||
* short representing the major version number for the TPM
|
||||
* @param tpmVersionMinor
|
||||
* short representing the minor version number for the TPM
|
||||
* @param tpmVersionRevMajor
|
||||
* short representing the major revision number for the TPM
|
||||
* @param tpmVersionRevMinor
|
||||
* short representing the minor revision number for the TPM
|
||||
* @param identityCertificate
|
||||
* byte array with the value of the identity certificate
|
||||
*/
|
||||
public TPMInfo(final String tpmMake, final short tpmVersionMajor,
|
||||
final short tpmVersionMinor, final short tpmVersionRevMajor,
|
||||
final short tpmVersionRevMinor,
|
||||
final X509Certificate identityCertificate) {
|
||||
this(tpmMake, tpmVersionMajor, tpmVersionMinor, tpmVersionRevMajor,
|
||||
tpmVersionRevMinor, identityCertificate,
|
||||
new byte[0], new byte[0], new byte[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor used for marshalling/unmarshalling XML objects.
|
||||
*/
|
||||
public TPMInfo() {
|
||||
this(DeviceInfoReport.NOT_SPECIFIED,
|
||||
(short) 0,
|
||||
(short) 0,
|
||||
(short) 0,
|
||||
(short) 0,
|
||||
new byte[0],
|
||||
new byte[0],
|
||||
new byte[0]);
|
||||
identityCertificate = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the tpmQuote passed up by the client.
|
||||
* @return a byte blob of quote
|
||||
*/
|
||||
public final byte[] getTpmQuoteHash() {
|
||||
return tpmQuoteHash.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the quote signature.
|
||||
* @return a byte blob.
|
||||
*/
|
||||
public final byte[] getTpmQuoteSignature() {
|
||||
return tpmQuoteSignature.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the pcr values.
|
||||
* @return a byte blob for the pcrValues.
|
||||
*/
|
||||
public final byte[] getPcrValues() {
|
||||
return pcrValues.clone();
|
||||
}
|
||||
|
||||
private void setTPMMake(final String tpmMake) {
|
||||
LOGGER.debug("setting TPM make info: {}", tpmMake);
|
||||
this.tpmMake = StringValidator.check(tpmMake, "tpmMake")
|
||||
.notNull().maxLength(DeviceInfoReport.MED_STRING_LENGTH).getValue();
|
||||
}
|
||||
|
||||
private void setTPMVersionMajor(final short tpmVersionMajor) {
|
||||
if (tpmVersionMajor < 0) {
|
||||
LOGGER.error("TPM major version number cannot be negative: {}",
|
||||
tpmVersionMajor);
|
||||
throw new IllegalArgumentException(
|
||||
"negative TPM major version number");
|
||||
}
|
||||
LOGGER.debug("setting TPM major version number: {}", tpmVersionMajor);
|
||||
this.tpmVersionMajor = tpmVersionMajor;
|
||||
}
|
||||
|
||||
private void setTPMVersionMinor(final short tpmVersionMinor) {
|
||||
if (tpmVersionMinor < 0) {
|
||||
LOGGER.error("TPM minor version number cannot be negative: {}",
|
||||
tpmVersionMinor);
|
||||
throw new IllegalArgumentException(
|
||||
"negative TPM minor version number");
|
||||
}
|
||||
LOGGER.debug("setting TPM minor version number: {}", tpmVersionMinor);
|
||||
this.tpmVersionMinor = tpmVersionMinor;
|
||||
}
|
||||
|
||||
private void setTPMVersionRevMajor(final short tpmVersionRevMajor) {
|
||||
if (tpmVersionRevMajor < 0) {
|
||||
LOGGER.error("TPM major revision number cannot be negative: {}",
|
||||
tpmVersionRevMajor);
|
||||
throw new IllegalArgumentException(
|
||||
"negative TPM major revision number");
|
||||
}
|
||||
LOGGER.debug("setting TPM major revision version number: {}",
|
||||
tpmVersionRevMajor);
|
||||
this.tpmVersionRevMajor = tpmVersionRevMajor;
|
||||
}
|
||||
|
||||
private void setTPMVersionRevMinor(final short tpmVersionRevMinor) {
|
||||
if (tpmVersionRevMinor < 0) {
|
||||
LOGGER.error("TPM minor revision number cannot be negative: {}",
|
||||
tpmVersionRevMinor);
|
||||
throw new IllegalArgumentException(
|
||||
"negative TPM minor revision number");
|
||||
}
|
||||
LOGGER.debug("setting TPM minor revision version number: {}",
|
||||
tpmVersionRevMinor);
|
||||
this.tpmVersionRevMinor = tpmVersionRevMinor;
|
||||
}
|
||||
|
||||
private void setIdentityCertificate(
|
||||
final X509Certificate identityCertificate) {
|
||||
if (identityCertificate == null) {
|
||||
LOGGER.error("identity certificate cannot be null");
|
||||
throw new NullPointerException("identityCertificate");
|
||||
}
|
||||
LOGGER.debug("setting identity certificate");
|
||||
this.identityCertificate = identityCertificate;
|
||||
}
|
||||
|
||||
private void setPcrValues(final byte[] pcrValues) {
|
||||
if (pcrValues == null) {
|
||||
this.pcrValues = new byte[0];
|
||||
} else {
|
||||
this.pcrValues = pcrValues.clone();
|
||||
}
|
||||
}
|
||||
|
||||
private void setTpmQuoteHash(final byte[] tpmQuoteHash) {
|
||||
if (tpmQuoteHash == null) {
|
||||
this.tpmQuoteHash = new byte[0];
|
||||
} else {
|
||||
this.tpmQuoteHash = tpmQuoteHash.clone();
|
||||
}
|
||||
}
|
||||
|
||||
private void setTpmQuoteSignature(final byte[] tpmQuoteSignature) {
|
||||
if (tpmQuoteSignature == null) {
|
||||
this.tpmQuoteSignature = new byte[0];
|
||||
} else {
|
||||
this.tpmQuoteSignature = tpmQuoteSignature.clone();
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined;
|
@ -1,289 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.report;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.Report;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.OSInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.TPMInfo;
|
||||
import hirs.attestationca.utils.VersionHelper;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embedded;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Transient;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
/**
|
||||
* A <code>DeviceInfoReport</code> is a <code>Report</code> used to transfer the
|
||||
* information about the device. This <code>Report</code> includes the network,
|
||||
* OS, and TPM information.
|
||||
*/
|
||||
@Entity
|
||||
public class DeviceInfoReport extends Report implements Serializable {
|
||||
|
||||
private static final Logger LOGGER = getLogger(DeviceInfoReport.class);
|
||||
|
||||
/**
|
||||
* A variable used to describe unavailable hardware, firmware, or OS info.
|
||||
*/
|
||||
public static final String NOT_SPECIFIED = "Not Specified";
|
||||
/**
|
||||
* Constant variable representing the various Short sized strings.
|
||||
*/
|
||||
public static final int SHORT_STRING_LENGTH = 32;
|
||||
/**
|
||||
* Constant variable representing the various Medium sized strings.
|
||||
*/
|
||||
public static final int MED_STRING_LENGTH = 64;
|
||||
/**
|
||||
* Constant variable representing the various Long sized strings.
|
||||
*/
|
||||
public static final int LONG_STRING_LENGTH = 255;
|
||||
|
||||
@Embedded
|
||||
private NetworkInfo networkInfo;
|
||||
|
||||
@Embedded
|
||||
private OSInfo osInfo;
|
||||
|
||||
@Embedded
|
||||
private FirmwareInfo firmwareInfo;
|
||||
|
||||
@Embedded
|
||||
private HardwareInfo hardwareInfo;
|
||||
|
||||
@Embedded
|
||||
private TPMInfo tpmInfo;
|
||||
|
||||
@Getter
|
||||
@Column(nullable = false)
|
||||
private String clientApplicationVersion;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Transient
|
||||
private String paccorOutputString;
|
||||
|
||||
/**
|
||||
* Default constructor necessary for marshalling/unmarshalling.
|
||||
*/
|
||||
public DeviceInfoReport() {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to create a <code>DeviceInfoReport</code>. The
|
||||
* information cannot be changed after the <code>DeviceInfoReport</code> is
|
||||
* created.
|
||||
*
|
||||
* @param networkInfo
|
||||
* NetworkInfo object, cannot be null
|
||||
* @param osInfo
|
||||
* OSInfo object, cannot be null
|
||||
* @param firmwareInfo
|
||||
* FirmwareInfo object, cannot be null
|
||||
* @param hardwareInfo
|
||||
* HardwareInfo object, cannot be null
|
||||
* @param tpmInfo
|
||||
* TPMInfo object, may be null if a TPM is not available on the
|
||||
* device
|
||||
*/
|
||||
public DeviceInfoReport(final NetworkInfo networkInfo, final OSInfo osInfo,
|
||||
final FirmwareInfo firmwareInfo, final HardwareInfo hardwareInfo,
|
||||
final TPMInfo tpmInfo) {
|
||||
this(networkInfo, osInfo, firmwareInfo, hardwareInfo, tpmInfo, VersionHelper.getVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to create a <code>DeviceInfoReport</code>. The
|
||||
* information cannot be changed after the <code>DeviceInfoReport</code> is
|
||||
* created.
|
||||
*
|
||||
* @param networkInfo
|
||||
* NetworkInfo object, cannot be null
|
||||
* @param osInfo
|
||||
* OSInfo object, cannot be null
|
||||
* @param firmwareInfo
|
||||
* FirmwareInfo object, cannot be null
|
||||
* @param hardwareInfo
|
||||
* HardwareInfo object, cannot be null
|
||||
* @param tpmInfo
|
||||
* TPMInfo object, may be null if a TPM is not available on the
|
||||
* device
|
||||
* @param clientApplicationVersion
|
||||
* string representing the version of the client that submitted this report,
|
||||
* cannot be null
|
||||
*/
|
||||
public DeviceInfoReport(final NetworkInfo networkInfo, final OSInfo osInfo,
|
||||
final FirmwareInfo firmwareInfo, final HardwareInfo hardwareInfo,
|
||||
final TPMInfo tpmInfo, final String clientApplicationVersion) {
|
||||
setNetworkInfo(networkInfo);
|
||||
setOSInfo(osInfo);
|
||||
setFirmwareInfo(firmwareInfo);
|
||||
setHardwareInfo(hardwareInfo);
|
||||
setTPMInfo(tpmInfo);
|
||||
this.clientApplicationVersion = clientApplicationVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the NetworkInfo for this <code>DeviceInfoReport</code>.
|
||||
*
|
||||
* @return networkInfo
|
||||
*/
|
||||
public final NetworkInfo getNetworkInfo() {
|
||||
/*
|
||||
* Hibernate bug requires this
|
||||
* https://hibernate.atlassian.net/browse/HHH-7610
|
||||
* without null may be returned, which this interface does not support
|
||||
*/
|
||||
if (networkInfo == null) {
|
||||
networkInfo = new NetworkInfo(null, null, null);
|
||||
}
|
||||
return networkInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the OSInfo for this <code>DeviceInfoReport</code>.
|
||||
*
|
||||
* @return osInfo
|
||||
*/
|
||||
public final OSInfo getOSInfo() {
|
||||
/*
|
||||
* Hibernate bug requires this
|
||||
* https://hibernate.atlassian.net/browse/HHH-7610
|
||||
* without null may be returned, which this interface does not support
|
||||
*/
|
||||
if (osInfo == null) {
|
||||
osInfo = new OSInfo(NOT_SPECIFIED, NOT_SPECIFIED,
|
||||
NOT_SPECIFIED, NOT_SPECIFIED, NOT_SPECIFIED);
|
||||
}
|
||||
return osInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the FirmwareInfo for this <code>DeviceInfoReport</code>.
|
||||
*
|
||||
* @return osInfo
|
||||
*/
|
||||
public final FirmwareInfo getFirmwareInfo() {
|
||||
/*
|
||||
* Hibernate bug requires this
|
||||
* https://hibernate.atlassian.net/browse/HHH-7610
|
||||
* without null may be returned, which this interface does not support
|
||||
*/
|
||||
if (firmwareInfo == null) {
|
||||
firmwareInfo = new FirmwareInfo(NOT_SPECIFIED,
|
||||
NOT_SPECIFIED, NOT_SPECIFIED);
|
||||
}
|
||||
return firmwareInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the OSInfo for this <code>DeviceInfoReport</code>.
|
||||
*
|
||||
* @return osInfo
|
||||
*/
|
||||
public HardwareInfo getHardwareInfo() {
|
||||
/*
|
||||
* Hibernate bug requires this
|
||||
* https://hibernate.atlassian.net/browse/HHH-7610
|
||||
* without null may be returned, which this interface does not support
|
||||
*/
|
||||
if (hardwareInfo == null) {
|
||||
hardwareInfo = new HardwareInfo(
|
||||
NOT_SPECIFIED,
|
||||
NOT_SPECIFIED,
|
||||
NOT_SPECIFIED,
|
||||
NOT_SPECIFIED,
|
||||
NOT_SPECIFIED,
|
||||
NOT_SPECIFIED
|
||||
);
|
||||
}
|
||||
return hardwareInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the TPMInfo for this <code>DeviceInfoReport</code>. TPMInfo may
|
||||
* be null if a TPM is not available on the device.
|
||||
*
|
||||
* @return tpmInfo, may be null if a TPM is not available on the device
|
||||
*/
|
||||
public final TPMInfo getTPMInfo() {
|
||||
return tpmInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReportType() {
|
||||
return this.getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the given set of TPMBaselines for matching device info fields that
|
||||
* are determined critical to detecting a kernel update.
|
||||
* @param tpmBaselines Iterable<TPMBaseline> set of TPMBaseline objects.
|
||||
* @return True, if one of the TPM baselines in the set has the same kernel-specific
|
||||
* info as this DeviceinfoReport.
|
||||
*/
|
||||
public final boolean matchesKernelInfo(final Iterable<TpmWhiteListBaseline> tpmBaselines) {
|
||||
boolean match = false;
|
||||
|
||||
if (tpmBaselines != null) {
|
||||
// Retrieve the fields which indicate a kernel update
|
||||
final OSInfo kernelOSInfo = getOSInfo();
|
||||
|
||||
// perform the search
|
||||
for (final TpmWhiteListBaseline baseline : tpmBaselines) {
|
||||
final OSInfo baselineOSInfo = baseline.getOSInfo();
|
||||
if(baselineOSInfo.getOSName().equalsIgnoreCase(kernelOSInfo.getOSName())
|
||||
&& baselineOSInfo.getOSVersion().equalsIgnoreCase(kernelOSInfo.getOSVersion())) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
private void setNetworkInfo(NetworkInfo networkInfo) {
|
||||
if (networkInfo == null) {
|
||||
LOGGER.error("NetworkInfo cannot be null");
|
||||
throw new NullPointerException("network info");
|
||||
}
|
||||
this.networkInfo = networkInfo;
|
||||
}
|
||||
|
||||
private void setOSInfo(OSInfo osInfo) {
|
||||
if (osInfo == null) {
|
||||
LOGGER.error("OSInfo cannot be null");
|
||||
throw new NullPointerException("os info");
|
||||
}
|
||||
this.osInfo = osInfo;
|
||||
}
|
||||
|
||||
private void setFirmwareInfo(FirmwareInfo firmwareInfo) {
|
||||
if (firmwareInfo == null) {
|
||||
LOGGER.error("FirmwareInfo cannot be null");
|
||||
throw new NullPointerException("firmware info");
|
||||
}
|
||||
this.firmwareInfo = firmwareInfo;
|
||||
}
|
||||
|
||||
private void setHardwareInfo(HardwareInfo hardwareInfo) {
|
||||
if (hardwareInfo == null) {
|
||||
LOGGER.error("HardwareInfo cannot be null");
|
||||
throw new NullPointerException("hardware info");
|
||||
}
|
||||
this.hardwareInfo = hardwareInfo;
|
||||
}
|
||||
|
||||
private void setTPMInfo(TPMInfo tpmInfo) {
|
||||
this.tpmInfo = tpmInfo;
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.result;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* An <code>CertificateValidationResult</code> represents the result of a certificate validation
|
||||
* operation.
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class CertificateValidationResult {
|
||||
/**
|
||||
* Enum used to represent certificate validation status.
|
||||
*/
|
||||
public enum CertificateValidationStatus {
|
||||
|
||||
/**
|
||||
* Represents a passing validation.
|
||||
*/
|
||||
PASS,
|
||||
|
||||
/**
|
||||
* Represents a failed validation.
|
||||
*/
|
||||
FAIL,
|
||||
|
||||
/**
|
||||
* Represents a validation error.
|
||||
*/
|
||||
ERROR
|
||||
}
|
||||
|
||||
private CertificateValidationStatus validationStatus;
|
||||
private String validationResultMessage;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the certificate validation status and result message.
|
||||
*
|
||||
* @param status enum representing the certificate validation status
|
||||
* @param resultMessage String representing certificate validation message
|
||||
*/
|
||||
public final void setCertValidationStatusAndResultMessage(
|
||||
final CertificateValidationStatus status,
|
||||
final String resultMessage) {
|
||||
this.validationStatus = status;
|
||||
this.validationResultMessage = resultMessage;
|
||||
}
|
||||
}
|
@ -1,390 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.rim;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
|
||||
import hirs.attestationca.persist.service.ReferenceManifestServiceImpl;
|
||||
import hirs.attestationca.utils.SwidResource;
|
||||
import hirs.attestationca.utils.xjc.BaseElement;
|
||||
import hirs.attestationca.utils.xjc.Directory;
|
||||
import hirs.attestationca.utils.xjc.File;
|
||||
import hirs.attestationca.utils.xjc.FilesystemItem;
|
||||
import hirs.attestationca.utils.xjc.Link;
|
||||
import hirs.attestationca.utils.xjc.Meta;
|
||||
import hirs.attestationca.utils.xjc.ResourceCollection;
|
||||
import hirs.attestationca.utils.xjc.SoftwareIdentity;
|
||||
import hirs.attestationca.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;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.validation.Schema;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@Entity
|
||||
public class BaseReferenceManifest extends ReferenceManifest {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(BaseReferenceManifest.class);
|
||||
/**
|
||||
* Holds the name of the 'base64Hash' field.
|
||||
*/
|
||||
public static final String BASE_64_HASH_FIELD = "base64Hash";
|
||||
|
||||
private static JAXBContext jaxbContext;
|
||||
|
||||
@Column
|
||||
@JsonIgnore
|
||||
private String base64Hash = "";
|
||||
@Column
|
||||
private String swidName = null;
|
||||
@Column
|
||||
private int swidCorpus = 0;
|
||||
@Column
|
||||
private String colloquialVersion = null;
|
||||
@Column
|
||||
private String product = null;
|
||||
@Column
|
||||
private String revision = null;
|
||||
@Column
|
||||
private String edition = null;
|
||||
@Column
|
||||
private String rimLinkHash = null;
|
||||
@Column
|
||||
private String bindingSpec = null;
|
||||
@Column
|
||||
private String bindingSpecVersion = null;
|
||||
@Column
|
||||
private String platformVersion = null;
|
||||
@Column
|
||||
private String payloadType = null;
|
||||
@Column
|
||||
private String pcURIGlobal = null;
|
||||
@Column
|
||||
private String pcURILocal = null;
|
||||
|
||||
private String entityName = null;
|
||||
private String entityRegId = null;
|
||||
private String entityRole = null;
|
||||
private String entityThumbprint = null;
|
||||
private String linkHref = null;
|
||||
private String linkRel = null;
|
||||
|
||||
/**
|
||||
* Support constructor for the RIM object.
|
||||
*
|
||||
* @param fileName - string representation of the uploaded file.
|
||||
* @param rimBytes - the file content of the uploaded file.
|
||||
* @throws java.io.IOException - thrown if the file is invalid.
|
||||
*/
|
||||
public BaseReferenceManifest(final String fileName, final byte[] rimBytes) throws IOException {
|
||||
this(rimBytes);
|
||||
this.setFileName(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main constructor for the RIM object. This takes in a byte array of a
|
||||
* valid swidtag file and parses the information.
|
||||
*
|
||||
* @param rimBytes byte array representation of the RIM
|
||||
* @throws java.io.IOException if unable to unmarshal the string
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:AvoidInlineConditionals")
|
||||
public BaseReferenceManifest(final byte[] rimBytes) throws IOException {
|
||||
super(rimBytes);
|
||||
this.setRimType(BASE_RIM);
|
||||
this.setFileName("");
|
||||
SoftwareIdentity si = validateSwidTag(new ByteArrayInputStream(rimBytes));
|
||||
|
||||
MessageDigest digest = null;
|
||||
this.base64Hash = "";
|
||||
try {
|
||||
digest = MessageDigest.getInstance("SHA-256");
|
||||
this.base64Hash = Base64.getEncoder().encodeToString(
|
||||
digest.digest(rimBytes));
|
||||
} catch (NoSuchAlgorithmException noSaEx) {
|
||||
LOGGER.error(noSaEx);
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
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.attestationca.utils.xjc.Entity entity
|
||||
= (hirs.attestationca.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":
|
||||
parseResource((ResourceCollection) element.getValue());
|
||||
break;
|
||||
case "Signature":
|
||||
// left blank for a followup issue enhancement
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a helper method that parses the SoftwareMeta tag and stores the
|
||||
* information in the class fields.
|
||||
*
|
||||
* @param softwareMeta The object to parse.
|
||||
*/
|
||||
private void parseSoftwareMeta(final SoftwareMeta softwareMeta) {
|
||||
if (softwareMeta != null) {
|
||||
for (Map.Entry<QName, String> 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 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.
|
||||
*
|
||||
* @param fileStream stream of the swidtag file.
|
||||
* @return a {@link SoftwareIdentity} object
|
||||
* @throws java.io.IOException Thrown by the unmarhsallSwidTag method.
|
||||
*/
|
||||
private SoftwareIdentity validateSwidTag(final InputStream fileStream) throws IOException {
|
||||
JAXBElement jaxbe = unmarshallSwidTag(fileStream);
|
||||
SoftwareIdentity swidTag = (SoftwareIdentity) jaxbe.getValue();
|
||||
|
||||
LOGGER.info(String.format("SWID Tag found: %nname: %s;%ntagId: %s%n%s",
|
||||
swidTag.getName(), swidTag.getTagId(), SCHEMA_STATEMENT));
|
||||
return swidTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that is used to parse a specific element of the SwidTag
|
||||
* based on an already established and stored byte array.
|
||||
*
|
||||
* @param elementName string of an xml tag in the file.
|
||||
* @return the object value of the element, if it exists
|
||||
*/
|
||||
private BaseElement getBaseElementFromBytes(final String elementName) {
|
||||
BaseElement baseElement = null;
|
||||
|
||||
if (getRimBytes() != null && elementName != null) {
|
||||
try {
|
||||
SoftwareIdentity si = validateSwidTag(new ByteArrayInputStream(getRimBytes()));
|
||||
JAXBElement element;
|
||||
for (Object object : si.getEntityOrEvidenceOrLink()) {
|
||||
if (object instanceof JAXBElement) {
|
||||
element = (JAXBElement) object;
|
||||
if (element.getName().getLocalPart().equals(elementName)) {
|
||||
// found the element
|
||||
baseElement = (BaseElement) element.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException ioEx) {
|
||||
LOGGER.error("Failed to parse Swid Tag bytes.", ioEx);
|
||||
}
|
||||
}
|
||||
|
||||
return baseElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 java.io.IOException if the swidtag cannot be unmarshalled or validated
|
||||
*/
|
||||
private JAXBElement unmarshallSwidTag(final InputStream stream) throws IOException {
|
||||
JAXBElement jaxbe = null;
|
||||
Schema schema;
|
||||
|
||||
try {
|
||||
schema = ReferenceManifestServiceImpl.getSchemaObject();
|
||||
if (jaxbContext == null) {
|
||||
jaxbContext = JAXBContext.newInstance(SCHEMA_PACKAGE);
|
||||
}
|
||||
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
||||
unmarshaller.setSchema(schema);
|
||||
jaxbe = (JAXBElement) unmarshaller.unmarshal(stream);
|
||||
} catch (UnmarshalException umEx) {
|
||||
LOGGER.error(String.format("Error validating swidtag file!%n%s%n%s",
|
||||
umEx.getMessage(), umEx.toString()));
|
||||
for (StackTraceElement ste : umEx.getStackTrace()) {
|
||||
LOGGER.error(ste.toString());
|
||||
}
|
||||
} catch (IllegalArgumentException iaEx) {
|
||||
LOGGER.error("Input file empty.");
|
||||
} catch (JAXBException jaxEx) {
|
||||
for (StackTraceElement ste : jaxEx.getStackTrace()) {
|
||||
LOGGER.error(ste.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (jaxbe != null) {
|
||||
return jaxbe;
|
||||
} else {
|
||||
throw new IOException("Invalid Base RIM, swidtag format expected.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default method for parsing the payload element.
|
||||
*
|
||||
* @return a collection of payload objects.
|
||||
*/
|
||||
public final List<SwidResource> parseResource() {
|
||||
return parseResource((ResourceCollection) this.getBaseElementFromBytes("Payload"));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method parses the payload method of a {@link ResourceCollection}.
|
||||
*
|
||||
* @param rc Resource Collection object.
|
||||
* @return a collection of payload objects.
|
||||
*/
|
||||
public final List<SwidResource> parseResource(final ResourceCollection rc) {
|
||||
List<SwidResource> resources = new ArrayList<>();
|
||||
|
||||
try {
|
||||
if (rc != null) {
|
||||
for (Meta meta : rc.getDirectoryOrFileOrProcess()) {
|
||||
if (meta != null) {
|
||||
if (meta instanceof Directory) {
|
||||
Directory directory = (Directory) meta;
|
||||
for (FilesystemItem fsi : directory.getDirectoryOrFile()) {
|
||||
if (fsi != null) {
|
||||
resources.add(new SwidResource(
|
||||
(File) fsi, null));
|
||||
}
|
||||
}
|
||||
} else if (meta instanceof File) {
|
||||
resources.add(new SwidResource((File) meta, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassCastException ccEx) {
|
||||
LOGGER.error(ccEx);
|
||||
LOGGER.error("At this time, the code does not support the "
|
||||
+ "particular formatting of this SwidTag's Payload.");
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ReferenceManifest{swidName=%s,"
|
||||
+ "platformManufacturer=%s,"
|
||||
+ " platformModel=%s,"
|
||||
+ "tagId=%s, rimHash=%s}",
|
||||
swidName, this.getPlatformManufacturer(),
|
||||
this.getPlatformModel(), getTagId(), this.getBase64Hash());
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.rim;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Sub class that will just focus on PCR Values and Events.
|
||||
* Similar to {@link main.java.hirs.attestationca.entity.userdefined.rim.SupportReferenceManifest}
|
||||
* however this is the live log from the client.
|
||||
*/
|
||||
@Entity
|
||||
public class EventLogMeasurements extends ReferenceManifest {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(EventLogMeasurements.class);
|
||||
|
||||
@Column
|
||||
@JsonIgnore
|
||||
@Getter @Setter
|
||||
private int pcrHash = 0;
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Getter @Setter
|
||||
private AppraisalStatus.Status overallValidationResult = AppraisalStatus.Status.FAIL;
|
||||
|
||||
/**
|
||||
* Support constructor for the RIM object.
|
||||
*
|
||||
* @param rimBytes byte array representation of the RIM
|
||||
* @throws java.io.IOException if unable to unmarshal the string
|
||||
*/
|
||||
public EventLogMeasurements(final byte[] rimBytes) throws IOException {
|
||||
this("blank.measurement", rimBytes);
|
||||
}
|
||||
/**
|
||||
* Support constructor for the RIM object.
|
||||
*
|
||||
* @param fileName - string representation of the uploaded file.
|
||||
* @param rimBytes byte array representation of the RIM
|
||||
* @throws java.io.IOException if unable to unmarshal the string
|
||||
*/
|
||||
public EventLogMeasurements(final String fileName,
|
||||
final byte[] rimBytes) throws IOException {
|
||||
super(rimBytes);
|
||||
this.setFileName(fileName);
|
||||
this.archive("Event Log Measurement");
|
||||
this.setRimType(MEASUREMENT_RIM);
|
||||
this.pcrHash = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected EventLogMeasurements() {
|
||||
super();
|
||||
this.pcrHash = 0;
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.rim;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
|
||||
import hirs.attestationca.utils.tpm.eventlog.TCGEventLog;
|
||||
import hirs.attestationca.utils.tpm.eventlog.TpmPcrEvent;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Sub class that will just focus on PCR Values and Events.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
public class SupportReferenceManifest extends ReferenceManifest {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(SupportReferenceManifest.class);
|
||||
@Column
|
||||
@JsonIgnore
|
||||
private int pcrHash = 0;
|
||||
@Column
|
||||
private boolean updated = false;
|
||||
@Column
|
||||
private boolean processed = false;
|
||||
|
||||
/**
|
||||
* 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 java.io.IOException if unable to unmarshal the string
|
||||
*/
|
||||
public SupportReferenceManifest(final String fileName,
|
||||
final byte[] rimBytes) throws IOException {
|
||||
super(rimBytes);
|
||||
this.setFileName(fileName);
|
||||
this.setRimType(SUPPORT_RIM);
|
||||
this.pcrHash = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main constructor for the RIM object. This takes in a byte array of a
|
||||
* valid swidtag file and parses the information.
|
||||
*
|
||||
* @param rimBytes byte array representation of the RIM
|
||||
* @throws java.io.IOException if unable to unmarshal the string
|
||||
*/
|
||||
public SupportReferenceManifest(final byte[] rimBytes) throws IOException {
|
||||
this("blank.rimel", rimBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected SupportReferenceManifest() {
|
||||
super();
|
||||
this.pcrHash = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getter method for the expected PCR values contained within the support
|
||||
* RIM.
|
||||
* @return a string array of the pcr values.
|
||||
*/
|
||||
public String[] getExpectedPCRList() {
|
||||
try {
|
||||
TCGEventLog logProcessor = new TCGEventLog(this.getRimBytes());
|
||||
this.pcrHash = Arrays.hashCode(logProcessor.getExpectedPCRValues());
|
||||
return logProcessor.getExpectedPCRValues();
|
||||
} catch (CertificateException cEx) {
|
||||
LOGGER.error(cEx);
|
||||
} catch (NoSuchAlgorithmException noSaEx) {
|
||||
LOGGER.error(noSaEx);
|
||||
} catch (IOException ioEx) {
|
||||
LOGGER.error(ioEx);
|
||||
}
|
||||
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter method for the event log that should be present in the support RIM.
|
||||
*
|
||||
* @return list of TPM PCR Events for display
|
||||
*/
|
||||
public Collection<TpmPcrEvent> getEventLog() {
|
||||
TCGEventLog logProcessor = null;
|
||||
try {
|
||||
logProcessor = new TCGEventLog(this.getRimBytes());
|
||||
return logProcessor.getEventList();
|
||||
} catch (CertificateException cEx) {
|
||||
LOGGER.error(cEx);
|
||||
} catch (NoSuchAlgorithmException noSaEx) {
|
||||
LOGGER.error(noSaEx);
|
||||
} catch (IOException ioEx) {
|
||||
LOGGER.error(ioEx);
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.entity.userdefined.rim;
|
@ -1,106 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.enums;
|
||||
|
||||
/**
|
||||
* Class to capture appraisal results and corresponding messages.
|
||||
*/
|
||||
public class AppraisalStatus {
|
||||
/**
|
||||
* Enum used to represent appraisal status.
|
||||
*/
|
||||
public enum Status {
|
||||
|
||||
/**
|
||||
* Represents a passing appraisal.
|
||||
*/
|
||||
PASS,
|
||||
|
||||
/**
|
||||
* Represents a failed appraisal.
|
||||
*/
|
||||
FAIL,
|
||||
|
||||
/**
|
||||
* Represents an appraisal generation error.
|
||||
*/
|
||||
ERROR,
|
||||
/**
|
||||
* Represents an unknown appraisal result.
|
||||
*/
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
private Status appStatus;
|
||||
private String message;
|
||||
private String additionalInfo;
|
||||
|
||||
/**
|
||||
* Default constructor. Set appraisal status and description.
|
||||
* @param appStatus status of appraisal
|
||||
* @param message description of result
|
||||
*/
|
||||
public AppraisalStatus(final Status appStatus, final String message) {
|
||||
this(appStatus, message, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor. Set appraisal status and description.
|
||||
* @param appStatus status of appraisal
|
||||
* @param message description of result
|
||||
* @param additionalInfo any additional information needed to
|
||||
* be passed on
|
||||
*/
|
||||
public AppraisalStatus(final Status appStatus, final String message,
|
||||
final String additionalInfo) {
|
||||
this.appStatus = appStatus;
|
||||
this.message = message;
|
||||
this.additionalInfo = additionalInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get appraisal status.
|
||||
* @return appraisal status
|
||||
*/
|
||||
public Status getAppStatus() {
|
||||
return appStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set appraisal status.
|
||||
* @param appStatus new status
|
||||
*/
|
||||
public void setAppStatus(final Status appStatus) {
|
||||
this.appStatus = appStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get appraisal description message.
|
||||
* @return appraisal description message
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set appraisal description message.
|
||||
* @param message appraisal description message
|
||||
*/
|
||||
public void setMessage(final String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for additional information during validation.
|
||||
* @return string of additional information
|
||||
*/
|
||||
public String getAdditionalInfo() {
|
||||
return additionalInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for any additional information.
|
||||
* @param additionalInfo the string of additional information
|
||||
*/
|
||||
public void setAdditionalInfo(final String additionalInfo) {
|
||||
this.additionalInfo = additionalInfo;
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.enums;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <code>HealthStatus</code> is used to represent the health of a device.
|
||||
*/
|
||||
public enum HealthStatus {
|
||||
/**
|
||||
* The trusted state, no issues with the device.
|
||||
*/
|
||||
TRUSTED("trusted"),
|
||||
|
||||
/**
|
||||
* The untrusted state, there is a problem with the device.
|
||||
*/
|
||||
UNTRUSTED("untrusted"),
|
||||
|
||||
/**
|
||||
* A state for when the health has not been calculated yet.
|
||||
*/
|
||||
UNKNOWN("unknown");
|
||||
|
||||
private String healthStatus;
|
||||
|
||||
/**
|
||||
* Creates a new <code>HealthStatus</code> object given a String.
|
||||
*
|
||||
* @param healthStatus
|
||||
* "trusted", "untrusted", or "unknown"
|
||||
*/
|
||||
HealthStatus(final String healthStatus) {
|
||||
this.healthStatus = healthStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the health status.
|
||||
*
|
||||
* @return the status
|
||||
*/
|
||||
public String getStatus() {
|
||||
return this.healthStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getStatus();
|
||||
}
|
||||
|
||||
public static boolean isValidStatus(final String healthStatus) {
|
||||
return Arrays.stream(HealthStatus.values())
|
||||
.map(HealthStatus::name)
|
||||
.collect(Collectors.toSet())
|
||||
.contains(healthStatus);
|
||||
}
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.enums;
|
||||
|
||||
import hirs.attestationca.utils.VersionHelper;
|
||||
|
||||
/**
|
||||
* Contains attributes required to display a portal page and its menu link.
|
||||
*/
|
||||
public enum Page {
|
||||
|
||||
/**
|
||||
* Site landing page.
|
||||
*/
|
||||
INDEX("HIRS Attestation CA", "Version: " + VersionHelper.getVersion(),
|
||||
null, false, false, null, null),
|
||||
/**
|
||||
* Page to display registered devices.
|
||||
*/
|
||||
DEVICES("Devices", "ic_devices", "first"),
|
||||
/**
|
||||
* Page that manages Attestation CA Policy.
|
||||
*/
|
||||
POLICY("Policy", "ic_subtitles"),
|
||||
/**
|
||||
* Help page.
|
||||
*/
|
||||
HELP("Help", "ic_live_help");
|
||||
|
||||
private final String title;
|
||||
private final String subtitle;
|
||||
private final String icon;
|
||||
|
||||
private final boolean hasMenu;
|
||||
private final String menuLinkClass;
|
||||
private final boolean inMenu;
|
||||
|
||||
private final String prefixPath;
|
||||
private final String viewName;
|
||||
|
||||
/**
|
||||
* Constructor for Page.
|
||||
*
|
||||
* @param title title of the page
|
||||
* @param subtitle subtitle of the page
|
||||
* @param icon icon for the page
|
||||
* @param hasMenu the page has its own menu
|
||||
* @param inMenu the page appears in a menu
|
||||
* @param menuLinkClass the category to which this page belongs
|
||||
* @param prefixPath prefix path that appears in the URL for this page
|
||||
*/
|
||||
Page(final String title,
|
||||
final String subtitle,
|
||||
final String icon,
|
||||
final boolean hasMenu,
|
||||
final boolean inMenu,
|
||||
final String menuLinkClass,
|
||||
final String prefixPath) {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
this.icon = icon;
|
||||
this.hasMenu = hasMenu;
|
||||
this.menuLinkClass = menuLinkClass;
|
||||
this.inMenu = inMenu;
|
||||
this.prefixPath = prefixPath;
|
||||
|
||||
viewName = this.name().toLowerCase().replaceAll("_", "-");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for Page.
|
||||
*
|
||||
* @param title title of the page
|
||||
* @param icon icon for the page
|
||||
* @param menuLinkClass the category to which this page belongs
|
||||
* @param prefixPath prefix path that appears in the URL for this page
|
||||
*/
|
||||
Page(final String title,
|
||||
final String icon,
|
||||
final String menuLinkClass,
|
||||
final String prefixPath) {
|
||||
this(title, null, icon, true, true, menuLinkClass, prefixPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for Page.
|
||||
*
|
||||
* @param title title of the page
|
||||
* @param icon icon for the page
|
||||
* @param menuLinkClass the category to which this page belongs
|
||||
*/
|
||||
Page(final String title,
|
||||
final String icon,
|
||||
final String menuLinkClass) {
|
||||
this(title, null, icon, true, true, menuLinkClass, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for Page.
|
||||
*
|
||||
* @param title title of the page
|
||||
* @param icon icon for the page
|
||||
*/
|
||||
Page(final String title,
|
||||
final String icon) {
|
||||
this(title, null, icon, true, true, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title of the page.
|
||||
*
|
||||
* @return the title of the page.
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subtitle of the page.
|
||||
*
|
||||
* @return the subtitle of the page.
|
||||
*/
|
||||
public String getSubtitle() {
|
||||
return subtitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base filename of the icon for page. E.g. "ic_my_icon", which will be appended
|
||||
* with appropriate size string (_24dp/_48dp) and file extension (.png) when used.
|
||||
*
|
||||
* @return the base filename of the icon for page.
|
||||
*/
|
||||
public String getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the page should be displayed in the navigation menu.
|
||||
*
|
||||
* @return true if the page should be displayed in the navigation menu.
|
||||
*/
|
||||
public boolean getInMenu() {
|
||||
return inMenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the css class to add to the menu link to display it appropriately. E.g. "first" if
|
||||
* the link is the first in a group to separate it visually from the previous group.
|
||||
*
|
||||
* @return he class to add to the menu link to display it appropriately.
|
||||
*/
|
||||
public String getMenuLinkClass() {
|
||||
return menuLinkClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the page should display the navigation menu.
|
||||
*
|
||||
* @return true if the page should display the navigation menu.
|
||||
*/
|
||||
public boolean getHasMenu() {
|
||||
return hasMenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the page's view name.
|
||||
*
|
||||
* @return the page's view name
|
||||
*/
|
||||
public String getViewName() {
|
||||
return viewName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the page's view name.
|
||||
*
|
||||
* @return the page's view name
|
||||
*/
|
||||
public String getPrefixPath() {
|
||||
return prefixPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.enums;
|
@ -1,15 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.service;
|
||||
|
||||
public class DbServiceImpl {
|
||||
/**
|
||||
* The default maximum number of retries to attempt a database transaction.
|
||||
*/
|
||||
public static final int DEFAULT_MAX_RETRY_ATTEMPTS = 10;
|
||||
/*
|
||||
* The default number of milliseconds to wait before retrying a database transaction.
|
||||
*/
|
||||
private static final long DEFAULT_RETRY_WAIT_TIME_MS = 3000;
|
||||
|
||||
// structure for retrying methods in the database
|
||||
// private RetryTemplate retryTemplate;
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.service;
|
||||
|
||||
public interface DefaultService {
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.service;
|
||||
|
||||
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
||||
import hirs.attestationca.persist.entity.userdefined.Device;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import hirs.attestationca.persist.enums.HealthStatus;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* https://github.com/darrachequesne/spring-data-jpa-datatables
|
||||
*/
|
||||
@Service
|
||||
public class DeviceServiceImpl {
|
||||
|
||||
@Autowired(required = false)
|
||||
private EntityManager entityManager;
|
||||
@Autowired
|
||||
private DeviceRepository deviceRepository;
|
||||
|
||||
private static List<Device> devices = new ArrayList<>(Arrays.asList(
|
||||
new Device("Dell", HealthStatus.TRUSTED,
|
||||
AppraisalStatus.Status.UNKNOWN,
|
||||
Timestamp.valueOf(LocalDateTime.MAX), false, "testing", "resting"),
|
||||
new Device("Intel", HealthStatus.UNTRUSTED,
|
||||
AppraisalStatus.Status.FAIL,
|
||||
Timestamp.valueOf(LocalDateTime.MIN), false, "testing", "resting"),
|
||||
new Device("Cybex", HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.PASS,
|
||||
Timestamp.valueOf(LocalDateTime.now()), false, "testing", "resting")));
|
||||
|
||||
public List<Device> retrieveDevices() {
|
||||
List<Device> devices = new ArrayList<Device>();
|
||||
|
||||
for (Device device : this.devices) {
|
||||
devices.add(device);
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.service;
|
||||
|
||||
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
|
||||
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Service
|
||||
public class ReferenceManifestServiceImpl {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(ReferenceManifestServiceImpl.class);
|
||||
/**
|
||||
* The variable that establishes a schema factory for xml processing.
|
||||
*/
|
||||
public static final SchemaFactory SCHEMA_FACTORY
|
||||
= SchemaFactory.newInstance(ReferenceManifest.SCHEMA_LANGUAGE);
|
||||
|
||||
@Autowired(required = false)
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
private ReferenceManifestRepository repository;
|
||||
|
||||
private static Schema schema;
|
||||
|
||||
public ReferenceManifestServiceImpl() {
|
||||
getSchemaObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the xml schema for processing RIMs.
|
||||
*
|
||||
* @return the schema
|
||||
*/
|
||||
public static final Schema getSchemaObject() {
|
||||
if (schema == null) {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = ReferenceManifest.class
|
||||
.getClassLoader()
|
||||
.getResourceAsStream(ReferenceManifest.SCHEMA_URL);
|
||||
schema = SCHEMA_FACTORY.newSchema(new StreamSource(is));
|
||||
} catch (SAXException saxEx) {
|
||||
LOGGER.error(String.format("Error setting schema for validation!%n%s",
|
||||
saxEx.getMessage()));
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException ioEx) {
|
||||
LOGGER.error(String.format("Error closing input stream%n%s",
|
||||
ioEx.getMessage()));
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Input stream variable is null");
|
||||
}
|
||||
}
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.service;
|
||||
|
||||
import hirs.attestationca.persist.entity.manager.SettingsRepository;
|
||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainSettings;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SettingsServiceImpl {
|
||||
|
||||
@Autowired(required = false)
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
private SettingsRepository repository;
|
||||
|
||||
public SupplyChainSettings updateSettings(SupplyChainSettings settings) {
|
||||
SupplyChainSettings existing = repository.findByName(settings.getName());
|
||||
|
||||
if (existing != null) {
|
||||
settings.setId(existing.getId());
|
||||
}
|
||||
return repository.save(settings);
|
||||
}
|
||||
|
||||
public void saveSettings(SupplyChainSettings settings) {
|
||||
repository.save(settings);
|
||||
}
|
||||
|
||||
public SupplyChainSettings getByName(String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
return repository.findByName(name);
|
||||
}
|
||||
|
||||
// public Policy getDefaultPolicy(Appraiser appraiser) {
|
||||
// return repository.findByAppraiser(appraiser);
|
||||
// }
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.type;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.type.StringType;
|
||||
import org.hibernate.type.descriptor.java.StringJavaType;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This is a class for persisting <code>InetAddress</code> objects via
|
||||
* Hibernate. This class provides the mapping from <code>InetAddress</code> to
|
||||
* Hibernate commands to JDBC.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PUBLIC)
|
||||
public final class InetAddressType implements UserType {
|
||||
|
||||
/**
|
||||
* Returns varchar type.
|
||||
*
|
||||
* @return varchar type
|
||||
*/
|
||||
@Override
|
||||
public int getSqlType() {
|
||||
return new StringJavaType.INSTANCE.sqlType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>InetAddress</code> class.
|
||||
*
|
||||
* @return <code>InetAddress</code> class
|
||||
*/
|
||||
@Override
|
||||
public Class returnedClass() {
|
||||
return InetAddress.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares x and y using {@link java.util.Objects#equals(Object, Object)}.
|
||||
*
|
||||
* @param x x
|
||||
* @param y y
|
||||
* @return value from equals call
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(final Object x, final Object y) {
|
||||
return Objects.equals(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash code of x, which will be the same as from
|
||||
* <code>InetAddress</code>.
|
||||
*
|
||||
* @param x x
|
||||
* @return hash value of x
|
||||
*/
|
||||
@Override
|
||||
public int hashCode(final Object x) {
|
||||
assert x != null;
|
||||
return x.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the IP address that is stored as a <code>String</code> and
|
||||
* converts it to an <code>InetAddress</code>.
|
||||
*
|
||||
* @param rs
|
||||
* result set
|
||||
* @param names
|
||||
* column names
|
||||
* @param session
|
||||
* session
|
||||
* @param owner
|
||||
* owner
|
||||
* @return InetAddress of String
|
||||
* @throws HibernateException
|
||||
* if unable to convert the String to an InetAddress
|
||||
* @throws java.sql.SQLException
|
||||
* if unable to retrieve the String from the result set
|
||||
*/
|
||||
@Override
|
||||
public Object nullSafeGet(final ResultSet rs, final String[] names,
|
||||
final SharedSessionContractImplementor session, final Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
|
||||
final String ip = StringJavaType.INSTANCE.getReplacement(rs.toString(), names[0],
|
||||
session);
|
||||
if (ip == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return InetAddress.getByName(ip);
|
||||
} catch (UnknownHostException e) {
|
||||
final String msg = String.format("unable to convert ip address: %s", ip);
|
||||
throw new HibernateException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the <code>InetAddress</code> <code>value</code> to a
|
||||
* <code>String</code> and stores it in the database.
|
||||
*
|
||||
* @param st prepared statement
|
||||
* @param value InetAddress
|
||||
* @param index index
|
||||
* @param session session
|
||||
* @throws java.sql.SQLException if unable to set the value in the result set
|
||||
*/
|
||||
@Override
|
||||
public void nullSafeSet(final PreparedStatement st, final Object value,
|
||||
final int index, final SharedSessionContractImplementor session)
|
||||
throws SQLException {
|
||||
if (value == null) {
|
||||
StringJavaType.INSTANCE.set(st, null, index, session);
|
||||
} else {
|
||||
final InetAddress address = (InetAddress) value;
|
||||
final String ip = address.getHostAddress();
|
||||
StringJavaType.INSTANCE.set(st, ip, index, session);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>value</code> since <code>InetAddress</code> is immutable.
|
||||
*
|
||||
* @param value value
|
||||
* @return value
|
||||
* @throws HibernateException will never be thrown
|
||||
*/
|
||||
@Override
|
||||
public Object deepCopy(final Object value) throws HibernateException {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false because <code>InetAddress</code> is immutable.
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>value</code> because <code>InetAddress</code> is
|
||||
* immutable.
|
||||
*
|
||||
* @param value value
|
||||
* @return value
|
||||
*/
|
||||
@Override
|
||||
public Serializable disassemble(final Object value) {
|
||||
return (Serializable) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>cached</code> because <code>InetAddress</code> is
|
||||
* immutable.
|
||||
*
|
||||
* @param cached cached
|
||||
* @param owner owner
|
||||
* @return cached
|
||||
*/
|
||||
@Override
|
||||
public Object assemble(final Serializable cached, final Object owner) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>original</code> because <code>InetAddress</code> is
|
||||
* immutable.
|
||||
*
|
||||
* @param original original
|
||||
* @param target target
|
||||
* @param owner owner
|
||||
* @return original
|
||||
*/
|
||||
@Override
|
||||
public Object replace(final Object original, final Object target,
|
||||
final Object owner) {
|
||||
return original;
|
||||
}
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
package hirs.attestationca.portal.persist.type;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
||||
import javax.sql.rowset.serial.SerialBlob;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.sql.Blob;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This is a class for persisting <code>X509Certificate</code> objects via
|
||||
* Hibernate. This class provides the mapping from <code>X509Certificate</code>
|
||||
* to Hibernate commands to JDBC.
|
||||
*/
|
||||
@NoArgsConstructor(access= AccessLevel.PUBLIC)
|
||||
public final class X509CertificateType implements UserType {
|
||||
|
||||
@Override
|
||||
public int getSqlType() {
|
||||
return Types.BLOB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>X509Certificate</code> class.
|
||||
*
|
||||
* @return <code>X509Certificate</code> class
|
||||
*/
|
||||
@Override
|
||||
public Class returnedClass() {
|
||||
return X509Certificate.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares x and y using {@link java.util.Objects#equals(Object, Object)}.
|
||||
*
|
||||
* @param x x
|
||||
* @param y y
|
||||
* @return value from equals call
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(final Object x, final Object y) {
|
||||
return Objects.equals(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash code of x, which will be the same as from
|
||||
* <code>X509Certificate</code>.
|
||||
*
|
||||
* @param x x
|
||||
* @return hash value of x
|
||||
*/
|
||||
@Override
|
||||
public int hashCode(final Object x) {
|
||||
assert x != null;
|
||||
return x.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the X509Certificate that is stored as a <code>String</code> and
|
||||
* converts it to an <code>X509Certificate</code>.
|
||||
*
|
||||
* @param rs
|
||||
* result set
|
||||
* @param names
|
||||
* column names
|
||||
* @param session
|
||||
* session
|
||||
* @param owner
|
||||
* owner
|
||||
* @return X509Certificate of String
|
||||
* @throws HibernateException
|
||||
* if unable to convert the String to an X509Certificate
|
||||
* @throws java.sql.SQLException
|
||||
* if unable to retrieve the String from the result set
|
||||
*/
|
||||
@Override
|
||||
public Object nullSafeGet(final ResultSet rs, final int names,
|
||||
final SharedSessionContractImplementor session, final Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
final Blob cert = rs.getBlob(names);
|
||||
if (cert == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
InputStream inputStream = new ByteArrayInputStream(
|
||||
cert.getBytes(1, (int) cert.length()));
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
return cf.generateCertificate(inputStream);
|
||||
} catch (CertificateException e) {
|
||||
final String msg = String.format(
|
||||
"unable to convert certificate: %s", cert);
|
||||
throw new HibernateException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the <code>X509Certificate</code> <code>value</code> to a
|
||||
* <code>String</code> and stores it in the database.
|
||||
*
|
||||
* @param st prepared statement
|
||||
* @param value X509Certificate
|
||||
* @param index index
|
||||
* @param session session
|
||||
* @throws java.sql.SQLException if unable to set the value in the result set
|
||||
*/
|
||||
@Override
|
||||
public void nullSafeSet(final PreparedStatement st, final Object value,
|
||||
final int index, final SharedSessionContractImplementor session)
|
||||
throws SQLException {
|
||||
if (value == null) {
|
||||
st.setString(index, null);
|
||||
} else {
|
||||
try {
|
||||
Blob blob =
|
||||
new SerialBlob(((Certificate) value).getEncoded());
|
||||
st.setBlob(index, blob);
|
||||
} catch (Exception e) {
|
||||
final String msg =
|
||||
String.format("unable to convert certificate: %s",
|
||||
value.toString());
|
||||
throw new HibernateException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>value</code> since <code>X509Certificate</code> is
|
||||
* immutable.
|
||||
*
|
||||
* @param value value
|
||||
* @return value
|
||||
* @throws HibernateException will never be thrown
|
||||
*/
|
||||
@Override
|
||||
public Object deepCopy(final Object value) throws HibernateException {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false because <code>X509Certificate</code> is immutable.
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>value</code> because <code>X509Certificate</code> is
|
||||
* immutable.
|
||||
*
|
||||
* @param value value
|
||||
* @return value
|
||||
*/
|
||||
@Override
|
||||
public Serializable disassemble(final Object value) {
|
||||
return (Serializable) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>cached</code> because <code>X509Certificate</code> is
|
||||
* immutable.
|
||||
*
|
||||
* @param cached cached
|
||||
* @param owner owner
|
||||
* @return cached
|
||||
*/
|
||||
@Override
|
||||
public Object assemble(final Serializable cached, final Object owner) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>original</code> because <code>X509Certificate</code> is
|
||||
* immutable.
|
||||
*
|
||||
* @param original original
|
||||
* @param target target
|
||||
* @param owner owner
|
||||
* @return original
|
||||
*/
|
||||
@Override
|
||||
public Object replace(final Object original, final Object target,
|
||||
final Object owner) {
|
||||
return original;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package hirs.attestationca.portal.portal;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"hirs.attestationca.portal", "hirs.attestationca.portal.page.controllers", "hirs.attestationca.persist.entity", "hirs.attestationca.persist.entity.service"})
|
||||
public class HIRSApplication extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(HIRSApplication.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication springApplication = new SpringApplication(HIRSApplication.class);
|
||||
springApplication.setDefaultProperties(Collections.singletonMap("server.servlet.context-path", "/portal"));
|
||||
springApplication.run(args);
|
||||
// SpringApplication.run(HIRSApplication.class, args);
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package hirs.attestationca.portal.portal;
|
||||
|
||||
import hirs.attestationca.persist.service.SettingsServiceImpl;
|
||||
import jakarta.servlet.ServletContextListener;
|
||||
import jakarta.servlet.annotation.WebListener;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
||||
@WebListener
|
||||
public class HIRSDbInitializer implements ServletContextListener {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(HIRSDbInitializer.class);
|
||||
|
||||
@Autowired
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
@Autowired
|
||||
static SettingsServiceImpl settingsService = new SettingsServiceImpl();
|
||||
//
|
||||
// public void contextInitialized(final ServletContextEvent servletContextEvent) {
|
||||
//// AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
// context.getEnvironment().addActiveProfile("server");
|
||||
// context.register(PersistenceJPAConfig.class);
|
||||
// context.refresh();
|
||||
//
|
||||
// // obtain reference to hibernate session factory
|
||||
// EntityManager entityManager = context.getBean(EntityManagerFactory.class)
|
||||
// .createEntityManager();
|
||||
// /**
|
||||
// * This fails if there is an entry already.
|
||||
// */
|
||||
//// entityManager.getTransaction().begin();
|
||||
//// entityManager.persist(context.getBean("default-settings"));
|
||||
//// entityManager.getTransaction().commit();
|
||||
//
|
||||
// insertDefaultEntries();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Insert the ACA's default entries into the DB. This class is invoked after successful
|
||||
// * install of the HIRS_AttestationCA RPM.
|
||||
// *
|
||||
// */
|
||||
// public static synchronized void insertDefaultEntries() {
|
||||
// LOGGER.error("Ensuring default ACA database entries are present.");
|
||||
//
|
||||
// // If the SupplyChainAppraiser exists, do not attempt to re-save the supply chain appraiser
|
||||
// // or SupplyChainSettings
|
||||
//
|
||||
// // Create the SupplyChainAppraiser
|
||||
// LOGGER.error("Saving supply chain appraiser...");
|
||||
//
|
||||
//
|
||||
// // Create the SupplyChainSettings
|
||||
// LOGGER.error("Saving default supply chain policy...");
|
||||
//// SupplyChainSettings supplyChainPolicy = new SupplyChainSettings(
|
||||
//// SupplyChainSettings.DEFAULT_POLICY);
|
||||
// settingsService.saveSettings(new SupplyChainSettings("Default", "Settings are configured for no validation flags set."));
|
||||
//
|
||||
// LOGGER.error("ACA database initialization complete.");
|
||||
// }
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package hirs.attestationca.portal.portal;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.JpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@PropertySource({ "classpath:hibernate.properties" })
|
||||
@ComponentScan({ "hirs.attestationca.portal.page" })
|
||||
@EnableJpaRepositories(basePackages = "hirs.attestationca.persist")
|
||||
public class PersistenceJPAConfig {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
final LocalContainerEntityManagerFactoryBean entityManagerBean = new LocalContainerEntityManagerFactoryBean();
|
||||
entityManagerBean.setDataSource(dataSource());
|
||||
entityManagerBean.setPackagesToScan(new String[] {"hirs.attestationca.persist"});
|
||||
|
||||
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||
entityManagerBean.setJpaVendorAdapter(vendorAdapter);
|
||||
entityManagerBean.setJpaProperties(additionalProperties());
|
||||
|
||||
return entityManagerBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||
dataSource.setDriverClassName(environment.getProperty("hibernate.connection.driver_class"));
|
||||
dataSource.setUrl(environment.getProperty("hibernate.connection.url"));
|
||||
dataSource.setUsername(environment.getProperty("hibernate.connection.username"));
|
||||
dataSource.setPassword(environment.getProperty("hibernate.connection.password"));
|
||||
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
final JpaTransactionManager transactionManager = new JpaTransactionManager();
|
||||
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
|
||||
return new PersistenceExceptionTranslationPostProcessor();
|
||||
}
|
||||
|
||||
final Properties additionalProperties() {
|
||||
final Properties hibernateProperties = new Properties();
|
||||
hibernateProperties.setProperty("hibernate.hbm2ddl.auto",
|
||||
environment.getProperty("hibernate.hbm2ddl.auto"));
|
||||
hibernateProperties.setProperty("hibernate.dialect",
|
||||
environment.getProperty("hibernate.dialect"));
|
||||
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache",
|
||||
"false");
|
||||
|
||||
return hibernateProperties;
|
||||
}
|
||||
//
|
||||
// @Bean(name="default-settings")
|
||||
// public SupplyChainSettings supplyChainSettings() {
|
||||
// SupplyChainSettings scSettings = new SupplyChainSettings("Default", "Settings are configured for no validation flags set.");
|
||||
//
|
||||
// return scSettings;
|
||||
// }
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.datatables;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A Wrapper for Data Table JSON responses. Allows Spring to serialize a data object with additional
|
||||
* meta data required by data tables.
|
||||
*
|
||||
* @param <T> the type of object that is being wrapped.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PUBLIC)
|
||||
public final class DataTableResponse<T> {
|
||||
|
||||
private List<T> data = new LinkedList<T>();
|
||||
@Getter @Setter
|
||||
private int draw;
|
||||
@Getter @Setter
|
||||
private long recordsTotal, recordsFiltered;
|
||||
|
||||
/**
|
||||
* Builds a data table response using a FilteredRecordList.
|
||||
*
|
||||
* @param recordList the filtered record list
|
||||
* @param inputQuery the data table input (used for draw)
|
||||
*/
|
||||
// public DataTableResponse(final FilteredRecordsList<T> recordList,
|
||||
// final DataTableInput inputQuery) {
|
||||
// this(recordList, inputQuery.getDraw(),
|
||||
// recordList.getRecordsTotal(), recordList.getRecordsFiltered());
|
||||
// }
|
||||
|
||||
/**
|
||||
* Constructs a data table response using the specified data with the data table specific
|
||||
* information.
|
||||
*
|
||||
* @param data that is to be displayed by data table
|
||||
* @param draw the originating draw request ID (usually from a web request)
|
||||
* @param recordsTotal total number of records inside the data
|
||||
* @param recordsFiltered number of records excluded from the request
|
||||
*/
|
||||
public DataTableResponse(final List<T> data, final int draw, final long recordsTotal,
|
||||
final long recordsFiltered) {
|
||||
setData(data);
|
||||
this.draw = draw;
|
||||
this.recordsTotal = recordsTotal;
|
||||
this.recordsFiltered = recordsFiltered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data table data.
|
||||
*
|
||||
* @return the data
|
||||
*/
|
||||
public List<T> getData() {
|
||||
return Collections.unmodifiableList(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data table data.
|
||||
*
|
||||
* @param data the data
|
||||
*/
|
||||
public void setData(final List<T> data) {
|
||||
this.data.clear();
|
||||
this.data.addAll(data);
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Root Package for HIRS Attestation CA Portal.
|
||||
*/
|
||||
package hirs.attestationca.portal.portal;
|
@ -1,172 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.page;
|
||||
|
||||
import hirs.attestationca.persist.enums.Page;
|
||||
import hirs.attestationca.utils.BannerConfiguration;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.ui.ExtendedModelMap;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Abstract class to provide common functionality for page Controllers.
|
||||
*
|
||||
* @param <P> PageParams class used by the subclass.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public abstract class PageController<P extends PageParams> {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(PageController.class);
|
||||
|
||||
/**
|
||||
* Model attribute name used by initPage for the initial data passed to the page.
|
||||
*/
|
||||
public static final String INITIAL_DATA = "initialData";
|
||||
|
||||
/**
|
||||
* Reserved attribute used by page.tag to identify a page's general
|
||||
* information.
|
||||
*/
|
||||
public static final String PAGE_ATTRIBUTE = "page";
|
||||
|
||||
/**
|
||||
* Reserved attribute used by page.tag to identify the page collection used
|
||||
* for navigation.
|
||||
*/
|
||||
public static final String PAGES_ATTRIBUTE = "pages";
|
||||
|
||||
/**
|
||||
* Reserved attribute used by page.tag to identify the banner information.
|
||||
*/
|
||||
public static final String BANNER_ATTRIBUTE = "banner";
|
||||
|
||||
/**
|
||||
* Reserved attribute used by page.tag to identify the messages the page
|
||||
* should display.
|
||||
*/
|
||||
public static final String MESSAGES_ATTRIBUTE = "messages";
|
||||
|
||||
private final Page page;
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from
|
||||
* redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@RequestMapping
|
||||
public abstract ModelAndView initPage(@ModelAttribute P params, Model model);
|
||||
|
||||
/**
|
||||
* Creates a generic ModelAndView containing this page's configuration and
|
||||
* the list of other pages for navigational purposes.
|
||||
*
|
||||
* @return A generic ModelAndView containing basic information for the page.
|
||||
*/
|
||||
protected final ModelAndView getBaseModelAndView() {
|
||||
return getBaseModelAndView(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a generic ModelAndView containing the specify page
|
||||
* configuration and the list of other pages for navigational
|
||||
* purposes.
|
||||
*
|
||||
* @param newPage new page to get the model and view
|
||||
* @return A generic ModelAndView containing basic information for the page.
|
||||
*/
|
||||
protected final ModelAndView getBaseModelAndView(final Page newPage) {
|
||||
ModelMap modelMap = new ExtendedModelMap();
|
||||
|
||||
// add page information
|
||||
modelMap.addAttribute(PAGE_ATTRIBUTE, newPage);
|
||||
|
||||
// add other pages for navigation
|
||||
modelMap.addAttribute(PAGES_ATTRIBUTE, Page.values());
|
||||
|
||||
// add banner information
|
||||
try {
|
||||
BannerConfiguration banner = new BannerConfiguration();
|
||||
modelMap.addAttribute(BANNER_ATTRIBUTE, banner);
|
||||
} catch (IOException ex) {
|
||||
modelMap.addAttribute(BANNER_ATTRIBUTE, null);
|
||||
}
|
||||
|
||||
return new ModelAndView(newPage.getViewName(), modelMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects back to this controller's page with the specified data.
|
||||
*
|
||||
* @param params The url parameters to pass to the page.
|
||||
* @param model The model data to pass to the page.
|
||||
* @param attr The request's RedirectAttributes to hold the model data.
|
||||
* @return RedirectView back to the page with the specified parameters.
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
protected final RedirectView redirectToSelf(
|
||||
final P params,
|
||||
final Map<String, ?> model,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
return redirectTo(page, params, model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects controller's page with the specified data.
|
||||
*
|
||||
* @param newPage new page to get the model and view
|
||||
* @param params The url parameters to pass to the page.
|
||||
* @param model The model data to pass to the page.
|
||||
* @param attr The request's RedirectAttributes to hold the model data.
|
||||
* @return RedirectView back to the page with the specified parameters.
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
protected final RedirectView redirectTo(
|
||||
final Page newPage,
|
||||
final P params,
|
||||
final Map<String, ?> model,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
String defaultUri = "../" + newPage.getViewName();
|
||||
// create uri with specified parameters
|
||||
URIBuilder uri = new URIBuilder("../" + newPage.getViewName());
|
||||
LOGGER.debug("Redirection URI = " + uri.toString());
|
||||
|
||||
if (params != null) {
|
||||
for (Map.Entry<String, ?> e : params.asMap().entrySet()) {
|
||||
Object v = Optional.ofNullable(e.getValue()).orElse("");
|
||||
uri.addParameter(e.getKey(), v.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// create view
|
||||
RedirectView redirect = new RedirectView(defaultUri);
|
||||
|
||||
// do not put model attributes in the url
|
||||
redirect.setExposeModelAttributes(false);
|
||||
|
||||
// add model data to forward to redirected page
|
||||
if (model != null) {
|
||||
for (Map.Entry<String, ?> e : model.entrySet()) {
|
||||
attr.addFlashAttribute(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return redirect;
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.page;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Encapsulates error, success, and informational messages to display on a page.
|
||||
*/
|
||||
public class PageMessages {
|
||||
|
||||
private final List<String> error = new ArrayList<>();
|
||||
private final List<String> success = new ArrayList<>();
|
||||
private final List<String> info = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Returns the list of error messages.
|
||||
*
|
||||
* @return the list of error messages.
|
||||
*/
|
||||
public List<String> getError() {
|
||||
return Collections.unmodifiableList(error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error message.
|
||||
*
|
||||
* @param error the error message to add
|
||||
*/
|
||||
public void addError(final String error) {
|
||||
this.error.add(error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of success messages.
|
||||
*
|
||||
* @return the list of success messages.
|
||||
*/
|
||||
public List<String> getSuccess() {
|
||||
return Collections.unmodifiableList(success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a success message.
|
||||
*
|
||||
* @param success the success message to add
|
||||
*/
|
||||
public void addSuccess(final String success) {
|
||||
this.success.add(success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of informational messages.
|
||||
*
|
||||
* @return the list of informational messages.
|
||||
*/
|
||||
public List<String> getInfo() {
|
||||
return Collections.unmodifiableList(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an informational message.
|
||||
*
|
||||
* @param info the informational message to add
|
||||
*/
|
||||
public void addInfo(final String info) {
|
||||
this.info.add(info);
|
||||
}
|
||||
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.page;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* Interface for a page's url parameters.
|
||||
*/
|
||||
public interface PageParams {
|
||||
|
||||
/**
|
||||
* Allows PageController to iterate over the url parameters.
|
||||
*
|
||||
* @return map containing the object's url parameters.
|
||||
*/
|
||||
LinkedHashMap<String, ?> asMap();
|
||||
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.page;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainSettings;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* PolicyPage model object to demonstrate data exchange between policy.jsp page
|
||||
* form form and controller.
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
public class PolicyPageModel {
|
||||
// Variables to communicate policy settings to page
|
||||
private boolean enableEcValidation;
|
||||
private boolean enablePcCertificateValidation;
|
||||
private boolean enablePcCertificateAttributeValidation;
|
||||
private boolean enableFirmwareValidation;
|
||||
private boolean issueAttestationCertificate;
|
||||
private boolean issueDevIdCertificate;
|
||||
private boolean generateOnExpiration;
|
||||
private boolean devIdExpirationFlag;
|
||||
private boolean enableIgnoreIma;
|
||||
private boolean enableIgnoreTboot;
|
||||
private boolean enableIgnoreGpt;
|
||||
private boolean enableIgnoreOsEvt;
|
||||
|
||||
// Variables to get policy settings from page
|
||||
private String pcValidate;
|
||||
private String pcAttributeValidate;
|
||||
private String ecValidate;
|
||||
private String fmValidate;
|
||||
private String attestationCertificateIssued;
|
||||
private String devIdCertificateIssued;
|
||||
private String generationExpirationOn;
|
||||
private String devIdExpirationChecked;
|
||||
private String numOfValidDays;
|
||||
private String reissueThreshold;
|
||||
private String devIdReissueThreshold;
|
||||
private String ignoreIma;
|
||||
private String ignoretBoot;
|
||||
private String ignoreGpt;
|
||||
private String ignoreOsEvt;
|
||||
private String expirationValue;
|
||||
private String devIdExpirationValue;
|
||||
private String thresholdValue;
|
||||
private String devIdThresholdValue;
|
||||
|
||||
/**
|
||||
* Constructor. Sets fields from policy.
|
||||
*
|
||||
* @param policy The supply chain policy
|
||||
*/
|
||||
public PolicyPageModel(final SupplyChainSettings policy) {
|
||||
this.enableEcValidation = policy.isEcValidationEnabled();
|
||||
this.enablePcCertificateValidation = policy.isPcValidationEnabled();
|
||||
this.enablePcCertificateAttributeValidation = policy.isPcAttributeValidationEnabled();
|
||||
this.enableFirmwareValidation = policy.isFirmwareValidationEnabled();
|
||||
this.issueAttestationCertificate = policy.isIssueAttestationCertificate();
|
||||
this.issueDevIdCertificate = policy.isIssueDevIdCertificate();
|
||||
this.generateOnExpiration = policy.isGenerateOnExpiration();
|
||||
this.devIdExpirationFlag = policy.isDevIdExpirationFlag();
|
||||
this.numOfValidDays = policy.getValidityDays();
|
||||
this.reissueThreshold = policy.getReissueThreshold();
|
||||
this.expirationValue = policy.getValidityDays();
|
||||
this.thresholdValue = policy.getReissueThreshold();
|
||||
this.devIdExpirationValue = policy.getDevIdValidityDays();
|
||||
this.devIdReissueThreshold = policy.getDevIdReissueThreshold();
|
||||
this.devIdThresholdValue = policy.getDevIdReissueThreshold();
|
||||
// pcrPolicy
|
||||
this.enableIgnoreIma = policy.isIgnoreImaEnabled();
|
||||
this.enableIgnoreTboot = policy.isIgnoretBootEnabled();
|
||||
this.enableIgnoreGpt = policy.isIgnoreGptEnabled();
|
||||
this.enableIgnoreOsEvt = policy.isIgnoreOsEvtEnabled();
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.page.controllers;
|
||||
|
||||
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
||||
import hirs.attestationca.persist.entity.userdefined.Device;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import hirs.attestationca.persist.enums.HealthStatus;
|
||||
import hirs.attestationca.persist.enums.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import hirs.attestationca.persist.service.DeviceServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/devices")
|
||||
public class DevicePageController extends PageController<NoPageParams> {
|
||||
/**
|
||||
* https://odrotbohm.de/2013/11/why-field-injection-is-evil/
|
||||
*
|
||||
* Autowiring property vs constructor
|
||||
*/
|
||||
|
||||
private final DeviceServiceImpl deviceServiceImpl;
|
||||
private final DeviceRepository deviceRepository;
|
||||
|
||||
@Autowired
|
||||
public DevicePageController(DeviceServiceImpl deviceServiceImpl,
|
||||
DeviceRepository deviceRepository) {
|
||||
super(Page.DEVICES);
|
||||
this.deviceServiceImpl = deviceServiceImpl;
|
||||
this.deviceRepository = deviceRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final NoPageParams params, final Model model) {
|
||||
return getBaseModelAndView();
|
||||
}
|
||||
|
||||
// @RequestMapping(value = "list", produces = MediaType.APPLICATION_JSON_VALUE,
|
||||
// method = RequestMethod.GET)
|
||||
// public DataTableResponse<HashMap<String, Object>> getTableData(
|
||||
// final DataTableInput input) {
|
||||
// String orderColumnName = input.getOrderColumnName();
|
||||
// FilteredRecordsList<HashMap<String, Object>> record
|
||||
// = retrieveDevicesAndAssociatedCertificates(deviceList);
|
||||
// modelMap.put("devices", deviceServiceImpl.retrieveDevices());
|
||||
// return new DataTableResponse<>(record, input);
|
||||
// }
|
||||
|
||||
@GetMapping(value = "populateDevices")
|
||||
public @ResponseBody String addDevice () {
|
||||
deviceRepository.save(new Device("Dell-01", HealthStatus.TRUSTED,
|
||||
AppraisalStatus.Status.UNKNOWN,
|
||||
Timestamp.valueOf(LocalDateTime.now()), false, "", "This is a summary"));
|
||||
|
||||
deviceRepository.save(new Device("Dell-02", HealthStatus.TRUSTED,
|
||||
AppraisalStatus.Status.UNKNOWN,
|
||||
Timestamp.valueOf(LocalDateTime.now()), false, "", "This is a summary"));
|
||||
|
||||
deviceRepository.save(new Device("HP-01", HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN,
|
||||
Timestamp.valueOf(LocalDateTime.now()), false, "", "This is a summary"));
|
||||
|
||||
deviceRepository.save(new Device("HP-02", HealthStatus.UNTRUSTED,
|
||||
AppraisalStatus.Status.UNKNOWN,
|
||||
Timestamp.valueOf(LocalDateTime.now()), false, "", "This is a summary"));
|
||||
|
||||
return "all";
|
||||
}
|
||||
|
||||
@GetMapping(path="/all")
|
||||
public @ResponseBody Iterable<Device> getAllDevices() {
|
||||
return deviceRepository.findAll();
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.page.controllers;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
|
||||
@Controller("error")
|
||||
public class ErrorController {
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ModelAndView handleException(HttpServletRequest request, Exception ex) {
|
||||
ModelAndView modelAndView = new ModelAndView();
|
||||
|
||||
modelAndView.addObject("exception", ex.getLocalizedMessage());
|
||||
modelAndView.addObject("url", request.getRequestURL());
|
||||
|
||||
modelAndView.setViewName("error");
|
||||
|
||||
return modelAndView;
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.page.controllers;
|
||||
|
||||
import hirs.attestationca.persist.enums.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/index")
|
||||
public class IndexPageController extends PageController<NoPageParams> {
|
||||
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
*/
|
||||
public IndexPageController() {
|
||||
super(Page.INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final NoPageParams params, final Model model) {
|
||||
return getBaseModelAndView();
|
||||
}
|
||||
|
||||
// @RequestMapping(value = "/", method = RequestMethod.GET)
|
||||
// public String showIndexPage(ModelMap model) {
|
||||
// model.put("name", "welcome");
|
||||
// return "welcome";
|
||||
// }
|
||||
}
|
@ -1,964 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.page.controllers;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainSettings;
|
||||
import hirs.attestationca.persist.enums.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.PageMessages;
|
||||
import hirs.attestationca.portal.page.PolicyPageModel;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import hirs.attestationca.persist.service.SettingsServiceImpl;
|
||||
import hirs.attestationca.utils.exception.PolicyManagerException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Controller for the Policy page.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/policy")
|
||||
public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(PolicyPageController.class);
|
||||
|
||||
/**
|
||||
* Represents a web request indicating to enable a setting (based on radio
|
||||
* buttons from a web form).
|
||||
*/
|
||||
private static final String ENABLED_CHECKED_PARAMETER_VALUE = "checked";
|
||||
|
||||
private static final String ENABLED_EXPIRES_PARAMETER_VALUE = "expires";
|
||||
|
||||
private SettingsServiceImpl settingsService;
|
||||
|
||||
/**
|
||||
* Model attribute name used by initPage for the initial data passed to the
|
||||
* page.
|
||||
*/
|
||||
public static final String INITIAL_DATA = "initialData";
|
||||
|
||||
/**
|
||||
* Flash attribute name used by initPage and post for the data forwarded
|
||||
* during the redirect from the POST operation back to the page.
|
||||
*/
|
||||
public static final String RESULT_DATA = "resultData";
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param policyService the policy service
|
||||
*/
|
||||
@Autowired
|
||||
public PolicyPageController(final SettingsServiceImpl policyService) {
|
||||
super(Page.POLICY);
|
||||
this.settingsService = policyService;
|
||||
|
||||
if (this.settingsService.getByName("Default") == null) {
|
||||
this.settingsService.saveSettings(new SupplyChainSettings("Default", "Settings are configured for no validation flags set."));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from
|
||||
* redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final NoPageParams params, final Model model) {
|
||||
// get the basic information to render the page
|
||||
ModelAndView mav = getBaseModelAndView();
|
||||
|
||||
SupplyChainSettings policy = getDefaultPolicy();
|
||||
LOGGER.debug(policy);
|
||||
PolicyPageModel pageModel = new PolicyPageModel(policy);
|
||||
mav.addObject(INITIAL_DATA, pageModel);
|
||||
|
||||
LOGGER.debug(pageModel);
|
||||
|
||||
return mav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Platform Cert Validation policy setting and redirects back to
|
||||
* the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-pc-validation", method = RequestMethod.POST)
|
||||
public RedirectView updatePcVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean pcValidationOptionEnabled
|
||||
= ppModel.getPcValidate().equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
// If PC policy setting change results in invalid policy, inform user
|
||||
if (!isPolicyValid(policy.isEcValidationEnabled(), pcValidationOptionEnabled,
|
||||
policy.isPcAttributeValidationEnabled())) {
|
||||
handleUserError(model, messages,
|
||||
"Unable to change Platform Validation setting,"
|
||||
+ " invalid policy configuration.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
// set the policy option and create display message
|
||||
if (pcValidationOptionEnabled) {
|
||||
policy.setPcValidationEnabled(true);
|
||||
successMessage = "Platform certificate validation enabled";
|
||||
} else {
|
||||
policy.setPcValidationEnabled(false);
|
||||
policy.setPcAttributeValidationEnabled(false);
|
||||
successMessage = "Platform certificate validation disabled";
|
||||
}
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
// Log and return any error messages to the user
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA platform validation Policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Platform Cert Attribute Validation policy setting and
|
||||
* redirects back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-pc-attribute-validation", method = RequestMethod.POST)
|
||||
public RedirectView updatePcAttributeVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean pcAttributeValidationOptionEnabled = ppModel.getPcAttributeValidate()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
// If PC Attribute Validation is enabled without PC Validation, disallow change
|
||||
if (!isPolicyValid(policy.isEcValidationEnabled(),
|
||||
policy.isPcValidationEnabled(), pcAttributeValidationOptionEnabled)) {
|
||||
|
||||
handleUserError(model, messages,
|
||||
"To enable Platform Attribute Validation, Platform Credential Validation"
|
||||
+ " must also be enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
// set the policy option and create display message
|
||||
if (pcAttributeValidationOptionEnabled) {
|
||||
policy.setPcAttributeValidationEnabled(true);
|
||||
successMessage = "Platform certificate attribute validation enabled";
|
||||
} else {
|
||||
policy.setPcAttributeValidationEnabled(false);
|
||||
successMessage = "Platform certificate attribute validation disabled";
|
||||
}
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
// Log and return any error messages to the user
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA platform certificate attribute validation policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Attestation Certificate generation policy setting and redirects
|
||||
* back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-issue-attestation", method = RequestMethod.POST)
|
||||
public RedirectView updateAttestationVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean issuedAttestationOptionEnabled
|
||||
= ppModel.getAttestationCertificateIssued()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
if (issuedAttestationOptionEnabled) {
|
||||
successMessage = "Attestation Certificate generation enabled.";
|
||||
} else {
|
||||
successMessage = "Attestation Certificate generation disabled.";
|
||||
policy.setGenerateOnExpiration(false);
|
||||
}
|
||||
|
||||
policy.setIssueAttestationCertificate(issuedAttestationOptionEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA Attestation Certificate generation policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the DevID Certificate generation policy setting and redirects
|
||||
* back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-issue-devid", method = RequestMethod.POST)
|
||||
public RedirectView updateDevIdVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean issuedDevIdOptionEnabled
|
||||
= ppModel.getDevIdCertificateIssued()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
if (issuedDevIdOptionEnabled) {
|
||||
successMessage = "DevID Certificate generation enabled.";
|
||||
} else {
|
||||
successMessage = "DevID Certificate generation disabled.";
|
||||
policy.setDevIdExpirationFlag(false);
|
||||
}
|
||||
|
||||
policy.setIssueDevIdCertificate(issuedDevIdOptionEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA DevID Certificate generation policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state of the policy setting that indicates that the generation
|
||||
* will occur in a set time frame and redirects
|
||||
* back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-expire-on", method = RequestMethod.POST)
|
||||
public RedirectView updateExpireOnVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
String numOfDays;
|
||||
|
||||
boolean generateCertificateEnabled = false;
|
||||
// because this is just one option, there is not 'unchecked' value, so it is either
|
||||
// 'checked' or null
|
||||
if (ppModel.getGenerationExpirationOn() != null) {
|
||||
generateCertificateEnabled
|
||||
= ppModel.getGenerationExpirationOn()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
}
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
boolean issuedAttestationOptionEnabled
|
||||
= policy.isIssueAttestationCertificate();
|
||||
|
||||
if (issuedAttestationOptionEnabled) {
|
||||
if (generateCertificateEnabled) {
|
||||
successMessage = "Attestation Certificate generation expiration time enabled.";
|
||||
} else {
|
||||
successMessage = "Attestation Certificate generation expiration time disabled.";
|
||||
}
|
||||
|
||||
if (generateCertificateEnabled) {
|
||||
numOfDays = ppModel.getExpirationValue();
|
||||
if (numOfDays == null) {
|
||||
numOfDays = SupplyChainSettings.TEN_YEARS;
|
||||
}
|
||||
} else {
|
||||
numOfDays = policy.getValidityDays();
|
||||
}
|
||||
|
||||
policy.setValidityDays(numOfDays);
|
||||
} else {
|
||||
generateCertificateEnabled = false;
|
||||
successMessage = "Attestation Certificate generation is disabled, "
|
||||
+ "can not set time expiration";
|
||||
}
|
||||
|
||||
policy.setGenerateOnExpiration(generateCertificateEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA Attestation Certificate generation policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state of the policy setting that indicates that the generation
|
||||
* will occur in a set time frame and redirects
|
||||
* back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-devid-expire-on", method = RequestMethod.POST)
|
||||
public RedirectView updateDevIdExpireOnVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
String numOfDays;
|
||||
|
||||
boolean generateDevIdCertificateEnabled = false;
|
||||
// because this is just one option, there is not 'unchecked' value, so it is either
|
||||
// 'checked' or null
|
||||
if (ppModel.getDevIdExpirationChecked() != null) {
|
||||
generateDevIdCertificateEnabled
|
||||
= ppModel.getDevIdExpirationChecked()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
}
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
boolean issuedDevIdOptionEnabled
|
||||
= policy.isIssueDevIdCertificate();
|
||||
|
||||
if (issuedDevIdOptionEnabled) {
|
||||
if (generateDevIdCertificateEnabled) {
|
||||
successMessage = "DevID Certificate generation expiration time enabled.";
|
||||
} else {
|
||||
successMessage = "DevID Certificate generation expiration time disabled.";
|
||||
}
|
||||
|
||||
if (generateDevIdCertificateEnabled) {
|
||||
numOfDays = ppModel.getDevIdExpirationValue();
|
||||
if (numOfDays == null) {
|
||||
numOfDays = SupplyChainSettings.TEN_YEARS;
|
||||
}
|
||||
} else {
|
||||
numOfDays = policy.getDevIdValidityDays();
|
||||
}
|
||||
|
||||
policy.setDevIdValidityDays(numOfDays);
|
||||
} else {
|
||||
generateDevIdCertificateEnabled = false;
|
||||
successMessage = "DevID Certificate generation is disabled, "
|
||||
+ "can not set time expiration";
|
||||
}
|
||||
|
||||
policy.setDevIdExpirationFlag(generateDevIdCertificateEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA DevID Certificate generation policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state of the policy setting that indicates that the generation
|
||||
* will occur in a set time frame from the end validity date and redirects
|
||||
* back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-threshold", method = RequestMethod.POST)
|
||||
public RedirectView updateThresholdVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
String threshold;
|
||||
|
||||
boolean generateCertificateEnabled = false;
|
||||
// because this is just one option, there is not 'unchecked' value, so it is either
|
||||
// 'checked' or null
|
||||
if (ppModel.getGenerationExpirationOn() != null) {
|
||||
generateCertificateEnabled
|
||||
= ppModel.getGenerationExpirationOn()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
}
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
boolean issuedAttestationOptionEnabled
|
||||
= policy.isIssueAttestationCertificate();
|
||||
|
||||
if (issuedAttestationOptionEnabled) {
|
||||
if (generateCertificateEnabled) {
|
||||
successMessage = "Attestation Certificate generation threshold time enabled.";
|
||||
} else {
|
||||
successMessage = "Attestation Certificate generation threshold time disabled.";
|
||||
}
|
||||
|
||||
if (generateCertificateEnabled) {
|
||||
threshold = ppModel.getThresholdValue();
|
||||
} else {
|
||||
threshold = ppModel.getReissueThreshold();
|
||||
}
|
||||
|
||||
if (threshold == null || threshold.isEmpty()) {
|
||||
threshold = SupplyChainSettings.YEAR;
|
||||
}
|
||||
|
||||
policy.setReissueThreshold(threshold);
|
||||
} else {
|
||||
generateCertificateEnabled = false;
|
||||
successMessage = "Attestation Certificate generation is disabled, "
|
||||
+ "can not set time expiration";
|
||||
}
|
||||
|
||||
policy.setGenerateOnExpiration(generateCertificateEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA Attestation Certificate generation policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state of the policy setting that indicates that the generation
|
||||
* will occur in a set time frame from the end validity date and redirects
|
||||
* back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-devid-threshold", method = RequestMethod.POST)
|
||||
public RedirectView updateDevIdThresholdVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
String threshold;
|
||||
|
||||
boolean generateDevIdCertificateEnabled = false;
|
||||
// because this is just one option, there is not 'unchecked' value, so it is either
|
||||
// 'checked' or null
|
||||
if (ppModel.getDevIdExpirationChecked() != null) {
|
||||
generateDevIdCertificateEnabled
|
||||
= ppModel.getDevIdExpirationChecked()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
}
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
boolean issuedDevIdOptionEnabled
|
||||
= policy.isIssueDevIdCertificate();
|
||||
|
||||
if (issuedDevIdOptionEnabled) {
|
||||
if (generateDevIdCertificateEnabled) {
|
||||
successMessage = "DevID Certificate generation threshold time enabled.";
|
||||
} else {
|
||||
successMessage = "DevID Certificate generation threshold time disabled.";
|
||||
}
|
||||
|
||||
if (generateDevIdCertificateEnabled) {
|
||||
threshold = ppModel.getDevIdThresholdValue();
|
||||
} else {
|
||||
threshold = ppModel.getDevIdReissueThreshold();
|
||||
}
|
||||
|
||||
if (threshold == null || threshold.isEmpty()) {
|
||||
threshold = SupplyChainSettings.YEAR;
|
||||
}
|
||||
|
||||
policy.setDevIdReissueThreshold(threshold);
|
||||
} else {
|
||||
generateDevIdCertificateEnabled = false;
|
||||
successMessage = "DevID Certificate generation is disabled, "
|
||||
+ "can not set time expiration";
|
||||
}
|
||||
|
||||
policy.setDevIdExpirationFlag(generateDevIdCertificateEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA DevID Certificate generation policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Endorsement Credential Validation policy setting and
|
||||
* redirects back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-ec-validation", method = RequestMethod.POST)
|
||||
public RedirectView updateEcVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean ecValidationOptionEnabled
|
||||
= ppModel.getEcValidate().equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If PC Validation is enabled without EC Validation, disallow change
|
||||
if (!isPolicyValid(ecValidationOptionEnabled, policy.isPcValidationEnabled(),
|
||||
policy.isPcAttributeValidationEnabled())) {
|
||||
handleUserError(model, messages,
|
||||
"To disable Endorsement Credential Validation, Platform Validation"
|
||||
+ " must also be disabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
// set the policy option and create success message
|
||||
if (ecValidationOptionEnabled) {
|
||||
policy.setEcValidationEnabled(true);
|
||||
successMessage = "Endorsement credential validation enabled";
|
||||
} else {
|
||||
policy.setEcValidationEnabled(false);
|
||||
successMessage = "Endorsement credential validation disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA endorsement validation policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Firmware Validation policy setting and
|
||||
* redirects back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-firmware-validation", method = RequestMethod.POST)
|
||||
public RedirectView updateFirmwareVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean firmwareValidationOptionEnabled = ppModel.getFmValidate()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If firmware is enabled without PC attributes, disallow change
|
||||
if (firmwareValidationOptionEnabled && !policy.isPcAttributeValidationEnabled()) {
|
||||
handleUserError(model, messages,
|
||||
"Firmware validation can not be "
|
||||
+ "enabled without PC Attributes policy enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
// set the policy option and create success message
|
||||
if (firmwareValidationOptionEnabled) {
|
||||
policy.setFirmwareValidationEnabled(true);
|
||||
policy.setIgnoreGptEnabled(true);
|
||||
successMessage = "Firmware validation enabled";
|
||||
} else {
|
||||
policy.setFirmwareValidationEnabled(false);
|
||||
policy.setIgnoreImaEnabled(false);
|
||||
policy.setIgnoretBootEnabled(false);
|
||||
policy.setIgnoreOsEvtEnabled(false);
|
||||
successMessage = "Firmware validation disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA firmware validation policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ignore IMA policy setting and
|
||||
* redirects back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-ima-ignore", method = RequestMethod.POST)
|
||||
public RedirectView updateIgnoreIma(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean ignoreImaOptionEnabled = ppModel.getIgnoreIma()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If Ignore IMA is enabled without firmware, disallow change
|
||||
if (ignoreImaOptionEnabled && !policy.isFirmwareValidationEnabled()) {
|
||||
handleUserError(model, messages,
|
||||
"Ignore IMA can not be "
|
||||
+ "enabled without Firmware Validation policy enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
// set the policy option and create success message
|
||||
if (ignoreImaOptionEnabled) {
|
||||
policy.setIgnoreImaEnabled(true);
|
||||
successMessage = "Ignore IMA enabled";
|
||||
} else {
|
||||
policy.setIgnoreImaEnabled(false);
|
||||
successMessage = "Ignore IMA disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA IMA ignore policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ignore TBoot policy setting and
|
||||
* redirects back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-tboot-ignore", method = RequestMethod.POST)
|
||||
public RedirectView updateIgnoreTboot(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean ignoreTbootOptionEnabled = ppModel.getIgnoretBoot()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If Ignore TBoot is enabled without firmware, disallow change
|
||||
if (ignoreTbootOptionEnabled && !policy.isFirmwareValidationEnabled()) {
|
||||
handleUserError(model, messages,
|
||||
"Ignore TBoot can not be "
|
||||
+ "enabled without Firmware Validation policy enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
// set the policy option and create success message
|
||||
if (ignoreTbootOptionEnabled) {
|
||||
policy.setIgnoretBootEnabled(true);
|
||||
successMessage = "Ignore TBoot enabled";
|
||||
} else {
|
||||
policy.setIgnoretBootEnabled(false);
|
||||
successMessage = "Ignore TBoot disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA TBoot ignore policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ignore GPT policy setting and
|
||||
* redirects back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-gpt-ignore", method = RequestMethod.POST)
|
||||
public RedirectView updateIgnoreGptEvents(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean ignoreGptOptionEnabled = ppModel.getIgnoreGpt()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If Ignore TBoot is enabled without firmware, disallow change
|
||||
if (ignoreGptOptionEnabled && !policy.isFirmwareValidationEnabled()) {
|
||||
handleUserError(model, messages,
|
||||
"Ignore GPT Events can not be "
|
||||
+ "enabled without Firmware Validation policy enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
// set the policy option and create success message
|
||||
if (ignoreGptOptionEnabled) {
|
||||
policy.setIgnoreGptEnabled(true);
|
||||
successMessage = "Ignore GPT enabled";
|
||||
} else {
|
||||
policy.setIgnoreGptEnabled(false);
|
||||
successMessage = "Ignore GPT disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA GPT ignore policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ignore Os Events policy setting and
|
||||
* redirects back to the original page.
|
||||
*
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-os-evt-ignore", method = RequestMethod.POST)
|
||||
public RedirectView updateIgnoreOsEvents(
|
||||
@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
boolean ignoreOsEvtOptionEnabled = ppModel.getIgnoreOsEvt()
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If Ignore TBoot is enabled without firmware, disallow change
|
||||
if (ignoreOsEvtOptionEnabled && !policy.isFirmwareValidationEnabled()) {
|
||||
handleUserError(model, messages,
|
||||
"Ignore Os Events can not be "
|
||||
+ "enabled without Firmware Validation policy enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
// set the policy option and create success message
|
||||
if (ignoreOsEvtOptionEnabled) {
|
||||
policy.setIgnoreOsEvtEnabled(true);
|
||||
policy.setIgnoreGptEnabled(true);
|
||||
successMessage = "Ignore OS Events enabled";
|
||||
} else {
|
||||
policy.setIgnoreOsEvtEnabled(false);
|
||||
successMessage = "Ignore OS Events disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA OS Events ignore policy",
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
private void handlePolicyManagerUpdateError(final Map<String, Object> model,
|
||||
final PageMessages messages,
|
||||
final PolicyManagerException pmEx,
|
||||
final String message, final String error) {
|
||||
LOGGER.error(message, pmEx);
|
||||
messages.addError(error);
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
}
|
||||
|
||||
private void handleUserError(final Map<String, Object> model,
|
||||
final PageMessages messages,
|
||||
final String errorMessage) {
|
||||
messages.addError(errorMessage);
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in policy setting states and determines if policy configuration is
|
||||
* valid or not. PC Attribute Validation must have PC Validation Enabled PC
|
||||
* Validation must have EC Validation enabled
|
||||
*
|
||||
* @param isEcEnable EC Validation Policy State
|
||||
* @param isPcEnable PC Validation Policy State
|
||||
* @param isPcAttEnable PC Attribute Validation Policy State
|
||||
* @return True if policy combination is valid
|
||||
*/
|
||||
private static boolean isPolicyValid(final boolean isEcEnable, final boolean isPcEnable,
|
||||
final boolean isPcAttEnable) {
|
||||
if (isPcAttEnable && !isPcEnable) {
|
||||
return false;
|
||||
} else {
|
||||
return !isPcEnable || isEcEnable;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get a fresh load of the default policy from the DB.
|
||||
*
|
||||
* @return The default Supply Chain Policy
|
||||
*/
|
||||
private SupplyChainSettings getDefaultPolicy() {
|
||||
SupplyChainSettings defaultSettings = this.settingsService.getByName("Default");
|
||||
|
||||
if (defaultSettings == null) {
|
||||
defaultSettings = new SupplyChainSettings("Default", "Settings are configured for no validation flags set.");
|
||||
}
|
||||
return defaultSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default policy and applies the current values in to the page
|
||||
* model.
|
||||
*
|
||||
* @param ppModel the page model
|
||||
* @param model the map of string messages to be displayed on the view
|
||||
* @return The default Supply Chain Policy
|
||||
*/
|
||||
private SupplyChainSettings getDefaultPolicyAndSetInModel(
|
||||
final PolicyPageModel ppModel, final Map<String, Object> model) {
|
||||
// load the current default policy from the DB
|
||||
SupplyChainSettings policy = getDefaultPolicy();
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
model.put(RESULT_DATA, ppModel);
|
||||
return policy;
|
||||
}
|
||||
|
||||
private void savePolicyAndApplySuccessMessage(
|
||||
final PolicyPageModel ppModel, final Map<String, Object> model,
|
||||
final PageMessages messages, final String successMessage,
|
||||
final SupplyChainSettings settings) {
|
||||
// save the policy to the DB
|
||||
settingsService.updateSettings(settings);
|
||||
|
||||
// Log and set the success message
|
||||
messages.addSuccess(successMessage);
|
||||
LOGGER.debug("ACA Policy set to: " + ppModel.toString());
|
||||
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
package hirs.attestationca.portal.portal.page.params;
|
||||
|
||||
import hirs.attestationca.portal.page.PageParams;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* Minimal implementation of PageParams for pages that do not have url parameters.
|
||||
*/
|
||||
public class NoPageParams implements PageParams {
|
||||
|
||||
/**
|
||||
* Returns empty map so when iteration is required, nothing happens.
|
||||
*
|
||||
* @return empty map.
|
||||
*/
|
||||
@Override
|
||||
public LinkedHashMap<String, ?> asMap() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
package hirs.attestationca.portal.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* This class exposes methods to get the banner properties file. Properties are read from
|
||||
* /etc/hirs/banner.properties if it exists. If no value for a property exists in the file,
|
||||
* no change will be applied for that property.
|
||||
*/
|
||||
public class BannerConfiguration {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(BannerConfiguration.class);
|
||||
|
||||
private static final Path BANNER_PROPERTIES_PATH = FileSystems.getDefault()
|
||||
.getPath("/opt/tomcat/webapps/HIRS_AttestationCAPortal", "WEB-INF", "classes", "banner.properties");
|
||||
|
||||
private static final String BANNER_COLOR = "banner.color";
|
||||
private static final String BANNER_STRING = "banner.string";
|
||||
private static final String BANNER_DYNAMIC = "banner.dynamic";
|
||||
private static final String LEFT_CONTENT = "left.content";
|
||||
private static final String RIGHT_CONTENT = "right.content";
|
||||
|
||||
private String bannerColor = "";
|
||||
private String bannerString = "";
|
||||
private String bannerDynamic = "";
|
||||
|
||||
private final ArrayList<String> leftContent = new ArrayList<>();
|
||||
private final ArrayList<String> rightContent = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Banner Configuration default constructor.
|
||||
* Verify if the file exist, if it does it will get all the
|
||||
* properties values and save them on the class.
|
||||
*
|
||||
* @throws java.io.IOException the banner level for the web site.
|
||||
*/
|
||||
public BannerConfiguration() throws IOException {
|
||||
if (!Files.exists(BANNER_PROPERTIES_PATH)) {
|
||||
LOGGER.info(String.format(
|
||||
"No file found at %s. Banner will not display.",
|
||||
BANNER_PROPERTIES_PATH.toString()
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
try (InputStream loggingIs = new FileInputStream(BANNER_PROPERTIES_PATH.toFile())) {
|
||||
Properties bannerProps = new Properties();
|
||||
bannerProps.load(loggingIs);
|
||||
setBannerProperties(bannerProps);
|
||||
} catch (IOException e) {
|
||||
throw new IOException("Could not apply banner configuration", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method applies any dynamically configuration found in the properties file,
|
||||
* if it exists.
|
||||
* @param bannerProps
|
||||
* @return the banner level for the web site.
|
||||
*/
|
||||
private void setBannerProperties(final Properties bannerProps) {
|
||||
|
||||
bannerColor = bannerProps.getProperty(BANNER_COLOR, "").toLowerCase();
|
||||
bannerString = bannerProps.getProperty(BANNER_STRING, "").toUpperCase();
|
||||
bannerDynamic = bannerProps.getProperty(BANNER_DYNAMIC, "").toUpperCase();
|
||||
|
||||
// We don't need these any more
|
||||
bannerProps.remove(BANNER_COLOR);
|
||||
bannerProps.remove(BANNER_STRING);
|
||||
bannerProps.remove(BANNER_DYNAMIC);
|
||||
|
||||
//Get property list and sort it
|
||||
ArrayList<String> propertyList = new ArrayList<>(bannerProps.stringPropertyNames());
|
||||
Collections.sort(propertyList);
|
||||
|
||||
// Set banner information from the property file
|
||||
for (String prop : propertyList) {
|
||||
if (prop.startsWith(LEFT_CONTENT)) {
|
||||
leftContent.add(bannerProps.getProperty(prop));
|
||||
} else if (prop.startsWith(RIGHT_CONTENT)) {
|
||||
rightContent.add(bannerProps.getProperty(prop));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the banner was set.
|
||||
*
|
||||
* @return if the banner was set.
|
||||
*/
|
||||
public Boolean getHasBanner() {
|
||||
if (!bannerColor.isEmpty() || !bannerString.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the banner color.
|
||||
*
|
||||
* @return the banner color.
|
||||
*/
|
||||
public String getBannerColor() {
|
||||
return bannerColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the banner string.
|
||||
*
|
||||
* @return the page's banner string.
|
||||
*/
|
||||
public String getBannerString() {
|
||||
return bannerString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the banner dynamic string.
|
||||
*
|
||||
* @return if the page is banner dynamic
|
||||
*/
|
||||
public String getBannerDynamic() {
|
||||
return bannerDynamic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the left content.
|
||||
*
|
||||
* @return the left content
|
||||
*/
|
||||
public List<String> getLeftContent() {
|
||||
return Collections.unmodifiableList(leftContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the right content.
|
||||
*
|
||||
* @return the right content
|
||||
*/
|
||||
public List<String> getRightContent() {
|
||||
return Collections.unmodifiableList(rightContent);
|
||||
}
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
package hirs.attestationca.portal.utils;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
|
||||
/**
|
||||
* Utilities class specific for additional Bouncy Castle functionality.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class BouncyCastleUtils {
|
||||
|
||||
private static final String SEPARATOR_COMMA = ",";
|
||||
private static final String SEPARATOR_PLUS = "+";
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(BouncyCastleUtils.class);
|
||||
|
||||
/**
|
||||
* This method can be used to compare the distinguished names given from
|
||||
* certificates. This compare uses X500Name class in bouncy castle, which
|
||||
* compares the RDNs and not the string itself. The method will check for
|
||||
* '+' and replace them, X500Name doesn't do this.
|
||||
*
|
||||
* @param nameValue1 first general name to be used
|
||||
* @param nameValue2 second general name to be used
|
||||
* @return true if the values match based on the RDNs, false if not
|
||||
*/
|
||||
public static boolean x500NameCompare(final String nameValue1, final String nameValue2) {
|
||||
if (nameValue1 == null || nameValue2 == null) {
|
||||
throw new IllegalArgumentException("Provided DN string is null.");
|
||||
}
|
||||
|
||||
boolean result = false;
|
||||
X500Name x500Name1;
|
||||
X500Name x500Name2;
|
||||
|
||||
try {
|
||||
x500Name1 = new X500Name(nameValue1.replace(SEPARATOR_PLUS, SEPARATOR_COMMA));
|
||||
x500Name2 = new X500Name(nameValue2.replace(SEPARATOR_PLUS, SEPARATOR_COMMA));
|
||||
result = x500Name1.equals(x500Name2);
|
||||
} catch (IllegalArgumentException iaEx) {
|
||||
LOGGER.error(iaEx.toString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
package hirs.attestationca.portal.utils;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Utilities for working with hex strings and byte arrays.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class HexUtils {
|
||||
|
||||
/**
|
||||
* The mathematical base for the hexadecimal representation.
|
||||
*/
|
||||
public static final int HEX_BASIS = 16;
|
||||
|
||||
/**
|
||||
* An integer representation of the byte 0xff or 255.
|
||||
*/
|
||||
public static final int FF_BYTE = 0xff;
|
||||
|
||||
/**
|
||||
* Converts a binary hex string to a byte array.
|
||||
* @param s string to convert
|
||||
* @return byte array representation of s
|
||||
*/
|
||||
public static byte[] hexStringToByteArray(final String s) {
|
||||
int sizeInt = s.length() / 2;
|
||||
byte[] returnArray = new byte[sizeInt];
|
||||
String byteVal;
|
||||
for (int i = 0; i < sizeInt; i++) {
|
||||
int index = 2 * i;
|
||||
byteVal = s.substring(index, index + 2);
|
||||
returnArray[i] = (byte) (Integer.parseInt(byteVal, HEX_BASIS));
|
||||
}
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a byte array to a hex represented binary string.
|
||||
* @param b byte array to convert
|
||||
* @return hex string representation of array
|
||||
*/
|
||||
public static String byteArrayToHexString(final byte[] b) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String returnStr = "";
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
String singleByte = Integer.toHexString(b[i] & FF_BYTE);
|
||||
if (singleByte.length() != 2) {
|
||||
singleByte = "0" + singleByte;
|
||||
}
|
||||
returnStr = sb.append(singleByte).toString();
|
||||
}
|
||||
return returnStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an individual hex string to an integer.
|
||||
* @param s an individual hex string
|
||||
* @return an integer representation of a hex string
|
||||
*/
|
||||
public static Integer hexToInt(final String s) {
|
||||
Integer i = Integer.parseInt(s, HEX_BASIS);
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a byte array returns a subset of the array.
|
||||
* @param b the array to take a subset of
|
||||
* @param start the first index to copy
|
||||
* @param end the last index to copy (inclusive)
|
||||
* @return a new array of bytes from start to end
|
||||
*/
|
||||
public static byte[] subarray(final byte[] b, final int start, final int end) {
|
||||
byte[] copy = new byte[end - start + 1];
|
||||
System.arraycopy(b, start, copy, 0, end - start + 1);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a byte array and reverses the order.
|
||||
* @param in byte array to reverse
|
||||
* @return reversed byte array
|
||||
*/
|
||||
public static byte[] leReverseByte(final byte[] in) {
|
||||
byte[] finished = new byte[in.length];
|
||||
for (int i = 0; i < finished.length; i++) {
|
||||
finished[i] = in[(in.length - 1) - i];
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a byte array and reverses the order then converts to an int.
|
||||
* @param in byte array to reverse
|
||||
* @return integer that represents the reversed byte array
|
||||
*/
|
||||
public static int leReverseInt(final byte[] in) {
|
||||
byte[] finished = leReverseByte(in);
|
||||
return new BigInteger(finished).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a byte array of 4 bytes and returns a long.
|
||||
* @param bytes byte array to convert
|
||||
* @return long representation of the bytes
|
||||
*/
|
||||
public static long bytesToLong(final byte[] bytes) {
|
||||
BigInteger lValue = new BigInteger(bytes);
|
||||
|
||||
return lValue.abs().longValue();
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
package hirs.attestationca.portal.utils;
|
||||
|
||||
import com.eclipsesource.json.Json;
|
||||
import com.eclipsesource.json.JsonObject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* A utility class for common JSON operations using the {@link com.eclipsesource}
|
||||
* library.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class JsonUtils {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtils.class);
|
||||
|
||||
/**
|
||||
* Getter for the JSON Object that is associated with the elementName value
|
||||
* mapped in the associated JSON file.
|
||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||
*
|
||||
* @param jsonPath the object holding the location of the file to parse.
|
||||
* @param elementName the specific object to pull from the file
|
||||
* @return a JSON object
|
||||
*/
|
||||
public static JsonObject getSpecificJsonObject(final Path jsonPath, final String elementName) {
|
||||
// find the file and load it
|
||||
return getSpecificJsonObject(jsonPath, elementName, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the JSON Object that is associated with the elementName value
|
||||
* mapped in the associated JSON file.
|
||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||
*
|
||||
* @param jsonPath the object holding the location of the file to parse.
|
||||
* @param elementName the specific object to pull from the file
|
||||
* @param charset the character set to use
|
||||
* @return a JSON object
|
||||
*/
|
||||
public static JsonObject getSpecificJsonObject(final Path jsonPath,
|
||||
final String elementName,
|
||||
final Charset charset) {
|
||||
// find the file and load it
|
||||
JsonObject jsonObject = getJsonObject(jsonPath, charset);
|
||||
|
||||
if (jsonObject != null && jsonObject.get(elementName) != null) {
|
||||
return jsonObject.get(elementName).asObject();
|
||||
}
|
||||
|
||||
return new JsonObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the JSON Object that is mapped in the associated JSON file.
|
||||
* Default {@link java.nio.charset.Charset} is UTF 8
|
||||
*
|
||||
* @param jsonPath the object holding the location of the file to parse.
|
||||
* @return a JSON object
|
||||
*/
|
||||
public static JsonObject getJsonObject(final Path jsonPath) {
|
||||
return getJsonObject(jsonPath, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the JSON Object that is mapped in the associated JSON file.
|
||||
*
|
||||
* @param jsonPath the object holding the location of the file to parse.
|
||||
* @param charset the character set to use
|
||||
* @return a JSON object
|
||||
*/
|
||||
public static JsonObject getJsonObject(final Path jsonPath, final Charset charset) {
|
||||
// find the file and load it
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
|
||||
if (Files.notExists(jsonPath)) {
|
||||
LOGGER.warn(String.format("No file found at %s.", jsonPath.toString()));
|
||||
} else {
|
||||
try {
|
||||
InputStream inputStream = new FileInputStream(jsonPath.toString());
|
||||
jsonObject = Json.parse(new InputStreamReader(inputStream,
|
||||
charset)).asObject();
|
||||
} catch (IOException ex) {
|
||||
// add log file thing here indication issue with JSON File
|
||||
jsonObject = new JsonObject();
|
||||
}
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
@ -1,225 +0,0 @@
|
||||
package hirs.attestationca.portal.utils;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainSettings;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* The class handles the flags that ignore certain PCRs for validation.
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class PCRQuoteValidator {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(PCRQuoteValidator.class);
|
||||
|
||||
/**
|
||||
* Minimum possible value for a PCR ID. This is 0.
|
||||
*/
|
||||
public static final int MIN_PCR_ID = 0;
|
||||
|
||||
/**
|
||||
* Maximum possible value for a PCR ID. This is 23.
|
||||
*/
|
||||
public static final int MAX_PCR_ID = 23;
|
||||
|
||||
private static final int NUM_TO_SKIP = 1;
|
||||
private static final int NUM_OF_TBOOT_PCR = 3;
|
||||
// PCR 5-16
|
||||
private static final int PXE_PCR_START = 5;
|
||||
private static final int PXE_PCR_END = 16;
|
||||
// PCR 10
|
||||
private static final int IMA_PCR = 10;
|
||||
// PCR 17-19
|
||||
private static final int TBOOT_PCR_START = 17;
|
||||
private static final int TBOOT_PCR_END = 19;
|
||||
// PCR 5
|
||||
private static final int GPT_PCR = 5;
|
||||
private static final int IMA_MASK = 0xfffbff;
|
||||
|
||||
// Event Log Event Types
|
||||
private static final String EVT_EFI_BOOT = "EV_EFI_BOOT_SERVICES_APPLICATION";
|
||||
private static final String EVT_EFI_VAR = "EV_EFI_VARIABLE_BOOT";
|
||||
private static final String EVT_EFI_GPT = "EV_EFI_GPT_EVENT";
|
||||
private static final String EVT_EFI_CFG = "EV_EFI_VARIABLE_DRIVER_CONFIG";
|
||||
|
||||
private String[] baselinePCRS = new String[MAX_PCR_ID + 1];
|
||||
@Getter
|
||||
@Setter
|
||||
private SupplyChainSettings settings;
|
||||
|
||||
/**
|
||||
* Constructor to parse PCR values.
|
||||
* @param pcrValues pcrValues RIM provided baseline PCRs
|
||||
* @param settings settings for the supply chain portal settings for provisioning
|
||||
*/
|
||||
public PCRQuoteValidator(final String[] pcrValues,
|
||||
final SupplyChainSettings settings) {
|
||||
if (pcrValues != null) {
|
||||
baselinePCRS = new String[MAX_PCR_ID + 1];
|
||||
for (int i = 0; i <= MAX_PCR_ID; i++) {
|
||||
baselinePCRS[i] = pcrValues[i];
|
||||
}
|
||||
}
|
||||
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the array of baseline PCRs.
|
||||
* @return instance of the PCRs.
|
||||
*/
|
||||
public String[] getBaselinePCRS() {
|
||||
return baselinePCRS.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the array of baseline PCRs.
|
||||
* @param baselinePCRS instance of the PCRs.
|
||||
*/
|
||||
public void setBaselinePCRS(final String[] baselinePCRS) {
|
||||
this.baselinePCRS = baselinePCRS.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the baseline pcr list and the quote pcr list. If the
|
||||
* ignore flags are set, 10 and 17-19 will be skipped for comparison.
|
||||
*
|
||||
* @param storedPCRS non-baseline pcr list
|
||||
* @return a StringBuilder that is empty if everything passes.
|
||||
*/
|
||||
public StringBuilder validatePCRS(final String[] storedPCRS) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String failureMsg = "PCR %d does not match%n";
|
||||
if (storedPCRS[0] == null || storedPCRS[0].isEmpty()) {
|
||||
sb.append("failureMsg");
|
||||
} else {
|
||||
for (int i = 0; i <= MAX_PCR_ID; i++) {
|
||||
if (settings.isIgnoreImaEnabled() && i == IMA_PCR) {
|
||||
LOGGER.info("PCR Policy IMA Ignore enabled.");
|
||||
i += NUM_TO_SKIP;
|
||||
}
|
||||
|
||||
if (settings.isIgnoretBootEnabled() && i == TBOOT_PCR_START) {
|
||||
LOGGER.info("PCR Policy TBoot Ignore enabled.");
|
||||
i += NUM_OF_TBOOT_PCR;
|
||||
}
|
||||
|
||||
if (settings.isIgnoreGptEnabled() && i == GPT_PCR) {
|
||||
LOGGER.info("PCR Policy GPT Ignore enabled.");
|
||||
i += NUM_TO_SKIP;
|
||||
}
|
||||
|
||||
if (!baselinePCRS[i].equals(storedPCRS[i])) {
|
||||
//error
|
||||
LOGGER.error(String.format("%s =/= %s", baselinePCRS[i], storedPCRS[i]));
|
||||
sb.append(String.format(failureMsg, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the expected FM events occurring. There are policy options that
|
||||
* will ignore certain PCRs, Event Types and Event Variables present.
|
||||
* @param tcgMeasurementLog Measurement log from the client
|
||||
* @param eventValueMap The events stored as baseline to compare
|
||||
* @return the events that didn't pass
|
||||
*/
|
||||
// public List<TpmPcrEvent> validateTpmEvents(final TCGEventLog tcgMeasurementLog,
|
||||
// final Map<String, ReferenceDigestValue> eventValueMap) {
|
||||
// List<TpmPcrEvent> tpmPcrEvents = new LinkedList<>();
|
||||
// for (TpmPcrEvent tpe : tcgMeasurementLog.getEventList()) {
|
||||
// if (enableIgnoreIma && tpe.getPcrIndex() == IMA_PCR) {
|
||||
// LOGGER.info(String.format("IMA Ignored -> %s", tpe));
|
||||
// } else if (enableIgnoretBoot && (tpe.getPcrIndex() >= TBOOT_PCR_START
|
||||
// && tpe.getPcrIndex() <= TBOOT_PCR_END)) {
|
||||
// LOGGER.info(String.format("TBOOT Ignored -> %s", tpe));
|
||||
// } else if (enableIgnoreOsEvt && (tpe.getPcrIndex() >= PXE_PCR_START
|
||||
// && tpe.getPcrIndex() <= PXE_PCR_END)) {
|
||||
// LOGGER.info(String.format("OS Evt Ignored -> %s", tpe));
|
||||
// } else {
|
||||
// if (enableIgnoreGpt && tpe.getEventTypeStr().contains(EVT_EFI_GPT)) {
|
||||
// LOGGER.info(String.format("GPT Ignored -> %s", tpe));
|
||||
// } else if (enableIgnoreOsEvt && (tpe.getEventTypeStr().contains(EVT_EFI_BOOT)
|
||||
// || tpe.getEventTypeStr().contains(EVT_EFI_VAR))) {
|
||||
// LOGGER.info(String.format("OS Evt Ignored -> %s", tpe));
|
||||
// } else if (enableIgnoreOsEvt && (tpe.getEventTypeStr().contains(EVT_EFI_CFG)
|
||||
// && tpe.getEventContentStr().contains("SecureBoot"))) {
|
||||
// LOGGER.info(String.format("OS Evt Config Ignored -> %s", tpe));
|
||||
// } else {
|
||||
// if (!eventValueMap.containsKey(tpe.getEventDigestStr())) {
|
||||
// tpmPcrEvents.add(tpe);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return tpmPcrEvents;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Compares hashes to validate the quote from the client.
|
||||
*
|
||||
* @param tpmQuote the provided quote
|
||||
* @param storedPCRS values from the RIM file
|
||||
* @return true if validated, false if not
|
||||
*/
|
||||
// public boolean validateQuote(final byte[] tpmQuote, final String[] storedPCRS) {
|
||||
// System.out.println("Validating quote from associated device.");
|
||||
// boolean validated = false;
|
||||
// short localityAtRelease = 0;
|
||||
// String quoteString = new String(tpmQuote, StandardCharsets.UTF_8);
|
||||
// int pcrMaskSelection = PcrSelection.ALL_PCRS_ON;
|
||||
//
|
||||
// if (enableIgnoreIma) {
|
||||
// pcrMaskSelection = IMA_MASK;
|
||||
// }
|
||||
//
|
||||
// ArrayList<TPMMeasurementRecord> measurements = new ArrayList<>();
|
||||
//
|
||||
// try {
|
||||
// for (int i = 0; i < storedPcrs.length; i++) {
|
||||
// if (i == IMA_PCR && enableIgnoreIma) {
|
||||
// LOGGER.info("Ignore IMA PCR policy is enabled.");
|
||||
// } else {
|
||||
// measurements.add(new TPMMeasurementRecord(i, storedPcrs[i]));
|
||||
// }
|
||||
// }
|
||||
// } catch (DecoderException deEx) {
|
||||
// //error
|
||||
// System.out.println(deEx);
|
||||
// }
|
||||
//
|
||||
// PcrSelection pcrSelection = new PcrSelection(pcrMaskSelection);
|
||||
// PcrComposite pcrComposite = new PcrComposite(pcrSelection);
|
||||
// PcrInfoShort pcrInfoShort = new PcrInfoShort(pcrSelection,
|
||||
// localityAtRelease,
|
||||
// tpmQuote, pcrComposite);
|
||||
//
|
||||
// try {
|
||||
// /**
|
||||
// * The calculated string is being used in the contains method
|
||||
// * because the TPM Quote's hash isn't just for PCR values,
|
||||
// * it contains the calculated digest of the PCRs, along with
|
||||
// * other information.
|
||||
// */
|
||||
// String calculatedString = Hex.encodeHexString(
|
||||
// pcrInfoShort.getCalculatedDigest());
|
||||
// validated = quoteString.contains(calculatedString);
|
||||
// if (!validated) {
|
||||
// // warn
|
||||
// System.out.println(calculatedString + " not found in " + quoteString);
|
||||
// }
|
||||
// } catch (NoSuchAlgorithmException naEx) {
|
||||
// // error
|
||||
// System.out.println(naEx);
|
||||
// }
|
||||
//
|
||||
// return validated;
|
||||
// }
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
package hirs.attestationca.portal.utils;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* A simple utility that exposes a fluent way to validate Strings. Can easily be generalized to
|
||||
* any type of data. See example usage in StringValidationTest.
|
||||
*/
|
||||
public final class StringValidator {
|
||||
private static final Logger DEFAULT_LOGGER = LogManager.getLogger();
|
||||
|
||||
@Getter
|
||||
private final String value;
|
||||
private final String fieldName;
|
||||
private final Logger logger;
|
||||
|
||||
/**
|
||||
* Begins a validation operation.
|
||||
*
|
||||
* @param value the value to check
|
||||
* @param fieldName the name of the field (to be used in error reporting)
|
||||
* @return a Validation object, upon which validation methods can be called
|
||||
*/
|
||||
public static StringValidator check(final String value, final String fieldName) {
|
||||
return new StringValidator(value, fieldName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins a validation operation.
|
||||
*
|
||||
* @param value the value to check
|
||||
* @param fieldName the name of the field (to be used in error reporting)
|
||||
* @param logger a logger to use in lieu of Validation's logger
|
||||
* @return a Validation object, upon which validation methods can be called
|
||||
*/
|
||||
public static StringValidator check(final String value, final String fieldName,
|
||||
final Logger logger) {
|
||||
return new StringValidator(value, fieldName, logger);
|
||||
}
|
||||
|
||||
private StringValidator(final String value, final String fieldName, final Logger logger) {
|
||||
this.value = value;
|
||||
this.fieldName = fieldName;
|
||||
if (logger == null) {
|
||||
this.logger = DEFAULT_LOGGER;
|
||||
} else {
|
||||
this.logger = logger;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given field is not null. Throws an IllegalArgumentException if the value
|
||||
* is indeed null.
|
||||
*
|
||||
* @return this Validation object for further validation
|
||||
*/
|
||||
public StringValidator notNull() {
|
||||
if (value == null) {
|
||||
String message = String.format("Field %s is null", fieldName);
|
||||
logger.error(message);
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given field is not blank (empty or null.) Throws an IllegalArgumentException
|
||||
* if the value is indeed blank.
|
||||
*
|
||||
* @return this Validation object for further validation
|
||||
*/
|
||||
public StringValidator notBlank() {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
String message = String.format("Field %s is blank (empty or null)", fieldName);
|
||||
logger.error(message);
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given field is not longer than the given value. Throws an
|
||||
* IllegalArgumentException if the value exceeds this length. A null value will pass
|
||||
* this validation.
|
||||
*
|
||||
* @param maxLength the maximum length of the String
|
||||
* @return this Validation object for further validation
|
||||
*/
|
||||
public StringValidator maxLength(final int maxLength) {
|
||||
if (value == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (value.length() > maxLength) {
|
||||
String message = String.format(
|
||||
"Field %s is too large (%d > %d) with value %s",
|
||||
fieldName, value.length(), maxLength, value
|
||||
);
|
||||
logger.error(message);
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
package hirs.attestationca.portal.utils;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.attestationca.utils.digest.DigestAlgorithm;
|
||||
import lombok.Getter;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import hirs.attestationca.utils.xjc.File;
|
||||
import javax.xml.namespace.QName;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This object is used to represent the content of a Swid Tags Directory
|
||||
* section.
|
||||
*/
|
||||
public class SwidResource {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(SwidResource.class);
|
||||
|
||||
@Getter
|
||||
private String name, size;
|
||||
@Getter
|
||||
private String rimFormat, rimType, rimUriGlobal, hashValue;
|
||||
// private TpmWhiteListBaseline tpmWhiteList;
|
||||
private DigestAlgorithm digest = DigestAlgorithm.SHA1;
|
||||
@Getter
|
||||
private boolean validFileSize = false;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public SwidResource() {
|
||||
name = null;
|
||||
size = null;
|
||||
rimFormat = null;
|
||||
rimType = null;
|
||||
rimUriGlobal = null;
|
||||
hashValue = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main constructor that processes a {@code hirs.utils.xjc.File}.
|
||||
*
|
||||
* @param file {@link File}
|
||||
* @param digest algorithm associated with pcr values
|
||||
*/
|
||||
public SwidResource(final File file, final DigestAlgorithm digest) {
|
||||
Preconditions.checkArgument(file != null,
|
||||
"Cannot construct a RIM Resource from a null File object");
|
||||
|
||||
this.name = file.getName();
|
||||
// at this time, there is a possibility to get an object with
|
||||
// no size even though it is required.
|
||||
if (file.getSize() != null) {
|
||||
this.size = file.getSize().toString();
|
||||
} else {
|
||||
this.size = BigInteger.ZERO.toString();
|
||||
}
|
||||
|
||||
for (Map.Entry<QName, String> entry
|
||||
: file.getOtherAttributes().entrySet()) {
|
||||
switch (entry.getKey().getLocalPart()) {
|
||||
case "supportRIMFormat":
|
||||
this.rimFormat = entry.getValue();
|
||||
break;
|
||||
case "supportRIMType":
|
||||
this.rimType = entry.getValue();
|
||||
break;
|
||||
case "supportRIMURIGlobal":
|
||||
this.rimUriGlobal = entry.getValue();
|
||||
break;
|
||||
case "hash":
|
||||
this.hashValue = entry.getValue();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
this.digest = digest;
|
||||
// tpmWhiteList = new TpmWhiteListBaseline(this.name);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package hirs.attestationca.portal.utils;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Resources;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Utility class to get the current version from the VERSION file.
|
||||
*/
|
||||
public final class VersionHelper {
|
||||
|
||||
private static final String VERSION_FILENAME = "VERSION";
|
||||
|
||||
private VersionHelper() {
|
||||
// intentionally blank, should never be instantiated
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current version of HIRS_Portal that is installed.
|
||||
*
|
||||
* @return A string representing the current version.
|
||||
*/
|
||||
public static String getVersion() {
|
||||
return getVersion(VERSION_FILENAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current version of HIRS_Portal that is installed.
|
||||
*
|
||||
* @param filename
|
||||
* that contains the version
|
||||
* @return A string representing the current version.
|
||||
*/
|
||||
public static String getVersion(final String filename) {
|
||||
String version;
|
||||
try {
|
||||
version = getFileContents(filename);
|
||||
} catch (Exception e) {
|
||||
version = "";
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the symbolic link to VERSION in the top level HIRS directory.
|
||||
* @param filename "VERSION"
|
||||
* @return the version number from the file
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
private static String getFileContents(final String filename) throws IOException {
|
||||
URL url = Resources.getResource(filename);
|
||||
return Resources.toString(url, Charsets.UTF_8).trim();
|
||||
}
|
||||
}
|
||||
|
@ -1,247 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.digest;
|
||||
|
||||
import jakarta.xml.bind.DatatypeConverter;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.util.ArrayUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* This abstract class represents a message digest. Extending classes include
|
||||
* {@link main.java.hirs.attestationca.utils.digest.Digest} and {@link main.java.hirs.attestationca.utils.digest.OptionalDigest}.
|
||||
* <p>
|
||||
* Two classes were made to facilitate persisting them with Hibernate in different ways.
|
||||
* To persist non-nullable entries in an embedded collection, use {@link main.java.hirs.attestationca.utils.digest.Digest} (see
|
||||
* {@link TPMBaseline} for reference.) To persist nullable entries, use {@link main.java.hirs.attestationca.utils.digest.OptionalDigest}
|
||||
* (see {@link ImaBlacklistRecord} for reference.)
|
||||
*/
|
||||
public abstract class AbstractDigest {
|
||||
private static final org.apache.logging.log4j.Logger LOGGER =
|
||||
LogManager.getLogger(AbstractDigest.class);
|
||||
/**
|
||||
* Length of MD2 digest.
|
||||
*/
|
||||
public static final int MD2_DIGEST_LENGTH = 16;
|
||||
/**
|
||||
* Length of MD5 digest.
|
||||
*/
|
||||
public static final int MD5_DIGEST_LENGTH = 16;
|
||||
/**
|
||||
* Length of SHA1 digest.
|
||||
*/
|
||||
public static final int SHA1_DIGEST_LENGTH = 20;
|
||||
/**
|
||||
* Length of SHA256 digest.
|
||||
*/
|
||||
public static final int SHA256_DIGEST_LENGTH = 32;
|
||||
/**
|
||||
* Length of SHA384 digest.
|
||||
*/
|
||||
public static final int SHA384_DIGEST_LENGTH = 48;
|
||||
/**
|
||||
* Length of SHA512 digest.
|
||||
*/
|
||||
public static final int SHA512_DIGEST_LENGTH = 64;
|
||||
|
||||
/**
|
||||
* Ensures the given algorithm type and digest byte array represent a valid digest.
|
||||
* This includes ensuring they are both not null or empty and ensuring that the length of the
|
||||
* digest matches the expected amount of data for the given algorithm.
|
||||
*
|
||||
* @param algorithm a digest algorithm
|
||||
* @param digest the digest computed by this algorithm
|
||||
* @throws IllegalArgumentException if the provided input does not represent a valid digest
|
||||
*/
|
||||
void validateInput(final DigestAlgorithm algorithm, final byte[] digest)
|
||||
throws IllegalArgumentException {
|
||||
if (algorithm == null) {
|
||||
throw new IllegalArgumentException("Algorithm must not be null");
|
||||
}
|
||||
|
||||
if (ArrayUtils.isEmpty(digest)) {
|
||||
throw new IllegalArgumentException("Digest must have at least one byte");
|
||||
}
|
||||
|
||||
if (digest.length != algorithm.getLengthInBytes()) {
|
||||
throw new IllegalDigestLength(algorithm, digest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will help class determine the algorithm associated with the
|
||||
* pcr values given.
|
||||
*
|
||||
* @param digest list of pcr values.
|
||||
* @return the associated algorithm.
|
||||
*/
|
||||
public static final DigestAlgorithm getDigestAlgorithm(final byte[] digest) {
|
||||
if (digest == null || ArrayUtils.isEmpty(digest)) {
|
||||
return DigestAlgorithm.UNSPECIFIED;
|
||||
}
|
||||
|
||||
switch (digest.length) {
|
||||
case MD2_DIGEST_LENGTH:
|
||||
return DigestAlgorithm.MD5;
|
||||
case SHA1_DIGEST_LENGTH:
|
||||
return DigestAlgorithm.SHA1;
|
||||
case SHA256_DIGEST_LENGTH:
|
||||
return DigestAlgorithm.SHA256;
|
||||
case SHA384_DIGEST_LENGTH:
|
||||
return DigestAlgorithm.SHA384;
|
||||
case SHA512_DIGEST_LENGTH:
|
||||
return DigestAlgorithm.SHA512;
|
||||
default:
|
||||
return DigestAlgorithm.UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will help class determine the algorithm associated with the
|
||||
* pcr values given.
|
||||
*
|
||||
* @param digest list of pcr values.
|
||||
* @return the associated algorithm.
|
||||
*/
|
||||
public static final DigestAlgorithm getDigestAlgorithm(final String digest) {
|
||||
try {
|
||||
return getDigestAlgorithm(Hex.decodeHex(digest.toCharArray()));
|
||||
} catch (Exception deEx) {
|
||||
LOGGER.error(deEx);
|
||||
}
|
||||
|
||||
return DigestAlgorithm.UNSPECIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the <code>DigestAlgorithm</code> that identifies which hash
|
||||
* function generated the digest.
|
||||
*
|
||||
* @return digest algorithm
|
||||
*/
|
||||
public abstract DigestAlgorithm getAlgorithm();
|
||||
|
||||
/**
|
||||
* Retrieves the digest.
|
||||
*
|
||||
* @return digest
|
||||
*/
|
||||
public abstract byte[] getDigest();
|
||||
|
||||
/**
|
||||
* Returns a hex <code>String</code> representing the binary digest.
|
||||
*
|
||||
* @return hex representation of digest
|
||||
*/
|
||||
public String getDigestString() {
|
||||
return Hex.encodeHexString(getDigest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this digest's hash with another digest's hash.
|
||||
* @param otherDigest a Digest to compare to.
|
||||
* @return the comparison result type.
|
||||
*/
|
||||
public DigestComparisonResultType compare(final Digest otherDigest) {
|
||||
if (null == otherDigest) {
|
||||
return DigestComparisonResultType.UNKNOWN;
|
||||
}
|
||||
|
||||
if (this.equals(otherDigest)) {
|
||||
return DigestComparisonResultType.MATCH;
|
||||
}
|
||||
|
||||
return DigestComparisonResultType.MISMATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a {@link hirs.attestationca.portal.utils.digest.DigestAlgorithm} from a String returned by {@link hirs.attestationca.portal.utils.digest.AbstractDigest#toString()}.
|
||||
*
|
||||
* @param digest the digest string as computed above
|
||||
* @return the DigestAlgorithm component of the String
|
||||
*/
|
||||
static DigestAlgorithm algorithmFromString(final String digest) {
|
||||
return DigestAlgorithm.findByString(matchString(digest).group(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a digest from a String returned by {@link hirs.attestationca.portal.utils.digest.AbstractDigest#toString()}.
|
||||
*
|
||||
* @param digest the digest string as computed above
|
||||
* @return the byte array representing the actual digest
|
||||
*/
|
||||
static byte[] digestFromString(final String digest) {
|
||||
return DatatypeConverter.parseHexBinary(matchString(digest).group(2));
|
||||
}
|
||||
|
||||
private static Matcher matchString(final String digest) {
|
||||
Pattern digestPattern = Pattern.compile("(.*) - 0x(.*)");
|
||||
Matcher matcher = digestPattern.matcher(digest);
|
||||
if (!matcher.matches()) {
|
||||
String message = String.format("String \"%s\" did not match pattern \"%s\"", digest,
|
||||
digestPattern.toString());
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
return matcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + getAlgorithm().hashCode();
|
||||
result = prime * result + Arrays.hashCode(getDigest());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj == null || !(obj instanceof AbstractDigest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AbstractDigest other = (AbstractDigest) obj;
|
||||
|
||||
if (getAlgorithm() != other.getAlgorithm()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Arrays.equals(getDigest(), other.getDigest())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the standard algorithm name and a hexadecimal representation of
|
||||
* the bytes.
|
||||
*
|
||||
* @return string representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
//NOTE: Any updates here should also be reflected in fromString()
|
||||
return String.format("%s - 0x%s", getAlgorithm().getStandardAlgorithmName(),
|
||||
Hex.encodeHexString(getDigest()));
|
||||
}
|
||||
|
||||
private static final class IllegalDigestLength extends
|
||||
IllegalArgumentException {
|
||||
|
||||
private static final long serialVersionUID = 8782184397041237374L;
|
||||
|
||||
private IllegalDigestLength(final DigestAlgorithm algorithm,
|
||||
final byte[] digest) {
|
||||
super(String.format(
|
||||
"digest length (%d) does not match that of algorithm (%s)",
|
||||
digest.length, algorithm.toString()));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.digest;
|
||||
|
||||
import jakarta.persistence.Access;
|
||||
import jakarta.persistence.AccessType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class represents a message digest. This stores the bytes of a message
|
||||
* digest as computed by a hash function.
|
||||
* <p>
|
||||
* This class differs from Java's provided <code>MessageDigest</code> class by the
|
||||
* fact that it does not compute a digest. This class simply stores the result
|
||||
* of a digest. This is useful for scenarios where the digest is already known.
|
||||
* This is the case for IMA reports that already have the digest computed. The
|
||||
* <code>MessageDigest</code> class does not provide a means to store that value.
|
||||
* The value must be computed.
|
||||
*/
|
||||
@Embeddable
|
||||
@Access(AccessType.FIELD)
|
||||
public final class Digest extends AbstractDigest {
|
||||
/**
|
||||
* A SHA1 digest whose content is all zeros.
|
||||
*/
|
||||
public static final Digest SHA1_ZERO = new Digest(
|
||||
DigestAlgorithm.SHA1,
|
||||
new byte[SHA1_DIGEST_LENGTH]
|
||||
);
|
||||
|
||||
private static final String SHA1_EMPTY_HEX =
|
||||
"da39a3ee5e6b4b0d3255bfef95601890afd80709";
|
||||
|
||||
/**
|
||||
* A SHA1 digest whose content is the hash of an empty buffer.
|
||||
*/
|
||||
public static final Digest SHA1_OF_NO_DATA;
|
||||
|
||||
static {
|
||||
try {
|
||||
SHA1_OF_NO_DATA = new Digest(
|
||||
DigestAlgorithm.SHA1,
|
||||
Hex.decodeHex(SHA1_EMPTY_HEX.toCharArray())
|
||||
);
|
||||
} catch (DecoderException e) {
|
||||
throw new RuntimeException("Could not decode hex value", e);
|
||||
}
|
||||
}
|
||||
|
||||
@XmlElement
|
||||
@Column(nullable = false, name = "digest", length = SHA512_DIGEST_LENGTH,
|
||||
columnDefinition = "varbinary(64)")
|
||||
private final byte[] digest;
|
||||
|
||||
@XmlElement
|
||||
@Column(nullable = false)
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
private final DigestAlgorithm algorithm;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Digest</code>.
|
||||
*
|
||||
* @param algorithm algorithm used to generate the digest
|
||||
* @param digest digest value
|
||||
* @throws IllegalArgumentException if digest length does not match that of the algorithm
|
||||
*/
|
||||
public Digest(final DigestAlgorithm algorithm, final byte[] digest)
|
||||
throws IllegalArgumentException {
|
||||
validateInput(algorithm, digest);
|
||||
this.algorithm = algorithm;
|
||||
this.digest = Arrays.copyOf(digest, digest.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>Digest</code> when an algorithm isn't specified.
|
||||
* @param digest byte array value
|
||||
*/
|
||||
public Digest(final byte[] digest) {
|
||||
this(AbstractDigest.getDigestAlgorithm(digest), digest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected Digest() {
|
||||
this.algorithm = null;
|
||||
this.digest = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the <code>DigestAlgorithm</code> that identifies which hash
|
||||
* function generated the digest.
|
||||
*
|
||||
* @return digest algorithm
|
||||
*/
|
||||
@Override
|
||||
public DigestAlgorithm getAlgorithm() {
|
||||
return this.algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the digest.
|
||||
*
|
||||
* @return digest
|
||||
*/
|
||||
@Override
|
||||
public byte[] getDigest() {
|
||||
return Arrays.copyOf(this.digest, this.digest.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Digest with the same attributes as this instance.
|
||||
*
|
||||
* @return a new equivalent Digest
|
||||
*/
|
||||
public OptionalDigest asOptionalDigest() {
|
||||
return new OptionalDigest(algorithm, digest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to reverse the toString method. Returns a Digest given a String
|
||||
* that was created using an AbstractDigest's toString method.
|
||||
*
|
||||
* @param digest String representation of an AbstractDigest
|
||||
* @return Digest object recreated from the String passed in
|
||||
*/
|
||||
public static Digest fromString(final String digest) {
|
||||
return new Digest(algorithmFromString(digest), digestFromString(digest));
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.digest;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Enum of digest algorithms. The enum values also provide a standardized
|
||||
* algorithm name. The standardized algorithm name is a String of the algorithm
|
||||
* name as defined by Java.
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DigestAlgorithm {
|
||||
/**
|
||||
* MD2 digest algorithm.
|
||||
*/
|
||||
MD2("MD2", AbstractDigest.MD2_DIGEST_LENGTH),
|
||||
/**
|
||||
* MD5 digest algorithm.
|
||||
*/
|
||||
MD5("MD5", AbstractDigest.MD5_DIGEST_LENGTH),
|
||||
/**
|
||||
* SHA-1 digest algorithm.
|
||||
*/
|
||||
SHA1("SHA-1", AbstractDigest.SHA1_DIGEST_LENGTH),
|
||||
/**
|
||||
* SHA-256 digest algorithm.
|
||||
*/
|
||||
SHA256("SHA-256", AbstractDigest.SHA256_DIGEST_LENGTH),
|
||||
/**
|
||||
* SHA-384 digest algorithm.
|
||||
*/
|
||||
SHA384("SHA-384", AbstractDigest.SHA384_DIGEST_LENGTH),
|
||||
/**
|
||||
* SHA-512 digest algorithm.
|
||||
*/
|
||||
SHA512("SHA-512", AbstractDigest.SHA512_DIGEST_LENGTH),
|
||||
/**
|
||||
* Condition used when an algorithm is not specified and
|
||||
* the size doesn't match known digests.
|
||||
*/
|
||||
UNSPECIFIED("NOT SPECIFIED", Integer.BYTES);
|
||||
|
||||
private final String standardAlgorithmName;
|
||||
private final int lengthInBytes;
|
||||
|
||||
/**
|
||||
* Returns a DigestAlgorithm object given a String. The String is expected to be one of the
|
||||
* options for standardAlgorithmName. Throws an IllegalArgumentException if no Enum exists with
|
||||
* that value.
|
||||
*
|
||||
* @param standardAlgorithmName
|
||||
* String value of the Enum
|
||||
* @return DigestAlgorithm object
|
||||
*/
|
||||
public static DigestAlgorithm findByString(final String standardAlgorithmName) {
|
||||
for (DigestAlgorithm algorithm: DigestAlgorithm.values()) {
|
||||
if (algorithm.getStandardAlgorithmName().equals(standardAlgorithmName)) {
|
||||
return algorithm;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("No constant with text \"%s\" found",
|
||||
standardAlgorithmName));
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.digest;
|
||||
|
||||
/**
|
||||
* Enumeration identifying the different outcomes of a comparison between
|
||||
* two {@link hirs.attestationca.portal.utils.digest.Digest} objects.
|
||||
*
|
||||
*/
|
||||
public enum DigestComparisonResultType {
|
||||
/**
|
||||
* When one of the Digests compared has a hash that is uninitialized, defaulted, or
|
||||
* is a byte array equal to zero.
|
||||
*/
|
||||
UNKNOWN,
|
||||
|
||||
/**
|
||||
* When the two digest hashes are equal, and are not zeroized / defaulted hash arrays.
|
||||
*/
|
||||
MATCH,
|
||||
|
||||
/**
|
||||
* When the two digest hashes are not equal, and are not zeroized / defaulted hash arrays.
|
||||
*/
|
||||
MISMATCH,
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.digest;
|
||||
|
||||
import jakarta.persistence.Access;
|
||||
import jakarta.persistence.AccessType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class is identical to {@link hirs.attestationca.portal.utils.digest.Digest} except its fields are nullable. However, in practice,
|
||||
* an instance of this class cannot have null values assigned to its fields. The fields are marked
|
||||
* as nullable to allow Hibernate to set a reference an embedded instance of this class to null
|
||||
* (as there is no way for Hibernate to distinguish between a null reference and completely
|
||||
* null fields on an embedded entity.) Otherwise, there is no operational difference between
|
||||
* this class and {@link hirs.attestationca.portal.utils.digest.Digest}.
|
||||
*/
|
||||
@Embeddable
|
||||
@Access(AccessType.FIELD)
|
||||
public final class OptionalDigest extends AbstractDigest {
|
||||
@XmlElement
|
||||
@Column(nullable = true, name = "digest", length = SHA512_DIGEST_LENGTH,
|
||||
columnDefinition = "varbinary(64)")
|
||||
private final byte[] digest;
|
||||
|
||||
@XmlElement
|
||||
@Column(nullable = true)
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
private final DigestAlgorithm algorithm;
|
||||
|
||||
/**
|
||||
* Creates a new <code>OptionalDigest</code>.
|
||||
*
|
||||
* @param algorithm algorithm used to generate the digest
|
||||
* @param digest digest value
|
||||
* @throws IllegalArgumentException if digest length does not match that of the algorithm
|
||||
*/
|
||||
public OptionalDigest(final DigestAlgorithm algorithm, final byte[] digest)
|
||||
throws IllegalArgumentException {
|
||||
validateInput(algorithm, digest);
|
||||
this.algorithm = algorithm;
|
||||
this.digest = Arrays.copyOf(digest, digest.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected OptionalDigest() {
|
||||
this.algorithm = null;
|
||||
this.digest = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>DigestAlgorithm</code> that identifies which hash
|
||||
* function generated the digest.
|
||||
*
|
||||
* @return digest algorithm
|
||||
*/
|
||||
@Override
|
||||
public DigestAlgorithm getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the digest.
|
||||
*
|
||||
* @return digest
|
||||
*/
|
||||
@Override
|
||||
public byte[] getDigest() {
|
||||
return Arrays.copyOf(this.digest, this.digest.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Digest with the same attributes as this instance.
|
||||
*
|
||||
* @return a new equivalent Digest
|
||||
*/
|
||||
public Digest asDigest() {
|
||||
return new Digest(algorithm, digest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to reverse the toString method. Returns an OptionalDigest given a String
|
||||
* that was created using an AbstractDigest's toString method.
|
||||
*
|
||||
* @param digest String representation of an AbstractDigest
|
||||
* @return OptionalDigest object recreated from the String passed in
|
||||
*/
|
||||
public static OptionalDigest fromString(final String digest) {
|
||||
return new OptionalDigest(algorithmFromString(digest), digestFromString(digest));
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.exception;
|
||||
|
||||
/**
|
||||
* This class represents an <code>Exception</code> generated by a
|
||||
* <code>PolicyManageer</code>.
|
||||
*/
|
||||
public class PolicyManagerException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 3081536085161873284L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>PolicyManagerException</code> that has the message
|
||||
* <code>msg</code>.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
*/
|
||||
public PolicyManagerException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>PolicyManagerException</code> that wraps the given
|
||||
* <code>Throwable</code>.
|
||||
*
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
public PolicyManagerException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>PolicyManagerException</code> that has the message
|
||||
* <code>msg</code> and wraps the root cause.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
public PolicyManagerException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.tpm;
|
||||
|
||||
/**
|
||||
* This class represents an <code>Exception</code> generated by
|
||||
* <code>CreateTPMBaseline</code>.
|
||||
*/
|
||||
public class TPMBaselineGeneratorException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 8850867303391694668L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreateTPMBaselineException</code> that has the
|
||||
* message <code>msg</code>.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
*/
|
||||
TPMBaselineGeneratorException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreateTPMBaselineException</code> that wraps the
|
||||
* given <code>Throwable</code>.
|
||||
*
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
TPMBaselineGeneratorException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreateTPMBaselineException</code> that has the
|
||||
* message <code>msg</code> and wraps the root cause.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
TPMBaselineGeneratorException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
}
|
@ -1,350 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.tpm.eventlog;
|
||||
|
||||
import hirs.attestationca.utils.HexUtils;
|
||||
import hirs.attestationca.utils.digest.AbstractDigest;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvConstants;
|
||||
import hirs.attestationca.utils.tpm.eventlog.uefi.UefiConstants;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* Class for handling different formats of TCG Event logs.
|
||||
*/
|
||||
public final class TCGEventLog {
|
||||
|
||||
/** Logger. */
|
||||
private static final Logger LOGGER = LogManager.getLogger(TCGEventLog.class);
|
||||
/** Name of the hash algorithm used to process the Event Log, default is SHA256. */
|
||||
@Getter
|
||||
private String algorithm = "TPM_ALG_SHA256";
|
||||
/** Parsed event log array. */
|
||||
private static final int SIG_OFFSET = 32;
|
||||
/** TEV_NO_ACTION signature size. */
|
||||
private static final int SIG_SIZE = 16;
|
||||
/** Initial value for SHA 256 values.*/
|
||||
public static final String INIT_SHA256_LIST = "00000000000000000000000000"
|
||||
+ "00000000000000000000000000000000000000";
|
||||
/** Initial value for SHA 256 values.*/
|
||||
public static final String LOCALITY4_SHA256_LIST = "ffffffffffffffffffffffffff"
|
||||
+ "ffffffffffffffffffffffffffffffffffffff";
|
||||
/** Initial value for SHA 1 values. */
|
||||
public static final String INIT_SHA1_LIST = "0000000000000000000000000000000000000000";
|
||||
/** Initial value for SHA 1 values. */
|
||||
public static final String LOCALITY4_SHA1_LIST = "ffffffffffffffffffffffffffffffffffffffff";
|
||||
/** PFP defined EV_NO_ACTION identifier. */
|
||||
public static final int NO_ACTION_EVENT = 0x00000003;
|
||||
/** String value of SHA1 hash.*/
|
||||
public static final String HASH_STRING = "SHA1";
|
||||
/** String value of SHA256 hash. */
|
||||
public static final String HASH256_STRING = "SHA-256";
|
||||
/** Each PCR bank holds 24 registers. */
|
||||
public static final int PCR_COUNT = 24;
|
||||
/** Locality 4 starts at PCR 17. */
|
||||
public static final int PCR_LOCALITY4_MIN = 17;
|
||||
/** Locality 4 Ends at PCR 23. */
|
||||
public static final int PCR_LOCALITY4_MAX = 23;
|
||||
/** 2 dimensional array holding the PCR values. */
|
||||
private byte[][] pcrList;
|
||||
/** List of parsed events within the log. */
|
||||
private LinkedHashMap<Integer, TpmPcrEvent> eventList = new LinkedHashMap<>();
|
||||
/** Length of PCR. Indicates which hash algorithm is used. */
|
||||
private int pcrLength;
|
||||
/** Name of hash algorithm. */
|
||||
private String hashType;
|
||||
/** Initial PCR Value to use. */
|
||||
private String initValue;
|
||||
/** Initial PcR Value to use for locality 4. */
|
||||
private String initLocalityFourValue;
|
||||
/** Content Output Flag use. */
|
||||
private boolean bContent = false;
|
||||
/** Event Output Flag use. */
|
||||
private boolean bHexEvent = false;
|
||||
/** Event Output Flag use. */
|
||||
private boolean bEvent = false;
|
||||
/** Event Output Flag use. */
|
||||
@Getter
|
||||
private boolean bCryptoAgile = false;
|
||||
|
||||
/**
|
||||
* Default blank object constructor.
|
||||
*/
|
||||
public TCGEventLog() {
|
||||
this.pcrList = new byte[PCR_COUNT][EvConstants.SHA1_LENGTH];
|
||||
initValue = INIT_SHA1_LIST;
|
||||
initLocalityFourValue = LOCALITY4_SHA1_LIST;
|
||||
pcrLength = EvConstants.SHA1_LENGTH;
|
||||
hashType = HASH_STRING;
|
||||
algorithm = "TPM_ALG_SHA1";
|
||||
initPcrList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple constructor for Event Log.
|
||||
* @param rawlog data for the event log file.
|
||||
* @throws java.security.NoSuchAlgorithmException if an unknown algorithm is encountered.
|
||||
* @throws java.security.cert.CertificateException if a certificate in the log cannot be parsed.
|
||||
* @throws java.io.IOException IO Stream if event cannot be parsed.
|
||||
*/
|
||||
public TCGEventLog(final byte[] rawlog)
|
||||
throws CertificateException, NoSuchAlgorithmException, IOException {
|
||||
this(rawlog, false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor for just the rawlog that'll set up SHA1 Log.
|
||||
* @param rawlog data for the event log file.
|
||||
* @param bEventFlag if true provides human readable event descriptions.
|
||||
* @param bContentFlag if true provides hex output for Content in the description.
|
||||
* @param bHexEventFlag if true provides hex event structure in the description.
|
||||
* @throws java.security.NoSuchAlgorithmException if an unknown algorithm is encountered.
|
||||
* @throws java.security.cert.CertificateException if a certificate in the log cannot be parsed.
|
||||
* @throws java.io.IOException IO Stream if event cannot be parsed.
|
||||
*/
|
||||
public TCGEventLog(final byte[] rawlog, final boolean bEventFlag,
|
||||
final boolean bContentFlag, final boolean bHexEventFlag)
|
||||
throws CertificateException, NoSuchAlgorithmException, IOException {
|
||||
|
||||
bCryptoAgile = isLogCrytoAgile(rawlog);
|
||||
if (bCryptoAgile) {
|
||||
initValue = INIT_SHA256_LIST;
|
||||
initLocalityFourValue = LOCALITY4_SHA256_LIST;
|
||||
algorithm = "TPM_ALG_SHA256";
|
||||
hashType = HASH256_STRING;
|
||||
pcrLength = EvConstants.SHA256_LENGTH;
|
||||
} else {
|
||||
initValue = INIT_SHA1_LIST;
|
||||
initLocalityFourValue = LOCALITY4_SHA1_LIST;
|
||||
hashType = HASH_STRING;
|
||||
algorithm = "TPM_ALG_SHA1";
|
||||
pcrLength = EvConstants.SHA1_LENGTH;
|
||||
}
|
||||
this.pcrList = new byte[PCR_COUNT][pcrLength];
|
||||
int eventNumber = 0;
|
||||
bContent = bContentFlag;
|
||||
bEvent = bEventFlag;
|
||||
bHexEvent = bHexEventFlag;
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(rawlog);
|
||||
// Process the 1st entry as a SHA1 format (per the spec)
|
||||
eventList.put(eventNumber, new TpmPcrEvent1(is, eventNumber++));
|
||||
// put all events into an event list for further processing
|
||||
|
||||
while (is.available() > 0) {
|
||||
if (bCryptoAgile) {
|
||||
eventList.put(eventNumber, new TpmPcrEvent2(is, eventNumber++));
|
||||
} else {
|
||||
eventList.put(eventNumber, new TpmPcrEvent1(is, eventNumber++));
|
||||
}
|
||||
}
|
||||
calculatePcrValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method puts blank values in the pcrList.
|
||||
*/
|
||||
private void initPcrList() {
|
||||
try {
|
||||
for (int i = 0; i < PCR_COUNT; i++) {
|
||||
System.arraycopy(Hex.decodeHex(initValue.toCharArray()),
|
||||
0, pcrList[i], 0, pcrLength);
|
||||
}
|
||||
for (int i = PCR_LOCALITY4_MIN; i < PCR_LOCALITY4_MAX; i++) {
|
||||
System.arraycopy(Hex.decodeHex(initLocalityFourValue.toCharArray()),
|
||||
0, pcrList[i], 0, pcrLength);
|
||||
}
|
||||
} catch (DecoderException deEx) {
|
||||
LOGGER.error(deEx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TPM baseline using the expected PCR Values.
|
||||
* Expected PCR Values were Calculated from the EventLog (RIM Support file).
|
||||
*
|
||||
* @param name name to call the TPM Baseline
|
||||
* @return whitelist baseline
|
||||
*/
|
||||
// public TpmWhiteListBaseline createTPMBaseline(final String name) {
|
||||
// TpmWhiteListBaseline baseline = new TpmWhiteListBaseline(name);
|
||||
// TPMMeasurementRecord record;
|
||||
// String pcrValue;
|
||||
// for (int i = 0; i < PCR_COUNT; i++) {
|
||||
// if (algorithm.compareToIgnoreCase("TPM_ALG_SHA1") == 0) { // Log Was SHA1 Format
|
||||
// pcrValue = getExpectedPCRValue(i);
|
||||
// byte[] hexValue = HexUtils.hexStringToByteArray(pcrValue);
|
||||
// final Digest hash = new Digest(DigestAlgorithm.SHA1, hexValue);
|
||||
// record = new TPMMeasurementRecord(i, hash);
|
||||
// } else { // Log was Crypto Agile, currently assumes SHA256
|
||||
// pcrValue = getExpectedPCRValue(i);
|
||||
// byte[] hexValue = HexUtils.hexStringToByteArray(pcrValue);
|
||||
// final Digest hash = new Digest(DigestAlgorithm.SHA256, hexValue);
|
||||
// record = new TPMMeasurementRecord(i, hash);
|
||||
// }
|
||||
// baseline.addToBaseline(record);
|
||||
// }
|
||||
// return baseline;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Calculates the "Expected Values for TPM PCRs based upon Event digests in the Event Log.
|
||||
* Uses the algorithm and eventList passed into the constructor,
|
||||
*/
|
||||
private void calculatePcrValues() {
|
||||
byte[] extendedPCR;
|
||||
initPcrList();
|
||||
for (TpmPcrEvent currentEvent : eventList.values()) {
|
||||
if (currentEvent.getPcrIndex() >= 0) { // Ignore NO_EVENTS which can have a PCR=-1
|
||||
try {
|
||||
if (currentEvent.getEventType() != NO_ACTION_EVENT) {
|
||||
// Don't include EV_NO_ACTION event
|
||||
extendedPCR = extendPCR(pcrList[currentEvent.getPcrIndex()],
|
||||
currentEvent.getEventDigest());
|
||||
System.arraycopy(extendedPCR, 0, pcrList[currentEvent.getPcrIndex()],
|
||||
0, currentEvent.getDigestLength());
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends a hash with a hash of new data.
|
||||
*
|
||||
* @param currentValue value to extend
|
||||
* @param newEvent value to extend with
|
||||
* @return new hash resultant hash
|
||||
* @throws java.security.NoSuchAlgorithmException if hash algorithm not supported
|
||||
*/
|
||||
private byte[] extendPCR(final byte[] currentValue, final byte[] newEvent)
|
||||
throws NoSuchAlgorithmException {
|
||||
MessageDigest md = MessageDigest.getInstance(hashType);
|
||||
StringBuilder sb = new StringBuilder(AbstractDigest.SHA512_DIGEST_LENGTH);
|
||||
sb.append(Hex.encodeHexString(currentValue).toCharArray());
|
||||
sb.append(Hex.encodeHexString(newEvent).toCharArray());
|
||||
|
||||
try {
|
||||
md.update(Hex.decodeHex(sb.toString().toCharArray()));
|
||||
} catch (DecoderException deEx) {
|
||||
LOGGER.error(deEx);
|
||||
}
|
||||
return md.digest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all 24 PCR values for display purposes.
|
||||
*
|
||||
* @return Returns an array of strings representing the expected hash values for all 24 PCRs
|
||||
*/
|
||||
public String[] getExpectedPCRValues() {
|
||||
String[] pcrs = new String[PCR_COUNT];
|
||||
for (int i = 0; i < PCR_COUNT; i++) {
|
||||
pcrs[i] = Hex.encodeHexString(pcrList[i]);
|
||||
}
|
||||
return pcrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of event found in the Event Log.
|
||||
* @return an arraylist of event.
|
||||
*/
|
||||
public Collection<TpmPcrEvent> getEventList() {
|
||||
return eventList.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specific element of the Event Log that corresponds to the requested
|
||||
* event number.
|
||||
* @param eventNumber specific event to find in the list.
|
||||
* @return TPM Event in the position of the list
|
||||
*/
|
||||
public TpmPcrEvent getEventByNumber(final int eventNumber) {
|
||||
return eventList.get(eventNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single PCR value given an index (PCR Number).
|
||||
*
|
||||
* @param index pcr index
|
||||
* @return String representing the PCR contents
|
||||
*/
|
||||
public String getExpectedPCRValue(final int index) {
|
||||
return HexUtils.byteArrayToHexString(pcrList[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Human readable string representing the contents of the Event Log.
|
||||
* @return Description of the log.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (TpmPcrEvent event : eventList.values()) {
|
||||
sb.append(event.toString(bEvent, bHexEvent, bContent));
|
||||
}
|
||||
sb.append("Event Log processing completed.\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Human readable string representing the contents of the Event Log.
|
||||
* @param bEvent flag to set
|
||||
* @param bHexEvent flag to set
|
||||
* @param bContent flag to set
|
||||
* @return Description of the log.
|
||||
*/
|
||||
public String toString(final boolean bEvent,
|
||||
final boolean bHexEvent,
|
||||
final boolean bContent) {
|
||||
this.bEvent = bEvent;
|
||||
this.bHexEvent = bHexEvent;
|
||||
this.bContent = bContent;
|
||||
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TCG Algorithm Registry defined ID for the Digest Algorithm
|
||||
* used in the event log.
|
||||
* @return TCG Defined Algorithm name
|
||||
*/
|
||||
public int getEventLogHashAlgorithmID() {
|
||||
return TcgTpmtHa.tcgAlgStringToId(algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an event is an EfiSpecIdEvent indicating that the log format is crypto agile.
|
||||
* The EfiSpecIdEvent should be the first event in the TCG TPM Event Log.
|
||||
*
|
||||
* @param log The Event Log
|
||||
* @return true if EfiSpecIDEvent is found and indicates that the format is crypto agile
|
||||
*/
|
||||
private boolean isLogCrytoAgile(final byte[] log) {
|
||||
byte[] eType = new byte[UefiConstants.SIZE_4];
|
||||
System.arraycopy(log, UefiConstants.SIZE_4, eType, 0, UefiConstants.SIZE_4);
|
||||
byte[] eventType = HexUtils.leReverseByte(eType);
|
||||
int eventID = new BigInteger(eventType).intValue();
|
||||
if (eventID != TCGEventLog.NO_ACTION_EVENT) {
|
||||
return false;
|
||||
} // Event Type should be EV_NO_ACTION
|
||||
byte[] signature = new byte[SIG_SIZE];
|
||||
// should be "Spec ID Event03"
|
||||
System.arraycopy(log, SIG_OFFSET, signature, 0, SIG_SIZE);
|
||||
// remove null char
|
||||
String sig = new String(signature, StandardCharsets.UTF_8).substring(0, SIG_SIZE - 1);
|
||||
|
||||
return sig.equals("Spec ID Event03");
|
||||
}
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.tpm.eventlog;
|
||||
|
||||
import hirs.attestationca.utils.HexUtils;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Class to for the TCG defined TPMT_HA structure used to support the Crypto Agile Log format.
|
||||
* <p>
|
||||
* typedef struct {
|
||||
* TPMI_ALG_HASH hashAlg;
|
||||
* TPMU_HA digest;
|
||||
* } TPMT_HA;
|
||||
*/
|
||||
public class TcgTpmtHa {
|
||||
/**
|
||||
* TCG Defined Algorithm Identifiers.
|
||||
*/
|
||||
@Getter
|
||||
private int hashAlgId = 0;
|
||||
/**
|
||||
* Length of the hash.
|
||||
*/
|
||||
@Getter
|
||||
private int hashLength = 0;
|
||||
/**
|
||||
* Human readable name of the hash algorithm.
|
||||
*/
|
||||
@Getter
|
||||
private String hashName = "";
|
||||
/**
|
||||
* Hash data.
|
||||
*/
|
||||
@Getter(value = AccessLevel.PROTECTED)
|
||||
private byte[] digest = null;
|
||||
/**
|
||||
* TCG ID for SHA1.
|
||||
*/
|
||||
public static final int TPM_ALG_SHA1 = 0x04;
|
||||
/**
|
||||
* TCG ID for SHA1.
|
||||
*/
|
||||
public static final int TPM_ALG_SHA256 = 0x0B;
|
||||
/**
|
||||
* TCG ID for SHA 384.
|
||||
*/
|
||||
public static final int TPM_ALG_SHA384 = 0x0C;
|
||||
/**
|
||||
* TCG ID for SHA512.
|
||||
*/
|
||||
public static final int TPM_ALG_SHA_512 = 0x0D;
|
||||
/**
|
||||
* TCG ID for Null algorithm.
|
||||
*/
|
||||
public static final int TPM_ALG_NULL = 0x10;
|
||||
/**
|
||||
* TCG ID for SHA1.
|
||||
*/
|
||||
public static final int TPM_ALG_SHA1_LENGTH = 20;
|
||||
/**
|
||||
* TCG ID for SHA1.
|
||||
*/
|
||||
public static final int TPM_ALG_SHA256_LENGTH = 32;
|
||||
/**
|
||||
* TCG ID for SHA 384.
|
||||
*/
|
||||
public static final int TPM_ALG_SHA384_LENGTH = 48;
|
||||
/**
|
||||
* TCG ID for SHA512.
|
||||
*/
|
||||
public static final int TPM_ALG_SHA512_LENGTH = 64;
|
||||
/**
|
||||
* TCG ID for Null algorithm.
|
||||
*/
|
||||
public static final int TPM_ALG_NULL_LENGTH = 0;
|
||||
/**
|
||||
* buffer to hold the structure.
|
||||
*/
|
||||
private byte[] buffer = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param is ByteArrayInputStream holding the TcgTPMT_HA structured data
|
||||
* @throws java.io.IOException if TPMT_HA structure cannot be parsed
|
||||
*/
|
||||
public TcgTpmtHa(final ByteArrayInputStream is) throws IOException {
|
||||
byte[] algID = new byte[2];
|
||||
is.read(algID);
|
||||
byte[] rAlgID = HexUtils.leReverseByte(algID);
|
||||
hashAlgId = new BigInteger(rAlgID).intValue();
|
||||
hashName = tcgAlgIdToString(algID[0]);
|
||||
hashLength = tcgAlgLength(algID[0]);
|
||||
digest = new byte[hashLength];
|
||||
is.read(digest);
|
||||
buffer = new byte[algID.length + digest.length];
|
||||
System.arraycopy(algID, 0, buffer, 0, algID.length);
|
||||
System.arraycopy(digest, 0, buffer, algID.length, digest.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of the TPMT_HA structure buffer.
|
||||
*
|
||||
* @return contents of the TPMT_HA structure.
|
||||
*/
|
||||
public byte[] getBuffer() {
|
||||
return java.util.Arrays.copyOf(buffer, buffer.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Readable description of the Algorithm.
|
||||
*
|
||||
* @return Readable Algorithm name
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s hash = %s", hashName, HexUtils.byteArrayToHexString(digest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash name via a lookup.
|
||||
* Lookup based upon section 6.3 for the TPM-Rev-2.0-Part-2-Structures.pdf document.
|
||||
* Only hash algorithms found in Table 7 are used.
|
||||
*
|
||||
* @param algId int to convert to string
|
||||
* @return name of the algorithm
|
||||
*/
|
||||
public static String tcgAlgIdToString(final int algId) {
|
||||
String alg;
|
||||
switch (algId) {
|
||||
case TPM_ALG_SHA1:
|
||||
alg = "TPM_ALG_SHA1";
|
||||
break;
|
||||
case TPM_ALG_SHA256:
|
||||
alg = "TPM_ALG_SHA256";
|
||||
break;
|
||||
case TPM_ALG_SHA384:
|
||||
alg = "TPM_ALG_SHA384";
|
||||
break;
|
||||
case TPM_ALG_SHA_512:
|
||||
alg = "TPM_ALG_SHA512";
|
||||
break;
|
||||
case TPM_ALG_NULL:
|
||||
alg = "TPM_ALG_NULL";
|
||||
break;
|
||||
default:
|
||||
alg = "Unknown or invalid Hash";
|
||||
}
|
||||
return alg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TCG defined ID via a lookup o the TCG Defined Algorithm String.
|
||||
* Lookup based upon section 6.3 for the TPM-Rev-2.0-Part-2-Structures.pdf document.
|
||||
* Only hash algorithms found in Table 7 are used.
|
||||
*
|
||||
* @param algorithm String to convert to an id
|
||||
* @return id of hash algorithm
|
||||
*/
|
||||
public static int tcgAlgStringToId(final String algorithm) {
|
||||
int alg;
|
||||
switch (algorithm) {
|
||||
case "TPM_ALG_SHA1":
|
||||
alg = TPM_ALG_SHA1;
|
||||
break;
|
||||
case "TPM_ALG_SHA256":
|
||||
alg = TPM_ALG_SHA256;
|
||||
break;
|
||||
case "TPM_ALG_SHA384":
|
||||
alg = TPM_ALG_SHA384;
|
||||
break;
|
||||
case "TPM_ALG_SHA512":
|
||||
alg = TPM_ALG_SHA_512;
|
||||
break;
|
||||
case "TPM_ALG_NULL":
|
||||
default:
|
||||
alg = TPM_ALG_NULL;
|
||||
}
|
||||
return alg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the length of a given TPM ALG Identifier.
|
||||
* (lookup based upon section 6.3 for the TPM-Rev-2.0-Part-2-Structures.pdf document)
|
||||
* Only hash algorithms found in Table 7 are used.
|
||||
*
|
||||
* @param algId TCG defined Algorithm identifier
|
||||
* @return length of hash data in bytes
|
||||
*/
|
||||
public static int tcgAlgLength(final int algId) {
|
||||
int length;
|
||||
switch (algId) {
|
||||
case TPM_ALG_SHA1:
|
||||
length = TPM_ALG_SHA1_LENGTH;
|
||||
break;
|
||||
case TPM_ALG_SHA256:
|
||||
length = TPM_ALG_SHA256_LENGTH;
|
||||
break;
|
||||
case TPM_ALG_SHA384:
|
||||
length = TPM_ALG_SHA384_LENGTH;
|
||||
break;
|
||||
case TPM_ALG_SHA_512:
|
||||
length = TPM_ALG_SHA512_LENGTH;
|
||||
break;
|
||||
case TPM_ALG_NULL:
|
||||
default:
|
||||
length = TPM_ALG_NULL_LENGTH;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
@ -1,731 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.tpm.eventlog;
|
||||
|
||||
import hirs.attestationca.utils.HexUtils;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvCompactHash;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvConstants;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvEfiGptPartition;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvEfiHandoffTable;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvEfiSpecIdEvent;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvEventTag;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvIPL;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvNoAction;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvSCrtmContents;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvSCrtmVersion;
|
||||
import hirs.attestationca.utils.tpm.eventlog.uefi.UefiConstants;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvEfiBootServicesApp;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvPostCode;
|
||||
import hirs.attestationca.utils.tpm.eventlog.uefi.UefiFirmware;
|
||||
import hirs.attestationca.utils.tpm.eventlog.uefi.UefiVariable;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Class to process a TCG_PCR_EVENT.
|
||||
* TCG_PCR_EVENT is used when the Event log uses the SHA1 Format as described in the
|
||||
* TCG Platform Firmware Profile (PFP) specification.
|
||||
* typedef struct {
|
||||
* TCG_PCRINDEX PCRIndex; //PCR Index value that either
|
||||
* //matches the PCRIndex of a
|
||||
* //previous extend operation or
|
||||
* //indicates that this Event Log
|
||||
* //entry is not associated with
|
||||
* //an extend operation
|
||||
* TCG_EVENTTYPE EventType; //See Log event types defined in toStrng()
|
||||
* TCG_DIGEST digest; //The hash of the event data
|
||||
* UINT32 EventSize; //Size of the event data
|
||||
* UINT8 Event[EventSize]; //The event data
|
||||
* } TCG_PCR_EVENT;
|
||||
*/
|
||||
public class TpmPcrEvent {
|
||||
private static final Logger LOGGER = LogManager.getLogger(TpmPcrEvent.class);
|
||||
/**
|
||||
* Indent Offset.
|
||||
*/
|
||||
private static final int INDENT_3 = 3;
|
||||
/**
|
||||
* Log format. SHA1=1, Crytpo agile=2.
|
||||
* this can be refactored out
|
||||
*/
|
||||
@Getter @Setter(value = AccessLevel.PROTECTED)
|
||||
private int logFormat = -1;
|
||||
/**
|
||||
* PCR index.
|
||||
*/
|
||||
@Getter
|
||||
private int pcrIndex = -1;
|
||||
/**
|
||||
* Event Type (long).
|
||||
*/
|
||||
@Getter
|
||||
private long eventType = 0;
|
||||
/**
|
||||
* Event digest.
|
||||
*/
|
||||
private byte[] digest = null;
|
||||
/**
|
||||
* Event data (no content).
|
||||
*/
|
||||
private byte[] event;
|
||||
/**
|
||||
* Event content data.
|
||||
*/
|
||||
private byte[] eventContent;
|
||||
/**
|
||||
* TCG Event Log spec version.
|
||||
*/
|
||||
@Getter
|
||||
private String specVersion = "Unknown";
|
||||
/**
|
||||
* TCG Event Log errata version.
|
||||
*/
|
||||
@Getter
|
||||
private String specErrataVersion = "Unknown";
|
||||
/**
|
||||
* Description for toString support.
|
||||
*/
|
||||
private String description = "";
|
||||
/**
|
||||
* Length (in bytes) of a pcr.
|
||||
*/
|
||||
@Setter @Getter
|
||||
private int digestLength = 0;
|
||||
/**
|
||||
* Event hash for SHA1 event logs.
|
||||
*/
|
||||
private byte[] eventDataSha1hash;
|
||||
/**
|
||||
* Event hash for Crypto Agile events.
|
||||
*/
|
||||
private byte[] eventDataSha256hash;
|
||||
private EvPostCode evPostCode;
|
||||
@Setter @Getter
|
||||
private int eventNumber;
|
||||
@Setter @Getter
|
||||
private boolean error = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param is ByteArrayInputStream holding the event
|
||||
* @throws java.io.IOException when event can't be parsed
|
||||
*/
|
||||
public TpmPcrEvent(final ByteArrayInputStream is) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the digest from a TCG_PCR_EVENT digest field.
|
||||
* This can be SHA1 for older event structures or any algorithm for newer structure.
|
||||
*
|
||||
* @param digestData cryptographic hash
|
||||
* @param digestLength length of the cryptographic hash
|
||||
*/
|
||||
protected void setEventDigest(final byte[] digestData, final int digestLength) {
|
||||
digest = new byte[digestLength];
|
||||
System.arraycopy(digestData, 0, digest, 0, digestLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the digest from a TCG Event.
|
||||
* This can be SHA1 for older event structures or any algorithm for newer structure.
|
||||
*
|
||||
* @return the digest data for the event
|
||||
*/
|
||||
public byte[] getEventDigest() {
|
||||
byte[] digestCopy = new byte[digestLength];
|
||||
System.arraycopy(digest, 0, digestCopy, 0, this.digestLength);
|
||||
return digestCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hex representation of the event digest.
|
||||
* @return hex string
|
||||
*/
|
||||
public String getEventDigestStr() {
|
||||
return Hex.encodeHexString(this.digest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the event PCR index value from a TCG Event.
|
||||
*
|
||||
* @param eventIndex TCG Event PCR Index as defined in the PFP
|
||||
*/
|
||||
protected void setPcrIndex(final byte[] eventIndex) {
|
||||
pcrIndex = HexUtils.leReverseInt(eventIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the EventType.
|
||||
*
|
||||
* @param type byte array holding the PFP defined log event type
|
||||
*/
|
||||
protected void setEventType(final byte[] type) {
|
||||
eventType = new BigInteger(1, HexUtils.leReverseByte(type)).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted string of the type for the event.
|
||||
* @return a string formatted to be human readable
|
||||
*/
|
||||
public String getEventTypeStr() {
|
||||
return String.format("0x%s %s", Long.toHexString(eventType), eventString((int) eventType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted string of the type for the event minus the byte code.
|
||||
* @return a string formatted to be human readable
|
||||
*/
|
||||
public String getEventTypeString() {
|
||||
return eventString((int) eventType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the event data after processing.
|
||||
*
|
||||
* @param eventData The PFP defined event content
|
||||
*/
|
||||
protected void setEventData(final byte[] eventData) {
|
||||
event = new byte[eventData.length];
|
||||
System.arraycopy(eventData, 0, event, 0, eventData.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Event Data (no event content) for the event.
|
||||
* event log format.
|
||||
*
|
||||
* @return byte array holding the event structure.
|
||||
*/
|
||||
public byte[] getEvent() {
|
||||
return Arrays.copyOf(event, event.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the event content after processing.
|
||||
*
|
||||
* @param eventData The PFP defined event content
|
||||
*/
|
||||
protected void setEventContent(final byte[] eventData) {
|
||||
eventContent = new byte[eventData.length];
|
||||
evPostCode = new EvPostCode(eventContent);
|
||||
System.arraycopy(eventData, 0, eventContent, 0, eventData.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the event Content Data (not the entire event structure).
|
||||
*
|
||||
* @return byte array holding the events content field
|
||||
*/
|
||||
public byte[] getEventContent() {
|
||||
return Arrays.copyOf(eventContent, eventContent.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter that parses the content based on the type and returns the proper string
|
||||
* value for the content.
|
||||
* @return an appended string of human readable data
|
||||
*/
|
||||
public String getEventContentStr() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
switch ((int) this.eventType) {
|
||||
case EvConstants.EV_PREBOOT_CERT:
|
||||
sb.append(" EV_PREBOOT_CERT");
|
||||
break;
|
||||
case EvConstants.EV_POST_CODE:
|
||||
sb.append(new EvPostCode(eventContent).toString());
|
||||
break;
|
||||
case EvConstants.EV_UNUSED:
|
||||
break;
|
||||
case EvConstants.EV_NO_ACTION:
|
||||
EvNoAction noAction = null;
|
||||
try {
|
||||
noAction = new EvNoAction(eventContent);
|
||||
sb.append(noAction.toString());
|
||||
if (noAction.isSpecIDEvent()) {
|
||||
// this should be in the constructor
|
||||
EvEfiSpecIdEvent specID = noAction.getSpecIDEvent();
|
||||
specVersion = String.format("%s.%s",
|
||||
specID.getVersionMajor(),
|
||||
specID.getVersionMinor());
|
||||
specErrataVersion = specID.getErrata();
|
||||
}
|
||||
} catch (UnsupportedEncodingException ueEx) {
|
||||
LOGGER.error(ueEx);
|
||||
sb.append(ueEx.toString());
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_SEPARATOR:
|
||||
if (EvPostCode.isAscii(eventContent)
|
||||
&& !this.isBlank(eventContent)) {
|
||||
sb.append(String.format("Separator event content = %s",
|
||||
new String(eventContent, StandardCharsets.UTF_8)));
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_EVENT_TAG:
|
||||
sb.append(new EvEventTag(eventContent).toString());
|
||||
break;
|
||||
case EvConstants.EV_S_CRTM_CONTENTS:
|
||||
sb.append(new EvSCrtmContents(eventContent).toString());
|
||||
break;
|
||||
case EvConstants.EV_S_CRTM_VERSION:
|
||||
try {
|
||||
sb.append(new EvSCrtmVersion(eventContent).toString());
|
||||
} catch (UnsupportedEncodingException ueEx) {
|
||||
LOGGER.error(ueEx);
|
||||
sb.append(ueEx.toString());
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_CPU_MICROCODE:
|
||||
case EvConstants.EV_PLATFORM_CONFIG_FLAGS:
|
||||
case EvConstants.EV_TABLE_OF_DEVICES:
|
||||
break;
|
||||
case EvConstants.EV_COMPACT_HASH:
|
||||
try {
|
||||
sb.append(new EvCompactHash(eventContent).toString());
|
||||
} catch (UnsupportedEncodingException ueEx) {
|
||||
LOGGER.error(ueEx);
|
||||
sb.append(ueEx.toString());
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_IPL:
|
||||
sb.append(new EvIPL(eventContent).toString());
|
||||
break;
|
||||
case EvConstants.EV_IPL_PARTITION_DATA:
|
||||
case EvConstants.EV_NONHOST_CODE:
|
||||
case EvConstants.EV_NONHOST_CONFIG:
|
||||
case EvConstants.EV_NONHOST_INFO:
|
||||
case EvConstants.EV_EV_OMIT_BOOT_DEVICES_EVENTS:
|
||||
case EvConstants.EV_EFI_EVENT_BASE:
|
||||
break;
|
||||
case EvConstants.EV_EFI_VARIABLE_DRIVER_CONFIG:
|
||||
UefiVariable efiVar = null;
|
||||
try {
|
||||
efiVar = new UefiVariable(eventContent);
|
||||
String efiVarDescription = efiVar.toString().replace("\n", "\n ");
|
||||
sb.append(efiVarDescription.substring(0,
|
||||
efiVarDescription.length() - INDENT_3));
|
||||
} catch (CertificateException cEx) {
|
||||
LOGGER.error(cEx);
|
||||
sb.append(cEx.toString());
|
||||
} catch (NoSuchAlgorithmException noSaEx) {
|
||||
LOGGER.error(noSaEx);
|
||||
sb.append(noSaEx.toString());
|
||||
} catch (IOException ioEx) {
|
||||
LOGGER.error(ioEx);
|
||||
sb.append(ioEx.toString());
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_EFI_VARIABLE_BOOT:
|
||||
case EvConstants.EV_EFI_VARIABLE_AUTHORITY:
|
||||
try {
|
||||
sb.append(new UefiVariable(eventContent).toString());
|
||||
} catch (CertificateException cEx) {
|
||||
LOGGER.error(cEx);
|
||||
sb.append(cEx.toString());
|
||||
} catch (NoSuchAlgorithmException noSaEx) {
|
||||
LOGGER.error(noSaEx);
|
||||
sb.append(noSaEx.toString());
|
||||
} catch (IOException ioEx) {
|
||||
LOGGER.error(ioEx);
|
||||
sb.append(ioEx.toString());
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_EFI_BOOT_SERVICES_APPLICATION:
|
||||
case EvConstants.EV_EFI_BOOT_SERVICES_DRIVER: // same as EV_EFI_BOOT_SERVICES_APP
|
||||
try {
|
||||
sb.append(new EvEfiBootServicesApp(eventContent).toString());
|
||||
} catch (UnsupportedEncodingException ueEx) {
|
||||
LOGGER.error(ueEx);
|
||||
sb.append(ueEx.toString());
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_EFI_RUNTIME_SERVICES_DRIVER:
|
||||
break;
|
||||
case EvConstants.EV_EFI_GPT_EVENT:
|
||||
try {
|
||||
sb.append(new EvEfiGptPartition(eventContent).toString());
|
||||
} catch (UnsupportedEncodingException ueEx) {
|
||||
LOGGER.error(ueEx);
|
||||
sb.append(ueEx.toString());
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_EFI_ACTION:
|
||||
case EvConstants.EV_ACTION:
|
||||
sb.append(new String(eventContent, StandardCharsets.UTF_8));
|
||||
break;
|
||||
case EvConstants.EV_EFI_PLATFORM_FIRMWARE_BLOB:
|
||||
sb.append(new UefiFirmware(eventContent).toString());
|
||||
break;
|
||||
case EvConstants.EV_EFI_HANDOFF_TABLES:
|
||||
sb.append(new EvEfiHandoffTable(eventContent).toString());
|
||||
break;
|
||||
case EvConstants.EV_EFI_HCRTM_EVENT:
|
||||
break;
|
||||
default:
|
||||
sb.append("Unknown Event found\n");
|
||||
}
|
||||
|
||||
return cleanTextContent(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the event content and creates a human readable description of each event.
|
||||
*
|
||||
* @param event the byte array holding the event data.
|
||||
* @param eventContent the byte array holding the event content.
|
||||
* @param eventNumber event position within the event log.
|
||||
* @param hashName name of the hash algorithm used by the event log
|
||||
* @return String description of the event.
|
||||
* @throws java.security.cert.CertificateException if the event contains an event that cannot be processed.
|
||||
* @throws java.security.NoSuchAlgorithmException if an event contains an unsupported algorithm.
|
||||
* @throws java.io.IOException if the event cannot be parsed.
|
||||
*/
|
||||
public String processEvent(final byte[] event, final byte[] eventContent, final int eventNumber,
|
||||
final String hashName)
|
||||
throws CertificateException, NoSuchAlgorithmException, IOException {
|
||||
int eventID = (int) eventType;
|
||||
this.eventNumber = eventNumber;
|
||||
description += "Event# " + eventNumber + ": ";
|
||||
description += "Index PCR[" + getPcrIndex() + "]\n";
|
||||
description += "Event Type: 0x" + Long.toHexString(eventType) + " " + eventString(eventID);
|
||||
description += "\n";
|
||||
if (hashName.compareToIgnoreCase("TPM_ALG_SHA1") == 0) { // Digest
|
||||
description += "digest (SHA-1): " + Hex.encodeHexString(this.digest);
|
||||
} else if (hashName.compareToIgnoreCase("TPM_ALG_SHA256") == 0) { // Digest
|
||||
description += "digest (SHA256): " + Hex.encodeHexString(this.digest);
|
||||
} else if (hashName.compareToIgnoreCase("TPM_ALG_SHA384") == 0) { // Digest
|
||||
description += "digest (SHA384): " + Hex.encodeHexString(this.digest);
|
||||
} else if (hashName.compareToIgnoreCase("TPM_ALG_SHA512") == 0) { // Digest
|
||||
description += "digest (SHA512): " + Hex.encodeHexString(this.digest);
|
||||
} else {
|
||||
description += "Unsupported Hash Algorithm encoutered";
|
||||
}
|
||||
if (eventID != UefiConstants.SIZE_4) {
|
||||
description += "\n";
|
||||
}
|
||||
// Calculate both the SHA1 and SHA256 on the event since this will equal the digest
|
||||
// field of about half the log messages.
|
||||
MessageDigest md1 = MessageDigest.getInstance("SHA-1");
|
||||
md1.update(event);
|
||||
eventDataSha1hash = md1.digest();
|
||||
MessageDigest md2 = MessageDigest.getInstance("SHA-256");
|
||||
md2.update(event);
|
||||
eventDataSha256hash = md2.digest();
|
||||
|
||||
switch (eventID) {
|
||||
case EvConstants.EV_PREBOOT_CERT:
|
||||
description += " EV_PREBOOT_CERT" + "\n";
|
||||
break;
|
||||
case EvConstants.EV_POST_CODE:
|
||||
EvPostCode postCode = new EvPostCode(eventContent);
|
||||
description += "Event Content:\n" + postCode.toString();
|
||||
break;
|
||||
case EvConstants.EV_UNUSED:
|
||||
break;
|
||||
case EvConstants.EV_NO_ACTION:
|
||||
EvNoAction noAction = new EvNoAction(eventContent);
|
||||
description += "Event Content:\n" + noAction.toString();
|
||||
if (noAction.isSpecIDEvent()) {
|
||||
EvEfiSpecIdEvent specID = noAction.getSpecIDEvent();
|
||||
specVersion = specID.getVersionMajor() + "." + specID.getVersionMinor();
|
||||
specErrataVersion = specID.getErrata();
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_SEPARATOR:
|
||||
if (EvPostCode.isAscii(eventContent)) {
|
||||
String separatorEventData = new String(eventContent, StandardCharsets.UTF_8);
|
||||
if (!this.isBlank(eventContent)) {
|
||||
description += "Separator event content = " + separatorEventData;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EvConstants.EV_ACTION:
|
||||
description += "Event Content:\n"
|
||||
+ new String(eventContent, StandardCharsets.UTF_8);
|
||||
break;
|
||||
case EvConstants.EV_EVENT_TAG:
|
||||
EvEventTag eventTag = new EvEventTag(eventContent);
|
||||
description += eventTag.toString();
|
||||
break;
|
||||
case EvConstants.EV_S_CRTM_CONTENTS:
|
||||
EvSCrtmContents sCrtmContents = new EvSCrtmContents(eventContent);
|
||||
description += "Event Content:\n " + sCrtmContents.toString();
|
||||
break;
|
||||
case EvConstants.EV_S_CRTM_VERSION:
|
||||
EvSCrtmVersion sCrtmVersion = new EvSCrtmVersion(eventContent);
|
||||
description += "Event Content:\n" + sCrtmVersion.toString();
|
||||
break;
|
||||
case EvConstants.EV_CPU_MICROCODE:
|
||||
break;
|
||||
case EvConstants.EV_PLATFORM_CONFIG_FLAGS:
|
||||
break;
|
||||
case EvConstants.EV_TABLE_OF_DEVICES:
|
||||
break;
|
||||
case EvConstants.EV_COMPACT_HASH:
|
||||
EvCompactHash compactHash = new EvCompactHash(eventContent);
|
||||
description += "Event Content:\n" + compactHash.toString();
|
||||
break;
|
||||
case EvConstants.EV_IPL:
|
||||
EvIPL ipl = new EvIPL(eventContent);
|
||||
description += "Event Content:\n" + ipl.toString();
|
||||
break;
|
||||
case EvConstants.EV_IPL_PARTITION_DATA:
|
||||
break;
|
||||
case EvConstants.EV_NONHOST_CODE:
|
||||
break;
|
||||
case EvConstants.EV_NONHOST_CONFIG:
|
||||
break;
|
||||
case EvConstants.EV_NONHOST_INFO:
|
||||
break;
|
||||
case EvConstants.EV_EV_OMIT_BOOT_DEVICES_EVENTS:
|
||||
break;
|
||||
case EvConstants.EV_EFI_EVENT_BASE:
|
||||
break;
|
||||
case EvConstants.EV_EFI_VARIABLE_DRIVER_CONFIG:
|
||||
UefiVariable efiVar = new UefiVariable(eventContent);
|
||||
String efiVarDescription = efiVar.toString().replace("\n", "\n ");
|
||||
description += "Event Content:\n " + efiVarDescription.substring(0,
|
||||
efiVarDescription.length() - INDENT_3);
|
||||
break;
|
||||
case EvConstants.EV_EFI_VARIABLE_BOOT:
|
||||
description += "Event Content:\n" + new UefiVariable(eventContent).toString();
|
||||
break;
|
||||
case EvConstants.EV_EFI_BOOT_SERVICES_APPLICATION:
|
||||
EvEfiBootServicesApp bootServices = new EvEfiBootServicesApp(eventContent);
|
||||
description += "Event Content:\n" + bootServices.toString();
|
||||
break;
|
||||
case EvConstants.EV_EFI_BOOT_SERVICES_DRIVER: // same as EV_EFI_BOOT_SERVICES_APP
|
||||
EvEfiBootServicesApp bootDriver = new EvEfiBootServicesApp(eventContent);
|
||||
description += "Event Content:\n" + bootDriver.toString();
|
||||
break;
|
||||
case EvConstants.EV_EFI_RUNTIME_SERVICES_DRIVER:
|
||||
break;
|
||||
case EvConstants.EV_EFI_GPT_EVENT:
|
||||
description += "Event Content:\n" + new EvEfiGptPartition(eventContent).toString();
|
||||
break;
|
||||
case EvConstants.EV_EFI_ACTION:
|
||||
description += new String(eventContent, StandardCharsets.UTF_8);
|
||||
break;
|
||||
case EvConstants.EV_EFI_PLATFORM_FIRMWARE_BLOB:
|
||||
description += "Event Content:\n"
|
||||
+ new UefiFirmware(eventContent).toString();
|
||||
break;
|
||||
case EvConstants.EV_EFI_HANDOFF_TABLES:
|
||||
EvEfiHandoffTable efiTable = new EvEfiHandoffTable(eventContent);
|
||||
description += "Event Content:\n" + efiTable.toString();
|
||||
break;
|
||||
case EvConstants.EV_EFI_HCRTM_EVENT:
|
||||
break;
|
||||
case EvConstants.EV_EFI_VARIABLE_AUTHORITY:
|
||||
description += "Event Content:\n" + new UefiVariable(eventContent).toString();
|
||||
break;
|
||||
default:
|
||||
description += " Unknown Event found" + "\n";
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the Event ID into a String As defined in the TCG PC Client FW Profile.
|
||||
* Event IDs have values larger than an integer,so a Long is used hold the value.
|
||||
*
|
||||
* @param event the event id.
|
||||
* @return TCG defined String that represents the event id
|
||||
*/
|
||||
private static String eventString(final long event) {
|
||||
|
||||
if (event == EvConstants.EV_PREBOOT_CERT) {
|
||||
return "EV_PREBOOT_CERT";
|
||||
} else if (event == EvConstants.EV_POST_CODE) {
|
||||
return "EV_POST_CODE";
|
||||
} else if (event == EvConstants.EV_UNUSED) {
|
||||
return "EV_Unused";
|
||||
} else if (event == EvConstants.EV_NO_ACTION) {
|
||||
return "EV_NO_ACTION";
|
||||
} else if (event == EvConstants.EV_SEPARATOR) {
|
||||
return "EV_SEPARATOR";
|
||||
} else if (event == EvConstants.EV_ACTION) {
|
||||
return "EV_ACTION";
|
||||
} else if (event == EvConstants.EV_EVENT_TAG) {
|
||||
return "EV_EVENT_TAG";
|
||||
} else if (event == EvConstants.EV_S_CRTM_CONTENTS) {
|
||||
return "EV_S_CRTM_CONTENTS";
|
||||
} else if (event == EvConstants.EV_S_CRTM_VERSION) {
|
||||
return "EV_S_CRTM_VERSION";
|
||||
} else if (event == EvConstants.EV_CPU_MICROCODE) {
|
||||
return "EV_CPU_MICROCODE";
|
||||
} else if (event == EvConstants.EV_PLATFORM_CONFIG_FLAGS) {
|
||||
return "EV_PLATFORM_CONFIG_FLAGS ";
|
||||
} else if (event == EvConstants.EV_TABLE_OF_DEVICES) {
|
||||
return "EV_TABLE_OF_DEVICES";
|
||||
} else if (event == EvConstants.EV_COMPACT_HASH) {
|
||||
return "EV_COMPACT_HASH";
|
||||
} else if (event == EvConstants.EV_IPL) {
|
||||
return "EV_IPL";
|
||||
} else if (event == EvConstants.EV_IPL_PARTITION_DATA) {
|
||||
return "EV_IPL_PARTITION_DATA";
|
||||
} else if (event == EvConstants.EV_NONHOST_CODE) {
|
||||
return "EV_NONHOST_CODE";
|
||||
} else if (event == EvConstants.EV_NONHOST_CONFIG) {
|
||||
return "EV_NONHOST_CONFIG";
|
||||
} else if (event == EvConstants.EV_NONHOST_INFO) {
|
||||
return "EV_NONHOST_INFO";
|
||||
} else if (event == EvConstants.EV_EV_OMIT_BOOT_DEVICES_EVENTS) {
|
||||
return "EV_EV_OMIT_BOOT_DEVICES_EVENTS";
|
||||
} else if (event == EvConstants.EV_EFI_EVENT_BASE) {
|
||||
return "EV_EFI_EVENT_BASE";
|
||||
} else if (event == EvConstants.EV_EFI_VARIABLE_DRIVER_CONFIG) {
|
||||
return "EV_EFI_VARIABLE_DRIVER_CONFIG";
|
||||
} else if (event == EvConstants.EV_EFI_VARIABLE_BOOT) {
|
||||
return "EV_EFI_VARIABLE_BOOT";
|
||||
} else if (event == EvConstants.EV_EFI_BOOT_SERVICES_APPLICATION) {
|
||||
return "EV_EFI_BOOT_SERVICES_APPLICATION";
|
||||
} else if (event == EvConstants.EV_EFI_BOOT_SERVICES_DRIVER) {
|
||||
return "EV_EFI_BOOT_SERVICES_DRIVER";
|
||||
} else if (event == EvConstants.EV_EFI_RUNTIME_SERVICES_DRIVER) {
|
||||
return "EV_EFI_RUNTIME_SERVICES_DRIVER";
|
||||
} else if (event == EvConstants.EV_EFI_GPT_EVENT) {
|
||||
return "EV_EFI_GPT_EVENT";
|
||||
} else if (event == EvConstants.EV_EFI_ACTION) {
|
||||
return "EV_EFI_ACTION";
|
||||
} else if (event == EvConstants.EV_EFI_PLATFORM_FIRMWARE_BLOB) {
|
||||
return "EV_EFI_PLATFORM_FIRMWARE_BLOB";
|
||||
} else if (event == EvConstants.EV_EFI_HANDOFF_TABLES) {
|
||||
return "EV_EFI_HANDOFF_TABLES";
|
||||
} else if (event == EvConstants.EV_EFI_HCRTM_EVENT) {
|
||||
return "EV_EFI_HCRTM_EVENT";
|
||||
} else if (event == EvConstants.EV_EFI_VARIABLE_AUTHORITY) {
|
||||
return "EV_EFI_VARIABLE_AUTHORITY";
|
||||
} else {
|
||||
return "Unknown Event ID " + event + " encountered";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Human readable output of a check of input against the current event hash.
|
||||
*
|
||||
* @return human readable string.
|
||||
*/
|
||||
private String eventHashCheck() {
|
||||
String result = "";
|
||||
if (logFormat == 1) {
|
||||
if (Arrays.equals(this.digest, eventDataSha1hash)) {
|
||||
result
|
||||
+= "Event digest matched hash of the event data " + "\n";
|
||||
} else {
|
||||
result += "Event digest DID NOT match the hash of the event data :"
|
||||
+ Hex.encodeHexString(getEventDigest()) + "\n";
|
||||
}
|
||||
} else {
|
||||
if (Arrays.equals(this.digest, eventDataSha256hash)) {
|
||||
result += "Event digest matched hash of the event data " + "\n";
|
||||
} else {
|
||||
result += "Event digest DID NOT match the hash of the event data :"
|
||||
+ Hex.encodeHexString(getEventDigest()) + "\n";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes in an event and compares the hashes to verify that they match.
|
||||
* @param tpmPcrEvent an event to match.
|
||||
* @return true if the event # matches and the hash is correct.
|
||||
*/
|
||||
public boolean eventCompare(final TpmPcrEvent tpmPcrEvent) {
|
||||
if (tpmPcrEvent.getPcrIndex() != this.getPcrIndex()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Arrays.equals(this.digest, tpmPcrEvent.getEventDigest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a byte array for all zeros.
|
||||
*
|
||||
* @param array holds data to check.
|
||||
* @return true of all zeros are found.
|
||||
*/
|
||||
public boolean isBlank(final byte[] array) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Human readable string representing the contents of the Event Log.
|
||||
*
|
||||
* @return Description of the log.
|
||||
*/
|
||||
public String toString() {
|
||||
return description + "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Human readable string representing the contents of the Event Log.
|
||||
*
|
||||
* @param bEvent event Flag.
|
||||
* @param bContent content flag.
|
||||
* @param bHexEvent hex event flag.
|
||||
* @return Description of the log.
|
||||
*/
|
||||
public String toString(final boolean bEvent, final boolean bContent, final boolean bHexEvent) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (bEvent) {
|
||||
sb.append(description);
|
||||
}
|
||||
if (bHexEvent) {
|
||||
if (bEvent || bContent) {
|
||||
sb.append("\n");
|
||||
}
|
||||
byte[] eventData = getEvent();
|
||||
sb.append("Event (Hex no Content) (" + eventData.length + " bytes): "
|
||||
+ Hex.encodeHexString(eventData));
|
||||
}
|
||||
if (bContent) {
|
||||
byte[] evContent = getEventContent();
|
||||
if (bEvent) {
|
||||
sb.append("\n");
|
||||
}
|
||||
sb.append("Event content (Hex) (" + evContent.length + " bytes): "
|
||||
+ Hex.encodeHexString(evContent));
|
||||
}
|
||||
return sb.toString() + "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove bad visual value text.
|
||||
* @param text content to operate over.
|
||||
* @return cleared string
|
||||
*/
|
||||
public String cleanTextContent(final String text) {
|
||||
String result;
|
||||
// strips off all non-ASCII characters
|
||||
result = text.replaceAll("[^\\x00-\\x7F]", "");
|
||||
|
||||
// erases all the ASCII control characters
|
||||
result = result.replaceAll("[\\p{Cntrl}&&[^\r\n\t]]", "");
|
||||
|
||||
// removes non-printable characters from Unicode
|
||||
result = result.replaceAll("\\p{C}", "");
|
||||
|
||||
return result.trim();
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package hirs.attestationca.portal.utils.tpm.eventlog;
|
||||
|
||||
import hirs.attestationca.utils.HexUtils;
|
||||
import hirs.attestationca.utils.tpm.eventlog.events.EvConstants;
|
||||
import hirs.attestationca.utils.tpm.eventlog.uefi.UefiConstants;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
/**
|
||||
* Class to process a TCG_PCR_EVENT.
|
||||
* TCG_PCR_EVENT is used when the Event log uses the SHA1 Format as described in the
|
||||
* TCG Platform Firmware Profile specification.
|
||||
* typedef struct {
|
||||
* UINT32 PCRIndex; //PCR Index value that either
|
||||
* //matches the PCRIndex of a
|
||||
* //previous extend operation or
|
||||
* //indicates that this Event Log
|
||||
* //entry is not associated with
|
||||
* //an extend operation
|
||||
* UINT32 EventType; //See Log event types
|
||||
* BYTE digest[20]; //The SHA1 hash of the event data
|
||||
* UINT32 EventSize; //Size of the event data
|
||||
* UINT8 Event[1]; //
|
||||
* } TCG_PCR_EVENT; //The event data structure to be added
|
||||
*/
|
||||
public class TpmPcrEvent1 extends TpmPcrEvent {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param is ByteArrayInputStream holding the TCG Log event.
|
||||
* @param eventNumber event position within the event log.
|
||||
* @throws java.io.IOException if an error occurs in parsing the event.
|
||||
* @throws java.security.NoSuchAlgorithmException if an undefined algorithm is encountered.
|
||||
* @throws java.security.cert.CertificateException If a certificate within an event can't be processed.
|
||||
*/
|
||||
public TpmPcrEvent1(final ByteArrayInputStream is, final int eventNumber)
|
||||
throws IOException, CertificateException, NoSuchAlgorithmException {
|
||||
super(is);
|
||||
setDigestLength(EvConstants.SHA1_LENGTH);
|
||||
setLogFormat(1);
|
||||
/** Event data. */
|
||||
byte[] event = null;
|
||||
byte[] rawIndex = new byte[UefiConstants.SIZE_4];
|
||||
byte[] rawType = new byte[UefiConstants.SIZE_4];
|
||||
byte[] rawEventSize = new byte[UefiConstants.SIZE_4];
|
||||
byte[] eventDigest = new byte[EvConstants.SHA1_LENGTH];
|
||||
byte[] eventContent = null;
|
||||
int digestSize = EvConstants.SHA1_LENGTH;
|
||||
int eventSize = 0;
|
||||
String hashName = "TPM_ALG_SHA1";
|
||||
if (is.available() > UefiConstants.SIZE_32) {
|
||||
is.read(rawIndex);
|
||||
setPcrIndex(rawIndex);
|
||||
is.read(rawType);
|
||||
setEventType(rawType);
|
||||
is.read(eventDigest);
|
||||
setEventDigest(eventDigest, digestSize);
|
||||
is.read(rawEventSize);
|
||||
eventSize = HexUtils.leReverseInt(rawEventSize);
|
||||
eventContent = new byte[eventSize];
|
||||
is.read(eventContent);
|
||||
setEventContent(eventContent);
|
||||
// copy entire event into a byte array for processing
|
||||
int eventLength = rawIndex.length + rawType.length + eventDigest.length
|
||||
+ rawEventSize.length;
|
||||
int offset = 0;
|
||||
event = new byte[eventLength];
|
||||
System.arraycopy(rawIndex, 0, event, offset, rawIndex.length);
|
||||
offset += rawIndex.length;
|
||||
System.arraycopy(rawType, 0, event, offset, rawType.length);
|
||||
offset += rawType.length;
|
||||
System.arraycopy(eventDigest, 0, event, offset, eventDigest.length);
|
||||
offset += eventDigest.length;
|
||||
System.arraycopy(rawEventSize, 0, event, offset, rawEventSize.length);
|
||||
offset += rawEventSize.length;
|
||||
setEventData(event);
|
||||
//System.arraycopy(eventContent, 0, event, offset, eventContent.length);
|
||||
this.processEvent(event, eventContent, eventNumber, hashName);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user