Merge commit 'de17aee' into v3_issue-877

This commit is contained in:
iadgovuser59 2024-11-18 12:27:09 -05:00
commit 8951faabe6
304 changed files with 6704 additions and 13239 deletions

View File

@ -84,4 +84,4 @@ HEALTHCHECK --start-period=50s --interval=1s --timeout=90s CMD curl -f https://l
WORKDIR /hirs
# On container launch, the database will be set up. Then bootRun should utilize build artifacts stored in the image.
CMD ["bash", "-c", "/hirs/package/linux/aca/aca_setup.sh --unattended && /tmp/hirs_add_aca_tls_path_to_os.sh && /hirs/package/linux/aca/aca_bootRun.sh"]
CMD ["bash", "-c", "/hirs/package/linux/aca/aca_check_env.sh && /hirs/package/linux/aca/aca_setup.sh --unattended && /tmp/hirs_add_aca_tls_path_to_os.sh && /hirs/package/linux/aca/aca_bootRun.sh"]

View File

@ -54,6 +54,9 @@ dependencies {
testImplementation 'org.mockito:mockito-core:4.2.0'
testImplementation 'org.springframework:spring-test:6.0.8'
compileOnly "com.github.spotbugs:spotbugs-annotations:${spotBugAnnotationVersion}"
annotationProcessor "com.github.spotbugs:spotbugs-annotations:${spotBugAnnotationVersion}"
// spring management
compileOnly libs.lombok
implementation libs.lombok
@ -89,7 +92,7 @@ protobuf {
sourceSets {
main {
proto {
srcDir '../HIRS_ProvisionerTPM2/src'
srcDir '../HIRS_Provisioner.NET/hirs/Resources'
}
}
}

View File

@ -7,10 +7,10 @@
dir=$(pwd)
# Relative paths are different when building locally versus on CI
if [[ "$dir" == *"package"* ]]; then
SRC_DIR=$dir/../../../../../../HIRS_ProvisionerTPM2/src
SRC_DIR=$dir/../../../../../../HIRS_Provisioner.NET/hirs/Resources
DEST_DIR=$dir/../src/main/java
else
SRC_DIR=../../HIRS_ProvisionerTPM2/src
SRC_DIR=../../HIRS_Provisioner.NET/hirs/Resources
DEST_DIR=../src/main/java
fi
protoc -I=$SRC_DIR --java_out=$DEST_DIR $SRC_DIR/ProvisionerTpm2.proto

View File

@ -45,15 +45,7 @@ public abstract class AttestationCertificateAuthority {
* A handle to the service used to validate the supply chain.
*/
private final SupplyChainValidationService supplyChainValidationService;
/**
* Container wired application configuration property identifying the number of days that
* certificates issued by this ACA are valid for.
*/
private Integer validDays = 1;
private final ComponentResultRepository componentResultRepository;
private ComponentInfoRepository componentInfoRepository;
private final CertificateRepository certificateRepository;
private final IssuedCertificateRepository issuedCertificateRepository;
private final ReferenceManifestRepository referenceManifestRepository;
@ -62,12 +54,18 @@ public abstract class AttestationCertificateAuthority {
private final ReferenceDigestValueRepository referenceDigestValueRepository;
private final PolicyRepository policyRepository;
private final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
private CertificateRequestProcessor certificateRequestHandler;
private IdentityClaimProcessor identityClaimHandler;
private final ComponentInfoRepository componentInfoRepository;
private final CertificateRequestProcessor certificateRequestHandler;
private final IdentityClaimProcessor identityClaimHandler;
/**
* Container wired application configuration property identifying the number of days that
* certificates issued by this ACA are valid for.
*/
private Integer validDays = 1;
/**
* Constructor.
*
* @param supplyChainValidationService the supply chain service
* @param privateKey the ACA private key
* @param acaCertificate the ACA certificate
@ -75,6 +73,7 @@ public abstract class AttestationCertificateAuthority {
* @param componentResultRepository the component result manager
* @param componentInfoRepository the component info manager
* @param certificateRepository the certificate manager
* @param issuedCertificateRepository the issued certificate repository
* @param referenceManifestRepository the Reference Manifest manager
* @param validDays the number of days issued certs are valid
* @param deviceRepository the device manager
@ -82,7 +81,6 @@ public abstract class AttestationCertificateAuthority {
* @param policyRepository policy setting repository
* @param tpm2ProvisionerStateRepository tpm2 provisioner state repository
*/
@SuppressWarnings("checkstyle:parameternumber")
public AttestationCertificateAuthority(
final SupplyChainValidationService supplyChainValidationService,
final PrivateKey privateKey, final X509Certificate acaCertificate,
@ -121,14 +119,31 @@ public abstract class AttestationCertificateAuthority {
deviceRepository, tpm2ProvisionerStateRepository, policyRepository);
}
/**
* Processes the provided identity claim.
*
* @param identityClaim a byte array representation of the identity claim
* @return processed identity claim response
*/
byte[] processIdentityClaimTpm2(final byte[] identityClaim) {
return this.identityClaimHandler.processIdentityClaimTpm2(identityClaim);
}
/**
* Processes the provided certificate request.
*
* @param certificateRequest a byte array representation of the certificate request
* @return processed certificate request response
*/
byte[] processCertificateRequest(final byte[] certificateRequest) {
return this.certificateRequestHandler.processCertificateRequest(certificateRequest);
}
/**
* Retrieves the encoded public key.
*
* @return encoded public key
*/
public byte[] getPublicKey() {
return acaCertificate.getPublicKey().getEncoded();
}

View File

@ -4,10 +4,13 @@ import jakarta.persistence.criteria.CriteriaQuery;
/**
* Allows a user of the DBManager to modify the criteria object before processing.
*
* @param <T> the parameter type
*/
public interface CriteriaModifier<T> {
/**
* Allows a client to modify the criteria object by reference.
*
* @param criteria The hibernate criteria builder object
*/
void modify(CriteriaQuery<T> criteria);

View File

@ -12,8 +12,7 @@ public class DBManagerException extends RuntimeException {
* Creates a new <code>DBManagerException</code> that has the message
* <code>msg</code>.
*
* @param msg
* exception message
* @param msg exception message
*/
public DBManagerException(final String msg) {
super(msg);
@ -23,8 +22,7 @@ public class DBManagerException extends RuntimeException {
* Creates a new <code>DBManagerException</code> that wraps the given
* <code>Throwable</code>.
*
* @param t
* root cause
* @param t root cause
*/
public DBManagerException(final Throwable t) {
super(t);
@ -34,10 +32,8 @@ public class DBManagerException extends RuntimeException {
* Creates a new <code>DBManagerException</code> that has the message
* <code>msg</code> and wraps the root cause.
*
* @param msg
* exception message
* @param t
* root cause
* @param msg exception message
* @param t root cause
*/
public DBManagerException(final String msg, final Throwable t) {
super(msg, t);

View File

@ -17,5 +17,7 @@ import java.util.ArrayList;
@EqualsAndHashCode(callSuper = false)
public class FilteredRecordsList<T> extends ArrayList<T> {
private long recordsTotal, recordsFiltered;
private long recordsTotal;
private long recordsFiltered;
}

View File

@ -5,6 +5,7 @@ import java.util.Map;
/**
* Interface defining methods for getting ordered lists from a data source. Includes
* properties for sorting, paging, and searching.
*
* @param <T> the record type, T.
*/
public interface OrderedListQuerier<T> {
@ -22,8 +23,8 @@ public interface OrderedListQuerier<T> {
* @param maxResults total number we want returned for display in table
* @param search string of criteria to be matched to visible columns
* @param searchableColumns Map of String and boolean values with column
* headers and whether they should be searched. Boolean is true if field provides a
* typical String that can be searched by Hibernate without transformation.
* headers and whether they should be searched. Boolean is true if field provides
* a typical String that can be searched by Hibernate without transformation.
* @return FilteredRecordsList object with query data
* @throws DBManagerException if unable to create the list
*/
@ -49,13 +50,12 @@ public interface OrderedListQuerier<T> {
* @param maxResults total number we want returned for display in table
* @param search string of criteria to be matched to visible columns
* @param searchableColumns Map of String and boolean values with column
* headers and whether they should be searched. Boolean is true if field provides a
* typical String that can be searched by Hibernate without transformation.
* headers and whether they should be searched. Boolean is true if field provides
* a typical String that can be searched by Hibernate without transformation.
* @param criteriaModifier a way to modify the criteria used in the query
* @return FilteredRecordsList object with query data
* @throws DBManagerException if unable to create the list
*/
@SuppressWarnings("checkstyle:parameternumber")
FilteredRecordsList<T> getOrderedList(
Class<? extends T> clazz, String columnToOrder,
boolean ascending, int firstResult,

View File

@ -33,13 +33,13 @@ import java.security.cert.X509Certificate;
// detects if file exists, if not, ignore errors
@PropertySource(value = "file:/etc/hirs/aca/application.properties",
ignoreResourceNotFound = true),
@PropertySource(value = "file:C:/ProgramData/hirs/aca/application.win.properties",
ignoreResourceNotFound = true)
})
@RestController
@RequestMapping("/HIRS_AttestationCA")
public class RestfulAttestationCertificateAuthority extends AttestationCertificateAuthority implements RestfulInterface {
public class RestfulAttestationCertificateAuthority extends AttestationCertificateAuthority
implements RestfulInterface {
/**
* Constructor.
@ -47,8 +47,11 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
* @param supplyChainValidationService scp service
* @param privateKey the ACA private key
* @param acaCertificate the ACA certificate
* @param structConverter the struct converter
* @param componentResultRepository the component result repository
* @param componentInfoRepository the component info repository
* @param certificateRepository the certificate manager
* @param issuedCertificateRepository the issued certificate repository
* @param referenceManifestRepository the referenceManifestManager
* @param validDays the number of days issued certs are valid
* @param deviceRepository the device manager
@ -56,11 +59,11 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
* @param policyRepository the provisioning policy entity
* @param tpm2ProvisionerStateRepository the provisioner state
*/
@SuppressWarnings({"checkstyle:parameternumber"})
@Autowired
public RestfulAttestationCertificateAuthority(
final SupplyChainValidationService supplyChainValidationService,
final PrivateKey privateKey, final X509Certificate acaCertificate,
final PrivateKey privateKey,
final X509Certificate acaCertificate,
final StructConverter structConverter,
final ComponentResultRepository componentResultRepository,
final ComponentInfoRepository componentInfoRepository,
@ -82,7 +85,7 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
/**
* Listener for identity requests from TPM 2.0 provisioning.
*
* <p>
* Processes a given IdentityClaim and generates a response
* containing an encrypted nonce to be returned by the client in
* a future handshake request.
@ -121,8 +124,8 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
* (non-javadoc)
* <p>
* Wrap the {@link AttestationCertificateAuthority#getPublicKey()} with a Spring
* {@link org.springframework.web.bind.annotation.RequestMapping} such that Spring can serialize the certificate to be returned to an
* HTTP Request.
* {@link org.springframework.web.bind.annotation.RequestMapping} such that Spring can serialize
* the certificate to be returned to an HTTP Request.
*/
@Override
@ResponseBody

View File

@ -5,8 +5,20 @@ package hirs.attestationca.persist;
*/
public interface RestfulInterface {
/**
* Processes the provided identity claim.
*
* @param identityClaim a byte array representation of the identity claim
* @return a byte array representation of the identity claim response
*/
byte[] processIdentityClaimTpm2(byte[] identityClaim);
/**
* Processes the provided certificate request.
*
* @param certificateRequest a byte array representation of the certificate request
* @return a byte array representation of the certificate request response
*/
byte[] processCertificateRequest(byte[] certificateRequest);
}

View File

@ -47,9 +47,10 @@ public abstract class AbstractEntity implements Serializable {
/**
* Setter for the UUID that can not be null
* and can not be overridden.
*
* @param id - primary able key
*/
public void setId(UUID id) {
public void setId(final UUID id) {
if (id != null) {
this.id = id;
}
@ -74,6 +75,11 @@ public abstract class AbstractEntity implements Serializable {
createTime.setTime(new Date().getTime());
}
/**
* Generates an integer hash code for this entity.
*
* @return hash code
*/
@Override
public int hashCode() {
if (id != null) {
@ -82,6 +88,13 @@ public abstract class AbstractEntity implements Serializable {
return super.hashCode();
}
/**
* Compares this entity to the provided object to verify
* that both objects are equal.
*
* @param object object to compare
* @return true if they are equal, false otherwise
*/
@Override
public boolean equals(final Object object) {
if (this == object) {

View File

@ -6,7 +6,11 @@ import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.*;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* The <code>Appraiser</code> class represents an appraiser that can appraise a <code>Report</code>.

View File

@ -55,8 +55,7 @@ public abstract class ArchivableEntity extends AbstractEntity {
* 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.
* @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() {
@ -73,8 +72,7 @@ public abstract class ArchivableEntity extends AbstractEntity {
* 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
* @return boolean result is dependent on the return value of the archive() method
*/
public final boolean archive(final String description) {
if (archive()) {
@ -104,8 +102,7 @@ public abstract class ArchivableEntity extends AbstractEntity {
* 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.
* @return true if the time is changed to null.
* false if time was already set to null.
*/
public final boolean restore() {

View File

@ -29,8 +29,7 @@ public abstract class Policy extends UserDefinedEntity {
/**
* Creates a new <code>Policy</code> with the specified name.
*
* @param name
* name
* @param name name
*/
public Policy(final String name) {
super(name);
@ -40,10 +39,8 @@ public abstract class Policy extends UserDefinedEntity {
* Creates a new <code>Policy</code> with the specified name and
* description.
*
* @param name
* name (required)
* @param description
* description (may be null)
* @param name name (required)
* @param description description (may be null)
*/
public Policy(final String name, final String description) {
super(name, description);

View File

@ -4,9 +4,9 @@ import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.ToString;
import lombok.NonNull;
/**
* An abstract archivable entity that can be given a user-defined name and description.
@ -18,11 +18,13 @@ import lombok.NonNull;
public abstract class UserDefinedEntity extends ArchivableEntity {
@Column(nullable = false, unique = true)
@NonNull private String name;
@NonNull
private String name;
@ToString.Exclude
@Column(nullable = false, unique = false)
@NonNull private String description = "";
@NonNull
private String description = "";
/**
* Default empty constructor is required for Hibernate. It is protected to
@ -47,8 +49,7 @@ public abstract class UserDefinedEntity extends ArchivableEntity {
* an instance of <code>UserDefinedEntity</code> and its name is the same as this
* <code>UserDefinedEntity</code>. Otherwise this returns false.
*
* @param other
* other object to test for equals
* @param other other object to test for equals
* @return true if other is <code>Baseline</code> and has same name
*/
@Override
@ -56,11 +57,10 @@ public abstract class UserDefinedEntity extends ArchivableEntity {
if (this == other) {
return true;
}
if (!(other instanceof UserDefinedEntity)) {
if (!(other instanceof UserDefinedEntity entity)) {
return false;
}
final UserDefinedEntity entity = (UserDefinedEntity) other;
return this.getName().equals(entity.getName());
}

View File

@ -12,12 +12,77 @@ import java.util.UUID;
@Repository
public interface CACredentialRepository extends JpaRepository<CertificateAuthorityCredential, UUID> {
/**
* Query that retrieves a list of certificate authority credentials using the provided archive flag.
*
* @param archiveFlag archive flag
* @return a list of certificate authority credentials
*/
List<CertificateAuthorityCredential> findByArchiveFlag(boolean archiveFlag);
/**
* Query that retrieves a page of certificate authority credentials using the provided archive
* flag and the provided pageable.
*
* @param archiveFlag archive flag
* @param pageable pageable
* @return a page of certificate authority credentials
*/
Page<CertificateAuthorityCredential> findByArchiveFlag(boolean archiveFlag, Pageable pageable);
/**
* Query that retrieves a list of certificate authority credentials using the provided subject.
*
* @param subject subject
* @return a list of certificate authority credentials
*/
List<CertificateAuthorityCredential> findBySubject(String subject);
/**
* Query that retrieves a sorted list of certificate authority credentials using the provided subject.
*
* @param subject subject
* @return a sorted list of certificate authority credentials
*/
List<CertificateAuthorityCredential> findBySubjectSorted(String subject);
/**
* Query that retrieves a list of certificate authority credentials using the provided subject
* and the provided archive flag.
*
* @param subject subject
* @param archiveFlag archive flag
* @return a list of certificate authority credentials
*/
List<CertificateAuthorityCredential> findBySubjectAndArchiveFlag(String subject, boolean archiveFlag);
List<CertificateAuthorityCredential> findBySubjectSortedAndArchiveFlag(String subject, boolean archiveFlag);
/**
* Query that retrieves a sorted list of certificate authority credentials using the provided subject
* and the provided archive flag.
*
* @param subject subject
* @param archiveFlag archive flag
* @return a sorted list of certificate authority credentials
*/
List<CertificateAuthorityCredential> findBySubjectSortedAndArchiveFlag(String subject,
boolean archiveFlag);
/**
* Query that retrieves a certificate authority credential using the provided subject key identifier.
*
* @param subjectKeyIdentifier byte array representation of the subject key identifier
* @return a certificate authority credential
*/
CertificateAuthorityCredential findBySubjectKeyIdentifier(byte[] subjectKeyIdentifier);
CertificateAuthorityCredential findBySubjectKeyIdStringAndArchiveFlag(String subjectKeyIdString, boolean archiveFlag);
/**
* Query that retrieves a certificate authority credential using the provided subject key identifier
* and the provided archive flag.
*
* @param subjectKeyIdString string representation of the subject key id
* @param archiveFlag archive flag
* @return a certificate authority credential
*/
CertificateAuthorityCredential findBySubjectKeyIdStringAndArchiveFlag(String subjectKeyIdString,
boolean archiveFlag);
}

View File

@ -16,26 +16,129 @@ import java.util.UUID;
@Repository
public interface CertificateRepository extends JpaRepository<Certificate, UUID> {
/**
* Query that retrieves a certificate using the provided uuid.
*
* @param uuid uuid
* @return a certificate
*/
@Query(value = "SELECT * FROM Certificate where id = ?1", nativeQuery = true)
Certificate getCertificate(UUID uuid);
/**
* Query that retrieves a list of certificates using the provided subject and dtype.
*
* @param subject subject
* @param dType dtype
* @return a list of certificates
*/
@Query(value = "SELECT * FROM Certificate where subject = ?1 AND DTYPE = ?2", nativeQuery = true)
List<Certificate> findBySubject(String subject, String dType);
/**
* Query that retrieves a sorted list of certificates using the provided subject and dtype.
*
* @param subjectSorted subject
* @param dType dtype
* @return a list of sorted certificates
*/
@Query(value = "SELECT * FROM Certificate where subjectSorted = ?1 AND DTYPE = ?2", nativeQuery = true)
List<Certificate> findBySubjectSorted(String subjectSorted, String dType);
/**
* Query that retrieves a list of certificates using the provided dtype.
*
* @param dType dtype
* @return a list of certificates
*/
@Query(value = "SELECT * FROM Certificate where DTYPE = ?1", nativeQuery = true)
List<Certificate> findByType(String dType);
/**
* Query that retrieves a list of certificates using the provided serial number and dtype.
*
* @param serialNumber serial number
* @param dType dtype
* @return a certificate
*/
@Query(value = "SELECT * FROM Certificate where serialNumber = ?1 AND DTYPE = ?2", nativeQuery = true)
Certificate findBySerialNumber(BigInteger serialNumber, String dType);
@Query(value = "SELECT * FROM Certificate where platformSerial = ?1 AND DTYPE = 'PlatformCredential'", nativeQuery = true)
/**
* Query that retrieves a list of platform credentials using the provided board serial number
* and a dtype of "Platform Credential".
*
* @param boardSerialNumber board serial number
* @return a list of platform credentials
*/
@Query(value = "SELECT * FROM Certificate where platformSerial = ?1 AND DTYPE = 'PlatformCredential'",
nativeQuery = true)
List<PlatformCredential> byBoardSerialNumber(String boardSerialNumber);
@Query(value = "SELECT * FROM Certificate where holderSerialNumber = ?1 AND DTYPE = 'PlatformCredential'", nativeQuery = true)
/**
* Query that retrieves a platform credential using the provided holder serial number
* and a dtype of "Platform Credential".
*
* @param holderSerialNumber holder serial number
* @return platform credential
*/
@Query(value = "SELECT * FROM Certificate where holderSerialNumber = ?1 AND DTYPE = 'PlatformCredential'",
nativeQuery = true)
PlatformCredential getPcByHolderSerialNumber(BigInteger holderSerialNumber);
@Query(value = "SELECT * FROM Certificate where holderSerialNumber = ?1 AND DTYPE = 'PlatformCredential'", nativeQuery = true)
/**
* Query that retrieves a list of platform credentials using the provided holder serial number
* and a dtype of "Platform Credential".
*
* @param holderSerialNumber holder serial numberz
* @return a list of platform credentials
*/
@Query(value = "SELECT * FROM Certificate where holderSerialNumber = ?1 AND DTYPE = 'PlatformCredential'",
nativeQuery = true)
List<PlatformCredential> getByHolderSerialNumber(BigInteger holderSerialNumber);
/**
* Query that retrieves a certificate using the provided certificate hash and dtype.
*
* @param certificateHash integer certificate hash
* @param dType dtype
* @return a certificate
*/
@Query(value = "SELECT * FROM Certificate where certificateHash = ?1 AND DTYPE = ?2", nativeQuery = true)
Certificate findByCertificateHash(int certificateHash, String dType);
/**
* Query that retrieves an endorssement credential using the provided public key modulus hex value.
*
* @param publicKeyModulusHexValue public key modulus hex value
* @return an endorsement credential
*/
EndorsementCredential findByPublicKeyModulusHexValue(String publicKeyModulusHexValue);
/**
* Query that retrieves an issued attestation certificate using the provided device id.
*
* @param deviceId uuid representation of the device id
* @return an issued attestation certificate
*/
IssuedAttestationCertificate findByDeviceId(UUID deviceId);
/**
* Query that retrieves a list of issued attestation certificates using the provided device id,
* isLDevID value and sort value.
*
* @param deviceId device id
* @param isLDevID is it a LDevId
* @param sort sort
* @return a list of issued attestation certificates
*/
List<IssuedAttestationCertificate> findByDeviceIdAndIsLDevID(UUID deviceId, boolean isLDevID, Sort sort);
/**
* Query that retrieves a certificates using the provided certificate hash.
*
* @param certificateHash integer certificate hash
* @return a certificate
*/
Certificate findByCertificateHash(int certificateHash);
}

View File

@ -10,6 +10,7 @@ public interface ComponentAttributeRepository extends JpaRepository<ComponentAtt
/**
* Query to look up Attribute Results based on the PlatformCredential's
* db component id.
*
* @param componentId the unique id for the component identifier
* @return a list of attribute results
*/
@ -17,6 +18,7 @@ public interface ComponentAttributeRepository extends JpaRepository<ComponentAtt
/**
* Query to look up Attribute Results based on the validation id.
*
* @param provisionSessionId unique id generated to link supply chain summary
* @return a list of attribute results
*/
@ -24,9 +26,11 @@ public interface ComponentAttributeRepository extends JpaRepository<ComponentAtt
/**
* Query to look up Attribute Results based on the component id and the session id.
*
* @param componentId the unique id for the component identifier
* @param provisionSessionId unique id generated to link supply chain summary
* @return a list of attribute results
*/
List<ComponentAttributeResult> findByComponentIdAndProvisionSessionId(UUID componentId, UUID provisionSessionId);
List<ComponentAttributeResult> findByComponentIdAndProvisionSessionId(UUID componentId,
UUID provisionSessionId);
}

View File

@ -9,6 +9,7 @@ import java.util.UUID;
public interface ComponentInfoRepository extends JpaRepository<ComponentInfo, UUID> {
/**
* Query that retrieves device components by device name.
*
* @param deviceName string for the host name
* @return a list of device components
*/
@ -17,6 +18,7 @@ public interface ComponentInfoRepository extends JpaRepository<ComponentInfo, UU
/**
* Query that retrieves device components by device name and
* the component serial number.
*
* @param deviceName string for the host name
* @param componentSerial string for the component serial
* @return a list of device components

View File

@ -12,6 +12,7 @@ public interface ComponentResultRepository extends JpaRepository<ComponentResult
/**
* Query based on the device serial number.
*
* @param boardSerialNumber variable holding the device serial number
* @return a list of component result.
*/
@ -19,6 +20,7 @@ public interface ComponentResultRepository extends JpaRepository<ComponentResult
/**
* Query based on the device serial number.
*
* @param boardSerialNumber variable holding the device serial number
* @param delta flag indicating if the component is associated with a delta certificate
* @return a list of component result.
@ -27,6 +29,7 @@ public interface ComponentResultRepository extends JpaRepository<ComponentResult
/**
* Query based on certificate serial number and device serial number.
*
* @param certificateSerialNumber certificate specific serial number
* @param boardSerialNumber variable holding the device serial number
* @return a list of component result.

View File

@ -8,5 +8,11 @@ import java.util.UUID;
@Repository
public interface DeviceRepository extends JpaRepository<Device, UUID> {
/**
* Query that retrieves a device using the provided device name.
*
* @param deviceName device name
* @return a device
*/
Device findByName(String deviceName);
}

View File

@ -13,9 +13,44 @@ import java.util.UUID;
@Repository
public interface EndorsementCredentialRepository extends JpaRepository<EndorsementCredential, UUID> {
/**
* Query that retrieves a list of endorsement credentials using the provided archive flag.
*
* @param archiveFlag archive flag
* @return a list of endorsement credentials
*/
List<EndorsementCredential> findByArchiveFlag(boolean archiveFlag);
/**
* Query that retrieves a page of endorsement credentials using provided archive flag and pageable value.
*
* @param archiveFlag archive flag
* @param pageable pageable value
* @return a page of endorsement credentials
*/
Page<EndorsementCredential> findByArchiveFlag(boolean archiveFlag, Pageable pageable);
/**
* Query that retrieves an endorsement credential using the provided holder serial number.
*
* @param holderSerialNumber big integer representation of the holder serial number
* @return an endorsement credential
*/
EndorsementCredential findByHolderSerialNumber(BigInteger holderSerialNumber);
/**
* Query that retrieves an endorsement credential using the provided serial number.
*
* @param serialNumber big integer representation of the serial number
* @return an endorsement credential
*/
EndorsementCredential findBySerialNumber(BigInteger serialNumber);
/**
* Query that retrieves a list of endorsement credentials using the provided device id.
*
* @param deviceId uuid representation of the device id
* @return an endorsement credential
*/
List<EndorsementCredential> findByDeviceId(UUID deviceId);
}

View File

@ -12,14 +12,74 @@ import java.util.UUID;
@Repository
public interface IDevIDCertificateRepository extends JpaRepository<IDevIDCertificate, UUID> {
/**
* Query that retrieves a list of IDevId certificates using the provided archive flag.
*
* @param archiveFlag archive flag
* @return a list of IDevId certificates
*/
List<IDevIDCertificate> findByArchiveFlag(boolean archiveFlag);
Page<IDevIDCertificate> findByArchiveFlag(boolean archiveFlag, Pageable pageable);
/*List<IDevIDCertificate> findBySubject(String subject);
List<IDevIDCertificate> findBySubjectSorted(String subject);
List<IDevIDCertificate> findBySubjectAndArchiveFlag(String subject, boolean archiveFlag);
List<IDevIDCertificate> findBySubjectSortedAndArchiveFlag(String subject, boolean archiveFlag);
IDevIDCertificate findBySubjectKeyIdentifier(byte[] subjectKeyIdentifier);
IDevIDCertificate findBySubjectKeyIdStringAndArchiveFlag(String subjectKeyIdString, boolean archiveFlag);
/**
* Query that retrieves a page of IDevId certificates using the provided archive flag and pageable value.
*
* @param archiveFlag archive flag
* @param pageable pageable value
* @return a page of IDevId certificates
*/
Page<IDevIDCertificate> findByArchiveFlag(boolean archiveFlag, Pageable pageable);
// /**
// * Query that retrieves a list of IDevId certificates using the provided subject.
// *
// * @param subject string representation of the subject
// * @return a list of IDevId certificates
// */
// List<IDevIDCertificate> findBySubject(String subject);
//
// /**
// * Query that retrieves a sorted list of IDevId certificates using the provided subject.
// *
// * @param subject string representation of the subject
// * @return a sorted list of IDevId certificates
// */
// List<IDevIDCertificate> findBySubjectSorted(String subject);
//
// /**
// * Query that retrieves a list of IDevId certificates using the provided subject and archive flag.
// *
// * @param subject string representation of the subject
// * @param archiveFlag archive flag
// * @return a list of IDevId certificates
// */
// List<IDevIDCertificate> findBySubjectAndArchiveFlag(String subject, boolean archiveFlag);
//
// /**
// * Query that retrieves a sorted list of IDevId certificates using the provided subject
// * and archive flag.
// *
// * @param subject string representation of the subject
// * @param archiveFlag archive flag
// * @return a sorted list of IDevId certificates
// */
// List<IDevIDCertificate> findBySubjectSortedAndArchiveFlag(String subject, boolean archiveFlag);
//
// /**
// * Query that retrieves an IDevId certificate using the provided subject key identifier.
// *
// * @param subjectKeyIdentifier byte representation of the subject key identifier
// * @return an IDevId certificate
// */
// IDevIDCertificate findBySubjectKeyIdentifier(byte[] subjectKeyIdentifier);
//
// /**
// * Query that retrieves an IDevId certificate using the provided subject key and archive flag.
// *
// * @param subjectKeyIdString string representation of the subject key id
// * @param archiveFlag archive flag
// * @return an IDevId certificate
// */
// IDevIDCertificate findBySubjectKeyIdStringAndArchiveFlag(String subjectKeyIdString,
// boolean archiveFlag);
}

View File

@ -12,7 +12,29 @@ import java.util.UUID;
@Repository
public interface IssuedCertificateRepository extends JpaRepository<IssuedAttestationCertificate, UUID> {
/**
* Query that retrieves a list of issued attestation certificates using the provided archive flag.
*
* @param archiveFlag archive flag
* @return a list of issued attestation certificates
*/
List<IssuedAttestationCertificate> findByArchiveFlag(boolean archiveFlag);
/**
* Query that retrieves a page of issued attestation certificates using the provided archive flag
* and pageable value.
*
* @param archiveFlag archive flag
* @param pageable pageable value
* @return a page of issued attestation certificates
*/
Page<IssuedAttestationCertificate> findByArchiveFlag(boolean archiveFlag, Pageable pageable);
/**
* Query that retrieves a list of issued attestation certificates using the provided device id.
*
* @param deviceId uuid representation of the device id
* @return a list of issued attestation certificates
*/
List<IssuedAttestationCertificate> findByDeviceId(UUID deviceId);
}

View File

@ -12,7 +12,29 @@ import java.util.UUID;
@Repository
public interface PlatformCertificateRepository extends JpaRepository<PlatformCredential, UUID> {
/**
* Query that retrieves a list of platform credentials using the provided archive flag.
*
* @param archiveFlag archive flag
* @return a list of platform credentials
*/
List<PlatformCredential> findByArchiveFlag(boolean archiveFlag);
/**
* Query that retrieves a page of platform credentials using the provided archive flag
* and pageable value.
*
* @param archiveFlag archive flag
* @param pageable pageable
* @return a page of platform credentials
*/
Page<PlatformCredential> findByArchiveFlag(boolean archiveFlag, Pageable pageable);
/**
* Query that retrieves a list of platform credentials using the provided device id.
*
* @param deviceId uuid representation of the device id
* @return a list of platform credentials
*/
List<PlatformCredential> findByDeviceId(UUID deviceId);
}

View File

@ -8,5 +8,12 @@ import java.util.UUID;
@Repository
public interface PolicyRepository extends JpaRepository<PolicySettings, UUID> {
/**
* Query that retrieves policy settings using the provided name.
*
* @param name name
* @return policy settings
*/
PolicySettings findByName(String name);
}

View File

@ -10,10 +10,52 @@ import java.util.UUID;
@Repository
public interface ReferenceDigestValueRepository extends JpaRepository<ReferenceDigestValue, UUID> {
/**
* Query that retrieves a list of reference digest values using the provided model.
*
* @param model string representation of the model
* @return a list of reference digest values
*/
List<ReferenceDigestValue> findByModel(String model);
/**
* Query that retrieves a list of reference digest values using the provided manufacturer.
*
* @param manufacturer string representation of the manufacturer
* @return a list of reference digest values
*/
List<ReferenceDigestValue> findByManufacturer(String manufacturer);
/**
* Query that retrieves a list of reference digest values using the provided associated rim id.
*
* @param associatedRimId uuid representation of the associated rim ID
* @return a list of reference digest values
*/
List<ReferenceDigestValue> findValuesByBaseRimId(UUID associatedRimId);
/**
* Query that retrieves a list of reference digest values using the provided support rim id.
*
* @param supportRimId uuid representation of the support rim ID
* @return a list of reference digest values
*/
List<ReferenceDigestValue> findBySupportRimId(UUID supportRimId);
/**
* Query that retrieves a list of reference digest values using the provided support rim hash.
*
* @param supportRimHash a string representation of the support rim hash
* @return a list of reference digest values
*/
List<ReferenceDigestValue> findBySupportRimHash(String supportRimHash);
/**
* Query that retrieves a list of reference digest values using the provided manufacturer and model.
*
* @param manufacturer string representation of the manufacturer
* @param model string representation of the model
* @return a list of reference digest values
*/
List<ReferenceDigestValue> findByManufacturerAndModel(String manufacturer, String model);
}

View File

@ -15,36 +15,193 @@ import java.util.UUID;
@Repository
public interface ReferenceManifestRepository extends JpaRepository<ReferenceManifest, UUID> {
/**
* Query that retrieves a reference manifest using the provided hex/dec hash.
*
* @param hexDecHash string representation of the hex dec hash
* @return a reference manifest
*/
ReferenceManifest findByHexDecHash(String hexDecHash);
/**
* Query that retrieves a reference manifest using the provided base 64 hash.
*
* @param base64Hash string representation of the base 64 hash
* @return a reference manifest
*/
ReferenceManifest findByBase64Hash(String base64Hash);
/**
* Query that retrieves a reference manifest using the provided hex/dec hash and rim type.
*
* @param hexDecHash string representation of the hex dec hash
* @param rimType string representation of the rim type
* @return a reference manifest
*/
ReferenceManifest findByHexDecHashAndRimType(String hexDecHash, String rimType);
/**
* Query that retrieves a reference manifest using the provided event log hash and rim type.
*
* @param hexDecHash string representation of the event log hash
* @param rimType string representation of the rim type
* @return a reference manifest
*/
ReferenceManifest findByEventLogHashAndRimType(String hexDecHash, String rimType);
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformManufacturer = ?1 AND platformModel = ?2 AND rimType = 'Base'", nativeQuery = true)
/**
* Query that retrieves a list of base reference manifests using the provided manufacturer and model
* and where the rim type is equal to base.
*
* @param manufacturer string representation of platform manufacturer
* @param model string representation of platform model
* @return a list of base reference manifests
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformManufacturer = ?1 AND platformModel = ?2 "
+ "AND rimType = 'Base'", nativeQuery = true)
List<BaseReferenceManifest> getBaseByManufacturerModel(String manufacturer, String model);
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformManufacturer = ?1 AND DTYPE = ?2", nativeQuery = true)
/**
* Query that retrieves a list of base reference manifests using the provided manufacturer and model.
*
* @param manufacturer string representation of platform manufacturer
* @param dType dtype
* @return a list of base reference manifests
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformManufacturer = ?1 AND DTYPE = ?2",
nativeQuery = true)
List<BaseReferenceManifest> getByManufacturer(String manufacturer, String dType);
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformModel = ?1 AND DTYPE = ?2", nativeQuery = true)
/**
* Query that retrieves a reference manifest using the provided model and dtype.
*
* @param model string representation of platform model
* @param dType dtype
* @return a reference manifest
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformModel = ?1 AND DTYPE = ?2",
nativeQuery = true)
ReferenceManifest getByModel(String model, String dType);
@Query(value = "SELECT * FROM ReferenceManifest WHERE DTYPE = 'BaseReferenceManifest'", nativeQuery = true)
/**
* Query that retrieves a list of base reference manifests where the dtype is a base reference manifest.
*
* @return a list of base reference manifests
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE DTYPE = 'BaseReferenceManifest'",
nativeQuery = true)
List<BaseReferenceManifest> findAllBaseRims();
@Query(value = "SELECT * FROM ReferenceManifest WHERE DTYPE = 'SupportReferenceManifest'", nativeQuery = true)
/**
* Query that retrieves a list of support reference manifests where the dtype is a
* support reference manifest.
*
* @return a list of support reference manifests
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE DTYPE = 'SupportReferenceManifest'",
nativeQuery = true)
List<SupportReferenceManifest> findAllSupportRims();
@Query(value = "SELECT * FROM ReferenceManifest WHERE id = ?1 AND DTYPE = 'BaseReferenceManifest'", nativeQuery = true)
/**
* Query that retrieves a base reference manifest using the provided uuid and where the dtype is a
* base reference manifest.
*
* @param uuid uuid
* @return a base reference manifest
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE id = ?1 AND DTYPE = 'BaseReferenceManifest'",
nativeQuery = true)
BaseReferenceManifest getBaseRimEntityById(UUID uuid);
@Query(value = "SELECT * FROM ReferenceManifest WHERE id = ?1 AND DTYPE = 'SupportReferenceManifest'", nativeQuery = true)
/**
* Query that retrieves a support reference manifest using the provided uuid and
* where the dtype is a support reference manifest.
*
* @param uuid uuid
* @return a support reference manifest
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE id = ?1 AND DTYPE = 'SupportReferenceManifest'",
nativeQuery = true)
SupportReferenceManifest getSupportRimEntityById(UUID uuid);
@Query(value = "SELECT * FROM ReferenceManifest WHERE id = ?1 AND DTYPE = 'EventLogMeasurements'", nativeQuery = true)
/**
* Query that retrieves event log measurements using the provided uuid and where the dtype is an
* event log measurement.
*
* @param uuid uuid
* @return event log measurements
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE id = ?1 AND DTYPE = 'EventLogMeasurements'",
nativeQuery = true)
EventLogMeasurements getEventLogRimEntityById(UUID uuid);
@Query(value = "SELECT * FROM ReferenceManifest WHERE deviceName = ?1 AND DTYPE = 'SupportReferenceManifest'", nativeQuery = true)
/**
* Query that retrieves a list of support reference manifests using the provided device name and where the
* dtype is a support reference manifest.
*
* @param deviceName string representation of the device name
* @return a list of support reference manifests
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE deviceName = ?1 "
+ "AND DTYPE = 'SupportReferenceManifest'", nativeQuery = true)
List<SupportReferenceManifest> byDeviceName(String deviceName);
@Query(value = "SELECT * FROM ReferenceManifest WHERE deviceName = ?1 AND DTYPE = 'EventLogMeasurements'", nativeQuery = true)
/**
* Query that retrieves event log measurements using the provided device name and where the dtype is
* event log measurements.
*
* @param deviceName string representation of the device name
* @return event log measurements
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE deviceName = ?1 "
+ "AND DTYPE = 'EventLogMeasurements'", nativeQuery = true)
EventLogMeasurements byMeasurementDeviceName(String deviceName);
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformManufacturer = ?1 AND platformModel = ?2 AND rimType = 'Support'", nativeQuery = true)
/**
* Query that retrieves a list of support reference manifests using the provided manufacturer and platform
* model and where the rim type is support.
*
* @param manufacturer string representation of platform manufacturer
* @param model string representation of platform model
* @return a list of support reference manifests
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformManufacturer = ?1 AND platformModel = ?2 "
+ "AND rimType = 'Support'", nativeQuery = true)
List<SupportReferenceManifest> getSupportByManufacturerModel(String manufacturer, String model);
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformModel = ?1 AND DTYPE = 'EventLogMeasurements'", nativeQuery = true)
/**
* Query that retrieves event log measurements using the provided platform model and where the dtype is
* event log measurements.
*
* @param model string representation of platform model.
* @return event log measurements
*/
@Query(value = "SELECT * FROM ReferenceManifest WHERE platformModel = ?1 "
+ "AND DTYPE = 'EventLogMeasurements'", nativeQuery = true)
EventLogMeasurements getLogByModel(String model);
/**
* Query that retrieves a list of reference manifests using the provided device name.
*
* @param deviceName string representation of device name
* @return a list of reference manifests
*/
List<ReferenceManifest> findByDeviceName(String deviceName);
/**
* Query that retrieves a list of reference manifests using the provided archive flag.
*
* @param archiveFlag archive flag
* @return a list of reference manifests
*/
List<ReferenceManifest> findByArchiveFlag(boolean archiveFlag);
/**
* Query that retrieves a page of reference manifests using the provided archive flag and pageable value.
*
* @param archiveFlag archive flag
* @param pageable pageable
* @return a page of reference manifests
*/
Page<ReferenceManifest> findByArchiveFlag(boolean archiveFlag, Pageable pageable);
}

View File

@ -9,6 +9,19 @@ import java.util.UUID;
@Repository
public interface SupplyChainValidationRepository extends JpaRepository<SupplyChainValidation, UUID> {
/**
* Query that retrieves a list of supply chain validation using the provided validate type.
*
* @param validateType string representation of the validate type
* @return a list of supply chain validation
*/
List<SupplyChainValidation> findByValidationType(String validateType);
/**
* Query that retrieves a list of supply chain validation using the provided validation result.
*
* @param validationResult string representation of the validation result
* @return a list of supply chain validation
*/
List<SupplyChainValidation> findByValidationResult(String validationResult);
}

View File

@ -7,12 +7,34 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.UUID;
import java.util.List;
import java.util.UUID;
@Repository
public interface SupplyChainValidationSummaryRepository extends JpaRepository<SupplyChainValidationSummary, UUID> {
public interface SupplyChainValidationSummaryRepository
extends JpaRepository<SupplyChainValidationSummary, UUID> {
/**
* Query that retrieves a supply chain validation summary using the provided device.
*
* @param device device
* @return a supply chain validation summary
*/
SupplyChainValidationSummary findByDevice(Device device);
/**
* Query that retrieves a list of supply chain validation summaries where the archive flag is false.
*
* @return a list of supply chain validation summary
*/
List<SupplyChainValidationSummary> findByArchiveFlagFalse();
/**
* Query that retrieves a page of supply chain validation summaries using the provided pageable value
* and where the archive flag is false.
*
* @param pageable pageable
* @return a page of supply chain validation summary
*/
Page<SupplyChainValidationSummary> findByArchiveFlagFalse(Pageable pageable);
}

View File

@ -7,5 +7,11 @@ import org.springframework.stereotype.Repository;
@Repository
public interface TPM2ProvisionerStateRepository extends JpaRepository<TPM2ProvisionerState, Long> {
/**
* Query that retrieves the TPM2 Provisioner State using the provided first part of nonce.
*
* @param findByFirstPartOfNonce long representation of the first part of nonce
* @return TPM2 Provisioner State
*/
TPM2ProvisionerState findByFirstPartOfNonce(Long findByFirstPartOfNonce);
}

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.entity.manager;

View File

@ -35,7 +35,7 @@ public class TPM2ProvisionerState {
private byte[] identityClaim;
@Column(nullable = false)
private Date timestamp = new Date();
private final Date timestamp = new Date();
/**
* Constructor.
@ -69,24 +69,6 @@ public class TPM2ProvisionerState {
}
}
/**
* Get the nonce.
*
* @return the nonce
*/
public byte[] getNonce() {
return Arrays.clone(nonce);
}
/**
* Get the identity claim.
*
* @return the identity claim
*/
public byte[] getIdentityClaim() {
return Arrays.clone(identityClaim);
}
/**
* Convenience method for finding the {@link TPM2ProvisionerState} associated with the nonce.
*
@ -114,4 +96,22 @@ public class TPM2ProvisionerState {
}
return null;
}
/**
* Get the nonce.
*
* @return the nonce
*/
public byte[] getNonce() {
return Arrays.clone(nonce);
}
/**
* Get the identity claim.
*
* @return the identity claim
*/
public byte[] getIdentityClaim() {
return Arrays.clone(identityClaim);
}
}

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.entity.tpm;

View File

@ -18,13 +18,11 @@ import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.DLSequence;
import org.bouncycastle.asn1.DLTaggedObject;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AccessDescription;
@ -79,24 +77,6 @@ import java.util.Objects;
@Entity
public abstract class Certificate extends ArchivableEntity {
/**
* Holds the different certificate types.
*/
public enum CertificateType {
/**
* Basic X509 Certificate.
*/
X509_CERTIFICATE,
/**
* Basic Attribute Certificate.
*/
ATTRIBUTE_CERTIFICATE,
/**
* Invalid Certificate.
*/
INVALID_CERTIFICATE
}
/**
* Decimal digit representation of base 16.
*/
@ -106,6 +86,7 @@ public abstract class Certificate extends ArchivableEntity {
* Min length representing the attribute certificate.
*/
public static final int MIN_ATTR_CERT_LENGTH = 8;
/**
* Holds the name of the entity 'ID' field.
*/
@ -120,52 +101,78 @@ public abstract class Certificate extends ArchivableEntity {
* Holds the name of the 'serialNumber' field.
*/
public static final String SERIAL_NUMBER_FIELD = "serialNumber";
@Getter
@Column(nullable = false, precision = CertificateVariables.MAX_NUMERIC_PRECISION, scale = 0)
private final BigInteger serialNumber;
/**
* Holds the name of the 'issuer' field.
*/
public static final String ISSUER_FIELD = "issuer";
@Getter
@Column(nullable = false)
private final String issuer;
/**
* Holds the name of the 'issuerSorted' field.
*/
public static final String ISSUER_SORTED_FIELD = "issuerSorted";
@Getter
@Column
private final String issuerSorted;
/**
* Holds the name of the 'subject' field.
*/
public static final String SUBJECT_FIELD = "subject";
@Getter
@Column(nullable = true)
private final String subject;
/**
* Holds the name of the 'subjectSorted' field.
*/
public static final String SUBJECT_SORTED_FIELD = "subjectSorted";
@Getter
@Column
private final String subjectSorted;
/**
* Holds the name of the 'encodedPublicKey' field.
*/
public static final String ENCODED_PUBLIC_KEY_FIELD = "encodedPublicKey";
@Column(length = CertificateVariables.MAX_CERT_LENGTH_BYTES, nullable = true)
private final byte[] encodedPublicKey;
/**
* Holds the name of the 'encodedPublicKey' field.
*/
public static final String PUBLIC_KEY_MODULUS_FIELD = "publicKeyModulusHexValue";
/**
* Holds the name of the 'certificateHash' field.
*/
public static final String CERTIFICATE_HASH_FIELD = "certificateHash";
/**
* Holds the name of the 'holderSerialNumber' field.
*/
public static final String HOLDER_SERIAL_NUMBER_FIELD = "holderSerialNumber";
/**
* Holds the name of the 'authorityKeyIdentifier' field.
*/
public static final String AUTHORITY_KEY_ID_FIELD = "authorityKeyIdentifier";
@SuppressWarnings("PMD.AvoidUsingHardCodedIP") // this is not an IP address; PMD thinks it is
private static final String POLICY_CONSTRAINTS = "2.5.29.36";
@Getter
@Column(nullable = false, precision = CertificateVariables.MAX_NUMERIC_PRECISION, scale = 0)
private final BigInteger serialNumber;
@Getter
@Column(nullable = false)
private final String issuer;
@Getter
@Column
private final String issuerSorted;
@Getter
@Column
private final String subject;
@Getter
@Column
private final String subjectSorted;
@Column(length = CertificateVariables.MAX_CERT_LENGTH_BYTES)
private final byte[] encodedPublicKey;
// We're currently seeing 2048-bit keys, which is 512 hex digits.
// Using a max length of 1024 for future-proofing.
@Getter
@ -181,16 +188,9 @@ public abstract class Certificate extends ArchivableEntity {
@Column(nullable = false)
private final Date endValidity;
@Column(length = CertificateVariables.MAX_CERT_LENGTH_BYTES*CertificateVariables.KEY_USAGE_BIT4, nullable = false)
@JsonIgnore
private byte[] certificateBytes;
/**
* Holds the name of the 'certificateHash' field.
*/
public static final String CERTIFICATE_HASH_FIELD = "certificateHash";
@Column(nullable = false)
@JsonIgnore @Getter
@JsonIgnore
@Getter
private final int certificateHash;
/**
@ -202,42 +202,48 @@ public abstract class Certificate extends ArchivableEntity {
@JsonIgnore
private final int certAndTypeHash;
/**
* Holds the name of the 'holderSerialNumber' field.
*/
public static final String HOLDER_SERIAL_NUMBER_FIELD = "holderSerialNumber";
@Getter
@Column(nullable = false, precision = CertificateVariables.MAX_NUMERIC_PRECISION)
private final BigInteger holderSerialNumber;
@Getter
@Column(nullable = false, precision = CertificateVariables.MAX_NUMERIC_PRECISION, scale = 0)
private final BigInteger holderSerialNumber;
@Getter
private String holderIssuer;
@Getter
@Column(nullable = true, precision = CertificateVariables.MAX_NUMERIC_PRECISION, scale = 0)
@Column(precision = CertificateVariables.MAX_NUMERIC_PRECISION)
private final BigInteger authoritySerialNumber;
@SuppressWarnings("PMD.AvoidUsingHardCodedIP") // this is not an IP address; PMD thinks it is
private static final String POLICY_CONSTRAINTS = "2.5.29.36";
@Column(length = CertificateVariables.MAX_CERT_LENGTH_BYTES * CertificateVariables.KEY_USAGE_BIT4,
nullable = false)
@JsonIgnore
private byte[] certificateBytes;
@Getter
private String holderIssuer;
// we don't need to persist this, but we don't want to unpack this cert multiple times
@Transient
private X509Certificate parsedX509Cert = null;
@Getter
private String signatureAlgorithm, publicKeyAlgorithm;
private String signatureAlgorithm;
@Getter
private String keyUsage, extendedKeyUsage;
private String publicKeyAlgorithm;
@Getter
private String keyUsage;
@Getter
private String extendedKeyUsage;
private byte[] policyConstraints;
/**
* Holds the name of the 'authorityKeyIdentifier' field.
*/
public static final String AUTHORITY_KEY_ID_FIELD = "authorityKeyIdentifier";
@Getter
private String authorityKeyIdentifier;
@Getter
private String authorityInfoAccess;
@Getter
private String crlPoints;
@Getter
private int publicKeySize;
@ -291,7 +297,7 @@ public abstract class Certificate extends ArchivableEntity {
* @param certificateBytes the contents of a certificate file
* @throws IOException if there is a problem extracting information from the certificate
*/
@SuppressWarnings("methodlength")
public Certificate(final byte[] certificateBytes) throws IOException {
Preconditions.checkArgument(
certificateBytes != null,
@ -342,7 +348,7 @@ public abstract class Certificate extends ArchivableEntity {
this.policyConstraints = x509Certificate
.getExtensionValue(POLICY_CONSTRAINTS);
authKeyIdentifier = AuthorityKeyIdentifier
.getInstance((DLSequence) getExtensionValue(
.getInstance(getExtensionValue(
Extension.authorityKeyIdentifier.getId()));
this.authorityInfoAccess = getAuthorityInfoAccess(x509Certificate
@ -460,12 +466,167 @@ public abstract class Certificate extends ArchivableEntity {
this.certAndTypeHash = Objects.hash(certificateHash, getClass().getSimpleName());
}
/**
* Gets the raw bytes for the certificate.
*
* @param certificatePath path to the certificate file
* @return bytes from the certificate file
* @throws IOException if there is a problem reading the file
*/
public static byte[] readBytes(final Path certificatePath) throws IOException {
Preconditions.checkArgument(
certificatePath != null,
"Cannot construct a Certificate from a null path"
);
return Files.readAllBytes(certificatePath);
}
/**
* Retrieve a formatted subject DN string from a certificate. This allows for extended support of DNs
* found in various RFCs.
*
* @param certificate the certificate holding subject DNs
* @return IOException if there is an issue decoding the subject DNs
*/
public static String getSubjectDNString(final X509Certificate certificate)
throws IOException {
X509CertificateHolder certificateHolder = null;
try {
certificateHolder = new X509CertificateHolder(certificate.getEncoded());
} catch (CertificateEncodingException e) {
throw new IOException("Could not encode certificate", e);
}
X500Name x500Name = certificateHolder.getSubject();
return x500Name.toString();
}
/**
* Retrieve a formatted issuer DN string from a certificate. This allows for extended support of DNs found
* in various RFCs.
*
* @param certificate the certificate holding issuer DNs
* @return IOException if there is an issue decoding the issuer DNs
*/
public static String getIssuerDNString(final X509Certificate certificate)
throws IOException {
X509CertificateHolder certificateHolder = null;
try {
certificateHolder = new X509CertificateHolder(certificate.getEncoded());
} catch (CertificateEncodingException e) {
throw new IOException("Could not encode certificate", e);
}
X500Name x500Name = certificateHolder.getIssuer();
return x500Name.toString();
}
/**
* Retrieve an RSA-based X509 certificate's public key modulus.
*
* @param certificate the certificate holding a public key
* @return a BigInteger representing its public key's modulus or null if none found
* @throws IOException if there is an issue decoding the encoded public key
*/
public static BigInteger getPublicKeyModulus(final X509Certificate certificate)
throws IOException {
X509CertificateHolder certificateHolder = null;
try {
certificateHolder = new X509CertificateHolder(certificate.getEncoded());
} catch (CertificateEncodingException e) {
throw new IOException("Could not encode certificate", e);
}
try {
return getPublicKeyModulus(
certificateHolder.getSubjectPublicKeyInfo().parsePublicKey().toASN1Primitive()
);
} catch (IOException e) {
log.info("No RSA Key Detected in certificate");
return null;
}
}
/**
* Retrieves the modulus of the given PublicKey.
*
* @param publicKey the public key
* @return a BigInteger representing the public key's modulus
* @throws IOException if there is an issue decoding the public key
*/
public static BigInteger getPublicKeyModulus(final PublicKey publicKey) throws IOException {
ASN1Primitive publicKeyASN1 = ASN1Primitive.fromByteArray(publicKey.getEncoded());
if (publicKeyASN1 instanceof ASN1Sequence publicKeyASN1Sequence) {
ASN1BitString encodedModulusAndExponent = (ASN1BitString)
publicKeyASN1Sequence.getObjectAt(1);
byte[] modulusAndExponentBytes = encodedModulusAndExponent.getOctets();
return getPublicKeyModulus(ASN1Primitive.fromByteArray(modulusAndExponentBytes));
} else {
throw new IOException("Could not read public key as ASN1Sequence");
}
}
private static BigInteger getPublicKeyModulus(final ASN1Primitive publicKey)
throws IOException {
if (publicKey instanceof ASN1Sequence pubKeySeq) {
ASN1Encodable modulus = pubKeySeq.getObjectAt(0);
if (modulus instanceof ASN1Integer) {
return ((ASN1Integer) modulus).getValue();
} else {
throw new IOException("Could not read modulus as an ASN1Integer");
}
} else {
throw new IOException("Could not parse public key information as an ASN1Sequence");
}
}
/**
* Retrieve the X509 Name array from the issuer in an Attribute Certificate.
*
* @param issuer for the Attribute Certificate
* @return a X500Name[] representing the names of the issuer
*/
public static X500Name[] getAttributeCertificateIssuerNames(final AttCertIssuer issuer) {
final ASN1Encodable form = issuer.getIssuer();
GeneralNames name;
if (form instanceof V2Form) {
name = ((V2Form) form).getIssuerName();
} else {
name = (GeneralNames) form;
}
GeneralName[] names = name.getNames();
List<X500Name> l = new ArrayList<>(names.length);
for (int i = 0; i != names.length; i++) {
if (names[i].getTagNo() == GeneralName.directoryName) {
l.add(X500Name.getInstance(names[i].getName()));
}
}
return l.toArray(new X500Name[l.size()]);
}
/**
* Retrieve the Date from an ASN1GeneralizedTime.
*
* @param time (ASN1GeneralizedTime) of the certificate
* @return the Date from a ASN1GeneralizedTime
*/
public static Date recoverDate(final ASN1GeneralizedTime time) {
try {
return time.getDate();
} catch (ParseException e) {
throw new IllegalStateException("unable to recover date: " + e.getMessage());
}
}
/**
* Getter for the CRL Distribution that is reference by the Revocation Locator
* on the portal.
*
* @return A list of URLs that inform the location of the certificate revocation lists
* @throws java.io.IOException
* @throws IOException if there is an issue while retrieving the CRL Distribution point
*/
private String getCRLDistributionPoint() throws IOException {
List<String> crlUrls = new ArrayList<>();
@ -502,6 +663,7 @@ public abstract class Certificate extends ArchivableEntity {
/**
* Getter for the x509 Platform Certificate version.
*
* @return a big integer representing the certificate version. If there
* is an error, return the max value to visible show error.
*/
@ -564,7 +726,7 @@ public abstract class Certificate extends ArchivableEntity {
}
/**
* Return whether or not this certificate is valid on a particular date.
* Return whether this certificate is valid on a particular date.
*
* @param date the date of interest.
* @return true if the attribute certificate is valid, false otherwise.
@ -601,7 +763,7 @@ public abstract class Certificate extends ArchivableEntity {
protected CertificateType getCertificateType() throws IOException {
//Parse the certificate into a sequence
ASN1Sequence testCred1 = (ASN1Sequence) ASN1Primitive.fromByteArray(this.certificateBytes);
ASN1Sequence testSeq = (ASN1Sequence) ((ASN1Object) testCred1.toArray()[0]);
ASN1Sequence testSeq = (ASN1Sequence) testCred1.toArray()[0];
if (testSeq.toArray()[0] instanceof ASN1Integer) {
if (testSeq.toArray().length >= MIN_ATTR_CERT_LENGTH) {
@ -611,7 +773,8 @@ public abstract class Certificate extends ArchivableEntity {
// V1 X509Certificate
return CertificateType.X509_CERTIFICATE;
}
} else if (testSeq.toArray()[0] instanceof DERTaggedObject || testSeq.toArray()[0] instanceof DLTaggedObject) {
} else if (testSeq.toArray()[0] instanceof DERTaggedObject
|| testSeq.toArray()[0] instanceof DLTaggedObject) {
// V2 or V3 X509Certificate
return CertificateType.X509_CERTIFICATE;
}
@ -619,7 +782,6 @@ public abstract class Certificate extends ArchivableEntity {
return CertificateType.INVALID_CERTIFICATE;
}
private String parseKeyUsage(final boolean[] bools) {
StringBuilder sb = new StringBuilder();
@ -636,6 +798,8 @@ public abstract class Certificate extends ArchivableEntity {
/**
* Getter for the authorityKeyIdentifier.
*
* @param aki authority key identifier
* @return the ID's byte representation
*/
private String authKeyIdentifierToString(final AuthorityKeyIdentifier aki) {
@ -655,7 +819,7 @@ public abstract class Certificate extends ArchivableEntity {
*
* @param oid Object Identifier
* @return ASN1Primitive Content related to the requested OID
* @throws java.io.IOException
* @throws IOException io exception
*/
private ASN1Primitive getExtensionValue(final String oid) throws IOException {
byte[] extensionValue = getX509Certificate().getExtensionValue(oid);
@ -684,6 +848,7 @@ public abstract class Certificate extends ArchivableEntity {
/**
* Getter for the AuthorityInfoAccess extension value on list format.
*
* @param authInfoAccess byte representation of the authority info access
* @return List Authority info access list
*/
private String getAuthorityInfoAccess(final byte[] authInfoAccess) {
@ -704,6 +869,7 @@ public abstract class Certificate extends ArchivableEntity {
/**
* Getter for the AuthorityInfoAccess extension value on list format.
*
* @param authInfoAccess authority information access
* @return List Authority info access list
*/
private String getAuthorityInfoAccess(final AuthorityInformationAccess authInfoAccess) {
@ -724,7 +890,6 @@ public abstract class Certificate extends ArchivableEntity {
return sb.toString();
}
/**
* Retrieve the original X509 attribute certificate.
*
@ -773,6 +938,7 @@ public abstract class Certificate extends ArchivableEntity {
/**
* Getter for the policy statement.
*
* @return cloned bit representation of constraints
*/
public byte[] getPolicyConstraints() {
@ -806,6 +972,11 @@ public abstract class Certificate extends ArchivableEntity {
return null;
}
/**
* Creates a string representation of the Certificate object.
*
* @return a string representation of the Certificate object.
*/
@Override
public String toString() {
return String.format("Certificate{%s, AuthID=%s, serialNumber=%s, "
@ -816,6 +987,13 @@ public abstract class Certificate extends ArchivableEntity {
signatureAlgorithm, certificateHash);
}
/**
* Compares this certificate to the provided object to verify that both this and the provided certificate
* objects are equal.
*
* @param o object to compare
* @return true if both the provided certificate and this certificate are equal, false otherwise
*/
@Override
public boolean equals(final Object o) {
if (this == o) {
@ -831,165 +1009,31 @@ public abstract class Certificate extends ArchivableEntity {
return Arrays.equals(certificateBytes, that.certificateBytes);
}
/**
* Creates an integer hash code for this Certificate object.
*
* @return integer hash code
*/
@Override
public int hashCode() {
return Arrays.hashCode(certificateBytes);
}
/**
*
* Gets the raw bytes for the certificate.
* @param certificatePath path to the certificate file
* @return bytes from the certificate file
* @throws IOException if there is a problem reading the file
* Holds the different certificate types.
*/
public static byte[] readBytes(final Path certificatePath) throws IOException {
Preconditions.checkArgument(
certificatePath != null,
"Cannot construct a Certificate from a null path"
);
return Files.readAllBytes(certificatePath);
}
public enum CertificateType {
/**
* Retrieve a formatted subject DN string from a certificate. This allows for extended support of DNs found in
* various RFCs.
*
* @param certificate the certificate holding subject DNs
* @return IOException if there is an issue decoding the subject DNs
* Basic X509 Certificate.
*/
public static String getSubjectDNString(final X509Certificate certificate)
throws IOException {
X509CertificateHolder certificateHolder = null;
try {
certificateHolder = new X509CertificateHolder(certificate.getEncoded());
} catch (CertificateEncodingException e) {
throw new IOException("Could not encode certificate", e);
}
X500Name x500Name = certificateHolder.getSubject();
return x500Name.toString();
}
X509_CERTIFICATE,
/**
* Retrieve a formatted issuer DN string from a certificate. This allows for extended support of DNs found in
* various RFCs.
*
* @param certificate the certificate holding issuer DNs
* @return IOException if there is an issue decoding the issuer DNs
* Basic Attribute Certificate.
*/
public static String getIssuerDNString(final X509Certificate certificate)
throws IOException {
X509CertificateHolder certificateHolder = null;
try {
certificateHolder = new X509CertificateHolder(certificate.getEncoded());
} catch (CertificateEncodingException e) {
throw new IOException("Could not encode certificate", e);
}
X500Name x500Name = certificateHolder.getIssuer();
return x500Name.toString();
}
ATTRIBUTE_CERTIFICATE,
/**
* Retrieve an RSA-based X509 certificate's public key modulus.
*
* @param certificate the certificate holding a public key
* @return a BigInteger representing its public key's modulus or null if none found
* @throws IOException if there is an issue decoding the encoded public key
* Invalid Certificate.
*/
public static BigInteger getPublicKeyModulus(final X509Certificate certificate)
throws IOException {
X509CertificateHolder certificateHolder = null;
try {
certificateHolder = new X509CertificateHolder(certificate.getEncoded());
} catch (CertificateEncodingException e) {
throw new IOException("Could not encode certificate", e);
}
try {
return getPublicKeyModulus(
certificateHolder.getSubjectPublicKeyInfo().parsePublicKey().toASN1Primitive()
);
} catch (IOException e) {
log.info("No RSA Key Detected in certificate");
return null;
}
}
/**
* Retrieves the modulus of the given PublicKey.
*
* @param publicKey the public key
* @return a BigInteger representing the public key's modulus
* @throws IOException if there is an issue decoding the public key
*/
public static BigInteger getPublicKeyModulus(final PublicKey publicKey) throws IOException {
ASN1Primitive publicKeyASN1 = ASN1Primitive.fromByteArray(publicKey.getEncoded());
if (publicKeyASN1 instanceof ASN1Sequence) {
ASN1Sequence publicKeyASN1Sequence = (ASN1Sequence) publicKeyASN1;
ASN1BitString encodedModulusAndExponent = (ASN1BitString)
publicKeyASN1Sequence.getObjectAt(1);
byte[] modulusAndExponentBytes = encodedModulusAndExponent.getOctets();
return getPublicKeyModulus(ASN1Primitive.fromByteArray(modulusAndExponentBytes));
} else {
throw new IOException("Could not read public key as ASN1Sequence");
}
}
private static BigInteger getPublicKeyModulus(final ASN1Primitive publicKey)
throws IOException {
if (publicKey instanceof ASN1Sequence) {
ASN1Sequence pubKeySeq = (ASN1Sequence) publicKey;
ASN1Encodable modulus = pubKeySeq.getObjectAt(0);
if (modulus instanceof ASN1Integer) {
return ((ASN1Integer) modulus).getValue();
} else {
throw new IOException("Could not read modulus as an ASN1Integer");
}
} else {
throw new IOException("Could not parse public key information as an ASN1Sequence");
}
}
/**
* Retrieve the X509 Name array from the issuer in an Attribute Certificate.
*
* @param issuer for the Attribute Certificate
* @return a X500Name[] representing the names of the issuer
*/
public static X500Name[] getAttributeCertificateIssuerNames(final AttCertIssuer issuer) {
final ASN1Encodable form = issuer.getIssuer();
GeneralNames name;
if (form instanceof V2Form) {
name = ((V2Form) form).getIssuerName();
} else {
name = (GeneralNames) form;
}
GeneralName[] names = name.getNames();
List<X500Name> l = new ArrayList<>(names.length);
for (int i = 0; i != names.length; i++) {
if (names[i].getTagNo() == GeneralName.directoryName) {
l.add(X500Name.getInstance(names[i].getName()));
}
}
return (X500Name[]) l.toArray(new X500Name[l.size()]);
}
/**
* Retrieve the Date from an ASN1GeneralizedTime.
*
* @param time (ASN1GeneralizedTime) of the certificate
* @return the Date from a ASN1GeneralizedTime
*/
public static Date recoverDate(final ASN1GeneralizedTime time) {
try {
return time.getDate();
} catch (ParseException e) {
throw new IllegalStateException("unable to recover date: " + e.getMessage());
}
INVALID_CERTIFICATE
}
}

View File

@ -14,19 +14,20 @@ import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Objects;
@Entity
@Table(name = "Device")
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class Device extends AbstractEntity {
@Getter
@ -34,7 +35,7 @@ public class Device extends AbstractEntity {
private String name;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
optional = true, orphanRemoval = true)
orphanRemoval = true)
private DeviceInfoReport deviceInfo;
@Getter
@ -65,6 +66,11 @@ public class Device extends AbstractEntity {
@Column(name = "summary_id")
private String summaryId;
/**
* Constructor creates a Device object using the provided device info report.
*
* @param deviceInfoReport device information report
*/
public Device(final DeviceInfoReport deviceInfoReport) {
super();
if (deviceInfoReport != null) {
@ -94,6 +100,7 @@ public class Device extends AbstractEntity {
/**
* Getter for the report time stamp.
*
* @return a cloned version
*/
public Timestamp getLastReportTimestamp() {
@ -106,39 +113,22 @@ public class Device extends AbstractEntity {
/**
* Setter for the report time stamp.
* @param lastReportTimestamp
*
* @param lastReportTimestamp last reported time
*/
public void setLastReportTimestamp(final Timestamp lastReportTimestamp) {
this.lastReportTimestamp = (Timestamp) lastReportTimestamp.clone();
}
/**
* Creates a string representation of the Device object.
*
* @return a string representation of the Device object.
*/
@Override
public String toString() {
return String.format("Device Name: %s%nStatus: %s%nSummary: %s%n",
name, (healthStatus == null ? "N/A" : healthStatus.getStatus()),
name, (healthStatus == null ? "N/A" : healthStatus.getHealthStatus()),
(supplyChainValidationStatus == null ? "N/A" : supplyChainValidationStatus.toString()));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Device)) {
return false;
}
Device device = (Device) o;
return isStateOverridden == device.isStateOverridden
&& Objects.equals(name, device.name)
&& healthStatus == device.healthStatus
&& supplyChainValidationStatus == device.supplyChainValidationStatus
&& Objects.equals(lastReportTimestamp, device.lastReportTimestamp)
&& Objects.equals(overrideReason, device.overrideReason)
&& Objects.equals(summaryId, device.summaryId);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), name, healthStatus,
supplyChainValidationStatus, lastReportTimestamp,
isStateOverridden, overrideReason, summaryId);
}
}

View File

@ -23,6 +23,29 @@ import lombok.extern.log4j.Log4j2;
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class ExaminableRecord {
@Getter
@Column(nullable = false)
// Decided on ORDINAL instead of STRING due to concerns surrounding overall size and retrieval
// time of field from database. Consistent with other implementations of ExaminableRecord.
@Enumerated(EnumType.ORDINAL)
private ExamineState examineState = ExamineState.UNEXAMINED;
/**
* Sets the examine state for this record.
*
* @param examineState the examine state
*/
public void setExamineState(final ExamineState examineState) {
if (examineState == ExamineState.UNEXAMINED) {
log.error("Can't set ExamineState on ExaminableRecord to Unexamined");
throw new IllegalArgumentException(
"Can't set ExamineState on ExaminableRecord to Unexamined"
);
}
this.examineState = examineState;
}
/**
* State capturing if a record was examined during appraisal or not.
*/
@ -42,26 +65,4 @@ public abstract class ExaminableRecord {
*/
IGNORED
}
@Getter
@Column(nullable = false)
// Decided on ORDINAL instead of STRING due to concerns surrounding overall size and retrieval
// time of field from database. Consistent with other implementations of ExaminableRecord.
@Enumerated(EnumType.ORDINAL)
private ExamineState examineState = ExamineState.UNEXAMINED;
/**
* Sets the examine state for this record.
* @param examineState the examine state
*/
public void setExamineState(final ExamineState examineState) {
if (examineState == ExamineState.UNEXAMINED) {
log.error("Can't set ExamineState on ExaminableRecord to Unexamined");
throw new IllegalArgumentException(
"Can't set ExamineState on ExaminableRecord to Unexamined"
);
}
this.examineState = examineState;
}
}

View File

@ -105,8 +105,7 @@ public class PolicySettings extends UserDefinedEntity {
/**
* Constructor used to initialize PolicySettings object.
*
* @param name
* A name used to uniquely identify and reference the Supply Chain policy.
* @param name A name used to uniquely identify and reference the Supply Chain policy.
*/
public PolicySettings(final String name) {
super(name);
@ -115,10 +114,8 @@ public class PolicySettings extends UserDefinedEntity {
/**
* Constructor used to initialize PolicySettings 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
* @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 PolicySettings(final String name, final String description) {
super(name, description);

View File

@ -10,6 +10,7 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@ -28,7 +29,9 @@ 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 @ToString
@Getter
@Setter
@ToString
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
@Log4j2
@Entity
@ -72,54 +75,55 @@ public class ReferenceManifest extends ArchivableEntity {
*/
public static final String SCHEMA_PACKAGE = "hirs.utils.xjc";
@Setter(AccessLevel.NONE)
@EqualsAndHashCode.Include
@Column(columnDefinition = "mediumblob", nullable = false)
private byte[] rimBytes;
@Setter
private final byte[] rimBytes;
@EqualsAndHashCode.Include
@Column(nullable = false)
private String rimType = "Base";
@Setter
@Column
private String tagId = null;
@Setter
@Column
private boolean swidPatch = false;
@Setter
@Column
private boolean swidSupplemental = false;
@Setter
@Column
private String platformManufacturer = null;
@Setter
@Column
private String platformManufacturerId = null;
@Setter
@Column
private String swidTagVersion = null;
@Setter
@Column
private String swidVersion = null;
@Setter
@Column
private String platformModel = null;
@Setter
@Column(nullable = false)
private String fileName = null;
@Setter
@JdbcTypeCode(java.sql.Types.VARCHAR)
@Column
private UUID associatedRim;
@Setter
@Column
private String deviceName;
@Setter
@Column
private String hexDecHash = "";
@Setter
@Column
private String eventLogHash = "";
@Setter
@Column
@JsonIgnore
private String base64Hash = "";
@ -141,6 +145,7 @@ public class ReferenceManifest extends ArchivableEntity {
/**
* Default constructor for ingesting the bytes of the file content.
*
* @param rimBytes - file contents.
*/
public ReferenceManifest(final byte[] rimBytes) {
@ -183,10 +188,20 @@ public class ReferenceManifest extends ArchivableEntity {
return null;
}
/**
* Determines if this reference manifest's rim type is a base rim.
*
* @return true if the rim type is a base rim, false otherwise
*/
public boolean isBase() {
return rimType.equals(BASE_RIM);
}
/**
* Determines if this reference manifest's rim type is a support rim.
*
* @return true if the rim type is a support rim, false otherwise
*/
public boolean isSupport() {
return rimType.equals(SUPPORT_RIM);
}

View File

@ -2,7 +2,6 @@ package hirs.attestationca.persist.entity.userdefined;
import com.google.common.base.Preconditions;
import hirs.attestationca.persist.entity.ArchivableEntity;
import hirs.attestationca.persist.entity.userdefined.rim.BaseReferenceManifest;
import hirs.attestationca.persist.enums.AppraisalStatus;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@ -10,6 +9,7 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import lombok.AccessLevel;
import lombok.Getter;
import java.util.ArrayList;
@ -19,51 +19,24 @@ import java.util.List;
/**
* Stores results of a single element of the supply chain validation process.
*/
@Getter
@Entity
public class SupplyChainValidation extends ArchivableEntity {
/**
* Used to indicate which type of validation a result is related to.
*/
public enum ValidationType {
/**
* Validation of an endorsement credential.
*/
ENDORSEMENT_CREDENTIAL,
/**
* Validation of a platform credential and also delta platform credentials from spec 1.1.
*/
PLATFORM_CREDENTIAL,
/**
* Validation of a platform credential's attributes.
*/
PLATFORM_CREDENTIAL_ATTRIBUTES,
/**
* Validation of the device firmware.
*/
FIRMWARE
}
@Getter
@Column
private final ValidationType validationType;
@Getter
@Column
private final AppraisalStatus.Status validationResult;
@Getter(AccessLevel.NONE)
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "CertificatesUsedToValidate",
joinColumns = {@JoinColumn(name = "validation_id", nullable = false)})
private final List<Certificate> certificatesUsed;
@Getter
@Column(length = RESULT_MESSAGE_LENGTH)
private final String message;
@Getter
@Column
private String rimId;
@ -122,4 +95,29 @@ public class SupplyChainValidation extends ArchivableEntity {
public List<Certificate> getCertificatesUsed() {
return Collections.unmodifiableList(certificatesUsed);
}
/**
* Used to indicate which type of validation a result is related to.
*/
public enum ValidationType {
/**
* Validation of an endorsement credential.
*/
ENDORSEMENT_CREDENTIAL,
/**
* Validation of a platform credential and also delta platform credentials from spec 1.1.
*/
PLATFORM_CREDENTIAL,
/**
* Validation of a platform credential's attributes.
*/
PLATFORM_CREDENTIAL_ATTRIBUTES,
/**
* Validation of the device firmware.
*/
FIRMWARE
}
}

View File

@ -32,7 +32,6 @@ import java.util.Set;
import java.util.UUID;
/**
* A container class to group multiple related {@link SupplyChainValidation} instances
* together.
@ -40,12 +39,10 @@ import java.util.UUID;
@Entity
public class SupplyChainValidationSummary extends ArchivableEntity {
private static final String DEVICE_ID_FIELD = "device.id";
@ManyToOne
@JoinColumn(name = "device_id")
private final Device device;
private static final String DEVICE_ID_FIELD = "device.id";
@Getter
@Column
@Enumerated(EnumType.STRING)
@ -72,115 +69,6 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
this.message = Strings.EMPTY;
}
/**
* This class enables the retrieval of SupplyChainValidationSummaries by their attributes.
*/
public static class Selector {
private final CrudRepository<SupplyChainValidationSummary, UUID>
supplyChainValidationSummaryCrudManager;
private final Map<String, Object> fieldValueSelections;
/**
* Construct a new Selector that will use the given {@link CrudRepository} to
* retrieve SupplyChainValidationSummaries.
*
* @param supplyChainValidationSummaryCrudManager the summary manager to be used to retrieve
* supply chain validation summaries
*/
public Selector(
final CrudRepository<SupplyChainValidationSummary, UUID>
supplyChainValidationSummaryCrudManager) {
Preconditions.checkArgument(
supplyChainValidationSummaryCrudManager != null,
"supply chain validation summary manager cannot be null"
);
this.supplyChainValidationSummaryCrudManager = supplyChainValidationSummaryCrudManager;
this.fieldValueSelections = new HashMap<>();
}
/**
* Construct the criterion that can be used to query for supply chain validation summaries
* matching the configuration of this Selector.
*
* @return a Criterion that can be used to query for supply chain validation summaries
* matching the configuration of this instance
*/
public Predicate[] getCriterion(final CriteriaBuilder criteriaBuilder) {
Predicate[] predicates = new Predicate[fieldValueSelections.size()];
CriteriaQuery<SupplyChainValidationSummary> query = criteriaBuilder.createQuery(SupplyChainValidationSummary.class);
Root<SupplyChainValidationSummary> root = query.from(SupplyChainValidationSummary.class);
int i = 0;
for (Map.Entry<String, Object> fieldValueEntry : fieldValueSelections.entrySet()) {
predicates[i++] = criteriaBuilder.equal(root.get(fieldValueEntry.getKey()), fieldValueEntry.getValue());
}
return predicates;
}
/**
* Set a field name and value to match.
*
* @param name the field name to query
* @param value the value to query
*/
protected void setFieldValue(final String name, final Object value) {
Object valueToAssign = value;
Preconditions.checkArgument(
value != null,
"field value cannot be null."
);
if (value instanceof String) {
Preconditions.checkArgument(
StringUtils.isNotEmpty((String) value),
"field value cannot be empty."
);
}
if (value instanceof byte[]) {
byte[] valueBytes = (byte[]) value;
Preconditions.checkArgument(
ArrayUtils.isNotEmpty(valueBytes),
"field value cannot be empty."
);
valueToAssign = Arrays.copyOf(valueBytes, valueBytes.length);
}
fieldValueSelections.put(name, valueToAssign);
}
/**
* Specify a device id that supply chain validation summaries 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 SupplyChainValidationSummary.
*
* @param certMan the CrudManager to be used to retrieve persisted supply chain validation
* summaries
* @return a SupplyChainValidationSummary.Selector instance to use for retrieving certificates
*/
public static SupplyChainValidationSummary.Selector select(
final CrudRepository<SupplyChainValidationSummary, UUID> certMan) {
return new SupplyChainValidationSummary.Selector(certMan);
}
/**
* Construct a new SupplyChainValidationSummary.
*
@ -221,6 +109,18 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
this.message = status.getMessage();
}
/**
* Get a Selector for use in retrieving SupplyChainValidationSummary.
*
* @param certMan the CrudManager to be used to retrieve persisted supply chain validation
* summaries
* @return a SupplyChainValidationSummary.Selector instance to use for retrieving certificates
*/
public static SupplyChainValidationSummary.Selector select(
final CrudRepository<SupplyChainValidationSummary, UUID> certMan) {
return new SupplyChainValidationSummary.Selector(certMan);
}
/**
* This retrieves the device associated with the supply chain validation summaries.
*
@ -270,4 +170,103 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
return new AppraisalStatus(AppraisalStatus.Status.PASS,
Strings.EMPTY);
}
/**
* This class enables the retrieval of SupplyChainValidationSummaries by their attributes.
*/
public static class Selector {
private final CrudRepository<SupplyChainValidationSummary, UUID>
supplyChainValidationSummaryCrudManager;
private final Map<String, Object> fieldValueSelections;
/**
* Construct a new Selector that will use the given {@link CrudRepository} to
* retrieve SupplyChainValidationSummaries.
*
* @param supplyChainValidationSummaryCrudManager the summary manager to be used to retrieve
* supply chain validation summaries
*/
public Selector(
final CrudRepository<SupplyChainValidationSummary, UUID>
supplyChainValidationSummaryCrudManager) {
Preconditions.checkArgument(
supplyChainValidationSummaryCrudManager != null,
"supply chain validation summary manager cannot be null"
);
this.supplyChainValidationSummaryCrudManager = supplyChainValidationSummaryCrudManager;
this.fieldValueSelections = new HashMap<>();
}
/**
* Construct the criterion that can be used to query for supply chain validation summaries
* matching the configuration of this Selector.
*
* @param criteriaBuilder criteria builder
* @return a Criterion that can be used to query for supply chain validation summaries
* matching the configuration of this instance
*/
public Predicate[] getCriterion(final CriteriaBuilder criteriaBuilder) {
Predicate[] predicates = new Predicate[fieldValueSelections.size()];
CriteriaQuery<SupplyChainValidationSummary> query =
criteriaBuilder.createQuery(SupplyChainValidationSummary.class);
Root<SupplyChainValidationSummary> root = query.from(SupplyChainValidationSummary.class);
int i = 0;
for (Map.Entry<String, Object> fieldValueEntry : fieldValueSelections.entrySet()) {
predicates[i++] =
criteriaBuilder.equal(root.get(fieldValueEntry.getKey()), fieldValueEntry.getValue());
}
return predicates;
}
/**
* Set a field name and value to match.
*
* @param name the field name to query
* @param value the value to query
*/
protected void setFieldValue(final String name, final Object value) {
Object valueToAssign = value;
Preconditions.checkArgument(
value != null,
"field value cannot be null."
);
if (value instanceof String) {
Preconditions.checkArgument(
StringUtils.isNotEmpty((String) value),
"field value cannot be empty."
);
}
if (value instanceof byte[] valueBytes) {
Preconditions.checkArgument(
ArrayUtils.isNotEmpty(valueBytes),
"field value cannot be empty."
);
valueToAssign = Arrays.copyOf(valueBytes, valueBytes.length);
}
fieldValueSelections.put(name, valueToAssign);
}
/**
* Specify a device id that supply chain validation summaries 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;
}
}
}

View File

@ -3,6 +3,7 @@ package hirs.attestationca.persist.entity.userdefined.certificate;
import hirs.attestationca.persist.entity.userdefined.Certificate;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import lombok.AccessLevel;
import lombok.Getter;
import org.apache.commons.codec.binary.Hex;
@ -14,36 +15,36 @@ import java.util.Arrays;
* This class persists Certificate Authority credentials by extending the base Certificate
* class with fields unique to CA credentials.
*/
@Getter
@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";
@SuppressWarnings("PMD.AvoidUsingHardCodedIP")
private static final String SUBJECT_KEY_IDENTIFIER_EXTENSION = "2.5.29.14";
private static final int CA_BYTE_SIZE = 20;
private static final int PREFIX_BYTE_SIZE = 4;
@Getter(AccessLevel.NONE)
@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";
@Column
private String subjectKeyIdString;
/**
* Construct a new CertificateAuthorityCredential given its binary contents. The given
* certificate should represent either an X509 certificate or X509 attribute certificate.
@ -111,6 +112,13 @@ public class CertificateAuthorityCredential extends Certificate {
return null;
}
/**
* Helper method that uses the provided certificate bytes and truncates a portion
* of the certificate bytes array.
*
* @param certificateBytes byte array representation of the certificate bytes
* @return a truncated certificate byte array
*/
private byte[] truncatePrefixBytes(final byte[] certificateBytes) {
byte[] temp = new byte[CA_BYTE_SIZE];
System.arraycopy(certificateBytes, PREFIX_BYTE_SIZE, temp, 0, CA_BYTE_SIZE);
@ -118,8 +126,14 @@ public class CertificateAuthorityCredential extends Certificate {
return temp;
}
@Override
@SuppressWarnings("checkstyle:avoidinlineconditionals")
/**
* Compares this Certificate Authority Credential object to another Certificate
* Authority Credential object.
*
* @param o object to compare
* @return true if both this and the provided Certificate Authority Credential objects are equal,
* false otherwise
*/
public boolean equals(final Object o) {
if (this == o) {
return true;
@ -140,12 +154,17 @@ public class CertificateAuthorityCredential extends Certificate {
return Arrays.equals(subjectKeyIdentifier, that.subjectKeyIdentifier);
}
/**
* Creates an integer hash code.
*
* @return an integer hash code
*/
@Override
@SuppressWarnings({"checkstyle:magicnumber", "checkstyle:avoidinlineconditionals"})
public int hashCode() {
final int hashCodeConst = 31;
int result = super.hashCode();
result = 31 * result + (credentialType != null ? credentialType.hashCode() : 0);
result = 31 * result + Arrays.hashCode(subjectKeyIdentifier);
result = hashCodeConst * result + credentialType.hashCode();
result = hashCodeConst * result + Arrays.hashCode(subjectKeyIdentifier);
return result;
}
}

View File

@ -1,47 +1,179 @@
package hirs.attestationca.persist.entity.userdefined.certificate;
public class CertificateVariables {
public final 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_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";
/**
* Private constructor was created to silence checkstyle error.
*/
private CertificateVariables() {
}
}

View File

@ -26,46 +26,76 @@ import java.util.Objects;
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ComponentResult extends ArchivableEntity {
// String value for the Manufacturer title
/**
* String value for the Manufacturer title.
*/
public static final String ATTRIBUTE_MANUFACTURER = "Manufacturer";
// String value for the Model title
/**
* String value for the Model title.
*/
public static final String ATTRIBUTE_MODEL = "Model";
// String value for the Serial title
/**
* String value for the Serial title.
*/
public static final String ATTRIBUTE_SERIAL = "Serial";
// String value for the revision title
/**
* String value for the revision title.
*/
public static final String ATTRIBUTE_REVISION = "Revision";
// embedded component info
/**
* Embedded component info.
*/
@Setter
private String manufacturer;
@Setter
private String model;
@Setter
private String serialNumber;
@Setter
private String revisionNumber;
private boolean fieldReplaceable = false;
// this is a string because component class doesn't inherit serializable.
@Setter
private String componentClassValue;
private String componentClassStr;
private String componentClassType;
private AttributeStatus attributeStatus;
private String componentAddress;
private boolean version2 = false;
@Setter
private boolean delta = false;
@Setter
private boolean failedValidation;
private String certificateType;
private String issuerDN;
private String certificateSerialNumber;
private String boardSerialNumber;
private String uniformResourceIdentifier;
private String certificateSerialNumber;
private String boardSerialNumber;
private String uniformResourceIdentifier;
/**
* Default constructor.
*
* @param boardSerialNumber associated platform certificate serial number.
* @param certificateSerialNumber unique number associated with header info.
* @param certificateType parameter holds version 1.2 or 2.0.
@ -94,10 +124,9 @@ public class ComponentResult extends ArchivableEntity {
// V2 fields
if (componentIdentifier.isVersion2()
&& componentIdentifier instanceof ComponentIdentifierV2) {
&& componentIdentifier instanceof ComponentIdentifierV2 ciV2) {
// this is a downside of findbugs, the code is set up to indicate if a CI is V2 or not
// but find bugs is throwing a flag because instanceof isn't being used.
ComponentIdentifierV2 ciV2 = (ComponentIdentifierV2) componentIdentifier;
this.componentClassValue = ciV2.getComponentClass().getComponentIdentifier();
this.componentClassStr = ciV2.getComponentClass().toString();
this.componentClassType = ciV2.getComponentClass().getRegistryType();
@ -117,6 +146,7 @@ public class ComponentResult extends ArchivableEntity {
* This method is only used by the certificate-details.jsp page. This
* method splits the compiled string of addresses into the component address
* object for display on the jsp page.
*
* @return a collection of component addresses.
*/
public List<ComponentAddress> getComponentAddresses() {
@ -135,6 +165,7 @@ public class ComponentResult extends ArchivableEntity {
/**
* Returns a hash code that is associated with common fields for components.
*
* @return int value of the elements
*/
public int hashCommonElements() {
@ -144,6 +175,7 @@ public class ComponentResult extends ArchivableEntity {
/**
* The string method for log entries.
*
* @return a string for the component result
*/
public String toString() {

View File

@ -15,9 +15,10 @@ import java.nio.file.Path;
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class ConformanceCredential extends Certificate {
/**
* This class enables the retrieval of ConformanceCredentials by their attributes.
*/
// /**
// * 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
@ -30,12 +31,12 @@ public class ConformanceCredential extends Certificate {
// }
// }
/**
* 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
*/
// /**
// * 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);
// }

View File

@ -18,26 +18,25 @@ import java.util.UUID;
*
* @see Certificate
*/
@Setter
@Getter
@NoArgsConstructor(access = AccessLevel.PACKAGE)
@MappedSuperclass
public abstract class DeviceAssociatedCertificate extends Certificate {
// a device can have multiple certs of this type.
@Getter
@Setter
@JdbcTypeCode(java.sql.Types.VARCHAR)
@Column
private UUID deviceId;
@Getter
@Setter
@Column
private String deviceName;
/**
* Holds the name of the entity 'DEVICE_ID' field.
*/
protected static final String DEVICE_ID_FIELD = "device_id";
// a device can have multiple certs of this type.
@JdbcTypeCode(java.sql.Types.VARCHAR)
@Column
private UUID deviceId;
@Column
private String deviceName;
/**
* 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.

View File

@ -1,5 +1,6 @@
package hirs.attestationca.persist.entity.userdefined.certificate;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.TPMSecurityAssertions;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.TPMSpecification;
import jakarta.persistence.Column;
@ -53,14 +54,16 @@ import java.util.Map;
import java.util.Set;
/**
*
* This class persists an Endorsement Credential 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.
*
* <p>
* trustedcomputinggroup.org/wp-content/uploads/Credential_Profiles_V1.2_Level2_Revision8.pdf
*/
@Log4j2
@SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE",
justification = "property credentialType is guaranteed to always be non-null/initialized. Warning"
+ "stems from auto-generated lombok equals and hashcode method doing redundant null checks.")
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@ -105,11 +108,27 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
/**
* 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
* manufacturer-provided ECs, and is therefore not currently parsed.
*/
@Getter
@Column
private String credentialType = "TCPA Trusted Platform Module Endorsement";
private final String credentialType = "TCPA Trusted Platform Module Endorsement";
/**
* 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 final 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
private final String revocationLocator = null; // optional
@Getter
@Column
@ -131,22 +150,6 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
@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;
@ -180,6 +183,7 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
* 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
*/
@ -228,6 +232,7 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
* 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 IOException the input certificate bytes were not readable into an X509
* certificate format
*/
@ -264,13 +269,13 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
value = entry.getValue();
if (oid.equals(TPM_MODEL)) {
model = value.toString();
log.debug("Found TPM Model: " + model);
log.debug("Found TPM Model: {}", model);
} else if (oid.equals(TPM_VERSION)) {
version = value.toString();
log.debug("Found TPM Version: " + version);
log.debug("Found TPM Version: {}", version);
} else if (oid.equals(TPM_MANUFACTURER)) {
manufacturer = value.toString();
log.debug("Found TPM Manufacturer: " + manufacturer);
log.debug("Found TPM Manufacturer: {}", manufacturer);
}
}
}
@ -280,6 +285,7 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
* 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
@ -315,7 +321,7 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
ASN1Integer revision = (ASN1Integer) seq.getObjectAt(ASN1_REV_INDEX);
tpmSpecification = new TPMSpecification(family.getString(), level.getValue(),
revision.getValue());
log.debug("Found TPM Spec:" + tpmSpecification.toString());
log.debug("Found TPM Spec:{}", tpmSpecification);
} else if (addToMapping && key.equals(TPM_SECURITY_ASSERTIONS)) {
// Parse TPM Security Assertions
int seqPosition = 0;
@ -341,7 +347,7 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
tpmSecurityAssertions = new TPMSecurityAssertions(ver.getValue(),
fieldUpgradeable.isTrue());
log.debug("Found TPM Assertions: " + tpmSecurityAssertions.toString());
log.debug("Found TPM Assertions: {}", tpmSecurityAssertions);
// Iterate through remaining fields to set optional attributes
int tag;
ASN1TaggedObject obj;
@ -392,13 +398,13 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
* 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 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
@ -421,13 +427,11 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
parsedFields.put(key, ((ASN1ObjectIdentifier) component).getId());
}
} else if (component instanceof ASN1TaggedObject) {
ASN1TaggedObject taggedObj = (ASN1TaggedObject) component;
} else if (component instanceof ASN1TaggedObject taggedObj) {
parseSingle(taggedObj.getBaseObject().toASN1Primitive(), addToMapping, key);
} else if (component instanceof ASN1OctetString) {
} else if (component instanceof ASN1OctetString octStr) {
// 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);
@ -446,12 +450,11 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
}
}
} else if (component instanceof ASN1Set) {
} else if (component instanceof ASN1Set set) {
// 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()) {
@ -563,7 +566,7 @@ public class EndorsementCredential extends DeviceAssociatedCertificate {
} else {
// there are some deprecated types that we don't parse
log.error("Unparsed type: " + component.getClass());
log.error("Unparsed type: {}", component.getClass());
}
}
}

View File

@ -4,10 +4,15 @@ import hirs.attestationca.persist.entity.userdefined.Certificate;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Transient;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import org.bouncycastle.asn1.x509.CertificatePolicies;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.PolicyInformation;
@ -15,23 +20,15 @@ import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@Entity
@Getter
@EqualsAndHashCode(callSuper = true)
@Log4j2
public class IDevIDCertificate extends Certificate {
@ -49,28 +46,24 @@ public class IDevIDCertificate extends Certificate {
private static final String POLICY_QUALIFIER_VERIFIED_TPM_FIXED = "2.23.133.11.1.2";
private static final String POLICY_QUALIFIER_VERIFIED_TPM_RESTRICTED = "2.23.133.11.1.3";
@Getter
@Transient
private byte[] subjectAltName;
/**
* Corresponds to the hwType field found in a Hardware Module Name (if present).
*/
@Getter
@Column
private String hwType;
/**
* Corresponds to the serial number found in a Hardware Module Name (if present).
*/
@Getter
@Column
private byte[] hwSerialNum;
/**
* TPM policy qualifiers (TCG only).
*/
@Getter
@Column
private String tpmPolicies;
@ -110,13 +103,14 @@ public class IDevIDCertificate extends Certificate {
}
/**
* Obtains TPM policy qualifiers from the Certificate Policies extension, if present. These policy qualifiers are
* specified in the TCG document "TPM 2.0 Keys for Device Identity and Attestation".
* Obtains TPM policy qualifiers from the Certificate Policies extension, if present. These policy
* qualifiers are specified in the TCG document "TPM 2.0 Keys for Device Identity and Attestation".
*
* @param policyBytes byte array representation of the policy
* @return A {@link java.util.Map} containing the policy qualifiers obtained.
* @throws IOException if policy qualifiers cannot be parsed from extension value
*/
public Map<String, Boolean> getTPMPolicyQualifiers(byte[] policyBytes) throws IOException {
public Map<String, Boolean> getTPMPolicyQualifiers(final byte[] policyBytes) throws IOException {
CertificatePolicies certPolicies =
CertificatePolicies.getInstance(JcaX509ExtensionUtils.parseExtensionValue(policyBytes));
Map<String, Boolean> policyQualifiers = new HashMap<>();
@ -154,6 +148,7 @@ public class IDevIDCertificate extends Certificate {
/**
* Parses fields related to IDevID certificates.
*
* @throws IOException if a problem is encountered during parsing
*/
private void parseIDevIDCertificate() throws IOException {
@ -170,13 +165,13 @@ public class IDevIDCertificate extends Certificate {
ASN1OctetString obj = (ASN1OctetString) input.readObject();
boolean tcgOid = false;
// Parse the otherName structure. According to the specification "TPM 2.0 Keys for Device Identity and
// Attestation", otherName can contain up to two structures: HardwareModuleName and PermanentIdentifier.
// Currently, this parser only supports HardwareModuleName (if present).
// Parse the otherName structure. According to the specification "TPM 2.0 Keys for Device Identity
// and Attestation", otherName can contain up to two structures: HardwareModuleName and
// PermanentIdentifier. Currently, this parser only supports HardwareModuleName (if present).
if (obj != null) {
// Parse Hardware Module Name structure, comprised of a hwType and hwSerialNum, and associated OID
// See also RFC 4108
// Parse Hardware Module Name structure, comprised of a hwType and hwSerialNum,
// and associated OID. See also RFC 4108
ASN1Sequence seq1 = ASN1Sequence.getInstance(obj.getOctets());
// Iterate over GeneralNames sequence until HardwareModuleName is found
@ -207,20 +202,21 @@ public class IDevIDCertificate extends Certificate {
} catch (IllegalArgumentException e) {
// Some certs have been found to contain tagged objects for hwSerialNum.
// Handle this as a special case.
log.warn("Could not parse octet string for hwSerialNum. Attempting to parse tag.");
log.warn(
"Could not parse octet string for hwSerialNum. "
+ "Attempting to parse tag.");
try {
tagObj1 = ASN1TaggedObject.getInstance(seq1.getObjectAt(1));
obj2 = ASN1OctetString.getInstance(tagObj1, false);
}
catch (Exception i) { // Invalid object found
} catch (Exception i) { // Invalid object found
log.warn("Invalid object found for hwSerialNum.");
break;
}
}
// If an OID corresponding to TPM 2.0 for hwType is supported, according to the
// specification "TPM 2.0 Keys for Device Identity and Attestation", the contents of
// the hwSerialNum field will be parsed accordingly.
// If an OID corresponding to TPM 2.0 for hwType is supported, according
// to the specification "TPM 2.0 Keys for Device Identity and Attestation",
// the contents of the hwSerialNum field will be parsed accordingly.
hwType = obj1.toString();
if (hasTCGOIDs()) {
tcgOid = true;
@ -234,10 +230,11 @@ public class IDevIDCertificate extends Certificate {
}
}
// Check for certificate policy qualifiers, which should be present for IDevIDs if in compliance with the
// TCG specification.
// For interoperability reasons, this will only log a warning if a TCG OID is specified above.
byte[] policyBytes = getX509Certificate().getExtensionValue(Extension.certificatePolicies.getId());
// Check for certificate policy qualifiers, which should be present for IDevIDs if in compliance
// with the TCG specification. For interoperability reasons, this will only log a warning
// if a TCG OID is specified above.
byte[] policyBytes =
getX509Certificate().getExtensionValue(Extension.certificatePolicies.getId());
Map<String, Boolean> policyQualifiers = null;
if (policyBytes != null) {
@ -257,22 +254,23 @@ public class IDevIDCertificate extends Certificate {
});
tpmPolicies = qualifierSB.toString();
failCondition = !(policyQualifiers.get("verifiedTPMResidency") &&
(policyQualifiers.get("verifiedTPMFixed") ||
policyQualifiers.get("verifiedTPMRestricted")));
failCondition = !(policyQualifiers.get("verifiedTPMResidency")
&& (policyQualifiers.get("verifiedTPMFixed")
|| policyQualifiers.get("verifiedTPMRestricted")));
} else {
failCondition = true;
}
if (failCondition) {
log.warn("TPM policy qualifiers not found, or do not meet logical criteria. Certificate may not " +
"be in compliance with TCG specification.");
log.warn(
"TPM policy qualifiers not found, or do not meet logical criteria. "
+ "Certificate may not be in compliance with TCG specification.");
}
}
// Log a warning if notAfter field has an expiry date that is not indefinite
if (!this.getEndValidity().toInstant().equals(Instant.ofEpochSecond(UNDEFINED_EXPIRY_DATE))) {
log.warn("IDevID does not contain an indefinite expiry date. This may indicate an invalid " +
"certificate.");
log.warn("IDevID does not contain an indefinite expiry date. This may indicate an invalid "
+ "certificate.");
}
input.close();
@ -280,54 +278,16 @@ public class IDevIDCertificate extends Certificate {
}
/**
* Function to check whether a given IDevID certificate has TCG OIDs, in order to check compliance with various
* fields.
* Function to check whether a given IDevID certificate has TCG OIDs, in order to check compliance with
* various fields.
*
* @return a boolean value
*/
public boolean hasTCGOIDs() {
if (this.getHwType() != null) {
return this.getHwType().equals(HWTYPE_TCG_TPM2_OID);
}
else {
} else {
return false;
}
}
@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;
}
IDevIDCertificate that = (IDevIDCertificate) o;
if (!Objects.equals(getTpmPolicies(), that.getTpmPolicies())) {
return false;
}
if (!Objects.equals(getHwType(), that.getHwType())) {
return false;
}
return Arrays.equals(getHwSerialNum(), that.getHwSerialNum());
}
@Override
@SuppressWarnings({"checkstyle:magicnumber", "checkstyle:avoidinlineconditionals"})
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (getTpmPolicies() != null ? getTpmPolicies().hashCode() : 0);
result = 31 * result + (getHwType() != null ? getHwType().hashCode() : 0);
result = 31 * result + (getHwSerialNum() != null ? Arrays.hashCode(getHwSerialNum()) : 0);
return result;
}
}

View File

@ -18,8 +18,8 @@ import java.util.List;
/**
* Represents an issued attestation certificate to a HIRS Client.
*/
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
@ -28,6 +28,9 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
*/
public static final String AIC_TYPE_LABEL = "TCPA Trusted Platform Identity";
@Column
private boolean isLDevID;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "ek_id")
private EndorsementCredential endorsementCredential;
@ -36,19 +39,19 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
@JoinColumn(name = "pc_id")
private List<PlatformCredential> platformCredentials;
@Column
public boolean isLDevID;
/**
* Constructor.
*
* @param certificateBytes the issued certificate bytes
* @param endorsementCredential the endorsement credential
* @param platformCredentials the platform credentials
* @param isLDevID is LDevId
* @throws IOException if there is a problem extracting information from the certificate
*/
public IssuedAttestationCertificate(final byte[] certificateBytes,
final EndorsementCredential endorsementCredential,
final List<PlatformCredential> platformCredentials, boolean isLDevID)
final List<PlatformCredential> platformCredentials,
final boolean isLDevID)
throws IOException {
super(certificateBytes);
this.endorsementCredential = endorsementCredential;
@ -58,9 +61,11 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
/**
* Constructor.
*
* @param certificatePath path to certificate
* @param endorsementCredential the endorsement credential
* @param platformCredentials the platform credentials
* @param isLDevID is it an LDev ID
* @throws IOException if there is a problem extracting information from the certificate
*/
public IssuedAttestationCertificate(final Path certificatePath,
@ -70,8 +75,4 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
throws IOException {
this(readBytes(certificatePath), endorsementCredential, platformCredentials, isLDevID);
}
public List<PlatformCredential> getPlatformCredentials() {
return new ArrayList<>(platformCredentials);
}
}

View File

@ -46,7 +46,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* This class persists Platform credentials by extending the base Certificate
@ -61,24 +60,29 @@ import java.util.UUID;
@Entity
public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* 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";
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";
@ -115,16 +119,11 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
// 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";
private static final String MANUFACTURER_FIELD = "manufacturer";
private static final String MODEL_FIELD = "model";
private static final String VERSION_FIELD = "version";
private static final String PLATFORM_SERIAL_FIELD = "platformSerial";
private static final String CHASSIS_SERIAL_NUMBER_FIELD = "chassisSerialNumber";
@Column
private String credentialType = null;
@ -132,23 +131,18 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
@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;
@ -175,6 +169,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
@Column(length = MAX_MESSAGE_LENGTH)
private String componentFailures = Strings.EMPTY;
@Column(length = MAX_MESSAGE_LENGTH)
private String componentFailureMessage = Strings.EMPTY;
@ -182,6 +177,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
private EndorsementCredential endorsementCredential = null;
private String platformChainType = Strings.EMPTY;
private boolean isDeltaChain = false;
/**
@ -223,6 +219,105 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
this(readBytes(certificatePath), true);
}
/**
* 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) {
log.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) {
log.warn("Failed to parse PC after multiple attempts", e1);
}
} else {
log.warn("EK parsing failed (only one attempt possible)", e);
}
}
return credential;
}
/**
* 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) {
return id2.getParameters() == null || id2.getParameters().equals(DERNull.INSTANCE);
}
if (id2.getParameters() == null) {
return id1.getParameters() == null || id1.getParameters().equals(DERNull.INSTANCE);
}
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;
}
/**
* Validate the signature on the attribute certificate in this holder.
*
@ -253,37 +348,6 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
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) {
log.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) {
log.warn("Failed to parse PC after multiple attempts", e1);
}
} else {
log.warn("EK parsing failed (only one attempt possible)", e);
}
}
return credential;
}
private void parseFields() throws IOException {
AttributeCertificateInfo certificate = getAttributeCertificate().getAcinfo();
@ -340,6 +404,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* Parse a 1.2 Platform Certificate (Attribute Certificate).
*
* @param certificate Attribute Certificate
*/
private void parseAttributeCert(final AttributeCertificateInfo certificate) {
@ -392,6 +457,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* Parse a 2.0 Platform Certificate (Attribute Certificate).
*
* @param certificate Attribute Certificate
*/
private void parseAttributeCert2(final AttributeCertificateInfo certificate)
@ -440,6 +506,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* Get the x509 Platform Certificate version.
*
* @return a big integer representing the certificate version.
*/
@Override
@ -458,6 +525,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* Get the cPSuri from the Certificate Policies.
*
* @return cPSuri from the CertificatePolicies.
* @throws IOException when reading the certificate.
*/
@ -473,6 +541,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* 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 IOException when reading the certificate.
@ -523,6 +592,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* 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
@ -535,6 +605,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* 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 IOException when reading the certificate.
@ -552,6 +623,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* 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 IOException when reading the certificate.
@ -567,6 +639,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* Get the TBB Security Assertion from the Platform Certificate.
*
* @return a TBBSecurityAssertion object.
* @throws IllegalArgumentException when there is a parsing error
* @throws IOException when reading the certificate.
@ -612,6 +685,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* Get the list of component identifiers if there are any.
*
* @return the list of component identifiers if there are any
*/
public List<ComponentIdentifier> getComponentIdentifiers() {
@ -626,76 +700,4 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
}
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;
}
}

View File

@ -25,7 +25,8 @@ import org.bouncycastle.asn1.ASN1TaggedObject;
* targetUri [4] IMPLICIT URIReference OPTIONAL }
* </pre>
*/
@Getter @Setter
@Getter
@Setter
public class CommonCriteriaMeasures {
private static final int STRENGTH_OF_FUNCTION = 0;
@ -33,140 +34,6 @@ public class CommonCriteriaMeasures {
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 ASN1IA5String version;
private EvaluationAssuranceLevel assuranceLevel;
private EvaluationStatus evaluationStatus;
@ -194,6 +61,7 @@ public class CommonCriteriaMeasures {
/**
* 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
*/
@ -258,7 +126,11 @@ public class CommonCriteriaMeasures {
}
}
/**
* Creates a custom string representation of the Common Criteria Measures object.
*
* @return a string representation of Common Criteria Measures
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@ -278,7 +150,7 @@ public class CommonCriteriaMeasures {
}
sb.append(", profileUri=");
if (profileUri != null) {
sb.append(profileUri.toString());
sb.append(profileUri);
}
sb.append(", targetOid=");
if (targetOid != null) {
@ -286,10 +158,148 @@ public class CommonCriteriaMeasures {
}
sb.append(", targetUri=");
if (targetUri != null) {
sb.append(targetUri.toString());
sb.append(targetUri);
}
sb.append("}");
return sb.toString();
}
/**
* 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;
}
}
}

View File

@ -27,12 +27,17 @@ public class ComponentAddress {
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 ASN1UTF8String addressValue;
private String addressTypeString;
private String addressValueString;
/**
@ -62,27 +67,24 @@ public class ComponentAddress {
/**
* 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;
return switch (this.addressType.getId()) {
case ETHERNET_MAC -> "ethernet mac";
case WLAN_MAC -> "wlan mac";
case BLUETOOTH_MAC -> "bluetooth mac";
default -> "unknown mac";
};
}
/**
* Creates a string representation of the Component Address object.
*
* @return a string representation of the Component Address object.
*/
@Override
public String toString() {
return "ComponentAddress{"

View File

@ -6,7 +6,6 @@ import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import java.util.UUID;
@ -14,7 +13,7 @@ import java.util.UUID;
* This is tied to the ComponentResult class. If a component has a mismatched
* value from what the device has listed, this class represents which attribute
* of that component mismatched.
*
* <p>
* If this is a delta issue, the component ID would be set to null if the
* remove or modified don't exist.
*/
@ -24,16 +23,21 @@ import java.util.UUID;
public class ComponentAttributeResult extends ArchivableEntity {
private UUID componentId;
@Setter
private UUID provisionSessionId;
// this is used to identify Revision for the ignore policy
@Setter
private String attribute;
private String expectedValue;
private String actualValue;
/**
* Default constructor that populates the expected and actual values.
*
* @param componentId id associated with component result
* @param expectedValue platform certificate value
* @param actualValue paccor value from the device
@ -48,6 +52,7 @@ public class ComponentAttributeResult extends ArchivableEntity {
/**
* Default constructor that populates the expected and actual values.
*
* @param componentId id associated with component result
* @param provisionSessionId an id for the associated provision
* @param expectedValue platform certificate value
@ -65,6 +70,8 @@ public class ComponentAttributeResult extends ArchivableEntity {
/**
* This method is used to check the mismatched status flag for
* displaying red if there is a failure.
*
* @return true if there is status match, false otherwise
*/
public boolean checkMatchedStatus() {
return this.actualValue.equals(this.expectedValue);
@ -72,6 +79,7 @@ public class ComponentAttributeResult extends ArchivableEntity {
/**
* For the state of the object, this shouldn't be negative.
*
* @return the string value of the attribute name
*/
public String getAttribute() {

View File

@ -23,39 +23,52 @@ import java.nio.file.Path;
* componentClassRegistry ComponentClassRegistry,
* componentClassValue OCTET STRING SIZE(4) ) }
* </pre>
*
* <p>
* A note for the future.
*/
public class ComponentClass {
@Getter
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 WINDOWS_JSON_PATH = FileSystems.getDefault().getPath(
"C:/", "ProgramData", "hirs", "aca", "default-properties", "component-class.json");
private static final Path JSON_PATH = WINDOWS_JSON_PATH.toFile().exists() ? WINDOWS_JSON_PATH :
FileSystems.getDefault().getPath(
private static final Path JSON_PATH = WINDOWS_JSON_PATH.toFile().exists() ? WINDOWS_JSON_PATH
: FileSystems.getDefault().getPath(
"/etc", "hirs", "aca", "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;
@Getter
private String registryType;
@Getter
private String componentIdentifier;
private final String registryType;
private final String componentIdentifier;
private String category;
private String categoryStr;
private String component;
private String componentStr;
/**
* Default class constructor.
@ -106,11 +119,11 @@ public class ComponentClass {
this.componentIdentifier = verifyComponentValue(componentIdentifier);
}
switch (registryOid) {
case TCG_COMPONENT_REGISTRY -> registryType = "TCG";
case SMBIOS_COMPONENT_REGISTRY -> registryType = "SMBIOS";
default -> registryType = UNKNOWN_STRING;
}
this.registryType = switch (registryOid) {
case TCG_COMPONENT_REGISTRY -> "TCG";
case SMBIOS_COMPONENT_REGISTRY -> "SMBIOS";
default -> UNKNOWN_STRING;
};
switch (this.componentIdentifier) {
case OTHER:
@ -135,9 +148,39 @@ public class ComponentClass {
}
}
/**
* 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;
}
/**
* 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
@ -173,12 +216,14 @@ public class ComponentClass {
found = true;
JsonObject componentTypes = categories.get(name)
.asObject().get("Types").asObject();
categoryStr = name;
this.categoryStr = name;
switch (componentMask) {
case OTHER -> componentStr = OTHER_STRING;
case UNKNOWN -> componentStr = UNKNOWN_STRING;
default -> getComponent(componentTypes);
if (componentMask.equals(OTHER)) {
this.componentStr = OTHER_STRING;
} else if (componentMask.equals(UNKNOWN)) {
this.componentStr = UNKNOWN_STRING;
} else {
getComponent(componentTypes);
}
}
}
@ -192,6 +237,7 @@ public class ComponentClass {
/**
* 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
@ -219,33 +265,4 @@ public class ComponentClass {
}
}
}
/**
* 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;
}
}

View File

@ -44,13 +44,11 @@ public class ComponentIdentifier {
* 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;
// optional sequence objects
/**
* Static variable indicated array position for the revision info.
*/
@ -68,13 +66,22 @@ public class ComponentIdentifier {
*/
protected static final int COMPONENT_ADDRESS = 4;
private static final int MANDATORY_ELEMENTS = 2;
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;
/**
@ -119,6 +126,7 @@ public class ComponentIdentifier {
/**
* Constructor given the SEQUENCE that contains Component Identifier.
*
* @param sequence containing the component identifier
* @throws IllegalArgumentException if there was an error on the parsing
*/
@ -194,21 +202,10 @@ public class ComponentIdentifier {
}
/**
* Getter for the component addresses.
* @return a collection of component addresses
* Creates a string representation of the Component Identifier object.
*
* @return a string representation of the Component Identifier object.
*/
public List<ComponentAddress> getComponentAddress() {
return componentAddress.stream().toList();
}
/**
* Setter for the list of component addresses.
* @param componentAddress collection of addresses
*/
public void setComponentAddress(List<ComponentAddress> componentAddress) {
this.componentAddress = componentAddress.stream().toList();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@ -230,7 +227,7 @@ public class ComponentIdentifier {
}
sb.append(", fieldReplaceable=");
if (fieldReplaceable != null) {
sb.append(fieldReplaceable.toString());
sb.append(fieldReplaceable);
}
sb.append(", componentAddress=");
if (!componentAddress.isEmpty()) {

View File

@ -3,6 +3,7 @@ package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.bouncycastle.asn1.ASN1Boolean;
import org.bouncycastle.asn1.ASN1Enumerated;
import org.bouncycastle.asn1.ASN1IA5String;
@ -17,64 +18,18 @@ import org.bouncycastle.asn1.ASN1Sequence;
* plus BOOLEAN DEFAULT FALSE }
* </pre>
*/
@Getter
@Setter
@AllArgsConstructor
@ToString
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 ASN1IA5String version;
@Getter @Setter
private SecurityLevel level;
@Getter @Setter
private ASN1Boolean plus;
/**
@ -111,12 +66,39 @@ public class FIPSLevel {
}
}
@Override
public String toString() {
return "FIPSLevel{"
+ "version=" + version.getString()
+ ", level=" + level.getValue()
+ ", plus=" + plus.toString()
+ '}';
/**
* 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>
*/
@Getter
@AllArgsConstructor
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;
}
}

View File

@ -15,10 +15,12 @@ import java.util.List;
@AllArgsConstructor
public abstract class PlatformConfiguration {
private ArrayList<ComponentIdentifier> componentIdentifier = new ArrayList<>();
@Getter @Setter
@Getter
@Setter
private URIReference componentIdentifierUri;
private ArrayList<PlatformProperty> platformProperties = new ArrayList<>();
@Getter @Setter
@Getter
@Setter
private URIReference platformPropertiesUri;
/**
@ -55,8 +57,16 @@ public abstract class PlatformConfiguration {
return Collections.unmodifiableList(componentIdentifier);
}
/**
* @param componentIdentifier the componentIdentifier to set
*/
public void setComponentIdentifier(final List<ComponentIdentifier> componentIdentifier) {
this.componentIdentifier = new ArrayList<>(componentIdentifier);
}
/**
* Add function for the component identifier array.
*
* @param componentIdentifier object to add
* @return status of the add, if successful or not
*/
@ -68,13 +78,6 @@ public abstract class PlatformConfiguration {
return false;
}
/**
* @param componentIdentifier the componentIdentifier to set
*/
public void setComponentIdentifier(final List<ComponentIdentifier> componentIdentifier) {
this.componentIdentifier = new ArrayList<>(componentIdentifier);
}
/**
* @return the platformProperties
*/
@ -82,8 +85,16 @@ public abstract class PlatformConfiguration {
return Collections.unmodifiableList(platformProperties);
}
/**
* @param platformProperties the platformProperties to set
*/
public void setPlatformProperties(final List<PlatformProperty> platformProperties) {
this.platformProperties = new ArrayList<>(platformProperties);
}
/**
* Add function for the platform property array.
*
* @param platformProperty property object to add
* @return status of the add, if successful or not
*/
@ -94,11 +105,4 @@ public abstract class PlatformConfiguration {
return false;
}
/**
* @param platformProperties the platformProperties to set
*/
public void setPlatformProperties(final List<PlatformProperty> platformProperties) {
this.platformProperties = new ArrayList<>(platformProperties);
}
}

View File

@ -25,6 +25,7 @@ public class PlatformConfigurationV1 extends PlatformConfiguration {
/**
* Constructor given the SEQUENCE that contains Platform Configuration.
*
* @param sequence containing the Platform Configuration.
* @throws IllegalArgumentException if there was an error on the parsing
*/
@ -76,6 +77,11 @@ public class PlatformConfigurationV1 extends PlatformConfiguration {
}
}
/**
* Creates a string representation of the Platform Configuration V1 object.
*
* @return a string representation of the Platform Configuration V1 object.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@ -96,7 +102,7 @@ public class PlatformConfigurationV1 extends PlatformConfiguration {
}
sb.append(", platformPropertiesUri=");
if (getPlatformPropertiesUri() != null) {
sb.append(getPlatformPropertiesUri().toString());
sb.append(getPlatformPropertiesUri());
}
sb.append("}");

View File

@ -3,12 +3,12 @@ package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1UTF8String;
import org.bouncycastle.asn1.DERUTF8String;
/**
*
* Basic class that handles a single property for the platform configuration.
* <pre>
* Properties ::= SEQUENCE {
@ -20,16 +20,17 @@ import org.bouncycastle.asn1.DERUTF8String;
@Getter
@Setter
@AllArgsConstructor
@ToString
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 static final String NOT_SPECIFIED = "Not Specified";
private ASN1UTF8String propertyName;
private ASN1UTF8String propertyValue;
/**
@ -57,12 +58,4 @@ public class PlatformProperty {
this.propertyName = ASN1UTF8String.getInstance(sequence.getObjectAt(0));
this.propertyValue = ASN1UTF8String.getInstance(sequence.getObjectAt(1));
}
@Override
public String toString() {
return "PlatformProperty{"
+ "propertyName=" + propertyName.getString()
+ ", propertyValue=" + propertyValue.getString()
+ "}";
}
}

View File

@ -2,6 +2,8 @@ package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.bouncycastle.asn1.ASN1Boolean;
import org.bouncycastle.asn1.ASN1Enumerated;
import org.bouncycastle.asn1.ASN1IA5String;
@ -24,71 +26,26 @@ import java.math.BigInteger;
* iso9000Uri IA5STRING (SIZE (1..URIMAX)) OPTIONAL }
* </pre>
*/
@Setter
@Getter
@AllArgsConstructor
@ToString
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 ASN1IA5String iso9000Uri;
/**
@ -105,6 +62,7 @@ public class TBBSecurityAssertion {
/**
* 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
*/
@ -169,114 +127,56 @@ public class TBBSecurityAssertion {
}
/**
* @return the version
* 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 ASN1Integer getVersion() {
return version;
}
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;
/**
* @param version the version to set
* Basic constructor.
*
* @param value string containing the value.
*/
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 ASN1IA5String getIso9000Uri() {
return iso9000Uri;
}
/**
* @param iso9000Uri the iso9000Uri to set
*/
public void setIso9000Uri(final ASN1IA5String 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();
MeasurementRootType(final String value) {
this.value = value;
}
}
}

View File

@ -7,6 +7,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
import java.math.BigInteger;
@ -14,19 +15,55 @@ 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.
*
* <p>
* https://www.trustedcomputinggroup.org/wp-content/uploads/IWG-Credential_Profiles_V1_R0.pdf
*
* <p>
* 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).
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter @Setter
@ToString
@Embeddable
public class TPMSecurityAssertions implements Serializable {
@Column
private BigInteger tpmSecAssertsVersion; //default v1
@Column
private boolean fieldUpgradeable; //default false
@Column
private EkGenerationType ekGenType; //optional
@Column
private EkGenerationLocation ekGenerationLocation; //optionalv
@Column
private EkGenerationLocation ekCertificateGenerationLocation; //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;
}
// 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
/**
* 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
@ -51,7 +88,7 @@ public class TPMSecurityAssertions implements Serializable {
* Generated externally and then inserted under a controlled environment during
* manufacturing. Can be revoked. Enum value of 3.
*/
INJECTED_REVOCABLE;
INJECTED_REVOCABLE
}
/**
@ -73,50 +110,6 @@ public class TPMSecurityAssertions implements Serializable {
/**
* 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
+ '}';
EK_CERT_SIGNER
}
}

View File

@ -6,6 +6,7 @@ import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
import java.math.BigInteger;
@ -13,16 +14,17 @@ 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.
*
* <p>
* https://www.trustedcomputinggroup.org/wp-content/uploads/IWG-Credential_Profiles_V1_R0.pdf
*
* <p>
* 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
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString
@EqualsAndHashCode
@Embeddable
public class TPMSpecification implements Serializable {
@ -37,6 +39,7 @@ public class TPMSpecification implements Serializable {
/**
* Standard constructor.
*
* @param family the specification family.
* @param level the specification level.
* @param revision the specification revision.
@ -47,13 +50,4 @@ public class TPMSpecification implements Serializable {
this.level = level;
this.revision = revision;
}
@Override
public String toString() {
return "TPMSpecification{"
+ "family='" + family + '\''
+ ", level=" + level
+ ", revision=" + revision
+ '}';
}
}

View File

@ -10,27 +10,30 @@ import org.bouncycastle.asn1.ASN1Sequence;
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
@Getter
@Setter
@AllArgsConstructor
public class URIReference {
private static final int PLATFORM_PROPERTIES_URI_MAX = 3;
private static final int PLATFORM_PROPERTIES_URI_MIN = 1;
private ASN1IA5String uniformResourceIdentifier;
private AlgorithmIdentifier hashAlgorithm;
@JsonIgnore
private ASN1BitString hashValue;
private static final int PLATFORM_PROPERTIES_URI_MAX = 3;
private static final int PLATFORM_PROPERTIES_URI_MIN = 1;
/**
* Default constructor.
*/
@ -71,6 +74,11 @@ public class URIReference {
}
}
/**
* Creates a string representation of the URI Reference object.
*
* @return a string representation of URI Reference
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();

View File

@ -51,6 +51,7 @@ public class CertificateIdentifier {
/**
* Primary constructor for the parsing of the sequence.
*
* @param sequence containing the name and value of the Certificate Identifier
*/
public CertificateIdentifier(final ASN1Sequence sequence) {
@ -103,6 +104,7 @@ public class CertificateIdentifier {
/**
* String for the internal data stored.
*
* @return String representation of the data.
*/
@Override
@ -114,11 +116,11 @@ public class CertificateIdentifier {
sb.append(", hashSigValue").append(hashSigValue);
sb.append(", issuerDN=");
if (issuerDN != null) {
sb.append(issuerDN.toString());
sb.append(issuerDN);
}
sb.append(", certificateSerialNumber=");
if (certificateSerialNumber != null) {
sb.append(certificateSerialNumber.toString());
sb.append(certificateSerialNumber);
}
sb.append("}");

View File

@ -4,6 +4,7 @@ import hirs.attestationca.persist.entity.userdefined.certificate.attributes.Comp
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;
@ -16,7 +17,6 @@ import org.bouncycastle.asn1.ASN1UTF8String;
import org.bouncycastle.asn1.DERUTF8String;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
@ -40,17 +40,24 @@ import java.util.stream.Collectors;
*/
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
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;
/**
@ -79,7 +86,6 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
* @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,
@ -103,6 +109,7 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
/**
* Constructor given the SEQUENCE that contains Component Identifier.
*
* @param sequence containing the component identifier
* @throws IllegalArgumentException if there was an error on the parsing
*/
@ -120,7 +127,8 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
ASN1OctetString.getInstance(componentIdSeq.getObjectAt(tag)).toString());
// Mandatory values
this.setComponentManufacturer((DERUTF8String) ASN1UTF8String.getInstance(sequence.getObjectAt(tag++)));
this.setComponentManufacturer(
(DERUTF8String) ASN1UTF8String.getInstance(sequence.getObjectAt(tag++)));
this.setComponentModel((DERUTF8String) ASN1UTF8String.getInstance(sequence.getObjectAt(tag++)));
// Continue reading the sequence if it does contain more than 2 values
@ -200,24 +208,11 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
ComponentIdentifierV2 that = (ComponentIdentifierV2) o;
return Objects.equals(componentClass, that.componentClass)
&& Objects.equals(certificateIdentifier, that.certificateIdentifier)
&& Objects.equals(componentPlatformUri, that.componentPlatformUri)
&& attributeStatus == that.attributeStatus;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), componentClass,
certificateIdentifier, componentPlatformUri, attributeStatus);
}
/**
* Creates a string representation of the Component Identifier V2 object.
*
* @return a string representation of the Component Identifier V2 object.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@ -241,7 +236,7 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
}
sb.append(", fieldReplaceable=");
if (getFieldReplaceable() != null) {
sb.append(getFieldReplaceable().toString());
sb.append(getFieldReplaceable());
}
sb.append(", componentAddress=");
if (getComponentAddress().size() > 0) {
@ -252,11 +247,11 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
}
sb.append(", certificateIdentifier=");
if (certificateIdentifier != null) {
sb.append(certificateIdentifier.toString());
sb.append(certificateIdentifier);
}
sb.append(", componentPlatformUri=");
if (componentPlatformUri != null) {
sb.append(componentPlatformUri.toString());
sb.append(componentPlatformUri);
}
sb.append(", status=");
if (attributeStatus != null) {

View File

@ -29,6 +29,7 @@ public class PlatformConfigurationV2 extends PlatformConfiguration {
/**
* 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
*/
@ -86,6 +87,11 @@ public class PlatformConfigurationV2 extends PlatformConfiguration {
}
}
/**
* Creates a string representation of the Platform Configuration V2 object.
*
* @return a string representation of the Platform Configuration V2 object.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@ -99,7 +105,7 @@ public class PlatformConfigurationV2 extends PlatformConfiguration {
}
sb.append(", componentIdentifierUri=");
if (getComponentIdentifierUri() != null) {
sb.append(getComponentIdentifierUri().toString());
sb.append(getComponentIdentifierUri());
}
sb.append(", platformProperties=");
if (getPlatformProperties().size() > 0) {
@ -110,7 +116,7 @@ public class PlatformConfigurationV2 extends PlatformConfiguration {
}
sb.append(", platformPropertiesUri=");
if (getPlatformPropertiesUri() != null) {
sb.append(getPlatformPropertiesUri().toString());
sb.append(getPlatformPropertiesUri());
}
sb.append("}");

View File

@ -8,7 +8,6 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1UTF8String;
/**
*
* Basic class that handles a single property for the platform configuration.
* <pre>
* Properties ::= SEQUENCE {
@ -18,10 +17,10 @@ import org.bouncycastle.asn1.ASN1UTF8String;
*
* </pre>
*/
@Setter
@Getter
public class PlatformPropertyV2 extends PlatformProperty {
@Getter
@Setter
private AttributeStatus attributeStatus;
/**
@ -84,6 +83,12 @@ public class PlatformPropertyV2 extends PlatformProperty {
return getAttributeStatus() != AttributeStatus.REMOVED;
}
/**
* Creates a string representation of the PlatformPropertyV2 object.
*
* @return a string representation of the PlatformPropertyV2 object
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@ -91,7 +96,7 @@ public class PlatformPropertyV2 extends PlatformProperty {
sb.append("PropertyName=").append(getPropertyName().getString());
sb.append(", propertyValue=").append(getPropertyValue().getString());
if (attributeStatus != null) {
sb.append(", attributeStatus=").append(attributeStatus.toString());
sb.append(", attributeStatus=").append(attributeStatus);
}
sb.append("}");

View File

@ -9,6 +9,7 @@ import jakarta.persistence.DiscriminatorType;
import jakarta.persistence.Entity;
import jakarta.xml.bind.annotation.XmlElement;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@ -24,6 +25,7 @@ import java.util.Objects;
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(callSuper = false)
@DiscriminatorColumn(name = "componentTypeEnum", discriminatorType = DiscriminatorType.STRING)
public class ComponentInfo extends ArchivableEntity {
@ -34,6 +36,7 @@ public class ComponentInfo extends ArchivableEntity {
@Column(nullable = false)
private String deviceName;
@XmlElement
@Column(nullable = false)
private String componentManufacturer;
@ -56,6 +59,7 @@ public class ComponentInfo extends ArchivableEntity {
/**
* Base constructor for children.
*
* @param componentManufacturer Component Manufacturer (must not be null)
* @param componentModel Component Model (must not be null)
* @param componentSerial Component Serial Number (can be null)
@ -68,8 +72,10 @@ public class ComponentInfo extends ArchivableEntity {
this(DeviceInfoEnums.NOT_SPECIFIED, componentManufacturer, componentModel,
componentSerial, componentRevision);
}
/**
* Constructor.
*
* @param deviceName the host machine associated with this component. (must not be null)
* @param componentManufacturer Component Manufacturer (must not be null)
* @param componentModel Component Model (must not be null)
@ -108,6 +114,7 @@ public class ComponentInfo extends ArchivableEntity {
/**
* Constructor.
*
* @param deviceName the host machine associated with this component.
* @param componentManufacturer Component Manufacturer (must not be null)
* @param componentModel Component Model (must not be null)
@ -147,43 +154,13 @@ public class ComponentInfo extends ArchivableEntity {
|| StringUtils.isEmpty(componentModel));
}
/**
* Equals for the component info that just uses this classes attributes.
* @param object the object to compare
* @return the boolean result
*/
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
ComponentInfo that = (ComponentInfo) object;
return Objects.equals(deviceName, that.deviceName)
&& Objects.equals(componentManufacturer,
that.componentManufacturer)
&& Objects.equals(componentModel, that.componentModel)
&& Objects.equals(componentSerial, that.componentSerial)
&& Objects.equals(componentRevision, that.componentRevision)
&& Objects.equals(componentClass, that.componentClass);
}
/**
* Returns a hash code that is associated with common fields for components.
*
* @return int value of the elements
*/
public int hashCommonElements() {
return Objects.hash(componentManufacturer, componentModel,
componentSerial, componentRevision, componentClass);
}
/**
* Hash method for the attributes of this class.
* @return int value that represents this class
*/
@Override
public int hashCode() {
return Objects.hash(deviceName, componentManufacturer,
componentModel, componentSerial, componentRevision,
componentClass);
}
}

View File

@ -10,46 +10,41 @@ import lombok.extern.log4j.Log4j2;
import java.io.Serializable;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Objects;
/**
* This class is used to represent the network info of a device.
*/
@Log4j2
@Embeddable
@EqualsAndHashCode
public class NetworkInfo implements Serializable {
private static final int NUM_MAC_ADDRESS_BYTES = 6;
@XmlElement
@Getter
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = true)
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH)
private String hostname;
@XmlElement
@Getter
// @XmlJavaTypeAdapter(value = InetAddressXmlAdapter.class)
@Column(length = DeviceInfoEnums.SHORT_STRING_LENGTH, nullable = true)
@Column(length = DeviceInfoEnums.SHORT_STRING_LENGTH)
// @JsonSubTypes.Type(type = "hirs.data.persist.type.InetAddressType")
private InetAddress ipAddress;
@XmlElement
@Column(length = NUM_MAC_ADDRESS_BYTES, nullable = true)
@SuppressWarnings("checkstyle:magicnumber")
@Column(length = NUM_MAC_ADDRESS_BYTES)
private byte[] macAddress;
/**
* Constructor used to create a NetworkInfo object.
*
* @param hostname
* String representing the hostname information for the device,
* @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,
* @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
* @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,
@ -82,16 +77,6 @@ public class NetworkInfo implements Serializable {
}
}
private void setHostname(final String hostname) {
log.debug("setting hostname to: {}", hostname);
this.hostname = hostname;
}
private void setIpAddress(final InetAddress ipAddress) {
log.debug("setting IP address to: {}", ipAddress);
this.ipAddress = ipAddress;
}
private void setMacAddress(final byte[] macAddress) {
StringBuilder sb;
if (macAddress == null) {
@ -114,22 +99,13 @@ public class NetworkInfo implements Serializable {
this.macAddress = macAddress;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof NetworkInfo)) {
return false;
}
NetworkInfo that = (NetworkInfo) o;
return Objects.equals(hostname, that.hostname)
&& Objects.equals(ipAddress, that.ipAddress)
&& Arrays.equals(macAddress, that.macAddress);
private void setHostname(final String hostname) {
log.debug("setting hostname to: {}", hostname);
this.hostname = hostname;
}
@Override
public int hashCode() {
int result = Objects.hash(hostname, ipAddress);
result = 31 * result + Arrays.hashCode(macAddress);
return result;
private void setIpAddress(final InetAddress ipAddress) {
log.debug("setting IP address to: {}", ipAddress);
this.ipAddress = ipAddress;
}
}

View File

@ -47,16 +47,11 @@ public class OSInfo implements Serializable {
* 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)
* @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,

View File

@ -38,6 +38,7 @@ public class RIMInfo implements Serializable {
/**
* 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

View File

@ -68,27 +68,17 @@ public class TPMInfo implements Serializable {
/**
* Constructor used to create a TPMInfo object.
*
* @param tpmMake
* String representing the make information for the TPM,
* @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
* @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,
@ -109,25 +99,16 @@ public class TPMInfo implements Serializable {
* Constructor used to create a TPMInfo object without an identity
* certificate.
*
* @param tpmMake
* String representing the make information for the TPM,
* @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
* @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,
@ -146,17 +127,12 @@ public class TPMInfo implements Serializable {
* Constructor used to create a TPMInfo object without an identity
* certificate.
*
* @param tpmMake
* String representing the make information for the TPM,
* @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 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,
@ -170,19 +146,13 @@ public class TPMInfo implements Serializable {
* Constructor used to create a TPMInfo object without an identity
* certificate.
*
* @param tpmMake
* String representing the make information for the TPM,
* @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 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,
@ -217,30 +187,67 @@ public class TPMInfo implements Serializable {
return identityCertificate;
}
private void setIdentityCertificate(
final X509Certificate identityCertificate) {
if (identityCertificate == null) {
log.error("identity certificate cannot be null");
throw new NullPointerException("identityCertificate");
}
log.debug("setting identity certificate");
this.identityCertificate = identityCertificate;
}
/**
* Getter for the tpmQuote passed up by the client.
*
* @return a byte blob of quote
*/
public final byte[] getTpmQuoteHash() {
return tpmQuoteHash.clone();
}
private void setTpmQuoteHash(final byte[] tpmQuoteHash) {
if (tpmQuoteHash == null) {
this.tpmQuoteHash = new byte[0];
} else {
this.tpmQuoteHash = tpmQuoteHash.clone();
}
}
/**
* Getter for the quote signature.
*
* @return a byte blob.
*/
public final byte[] getTpmQuoteSignature() {
return tpmQuoteSignature.clone();
}
private void setTpmQuoteSignature(final byte[] tpmQuoteSignature) {
if (tpmQuoteSignature == null) {
this.tpmQuoteSignature = new byte[0];
} else {
this.tpmQuoteSignature = tpmQuoteSignature.clone();
}
}
/**
* Getter for the pcr values.
*
* @return a byte blob for the pcrValues.
*/
public final byte[] getPcrValues() {
return pcrValues.clone();
}
private void setPcrValues(final byte[] pcrValues) {
if (pcrValues == null) {
this.pcrValues = new byte[0];
} else {
this.pcrValues = pcrValues.clone();
}
}
private void setTPMMake(final String tpmMake) {
log.debug("setting TPM make info: {}", tpmMake);
this.tpmMake = StringValidator.check(tpmMake, "tpmMake")
@ -292,38 +299,4 @@ public class TPMInfo implements Serializable {
tpmVersionRevMinor);
this.tpmVersionRevMinor = tpmVersionRevMinor;
}
private void setIdentityCertificate(
final X509Certificate identityCertificate) {
if (identityCertificate == null) {
log.error("identity certificate cannot be null");
throw new NullPointerException("identityCertificate");
}
log.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();
}
}
}

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.entity.userdefined.info.component;

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.entity.userdefined.info;

View File

@ -26,7 +26,7 @@ import org.apache.commons.codec.binary.Hex;
@Log4j2
@Getter
@ToString
@EqualsAndHashCode
@EqualsAndHashCode(callSuper = false)
@Embeddable
@XmlAccessorType(XmlAccessType.FIELD)
public final class TPMMeasurementRecord extends ExaminableRecord {
@ -51,7 +51,6 @@ public final class TPMMeasurementRecord extends ExaminableRecord {
*/
public static final int SHA_256_BYTE_LENGTH = 64;
@Column(name = "pcr", nullable = false)
@XmlAttribute(name = "PcrNumber", required = true)
private final int pcrId;
@ -63,8 +62,7 @@ public final class TPMMeasurementRecord extends ExaminableRecord {
* Constructor initializes values associated with TPMMeasurementRecord.
*
* @param pcrId is the TPM PCR index. pcrId must be between 0 and 23.
* @param hash
* represents the measurement digest found at the particular PCR
* @param hash represents the measurement digest found at the particular PCR
* index.
* @throws IllegalArgumentException if pcrId is not valid
*/
@ -105,11 +103,19 @@ public final class TPMMeasurementRecord extends ExaminableRecord {
this(pcrId, new Digest(hash));
}
/**
* Default constructor necessary for Hibernate.
*/
private TPMMeasurementRecord() {
super();
this.pcrId = -1;
this.hash = null;
}
/**
* Helper method to determine if a PCR ID number is valid.
*
* @param pcrId
* int to check
* @param pcrId int to check
*/
public static void checkForValidPcrId(final int pcrId) {
if (pcrId < MIN_PCR_ID || pcrId > MAX_PCR_ID) {
@ -118,13 +124,4 @@ public final class TPMMeasurementRecord extends ExaminableRecord {
throw new IllegalArgumentException(msg);
}
}
/**
* Default constructor necessary for Hibernate.
*/
protected TPMMeasurementRecord() {
super();
this.pcrId = -1;
this.hash = null;
}
}

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.entity.userdefined.record;

View File

@ -1,5 +1,6 @@
package hirs.attestationca.persist.entity.userdefined.report;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hirs.attestationca.persist.entity.AbstractEntity;
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
@ -13,6 +14,8 @@ import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.Transient;
import jakarta.xml.bind.annotation.XmlElement;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -20,16 +23,19 @@ import lombok.extern.log4j.Log4j2;
import java.io.Serializable;
import java.net.InetAddress;
import java.util.Objects;
/**
* 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.
*/
@Log4j2
@SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE",
justification = "various class properties here are guaranteed to always be non-null/initialized."
+ " Warning stems from auto-generated lombok equals and hashcode method doing redundant "
+ "null checks.")
@NoArgsConstructor
@Getter
@EqualsAndHashCode(callSuper = false)
@Log4j2
@Entity
public class DeviceInfoReport extends AbstractEntity implements Serializable {
@ -49,14 +55,18 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
@Embedded
private HardwareInfo hardwareInfo;
@Setter(AccessLevel.PRIVATE)
@Getter
@XmlElement
@Embedded
private TPMInfo tpmInfo;
@Getter
@XmlElement
@Column(nullable = false)
private String clientApplicationVersion;
@Getter
@Setter
@XmlElement
@Transient
@ -67,16 +77,11 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
* 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
* @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,
@ -90,20 +95,14 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
* 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
* @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
* @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,
@ -112,7 +111,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
setOSInfo(osInfo);
setFirmwareInfo(firmwareInfo);
setHardwareInfo(hardwareInfo);
setTPMInfo(tpmInfo);
setTpmInfo(tpmInfo);
this.clientApplicationVersion = clientApplicationVersion;
}
@ -135,6 +134,14 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
networkInfo.getIpAddress(), networkInfo.getMacAddress());
}
private void setNetworkInfo(final NetworkInfo networkInfo) {
if (networkInfo == null) {
log.error("NetworkInfo cannot be null");
throw new NullPointerException("network info");
}
this.networkInfo = networkInfo;
}
/**
* Retrieves the OSInfo for this <code>DeviceInfoReport</code>.
*
@ -154,6 +161,14 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
return osInfo;
}
private void setOSInfo(final OSInfo osInfo) {
if (osInfo == null) {
log.error("OSInfo cannot be null");
throw new NullPointerException("os info");
}
this.osInfo = osInfo;
}
/**
* Retrieves the FirmwareInfo for this <code>DeviceInfoReport</code>.
*
@ -172,6 +187,14 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
return firmwareInfo;
}
private void setFirmwareInfo(final FirmwareInfo firmwareInfo) {
if (firmwareInfo == null) {
log.error("FirmwareInfo cannot be null");
throw new NullPointerException("firmware info");
}
this.firmwareInfo = firmwareInfo;
}
/**
* Retrieves the OSInfo for this <code>DeviceInfoReport</code>.
*
@ -196,30 +219,6 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
return hardwareInfo;
}
private void setNetworkInfo(final NetworkInfo networkInfo) {
if (networkInfo == null) {
log.error("NetworkInfo cannot be null");
throw new NullPointerException("network info");
}
this.networkInfo = networkInfo;
}
private void setOSInfo(final OSInfo osInfo) {
if (osInfo == null) {
log.error("OSInfo cannot be null");
throw new NullPointerException("os info");
}
this.osInfo = osInfo;
}
private void setFirmwareInfo(final FirmwareInfo firmwareInfo) {
if (firmwareInfo == null) {
log.error("FirmwareInfo cannot be null");
throw new NullPointerException("firmware info");
}
this.firmwareInfo = firmwareInfo;
}
private void setHardwareInfo(final HardwareInfo hardwareInfo) {
if (hardwareInfo == null) {
log.error("HardwareInfo cannot be null");
@ -227,31 +226,6 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
}
this.hardwareInfo = hardwareInfo;
}
private void setTPMInfo(final TPMInfo tpmInfo) {
this.tpmInfo = tpmInfo;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DeviceInfoReport)) {
return false;
}
DeviceInfoReport that = (DeviceInfoReport) o;
return Objects.equals(networkInfo, that.networkInfo)
&& Objects.equals(osInfo, that.osInfo)
&& Objects.equals(firmwareInfo, that.firmwareInfo)
&& Objects.equals(hardwareInfo, that.hardwareInfo)
&& Objects.equals(tpmInfo, that.tpmInfo)
&& Objects.equals(clientApplicationVersion, that.clientApplicationVersion)
&& Objects.equals(paccorOutputString, that.paccorOutputString);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), networkInfo, osInfo,
firmwareInfo, hardwareInfo, tpmInfo,
clientApplicationVersion, paccorOutputString);
}
}

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.entity.userdefined.report;

View File

@ -6,11 +6,27 @@ import lombok.Setter;
/**
* An <code>CertificateValidationResult</code> represents the result of a certificate validation
* operation.
*
*/
@Getter
@Setter
public class CertificateValidationResult {
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;
}
/**
* Enum used to represent certificate validation status.
*/
@ -31,21 +47,4 @@ public class CertificateValidationResult {
*/
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;
}
}

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.entity.userdefined.result;

View File

@ -10,6 +10,7 @@ import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.UnmarshalException;
import jakarta.xml.bind.Unmarshaller;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -33,7 +34,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
*
@ -42,6 +42,7 @@ import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(callSuper = true)
@Entity
public class BaseReferenceManifest extends ReferenceManifest {
/**
@ -53,43 +54,60 @@ public class BaseReferenceManifest extends ReferenceManifest {
@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 rimBytes - the file content of the uploaded file.
* @throws IOException - thrown if the file is invalid.
* @throws UnmarshalException - thrown if the file is invalid.
*/
public BaseReferenceManifest(final byte[] rimBytes) throws UnmarshalException {
this("", rimBytes);
@ -101,7 +119,7 @@ public class BaseReferenceManifest extends ReferenceManifest {
*
* @param fileName - string representation of the uploaded file.
* @param rimBytes byte array representation of the RIM
* @throws IOException if unable to unmarshal the string
* @throws UnmarshalException if unable to unmarshal the string
*/
public BaseReferenceManifest(final String fileName, final byte[] rimBytes)
throws UnmarshalException {
@ -205,6 +223,9 @@ public class BaseReferenceManifest extends ReferenceManifest {
* This method validates the .swidtag file at the given filepath against the
* schema. A successful validation results in the output of the tag's name
* and tagId attributes, otherwise a generic error message is printed.
*
* @param rimBytes byte array representation of the RIM
* @return an element
*/
private Element getDirectoryTag(final byte[] rimBytes) {
if (rimBytes == null || rimBytes.length == 0) {
@ -220,13 +241,14 @@ public class BaseReferenceManifest extends ReferenceManifest {
* and tagId attributes, otherwise a generic error message is printed.
*
* @param byteArrayInputStream the location of the file to be validated
* @return an element
*/
private Element getDirectoryTag(final ByteArrayInputStream byteArrayInputStream) {
Document document = null;
try {
document = unmarshallSwidTag(byteArrayInputStream);
} catch (UnmarshalException e) {
log.error("Error while parsing Directory tag: " + e.getMessage());
log.error("Error while parsing Directory tag: {}", e.getMessage());
}
if (document != null) {
Element softwareIdentity =
@ -246,7 +268,9 @@ public class BaseReferenceManifest extends ReferenceManifest {
}
/**
* This method iterates over the list of File elements under the directory. *
* This method iterates over the list of File elements under the directory.
*
* @return a list of swid resources
*/
public List<SwidResource> getFileResources() {
return getFileResources(getRimBytes());
@ -256,6 +280,7 @@ public class BaseReferenceManifest extends ReferenceManifest {
* This method iterates over the list of File elements under the directory.
*
* @param rimBytes the bytes to find the files
* @return a list of swid resources
*/
public List<SwidResource> getFileResources(final byte[] rimBytes) {
Element directoryTag = getDirectoryTag(rimBytes);
@ -352,49 +377,11 @@ public class BaseReferenceManifest extends ReferenceManifest {
return document;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
BaseReferenceManifest that = (BaseReferenceManifest) o;
return swidCorpus == that.swidCorpus && Objects.equals(swidName, that.swidName)
&& Objects.equals(colloquialVersion, that.colloquialVersion)
&& Objects.equals(product, that.product)
&& Objects.equals(revision, that.revision)
&& Objects.equals(edition, that.edition)
&& Objects.equals(rimLinkHash, that.rimLinkHash)
&& Objects.equals(bindingSpec, that.bindingSpec)
&& Objects.equals(bindingSpecVersion, that.bindingSpecVersion)
&& Objects.equals(platformVersion, that.platformVersion)
&& Objects.equals(payloadType, that.payloadType)
&& Objects.equals(pcURIGlobal, that.pcURIGlobal)
&& Objects.equals(pcURILocal, that.pcURILocal)
&& Objects.equals(entityName, that.entityName)
&& Objects.equals(entityRegId, that.entityRegId)
&& Objects.equals(entityRole, that.entityRole)
&& Objects.equals(entityThumbprint, that.entityThumbprint)
&& Objects.equals(linkHref, that.linkHref)
&& Objects.equals(linkRel, that.linkRel);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), swidName,
swidCorpus, colloquialVersion, product,
revision, edition, rimLinkHash, bindingSpec,
bindingSpecVersion, platformVersion,
payloadType, pcURIGlobal, pcURILocal,
entityName, entityRegId, entityRole,
entityThumbprint, linkHref, linkRel);
}
/**
* Creates a string representation of the Base Reference Manifest object.
*
* @return a string representation of the Base Reference Manifest object.
*/
@Override
public String toString() {
return String.format("ReferenceManifest{swidName=%s,"

View File

@ -1,7 +1,6 @@
package hirs.attestationca.persist.entity.userdefined.rim;
import com.fasterxml.jackson.annotation.JsonIgnore;
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
import hirs.attestationca.persist.enums.AppraisalStatus;
import hirs.utils.tpm.eventlog.TCGEventLog;
import hirs.utils.tpm.eventlog.TpmPcrEvent;
@ -9,6 +8,7 @@ import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
@ -25,16 +25,18 @@ import java.util.Collection;
* Similar to {@link SupportReferenceManifest}
* however this is the live log from the client.
*/
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
@Log4j2
@Entity
public class EventLogMeasurements extends SupportReferenceManifest {
@Column
@JsonIgnore
@Getter @Setter
private int pcrHash = 0;
@Enumerated(EnumType.STRING)
@Getter @Setter
private AppraisalStatus.Status overallValidationResult = AppraisalStatus.Status.FAIL;
/**
@ -74,6 +76,7 @@ public class EventLogMeasurements extends SupportReferenceManifest {
/**
* Getter method for the expected PCR values contained within the support
* RIM.
*
* @return a string array of the pcr values.
*/
public String[] getExpectedPCRList() {
@ -81,12 +84,8 @@ public class EventLogMeasurements extends SupportReferenceManifest {
TCGEventLog logProcessor = new TCGEventLog(this.getRimBytes());
this.pcrHash = Arrays.hashCode(logProcessor.getExpectedPCRValues());
return logProcessor.getExpectedPCRValues();
} catch (CertificateException cEx) {
log.error(cEx);
} catch (NoSuchAlgorithmException noSaEx) {
log.error(noSaEx);
} catch (IOException ioEx) {
log.error(ioEx);
} catch (CertificateException | NoSuchAlgorithmException | IOException exception) {
log.error(exception);
}
return new String[0];
@ -102,32 +101,10 @@ public class EventLogMeasurements extends SupportReferenceManifest {
try {
logProcessor = new TCGEventLog(this.getRimBytes());
return logProcessor.getEventList();
} catch (CertificateException cEx) {
log.error(cEx);
} catch (NoSuchAlgorithmException noSaEx) {
log.error(noSaEx);
} catch (IOException ioEx) {
log.error(ioEx);
} catch (CertificateException | NoSuchAlgorithmException | IOException exception) {
log.error(exception);
}
return new ArrayList<>();
}
@Override
public boolean equals(final Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
EventLogMeasurements that = (EventLogMeasurements) object;
return this.getHexDecHash().equals(that.getHexDecHash());
}
@Override
public int hashCode() {
return super.hashCode();
}
}

View File

@ -6,9 +6,9 @@ import jakarta.persistence.AccessType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@ -22,6 +22,7 @@ import java.util.UUID;
* Digest Value, Event Type, index, RIM Tagid
*/
@Getter
@Setter
@Builder
@AllArgsConstructor
@Entity
@ -29,41 +30,42 @@ import java.util.UUID;
@Table(name = "ReferenceDigestValue")
@Access(AccessType.FIELD)
public class ReferenceDigestValue extends AbstractEntity {
@Setter
@JdbcTypeCode(java.sql.Types.VARCHAR)
@Column
private UUID baseRimId;
@Setter
@JdbcTypeCode(java.sql.Types.VARCHAR)
@Column
private UUID supportRimId;
@Setter
@Column(nullable = false)
private String manufacturer;
@Setter
@Column(nullable = false)
private String model;
@Setter
@Column(nullable = false)
private int pcrIndex;
@Setter
@Column(nullable = false)
private String digestValue;
@Setter
@Column(nullable = false)
private String supportRimHash;
@Setter
@Column(nullable = false)
private String eventType;
@Column(columnDefinition = "blob", nullable = true)
@Setter(AccessLevel.NONE)
@Column(columnDefinition = "blob")
private byte[] contentBlob;
@Setter
@Column(nullable = false)
private boolean matchFail;
@Setter
@Column(nullable = false)
private boolean patched;
@Setter
@Column(nullable = false)
private boolean updated;
@ -88,6 +90,7 @@ public class ReferenceDigestValue extends AbstractEntity {
/**
* Default Constructor with parameters for all associated data.
*
* @param baseRimId the UUID of the associated record
* @param supportRimId the UUID of the associated record
* @param manufacturer associated creator for this information
@ -108,6 +111,8 @@ public class ReferenceDigestValue extends AbstractEntity {
final String eventType, final boolean matchFail,
final boolean patched, final boolean updated,
final byte[] contentBlob) {
this.baseRimId = baseRimId;
this.supportRimId = supportRimId;
this.manufacturer = manufacturer;
@ -122,16 +127,9 @@ public class ReferenceDigestValue extends AbstractEntity {
this.contentBlob = Arrays.clone(contentBlob);
}
/**
* the object that contains the raw bytes for this RDV.
* @return the raw bytes
*/
public byte[] getContentBlob() {
return Arrays.clone(contentBlob);
}
/**
* Helper method to update the attributes of this object.
*
* @param support the associated RIM.
* @param baseRimId the main id to update
*/
@ -151,6 +149,7 @@ public class ReferenceDigestValue extends AbstractEntity {
/**
* Returns a string of the classes fields.
*
* @return a string
*/
public String toString() {

View File

@ -6,6 +6,7 @@ import hirs.utils.tpm.eventlog.TCGEventLog;
import hirs.utils.tpm.eventlog.TpmPcrEvent;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
@ -16,7 +17,6 @@ import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
/**
* Sub class that will just focus on PCR Values and Events.
@ -24,12 +24,14 @@ import java.util.Objects;
@Log4j2
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@Entity
public class SupportReferenceManifest extends ReferenceManifest {
@Column
@JsonIgnore
private int pcrHash = 0;
@Column
private boolean updated = false;
@ -71,6 +73,7 @@ public class SupportReferenceManifest extends ReferenceManifest {
/**
* Getter method for the expected PCR values contained within the support
* RIM.
*
* @return a string array of the pcr values.
*/
public String[] getExpectedPCRList() {
@ -78,12 +81,8 @@ public class SupportReferenceManifest extends ReferenceManifest {
TCGEventLog logProcessor = new TCGEventLog(this.getRimBytes());
this.pcrHash = Arrays.hashCode(logProcessor.getExpectedPCRValues());
return logProcessor.getExpectedPCRValues();
} catch (CertificateException cEx) {
log.error(cEx);
} catch (NoSuchAlgorithmException noSaEx) {
log.error(noSaEx);
} catch (IOException ioEx) {
log.error(ioEx);
} catch (CertificateException | NoSuchAlgorithmException | IOException exception) {
log.error(exception);
}
return new String[0];
@ -99,12 +98,8 @@ public class SupportReferenceManifest extends ReferenceManifest {
try {
logProcessor = new TCGEventLog(this.getRimBytes());
return logProcessor.getEventList();
} catch (CertificateException cEx) {
log.error(cEx);
} catch (NoSuchAlgorithmException noSaEx) {
log.error(noSaEx);
} catch (IOException ioEx) {
log.error(ioEx);
} catch (CertificateException | NoSuchAlgorithmException | IOException exception) {
log.error(exception);
}
return new ArrayList<>();
@ -113,23 +108,10 @@ public class SupportReferenceManifest extends ReferenceManifest {
/**
* This is a method to indicate whether or not this support
* rim is a base log file.
*
* @return flag for base.
*/
public boolean isBaseSupport() {
return !this.isSwidSupplemental() && !this.isSwidPatch();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
SupportReferenceManifest that = (SupportReferenceManifest) o;
return pcrHash == that.pcrHash && updated == that.updated;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), pcrHash, updated);
}
}

View File

@ -9,6 +9,35 @@ import lombok.Setter;
@Getter
@Setter
public class AppraisalStatus {
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;
}
/**
* Enum used to represent appraisal status.
*/
@ -33,31 +62,4 @@ public class AppraisalStatus {
*/
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;
}
}

View File

@ -1,11 +1,18 @@
package hirs.attestationca.persist.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
* <code>HealthStatus</code> is used to represent the health of a device.
*/
@Getter
@AllArgsConstructor
@ToString
public enum HealthStatus {
/**
* The trusted state, no issues with the device.
@ -22,32 +29,14 @@ public enum HealthStatus {
*/
UNKNOWN("unknown");
private String healthStatus;
private final String healthStatus;
/**
* Creates a new <code>HealthStatus</code> object given a String.
* Determines if the provided health status is a valid health status.
*
* @param healthStatus
* "trusted", "untrusted", or "unknown"
* @param healthStatus string representation of the healh status
* @return true if the health status is valid, otherwise false
*/
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)

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.exceptions;

View File

@ -0,0 +1 @@
package hirs.attestationca.persist;

View File

@ -43,20 +43,21 @@ import java.util.Date;
import java.util.LinkedList;
import java.util.List;
@Getter
@Log4j2
@NoArgsConstructor
public class AbstractProcessor {
@Getter
private int validDays;
@Getter
private PrivateKey privateKey;
@Setter
@Getter
private PolicyRepository policyRepository;
/**
* Default constructor that sets main class fields.
*
* @param privateKey private key used for communication authentication
* @param validDays property value to set for issued certificates
*/
@ -79,7 +80,8 @@ public class AbstractProcessor {
protected X509Certificate generateCredential(final PublicKey publicKey,
final EndorsementCredential endorsementCredential,
final List<PlatformCredential> platformCredentials,
final String deviceName, final X509Certificate acaCertificate) {
final String deviceName,
final X509Certificate acaCertificate) {
try {
// have the certificate expire in the configured number of days
Calendar expiry = Calendar.getInstance();
@ -210,6 +212,7 @@ public class AbstractProcessor {
/**
* Gets the Endorsement Credential from the DB given the EK public key.
*
* @param ekPublicKey the EK public key
* @param certificateRepository db store manager for certificates
* @return the Endorsement credential, if found, otherwise null
@ -261,7 +264,8 @@ public class AbstractProcessor {
final byte[] derEncodedAttestationCertificate,
final EndorsementCredential endorsementCredential,
final List<PlatformCredential> platformCredentials,
final Device device, boolean isLDevID) {
final Device device,
final boolean isLDevID) {
List<IssuedAttestationCertificate> issuedAc;
boolean generateCertificate = true;
PolicyRepository scp = getPolicyRepository();
@ -277,23 +281,22 @@ public class AbstractProcessor {
policySettings = scp.findByName("Default");
Sort sortCriteria = Sort.by(Sort.Direction.DESC, "endValidity");
issuedAc = certificateRepository.findByDeviceIdAndIsLDevID(device.getId(), isLDevID, sortCriteria);
issuedAc = certificateRepository.findByDeviceIdAndIsLDevID(device.getId(), isLDevID,
sortCriteria);
generateCertificate = isLDevID ? policySettings.isIssueDevIdCertificate()
: policySettings.isIssueAttestationCertificate();
if (issuedAc != null && issuedAc.size() > 0 && (isLDevID ? policySettings.isDevIdExpirationFlag()
if (issuedAc != null && issuedAc.size() > 0
&& (isLDevID ? policySettings.isDevIdExpirationFlag()
: policySettings.isGenerateOnExpiration())) {
if (issuedAc.get(0).getEndValidity().after(currentDate)) {
// so the issued AC is not expired
// however are we within the threshold
days = ProvisionUtils.daysBetween(currentDate, issuedAc.get(0).getEndValidity());
if (days < Integer.parseInt(isLDevID ? policySettings.getDevIdReissueThreshold()
: policySettings.getReissueThreshold())) {
generateCertificate = true;
} else {
generateCertificate = false;
}
generateCertificate =
days < Integer.parseInt(isLDevID ? policySettings.getDevIdReissueThreshold()
: policySettings.getReissueThreshold());
}
}
}

View File

@ -1,6 +1,5 @@
package hirs.attestationca.persist.provision;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
@ -30,14 +29,15 @@ import java.util.List;
@Log4j2
public class CertificateRequestProcessor extends AbstractProcessor {
private SupplyChainValidationService supplyChainValidationService;
private CertificateRepository certificateRepository;
private DeviceRepository deviceRepository;
private X509Certificate acaCertificate;
private TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
private final SupplyChainValidationService supplyChainValidationService;
private final CertificateRepository certificateRepository;
private final DeviceRepository deviceRepository;
private final X509Certificate acaCertificate;
private final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
/**
* Constructor.
*
* @param supplyChainValidationService object that is used to run provisioning
* @param certificateRepository db connector for all certificates.
* @param deviceRepository database connector for Devices.
@ -167,10 +167,11 @@ public class CertificateRequestProcessor extends AbstractProcessor {
// We validated the nonce and made use of the identity claim so state can be deleted
tpm2ProvisionerStateRepository.delete(tpm2ProvisionerState);
boolean generateAtt = saveAttestationCertificate(certificateRepository, derEncodedAttestationCertificate,
boolean generateAtt = saveAttestationCertificate(certificateRepository,
derEncodedAttestationCertificate,
endorsementCredential, platformCredentials, device, false);
boolean generateLDevID = saveAttestationCertificate(certificateRepository, derEncodedLdevidCertificate,
boolean generateLDevID =
saveAttestationCertificate(certificateRepository, derEncodedLdevidCertificate,
endorsementCredential, platformCredentials, device, true);
ProvisionerTpm2.CertificateResponse.Builder builder = ProvisionerTpm2.CertificateResponse.
@ -184,8 +185,7 @@ public class CertificateRequestProcessor extends AbstractProcessor {
ProvisionerTpm2.CertificateResponse response = builder.build();
return response.toByteArray();
}
else {
} else {
byte[] derEncodedAttestationCertificate = ProvisionUtils.getDerEncodedCertificate(
attestationCertificate);
String pemEncodedAttestationCertificate = ProvisionUtils.getPemEncodedCertificate(
@ -197,7 +197,8 @@ public class CertificateRequestProcessor extends AbstractProcessor {
ProvisionerTpm2.CertificateResponse.Builder builder = ProvisionerTpm2.CertificateResponse.
newBuilder().setStatus(ProvisionerTpm2.ResponseStatus.PASS);
boolean generateAtt = saveAttestationCertificate(certificateRepository, derEncodedAttestationCertificate,
boolean generateAtt = saveAttestationCertificate(certificateRepository,
derEncodedAttestationCertificate,
endorsementCredential, platformCredentials, device, false);
if (generateAtt) {
builder = builder.setCertificate(pemEncodedAttestationCertificate);
@ -218,7 +219,7 @@ public class CertificateRequestProcessor extends AbstractProcessor {
}
} else {
log.error("Could not process credential request. Invalid nonce provided: "
+ request.getNonce().toString());
+ request.getNonce());
throw new CertificateProcessingException("Invalid nonce given in request by client.");
}
}

View File

@ -1,6 +1,5 @@
package hirs.attestationca.persist.provision;
import com.fasterxml.jackson.databind.ser.Serializers;
import com.google.protobuf.ByteString;
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
@ -69,27 +68,36 @@ import java.util.regex.Pattern;
@Log4j2
public class IdentityClaimProcessor extends AbstractProcessor {
private static final String PCR_QUOTE_MASK = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,"
+ "14,15,16,17,18,19,20,21,22,23";
private static final int NUM_OF_VARIABLES = 5;
/**
* Number of bytes to include in the TPM2.0 nonce.
*/
public static final int NONCE_LENGTH = 20;
private static final String PCR_QUOTE_MASK = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,"
+ "14,15,16,17,18,19,20,21,22,23";
private static final int NUM_OF_VARIABLES = 5;
private static final int MAC_BYTES = 6;
private SupplyChainValidationService supplyChainValidationService;
private CertificateRepository certificateRepository;
private ComponentResultRepository componentResultRepository;
private ComponentInfoRepository componentInfoRepository;
private ReferenceManifestRepository referenceManifestRepository;
private ReferenceDigestValueRepository referenceDigestValueRepository;
private DeviceRepository deviceRepository;
private TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
private final SupplyChainValidationService supplyChainValidationService;
private final CertificateRepository certificateRepository;
private final ComponentResultRepository componentResultRepository;
private final ComponentInfoRepository componentInfoRepository;
private final ReferenceManifestRepository referenceManifestRepository;
private final ReferenceDigestValueRepository referenceDigestValueRepository;
private final DeviceRepository deviceRepository;
private final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
/**
* Constructor.
*
* @param supplyChainValidationService supply chain validation service
* @param certificateRepository certificate repository
* @param componentResultRepository component result repository
* @param componentInfoRepository component info repository
* @param referenceManifestRepository reference manifest repository
* @param referenceDigestValueRepository reference digest value repository
* @param deviceRepository device repository
* @param tpm2ProvisionerStateRepository tpm2 provisioner state repository
* @param policyRepository policy repository
*/
public IdentityClaimProcessor(
final SupplyChainValidationService supplyChainValidationService,
@ -117,7 +125,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
* stores the device info, performs supply chain validation, generates a nonce,
* and wraps that nonce with the make credential process before returning it to the client.
* attCert.setPcrValues(pcrValues);
*
* @param identityClaim the request to process, cannot be null
* @return an identity claim response for the specified request containing a wrapped blob
*/
@ -157,8 +165,8 @@ public class IdentityClaimProcessor extends AbstractProcessor {
String pcrQuoteMask = PCR_QUOTE_MASK;
String strNonce = HexUtils.byteArrayToHexString(nonce);
log.info("Sending nonce: " + strNonce);
log.info("Persisting claim of length: " + identityClaim.length);
log.info("Sending nonce: {}", strNonce);
log.info("Persisting claim of length: {}", identityClaim.length);
tpm2ProvisionerStateRepository.save(new TPM2ProvisionerState(nonce, identityClaim));
@ -173,8 +181,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
.build();
return response.toByteArray();
} else {
log.error("Supply chain validation did not succeed. Result is: "
+ validationResult);
log.error("Supply chain validation did not succeed. Result is: {}", validationResult);
// empty response
ProvisionerTpm2.IdentityClaimResponse response
= ProvisionerTpm2.IdentityClaimResponse.newBuilder()
@ -195,7 +202,8 @@ public class IdentityClaimProcessor extends AbstractProcessor {
private AppraisalStatus.Status doSupplyChainValidation(
final ProvisionerTpm2.IdentityClaim claim, final PublicKey ekPub) {
// attempt to find an endorsement credential to validate
EndorsementCredential endorsementCredential = parseEcFromIdentityClaim(claim, ekPub, certificateRepository);
EndorsementCredential endorsementCredential =
parseEcFromIdentityClaim(claim, ekPub, certificateRepository);
// attempt to find platform credentials to validate
List<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,
@ -283,10 +291,10 @@ public class IdentityClaimProcessor extends AbstractProcessor {
/**
* Converts a protobuf DeviceInfo object to a HIRS Utils DeviceInfoReport object.
*
* @param claim the protobuf serialized identity claim containing the device info
* @return a HIRS Utils DeviceInfoReport representation of device info
*/
@SuppressWarnings("methodlength")
private DeviceInfoReport parseDeviceInfo(final ProvisionerTpm2.IdentityClaim claim)
throws NoSuchAlgorithmException {
ProvisionerTpm2.DeviceInfo dv = claim.getDv();
@ -348,9 +356,9 @@ public class IdentityClaimProcessor extends AbstractProcessor {
String defaultClientName = String.format("%s_%s",
dv.getHw().getManufacturer(),
dv.getHw().getProductName());
BaseReferenceManifest dbBaseRim = null;
SupportReferenceManifest support = null;
EventLogMeasurements measurements;
BaseReferenceManifest baseRim = null;
SupportReferenceManifest supportRim = null;
EventLogMeasurements integrityMeasurements;
boolean isReplacement = false;
String replacementRimId = "";
String tagId = "";
@ -362,73 +370,73 @@ public class IdentityClaimProcessor extends AbstractProcessor {
if (dv.getSwidfileCount() > 0) {
for (ByteString swidFile : dv.getSwidfileList()) {
try {
dbBaseRim = (BaseReferenceManifest) referenceManifestRepository
baseRim = (BaseReferenceManifest) referenceManifestRepository
.findByBase64Hash(Base64.getEncoder()
.encodeToString(messageDigest
.digest(swidFile.toByteArray())));
if (dbBaseRim == null) {
if (baseRim == null) {
/*
Either the swidFile does not have a corresponding base RIM in the backend
or it was deleted. Check if there is a replacement by comparing tagId against
all other base RIMs, and then set the corresponding support rim's deviceName.
*/
dbBaseRim = new BaseReferenceManifest(
baseRim = new BaseReferenceManifest(
String.format("%s.swidtag",
defaultClientName),
swidFile.toByteArray());
List<BaseReferenceManifest> baseRims = referenceManifestRepository.findAllBaseRims();
for (BaseReferenceManifest bRim : baseRims) {
if (bRim.getTagId().equals(dbBaseRim.getTagId())) {
dbBaseRim = bRim;
replacementRimId = dbBaseRim.getAssociatedRim().toString();
if (bRim.getTagId().equals(baseRim.getTagId())) {
baseRim = bRim;
replacementRimId = baseRim.getAssociatedRim().toString();
isReplacement = true;
break;
}
}
dbBaseRim.setDeviceName(dv.getNw().getHostname());
this.referenceManifestRepository.save(dbBaseRim);
} else if (dbBaseRim.isArchived()) {
baseRim.setDeviceName(dv.getNw().getHostname());
this.referenceManifestRepository.save(baseRim);
} else if (baseRim.isArchived()) {
/*
This block accounts for RIMs that may have been soft-deleted (archived)
in an older version of the ACA.
*/
List<ReferenceManifest> rims = referenceManifestRepository.findByArchiveFlag(false);
for (ReferenceManifest rim : rims) {
if (rim.isBase() && rim.getTagId().equals(dbBaseRim.getTagId()) &&
rim.getCreateTime().after(dbBaseRim.getCreateTime())) {
dbBaseRim.setDeviceName(null);
dbBaseRim = (BaseReferenceManifest) rim;
dbBaseRim.setDeviceName(dv.getNw().getHostname());
if (rim.isBase() && rim.getTagId().equals(baseRim.getTagId())
&& rim.getCreateTime().after(baseRim.getCreateTime())) {
baseRim.setDeviceName(null);
baseRim = (BaseReferenceManifest) rim;
baseRim.setDeviceName(dv.getNw().getHostname());
}
}
if (dbBaseRim.isArchived()) {
if (baseRim.isArchived()) {
throw new Exception("Unable to locate an unarchived base RIM.");
} else {
this.referenceManifestRepository.save(dbBaseRim);
this.referenceManifestRepository.save(baseRim);
}
} else {
dbBaseRim.setDeviceName(dv.getNw().getHostname());
this.referenceManifestRepository.save(dbBaseRim);
baseRim.setDeviceName(dv.getNw().getHostname());
this.referenceManifestRepository.save(baseRim);
}
tagId = dbBaseRim.getTagId();
tagId = baseRim.getTagId();
} catch (UnmarshalException e) {
log.error(e);
} catch (Exception ex) {
log.error(String.format("Failed to load base rim: %s", ex.getMessage()));
log.error("Failed to load base rim: {}", ex.getMessage());
}
}
} else {
log.warn(String.format("%s did not send swid tag file...",
dv.getNw().getHostname()));
log.warn("{} did not send swid tag file...", dv.getNw().getHostname());
}
if (dv.getLogfileCount() > 0) {
for (ByteString logFile : dv.getLogfileList()) {
try {
support = (SupportReferenceManifest) referenceManifestRepository.findByHexDecHashAndRimType(
supportRim =
(SupportReferenceManifest) referenceManifestRepository.findByHexDecHashAndRimType(
Hex.encodeHexString(messageDigest.digest(logFile.toByteArray())),
ReferenceManifest.SUPPORT_RIM);
if (support == null) {
if (supportRim == null) {
/*
Either the logFile does not have a corresponding support RIM in the backend
or it was deleted. The support RIM for a replacement base RIM is handled
@ -438,97 +446,98 @@ public class IdentityClaimProcessor extends AbstractProcessor {
Optional<ReferenceManifest> replacementRim =
referenceManifestRepository.findById(UUID.fromString(replacementRimId));
if (replacementRim.isPresent()) {
support = (SupportReferenceManifest) replacementRim.get();
support.setDeviceName(dv.getNw().getHostname());
supportRim = (SupportReferenceManifest) replacementRim.get();
supportRim.setDeviceName(dv.getNw().getHostname());
} else {
throw new Exception("Unable to locate support RIM " + replacementRimId);
}
} else {
support = new SupportReferenceManifest(
supportRim = new SupportReferenceManifest(
String.format("%s.rimel",
defaultClientName),
logFile.toByteArray());
// this is a validity check
new TCGEventLog(support.getRimBytes());
new TCGEventLog(supportRim.getRimBytes());
// no issues, continue
support.setPlatformManufacturer(dv.getHw().getManufacturer());
support.setPlatformModel(dv.getHw().getProductName());
support.setFileName(String.format("%s_[%s].rimel", defaultClientName,
support.getHexDecHash().substring(
support.getHexDecHash().length() - NUM_OF_VARIABLES)));
supportRim.setPlatformManufacturer(dv.getHw().getManufacturer());
supportRim.setPlatformModel(dv.getHw().getProductName());
supportRim.setFileName(String.format("%s_[%s].rimel", defaultClientName,
supportRim.getHexDecHash().substring(
supportRim.getHexDecHash().length() - NUM_OF_VARIABLES)));
}
support.setDeviceName(dv.getNw().getHostname());
this.referenceManifestRepository.save(support);
} else if (support.isArchived()) {
supportRim.setDeviceName(dv.getNw().getHostname());
this.referenceManifestRepository.save(supportRim);
} else if (supportRim.isArchived()) {
/*
This block accounts for RIMs that may have been soft-deleted (archived)
in an older version of the ACA.
*/
List<ReferenceManifest> rims = referenceManifestRepository.findByArchiveFlag(false);
for (ReferenceManifest rim : rims) {
if (rim.isSupport() &&
rim.getTagId().equals(support.getTagId()) &&
rim.getCreateTime().after(support.getCreateTime())) {
support.setDeviceName(null);
support = (SupportReferenceManifest) rim;
support.setDeviceName(dv.getNw().getHostname());
if (rim.isSupport()
&& rim.getTagId().equals(supportRim.getTagId())
&& rim.getCreateTime().after(supportRim.getCreateTime())) {
supportRim.setDeviceName(null);
supportRim = (SupportReferenceManifest) rim;
supportRim.setDeviceName(dv.getNw().getHostname());
}
}
if (support.isArchived()) {
if (supportRim.isArchived()) {
throw new Exception("Unable to locate an unarchived support RIM.");
} else {
this.referenceManifestRepository.save(support);
this.referenceManifestRepository.save(supportRim);
}
} else {
support.setDeviceName(dv.getNw().getHostname());
this.referenceManifestRepository.save(support);
supportRim.setDeviceName(dv.getNw().getHostname());
this.referenceManifestRepository.save(supportRim);
}
} catch (IOException ioEx) {
log.error(ioEx);
} catch (Exception ex) {
log.error(String.format("Failed to load support rim: %s", ex.getMessage()));
log.error("Failed to load support rim: {}", ex.getMessage());
}
}
} else {
log.warn(String.format("%s did not send support RIM file...",
dv.getNw().getHostname()));
log.warn("{} did not send support RIM file...", dv.getNw().getHostname());
}
//update Support RIMs and Base RIMs.
for (ByteString swidFile : dv.getSwidfileList()) {
dbBaseRim = (BaseReferenceManifest) referenceManifestRepository
baseRim = (BaseReferenceManifest) referenceManifestRepository
.findByBase64Hash(Base64.getEncoder().encodeToString(messageDigest.digest(
swidFile.toByteArray())));
if (dbBaseRim != null) {
if (baseRim != null) {
// get file name to use
for (SwidResource swid : dbBaseRim.getFileResources()) {
for (SwidResource swid : baseRim.getFileResources()) {
matcher = pattern.matcher(swid.getName());
if (matcher.matches()) {
//found the file name
int dotIndex = swid.getName().lastIndexOf(".");
fileName = swid.getName().substring(0, dotIndex);
dbBaseRim.setFileName(String.format("%s.swidtag",
baseRim.setFileName(String.format("%s.swidtag",
fileName));
}
// now update support rim
SupportReferenceManifest dbSupport = (SupportReferenceManifest) referenceManifestRepository
.findByHexDecHashAndRimType(swid.getHashValue(), ReferenceManifest.SUPPORT_RIM);
SupportReferenceManifest dbSupport =
(SupportReferenceManifest) referenceManifestRepository
.findByHexDecHashAndRimType(swid.getHashValue(),
ReferenceManifest.SUPPORT_RIM);
if (dbSupport != null) {
dbSupport.setFileName(swid.getName());
dbSupport.setSwidTagVersion(dbBaseRim.getSwidTagVersion());
dbSupport.setTagId(dbBaseRim.getTagId());
dbSupport.setSwidTagVersion(dbBaseRim.getSwidTagVersion());
dbSupport.setSwidVersion(dbBaseRim.getSwidVersion());
dbSupport.setSwidPatch(dbBaseRim.isSwidPatch());
dbSupport.setSwidSupplemental(dbBaseRim.isSwidSupplemental());
dbBaseRim.setAssociatedRim(dbSupport.getId());
dbSupport.setSwidTagVersion(baseRim.getSwidTagVersion());
dbSupport.setTagId(baseRim.getTagId());
dbSupport.setSwidTagVersion(baseRim.getSwidTagVersion());
dbSupport.setSwidVersion(baseRim.getSwidVersion());
dbSupport.setSwidPatch(baseRim.isSwidPatch());
dbSupport.setSwidSupplemental(baseRim.isSwidSupplemental());
baseRim.setAssociatedRim(dbSupport.getId());
dbSupport.setUpdated(true);
dbSupport.setAssociatedRim(dbBaseRim.getId());
dbSupport.setAssociatedRim(baseRim.getId());
this.referenceManifestRepository.save(dbSupport);
}
}
this.referenceManifestRepository.save(dbBaseRim);
this.referenceManifestRepository.save(baseRim);
}
}
@ -539,40 +548,40 @@ public class IdentityClaimProcessor extends AbstractProcessor {
fileName = String.format("%s.measurement",
dv.getNw().getHostname());
try {
EventLogMeasurements temp = new EventLogMeasurements(fileName,
EventLogMeasurements deviceLiveLog = new EventLogMeasurements(fileName,
dv.getLivelog().toByteArray());
// find previous version.
measurements = referenceManifestRepository
integrityMeasurements = referenceManifestRepository
.byMeasurementDeviceName(dv.getNw().getHostname());
if (measurements != null) {
if (integrityMeasurements != null) {
// Find previous log and delete it
referenceManifestRepository.delete(measurements);
referenceManifestRepository.delete(integrityMeasurements);
}
List<BaseReferenceManifest> baseRims = referenceManifestRepository
.getBaseByManufacturerModel(dv.getHw().getManufacturer(),
dv.getHw().getProductName());
measurements = temp;
measurements.setPlatformManufacturer(dv.getHw().getManufacturer());
measurements.setPlatformModel(dv.getHw().getProductName());
integrityMeasurements = deviceLiveLog;
integrityMeasurements.setPlatformManufacturer(dv.getHw().getManufacturer());
integrityMeasurements.setPlatformModel(dv.getHw().getProductName());
if (tagId != null && !tagId.trim().isEmpty()) {
measurements.setTagId(tagId);
integrityMeasurements.setTagId(tagId);
}
measurements.setDeviceName(dv.getNw().getHostname());
measurements.archive();
integrityMeasurements.setDeviceName(dv.getNw().getHostname());
integrityMeasurements.archive();
this.referenceManifestRepository.save(measurements);
this.referenceManifestRepository.save(integrityMeasurements);
for (BaseReferenceManifest baseRim : baseRims) {
if (baseRim != null) {
for (BaseReferenceManifest bRim : baseRims) {
if (bRim != null) {
// pull the base versions of the swidtag and rimel and set the
// event log hash for use during provision
SupportReferenceManifest sBaseRim = referenceManifestRepository
.getSupportRimEntityById(baseRim.getAssociatedRim());
baseRim.setEventLogHash(temp.getHexDecHash());
sBaseRim.setEventLogHash(temp.getHexDecHash());
referenceManifestRepository.save(baseRim);
.getSupportRimEntityById(bRim.getAssociatedRim());
bRim.setEventLogHash(deviceLiveLog.getHexDecHash());
sBaseRim.setEventLogHash(deviceLiveLog.getHexDecHash());
referenceManifestRepository.save(bRim);
referenceManifestRepository.save(sBaseRim);
}
}
@ -580,8 +589,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
log.error(ioEx);
}
} else {
log.warn(String.format("%s did not send bios measurement log...",
dv.getNw().getHostname()));
log.warn("{} did not send bios measurement log...", dv.getNw().getHostname());
}
// Get TPM info, currently unimplemented
@ -608,11 +616,11 @@ public class IdentityClaimProcessor extends AbstractProcessor {
List<SupportReferenceManifest> patchRims = new ArrayList<>();
List<SupportReferenceManifest> dbSupportRims = this.referenceManifestRepository
.getSupportByManufacturerModel(manufacturer, model);
List<ReferenceDigestValue> sourcedValues = referenceDigestValueRepository
List<ReferenceDigestValue> expectedValues = referenceDigestValueRepository
.findByManufacturerAndModel(manufacturer, model);
Map<String, ReferenceDigestValue> digestValueMap = new HashMap<>();
sourcedValues.stream().forEach((rdv) -> {
expectedValues.stream().forEach((rdv) -> {
digestValueMap.put(rdv.getDigestValue(), rdv);
});
@ -628,11 +636,12 @@ public class IdentityClaimProcessor extends AbstractProcessor {
}
if (baseSupportRim != null
&& referenceDigestValueRepository.findBySupportRimHash(baseSupportRim.getHexDecHash()).isEmpty()) {
&& referenceDigestValueRepository.findBySupportRimHash(baseSupportRim.getHexDecHash())
.isEmpty()) {
try {
TCGEventLog logProcessor = new TCGEventLog(baseSupportRim.getRimBytes());
TCGEventLog eventLog = new TCGEventLog(baseSupportRim.getRimBytes());
ReferenceDigestValue rdv;
for (TpmPcrEvent tpe : logProcessor.getEventList()) {
for (TpmPcrEvent tpe : eventLog.getEventList()) {
rdv = new ReferenceDigestValue(baseSupportRim.getAssociatedRim(),
baseSupportRim.getId(), manufacturer, model, tpe.getPcrIndex(),
tpe.getEventDigestStr(), baseSupportRim.getHexDecHash(),
@ -644,8 +653,8 @@ public class IdentityClaimProcessor extends AbstractProcessor {
// since I have the base already I don't have to care about the backward
// linkage
for (SupportReferenceManifest supplemental : supplementalRims) {
logProcessor = new TCGEventLog(supplemental.getRimBytes());
for (TpmPcrEvent tpe : logProcessor.getEventList()) {
eventLog = new TCGEventLog(supplemental.getRimBytes());
for (TpmPcrEvent tpe : eventLog.getEventList()) {
// all RDVs will have the same base rim
rdv = new ReferenceDigestValue(baseSupportRim.getAssociatedRim(),
supplemental.getId(), manufacturer, model, tpe.getPcrIndex(),
@ -679,14 +688,13 @@ public class IdentityClaimProcessor extends AbstractProcessor {
ReferenceDigestValue dbRdv;
String patchedValue;
for (SupportReferenceManifest patch : patchRims) {
logProcessor = new TCGEventLog(patch.getRimBytes());
for (TpmPcrEvent tpe : logProcessor.getEventList()) {
eventLog = new TCGEventLog(patch.getRimBytes());
for (TpmPcrEvent tpe : eventLog.getEventList()) {
patchedValue = tpe.getEventDigestStr();
dbRdv = digestValueMap.get(patchedValue);
if (dbRdv == null) {
log.error(String.format("Patching value does not exist (%s)",
patchedValue));
log.error("Patching value does not exist ({})", patchedValue);
} else {
// WIP - Until we get patch examples
dbRdv.setPatched(true);

View File

@ -22,6 +22,7 @@ public final class CredentialManagementHelper {
/**
* Parses and stores the EK in the cert manager. If the cert is already present and archived,
* it is unarchived.
*
* @param certificateRepository the certificate manager used for storage
* @param endorsementBytes the raw EK bytes used for parsing
* @param deviceName the host name
@ -63,7 +64,7 @@ public final class CredentialManagementHelper {
if (existingCredential == null) {
log.info("No Endorsement Credential found with hash: " + certificateHash);
endorsementCredential.setDeviceName(deviceName);
return (EndorsementCredential) certificateRepository.save(endorsementCredential);
return certificateRepository.save(endorsementCredential);
} else if (existingCredential.isArchived()) {
// if the EK is stored in the DB and it's archived, unarchive.
log.info("Unarchiving credential");
@ -77,6 +78,7 @@ public final class CredentialManagementHelper {
/**
* Parses and stores the PC in the cert manager. If the cert is already present and archived,
* it is unarchived.
*
* @param certificateRepository the certificate manager used for storage
* @param platformBytes the raw PC bytes used for parsing
* @param deviceName the host name of the associated machine
@ -129,7 +131,7 @@ public final class CredentialManagementHelper {
}
}
platformCredential.setDeviceName(deviceName);
return (PlatformCredential) certificateRepository.save(platformCredential);
return certificateRepository.save(platformCredential);
} else if (existingCredential.isArchived()) {
// if the PC is stored in the DB and it's archived, unarchive.
log.info("Unarchiving credential");

View File

@ -12,6 +12,7 @@ import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
@ -22,7 +23,6 @@ import org.bouncycastle.asn1.x509.GeneralNamesBuilder;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.asn1.x509.TBSCertificate;
import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
import java.io.IOException;
import java.security.cert.CertificateEncodingException;
@ -36,17 +36,16 @@ import java.util.Collection;
@Log4j2
public final class IssuedCertificateAttributeHelper {
/**
* The extended key usage extension.
*/
public static final Extension EXTENDED_KEY_USAGE_EXTENSION;
private static final String TPM_ID_LABEL_OID = "2.23.133.2.15";
/**
* Object Identifier TCPA at TPM ID Label.
*/
public static final ASN1ObjectIdentifier TCPA_AT_TPM_ID_LABEL =
new ASN1ObjectIdentifier(TPM_ID_LABEL_OID);
/**
* The extended key usage extension.
*/
public static final Extension EXTENDED_KEY_USAGE_EXTENSION;
private static final ASN1ObjectIdentifier TCG_KP_AIK_CERTIFICATE_ATTRIBUTE =
new ASN1ObjectIdentifier("2.23.133.8.3");
@ -70,6 +69,7 @@ public final class IssuedCertificateAttributeHelper {
/**
* This method builds the AKI extension that will be stored in the generated
* Attestation Issued Certificate.
*
* @param acaCertificate ACA certificate to pull SKI from, that will be used to build matching AKI.
* @return the AKI extension.
* @throws IOException on bad get instance for SKI.
@ -96,6 +96,7 @@ public final class IssuedCertificateAttributeHelper {
/**
* Builds the subject alternative name based on the supplied certificates.
*
* @param endorsementCredential the endorsement credential
* @param platformCredentials the platform credentials
* @param hostName the host name
@ -181,14 +182,11 @@ public final class IssuedCertificateAttributeHelper {
populateRdnAttributesInNameBuilder(nameBuilder, rdns);
} else {
log.error("No RDNs in endorsement credential attributes");
return;
}
} catch (CertificateEncodingException e) {
log.error("Certificate encoding exception", e);
return;
} catch (IOException e) {
log.error("Error creating x509 cert from endorsement credential", e);
return;
}
}

View File

@ -3,7 +3,6 @@ package hirs.attestationca.persist.provision.helper;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
import hirs.attestationca.persist.entity.userdefined.info.TPMInfo;
import hirs.attestationca.persist.exceptions.CertificateProcessingException;
import hirs.attestationca.persist.exceptions.IdentityProcessingException;
import hirs.attestationca.persist.exceptions.UnexpectedServerException;
@ -14,7 +13,6 @@ import hirs.structs.elements.tpm.IdentityRequest;
import hirs.structs.elements.tpm.SymmetricKey;
import hirs.structs.elements.tpm.SymmetricKeyParams;
import hirs.utils.HexUtils;
import hirs.utils.enums.DeviceInfoEnums;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.ArrayUtils;
@ -56,32 +54,65 @@ public final class ProvisionUtils {
/**
* The default size for IV blocks.
*/
public final static int DEFAULT_IV_SIZE = 16;
public static final int DEFAULT_IV_SIZE = 16;
/**
* HMAC Size Length in bytes.
*/
public static final int HMAC_SIZE_LENGTH_BYTES = 2;
/**
* HMAC key Length in bytes.
*/
public static final int HMAC_KEY_LENGTH_BYTES = 32;
/**
* Seed Length in bytes.
*/
public static final int SEED_LENGTH = 32;
/**
* Max secret length.
*/
public static final int MAX_SECRET_LENGTH = 32;
/**
* AES Key Length un bytes.
*/
public static final int AES_KEY_LENGTH_BYTES = 16;
/**
* Defines the well known exponent.
* https://en.wikipedia.org/wiki/65537_(number)#Applications
*/
private final static BigInteger EXPONENT = new BigInteger("010001", DEFAULT_IV_SIZE);
public static final int HMAC_SIZE_LENGTH_BYTES = 2;
public static final int HMAC_KEY_LENGTH_BYTES = 32;
public static final int SEED_LENGTH = 32;
public static final int MAX_SECRET_LENGTH = 32;
public static final int AES_KEY_LENGTH_BYTES = 16;
private static final BigInteger EXPONENT = new BigInteger("010001", DEFAULT_IV_SIZE);
private static final int TPM2_CREDENTIAL_BLOB_SIZE = 392;
private static final int RSA_MODULUS_LENGTH = 256;
// Constants used to parse out the ak name from the ak public data. Used in generateAkName
private static final String AK_NAME_PREFIX = "000b";
private static final String AK_NAME_HASH_PREFIX =
"0001000b00050072000000100014000b0800000000000100";
private static final SecureRandom random = new SecureRandom();
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
/**
* Helper method to parse a byte array into an {@link hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2.IdentityClaim}.
* This private constructor was created to silence checkstyle error.
*/
private ProvisionUtils() {
}
/**
* Helper method to parse a byte array into an
* {@link hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2.IdentityClaim}.
*
* @param identityClaim byte array that should be converted to a Protobuf IdentityClaim
* object
* @throws {@link IdentityProcessingException} if byte array could not be parsed
* @return the Protobuf generated Identity Claim object
* @throws {@link InvalidProtocolBufferException} if byte array could not be parsed
*/
public static ProvisionerTpm2.IdentityClaim parseIdentityClaim(final byte[] identityClaim) {
try {
@ -96,8 +127,8 @@ public final class ProvisionUtils {
* Helper method to extract a DER encoded ASN.1 certificate from an X509 certificate.
*
* @param certificate the X509 certificate to be converted to DER encoding
* @throws {@link UnexpectedServerException} if error occurs during encoding retrieval
* @return the byte array representing the DER encoded certificate
* @throws {@link UnexpectedServerException} if error occurs during encoding retrieval
*/
public static byte[] getDerEncodedCertificate(final X509Certificate certificate) {
try {
@ -135,6 +166,7 @@ public final class ProvisionUtils {
/**
* Parse public key from public data segment generated by TPM 2.0.
*
* @param publicArea the public area segment to parse
* @return the RSA public key of the supplied public data
*/
@ -154,8 +186,7 @@ public final class ProvisionUtils {
/**
* Constructs a public key where the modulus is in raw form.
*
* @param modulus
* in byte array form
* @param modulus in byte array form
* @return public key using specific modulus and the well known exponent
*/
public static PublicKey assemblePublicKey(final byte[] modulus) {
@ -165,8 +196,7 @@ public final class ProvisionUtils {
/**
* Constructs a public key where the modulus is Hex encoded.
*
* @param modulus
* hex encoded modulus
* @param modulus hex encoded modulus
* @return public key using specific modulus and the well known exponent
*/
public static PublicKey assemblePublicKey(final String modulus) {
@ -175,6 +205,9 @@ public final class ProvisionUtils {
/**
* Assembles a public key using a defined big int modulus and the well known exponent.
*
* @param modulus modulus
* @return public key using the provided integer modulus
*/
public static PublicKey assemblePublicKey(final BigInteger modulus) {
// generate a key spec using mod and exp
@ -206,15 +239,13 @@ public final class ProvisionUtils {
// create a cipher from the specified transformation
Cipher cipher = Cipher.getInstance(scheme.toString());
switch (scheme) {
case OAEP:
if (scheme == EncryptionScheme.OAEP) {
OAEPParameterSpec spec =
new OAEPParameterSpec("Sha1", "MGF1", MGF1ParameterSpec.SHA1,
new PSource.PSpecified("".getBytes(StandardCharsets.UTF_8)));
cipher.init(Cipher.PRIVATE_KEY, privateKey, spec);
break;
default:
} else {
// initialize the cipher to decrypt using the ACA private key.
cipher.init(Cipher.DECRYPT_MODE, privateKey);
}
@ -266,6 +297,11 @@ public final class ProvisionUtils {
return new byte[0];
}
/**
* Generates a symmetric key.
*
* @return a symmetric key
*/
public static SymmetricKey generateSymmetricKey() {
// create a session key for the CA contents
byte[] responseSymmetricKey =
@ -287,7 +323,7 @@ public final class ProvisionUtils {
* key to generate an HMAC to cover the encrypted secret and the ak name. The output is an
* encrypted blob that acts as the first part of a challenge-response authentication mechanism
* to validate an identity claim.
*
* <p>
* Equivalent to calling tpm2_makecredential using tpm2_tools.
*
* @param ek endorsement key in the identity claim
@ -310,7 +346,8 @@ public final class ProvisionUtils {
// encrypt seed with pubEk
Cipher asymCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
OAEPParameterSpec oaepSpec = new OAEPParameterSpec("SHA-256", "MGF1",
MGF1ParameterSpec.SHA256, new PSource.PSpecified("IDENTITY\0".getBytes(StandardCharsets.UTF_8)));
MGF1ParameterSpec.SHA256,
new PSource.PSpecified("IDENTITY\0".getBytes(StandardCharsets.UTF_8)));
asymCipher.init(Cipher.PUBLIC_KEY, ek, oaepSpec);
asymCipher.update(seed);
byte[] encSeed = asymCipher.doFinal();
@ -497,7 +534,15 @@ public final class ProvisionUtils {
}
}
@SuppressWarnings("magicnumber")
/**
* Assembles a credential blob.
*
* @param topSize byte array representation of the top size
* @param integrityHmac byte array representation of the integrity HMAC
* @param encryptedSecret byte array representation of the encrypted secret
* @param encryptedSeed byte array representation of the encrypted seed
* @return byte array representation of a credential blob
*/
public static byte[] assembleCredential(final byte[] topSize, final byte[] integrityHmac,
final byte[] encryptedSecret,
final byte[] encryptedSeed) {
@ -514,21 +559,39 @@ public final class ProvisionUtils {
credentialBlob[0] = topSize[1];
credentialBlob[1] = topSize[0];
credentialBlob[2] = 0x00;
credentialBlob[3] = 0x20;
System.arraycopy(integrityHmac, 0, credentialBlob, 4, 32);
for (int i = 0; i < 98; i++) {
credentialBlob[36 + i] = 0x00;
final int credBlobPosition4 = 3;
final byte credBlobFourthPositionValue = 0x20;
credentialBlob[credBlobPosition4] = credBlobFourthPositionValue;
final int credBlobPosition5 = 4;
final int credBlobSizeFromPosition5 = 32;
System.arraycopy(integrityHmac, 0, credentialBlob, credBlobPosition5, credBlobSizeFromPosition5);
final int credBlobPosition99 = 98;
final int credBlobPosition37 = 36;
for (int i = 0; i < credBlobPosition99; i++) {
credentialBlob[credBlobPosition37 + i] = 0x00;
}
System.arraycopy(encryptedSecret, 0, credentialBlob, 36, encryptedSecret.length);
credentialBlob[134] = 0x00;
credentialBlob[135] = 0x01;
System.arraycopy(encryptedSeed, 0, credentialBlob, 136, 256);
System.arraycopy(encryptedSecret, 0, credentialBlob, credBlobPosition37, encryptedSecret.length);
final int credBlobPosition135 = 134;
credentialBlob[credBlobPosition135] = 0x00;
final int credBlobPosition136 = 135;
credentialBlob[credBlobPosition136] = 0x01;
final int credBlobPosition137 = 136;
final int credBlobSizeFromPosition137 = 256;
System.arraycopy(encryptedSeed, 0, credentialBlob, credBlobPosition137, credBlobSizeFromPosition137);
// return the result
return credentialBlob;
}
/**
* Determines the AK name from the AK Modulus.
*
* @param akModulus modulus of an attestation key
* @return the ak name byte array
* @throws java.security.NoSuchAlgorithmException Underlying SHA256 method used a bad algorithm
@ -560,37 +623,41 @@ public final class ProvisionUtils {
* @throws NoSuchAlgorithmException Wrong crypto algorithm selected
* @throws java.security.InvalidKeyException Invalid key used
*/
@SuppressWarnings("magicnumber")
public static byte[] cryptKDFa(final byte[] seed, final String label, final byte[] context,
final int sizeInBytes)
throws NoSuchAlgorithmException, InvalidKeyException {
ByteBuffer b = ByteBuffer.allocate(4);
final int capacity = 4;
ByteBuffer b = ByteBuffer.allocate(capacity);
b.putInt(1);
byte[] counter = b.array();
// get the label
String labelWithEnding = label;
if (label.charAt(label.length() - 1) != "\0".charAt(0)) {
if (label.charAt(label.length() - 1) != '\u0000') {
labelWithEnding = label + "\0";
}
byte[] labelBytes = labelWithEnding.getBytes(StandardCharsets.UTF_8);
b = ByteBuffer.allocate(4);
b.putInt(sizeInBytes * 8);
final int byteOffset = 8;
b = ByteBuffer.allocate(capacity);
b.putInt(sizeInBytes * byteOffset);
byte[] desiredSizeInBits = b.array();
int sizeOfMessage = 8 + labelBytes.length;
int sizeOfMessage = byteOffset + labelBytes.length;
if (context != null) {
sizeOfMessage += context.length;
}
byte[] message = new byte[sizeOfMessage];
int marker = 0;
System.arraycopy(counter, 0, message, marker, 4);
marker += 4;
final int markerLength = 4;
System.arraycopy(counter, 0, message, marker, markerLength);
marker += markerLength;
System.arraycopy(labelBytes, 0, message, marker, labelBytes.length);
marker += labelBytes.length;
if (context != null) {
System.arraycopy(context, 0, message, marker, context.length);
marker += context.length;
}
System.arraycopy(desiredSizeInBits, 0, message, marker, 4);
System.arraycopy(desiredSizeInBits, 0, message, marker, markerLength);
Mac hmac;
byte[] toReturn = new byte[sizeInBytes];
@ -606,7 +673,9 @@ public final class ProvisionUtils {
/**
* This method takes the provided TPM Quote and splits it between the PCR
* quote and the signature hash.
*
* @param tpmQuote contains hash values for the quote and the signature
* @return parsed TPM Quote hash
*/
public static String parseTPMQuoteHash(final String tpmQuote) {
if (tpmQuote != null) {
@ -624,7 +693,9 @@ public final class ProvisionUtils {
/**
* This method takes the provided TPM Quote and splits it between the PCR
* quote and the signature hash.
*
* @param tpmQuote contains hash values for the quote and the signature
* @return parsed TPM Quote signature
*/
public static String parseTPMQuoteSignature(final String tpmQuote) {
if (tpmQuote != null) {
@ -638,6 +709,7 @@ public final class ProvisionUtils {
/**
* Computes the sha256 hash of the given blob.
*
* @param blob byte array to take the hash of
* @return sha256 hash of blob
* @throws NoSuchAlgorithmException improper algorithm selected
@ -649,20 +721,29 @@ public final class ProvisionUtils {
}
/**
* Generates a array of random bytes.
* Generates an array of random bytes.
*
* @param numberOfBytes
* to be generated
* @param numberOfBytes to be generated
* @return byte array filled with the specified number of bytes.
*/
public static byte[] generateRandomBytes(final int numberOfBytes) {
byte[] bytes = new byte[numberOfBytes];
random.nextBytes(bytes);
SECURE_RANDOM.nextBytes(bytes);
return bytes;
}
@SuppressWarnings("magicnumber")
/**
* Calculates the difference in days between the two provided dates.
*
* @param date1 first provided date
* @param date2 second provided date
* @return difference in days between two dates
*/
public static int daysBetween(final Date date1, final Date date2) {
return (int) ((date2.getTime() - date1.getTime()) / (1000 * 60 * 60 * 24));
final int hoursInADay = 24;
final int secondsInAnHour = 3600;
final int millisecondsInASecond = 1000;
return (int) ((date2.getTime() - date1.getTime())
/ (millisecondsInASecond * secondsInAnHour * hoursInADay));
}
}

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.provision.helper;

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.provision;

View File

@ -11,7 +11,11 @@ import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.attestationca.persist.entity.manager.SupplyChainValidationRepository;
import hirs.attestationca.persist.entity.manager.SupplyChainValidationSummaryRepository;
import hirs.attestationca.persist.entity.userdefined.*;
import hirs.attestationca.persist.entity.userdefined.Device;
import hirs.attestationca.persist.entity.userdefined.PolicySettings;
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary;
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
@ -27,12 +31,10 @@ import lombok.extern.log4j.Log4j2;
import org.apache.logging.log4j.Level;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.events.Event;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -46,15 +48,15 @@ import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
@Service
public class SupplyChainValidationService {
private CACredentialRepository caCredentialRepository;
private PolicyRepository policyRepository;
private ReferenceManifestRepository referenceManifestRepository;
private ReferenceDigestValueRepository referenceDigestValueRepository;
private ComponentResultRepository componentResultRepository;
private ComponentAttributeRepository componentAttributeRepository;
private CertificateRepository certificateRepository;
private SupplyChainValidationRepository supplyChainValidationRepository;
private SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository;
private final CACredentialRepository caCredentialRepository;
private final PolicyRepository policyRepository;
private final ReferenceManifestRepository referenceManifestRepository;
private final ReferenceDigestValueRepository referenceDigestValueRepository;
private final ComponentResultRepository componentResultRepository;
private final ComponentAttributeRepository componentAttributeRepository;
private final CertificateRepository certificateRepository;
private final SupplyChainValidationRepository supplyChainValidationRepository;
private final SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository;
private UUID provisionSessionId;
/**
@ -64,13 +66,13 @@ public class SupplyChainValidationService {
* @param policyRepository the policy manager
* @param certificateRepository the cert manager
* @param componentResultRepository the comp result manager
* @param componentAttributeRepository component attribute repository
* @param referenceManifestRepository the RIM manager
* @param supplyChainValidationRepository the scv manager
* @param supplyChainValidationSummaryRepository the summary manager
* @param referenceDigestValueRepository the even manager
*/
@Autowired
@SuppressWarnings("ParameterNumberCheck")
public SupplyChainValidationService(
final CACredentialRepository caCredentialRepository,
final PolicyRepository policyRepository,
@ -103,7 +105,6 @@ public class SupplyChainValidationService {
* @param componentInfos list of components from the device
* @return A summary of the validation results.
*/
@SuppressWarnings("methodlength")
public SupplyChainValidationSummary validateSupplyChain(final EndorsementCredential ec,
final List<PlatformCredential> pcs,
final Device device,
@ -323,7 +324,8 @@ public class SupplyChainValidationService {
deviceName));
} else {
ReferenceManifest manifest = referenceManifestRepository
.findByHexDecHashAndRimType(sRim.getEventLogHash(), ReferenceManifest.MEASUREMENT_RIM);
.findByHexDecHashAndRimType(sRim.getEventLogHash(),
ReferenceManifest.MEASUREMENT_RIM);
if (manifest instanceof EventLogMeasurements) {
eventLog = (EventLogMeasurements) manifest;
}
@ -357,7 +359,8 @@ public class SupplyChainValidationService {
BaseReferenceManifest bRim = null;
if (sRim != null && sRim.getAssociatedRim() != null) {
Optional<ReferenceManifest> oRim = referenceManifestRepository.findById(sRim.getAssociatedRim());
Optional<ReferenceManifest> oRim =
referenceManifestRepository.findById(sRim.getAssociatedRim());
if (oRim.isPresent()) {
ReferenceManifest rim = oRim.get();
if (rim instanceof BaseReferenceManifest) {
@ -375,7 +378,8 @@ public class SupplyChainValidationService {
Optional<SupplyChainValidationSummary> previousOpt
//= this.supplyChainValidationSummaryRepository.findByDevice(deviceName);
//= this.supplyChainValidationSummaryRepository.findByDevice(device);
= this.supplyChainValidationSummaryRepository.findById(UUID.fromString(device.getSummaryId()));
= this.supplyChainValidationSummaryRepository.findById(
UUID.fromString(device.getSummaryId()));
if (previousOpt.isPresent()) {
SupplyChainValidationSummary previous = previousOpt.get();
for (SupplyChainValidation scv : previous.getValidations()) {
@ -421,6 +425,7 @@ public class SupplyChainValidationService {
* If the platform attributes policy is enabled, this method updates the matched
* status for the component result. This is done so that the details page for the
* platform certificate highlights the title card red.
*
* @param componentResults list of associated component results
*/
private void updateComponentStatus(final List<ComponentResult> componentResults) {

View File

@ -18,7 +18,6 @@ import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredent
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
import hirs.attestationca.persist.enums.AppraisalStatus;
import hirs.attestationca.persist.validation.CertificateAttributeScvValidator;
import hirs.attestationca.persist.validation.CredentialValidator;
import hirs.attestationca.persist.validation.FirmwareScvValidator;
import hirs.utils.BouncyCastleUtils;
@ -41,70 +40,101 @@ import java.util.Set;
import java.util.UUID;
@Log4j2
public class ValidationService {
public final class ValidationService {
/**
* This private constructor was created to silence checkstyle errors.
*/
private ValidationService() {
}
/**
* Evaluates the provided endorsement credential status.
*
* @param endorsementCredential endorsement credential
* @param caCredentialRepository CA Credential repository
* @param acceptExpiredCerts whether to accept expired certificates
* @return a supply chain validation
*/
public static SupplyChainValidation evaluateEndorsementCredentialStatus(
final EndorsementCredential ec,
final EndorsementCredential endorsementCredential,
final CACredentialRepository caCredentialRepository,
final boolean acceptExpiredCerts) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL;
log.info("Validating endorsement credential");
if (ec == null) {
if (endorsementCredential == null) {
log.error("No endorsement credential to validate");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Endorsement credential is missing",
null, Level.ERROR);
}
KeyStore ecStore = getCaChain(ec, caCredentialRepository);
KeyStore ecStore = getCaChain(endorsementCredential, caCredentialRepository);
AppraisalStatus result = CredentialValidator.
validateEndorsementCredential(ec, ecStore, acceptExpiredCerts);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), ec, Level.INFO);
case FAIL:
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), ec, Level.WARN);
case ERROR:
default:
return buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), ec, Level.ERROR);
}
validateEndorsementCredential(endorsementCredential, ecStore, acceptExpiredCerts);
return switch (result.getAppStatus()) {
case PASS -> buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), endorsementCredential, Level.INFO);
case FAIL -> buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), endorsementCredential, Level.WARN);
default -> buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), endorsementCredential, Level.ERROR);
};
}
/**
* Evaluates the provided platform credential status.
*
* @param platformCredential platform credential
* @param trustedCertificateAuthority trusted certificate authority
* @param acceptExpiredCerts whether to accept expired certificates
* @return a supply chain validation
*/
public static SupplyChainValidation evaluatePlatformCredentialStatus(
final PlatformCredential pc,
final PlatformCredential platformCredential,
final KeyStore trustedCertificateAuthority, final boolean acceptExpiredCerts) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL;
if (pc == null) {
if (platformCredential == null) {
log.error("No platform credential to validate");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Empty Platform credential", null, Level.ERROR);
}
log.info("Validating Platform Credential");
AppraisalStatus result = CredentialValidator.validatePlatformCredential(pc,
AppraisalStatus result = CredentialValidator.validatePlatformCredential(platformCredential,
trustedCertificateAuthority, acceptExpiredCerts);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), pc, Level.INFO);
case FAIL:
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), pc, Level.WARN);
case ERROR:
default:
return buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), pc, Level.ERROR);
}
return switch (result.getAppStatus()) {
case PASS -> buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), platformCredential, Level.INFO);
case FAIL -> buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), platformCredential, Level.WARN);
default -> buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), platformCredential, Level.ERROR);
};
}
/**
* Evaluates PC Attributes status.
*
* @param platformCredential platform credential
* @param deviceInfoReport device information report
* @param endorsementCredential endorsement credential
* @param certificateRepository certificate repository
* @param componentResultRepository component result repository
* @param componentAttributeRepository component attribute repository
* @param componentInfos list of component information
* @param provisionSessionId uuid representation of the provision session id
* @param ignoreRevisionAttribute whether to ignore revision attribute
* @return a supply chain validation
*/
public static SupplyChainValidation evaluatePCAttributesStatus(
final PlatformCredential pc, final DeviceInfoReport deviceInfoReport,
final EndorsementCredential ec,
final PlatformCredential platformCredential, final DeviceInfoReport deviceInfoReport,
final EndorsementCredential endorsementCredential,
final CertificateRepository certificateRepository,
final ComponentResultRepository componentResultRepository,
final ComponentAttributeRepository componentAttributeRepository,
@ -113,36 +143,51 @@ public class ValidationService {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
if (pc == null) {
if (platformCredential == null) {
log.error("No platform credential to validate");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Platform credential is missing",
null, Level.ERROR);
}
log.info("Validating platform credential attributes");
AppraisalStatus result = CredentialValidator.
validatePlatformCredentialAttributes(pc, deviceInfoReport, ec,
validatePlatformCredentialAttributes(platformCredential, deviceInfoReport,
endorsementCredential,
componentResultRepository, componentAttributeRepository,
componentInfos, provisionSessionId, ignoreRevisionAttribute);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), pc, Level.INFO);
case FAIL:
return switch (result.getAppStatus()) {
case PASS -> buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), platformCredential, Level.INFO);
case FAIL -> {
if (!result.getAdditionalInfo().isEmpty()) {
pc.setComponentFailures(result.getAdditionalInfo());
pc.setComponentFailureMessage(result.getMessage());
certificateRepository.save(pc);
platformCredential.setComponentFailures(result.getAdditionalInfo());
platformCredential.setComponentFailureMessage(result.getMessage());
certificateRepository.save(platformCredential);
}
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), pc, Level.WARN);
case ERROR:
default:
return buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), pc, Level.ERROR);
yield buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), platformCredential, Level.WARN);
}
default -> buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), platformCredential, Level.ERROR);
};
}
/**
* Evaluates delta attributes status.
*
* @param deviceInfoReport device information report
* @param base base platform credential
* @param deltaMapping delta mapping
* @param certificateRepository certificate repository
* @param componentResultRepository component result repository
* @param componentAttributeRepository component attribute repository
* @param componentInfos list of component information
* @param provisionSessionId uuid representation of the provision session ID
* @param ignoreRevisionAttribute whether to ignore the revision attribute
* @return a supply chain validation
*/
public static SupplyChainValidation evaluateDeltaAttributesStatus(
final DeviceInfoReport deviceInfoReport,
final PlatformCredential base,
@ -161,11 +206,11 @@ public class ValidationService {
base, deltaMapping, componentInfos,
componentResultRepository, componentAttributeRepository,
provisionSessionId, ignoreRevisionAttribute);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
return switch (result.getAppStatus()) {
case PASS -> buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
result.getMessage(), base, Level.INFO);
case FAIL:
case FAIL -> {
if (!result.getAdditionalInfo().isEmpty()) {
base.setComponentFailures(result.getAdditionalInfo());
base.setComponentFailureMessage(result.getMessage());
@ -173,15 +218,26 @@ public class ValidationService {
}
// we are adding things to componentFailures
// certificateRepository.save(delta);
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
yield buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
result.getMessage(), base, Level.WARN);
case ERROR:
default:
return buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), base, Level.ERROR);
// we are adding things to componentFailures
// certificateRepository.save(delta);
}
default -> buildValidationRecord(validationType, AppraisalStatus.Status.ERROR,
result.getMessage(), base, Level.ERROR);
};
}
/**
* Evaluates the firmware status.
*
* @param device device
* @param policySettings policy settings
* @param rimRepo reference manifest repository
* @param rdvRepo reference digest value repository
* @param caRepo CA Credential repository
* @return a supply chain validation
*/
public static SupplyChainValidation evaluateFirmwareStatus(
final Device device,
final PolicySettings policySettings, final ReferenceManifestRepository rimRepo,
@ -207,17 +263,12 @@ public class ValidationService {
}
}
switch (result.getAppStatus()) {
case PASS:
logLevel = Level.INFO;
break;
case FAIL:
logLevel = Level.WARN;
break;
case ERROR:
default:
logLevel = Level.ERROR;
}
logLevel = switch (result.getAppStatus()) {
case PASS -> Level.INFO;
case FAIL -> Level.WARN;
default -> Level.ERROR;
};
return buildValidationRecord(validationType, result.getAppStatus(),
result.getMessage(), referenceManifest, logLevel);
}
@ -297,6 +348,7 @@ public class ValidationService {
* @param credential the credential whose CA chain should be retrieved
* @param previouslyQueriedSubjects a list of organizations to refrain
* from querying
* @param caCredentialRepository CA Credential repository
* @return a Set containing all relevant CA credentials to the given
* certificate's organization
*/
@ -318,7 +370,8 @@ public class ValidationService {
certAuthsWithMatchingIssuer = caCredentialRepository.findBySubject(credential.getIssuer());
} else {
//Get certificates by subject organization
certAuthsWithMatchingIssuer = caCredentialRepository.findBySubjectSorted(credential.getIssuerSorted());
certAuthsWithMatchingIssuer =
caCredentialRepository.findBySubjectSorted(credential.getIssuerSorted());
}
} else {
certAuthsWithMatchingIssuer.add(skiCA);
@ -337,6 +390,14 @@ public class ValidationService {
return caCreds;
}
/**
* Creates a key store using the provided set of certificate authority credentials.
*
* @param certs set of certificate authority credentials
* @return a keystore
* @throws KeyStoreException if there is an issue creating a key store
* @throws IOException if there is an issue creating a key store
*/
public static KeyStore caCertSetToKeystore(final Set<CertificateAuthorityCredential> certs)
throws KeyStoreException, IOException {
KeyStore keyStore = KeyStore.getInstance("JKS");

View File

@ -0,0 +1 @@
package hirs.attestationca.persist.service;

View File

@ -6,6 +6,7 @@ import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import lombok.Getter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.util.Arrays;
@ -24,7 +25,7 @@ import java.util.UUID;
* This class is used to select one or many certificates in conjunction
* with a {@link }. To make use of this object,
* use (some CertificateImpl).select(CertificateManager).
*
* <p>
* This class loosely follows the builder pattern. It is instantiated with
* the type of certificate that should be retrieved. It is possible to
* further specify which certificate(s) should be retrieved by using an
@ -32,10 +33,10 @@ import java.util.UUID;
* restrict the result set. At any time, the results may be retrieved
* by using one of the get* methods according to the form the
* results should be in.
*
* <p>
* If no matching certificates were found for the query, the returned
* value may empty or null, depending on the return type.
*
* <p>
* For example, to retrieve all platform certificates:
*
* <pre>
@ -45,7 +46,7 @@ import java.util.UUID;
* .getCertificates();
* }
* </pre>
*
* <p>
* To retrieve all CA certificates in a KeyStore:
*
* <pre>
@ -55,7 +56,7 @@ import java.util.UUID;
* .getKeyStore();
* }
* </pre>
*
* <p>
* To retrieve all CA certificates matching a certain issuer in X509 format:
*
* <pre>
@ -71,6 +72,7 @@ import java.util.UUID;
*/
public abstract class CertificateSelector<T extends Certificate> {
@Getter
private final Class<T> certificateClass;
private final Map<String, Object> fieldValueSelections;
@ -105,6 +107,7 @@ public abstract class CertificateSelector<T extends Certificate> {
this.fieldValueSelections = new HashMap<>();
this.excludeArchivedCertificates = excludeArchivedCertificates;
}
/**
* Specify the entity id that certificates must have to be considered
* as matching.
@ -249,6 +252,7 @@ public abstract class CertificateSelector<T extends Certificate> {
/**
* Specify the authority key identifier to find certificate(s).
*
* @param authorityKeyIdentifier the string of the AKI associated with the certificate.
* @return this instance
*/
@ -307,8 +311,7 @@ public abstract class CertificateSelector<T extends Certificate> {
);
}
if (value instanceof byte[]) {
byte[] valueBytes = (byte[]) value;
if (value instanceof byte[] valueBytes) {
Preconditions.checkArgument(
ArrayUtils.isNotEmpty(valueBytes),
@ -349,6 +352,7 @@ public abstract class CertificateSelector<T extends Certificate> {
* Construct the criterion that can be used to query for certificates matching the configuration
* of this {@link CertificateSelector}.
*
* @param criteriaBuilder criteria builder
* @return a Criterion that can be used to query for certificates matching the configuration of
* this instance
*/
@ -359,7 +363,8 @@ public abstract class CertificateSelector<T extends Certificate> {
int i = 0;
for (Map.Entry<String, Object> fieldValueEntry : fieldValueSelections.entrySet()) {
predicates[i++] = criteriaBuilder.equal(root.get(fieldValueEntry.getKey()), fieldValueEntry.getValue());
predicates[i++] =
criteriaBuilder.equal(root.get(fieldValueEntry.getKey()), fieldValueEntry.getValue());
}
if (this.excludeArchivedCertificates) {
@ -369,15 +374,9 @@ public abstract class CertificateSelector<T extends Certificate> {
return predicates;
}
/**
* @return the certificate class that this instance will query
*/
public Class<T> getCertificateClass() {
return certificateClass;
}
/**
* Configures the selector to query for archived and unarchived certificates.
*
* @return the selector
*/
public CertificateSelector<T> includeArchived() {

Some files were not shown because too many files have changed in this diff Show More