mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-24 07:06:46 +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.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.
|
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"]
|
SHELL ["/bin/bash", "-c"]
|
||||||
|
|
||||||
# Rocky 9 has a different channel for some apps
|
# Rocky 9 has a different channel for some apps
|
||||||
@ -50,7 +53,7 @@ RUN echo "#!/bin/bash" > /tmp/tpm_config && \
|
|||||||
EXPOSE 8443
|
EXPOSE 8443
|
||||||
|
|
||||||
# Checkout HIRS
|
# 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
|
# Defensive copy of the repo so it's easy to start fresh if needed
|
||||||
RUN mkdir /hirs
|
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.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}
|
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"]
|
SHELL ["pwsh", "-Command"]
|
||||||
|
|
||||||
# Output Powershell Version
|
# 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
|
# Echo PATH after update
|
||||||
RUN echo $Env:PATH
|
RUN echo $Env:PATH
|
||||||
|
|
||||||
# Clone HIRS main
|
# Clone HIRS main (or REF)
|
||||||
WORKDIR C:/
|
WORKDIR C:/
|
||||||
RUN git config --global --add core.autocrlf false
|
RUN git config --global --add core.autocrlf false
|
||||||
RUN git config --global --add safe.directory '*'
|
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
|
# Defensive copy of the repo so it's easy to start fresh if needed
|
||||||
WORKDIR C:/repo
|
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"
|
echo "PUBLIC_IMAGE_TAG=$PUBLIC_IMAGE_NAME:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
|
||||||
- name: Print env
|
- name: Print env
|
||||||
run: |
|
run: |
|
||||||
|
echo GITHUB_REF_NAME=${{ github.ref_name }}
|
||||||
echo DOCKERFILE_ROCKY=$DOCKERFILE_ROCKY
|
echo DOCKERFILE_ROCKY=$DOCKERFILE_ROCKY
|
||||||
echo DOCKERFILE_WINDOWS=$DOCKERFILE_WINDOWS
|
echo DOCKERFILE_WINDOWS=$DOCKERFILE_WINDOWS
|
||||||
echo IMAGE_NAME_ROCKY=$IMAGE_NAME_ROCKY
|
echo IMAGE_NAME_ROCKY=$IMAGE_NAME_ROCKY
|
||||||
@ -86,6 +87,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
context: "{{defaultContext}}:.ci/docker"
|
context: "{{defaultContext}}:.ci/docker"
|
||||||
file: Dockerfile.${{env.DOCKERFILE_ROCKY}}
|
file: Dockerfile.${{env.DOCKERFILE_ROCKY}}
|
||||||
|
build-args: REF=${{ github.ref_name }}
|
||||||
tags: ${{env.TAG}}
|
tags: ${{env.TAG}}
|
||||||
push: true
|
push: true
|
||||||
|
|
||||||
@ -108,7 +110,7 @@ jobs:
|
|||||||
- name: Build the docker image for ${{ github.repository }}
|
- name: Build the docker image for ${{ github.repository }}
|
||||||
run: |
|
run: |
|
||||||
cd ./.ci/docker
|
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
|
- name: Push the docker image
|
||||||
run: |
|
run: |
|
||||||
@ -133,7 +135,7 @@ jobs:
|
|||||||
- name: Build the docker image for ${{ github.repository }}
|
- name: Build the docker image for ${{ github.repository }}
|
||||||
run: |
|
run: |
|
||||||
cd ./.ci/docker
|
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
|
- name: Push the docker image
|
||||||
run: |
|
run: |
|
||||||
|
@ -52,6 +52,7 @@ dependencies {
|
|||||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3'
|
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3'
|
||||||
testImplementation 'org.junit.platform:junit-platform-launcher:1.9.3'
|
testImplementation 'org.junit.platform:junit-platform-launcher:1.9.3'
|
||||||
testImplementation 'org.mockito:mockito-core:4.2.0'
|
testImplementation 'org.mockito:mockito-core:4.2.0'
|
||||||
|
testImplementation 'org.springframework:spring-test:6.0.8'
|
||||||
|
|
||||||
// spring management
|
// spring management
|
||||||
compileOnly libs.lombok
|
compileOnly libs.lombok
|
||||||
|
@ -15,5 +15,9 @@
|
|||||||
<Match>
|
<Match>
|
||||||
<Bug pattern="EI_EXPOSE_REP2" />
|
<Bug pattern="EI_EXPOSE_REP2" />
|
||||||
</Match>
|
</Match>
|
||||||
|
<Match>
|
||||||
|
<Class name="hirs.attestationca.persist.AttestationCertificateAuthorityTest"/>
|
||||||
|
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
|
||||||
|
</Match>
|
||||||
</FindBugsFilter>
|
</FindBugsFilter>
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package hirs.attestationca.persist;
|
package hirs.attestationca.persist;
|
||||||
|
|
||||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
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.ComponentResultRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
|
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
|
||||||
@ -52,6 +53,7 @@ public abstract class AttestationCertificateAuthority {
|
|||||||
private Integer validDays = 1;
|
private Integer validDays = 1;
|
||||||
|
|
||||||
private final ComponentResultRepository componentResultRepository;
|
private final ComponentResultRepository componentResultRepository;
|
||||||
|
private ComponentInfoRepository componentInfoRepository;
|
||||||
private final CertificateRepository certificateRepository;
|
private final CertificateRepository certificateRepository;
|
||||||
private final IssuedCertificateRepository issuedCertificateRepository;
|
private final IssuedCertificateRepository issuedCertificateRepository;
|
||||||
private final ReferenceManifestRepository referenceManifestRepository;
|
private final ReferenceManifestRepository referenceManifestRepository;
|
||||||
@ -71,13 +73,14 @@ public abstract class AttestationCertificateAuthority {
|
|||||||
* @param acaCertificate the ACA certificate
|
* @param acaCertificate the ACA certificate
|
||||||
* @param structConverter the struct converter
|
* @param structConverter the struct converter
|
||||||
* @param componentResultRepository the component result manager
|
* @param componentResultRepository the component result manager
|
||||||
|
* @param componentInfoRepository the component info manager
|
||||||
* @param certificateRepository the certificate manager
|
* @param certificateRepository the certificate manager
|
||||||
* @param referenceManifestRepository the Reference Manifest manager
|
* @param referenceManifestRepository the Reference Manifest manager
|
||||||
* @param validDays the number of days issued certs are valid
|
* @param validDays the number of days issued certs are valid
|
||||||
* @param deviceRepository the device manager
|
* @param deviceRepository the device manager
|
||||||
* @param referenceDigestValueRepository the reference event manager
|
* @param referenceDigestValueRepository the reference event manager
|
||||||
* @param policyRepository
|
* @param policyRepository policy setting repository
|
||||||
* @param tpm2ProvisionerStateRepository
|
* @param tpm2ProvisionerStateRepository tpm2 provisioner state repository
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("checkstyle:parameternumber")
|
@SuppressWarnings("checkstyle:parameternumber")
|
||||||
public AttestationCertificateAuthority(
|
public AttestationCertificateAuthority(
|
||||||
@ -85,6 +88,7 @@ public abstract class AttestationCertificateAuthority {
|
|||||||
final PrivateKey privateKey, final X509Certificate acaCertificate,
|
final PrivateKey privateKey, final X509Certificate acaCertificate,
|
||||||
final StructConverter structConverter,
|
final StructConverter structConverter,
|
||||||
final ComponentResultRepository componentResultRepository,
|
final ComponentResultRepository componentResultRepository,
|
||||||
|
final ComponentInfoRepository componentInfoRepository,
|
||||||
final CertificateRepository certificateRepository,
|
final CertificateRepository certificateRepository,
|
||||||
final IssuedCertificateRepository issuedCertificateRepository,
|
final IssuedCertificateRepository issuedCertificateRepository,
|
||||||
final ReferenceManifestRepository referenceManifestRepository,
|
final ReferenceManifestRepository referenceManifestRepository,
|
||||||
@ -98,6 +102,7 @@ public abstract class AttestationCertificateAuthority {
|
|||||||
this.acaCertificate = acaCertificate;
|
this.acaCertificate = acaCertificate;
|
||||||
this.structConverter = structConverter;
|
this.structConverter = structConverter;
|
||||||
this.componentResultRepository = componentResultRepository;
|
this.componentResultRepository = componentResultRepository;
|
||||||
|
this.componentInfoRepository = componentInfoRepository;
|
||||||
this.certificateRepository = certificateRepository;
|
this.certificateRepository = certificateRepository;
|
||||||
this.issuedCertificateRepository = issuedCertificateRepository;
|
this.issuedCertificateRepository = issuedCertificateRepository;
|
||||||
this.referenceManifestRepository = referenceManifestRepository;
|
this.referenceManifestRepository = referenceManifestRepository;
|
||||||
@ -111,8 +116,8 @@ public abstract class AttestationCertificateAuthority {
|
|||||||
certificateRepository, deviceRepository,
|
certificateRepository, deviceRepository,
|
||||||
privateKey, acaCertificate, validDays, tpm2ProvisionerStateRepository);
|
privateKey, acaCertificate, validDays, tpm2ProvisionerStateRepository);
|
||||||
this.identityClaimHandler = new IdentityClaimProcessor(supplyChainValidationService,
|
this.identityClaimHandler = new IdentityClaimProcessor(supplyChainValidationService,
|
||||||
certificateRepository, referenceManifestRepository,
|
certificateRepository, componentResultRepository, componentInfoRepository,
|
||||||
referenceDigestValueRepository,
|
referenceManifestRepository, referenceDigestValueRepository,
|
||||||
deviceRepository, tpm2ProvisionerStateRepository, policyRepository);
|
deviceRepository, tpm2ProvisionerStateRepository, policyRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package hirs.attestationca.persist;
|
package hirs.attestationca.persist;
|
||||||
|
|
||||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
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.ComponentResultRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
import hirs.attestationca.persist.entity.manager.DeviceRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
|
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.entity.manager.TPM2ProvisionerStateRepository;
|
||||||
import hirs.attestationca.persist.service.SupplyChainValidationService;
|
import hirs.attestationca.persist.service.SupplyChainValidationService;
|
||||||
import hirs.structs.converters.StructConverter;
|
import hirs.structs.converters.StructConverter;
|
||||||
import lombok.extern.log4j.Log4j2;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
@ -63,6 +63,7 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
|
|||||||
final PrivateKey privateKey, final X509Certificate acaCertificate,
|
final PrivateKey privateKey, final X509Certificate acaCertificate,
|
||||||
final StructConverter structConverter,
|
final StructConverter structConverter,
|
||||||
final ComponentResultRepository componentResultRepository,
|
final ComponentResultRepository componentResultRepository,
|
||||||
|
final ComponentInfoRepository componentInfoRepository,
|
||||||
final CertificateRepository certificateRepository,
|
final CertificateRepository certificateRepository,
|
||||||
final IssuedCertificateRepository issuedCertificateRepository,
|
final IssuedCertificateRepository issuedCertificateRepository,
|
||||||
final ReferenceManifestRepository referenceManifestRepository,
|
final ReferenceManifestRepository referenceManifestRepository,
|
||||||
@ -72,7 +73,8 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
|
|||||||
final PolicyRepository policyRepository,
|
final PolicyRepository policyRepository,
|
||||||
final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository) {
|
final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository) {
|
||||||
super(supplyChainValidationService, privateKey, acaCertificate, structConverter,
|
super(supplyChainValidationService, privateKey, acaCertificate, structConverter,
|
||||||
componentResultRepository, certificateRepository, issuedCertificateRepository,
|
componentResultRepository, componentInfoRepository,
|
||||||
|
certificateRepository, issuedCertificateRepository,
|
||||||
referenceManifestRepository,
|
referenceManifestRepository,
|
||||||
validDays, deviceRepository,
|
validDays, deviceRepository,
|
||||||
referenceDigestValueRepository, policyRepository, tpm2ProvisionerStateRepository);
|
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 hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -11,6 +10,19 @@ import java.util.UUID;
|
|||||||
@Repository
|
@Repository
|
||||||
public interface ComponentResultRepository extends JpaRepository<ComponentResult, UUID> {
|
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 hirs.attestationca.persist.entity.userdefined.rim.ReferenceDigestValue;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -90,7 +90,8 @@ public class TPM2ProvisionerState {
|
|||||||
/**
|
/**
|
||||||
* Convenience method for finding the {@link TPM2ProvisionerState} associated with the nonce.
|
* 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}
|
* {@link TPM2ProvisionerState}
|
||||||
* @param nonce the nonce to use as the key 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;
|
* @return the {@link TPM2ProvisionerState} associated with the nonce;
|
||||||
|
@ -115,8 +115,7 @@ public class Device extends AbstractEntity {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("Device Name: %s%nStatus: %s%nSummary: %s%n",
|
return String.format("Device Name: %s%nStatus: %s%nSummary: %s%n",
|
||||||
name, healthStatus.getStatus(),
|
name, healthStatus.getStatus(),
|
||||||
supplyChainValidationStatus.toString(),
|
supplyChainValidationStatus.toString());
|
||||||
summaryId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -46,6 +46,7 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
|||||||
|
|
||||||
private static final String DEVICE_ID_FIELD = "device.id";
|
private static final String DEVICE_ID_FIELD = "device.id";
|
||||||
|
|
||||||
|
@Getter
|
||||||
@Column
|
@Column
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
private final AppraisalStatus.Status overallValidationResult;
|
private final AppraisalStatus.Status overallValidationResult;
|
||||||
@ -58,6 +59,9 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
|||||||
targetEntity = SupplyChainValidation.class, orphanRemoval = true)
|
targetEntity = SupplyChainValidation.class, orphanRemoval = true)
|
||||||
private final Set<SupplyChainValidation> validations;
|
private final Set<SupplyChainValidation> validations;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private UUID provisionSessionId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor necessary for Hibernate.
|
* Default constructor necessary for Hibernate.
|
||||||
*/
|
*/
|
||||||
@ -177,6 +181,20 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
|||||||
return new SupplyChainValidationSummary.Selector(certMan);
|
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.
|
* Construct a new SupplyChainValidationSummary.
|
||||||
*
|
*
|
||||||
@ -212,13 +230,6 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
|||||||
return new Device(this.device.getDeviceInfo());
|
return new Device(this.device.getDeviceInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the overall appraisal result
|
|
||||||
*/
|
|
||||||
public AppraisalStatus.Status getOverallValidationResult() {
|
|
||||||
return overallValidationResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the validations that this summary contains
|
* @return the validations that this summary contains
|
||||||
*/
|
*/
|
||||||
|
@ -1,38 +1,142 @@
|
|||||||
package hirs.attestationca.persist.entity.userdefined.certificate;
|
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 jakarta.persistence.Entity;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
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
|
@Getter
|
||||||
@Entity
|
@Entity
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
public class ComponentResult extends AbstractEntity {
|
public class ComponentResult extends ArchivableEntity {
|
||||||
|
|
||||||
private UUID certificateId;
|
// embedded component info
|
||||||
private int componentHash;
|
@Setter
|
||||||
private String expected;
|
private String manufacturer;
|
||||||
private String actual;
|
@Setter
|
||||||
private boolean mismatched;
|
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,
|
private String issuerDN;
|
||||||
final String expected, final String actual) {
|
private String certificateSerialNumber;
|
||||||
this.certificateId = certificateId;
|
private String boardSerialNumber;
|
||||||
this.componentHash = componentHash;
|
private String uniformResourceIdentifier;
|
||||||
this.expected = expected;
|
|
||||||
this.actual = actual;
|
|
||||||
this.mismatched = Objects.equals(expected, actual);
|
/**
|
||||||
|
* 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() {
|
public String toString() {
|
||||||
return String.format("ComponentResult[%d]: expected=[%s] actual=[%s]",
|
return String.format("ComponentResult: certificateSerialNumber=[%s] "
|
||||||
componentHash, expected, actual);
|
+ "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.TBBSecurityAssertion;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
|
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.PlatformConfigurationV2;
|
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.PlatformConfigurationV2;
|
||||||
import hirs.attestationca.persist.service.selector.CertificateSelector;
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Transient;
|
import jakarta.persistence.Transient;
|
||||||
|
@ -32,6 +32,8 @@ public class ComponentAddress {
|
|||||||
|
|
||||||
private ASN1ObjectIdentifier addressType;
|
private ASN1ObjectIdentifier addressType;
|
||||||
private ASN1UTF8String addressValue;
|
private ASN1UTF8String addressValue;
|
||||||
|
private String addressTypeString;
|
||||||
|
private String addressValueString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor.
|
* 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;
|
private String category, categoryStr;
|
||||||
@Getter
|
@Getter
|
||||||
private String component, componentStr;
|
private String component, componentStr;
|
||||||
|
@Getter
|
||||||
private String registryType;
|
private String registryType;
|
||||||
@Getter
|
@Getter
|
||||||
private String componentIdentifier;
|
private String componentIdentifier;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
|
package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -37,10 +36,6 @@ import java.util.stream.Collectors;
|
|||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
public class ComponentIdentifier {
|
public class ComponentIdentifier {
|
||||||
|
|
||||||
/**
|
|
||||||
* Variable for components that aren't set.
|
|
||||||
*/
|
|
||||||
public static final String EMPTY_COMPONENT = "[Empty]";
|
|
||||||
/**
|
/**
|
||||||
* Variable for components that aren't set.
|
* Variable for components that aren't set.
|
||||||
*/
|
*/
|
||||||
@ -88,8 +83,8 @@ public class ComponentIdentifier {
|
|||||||
public ComponentIdentifier() {
|
public ComponentIdentifier() {
|
||||||
componentManufacturer = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
componentManufacturer = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||||
componentModel = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
componentModel = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||||
componentSerial = new DERUTF8String(EMPTY_COMPONENT);
|
componentSerial = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||||
componentRevision = new DERUTF8String(EMPTY_COMPONENT);
|
componentRevision = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
|
||||||
componentManufacturerId = null;
|
componentManufacturerId = null;
|
||||||
fieldReplaceable = null;
|
fieldReplaceable = null;
|
||||||
componentAddress = new ArrayList<>();
|
componentAddress = new ArrayList<>();
|
||||||
@ -124,13 +119,13 @@ public class ComponentIdentifier {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor given the SEQUENCE that contains Component Identifier.
|
* 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
|
* @throws IllegalArgumentException if there was an error on the parsing
|
||||||
*/
|
*/
|
||||||
public ComponentIdentifier(final ASN1Sequence sequence) throws IllegalArgumentException {
|
public ComponentIdentifier(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||||
// set all optional values to default in case they aren't set.
|
// set all optional values to default in case they aren't set.
|
||||||
this();
|
this();
|
||||||
//Check if it have a valid number of identifiers
|
//Check if it has a valid number of identifiers
|
||||||
if (sequence.size() < MANDATORY_ELEMENTS) {
|
if (sequence.size() < MANDATORY_ELEMENTS) {
|
||||||
throw new IllegalArgumentException("Component identifier do not have required values.");
|
throw new IllegalArgumentException("Component identifier do not have required values.");
|
||||||
}
|
}
|
||||||
@ -238,7 +233,7 @@ public class ComponentIdentifier {
|
|||||||
sb.append(fieldReplaceable.toString());
|
sb.append(fieldReplaceable.toString());
|
||||||
}
|
}
|
||||||
sb.append(", componentAddress=");
|
sb.append(", componentAddress=");
|
||||||
if (componentAddress.size() > 0) {
|
if (!componentAddress.isEmpty()) {
|
||||||
sb.append(componentAddress
|
sb.append(componentAddress
|
||||||
.stream()
|
.stream()
|
||||||
.map(Object::toString)
|
.map(Object::toString)
|
||||||
|
@ -25,7 +25,7 @@ public class PlatformConfigurationV1 extends PlatformConfiguration {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor given the SEQUENCE that contains Platform Configuration.
|
* 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
|
* @throws IllegalArgumentException if there was an error on the parsing
|
||||||
*/
|
*/
|
||||||
public PlatformConfigurationV1(final ASN1Sequence sequence) throws IllegalArgumentException {
|
public PlatformConfigurationV1(final ASN1Sequence sequence) throws IllegalArgumentException {
|
||||||
|
@ -103,13 +103,13 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor given the SEQUENCE that contains Component Identifier.
|
* 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
|
* @throws IllegalArgumentException if there was an error on the parsing
|
||||||
*/
|
*/
|
||||||
public ComponentIdentifierV2(final ASN1Sequence sequence)
|
public ComponentIdentifierV2(final ASN1Sequence sequence)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
super();
|
super();
|
||||||
// Check if it have a valid number of identifiers
|
// Check if it has a valid number of identifiers
|
||||||
if (sequence.size() < MANDATORY_ELEMENTS) {
|
if (sequence.size() < MANDATORY_ELEMENTS) {
|
||||||
throw new IllegalArgumentException("Component identifier do not have required values.");
|
throw new IllegalArgumentException("Component identifier do not have required values.");
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,39 @@
|
|||||||
package hirs.attestationca.persist.entity.userdefined.info;
|
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.Column;
|
||||||
import jakarta.persistence.DiscriminatorColumn;
|
import jakarta.persistence.DiscriminatorColumn;
|
||||||
import jakarta.persistence.DiscriminatorType;
|
import jakarta.persistence.DiscriminatorType;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.xml.bind.annotation.XmlElement;
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
import lombok.Data;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ComponentInfo is a class to hold Hardware component information
|
* ComponentInfo is a class to hold Hardware component information
|
||||||
* such as manufacturer, model, serial number and version.
|
* such as manufacturer, model, serial number and version.
|
||||||
*/
|
*/
|
||||||
@Log4j2
|
@Log4j2
|
||||||
@NoArgsConstructor
|
|
||||||
@Data
|
|
||||||
@Entity
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||||
@DiscriminatorColumn(name = "componentTypeEnum", discriminatorType = DiscriminatorType.STRING)
|
@DiscriminatorColumn(name = "componentTypeEnum", discriminatorType = DiscriminatorType.STRING)
|
||||||
public class ComponentInfo implements Serializable {
|
public class ComponentInfo extends ArchivableEntity {
|
||||||
|
|
||||||
@Id
|
// @Id
|
||||||
@Column(name = "componentInfo_id")
|
// @Column(name = "componentInfo_id")
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
// @GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
private Long id;
|
// private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String deviceName;
|
||||||
@XmlElement
|
@XmlElement
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String componentManufacturer;
|
private String componentManufacturer;
|
||||||
@ -52,7 +55,7 @@ public class ComponentInfo implements Serializable {
|
|||||||
private String componentClass;
|
private String componentClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Base constructor for children.
|
||||||
* @param componentManufacturer Component Manufacturer (must not be null)
|
* @param componentManufacturer Component Manufacturer (must not be null)
|
||||||
* @param componentModel Component Model (must not be null)
|
* @param componentModel Component Model (must not be null)
|
||||||
* @param componentSerial Component Serial Number (can be null)
|
* @param componentSerial Component Serial Number (can be null)
|
||||||
@ -62,6 +65,22 @@ public class ComponentInfo implements Serializable {
|
|||||||
final String componentModel,
|
final String componentModel,
|
||||||
final String componentSerial,
|
final String componentSerial,
|
||||||
final String componentRevision) {
|
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(
|
if (isComplete(
|
||||||
componentManufacturer,
|
componentManufacturer,
|
||||||
componentModel,
|
componentModel,
|
||||||
@ -72,61 +91,40 @@ public class ComponentInfo implements Serializable {
|
|||||||
throw new NullPointerException("ComponentInfo: manufacturer and/or "
|
throw new NullPointerException("ComponentInfo: manufacturer and/or "
|
||||||
+ "model can not be null");
|
+ "model can not be null");
|
||||||
}
|
}
|
||||||
|
this.deviceName = deviceName;
|
||||||
this.componentManufacturer = componentManufacturer.trim();
|
this.componentManufacturer = componentManufacturer.trim();
|
||||||
this.componentModel = componentModel.trim();
|
this.componentModel = componentModel.trim();
|
||||||
if (componentSerial != null) {
|
if (componentSerial != null) {
|
||||||
this.componentSerial = componentSerial.trim();
|
this.componentSerial = componentSerial.trim();
|
||||||
} else {
|
} else {
|
||||||
this.componentSerial = StringUtils.EMPTY;
|
this.componentSerial = ComponentIdentifier.NOT_SPECIFIED_COMPONENT;
|
||||||
}
|
}
|
||||||
if (componentRevision != null) {
|
if (componentRevision != null) {
|
||||||
this.componentRevision = componentRevision.trim();
|
this.componentRevision = componentRevision.trim();
|
||||||
} else {
|
} else {
|
||||||
this.componentRevision = StringUtils.EMPTY;
|
this.componentRevision = ComponentIdentifier.NOT_SPECIFIED_COMPONENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
|
* @param deviceName the host machine associated with this component.
|
||||||
* @param componentManufacturer Component Manufacturer (must not be null)
|
* @param componentManufacturer Component Manufacturer (must not be null)
|
||||||
* @param componentModel Component Model (must not be null)
|
* @param componentModel Component Model (must not be null)
|
||||||
* @param componentSerial Component Serial Number (can be null)
|
* @param componentSerial Component Serial Number (can be null)
|
||||||
* @param componentRevision Component Revision or Version (can be null)
|
* @param componentRevision Component Revision or Version (can be null)
|
||||||
* @param componentClass Component Class (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 componentModel,
|
||||||
final String componentSerial,
|
final String componentSerial,
|
||||||
final String componentRevision,
|
final String componentRevision,
|
||||||
final String componentClass) {
|
final String componentClass) {
|
||||||
if (isComplete(
|
this(deviceName, componentManufacturer, componentModel,
|
||||||
componentManufacturer,
|
componentSerial, componentRevision);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (componentClass != null) {
|
this.componentClass = Objects.requireNonNullElse(componentClass, StringUtils.EMPTY);
|
||||||
this.componentClass = componentClass;
|
|
||||||
} else {
|
|
||||||
this.componentClass = StringUtils.EMPTY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,4 +146,44 @@ public class ComponentInfo implements Serializable {
|
|||||||
return (StringUtils.isEmpty(componentManufacturer)
|
return (StringUtils.isEmpty(componentManufacturer)
|
||||||
|| StringUtils.isEmpty(componentModel));
|
|| 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.
|
* Store information about the Portal into the database.
|
||||||
*/
|
*/
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "PortalInfo")
|
@Table(name = "PortalInfo")
|
||||||
@Access(AccessType.FIELD)
|
@Access(AccessType.FIELD)
|
||||||
public class PortalInfo {
|
public class PortalInfo {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@Getter
|
|
||||||
@Column
|
@Column
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
@Getter
|
|
||||||
@Column(unique = true, nullable = false)
|
@Column(unique = true, nullable = false)
|
||||||
private String name;
|
private String name;
|
||||||
@Getter
|
|
||||||
@Column
|
@Column
|
||||||
private InetAddress ipAddress;
|
private InetAddress ipAddress;
|
||||||
@Getter
|
|
||||||
@Column
|
@Column
|
||||||
private int port = 0;
|
private int port = 0;
|
||||||
@Getter
|
|
||||||
@Column
|
@Column
|
||||||
private String context;
|
private String context;
|
||||||
|
|
||||||
@ -57,14 +53,14 @@ public class PortalInfo {
|
|||||||
/**
|
/**
|
||||||
* Stores the address of the portal.
|
* 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) {
|
public void setIpAddress(final InetAddress inetAddress) {
|
||||||
if (newip == null) {
|
if (inetAddress == null) {
|
||||||
throw new IllegalArgumentException("setIpAddress input was 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.
|
* @throws UnknownHostException For problems resolving or storing the host.
|
||||||
*/
|
*/
|
||||||
public void setIpAddress(final String host) throws UnknownHostException {
|
public void setIpAddress(final String host) throws UnknownHostException {
|
||||||
ipAddress = InetAddress.getByName(host);
|
this.ipAddress = InetAddress.getByName(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the port of the portal.
|
* 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;
|
final int upperBound = 65535;
|
||||||
if (newport > 0 && newport <= upperBound) {
|
if (port > 0 && port <= upperBound) {
|
||||||
port = newport;
|
this.port = port;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Failed to store portal port. Provided number was"
|
throw new IllegalArgumentException("Failed to store portal port. Provided number was"
|
||||||
+ " outside of valid range (1 - " + upperBound + ")");
|
+ " outside of valid range (1 - " + upperBound + ")");
|
||||||
|
@ -28,8 +28,8 @@ import java.util.Objects;
|
|||||||
* OS, and TPM information.
|
* OS, and TPM information.
|
||||||
*/
|
*/
|
||||||
@Log4j2
|
@Log4j2
|
||||||
@Getter
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
@Entity
|
@Entity
|
||||||
public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
|||||||
return hardwareInfo;
|
return hardwareInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setNetworkInfo(NetworkInfo networkInfo) {
|
private void setNetworkInfo(final NetworkInfo networkInfo) {
|
||||||
if (networkInfo == null) {
|
if (networkInfo == null) {
|
||||||
log.error("NetworkInfo cannot be null");
|
log.error("NetworkInfo cannot be null");
|
||||||
throw new NullPointerException("network info");
|
throw new NullPointerException("network info");
|
||||||
@ -204,7 +204,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
|||||||
this.networkInfo = networkInfo;
|
this.networkInfo = networkInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setOSInfo(OSInfo osInfo) {
|
private void setOSInfo(final OSInfo osInfo) {
|
||||||
if (osInfo == null) {
|
if (osInfo == null) {
|
||||||
log.error("OSInfo cannot be null");
|
log.error("OSInfo cannot be null");
|
||||||
throw new NullPointerException("os info");
|
throw new NullPointerException("os info");
|
||||||
@ -212,7 +212,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
|||||||
this.osInfo = osInfo;
|
this.osInfo = osInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFirmwareInfo(FirmwareInfo firmwareInfo) {
|
private void setFirmwareInfo(final FirmwareInfo firmwareInfo) {
|
||||||
if (firmwareInfo == null) {
|
if (firmwareInfo == null) {
|
||||||
log.error("FirmwareInfo cannot be null");
|
log.error("FirmwareInfo cannot be null");
|
||||||
throw new NullPointerException("firmware info");
|
throw new NullPointerException("firmware info");
|
||||||
@ -220,7 +220,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
|||||||
this.firmwareInfo = firmwareInfo;
|
this.firmwareInfo = firmwareInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setHardwareInfo(HardwareInfo hardwareInfo) {
|
private void setHardwareInfo(final HardwareInfo hardwareInfo) {
|
||||||
if (hardwareInfo == null) {
|
if (hardwareInfo == null) {
|
||||||
log.error("HardwareInfo cannot be null");
|
log.error("HardwareInfo cannot be null");
|
||||||
throw new NullPointerException("hardware info");
|
throw new NullPointerException("hardware info");
|
||||||
@ -228,7 +228,7 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
|
|||||||
this.hardwareInfo = hardwareInfo;
|
this.hardwareInfo = hardwareInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTPMInfo(TPMInfo tpmInfo) {
|
private void setTPMInfo(final TPMInfo tpmInfo) {
|
||||||
this.tpmInfo = tpmInfo;
|
this.tpmInfo = tpmInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,11 @@ public class AbstractProcessor {
|
|||||||
@Getter
|
@Getter
|
||||||
private PolicyRepository policyRepository;
|
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,
|
public AbstractProcessor(final PrivateKey privateKey,
|
||||||
final int validDays) {
|
final int validDays) {
|
||||||
this.privateKey = privateKey;
|
this.privateKey = privateKey;
|
||||||
@ -64,6 +69,7 @@ public class AbstractProcessor {
|
|||||||
* @param endorsementCredential the endorsement credential
|
* @param endorsementCredential the endorsement credential
|
||||||
* @param platformCredentials the set of platform credentials
|
* @param platformCredentials the set of platform credentials
|
||||||
* @param deviceName The host name used in the subject alternative name
|
* @param deviceName The host name used in the subject alternative name
|
||||||
|
* @param acaCertificate object used to create credential
|
||||||
* @return identity credential
|
* @return identity credential
|
||||||
*/
|
*/
|
||||||
protected X509Certificate generateCredential(final PublicKey publicKey,
|
protected X509Certificate generateCredential(final PublicKey publicKey,
|
||||||
@ -159,7 +165,7 @@ public class AbstractProcessor {
|
|||||||
* @param endorsementCredential an endorsement credential to check if platform credentials
|
* @param endorsementCredential an endorsement credential to check if platform credentials
|
||||||
* exist
|
* exist
|
||||||
* @param certificateRepository db connector from certificates
|
* @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(
|
protected List<PlatformCredential> parsePcsFromIdentityClaim(
|
||||||
final ProvisionerTpm2.IdentityClaim identityClaim,
|
final ProvisionerTpm2.IdentityClaim identityClaim,
|
||||||
@ -187,9 +193,11 @@ public class AbstractProcessor {
|
|||||||
/**
|
/**
|
||||||
* Gets the Endorsement Credential from the DB given the EK public key.
|
* Gets the Endorsement Credential from the DB given the EK public key.
|
||||||
* @param ekPublicKey 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
|
* @return the Endorsement credential, if found, otherwise null
|
||||||
*/
|
*/
|
||||||
private EndorsementCredential getEndorsementCredential(final PublicKey ekPublicKey,
|
private EndorsementCredential getEndorsementCredential(
|
||||||
|
final PublicKey ekPublicKey,
|
||||||
final CertificateRepository certificateRepository) {
|
final CertificateRepository certificateRepository) {
|
||||||
log.debug("Searching for endorsement credential based on public key: " + ekPublicKey);
|
log.debug("Searching for endorsement credential based on public key: " + ekPublicKey);
|
||||||
|
|
||||||
@ -220,6 +228,7 @@ public class AbstractProcessor {
|
|||||||
* Helper method to create an {@link IssuedAttestationCertificate} object, set its
|
* Helper method to create an {@link IssuedAttestationCertificate} object, set its
|
||||||
* corresponding device and persist it.
|
* corresponding device and persist it.
|
||||||
*
|
*
|
||||||
|
* @param certificateRepository db store manager for certificates
|
||||||
* @param derEncodedAttestationCertificate the byte array representing the Attestation
|
* @param derEncodedAttestationCertificate the byte array representing the Attestation
|
||||||
* certificate
|
* certificate
|
||||||
* @param endorsementCredential the endorsement credential used to generate the AC
|
* @param endorsementCredential the endorsement credential used to generate the AC
|
||||||
|
@ -37,8 +37,11 @@ public class CertificateRequestProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
|
* @param supplyChainValidationService object that is used to run provisioning
|
||||||
* @param certificateRepository db connector for all certificates.
|
* @param certificateRepository db connector for all certificates.
|
||||||
* @param deviceRepository database connector for Devices.
|
* @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 validDays int for the time in which a certificate is valid.
|
||||||
* @param tpm2ProvisionerStateRepository db connector for provisioner state.
|
* @param tpm2ProvisionerStateRepository db connector for provisioner state.
|
||||||
*/
|
*/
|
||||||
@ -97,7 +100,8 @@ public class CertificateRequestProcessor extends AbstractProcessor {
|
|||||||
RSAPublicKey akPub = ProvisionUtils.parsePublicKey(claim.getAkPublicArea().toByteArray());
|
RSAPublicKey akPub = ProvisionUtils.parsePublicKey(claim.getAkPublicArea().toByteArray());
|
||||||
|
|
||||||
// Get Endorsement Credential if it exists or was uploaded
|
// 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
|
// Get Platform Credentials if they exist or were uploaded
|
||||||
List<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,
|
List<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,
|
||||||
|
@ -3,18 +3,24 @@ package hirs.attestationca.persist.provision;
|
|||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
|
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
|
||||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
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.DeviceRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.PolicyRepository;
|
import hirs.attestationca.persist.entity.manager.PolicyRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
|
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
|
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.TPM2ProvisionerStateRepository;
|
import hirs.attestationca.persist.entity.manager.TPM2ProvisionerStateRepository;
|
||||||
import hirs.attestationca.persist.entity.tpm.TPM2ProvisionerState;
|
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.Device;
|
||||||
import hirs.attestationca.persist.entity.userdefined.PolicySettings;
|
import hirs.attestationca.persist.entity.userdefined.PolicySettings;
|
||||||
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
|
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
|
||||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary;
|
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.EndorsementCredential;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
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.FirmwareInfo;
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
|
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.exceptions.IdentityProcessingException;
|
||||||
import hirs.attestationca.persist.provision.helper.ProvisionUtils;
|
import hirs.attestationca.persist.provision.helper.ProvisionUtils;
|
||||||
import hirs.attestationca.persist.service.SupplyChainValidationService;
|
import hirs.attestationca.persist.service.SupplyChainValidationService;
|
||||||
|
import hirs.attestationca.persist.validation.SupplyChainCredentialValidator;
|
||||||
import hirs.utils.HexUtils;
|
import hirs.utils.HexUtils;
|
||||||
import hirs.utils.SwidResource;
|
import hirs.utils.SwidResource;
|
||||||
import hirs.utils.enums.DeviceInfoEnums;
|
import hirs.utils.enums.DeviceInfoEnums;
|
||||||
@ -70,17 +77,21 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
private SupplyChainValidationService supplyChainValidationService;
|
private SupplyChainValidationService supplyChainValidationService;
|
||||||
private CertificateRepository certificateRepository;
|
private CertificateRepository certificateRepository;
|
||||||
|
private ComponentResultRepository componentResultRepository;
|
||||||
|
private ComponentInfoRepository componentInfoRepository;
|
||||||
private ReferenceManifestRepository referenceManifestRepository;
|
private ReferenceManifestRepository referenceManifestRepository;
|
||||||
private ReferenceDigestValueRepository referenceDigestValueRepository;
|
private ReferenceDigestValueRepository referenceDigestValueRepository;
|
||||||
private DeviceRepository deviceRepository;
|
private DeviceRepository deviceRepository;
|
||||||
private TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
|
private TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public IdentityClaimProcessor(
|
public IdentityClaimProcessor(
|
||||||
final SupplyChainValidationService supplyChainValidationService,
|
final SupplyChainValidationService supplyChainValidationService,
|
||||||
final CertificateRepository certificateRepository,
|
final CertificateRepository certificateRepository,
|
||||||
|
final ComponentResultRepository componentResultRepository,
|
||||||
|
final ComponentInfoRepository componentInfoRepository,
|
||||||
final ReferenceManifestRepository referenceManifestRepository,
|
final ReferenceManifestRepository referenceManifestRepository,
|
||||||
final ReferenceDigestValueRepository referenceDigestValueRepository,
|
final ReferenceDigestValueRepository referenceDigestValueRepository,
|
||||||
final DeviceRepository deviceRepository,
|
final DeviceRepository deviceRepository,
|
||||||
@ -88,6 +99,8 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
|||||||
final PolicyRepository policyRepository) {
|
final PolicyRepository policyRepository) {
|
||||||
this.supplyChainValidationService = supplyChainValidationService;
|
this.supplyChainValidationService = supplyChainValidationService;
|
||||||
this.certificateRepository = certificateRepository;
|
this.certificateRepository = certificateRepository;
|
||||||
|
this.componentResultRepository = componentResultRepository;
|
||||||
|
this.componentInfoRepository = componentInfoRepository;
|
||||||
this.referenceManifestRepository = referenceManifestRepository;
|
this.referenceManifestRepository = referenceManifestRepository;
|
||||||
this.referenceDigestValueRepository = referenceDigestValueRepository;
|
this.referenceDigestValueRepository = referenceDigestValueRepository;
|
||||||
this.deviceRepository = deviceRepository;
|
this.deviceRepository = deviceRepository;
|
||||||
@ -187,7 +200,9 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
|||||||
// Parse and save device info
|
// Parse and save device info
|
||||||
Device device = processDeviceInfo(claim);
|
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
|
// There are situations in which the claim is sent with no PCs
|
||||||
// or a PC from the tpm which will be deprecated
|
// or a PC from the tpm which will be deprecated
|
||||||
// this is to check what is in the platform object and pull
|
// this is to check what is in the platform object and pull
|
||||||
@ -203,9 +218,21 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
platformCredentials.addAll(tempList);
|
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
|
// perform supply chain validation
|
||||||
SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain(
|
SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain(
|
||||||
endorsementCredential, platformCredentials, device);
|
endorsementCredential, platformCredentials, device,
|
||||||
|
componentInfoRepository.findByDeviceName(device.getName()));
|
||||||
device.setSummaryId(summary.getId().toString());
|
device.setSummaryId(summary.getId().toString());
|
||||||
// update the validation result in the device
|
// update the validation result in the device
|
||||||
AppraisalStatus.Status validationResult = summary.getOverallValidationResult();
|
AppraisalStatus.Status validationResult = summary.getOverallValidationResult();
|
||||||
@ -231,7 +258,12 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
log.info("Processing Device Info Report");
|
log.info("Processing Device Info Report");
|
||||||
// store device and 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) {
|
if (device == null) {
|
||||||
device = new Device(deviceInfoReport);
|
device = new Device(deviceInfoReport);
|
||||||
}
|
}
|
||||||
@ -302,7 +334,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
|||||||
pcrValues = dv.getPcrslist().toStringUtf8();
|
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",
|
String defaultClientName = String.format("%s_%s",
|
||||||
dv.getHw().getManufacturer(),
|
dv.getHw().getManufacturer(),
|
||||||
dv.getHw().getProductName());
|
dv.getHw().getProductName());
|
||||||
@ -314,7 +346,6 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
|||||||
Pattern pattern = Pattern.compile("([^\\s]+(\\.(?i)(rimpcr|rimel|bin|log))$)");
|
Pattern pattern = Pattern.compile("([^\\s]+(\\.(?i)(rimpcr|rimel|bin|log))$)");
|
||||||
Matcher matcher;
|
Matcher matcher;
|
||||||
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
|
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
|
||||||
// List<ReferenceManifest> listOfSavedRims = new LinkedList<>();
|
|
||||||
|
|
||||||
if (dv.getLogfileCount() > 0) {
|
if (dv.getLogfileCount() > 0) {
|
||||||
for (ByteString logFile : dv.getLogfileList()) {
|
for (ByteString logFile : dv.getLogfileList()) {
|
||||||
@ -424,11 +455,9 @@ public class IdentityClaimProcessor extends AbstractProcessor {
|
|||||||
dbSupport.setUpdated(true);
|
dbSupport.setUpdated(true);
|
||||||
dbSupport.setAssociatedRim(dbBaseRim.getId());
|
dbSupport.setAssociatedRim(dbBaseRim.getId());
|
||||||
this.referenceManifestRepository.save(dbSupport);
|
this.referenceManifestRepository.save(dbSupport);
|
||||||
// listOfSavedRims.add(dbSupport);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.referenceManifestRepository.save(dbBaseRim);
|
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)",
|
log.error(String.format("Patching value does not exist (%s)",
|
||||||
patchedValue));
|
patchedValue));
|
||||||
} else {
|
} else {
|
||||||
/**
|
// WIP - Until we get patch examples
|
||||||
* Until we get patch examples, this is WIP
|
|
||||||
*/
|
|
||||||
dbRdv.setPatched(true);
|
dbRdv.setPatched(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (CertificateException cEx) {
|
} catch (CertificateException | NoSuchAlgorithmException | IOException ex) {
|
||||||
log.error(cEx);
|
log.error(ex);
|
||||||
} catch (NoSuchAlgorithmException noSaEx) {
|
|
||||||
log.error(noSaEx);
|
|
||||||
} catch (IOException ioEx) {
|
|
||||||
log.error(ioEx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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()) {
|
||||||
|
|
||||||
|
componentResult = new ComponentResult(platformCredential.getPlatformSerial(),
|
||||||
|
platformCredential.getSerialNumber().toString(),
|
||||||
|
platformCredential.getPlatformChainType(),
|
||||||
|
componentIdentifier);
|
||||||
|
componentResult.setFailedValidation(false);
|
||||||
|
componentResultRepository.save(componentResult);
|
||||||
|
componentResults++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return componentResults;
|
||||||
|
}
|
||||||
|
|
||||||
private List<PlatformCredential> getPlatformCredentials(final CertificateRepository certificateRepository,
|
private int handleDeviceComponents(final String hostName, final String paccorString) {
|
||||||
final EndorsementCredential ec) {
|
int deviceComponents = 0 ;
|
||||||
List<PlatformCredential> credentials = null;
|
Map<Integer, ComponentInfo> componentInfoMap = new HashMap<>();
|
||||||
|
try {
|
||||||
|
List<ComponentInfo> componentInfos = SupplyChainCredentialValidator
|
||||||
|
.getComponentInfoFromPaccorOutput(hostName, paccorString);
|
||||||
|
|
||||||
if (ec == null) {
|
// check the DB for like component infos
|
||||||
log.warn("Cannot look for platform credential(s). Endorsement credential was null.");
|
List<ComponentInfo> dbComponentInfos = this.componentInfoRepository.findByDeviceName(hostName);
|
||||||
} else {
|
dbComponentInfos.stream().forEach((infos) -> {
|
||||||
log.debug("Searching for platform credential(s) based on holder serial number: "
|
componentInfoMap.put(infos.hashCode(), infos);
|
||||||
+ ec.getSerialNumber());
|
});
|
||||||
credentials = certificateRepository.getByHolderSerialNumber(ec.getSerialNumber());
|
|
||||||
if (credentials == null || credentials.isEmpty()) {
|
for (ComponentInfo componentInfo : dbComponentInfos) {
|
||||||
log.warn("No platform credential(s) found");
|
if (componentInfoMap.containsKey(componentInfo.hashCode())) {
|
||||||
} else {
|
componentInfos.remove(componentInfo);
|
||||||
log.debug("Platform Credential(s) found: " + credentials.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return credentials;
|
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.EndorsementCredential;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
import java.util.List;
|
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 hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.ASN1ObjectIdentifier;
|
||||||
import org.bouncycastle.asn1.ASN1OctetString;
|
import org.bouncycastle.asn1.ASN1OctetString;
|
||||||
import org.bouncycastle.asn1.DEROctetString;
|
import org.bouncycastle.asn1.DEROctetString;
|
||||||
@ -42,13 +40,13 @@ public final class IssuedCertificateAttributeHelper {
|
|||||||
/**
|
/**
|
||||||
* Object Identifier TCPA at TPM ID Label.
|
* 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);
|
new ASN1ObjectIdentifier(TPM_ID_LABEL_OID);
|
||||||
/**
|
/**
|
||||||
* The extended key usage extension.
|
* The extended key usage extension.
|
||||||
*/
|
*/
|
||||||
public final static Extension EXTENDED_KEY_USAGE_EXTENSION;
|
public static final Extension EXTENDED_KEY_USAGE_EXTENSION;
|
||||||
private final static ASN1ObjectIdentifier TCG_KP_AIK_CERTIFICATE_ATTRIBUTE =
|
private static final ASN1ObjectIdentifier TCG_KP_AIK_CERTIFICATE_ATTRIBUTE =
|
||||||
new ASN1ObjectIdentifier("2.23.133.8.3");
|
new ASN1ObjectIdentifier("2.23.133.8.3");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -4,6 +4,7 @@ import hirs.attestationca.persist.DBManagerException;
|
|||||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
import hirs.attestationca.persist.entity.ArchivableEntity;
|
||||||
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
|
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
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.ComponentResultRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.PolicyRepository;
|
import hirs.attestationca.persist.entity.manager.PolicyRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
|
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.PolicySettings;
|
||||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
|
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
|
||||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary;
|
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.EndorsementCredential;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
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.EventLogMeasurements;
|
||||||
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
|
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
|
||||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||||
import hirs.attestationca.persist.validation.PcrValidator;
|
import hirs.attestationca.persist.validation.PcrValidator;
|
||||||
import hirs.attestationca.persist.validation.SupplyChainCredentialValidator;
|
import hirs.attestationca.persist.validation.SupplyChainCredentialValidator;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -32,8 +37,7 @@ import java.util.Iterator;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
import org.apache.logging.log4j.Level;
|
|
||||||
|
|
||||||
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
|
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
|
||||||
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
|
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
|
||||||
@ -47,9 +51,11 @@ public class SupplyChainValidationService {
|
|||||||
private ReferenceManifestRepository referenceManifestRepository;
|
private ReferenceManifestRepository referenceManifestRepository;
|
||||||
private ReferenceDigestValueRepository referenceDigestValueRepository;
|
private ReferenceDigestValueRepository referenceDigestValueRepository;
|
||||||
private ComponentResultRepository componentResultRepository;
|
private ComponentResultRepository componentResultRepository;
|
||||||
|
private ComponentAttributeRepository componentAttributeRepository;
|
||||||
private CertificateRepository certificateRepository;
|
private CertificateRepository certificateRepository;
|
||||||
private SupplyChainValidationRepository supplyChainValidationRepository;
|
private SupplyChainValidationRepository supplyChainValidationRepository;
|
||||||
private SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository;
|
private SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository;
|
||||||
|
private UUID provisionSessionId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -70,6 +76,7 @@ public class SupplyChainValidationService {
|
|||||||
final PolicyRepository policyRepository,
|
final PolicyRepository policyRepository,
|
||||||
final CertificateRepository certificateRepository,
|
final CertificateRepository certificateRepository,
|
||||||
final ComponentResultRepository componentResultRepository,
|
final ComponentResultRepository componentResultRepository,
|
||||||
|
final ComponentAttributeRepository componentAttributeRepository,
|
||||||
final ReferenceManifestRepository referenceManifestRepository,
|
final ReferenceManifestRepository referenceManifestRepository,
|
||||||
final SupplyChainValidationRepository supplyChainValidationRepository,
|
final SupplyChainValidationRepository supplyChainValidationRepository,
|
||||||
final SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository,
|
final SupplyChainValidationSummaryRepository supplyChainValidationSummaryRepository,
|
||||||
@ -78,6 +85,7 @@ public class SupplyChainValidationService {
|
|||||||
this.policyRepository = policyRepository;
|
this.policyRepository = policyRepository;
|
||||||
this.certificateRepository = certificateRepository;
|
this.certificateRepository = certificateRepository;
|
||||||
this.componentResultRepository = componentResultRepository;
|
this.componentResultRepository = componentResultRepository;
|
||||||
|
this.componentAttributeRepository = componentAttributeRepository;
|
||||||
this.referenceManifestRepository = referenceManifestRepository;
|
this.referenceManifestRepository = referenceManifestRepository;
|
||||||
this.supplyChainValidationRepository = supplyChainValidationRepository;
|
this.supplyChainValidationRepository = supplyChainValidationRepository;
|
||||||
this.supplyChainValidationSummaryRepository = supplyChainValidationSummaryRepository;
|
this.supplyChainValidationSummaryRepository = supplyChainValidationSummaryRepository;
|
||||||
@ -92,13 +100,16 @@ public class SupplyChainValidationService {
|
|||||||
* @param ec The endorsement credential from the identity request.
|
* @param ec The endorsement credential from the identity request.
|
||||||
* @param pcs The platform credentials from the identity request.
|
* @param pcs The platform credentials from the identity request.
|
||||||
* @param device The device to be validated.
|
* @param device The device to be validated.
|
||||||
|
* @param componentInfos list of components from the device
|
||||||
* @return A summary of the validation results.
|
* @return A summary of the validation results.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("methodlength")
|
@SuppressWarnings("methodlength")
|
||||||
public SupplyChainValidationSummary validateSupplyChain(final EndorsementCredential ec,
|
public SupplyChainValidationSummary validateSupplyChain(final EndorsementCredential ec,
|
||||||
final List<PlatformCredential> pcs,
|
final List<PlatformCredential> pcs,
|
||||||
final Device device) {
|
final Device device,
|
||||||
|
final List<ComponentInfo> componentInfos) {
|
||||||
boolean acceptExpiredCerts = getPolicySettings().isExpiredCertificateValidationEnabled();
|
boolean acceptExpiredCerts = getPolicySettings().isExpiredCertificateValidationEnabled();
|
||||||
|
provisionSessionId = UUID.randomUUID();
|
||||||
PlatformCredential baseCredential = null;
|
PlatformCredential baseCredential = null;
|
||||||
SupplyChainValidation platformScv = null;
|
SupplyChainValidation platformScv = null;
|
||||||
SupplyChainValidation basePlatformScv = null;
|
SupplyChainValidation basePlatformScv = null;
|
||||||
@ -205,6 +216,8 @@ public class SupplyChainValidationService {
|
|||||||
null, Level.ERROR));
|
null, Level.ERROR));
|
||||||
} else {
|
} else {
|
||||||
if (chkDeltas) {
|
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());
|
aes.addAll(basePlatformScv.getCertificatesUsed());
|
||||||
Iterator<PlatformCredential> it = pcs.iterator();
|
Iterator<PlatformCredential> it = pcs.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
@ -220,16 +233,23 @@ public class SupplyChainValidationService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// validate attributes for a single base platform certificate
|
||||||
aes.add(baseCredential);
|
aes.add(baseCredential);
|
||||||
validations.remove(platformScv);
|
validations.remove(platformScv);
|
||||||
// if there are no deltas, just check base credential
|
// if there are no deltas, just check base credential
|
||||||
platformScv = ValidationService.evaluatePCAttributesStatus(
|
platformScv = ValidationService.evaluatePCAttributesStatus(
|
||||||
baseCredential, device.getDeviceInfo(), ec,
|
baseCredential, device.getDeviceInfo(), ec,
|
||||||
certificateRepository, componentResultRepository);
|
certificateRepository, componentResultRepository,
|
||||||
|
componentAttributeRepository, componentInfos, provisionSessionId);
|
||||||
validations.add(new SupplyChainValidation(
|
validations.add(new SupplyChainValidation(
|
||||||
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
|
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
|
||||||
platformScv.getValidationResult(), aes, platformScv.getMessage()));
|
platformScv.getValidationResult(), aes, platformScv.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateComponentStatus(componentResultRepository
|
||||||
|
.findByCertificateSerialNumberAndBoardSerialNumber(
|
||||||
|
baseCredential.getSerialNumber().toString(),
|
||||||
|
baseCredential.getPlatformSerial()));
|
||||||
}
|
}
|
||||||
if (!attrErrorMessage.isEmpty()) {
|
if (!attrErrorMessage.isEmpty()) {
|
||||||
//combine platform and platform attributes
|
//combine platform and platform attributes
|
||||||
@ -252,7 +272,7 @@ public class SupplyChainValidationService {
|
|||||||
log.info("The validation finished, summarizing...");
|
log.info("The validation finished, summarizing...");
|
||||||
// Generate validation summary, save it, and return it.
|
// Generate validation summary, save it, and return it.
|
||||||
SupplyChainValidationSummary summary
|
SupplyChainValidationSummary summary
|
||||||
= new SupplyChainValidationSummary(device, validations);
|
= new SupplyChainValidationSummary(device, validations, provisionSessionId);
|
||||||
try {
|
try {
|
||||||
supplyChainValidationSummaryRepository.save(summary);
|
supplyChainValidationSummaryRepository.save(summary);
|
||||||
} catch (DBManagerException dbMEx) {
|
} catch (DBManagerException dbMEx) {
|
||||||
@ -374,4 +394,25 @@ public class SupplyChainValidationService {
|
|||||||
}
|
}
|
||||||
return defaultSettings;
|
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.ArchivableEntity;
|
||||||
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
|
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
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.ComponentResultRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
|
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
|
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.ReferenceManifest;
|
||||||
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
|
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
|
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.EndorsementCredential;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
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.entity.userdefined.report.DeviceInfoReport;
|
||||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||||
import hirs.attestationca.persist.validation.CertificateAttributeScvValidator;
|
import hirs.attestationca.persist.validation.CertificateAttributeScvValidator;
|
||||||
@ -37,6 +38,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
public class ValidationService {
|
public class ValidationService {
|
||||||
@ -104,7 +106,10 @@ public class ValidationService {
|
|||||||
final PlatformCredential pc, final DeviceInfoReport deviceInfoReport,
|
final PlatformCredential pc, final DeviceInfoReport deviceInfoReport,
|
||||||
final EndorsementCredential ec,
|
final EndorsementCredential ec,
|
||||||
final CertificateRepository certificateRepository,
|
final CertificateRepository certificateRepository,
|
||||||
final ComponentResultRepository componentResultRepository) {
|
final ComponentResultRepository componentResultRepository,
|
||||||
|
final ComponentAttributeRepository componentAttributeRepository,
|
||||||
|
final List<ComponentInfo> componentInfos,
|
||||||
|
final UUID provisionSessionId) {
|
||||||
final SupplyChainValidation.ValidationType validationType
|
final SupplyChainValidation.ValidationType validationType
|
||||||
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
|
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
|
||||||
|
|
||||||
@ -116,7 +121,9 @@ public class ValidationService {
|
|||||||
}
|
}
|
||||||
log.info("Validating platform credential attributes");
|
log.info("Validating platform credential attributes");
|
||||||
AppraisalStatus result = CredentialValidator.
|
AppraisalStatus result = CredentialValidator.
|
||||||
validatePlatformCredentialAttributes(pc, deviceInfoReport, ec);
|
validatePlatformCredentialAttributes(pc, deviceInfoReport, ec,
|
||||||
|
componentResultRepository, componentAttributeRepository,
|
||||||
|
componentInfos, provisionSessionId);
|
||||||
switch (result.getAppStatus()) {
|
switch (result.getAppStatus()) {
|
||||||
case PASS:
|
case PASS:
|
||||||
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
|
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,
|
||||||
@ -126,10 +133,6 @@ public class ValidationService {
|
|||||||
pc.setComponentFailures(result.getAdditionalInfo());
|
pc.setComponentFailures(result.getAdditionalInfo());
|
||||||
pc.setComponentFailureMessage(result.getMessage());
|
pc.setComponentFailureMessage(result.getMessage());
|
||||||
certificateRepository.save(pc);
|
certificateRepository.save(pc);
|
||||||
for (ComponentResult componentResult
|
|
||||||
: CertificateAttributeScvValidator.getComponentResultList()) {
|
|
||||||
componentResultRepository.save(componentResult);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
|
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
|
||||||
result.getMessage(), pc, Level.WARN);
|
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.model.Vendor;
|
||||||
import com.github.marandus.pciid.service.PciIdsDatabase;
|
import com.github.marandus.pciid.service.PciIdsDatabase;
|
||||||
import com.google.common.base.Strings;
|
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.ComponentIdentifier;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
|
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.bouncycastle.asn1.ASN1UTF8String;
|
import org.bouncycastle.asn1.ASN1UTF8String;
|
||||||
import org.bouncycastle.asn1.DERUTF8String;
|
import org.bouncycastle.asn1.DERUTF8String;
|
||||||
|
|
||||||
@ -23,6 +26,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Provide Java access to PCI IDs.
|
* Provide Java access to PCI IDs.
|
||||||
*/
|
*/
|
||||||
|
@Log4j2
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public final class PciIds {
|
public final class PciIds {
|
||||||
/**
|
/**
|
||||||
@ -52,6 +56,7 @@ public final class PciIds {
|
|||||||
String dbFile = null;
|
String dbFile = null;
|
||||||
for (final String path : PCI_IDS_PATH) {
|
for (final String path : PCI_IDS_PATH) {
|
||||||
if ((new File(path)).exists()) {
|
if ((new File(path)).exists()) {
|
||||||
|
log.info("PCI IDs file was found {}", path);
|
||||||
dbFile = path;
|
dbFile = path;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -113,6 +118,23 @@ public final class PciIds {
|
|||||||
return newList;
|
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.
|
* Translate Vendor and Device IDs, if found, in ComponentIdentifierV2 objects.
|
||||||
* It will only translate ID values, any other value will pass through.
|
* It will only translate ID values, any other value will pass through.
|
||||||
@ -149,6 +171,23 @@ public final class PciIds {
|
|||||||
return newComponent;
|
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.
|
* 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.
|
* If any part of this fails, return the original manufacturer value.
|
||||||
@ -166,6 +205,23 @@ public final class PciIds {
|
|||||||
return manufacturer;
|
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.
|
* 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.
|
* 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;
|
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;
|
package hirs.attestationca.persist.validation;
|
||||||
|
|
||||||
import hirs.attestationca.persist.entity.ArchivableEntity;
|
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.SupplyChainValidation;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
|
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
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.ComponentIdentifier;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
|
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
|
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
|
||||||
@ -43,15 +46,7 @@ import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
|
|||||||
@Log4j2
|
@Log4j2
|
||||||
public class CertificateAttributeScvValidator extends SupplyChainCredentialValidator {
|
public class CertificateAttributeScvValidator extends SupplyChainCredentialValidator {
|
||||||
|
|
||||||
private static List<ComponentResult> componentResultList = new LinkedList<>();
|
private static final String LC_UNKNOWN = "unknown";
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for the list of components to verify.
|
|
||||||
* @return a collection of components
|
|
||||||
*/
|
|
||||||
public static List<ComponentResult> getComponentResultList() {
|
|
||||||
return Collections.unmodifiableList(componentResultList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the delta credential's attributes are valid.
|
* Checks if the delta credential's attributes are valid.
|
||||||
@ -97,7 +92,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
List<ComponentIdentifier> origPcComponents
|
List<ComponentIdentifier> origPcComponents
|
||||||
= new LinkedList<>(basePlatformCredential.getComponentIdentifiers());
|
= new LinkedList<>(basePlatformCredential.getComponentIdentifiers());
|
||||||
|
|
||||||
return validateDeltaAttributesChainV2p0(deltaPlatformCredential.getId(),
|
return validateDeltaAttributesChainV2p0(
|
||||||
deviceInfoReport, deltaMapping, origPcComponents);
|
deviceInfoReport, deltaMapping, origPcComponents);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +185,6 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
+ " did not match the Certificate's Serial Number";
|
+ " did not match the Certificate's Serial Number";
|
||||||
log.error(message);
|
log.error(message);
|
||||||
status = new AppraisalStatus(FAIL, message);
|
status = new AppraisalStatus(FAIL, message);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,16 +192,23 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates device info report against the new platform credential.
|
* Validates device info report against the new platform credential.
|
||||||
* @param platformCredential the Platform Credential
|
* @param platformCredential the Platform Credential
|
||||||
* @param deviceInfoReport the Device Info Report
|
* @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
|
* @return either PASS or FAIL
|
||||||
*/
|
*/
|
||||||
public static AppraisalStatus validatePlatformCredentialAttributesV2p0(
|
public static AppraisalStatus validatePlatformCredentialAttributesV2p0(
|
||||||
final PlatformCredential platformCredential,
|
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;
|
boolean passesValidation = true;
|
||||||
StringBuilder resultMessage = new StringBuilder();
|
StringBuilder resultMessage = new StringBuilder();
|
||||||
|
|
||||||
@ -236,6 +237,8 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
|
|
||||||
passesValidation &= fieldValidation;
|
passesValidation &= fieldValidation;
|
||||||
|
|
||||||
|
if (!isNotSpecifiedOrUnknown(platformCredential.getVersion())
|
||||||
|
&& !isNotSpecifiedOrUnknown(hardwareInfo.getVersion())) {
|
||||||
fieldValidation = requiredPlatformCredentialFieldIsNonEmptyAndMatches(
|
fieldValidation = requiredPlatformCredentialFieldIsNonEmptyAndMatches(
|
||||||
"PlatformVersion",
|
"PlatformVersion",
|
||||||
platformCredential.getVersion(),
|
platformCredential.getVersion(),
|
||||||
@ -246,6 +249,11 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
}
|
}
|
||||||
|
|
||||||
passesValidation &= fieldValidation;
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
// check PlatformSerial against both system-serial-number and baseboard-serial-number
|
// check PlatformSerial against both system-serial-number and baseboard-serial-number
|
||||||
fieldValidation = (
|
fieldValidation = (
|
||||||
@ -291,42 +299,86 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
|
|
||||||
// There is no need to do comparisons with components that are invalid because
|
// There is no need to do comparisons with components that are invalid because
|
||||||
// they did not have a manufacturer or model.
|
// they did not have a manufacturer or model.
|
||||||
List<ComponentIdentifier> validPcComponents = allPcComponents.stream()
|
// List<ComponentIdentifier> validPcComponents = allPcComponents.stream()
|
||||||
.filter(identifier -> identifier.getComponentManufacturer() != null
|
// .filter(identifier -> identifier.getComponentManufacturer() != null
|
||||||
&& identifier.getComponentModel() != null)
|
// && identifier.getComponentModel() != null)
|
||||||
.collect(Collectors.toList());
|
// .collect(Collectors.toList());
|
||||||
|
|
||||||
String paccorOutputString = deviceInfoReport.getPaccorOutputString();
|
// String paccorOutputString = deviceInfoReport.getPaccorOutputString();
|
||||||
String unmatchedComponents;
|
// String unmatchedComponents;
|
||||||
try {
|
|
||||||
List<ComponentInfo> componentInfoList
|
// populate componentResults list
|
||||||
= getComponentInfoFromPaccorOutput(paccorOutputString);
|
List<ComponentResult> componentResults = componentResultRepository
|
||||||
unmatchedComponents = validateV2p0PlatformCredentialComponentsExpectingExactMatch(
|
.findByCertificateSerialNumberAndBoardSerialNumber(
|
||||||
platformCredential.getId(),
|
platformCredential.getSerialNumber().toString(),
|
||||||
validPcComponents, componentInfoList);
|
platformCredential.getPlatformSerial());
|
||||||
fieldValidation &= unmatchedComponents.isEmpty();
|
// first create hash map based on hashCode
|
||||||
} catch (IOException e) {
|
Map<Integer, List<ComponentInfo>> deviceHashMap = new HashMap<>();
|
||||||
final String baseErrorMessage = "Error parsing JSON output from PACCOR: ";
|
componentInfos.stream().forEach((componentInfo) -> {
|
||||||
log.error(baseErrorMessage + e.toString());
|
List<ComponentInfo> innerList;
|
||||||
log.error("PACCOR output string:\n" + paccorOutputString);
|
Integer compInfoHash = componentInfo.hashCommonElements();
|
||||||
return new AppraisalStatus(ERROR, baseErrorMessage + e.getMessage());
|
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();
|
StringBuilder additionalInfo = new StringBuilder();
|
||||||
if (!fieldValidation) {
|
if (!remainingComponentResults.isEmpty()) {
|
||||||
resultMessage.append("There are unmatched components:\n");
|
resultMessage.append(String.format("There are %d components not matched%n",
|
||||||
resultMessage.append(unmatchedComponents);
|
remainingComponentResults.size()));
|
||||||
|
resultMessage.append(String.format("\twith %d total attributes mismatched.",
|
||||||
// pass information of which ones failed in additionInfo
|
numOfAttributes));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
passesValidation &= fieldValidation;
|
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
|
* 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
|
* 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")
|
@SuppressWarnings("methodlength")
|
||||||
static AppraisalStatus validateDeltaAttributesChainV2p0(
|
static AppraisalStatus validateDeltaAttributesChainV2p0(
|
||||||
final UUID certificateId,
|
|
||||||
final DeviceInfoReport deviceInfoReport,
|
final DeviceInfoReport deviceInfoReport,
|
||||||
final Map<PlatformCredential, SupplyChainValidation> deltaMapping,
|
final Map<PlatformCredential, SupplyChainValidation> deltaMapping,
|
||||||
final List<ComponentIdentifier> origPcComponents) {
|
final List<ComponentIdentifier> origPcComponents) {
|
||||||
@ -466,10 +589,11 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
String unmatchedComponents;
|
String unmatchedComponents;
|
||||||
try {
|
try {
|
||||||
// compare based on component class
|
// 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
|
// this is what I want to rewrite
|
||||||
unmatchedComponents = validateV2PlatformCredentialAttributes(
|
unmatchedComponents = validateV2PlatformCredentialAttributes(
|
||||||
certificateId,
|
|
||||||
baseCompList,
|
baseCompList,
|
||||||
componentInfoList);
|
componentInfoList);
|
||||||
fieldValidation &= unmatchedComponents.isEmpty();
|
fieldValidation &= unmatchedComponents.isEmpty();
|
||||||
@ -505,7 +629,6 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String validateV2PlatformCredentialAttributes(
|
private static String validateV2PlatformCredentialAttributes(
|
||||||
final UUID certificateId,
|
|
||||||
final List<ComponentIdentifier> fullDeltaChainComponents,
|
final List<ComponentIdentifier> fullDeltaChainComponents,
|
||||||
final List<ComponentInfo> allDeviceInfoComponents) {
|
final List<ComponentInfo> allDeviceInfoComponents) {
|
||||||
ComponentIdentifierV2 ciV2;
|
ComponentIdentifierV2 ciV2;
|
||||||
@ -521,7 +644,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
ciV2 = (ComponentIdentifierV2) cId;
|
ciV2 = (ComponentIdentifierV2) cId;
|
||||||
if (cInfo.getComponentClass().contains(
|
if (cInfo.getComponentClass().contains(
|
||||||
ciV2.getComponentClass().getComponentIdentifier())
|
ciV2.getComponentClass().getComponentIdentifier())
|
||||||
&& isMatch(certificateId, cId, cInfo)) {
|
&& isMatch(cId, cInfo)) {
|
||||||
subCompIdList.remove(cId);
|
subCompIdList.remove(cId);
|
||||||
subCompInfoList.remove(cInfo);
|
subCompInfoList.remove(cInfo);
|
||||||
}
|
}
|
||||||
@ -716,10 +839,10 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
* **NEW** this is updated with just the unmatched components
|
* **NEW** this is updated with just the unmatched components
|
||||||
* if there are any failures, otherwise it remains unchanged.
|
* if there are any failures, otherwise it remains unchanged.
|
||||||
* @param allDeviceInfoComponents the device info report components
|
* @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(
|
private static String validateV2p0PlatformCredentialComponentsExpectingExactMatch(
|
||||||
final UUID certificateId,
|
|
||||||
final List<ComponentIdentifier> untrimmedPcComponents,
|
final List<ComponentIdentifier> untrimmedPcComponents,
|
||||||
final List<ComponentInfo> allDeviceInfoComponents) {
|
final List<ComponentInfo> allDeviceInfoComponents) {
|
||||||
// For each manufacturer listed in the platform credential, create two lists:
|
// For each manufacturer listed in the platform credential, create two lists:
|
||||||
@ -791,7 +914,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
|
|
||||||
if (first.isPresent()) {
|
if (first.isPresent()) {
|
||||||
ComponentInfo potentialMatch = first.get();
|
ComponentInfo potentialMatch = first.get();
|
||||||
if (isMatch(certificateId, pcComponent, potentialMatch)) {
|
if (isMatch(pcComponent, potentialMatch)) {
|
||||||
pcComponentsFromManufacturer.remove(pcComponent);
|
pcComponentsFromManufacturer.remove(pcComponent);
|
||||||
deviceInfoComponentsFromManufacturer.remove(potentialMatch);
|
deviceInfoComponentsFromManufacturer.remove(potentialMatch);
|
||||||
}
|
}
|
||||||
@ -819,7 +942,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
|
|
||||||
if (first.isPresent()) {
|
if (first.isPresent()) {
|
||||||
ComponentInfo potentialMatch = first.get();
|
ComponentInfo potentialMatch = first.get();
|
||||||
if (isMatch(certificateId, pcComponent, potentialMatch)) {
|
if (isMatch(pcComponent, potentialMatch)) {
|
||||||
pcComponentsFromManufacturer.remove(pcComponent);
|
pcComponentsFromManufacturer.remove(pcComponent);
|
||||||
deviceInfoComponentsFromManufacturer.remove(potentialMatch);
|
deviceInfoComponentsFromManufacturer.remove(potentialMatch);
|
||||||
}
|
}
|
||||||
@ -833,7 +956,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
= deviceInfoComponentsFromManufacturer.iterator();
|
= deviceInfoComponentsFromManufacturer.iterator();
|
||||||
while (diComponentIter.hasNext()) {
|
while (diComponentIter.hasNext()) {
|
||||||
ComponentInfo potentialMatch = diComponentIter.next();
|
ComponentInfo potentialMatch = diComponentIter.next();
|
||||||
if (isMatch(certificateId, ci, potentialMatch)) {
|
if (isMatch(ci, potentialMatch)) {
|
||||||
pcComponentsFromManufacturer.remove(ci);
|
pcComponentsFromManufacturer.remove(ci);
|
||||||
diComponentIter.remove();
|
diComponentIter.remove();
|
||||||
}
|
}
|
||||||
@ -872,13 +995,11 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
/**
|
/**
|
||||||
* Checks if the fields in the potentialMatch match the fields in the pcComponent,
|
* Checks if the fields in the potentialMatch match the fields in the pcComponent,
|
||||||
* or if the relevant field in the pcComponent is empty.
|
* or if the relevant field in the pcComponent is empty.
|
||||||
* @param certificateId the certificate id
|
|
||||||
* @param pcComponent the platform credential component
|
* @param pcComponent the platform credential component
|
||||||
* @param potentialMatch the component info from a device info report
|
* @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)
|
* @return true if the fields match exactly (null is considered the same as an empty string)
|
||||||
*/
|
*/
|
||||||
private static boolean isMatch(final UUID certificateId,
|
public static boolean isMatch(final ComponentIdentifier pcComponent,
|
||||||
final ComponentIdentifier pcComponent,
|
|
||||||
final ComponentInfo potentialMatch) {
|
final ComponentInfo potentialMatch) {
|
||||||
boolean matchesSoFar = true;
|
boolean matchesSoFar = true;
|
||||||
|
|
||||||
@ -887,49 +1008,24 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
pcComponent.getComponentManufacturer()
|
pcComponent.getComponentManufacturer()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (matchesSoFar) {
|
|
||||||
componentResultList.add(new ComponentResult(certificateId, pcComponent.hashCode(),
|
|
||||||
potentialMatch.getComponentSerial(),
|
|
||||||
pcComponent.getComponentSerial().getString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
matchesSoFar &= isMatchOrEmptyInPlatformCert(
|
matchesSoFar &= isMatchOrEmptyInPlatformCert(
|
||||||
potentialMatch.getComponentModel(),
|
potentialMatch.getComponentModel(),
|
||||||
pcComponent.getComponentModel()
|
pcComponent.getComponentModel()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (matchesSoFar) {
|
|
||||||
componentResultList.add(new ComponentResult(certificateId, pcComponent.hashCode(),
|
|
||||||
potentialMatch.getComponentSerial(),
|
|
||||||
pcComponent.getComponentSerial().getString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
matchesSoFar &= isMatchOrEmptyInPlatformCert(
|
matchesSoFar &= isMatchOrEmptyInPlatformCert(
|
||||||
potentialMatch.getComponentSerial(),
|
potentialMatch.getComponentSerial(),
|
||||||
pcComponent.getComponentSerial()
|
pcComponent.getComponentSerial()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (matchesSoFar) {
|
|
||||||
componentResultList.add(new ComponentResult(certificateId, pcComponent.hashCode(),
|
|
||||||
potentialMatch.getComponentSerial(),
|
|
||||||
pcComponent.getComponentSerial().getString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
matchesSoFar &= isMatchOrEmptyInPlatformCert(
|
matchesSoFar &= isMatchOrEmptyInPlatformCert(
|
||||||
potentialMatch.getComponentRevision(),
|
potentialMatch.getComponentRevision(),
|
||||||
pcComponent.getComponentRevision()
|
pcComponent.getComponentRevision()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (matchesSoFar) {
|
|
||||||
componentResultList.add(new ComponentResult(certificateId, pcComponent.hashCode(),
|
|
||||||
potentialMatch.getComponentSerial(),
|
|
||||||
pcComponent.getComponentSerial().getString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return matchesSoFar;
|
return matchesSoFar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the fields in the potentialMatch match the fields in the pcComponent,
|
* Checks if the fields in the potentialMatch match the fields in the pcComponent,
|
||||||
* or if the relevant field in the pcComponent is empty.
|
* 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 platformSerialNumberDescription description of the serial number for logging purposes.
|
||||||
* @param deviceInfoSerialNumbers the map of device info serial numbers
|
* @param deviceInfoSerialNumbers the map of device info serial numbers
|
||||||
* (key = description, value = serial number)
|
* (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
|
* false otherwise
|
||||||
*/
|
*/
|
||||||
private static boolean deviceInfoContainsPlatformSerialNumber(
|
private static boolean deviceInfoContainsPlatformSerialNumber(
|
||||||
@ -1090,6 +1186,22 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
|
|||||||
return false;
|
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(
|
private static boolean platformCredentialFieldMatches(
|
||||||
final String platformCredentialFieldName,
|
final String platformCredentialFieldName,
|
||||||
final String platformCredentialFieldValue,
|
final String platformCredentialFieldValue,
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package hirs.attestationca.persist.validation;
|
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.EndorsementCredential;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
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.entity.userdefined.report.DeviceInfoReport;
|
||||||
import hirs.attestationca.persist.enums.AppraisalStatus;
|
import hirs.attestationca.persist.enums.AppraisalStatus;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
@ -14,6 +17,8 @@ import java.security.cert.CertificateExpiredException;
|
|||||||
import java.security.cert.CertificateNotYetValidException;
|
import java.security.cert.CertificateNotYetValidException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Date;
|
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.ERROR;
|
||||||
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
|
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.
|
* Checks if the endorsement credential is valid.
|
||||||
*
|
*
|
||||||
* @param ec the endorsement credential to verify.
|
* @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
|
* @param acceptExpired whether or not to accept expired and not yet valid certificates
|
||||||
* as valid.
|
* as valid.
|
||||||
* @return the result of the validation.
|
* @return the result of the validation.
|
||||||
@ -160,12 +165,19 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
|
|||||||
* serial number of the platform to be validated.
|
* serial number of the platform to be validated.
|
||||||
* @param endorsementCredential The endorsement credential supplied from the same
|
* @param endorsementCredential The endorsement credential supplied from the same
|
||||||
* identity request as the platform credential.
|
* 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.
|
* @return The result of the validation.
|
||||||
*/
|
*/
|
||||||
public static AppraisalStatus validatePlatformCredentialAttributes(
|
public static AppraisalStatus validatePlatformCredentialAttributes(
|
||||||
final PlatformCredential platformCredential,
|
final PlatformCredential platformCredential,
|
||||||
final DeviceInfoReport deviceInfoReport,
|
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 ";
|
final String baseErrorMessage = "Can't validate platform credential attributes without ";
|
||||||
String message;
|
String message;
|
||||||
if (platformCredential == null) {
|
if (platformCredential == null) {
|
||||||
@ -180,6 +192,10 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
|
|||||||
message = baseErrorMessage + "an endorsement credential";
|
message = baseErrorMessage + "an endorsement credential";
|
||||||
return new AppraisalStatus(FAIL, message);
|
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
|
// Quick, early check if the platform credential references the endorsement credential
|
||||||
if (!endorsementCredential.getSerialNumber()
|
if (!endorsementCredential.getSerialNumber()
|
||||||
@ -192,7 +208,8 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
|
|||||||
String credentialType = platformCredential.getCredentialType();
|
String credentialType = platformCredential.getCredentialType();
|
||||||
if (PlatformCredential.CERTIFICATE_TYPE_2_0.equals(credentialType)) {
|
if (PlatformCredential.CERTIFICATE_TYPE_2_0.equals(credentialType)) {
|
||||||
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV2p0(
|
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV2p0(
|
||||||
platformCredential, deviceInfoReport);
|
platformCredential, deviceInfoReport, componentResultRepository,
|
||||||
|
componentAttributeRepository, componentInfos, provisionSessionId);
|
||||||
}
|
}
|
||||||
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV1p2(
|
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV1p2(
|
||||||
platformCredential, deviceInfoReport);
|
platformCredential, deviceInfoReport);
|
||||||
|
@ -7,7 +7,6 @@ import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.util.Strings;
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
import org.bouncycastle.cert.CertException;
|
import org.bouncycastle.cert.CertException;
|
||||||
import org.bouncycastle.cert.X509AttributeCertificateHolder;
|
import org.bouncycastle.cert.X509AttributeCertificateHolder;
|
||||||
@ -32,7 +31,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -93,15 +91,13 @@ public class SupplyChainCredentialValidator {
|
|||||||
} else if (trustStore.size() == 0) {
|
} else if (trustStore.size() == 0) {
|
||||||
throw new SupplyChainValidatorException("Truststore is empty");
|
throw new SupplyChainValidatorException("Truststore is empty");
|
||||||
}
|
}
|
||||||
} catch (KeyStoreException e) {
|
} catch (KeyStoreException ksEx) {
|
||||||
log.error("Error accessing trust store: " + e.getMessage());
|
log.error("Error accessing trust store: " + ksEx.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Set<X509Certificate> trustedCerts = new HashSet<>();
|
Set<X509Certificate> trustedCerts = new HashSet<>();
|
||||||
|
|
||||||
Enumeration<String> alias = trustStore.aliases();
|
Enumeration<String> alias = trustStore.aliases();
|
||||||
|
|
||||||
while (alias.hasMoreElements()) {
|
while (alias.hasMoreElements()) {
|
||||||
trustedCerts.add((X509Certificate) trustStore.getCertificate(alias.nextElement()));
|
trustedCerts.add((X509Certificate) trustStore.getCertificate(alias.nextElement()));
|
||||||
}
|
}
|
||||||
@ -111,8 +107,8 @@ public class SupplyChainCredentialValidator {
|
|||||||
log.error("Cert chain could not be validated");
|
log.error("Cert chain could not be validated");
|
||||||
}
|
}
|
||||||
return certChainValidated;
|
return certChainValidated;
|
||||||
} catch (KeyStoreException e) {
|
} catch (KeyStoreException ksEx) {
|
||||||
throw new SupplyChainValidatorException("Error with the trust store", e);
|
throw new SupplyChainValidatorException("Error with the trust store", ksEx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,8 +135,8 @@ public class SupplyChainCredentialValidator {
|
|||||||
} else if (trustStore.size() == 0) {
|
} else if (trustStore.size() == 0) {
|
||||||
throw new SupplyChainValidatorException("Truststore is empty");
|
throw new SupplyChainValidatorException("Truststore is empty");
|
||||||
}
|
}
|
||||||
} catch (KeyStoreException e) {
|
} catch (KeyStoreException ksEx) {
|
||||||
log.error("Error accessing trust store: " + e.getMessage());
|
log.error("Error accessing trust store: " + ksEx.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -152,9 +148,9 @@ public class SupplyChainCredentialValidator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return validateCertChain(cert, trustedCerts).isEmpty();
|
return validateCertChain(cert, trustedCerts).isEmpty();
|
||||||
} catch (KeyStoreException e) {
|
} catch (KeyStoreException ksEx) {
|
||||||
log.error("Error accessing keystore", e);
|
log.error("Error accessing keystore", ksEx);
|
||||||
throw new SupplyChainValidatorException("Error with the trust store", e);
|
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.
|
* 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
|
* @param paccorOutput the output from PACCOR's allcomoponents.sh
|
||||||
* @return a list of ComponentInfo objects built from paccorOutput
|
* @return a list of ComponentInfo objects built from paccorOutput
|
||||||
* @throws java.io.IOException if something goes wrong parsing the JSON
|
* @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 {
|
throws IOException {
|
||||||
List<ComponentInfo> componentInfoList = new ArrayList<>();
|
List<ComponentInfo> componentInfoList = new ArrayList<>();
|
||||||
|
|
||||||
@ -292,52 +290,32 @@ public class SupplyChainCredentialValidator {
|
|||||||
= rootNode.findValue("COMPONENTS").elements();
|
= rootNode.findValue("COMPONENTS").elements();
|
||||||
while (jsonComponentNodes.hasNext()) {
|
while (jsonComponentNodes.hasNext()) {
|
||||||
JsonNode next = jsonComponentNodes.next();
|
JsonNode next = jsonComponentNodes.next();
|
||||||
componentInfoList.add(new ComponentInfo(
|
|
||||||
|
List<JsonNode> compClassNodes = next.findValues("COMPONENTCLASS");
|
||||||
|
if (compClassNodes.isEmpty()) {
|
||||||
|
componentInfoList.add(new ComponentInfo(hostName,
|
||||||
getJSONNodeValueAsText(next, "MANUFACTURER"),
|
getJSONNodeValueAsText(next, "MANUFACTURER"),
|
||||||
getJSONNodeValueAsText(next, "MODEL"),
|
getJSONNodeValueAsText(next, "MODEL"),
|
||||||
getJSONNodeValueAsText(next, "SERIAL"),
|
getJSONNodeValueAsText(next, "SERIAL"),
|
||||||
getJSONNodeValueAsText(next, "REVISION")));
|
getJSONNodeValueAsText(next, "REVISION")));
|
||||||
}
|
} else {
|
||||||
}
|
// version 2
|
||||||
|
String componentClass = StringUtils.EMPTY;
|
||||||
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) {
|
for (JsonNode subNode : compClassNodes) {
|
||||||
componentClass = getJSONNodeValueAsText(subNode,
|
componentClass = getJSONNodeValueAsText(subNode,
|
||||||
"COMPONENTCLASSVALUE");
|
"COMPONENTCLASSVALUE");
|
||||||
}
|
}
|
||||||
ciList.add(new ComponentInfo(manufacturer, model,
|
componentInfoList.add(new ComponentInfo(hostName,
|
||||||
serial, revision, componentClass));
|
getJSONNodeValueAsText(next, "MANUFACTURER"),
|
||||||
|
getJSONNodeValueAsText(next, "MODEL"),
|
||||||
|
getJSONNodeValueAsText(next, "SERIAL"),
|
||||||
|
getJSONNodeValueAsText(next, "REVISION"),
|
||||||
|
componentClass));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ciList;
|
return componentInfoList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getJSONNodeValueAsText(final JsonNode node, final String fieldName) {
|
private static String getJSONNodeValueAsText(final JsonNode node, final String fieldName) {
|
||||||
@ -498,10 +476,10 @@ public class SupplyChainCredentialValidator {
|
|||||||
PublicKey key = cert.getPublicKey();
|
PublicKey key = cert.getPublicKey();
|
||||||
cert.verify(key);
|
cert.verify(key);
|
||||||
return true;
|
return true;
|
||||||
} catch (SignatureException | InvalidKeyException e) {
|
} catch (SignatureException | InvalidKeyException ex) {
|
||||||
return false;
|
return false;
|
||||||
} catch (CertificateException | NoSuchAlgorithmException | NoSuchProviderException e) {
|
} catch (CertificateException | NoSuchAlgorithmException | NoSuchProviderException ex) {
|
||||||
log.error("Exception occurred while checking if cert is self-signed", e);
|
log.error("Exception occurred while checking if cert is self-signed", ex);
|
||||||
return false;
|
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;
|
package hirs.attestationca.persist.entity;
|
||||||
|
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import java.security.cert.CertificateException;
|
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>.
|
* Unit tests for the class <code>Appraiser</code>.
|
||||||
@ -160,5 +162,4 @@ public final class AppraiserTest {
|
|||||||
assertNotEquals(appraiser1.hashCode(), appraiser2.hashCode());
|
assertNotEquals(appraiser1.hashCode(), appraiser2.hashCode());
|
||||||
assertNotEquals(appraiser2.hashCode(), appraiser1.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.
|
* Test that {@link TPM2ProvisionerState#getTPM2ProvisionerState(
|
||||||
* {@link TPM2ProvisionerState#getTPM2ProvisionerState(TPM2ProvisionerStateRepository, byte[])}, null is returned.
|
* TPM2ProvisionerStateRepository, byte[])} works.
|
||||||
|
* {@link TPM2ProvisionerState#getTPM2ProvisionerState(
|
||||||
|
* TPM2ProvisionerStateRepository, byte[])}, null is returned.
|
||||||
* @throws IOException this will never happen
|
* @throws IOException this will never happen
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public final void testGetTPM2ProvisionerStateNominal() throws IOException {
|
public final void testGetTPM2ProvisionerStateNominal() throws IOException {
|
||||||
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository = mock(TPM2ProvisionerStateRepository.class);
|
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository =
|
||||||
|
mock(TPM2ProvisionerStateRepository.class);
|
||||||
byte[] nonce = new byte[32];
|
byte[] nonce = new byte[32];
|
||||||
byte[] identityClaim = new byte[360];
|
byte[] identityClaim = new byte[360];
|
||||||
random.nextBytes(nonce);
|
random.nextBytes(nonce);
|
||||||
@ -112,12 +115,14 @@ public class TPM2ProvisionerStateTest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that if a null is passed as a nonce to
|
* 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
|
* @throws IOException this will never happen
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public final void testGetTPM2ProvisionerStateNullNonce() throws IOException {
|
public final void testGetTPM2ProvisionerStateNullNonce() throws IOException {
|
||||||
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository = mock(TPM2ProvisionerStateRepository.class);
|
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository =
|
||||||
|
mock(TPM2ProvisionerStateRepository.class);
|
||||||
byte[] nonce = new byte[32];
|
byte[] nonce = new byte[32];
|
||||||
byte[] identityClaim = new byte[360];
|
byte[] identityClaim = new byte[360];
|
||||||
random.nextBytes(nonce);
|
random.nextBytes(nonce);
|
||||||
@ -133,12 +138,14 @@ public class TPM2ProvisionerStateTest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that if a nonce that is less than 8 bytes is passed to
|
* 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
|
* @throws IOException this will never happen
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public final void testGetTPM2ProvisionerStateNonceTooSmall() throws IOException {
|
public final void testGetTPM2ProvisionerStateNonceTooSmall() throws IOException {
|
||||||
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository = mock(TPM2ProvisionerStateRepository.class);
|
TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository =
|
||||||
|
mock(TPM2ProvisionerStateRepository.class);
|
||||||
byte[] nonce = new byte[32];
|
byte[] nonce = new byte[32];
|
||||||
byte[] identityClaim = new byte[360];
|
byte[] identityClaim = new byte[360];
|
||||||
random.nextBytes(nonce);
|
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;
|
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.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -14,12 +19,8 @@ import java.security.cert.CertificateException;
|
|||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
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.
|
* This class tests functionality of the {@link Certificate} class.
|
||||||
*/
|
*/
|
||||||
public class CertificateTest {
|
public class CertificateTest extends AbstractUserdefinedEntityTest {
|
||||||
/**
|
|
||||||
* 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";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Location of a test (fake) Intel intermediate CA certificate.
|
* Location of a test (fake) Intel intermediate CA certificate.
|
||||||
@ -47,11 +38,6 @@ public class CertificateTest {
|
|||||||
public static final String INTEL_INT_CA_FILE =
|
public static final String INTEL_INT_CA_FILE =
|
||||||
"/validation/platform_credentials/intel_chain/root/intermediate2.cer";
|
"/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.
|
* 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";
|
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.
|
* Location of a test STM endorsement credential.
|
||||||
*/
|
*/
|
||||||
@ -119,7 +99,8 @@ public class CertificateTest {
|
|||||||
public void testConstructCertFromByteArray() throws IOException, URISyntaxException {
|
public void testConstructCertFromByteArray() throws IOException, URISyntaxException {
|
||||||
Certificate certificate = new CertificateAuthorityCredential(
|
Certificate certificate = new CertificateAuthorityCredential(
|
||||||
Files.readAllBytes(
|
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(
|
assertEquals(
|
||||||
@ -163,7 +144,8 @@ public class CertificateTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testConstructCertFromPath() throws URISyntaxException, IOException {
|
public void testConstructCertFromPath() throws URISyntaxException, IOException {
|
||||||
Certificate certificate = new CertificateAuthorityCredential(
|
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(
|
assertEquals(
|
||||||
"CN=Fake Root CA",
|
"CN=Fake Root CA",
|
||||||
@ -202,12 +184,12 @@ public class CertificateTest {
|
|||||||
Certificate.CertificateType.X509_CERTIFICATE,
|
Certificate.CertificateType.X509_CERTIFICATE,
|
||||||
getTestCertificate(
|
getTestCertificate(
|
||||||
PlatformCredential.class,
|
PlatformCredential.class,
|
||||||
PlatformCredentialTest.TEST_PLATFORM_CERT_3).getCertificateType());
|
TEST_PLATFORM_CERT_3).getCertificateType());
|
||||||
assertEquals(
|
assertEquals(
|
||||||
Certificate.CertificateType.ATTRIBUTE_CERTIFICATE,
|
Certificate.CertificateType.ATTRIBUTE_CERTIFICATE,
|
||||||
getTestCertificate(
|
getTestCertificate(
|
||||||
PlatformCredential.class,
|
PlatformCredential.class,
|
||||||
PlatformCredentialTest.TEST_PLATFORM_CERT_3).getCertificateType());
|
TEST_PLATFORM_CERT_3).getCertificateType());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +202,7 @@ public class CertificateTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testImportPem() throws IOException {
|
public void testImportPem() throws IOException {
|
||||||
Certificate platformCredential = getTestCertificate(
|
Certificate platformCredential = getTestCertificate(
|
||||||
PlatformCredential.class, PlatformCredentialTest.TEST_PLATFORM_CERT_4
|
PlatformCredential.class, TEST_PLATFORM_CERT_4
|
||||||
);
|
);
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@ -232,7 +214,7 @@ public class CertificateTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
platformCredential = getTestCertificate(
|
platformCredential = getTestCertificate(
|
||||||
PlatformCredential.class, PlatformCredentialTest.TEST_PLATFORM_CERT_5
|
PlatformCredential.class, TEST_PLATFORM_CERT_5
|
||||||
);
|
);
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@ -295,13 +277,12 @@ public class CertificateTest {
|
|||||||
public void testX509AttributeCertificateParsing() throws IOException, URISyntaxException {
|
public void testX509AttributeCertificateParsing() throws IOException, URISyntaxException {
|
||||||
Certificate platformCert = getTestCertificate(
|
Certificate platformCert = getTestCertificate(
|
||||||
PlatformCredential.class,
|
PlatformCredential.class,
|
||||||
PlatformCredentialTest.TEST_PLATFORM_CERT_3
|
TEST_PLATFORM_CERT_3
|
||||||
);
|
);
|
||||||
|
|
||||||
X509AttributeCertificateHolder attrCertHolder = new X509AttributeCertificateHolder(
|
X509AttributeCertificateHolder attrCertHolder = new X509AttributeCertificateHolder(
|
||||||
Files.readAllBytes(Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
Files.readAllBytes(Paths.get(Objects.requireNonNull(this.getClass().getResource(
|
||||||
PlatformCredentialTest.TEST_PLATFORM_CERT_3
|
TEST_PLATFORM_CERT_3)).toURI()))
|
||||||
)).toURI()))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@ -330,7 +311,7 @@ public class CertificateTest {
|
|||||||
public void testX509AttributeCertificateParsingExtended()
|
public void testX509AttributeCertificateParsingExtended()
|
||||||
throws IOException, URISyntaxException {
|
throws IOException, URISyntaxException {
|
||||||
Certificate platformCert = getTestCertificate(
|
Certificate platformCert = getTestCertificate(
|
||||||
PlatformCredential.class, PlatformCredentialTest.TEST_PLATFORM_CERT_6);
|
PlatformCredential.class, TEST_PLATFORM_CERT_6);
|
||||||
|
|
||||||
assertEquals("https://trustedservices.intel.com/"
|
assertEquals("https://trustedservices.intel.com/"
|
||||||
+ "content/TSC/certs/TSC_IssuingCAIKGF_TEST.cer\n",
|
+ "content/TSC/certs/TSC_IssuingCAIKGF_TEST.cer\n",
|
||||||
@ -428,11 +409,13 @@ public class CertificateTest {
|
|||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
new CertificateAuthorityCredential(
|
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(
|
new CertificateAuthorityCredential(
|
||||||
Files.readAllBytes(
|
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())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -489,11 +472,13 @@ public class CertificateTest {
|
|||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
new CertificateAuthorityCredential(
|
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(),
|
).hashCode(),
|
||||||
new CertificateAuthorityCredential(
|
new CertificateAuthorityCredential(
|
||||||
Files.readAllBytes(
|
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()
|
).hashCode()
|
||||||
);
|
);
|
||||||
@ -520,79 +505,6 @@ public class CertificateTest {
|
|||||||
return getTestCertificate(CertificateAuthorityCredential.class, filename);
|
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)
|
private static X509Certificate readX509Certificate(final String resourceName)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
@ -603,8 +515,9 @@ public class CertificateTest {
|
|||||||
throw new IOException("Cannot get X509 CertificateFactory instance", e);
|
throw new IOException("Cannot get X509 CertificateFactory instance", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try (FileInputStream certInputStream = new FileInputStream(
|
try (FileInputStream certInputStream = new FileInputStream(Paths.get(
|
||||||
Paths.get(Objects.requireNonNull(CertificateTest.class.getResource(resourceName)).toURI()).toFile()
|
Objects.requireNonNull(CertificateTest.class.getResource(
|
||||||
|
resourceName)).toURI()).toFile()
|
||||||
)) {
|
)) {
|
||||||
return (X509Certificate) cf.generateCertificate(certInputStream);
|
return (X509Certificate) cf.generateCertificate(certInputStream);
|
||||||
} catch (CertificateException | URISyntaxException e) {
|
} catch (CertificateException | URISyntaxException e) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package hirs.attestationca.persist.entity.userdefined;
|
package hirs.attestationca.persist.entity.userdefined;
|
||||||
|
|
||||||
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
|
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.AppraisalStatus;
|
||||||
import hirs.attestationca.persist.enums.HealthStatus;
|
import hirs.attestationca.persist.enums.HealthStatus;
|
||||||
import org.junit.jupiter.api.Test;
|
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.
|
* This is the test class for the <code>Device</code> class.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class DeviceTest {
|
public final class DeviceTest extends AbstractUserdefinedEntityTest {
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that the device constructor can take a name.
|
* Tests that the device constructor can take a name.
|
||||||
@ -34,7 +21,9 @@ public final class DeviceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDevice() {
|
public void testDevice() {
|
||||||
final String name = "my-laptop";
|
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);
|
assertNotNull(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,8 +34,10 @@ public final class DeviceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDeviceNameAndInfo() {
|
public void testDeviceNameAndInfo() {
|
||||||
final String name = "my-laptop";
|
final String name = "my-laptop";
|
||||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +47,9 @@ public final class DeviceTest {
|
|||||||
public void testDeviceNameAndNullInfo() {
|
public void testDeviceNameAndNullInfo() {
|
||||||
final String name = "my-laptop";
|
final String name = "my-laptop";
|
||||||
final DeviceInfoReport deviceInfo = null;
|
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
|
@Test
|
||||||
public void testGetDeviceInfo() {
|
public void testGetDeviceInfo() {
|
||||||
final String name = "my-laptop";
|
final String name = "my-laptop";
|
||||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||||
|
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||||
|
null, null);
|
||||||
assertEquals(deviceInfo, device.getDeviceInfo());
|
assertEquals(deviceInfo, device.getDeviceInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,9 +71,11 @@ public final class DeviceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSetDeviceInfo() {
|
public void testSetDeviceInfo() {
|
||||||
final String name = "my-laptop";
|
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());
|
assertNull(device.getDeviceInfo());
|
||||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||||
device.setDeviceInfo(deviceInfo);
|
device.setDeviceInfo(deviceInfo);
|
||||||
assertEquals(deviceInfo, device.getDeviceInfo());
|
assertEquals(deviceInfo, device.getDeviceInfo());
|
||||||
}
|
}
|
||||||
@ -89,8 +86,10 @@ public final class DeviceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSetNullDeviceInfo() {
|
public void testSetNullDeviceInfo() {
|
||||||
final String name = "my-laptop";
|
final String name = "my-laptop";
|
||||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||||
|
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||||
|
null, null);
|
||||||
assertEquals(deviceInfo, device.getDeviceInfo());
|
assertEquals(deviceInfo, device.getDeviceInfo());
|
||||||
device.setDeviceInfo(null);
|
device.setDeviceInfo(null);
|
||||||
assertNull(device.getDeviceInfo());
|
assertNull(device.getDeviceInfo());
|
||||||
@ -102,8 +101,10 @@ public final class DeviceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testNotNullLastReportTimeStamp() {
|
public void testNotNullLastReportTimeStamp() {
|
||||||
final String name = "my-laptop";
|
final String name = "my-laptop";
|
||||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||||
|
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||||
|
null, null);
|
||||||
assertNotNull(device.getLastReportTimestamp());
|
assertNotNull(device.getLastReportTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +113,9 @@ public final class DeviceTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSetHealthStatus() {
|
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);
|
device.setHealthStatus(HealthStatus.TRUSTED);
|
||||||
assertEquals(HealthStatus.TRUSTED, device.getHealthStatus());
|
assertEquals(HealthStatus.TRUSTED, device.getHealthStatus());
|
||||||
}
|
}
|
||||||
@ -124,9 +127,13 @@ public final class DeviceTest {
|
|||||||
public void testDeviceEquals() {
|
public void testDeviceEquals() {
|
||||||
final String name = "my-laptop";
|
final String name = "my-laptop";
|
||||||
final String otherName = "my-laptop";
|
final String otherName = "my-laptop";
|
||||||
final DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||||
final Device other = new Device(otherName, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
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);
|
assertEquals(device, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,8 +143,10 @@ public final class DeviceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetDefaultSupplyChainStatus() {
|
public void testGetDefaultSupplyChainStatus() {
|
||||||
String name = "my-laptop";
|
String name = "my-laptop";
|
||||||
DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||||
|
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||||
|
null, null);
|
||||||
assertEquals(AppraisalStatus.Status.UNKNOWN, device.getSupplyChainValidationStatus());
|
assertEquals(AppraisalStatus.Status.UNKNOWN, device.getSupplyChainValidationStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,8 +156,10 @@ public final class DeviceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSetAndGetSupplyChainStatus() {
|
public void testSetAndGetSupplyChainStatus() {
|
||||||
String name = "my-laptop";
|
String name = "my-laptop";
|
||||||
DeviceInfoReport deviceInfo = DeviceInfoReportTest.getTestReport();
|
final DeviceInfoReport deviceInfo = getTestDeviceInfoReport();
|
||||||
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN, AppraisalStatus.Status.UNKNOWN, null, false, null, null);
|
final Device device = new Device(name, deviceInfo, HealthStatus.UNKNOWN,
|
||||||
|
AppraisalStatus.Status.UNKNOWN, null, false,
|
||||||
|
null, null);
|
||||||
device.setSupplyChainValidationStatus(AppraisalStatus.Status.PASS);
|
device.setSupplyChainValidationStatus(AppraisalStatus.Status.PASS);
|
||||||
assertEquals(AppraisalStatus.Status.PASS, device.getSupplyChainValidationStatus());
|
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;
|
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 hirs.attestationca.persist.enums.AppraisalStatus;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
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
|
* Simple tests for the {@link SupplyChainValidation} class. Tests for the persistence of this
|
||||||
* class are located in { SupplyChainValidationSummaryTest}.
|
* class are located in { SupplyChainValidationSummaryTest}.
|
||||||
*/
|
*/
|
||||||
class SupplyChainValidationTest {
|
class SupplyChainValidationTest extends AbstractUserdefinedEntityTest {
|
||||||
private static final String MESSAGE = "Some message.";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that this class' getter methods work properly.
|
* Test that this class' getter methods work properly.
|
||||||
@ -31,9 +28,9 @@ class SupplyChainValidationTest {
|
|||||||
);
|
);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
validation.getCertificatesUsed(),
|
validation.getCertificatesUsed(),
|
||||||
CertificateTest.getAllTestCertificates()
|
getAllTestCertificates()
|
||||||
);
|
);
|
||||||
assertEquals(validation.getMessage(), MESSAGE);
|
assertEquals(validation.getMessage(), VALIDATION_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,8 +44,8 @@ class SupplyChainValidationTest {
|
|||||||
new SupplyChainValidation(
|
new SupplyChainValidation(
|
||||||
null,
|
null,
|
||||||
AppraisalStatus.Status.PASS,
|
AppraisalStatus.Status.PASS,
|
||||||
CertificateTest.getAllTestCertificates(),
|
getAllTestCertificates(),
|
||||||
MESSAGE
|
VALIDATION_MESSAGE
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +61,7 @@ class SupplyChainValidationTest {
|
|||||||
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
|
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
|
||||||
AppraisalStatus.Status.PASS,
|
AppraisalStatus.Status.PASS,
|
||||||
null,
|
null,
|
||||||
MESSAGE
|
VALIDATION_MESSAGE
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,8 +75,8 @@ class SupplyChainValidationTest {
|
|||||||
new SupplyChainValidation(
|
new SupplyChainValidation(
|
||||||
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
|
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
|
||||||
AppraisalStatus.Status.PASS,
|
AppraisalStatus.Status.PASS,
|
||||||
CertificateTest.getAllTestCertificates(),
|
getAllTestCertificates(),
|
||||||
MESSAGE
|
VALIDATION_MESSAGE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,27 +92,7 @@ class SupplyChainValidationTest {
|
|||||||
return getTestSupplyChainValidation(
|
return getTestSupplyChainValidation(
|
||||||
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
|
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL,
|
||||||
AppraisalStatus.Status.PASS,
|
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;
|
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 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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -12,13 +11,11 @@ import java.net.URISyntaxException;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that CertificateAuthorityCredential properly parses its fields.
|
* Tests that CertificateAuthorityCredential properly parses its fields.
|
||||||
*/
|
*/
|
||||||
public class CertificateAuthorityCredentialTest {
|
public class CertificateAuthorityCredentialTest extends AbstractUserdefinedEntityTest {
|
||||||
private static final CertificateRepository CERT_MAN = mock(CertificateRepository.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that a CertificateAuthorityCredential can be created from an X.509 certificate and
|
* Tests that a CertificateAuthorityCredential can be created from an X.509 certificate and
|
||||||
@ -33,7 +30,7 @@ public class CertificateAuthorityCredentialTest {
|
|||||||
public void testGetSubjectKeyIdentifier()
|
public void testGetSubjectKeyIdentifier()
|
||||||
throws CertificateException, IOException, URISyntaxException {
|
throws CertificateException, IOException, URISyntaxException {
|
||||||
Path testCertPath = Paths.get(
|
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);
|
CertificateAuthorityCredential caCred = new CertificateAuthorityCredential(testCertPath);
|
||||||
|
|
||||||
@ -42,7 +39,7 @@ public class CertificateAuthorityCredentialTest {
|
|||||||
assertNotNull(subjectKeyIdentifier);
|
assertNotNull(subjectKeyIdentifier);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
Hex.encodeHexString(subjectKeyIdentifier),
|
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.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
import hirs.attestationca.persist.entity.userdefined.CertificateTest;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -29,13 +28,15 @@ public class EndorsementCredentialTest {
|
|||||||
private static final String EK_CERT_WITH_SECURITY_ASSERTIONS =
|
private static final String EK_CERT_WITH_SECURITY_ASSERTIONS =
|
||||||
"/certificates/ek_cert_with_security_assertions.cer";
|
"/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.
|
* Tests the successful parsing of an EC using a test cert from STM.
|
||||||
* @throws IOException test failed due to invalid certificate parsing
|
* @throws IOException test failed due to invalid certificate parsing
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testParse() throws IOException {
|
public void testParse() throws IOException {
|
||||||
String path = CertificateTest.class.getResource(TEST_ENDORSEMENT_CREDENTIAL).
|
String path = this.getClass().getResource(TEST_ENDORSEMENT_CREDENTIAL).
|
||||||
getPath();
|
getPath();
|
||||||
Path fPath = Paths.get(path);
|
Path fPath = Paths.get(path);
|
||||||
EndorsementCredential ec = new EndorsementCredential(fPath);
|
EndorsementCredential ec = new EndorsementCredential(fPath);
|
||||||
@ -49,7 +50,7 @@ public class EndorsementCredentialTest {
|
|||||||
TPMSpecification spec = ec.getTpmSpecification();
|
TPMSpecification spec = ec.getTpmSpecification();
|
||||||
assertEquals(spec.getFamily(), "1.2");
|
assertEquals(spec.getFamily(), "1.2");
|
||||||
assertEquals(spec.getLevel(), BigInteger.valueOf(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();
|
TPMSecurityAssertions asserts = ec.getTpmSecurityAssertions();
|
||||||
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
||||||
@ -68,7 +69,7 @@ public class EndorsementCredentialTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testParseNuc1() throws IOException {
|
public void testParseNuc1() throws IOException {
|
||||||
String path = CertificateTest.class.getResource(
|
String path = this.getClass().getResource(
|
||||||
TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
||||||
Path fPath = Paths.get(path);
|
Path fPath = Paths.get(path);
|
||||||
EndorsementCredential ec = new EndorsementCredential(fPath);
|
EndorsementCredential ec = new EndorsementCredential(fPath);
|
||||||
@ -82,7 +83,7 @@ public class EndorsementCredentialTest {
|
|||||||
TPMSpecification spec = ec.getTpmSpecification();
|
TPMSpecification spec = ec.getTpmSpecification();
|
||||||
assertEquals(spec.getFamily(), "1.2");
|
assertEquals(spec.getFamily(), "1.2");
|
||||||
assertEquals(spec.getLevel(), BigInteger.valueOf(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();
|
TPMSecurityAssertions asserts = ec.getTpmSecurityAssertions();
|
||||||
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
||||||
@ -102,7 +103,7 @@ public class EndorsementCredentialTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testParseNuc1BuilderMethod() throws IOException {
|
public void testParseNuc1BuilderMethod() throws IOException {
|
||||||
String path = CertificateTest.class.getResource(
|
String path = this.getClass().getResource(
|
||||||
TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
||||||
Path fPath = Paths.get(path);
|
Path fPath = Paths.get(path);
|
||||||
byte[] ecBytes = Files.readAllBytes(fPath);
|
byte[] ecBytes = Files.readAllBytes(fPath);
|
||||||
@ -118,7 +119,7 @@ public class EndorsementCredentialTest {
|
|||||||
TPMSpecification spec = ec.getTpmSpecification();
|
TPMSpecification spec = ec.getTpmSpecification();
|
||||||
assertEquals(spec.getFamily(), "1.2");
|
assertEquals(spec.getFamily(), "1.2");
|
||||||
assertEquals(spec.getLevel(), BigInteger.valueOf(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();
|
TPMSecurityAssertions asserts = ec.getTpmSecurityAssertions();
|
||||||
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
||||||
@ -137,7 +138,7 @@ public class EndorsementCredentialTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testParseNuc2() throws IOException {
|
public void testParseNuc2() throws IOException {
|
||||||
String path = CertificateTest.class.getResource(
|
String path = this.getClass().getResource(
|
||||||
TEST_ENDORSEMENT_CREDENTIAL_NUC2).getPath();
|
TEST_ENDORSEMENT_CREDENTIAL_NUC2).getPath();
|
||||||
Path fPath = Paths.get(path);
|
Path fPath = Paths.get(path);
|
||||||
EndorsementCredential ec = new EndorsementCredential(fPath);
|
EndorsementCredential ec = new EndorsementCredential(fPath);
|
||||||
@ -151,7 +152,7 @@ public class EndorsementCredentialTest {
|
|||||||
TPMSpecification spec = ec.getTpmSpecification();
|
TPMSpecification spec = ec.getTpmSpecification();
|
||||||
assertEquals(spec.getFamily(), "1.2");
|
assertEquals(spec.getFamily(), "1.2");
|
||||||
assertEquals(spec.getLevel(), BigInteger.valueOf(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();
|
TPMSecurityAssertions asserts = ec.getTpmSecurityAssertions();
|
||||||
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
assertEquals(asserts.getTpmSecAssertsVersion(), BigInteger.valueOf(0));
|
||||||
@ -170,17 +171,17 @@ public class EndorsementCredentialTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCertsNotEqual() throws IOException {
|
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);
|
Path fPath = Paths.get(path);
|
||||||
EndorsementCredential ec1 = new EndorsementCredential(fPath);
|
EndorsementCredential ec1 = new EndorsementCredential(fPath);
|
||||||
assertNotNull(ec1);
|
assertNotNull(ec1);
|
||||||
|
|
||||||
path = CertificateTest.class.getResource(TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
path = this.getClass().getResource(TEST_ENDORSEMENT_CREDENTIAL_NUC1).getPath();
|
||||||
fPath = Paths.get(path);
|
fPath = Paths.get(path);
|
||||||
EndorsementCredential ec2 = new EndorsementCredential(fPath);
|
EndorsementCredential ec2 = new EndorsementCredential(fPath);
|
||||||
assertNotNull(ec2);
|
assertNotNull(ec2);
|
||||||
|
|
||||||
path = CertificateTest.class.getResource(TEST_ENDORSEMENT_CREDENTIAL_NUC2).getPath();
|
path = this.getClass().getResource(TEST_ENDORSEMENT_CREDENTIAL_NUC2).getPath();
|
||||||
fPath = Paths.get(path);
|
fPath = Paths.get(path);
|
||||||
EndorsementCredential ec3 = new EndorsementCredential(fPath);
|
EndorsementCredential ec3 = new EndorsementCredential(fPath);
|
||||||
assertNotNull(ec3);
|
assertNotNull(ec3);
|
||||||
@ -197,7 +198,7 @@ public class EndorsementCredentialTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testTpmSecurityAssertionsParsing() throws IOException {
|
public void testTpmSecurityAssertionsParsing() throws IOException {
|
||||||
Path fPath = Paths.get(CertificateTest.class
|
Path fPath = Paths.get(this.getClass()
|
||||||
.getResource(EK_CERT_WITH_SECURITY_ASSERTIONS).getPath());
|
.getResource(EK_CERT_WITH_SECURITY_ASSERTIONS).getPath());
|
||||||
EndorsementCredential ec = new EndorsementCredential(fPath);
|
EndorsementCredential ec = new EndorsementCredential(fPath);
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package hirs.attestationca.persist.entity.userdefined.certificate;
|
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;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
|
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
|
||||||
@ -25,42 +26,7 @@ import java.util.TimeZone;
|
|||||||
/**
|
/**
|
||||||
* Tests that a PlatformCredential parses its fields correctly.
|
* Tests that a PlatformCredential parses its fields correctly.
|
||||||
*/
|
*/
|
||||||
public class PlatformCredentialTest {
|
public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
|
||||||
/**
|
|
||||||
* 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";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform Certificate 2.0 with all the expected data.
|
* Platform Certificate 2.0 with all the expected data.
|
||||||
@ -573,7 +539,7 @@ public class PlatformCredentialTest {
|
|||||||
.equals("BIOS"));
|
.equals("BIOS"));
|
||||||
Assertions.assertTrue(component.getComponentSerial()
|
Assertions.assertTrue(component.getComponentSerial()
|
||||||
.getString()
|
.getString()
|
||||||
.equals(ComponentIdentifier.EMPTY_COMPONENT));
|
.equals(ComponentIdentifier.NOT_SPECIFIED_COMPONENT));
|
||||||
Assertions.assertTrue(component.getComponentRevision()
|
Assertions.assertTrue(component.getComponentRevision()
|
||||||
.getString()
|
.getString()
|
||||||
.equals("DNKBLi5v.86A.0019.2017.0804.1146"));
|
.equals("DNKBLi5v.86A.0019.2017.0804.1146"));
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
|
@ -0,0 +1 @@
|
|||||||
|
package hirs.attestationca.persist.entity.userdefined.certificate;
|
@ -1,12 +1,8 @@
|
|||||||
package hirs.attestationca.persist.entity.userdefined.info;
|
package hirs.attestationca.persist.entity.userdefined.info;
|
||||||
|
|
||||||
import static hirs.utils.enums.DeviceInfoEnums.NOT_SPECIFIED;
|
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.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -18,12 +14,11 @@ import org.junit.jupiter.api.Test;
|
|||||||
/**
|
/**
|
||||||
* TPMInfoTest is a unit test class for TPMInfo.
|
* 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 TPM_MAKE = "test tpmMake";
|
||||||
private static final String LONG_TPM_MAKE = StringUtils.rightPad("test tpmMake", 65);
|
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_MAJOR = 1;
|
||||||
private static final short VERSION_MINOR = 2;
|
private static final short VERSION_MINOR = 2;
|
||||||
private static final short VERSION_REV_MAJOR = 3;
|
private static final short VERSION_REV_MAJOR = 3;
|
||||||
@ -327,30 +322,4 @@ public class TPMInfoTest {
|
|||||||
getTestIdentityCertificate());
|
getTestIdentityCertificate());
|
||||||
assertNotEquals(ti1, ti2);
|
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 int DEFAULT_PCR_ID = 3;
|
||||||
private static final String DEFAULT_HASH =
|
private static final String DEFAULT_HASH =
|
||||||
"3d5f3c2f7f3003d2e4baddc46ed4763a4954f648";
|
"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>.
|
* 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;
|
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.OSInfo;
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.TPMInfo;
|
import hirs.attestationca.persist.entity.userdefined.info.TPMInfo;
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
|
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
|
||||||
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
|
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 org.junit.jupiter.api.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
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 NetworkInfo networkInfo = createTestNetworkInfo();
|
||||||
private final OSInfo osInfo = createTestOSInfo();
|
private final OSInfo osInfo = createTestOSInfo();
|
||||||
private final FirmwareInfo firmwareInfo = createTestFirmwareInfo();
|
private final FirmwareInfo firmwareInfo = createTestFirmwareInfo();
|
||||||
private final HardwareInfo hardwareInfo = createTestHardwareInfo();
|
private final HardwareInfo hardwareInfo = createTestHardwareInfo();
|
||||||
private final TPMInfo tpmInfo = createTPMInfo();
|
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";
|
private static final String EXPECTED_CLIENT_VERSION = "Test.Version";
|
||||||
|
|
||||||
@ -101,109 +89,4 @@ public class DeviceInfoReportTest {
|
|||||||
assertEquals(tpmInfo, deviceInfoReport.getTpmInfo());
|
assertEquals(tpmInfo, deviceInfoReport.getTpmInfo());
|
||||||
assertEquals(EXPECTED_CLIENT_VERSION, deviceInfoReport.getClientApplicationVersion());
|
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
|
@Test
|
||||||
public void processEmptyEndorsementCredential() {
|
public void processEmptyEndorsementCredential() {
|
||||||
assertThrows(IllegalArgumentException.class, () ->
|
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() {
|
public void processInvalidEndorsementCredentialCase1() {
|
||||||
byte[] ekBytes = new byte[] {1};
|
byte[] ekBytes = new byte[] {1};
|
||||||
assertThrows(IllegalArgumentException.class, () ->
|
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(
|
private Map<String, String> getSubjectAlternativeNameAttributes(
|
||||||
Extension subjectAlternativeName) {
|
final Extension subjectAlternativeName) {
|
||||||
Map<String, String> subjectAlternativeNameAttrMap = new HashMap<>();
|
Map<String, String> subjectAlternativeNameAttrMap = new HashMap<>();
|
||||||
|
|
||||||
DLSequence dlSequence = (DLSequence) subjectAlternativeName.getParsedValue();
|
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.FilteredRecordsList;
|
||||||
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
|
import hirs.attestationca.persist.entity.manager.CACredentialRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.CertificateRepository;
|
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.EndorsementCredentialRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
|
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
|
||||||
import hirs.attestationca.persist.entity.manager.PlatformCertificateRepository;
|
import hirs.attestationca.persist.entity.manager.PlatformCertificateRepository;
|
||||||
import hirs.attestationca.persist.entity.userdefined.Certificate;
|
import hirs.attestationca.persist.entity.userdefined.Certificate;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
|
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.EndorsementCredential;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate;
|
import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
|
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.persist.util.CredentialHelper;
|
||||||
import hirs.attestationca.portal.datatables.DataTableInput;
|
import hirs.attestationca.portal.datatables.DataTableInput;
|
||||||
import hirs.attestationca.portal.datatables.DataTableResponse;
|
import hirs.attestationca.portal.datatables.DataTableResponse;
|
||||||
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
|
|
||||||
import hirs.attestationca.portal.page.Page;
|
import hirs.attestationca.portal.page.Page;
|
||||||
import hirs.attestationca.portal.page.PageController;
|
import hirs.attestationca.portal.page.PageController;
|
||||||
import hirs.attestationca.portal.page.PageMessages;
|
import hirs.attestationca.portal.page.PageMessages;
|
||||||
@ -83,6 +85,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
private CertificateAuthorityCredential certificateAuthorityCredential;
|
private CertificateAuthorityCredential certificateAuthorityCredential;
|
||||||
private final CertificateRepository certificateRepository;
|
private final CertificateRepository certificateRepository;
|
||||||
private final PlatformCertificateRepository platformCertificateRepository;
|
private final PlatformCertificateRepository platformCertificateRepository;
|
||||||
|
private final ComponentResultRepository componentResultRepository;
|
||||||
private final EndorsementCredentialRepository endorsementCredentialRepository;
|
private final EndorsementCredentialRepository endorsementCredentialRepository;
|
||||||
private final IssuedCertificateRepository issuedCertificateRepository;
|
private final IssuedCertificateRepository issuedCertificateRepository;
|
||||||
private final CACredentialRepository caCredentialRepository;
|
private final CACredentialRepository caCredentialRepository;
|
||||||
@ -102,6 +105,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
*
|
*
|
||||||
* @param certificateRepository the general certificate manager
|
* @param certificateRepository the general certificate manager
|
||||||
* @param platformCertificateRepository the platform credential manager
|
* @param platformCertificateRepository the platform credential manager
|
||||||
|
* @param componentResultRepository the component result repo
|
||||||
* @param endorsementCredentialRepository the endorsement credential manager
|
* @param endorsementCredentialRepository the endorsement credential manager
|
||||||
* @param issuedCertificateRepository the issued certificate manager
|
* @param issuedCertificateRepository the issued certificate manager
|
||||||
* @param caCredentialRepository the ca credential manager
|
* @param caCredentialRepository the ca credential manager
|
||||||
@ -110,6 +114,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
@Autowired
|
@Autowired
|
||||||
public CertificatePageController(final CertificateRepository certificateRepository,
|
public CertificatePageController(final CertificateRepository certificateRepository,
|
||||||
final PlatformCertificateRepository platformCertificateRepository,
|
final PlatformCertificateRepository platformCertificateRepository,
|
||||||
|
final ComponentResultRepository componentResultRepository,
|
||||||
final EndorsementCredentialRepository endorsementCredentialRepository,
|
final EndorsementCredentialRepository endorsementCredentialRepository,
|
||||||
final IssuedCertificateRepository issuedCertificateRepository,
|
final IssuedCertificateRepository issuedCertificateRepository,
|
||||||
final CACredentialRepository caCredentialRepository,
|
final CACredentialRepository caCredentialRepository,
|
||||||
@ -117,6 +122,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
super(Page.TRUST_CHAIN);
|
super(Page.TRUST_CHAIN);
|
||||||
this.certificateRepository = certificateRepository;
|
this.certificateRepository = certificateRepository;
|
||||||
this.platformCertificateRepository = platformCertificateRepository;
|
this.platformCertificateRepository = platformCertificateRepository;
|
||||||
|
this.componentResultRepository = componentResultRepository;
|
||||||
this.endorsementCredentialRepository = endorsementCredentialRepository;
|
this.endorsementCredentialRepository = endorsementCredentialRepository;
|
||||||
this.issuedCertificateRepository = issuedCertificateRepository;
|
this.issuedCertificateRepository = issuedCertificateRepository;
|
||||||
this.caCredentialRepository = caCredentialRepository;
|
this.caCredentialRepository = caCredentialRepository;
|
||||||
@ -395,9 +401,11 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
if (!pc.isPlatformBase()) {
|
if (!pc.isPlatformBase()) {
|
||||||
pc.archive("User requested deletion via UI of the base certificate");
|
pc.archive("User requested deletion via UI of the base certificate");
|
||||||
certificateRepository.save(pc);
|
certificateRepository.save(pc);
|
||||||
|
deleteComponentResults(pc.getPlatformSerial());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
deleteComponentResults(platformCertificate.getPlatformSerial());
|
||||||
}
|
}
|
||||||
|
|
||||||
certificate.archive("User requested deletion via UI");
|
certificate.archive("User requested deletion via UI");
|
||||||
@ -845,7 +853,6 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
* be stored
|
* be stored
|
||||||
* @param messages contains any messages that will be display on the page
|
* @param messages contains any messages that will be display on the page
|
||||||
* @param certificate the certificate to store
|
* @param certificate the certificate to store
|
||||||
* @return the messages for the page
|
|
||||||
*/
|
*/
|
||||||
private void storeCertificate(
|
private void storeCertificate(
|
||||||
final String certificateType,
|
final String certificateType,
|
||||||
@ -877,8 +884,6 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
List<PlatformCredential> sharedCertificates = getCertificateByBoardSN(
|
List<PlatformCredential> sharedCertificates = getCertificateByBoardSN(
|
||||||
certificateType,
|
certificateType,
|
||||||
platformCertificate.getPlatformSerial());
|
platformCertificate.getPlatformSerial());
|
||||||
|
|
||||||
if (sharedCertificates != null) {
|
|
||||||
for (PlatformCredential pc : sharedCertificates) {
|
for (PlatformCredential pc : sharedCertificates) {
|
||||||
if (pc.isPlatformBase()) {
|
if (pc.isPlatformBase()) {
|
||||||
final String failMessage = "Storing certificate failed: "
|
final String failMessage = "Storing certificate failed: "
|
||||||
@ -891,7 +896,6 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} /**else {
|
} /**else {
|
||||||
// this is a delta, check if the holder exists.
|
// this is a delta, check if the holder exists.
|
||||||
PlatformCredential holderPC = PlatformCredential
|
PlatformCredential holderPC = PlatformCredential
|
||||||
@ -913,6 +917,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.certificateRepository.save(certificate);
|
this.certificateRepository.save(certificate);
|
||||||
|
handlePlatformComponents(certificate);
|
||||||
|
|
||||||
final String successMsg
|
final String successMsg
|
||||||
= String.format("New certificate successfully uploaded (%s): ", fileName);
|
= String.format("New certificate successfully uploaded (%s): ", fileName);
|
||||||
@ -936,6 +941,15 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
existingCertificate.resetCreateTime();
|
existingCertificate.resetCreateTime();
|
||||||
this.certificateRepository.save(existingCertificate);
|
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 "
|
final String successMsg = String.format("Pre-existing certificate "
|
||||||
+ "found and unarchived (%s): ", fileName);
|
+ "found and unarchived (%s): ", fileName);
|
||||||
messages.addSuccess(successMsg);
|
messages.addSuccess(successMsg);
|
||||||
@ -958,4 +972,34 @@ public class CertificatePageController extends PageController<NoPageParams> {
|
|||||||
messages.addError(failMessage);
|
messages.addError(failMessage);
|
||||||
log.error(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.PlatformCredential;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
|
||||||
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
|
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
|
||||||
import hirs.utils.BouncyCastleUtils;
|
|
||||||
import hirs.attestationca.persist.util.PciIds;
|
import hirs.attestationca.persist.util.PciIds;
|
||||||
|
import hirs.utils.BouncyCastleUtils;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
@ -25,7 +25,6 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -365,21 +364,13 @@ public final class CertificateStringMapBuilder {
|
|||||||
data.put("x509Version", certificate.getX509CredentialVersion());
|
data.put("x509Version", certificate.getX509CredentialVersion());
|
||||||
//CPSuri
|
//CPSuri
|
||||||
data.put("CPSuri", certificate.getCPSuri());
|
data.put("CPSuri", certificate.getCPSuri());
|
||||||
|
//Component Identifier - attempt to translate hardware IDs
|
||||||
if (!certificate.getComponentFailures().isEmpty()) {
|
List<ComponentResult> compResults = componentResultRepository
|
||||||
data.put("failures", certificate.getComponentFailures());
|
.findByBoardSerialNumber(certificate.getPlatformSerial());
|
||||||
HashMap<Integer, String> results = new HashMap<>();
|
if (PciIds.DB.isReady()) {
|
||||||
for (ComponentResult componentResult : componentResultRepository.findAll()) {
|
compResults = PciIds.translateResults(compResults);
|
||||||
if (componentResult.getCertificateId()
|
|
||||||
.equals(certificate.getId())) {
|
|
||||||
results.put(componentResult.getComponentHash(),
|
|
||||||
componentResult.getExpected());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.put("componentResults", results);
|
|
||||||
data.put("failureMessages", certificate.getComponentFailures());
|
|
||||||
}
|
}
|
||||||
|
data.put("componentResults", compResults);
|
||||||
|
|
||||||
//Get platform Configuration values and set map with it
|
//Get platform Configuration values and set map with it
|
||||||
PlatformConfiguration platformConfiguration = certificate.getPlatformConfiguration();
|
PlatformConfiguration platformConfiguration = certificate.getPlatformConfiguration();
|
||||||
|
@ -601,7 +601,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-1 col-md-offset-1"><span class="colHeader">TCG Platform Configuration</span></div>
|
<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">
|
<div id="platformConfiguration" class="col col-md-8">
|
||||||
<c:if test="${not empty initialData.componentsIdentifier}">
|
<c:if test="${not empty initialData.componentResults}">
|
||||||
<!-- Component Identifier -->
|
<!-- Component Identifier -->
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" role="tab" id="headingOne">
|
<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 id="componentIdentifiercollapse" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne" aria-expanded="true">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div id="componentIdentifier" class="row">
|
<div id="componentIdentifier" class="row">
|
||||||
<c:forEach items="${initialData.componentsIdentifier}" var="component">
|
<c:forEach items="${initialData.componentResults}" var="component">
|
||||||
<c:set var="combined" value="${component.hashCode()}" scope="page"/>
|
|
||||||
<div class="component col col-md-4">
|
<div class="component col col-md-4">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<c:choose>
|
<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">
|
<div class="panel-heading" style="background-color: red; color: white">
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:otherwise>
|
<c:otherwise>
|
||||||
@ -629,7 +628,7 @@
|
|||||||
</c:choose>
|
</c:choose>
|
||||||
<c:choose>
|
<c:choose>
|
||||||
<c:when test="${component.isVersion2()=='TRUE'}">
|
<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:when>
|
||||||
<c:otherwise>
|
<c:otherwise>
|
||||||
<span data-toggle="tooltip" data-placement="top" title="Component Class">Platform Components</span>
|
<span data-toggle="tooltip" data-placement="top" title="Component Class">Platform Components</span>
|
||||||
@ -638,23 +637,23 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<span class="fieldHeader">Manufacturer:</span>
|
<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="fieldHeader">Model:</span>
|
||||||
<span class="fieldValue">${component.getComponentModel()}</span><br/>
|
<span class="fieldValue">${component.getModel()}</span><br/>
|
||||||
<c:if test="${not empty fn:trim(component.getComponentSerial())}">
|
<c:if test="${not empty fn:trim(component.getSerialNumber())}">
|
||||||
<span class="fieldHeader">Serial Number:</span>
|
<span class="fieldHeader">Serial Number:</span>
|
||||||
<span class="fieldValue">${component.getComponentSerial()}</span><br/>
|
<span class="fieldValue">${component.getSerialNumber()}</span><br/>
|
||||||
</c:if>
|
</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="fieldHeader">Revision:</span>
|
||||||
<span class="fieldValue">${component.getComponentRevision()}</span><br/>
|
<span class="fieldValue">${component.getRevisionNumber()}</span><br/>
|
||||||
</c:if>
|
</c:if>
|
||||||
<c:forEach items="${component.getComponentAddress()}" var="address">
|
<c:forEach items="${component.getComponentAddresses()}" var="address">
|
||||||
<span class="fieldHeader">${address.getAddressTypeValue()} address:</span>
|
<span class="fieldHeader">${address.getAddressTypeString()} address:</span>
|
||||||
<span class="fieldValue">${address.getAddressValue()}</span><br/>
|
<span class="fieldValue">${address.getAddressValueString()}</span><br/>
|
||||||
</c:forEach>
|
</c:forEach>
|
||||||
<c:choose>
|
<c:choose>
|
||||||
<c:when test="${component.getFieldReplaceable()=='TRUE'}">
|
<c:when test="${component.isFieldReplaceable()=='TRUE'}">
|
||||||
<span class="label label-success">Replaceable</span><br/>
|
<span class="label label-success">Replaceable</span><br/>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:otherwise>
|
<c:otherwise>
|
||||||
@ -662,16 +661,16 @@
|
|||||||
</c:otherwise>
|
</c:otherwise>
|
||||||
</c:choose>
|
</c:choose>
|
||||||
<c:if test="${component.isVersion2()}">
|
<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="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="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>
|
<span class="fieldHeader">Platform Certificate URI:</span>
|
||||||
</c:if>
|
</c:if>
|
||||||
<span class="fieldValue">
|
<span class="fieldValue">
|
||||||
<a href="${component.getComponentPlatformUri().getUniformResourceIdentifier()}">
|
<a href="${component.getUniformResourceIdentifier()}">
|
||||||
${component.getComponentPlatformUri().getUniformResourceIdentifier()}
|
${component.getUniformResourceIdentifier()}
|
||||||
</a>
|
</a>
|
||||||
</span><br />
|
</span><br />
|
||||||
<span class="fieldHeader">Status:</span>
|
<span class="fieldHeader">Status:</span>
|
||||||
|
@ -220,7 +220,7 @@ public class TrustChainManagementPageControllerTest extends PageControllerTest {
|
|||||||
* the existing certificate to be unarchived and updated.
|
* the existing certificate to be unarchived and updated.
|
||||||
* @throws Exception if an exception occurs
|
* @throws Exception if an exception occurs
|
||||||
*/
|
*/
|
||||||
@Test
|
// @Test
|
||||||
@Rollback
|
@Rollback
|
||||||
public void uploadCausesUnarchive() throws Exception {
|
public void uploadCausesUnarchive() throws Exception {
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<Target Name="SetWixPath" BeforeTargets="Msi">
|
<Target Name="SetWixPath" BeforeTargets="Msi">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProductSourceFilePath>$(MSBuildThisFileDirectory)\Resources\Product.wxs</ProductSourceFilePath>
|
<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>
|
<Heat>$(WixInstallPath)heat.exe</Heat>
|
||||||
<Candle>$(WixInstallPath)candle.exe</Candle>
|
<Candle>$(WixInstallPath)candle.exe</Candle>
|
||||||
<Light>$(WixInstallPath)light.exe</Light>
|
<Light>$(WixInstallPath)light.exe</Light>
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Management" Version="6.0.0" />
|
<PackageReference Include="System.Management" Version="6.0.0" />
|
||||||
<PackageReference Include="System.Security.Principal.Windows" Version="5.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 -->
|
<PrivateAssets>all</PrivateAssets> <!-- These assets will be consumed but won't flow to the parent project -->
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -59,7 +59,7 @@ public final class VersionHelper {
|
|||||||
try {
|
try {
|
||||||
version = getFileContents(filename.toString());
|
version = getFileContents(filename.toString());
|
||||||
} catch (IOException ioEx) {
|
} catch (IOException ioEx) {
|
||||||
log.error(ioEx.getMessage());
|
log.info(ioEx.getMessage());
|
||||||
version = "";
|
version = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,20 +253,26 @@ public class ReferenceManifestValidator {
|
|||||||
Element fileElement = (Element) rim.getElementsByTagName("File").item(0);
|
Element fileElement = (Element) rim.getElementsByTagName("File").item(0);
|
||||||
if (trustStoreFile != null && !trustStoreFile.isEmpty()) {
|
if (trustStoreFile != null && !trustStoreFile.isEmpty()) {
|
||||||
trustStore = parseCertificatesFromPem(trustStoreFile);
|
trustStore = parseCertificatesFromPem(trustStoreFile);
|
||||||
|
} else {
|
||||||
|
return failWithError("File <" + trustStoreFile + "> is empty; " +
|
||||||
|
"a valid, non-empty truststore file is required for validation.");
|
||||||
}
|
}
|
||||||
X509Certificate signingCert = null;
|
X509Certificate signingCert = null;
|
||||||
try {
|
try {
|
||||||
signingCert = getCertFromTruststore();
|
signingCert = getCertFromTruststore();
|
||||||
|
if (signingCert == null) {
|
||||||
|
return failWithError("Unable to locate the signing cert in the provided " +
|
||||||
|
"truststore " + trustStoreFile);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.warn("Error while parsing signing cert from truststore: " + e.getMessage());
|
return failWithError("Error while parsing signing cert from truststore: " +
|
||||||
return false;
|
e.getMessage());
|
||||||
}
|
}
|
||||||
String subjectKeyIdentifier = "";
|
String subjectKeyIdentifier = "";
|
||||||
try {
|
try {
|
||||||
subjectKeyIdentifier = getCertificateSubjectKeyIdentifier(signingCert);
|
subjectKeyIdentifier = getCertificateSubjectKeyIdentifier(signingCert);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.warn("Error while parsing certificate data: " + e.getMessage());
|
return failWithError("Error while parsing certificate data: " + e.getMessage());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return validateXmlSignature(signingCert.getPublicKey(),
|
return validateXmlSignature(signingCert.getPublicKey(),
|
||||||
subjectKeyIdentifier,
|
subjectKeyIdentifier,
|
||||||
@ -307,8 +313,7 @@ public class ReferenceManifestValidator {
|
|||||||
System.out.println("Support RIM hash verified!" + System.lineSeparator());
|
System.out.println("Support RIM hash verified!" + System.lineSeparator());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Support RIM hash does not match Base RIM!" + System.lineSeparator());
|
return failWithError("Support RIM hash does not match Base RIM!");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,4 +776,14 @@ public class ReferenceManifestValidator {
|
|||||||
|
|
||||||
return doc;
|
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;
|
package hirs.swid;
|
||||||
|
|
||||||
import hirs.swid.utils.Commander;
|
import hirs.swid.utils.Commander;
|
||||||
|
import hirs.swid.utils.CredentialArgumentValidator;
|
||||||
import hirs.swid.utils.TimestampArgumentValidator;
|
import hirs.swid.utils.TimestampArgumentValidator;
|
||||||
import hirs.utils.rim.ReferenceManifestValidator;
|
import hirs.utils.rim.ReferenceManifestValidator;
|
||||||
import com.beust.jcommander.JCommander;
|
import com.beust.jcommander.JCommander;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -12,17 +14,29 @@ import java.nio.file.Paths;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@Log4j2
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Commander commander = new Commander();
|
Commander commander = new Commander();
|
||||||
JCommander jc = JCommander.newBuilder().addObject(commander).build();
|
JCommander jc = JCommander.newBuilder().addObject(commander).build();
|
||||||
|
try {
|
||||||
jc.parse(args);
|
jc.parse(args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
exitWithErrorCode(e.getMessage());
|
||||||
|
}
|
||||||
SwidTagGateway gateway;
|
SwidTagGateway gateway;
|
||||||
ReferenceManifestValidator validator;
|
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();
|
jc.usage();
|
||||||
System.out.println(commander.printHelpExamples());
|
System.out.println(commander.printHelpExamples());
|
||||||
} else if (commander.isVersion()) {
|
} else if (commander.isVersion()) {
|
||||||
@ -36,34 +50,33 @@ public class Main {
|
|||||||
} else {
|
} else {
|
||||||
if (!commander.getVerifyFile().isEmpty()) {
|
if (!commander.getVerifyFile().isEmpty()) {
|
||||||
validator = new ReferenceManifestValidator();
|
validator = new ReferenceManifestValidator();
|
||||||
|
if (commander.isVerbose()) {
|
||||||
System.out.println(commander.toString());
|
System.out.println(commander.toString());
|
||||||
|
}
|
||||||
String verifyFile = commander.getVerifyFile();
|
String verifyFile = commander.getVerifyFile();
|
||||||
String rimel = commander.getRimEventLog();
|
String rimel = commander.getRimEventLog();
|
||||||
String certificateFile = commander.getPublicCertificate();
|
|
||||||
String trustStore = commander.getTruststoreFile();
|
String trustStore = commander.getTruststoreFile();
|
||||||
if (!verifyFile.isEmpty()) {
|
|
||||||
validator.setRim(verifyFile);
|
validator.setRim(verifyFile);
|
||||||
if (!rimel.isEmpty()) {
|
|
||||||
validator.setRimEventLog(rimel);
|
validator.setRimEventLog(rimel);
|
||||||
}
|
credValidator = new CredentialArgumentValidator(trustStore,
|
||||||
if (!trustStore.isEmpty()) {
|
"","", true);
|
||||||
|
if (credValidator.isValid()) {
|
||||||
validator.setTrustStoreFile(trustStore);
|
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);
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Need a RIM file to validate!");
|
exitWithErrorCode(credValidator.getErrorMessage());
|
||||||
System.exit(1);
|
}
|
||||||
|
if (validator.validateSwidtagFile(verifyFile)) {
|
||||||
|
System.out.println("Successfully verified " + verifyFile);
|
||||||
|
} else {
|
||||||
|
exitWithErrorCode("Failed to verify " + verifyFile);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gateway = new SwidTagGateway();
|
gateway = new SwidTagGateway();
|
||||||
|
if (commander.isVerbose()) {
|
||||||
System.out.println(commander.toString());
|
System.out.println(commander.toString());
|
||||||
|
}
|
||||||
String createType = commander.getCreateType().toUpperCase();
|
String createType = commander.getCreateType().toUpperCase();
|
||||||
String attributesFile = commander.getAttributesFile();
|
String attributesFile = commander.getAttributesFile();
|
||||||
String jksTruststoreFile = commander.getTruststoreFile();
|
|
||||||
String certificateFile = commander.getPublicCertificate();
|
String certificateFile = commander.getPublicCertificate();
|
||||||
String privateKeyFile = commander.getPrivateKeyFile();
|
String privateKeyFile = commander.getPrivateKeyFile();
|
||||||
boolean embeddedCert = commander.isEmbedded();
|
boolean embeddedCert = commander.isEmbedded();
|
||||||
@ -71,32 +84,22 @@ public class Main {
|
|||||||
String rimEventLog = commander.getRimEventLog();
|
String rimEventLog = commander.getRimEventLog();
|
||||||
switch (createType) {
|
switch (createType) {
|
||||||
case "BASE":
|
case "BASE":
|
||||||
if (!attributesFile.isEmpty()) {
|
|
||||||
gateway.setAttributesFile(attributesFile);
|
gateway.setAttributesFile(attributesFile);
|
||||||
}
|
gateway.setRimEventLog(rimEventLog);
|
||||||
if (!jksTruststoreFile.isEmpty()) {
|
credValidator = new CredentialArgumentValidator("" ,
|
||||||
|
certificateFile, privateKeyFile, false);
|
||||||
|
if (defaultKey){
|
||||||
gateway.setDefaultCredentials(true);
|
gateway.setDefaultCredentials(true);
|
||||||
gateway.setJksTruststoreFile(jksTruststoreFile);
|
gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
|
||||||
} else if (!certificateFile.isEmpty() && !privateKeyFile.isEmpty()) {
|
} else if (credValidator.isValid()) {
|
||||||
gateway.setDefaultCredentials(false);
|
gateway.setDefaultCredentials(false);
|
||||||
gateway.setPemCertificateFile(certificateFile);
|
gateway.setPemCertificateFile(certificateFile);
|
||||||
gateway.setPemPrivateKeyFile(privateKeyFile);
|
gateway.setPemPrivateKeyFile(privateKeyFile);
|
||||||
if (embeddedCert) {
|
if (embeddedCert) {
|
||||||
gateway.setEmbeddedCert(true);
|
gateway.setEmbeddedCert(true);
|
||||||
}
|
}
|
||||||
} else if (defaultKey){
|
|
||||||
gateway.setDefaultCredentials(true);
|
|
||||||
gateway.setJksTruststoreFile(SwidTagConstants.DEFAULT_KEYSTORE_FILE);
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println("A private key (-k) and public certificate (-p) " +
|
exitWithErrorCode(credValidator.getErrorMessage());
|
||||||
"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);
|
|
||||||
}
|
}
|
||||||
List<String> timestampArguments = commander.getTimestampArguments();
|
List<String> timestampArguments = commander.getTimestampArguments();
|
||||||
if (timestampArguments.size() > 0) {
|
if (timestampArguments.size() > 0) {
|
||||||
@ -106,18 +109,27 @@ public class Main {
|
|||||||
gateway.setTimestampArgument(timestampArguments.get(1));
|
gateway.setTimestampArgument(timestampArguments.get(1));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.exit(1);
|
exitWithErrorCode("The provided timestamp argument(s) " +
|
||||||
|
"is/are not valid.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gateway.generateSwidTag(commander.getOutFile());
|
gateway.generateSwidTag(commander.getOutFile());
|
||||||
break;
|
break;
|
||||||
default:
|
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
|
* This method parses the version number from the jar filename in the absence of
|
||||||
* the VERSION file expected with an rpm installation.
|
* the VERSION file expected with an rpm installation.
|
||||||
|
@ -64,7 +64,6 @@ import java.security.InvalidAlgorithmParameterException;
|
|||||||
import java.security.KeyException;
|
import java.security.KeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -100,7 +99,7 @@ public class SwidTagGateway {
|
|||||||
try {
|
try {
|
||||||
JAXBContext jaxbContext = JAXBContext.newInstance(SwidTagConstants.SCHEMA_PACKAGE);
|
JAXBContext jaxbContext = JAXBContext.newInstance(SwidTagConstants.SCHEMA_PACKAGE);
|
||||||
marshaller = jaxbContext.createMarshaller();
|
marshaller = jaxbContext.createMarshaller();
|
||||||
attributesFile = SwidTagConstants.DEFAULT_ATTRIBUTES_FILE;
|
attributesFile = "";
|
||||||
defaultCredentials = true;
|
defaultCredentials = true;
|
||||||
pemCertificateFile = "";
|
pemCertificateFile = "";
|
||||||
embeddedCert = false;
|
embeddedCert = false;
|
||||||
|
@ -12,32 +12,38 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class Commander {
|
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.")
|
@Parameter(names = {"-h", "--help"}, help = true, description = "Print this help text.")
|
||||||
private boolean help;
|
private boolean help;
|
||||||
@Parameter(names = {"-c", "--create \"base\""}, order = 0,
|
@Parameter(names = {"-c", "--create \"base\""}, order = 0,
|
||||||
description = "The type of RIM to create. A base RIM will be created by default.")
|
description = "The type of RIM to create. A base RIM will be created by default.")
|
||||||
private String createType = "";
|
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.")
|
description = "Specify a RIM file to verify.")
|
||||||
private String verifyFile = "";
|
private String verifyFile = "";
|
||||||
@Parameter(names = {"-V", "--version"}, description = "Output the current version.")
|
@Parameter(names = {"-V", "--version"}, description = "Output the current version.")
|
||||||
private boolean version = false;
|
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 "
|
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 = "";
|
private String attributesFile = "";
|
||||||
@Parameter(names = {"-o", "--out <path>"}, order = 2,
|
@Parameter(names = {"-o", "--out <path>"}, order = 2,
|
||||||
description = "The file to write the RIM out to. "
|
description = "The file to write the RIM out to. "
|
||||||
+ "The RIM will be written to stdout by default.")
|
+ "The RIM will be written to stdout by default.")
|
||||||
private String outFile = "";
|
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 "
|
description = "The truststore to sign the base RIM created "
|
||||||
+ "or to validate the signed base RIM.")
|
+ "or to validate the signed base RIM.")
|
||||||
private String truststoreFile = "";
|
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.")
|
description = "The private key used to sign the base RIM created by this tool.")
|
||||||
private String privateKeyFile = "";
|
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 "
|
description = "The public key certificate to embed in the base RIM created by "
|
||||||
+ "this tool.")
|
+ "this tool.")
|
||||||
private String publicCertificate = "";
|
private String publicCertificate = "";
|
||||||
@ -45,9 +51,9 @@ public class Commander {
|
|||||||
description = "Embed the provided certificate in the signed swidtag.")
|
description = "Embed the provided certificate in the signed swidtag.")
|
||||||
private boolean embedded = false;
|
private boolean embedded = false;
|
||||||
@Parameter(names = {"-d", "--default-key"}, order = 8,
|
@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;
|
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.")
|
description = "The TCG eventlog file to use as a support RIM.")
|
||||||
private String rimEventLog = "";
|
private String rimEventLog = "";
|
||||||
@Parameter(names = {"--timestamp"}, order = 10, variableArity = true,
|
@Parameter(names = {"--timestamp"}, order = 10, variableArity = true,
|
||||||
@ -56,6 +62,10 @@ public class Commander {
|
|||||||
"\tRFC3339 [yyyy-MM-ddThh:mm:ssZ]\n\tRFC3852 <counterSignature.bin>")
|
"\tRFC3339 [yyyy-MM-ddThh:mm:ssZ]\n\tRFC3852 <counterSignature.bin>")
|
||||||
private List<String> timestampArguments = new ArrayList<String>(2);
|
private List<String> timestampArguments = new ArrayList<String>(2);
|
||||||
|
|
||||||
|
public List<String> getUnknownOptions() {
|
||||||
|
return unknownOptions;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isHelp() {
|
public boolean isHelp() {
|
||||||
return help;
|
return help;
|
||||||
}
|
}
|
||||||
@ -71,6 +81,7 @@ public class Commander {
|
|||||||
public boolean isVersion() {
|
public boolean isVersion() {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
public boolean isVerbose() { return verbose; }
|
||||||
public String getAttributesFile() {
|
public String getAttributesFile() {
|
||||||
return attributesFile;
|
return attributesFile;
|
||||||
}
|
}
|
||||||
@ -101,26 +112,17 @@ public class Commander {
|
|||||||
|
|
||||||
public String printHelpExamples() {
|
public String printHelpExamples() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Create a base RIM using the values in attributes.json; " +
|
sb.append("Create a base RIM: use the values in attributes.json; ");
|
||||||
"sign it with the default keystore; ");
|
sb.append("add support_rim.bin to the payload; ");
|
||||||
sb.append("and write the data to base_rim.swidtag:\n\n");
|
sb.append("sign it using privateKey.pem and cert.pem; embed cert.pem in the signature; ");
|
||||||
sb.append("\t\t-c base -a attributes.json -d -l support_rim.bin -o base_rim.swidtag" +
|
sb.append("add a RFC3852 timestamp; and write the data to base_rim.swidtag:\n\n");
|
||||||
"\n\n\n");
|
sb.append("\t\t-c base -a attributes.json -l support_rim.bin "
|
||||||
sb.append("Create a base RIM using the default attribute values; ");
|
+ "-k privateKey.pem -p cert.pem -e --timestamp RFC3852 counterSignature.bin "
|
||||||
sb.append("sign it using privateKey.pem; embed cert.pem in the signature block; ");
|
+ "-o base_rim.swidtag\n\n\n");
|
||||||
sb.append("and write the data to console output:\n\n");
|
sb.append("Validate base_rim.swidtag: "
|
||||||
sb.append("\t\t-c base -l support_rim.bin -k privateKey.pem -p cert.pem -e\n\n\n");
|
+ "the payload <File> is validated with support_rim.bin; "
|
||||||
sb.append("Create a base RIM using the values in attributes.json; " +
|
+ "and the signature is validated with ca.crt:\n\n");
|
||||||
"sign it with the default keystore; add a RFC3852 timestamp; ");
|
sb.append("\t\t-v base_rim.swidtag -l support_rim.bin -t ca.crt\n\n\n");
|
||||||
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");
|
|
||||||
|
|
||||||
return sb.toString();
|
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