mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-18 20:47:58 +00:00
fixed merge conflict
This commit is contained in:
commit
8e1ec11c41
@ -3,6 +3,9 @@ LABEL org.opencontainers.image.vendor NSA Laboratory for Advanced Cybersecurity
|
||||
LABEL org.opencontainers.image.source https://github.com/nsacyber/hirs
|
||||
LABEL org.opencontainers.image.description NSA\'s HIRS Attestation Certificate Authority. Expose port 8443 to access the portal from outside the container.
|
||||
|
||||
# REF can be specified as a docker run environment variable to select the HIRS branch to work with
|
||||
ARG REF=main
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
# Rocky 9 has a different channel for some apps
|
||||
@ -50,7 +53,7 @@ RUN echo "#!/bin/bash" > /tmp/tpm_config && \
|
||||
EXPOSE 8443
|
||||
|
||||
# Checkout HIRS
|
||||
RUN git clone -b main https://github.com/nsacyber/HIRS.git /repo
|
||||
RUN git clone -b ${REF} https://github.com/nsacyber/HIRS.git /repo
|
||||
|
||||
# Defensive copy of the repo so it's easy to start fresh if needed
|
||||
RUN mkdir /hirs
|
||||
|
@ -9,6 +9,9 @@ LABEL org.opencontainers.image.source https://github.com/nsacyber/hirs
|
||||
LABEL org.opencontainers.image.description NSA\'s HIRS Attestation Certificate Authority in a Windows-native image. Expose port 8443 to access the portal from outside the container.
|
||||
LABEL org.opencontainers.image.base.name mcr.microsoft.com/powershell:${BASE_IMAGE_TAG}
|
||||
|
||||
# REF can be specified as a docker run environment variable to select the HIRS branch to work with
|
||||
ARG REF=main
|
||||
|
||||
SHELL ["pwsh", "-Command"]
|
||||
|
||||
# Output Powershell Version
|
||||
@ -105,11 +108,11 @@ RUN setx PATH '%JAVA_HOME%\bin;C:\Program Files\MariaDB 11.1\bin;%GIT_HOME%\bin;
|
||||
# Echo PATH after update
|
||||
RUN echo $Env:PATH
|
||||
|
||||
# Clone HIRS main
|
||||
# Clone HIRS main (or REF)
|
||||
WORKDIR C:/
|
||||
RUN git config --global --add core.autocrlf false
|
||||
RUN git config --global --add safe.directory '*'
|
||||
RUN git clone -b main https://github.com/nsacyber/hirs.git C:/repo
|
||||
RUN git clone -b ${REF} https://github.com/nsacyber/hirs.git C:/repo
|
||||
|
||||
# Defensive copy of the repo so it's easy to start fresh if needed
|
||||
WORKDIR C:/repo
|
||||
|
6
.github/workflows/create_aca_images.yml
vendored
6
.github/workflows/create_aca_images.yml
vendored
@ -51,6 +51,7 @@ jobs:
|
||||
echo "PUBLIC_IMAGE_TAG=$PUBLIC_IMAGE_NAME:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
|
||||
- name: Print env
|
||||
run: |
|
||||
echo GITHUB_REF_NAME=${{ github.ref_name }}
|
||||
echo DOCKERFILE_ROCKY=$DOCKERFILE_ROCKY
|
||||
echo DOCKERFILE_WINDOWS=$DOCKERFILE_WINDOWS
|
||||
echo IMAGE_NAME_ROCKY=$IMAGE_NAME_ROCKY
|
||||
@ -86,6 +87,7 @@ jobs:
|
||||
with:
|
||||
context: "{{defaultContext}}:.ci/docker"
|
||||
file: Dockerfile.${{env.DOCKERFILE_ROCKY}}
|
||||
build-args: REF=${{ github.ref_name }}
|
||||
tags: ${{env.TAG}}
|
||||
push: true
|
||||
|
||||
@ -108,7 +110,7 @@ jobs:
|
||||
- name: Build the docker image for ${{ github.repository }}
|
||||
run: |
|
||||
cd ./.ci/docker
|
||||
docker build -f ./Dockerfile.${{env.DOCKERFILE_WINDOWS}} -t ${{env.TAG}} .
|
||||
docker build --build-arg "REF=${{ github.ref_name }}" -f ./Dockerfile.${{env.DOCKERFILE_WINDOWS}} -t ${{env.TAG}} .
|
||||
|
||||
- name: Push the docker image
|
||||
run: |
|
||||
@ -133,7 +135,7 @@ jobs:
|
||||
- name: Build the docker image for ${{ github.repository }}
|
||||
run: |
|
||||
cd ./.ci/docker
|
||||
docker build -f ./Dockerfile.${{env.DOCKERFILE_WINDOWS}} -t ${{env.TAG}} --build-arg BASE_IMAGE_TAG=lts-windowsservercore-1809 .
|
||||
docker build --build-arg "REF=${{ github.ref_name }}" -f ./Dockerfile.${{env.DOCKERFILE_WINDOWS}} -t ${{env.TAG}} --build-arg BASE_IMAGE_TAG=lts-windowsservercore-1809 .
|
||||
|
||||
- name: Push the docker image
|
||||
run: |
|
||||
|
@ -52,6 +52,7 @@ dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3'
|
||||
testImplementation 'org.junit.platform:junit-platform-launcher:1.9.3'
|
||||
testImplementation 'org.mockito:mockito-core:4.2.0'
|
||||
testImplementation 'org.springframework:spring-test:6.0.8'
|
||||
|
||||
// spring management
|
||||
compileOnly libs.lombok
|
||||
|
@ -15,5 +15,9 @@
|
||||
<Match>
|
||||
<Bug pattern="EI_EXPOSE_REP2" />
|
||||
</Match>
|
||||
<Match>
|
||||
<Class name="hirs.attestationca.persist.AttestationCertificateAuthorityTest"/>
|
||||
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
|
||||
</Match>
|
||||
</FindBugsFilter>
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hirs.attestationca.persist;
|
||||
|
||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentInfoRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
|
||||
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
||||
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
|
||||
@ -52,6 +53,7 @@ public abstract class AttestationCertificateAuthority {
|
||||
private Integer validDays = 1;
|
||||
|
||||
private final ComponentResultRepository componentResultRepository;
|
||||
private ComponentInfoRepository componentInfoRepository;
|
||||
private final CertificateRepository certificateRepository;
|
||||
private final IssuedCertificateRepository issuedCertificateRepository;
|
||||
private final ReferenceManifestRepository referenceManifestRepository;
|
||||
@ -71,13 +73,14 @@ public abstract class AttestationCertificateAuthority {
|
||||
* @param acaCertificate the ACA certificate
|
||||
* @param structConverter the struct converter
|
||||
* @param componentResultRepository the component result manager
|
||||
* @param componentInfoRepository the component info manager
|
||||
* @param certificateRepository the certificate manager
|
||||
* @param referenceManifestRepository the Reference Manifest manager
|
||||
* @param validDays the number of days issued certs are valid
|
||||
* @param deviceRepository the device manager
|
||||
* @param referenceDigestValueRepository the reference event manager
|
||||
* @param policyRepository
|
||||
* @param tpm2ProvisionerStateRepository
|
||||
* @param policyRepository policy setting repository
|
||||
* @param tpm2ProvisionerStateRepository tpm2 provisioner state repository
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
public AttestationCertificateAuthority(
|
||||
@ -85,6 +88,7 @@ public abstract class AttestationCertificateAuthority {
|
||||
final PrivateKey privateKey, final X509Certificate acaCertificate,
|
||||
final StructConverter structConverter,
|
||||
final ComponentResultRepository componentResultRepository,
|
||||
final ComponentInfoRepository componentInfoRepository,
|
||||
final CertificateRepository certificateRepository,
|
||||
final IssuedCertificateRepository issuedCertificateRepository,
|
||||
final ReferenceManifestRepository referenceManifestRepository,
|
||||
@ -98,6 +102,7 @@ public abstract class AttestationCertificateAuthority {
|
||||
this.acaCertificate = acaCertificate;
|
||||
this.structConverter = structConverter;
|
||||
this.componentResultRepository = componentResultRepository;
|
||||
this.componentInfoRepository = componentInfoRepository;
|
||||
this.certificateRepository = certificateRepository;
|
||||
this.issuedCertificateRepository = issuedCertificateRepository;
|
||||
this.referenceManifestRepository = referenceManifestRepository;
|
||||
@ -111,8 +116,8 @@ public abstract class AttestationCertificateAuthority {
|
||||
certificateRepository, deviceRepository,
|
||||
privateKey, acaCertificate, validDays, tpm2ProvisionerStateRepository);
|
||||
this.identityClaimHandler = new IdentityClaimProcessor(supplyChainValidationService,
|
||||
certificateRepository, referenceManifestRepository,
|
||||
referenceDigestValueRepository,
|
||||
certificateRepository, componentResultRepository, componentInfoRepository,
|
||||
referenceManifestRepository, referenceDigestValueRepository,
|
||||
deviceRepository, tpm2ProvisionerStateRepository, policyRepository);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hirs.attestationca.persist;
|
||||
|
||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentInfoRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
|
||||
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
||||
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
|
||||
@ -10,7 +11,6 @@ import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
|
||||
import hirs.attestationca.persist.entity.manager.TPM2ProvisionerStateRepository;
|
||||
import hirs.attestationca.persist.service.SupplyChainValidationService;
|
||||
import hirs.structs.converters.StructConverter;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
@ -63,6 +63,7 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
|
||||
final PrivateKey privateKey, final X509Certificate acaCertificate,
|
||||
final StructConverter structConverter,
|
||||
final ComponentResultRepository componentResultRepository,
|
||||
final ComponentInfoRepository componentInfoRepository,
|
||||
final CertificateRepository certificateRepository,
|
||||
final IssuedCertificateRepository issuedCertificateRepository,
|
||||
final ReferenceManifestRepository referenceManifestRepository,
|
||||
@ -72,7 +73,8 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
|
||||
final PolicyRepository policyRepository,
|
||||
final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository) {
|
||||
super(supplyChainValidationService, privateKey, acaCertificate, structConverter,
|
||||
componentResultRepository, certificateRepository, issuedCertificateRepository,
|
||||
componentResultRepository, componentInfoRepository,
|
||||
certificateRepository, issuedCertificateRepository,
|
||||
referenceManifestRepository,
|
||||
validDays, deviceRepository,
|
||||
referenceDigestValueRepository, policyRepository, tpm2ProvisionerStateRepository);
|
||||
|
@ -0,0 +1,32 @@
|
||||
package hirs.attestationca.persist.entity.manager;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentAttributeResult;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ComponentAttributeRepository extends JpaRepository<ComponentAttributeResult, UUID> {
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
List<ComponentAttributeResult> findByComponentId(UUID componentId);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
List<ComponentAttributeResult> findByProvisionSessionId(UUID provisionSessionId);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package hirs.attestationca.persist.entity.manager;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
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
|
||||
*/
|
||||
List<ComponentInfo> findByDeviceName(String deviceName);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
List<ComponentInfo> findByDeviceNameAndComponentSerial(String deviceName, String componentSerial);
|
||||
}
|
@ -2,7 +2,6 @@ package hirs.attestationca.persist.entity.manager;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
@ -11,6 +10,19 @@ import java.util.UUID;
|
||||
@Repository
|
||||
public interface ComponentResultRepository extends JpaRepository<ComponentResult, UUID> {
|
||||
|
||||
@Query(value = "SELECT * FROM ComponentResult where certificateId = ?1", nativeQuery = true)
|
||||
List<ComponentResult> getComponentResultsByCertificate(UUID certificateId);
|
||||
/**
|
||||
* Query based on the device serial number.
|
||||
* @param boardSerialNumber variable holding the device serial number
|
||||
* @return a list of component result.
|
||||
*/
|
||||
List<ComponentResult> findByBoardSerialNumber(String boardSerialNumber);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
List<ComponentResult> findByCertificateSerialNumberAndBoardSerialNumber(
|
||||
String certificateSerialNumber, String boardSerialNumber);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package hirs.attestationca.persist.entity.manager;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.rim.ReferenceDigestValue;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -90,7 +90,8 @@ public class TPM2ProvisionerState {
|
||||
/**
|
||||
* Convenience method for finding the {@link TPM2ProvisionerState} associated with the nonce.
|
||||
*
|
||||
* @param tpm2ProvisionerStateRepository the {@link TPM2ProvisionerStateRepository} to use when looking for the
|
||||
* @param tpm2ProvisionerStateRepository the {@link TPM2ProvisionerStateRepository}
|
||||
* to use when looking for the
|
||||
* {@link TPM2ProvisionerState}
|
||||
* @param nonce the nonce to use as the key for the {@link TPM2ProvisionerState}
|
||||
* @return the {@link TPM2ProvisionerState} associated with the nonce;
|
||||
|
@ -115,8 +115,7 @@ public class Device extends AbstractEntity {
|
||||
public String toString() {
|
||||
return String.format("Device Name: %s%nStatus: %s%nSummary: %s%n",
|
||||
name, healthStatus.getStatus(),
|
||||
supplyChainValidationStatus.toString(),
|
||||
summaryId);
|
||||
supplyChainValidationStatus.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,6 +46,7 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
||||
|
||||
private static final String DEVICE_ID_FIELD = "device.id";
|
||||
|
||||
@Getter
|
||||
@Column
|
||||
@Enumerated(EnumType.STRING)
|
||||
private final AppraisalStatus.Status overallValidationResult;
|
||||
@ -58,6 +59,9 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
||||
targetEntity = SupplyChainValidation.class, orphanRemoval = true)
|
||||
private final Set<SupplyChainValidation> validations;
|
||||
|
||||
@Column
|
||||
private UUID provisionSessionId;
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
@ -177,6 +181,20 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
||||
return new SupplyChainValidationSummary.Selector(certMan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new SupplyChainValidationSummary.
|
||||
*
|
||||
* @param device device that underwent supply chain validation
|
||||
* @param validations a Collection of Validations that should comprise this summary; not null
|
||||
* @param provisionSessionId randomly generated UUID to associate with results
|
||||
*/
|
||||
public SupplyChainValidationSummary(final Device device,
|
||||
final Collection<SupplyChainValidation> validations,
|
||||
final UUID provisionSessionId) {
|
||||
this(device, validations);
|
||||
this.provisionSessionId = provisionSessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new SupplyChainValidationSummary.
|
||||
*
|
||||
@ -212,13 +230,6 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
||||
return new Device(this.device.getDeviceInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the overall appraisal result
|
||||
*/
|
||||
public AppraisalStatus.Status getOverallValidationResult() {
|
||||
return overallValidationResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the validations that this summary contains
|
||||
*/
|
||||
|
@ -1,38 +1,142 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.certificate;
|
||||
|
||||
import hirs.attestationca.persist.entity.AbstractEntity;
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentAddress;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.AttributeStatus;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
/**
|
||||
* A component result is a DO to hold the status of a component validation status. This will
|
||||
* also be used to display this common information on the certificate details page.
|
||||
*/
|
||||
@Getter
|
||||
@Entity
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public class ComponentResult extends AbstractEntity {
|
||||
public class ComponentResult extends ArchivableEntity {
|
||||
|
||||
private UUID certificateId;
|
||||
private int componentHash;
|
||||
private String expected;
|
||||
private String actual;
|
||||
private boolean mismatched;
|
||||
// embedded component info
|
||||
@Setter
|
||||
private String manufacturer;
|
||||
@Setter
|
||||
private String model;
|
||||
private String serialNumber;
|
||||
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 failedValidation;
|
||||
private String certificateType;
|
||||
|
||||
public ComponentResult(final UUID certificateId, final int componentHash,
|
||||
final String expected, final String actual) {
|
||||
this.certificateId = certificateId;
|
||||
this.componentHash = componentHash;
|
||||
this.expected = expected;
|
||||
this.actual = actual;
|
||||
this.mismatched = Objects.equals(expected, actual);
|
||||
private String issuerDN;
|
||||
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.
|
||||
* @param componentIdentifier object with information from the platform certificate components.
|
||||
*/
|
||||
public ComponentResult(final String boardSerialNumber, final String certificateSerialNumber,
|
||||
final String certificateType,
|
||||
final ComponentIdentifier componentIdentifier) {
|
||||
this.boardSerialNumber = boardSerialNumber;
|
||||
this.certificateSerialNumber = certificateSerialNumber;
|
||||
this.certificateType = certificateType;
|
||||
this.manufacturer = componentIdentifier.getComponentManufacturer().toString();
|
||||
this.model = componentIdentifier.getComponentModel().toString();
|
||||
this.serialNumber = componentIdentifier.getComponentSerial().toString();
|
||||
this.revisionNumber = componentIdentifier.getComponentRevision().toString();
|
||||
if (componentIdentifier.getFieldReplaceable() != null) {
|
||||
this.fieldReplaceable = componentIdentifier.getFieldReplaceable().isTrue();
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (ComponentAddress element : componentIdentifier.getComponentAddress()) {
|
||||
sb.append(String.format("%s:%s;", element.getAddressTypeValue(),
|
||||
element.getAddressValue().toString()));
|
||||
}
|
||||
componentAddress = sb.toString();
|
||||
|
||||
// V2 fields
|
||||
if (componentIdentifier.isVersion2()
|
||||
&& componentIdentifier instanceof ComponentIdentifierV2) {
|
||||
// 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();
|
||||
this.attributeStatus = ciV2.getAttributeStatus();
|
||||
this.version2 = true;
|
||||
if (ciV2.getCertificateIdentifier() != null) {
|
||||
this.issuerDN = ciV2.getCertificateIdentifier().getIssuerDN().toString();
|
||||
if (ciV2.getComponentPlatformUri() != null) {
|
||||
this.uniformResourceIdentifier = ciV2.getComponentPlatformUri()
|
||||
.getUniformResourceIdentifier().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
List<ComponentAddress> addresses = new LinkedList<>();
|
||||
ComponentAddress address;
|
||||
if (componentAddress != null && !componentAddress.isEmpty()) {
|
||||
for (String s : componentAddress.split(";", 0)) {
|
||||
address = new ComponentAddress();
|
||||
address.setAddressTypeString(s.split(":")[0]);
|
||||
address.setAddressValueString(s.split(":")[1]);
|
||||
addresses.add(address);
|
||||
}
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code that is associated with common fields for components.
|
||||
* @return int value of the elements
|
||||
*/
|
||||
public int hashCommonElements() {
|
||||
return Objects.hash(manufacturer,
|
||||
model, serialNumber, revisionNumber, componentClassValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* The string method for log entries.
|
||||
* @return a string for the component result
|
||||
*/
|
||||
public String toString() {
|
||||
return String.format("ComponentResult[%d]: expected=[%s] actual=[%s]",
|
||||
componentHash, expected, actual);
|
||||
return String.format("ComponentResult: certificateSerialNumber=[%s] "
|
||||
+ "manufacturer=[%s] model=[%s] componentClass=[%s]",
|
||||
boardSerialNumber, manufacturer, model, componentClassValue);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import hirs.attestationca.persist.entity.userdefined.certificate.attributes.Plat
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.TBBSecurityAssertion;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.PlatformConfigurationV2;
|
||||
import hirs.attestationca.persist.service.selector.CertificateSelector;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Transient;
|
||||
@ -483,7 +482,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
ASN1Sequence attributeSequence;
|
||||
// Check all attributes for Platform Configuration
|
||||
for (ASN1Encodable enc: getAttributeCertificate().getAcinfo().getAttributes().toArray()) {
|
||||
for (ASN1Encodable enc : getAttributeCertificate().getAcinfo().getAttributes().toArray()) {
|
||||
Attribute attr = Attribute.getInstance(enc);
|
||||
attributeSequence
|
||||
= ASN1Sequence.getInstance(attr.getAttrValues().getObjectAt(0));
|
||||
|
@ -32,6 +32,8 @@ public class ComponentAddress {
|
||||
|
||||
private ASN1ObjectIdentifier addressType;
|
||||
private ASN1UTF8String addressValue;
|
||||
private String addressTypeString;
|
||||
private String addressValueString;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
|
@ -0,0 +1,49 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
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.
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public class ComponentAttributeResult extends ArchivableEntity {
|
||||
|
||||
private UUID componentId;
|
||||
@Setter
|
||||
private UUID provisionSessionId;
|
||||
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
|
||||
*/
|
||||
public ComponentAttributeResult(final UUID componentId,
|
||||
final String expectedValue,
|
||||
final String actualValue) {
|
||||
this.componentId = componentId;
|
||||
this.expectedValue = expectedValue;
|
||||
this.actualValue = actualValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to check the mismatched status flag for
|
||||
* displaying red if there is a failure.
|
||||
*/
|
||||
public boolean checkMatchedStatus() {
|
||||
return this.actualValue.equals(this.expectedValue);
|
||||
}
|
||||
}
|
@ -52,6 +52,7 @@ public class ComponentClass {
|
||||
private String category, categoryStr;
|
||||
@Getter
|
||||
private String component, componentStr;
|
||||
@Getter
|
||||
private String registryType;
|
||||
@Getter
|
||||
private String componentIdentifier;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@ -37,10 +36,6 @@ import java.util.stream.Collectors;
|
||||
@EqualsAndHashCode
|
||||
public class ComponentIdentifier {
|
||||
|
||||
/**
|
||||
* Variable for components that aren't set.
|
||||
*/
|
||||
public static final String EMPTY_COMPONENT = "[Empty]";
|
||||
/**
|
||||
* Variable for components that aren't set.
|
||||
*/
|
||||
@ -88,8 +83,8 @@ public class ComponentIdentifier {
|
||||
public ComponentIdentifier() {
|
||||
componentManufacturer = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||
componentModel = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||
componentSerial = new DERUTF8String(EMPTY_COMPONENT);
|
||||
componentRevision = new DERUTF8String(EMPTY_COMPONENT);
|
||||
componentSerial = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||
componentRevision = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||
componentManufacturerId = null;
|
||||
fieldReplaceable = null;
|
||||
componentAddress = new ArrayList<>();
|
||||
@ -124,13 +119,13 @@ public class ComponentIdentifier {
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains Component Identifier.
|
||||
* @param sequence containing the the component identifier
|
||||
* @param sequence containing the component identifier
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public ComponentIdentifier(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
// set all optional values to default in case they aren't set.
|
||||
this();
|
||||
//Check if it have a valid number of identifiers
|
||||
//Check if it has a valid number of identifiers
|
||||
if (sequence.size() < MANDATORY_ELEMENTS) {
|
||||
throw new IllegalArgumentException("Component identifier do not have required values.");
|
||||
}
|
||||
@ -238,7 +233,7 @@ public class ComponentIdentifier {
|
||||
sb.append(fieldReplaceable.toString());
|
||||
}
|
||||
sb.append(", componentAddress=");
|
||||
if (componentAddress.size() > 0) {
|
||||
if (!componentAddress.isEmpty()) {
|
||||
sb.append(componentAddress
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
|
@ -25,7 +25,7 @@ public class PlatformConfigurationV1 extends PlatformConfiguration {
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains Platform Configuration.
|
||||
* @param sequence containing the the Platform Configuration.
|
||||
* @param sequence containing the Platform Configuration.
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public PlatformConfigurationV1(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||
|
@ -103,13 +103,13 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
|
||||
|
||||
/**
|
||||
* Constructor given the SEQUENCE that contains Component Identifier.
|
||||
* @param sequence containing the the component identifier
|
||||
* @param sequence containing the component identifier
|
||||
* @throws IllegalArgumentException if there was an error on the parsing
|
||||
*/
|
||||
public ComponentIdentifierV2(final ASN1Sequence sequence)
|
||||
throws IllegalArgumentException {
|
||||
super();
|
||||
// Check if it have a valid number of identifiers
|
||||
// Check if it has a valid number of identifiers
|
||||
if (sequence.size() < MANDATORY_ELEMENTS) {
|
||||
throw new IllegalArgumentException("Component identifier do not have required values.");
|
||||
}
|
||||
|
@ -1,36 +1,39 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.info;
|
||||
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.utils.enums.DeviceInfoEnums;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.DiscriminatorColumn;
|
||||
import jakarta.persistence.DiscriminatorType;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import lombok.Data;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* ComponentInfo is a class to hold Hardware component information
|
||||
* such as manufacturer, model, serial number and version.
|
||||
*/
|
||||
@Log4j2
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@DiscriminatorColumn(name = "componentTypeEnum", discriminatorType = DiscriminatorType.STRING)
|
||||
public class ComponentInfo implements Serializable {
|
||||
public class ComponentInfo extends ArchivableEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = "componentInfo_id")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
// @Id
|
||||
// @Column(name = "componentInfo_id")
|
||||
// @GeneratedValue(strategy = GenerationType.AUTO)
|
||||
// private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String deviceName;
|
||||
@XmlElement
|
||||
@Column(nullable = false)
|
||||
private String componentManufacturer;
|
||||
@ -52,7 +55,7 @@ public class ComponentInfo implements Serializable {
|
||||
private String componentClass;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* 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)
|
||||
@ -62,6 +65,22 @@ public class ComponentInfo implements Serializable {
|
||||
final String componentModel,
|
||||
final String componentSerial,
|
||||
final String componentRevision) {
|
||||
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)
|
||||
* @param componentSerial Component Serial Number (can be null)
|
||||
* @param componentRevision Component Revision or Version (can be null)
|
||||
*/
|
||||
public ComponentInfo(final String deviceName,
|
||||
final String componentManufacturer,
|
||||
final String componentModel,
|
||||
final String componentSerial,
|
||||
final String componentRevision) {
|
||||
if (isComplete(
|
||||
componentManufacturer,
|
||||
componentModel,
|
||||
@ -72,61 +91,40 @@ public class ComponentInfo implements Serializable {
|
||||
throw new NullPointerException("ComponentInfo: manufacturer and/or "
|
||||
+ "model can not be null");
|
||||
}
|
||||
this.deviceName = deviceName;
|
||||
this.componentManufacturer = componentManufacturer.trim();
|
||||
this.componentModel = componentModel.trim();
|
||||
if (componentSerial != null) {
|
||||
this.componentSerial = componentSerial.trim();
|
||||
} else {
|
||||
this.componentSerial = StringUtils.EMPTY;
|
||||
this.componentSerial = ComponentIdentifier.NOT_SPECIFIED_COMPONENT;
|
||||
}
|
||||
if (componentRevision != null) {
|
||||
this.componentRevision = componentRevision.trim();
|
||||
} else {
|
||||
this.componentRevision = StringUtils.EMPTY;
|
||||
this.componentRevision = ComponentIdentifier.NOT_SPECIFIED_COMPONENT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
* @param componentSerial Component Serial Number (can be null)
|
||||
* @param componentRevision Component Revision or Version (can be null)
|
||||
* @param componentClass Component Class (can be null)
|
||||
*/
|
||||
public ComponentInfo(final String componentManufacturer,
|
||||
public ComponentInfo(final String deviceName,
|
||||
final String componentManufacturer,
|
||||
final String componentModel,
|
||||
final String componentSerial,
|
||||
final String componentRevision,
|
||||
final String componentClass) {
|
||||
if (isComplete(
|
||||
componentManufacturer,
|
||||
componentModel,
|
||||
componentSerial,
|
||||
componentRevision)) {
|
||||
log.error("ComponentInfo: manufacturer and/or "
|
||||
+ "model can not be null");
|
||||
throw new NullPointerException("ComponentInfo: manufacturer and/or "
|
||||
+ "model can not be null");
|
||||
}
|
||||
this.componentManufacturer = componentManufacturer.trim();
|
||||
this.componentModel = componentModel.trim();
|
||||
if (componentSerial != null) {
|
||||
this.componentSerial = componentSerial.trim();
|
||||
} else {
|
||||
this.componentSerial = StringUtils.EMPTY;
|
||||
}
|
||||
if (componentRevision != null) {
|
||||
this.componentRevision = componentRevision.trim();
|
||||
} else {
|
||||
this.componentRevision = StringUtils.EMPTY;
|
||||
}
|
||||
this(deviceName, componentManufacturer, componentModel,
|
||||
componentSerial, componentRevision);
|
||||
|
||||
if (componentClass != null) {
|
||||
this.componentClass = componentClass;
|
||||
} else {
|
||||
this.componentClass = StringUtils.EMPTY;
|
||||
}
|
||||
this.componentClass = Objects.requireNonNullElse(componentClass, StringUtils.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,4 +146,44 @@ public class ComponentInfo implements Serializable {
|
||||
return (StringUtils.isEmpty(componentManufacturer)
|
||||
|| 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);
|
||||
}
|
||||
}
|
||||
|
@ -19,26 +19,22 @@ import java.net.UnknownHostException;
|
||||
* Store information about the Portal into the database.
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Entity
|
||||
@Table(name = "PortalInfo")
|
||||
@Access(AccessType.FIELD)
|
||||
public class PortalInfo {
|
||||
|
||||
@Id
|
||||
@Getter
|
||||
@Column
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
@Getter
|
||||
@Column(unique = true, nullable = false)
|
||||
private String name;
|
||||
@Getter
|
||||
@Column
|
||||
private InetAddress ipAddress;
|
||||
@Getter
|
||||
@Column
|
||||
private int port = 0;
|
||||
@Getter
|
||||
@Column
|
||||
private String context;
|
||||
|
||||
@ -57,14 +53,14 @@ public class PortalInfo {
|
||||
/**
|
||||
* Stores the address of the portal.
|
||||
*
|
||||
* @param newip address used by the portal.
|
||||
* @param inetAddress address used by the portal.
|
||||
*/
|
||||
public void setIpAddress(final InetAddress newip) {
|
||||
if (newip == null) {
|
||||
public void setIpAddress(final InetAddress inetAddress) {
|
||||
if (inetAddress == null) {
|
||||
throw new IllegalArgumentException("setIpAddress input was null.");
|
||||
}
|
||||
|
||||
ipAddress = newip;
|
||||
this.ipAddress = inetAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,18 +70,18 @@ public class PortalInfo {
|
||||
* @throws UnknownHostException For problems resolving or storing the host.
|
||||
*/
|
||||
public void setIpAddress(final String host) throws UnknownHostException {
|
||||
ipAddress = InetAddress.getByName(host);
|
||||
this.ipAddress = InetAddress.getByName(host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the port of the portal.
|
||||
*
|
||||
* @param newport port of the portal
|
||||
* @param port port of the portal
|
||||
*/
|
||||
public void setPort(final int newport) {
|
||||
public void setPort(final int port) {
|
||||
final int upperBound = 65535;
|
||||
if (newport > 0 && newport <= upperBound) {
|
||||
port = newport;
|
||||
if (port > 0 && port <= upperBound) {
|
||||
this.port = port;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Failed to store portal port. Provided number was"
|
||||
+ " outside of valid range (1 - " + upperBound + ")");
|
||||
|
@ -28,8 +28,8 @@ import java.util.Objects;
|
||||
* OS, and TPM information.
|
||||
*/
|
||||
@Log4j2
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Entity
|
||||
public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
||||
|
||||
@ -196,7 +196,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
||||
return hardwareInfo;
|
||||
}
|
||||
|
||||
private void setNetworkInfo(NetworkInfo networkInfo) {
|
||||
private void setNetworkInfo(final NetworkInfo networkInfo) {
|
||||
if (networkInfo == null) {
|
||||
log.error("NetworkInfo cannot be null");
|
||||
throw new NullPointerException("network info");
|
||||
@ -204,7 +204,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
||||
this.networkInfo = networkInfo;
|
||||
}
|
||||
|
||||
private void setOSInfo(OSInfo osInfo) {
|
||||
private void setOSInfo(final OSInfo osInfo) {
|
||||
if (osInfo == null) {
|
||||
log.error("OSInfo cannot be null");
|
||||
throw new NullPointerException("os info");
|
||||
@ -212,7 +212,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
||||
this.osInfo = osInfo;
|
||||
}
|
||||
|
||||
private void setFirmwareInfo(FirmwareInfo firmwareInfo) {
|
||||
private void setFirmwareInfo(final FirmwareInfo firmwareInfo) {
|
||||
if (firmwareInfo == null) {
|
||||
log.error("FirmwareInfo cannot be null");
|
||||
throw new NullPointerException("firmware info");
|
||||
@ -220,7 +220,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
||||
this.firmwareInfo = firmwareInfo;
|
||||
}
|
||||
|
||||
private void setHardwareInfo(HardwareInfo hardwareInfo) {
|
||||
private void setHardwareInfo(final HardwareInfo hardwareInfo) {
|
||||
if (hardwareInfo == null) {
|
||||
log.error("HardwareInfo cannot be null");
|
||||
throw new NullPointerException("hardware info");
|
||||
@ -228,7 +228,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
||||
this.hardwareInfo = hardwareInfo;
|
||||
}
|
||||
|
||||
private void setTPMInfo(TPMInfo tpmInfo) {
|
||||
private void setTPMInfo(final TPMInfo tpmInfo) {
|
||||
this.tpmInfo = tpmInfo;
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,11 @@ public class AbstractProcessor {
|
||||
@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
|
||||
*/
|
||||
public AbstractProcessor(final PrivateKey privateKey,
|
||||
final int validDays) {
|
||||
this.privateKey = privateKey;
|
||||
@ -64,6 +69,7 @@ public class AbstractProcessor {
|
||||
* @param endorsementCredential the endorsement credential
|
||||
* @param platformCredentials the set of platform credentials
|
||||
* @param deviceName The host name used in the subject alternative name
|
||||
* @param acaCertificate object used to create credential
|
||||
* @return identity credential
|
||||
*/
|
||||
protected X509Certificate generateCredential(final PublicKey publicKey,
|
||||
@ -159,7 +165,7 @@ public class AbstractProcessor {
|
||||
* @param endorsementCredential an endorsement credential to check if platform credentials
|
||||
* exist
|
||||
* @param certificateRepository db connector from certificates
|
||||
* @return the Set of Platform Credentials, if they exist, an empty set otherwise
|
||||
* @return the List of Platform Credentials, if they exist, an empty set otherwise
|
||||
*/
|
||||
protected List<PlatformCredential> parsePcsFromIdentityClaim(
|
||||
final ProvisionerTpm2.IdentityClaim identityClaim,
|
||||
@ -187,10 +193,12 @@ 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
|
||||
*/
|
||||
private EndorsementCredential getEndorsementCredential(final PublicKey ekPublicKey,
|
||||
final CertificateRepository certificateRepository) {
|
||||
private EndorsementCredential getEndorsementCredential(
|
||||
final PublicKey ekPublicKey,
|
||||
final CertificateRepository certificateRepository) {
|
||||
log.debug("Searching for endorsement credential based on public key: " + ekPublicKey);
|
||||
|
||||
if (ekPublicKey == null) {
|
||||
@ -220,6 +228,7 @@ public class AbstractProcessor {
|
||||
* Helper method to create an {@link IssuedAttestationCertificate} object, set its
|
||||
* corresponding device and persist it.
|
||||
*
|
||||
* @param certificateRepository db store manager for certificates
|
||||
* @param derEncodedAttestationCertificate the byte array representing the Attestation
|
||||
* certificate
|
||||
* @param endorsementCredential the endorsement credential used to generate the AC
|
||||
|
@ -37,8 +37,11 @@ public class CertificateRequestProcessor extends AbstractProcessor {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param supplyChainValidationService object that is used to run provisioning
|
||||
* @param certificateRepository db connector for all certificates.
|
||||
* @param deviceRepository database connector for Devices.
|
||||
* @param privateKey private key used for communication authentication
|
||||
* @param acaCertificate object used to create credential
|
||||
* @param validDays int for the time in which a certificate is valid.
|
||||
* @param tpm2ProvisionerStateRepository db connector for provisioner state.
|
||||
*/
|
||||
@ -97,7 +100,8 @@ public class CertificateRequestProcessor extends AbstractProcessor {
|
||||
RSAPublicKey akPub = ProvisionUtils.parsePublicKey(claim.getAkPublicArea().toByteArray());
|
||||
|
||||
// Get Endorsement Credential if it exists or was uploaded
|
||||
EndorsementCredential endorsementCredential = parseEcFromIdentityClaim(claim, ekPub, certificateRepository);
|
||||
EndorsementCredential endorsementCredential = parseEcFromIdentityClaim(claim,
|
||||
ekPub, certificateRepository);
|
||||
|
||||
// Get Platform Credentials if they exist or were uploaded
|
||||
List<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,
|
||||
|
@ -3,18 +3,24 @@ package hirs.attestationca.persist.provision;
|
||||
import com.google.protobuf.ByteString;
|
||||
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
|
||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentInfoRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
|
||||
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
||||
import hirs.attestationca.persist.entity.manager.PolicyRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
|
||||
import hirs.attestationca.persist.entity.manager.TPM2ProvisionerStateRepository;
|
||||
import hirs.attestationca.persist.entity.tpm.TPM2ProvisionerState;
|
||||
import hirs.attestationca.persist.entity.userdefined.Certificate;
|
||||
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.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;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
|
||||
@ -29,6 +35,7 @@ import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import hirs.attestationca.persist.exceptions.IdentityProcessingException;
|
||||
import hirs.attestationca.persist.provision.helper.ProvisionUtils;
|
||||
import hirs.attestationca.persist.service.SupplyChainValidationService;
|
||||
import hirs.attestationca.persist.validation.SupplyChainCredentialValidator;
|
||||
import hirs.utils.HexUtils;
|
||||
import hirs.utils.SwidResource;
|
||||
import hirs.utils.enums.DeviceInfoEnums;
|
||||
@ -70,17 +77,21 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
||||
|
||||
private SupplyChainValidationService supplyChainValidationService;
|
||||
private CertificateRepository certificateRepository;
|
||||
private ComponentResultRepository componentResultRepository;
|
||||
private ComponentInfoRepository componentInfoRepository;
|
||||
private ReferenceManifestRepository referenceManifestRepository;
|
||||
private ReferenceDigestValueRepository referenceDigestValueRepository;
|
||||
private DeviceRepository deviceRepository;
|
||||
private TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Constructor.
|
||||
*/
|
||||
public IdentityClaimProcessor(
|
||||
final SupplyChainValidationService supplyChainValidationService,
|
||||
final CertificateRepository certificateRepository,
|
||||
final ComponentResultRepository componentResultRepository,
|
||||
final ComponentInfoRepository componentInfoRepository,
|
||||
final ReferenceManifestRepository referenceManifestRepository,
|
||||
final ReferenceDigestValueRepository referenceDigestValueRepository,
|
||||
final DeviceRepository deviceRepository,
|
||||
@ -88,6 +99,8 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
||||
final PolicyRepository policyRepository) {
|
||||
this.supplyChainValidationService = supplyChainValidationService;
|
||||
this.certificateRepository = certificateRepository;
|
||||
this.componentResultRepository = componentResultRepository;
|
||||
this.componentInfoRepository = componentInfoRepository;
|
||||
this.referenceManifestRepository = referenceManifestRepository;
|
||||
this.referenceDigestValueRepository = referenceDigestValueRepository;
|
||||
this.deviceRepository = deviceRepository;
|
||||
@ -187,7 +200,9 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
||||
// Parse and save device info
|
||||
Device device = processDeviceInfo(claim);
|
||||
|
||||
device.getDeviceInfo().setPaccorOutputString(claim.getPaccorOutput());
|
||||
// device.getDeviceInfo().setPaccorOutputString(claim.getPaccorOutput());
|
||||
handleDeviceComponents(device.getDeviceInfo().getNetworkInfo().getHostname(),
|
||||
claim.getPaccorOutput());
|
||||
// There are situations in which the claim is sent with no PCs
|
||||
// or a PC from the tpm which will be deprecated
|
||||
// this is to check what is in the platform object and pull
|
||||
@ -203,9 +218,21 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
||||
|
||||
platformCredentials.addAll(tempList);
|
||||
}
|
||||
// store component results objects
|
||||
for (PlatformCredential platformCredential : platformCredentials) {
|
||||
List<ComponentResult> componentResults = componentResultRepository
|
||||
.findByCertificateSerialNumberAndBoardSerialNumber(
|
||||
platformCredential.getSerialNumber().toString(),
|
||||
platformCredential.getPlatformSerial());
|
||||
if (componentResults.isEmpty()) {
|
||||
handlePlatformComponents(platformCredential);
|
||||
}
|
||||
}
|
||||
|
||||
// perform supply chain validation
|
||||
SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain(
|
||||
endorsementCredential, platformCredentials, device);
|
||||
endorsementCredential, platformCredentials, device,
|
||||
componentInfoRepository.findByDeviceName(device.getName()));
|
||||
device.setSummaryId(summary.getId().toString());
|
||||
// update the validation result in the device
|
||||
AppraisalStatus.Status validationResult = summary.getOverallValidationResult();
|
||||
@ -231,7 +258,12 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
||||
|
||||
log.info("Processing Device Info Report");
|
||||
// store device and device info report.
|
||||
Device device = this.deviceRepository.findByName(deviceInfoReport.getNetworkInfo().getHostname());
|
||||
Device device = null;
|
||||
if (deviceInfoReport.getNetworkInfo() != null
|
||||
&& deviceInfoReport.getNetworkInfo().getHostname() != null
|
||||
&& !deviceInfoReport.getNetworkInfo().getHostname().isEmpty()) {
|
||||
device = this.deviceRepository.findByName(deviceInfoReport.getNetworkInfo().getHostname());
|
||||
}
|
||||
if (device == null) {
|
||||
device = new Device(deviceInfoReport);
|
||||
}
|
||||
@ -302,7 +334,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
||||
pcrValues = dv.getPcrslist().toStringUtf8();
|
||||
}
|
||||
|
||||
// check for RIM Base and Support files, if they don't exists in the database, load them
|
||||
// check for RIM Base and Support files, if they don't exist in the database, load them
|
||||
String defaultClientName = String.format("%s_%s",
|
||||
dv.getHw().getManufacturer(),
|
||||
dv.getHw().getProductName());
|
||||
@ -314,7 +346,6 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
||||
Pattern pattern = Pattern.compile("([^\\s]+(\\.(?i)(rimpcr|rimel|bin|log))$)");
|
||||
Matcher matcher;
|
||||
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
|
||||
// List<ReferenceManifest> listOfSavedRims = new LinkedList<>();
|
||||
|
||||
if (dv.getLogfileCount() > 0) {
|
||||
for (ByteString logFile : dv.getLogfileList()) {
|
||||
@ -424,11 +455,9 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
||||
dbSupport.setUpdated(true);
|
||||
dbSupport.setAssociatedRim(dbBaseRim.getId());
|
||||
this.referenceManifestRepository.save(dbSupport);
|
||||
// listOfSavedRims.add(dbSupport);
|
||||
}
|
||||
}
|
||||
this.referenceManifestRepository.save(dbBaseRim);
|
||||
// listOfSavedRims.add(dbBaseRim);
|
||||
}
|
||||
}
|
||||
|
||||
@ -586,44 +615,66 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
||||
log.error(String.format("Patching value does not exist (%s)",
|
||||
patchedValue));
|
||||
} else {
|
||||
/**
|
||||
* Until we get patch examples, this is WIP
|
||||
*/
|
||||
// WIP - Until we get patch examples
|
||||
dbRdv.setPatched(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (CertificateException cEx) {
|
||||
log.error(cEx);
|
||||
} catch (NoSuchAlgorithmException noSaEx) {
|
||||
log.error(noSaEx);
|
||||
} catch (IOException ioEx) {
|
||||
log.error(ioEx);
|
||||
} catch (CertificateException | NoSuchAlgorithmException | IOException ex) {
|
||||
log.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int handlePlatformComponents(final Certificate certificate) {
|
||||
PlatformCredential platformCredential;
|
||||
int componentResults = 0;
|
||||
if (certificate instanceof PlatformCredential) {
|
||||
platformCredential = (PlatformCredential) certificate;
|
||||
ComponentResult componentResult;
|
||||
for (ComponentIdentifier componentIdentifier : platformCredential
|
||||
.getComponentIdentifiers()) {
|
||||
|
||||
|
||||
private List<PlatformCredential> getPlatformCredentials(final CertificateRepository certificateRepository,
|
||||
final EndorsementCredential ec) {
|
||||
List<PlatformCredential> credentials = null;
|
||||
|
||||
if (ec == null) {
|
||||
log.warn("Cannot look for platform credential(s). Endorsement credential was null.");
|
||||
} else {
|
||||
log.debug("Searching for platform credential(s) based on holder serial number: "
|
||||
+ ec.getSerialNumber());
|
||||
credentials = certificateRepository.getByHolderSerialNumber(ec.getSerialNumber());
|
||||
if (credentials == null || credentials.isEmpty()) {
|
||||
log.warn("No platform credential(s) found");
|
||||
} else {
|
||||
log.debug("Platform Credential(s) found: " + credentials.size());
|
||||
componentResult = new ComponentResult(platformCredential.getPlatformSerial(),
|
||||
platformCredential.getSerialNumber().toString(),
|
||||
platformCredential.getPlatformChainType(),
|
||||
componentIdentifier);
|
||||
componentResult.setFailedValidation(false);
|
||||
componentResultRepository.save(componentResult);
|
||||
componentResults++;
|
||||
}
|
||||
}
|
||||
return componentResults;
|
||||
}
|
||||
|
||||
return credentials;
|
||||
private int handleDeviceComponents(final String hostName, final String paccorString) {
|
||||
int deviceComponents = 0 ;
|
||||
Map<Integer, ComponentInfo> componentInfoMap = new HashMap<>();
|
||||
try {
|
||||
List<ComponentInfo> componentInfos = SupplyChainCredentialValidator
|
||||
.getComponentInfoFromPaccorOutput(hostName, paccorString);
|
||||
|
||||
// check the DB for like component infos
|
||||
List<ComponentInfo> dbComponentInfos = this.componentInfoRepository.findByDeviceName(hostName);
|
||||
dbComponentInfos.stream().forEach((infos) -> {
|
||||
componentInfoMap.put(infos.hashCode(), infos);
|
||||
});
|
||||
|
||||
for (ComponentInfo componentInfo : dbComponentInfos) {
|
||||
if (componentInfoMap.containsKey(componentInfo.hashCode())) {
|
||||
componentInfos.remove(componentInfo);
|
||||
}
|
||||
}
|
||||
|
||||
for (ComponentInfo componentInfo : componentInfos) {
|
||||
this.componentInfoRepository.save(componentInfo);
|
||||
}
|
||||
} catch (IOException ioEx) {
|
||||
log.warn("Error parsing paccor string");
|
||||
}
|
||||
|
||||
return deviceComponents;
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,8 @@ import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -4,8 +4,6 @@ import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCred
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
@ -42,13 +40,13 @@ public final class IssuedCertificateAttributeHelper {
|
||||
/**
|
||||
* Object Identifier TCPA at TPM ID Label.
|
||||
*/
|
||||
public final static ASN1ObjectIdentifier 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 final static Extension EXTENDED_KEY_USAGE_EXTENSION;
|
||||
private final static ASN1ObjectIdentifier TCG_KP_AIK_CERTIFICATE_ATTRIBUTE =
|
||||
public static final Extension EXTENDED_KEY_USAGE_EXTENSION;
|
||||
private static final ASN1ObjectIdentifier TCG_KP_AIK_CERTIFICATE_ATTRIBUTE =
|
||||
new ASN1ObjectIdentifier("2.23.133.8.3");
|
||||
|
||||
static {
|
||||
|
@ -4,6 +4,7 @@ import hirs.attestationca.persist.DBManagerException;
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
|
||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentAttributeRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
|
||||
import hirs.attestationca.persist.entity.manager.PolicyRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
|
||||
@ -14,14 +15,18 @@ import hirs.attestationca.persist.entity.userdefined.Device;
|
||||
import hirs.attestationca.persist.entity.userdefined.PolicySettings;
|
||||
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;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentAttributeResult;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.rim.EventLogMeasurements;
|
||||
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import hirs.attestationca.persist.validation.PcrValidator;
|
||||
import hirs.attestationca.persist.validation.SupplyChainCredentialValidator;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -32,8 +37,7 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import java.util.UUID;
|
||||
|
||||
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
|
||||
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
|
||||
@ -47,9 +51,11 @@ public class SupplyChainValidationService {
|
||||
private ReferenceManifestRepository referenceManifestRepository;
|
||||
private ReferenceDigestValueRepository referenceDigestValueRepository;
|
||||
private ComponentResultRepository componentResultRepository;
|
||||
private ComponentAttributeRepository componentAttributeRepository;
|
||||
private CertificateRepository certificateRepository;
|
||||
private SupplyChainValidationRepository supplyChainValidationRepository;
|
||||
private SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository;
|
||||
private UUID provisionSessionId;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -70,6 +76,7 @@ public class SupplyChainValidationService {
|
||||
final PolicyRepository policyRepository,
|
||||
final CertificateRepository certificateRepository,
|
||||
final ComponentResultRepository componentResultRepository,
|
||||
final ComponentAttributeRepository componentAttributeRepository,
|
||||
final ReferenceManifestRepository referenceManifestRepository,
|
||||
final SupplyChainValidationRepository supplyChainValidationRepository,
|
||||
final SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository,
|
||||
@ -78,6 +85,7 @@ public class SupplyChainValidationService {
|
||||
this.policyRepository = policyRepository;
|
||||
this.certificateRepository = certificateRepository;
|
||||
this.componentResultRepository = componentResultRepository;
|
||||
this.componentAttributeRepository = componentAttributeRepository;
|
||||
this.referenceManifestRepository = referenceManifestRepository;
|
||||
this.supplyChainValidationRepository = supplyChainValidationRepository;
|
||||
this.supplyChainValidationSummaryRepository = supplyChainValidationSummaryRepository;
|
||||
@ -92,13 +100,16 @@ public class SupplyChainValidationService {
|
||||
* @param ec The endorsement credential from the identity request.
|
||||
* @param pcs The platform credentials from the identity request.
|
||||
* @param device The device to be validated.
|
||||
* @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) {
|
||||
final Device device,
|
||||
final List<ComponentInfo> componentInfos) {
|
||||
boolean acceptExpiredCerts = getPolicySettings().isExpiredCertificateValidationEnabled();
|
||||
provisionSessionId = UUID.randomUUID();
|
||||
PlatformCredential baseCredential = null;
|
||||
SupplyChainValidation platformScv = null;
|
||||
SupplyChainValidation basePlatformScv = null;
|
||||
@ -205,6 +216,8 @@ public class SupplyChainValidationService {
|
||||
null, Level.ERROR));
|
||||
} else {
|
||||
if (chkDeltas) {
|
||||
// There are delta certificates, so the code need to build a new list of
|
||||
// certificate components to then compare against the device component list
|
||||
aes.addAll(basePlatformScv.getCertificatesUsed());
|
||||
Iterator<PlatformCredential> it = pcs.iterator();
|
||||
while (it.hasNext()) {
|
||||
@ -220,16 +233,23 @@ public class SupplyChainValidationService {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// validate attributes for a single base platform certificate
|
||||
aes.add(baseCredential);
|
||||
validations.remove(platformScv);
|
||||
// if there are no deltas, just check base credential
|
||||
platformScv = ValidationService.evaluatePCAttributesStatus(
|
||||
baseCredential, device.getDeviceInfo(), ec,
|
||||
certificateRepository, componentResultRepository);
|
||||
certificateRepository, componentResultRepository,
|
||||
componentAttributeRepository, componentInfos, provisionSessionId);
|
||||
validations.add(new SupplyChainValidation(
|
||||
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
|
||||
platformScv.getValidationResult(), aes, platformScv.getMessage()));
|
||||
}
|
||||
|
||||
updateComponentStatus(componentResultRepository
|
||||
.findByCertificateSerialNumberAndBoardSerialNumber(
|
||||
baseCredential.getSerialNumber().toString(),
|
||||
baseCredential.getPlatformSerial()));
|
||||
}
|
||||
if (!attrErrorMessage.isEmpty()) {
|
||||
//combine platform and platform attributes
|
||||
@ -252,7 +272,7 @@ public class SupplyChainValidationService {
|
||||
log.info("The validation finished, summarizing...");
|
||||
// Generate validation summary, save it, and return it.
|
||||
SupplyChainValidationSummary summary
|
||||
= new SupplyChainValidationSummary(device, validations);
|
||||
= new SupplyChainValidationSummary(device, validations, provisionSessionId);
|
||||
try {
|
||||
supplyChainValidationSummaryRepository.save(summary);
|
||||
} catch (DBManagerException dbMEx) {
|
||||
@ -374,4 +394,25 @@ public class SupplyChainValidationService {
|
||||
}
|
||||
return defaultSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
List<ComponentAttributeResult> componentAttributeResults = componentAttributeRepository
|
||||
.findByProvisionSessionId(provisionSessionId);
|
||||
List<UUID> componentIdList = new ArrayList<>();
|
||||
|
||||
for (ComponentAttributeResult componentAttributeResult : componentAttributeResults) {
|
||||
componentIdList.add(componentAttributeResult.getComponentId());
|
||||
}
|
||||
|
||||
for (ComponentResult componentResult : componentResults) {
|
||||
componentResult.setFailedValidation(componentIdList.contains(componentResult.getId()));
|
||||
componentResultRepository.save(componentResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package hirs.attestationca.persist.service;
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
|
||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentAttributeRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
|
||||
@ -12,9 +13,9 @@ 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.certificate.CertificateAuthorityCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
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;
|
||||
@ -37,6 +38,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Log4j2
|
||||
public class ValidationService {
|
||||
@ -104,7 +106,10 @@ public class ValidationService {
|
||||
final PlatformCredential pc, final DeviceInfoReport deviceInfoReport,
|
||||
final EndorsementCredential ec,
|
||||
final CertificateRepository certificateRepository,
|
||||
final ComponentResultRepository componentResultRepository) {
|
||||
final ComponentResultRepository componentResultRepository,
|
||||
final ComponentAttributeRepository componentAttributeRepository,
|
||||
final List<ComponentInfo> componentInfos,
|
||||
final UUID provisionSessionId) {
|
||||
final SupplyChainValidation.ValidationType validationType
|
||||
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
|
||||
|
||||
@ -116,7 +121,9 @@ public class ValidationService {
|
||||
}
|
||||
log.info("Validating platform credential attributes");
|
||||
AppraisalStatus result = CredentialValidator.
|
||||
validatePlatformCredentialAttributes(pc, deviceInfoReport, ec);
|
||||
validatePlatformCredentialAttributes(pc, deviceInfoReport, ec,
|
||||
componentResultRepository, componentAttributeRepository,
|
||||
componentInfos, provisionSessionId);
|
||||
switch (result.getAppStatus()) {
|
||||
case PASS:
|
||||
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
|
||||
@ -126,10 +133,6 @@ public class ValidationService {
|
||||
pc.setComponentFailures(result.getAdditionalInfo());
|
||||
pc.setComponentFailureMessage(result.getMessage());
|
||||
certificateRepository.save(pc);
|
||||
for (ComponentResult componentResult
|
||||
: CertificateAttributeScvValidator.getComponentResultList()) {
|
||||
componentResultRepository.save(componentResult);
|
||||
}
|
||||
}
|
||||
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
|
||||
result.getMessage(), pc, Level.WARN);
|
||||
|
@ -4,11 +4,14 @@ import com.github.marandus.pciid.model.Device;
|
||||
import com.github.marandus.pciid.model.Vendor;
|
||||
import com.github.marandus.pciid.service.PciIdsDatabase;
|
||||
import com.google.common.base.Strings;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
|
||||
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.V2.ComponentIdentifierV2;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.bouncycastle.asn1.ASN1UTF8String;
|
||||
import org.bouncycastle.asn1.DERUTF8String;
|
||||
|
||||
@ -23,6 +26,7 @@ import java.util.List;
|
||||
/**
|
||||
* Provide Java access to PCI IDs.
|
||||
*/
|
||||
@Log4j2
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class PciIds {
|
||||
/**
|
||||
@ -52,6 +56,7 @@ public final class PciIds {
|
||||
String dbFile = null;
|
||||
for (final String path : PCI_IDS_PATH) {
|
||||
if ((new File(path)).exists()) {
|
||||
log.info("PCI IDs file was found {}", path);
|
||||
dbFile = path;
|
||||
break;
|
||||
}
|
||||
@ -113,6 +118,23 @@ public final class PciIds {
|
||||
return newList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all components and translate PCI hardware IDs as necessary. It will only
|
||||
* translate ComponentResults objects as it relies on Component Class information.
|
||||
* @param componentResults List of ComponentResults.
|
||||
* @return the translated list of ComponentResults.
|
||||
*/
|
||||
public static List<ComponentResult> translateResults(final List<ComponentResult> componentResults) {
|
||||
List<ComponentResult> newList = new ArrayList<>();
|
||||
if (componentResults != null && !componentResults.isEmpty()) {
|
||||
for (final ComponentResult componentResult : componentResults) {
|
||||
newList.add(translateResult(componentResult));
|
||||
}
|
||||
}
|
||||
|
||||
return newList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate Vendor and Device IDs, if found, in ComponentIdentifierV2 objects.
|
||||
* It will only translate ID values, any other value will pass through.
|
||||
@ -149,6 +171,23 @@ public final class PciIds {
|
||||
return newComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate Vendor and Device IDs, if found, in ComponentResult objects.
|
||||
* It will only translate ID values, any other value will pass through.
|
||||
* @param componentResult ComponentResult object.
|
||||
* @return the translated ComponentResult object.
|
||||
*/
|
||||
public static ComponentResult translateResult(final ComponentResult componentResult) {
|
||||
ComponentResult newComponent = null;
|
||||
if (componentResult != null) {
|
||||
newComponent = componentResult;
|
||||
newComponent.setManufacturer(translateVendor(componentResult.getManufacturer()));
|
||||
newComponent.setModel(translateDevice(componentResult.getManufacturer(),
|
||||
componentResult.getModel()));
|
||||
}
|
||||
return newComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the vendor name from the PCI IDs list, if the input string contains an ID.
|
||||
* If any part of this fails, return the original manufacturer value.
|
||||
@ -166,6 +205,23 @@ public final class PciIds {
|
||||
return manufacturer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the vendor name from the PCI IDs list, if the input string contains an ID.
|
||||
* If any part of this fails, return the original manufacturer value.
|
||||
* @param refManufacturer String, likely from a ComponentResult
|
||||
* @return String with the discovered vendor name, or the original manufacturer value.
|
||||
*/
|
||||
public static String translateVendor(final String refManufacturer) {
|
||||
String manufacturer = refManufacturer;
|
||||
if (manufacturer != null && manufacturer.trim().matches("^[0-9A-Fa-f]{4}$")) {
|
||||
Vendor ven = DB.findVendor(manufacturer.toLowerCase());
|
||||
if (ven != null && !Strings.isNullOrEmpty(ven.getName())) {
|
||||
manufacturer = ven.getName();
|
||||
}
|
||||
}
|
||||
return manufacturer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the device name from the PCI IDs list, if the input strings contain IDs.
|
||||
* The Device lookup requires the Vendor ID AND the Device ID to be valid values.
|
||||
@ -190,4 +246,28 @@ public final class PciIds {
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the device name from the PCI IDs list, if the input strings contain IDs.
|
||||
* The Device lookup requires the Vendor ID AND the Device ID to be valid values.
|
||||
* If any part of this fails, return the original model value.
|
||||
* @param refManufacturer String, likely from a ComponentResult
|
||||
* @param refModel String, likely from a ComponentResult
|
||||
* @return String with the discovered device name, or the original model value.
|
||||
*/
|
||||
public static String translateDevice(final String refManufacturer,
|
||||
final String refModel) {
|
||||
String model = refModel;
|
||||
if (refManufacturer != null
|
||||
&& model != null
|
||||
&& refManufacturer.trim().matches("^[0-9A-Fa-f]{4}$")
|
||||
&& model.trim().matches("^[0-9A-Fa-f]{4}$")) {
|
||||
Device dev = DB.findDevice(refManufacturer.toLowerCase(),
|
||||
model.toLowerCase());
|
||||
if (dev != null && !Strings.isNullOrEmpty(dev.getName())) {
|
||||
model = dev.getName();
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package hirs.attestationca.persist.validation;
|
||||
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentAttributeRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
|
||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentAttributeResult;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
|
||||
@ -43,15 +46,7 @@ import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
|
||||
@Log4j2
|
||||
public class CertificateAttributeScvValidator extends SupplyChainCredentialValidator {
|
||||
|
||||
private static List<ComponentResult> componentResultList = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Getter for the list of components to verify.
|
||||
* @return a collection of components
|
||||
*/
|
||||
public static List<ComponentResult> getComponentResultList() {
|
||||
return Collections.unmodifiableList(componentResultList);
|
||||
}
|
||||
private static final String LC_UNKNOWN = "unknown";
|
||||
|
||||
/**
|
||||
* Checks if the delta credential's attributes are valid.
|
||||
@ -97,7 +92,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
List<ComponentIdentifier> origPcComponents
|
||||
= new LinkedList<>(basePlatformCredential.getComponentIdentifiers());
|
||||
|
||||
return validateDeltaAttributesChainV2p0(deltaPlatformCredential.getId(),
|
||||
return validateDeltaAttributesChainV2p0(
|
||||
deviceInfoReport, deltaMapping, origPcComponents);
|
||||
}
|
||||
|
||||
@ -190,7 +185,6 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
+ " did not match the Certificate's Serial Number";
|
||||
log.error(message);
|
||||
status = new AppraisalStatus(FAIL, message);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,16 +192,23 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates device info report against the new platform credential.
|
||||
* @param platformCredential the Platform Credential
|
||||
* @param deviceInfoReport the Device Info Report
|
||||
* @param componentResultRepository db access to component result of mismatching
|
||||
* @param componentAttributeRepository db access to component attribute match status
|
||||
* @param componentInfos list of device components
|
||||
* @param provisionSessionId UUID associated with the SCV Summary
|
||||
* @return either PASS or FAIL
|
||||
*/
|
||||
public static AppraisalStatus validatePlatformCredentialAttributesV2p0(
|
||||
final PlatformCredential platformCredential,
|
||||
final DeviceInfoReport deviceInfoReport) {
|
||||
final DeviceInfoReport deviceInfoReport,
|
||||
final ComponentResultRepository componentResultRepository,
|
||||
final ComponentAttributeRepository componentAttributeRepository,
|
||||
final List<ComponentInfo> componentInfos,
|
||||
final UUID provisionSessionId) {
|
||||
boolean passesValidation = true;
|
||||
StringBuilder resultMessage = new StringBuilder();
|
||||
|
||||
@ -236,17 +237,24 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
|
||||
passesValidation &= fieldValidation;
|
||||
|
||||
fieldValidation = requiredPlatformCredentialFieldIsNonEmptyAndMatches(
|
||||
"PlatformVersion",
|
||||
platformCredential.getVersion(),
|
||||
hardwareInfo.getVersion());
|
||||
if (!isNotSpecifiedOrUnknown(platformCredential.getVersion())
|
||||
&& !isNotSpecifiedOrUnknown(hardwareInfo.getVersion())) {
|
||||
fieldValidation = requiredPlatformCredentialFieldIsNonEmptyAndMatches(
|
||||
"PlatformVersion",
|
||||
platformCredential.getVersion(),
|
||||
hardwareInfo.getVersion());
|
||||
|
||||
if (!fieldValidation) {
|
||||
resultMessage.append("Platform version did not match\n");
|
||||
if (!fieldValidation) {
|
||||
resultMessage.append("Platform version did not match\n");
|
||||
}
|
||||
|
||||
passesValidation &= fieldValidation;
|
||||
} else {
|
||||
log.warn("The Platform Certificate System version was {} and the reported Device System Information "
|
||||
+ "version was {}, therefore this check is skipped...",
|
||||
platformCredential.getVersion(), hardwareInfo.getVersion());
|
||||
}
|
||||
|
||||
passesValidation &= fieldValidation;
|
||||
|
||||
// check PlatformSerial against both system-serial-number and baseboard-serial-number
|
||||
fieldValidation = (
|
||||
(optionalPlatformCredentialFieldNullOrMatches(
|
||||
@ -291,42 +299,86 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
|
||||
// There is no need to do comparisons with components that are invalid because
|
||||
// they did not have a manufacturer or model.
|
||||
List<ComponentIdentifier> validPcComponents = allPcComponents.stream()
|
||||
.filter(identifier -> identifier.getComponentManufacturer() != null
|
||||
&& identifier.getComponentModel() != null)
|
||||
.collect(Collectors.toList());
|
||||
// List<ComponentIdentifier> validPcComponents = allPcComponents.stream()
|
||||
// .filter(identifier -> identifier.getComponentManufacturer() != null
|
||||
// && identifier.getComponentModel() != null)
|
||||
// .collect(Collectors.toList());
|
||||
|
||||
String paccorOutputString = deviceInfoReport.getPaccorOutputString();
|
||||
String unmatchedComponents;
|
||||
try {
|
||||
List<ComponentInfo> componentInfoList
|
||||
= getComponentInfoFromPaccorOutput(paccorOutputString);
|
||||
unmatchedComponents = validateV2p0PlatformCredentialComponentsExpectingExactMatch(
|
||||
platformCredential.getId(),
|
||||
validPcComponents, componentInfoList);
|
||||
fieldValidation &= unmatchedComponents.isEmpty();
|
||||
} catch (IOException e) {
|
||||
final String baseErrorMessage = "Error parsing JSON output from PACCOR: ";
|
||||
log.error(baseErrorMessage + e.toString());
|
||||
log.error("PACCOR output string:\n" + paccorOutputString);
|
||||
return new AppraisalStatus(ERROR, baseErrorMessage + e.getMessage());
|
||||
// String paccorOutputString = deviceInfoReport.getPaccorOutputString();
|
||||
// String unmatchedComponents;
|
||||
|
||||
// populate componentResults list
|
||||
List<ComponentResult> componentResults = componentResultRepository
|
||||
.findByCertificateSerialNumberAndBoardSerialNumber(
|
||||
platformCredential.getSerialNumber().toString(),
|
||||
platformCredential.getPlatformSerial());
|
||||
// first create hash map based on hashCode
|
||||
Map<Integer, List<ComponentInfo>> deviceHashMap = new HashMap<>();
|
||||
componentInfos.stream().forEach((componentInfo) -> {
|
||||
List<ComponentInfo> innerList;
|
||||
Integer compInfoHash = componentInfo.hashCommonElements();
|
||||
if (deviceHashMap.containsKey(compInfoHash)) {
|
||||
innerList = deviceHashMap.get(compInfoHash);
|
||||
innerList.add(componentInfo);
|
||||
} else {
|
||||
innerList = new ArrayList<>(0);
|
||||
innerList.add(componentInfo);
|
||||
}
|
||||
deviceHashMap.put(compInfoHash, innerList);
|
||||
});
|
||||
|
||||
// Look for hash code in device mapping
|
||||
// if it exists, don't save the component
|
||||
List<ComponentResult> remainingComponentResults = new ArrayList<>();
|
||||
int numOfAttributes = 0;
|
||||
for (ComponentResult componentResult : componentResults) {
|
||||
if (!deviceHashMap.containsKey(componentResult.hashCommonElements())) {
|
||||
// didn't find the component result in the hashed mapping
|
||||
remainingComponentResults.add(componentResult);
|
||||
}
|
||||
}
|
||||
if (!remainingComponentResults.isEmpty()) {
|
||||
// continue down the options, move to a different method.
|
||||
// create component class mapping to component info
|
||||
Map<String, List<ComponentInfo>> componentDeviceMap = new HashMap<>();
|
||||
componentInfos.stream().forEach((componentInfo) -> {
|
||||
List<ComponentInfo> innerList;
|
||||
String componentClass = componentInfo.getComponentClass();
|
||||
if (componentDeviceMap.containsKey(componentClass)) {
|
||||
innerList = componentDeviceMap.get(componentClass);
|
||||
innerList.add(componentInfo);
|
||||
} else {
|
||||
innerList = new ArrayList<>(0);
|
||||
innerList.add(componentInfo);
|
||||
}
|
||||
componentDeviceMap.put(componentClass, innerList);
|
||||
});
|
||||
|
||||
List<ComponentInfo> componentClassInfo;
|
||||
List<ComponentAttributeResult> attributeResults = new ArrayList<>();
|
||||
for (ComponentResult componentResult : remainingComponentResults) {
|
||||
componentClassInfo = componentDeviceMap.get(componentResult.getComponentClassValue());
|
||||
if (componentClassInfo.size() == 1) {
|
||||
attributeResults.addAll(generateComponentResults(componentClassInfo.get(0), componentResult));
|
||||
} else {
|
||||
attributeResults.addAll(findMismatchedValues(componentClassInfo, componentResult));
|
||||
}
|
||||
}
|
||||
|
||||
for (ComponentAttributeResult componentAttributeResult : attributeResults) {
|
||||
componentAttributeResult.setProvisionSessionId(provisionSessionId);
|
||||
componentAttributeRepository.save(componentAttributeResult);
|
||||
fieldValidation &= componentAttributeResult.checkMatchedStatus();
|
||||
}
|
||||
numOfAttributes = attributeResults.size();
|
||||
}
|
||||
|
||||
StringBuilder additionalInfo = new StringBuilder();
|
||||
if (!fieldValidation) {
|
||||
resultMessage.append("There are unmatched components:\n");
|
||||
resultMessage.append(unmatchedComponents);
|
||||
|
||||
// pass information of which ones failed in additionInfo
|
||||
int counter = 0;
|
||||
for (ComponentIdentifier ci : validPcComponents) {
|
||||
counter++;
|
||||
additionalInfo.append(String.format("%d;", ci.hashCode()));
|
||||
}
|
||||
if (counter > 0) {
|
||||
additionalInfo.insert(0, "COMPID=");
|
||||
additionalInfo.append(counter);
|
||||
}
|
||||
if (!remainingComponentResults.isEmpty()) {
|
||||
resultMessage.append(String.format("There are %d components not matched%n",
|
||||
remainingComponentResults.size()));
|
||||
resultMessage.append(String.format("\twith %d total attributes mismatched.",
|
||||
numOfAttributes));
|
||||
}
|
||||
|
||||
passesValidation &= fieldValidation;
|
||||
@ -338,6 +390,78 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method produces component attribute results for a single device that was found
|
||||
* by component class.
|
||||
* @param componentInfo the device object
|
||||
* @param componentResult the certificate expected object
|
||||
* @return a list of attribute match results
|
||||
*/
|
||||
private static List<ComponentAttributeResult> generateComponentResults(
|
||||
final ComponentInfo componentInfo,
|
||||
final ComponentResult componentResult) {
|
||||
// there are instances of components with the same class (ie hard disks, memory)
|
||||
List<ComponentAttributeResult> attributeResults = new ArrayList<>();
|
||||
if (!componentInfo.getComponentManufacturer().equals(componentResult.getManufacturer())) {
|
||||
attributeResults.add(new ComponentAttributeResult(componentResult.getId(),
|
||||
componentResult.getManufacturer(), componentInfo.getComponentManufacturer()));
|
||||
}
|
||||
|
||||
if (!componentInfo.getComponentModel().equals(componentResult.getModel())) {
|
||||
attributeResults.add(new ComponentAttributeResult(componentResult.getId(),
|
||||
componentResult.getModel(), componentInfo.getComponentModel()));
|
||||
}
|
||||
|
||||
if (!componentInfo.getComponentSerial().equals(componentResult.getSerialNumber())) {
|
||||
attributeResults.add(new ComponentAttributeResult(componentResult.getId(),
|
||||
componentResult.getSerialNumber(), componentInfo.getComponentSerial()));
|
||||
}
|
||||
|
||||
if (!componentInfo.getComponentRevision().equals(componentResult.getRevisionNumber())) {
|
||||
attributeResults.add(new ComponentAttributeResult(componentResult.getId(),
|
||||
componentResult.getRevisionNumber(), componentInfo.getComponentRevision()));
|
||||
}
|
||||
|
||||
return attributeResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when there are multiple components on the device that match
|
||||
* the certificate component's component class type and there is either a mismatch or
|
||||
* a status of not found to be assigned.
|
||||
* @param componentClassInfo list of device components with the same class type
|
||||
* @param componentResult the certificate component that is mismatched
|
||||
* @return a list of attribute results, if all 4 attributes are never matched, it is not found
|
||||
*/
|
||||
private static List<ComponentAttributeResult> findMismatchedValues(
|
||||
final List<ComponentInfo> componentClassInfo,
|
||||
final ComponentResult componentResult) {
|
||||
// this list only has those of the same class type
|
||||
Map<String, ComponentInfo> componentSerialMap = new HashMap<>();
|
||||
componentClassInfo.stream().forEach((componentInfo) -> {
|
||||
componentSerialMap.put(componentInfo.getComponentSerial(), componentInfo);
|
||||
});
|
||||
// see if the serial exists
|
||||
ComponentInfo componentInfo = componentSerialMap.get(componentResult.getSerialNumber());
|
||||
|
||||
if (componentInfo != null && componentInfo.getComponentManufacturer()
|
||||
.equals(componentResult.getManufacturer())) {
|
||||
// the serial matched and the manufacturer, create attribute result and move on
|
||||
return generateComponentResults(componentInfo, componentResult);
|
||||
} else {
|
||||
// didn't find based on serial
|
||||
// look for highest match; otherwise ignore
|
||||
// I already know serial doesn't match
|
||||
for (ComponentInfo ci : componentClassInfo) {
|
||||
if (ci.getComponentManufacturer().equals(componentResult.getManufacturer())
|
||||
&& ci.getComponentModel().equals(componentResult.getModel())) {
|
||||
return generateComponentResults(ci, componentResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* The main purpose of this method, the in process of validation, is to
|
||||
* pick out the changes that lead to the delta cert and make sure the changes
|
||||
@ -351,7 +475,6 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
*/
|
||||
@SuppressWarnings("methodlength")
|
||||
static AppraisalStatus validateDeltaAttributesChainV2p0(
|
||||
final UUID certificateId,
|
||||
final DeviceInfoReport deviceInfoReport,
|
||||
final Map<PlatformCredential, SupplyChainValidation> deltaMapping,
|
||||
final List<ComponentIdentifier> origPcComponents) {
|
||||
@ -466,10 +589,11 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
String unmatchedComponents;
|
||||
try {
|
||||
// compare based on component class
|
||||
List<ComponentInfo> componentInfoList = getV2PaccorOutput(paccorOutputString);
|
||||
List<ComponentInfo> componentInfoList = getComponentInfoFromPaccorOutput(
|
||||
deviceInfoReport.getNetworkInfo().getHostname(),
|
||||
paccorOutputString);
|
||||
// this is what I want to rewrite
|
||||
unmatchedComponents = validateV2PlatformCredentialAttributes(
|
||||
certificateId,
|
||||
baseCompList,
|
||||
componentInfoList);
|
||||
fieldValidation &= unmatchedComponents.isEmpty();
|
||||
@ -505,7 +629,6 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
}
|
||||
|
||||
private static String validateV2PlatformCredentialAttributes(
|
||||
final UUID certificateId,
|
||||
final List<ComponentIdentifier> fullDeltaChainComponents,
|
||||
final List<ComponentInfo> allDeviceInfoComponents) {
|
||||
ComponentIdentifierV2 ciV2;
|
||||
@ -521,7 +644,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
ciV2 = (ComponentIdentifierV2) cId;
|
||||
if (cInfo.getComponentClass().contains(
|
||||
ciV2.getComponentClass().getComponentIdentifier())
|
||||
&& isMatch(certificateId, cId, cInfo)) {
|
||||
&& isMatch(cId, cInfo)) {
|
||||
subCompIdList.remove(cId);
|
||||
subCompInfoList.remove(cInfo);
|
||||
}
|
||||
@ -716,10 +839,10 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
* **NEW** this is updated with just the unmatched components
|
||||
* if there are any failures, otherwise it remains unchanged.
|
||||
* @param allDeviceInfoComponents the device info report components
|
||||
* @return true if validation passes
|
||||
* @return passes if the returned value is empty, otherwise the components that are unmatched
|
||||
* populate the string
|
||||
*/
|
||||
private static String validateV2p0PlatformCredentialComponentsExpectingExactMatch(
|
||||
final UUID certificateId,
|
||||
final List<ComponentIdentifier> untrimmedPcComponents,
|
||||
final List<ComponentInfo> allDeviceInfoComponents) {
|
||||
// For each manufacturer listed in the platform credential, create two lists:
|
||||
@ -791,7 +914,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
|
||||
if (first.isPresent()) {
|
||||
ComponentInfo potentialMatch = first.get();
|
||||
if (isMatch(certificateId, pcComponent, potentialMatch)) {
|
||||
if (isMatch(pcComponent, potentialMatch)) {
|
||||
pcComponentsFromManufacturer.remove(pcComponent);
|
||||
deviceInfoComponentsFromManufacturer.remove(potentialMatch);
|
||||
}
|
||||
@ -819,7 +942,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
|
||||
if (first.isPresent()) {
|
||||
ComponentInfo potentialMatch = first.get();
|
||||
if (isMatch(certificateId, pcComponent, potentialMatch)) {
|
||||
if (isMatch(pcComponent, potentialMatch)) {
|
||||
pcComponentsFromManufacturer.remove(pcComponent);
|
||||
deviceInfoComponentsFromManufacturer.remove(potentialMatch);
|
||||
}
|
||||
@ -833,7 +956,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
= deviceInfoComponentsFromManufacturer.iterator();
|
||||
while (diComponentIter.hasNext()) {
|
||||
ComponentInfo potentialMatch = diComponentIter.next();
|
||||
if (isMatch(certificateId, ci, potentialMatch)) {
|
||||
if (isMatch(ci, potentialMatch)) {
|
||||
pcComponentsFromManufacturer.remove(ci);
|
||||
diComponentIter.remove();
|
||||
}
|
||||
@ -872,13 +995,11 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
/**
|
||||
* Checks if the fields in the potentialMatch match the fields in the pcComponent,
|
||||
* or if the relevant field in the pcComponent is empty.
|
||||
* @param certificateId the certificate id
|
||||
* @param pcComponent the platform credential component
|
||||
* @param potentialMatch the component info from a device info report
|
||||
* @return true if the fields match exactly (null is considered the same as an empty string)
|
||||
*/
|
||||
private static boolean isMatch(final UUID certificateId,
|
||||
final ComponentIdentifier pcComponent,
|
||||
public static boolean isMatch(final ComponentIdentifier pcComponent,
|
||||
final ComponentInfo potentialMatch) {
|
||||
boolean matchesSoFar = true;
|
||||
|
||||
@ -887,49 +1008,24 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
pcComponent.getComponentManufacturer()
|
||||
);
|
||||
|
||||
if (matchesSoFar) {
|
||||
componentResultList.add(new ComponentResult(certificateId, pcComponent.hashCode(),
|
||||
potentialMatch.getComponentSerial(),
|
||||
pcComponent.getComponentSerial().getString()));
|
||||
}
|
||||
|
||||
matchesSoFar &= isMatchOrEmptyInPlatformCert(
|
||||
potentialMatch.getComponentModel(),
|
||||
pcComponent.getComponentModel()
|
||||
);
|
||||
|
||||
if (matchesSoFar) {
|
||||
componentResultList.add(new ComponentResult(certificateId, pcComponent.hashCode(),
|
||||
potentialMatch.getComponentSerial(),
|
||||
pcComponent.getComponentSerial().getString()));
|
||||
}
|
||||
|
||||
matchesSoFar &= isMatchOrEmptyInPlatformCert(
|
||||
potentialMatch.getComponentSerial(),
|
||||
pcComponent.getComponentSerial()
|
||||
);
|
||||
|
||||
if (matchesSoFar) {
|
||||
componentResultList.add(new ComponentResult(certificateId, pcComponent.hashCode(),
|
||||
potentialMatch.getComponentSerial(),
|
||||
pcComponent.getComponentSerial().getString()));
|
||||
}
|
||||
|
||||
matchesSoFar &= isMatchOrEmptyInPlatformCert(
|
||||
potentialMatch.getComponentRevision(),
|
||||
pcComponent.getComponentRevision()
|
||||
);
|
||||
|
||||
if (matchesSoFar) {
|
||||
componentResultList.add(new ComponentResult(certificateId, pcComponent.hashCode(),
|
||||
potentialMatch.getComponentSerial(),
|
||||
pcComponent.getComponentSerial().getString()));
|
||||
}
|
||||
|
||||
return matchesSoFar;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the fields in the potentialMatch match the fields in the pcComponent,
|
||||
* or if the relevant field in the pcComponent is empty.
|
||||
@ -1009,7 +1105,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
* @param platformSerialNumberDescription description of the serial number for logging purposes.
|
||||
* @param deviceInfoSerialNumbers the map of device info serial numbers
|
||||
* (key = description, value = serial number)
|
||||
* @return true if the platform serial number was found (case insensitive search),
|
||||
* @return true if the platform serial number was found (case-insensitive search),
|
||||
* false otherwise
|
||||
*/
|
||||
private static boolean deviceInfoContainsPlatformSerialNumber(
|
||||
@ -1090,6 +1186,22 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per update to the provisioning via Issue 723, Not Specified and Unknown values
|
||||
* are to be ignored.
|
||||
* @param versionNumber string value of the device/platform version number
|
||||
* @return true if they equal Not Specified or Unknown
|
||||
*/
|
||||
public static boolean isNotSpecifiedOrUnknown(final String versionNumber) {
|
||||
if(versionNumber == null) {
|
||||
return true;
|
||||
}
|
||||
String fieldValue = versionNumber.toLowerCase();
|
||||
|
||||
return fieldValue.equals(DeviceInfoEnums.NOT_SPECIFIED.toLowerCase())
|
||||
|| fieldValue.equals(LC_UNKNOWN);
|
||||
}
|
||||
|
||||
private static boolean platformCredentialFieldMatches(
|
||||
final String platformCredentialFieldName,
|
||||
final String platformCredentialFieldValue,
|
||||
|
@ -1,7 +1,10 @@
|
||||
package hirs.attestationca.persist.validation;
|
||||
|
||||
import hirs.attestationca.persist.entity.manager.ComponentAttributeRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
@ -14,6 +17,8 @@ import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateNotYetValidException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.ERROR;
|
||||
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
|
||||
@ -26,7 +31,7 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
|
||||
* Checks if the endorsement credential is valid.
|
||||
*
|
||||
* @param ec the endorsement credential to verify.
|
||||
* @param trustStore trust store holding trusted trusted certificates.
|
||||
* @param trustStore trust store holding trusted certificates.
|
||||
* @param acceptExpired whether or not to accept expired and not yet valid certificates
|
||||
* as valid.
|
||||
* @return the result of the validation.
|
||||
@ -160,12 +165,19 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
|
||||
* serial number of the platform to be validated.
|
||||
* @param endorsementCredential The endorsement credential supplied from the same
|
||||
* identity request as the platform credential.
|
||||
* @param componentResultRepository db access to component result of mismatching
|
||||
* @param componentAttributeRepository db access to component attribute match status
|
||||
* @param componentInfos list of device components
|
||||
* @return The result of the validation.
|
||||
*/
|
||||
public static AppraisalStatus validatePlatformCredentialAttributes(
|
||||
final PlatformCredential platformCredential,
|
||||
final DeviceInfoReport deviceInfoReport,
|
||||
final EndorsementCredential endorsementCredential) {
|
||||
final EndorsementCredential endorsementCredential,
|
||||
final ComponentResultRepository componentResultRepository,
|
||||
final ComponentAttributeRepository componentAttributeRepository,
|
||||
final List<ComponentInfo> componentInfos,
|
||||
final UUID provisionSessionId) {
|
||||
final String baseErrorMessage = "Can't validate platform credential attributes without ";
|
||||
String message;
|
||||
if (platformCredential == null) {
|
||||
@ -180,6 +192,10 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
|
||||
message = baseErrorMessage + "an endorsement credential";
|
||||
return new AppraisalStatus(FAIL, message);
|
||||
}
|
||||
if (componentInfos.isEmpty()) {
|
||||
message = baseErrorMessage + "a list of device components";
|
||||
return new AppraisalStatus(FAIL, message);
|
||||
}
|
||||
|
||||
// Quick, early check if the platform credential references the endorsement credential
|
||||
if (!endorsementCredential.getSerialNumber()
|
||||
@ -192,7 +208,8 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
|
||||
String credentialType = platformCredential.getCredentialType();
|
||||
if (PlatformCredential.CERTIFICATE_TYPE_2_0.equals(credentialType)) {
|
||||
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV2p0(
|
||||
platformCredential, deviceInfoReport);
|
||||
platformCredential, deviceInfoReport, componentResultRepository,
|
||||
componentAttributeRepository, componentInfos, provisionSessionId);
|
||||
}
|
||||
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV1p2(
|
||||
platformCredential, deviceInfoReport);
|
||||
|
@ -7,7 +7,6 @@ import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.cert.CertException;
|
||||
import org.bouncycastle.cert.X509AttributeCertificateHolder;
|
||||
@ -32,7 +31,6 @@ import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -93,15 +91,13 @@ public class SupplyChainCredentialValidator {
|
||||
} else if (trustStore.size() == 0) {
|
||||
throw new SupplyChainValidatorException("Truststore is empty");
|
||||
}
|
||||
} catch (KeyStoreException e) {
|
||||
log.error("Error accessing trust store: " + e.getMessage());
|
||||
} catch (KeyStoreException ksEx) {
|
||||
log.error("Error accessing trust store: " + ksEx.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
Set<X509Certificate> trustedCerts = new HashSet<>();
|
||||
|
||||
Enumeration<String> alias = trustStore.aliases();
|
||||
|
||||
while (alias.hasMoreElements()) {
|
||||
trustedCerts.add((X509Certificate) trustStore.getCertificate(alias.nextElement()));
|
||||
}
|
||||
@ -111,8 +107,8 @@ public class SupplyChainCredentialValidator {
|
||||
log.error("Cert chain could not be validated");
|
||||
}
|
||||
return certChainValidated;
|
||||
} catch (KeyStoreException e) {
|
||||
throw new SupplyChainValidatorException("Error with the trust store", e);
|
||||
} catch (KeyStoreException ksEx) {
|
||||
throw new SupplyChainValidatorException("Error with the trust store", ksEx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,8 +135,8 @@ public class SupplyChainCredentialValidator {
|
||||
} else if (trustStore.size() == 0) {
|
||||
throw new SupplyChainValidatorException("Truststore is empty");
|
||||
}
|
||||
} catch (KeyStoreException e) {
|
||||
log.error("Error accessing trust store: " + e.getMessage());
|
||||
} catch (KeyStoreException ksEx) {
|
||||
log.error("Error accessing trust store: " + ksEx.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
@ -152,9 +148,9 @@ public class SupplyChainCredentialValidator {
|
||||
}
|
||||
|
||||
return validateCertChain(cert, trustedCerts).isEmpty();
|
||||
} catch (KeyStoreException e) {
|
||||
log.error("Error accessing keystore", e);
|
||||
throw new SupplyChainValidatorException("Error with the trust store", e);
|
||||
} catch (KeyStoreException ksEx) {
|
||||
log.error("Error accessing keystore", ksEx);
|
||||
throw new SupplyChainValidatorException("Error with the trust store", ksEx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,11 +273,13 @@ public class SupplyChainCredentialValidator {
|
||||
|
||||
/**
|
||||
* Parses the output from PACCOR's allcomponents.sh script into ComponentInfo objects.
|
||||
* @param hostName the host machine associated with the component
|
||||
* @param paccorOutput the output from PACCOR's allcomoponents.sh
|
||||
* @return a list of ComponentInfo objects built from paccorOutput
|
||||
* @throws java.io.IOException if something goes wrong parsing the JSON
|
||||
*/
|
||||
public static List<ComponentInfo> getComponentInfoFromPaccorOutput(final String paccorOutput)
|
||||
public static List<ComponentInfo> getComponentInfoFromPaccorOutput(final String hostName,
|
||||
final String paccorOutput)
|
||||
throws IOException {
|
||||
List<ComponentInfo> componentInfoList = new ArrayList<>();
|
||||
|
||||
@ -292,54 +290,34 @@ public class SupplyChainCredentialValidator {
|
||||
= rootNode.findValue("COMPONENTS").elements();
|
||||
while (jsonComponentNodes.hasNext()) {
|
||||
JsonNode next = jsonComponentNodes.next();
|
||||
componentInfoList.add(new ComponentInfo(
|
||||
getJSONNodeValueAsText(next, "MANUFACTURER"),
|
||||
getJSONNodeValueAsText(next, "MODEL"),
|
||||
getJSONNodeValueAsText(next, "SERIAL"),
|
||||
getJSONNodeValueAsText(next, "REVISION")));
|
||||
|
||||
List<JsonNode> compClassNodes = next.findValues("COMPONENTCLASS");
|
||||
if (compClassNodes.isEmpty()) {
|
||||
componentInfoList.add(new ComponentInfo(hostName,
|
||||
getJSONNodeValueAsText(next, "MANUFACTURER"),
|
||||
getJSONNodeValueAsText(next, "MODEL"),
|
||||
getJSONNodeValueAsText(next, "SERIAL"),
|
||||
getJSONNodeValueAsText(next, "REVISION")));
|
||||
} else {
|
||||
// version 2
|
||||
String componentClass = StringUtils.EMPTY;
|
||||
for (JsonNode subNode : compClassNodes) {
|
||||
componentClass = getJSONNodeValueAsText(subNode,
|
||||
"COMPONENTCLASSVALUE");
|
||||
}
|
||||
componentInfoList.add(new ComponentInfo(hostName,
|
||||
getJSONNodeValueAsText(next, "MANUFACTURER"),
|
||||
getJSONNodeValueAsText(next, "MODEL"),
|
||||
getJSONNodeValueAsText(next, "SERIAL"),
|
||||
getJSONNodeValueAsText(next, "REVISION"),
|
||||
componentClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return componentInfoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the output from PACCOR's allcomponents.sh script into ComponentInfo objects.
|
||||
* @param paccorOutput the output from PACCOR's allcomoponents.sh
|
||||
* @return a list of ComponentInfo objects built from paccorOutput
|
||||
* @throws IOException if something goes wrong parsing the JSON
|
||||
*/
|
||||
public static List<ComponentInfo> getV2PaccorOutput(
|
||||
final String paccorOutput) throws IOException {
|
||||
List<ComponentInfo> ciList = new LinkedList<>();
|
||||
String manufacturer, model, serial, revision;
|
||||
String componentClass = Strings.EMPTY;
|
||||
|
||||
if (StringUtils.isNotEmpty(paccorOutput)) {
|
||||
ObjectMapper objectMapper = new ObjectMapper(new JsonFactory());
|
||||
JsonNode rootNode = objectMapper.readTree(paccorOutput);
|
||||
Iterator<JsonNode> jsonComponentNodes
|
||||
= rootNode.findValue("COMPONENTS").elements();
|
||||
while (jsonComponentNodes.hasNext()) {
|
||||
JsonNode next = jsonComponentNodes.next();
|
||||
manufacturer = getJSONNodeValueAsText(next, "MANUFACTURER");
|
||||
model = getJSONNodeValueAsText(next, "MODEL");
|
||||
serial = getJSONNodeValueAsText(next, "SERIAL");
|
||||
revision = getJSONNodeValueAsText(next, "REVISION");
|
||||
List<JsonNode> compClassNodes = next.findValues("COMPONENTCLASS");
|
||||
|
||||
for (JsonNode subNode : compClassNodes) {
|
||||
componentClass = getJSONNodeValueAsText(subNode,
|
||||
"COMPONENTCLASSVALUE");
|
||||
}
|
||||
ciList.add(new ComponentInfo(manufacturer, model,
|
||||
serial, revision, componentClass));
|
||||
}
|
||||
}
|
||||
|
||||
return ciList;
|
||||
}
|
||||
|
||||
private static String getJSONNodeValueAsText(final JsonNode node, final String fieldName) {
|
||||
if (node.hasNonNull(fieldName)) {
|
||||
return node.findValue(fieldName).textValue();
|
||||
@ -498,10 +476,10 @@ public class SupplyChainCredentialValidator {
|
||||
PublicKey key = cert.getPublicKey();
|
||||
cert.verify(key);
|
||||
return true;
|
||||
} catch (SignatureException | InvalidKeyException e) {
|
||||
} catch (SignatureException | InvalidKeyException ex) {
|
||||
return false;
|
||||
} catch (CertificateException | NoSuchAlgorithmException | NoSuchProviderException e) {
|
||||
log.error("Exception occurred while checking if cert is self-signed", e);
|
||||
} catch (CertificateException | NoSuchAlgorithmException | NoSuchProviderException ex) {
|
||||
log.error("Exception occurred while checking if cert is self-signed", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,757 @@
|
||||
package hirs.attestationca.persist;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
import hirs.attestationca.persist.provision.AbstractProcessor;
|
||||
import hirs.attestationca.persist.provision.helper.IssuedCertificateAttributeHelper;
|
||||
import hirs.attestationca.persist.provision.helper.ProvisionUtils;
|
||||
import hirs.structs.elements.aca.SymmetricAttestation;
|
||||
import hirs.structs.elements.tpm.AsymmetricPublicKey;
|
||||
import hirs.structs.elements.tpm.EncryptionScheme;
|
||||
import hirs.structs.elements.tpm.IdentityProof;
|
||||
import hirs.structs.elements.tpm.StorePubKey;
|
||||
import hirs.structs.elements.tpm.SymmetricKey;
|
||||
import hirs.utils.HexUtils;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x509.Extension;
|
||||
import org.bouncycastle.asn1.x509.GeneralNames;
|
||||
import org.bouncycastle.asn1.x509.TBSCertificate;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.OAEPParameterSpec;
|
||||
import javax.crypto.spec.PSource;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.MGF1ParameterSpec;
|
||||
import java.util.Calendar;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Test suite for {@link AttestationCertificateAuthority}.
|
||||
*/
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS) // needed to use non-static BeforeAll
|
||||
public class AttestationCertificateAuthorityTest {
|
||||
|
||||
/**
|
||||
* This internal class handles setup for testing the function
|
||||
* generateCredential() from class AbstractProcessor. Because the
|
||||
* function is Protected and in a different package than the test,
|
||||
* it cannot be accessed directly.
|
||||
*/
|
||||
@Nested
|
||||
public class AccessAbstractProcessor extends AbstractProcessor {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param privateKey the private key of the ACA
|
||||
* @param validDays int for the time in which a certificate is valid.
|
||||
*/
|
||||
public AccessAbstractProcessor(final PrivateKey privateKey,
|
||||
final int validDays) {
|
||||
super(privateKey, validDays);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public wrapper for the protected function generateCredential(), to access for testing.
|
||||
*
|
||||
* @param publicKey cannot be null
|
||||
* @param endorsementCredential the endorsement credential
|
||||
* @param platformCredentials the set of platform credentials
|
||||
* @param deviceName The host name used in the subject alternative name
|
||||
* @param acaCertificate the aca certificate
|
||||
* @return the generated X509 certificate
|
||||
*/
|
||||
public X509Certificate accessGenerateCredential(final PublicKey publicKey,
|
||||
final EndorsementCredential endorsementCredential,
|
||||
final List<PlatformCredential> platformCredentials,
|
||||
final String deviceName,
|
||||
final X509Certificate acaCertificate) {
|
||||
|
||||
return generateCredential(publicKey,
|
||||
endorsementCredential,
|
||||
platformCredentials,
|
||||
deviceName,
|
||||
acaCertificate);
|
||||
}
|
||||
}
|
||||
|
||||
// object in test
|
||||
private AttestationCertificateAuthority aca;
|
||||
private AccessAbstractProcessor abstractProcessor;
|
||||
|
||||
// test key pair
|
||||
private KeyPair keyPair;
|
||||
|
||||
// length of IV used in PKI
|
||||
private static final int ENCRYPTION_IV_LEN = 16;
|
||||
// length of secret key used in PKI
|
||||
private static final int SECRETKEY_LEN = 128;
|
||||
|
||||
private static final String EK_PUBLIC_PATH = "/tpm2/ek.pub";
|
||||
private static final String AK_PUBLIC_PATH = "/tpm2/ak.pub";
|
||||
private static final String AK_NAME_PATH = "/tpm2/ak.name";
|
||||
private static final String TEST_NONCE_BLOB_PATH = "test/nonce.blob";
|
||||
private static final String EK_MODULUS_HEX = "a3 b5 c2 1c 57 be 40 c4 3c 78 90 0d 00 81 01 78"
|
||||
+ "13 ca 02 ec b6 75 89 60 ca 60 9b 10 b6 b4 d0 0b"
|
||||
+ "4d e4 68 ad 01 a6 91 e2 56 20 5e cf 16 fe 77 ae"
|
||||
+ "1f 13 d7 ac a1 91 0b 68 f6 07 cf c2 4b 5e c1 2c"
|
||||
+ "4c fe 3a c9 62 7e 10 02 5b 33 c8 c2 1a cd 2e 7f"
|
||||
+ "dd 7c 43 ac a9 5f b1 d6 07 56 4f 72 9b 0a 00 6c"
|
||||
+ "f6 8d 23 a1 84 ca c1 7f 5a 8b ef 0e 23 11 90 00"
|
||||
+ "30 f2 99 e9 94 59 c6 b0 fe b2 5c 0c c7 b4 76 69"
|
||||
+ "6c f1 b7 d8 e5 60 d6 61 9f ab 7c 17 ce a4 74 6d"
|
||||
+ "8c cd e6 9e 6e bb 64 52 a7 c3 bf ac 07 e8 5e 3e"
|
||||
+ "ae eb dc c5 95 37 26 6a 5d a6 a2 12 52 fa 03 43"
|
||||
+ "b2 62 2d 87 8c a7 06 8f d6 3f 63 b6 2d 73 c4 9d"
|
||||
+ "9d d6 55 0e bb db b1 eb dd c5 4b 8f c3 17 cb 3b"
|
||||
+ "c3 bf f6 7f 13 44 de 8e d7 b9 f1 a7 15 56 8f 6c"
|
||||
+ "cd f2 4c 86 99 39 19 88 d3 4a 2f 38 c4 c4 37 39"
|
||||
+ "85 6f 41 98 19 14 a4 1f 95 bc 04 ef 74 c2 0d f3";
|
||||
private static final String AK_MODULUS_HEX = "d7 c9 f0 e3 ac 1b 4a 1e 3c 9d 2d 57 02 e9 2a 93"
|
||||
+ "b0 c0 e1 50 af e4 61 11 31 73 a1 96 b8 d6 d2 1c"
|
||||
+ "40 40 c8 a6 46 a4 10 4b d1 06 74 32 f6 e3 8a 55"
|
||||
+ "1e 03 c0 3e cc 75 04 c6 44 88 b6 ad 18 c9 45 65"
|
||||
+ "0d be c5 45 22 bd 24 ad 32 8c be 83 a8 9b 1b d9"
|
||||
+ "e0 c8 d9 ec 14 67 55 1b fe 68 dd c7 f7 33 e4 cd"
|
||||
+ "87 bd ba 9a 07 e7 74 eb 57 ef 80 9c 6d ee f9 35"
|
||||
+ "52 67 36 e2 53 98 46 a5 4e 8f 17 41 8d ff eb bb"
|
||||
+ "9c d2 b4 df 57 f8 7f 31 ef 2e 2d 6e 06 7f 05 ed"
|
||||
+ "3f e9 6f aa b4 b7 5a f9 6d ba ff 2b 5e f7 c1 05"
|
||||
+ "90 68 1f b6 4b 38 67 f7 92 d8 73 51 6e 08 19 ad"
|
||||
+ "ca 35 48 a7 c1 fb cb 01 9a 28 03 c9 fe bb 49 2f"
|
||||
+ "88 3f a1 e7 a8 69 f0 f8 e8 78 db d3 6d c5 80 8d"
|
||||
+ "c2 e4 8a af 4b c2 ac 48 2a 44 63 6e 39 b0 8f dd"
|
||||
+ "e4 b3 a3 f9 2a b1 c8 d9 3d 6b c4 08 b0 16 c4 e7"
|
||||
+ "c7 2f f5 94 c6 43 3e ee 9b 8a da e7 31 d1 54 dd";
|
||||
private static final String AK_NAME_HEX = "00 0b 6e 8f 79 1c 7e 16 96 1b 11 71 65 9c e0 cd"
|
||||
+ "ae 0d 4d aa c5 41 be 58 89 74 67 55 96 c2 5e 38"
|
||||
+ "e2 94";
|
||||
|
||||
|
||||
/**
|
||||
* Registers bouncy castle as a security provider. Normally the JEE container will handle this,
|
||||
* but since the tests are not instantiating a container, have the unit test runner set up the
|
||||
* provider.
|
||||
*/
|
||||
@BeforeAll
|
||||
public void setupTests() throws Exception {
|
||||
|
||||
//BeforeSuite
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGenerator.initialize(2048);
|
||||
keyPair = keyPairGenerator.generateKeyPair();
|
||||
|
||||
//BeforeTest
|
||||
aca = new AttestationCertificateAuthority(null, keyPair.getPrivate(),
|
||||
null, null, null, null, null, null, null, 1,
|
||||
null, null, null, null) {
|
||||
};
|
||||
abstractProcessor = new AccessAbstractProcessor(keyPair.getPrivate(), 1);
|
||||
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AttestationCertificateAuthority#processIdentityClaimTpm2(byte[])}
|
||||
* where the byte array is null. Expects an illegal argument exception to be thrown.
|
||||
*/
|
||||
@Test
|
||||
public void testProcessIdentityClaimTpm2NullRequest() {
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
aca.processIdentityClaimTpm2(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AttestationCertificateAuthority#getPublicKey()}.
|
||||
*/
|
||||
@Test
|
||||
public void testGetPublicKey() {
|
||||
|
||||
// encoded byte array to be returned by public key
|
||||
byte[] encoded = new byte[]{0, 1, 0, 1, 0};
|
||||
|
||||
// create mocks for testing
|
||||
X509Certificate acaCertificate = mock(X509Certificate.class);
|
||||
PublicKey publicKey = mock(PublicKey.class);
|
||||
|
||||
// assign the aca certificate to the aca
|
||||
ReflectionTestUtils.setField(aca, "acaCertificate", acaCertificate);
|
||||
|
||||
// return a mocked public key
|
||||
when(acaCertificate.getPublicKey()).thenReturn(publicKey);
|
||||
|
||||
// return test byte array
|
||||
when(publicKey.getEncoded()).thenReturn(encoded);
|
||||
|
||||
// assert what the ACA returns is as expected
|
||||
assertArrayEquals(encoded, aca.getPublicKey());
|
||||
|
||||
// verify mock interactions
|
||||
verify(acaCertificate).getPublicKey();
|
||||
verify(publicKey).getEncoded();
|
||||
|
||||
// verify no other interactions with mocks
|
||||
verifyNoMoreInteractions(acaCertificate, publicKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ProvisionUtils#decryptAsymmetricBlob(byte[],
|
||||
* EncryptionScheme, PrivateKey)}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testDecryptAsymmetricBlob() throws Exception {
|
||||
|
||||
// test encryption transformation
|
||||
EncryptionScheme encryptionScheme = EncryptionScheme.PKCS1;
|
||||
|
||||
// test variables
|
||||
byte[] expected = "test".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
// encrypt the expected value using same algorithm as the ACA.
|
||||
byte[] encrypted = encryptBlob(expected, encryptionScheme.toString());
|
||||
|
||||
// perform the decryption and assert that the decrypted bytes equal the expected bytes
|
||||
assertArrayEquals(expected, ProvisionUtils.decryptAsymmetricBlob(
|
||||
encrypted, encryptionScheme, keyPair.getPrivate()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ProvisionUtils#decryptSymmetricBlob(
|
||||
* byte[], byte[], byte[], String)}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testDecryptSymmetricBlob() throws Exception {
|
||||
// test encryption transformation
|
||||
String transformation = "AES/CBC/PKCS5Padding";
|
||||
|
||||
// test variables
|
||||
byte[] expected = "test".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
// create a key generator to generate a "shared" secret
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(SECRETKEY_LEN);
|
||||
|
||||
// use some random bytes as the IV to encrypt and subsequently decrypt with
|
||||
byte[] randomBytes = new byte[ENCRYPTION_IV_LEN];
|
||||
|
||||
// generate the random bytes
|
||||
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
|
||||
random.nextBytes(randomBytes);
|
||||
|
||||
// the shared secret
|
||||
byte[] secretKey = keyGenerator.generateKey().getEncoded();
|
||||
|
||||
// encrypt the expected value with the private key being the shared secret
|
||||
byte[] encrypted = encryptBlob(expected, secretKey, randomBytes, transformation);
|
||||
|
||||
// perform the decryption using the generated shared secret, random bytes as an IV, and the
|
||||
// AES CBC transformation for the cipher. then assert the decrypted results are the same
|
||||
// as our expected value.
|
||||
assertArrayEquals(expected,
|
||||
ProvisionUtils.decryptSymmetricBlob(encrypted, secretKey, randomBytes, transformation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ProvisionUtils#generateSymmetricKey()}.
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateSymmetricKey() {
|
||||
// perform the test
|
||||
SymmetricKey symmetricKey = ProvisionUtils.generateSymmetricKey();
|
||||
|
||||
// assert the symmetric algorithm, scheme, and key size are all set appropriately
|
||||
assertTrue(symmetricKey.getAlgorithmId() == 6);
|
||||
assertTrue(symmetricKey.getEncryptionScheme() == 255);
|
||||
assertTrue(symmetricKey.getKeySize() == symmetricKey.getKey().length);
|
||||
}
|
||||
|
||||
private void assertTrue(final boolean b) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ProvisionUtils#generateAsymmetricContents(
|
||||
* byte[], byte[], PublicKey)}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateAsymmetricContents() throws Exception {
|
||||
|
||||
// "encoded" identity proof (returned by struct converter)
|
||||
byte[] identityProofEncoded = new byte[]{0, 0, 1, 1};
|
||||
|
||||
// generate a random session key to be used for encryption and decryption
|
||||
byte[] sessionKey = new byte[ENCRYPTION_IV_LEN];
|
||||
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
|
||||
random.nextBytes(sessionKey);
|
||||
|
||||
// perform the test
|
||||
byte[] result = ProvisionUtils.generateAsymmetricContents(identityProofEncoded,
|
||||
sessionKey, keyPair.getPublic());
|
||||
|
||||
// decrypt the result
|
||||
byte[] decryptedResult = decryptBlob(result);
|
||||
|
||||
// create a SHA1 digest of the identity key
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
md.update(identityProofEncoded);
|
||||
|
||||
// generate the digest
|
||||
byte[] identityDigest = md.digest();
|
||||
|
||||
// the decrypted asymmetric contents should be the session key and a SHA-1 hash of the
|
||||
// encoded identity proof.
|
||||
byte[] expected = ArrayUtils.addAll(sessionKey, identityDigest);
|
||||
|
||||
// compare the two byte arrays
|
||||
assertArrayEquals(expected, decryptedResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ProvisionUtils#generateAttestation(X509Certificate,
|
||||
* SymmetricKey)}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateAttestation() throws Exception {
|
||||
|
||||
// create some mocks for the unit tests
|
||||
X509Certificate certificate = mock(X509Certificate.class);
|
||||
SymmetricKey symmetricKey = mock(SymmetricKey.class);
|
||||
|
||||
// create a key generator to generate a secret key
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(SECRETKEY_LEN);
|
||||
|
||||
// obtain the key from the generator
|
||||
byte[] secretKey = keyGenerator.generateKey().getEncoded();
|
||||
|
||||
// use our public key for encryption
|
||||
when(symmetricKey.getKey()).thenReturn(secretKey);
|
||||
|
||||
// just use the existing public key for the credential
|
||||
when(certificate.getEncoded()).thenReturn(keyPair.getPublic().getEncoded());
|
||||
|
||||
// perform the actual test
|
||||
SymmetricAttestation attestation = ProvisionUtils.generateAttestation(certificate, symmetricKey);
|
||||
|
||||
// validate that the attestation is not null
|
||||
assertNotNull(attestation);
|
||||
|
||||
// validate the attestation algorithm
|
||||
assertNotNull(attestation.getAlgorithm());
|
||||
assertTrue(attestation.getAlgorithm().getAlgorithmId() == 6);
|
||||
assertTrue(attestation.getAlgorithm().getEncryptionScheme() == 0x1);
|
||||
assertTrue(attestation.getAlgorithm().getSignatureScheme() == 0);
|
||||
assertTrue(attestation.getAlgorithm().getParamsSize() == 0);
|
||||
|
||||
// validate the attestation credential
|
||||
assertNotNull(attestation.getCredential());
|
||||
|
||||
// validate that the credential size is the size of the actual credential block
|
||||
assertTrue(attestation.getCredential().length == attestation.getCredentialSize());
|
||||
|
||||
// create containers for the 2 parts of the credential
|
||||
byte[] iv = new byte[ENCRYPTION_IV_LEN];
|
||||
byte[] credential = new byte[attestation.getCredential().length - iv.length];
|
||||
|
||||
// siphon off the first 16 bytes for the IV
|
||||
System.arraycopy(attestation.getCredential(), 0, iv, 0, iv.length);
|
||||
|
||||
// the rest is the actual encrypted credential
|
||||
System.arraycopy(attestation.getCredential(), iv.length, credential, 0, credential.length);
|
||||
|
||||
// decrypt the credential
|
||||
byte[] decrypted = decryptBlob(credential, secretKey, iv, "AES/CBC/PKCS5Padding");
|
||||
|
||||
// assert that the decrypted credential is our public key
|
||||
assertArrayEquals(keyPair.getPublic().getEncoded(), decrypted);
|
||||
|
||||
// verify that the mocks were interacted with appropriately
|
||||
verify(symmetricKey).getKey();
|
||||
verify(certificate).getEncoded();
|
||||
verifyNoMoreInteractions(certificate, symmetricKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AttestationCertificateAuthority#
|
||||
* AttestationCertificateAuthority(SupplyChainValidationService, PrivateKey,
|
||||
* X509Certificate, StructConverter, CertificateManager, DeviceRegister, int,
|
||||
* DeviceManager, DBManager)}.
|
||||
*
|
||||
* @throws Exception during subject alternative name checking if cert formatting is bad
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateCredential() throws Exception {
|
||||
// test variables
|
||||
final String identityProofLabelString = "label";
|
||||
byte[] identityProofLabel = identityProofLabelString.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] modulus = ((RSAPublicKey) keyPair.getPublic()).getModulus().toByteArray();
|
||||
X500Principal principal = new X500Principal("CN=TEST, OU=TEST, O=TEST, C=TEST");
|
||||
int validDays = 1;
|
||||
|
||||
// create mocks for testing
|
||||
IdentityProof identityProof = mock(IdentityProof.class);
|
||||
AsymmetricPublicKey asymmetricPublicKey = mock(AsymmetricPublicKey.class);
|
||||
StorePubKey storePubKey = mock(StorePubKey.class);
|
||||
X509Certificate acaCertificate = mock(X509Certificate.class);
|
||||
|
||||
// assign ACA fields
|
||||
ReflectionTestUtils.setField(aca, "validDays", validDays);
|
||||
ReflectionTestUtils.setField(aca, "acaCertificate", acaCertificate);
|
||||
|
||||
// prepare identity proof interactions
|
||||
when(identityProof.getLabel()).thenReturn(identityProofLabel);
|
||||
|
||||
// prepare other mocks
|
||||
when(acaCertificate.getSubjectX500Principal()).thenReturn(principal);
|
||||
when(acaCertificate.getIssuerX500Principal()).thenReturn(principal);
|
||||
|
||||
// perform the test
|
||||
X509Certificate certificate = abstractProcessor.accessGenerateCredential(keyPair.getPublic(),
|
||||
null,
|
||||
new LinkedList<PlatformCredential>(),
|
||||
"exampleIdLabel",
|
||||
acaCertificate);
|
||||
|
||||
// grab the modulus from the generate certificate
|
||||
byte[] resultMod = ((RSAPublicKey) certificate.getPublicKey()).getModulus().toByteArray();
|
||||
|
||||
// today and tomorrow, when the certificate should be valid for
|
||||
Calendar today = Calendar.getInstance();
|
||||
Calendar tomorrow = Calendar.getInstance();
|
||||
tomorrow.add(Calendar.DATE, 1);
|
||||
|
||||
// validate the certificate
|
||||
assertTrue(certificate.getIssuerX500Principal().toString().contains("CN=TEST"));
|
||||
assertTrue(certificate.getIssuerX500Principal().toString().contains("OU=TEST"));
|
||||
assertTrue(certificate.getIssuerX500Principal().toString().contains("O=TEST"));
|
||||
assertTrue(certificate.getIssuerX500Principal().toString().contains("C=TEST"));
|
||||
|
||||
// validate the format of the subject and subject alternative name
|
||||
assertEquals("", certificate.getSubjectX500Principal().getName());
|
||||
assertEquals("exampleIdLabel",
|
||||
((X500Name) GeneralNames.fromExtensions(((TBSCertificate.getInstance(
|
||||
certificate.getTBSCertificate()).getExtensions())), Extension.
|
||||
subjectAlternativeName).getNames()[0].getName()).getRDNs(
|
||||
IssuedCertificateAttributeHelper.TCPA_AT_TPM_ID_LABEL)[0].getFirst()
|
||||
.getValue().toString());
|
||||
|
||||
assertArrayEquals(modulus, resultMod);
|
||||
|
||||
// obtain the expiration dates from the certificate
|
||||
Calendar beforeDate = Calendar.getInstance();
|
||||
Calendar afterDate = Calendar.getInstance();
|
||||
beforeDate.setTime(certificate.getNotBefore());
|
||||
afterDate.setTime(certificate.getNotAfter());
|
||||
|
||||
// assert the dates are set correctly
|
||||
assertEquals(today.get(Calendar.DATE), beforeDate.get(Calendar.DATE));
|
||||
assertEquals(tomorrow.get(Calendar.DATE), afterDate.get(Calendar.DATE));
|
||||
|
||||
// validate mock interactions
|
||||
verify(acaCertificate).getSubjectX500Principal();
|
||||
verifyNoMoreInteractions(identityProof, asymmetricPublicKey, storePubKey, acaCertificate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ProvisionUtils#assemblePublicKey(byte[])}.
|
||||
*/
|
||||
@Test
|
||||
public void testAssemblePublicKeyUsingByteArray() {
|
||||
// obtain the expected modulus from the existing public key
|
||||
final BigInteger modulus = ((RSAPublicKey) keyPair.getPublic()).getModulus();
|
||||
|
||||
// perform test
|
||||
RSAPublicKey publicKey = (RSAPublicKey) ProvisionUtils.assemblePublicKey(modulus.toByteArray());
|
||||
|
||||
// assert that the exponent and the modulus are the same. the exponents should be the well
|
||||
// known prime, 101
|
||||
assertTrue(publicKey.getPublicExponent().equals(new BigInteger("010001", 16)));
|
||||
assertTrue(publicKey.getModulus().equals(modulus));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link ProvisionUtils#assemblePublicKey(String)}.
|
||||
*/
|
||||
@Test
|
||||
public void testAssemblePublicKeyUsingHexEncodedString() {
|
||||
// obtain the expected modulus from the existing public key
|
||||
final BigInteger modulus = ((RSAPublicKey) keyPair.getPublic()).getModulus();
|
||||
|
||||
// encode our existing public key into hex
|
||||
final String modulusString = Hex.encodeHexString(
|
||||
((RSAPublicKey) keyPair.getPublic()).getModulus().toByteArray());
|
||||
|
||||
// perform test
|
||||
RSAPublicKey publicKey = (RSAPublicKey) ProvisionUtils.assemblePublicKey(modulusString);
|
||||
|
||||
// assert that the exponent and the modulus are the same. the exponents should be the well
|
||||
// known prime, 101.
|
||||
assertTrue(publicKey.getPublicExponent().equals(new BigInteger("010001", 16)));
|
||||
assertTrue(publicKey.getModulus().equals(modulus));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing the EK from the TPM2 output file.
|
||||
* @throws URISyntaxException incorrect resource path
|
||||
* @throws IOException unable to read from file
|
||||
*/
|
||||
@Test
|
||||
public void testParseEk() throws URISyntaxException, IOException {
|
||||
Path ekPath = Paths.get(getClass().getResource(
|
||||
EK_PUBLIC_PATH).toURI());
|
||||
|
||||
byte[] ekFile = Files.readAllBytes(ekPath);
|
||||
|
||||
RSAPublicKey ek = ProvisionUtils.parsePublicKey(ekFile);
|
||||
assertTrue(ek.getPublicExponent().equals(new BigInteger("010001", 16)));
|
||||
|
||||
byte[] mod = ek.getModulus().toByteArray();
|
||||
// big integer conversion is signed so it can add a 0 byte
|
||||
if (mod[0] == 0) {
|
||||
byte[] tmp = new byte[mod.length - 1];
|
||||
System.arraycopy(mod, 1, tmp, 0, mod.length - 1);
|
||||
mod = tmp;
|
||||
}
|
||||
String hex = HexUtils.byteArrayToHexString(mod);
|
||||
String realMod = EK_MODULUS_HEX.replaceAll("\\s+", "");
|
||||
assertEquals(realMod, hex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing the AK public key from the TPM2 output file.
|
||||
* @throws URISyntaxException incorrect resource path
|
||||
* @throws IOException unable to read from file
|
||||
*/
|
||||
@Test
|
||||
public void testParseAk() throws URISyntaxException, IOException {
|
||||
Path akPath = Paths.get(getClass().getResource(
|
||||
AK_PUBLIC_PATH).toURI());
|
||||
|
||||
byte[] akFile = Files.readAllBytes(akPath);
|
||||
|
||||
RSAPublicKey ak = ProvisionUtils.parsePublicKey(akFile);
|
||||
assertTrue(ak.getPublicExponent().equals(new BigInteger("010001", 16)));
|
||||
|
||||
byte[] mod = ak.getModulus().toByteArray();
|
||||
// big integer conversion is signed so it can add a 0 byte
|
||||
if (mod[0] == 0) {
|
||||
byte[] tmp = new byte[mod.length - 1];
|
||||
System.arraycopy(mod, 1, tmp, 0, mod.length - 1);
|
||||
mod = tmp;
|
||||
}
|
||||
String hex = HexUtils.byteArrayToHexString(mod);
|
||||
String realMod = AK_MODULUS_HEX.replaceAll("\\s+", "");
|
||||
assertEquals(realMod, hex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing the AK name from the TPM2 output file.
|
||||
* @throws URISyntaxException incorrect resource path
|
||||
* @throws IOException unable to read from file
|
||||
* @throws NoSuchAlgorithmException inavlid algorithm
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateAkName() throws URISyntaxException, IOException,
|
||||
NoSuchAlgorithmException {
|
||||
Path akNamePath = Paths.get(getClass().getResource(
|
||||
AK_NAME_PATH).toURI());
|
||||
|
||||
byte[] akNameFileBytes = Files.readAllBytes(akNamePath);
|
||||
String realHex = HexUtils.byteArrayToHexString(akNameFileBytes);
|
||||
|
||||
String realMod = AK_MODULUS_HEX.replaceAll("\\s+", "");
|
||||
byte[] akName = ProvisionUtils.generateAkName(HexUtils.hexStringToByteArray(realMod));
|
||||
|
||||
String hex = HexUtils.byteArrayToHexString(akName);
|
||||
String realName = AK_NAME_HEX.replaceAll("\\s+", "");
|
||||
assertEquals(hex, realName);
|
||||
assertEquals(hex, realHex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate a make credential output file for use in manual testing. Feed to
|
||||
* a TPM 2.0 or emulator using the activate credential command to ensure proper parsing.
|
||||
* Must be performed manually. To use, copy the TPM's ek and ak into
|
||||
* HIRS_AttestationCA/src/test/resources/tpm2/test/ and ensure the variables akPubPath
|
||||
* and ekPubPath are correct. Your output file will be
|
||||
* HIRS_AttestationCA/src/test/resources/tpm2/test/make.blob and the nonce used will be
|
||||
* output as HIRS_AttestationCA/src/test/resources/tpm2/test/secret.blob
|
||||
* @throws URISyntaxException invalid file path
|
||||
* @throws IOException unable to read file
|
||||
*/
|
||||
@Disabled
|
||||
@Test
|
||||
public void testMakeCredential() throws URISyntaxException, IOException {
|
||||
Path akPubPath = Paths.get(getClass().getResource(
|
||||
AK_PUBLIC_PATH).toURI());
|
||||
Path ekPubPath = Paths.get(getClass().getResource(
|
||||
EK_PUBLIC_PATH).toURI());
|
||||
|
||||
byte[] ekPubFile = Files.readAllBytes(ekPubPath);
|
||||
byte[] akPubFile = Files.readAllBytes(akPubPath);
|
||||
|
||||
RSAPublicKey ekPub = ProvisionUtils.parsePublicKey(ekPubFile);
|
||||
RSAPublicKey akPub = ProvisionUtils.parsePublicKey(akPubFile);
|
||||
|
||||
// prepare the nonce and wrap it with keys
|
||||
byte[] nonce = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
ByteString blob = ProvisionUtils.tpm20MakeCredential(ekPub, akPub, nonce);
|
||||
|
||||
Path resources = Objects.requireNonNull(Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
||||
"/").toURI()))
|
||||
.getParent().getParent().getParent().getParent());
|
||||
Path makeBlob = resources.resolve("src/test/resources/tpm2/test/make.blob");
|
||||
Files.write(makeBlob, blob.toByteArray());
|
||||
|
||||
Path secretPath = resources.resolve("src/test/resources/tpm2/test/secret.blob");
|
||||
Files.write(secretPath, nonce);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method that encrypts a blob using the specified transformation and the test key
|
||||
* pair public key.
|
||||
*
|
||||
* @param blob to be encrypted
|
||||
* @param transformation used by a cipher to encrypt
|
||||
* @return encrypted blob
|
||||
* @throws Exception during the encryption process
|
||||
*/
|
||||
private byte[] encryptBlob(final byte[] blob, final String transformation) throws Exception {
|
||||
// initialize a cipher using the specified transformation
|
||||
Cipher cipher = Cipher.getInstance(transformation);
|
||||
|
||||
// use our generated public key to encrypt
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
|
||||
|
||||
// return the cipher text
|
||||
return cipher.doFinal(blob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method that encrypts a blob using a shared key and IV using the specified
|
||||
* transformation.
|
||||
*
|
||||
* @param blob to be encrypted
|
||||
* @param key shared key
|
||||
* @param iv to encrypt with
|
||||
* @param transformation of the encryption cipher
|
||||
* @return encrypted blob
|
||||
* @throws Exception
|
||||
*/
|
||||
private byte[] encryptBlob(final byte[] blob, final byte[] key, final byte[] iv,
|
||||
final String transformation) throws Exception {
|
||||
// initialize a cipher using the specified transformation
|
||||
Cipher cipher = Cipher.getInstance(transformation);
|
||||
|
||||
// generate a secret key specification using the key and AES.
|
||||
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
|
||||
|
||||
// create IV parameter for key specification
|
||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
|
||||
|
||||
// encrypt using the key specification with the generated IV
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
|
||||
|
||||
// return the cipher text
|
||||
return cipher.doFinal(blob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method to decrypt blobs.
|
||||
*
|
||||
* @param blob to be decrypted
|
||||
* @return decrypted blob
|
||||
* @throws Exception
|
||||
*/
|
||||
private byte[] decryptBlob(final byte[] blob) throws Exception {
|
||||
// initialize a cipher using the specified transformation
|
||||
Cipher cipher = Cipher.getInstance(EncryptionScheme.OAEP.toString());
|
||||
|
||||
OAEPParameterSpec spec = new OAEPParameterSpec("Sha1", "MGF1",
|
||||
MGF1ParameterSpec.SHA1, new PSource.PSpecified("TCPA".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
// use our generated public key to encrypt
|
||||
cipher.init(Cipher.PRIVATE_KEY, keyPair.getPrivate(), spec);
|
||||
|
||||
// return the cipher text
|
||||
return cipher.doFinal(blob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method that decrypts a blob using a shared key and IV using the specified.
|
||||
* transformation.
|
||||
*
|
||||
* @param blob to be decrypted
|
||||
* @param key shared key
|
||||
* @param iv to decrypt with
|
||||
* @param transformation of the decryption cipher
|
||||
* @return decrypted blob
|
||||
* @throws Exception
|
||||
*/
|
||||
private byte[] decryptBlob(final byte[] blob, final byte[] key, final byte[] iv,
|
||||
final String transformation) throws Exception {
|
||||
// initialize a cipher using the specified transformation
|
||||
Cipher cipher = Cipher.getInstance(transformation);
|
||||
|
||||
// generate a secret key specification using the key and AES
|
||||
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
|
||||
|
||||
// create IV parameter for key specification
|
||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
|
||||
|
||||
// encrypt using the key specification with the generated IV
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
|
||||
|
||||
// return the cipher text
|
||||
return cipher.doFinal(blob);
|
||||
}
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
package hirs.attestationca.persist.entity;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.cert.CertificateException;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Unit tests for the class <code>Appraiser</code>.
|
||||
@ -160,5 +162,4 @@ public final class AppraiserTest {
|
||||
assertNotEquals(appraiser1.hashCode(), appraiser2.hashCode());
|
||||
assertNotEquals(appraiser2.hashCode(), appraiser1.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.entity;
|
@ -87,13 +87,16 @@ public class TPM2ProvisionerStateTest {
|
||||
|
||||
|
||||
/**
|
||||
* Test that {@link TPM2ProvisionerState#getTPM2ProvisionerState(TPM2ProvisionerStateRepository, byte[])} works.
|
||||
* {@link TPM2ProvisionerState#getTPM2ProvisionerState(TPM2ProvisionerStateRepository, byte[])}, null is returned.
|
||||
* Test that {@link TPM2ProvisionerState#getTPM2ProvisionerState(
|
||||
* TPM2ProvisionerStateRepository, byte[])} works.
|
||||
* {@link TPM2ProvisionerState#getTPM2ProvisionerState(
|
||||
* TPM2ProvisionerStateRepository, byte[])}, null is returned.
|
||||
* @throws IOException this will never happen
|
||||
*/
|
||||
@Test
|
||||
public final void testGetTPM2ProvisionerStateNominal() throws IOException {
|
||||
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository = mock(TPM2ProvisionerStateRepository.class);
|
||||
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository =
|
||||
mock(TPM2ProvisionerStateRepository.class);
|
||||
byte[] nonce = new byte[32];
|
||||
byte[] identityClaim = new byte[360];
|
||||
random.nextBytes(nonce);
|
||||
@ -112,12 +115,14 @@ public class TPM2ProvisionerStateTest {
|
||||
|
||||
/**
|
||||
* Test that if a null is passed as a nonce to
|
||||
* {@link TPM2ProvisionerState#getTPM2ProvisionerState(TPM2ProvisionerStateRepository, byte[])}, null is returned.
|
||||
* {@link TPM2ProvisionerState#getTPM2ProvisionerState(
|
||||
* TPM2ProvisionerStateRepository, byte[])}, null is returned.
|
||||
* @throws IOException this will never happen
|
||||
*/
|
||||
@Test
|
||||
public final void testGetTPM2ProvisionerStateNullNonce() throws IOException {
|
||||
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository = mock(TPM2ProvisionerStateRepository.class);
|
||||
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository =
|
||||
mock(TPM2ProvisionerStateRepository.class);
|
||||
byte[] nonce = new byte[32];
|
||||
byte[] identityClaim = new byte[360];
|
||||
random.nextBytes(nonce);
|
||||
@ -133,12 +138,14 @@ public class TPM2ProvisionerStateTest {
|
||||
|
||||
/**
|
||||
* Test that if a nonce that is less than 8 bytes is passed to
|
||||
* {@link TPM2ProvisionerState#getTPM2ProvisionerState(TPM2ProvisionerStateRepository, byte[])}, null is returned.
|
||||
* {@link TPM2ProvisionerState#getTPM2ProvisionerState(
|
||||
* TPM2ProvisionerStateRepository, byte[])}, null is returned.
|
||||
* @throws IOException this will never happen
|
||||
*/
|
||||
@Test
|
||||
public final void testGetTPM2ProvisionerStateNonceTooSmall() throws IOException {
|
||||
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository = mock(TPM2ProvisionerStateRepository.class);
|
||||
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository =
|
||||
mock(TPM2ProvisionerStateRepository.class);
|
||||
byte[] nonce = new byte[32];
|
||||
byte[] identityClaim = new byte[360];
|
||||
random.nextBytes(nonce);
|
||||
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.entity.tpm;
|
@ -0,0 +1,313 @@
|
||||
package hirs.attestationca.persist.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.ConformanceCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.OSInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.TPMInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReportTest;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Class with definitions and functions common to multiple Userdefined Entity object tests.
|
||||
*
|
||||
*/
|
||||
public class AbstractUserdefinedEntityTest {
|
||||
|
||||
/**
|
||||
* Location of a test (fake) SGI intermediate CA certificate.
|
||||
*/
|
||||
public static final String FAKE_SGI_INT_CA_FILE = "/certificates/fakeSGIIntermediateCA.cer";
|
||||
|
||||
/**
|
||||
* Location of a test (fake) Intel intermediate CA certificate.
|
||||
*/
|
||||
public static final String FAKE_INTEL_INT_CA_FILE =
|
||||
"/certificates/fakeIntelIntermediateCA.cer";
|
||||
|
||||
/**
|
||||
* Location of a test (fake) root CA certificate.
|
||||
*/
|
||||
public static final String FAKE_ROOT_CA_FILE = "/certificates/fakeRootCA.cer";
|
||||
|
||||
/**
|
||||
* Hex-encoded subject key identifier for the FAKE_ROOT_CA_FILE.
|
||||
*/
|
||||
public static final String FAKE_ROOT_CA_SUBJECT_KEY_IDENTIFIER_HEX =
|
||||
"58ec313a1699f94c1c8c4e2c6412402b258f0177";
|
||||
|
||||
/**
|
||||
* Location of a test identity certificate.
|
||||
*/
|
||||
private static final String TEST_IDENTITY_CERT = "/tpm/sample_identity_cert.cer";
|
||||
|
||||
/**
|
||||
* Location of a test platform attribute cert.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_1 =
|
||||
"/validation/platform_credentials/Intel_pc1.cer";
|
||||
|
||||
/**
|
||||
* Location of another, slightly different platform attribute cert.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_2 =
|
||||
"/validation/platform_credentials/Intel_pc2.cer";
|
||||
|
||||
/**
|
||||
* Location of another, slightly different platform attribute cert.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_3 =
|
||||
"/validation/platform_credentials/Intel_pc3.cer";
|
||||
|
||||
/**
|
||||
* Platform cert with comma separated baseboard and chassis serial number.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_4 =
|
||||
"/validation/platform_credentials/Intel_pc4.pem";
|
||||
|
||||
/**
|
||||
* Another platform cert with comma separated baseboard and chassis serial number.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_5 =
|
||||
"/validation/platform_credentials/Intel_pc5.pem";
|
||||
|
||||
/**
|
||||
* Location of another, slightly different platform attribute cert.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_6 =
|
||||
"/validation/platform_credentials/TPM_INTC_Platform_Cert_RSA.txt";
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(DeviceInfoReportTest.class);
|
||||
|
||||
/**
|
||||
* Dummy message for supply chain validation test.
|
||||
*/
|
||||
public static final String VALIDATION_MESSAGE = "Some message.";
|
||||
|
||||
/**
|
||||
* Construct a test certificate from the given parameters.
|
||||
*
|
||||
* @param <T> the type of Certificate that will be created
|
||||
* @param certificateClass the class of certificate to generate
|
||||
* @param filename the location of the certificate to be used
|
||||
* @return the newly-constructed Certificate
|
||||
* @throws IOException if there is a problem constructing the test certificate
|
||||
*/
|
||||
public static <T extends ArchivableEntity> Certificate getTestCertificate(
|
||||
final Class<T> certificateClass, final String filename)
|
||||
throws IOException {
|
||||
return getTestCertificate(certificateClass, filename, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a test certificate from the given parameters.
|
||||
*
|
||||
* @param <T> the type of Certificate that will be created
|
||||
* @param certificateClass the class of certificate to generate
|
||||
* @param filename the location of the certificate to be used
|
||||
* @param endorsementCredential the endorsement credentials (can be null)
|
||||
* @param platformCredentials the platform credentials (can be null)
|
||||
* @return the newly-constructed Certificate
|
||||
* @throws IOException if there is a problem constructing the test certificate
|
||||
*/
|
||||
public static <T extends ArchivableEntity> Certificate getTestCertificate(
|
||||
final Class<T> certificateClass, final String filename,
|
||||
final EndorsementCredential endorsementCredential,
|
||||
final List<PlatformCredential> platformCredentials)
|
||||
throws IOException {
|
||||
|
||||
Path certPath;
|
||||
try {
|
||||
certPath = Paths.get(Objects.requireNonNull(
|
||||
AbstractUserdefinedEntityTest.class.getResource(filename)).toURI());
|
||||
// certPath = Paths.get(Objects.requireNonNull(
|
||||
// CertificateTest.class.getResource(filename)).toURI());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IOException("Could not resolve path URI", e);
|
||||
}
|
||||
|
||||
switch (certificateClass.getSimpleName()) {
|
||||
case "CertificateAuthorityCredential":
|
||||
return new CertificateAuthorityCredential(certPath);
|
||||
case "ConformanceCredential":
|
||||
return new ConformanceCredential(certPath);
|
||||
case "EndorsementCredential":
|
||||
return new EndorsementCredential(certPath);
|
||||
case "PlatformCredential":
|
||||
return new PlatformCredential(certPath);
|
||||
case "IssuedAttestationCertificate":
|
||||
return new IssuedAttestationCertificate(certPath,
|
||||
endorsementCredential, platformCredentials);
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Unknown certificate class %s", certificateClass.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all test certificates.
|
||||
*
|
||||
* @return a list of all test certificates
|
||||
* @throws IOException if there is a problem deserializing certificates
|
||||
*/
|
||||
public static List<ArchivableEntity> getAllTestCertificates() throws IOException {
|
||||
return Arrays.asList(
|
||||
getTestCertificate(CertificateAuthorityCredential.class, FAKE_SGI_INT_CA_FILE),
|
||||
getTestCertificate(CertificateAuthorityCredential.class, FAKE_INTEL_INT_CA_FILE),
|
||||
getTestCertificate(CertificateAuthorityCredential.class, FAKE_ROOT_CA_FILE)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DeviceInfoReport instance usable for testing.
|
||||
*
|
||||
* @return a test DeviceInfoReport
|
||||
*/
|
||||
public static DeviceInfoReport getTestDeviceInfoReport() {
|
||||
return new DeviceInfoReport(
|
||||
createTestNetworkInfo(), createTestOSInfo(), createTestFirmwareInfo(),
|
||||
createTestHardwareInfo(), createTPMInfo()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of NetworkInfo.
|
||||
*
|
||||
* @return network information for a fake device
|
||||
*/
|
||||
public static NetworkInfo createTestNetworkInfo() {
|
||||
try {
|
||||
final String hostname = "test.hostname";
|
||||
final InetAddress ipAddress =
|
||||
InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
|
||||
final byte[] macAddress = new byte[] {11, 22, 33, 44, 55, 66};
|
||||
return new NetworkInfo(hostname, ipAddress, macAddress);
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
LOGGER.error("error occurred while creating InetAddress");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of OSInfo.
|
||||
*
|
||||
* @return OS information for a fake device
|
||||
*/
|
||||
public static OSInfo createTestOSInfo() {
|
||||
return new OSInfo("test os name", "test os version", "test os arch",
|
||||
"test distribution", "test distribution release");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of FirmwareInfo.
|
||||
*
|
||||
* @return Firmware information for a fake device
|
||||
*/
|
||||
public static FirmwareInfo createTestFirmwareInfo() {
|
||||
return new FirmwareInfo("test bios vendor", "test bios version", "test bios release date");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of HardwareInfo.
|
||||
*
|
||||
* @return Hardware information for a fake device
|
||||
*/
|
||||
public static HardwareInfo createTestHardwareInfo() {
|
||||
return new HardwareInfo("test manufacturer", "test product name", "test version",
|
||||
"test really long serial number with many characters", "test really long chassis "
|
||||
+ "serial number with many characters",
|
||||
"test really long baseboard serial number with many characters");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of TPMInfo.
|
||||
*
|
||||
* @return TPM information for a fake device
|
||||
*/
|
||||
public static final TPMInfo createTPMInfo() {
|
||||
final short num1 = 1;
|
||||
final short num2 = 2;
|
||||
final short num3 = 3;
|
||||
final short num4 = 4;
|
||||
return new TPMInfo("test os make", num1, num2, num3, num4,
|
||||
getTestIdentityCertificate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test identity certificate.
|
||||
*
|
||||
* @return the test X509 certificate
|
||||
*/
|
||||
public static X509Certificate getTestIdentityCertificate() {
|
||||
X509Certificate certificateValue = null;
|
||||
InputStream istream = null;
|
||||
istream = AbstractUserdefinedEntityTest.class.getResourceAsStream(
|
||||
TEST_IDENTITY_CERT
|
||||
);
|
||||
try {
|
||||
if (istream == null) {
|
||||
throw new FileNotFoundException(TEST_IDENTITY_CERT);
|
||||
}
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
certificateValue = (X509Certificate) cf.generateCertificate(
|
||||
istream);
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
} finally {
|
||||
if (istream != null) {
|
||||
try {
|
||||
istream.close();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("test certificate file could not be closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
return certificateValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a SupplyChainValidation for use in tests according to the provided parameters.
|
||||
*
|
||||
* @param type the type of validation
|
||||
* @param result the appraisal result
|
||||
* @param certificates the certificates related to this validation
|
||||
* @return the resulting SupplyChainValidation object
|
||||
*/
|
||||
public static SupplyChainValidation getTestSupplyChainValidation(
|
||||
final SupplyChainValidation.ValidationType type,
|
||||
final AppraisalStatus.Status result,
|
||||
final List<ArchivableEntity> certificates) {
|
||||
return new SupplyChainValidation(
|
||||
type,
|
||||
result,
|
||||
certificates,
|
||||
VALIDATION_MESSAGE
|
||||
);
|
||||
}
|
||||
}
|
@ -1,6 +1,11 @@
|
||||
package hirs.attestationca.persist.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.ConformanceCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
import org.bouncycastle.cert.X509AttributeCertificateHolder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@ -14,12 +19,8 @@ import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.*;
|
||||
import org.bouncycastle.cert.X509AttributeCertificateHolder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@ -29,17 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
/**
|
||||
* This class tests functionality of the {@link Certificate} class.
|
||||
*/
|
||||
public class CertificateTest {
|
||||
/**
|
||||
* Location of a test (fake) root CA certificate.
|
||||
*/
|
||||
public static final String FAKE_ROOT_CA_FILE = "/certificates/fakeRootCA.cer";
|
||||
|
||||
/**
|
||||
* Location of a test (fake) Intel intermediate CA certificate.
|
||||
*/
|
||||
public static final String FAKE_INTEL_INT_CA_FILE =
|
||||
"/certificates/fakeIntelIntermediateCA.cer";
|
||||
public class CertificateTest extends AbstractUserdefinedEntityTest {
|
||||
|
||||
/**
|
||||
* Location of a test (fake) Intel intermediate CA certificate.
|
||||
@ -47,11 +38,6 @@ public class CertificateTest {
|
||||
public static final String INTEL_INT_CA_FILE =
|
||||
"/validation/platform_credentials/intel_chain/root/intermediate2.cer";
|
||||
|
||||
/**
|
||||
* Location of a test (fake) SGI intermediate CA certificate.
|
||||
*/
|
||||
public static final String FAKE_SGI_INT_CA_FILE = "/certificates/fakeSGIIntermediateCA.cer";
|
||||
|
||||
/**
|
||||
* Location of another test self-signed certificate.
|
||||
*/
|
||||
@ -78,12 +64,6 @@ public class CertificateTest {
|
||||
*/
|
||||
public static final String GS_ROOT_CA = "/certificates/stMicroCaCerts/gstpmroot.crt";
|
||||
|
||||
/**
|
||||
* Hex-encoded subject key identifier for the FAKE_ROOT_CA_FILE.
|
||||
*/
|
||||
public static final String FAKE_ROOT_CA_SUBJECT_KEY_IDENTIFIER_HEX =
|
||||
"58ec313a1699f94c1c8c4e2c6412402b258f0177";
|
||||
|
||||
/**
|
||||
* Location of a test STM endorsement credential.
|
||||
*/
|
||||
@ -119,7 +99,8 @@ public class CertificateTest {
|
||||
public void testConstructCertFromByteArray() throws IOException, URISyntaxException {
|
||||
Certificate certificate = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(FAKE_ROOT_CA_FILE)).toURI())
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
||||
FAKE_ROOT_CA_FILE)).toURI())
|
||||
)
|
||||
);
|
||||
assertEquals(
|
||||
@ -163,7 +144,8 @@ public class CertificateTest {
|
||||
@Test
|
||||
public void testConstructCertFromPath() throws URISyntaxException, IOException {
|
||||
Certificate certificate = new CertificateAuthorityCredential(
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(FAKE_ROOT_CA_FILE)).toURI())
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
||||
FAKE_ROOT_CA_FILE)).toURI())
|
||||
);
|
||||
assertEquals(
|
||||
"CN=Fake Root CA",
|
||||
@ -202,12 +184,12 @@ public class CertificateTest {
|
||||
Certificate.CertificateType.X509_CERTIFICATE,
|
||||
getTestCertificate(
|
||||
PlatformCredential.class,
|
||||
PlatformCredentialTest.TEST_PLATFORM_CERT_3).getCertificateType());
|
||||
TEST_PLATFORM_CERT_3).getCertificateType());
|
||||
assertEquals(
|
||||
Certificate.CertificateType.ATTRIBUTE_CERTIFICATE,
|
||||
getTestCertificate(
|
||||
PlatformCredential.class,
|
||||
PlatformCredentialTest.TEST_PLATFORM_CERT_3).getCertificateType());
|
||||
TEST_PLATFORM_CERT_3).getCertificateType());
|
||||
|
||||
}
|
||||
|
||||
@ -220,7 +202,7 @@ public class CertificateTest {
|
||||
@Test
|
||||
public void testImportPem() throws IOException {
|
||||
Certificate platformCredential = getTestCertificate(
|
||||
PlatformCredential.class, PlatformCredentialTest.TEST_PLATFORM_CERT_4
|
||||
PlatformCredential.class, TEST_PLATFORM_CERT_4
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
@ -232,7 +214,7 @@ public class CertificateTest {
|
||||
);
|
||||
|
||||
platformCredential = getTestCertificate(
|
||||
PlatformCredential.class, PlatformCredentialTest.TEST_PLATFORM_CERT_5
|
||||
PlatformCredential.class, TEST_PLATFORM_CERT_5
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
@ -295,13 +277,12 @@ public class CertificateTest {
|
||||
public void testX509AttributeCertificateParsing() throws IOException, URISyntaxException {
|
||||
Certificate platformCert = getTestCertificate(
|
||||
PlatformCredential.class,
|
||||
PlatformCredentialTest.TEST_PLATFORM_CERT_3
|
||||
TEST_PLATFORM_CERT_3
|
||||
);
|
||||
|
||||
X509AttributeCertificateHolder attrCertHolder = new X509AttributeCertificateHolder(
|
||||
Files.readAllBytes(Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
||||
PlatformCredentialTest.TEST_PLATFORM_CERT_3
|
||||
)).toURI()))
|
||||
TEST_PLATFORM_CERT_3)).toURI()))
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
@ -330,7 +311,7 @@ public class CertificateTest {
|
||||
public void testX509AttributeCertificateParsingExtended()
|
||||
throws IOException, URISyntaxException {
|
||||
Certificate platformCert = getTestCertificate(
|
||||
PlatformCredential.class, PlatformCredentialTest.TEST_PLATFORM_CERT_6);
|
||||
PlatformCredential.class, TEST_PLATFORM_CERT_6);
|
||||
|
||||
assertEquals("https://trustedservices.intel.com/"
|
||||
+ "content/TSC/certs/TSC_IssuingCAIKGF_TEST.cer\n",
|
||||
@ -428,11 +409,13 @@ public class CertificateTest {
|
||||
|
||||
assertEquals(
|
||||
new CertificateAuthorityCredential(
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(FAKE_ROOT_CA_FILE)).toURI())
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
||||
FAKE_ROOT_CA_FILE)).toURI())
|
||||
),
|
||||
new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(FAKE_ROOT_CA_FILE)).toURI())
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
||||
FAKE_ROOT_CA_FILE)).toURI())
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -450,7 +433,7 @@ public class CertificateTest {
|
||||
assertNotEquals(
|
||||
null,
|
||||
getTestCertificate(CertificateAuthorityCredential.class, FAKE_ROOT_CA_FILE)
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -489,11 +472,13 @@ public class CertificateTest {
|
||||
|
||||
assertEquals(
|
||||
new CertificateAuthorityCredential(
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(FAKE_ROOT_CA_FILE)).toURI())
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
||||
FAKE_ROOT_CA_FILE)).toURI())
|
||||
).hashCode(),
|
||||
new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(FAKE_ROOT_CA_FILE)).toURI())
|
||||
Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
||||
FAKE_ROOT_CA_FILE)).toURI())
|
||||
)
|
||||
).hashCode()
|
||||
);
|
||||
@ -520,79 +505,6 @@ public class CertificateTest {
|
||||
return getTestCertificate(CertificateAuthorityCredential.class, filename);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a test certificate from the given parameters.
|
||||
*
|
||||
* @param <T> the type of Certificate that will be created
|
||||
* @param certificateClass the class of certificate to generate
|
||||
* @param filename the location of the certificate to be used
|
||||
* @return the newly-constructed Certificate
|
||||
* @throws IOException if there is a problem constructing the test certificate
|
||||
*/
|
||||
public static <T extends ArchivableEntity> Certificate getTestCertificate(
|
||||
final Class<T> certificateClass, final String filename)
|
||||
throws IOException {
|
||||
return getTestCertificate(certificateClass, filename, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a test certificate from the given parameters.
|
||||
*
|
||||
* @param <T> the type of Certificate that will be created
|
||||
* @param certificateClass the class of certificate to generate
|
||||
* @param filename the location of the certificate to be used
|
||||
* @param endorsementCredential the endorsement credentials (can be null)
|
||||
* @param platformCredentials the platform credentials (can be null)
|
||||
* @return the newly-constructed Certificate
|
||||
* @throws IOException if there is a problem constructing the test certificate
|
||||
*/
|
||||
public static <T extends ArchivableEntity> Certificate getTestCertificate(
|
||||
final Class<T> certificateClass, final String filename,
|
||||
final EndorsementCredential endorsementCredential,
|
||||
final List<PlatformCredential> platformCredentials)
|
||||
throws IOException {
|
||||
|
||||
Path certPath;
|
||||
try {
|
||||
certPath = Paths.get(Objects.requireNonNull(CertificateTest.class.getResource(filename)).toURI());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IOException("Could not resolve path URI", e);
|
||||
}
|
||||
|
||||
switch (certificateClass.getSimpleName()) {
|
||||
case "CertificateAuthorityCredential":
|
||||
return new CertificateAuthorityCredential(certPath);
|
||||
case "ConformanceCredential":
|
||||
return new ConformanceCredential(certPath);
|
||||
case "EndorsementCredential":
|
||||
return new EndorsementCredential(certPath);
|
||||
case "PlatformCredential":
|
||||
return new PlatformCredential(certPath);
|
||||
case "IssuedAttestationCertificate":
|
||||
return new IssuedAttestationCertificate(certPath,
|
||||
endorsementCredential, platformCredentials);
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Unknown certificate class %s", certificateClass.getName())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all test certificates.
|
||||
*
|
||||
* @return a list of all test certificates
|
||||
* @throws IOException if there is a problem deserializing certificates
|
||||
*/
|
||||
public static List<ArchivableEntity> getAllTestCertificates() throws IOException {
|
||||
return Arrays.asList(
|
||||
getTestCertificate(CertificateAuthorityCredential.class, FAKE_SGI_INT_CA_FILE),
|
||||
getTestCertificate(CertificateAuthorityCredential.class, FAKE_INTEL_INT_CA_FILE),
|
||||
getTestCertificate(CertificateAuthorityCredential.class, FAKE_ROOT_CA_FILE)
|
||||
);
|
||||
}
|
||||
|
||||
private static X509Certificate readX509Certificate(final String resourceName)
|
||||
throws IOException {
|
||||
|
||||
@ -603,12 +515,13 @@ public class CertificateTest {
|
||||
throw new IOException("Cannot get X509 CertificateFactory instance", e);
|
||||
}
|
||||
|
||||
try (FileInputStream certInputStream = new FileInputStream(
|
||||
Paths.get(Objects.requireNonNull(CertificateTest.class.getResource(resourceName)).toURI()).toFile()
|
||||
try (FileInputStream certInputStream = new FileInputStream(Paths.get(
|
||||
Objects.requireNonNull(CertificateTest.class.getResource(
|
||||
resourceName)).toURI()).toFile()
|
||||
)) {
|
||||
return (X509Certificate) cf.generateCertificate(certInputStream);
|
||||
} catch (CertificateException | URISyntaxException e) {
|
||||
throw new IOException("Cannot read certificate", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package hirs.attestationca.persist.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReportTest;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import hirs.attestationca.persist.enums.HealthStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -14,19 +13,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
* This is the test class for the <code>Device</code> class.
|
||||
*
|
||||
*/
|
||||
public final class DeviceTest {
|
||||
/**
|
||||
* Utility method for getting a <code>Device</code> that can be used for
|
||||
* testing.
|
||||
*
|
||||
* @param name name for the <code>Device</code>
|
||||
*
|
||||
* @return device
|
||||
*/
|
||||
public static Device getTestDevice(final String name) {
|
||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
||||
return new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
}
|
||||
public final class DeviceTest extends AbstractUserdefinedEntityTest {
|
||||
|
||||
/**
|
||||
* Tests that the device constructor can take a name.
|
||||
@ -34,7 +21,9 @@ public final class DeviceTest {
|
||||
@Test
|
||||
public void testDevice() {
|
||||
final String name = "my-laptop";
|
||||
final Device device = new Device(name, null, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null , null);
|
||||
final Device device = new Device(name, null, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
assertNotNull(device);
|
||||
}
|
||||
|
||||
@ -45,8 +34,10 @@ public final class DeviceTest {
|
||||
@Test
|
||||
public void testDeviceNameAndInfo() {
|
||||
final String name = "my-laptop";
|
||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
||||
new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||
new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,7 +47,9 @@ public final class DeviceTest {
|
||||
public void testDeviceNameAndNullInfo() {
|
||||
final String name = "my-laptop";
|
||||
final DeviceInfoReport deviceInfo = null;
|
||||
new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,8 +58,10 @@ public final class DeviceTest {
|
||||
@Test
|
||||
public void testGetDeviceInfo() {
|
||||
final String name = "my-laptop";
|
||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
assertEquals(deviceInfo, device.getDeviceInfo());
|
||||
}
|
||||
|
||||
@ -76,9 +71,11 @@ public final class DeviceTest {
|
||||
@Test
|
||||
public void testSetDeviceInfo() {
|
||||
final String name = "my-laptop";
|
||||
final Device device = new Device(name, null, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final Device device = new Device(name, null, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
assertNull(device.getDeviceInfo());
|
||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
||||
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||
device.setDeviceInfo(deviceInfo);
|
||||
assertEquals(deviceInfo, device.getDeviceInfo());
|
||||
}
|
||||
@ -89,8 +86,10 @@ public final class DeviceTest {
|
||||
@Test
|
||||
public void testSetNullDeviceInfo() {
|
||||
final String name = "my-laptop";
|
||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
assertEquals(deviceInfo, device.getDeviceInfo());
|
||||
device.setDeviceInfo(null);
|
||||
assertNull(device.getDeviceInfo());
|
||||
@ -102,8 +101,10 @@ public final class DeviceTest {
|
||||
@Test
|
||||
public void testNotNullLastReportTimeStamp() {
|
||||
final String name = "my-laptop";
|
||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
assertNotNull(device.getLastReportTimestamp());
|
||||
}
|
||||
|
||||
@ -112,7 +113,9 @@ public final class DeviceTest {
|
||||
*/
|
||||
@Test
|
||||
public void testSetHealthStatus() {
|
||||
final Device device = new Device("test-device", null, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final Device device = new Device("test-device", null, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
device.setHealthStatus(HealthStatus.TRUSTED);
|
||||
assertEquals(HealthStatus.TRUSTED, device.getHealthStatus());
|
||||
}
|
||||
@ -124,9 +127,13 @@ public final class DeviceTest {
|
||||
public void testDeviceEquals() {
|
||||
final String name = "my-laptop";
|
||||
final String otherName = "my-laptop";
|
||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final Device other = new Device(otherName, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
final Device other = new Device(otherName, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
assertEquals(device, other);
|
||||
}
|
||||
|
||||
@ -136,8 +143,10 @@ public final class DeviceTest {
|
||||
@Test
|
||||
public void testGetDefaultSupplyChainStatus() {
|
||||
String name = "my-laptop";
|
||||
DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
assertEquals(AppraisalStatus.Status.UNKNOWN, device.getSupplyChainValidationStatus());
|
||||
}
|
||||
|
||||
@ -147,8 +156,10 @@ public final class DeviceTest {
|
||||
@Test
|
||||
public void testSetAndGetSupplyChainStatus() {
|
||||
String name = "my-laptop";
|
||||
DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
||||
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||
null, null);
|
||||
device.setSupplyChainValidationStatus(AppraisalStatus.Status.PASS);
|
||||
assertEquals(AppraisalStatus.Status.PASS, device.getSupplyChainValidationStatus());
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
package hirs.attestationca.persist.entity.userdefined;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit test class for PolicySettings.
|
||||
*/
|
||||
public class PolicySettingsTest {
|
||||
|
||||
/**
|
||||
* Tests that default policy settings are set correctly.
|
||||
*/
|
||||
@Test
|
||||
public final void checkDefaultSettings() {
|
||||
PolicySettings policy = new PolicySettings("Default Supply Chain Policy");
|
||||
assertFalse(policy.isEcValidationEnabled());
|
||||
assertFalse(policy.isPcValidationEnabled());
|
||||
assertFalse(policy.isPcAttributeValidationEnabled());
|
||||
assertFalse(policy.isExpiredCertificateValidationEnabled());
|
||||
assertFalse(policy.isReplaceEC());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all setters and getters work.
|
||||
*/
|
||||
@Test
|
||||
public final void flipDefaultSettings() {
|
||||
PolicySettings policy = new PolicySettings("Default Supply Chain Policy");
|
||||
policy.setEcValidationEnabled(false);
|
||||
policy.setPcValidationEnabled(false);
|
||||
policy.setPcAttributeValidationEnabled(false);
|
||||
policy.setExpiredCertificateValidationEnabled(false);
|
||||
policy.setReplaceEC(true);
|
||||
assertFalse(policy.isEcValidationEnabled());
|
||||
assertFalse(policy.isPcValidationEnabled());
|
||||
assertFalse(policy.isPcAttributeValidationEnabled());
|
||||
assertFalse(policy.isExpiredCertificateValidationEnabled());
|
||||
assertTrue(policy.isReplaceEC());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we can initiate a policy with a description.
|
||||
*/
|
||||
@Test
|
||||
public final void createPolicyWithDescription() {
|
||||
final String description = "A default policy";
|
||||
PolicySettings policy = new PolicySettings("Default Supply Chain Policy",
|
||||
description);
|
||||
assertEquals(description, policy.getDescription());
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
package hirs.attestationca.persist.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import hirs.attestationca.persist.enums.HealthStatus;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* Tests the functionality in SupplyChainValidationSummary.
|
||||
*/
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class SupplyChainValidationSummaryTest extends AbstractUserdefinedEntityTest {
|
||||
|
||||
/**
|
||||
* Test device.
|
||||
*
|
||||
*/
|
||||
private Device device;
|
||||
|
||||
/**
|
||||
* List of test certificates.
|
||||
*
|
||||
*/
|
||||
private List<ArchivableEntity> certificates;
|
||||
|
||||
/**
|
||||
* Create a set of certificates and a device for use by these tests.
|
||||
*
|
||||
* @throws Exception if there is a problem deserializing certificates or creating test device
|
||||
*/
|
||||
@BeforeAll
|
||||
public void setup() throws Exception {
|
||||
|
||||
certificates = getAllTestCertificates();
|
||||
device = getTestDevice("TestDevice");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that an empty summary behaves as expected.
|
||||
*/
|
||||
@Test
|
||||
public void testEmptySummary() throws InterruptedException {
|
||||
SupplyChainValidationSummary emptySummary = getTestSummary(
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
//assertEquals(device, emptySummary.getDevice());
|
||||
assertEquals(device.getDeviceInfo(), emptySummary.getDevice().getDeviceInfo());
|
||||
assertEquals(Collections.EMPTY_SET, emptySummary.getValidations());
|
||||
assertEquals(AppraisalStatus.Status.PASS, emptySummary.getOverallValidationResult());
|
||||
assertNotNull(emptySummary.getCreateTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a summary can't be created with a null validationIdentifier.
|
||||
*/
|
||||
@Test
|
||||
public void testNullValidationIdentifier() {
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
new SupplyChainValidationSummary(null, Collections.emptyList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a summary can't be created with a null validations list.
|
||||
*/
|
||||
@Test
|
||||
public void testNullValidationList() {
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
new SupplyChainValidationSummary(device, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that summaries with one and two component validations, which both represent successful
|
||||
* validations, have getters that return the expected information.
|
||||
*/
|
||||
@Test
|
||||
public void testSuccessfulSummary() throws InterruptedException {
|
||||
SupplyChainValidationSummary oneValidation = getTestSummary(
|
||||
1,
|
||||
0
|
||||
);
|
||||
|
||||
//assertEquals(device, oneValidation.getDevice());
|
||||
assertEquals(device.getDeviceInfo(), oneValidation.getDevice().getDeviceInfo());
|
||||
assertEquals(1, oneValidation.getValidations().size());
|
||||
assertEquals(AppraisalStatus.Status.PASS, oneValidation.getOverallValidationResult());
|
||||
assertNotNull(oneValidation.getCreateTime());
|
||||
|
||||
SupplyChainValidationSummary twoValidations = getTestSummary(
|
||||
2,
|
||||
0
|
||||
);
|
||||
|
||||
//assertEquals(device, twoValidations.getDevice());
|
||||
assertEquals(device.getDeviceInfo(), twoValidations.getDevice().getDeviceInfo());
|
||||
assertEquals(2, twoValidations.getValidations().size());
|
||||
assertEquals(twoValidations.getOverallValidationResult(), AppraisalStatus.Status.PASS);
|
||||
assertNotNull(twoValidations.getCreateTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that summaries with one and two component validations, of which one represents an
|
||||
* unsuccessful validations, have getters that return the expected information.
|
||||
*/
|
||||
@Test
|
||||
public void testUnsuccessfulSummary() throws InterruptedException {
|
||||
SupplyChainValidationSummary oneValidation = getTestSummary(
|
||||
1,
|
||||
1
|
||||
);
|
||||
|
||||
//assertEquals(device, oneValidation.getDevice());
|
||||
assertEquals(device.getDeviceInfo(), oneValidation.getDevice().getDeviceInfo());
|
||||
assertEquals(1, oneValidation.getValidations().size());
|
||||
assertEquals(AppraisalStatus.Status.FAIL, oneValidation.getOverallValidationResult());
|
||||
assertNotNull(oneValidation.getCreateTime());
|
||||
|
||||
SupplyChainValidationSummary twoValidations = getTestSummary(
|
||||
2,
|
||||
1
|
||||
);
|
||||
|
||||
//assertEquals(device, twoValidations.getDevice());
|
||||
assertEquals(device.getDeviceInfo(), twoValidations.getDevice().getDeviceInfo());
|
||||
assertEquals(2, twoValidations.getValidations().size());
|
||||
assertEquals(AppraisalStatus.Status.FAIL, twoValidations.getOverallValidationResult());
|
||||
assertNotNull(twoValidations.getCreateTime());
|
||||
|
||||
SupplyChainValidationSummary twoBadValidations = getTestSummary(
|
||||
2,
|
||||
2
|
||||
);
|
||||
|
||||
//assertEquals(device, twoBadValidations.getDevice());
|
||||
assertEquals(device.getDeviceInfo(), twoBadValidations.getDevice().getDeviceInfo());
|
||||
assertEquals(2, twoBadValidations.getValidations().size());
|
||||
assertEquals(AppraisalStatus.Status.FAIL, twoBadValidations.getOverallValidationResult());
|
||||
assertNotNull(twoBadValidations.getCreateTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for getting a <code>Device</code> that can be used for
|
||||
* testing.
|
||||
*
|
||||
* @param name name for the <code>Device</code>
|
||||
*
|
||||
* @return device
|
||||
*/
|
||||
public static Device getTestDevice(final String name) {
|
||||
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||
return new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN, null,
|
||||
false, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for getting a <code>SupplyChainValidationSummary</code> that can be used for
|
||||
* testing.
|
||||
*
|
||||
* @param numberOfValidations number of validations for the <code>SupplyChainValidationSummary</code>
|
||||
* @param numFail number of failed validations
|
||||
*
|
||||
* @return device
|
||||
*/
|
||||
private SupplyChainValidationSummary getTestSummary(
|
||||
final int numberOfValidations,
|
||||
final int numFail
|
||||
) throws InterruptedException {
|
||||
SupplyChainValidation.ValidationType[] validationTypes =
|
||||
SupplyChainValidation.ValidationType.values();
|
||||
|
||||
if (numberOfValidations > validationTypes.length) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Cannot have more than %d validation types",
|
||||
validationTypes.length
|
||||
));
|
||||
}
|
||||
|
||||
if (numFail > numberOfValidations) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Cannot have more than %d failed validations",
|
||||
validationTypes.length
|
||||
));
|
||||
}
|
||||
|
||||
Collection<SupplyChainValidation> validations = new HashSet<>();
|
||||
for (int i = 0; i < numberOfValidations; i++) {
|
||||
boolean successful = true;
|
||||
if (i >= (numberOfValidations - numFail)) {
|
||||
successful = false;
|
||||
}
|
||||
|
||||
AppraisalStatus.Status result = AppraisalStatus.Status.FAIL;
|
||||
if (successful) {
|
||||
result = AppraisalStatus.Status.PASS;
|
||||
}
|
||||
|
||||
validations.add(SupplyChainValidationTest.getTestSupplyChainValidation(
|
||||
validationTypes[i],
|
||||
result,
|
||||
certificates
|
||||
));
|
||||
}
|
||||
|
||||
return new SupplyChainValidationSummary(device, validations);
|
||||
}
|
||||
}
|
@ -1,21 +1,18 @@
|
||||
package hirs.attestationca.persist.entity.userdefined;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* Simple tests for the {@link SupplyChainValidation} class. Tests for the persistence of this
|
||||
* class are located in { SupplyChainValidationSummaryTest}.
|
||||
*/
|
||||
class SupplyChainValidationTest {
|
||||
private static final String MESSAGE = "Some message.";
|
||||
class SupplyChainValidationTest extends AbstractUserdefinedEntityTest {
|
||||
|
||||
/**
|
||||
* Test that this class' getter methods work properly.
|
||||
@ -31,9 +28,9 @@ class SupplyChainValidationTest {
|
||||
);
|
||||
assertEquals(
|
||||
validation.getCertificatesUsed(),
|
||||
CertificateTest.getAllTestCertificates()
|
||||
getAllTestCertificates()
|
||||
);
|
||||
assertEquals(validation.getMessage(), MESSAGE);
|
||||
assertEquals(validation.getMessage(), VALIDATION_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,8 +44,8 @@ class SupplyChainValidationTest {
|
||||
new SupplyChainValidation(
|
||||
null,
|
||||
AppraisalStatus.Status.PASS,
|
||||
CertificateTest.getAllTestCertificates(),
|
||||
MESSAGE
|
||||
getAllTestCertificates(),
|
||||
VALIDATION_MESSAGE
|
||||
));
|
||||
}
|
||||
|
||||
@ -64,7 +61,7 @@ class SupplyChainValidationTest {
|
||||
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
|
||||
AppraisalStatus.Status.PASS,
|
||||
null,
|
||||
MESSAGE
|
||||
VALIDATION_MESSAGE
|
||||
));
|
||||
}
|
||||
|
||||
@ -78,8 +75,8 @@ class SupplyChainValidationTest {
|
||||
new SupplyChainValidation(
|
||||
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
|
||||
AppraisalStatus.Status.PASS,
|
||||
CertificateTest.getAllTestCertificates(),
|
||||
MESSAGE
|
||||
getAllTestCertificates(),
|
||||
VALIDATION_MESSAGE
|
||||
);
|
||||
}
|
||||
|
||||
@ -95,27 +92,7 @@ class SupplyChainValidationTest {
|
||||
return getTestSupplyChainValidation(
|
||||
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
|
||||
AppraisalStatus.Status.PASS,
|
||||
CertificateTest.getAllTestCertificates()
|
||||
getAllTestCertificates()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a SupplyChainValidation for use in tests according to the provided parameters.
|
||||
*
|
||||
* @param type the type of validation
|
||||
* @param result the appraisal result
|
||||
* @param certificates the certificates related to this validation
|
||||
* @return the resulting SupplyChainValidation object
|
||||
*/
|
||||
public static SupplyChainValidation getTestSupplyChainValidation(
|
||||
final SupplyChainValidation.ValidationType type,
|
||||
final AppraisalStatus.Status result,
|
||||
final List<ArchivableEntity> certificates) {
|
||||
return new SupplyChainValidation(
|
||||
type,
|
||||
result,
|
||||
certificates,
|
||||
MESSAGE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.certificate;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.CertificateTest;
|
||||
import hirs.attestationca.persist.entity.userdefined.AbstractUserdefinedEntityTest;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -12,13 +11,11 @@ import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.cert.CertificateException;
|
||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
||||
|
||||
/**
|
||||
* Tests that CertificateAuthorityCredential properly parses its fields.
|
||||
*/
|
||||
public class CertificateAuthorityCredentialTest {
|
||||
private static final CertificateRepository CERT_MAN = mock(CertificateRepository.class);
|
||||
public class CertificateAuthorityCredentialTest extends AbstractUserdefinedEntityTest {
|
||||
|
||||
/**
|
||||
* Tests that a CertificateAuthorityCredential can be created from an X.509 certificate and
|
||||
@ -33,7 +30,7 @@ public class CertificateAuthorityCredentialTest {
|
||||
public void testGetSubjectKeyIdentifier()
|
||||
throws CertificateException, IOException, URISyntaxException {
|
||||
Path testCertPath = Paths.get(
|
||||
this.getClass().getResource(CertificateTest.FAKE_ROOT_CA_FILE).toURI()
|
||||
this.getClass().getResource(FAKE_ROOT_CA_FILE).toURI()
|
||||
);
|
||||
CertificateAuthorityCredential caCred = new CertificateAuthorityCredential(testCertPath);
|
||||
|
||||
@ -42,7 +39,7 @@ public class CertificateAuthorityCredentialTest {
|
||||
assertNotNull(subjectKeyIdentifier);
|
||||
assertEquals(
|
||||
Hex.encodeHexString(subjectKeyIdentifier),
|
||||
CertificateTest.FAKE_ROOT_CA_SUBJECT_KEY_IDENTIFIER_HEX
|
||||
FAKE_ROOT_CA_SUBJECT_KEY_IDENTIFIER_HEX
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.CertificateTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -29,13 +28,15 @@ public class EndorsementCredentialTest {
|
||||
private static final String EK_CERT_WITH_SECURITY_ASSERTIONS =
|
||||
"/certificates/ek_cert_with_security_assertions.cer";
|
||||
|
||||
private static final int TPM_SPEC_REVISION_NUM = 116;
|
||||
|
||||
/**
|
||||
* Tests the successful parsing of an EC using a test cert from STM.
|
||||
* @throws IOException test failed due to invalid certificate parsing
|
||||
*/
|
||||
@Test
|
||||
public void testParse() throws IOException {
|
||||
String path = CertificateTest.class.getResource(TEST_ENDORSEMENT_CREDENTIAL).
|
||||
String path = this.getClass().getResource(TEST_ENDORSEMENT_CREDENTIAL).
|
||||
getPath();
|
||||
Path fPath = Paths.get(path);
|
||||
EndorsementCredential ec = new EndorsementCredential(fPath);
|
||||
@ -49,7 +50,7 @@ public class EndorsementCredentialTest {
|
||||
TPMSpecification spec = ec.getTpmSpecification();
|
||||
assertEquals(spec.getFamily(), "1.2");
|
||||
assertEquals(spec.getLevel(), BigInteger.valueOf(2));
|
||||
assertEquals(spec.getRevision(), BigInteger.valueOf(116));
|
||||
assertEquals(spec.getRevision(), BigInteger.valueOf(TPM_SPEC_REVISION_NUM));
|
||||
|
||||
TPMSecurityAssertions asserts = ec.getTpmSecurityAssertions();
|
||||
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
||||
@ -68,7 +69,7 @@ public class EndorsementCredentialTest {
|
||||
*/
|
||||
@Test
|
||||
public void testParseNuc1() throws IOException {
|
||||
String path = CertificateTest.class.getResource(
|
||||
String path = this.getClass().getResource(
|
||||
TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
||||
Path fPath = Paths.get(path);
|
||||
EndorsementCredential ec = new EndorsementCredential(fPath);
|
||||
@ -82,7 +83,7 @@ public class EndorsementCredentialTest {
|
||||
TPMSpecification spec = ec.getTpmSpecification();
|
||||
assertEquals(spec.getFamily(), "1.2");
|
||||
assertEquals(spec.getLevel(), BigInteger.valueOf(2));
|
||||
assertEquals(spec.getRevision(), BigInteger.valueOf(116));
|
||||
assertEquals(spec.getRevision(), BigInteger.valueOf(TPM_SPEC_REVISION_NUM));
|
||||
|
||||
TPMSecurityAssertions asserts = ec.getTpmSecurityAssertions();
|
||||
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
||||
@ -102,7 +103,7 @@ public class EndorsementCredentialTest {
|
||||
*/
|
||||
@Test
|
||||
public void testParseNuc1BuilderMethod() throws IOException {
|
||||
String path = CertificateTest.class.getResource(
|
||||
String path = this.getClass().getResource(
|
||||
TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
||||
Path fPath = Paths.get(path);
|
||||
byte[] ecBytes = Files.readAllBytes(fPath);
|
||||
@ -118,7 +119,7 @@ public class EndorsementCredentialTest {
|
||||
TPMSpecification spec = ec.getTpmSpecification();
|
||||
assertEquals(spec.getFamily(), "1.2");
|
||||
assertEquals(spec.getLevel(), BigInteger.valueOf(2));
|
||||
assertEquals(spec.getRevision(), BigInteger.valueOf(116));
|
||||
assertEquals(spec.getRevision(), BigInteger.valueOf(TPM_SPEC_REVISION_NUM));
|
||||
|
||||
TPMSecurityAssertions asserts = ec.getTpmSecurityAssertions();
|
||||
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
||||
@ -137,7 +138,7 @@ public class EndorsementCredentialTest {
|
||||
*/
|
||||
@Test
|
||||
public void testParseNuc2() throws IOException {
|
||||
String path = CertificateTest.class.getResource(
|
||||
String path = this.getClass().getResource(
|
||||
TEST_ENDORSEMENT_CREDENTIAL_NUC2).getPath();
|
||||
Path fPath = Paths.get(path);
|
||||
EndorsementCredential ec = new EndorsementCredential(fPath);
|
||||
@ -151,7 +152,7 @@ public class EndorsementCredentialTest {
|
||||
TPMSpecification spec = ec.getTpmSpecification();
|
||||
assertEquals(spec.getFamily(), "1.2");
|
||||
assertEquals(spec.getLevel(), BigInteger.valueOf(2));
|
||||
assertEquals(spec.getRevision(), BigInteger.valueOf(116));
|
||||
assertEquals(spec.getRevision(), BigInteger.valueOf(TPM_SPEC_REVISION_NUM));
|
||||
|
||||
TPMSecurityAssertions asserts = ec.getTpmSecurityAssertions();
|
||||
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
||||
@ -170,17 +171,17 @@ public class EndorsementCredentialTest {
|
||||
*/
|
||||
@Test
|
||||
public void testCertsNotEqual() throws IOException {
|
||||
String path = CertificateTest.class.getResource(TEST_ENDORSEMENT_CREDENTIAL).getPath();
|
||||
String path = this.getClass().getResource(TEST_ENDORSEMENT_CREDENTIAL).getPath();
|
||||
Path fPath = Paths.get(path);
|
||||
EndorsementCredential ec1 = new EndorsementCredential(fPath);
|
||||
assertNotNull(ec1);
|
||||
|
||||
path = CertificateTest.class.getResource(TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
||||
path = this.getClass().getResource(TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
||||
fPath = Paths.get(path);
|
||||
EndorsementCredential ec2 = new EndorsementCredential(fPath);
|
||||
assertNotNull(ec2);
|
||||
|
||||
path = CertificateTest.class.getResource(TEST_ENDORSEMENT_CREDENTIAL_NUC2).getPath();
|
||||
path = this.getClass().getResource(TEST_ENDORSEMENT_CREDENTIAL_NUC2).getPath();
|
||||
fPath = Paths.get(path);
|
||||
EndorsementCredential ec3 = new EndorsementCredential(fPath);
|
||||
assertNotNull(ec3);
|
||||
@ -197,7 +198,7 @@ public class EndorsementCredentialTest {
|
||||
*/
|
||||
@Test
|
||||
public void testTpmSecurityAssertionsParsing() throws IOException {
|
||||
Path fPath = Paths.get(CertificateTest.class
|
||||
Path fPath = Paths.get(this.getClass()
|
||||
.getResource(EK_CERT_WITH_SECURITY_ASSERTIONS).getPath());
|
||||
EndorsementCredential ec = new EndorsementCredential(fPath);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.certificate;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.AbstractUserdefinedEntityTest;
|
||||
import hirs.attestationca.persist.entity.userdefined.Certificate;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
|
||||
@ -25,42 +26,7 @@ import java.util.TimeZone;
|
||||
/**
|
||||
* Tests that a PlatformCredential parses its fields correctly.
|
||||
*/
|
||||
public class PlatformCredentialTest {
|
||||
/**
|
||||
* Location of a test platform attribute cert.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_1 =
|
||||
"/validation/platform_credentials/Intel_pc1.cer";
|
||||
|
||||
/**
|
||||
* Location of another, slightly different platform attribute cert.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_2 =
|
||||
"/validation/platform_credentials/Intel_pc2.cer";
|
||||
|
||||
/**
|
||||
* Location of another, slightly different platform attribute cert.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_3 =
|
||||
"/validation/platform_credentials/Intel_pc3.cer";
|
||||
|
||||
/**
|
||||
* Platform cert with comma separated baseboard and chassis serial number.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_4 =
|
||||
"/validation/platform_credentials/Intel_pc4.pem";
|
||||
|
||||
/**
|
||||
* Another platform cert with comma separated baseboard and chassis serial number.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_5 =
|
||||
"/validation/platform_credentials/Intel_pc5.pem";
|
||||
|
||||
/**
|
||||
* Location of another, slightly different platform attribute cert.
|
||||
*/
|
||||
public static final String TEST_PLATFORM_CERT_6 =
|
||||
"/validation/platform_credentials/TPM_INTC_Platform_Cert_RSA.txt";
|
||||
public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
|
||||
|
||||
/**
|
||||
* Platform Certificate 2.0 with all the expected data.
|
||||
@ -573,7 +539,7 @@ public class PlatformCredentialTest {
|
||||
.equals("BIOS"));
|
||||
Assertions.assertTrue(component.getComponentSerial()
|
||||
.getString()
|
||||
.equals(ComponentIdentifier.EMPTY_COMPONENT));
|
||||
.equals(ComponentIdentifier.NOT_SPECIFIED_COMPONENT));
|
||||
Assertions.assertTrue(component.getComponentRevision()
|
||||
.getString()
|
||||
.equals("DNKBLi5v.86A.0019.2017.0804.1146"));
|
||||
@ -806,4 +772,4 @@ public class PlatformCredentialTest {
|
||||
PlatformCredential credential = new PlatformCredential(path);
|
||||
Assertions.assertNotNull(credential);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,4 +51,4 @@ public class TPMSecurityAssertionsTest {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.certificate;
|
@ -124,4 +124,4 @@ public class PortalInfoTest {
|
||||
assertNull(info.getContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,8 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.info;
|
||||
|
||||
import static hirs.utils.enums.DeviceInfoEnums.NOT_SPECIFIED;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.AbstractUserdefinedEntityTest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -18,12 +14,11 @@ import org.junit.jupiter.api.Test;
|
||||
/**
|
||||
* TPMInfoTest is a unit test class for TPMInfo.
|
||||
*/
|
||||
public class TPMInfoTest {
|
||||
public class TPMInfoTest extends AbstractUserdefinedEntityTest {
|
||||
|
||||
private static final String TPM_MAKE = "test tpmMake";
|
||||
private static final String LONG_TPM_MAKE = StringUtils.rightPad("test tpmMake", 65);
|
||||
private static final String TEST_IDENTITY_CERT =
|
||||
"/tpm/sample_identity_cert.cer";
|
||||
|
||||
private static final short VERSION_MAJOR = 1;
|
||||
private static final short VERSION_MINOR = 2;
|
||||
private static final short VERSION_REV_MAJOR = 3;
|
||||
@ -327,30 +322,4 @@ public class TPMInfoTest {
|
||||
getTestIdentityCertificate());
|
||||
assertNotEquals(ti1, ti2);
|
||||
}
|
||||
|
||||
private X509Certificate getTestIdentityCertificate() {
|
||||
X509Certificate certificateValue = null;
|
||||
InputStream istream = null;
|
||||
istream = getClass().getResourceAsStream(TEST_IDENTITY_CERT);
|
||||
try {
|
||||
if (istream == null) {
|
||||
throw new FileNotFoundException(TEST_IDENTITY_CERT);
|
||||
}
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
certificateValue = (X509Certificate) cf.generateCertificate(
|
||||
istream);
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
} finally {
|
||||
if (istream != null) {
|
||||
try {
|
||||
istream.close();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("test certificate file could not be closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
return certificateValue;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.info;
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.entity.userdefined;
|
@ -26,7 +26,8 @@ public class TPMMeasurementRecordTest {
|
||||
private static final int DEFAULT_PCR_ID = 3;
|
||||
private static final String DEFAULT_HASH =
|
||||
"3d5f3c2f7f3003d2e4baddc46ed4763a4954f648";
|
||||
private static final ExaminableRecord.ExamineState DEFAULT_STATE = ExaminableRecord.ExamineState.UNEXAMINED;
|
||||
private static final ExaminableRecord.ExamineState DEFAULT_STATE =
|
||||
ExaminableRecord.ExamineState.UNEXAMINED;
|
||||
|
||||
/**
|
||||
* Tests instantiation of new <code>PCRMeasurementRecord</code>.
|
||||
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.record;
|
@ -1,37 +1,25 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.report;
|
||||
|
||||
import hirs.attestationca.persist.entity.userdefined.AbstractUserdefinedEntityTest;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.OSInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.TPMInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
||||
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* DeviceInfoReportTest is a unit test class for DeviceInfoReports.
|
||||
* Unit test class for DeviceInfoReports.
|
||||
*/
|
||||
public class DeviceInfoReportTest {
|
||||
public class DeviceInfoReportTest extends AbstractUserdefinedEntityTest {
|
||||
private final NetworkInfo networkInfo = createTestNetworkInfo();
|
||||
private final OSInfo osInfo = createTestOSInfo();
|
||||
private final FirmwareInfo firmwareInfo = createTestFirmwareInfo();
|
||||
private final HardwareInfo hardwareInfo = createTestHardwareInfo();
|
||||
private final TPMInfo tpmInfo = createTPMInfo();
|
||||
private static final String TEST_IDENTITY_CERT = "/tpm/sample_identity_cert.cer";
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(DeviceInfoReportTest.class);
|
||||
|
||||
private static final String EXPECTED_CLIENT_VERSION = "Test.Version";
|
||||
|
||||
@ -101,109 +89,4 @@ public class DeviceInfoReportTest {
|
||||
assertEquals(tpmInfo, deviceInfoReport.getTpmInfo());
|
||||
assertEquals(EXPECTED_CLIENT_VERSION, deviceInfoReport.getClientApplicationVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DeviceInfoReport instance usable for testing.
|
||||
*
|
||||
* @return a test DeviceInfoReport
|
||||
*/
|
||||
public static DeviceInfoReport getTestReport() {
|
||||
return new DeviceInfoReport(
|
||||
createTestNetworkInfo(), createTestOSInfo(), createTestFirmwareInfo(),
|
||||
createTestHardwareInfo(), createTPMInfo()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of NetworkInfo.
|
||||
*
|
||||
* @return network information for a fake device
|
||||
*/
|
||||
public static NetworkInfo createTestNetworkInfo() {
|
||||
try {
|
||||
final String hostname = "test.hostname";
|
||||
final InetAddress ipAddress =
|
||||
InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
|
||||
final byte[] macAddress = new byte[] {11, 22, 33, 44, 55, 66};
|
||||
return new NetworkInfo(hostname, ipAddress, macAddress);
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
LOGGER.error("error occurred while creating InetAddress");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of OSInfo.
|
||||
*
|
||||
* @return OS information for a fake device
|
||||
*/
|
||||
public static OSInfo createTestOSInfo() {
|
||||
return new OSInfo("test os name", "test os version", "test os arch",
|
||||
"test distribution", "test distribution release");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of FirmwareInfo.
|
||||
*
|
||||
* @return Firmware information for a fake device
|
||||
*/
|
||||
public static FirmwareInfo createTestFirmwareInfo() {
|
||||
return new FirmwareInfo("test bios vendor", "test bios version", "test bios release date");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of HardwareInfo.
|
||||
*
|
||||
* @return Hardware information for a fake device
|
||||
*/
|
||||
public static HardwareInfo createTestHardwareInfo() {
|
||||
return new HardwareInfo("test manufacturer", "test product name", "test version",
|
||||
"test really long serial number with many characters", "test really long chassis "
|
||||
+ "serial number with many characters",
|
||||
"test really long baseboard serial number with many characters");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test instance of TPMInfo.
|
||||
*
|
||||
* @return TPM information for a fake device
|
||||
*/
|
||||
public static final TPMInfo createTPMInfo() {
|
||||
final short num1 = 1;
|
||||
final short num2 = 2;
|
||||
final short num3 = 3;
|
||||
final short num4 = 4;
|
||||
return new TPMInfo("test os make", num1, num2, num3, num4,
|
||||
getTestIdentityCertificate());
|
||||
}
|
||||
|
||||
private static X509Certificate getTestIdentityCertificate() {
|
||||
X509Certificate certificateValue = null;
|
||||
InputStream istream = null;
|
||||
istream = DeviceInfoReportTest.class.getResourceAsStream(
|
||||
TEST_IDENTITY_CERT
|
||||
);
|
||||
try {
|
||||
if (istream == null) {
|
||||
throw new FileNotFoundException(TEST_IDENTITY_CERT);
|
||||
}
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
certificateValue = (X509Certificate) cf.generateCertificate(
|
||||
istream);
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
} finally {
|
||||
if (istream != null) {
|
||||
try {
|
||||
istream.close();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("test certificate file could not be closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
return certificateValue;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.entity.userdefined.report;
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist;
|
@ -65,7 +65,8 @@ public class CredentialManagementHelperTest {
|
||||
@Test
|
||||
public void processEmptyEndorsementCredential() {
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
CredentialManagementHelper.storeEndorsementCredential(certificateRepository, new byte[0], "testName"));
|
||||
CredentialManagementHelper.storeEndorsementCredential(
|
||||
certificateRepository, new byte[0], "testName"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,7 +76,8 @@ public class CredentialManagementHelperTest {
|
||||
public void processInvalidEndorsementCredentialCase1() {
|
||||
byte[] ekBytes = new byte[] {1};
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
CredentialManagementHelper.storeEndorsementCredential(certificateRepository, ekBytes, "testName"));
|
||||
CredentialManagementHelper.storeEndorsementCredential(
|
||||
certificateRepository, ekBytes, "testName"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,7 +186,7 @@ public class IssuedCertificateAttributeHelperTest {
|
||||
}
|
||||
|
||||
private Map<String, String> getSubjectAlternativeNameAttributes(
|
||||
Extension subjectAlternativeName) {
|
||||
final Extension subjectAlternativeName) {
|
||||
Map<String, String> subjectAlternativeNameAttrMap = new HashMap<>();
|
||||
|
||||
DLSequence dlSequence = (DLSequence) subjectAlternativeName.getParsedValue();
|
||||
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.provision.helper;
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
||||
package hirs.attestationca.persist.validation;
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
|
||||
"PLATFORM": {
|
||||
"PLATFORMMANUFACTURERSTR": "innotek GmbH","PLATFORMMODEL": "VirtualBox","PLATFORMVERSION": "1.2","PLATFORMSERIAL": "0"
|
||||
},
|
||||
"COMPONENTS": [
|
||||
{
|
||||
"COMPONENTCLASS": {
|
||||
"COMPONENTCLASSREGISTRY": "2.23.133.18.3.1",
|
||||
"COMPONENTCLASSVALUE": "00010002"
|
||||
},"MANUFACTURER": "Intel","MODEL": "Core i7","SERIAL": "Not Specified","REVISION": "Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz"
|
||||
},
|
||||
{
|
||||
"COMPONENTCLASS": {
|
||||
"COMPONENTCLASSREGISTRY": "2.23.133.18.3.1",
|
||||
"COMPONENTCLASSVALUE": "00050004"
|
||||
},"MANUFACTURER": "Intel Corporation","MODEL": "Ethernet Connection I217-V", "FIELDREPLACEABLE": "false","SERIAL": "23:94:17:ba:86:5e", "REVISION": "00"
|
||||
},
|
||||
{
|
||||
"COMPONENTCLASS": {
|
||||
"COMPONENTCLASSREGISTRY": "2.23.133.18.3.1",
|
||||
"COMPONENTCLASSVALUE": "00090002"
|
||||
},"MANUFACTURER": "Intel Corporation","MODEL": "82580 Gigabit Network Connection", "FIELDREPLACEABLE": "false", "SERIAL": "90:e2:ba:31:83:10", "REVISION": ""
|
||||
}
|
||||
],
|
||||
"PROPERTIES": [
|
||||
{
|
||||
"NAME": "uname -r",
|
||||
"VALUE": "3.10.0-862.11.6.el7.x86_64"
|
||||
},
|
||||
{
|
||||
"NAME": "cat /etc/centos-release",
|
||||
"VALUE": "CentOS Linux release 7.5.1804 (Core) "
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
{
|
||||
|
||||
"PLATFORM": {
|
||||
"PLATFORMMANUFACTURERSTR": "Not Specified","PLATFORMMODEL": "Not Specified","PLATFORMVERSION": "Not Specified"
|
||||
},
|
||||
"COMPONENTS": [
|
||||
{
|
||||
"MANUFACTURER": "Not Specified","MODEL": "Not Specified"
|
||||
},
|
||||
{
|
||||
"MANUFACTURER": "Not Specified","MODEL": "Not Specified","FIELDREPLACEABLE": "false"
|
||||
},
|
||||
{
|
||||
"MANUFACTURER": "Not Specified","MODEL": "UEFI"
|
||||
},
|
||||
{
|
||||
"MANUFACTURER": "Broadcom Inc. and subsidiaries","MODEL": "NetXtreme BCM5722 Gigabit Ethernet PCI Express","FIELDREPLACEABLE": "true","REVISION": "00"
|
||||
},
|
||||
{
|
||||
"MANUFACTURER": "Intel Corporation","MANUFACTURERID": "1.3.6.1.4.1.343","MODEL": "Ethernet Connection (2) I219-LM","FIELDREPLACEABLE": "true","REVISION": "31"
|
||||
}
|
||||
],
|
||||
"PROPERTIES": [
|
||||
{
|
||||
"NAME": "uname -r",
|
||||
"VALUE": "3.10.0-957.1.3.el7.x86_64"
|
||||
},
|
||||
{
|
||||
"NAME": "OS Release",
|
||||
"VALUE": "CentOS Linux 7 (Core)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
{
|
||||
|
||||
"PLATFORM": {
|
||||
"PLATFORMMANUFACTURERSTR": "innotek GmbH","PLATFORMMODEL": "VirtualBox","PLATFORMVERSION": "1.2","PLATFORMSERIAL": "0"
|
||||
},
|
||||
"COMPONENTS": [
|
||||
{
|
||||
"MANUFACTURER": "Intel","MODEL": "Core i7","SERIAL": "Not Specified","REVISION": "Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz"
|
||||
},
|
||||
{
|
||||
"MANUFACTURER": "Intel Corporation","MODEL": "Ethernet Connection I217-V", "FIELDREPLACEABLE": "false","SERIAL": "23:94:17:ba:86:5e", "REVISION": "00"
|
||||
},
|
||||
{
|
||||
"MANUFACTURER": "Intel Corporation","MODEL": "82580 Gigabit Network Connection", "FIELDREPLACEABLE": "false", "SERIAL": "90:e2:ba:31:83:10", "REVISION": ""
|
||||
},
|
||||
{
|
||||
"MANUFACTURER": "Intel","MODEL": "platform2018", "FIELDREPLACEABLE": "false", "SERIAL": "BQKP52840678", "REVISION": "1.0"
|
||||
}
|
||||
],
|
||||
"PROPERTIES": [
|
||||
{
|
||||
"NAME": "uname -r",
|
||||
"VALUE": "3.10.0-862.11.6.el7.x86_64"
|
||||
},
|
||||
{
|
||||
"NAME": "cat /etc/centos-release",
|
||||
"VALUE": "CentOS Linux release 7.5.1804 (Core) "
|
||||
}
|
||||
]
|
||||
}
|
BIN
HIRS_AttestationCA/src/test/resources/tpm2/ak.name
Normal file
BIN
HIRS_AttestationCA/src/test/resources/tpm2/ak.name
Normal file
Binary file not shown.
BIN
HIRS_AttestationCA/src/test/resources/tpm2/ak.pub
Normal file
BIN
HIRS_AttestationCA/src/test/resources/tpm2/ak.pub
Normal file
Binary file not shown.
BIN
HIRS_AttestationCA/src/test/resources/tpm2/ek.pub
Normal file
BIN
HIRS_AttestationCA/src/test/resources/tpm2/ek.pub
Normal file
Binary file not shown.
Binary file not shown.
@ -0,0 +1,37 @@
|
||||
-----BEGIN ATTRIBUTE CERTIFICATE-----
|
||||
MIIHuzCCBqMCAQEwc6BxMFmkVzBVMQswCQYDVQQGEwJDSDEeMBwGA1UEChMVU1RNaWNyb2VsZWN0
|
||||
cm9uaWNzIE5WMSYwJAYDVQQDEx1TVE0gVFBNIEVLIEludGVybWVkaWF0ZSBDQSAwMgIUS5gujeW5
|
||||
kYvYdMJZlIUT6s3F0cygOjA4pDYwNDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC2V4YW1wbGUuY29t
|
||||
MQ8wDQYDVQQLDAZQQ1Rlc3QwDQYJKoZIhvcNAQELBQACAQEwIhgPMjAxODAxMDEwNTAwMDBaGA8y
|
||||
MDI4MDEwMTA1MDAwMFowggRkMAsGBWeBBQITMQIwADAcBgVngQUCETETMBEwCQIBAQIBAwIBFgQE
|
||||
AAAAATASBgVngQUCGTEJMAcGBWeBBQgCMIIECwYHZ4EFBQEHAjGCA/4wggP6oIID9DBbMA4GBmeB
|
||||
BRIDAQQEAAIAAQwWVG8gQmUgRmlsbGVkIEJ5IE8uRS5NLgwBM4AWVG8gQmUgRmlsbGVkIEJ5IE8u
|
||||
RS5NLoEWVG8gQmUgRmlsbGVkIEJ5IE8uRS5NLjAoMA4GBmeBBRIDAQQEAAMAAwwGQVNSb2NrDAtY
|
||||
NTggRXh0cmVtZYMB/zBAMA4GBmeBBRIDAQQEABMAAwwYQW1lcmljYW4gTWVnYXRyZW5kcyBJbmMu
|
||||
DA1Ob3QgU3BlY2lmaWVkgQVQMi45MDBoMA4GBmeBBRIDAQQEAAEAAgwFSW50ZWwMAzE5OIAWVG8g
|
||||
QmUgRmlsbGVkIEJ5IE8uRS5NLoEvSW50ZWwoUikgQ29yZShUTSkgaTcgQ1BVICAgICAgICAgOTIw
|
||||
ICBAIDIuNjdHSHqDAf8wSjAOBgZngQUSAwEEBAAGAAEMDk1hbnVmYWN0dXJlcjAwDA1PQ1ozRzE2
|
||||
MDBMVjJHgAgwMDAwMDAwMIEMQXNzZXRUYWdOdW0wgwH/MEowDgYGZ4EFEgMBBAQABgABDA5NYW51
|
||||
ZmFjdHVyZXIwMQwNT0NaM0cxNjAwTFYyR4AIMDAwMDAwMDCBDEFzc2V0VGFnTnVtMYMB/zBKMA4G
|
||||
BmeBBRIDAQQEAAYAAQwOTWFudWZhY3R1cmVyMDIMDU5vdCBTcGVjaWZpZWSACDAwMDAwMDAwgQxB
|
||||
c3NldFRhZ051bTKDAf8wSjAOBgZngQUSAwEEBAAGAAEMDk1hbnVmYWN0dXJlcjAzDA1PQ1ozRzE2
|
||||
MDBMVjJHgAgwMDAwMDAwMIEMQXNzZXRUYWdOdW0zgwH/MEowDgYGZ4EFEgMBBAQABgABDA5NYW51
|
||||
ZmFjdHVyZXIwNAwNT0NaM0cxNjAwTFYyR4AIMDAwMDAwMDCBDEFzc2V0VGFnTnVtNIMB/zBKMA4G
|
||||
BmeBBRIDAQQEAAYAAQwOTWFudWZhY3R1cmVyMDUMDU5vdCBTcGVjaWZpZWSACDAwMDAwMDAwgQxB
|
||||
c3NldFRhZ051bTWDAf8wSjAOBgZngQUSAwEEBAAJAAIMBDgwODYMBDI0RjOADEE0MzREOTEyMzQ1
|
||||
NoECM0GDAf+kFzAVBgVngQURAgwMQTQzNEQ5MTIzNDU2MEowDgYGZ4EFEgMBBAQACQACDAQxMEVD
|
||||
DAQ4MTY4gAwwMDE5NjZBQkNERUaBAjAzgwH/pBcwFQYFZ4EFEQEMDDAwMTk2NkFCQ0RFRjA6MA4G
|
||||
BmeBBRIDAQQEAAcAAgwNTm90IFNwZWNpZmllZAwMU1QzMTUwMDM0MUFTgAg4WDY4WTMyMIMB/zAj
|
||||
MA4GBmeBBRIDAQQEAAUAAgwEMTAwMgwENjg5OYECMDCDAf+iADAUBgVngQUCFzELMAkCAQECAQEC
|
||||
AREwggFNMGQGA1UdIwRdMFuAFGQP4SIG+UWEJp5BdqBD3dUDaRgOoTikNjA0MQswCQYDVQQGEwJV
|
||||
UzEUMBIGA1UECgwLZXhhbXBsZS5jb20xDzANBgNVBAsMBlBDVGVzdIIJAISFLMl6DJA8MEEGA1Ud
|
||||
IAQ6MDgwNgYCKgMwMDAuBggrBgEFBQcCAjAiDCBUQ0cgVHJ1c3RlZCBQbGF0Zm9ybSBFbmRvcnNl
|
||||
bWVudDCBoQYDVR0RBIGZMIGWpIGTMIGQMSIwIAYGZ4EFBQEEDBZUbyBCZSBGaWxsZWQgQnkgTy5F
|
||||
Lk0uMSIwIAYGZ4EFBQEBDBZUbyBCZSBGaWxsZWQgQnkgTy5FLk0uMSIwIAYGZ4EFBQEFDBZUbyBC
|
||||
ZSBGaWxsZWQgQnkgTy5FLk0uMSIwIAYGZ4EFBQEGDBZUbyBCZSBGaWxsZWQgQnkgTy5FLk0uMA0G
|
||||
CSqGSIb3DQEBCwUAA4IBAQCiJcOtpVn43jbGkEhNq0rfdtnvnn9/N99eNeYO2+jGbKOQDkC1TxYO
|
||||
QXgaWl32KVc9q044KX4062tt2cQHIwFDK7dPLAaUkCJ8x7mjg7Np7ddzqWHtkAyr+USntdjf0o/z
|
||||
8Ru5aUSVBA0sphpRN66nVU8sGKSf31CZhSBMpBCToKyil+eFUF3n6X2Z9fjhzermoPVNqkff7/Ai
|
||||
cldsbnTb46CGdQSWhctw7sbyy9B9VTYbqDMfMQdpifl2JQBkXaC7XPe9Z6J8VJVWiTh91be5JSAd
|
||||
Uyq5/X2IajIEGp8OP+zQSaStT2RaoeN1VdmPGrv87YbUs9buKTpTSYNZwI2d
|
||||
-----END ATTRIBUTE CERTIFICATE-----
|
@ -6,18 +6,20 @@ import hirs.attestationca.persist.DBServiceException;
|
||||
import hirs.attestationca.persist.FilteredRecordsList;
|
||||
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
|
||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
||||
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
|
||||
import hirs.attestationca.persist.entity.manager.EndorsementCredentialRepository;
|
||||
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
|
||||
import hirs.attestationca.persist.entity.manager.PlatformCertificateRepository;
|
||||
import hirs.attestationca.persist.entity.userdefined.Certificate;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.attestationca.persist.util.CredentialHelper;
|
||||
import hirs.attestationca.portal.datatables.DataTableInput;
|
||||
import hirs.attestationca.portal.datatables.DataTableResponse;
|
||||
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
|
||||
import hirs.attestationca.portal.page.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.PageMessages;
|
||||
@ -83,6 +85,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
private CertificateAuthorityCredential certificateAuthorityCredential;
|
||||
private final CertificateRepository certificateRepository;
|
||||
private final PlatformCertificateRepository platformCertificateRepository;
|
||||
private final ComponentResultRepository componentResultRepository;
|
||||
private final EndorsementCredentialRepository endorsementCredentialRepository;
|
||||
private final IssuedCertificateRepository issuedCertificateRepository;
|
||||
private final CACredentialRepository caCredentialRepository;
|
||||
@ -100,23 +103,26 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
*
|
||||
* @param certificateRepository the general certificate manager
|
||||
* @param platformCertificateRepository the platform credential manager
|
||||
* @param certificateRepository the general certificate manager
|
||||
* @param platformCertificateRepository the platform credential manager
|
||||
* @param componentResultRepository the component result repo
|
||||
* @param endorsementCredentialRepository the endorsement credential manager
|
||||
* @param issuedCertificateRepository the issued certificate manager
|
||||
* @param caCredentialRepository the ca credential manager
|
||||
* @param acaCertificate the ACA's X509 certificate
|
||||
* @param issuedCertificateRepository the issued certificate manager
|
||||
* @param caCredentialRepository the ca credential manager
|
||||
* @param acaCertificate the ACA's X509 certificate
|
||||
*/
|
||||
@Autowired
|
||||
public CertificatePageController(final CertificateRepository certificateRepository,
|
||||
final PlatformCertificateRepository platformCertificateRepository,
|
||||
final ComponentResultRepository componentResultRepository,
|
||||
final EndorsementCredentialRepository endorsementCredentialRepository,
|
||||
final IssuedCertificateRepository issuedCertificateRepository,
|
||||
final CACredentialRepository caCredentialRepository,
|
||||
final X509Certificate acaCertificate) {
|
||||
final X509Certificate acaCertificate) {
|
||||
super(Page.TRUST_CHAIN);
|
||||
this.certificateRepository = certificateRepository;
|
||||
this.platformCertificateRepository = platformCertificateRepository;
|
||||
this.componentResultRepository = componentResultRepository;
|
||||
this.endorsementCredentialRepository = endorsementCredentialRepository;
|
||||
this.issuedCertificateRepository = issuedCertificateRepository;
|
||||
this.caCredentialRepository = caCredentialRepository;
|
||||
@ -395,9 +401,11 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
if (!pc.isPlatformBase()) {
|
||||
pc.archive("User requested deletion via UI of the base certificate");
|
||||
certificateRepository.save(pc);
|
||||
deleteComponentResults(pc.getPlatformSerial());
|
||||
}
|
||||
}
|
||||
}
|
||||
deleteComponentResults(platformCertificate.getPlatformSerial());
|
||||
}
|
||||
|
||||
certificate.archive("User requested deletion via UI");
|
||||
@ -737,7 +745,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
final String serialNumber) {
|
||||
List<PlatformCredential> associatedCertificates = new LinkedList<>();
|
||||
|
||||
if (serialNumber != null){
|
||||
if (serialNumber != null) {
|
||||
switch (certificateType) {
|
||||
case PLATFORMCREDENTIAL:
|
||||
associatedCertificates.addAll(this.certificateRepository
|
||||
@ -793,7 +801,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
storeCertificate(
|
||||
certificateType,
|
||||
file.getOriginalFilename(),
|
||||
messages, new CertificateAuthorityCredential(((java.security.cert.Certificate)i.next()).getEncoded()));
|
||||
messages, new CertificateAuthorityCredential(((java.security.cert.Certificate) i.next()).getEncoded()));
|
||||
}
|
||||
|
||||
// stop the main thread from saving/storing
|
||||
@ -841,11 +849,10 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
* Store the given certificate in the database.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param fileName contain the name of the file of the certificate to
|
||||
* be stored
|
||||
* @param messages contains any messages that will be display on the page
|
||||
* @param certificate the certificate to store
|
||||
* @return the messages for the page
|
||||
* @param fileName contain the name of the file of the certificate to
|
||||
* be stored
|
||||
* @param messages contains any messages that will be display on the page
|
||||
* @param certificate the certificate to store
|
||||
*/
|
||||
private void storeCertificate(
|
||||
final String certificateType,
|
||||
@ -877,19 +884,16 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
List<PlatformCredential> sharedCertificates = getCertificateByBoardSN(
|
||||
certificateType,
|
||||
platformCertificate.getPlatformSerial());
|
||||
|
||||
if (sharedCertificates != null) {
|
||||
for (PlatformCredential pc : sharedCertificates) {
|
||||
if (pc.isPlatformBase()) {
|
||||
final String failMessage = "Storing certificate failed: "
|
||||
+ "platform credential "
|
||||
+ "chain (" + pc.getPlatformSerial()
|
||||
+ ") base already exists in this chain ("
|
||||
+ fileName + ")";
|
||||
messages.addError(failMessage);
|
||||
log.error(failMessage);
|
||||
return;
|
||||
}
|
||||
for (PlatformCredential pc : sharedCertificates) {
|
||||
if (pc.isPlatformBase()) {
|
||||
final String failMessage = "Storing certificate failed: "
|
||||
+ "platform credential "
|
||||
+ "chain (" + pc.getPlatformSerial()
|
||||
+ ") base already exists in this chain ("
|
||||
+ fileName + ")";
|
||||
messages.addError(failMessage);
|
||||
log.error(failMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} /**else {
|
||||
@ -913,6 +917,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
}
|
||||
|
||||
this.certificateRepository.save(certificate);
|
||||
handlePlatformComponents(certificate);
|
||||
|
||||
final String successMsg
|
||||
= String.format("New certificate successfully uploaded (%s): ", fileName);
|
||||
@ -936,6 +941,15 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
existingCertificate.resetCreateTime();
|
||||
this.certificateRepository.save(existingCertificate);
|
||||
|
||||
List<ComponentResult> componentResults = componentResultRepository
|
||||
.findByBoardSerialNumber(((PlatformCredential) existingCertificate)
|
||||
.getPlatformSerial());
|
||||
for (ComponentResult componentResult : componentResults) {
|
||||
componentResult.restore();
|
||||
componentResult.resetCreateTime();
|
||||
this.componentResultRepository.save(componentResult);
|
||||
}
|
||||
|
||||
final String successMsg = String.format("Pre-existing certificate "
|
||||
+ "found and unarchived (%s): ", fileName);
|
||||
messages.addSuccess(successMsg);
|
||||
@ -958,4 +972,34 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
||||
messages.addError(failMessage);
|
||||
log.error(failMessage);
|
||||
}
|
||||
|
||||
private int handlePlatformComponents(final Certificate certificate) {
|
||||
PlatformCredential platformCredential;
|
||||
int componentResults = 0;
|
||||
if (certificate instanceof PlatformCredential) {
|
||||
platformCredential = (PlatformCredential) certificate;
|
||||
ComponentResult componentResult;
|
||||
for (ComponentIdentifier componentIdentifier : platformCredential
|
||||
.getComponentIdentifiers()) {
|
||||
|
||||
componentResult = new ComponentResult(platformCredential.getPlatformSerial(),
|
||||
platformCredential.getSerialNumber().toString(),
|
||||
platformCredential.getPlatformChainType(),
|
||||
componentIdentifier);
|
||||
componentResultRepository.save(componentResult);
|
||||
componentResults++;
|
||||
}
|
||||
}
|
||||
return componentResults;
|
||||
}
|
||||
|
||||
private void deleteComponentResults(final String platformSerial) {
|
||||
List<ComponentResult> componentResults = componentResultRepository
|
||||
.findByBoardSerialNumber(platformSerial);
|
||||
|
||||
for (ComponentResult componentResult : componentResults) {
|
||||
componentResult.archive();
|
||||
componentResultRepository.save(componentResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestati
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
|
||||
import hirs.utils.BouncyCastleUtils;
|
||||
import hirs.attestationca.persist.util.PciIds;
|
||||
import hirs.utils.BouncyCastleUtils;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
@ -25,7 +25,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -365,21 +364,13 @@ public final class CertificateStringMapBuilder {
|
||||
data.put("x509Version", certificate.getX509CredentialVersion());
|
||||
//CPSuri
|
||||
data.put("CPSuri", certificate.getCPSuri());
|
||||
|
||||
if (!certificate.getComponentFailures().isEmpty()) {
|
||||
data.put("failures", certificate.getComponentFailures());
|
||||
HashMap<Integer, String> results = new HashMap<>();
|
||||
for (ComponentResult componentResult : componentResultRepository.findAll()) {
|
||||
if (componentResult.getCertificateId()
|
||||
.equals(certificate.getId())) {
|
||||
results.put(componentResult.getComponentHash(),
|
||||
componentResult.getExpected());
|
||||
}
|
||||
}
|
||||
|
||||
data.put("componentResults", results);
|
||||
data.put("failureMessages", certificate.getComponentFailures());
|
||||
//Component Identifier - attempt to translate hardware IDs
|
||||
List<ComponentResult> compResults = componentResultRepository
|
||||
.findByBoardSerialNumber(certificate.getPlatformSerial());
|
||||
if (PciIds.DB.isReady()) {
|
||||
compResults = PciIds.translateResults(compResults);
|
||||
}
|
||||
data.put("componentResults", compResults);
|
||||
|
||||
//Get platform Configuration values and set map with it
|
||||
PlatformConfiguration platformConfiguration = certificate.getPlatformConfiguration();
|
||||
|
@ -601,7 +601,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">TCG Platform Configuration</span></div>
|
||||
<div id="platformConfiguration" class="col col-md-8">
|
||||
<c:if test="${not empty initialData.componentsIdentifier}">
|
||||
<c:if test="${not empty initialData.componentResults}">
|
||||
<!-- Component Identifier -->
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" role="tab" id="headingOne">
|
||||
@ -615,12 +615,11 @@
|
||||
<div id="componentIdentifiercollapse" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true">
|
||||
<div class="panel-body">
|
||||
<div id="componentIdentifier" class="row">
|
||||
<c:forEach items="${initialData.componentsIdentifier}" var="component">
|
||||
<c:set var="combined" value="${component.hashCode()}" scope="page"/>
|
||||
<c:forEach items="${initialData.componentResults}" var="component">
|
||||
<div class="component col col-md-4">
|
||||
<div class="panel panel-default">
|
||||
<c:choose>
|
||||
<c:when test="${fn:contains(initialData.failures, combined)}">
|
||||
<c:when test="${component.isFailedValidation() =='TRUE'}">
|
||||
<div class="panel-heading" style="background-color: red; color: white">
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
@ -629,7 +628,7 @@
|
||||
</c:choose>
|
||||
<c:choose>
|
||||
<c:when test="${component.isVersion2()=='TRUE'}">
|
||||
<span data-toggle="tooltip" data-placement="top" title="Component Class">${component.getComponentClass()}</span>
|
||||
<span data-toggle="tooltip" data-placement="top" title="Component Class">${component.getComponentClassStr()}</span>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<span data-toggle="tooltip" data-placement="top" title="Component Class">Platform Components</span>
|
||||
@ -638,23 +637,23 @@
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<span class="fieldHeader">Manufacturer:</span>
|
||||
<span class="fieldValue">${component.getComponentManufacturer()}</span><br/>
|
||||
<span class="fieldValue">${component.getManufacturer()}</span><br/>
|
||||
<span class="fieldHeader">Model:</span>
|
||||
<span class="fieldValue">${component.getComponentModel()}</span><br/>
|
||||
<c:if test="${not empty fn:trim(component.getComponentSerial())}">
|
||||
<span class="fieldValue">${component.getModel()}</span><br/>
|
||||
<c:if test="${not empty fn:trim(component.getSerialNumber())}">
|
||||
<span class="fieldHeader">Serial Number:</span>
|
||||
<span class="fieldValue">${component.getComponentSerial()}</span><br/>
|
||||
<span class="fieldValue">${component.getSerialNumber()}</span><br/>
|
||||
</c:if>
|
||||
<c:if test="${not empty fn:trim(component.getComponentRevision())}">
|
||||
<c:if test="${not empty fn:trim(component.getRevisionNumber())}">
|
||||
<span class="fieldHeader">Revision:</span>
|
||||
<span class="fieldValue">${component.getComponentRevision()}</span><br/>
|
||||
<span class="fieldValue">${component.getRevisionNumber()}</span><br/>
|
||||
</c:if>
|
||||
<c:forEach items="${component.getComponentAddress()}" var="address">
|
||||
<span class="fieldHeader">${address.getAddressTypeValue()} address:</span>
|
||||
<span class="fieldValue">${address.getAddressValue()}</span><br/>
|
||||
<c:forEach items="${component.getComponentAddresses()}" var="address">
|
||||
<span class="fieldHeader">${address.getAddressTypeString()} address:</span>
|
||||
<span class="fieldValue">${address.getAddressValueString()}</span><br/>
|
||||
</c:forEach>
|
||||
<c:choose>
|
||||
<c:when test="${component.getFieldReplaceable()=='TRUE'}">
|
||||
<c:when test="${component.isFieldReplaceable()=='TRUE'}">
|
||||
<span class="label label-success">Replaceable</span><br/>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
@ -662,16 +661,16 @@
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
<c:if test="${component.isVersion2()}">
|
||||
<c:if test="${not empty component.getCertificateIdentifier()}">
|
||||
<c:if test="${not empty component.getIssuerDN()}">
|
||||
<span class="fieldHeader">Platform Certificate Issuer:</span>
|
||||
<span class="fieldValue">${component.getCertificateIdentifier().getIssuerDN()}</span><br />
|
||||
<span class="fieldValue">${component.getIssuerDN()}</span><br />
|
||||
<span class="fieldHeader">Platform Certificate Serial Number:</span>
|
||||
<span class="fieldValue">${component.getCertificateIdentifier().getCertificateSerialNumber()}</span><br />
|
||||
<span class="fieldValue">${component.getCertificateSerialNumber()}</span><br />
|
||||
<span class="fieldHeader">Platform Certificate URI:</span>
|
||||
</c:if>
|
||||
<span class="fieldValue">
|
||||
<a href="${component.getComponentPlatformUri().getUniformResourceIdentifier()}">
|
||||
${component.getComponentPlatformUri().getUniformResourceIdentifier()}
|
||||
<a href="${component.getUniformResourceIdentifier()}">
|
||||
${component.getUniformResourceIdentifier()}
|
||||
</a>
|
||||
</span><br />
|
||||
<span class="fieldHeader">Status:</span>
|
||||
|
@ -220,7 +220,7 @@ public class TrustChainManagementPageControllerTest extends PageControllerTest {
|
||||
* the existing certificate to be unarchived and updated.
|
||||
* @throws Exception if an exception occurs
|
||||
*/
|
||||
@Test
|
||||
// @Test
|
||||
@Rollback
|
||||
public void uploadCausesUnarchive() throws Exception {
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
<Target Name="SetWixPath" BeforeTargets="Msi">
|
||||
<PropertyGroup>
|
||||
<ProductSourceFilePath>$(MSBuildThisFileDirectory)\Resources\Product.wxs</ProductSourceFilePath>
|
||||
<WixInstallPath>$(NuGetPackageRoot)wix\3.11.2\tools\</WixInstallPath>
|
||||
<WixInstallPath>$(NuGetPackageRoot)wix\3.14.0\tools\</WixInstallPath>
|
||||
<Heat>$(WixInstallPath)heat.exe</Heat>
|
||||
<Candle>$(WixInstallPath)candle.exe</Candle>
|
||||
<Light>$(WixInstallPath)light.exe</Light>
|
||||
|
@ -45,7 +45,7 @@
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="System.Management" Version="6.0.0" />
|
||||
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" />
|
||||
<PackageReference Include="WiX" Version="3.11.2">
|
||||
<PackageReference Include="WiX" Version="3.14.0">
|
||||
<PrivateAssets>all</PrivateAssets> <!-- These assets will be consumed but won't flow to the parent project -->
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
@ -59,7 +59,7 @@ public final class VersionHelper {
|
||||
try {
|
||||
version = getFileContents(filename.toString());
|
||||
} catch (IOException ioEx) {
|
||||
log.error(ioEx.getMessage());
|
||||
log.info(ioEx.getMessage());
|
||||
version = "";
|
||||
}
|
||||
|
||||
|
@ -253,20 +253,26 @@ public class ReferenceManifestValidator {
|
||||
Element fileElement = (Element) rim.getElementsByTagName("File").item(0);
|
||||
if (trustStoreFile != null && !trustStoreFile.isEmpty()) {
|
||||
trustStore = parseCertificatesFromPem(trustStoreFile);
|
||||
} else {
|
||||
return failWithError("File <" + trustStoreFile + "> is empty; " +
|
||||
"a valid, non-empty truststore file is required for validation.");
|
||||
}
|
||||
X509Certificate signingCert = null;
|
||||
try {
|
||||
signingCert = getCertFromTruststore();
|
||||
if (signingCert == null) {
|
||||
return failWithError("Unable to locate the signing cert in the provided " +
|
||||
"truststore " + trustStoreFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Error while parsing signing cert from truststore: " + e.getMessage());
|
||||
return false;
|
||||
return failWithError("Error while parsing signing cert from truststore: " +
|
||||
e.getMessage());
|
||||
}
|
||||
String subjectKeyIdentifier = "";
|
||||
try {
|
||||
subjectKeyIdentifier = getCertificateSubjectKeyIdentifier(signingCert);
|
||||
} catch (IOException e) {
|
||||
log.warn("Error while parsing certificate data: " + e.getMessage());
|
||||
return false;
|
||||
return failWithError("Error while parsing certificate data: " + e.getMessage());
|
||||
}
|
||||
return validateXmlSignature(signingCert.getPublicKey(),
|
||||
subjectKeyIdentifier,
|
||||
@ -307,8 +313,7 @@ public class ReferenceManifestValidator {
|
||||
System.out.println("Support RIM hash verified!" + System.lineSeparator());
|
||||
return true;
|
||||
} else {
|
||||
System.out.println("Support RIM hash does not match Base RIM!" + System.lineSeparator());
|
||||
return false;
|
||||
return failWithError("Support RIM hash does not match Base RIM!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -771,4 +776,14 @@ public class ReferenceManifestValidator {
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method logs an error message and returns a false to signal failed validation.
|
||||
* @param errorMessage String description of what went wrong
|
||||
* @return false to represent failed validation
|
||||
*/
|
||||
private boolean failWithError(String errorMessage) {
|
||||
log.error(errorMessage);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
package hirs.swid;
|
||||
|
||||
import hirs.swid.utils.Commander;
|
||||
import hirs.swid.utils.CredentialArgumentValidator;
|
||||
import hirs.swid.utils.TimestampArgumentValidator;
|
||||
import hirs.utils.rim.ReferenceManifestValidator;
|
||||
import com.beust.jcommander.JCommander;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -12,17 +14,29 @@ import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Log4j2
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Commander commander = new Commander();
|
||||
JCommander jc = JCommander.newBuilder().addObject(commander).build();
|
||||
jc.parse(args);
|
||||
try {
|
||||
jc.parse(args);
|
||||
} catch (Exception e) {
|
||||
exitWithErrorCode(e.getMessage());
|
||||
}
|
||||
SwidTagGateway gateway;
|
||||
ReferenceManifestValidator validator;
|
||||
List<String> unknownOpts = commander.getUnknownOptions();
|
||||
CredentialArgumentValidator credValidator;
|
||||
|
||||
if (commander.isHelp()) {
|
||||
if (!unknownOpts.isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder("Unknown options encountered: ");
|
||||
for (String opt : unknownOpts) {
|
||||
sb.append(opt + ", ");
|
||||
}
|
||||
exitWithErrorCode(sb.substring(0,sb.lastIndexOf(",")));
|
||||
} else if (commander.isHelp()) {
|
||||
jc.usage();
|
||||
System.out.println(commander.printHelpExamples());
|
||||
} else if (commander.isVersion()) {
|
||||
@ -36,34 +50,33 @@ public class Main {
|
||||
} else {
|
||||
if (!commander.getVerifyFile().isEmpty()) {
|
||||
validator = new ReferenceManifestValidator();
|
||||
System.out.println(commander.toString());
|
||||
if (commander.isVerbose()) {
|
||||
System.out.println(commander.toString());
|
||||
}
|
||||
String verifyFile = commander.getVerifyFile();
|
||||
String rimel = commander.getRimEventLog();
|
||||
String certificateFile = commander.getPublicCertificate();
|
||||
String trustStore = commander.getTruststoreFile();
|
||||
if (!verifyFile.isEmpty()) {
|
||||
validator.setRim(verifyFile);
|
||||
if (!rimel.isEmpty()) {
|
||||
validator.setRimEventLog(rimel);
|
||||
}
|
||||
if (!trustStore.isEmpty()) {
|
||||
validator.setTrustStoreFile(trustStore);
|
||||
}
|
||||
if (!certificateFile.isEmpty()) {
|
||||
System.out.println("A single cert cannot be used for verification. " +
|
||||
"The signing cert will be searched for in the trust store.");
|
||||
}
|
||||
validator.validateSwidtagFile(verifyFile);
|
||||
validator.setRim(verifyFile);
|
||||
validator.setRimEventLog(rimel);
|
||||
credValidator = new CredentialArgumentValidator(trustStore,
|
||||
"","", true);
|
||||
if (credValidator.isValid()) {
|
||||
validator.setTrustStoreFile(trustStore);
|
||||
} else {
|
||||
System.out.println("Need a RIM file to validate!");
|
||||
System.exit(1);
|
||||
exitWithErrorCode(credValidator.getErrorMessage());
|
||||
}
|
||||
if (validator.validateSwidtagFile(verifyFile)) {
|
||||
System.out.println("Successfully verified " + verifyFile);
|
||||
} else {
|
||||
exitWithErrorCode("Failed to verify " + verifyFile);
|
||||
}
|
||||
} else {
|
||||
gateway = new SwidTagGateway();
|
||||
System.out.println(commander.toString());
|
||||
if (commander.isVerbose()) {
|
||||
System.out.println(commander.toString());
|
||||
}
|
||||
String createType = commander.getCreateType().toUpperCase();
|
||||
String attributesFile = commander.getAttributesFile();
|
||||
String jksTruststoreFile = commander.getTruststoreFile();
|
||||
String certificateFile = commander.getPublicCertificate();
|
||||
String privateKeyFile = commander.getPrivateKeyFile();
|
||||
boolean embeddedCert = commander.isEmbedded();
|
||||
@ -71,32 +84,22 @@ public class Main {
|
||||
String rimEventLog = commander.getRimEventLog();
|
||||
switch (createType) {
|
||||
case "BASE":
|
||||
if (!attributesFile.isEmpty()) {
|
||||
gateway.setAttributesFile(attributesFile);
|
||||
}
|
||||
if (!jksTruststoreFile.isEmpty()) {
|
||||
gateway.setAttributesFile(attributesFile);
|
||||
gateway.setRimEventLog(rimEventLog);
|
||||
credValidator = new CredentialArgumentValidator("" ,
|
||||
certificateFile, privateKeyFile, false);
|
||||
if (defaultKey){
|
||||
gateway.setDefaultCredentials(true);
|
||||
gateway.setJksTruststoreFile(jksTruststoreFile);
|
||||
} else if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) {
|
||||
gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
|
||||
} else if (credValidator.isValid()) {
|
||||
gateway.setDefaultCredentials(false);
|
||||
gateway.setPemCertificateFile(certificateFile);
|
||||
gateway.setPemPrivateKeyFile(privateKeyFile);
|
||||
if (embeddedCert) {
|
||||
gateway.setEmbeddedCert(true);
|
||||
}
|
||||
} else if (defaultKey){
|
||||
gateway.setDefaultCredentials(true);
|
||||
gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
|
||||
} else {
|
||||
System.out.println("A private key (-k) and public certificate (-p) " +
|
||||
"are required, or the default key (-d) must be indicated.");
|
||||
System.exit(1);
|
||||
}
|
||||
if (rimEventLog.isEmpty()) {
|
||||
System.out.println("Error: a support RIM is required!");
|
||||
System.exit(1);
|
||||
} else {
|
||||
gateway.setRimEventLog(rimEventLog);
|
||||
exitWithErrorCode(credValidator.getErrorMessage());
|
||||
}
|
||||
List<String> timestampArguments = commander.getTimestampArguments();
|
||||
if (timestampArguments.size() > 0) {
|
||||
@ -106,18 +109,27 @@ public class Main {
|
||||
gateway.setTimestampArgument(timestampArguments.get(1));
|
||||
}
|
||||
} else {
|
||||
System.exit(1);
|
||||
exitWithErrorCode("The provided timestamp argument(s) " +
|
||||
"is/are not valid.");
|
||||
}
|
||||
}
|
||||
gateway.generateSwidTag(commander.getOutFile());
|
||||
break;
|
||||
default:
|
||||
System.out.println("No create type given, nothing to do");
|
||||
exitWithErrorCode("Create type not recognized.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use cases that exit with an error code are redirected here.
|
||||
*/
|
||||
private static void exitWithErrorCode(String errorMessage) {
|
||||
log.error(errorMessage);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method parses the version number from the jar filename in the absence of
|
||||
* the VERSION file expected with an rpm installation.
|
||||
|
@ -64,7 +64,6 @@ import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.KeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
@ -100,7 +99,7 @@ public class SwidTagGateway {
|
||||
try {
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(SwidTagConstants.SCHEMA_PACKAGE);
|
||||
marshaller = jaxbContext.createMarshaller();
|
||||
attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE;
|
||||
attributesFile = "";
|
||||
defaultCredentials = true;
|
||||
pemCertificateFile = "";
|
||||
embeddedCert = false;
|
||||
|
@ -12,32 +12,38 @@ import java.util.List;
|
||||
*/
|
||||
public class Commander {
|
||||
|
||||
@Parameter(description = "This parameter catches all unrecognized arguments.")
|
||||
private List<String> unknownOptions = new ArrayList<>();
|
||||
@Parameter(names = {"-h", "--help"}, help = true, description = "Print this help text.")
|
||||
private boolean help;
|
||||
@Parameter(names = {"-c", "--create \"base\""}, order = 0,
|
||||
description = "The type of RIM to create. A base RIM will be created by default.")
|
||||
private String createType = "";
|
||||
@Parameter(names = {"-v", "--verify <path>"}, order = 3,
|
||||
@Parameter(names = {"-v", "--verify <path>"}, validateWith = FileArgumentValidator.class,
|
||||
description = "Specify a RIM file to verify.")
|
||||
private String verifyFile = "";
|
||||
@Parameter(names = {"-V", "--version"}, description = "Output the current version.")
|
||||
private boolean version = false;
|
||||
@Parameter(names = {"-a", "--attributes <path>"}, order = 1,
|
||||
@Parameter(names = {"-a", "--attributes <path>"}, validateWith = FileArgumentValidator.class,
|
||||
description = "The configuration file holding attributes "
|
||||
+ "to populate the base RIM with.")
|
||||
+ "to populate the base RIM with. An example file can be found in /opt/rimtool/data.")
|
||||
private String attributesFile = "";
|
||||
@Parameter(names = {"-o", "--out <path>"}, order = 2,
|
||||
description = "The file to write the RIM out to. "
|
||||
+ "The RIM will be written to stdout by default.")
|
||||
private String outFile = "";
|
||||
@Parameter(names = {"-t", "--truststore <path>"}, order = 4,
|
||||
@Parameter(names = {"--verbose"}, description = "Control output verbosity.")
|
||||
private boolean verbose = false;
|
||||
@Parameter(names = {"-t", "--truststore <path>"}, validateWith = FileArgumentValidator.class,
|
||||
description = "The truststore to sign the base RIM created "
|
||||
+ "or to validate the signed base RIM.")
|
||||
private String truststoreFile = "";
|
||||
@Parameter(names = {"-k", "--privateKeyFile <path>"}, order = 5,
|
||||
@Parameter(names = {"-k", "--privateKeyFile <path>"},
|
||||
validateWith = FileArgumentValidator.class,
|
||||
description = "The private key used to sign the base RIM created by this tool.")
|
||||
private String privateKeyFile = "";
|
||||
@Parameter(names = {"-p", "--publicCertificate <path>"}, order = 6,
|
||||
@Parameter(names = {"-p", "--publicCertificate <path>"},
|
||||
validateWith = FileArgumentValidator.class,
|
||||
description = "The public key certificate to embed in the base RIM created by "
|
||||
+ "this tool.")
|
||||
private String publicCertificate = "";
|
||||
@ -45,9 +51,9 @@ public class Commander {
|
||||
description = "Embed the provided certificate in the signed swidtag.")
|
||||
private boolean embedded = false;
|
||||
@Parameter(names = {"-d", "--default-key"}, order = 8,
|
||||
description = "Use default signing credentials.")
|
||||
description = "Use the JKS keystore installed in /opt/rimtool/data.")
|
||||
private boolean defaultKey = false;
|
||||
@Parameter(names = {"-l", "--rimel <path>"}, order = 9,
|
||||
@Parameter(names = {"-l", "--rimel <path>"}, validateWith = FileArgumentValidator.class,
|
||||
description = "The TCG eventlog file to use as a support RIM.")
|
||||
private String rimEventLog = "";
|
||||
@Parameter(names = {"--timestamp"}, order = 10, variableArity = true,
|
||||
@ -56,6 +62,10 @@ public class Commander {
|
||||
"\tRFC3339 [yyyy-MM-ddThh:mm:ssZ]\n\tRFC3852 <counterSignature.bin>")
|
||||
private List<String> timestampArguments = new ArrayList<String>(2);
|
||||
|
||||
public List<String> getUnknownOptions() {
|
||||
return unknownOptions;
|
||||
}
|
||||
|
||||
public boolean isHelp() {
|
||||
return help;
|
||||
}
|
||||
@ -71,6 +81,7 @@ public class Commander {
|
||||
public boolean isVersion() {
|
||||
return version;
|
||||
}
|
||||
public boolean isVerbose() { return verbose; }
|
||||
public String getAttributesFile() {
|
||||
return attributesFile;
|
||||
}
|
||||
@ -101,26 +112,17 @@ public class Commander {
|
||||
|
||||
public String printHelpExamples() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Create a base RIM using the values in attributes.json; " +
|
||||
"sign it with the default keystore; ");
|
||||
sb.append("and write the data to base_rim.swidtag:\n\n");
|
||||
sb.append("\t\t-c base -a attributes.json -d -l support_rim.bin -o base_rim.swidtag" +
|
||||
"\n\n\n");
|
||||
sb.append("Create a base RIM using the default attribute values; ");
|
||||
sb.append("sign it using privateKey.pem; embed cert.pem in the signature block; ");
|
||||
sb.append("and write the data to console output:\n\n");
|
||||
sb.append("\t\t-c base -l support_rim.bin -k privateKey.pem -p cert.pem -e\n\n\n");
|
||||
sb.append("Create a base RIM using the values in attributes.json; " +
|
||||
"sign it with the default keystore; add a RFC3852 timestamp; ");
|
||||
sb.append("and write the data to base_rim.swidtag:\n\n");
|
||||
sb.append("\t\t-c base -a attributes.json -d -l support_rim.bin " +
|
||||
"--timestamp RFC3852 counterSignature.bin -o base_rim.swidtag\n\n\n");
|
||||
sb.append("Validate a base RIM using an external support RIM to override the ");
|
||||
sb.append("payload file:\n\n");
|
||||
sb.append("\t\t-v base_rim.swidtag -l support_rim.bin\n\n\n");
|
||||
sb.append("Validate a base RIM with its own payload file and a PEM truststore ");
|
||||
sb.append("containing the signing cert:\n\n");
|
||||
sb.append("\t\t-v base_rim.swidtag -t ca.crt\n\n\n");
|
||||
sb.append("Create a base RIM: use the values in attributes.json; ");
|
||||
sb.append("add support_rim.bin to the payload; ");
|
||||
sb.append("sign it using privateKey.pem and cert.pem; embed cert.pem in the signature; ");
|
||||
sb.append("add a RFC3852 timestamp; and write the data to base_rim.swidtag:\n\n");
|
||||
sb.append("\t\t-c base -a attributes.json -l support_rim.bin "
|
||||
+ "-k privateKey.pem -p cert.pem -e --timestamp RFC3852 counterSignature.bin "
|
||||
+ "-o base_rim.swidtag\n\n\n");
|
||||
sb.append("Validate base_rim.swidtag: "
|
||||
+ "the payload <File> is validated with support_rim.bin; "
|
||||
+ "and the signature is validated with ca.crt:\n\n");
|
||||
sb.append("\t\t-v base_rim.swidtag -l support_rim.bin -t ca.crt\n\n\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
package hirs.swid.utils;
|
||||
|
||||
public class CredentialArgumentValidator {
|
||||
private String truststoreFile;
|
||||
private String certificateFile;
|
||||
private String privateKeyFile;
|
||||
private String format;
|
||||
private boolean isValidating;
|
||||
private String errorMessage;
|
||||
private static final String PEM = "PEM";
|
||||
|
||||
public CredentialArgumentValidator(String truststoreFile,
|
||||
String certificateFile,
|
||||
String privateKeyFile,
|
||||
boolean isValidating) {
|
||||
this.truststoreFile = truststoreFile;
|
||||
this.certificateFile = certificateFile;
|
||||
this.privateKeyFile = privateKeyFile;
|
||||
this.isValidating = isValidating;
|
||||
errorMessage = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for format property
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public String getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for error message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks for the following valid configurations of input arguments:
|
||||
* 1.
|
||||
* 2. truststore only for validating (PEM format)
|
||||
* 3. certificate + private key for signing (PEM format)
|
||||
* 4.
|
||||
*
|
||||
* @return true if the above are found, false otherwise
|
||||
*/
|
||||
public boolean isValid() {
|
||||
if (isValidating) {
|
||||
if (!truststoreFile.isEmpty()) {
|
||||
format = PEM;
|
||||
return true;
|
||||
} else {
|
||||
errorMessage = "Validation requires a valid truststore file.";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) {
|
||||
format = PEM;
|
||||
return true;
|
||||
} else {
|
||||
if (certificateFile.isEmpty()) {
|
||||
errorMessage = "A public certificate must be specified by \'-p\' " +
|
||||
"for signing operations.";
|
||||
}
|
||||
if (privateKeyFile.isEmpty()) {
|
||||
errorMessage = "A private key must be specified by \'-k\' " +
|
||||
"for signing operations.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package hirs.swid.utils;
|
||||
|
||||
import com.beust.jcommander.IParameterValidator;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
|
||||
import java.io.File;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
||||
/**
|
||||
* This class validates arguments that take a String path to a file.
|
||||
* The file path is checked for null, and if the file is found it is checked
|
||||
* for validity, emptiness, and read permissions.
|
||||
*/
|
||||
@Log4j2
|
||||
public class FileArgumentValidator implements IParameterValidator {
|
||||
public void validate(String name, String value) throws ParameterException {
|
||||
try {
|
||||
File file = new File(value);
|
||||
if (!file.isFile()) {
|
||||
throw new ParameterException("Invalid file path: " + value +
|
||||
". Please verify file path.");
|
||||
}
|
||||
if (file.length() == 0) {
|
||||
throw new ParameterException("File " + value + " is empty.");
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
throw new ParameterException("File path cannot be null: " + e.getMessage());
|
||||
} catch (SecurityException e) {
|
||||
throw new ParameterException("Read access denied for " + value +
|
||||
", please verify permissions.");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user