Merge branch 'main' into v3_issue_909-refactor-requestmapping
Some checks failed
Dotnet Provisioner Unit Tests / Restore and Run Unit Tests (ubuntu-latest) (push) Has been cancelled
Dotnet Provisioner Unit Tests / Restore and Run Unit Tests (windows-2022) (push) Has been cancelled
HIRS Build and Unit Test / ACA_Provisioner_Unit_Tests (push) Has been cancelled
HIRS System Tests / DockerTests (push) Has been cancelled
Dotnet Provisioner Unit Tests / Evaluate Tests (push) Has been cancelled

This commit is contained in:
ThatSilentCoder 2025-04-10 15:49:38 -04:00
commit baf0c51ce4
55 changed files with 2657 additions and 2114 deletions

View File

@ -1,3 +1,4 @@
# Updated: 02/11/2025
name: Create ACA Docker Image
on:
release:
@ -17,7 +18,7 @@ env:
PUBLIC_IMAGE_NAME: ghcr.io/nsacyber/hirs/aca
PUBLIC_IMAGE_TAG_LATEST: ghcr.io/nsacyber/hirs/aca:latest
TAG_LATEST: ${{ github.event_name == 'release' || inputs.also_tag_latest }} # The public docker image will be tagged 'latest' for releases, or if this option is manually selected.
jobs:
jobs:
setup:
runs-on: ubuntu-latest
outputs:
@ -27,44 +28,44 @@ jobs:
WINDOWS_COMPAT_IMAGE_TAG: ${{ steps.setenv.outputs.WINDOWS_COMPAT_IMAGE_TAG }}
PUBLIC_IMAGE_TAG: ${{ steps.setenv.outputs.PUBLIC_IMAGE_TAG }}
steps:
- name: Set env
id: setenv
shell: bash
run: |
# Parse docker image tag from GitHub tag if available
if [ "${{ github.ref_type }}" = "tag" ]; then
# tags start with refs/tags/. Also remove v if it exists.
export IMAGE_TAG_VAR=${GITHUB_REF:10}
export IMAGE_TAG_VAR=${IMAGE_TAG_VAR//v/}
else
# Not a tag, use the commit hash. Do not tag as latest.
export IMAGE_TAG_VAR=${GITHUB_SHA:0:7}
fi
# To lowercase
export IMAGE_TAG_VAR=${IMAGE_TAG_VAR,,}
# Save to output
echo "IMAGE_TAG=$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
echo "ROCKY_IMAGE_TAG=$IMAGE_NAME_ROCKY:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
echo "WINDOWS_IMAGE_TAG=$IMAGE_NAME_WINDOWS:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
echo "WINDOWS_COMPAT_IMAGE_TAG=$IMAGE_NAME_WINDOWS_COMPAT:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
echo "PUBLIC_IMAGE_TAG=$PUBLIC_IMAGE_NAME:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
- name: Print env
run: |
echo GITHUB_REF_NAME=${{ github.ref_name }}
echo DOCKERFILE_ROCKY=$DOCKERFILE_ROCKY
echo DOCKERFILE_WINDOWS=$DOCKERFILE_WINDOWS
echo IMAGE_NAME_ROCKY=$IMAGE_NAME_ROCKY
echo IMAGE_NAME_WINDOWS=$IMAGE_NAME_WINDOWS
echo IMAGE_NAME_WINDOWS_COMPAT=$IMAGE_NAME_WINDOWS_COMPAT
echo PUBLIC_IMAGE_NAME=$PUBLIC_IMAGE_NAME
echo PUBLIC_IMAGE_TAG_LATEST=$PUBLIC_IMAGE_TAG_LATEST
echo TAG_LATEST=$TAG_LATEST
echo IMAGE_TAG=${{ steps.setenv.outputs.IMAGE_TAG }}
echo ROCKY_IMAGE_TAG=${{ steps.setenv.outputs.ROCKY_IMAGE_TAG }}
echo WINDOWS_IMAGE_TAG=${{ steps.setenv.outputs.WINDOWS_IMAGE_TAG }}
echo WINDOWS_COMPAT_IMAGE_TAG=${{ steps.setenv.outputs.WINDOWS_COMPAT_IMAGE_TAG }}
echo PUBLIC_IMAGE_TAG=${{ steps.setenv.outputs.PUBLIC_IMAGE_TAG }}
- name: Set env
id: setenv
shell: bash
run: |
# Parse docker image tag from GitHub tag if available
if [ "${{ github.ref_type }}" = "tag" ]; then
# tags start with refs/tags/. Also remove v if it exists.
export IMAGE_TAG_VAR=${GITHUB_REF:10}
export IMAGE_TAG_VAR=${IMAGE_TAG_VAR//v/}
else
# Not a tag, use the commit hash. Do not tag as latest.
export IMAGE_TAG_VAR=${GITHUB_SHA:0:7}
fi
# To lowercase
export IMAGE_TAG_VAR=${IMAGE_TAG_VAR,,}
# Save to output
echo "IMAGE_TAG=$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
echo "ROCKY_IMAGE_TAG=$IMAGE_NAME_ROCKY:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
echo "WINDOWS_IMAGE_TAG=$IMAGE_NAME_WINDOWS:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
echo "WINDOWS_COMPAT_IMAGE_TAG=$IMAGE_NAME_WINDOWS_COMPAT:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
echo "PUBLIC_IMAGE_TAG=$PUBLIC_IMAGE_NAME:$IMAGE_TAG_VAR" >> "$GITHUB_OUTPUT"
- name: Print env
run: |
echo GITHUB_REF_NAME=${{ github.ref_name }}
echo DOCKERFILE_ROCKY=$DOCKERFILE_ROCKY
echo DOCKERFILE_WINDOWS=$DOCKERFILE_WINDOWS
echo IMAGE_NAME_ROCKY=$IMAGE_NAME_ROCKY
echo IMAGE_NAME_WINDOWS=$IMAGE_NAME_WINDOWS
echo IMAGE_NAME_WINDOWS_COMPAT=$IMAGE_NAME_WINDOWS_COMPAT
echo PUBLIC_IMAGE_NAME=$PUBLIC_IMAGE_NAME
echo PUBLIC_IMAGE_TAG_LATEST=$PUBLIC_IMAGE_TAG_LATEST
echo TAG_LATEST=$TAG_LATEST
echo IMAGE_TAG=${{ steps.setenv.outputs.IMAGE_TAG }}
echo ROCKY_IMAGE_TAG=${{ steps.setenv.outputs.ROCKY_IMAGE_TAG }}
echo WINDOWS_IMAGE_TAG=${{ steps.setenv.outputs.WINDOWS_IMAGE_TAG }}
echo WINDOWS_COMPAT_IMAGE_TAG=${{ steps.setenv.outputs.WINDOWS_COMPAT_IMAGE_TAG }}
echo PUBLIC_IMAGE_TAG=${{ steps.setenv.outputs.PUBLIC_IMAGE_TAG }}
rocky-image:
needs: setup
@ -72,78 +73,78 @@ jobs:
env:
TAG: ${{ needs.setup.outputs.ROCKY_IMAGE_TAG }}
steps:
- name: Checkout main
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push a release Docker image for ${{ github.repository }}
uses: docker/build-push-action@v5
with:
context: "{{defaultContext}}:.ci/docker"
file: Dockerfile.${{env.DOCKERFILE_ROCKY}}
build-args: REF=${{ github.ref_name }}
tags: ${{env.TAG}}
push: true
- name: Checkout main
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push a release Docker image for ${{ github.repository }}
uses: docker/build-push-action@v5
with:
context: "{{defaultContext}}:.ci/docker"
file: Dockerfile.${{env.DOCKERFILE_ROCKY}}
build-args: REF=${{ github.ref_name }}
tags: ${{env.TAG}}
push: true
windows-11-image:
needs: setup
runs-on: windows-latest
env:
TAG: ${{ needs.setup.outputs.WINDOWS_IMAGE_TAG }}
steps:
- name: Checkout main
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout main
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build the docker image for ${{ github.repository }}
run: |
cd ./.ci/docker
docker build --build-arg REF=${{ github.ref_name }} -f ./Dockerfile.${{env.DOCKERFILE_WINDOWS}} -t ${{env.TAG}} .
- name: Push the docker image
run: |
docker push ${{env.TAG}}
- name: Build the docker image for ${{ github.repository }}
run: |
cd ./.ci/docker
docker build --build-arg REF=${{ github.ref_name }} -f ./Dockerfile.${{env.DOCKERFILE_WINDOWS}} -t ${{env.TAG}} .
- name: Push the docker image
run: |
docker push ${{env.TAG}}
windows-compat-image: # This job uses a different runner and build arg than the other windows job.
needs: setup
runs-on: windows-2019
env:
TAG: ${{ needs.setup.outputs.WINDOWS_COMPAT_IMAGE_TAG }}
steps:
- name: Checkout main
uses: actions/checkout@v4
- name: Checkout main
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build the docker image for ${{ github.repository }}
run: |
cd ./.ci/docker
docker build --build-arg REF=${{ github.ref_name }} -f ./Dockerfile.${{env.DOCKERFILE_WINDOWS}} -t ${{env.TAG}} --build-arg BASE_IMAGE_TAG=lts-windowsservercore-1809 .
- name: Push the docker image
run: |
docker push ${{env.TAG}}
- name: Build the docker image for ${{ github.repository }}
run: |
cd ./.ci/docker
docker build --build-arg REF=${{ github.ref_name }} -f ./Dockerfile.${{env.DOCKERFILE_WINDOWS}} -t ${{env.TAG}} --build-arg BASE_IMAGE_TAG=lts-windowsservercore-1809 .
- name: Push the docker image
run: |
docker push ${{env.TAG}}
manifest:
needs: [setup, rocky-image, windows-11-image, windows-compat-image]
needs: [ setup, rocky-image, windows-11-image, windows-compat-image ]
runs-on: ubuntu-latest
env:
IMAGE1: ${{ needs.setup.outputs.ROCKY_IMAGE_TAG }}
@ -151,34 +152,34 @@ jobs:
IMAGE3: ${{ needs.setup.outputs.WINDOWS_COMPAT_IMAGE_TAG }}
PUB: ${{ needs.setup.outputs.PUBLIC_IMAGE_TAG }}
steps:
- name: Print env
run: |
echo IMAGE1=${{env.IMAGE1}}
echo IMAGE2=${{env.IMAGE2}}
echo IMAGE3=${{env.IMAGE3}}
echo PUB=${{env.PUB}}
- name: Checkout main
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create a new manifest
run: |
docker manifest create ${{env.PUB}} --amend ${{env.IMAGE1}} --amend ${{env.IMAGE2}} --amend ${{env.IMAGE3}}
- name: Push the new manifest
run: |
docker manifest push ${{env.PUB}}
- name: Create and push manifest latest if selected
if: env.TAG_LATEST != 'false'
run: |
docker manifest create $PUBLIC_IMAGE_TAG_LATEST --amend $IMAGE1 --amend $IMAGE2 --amend $IMAGE3
docker manifest push $PUBLIC_IMAGE_TAG_LATEST
- name: Print env
run: |
echo IMAGE1=${{env.IMAGE1}}
echo IMAGE2=${{env.IMAGE2}}
echo IMAGE3=${{env.IMAGE3}}
echo PUB=${{env.PUB}}
- name: Checkout main
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create a new manifest
run: |
docker manifest create ${{env.PUB}} --amend ${{env.IMAGE1}} --amend ${{env.IMAGE2}} --amend ${{env.IMAGE3}}
- name: Push the new manifest
run: |
docker manifest push ${{env.PUB}}
- name: Create and push manifest latest if selected
if: env.TAG_LATEST != 'false'
run: |
docker manifest create $PUBLIC_IMAGE_TAG_LATEST --amend $IMAGE1 --amend $IMAGE2 --amend $IMAGE3
docker manifest push $PUBLIC_IMAGE_TAG_LATEST

View File

@ -1,8 +1,9 @@
# Updated: 02/11/2025
name: Dotnet Provisioner Unit Tests
on: push
env:
DOTNET_VERSION: '6.0'
DOTNET_VERSION: '8.0'
jobs:
dotnet_provisioner_unit_tests:
name: Restore and Run Unit Tests
@ -12,7 +13,7 @@ jobs:
matrix:
include:
- os: windows-2022
- os: ubuntu-20.04
- os: ubuntu-latest
# - os: windows-2019 Cannot Target windows-2019 because the .NET 6 SDK won't receive security patches for this image
steps:
- name: Set git to use LF
@ -97,7 +98,7 @@ jobs:
Evaluator:
name: Evaluate Tests
needs: [dotnet_provisioner_unit_tests]
needs: [ dotnet_provisioner_unit_tests ]
runs-on: ubuntu-latest
continue-on-error: false
steps:

View File

@ -1,3 +1,4 @@
# Updated: 02/11/2025
name: HIRS build and packages for Linux
on:
push:
@ -8,34 +9,34 @@ on:
jobs:
# run the package script for HIRS ACA, Provisioners, tcg_rim_tool, and tcg_eventlog_tool
Package_linux:
Package_linux:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: directory setup
run: |
mkdir -p artifacts/jars
mkdir -p artifacts/win
mkdir -p artifacts/win/hirstools
- name: install dependencies
run: |
sudo apt-get update
sudo apt-get install git curl nano cron mariadb-server
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- name: Execute Gradle build
run: |
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: directory setup
run: |
mkdir -p artifacts/jars
mkdir -p artifacts/win
mkdir -p artifacts/win/hirstools
- name: install dependencies
run: |
sudo apt-get update
sudo apt-get install git curl nano cron mariadb-server
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Execute Gradle build
run: |
./gradlew build;
./gradlew bootWar;
./gradlew buildDeb;
@ -48,35 +49,35 @@ jobs:
cp tools/tcg_rim_tool/build/distributions/*.zip artifacts/win
cp tools/tcg_eventlog_tool/build/distributions/*.zip artifacts/win
cp package/win/tcg-rim-tool/* artifacts/win/hirstools
- name: Archive RPM files
uses: actions/upload-artifact@v4
with:
name: RPM_Files
path: HIRS_AttestationCAPortal/build/distributions/*.rpm
if-no-files-found: error
- name: Archive DEB files
uses: actions/upload-artifact@v4
with:
name: DEB_Files
path: HIRS_AttestationCAPortal/build/distributions/*.deb
if-no-files-found: error
- name: War files
uses: actions/upload-artifact@v4
with:
name: WAR_Files
path: HIRS_AttestationCAPortal/build/libs/HIRS_AttestationCAPortal.war
if-no-files-found: error
- name: JAR_Files
uses: actions/upload-artifact@v4
with:
name: JAR_Files
path: artifacts/jars/
if-no-files-found: error
- name: ZIP_Files
uses: actions/upload-artifact@v4
with:
name: ZIP_Files
path: artifacts/win/
if-no-files-found: error
- name: Archive RPM files
uses: actions/upload-artifact@v4
with:
name: RPM_Files
path: HIRS_AttestationCAPortal/build/distributions/*.rpm
if-no-files-found: error
- name: Archive DEB files
uses: actions/upload-artifact@v4
with:
name: DEB_Files
path: HIRS_AttestationCAPortal/build/distributions/*.deb
if-no-files-found: error
- name: War files
uses: actions/upload-artifact@v4
with:
name: WAR_Files
path: HIRS_AttestationCAPortal/build/libs/HIRS_AttestationCAPortal.war
if-no-files-found: error
- name: JAR_Files
uses: actions/upload-artifact@v4
with:
name: JAR_Files
path: artifacts/jars/
if-no-files-found: error
- name: ZIP_Files
uses: actions/upload-artifact@v4
with:
name: ZIP_Files
path: artifacts/win/
if-no-files-found: error

View File

@ -1,6 +1,5 @@
# This workflow will build HIRS, run unit tests, and create HIRS artifacts
# Updated: 8/15/23
# Updated: 02/11/2025
name: HIRS Build and Unit Test
on:
@ -17,82 +16,82 @@ jobs:
ACA_Provisioner_Unit_Tests:
runs-on: ubuntu-latest # Configures the job to run on the latest version of an Ubuntu Linux runner
steps:
- uses: actions/checkout@v3 # run v3 of actions/checkout action, which checks out your repository onto the runner
# Build will archive build reports and will create a failedFile if build is not successful
- name: Directory setup
run: |
mkdir -p artifacts/githubActionsResults
mkdir -p artifacts/upload_reports/HIRS_AttestationCA
mkdir -p artifacts/upload_reports/HIRS_AttestationCAPortal
mkdir -p artifacts/upload_reports/HIRS_Provisioner
mkdir -p artifacts/upload_reports/HIRS_ProvisionerTPM2
mkdir -p artifacts/upload_reports/HIRS_Structs
mkdir -p artifacts/upload_reports/HIRS_Utils
mkdir -p artifacts/upload_reports/tcg_rim_tool
mkdir -p artifacts/upload_reports/tcg_eventlog_tool
# Run the provisioner and ACA unit tests via gradle build in a Rocky Docker container
- name: Build HIRS and run unit tests
run: |
# log into and run docker (note: must set up secrets in github for ghcr username and access_token)
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u $ --password-stdin
# docker run options:
# create a mount between curr directory on the runner and the HIRS folder created by the cloning of HIRS repo
# -v $(pwd):/HIRS
# image used for the container, given by <repository>:<tag_name>
# rocky8: ghcr.io/nsacyber/hirs/hirs-rocky8-ci:latest [repo: https://github.com/orgs/nsacyber/packages]
# bash commands to clean/build/test each subproject
# /bin/bash -c '<commands>'
docker run --rm \
-v $(pwd):/HIRS \
ghcr.io/nsacyber/hirs/hirs-rocky8-ci:latest /bin/bash -c \
'pushd /HIRS
gradle_status=0
# git added a feature that gives error if user is not owner of the top-level directory; need to override this
git config --global --add safe.directory /HIRS
# clean, build and run unit tests on all sub-projects; copy build reports to an artifacts directory
./gradlew :HIRS_AttestationCA:clean :HIRS_AttestationCA:build :HIRS_AttestationCA:test
if (( $? != "0" )) ; then gradle_status=1; fi
cp -r /HIRS/HIRS_AttestationCA/build/reports/ /HIRS/artifacts/upload_reports/HIRS_AttestationCA/.
./gradlew :HIRS_AttestationCAPortal:clean :HIRS_AttestationCAPortal:build :HIRS_AttestationCAPortal:test
if (( $? != "0" )) ; then gradle_status=1; fi
cp -r /HIRS/HIRS_AttestationCAPortal/build/reports/ /HIRS/artifacts/upload_reports/HIRS_AttestationCAPortal/.
#./gradlew :HIRS_Provisioner:clean :HIRS_Provisioner:build :HIRS_Provisioner:test
#if (( $? != "0" )) ; then gradle_status=1; fi
#cp -r /HIRS/HIRS_Provisioner/build/reports/ /HIRS/artifacts/upload_reports/HIRS_Provisioner/.
#./gradlew :HIRS_ProvisionerTPM2:clean :HIRS_ProvisionerTPM2:build :HIRS_ProvisionerTPM2:test
#if (( $? != "0" )) ; then gradle_status=1; fi
#cp -r /HIRS/HIRS_ProvisionerTPM2/docs/ /HIRS/artifacts/upload_reports/HIRS_ProvisionerTPM2/.
./gradlew :HIRS_Structs:clean :HIRS_Structs:build :HIRS_Structs:test
if (( $? != "0" )) ; then gradle_status=1; fi
cp -r /HIRS/HIRS_Structs/build/reports/ /HIRS/artifacts/upload_reports/HIRS_Structs/.
./gradlew :HIRS_Utils:clean :HIRS_Utils:build :HIRS_Utils:test
if (( $? != "0" )) ; then gradle_status=1; fi
cp -r /HIRS/HIRS_Utils/build/reports/ /HIRS/artifacts/upload_reports/HIRS_Utils/.
#./gradlew :TPM_Utils:clean :TPM_Utils:build :TPM_Utils:test
#if (( $? != "0" )) ; then gradle_status=1; fi
# Create "fail file" to fail the Build ACA tests if gradle exited with anything other than 0
if (( $gradle_status == "0" )) ; then
echo "In docker: Build Passed"
else
echo "In docker: Build Failed"
touch /HIRS/artifacts/githubActionsResults/buildFailed.txt
fi; popd;'
# Upload build report files
- name: Archive report files
uses: actions/upload-artifact@v4
with:
name: HIRS_Build_Reports
path: artifacts/upload_reports/*
if-no-files-found: ignore
# If buildFailed file exists, use that to fail the ACA unit tests
- name: Check if build/test passed or failed
if: ${{ hashFiles('artifacts/githubActionsResults/buildFailed.txt') != '' }}
uses: actions/github-script@v6
with:
script: |
core.setFailed('Build or Unit Test Failed')
- uses: actions/checkout@v4 # run v4 of actions/checkout action, which checks out your repository onto the runner
# Build will archive build reports and will create a failedFile if build is not successful
- name: Directory setup
run: |
mkdir -p artifacts/githubActionsResults
mkdir -p artifacts/upload_reports/HIRS_AttestationCA
mkdir -p artifacts/upload_reports/HIRS_AttestationCAPortal
mkdir -p artifacts/upload_reports/HIRS_Provisioner
mkdir -p artifacts/upload_reports/HIRS_ProvisionerTPM2
mkdir -p artifacts/upload_reports/HIRS_Structs
mkdir -p artifacts/upload_reports/HIRS_Utils
mkdir -p artifacts/upload_reports/tcg_rim_tool
mkdir -p artifacts/upload_reports/tcg_eventlog_tool
# Run the provisioner and ACA unit tests via gradle build in a Rocky Docker container
- name: Build HIRS and run unit tests
run: |
# log into and run docker (note: must set up secrets in github for ghcr username and access_token)
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u $ --password-stdin
# docker run options:
# create a mount between curr directory on the runner and the HIRS folder created by the cloning of HIRS repo
# -v $(pwd):/HIRS
# image used for the container, given by <repository>:<tag_name>
# rocky8: ghcr.io/nsacyber/hirs/hirs-rocky8-ci:latest [repo: https://github.com/orgs/nsacyber/packages]
# bash commands to clean/build/test each subproject
# /bin/bash -c '<commands>'
docker run --rm \
-v $(pwd):/HIRS \
ghcr.io/nsacyber/hirs/hirs-rocky8-ci:latest /bin/bash -c \
'pushd /HIRS
gradle_status=0
# git added a feature that gives error if user is not owner of the top-level directory; need to override this
git config --global --add safe.directory /HIRS
# clean, build and run unit tests on all sub-projects; copy build reports to an artifacts directory
./gradlew :HIRS_AttestationCA:clean :HIRS_AttestationCA:build :HIRS_AttestationCA:test
if (( $? != "0" )) ; then gradle_status=1; fi
cp -r /HIRS/HIRS_AttestationCA/build/reports/ /HIRS/artifacts/upload_reports/HIRS_AttestationCA/.
./gradlew :HIRS_AttestationCAPortal:clean :HIRS_AttestationCAPortal:build :HIRS_AttestationCAPortal:test
if (( $? != "0" )) ; then gradle_status=1; fi
cp -r /HIRS/HIRS_AttestationCAPortal/build/reports/ /HIRS/artifacts/upload_reports/HIRS_AttestationCAPortal/.
#./gradlew :HIRS_Provisioner:clean :HIRS_Provisioner:build :HIRS_Provisioner:test
#if (( $? != "0" )) ; then gradle_status=1; fi
#cp -r /HIRS/HIRS_Provisioner/build/reports/ /HIRS/artifacts/upload_reports/HIRS_Provisioner/.
#./gradlew :HIRS_ProvisionerTPM2:clean :HIRS_ProvisionerTPM2:build :HIRS_ProvisionerTPM2:test
#if (( $? != "0" )) ; then gradle_status=1; fi
#cp -r /HIRS/HIRS_ProvisionerTPM2/docs/ /HIRS/artifacts/upload_reports/HIRS_ProvisionerTPM2/.
./gradlew :HIRS_Structs:clean :HIRS_Structs:build :HIRS_Structs:test
if (( $? != "0" )) ; then gradle_status=1; fi
cp -r /HIRS/HIRS_Structs/build/reports/ /HIRS/artifacts/upload_reports/HIRS_Structs/.
./gradlew :HIRS_Utils:clean :HIRS_Utils:build :HIRS_Utils:test
if (( $? != "0" )) ; then gradle_status=1; fi
cp -r /HIRS/HIRS_Utils/build/reports/ /HIRS/artifacts/upload_reports/HIRS_Utils/.
#./gradlew :TPM_Utils:clean :TPM_Utils:build :TPM_Utils:test
#if (( $? != "0" )) ; then gradle_status=1; fi
# Create "fail file" to fail the Build ACA tests if gradle exited with anything other than 0
if (( $gradle_status == "0" )) ; then
echo "In docker: Build Passed"
else
echo "In docker: Build Failed"
touch /HIRS/artifacts/githubActionsResults/buildFailed.txt
fi; popd;'
# Upload build report files
- name: Archive report files
uses: actions/upload-artifact@v4
with:
name: HIRS_Build_Reports
path: artifacts/upload_reports/*
if-no-files-found: ignore
# If buildFailed file exists, use that to fail the ACA unit tests
- name: Check if build/test passed or failed
if: ${{ hashFiles('artifacts/githubActionsResults/buildFailed.txt') != '' }}
uses: actions/github-script@v6
with:
script: |
core.setFailed('Build or Unit Test Failed')

View File

@ -1,4 +1,5 @@
# workflow is used to run RIM tests
# Updated: 02/11/2025
name: RIM Test
on:
push:
@ -28,7 +29,7 @@ jobs:
sudo apt-get update
sudo apt-get install git curl nano cron mariadb-server
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
uses: gradle/actions/setup-gradle@v4
- name: Execute Gradle build
run: |
./gradlew build;
@ -37,7 +38,7 @@ jobs:
run: |
sudo dpkg -i tools/tcg_rim_tool/build/distributions/tcg-rim-tool*.deb
- name: RIM tests
run: |
run: |
./.ci/tcg-rim-tool/scripts/run_all_tests.sh --verbose

View File

@ -1,6 +1,5 @@
# This workflow will build HIRS, run system tests, and create artifacts consisting of ACA and Provisioner logs.
# Updated: 06/05/2024
#
# Updated: 02/11/2025
name: HIRS System Tests
on:
push:

View File

@ -65,8 +65,4 @@ sourceSets {
srcDir '../HIRS_Provisioner.NET/hirs/Resources'
}
}
}
test {
useJUnitPlatform()
}
}

View File

@ -108,7 +108,7 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
* the client's desired attestation key, if the correct nonce is supplied.
*
* @param certificateRequest request containing nonce from earlier identity
* * claim handshake
* claim handshake
* @return The response to the client provisioner.
*/
@Override

View File

@ -98,7 +98,7 @@ public class ComponentResult extends ArchivableEntity {
*
* @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 certificateType type of certificate. 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,
@ -116,28 +116,51 @@ public class ComponentResult extends ArchivableEntity {
}
StringBuilder sb = new StringBuilder();
for (ComponentAddress element : componentIdentifier.getComponentAddress()) {
for (ComponentAddress element : componentIdentifier.getComponentAddresses()) {
sb.append(String.format("%s:%s;", element.getAddressTypeValue(),
element.getAddressValue().toString()));
}
componentAddress = sb.toString();
}
/**
* @param boardSerialNumber associated platform certificate serial number
* @param certificateSerialNumber unique number associated with header info
* @param certificateType type of certificate. Parameter holds version 1.2 or 2.0.
* @param componentIdentifierV2 version 2 component identifier
*/
public ComponentResult(final String boardSerialNumber, final String certificateSerialNumber,
final String certificateType,
final ComponentIdentifierV2 componentIdentifierV2) {
this.boardSerialNumber = boardSerialNumber;
this.certificateSerialNumber = certificateSerialNumber;
this.certificateType = certificateType;
this.manufacturer = componentIdentifierV2.getComponentManufacturer().toString();
this.model = componentIdentifierV2.getComponentModel().toString();
this.serialNumber = componentIdentifierV2.getComponentSerial().toString();
this.revisionNumber = componentIdentifierV2.getComponentRevision().toString();
if (componentIdentifierV2.getFieldReplaceable() != null) {
this.fieldReplaceable = componentIdentifierV2.getFieldReplaceable().isTrue();
}
StringBuilder sb = new StringBuilder();
for (ComponentAddress element : componentIdentifierV2.getComponentAddresses()) {
sb.append(String.format("%s:%s;", element.getAddressTypeValue(),
element.getAddressValue().toString()));
}
componentAddress = sb.toString();
// V2 fields
if (componentIdentifier.isVersion2()
&& componentIdentifier instanceof ComponentIdentifierV2 ciV2) {
// this is a downside of findbugs, the code is set up to indicate if a CI is V2 or not
// but find bugs is throwing a flag because instanceof isn't being used.
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.componentClassValue = componentIdentifierV2.getComponentClass().getComponentIdentifier();
this.componentClassStr = componentIdentifierV2.getComponentClass().toString();
this.componentClassType = componentIdentifierV2.getComponentClass().getRegistryType();
this.attributeStatus = componentIdentifierV2.getAttributeStatus();
this.version2 = true;
if (componentIdentifierV2.getComponentPlatformCert() != null) {
this.issuerDN = componentIdentifierV2.getComponentPlatformCert().getIssuerDN().toString();
if (componentIdentifierV2.getComponentPlatformCertUri() != null) {
this.uniformResourceIdentifier = componentIdentifierV2.getComponentPlatformCertUri()
.getUniformResourceIdentifier().toString();
}
}
}

View File

@ -2,10 +2,10 @@ package hirs.attestationca.persist.entity.userdefined.certificate;
import com.google.common.base.Preconditions;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfigurationV1;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.TBBSecurityAssertion;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.PlatformConfigurationV2;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@ -64,25 +64,30 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
* TCPA Trusted Platform Endorsement.
*/
public static final String CERTIFICATE_TYPE_1_2 = "TCPA Trusted Platform Endorsement";
/**
* TCG Trusted Platform Endorsement.
*/
public static final String CERTIFICATE_TYPE_2_0 = "TCG Trusted Platform Endorsement";
private static final int TCG_SPECIFICATION_LENGTH = 3;
// These are Object Identifiers (OIDs) for sections in the credentials
private static final String POLICY_QUALIFIER_CPSURI = "1.3.6.1.5.5.7.2.1";
private static final String POLICY_QUALIFIER_USER_NOTICE = "1.3.6.1.5.5.7.2.2";
// OID for TCG Attributes
private static final String PLATFORM_MANUFACTURER = "2.23.133.2.4";
private static final String PLATFORM_MODEL = "2.23.133.2.5";
private static final String PLATFORM_VERSION = "2.23.133.2.6";
private static final String PLATFORM_SERIAL = "2.23.133.2.23";
private static final String PLATFORM_BASEBOARD_CHASSIS_COMBINED = "2.23.133.5.1.6";
// OID for TCG Platform Class Common Attributes
private static final String PLATFORM_MANUFACTURER_2_0 = "2.23.133.5.1.1";
private static final String PLATFORM_MODEL_2_0 = "2.23.133.5.1.4";
private static final String PLATFORM_VERSION_2_0 = "2.23.133.5.1.5";
private static final String PLATFORM_SERIAL_2_0 = "2.23.133.5.1.6";
// OID for Certificate Attributes
private static final String TCG_PLATFORM_SPECIFICATION = "2.23.133.2.17";
private static final String TPM_SECURITY_ASSERTION = "2.23.133.2.18";
@ -255,8 +260,8 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
/**
* Verify if the AlgorithmIdentifiers are equal.
*
* @param id1 AlgorithIdentifier one
* @param id2 AlgorithIdentifier two
* @param id1 Algorithm Identifier one
* @param id2 Algorithm Identifier two
* @return True if are the same, False if not
*/
public static boolean isAlgIdEqual(final AlgorithmIdentifier id1,
@ -349,6 +354,9 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
return verifier.verify(attCert.getSignatureValue().getOctets());
}
/**
* Parses the Platform Certificate fields.
*/
private void parseFields() throws IOException {
AttributeCertificateInfo certificate = getAttributeCertificate().getAcinfo();
Map<String, String> policyQualifier = getPolicyQualifier(certificate);
@ -403,7 +411,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
}
/**
* Parse a 1.2 Platform Certificate (Attribute Certificate).
* Parses a 1.2 Platform Certificate (Attribute Certificate).
*
* @param certificate Attribute Certificate
*/
@ -456,7 +464,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
}
/**
* Parse a 2.0 Platform Certificate (Attribute Certificate).
* Parses a 2.0 Platform Certificate (Attribute Certificate).
*
* @param certificate Attribute Certificate
*/
@ -505,7 +513,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
}
/**
* Get the x509 Platform Certificate version.
* Retrieves the x509 Platform Certificate version.
*
* @return a big integer representing the certificate version.
*/
@ -524,7 +532,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
}
/**
* Get the cPSuri from the Certificate Policies.
* Retrieves the cPSuri from the Certificate Policies.
*
* @return cPSuri from the CertificatePolicies.
* @throws IOException when reading the certificate.
@ -540,7 +548,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
}
/**
* Get the Platform Configuration Attribute from the Platform Certificate.
* Retrieves the Platform Configuration Attribute from the Platform Certificate.
*
* @return a map with all the attributes
* @throws IllegalArgumentException when there is a parsing error
@ -550,8 +558,11 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
throws IllegalArgumentException, IOException {
Map<String, Object> attributes = new HashMap<>();
ASN1Sequence attributeSequence;
ASN1Encodable[] asn1EncodableArray = getAttributeCertificate().getAcinfo().getAttributes().toArray();
// Check all attributes for Platform Configuration
for (ASN1Encodable enc : getAttributeCertificate().getAcinfo().getAttributes().toArray()) {
for (ASN1Encodable enc : asn1EncodableArray) {
Attribute attr = Attribute.getInstance(enc);
attributeSequence
= ASN1Sequence.getInstance(attr.getAttrValues().getObjectAt(0));
@ -582,8 +593,7 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
break;
default:
// No class defined for this attribute
log.warn("No class defined for attribute with OID: "
+ attr.getAttrType().getId());
log.warn("No class defined for attribute with OID: {}", attr.getAttrType().getId());
break;
}
}
@ -610,12 +620,30 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
* @throws IllegalArgumentException when there is a parsing error
* @throws IOException when reading the certificate.
*/
public PlatformConfiguration getPlatformConfiguration()
public PlatformConfigurationV1 getPlatformConfigurationV1()
throws IllegalArgumentException, IOException {
if (getAttribute("platformConfiguration") != null
&& getAttribute("platformConfiguration") instanceof PlatformConfiguration) {
return (PlatformConfiguration) getAttribute("platformConfiguration");
&& getAttribute("platformConfiguration") instanceof PlatformConfigurationV1) {
return (PlatformConfigurationV1) getAttribute("platformConfiguration");
}
return null;
}
/**
* Get the Version 2 Platform Configuration Attribute from the Platform Certificate.
*
* @return a map with the Version 2 Platform Configuration information.
* @throws IllegalArgumentException when there is a parsing error
* @throws IOException when reading the certificate.
*/
public PlatformConfigurationV2 getPlatformConfigurationV2()
throws IllegalArgumentException, IOException {
if (getAttribute("platformConfiguration") != null
&& getAttribute("platformConfiguration") instanceof PlatformConfigurationV2) {
return (PlatformConfigurationV2) getAttribute("platformConfiguration");
}
return null;
@ -684,20 +712,39 @@ public class PlatformCredential extends DeviceAssociatedCertificate {
}
/**
* Get the list of component identifiers if there are any.
* Retrieves the list of component identifiers if there are any.
*
* @return the list of component identifiers if there are any
*/
public List<ComponentIdentifier> getComponentIdentifiers() {
try {
PlatformConfiguration platformConfig = getPlatformConfiguration();
PlatformConfigurationV1 platformConfig = getPlatformConfigurationV1();
if (platformConfig != null) {
return platformConfig.getComponentIdentifier();
return platformConfig.getComponentIdentifiers();
}
} catch (IOException e) {
log.error("Unable to parse Platform Configuration from Credential or find"
log.error("Unable to parse Platform Configuration from Platform Credential or find"
+ "component identifiers");
}
return Collections.emptyList();
}
/**
* Retrieves the list of version 2 component identifiers if there are any.
*
* @return the list of version 2 component identifiers if there are any
*/
public List<ComponentIdentifierV2> getComponentIdentifiersV2() {
try {
PlatformConfigurationV2 platformConfigV2 = getPlatformConfigurationV2();
if (platformConfigV2 != null) {
return platformConfigV2.getComponentIdentifiers();
}
} catch (IOException e) {
log.error("Unable to parse Platform Configuration Version 2 from Platform Credential or find"
+ "version 2 component identifiers");
}
return Collections.emptyList();
}
}

View File

@ -8,7 +8,7 @@ import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1UTF8String;
/**
* Basic class that handle component addresses from the component identifier.
* Basic class that represents the component addresses from the component identifier object.
* <pre>
* componentAddress ::= SEQUENCE {
* addressType AddressType,

View File

@ -33,6 +33,10 @@ ComponentClass {
private static final String SMBIOS_COMPONENT_REGISTRY = "2.23.133.18.3.3";
private static final String PCIE_BASED_COMPONENT_REGISTRY = "2.23.133.18.3.4";
private static final String STORAGE_COMPONENT_REGISTRY = "2.23.133.18.3.5";
private static final Path WINDOWS_JSON_PATH = FileSystems.getDefault().getPath(
"C:/", "ProgramData", "hirs", "aca", "default-properties", "component-class.json");
@ -122,6 +126,8 @@ ComponentClass {
this.registryType = switch (registryOid) {
case TCG_COMPONENT_REGISTRY -> "TCG";
case SMBIOS_COMPONENT_REGISTRY -> "SMBIOS";
case PCIE_BASED_COMPONENT_REGISTRY -> "PCIE";
case STORAGE_COMPONENT_REGISTRY -> "STORAGE";
default -> UNKNOWN_STRING;
};

View File

@ -16,8 +16,8 @@ import java.util.List;
import java.util.stream.Collectors;
/**
* Basic class that handle component identifiers from the Platform Configuration
* Attribute.
* Basic class that represents version 1 of the component identifiers from the Version 1
* Platform Configuration Attribute.
* <pre>
* ComponentIdentifier ::= SEQUENCE {
* componentManufacturer UTF8String (SIZE (1..STRMAX)),
@ -26,7 +26,7 @@ import java.util.stream.Collectors;
* componentRevision [1] IMPLICIT UTF8String (SIZE (1..STRMAX)) OPTIONAL,
* componentManufacturerId [2] IMPLICIT PrivateEnterpriseNumber OPTIONAL,
* fieldReplaceable [3] IMPLICIT BOOLEAN OPTIONAL,
* componentAddress [4] IMPLICIT
* componentAddresses [4] IMPLICIT
* SEQUENCE(SIZE(1..CONFIGMAX)) OF ComponentAddress OPTIONAL}
* where STRMAX is 256, CONFIGMAX is 32
* </pre>
@ -80,7 +80,7 @@ public class ComponentIdentifier {
private ASN1Boolean fieldReplaceable;
private List<ComponentAddress> componentAddress;
private List<ComponentAddress> componentAddresses;
private boolean validationResult = true;
@ -94,7 +94,7 @@ public class ComponentIdentifier {
componentRevision = new DERUTF8String(NOT_SPECIFIED_COMPONENT);
componentManufacturerId = null;
fieldReplaceable = null;
componentAddress = new ArrayList<>();
componentAddresses = new ArrayList<>();
}
/**
@ -106,7 +106,7 @@ public class ComponentIdentifier {
* @param componentRevision represents the component revision
* @param componentManufacturerId represents the component manufacturer ID
* @param fieldReplaceable represents if the component is replaceable
* @param componentAddress represents a list of addresses
* @param componentAddresses represents a list of addresses
*/
public ComponentIdentifier(final DERUTF8String componentManufacturer,
final DERUTF8String componentModel,
@ -114,14 +114,14 @@ public class ComponentIdentifier {
final DERUTF8String componentRevision,
final ASN1ObjectIdentifier componentManufacturerId,
final ASN1Boolean fieldReplaceable,
final List<ComponentAddress> componentAddress) {
final List<ComponentAddress> componentAddresses) {
this.componentManufacturer = componentManufacturer;
this.componentModel = componentModel;
this.componentSerial = componentSerial;
this.componentRevision = componentRevision;
this.componentManufacturerId = componentManufacturerId;
this.fieldReplaceable = fieldReplaceable;
this.componentAddress = componentAddress.stream().toList();
this.componentAddresses = componentAddresses.stream().toList();
}
/**
@ -160,7 +160,7 @@ public class ComponentIdentifier {
break;
case COMPONENT_ADDRESS:
ASN1Sequence addressesSequence = ASN1Sequence.getInstance(taggedObj, false);
componentAddress = retrieveComponentAddress(addressesSequence);
componentAddresses = retrieveComponentAddress(addressesSequence);
break;
default:
throw new IllegalArgumentException("Component identifier contains "
@ -229,14 +229,16 @@ public class ComponentIdentifier {
if (fieldReplaceable != null) {
sb.append(fieldReplaceable);
}
sb.append(", componentAddress=");
if (!componentAddress.isEmpty()) {
sb.append(componentAddress
sb.append(", componentAddresses=");
if (!componentAddresses.isEmpty()) {
sb.append(componentAddresses
.stream()
.map(Object::toString)
.collect(Collectors.joining(",")));
}
sb.append(", certificateIdentifier=");
if (sb.charAt(sb.length() - 1) == ',') {
sb.deleteCharAt(sb.length() - 1);
}
sb.append("}");
return sb.toString();

View File

@ -1,108 +0,0 @@
package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Abstract class that provides base info for Platform Configuration of
* the Platform Certificate Attribute.
*/
@AllArgsConstructor
public abstract class PlatformConfiguration {
private ArrayList<ComponentIdentifier> componentIdentifier = new ArrayList<>();
@Getter
@Setter
private URIReference componentIdentifierUri;
private ArrayList<PlatformProperty> platformProperties = new ArrayList<>();
@Getter
@Setter
private URIReference platformPropertiesUri;
/**
* Default constructor.
*/
public PlatformConfiguration() {
this.componentIdentifier = new ArrayList<>();
this.componentIdentifierUri = null;
this.platformProperties = new ArrayList<>();
this.platformPropertiesUri = null;
}
/**
* Constructor given the Platform Configuration values.
*
* @param componentIdentifier list containing all the components inside the
* Platform Configuration.
* @param platformProperties list containing all the properties inside the
* Platform Configuration.
* @param platformPropertiesUri object containing the URI Reference
*/
public PlatformConfiguration(final List<ComponentIdentifier> componentIdentifier,
final List<PlatformProperty> platformProperties,
final URIReference platformPropertiesUri) {
this.componentIdentifier = new ArrayList<>(componentIdentifier);
this.platformProperties = new ArrayList<>(platformProperties);
this.platformPropertiesUri = platformPropertiesUri;
}
/**
* @return the componentIdentifier
*/
public List<ComponentIdentifier> getComponentIdentifier() {
return Collections.unmodifiableList(componentIdentifier);
}
/**
* @param componentIdentifier the componentIdentifier to set
*/
public void setComponentIdentifier(final List<ComponentIdentifier> componentIdentifier) {
this.componentIdentifier = new ArrayList<>(componentIdentifier);
}
/**
* Add function for the component identifier array.
*
* @param componentIdentifier object to add
* @return status of the add, if successful or not
*/
protected boolean add(final ComponentIdentifier componentIdentifier) {
if (this.componentIdentifier != null) {
return this.componentIdentifier.add(componentIdentifier);
}
return false;
}
/**
* @return the platformProperties
*/
public List<PlatformProperty> getPlatformProperties() {
return Collections.unmodifiableList(platformProperties);
}
/**
* @param platformProperties the platformProperties to set
*/
public void setPlatformProperties(final List<PlatformProperty> platformProperties) {
this.platformProperties = new ArrayList<>(platformProperties);
}
/**
* Add function for the platform property array.
*
* @param platformProperty property object to add
* @return status of the add, if successful or not
*/
protected boolean add(final PlatformProperty platformProperty) {
if (this.platformProperties != null) {
return this.platformProperties.add(platformProperty);
}
return false;
}
}

View File

@ -1,28 +1,53 @@
package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Basic class that handle Platform Configuration for the Platform Certificate
* Basic class that represents the Version 1 Platform Configuration used for the Platform Certificate
* Attribute.
* <pre>
* PlatformConfiguration ::= SEQUENCE {
* componentIdentifier [0] IMPLICIT SEQUENCE(SIZE(1..CONFIGMAX)) OF
* componentIdentifiers [0] IMPLICIT SEQUENCE(SIZE(1..CONFIGMAX)) OF
* ComponentIdentifier OPTIONAL,
* platformProperties [1] IMPLICIT SEQUENCE(SIZE(1..CONFIGMAX)) OF Properties OPTIONAL,
* platformPropertiesUri [2] IMPLICIT URIReference OPTIONAL }
* </pre>
*/
public class PlatformConfigurationV1 extends PlatformConfiguration {
@AllArgsConstructor
public class PlatformConfigurationV1 {
private static final int COMPONENT_IDENTIFIER = 0;
private static final int PLATFORM_PROPERTIES = 1;
private static final int PLATFORM_PROPERTIES_URI = 2;
private List<ComponentIdentifier> componentIdentifiers;
private List<PlatformProperty> platformProperties;
@Getter
@Setter
private URIReference platformPropertiesUri;
/**
* Default constructor.
*/
public PlatformConfigurationV1() {
componentIdentifiers = new ArrayList<>();
platformProperties = new ArrayList<>();
platformPropertiesUri = null;
}
/**
* Constructor given the SEQUENCE that contains Platform Configuration.
*
@ -32,7 +57,7 @@ public class PlatformConfigurationV1 extends PlatformConfiguration {
public PlatformConfigurationV1(final ASN1Sequence sequence) throws IllegalArgumentException {
//Default values
setComponentIdentifier(new ArrayList<>());
setComponentIdentifiers(new ArrayList<>());
setPlatformProperties(new ArrayList<>());
setPlatformPropertiesUri(null);
@ -42,7 +67,7 @@ public class PlatformConfigurationV1 extends PlatformConfiguration {
//Set information based on the set tagged
switch (taggedSequence.getTagNo()) {
case COMPONENT_IDENTIFIER:
//Get componentIdentifier
//Get componentIdentifiers
ASN1Sequence componentConfiguration
= ASN1Sequence.getInstance(taggedSequence, false);
@ -77,6 +102,62 @@ public class PlatformConfigurationV1 extends PlatformConfiguration {
}
}
/**
* @return list of version 1 component identifiers
*/
public List<ComponentIdentifier> getComponentIdentifiers() {
return Collections.unmodifiableList(componentIdentifiers);
}
/**
* @param componentIdentifiers list of version 1 component identifiers
*/
public void setComponentIdentifiers(final List<ComponentIdentifier> componentIdentifiers) {
this.componentIdentifiers = new ArrayList<>(componentIdentifiers);
}
/**
* Add function for the version 1 component identifier array.
*
* @param componentIdentifier object to add
* @return status of the add, if successful or not
*/
protected boolean add(final ComponentIdentifier componentIdentifier) {
if (this.componentIdentifiers != null) {
return this.componentIdentifiers.add(componentIdentifier);
}
return false;
}
/**
* @return the platformProperties
*/
public List<PlatformProperty> getPlatformProperties() {
return Collections.unmodifiableList(platformProperties);
}
/**
* @param platformProperties the platformProperties to set
*/
public void setPlatformProperties(final List<PlatformProperty> platformProperties) {
this.platformProperties = new ArrayList<>(platformProperties);
}
/**
* Add function for the platform property array.
*
* @param platformProperty property object to add
* @return status of the add, if successful or not
*/
protected boolean add(final PlatformProperty platformProperty) {
if (this.platformProperties != null) {
return this.platformProperties.add(platformProperty);
}
return false;
}
/**
* Creates a string representation of the Platform Configuration V1 object.
*
@ -86,15 +167,15 @@ public class PlatformConfigurationV1 extends PlatformConfiguration {
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("PlatformConfiguration{");
sb.append("componentIdentifier=");
if (getComponentIdentifier().size() > 0) {
sb.append(getComponentIdentifier()
sb.append("componentIdentifiers=");
if (!getComponentIdentifiers().isEmpty()) {
sb.append(getComponentIdentifiers()
.stream()
.map(Object::toString)
.collect(Collectors.joining(",")));
}
sb.append(", platformProperties=");
if (getPlatformProperties().size() > 0) {
if (!getPlatformProperties().isEmpty()) {
sb.append(getPlatformProperties()
.stream()
.map(Object::toString)

View File

@ -16,6 +16,7 @@ import org.apache.commons.lang3.StringUtils;
* removed (2) }
* </pre>
*/
@Getter
@AllArgsConstructor
public enum AttributeStatus {
/**
@ -35,6 +36,5 @@ public enum AttributeStatus {
*/
EMPTY_STATUS(StringUtils.EMPTY);
@Getter
private final String value;
}

View File

@ -76,6 +76,12 @@ public class CertificateIdentifier {
}
}
/**
* Helper method that parses the attribute certificate id from the provided attribute
* certificate ASN1 Sequence.
*
* @param attrCertSeq ASN1 attribute certificate sequence
*/
private void parseAttributeCertId(final ASN1Sequence attrCertSeq) {
//Check if it have a valid number of identifiers
if (attrCertSeq.size() != SEQUENCE_NUMBER) {
@ -87,6 +93,11 @@ public class CertificateIdentifier {
hashSigValue = attrCertSeq.getObjectAt(1).toString();
}
/**
* Helper method that parses the generic certificate id from the provided issuer serial ASN1 sequence.
*
* @param issuerSerialSeq ASN1 issuer serial sequence
*/
private void parseGenericCertId(final ASN1Sequence issuerSerialSeq) {
//Check if it have a valid number of identifiers
if (issuerSerialSeq.size() != SEQUENCE_NUMBER) {

View File

@ -20,17 +20,18 @@ import java.util.List;
import java.util.stream.Collectors;
/**
* Basic class that handle component identifiers from the Platform Configuration
* Attribute.
* Basic class that represents version 2 of the component identifiers from the Version 2
* Platform Configuration Attribute.
* <pre>
* ComponentIdentifier ::= SEQUENCE {
* componentClass ComponentClass
* componentManufacturer UTF8String (SIZE (1..STRMAX)),
* componentModel UTF8String (SIZE (1..STRMAX)),
* componentSerial[0] IMPLICIT UTF8String (SIZE (1..STRMAX)) OPTIONAL,
* componentRevision [1] IMPLICIT UTF8String (SIZE (1..STRMAX)) OPTIONAL,
* componentManufacturerId [2] IMPLICIT PrivateEnterpriseNumber OPTIONAL,
* fieldReplaceable [3] IMPLICIT BOOLEAN OPTIONAL,
* componentAddress [4] IMPLICIT
* componentAddresses [4] IMPLICIT
* SEQUENCE(SIZE(1..CONFIGMAX)) OF ComponentAddress OPTIONAL
* componentPlatformCert [5] IMPLICIT CertificateIdentifier OPTIONAL,
* componentPlatformCertUri [6] IMPLICIT URIReference OPTIONAL,
@ -48,15 +49,15 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
// Additional optional identifiers for version 2
private static final int COMPONENT_PLATFORM_CERT = 5;
private static final int COMPONENT_PLATFORM_URI = 6;
private static final int COMPONENT_PLATFORM_CERT_URI = 6;
private static final int ATTRIBUTE_STATUS = 7;
private ComponentClass componentClass;
private CertificateIdentifier certificateIdentifier;
private CertificateIdentifier componentPlatformCert;
private URIReference componentPlatformUri;
private URIReference componentPlatformCertUri;
private AttributeStatus attributeStatus;
@ -66,25 +67,25 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
public ComponentIdentifierV2() {
super();
componentClass = new ComponentClass();
certificateIdentifier = null;
componentPlatformUri = null;
componentPlatformCert = null;
componentPlatformCertUri = null;
attributeStatus = AttributeStatus.EMPTY_STATUS;
}
/**
* Constructor given the components values.
*
* @param componentClass represent the component type
* @param componentManufacturer represents the component manufacturer
* @param componentModel represents the component model
* @param componentSerial represents the component serial number
* @param componentRevision represents the component revision
* @param componentManufacturerId represents the component manufacturer ID
* @param fieldReplaceable represents if the component is replaceable
* @param componentAddress represents a list of addresses
* @param certificateIdentifier object representing certificate Id
* @param componentPlatformUri object containing the URI Reference
* @param attributeStatus object containing enumerated status
* @param componentClass represent the component type
* @param componentManufacturer represents the component manufacturer
* @param componentModel represents the component model
* @param componentSerial represents the component serial number
* @param componentRevision represents the component revision
* @param componentManufacturerId represents the component manufacturer ID
* @param fieldReplaceable represents if the component is replaceable
* @param componentAddress represents a list of addresses
* @param componentPlatformCert object representing certificate Id
* @param componentPlatformCertUri object containing the URI Reference
* @param attributeStatus object containing enumerated status
*/
public ComponentIdentifierV2(final ComponentClass componentClass,
final DERUTF8String componentManufacturer,
@ -94,16 +95,16 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
final ASN1ObjectIdentifier componentManufacturerId,
final ASN1Boolean fieldReplaceable,
final List<ComponentAddress> componentAddress,
final CertificateIdentifier certificateIdentifier,
final URIReference componentPlatformUri,
final CertificateIdentifier componentPlatformCert,
final URIReference componentPlatformCertUri,
final AttributeStatus attributeStatus) {
super(componentManufacturer, componentModel, componentSerial,
componentRevision, componentManufacturerId, fieldReplaceable,
componentAddress);
this.componentClass = componentClass;
// additional optional component identifiers
this.certificateIdentifier = certificateIdentifier;
this.componentPlatformUri = componentPlatformUri;
this.componentPlatformCert = componentPlatformCert;
this.componentPlatformCertUri = componentPlatformCertUri;
this.attributeStatus = attributeStatus;
}
@ -150,15 +151,15 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
break;
case COMPONENT_ADDRESS:
ASN1Sequence addressesSequence = ASN1Sequence.getInstance(taggedObj, false);
this.setComponentAddress(retrieveComponentAddress(addressesSequence));
this.setComponentAddresses(retrieveComponentAddress(addressesSequence));
break;
case COMPONENT_PLATFORM_CERT:
ASN1Sequence ciSequence = ASN1Sequence.getInstance(taggedObj, false);
certificateIdentifier = new CertificateIdentifier(ciSequence);
componentPlatformCert = new CertificateIdentifier(ciSequence);
break;
case COMPONENT_PLATFORM_URI:
case COMPONENT_PLATFORM_CERT_URI:
ASN1Sequence uriSequence = ASN1Sequence.getInstance(taggedObj, false);
this.componentPlatformUri = new URIReference(uriSequence);
this.componentPlatformCertUri = new URIReference(uriSequence);
break;
case ATTRIBUTE_STATUS:
ASN1Enumerated enumerated = ASN1Enumerated.getInstance(taggedObj, false);
@ -172,34 +173,6 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
}
}
/**
* @return true if the component has been modified.
*/
public final boolean isAdded() {
return getAttributeStatus() == AttributeStatus.ADDED;
}
/**
* @return true if the component has been modified.
*/
public final boolean isModified() {
return getAttributeStatus() == AttributeStatus.MODIFIED;
}
/**
* @return true if the component has been removed.
*/
public final boolean isRemoved() {
return getAttributeStatus() == AttributeStatus.REMOVED;
}
/**
* @return true if the component status wasn't set.
*/
public final boolean isEmpty() {
return (getAttributeStatus() == AttributeStatus.EMPTY_STATUS)
|| (getAttributeStatus() == null);
}
/**
* @return indicates the type of platform certificate.
@ -238,20 +211,20 @@ public class ComponentIdentifierV2 extends ComponentIdentifier {
if (getFieldReplaceable() != null) {
sb.append(getFieldReplaceable());
}
sb.append(", componentAddress=");
if (getComponentAddress().size() > 0) {
sb.append(getComponentAddress()
sb.append(", componentAddresses=");
if (!getComponentAddresses().isEmpty()) {
sb.append(getComponentAddresses()
.stream()
.map(Object::toString)
.collect(Collectors.joining(",")));
}
sb.append(", certificateIdentifier=");
if (certificateIdentifier != null) {
sb.append(certificateIdentifier);
sb.append(", componentPlatformCert=");
if (componentPlatformCert != null) {
sb.append(componentPlatformCert);
}
sb.append(", componentPlatformUri=");
if (componentPlatformUri != null) {
sb.append(componentPlatformUri);
sb.append(", componentPlatformCertUri=");
if (componentPlatformCertUri != null) {
sb.append(componentPlatformCertUri);
}
sb.append(", status=");
if (attributeStatus != null) {

View File

@ -1,15 +1,20 @@
package hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformProperty;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1TaggedObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Basic class that handle Platform Configuration for the Platform Certificate
* Basic class that represents the Version 2 Platform Configuration used for the Platform Certificate
* Attribute.
* <pre>
* PlatformConfiguration ::= SEQUENCE {
@ -20,23 +25,49 @@ import java.util.stream.Collectors;
* platformPropertiesUri [3] IMPLICIT URIReference OPTIONAL }
* </pre>
*/
public class PlatformConfigurationV2 extends PlatformConfiguration {
@AllArgsConstructor
public class PlatformConfigurationV2 {
private static final int COMPONENT_IDENTIFIER = 0;
private static final int COMPONENT_IDENTIFIER_URI = 1;
private static final int PLATFORM_PROPERTIES = 2;
private static final int PLATFORM_PROPERTIES_URI = 3;
private List<ComponentIdentifierV2> componentIdentifiers;
@Getter
@Setter
private URIReference componentIdentifiersUri;
private List<PlatformProperty> platformProperties;
@Getter
@Setter
private URIReference platformPropertiesUri;
/**
* Constructor given the SEQUENCE that contains Platform Configuration.
* Default constructor.
*/
public PlatformConfigurationV2() {
componentIdentifiers = new ArrayList<>();
componentIdentifiersUri = null;
platformProperties = new ArrayList<>();
platformPropertiesUri = null;
}
/**
* Constructor given the SEQUENCE that contains version 2 Platform Configuration.
*
* @param sequence containing the the Platform Configuration.
* @throws IllegalArgumentException if there was an error on the parsing
* @param sequence containing the version 2 Platform Configuration.
* @throws IllegalArgumentException if there was an error while parsing
*/
public PlatformConfigurationV2(final ASN1Sequence sequence) throws IllegalArgumentException {
//Default values
setComponentIdentifier(new ArrayList<>());
setComponentIdentifierUri(null);
setComponentIdentifiers(new ArrayList<>());
setComponentIdentifiersUri(null);
setPlatformProperties(new ArrayList<>());
setPlatformPropertiesUri(null);
@ -62,7 +93,7 @@ public class PlatformConfigurationV2 extends PlatformConfiguration {
//Get componentIdentifierURI
ASN1Sequence componentUri = ASN1Sequence.getInstance(taggedSequence, false);
//Save Component Identifier URI
setComponentIdentifierUri(new URIReference(componentUri));
setComponentIdentifiersUri(new URIReference(componentUri));
break;
case PLATFORM_PROPERTIES:
//Get platformProperties
@ -87,6 +118,64 @@ public class PlatformConfigurationV2 extends PlatformConfiguration {
}
}
/**
* @return a collection of version 2 component identifiers.
*/
public List<ComponentIdentifierV2> getComponentIdentifiers() {
return Collections.unmodifiableList(componentIdentifiers);
}
/**
* @param componentIdentifiers list of version 2 component identifiers
*/
public void setComponentIdentifiers(
final List<ComponentIdentifierV2> componentIdentifiers) {
this.componentIdentifiers = new ArrayList<>(componentIdentifiers);
}
/**
* Add function for the component identifier array.
*
* @param componentIdentifierV2 object to add
* @return status of the add, if successful or not
*/
protected boolean add(final ComponentIdentifierV2 componentIdentifierV2) {
if (this.componentIdentifiers != null) {
return this.componentIdentifiers.add(componentIdentifierV2);
}
return false;
}
/**
* @return the platformProperties
*/
public List<PlatformProperty> getPlatformProperties() {
return Collections.unmodifiableList(platformProperties);
}
/**
* @param platformProperties the platformProperties to set
*/
public void setPlatformProperties(final List<PlatformProperty> platformProperties) {
this.platformProperties = new ArrayList<>(platformProperties);
}
/**
* Add function for the platform property array.
*
* @param platformProperty property object to add
* @return status of the add, if successful or not
*/
protected boolean add(final PlatformProperty platformProperty) {
if (this.platformProperties != null) {
return this.platformProperties.add(platformProperty);
}
return false;
}
/**
* Creates a string representation of the Platform Configuration V2 object.
*
@ -95,20 +184,20 @@ public class PlatformConfigurationV2 extends PlatformConfiguration {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("PlatformConfiguration{");
sb.append("componentIdentifier=");
if (getComponentIdentifier().size() > 0) {
sb.append(getComponentIdentifier()
sb.append("PlatformConfigurationV2{");
sb.append("componentIdentifiers=");
if (!getComponentIdentifiers().isEmpty()) {
sb.append(getComponentIdentifiers()
.stream()
.map(Object::toString)
.collect(Collectors.joining(",")));
}
sb.append(", componentIdentifierUri=");
if (getComponentIdentifierUri() != null) {
sb.append(getComponentIdentifierUri());
sb.append(", componentIdentifiersUri=");
if (getComponentIdentifiersUri() != null) {
sb.append(getComponentIdentifiersUri());
}
sb.append(", platformProperties=");
if (getPlatformProperties().size() > 0) {
if (!getPlatformProperties().isEmpty()) {
sb.append(getPlatformProperties()
.stream()
.map(Object::toString)

View File

@ -55,10 +55,14 @@ public class ComponentInfo extends ArchivableEntity {
@XmlElement
@Column
private String componentClass;
private String componentClassValue;
@XmlElement
@Column
private String componentClassRegistry;
/**
* Base constructor for children.
* Constructor.
*
* @param componentManufacturer Component Manufacturer (must not be null)
* @param componentModel Component Model (must not be null)
@ -87,24 +91,34 @@ public class ComponentInfo extends ArchivableEntity {
final String componentModel,
final String componentSerial,
final String componentRevision) {
if (isComplete(
componentManufacturer,
componentModel,
componentSerial,
componentRevision)) {
log.error("ComponentInfo: manufacturer and/or "
+ "model can not be null");
throw new NullPointerException("ComponentInfo: manufacturer and/or "
+ "model can not be null");
if (deviceName == null) {
log.error("Component Info's device name cannot be null.");
this.deviceName = "";
} else {
this.deviceName = deviceName;
}
this.deviceName = deviceName;
this.componentManufacturer = componentManufacturer.trim();
this.componentModel = componentModel.trim();
if (componentManufacturer == null) {
log.error("Component Info's manufacturer cannot be null.");
this.componentManufacturer = "";
} else {
this.componentManufacturer = componentManufacturer.trim();
}
if (componentModel == null) {
log.error("Component Info's model cannot be null.");
this.componentModel = "";
} else {
this.componentModel = componentModel.trim();
}
if (componentSerial != null) {
this.componentSerial = componentSerial.trim();
} else {
this.componentSerial = ComponentIdentifier.NOT_SPECIFIED_COMPONENT;
}
if (componentRevision != null) {
this.componentRevision = componentRevision.trim();
} else {
@ -115,44 +129,28 @@ public class ComponentInfo extends ArchivableEntity {
/**
* Constructor.
*
* @param deviceName the host machine associated with this component.
* @param componentManufacturer Component Manufacturer (must not be null)
* @param componentModel Component Model (must not be null)
* @param componentSerial Component Serial Number (can be null)
* @param componentRevision Component Revision or Version (can be null)
* @param componentClass Component Class (can be null)
* @param deviceName the host machine associated with this component.
* @param componentManufacturer Component Manufacturer (must not be null)
* @param componentModel Component Model (must not be null)
* @param componentSerial Component Serial Number (can be null)
* @param componentRevision Component Revision or Version (can be null)
* @param componentClassValue Component Class Value (can be null)
* @param componentClassRegistry Component Class Registry (can be null)
*/
public ComponentInfo(final String deviceName,
final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision,
final String componentClass) {
final String componentClassValue,
final String componentClassRegistry) {
this(deviceName, componentManufacturer, componentModel,
componentSerial, componentRevision);
this.componentClass = Objects.requireNonNullElse(componentClass, StringUtils.EMPTY);
this.componentClassValue = Objects.requireNonNullElse(componentClassValue, StringUtils.EMPTY);
this.componentClassRegistry = Objects.requireNonNullElse(componentClassRegistry, StringUtils.EMPTY);
}
/**
* Determines whether the given properties represent a
* ComponentInfo that will be useful in validation.
* Currently, only components which have a non-null
* manufacturer and model are considered valid.
*
* @param componentManufacturer a String containing a component's manufacturer
* @param componentModel a String representing a component's model
* @param componentSerial a String representing a component's serial number
* @param componentRevision a String representing a component's revision
* @return true if the component is valid, false if not
*/
public static boolean isComplete(final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision) {
return (StringUtils.isEmpty(componentManufacturer)
|| StringUtils.isEmpty(componentModel));
}
/**
* Returns a hash code that is associated with common fields for components.
@ -161,6 +159,6 @@ public class ComponentInfo extends ArchivableEntity {
*/
public int hashCommonElements() {
return Objects.hash(componentManufacturer, componentModel,
componentSerial, componentRevision, componentClass);
componentSerial, componentRevision, componentClassValue, componentClassRegistry);
}
}

View File

@ -19,11 +19,11 @@ import java.io.Serializable;
public class FirmwareInfo implements Serializable {
@XmlElement
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = false)
@Column(nullable = false)
private final String biosVendor;
@XmlElement
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = false)
@Column(nullable = false)
private final String biosVersion;
@XmlElement

View File

@ -22,11 +22,11 @@ import java.io.Serializable;
public class HardwareInfo implements Serializable {
@XmlElement
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = false)
@Column(nullable = false)
private String manufacturer = DeviceInfoEnums.NOT_SPECIFIED;
@XmlElement
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = false)
@Column(nullable = false)
private String productName = DeviceInfoEnums.NOT_SPECIFIED;
@XmlElement
@ -34,15 +34,15 @@ public class HardwareInfo implements Serializable {
private String version = DeviceInfoEnums.NOT_SPECIFIED;
@XmlElement
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = false)
@Column(nullable = false)
private String systemSerialNumber = DeviceInfoEnums.NOT_SPECIFIED;
@XmlElement
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = false)
@Column(nullable = false)
private String chassisSerialNumber = DeviceInfoEnums.NOT_SPECIFIED;
@XmlElement
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = false)
@Column(nullable = false)
private String baseboardSerialNumber = DeviceInfoEnums.NOT_SPECIFIED;
/**

View File

@ -23,7 +23,7 @@ public class NetworkInfo implements Serializable {
@XmlElement
@Getter
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH)
@Column
private String hostname;
@XmlElement

View File

@ -21,11 +21,11 @@ import java.io.Serializable;
public class OSInfo implements Serializable {
@XmlElement
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = false)
@Column(nullable = false)
private final String osName;
@XmlElement
@Column(length = DeviceInfoEnums.LONG_STRING_LENGTH, nullable = false)
@Column(nullable = false)
private final String osVersion;
@XmlElement
@ -33,11 +33,11 @@ public class OSInfo implements Serializable {
private final String osArch;
@XmlElement
@Column(length = DeviceInfoEnums.SHORT_STRING_LENGTH, nullable = true)
@Column(length = DeviceInfoEnums.SHORT_STRING_LENGTH)
private final String distribution;
@XmlElement
@Column(length = DeviceInfoEnums.SHORT_STRING_LENGTH, nullable = true)
@Column(length = DeviceInfoEnums.SHORT_STRING_LENGTH)
private final String distributionRelease;
/**

View File

@ -30,23 +30,23 @@ public class TPMInfo implements Serializable {
private static final int MAX_BLOB_SIZE = 65535;
@XmlElement
@Column(length = DeviceInfoEnums.MED_STRING_LENGTH, nullable = true)
@Column(length = DeviceInfoEnums.MED_STRING_LENGTH)
private String tpmMake;
@XmlElement
@Column(nullable = true)
@Column
private short tpmVersionMajor;
@XmlElement
@Column(nullable = true)
@Column
private short tpmVersionMinor;
@XmlElement
@Column(nullable = true)
@Column
private short tpmVersionRevMajor;
@XmlElement
@Column(nullable = true)
@Column
private short tpmVersionRevMinor;
/**
@ -60,13 +60,13 @@ public class TPMInfo implements Serializable {
@JsonIgnore
private X509Certificate identityCertificate;
@Column(nullable = true, columnDefinition = "blob")
@Column(columnDefinition = "blob")
private byte[] pcrValues;
@Column(nullable = true, columnDefinition = "blob")
@Column(columnDefinition = "blob")
private byte[] tpmQuoteHash;
@Column(nullable = true, columnDefinition = "blob")
@Column(columnDefinition = "blob")
private byte[] tpmQuoteSignature;
/**

View File

@ -1,30 +0,0 @@
package hirs.attestationca.persist.entity.userdefined.info.component;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.utils.enums.ComponentType;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import lombok.NoArgsConstructor;
/**
* Class to hold BIOS/UEFI Component information.
*/
@NoArgsConstructor
@Entity
@DiscriminatorValue(value = ComponentType.Values.BIOS_UEFI)
public class BIOSComponentInfo extends ComponentInfo {
/**
* Constructor.
*
* @param componentManufacturer Component Manufacturer (must not be null)
* @param componentModel Component Model (must not be null)
* @param componentRevision Component Revision or Version (can be null)
*/
public BIOSComponentInfo(final String componentManufacturer,
final String componentModel,
final String componentRevision) {
super(componentManufacturer, componentModel, null,
componentRevision);
}
}

View File

@ -1,32 +0,0 @@
package hirs.attestationca.persist.entity.userdefined.info.component;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.utils.enums.ComponentType;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import lombok.NoArgsConstructor;
/**
* Class to hold information about baseboard components.
*/
@NoArgsConstructor
@Entity
@DiscriminatorValue(value = ComponentType.Values.BASEBOARD)
public class BaseboardComponentInfo extends ComponentInfo {
/**
* Constructor.
*
* @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 BaseboardComponentInfo(final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision) {
super(componentManufacturer, componentModel, componentSerial,
componentRevision);
}
}

View File

@ -1,32 +0,0 @@
package hirs.attestationca.persist.entity.userdefined.info.component;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.utils.enums.ComponentType;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import lombok.NoArgsConstructor;
/**
* Class to hold chassis component information.
*/
@NoArgsConstructor
@Entity
@DiscriminatorValue(value = ComponentType.Values.CHASSIS)
public class ChassisComponentInfo extends ComponentInfo {
/**
* Constructor.
*
* @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 ChassisComponentInfo(final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision) {
super(componentManufacturer, componentModel,
componentSerial, componentRevision);
}
}

View File

@ -1,32 +0,0 @@
package hirs.attestationca.persist.entity.userdefined.info.component;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.utils.enums.ComponentType;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import lombok.NoArgsConstructor;
/**
* Class to hold hard drive component information.
*/
@NoArgsConstructor
@Entity
@DiscriminatorValue(value = ComponentType.Values.HARD_DRIVE)
public class HardDriveComponentInfo extends ComponentInfo {
/**
* Constructor.
*
* @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 HardDriveComponentInfo(final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision) {
super(componentManufacturer, componentModel,
componentSerial, componentRevision);
}
}

View File

@ -1,32 +0,0 @@
package hirs.attestationca.persist.entity.userdefined.info.component;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.utils.enums.ComponentType;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import lombok.NoArgsConstructor;
/**
* Class to hold memory component information.
*/
@NoArgsConstructor
@Entity
@DiscriminatorValue(value = ComponentType.Values.MEMORY)
public class MemoryComponentInfo extends ComponentInfo {
/**
* Constructor.
*
* @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 MemoryComponentInfo(final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision) {
super(componentManufacturer, componentModel,
componentSerial, componentRevision);
}
}

View File

@ -1,32 +0,0 @@
package hirs.attestationca.persist.entity.userdefined.info.component;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.utils.enums.ComponentType;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import lombok.NoArgsConstructor;
/**
* Class to hold Network Interface Card (NIC) component information.
*/
@NoArgsConstructor
@Entity
@DiscriminatorValue(value = ComponentType.Values.NIC)
public class NICComponentInfo extends ComponentInfo {
/**
* Constructor.
*
* @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 NICComponentInfo(final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision) {
super(componentManufacturer, componentModel,
componentSerial, componentRevision);
}
}

View File

@ -1,32 +0,0 @@
package hirs.attestationca.persist.entity.userdefined.info.component;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.utils.enums.ComponentType;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import lombok.NoArgsConstructor;
/**
* Class to hold processor component information.
*/
@NoArgsConstructor
@Entity
@DiscriminatorValue(value = ComponentType.Values.PROCESSOR)
public class ProcessorComponentInfo extends ComponentInfo {
/**
* Constructor.
*
* @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 ProcessorComponentInfo(final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision) {
super(componentManufacturer, componentModel,
componentSerial, componentRevision);
}
}

View File

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

View File

@ -159,6 +159,7 @@ public class AbstractProcessor {
final ProvisionerTpm2.IdentityClaim identityClaim,
final PublicKey ekPub, final CertificateRepository certificateRepository) {
EndorsementCredential endorsementCredential = null;
if (identityClaim.hasEndorsementCredential()) {
endorsementCredential = CredentialManagementHelper.storeEndorsementCredential(
certificateRepository,
@ -172,6 +173,7 @@ public class AbstractProcessor {
log.warn("No endorsement credential was received in identity claim and no EK Public"
+ " Key was provided to check for uploaded certificates.");
}
return endorsementCredential;
}
@ -191,12 +193,21 @@ public class AbstractProcessor {
final EndorsementCredential endorsementCredential,
final CertificateRepository certificateRepository) {
List<PlatformCredential> platformCredentials = new LinkedList<>();
if (identityClaim.getPlatformCredentialCount() > 0) {
for (ByteString platformCredential : identityClaim.getPlatformCredentialList()) {
List<ByteString> platformCredentialList = identityClaim.getPlatformCredentialList();
for (ByteString platformCredential : platformCredentialList) {
if (!platformCredential.isEmpty()) {
platformCredentials.add(CredentialManagementHelper.storePlatformCredential(
certificateRepository, platformCredential.toByteArray(),
identityClaim.getDv().getNw().getHostname()));
PlatformCredential storedPlatformCredential =
CredentialManagementHelper.storePlatformCredential(
certificateRepository, platformCredential.toByteArray(),
identityClaim.getDv().getNw().getHostname());
if (storedPlatformCredential != null) {
platformCredentials.add(storedPlatformCredential);
}
}
}
} else if (endorsementCredential != null) {
@ -206,6 +217,7 @@ public class AbstractProcessor {
} else {
log.warn("No platform credential received in identity claim.");
}
return platformCredentials;
}
@ -219,7 +231,7 @@ public class AbstractProcessor {
private EndorsementCredential getEndorsementCredential(
final PublicKey ekPublicKey,
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);
if (ekPublicKey == null) {
throw new IllegalArgumentException("Cannot look up an EC given a null public key");
@ -254,10 +266,8 @@ public class AbstractProcessor {
* @param endorsementCredential the endorsement credential used to generate the AC
* @param platformCredentials the platform credentials used to generate the AC
* @param device the device to which the attestation certificate is tied
* @param ldevID whether the certificate is a ldevid
* @param ldevID whether the certificate is a ldevid
* @return whether the certificate was saved successfully
* @throws {@link CertificateProcessingException} if error occurs in persisting the Attestation
* Certificate
*/
public boolean saveAttestationCertificate(final CertificateRepository certificateRepository,
final byte[] derEncodedAttestationCertificate,
@ -286,7 +296,7 @@ public class AbstractProcessor {
generateCertificate = ldevID ? policySettings.isIssueDevIdCertificate()
: policySettings.isIssueAttestationCertificate();
if (issuedAc != null && issuedAc.size() > 0
if (issuedAc != null && !issuedAc.isEmpty()
&& (ldevID ? policySettings.isDevIdExpirationFlag()
: policySettings.isGenerateOnExpiration())) {
if (issuedAc.get(0).getEndValidity().after(currentDate)) {
@ -322,13 +332,13 @@ public class AbstractProcessor {
if (ec == null) {
log.warn("Cannot look for platform credential(s). Endorsement credential was null.");
} else {
log.debug("Searching for platform credential(s) based on holder serial number: "
+ ec.getSerialNumber());
log.debug("Searching for platform credential(s) based on holder serial number: {}",
ec.getSerialNumber());
credentials = certificateRepository.getByHolderSerialNumber(ec.getSerialNumber());
if (credentials == null || credentials.isEmpty()) {
log.warn("No platform credential(s) found");
} else {
log.debug("Platform Credential(s) found: " + credentials.size());
log.debug("Platform Credential(s) found: {}", credentials.size());
}
}

View File

@ -20,6 +20,7 @@ import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
@ -156,6 +157,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
}
ByteString blobStr = ByteString.copyFrom(new byte[] {});
if (validationResult == AppraisalStatus.Status.PASS) {
RSAPublicKey akPub = ProvisionUtils.parsePublicKey(claim.getAkPublicArea().toByteArray());
byte[] nonce = ProvisionUtils.generateRandomBytes(NONCE_LENGTH);
@ -173,12 +175,14 @@ public class IdentityClaimProcessor extends AbstractProcessor {
if (policySettings != null && policySettings.isIgnoreImaEnabled()) {
pcrQuoteMask = PCR_QUOTE_MASK.replace("10,", "");
}
// Package response
ProvisionerTpm2.IdentityClaimResponse response
= ProvisionerTpm2.IdentityClaimResponse.newBuilder()
.setCredentialBlob(blobStr).setPcrMask(pcrQuoteMask)
.setStatus(ProvisionerTpm2.ResponseStatus.PASS)
.build();
return response.toByteArray();
} else {
log.error("Supply chain validation did not succeed. Result is: {}", validationResult);
@ -200,7 +204,8 @@ public class IdentityClaimProcessor extends AbstractProcessor {
* @return the {@link AppraisalStatus} of the supply chain validation
*/
private AppraisalStatus.Status doSupplyChainValidation(
final ProvisionerTpm2.IdentityClaim claim, final PublicKey ekPub) {
final ProvisionerTpm2.IdentityClaim claim, final PublicKey ekPub) throws IOException {
// attempt to find an endorsement credential to validate
EndorsementCredential endorsementCredential =
parseEcFromIdentityClaim(claim, ekPub, certificateRepository);
@ -215,6 +220,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
// device.getDeviceInfo().setPaccorOutputString(claim.getPaccorOutput());
handleDeviceComponents(device.getDeviceInfo().getNetworkInfo().getHostname(),
claim.getPaccorOutput());
// There are situations in which the claim is sent with no PCs
// or a PC from the tpm which will be deprecated
// this is to check what is in the platform object and pull
@ -230,16 +236,18 @@ public class IdentityClaimProcessor extends AbstractProcessor {
platformCredentials.addAll(tempList);
}
// store component results objects
for (PlatformCredential platformCredential : platformCredentials) {
List<ComponentResult> componentResults = componentResultRepository
.findByCertificateSerialNumberAndBoardSerialNumber(
platformCredential.getSerialNumber().toString(),
platformCredential.getPlatformSerial());
if (componentResults.isEmpty()) {
savePlatformComponents(platformCredential);
} else {
componentResults.stream().forEach((componentResult) -> {
componentResults.forEach((componentResult) -> {
componentResult.restore();
componentResult.resetCreateTime();
componentResultRepository.save(componentResult);
@ -252,13 +260,21 @@ public class IdentityClaimProcessor extends AbstractProcessor {
endorsementCredential, platformCredentials, device,
componentInfoRepository.findByDeviceName(device.getName()));
device.setSummaryId(summary.getId().toString());
// update the validation result in the device
AppraisalStatus.Status validationResult = summary.getOverallValidationResult();
device.setSupplyChainValidationStatus(validationResult);
this.deviceRepository.save(device);
return validationResult;
}
/**
* Helper method that utilizes the identity claim to produce a device info report.
*
* @param claim identity claim
* @return device info
*/
private Device processDeviceInfo(final ProvisionerTpm2.IdentityClaim claim) {
DeviceInfoReport deviceInfoReport = null;
@ -275,13 +291,16 @@ public class IdentityClaimProcessor extends AbstractProcessor {
}
log.info("Processing Device Info Report");
// store device and device info report.
Device device = null;
if (deviceInfoReport.getNetworkInfo() != null
&& deviceInfoReport.getNetworkInfo().getHostname() != null
&& !deviceInfoReport.getNetworkInfo().getHostname().isEmpty()) {
device = this.deviceRepository.findByName(deviceInfoReport.getNetworkInfo().getHostname());
}
if (device == null) {
device = new Device(deviceInfoReport);
}
@ -320,6 +339,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
macAddressBytes[i] = hex.byteValue();
}
}
NetworkInfo nw = new NetworkInfo(nwProto.getHostname(), ip, macAddressBytes);
// Get firmware info
@ -334,16 +354,19 @@ public class IdentityClaimProcessor extends AbstractProcessor {
// Get hardware info
ProvisionerTpm2.HardwareInfo hwProto = dv.getHw();
// Make sure chassis info has at least one chassis
String firstChassisSerialNumber = DeviceInfoEnums.NOT_SPECIFIED;
if (hwProto.getChassisInfoCount() > 0) {
firstChassisSerialNumber = hwProto.getChassisInfo(0).getSerialNumber();
}
// Make sure baseboard info has at least one baseboard
String firstBaseboardSerialNumber = DeviceInfoEnums.NOT_SPECIFIED;
if (hwProto.getBaseboardInfoCount() > 0) {
firstBaseboardSerialNumber = hwProto.getBaseboardInfo(0).getSerialNumber();
}
HardwareInfo hw = new HardwareInfo(hwProto.getManufacturer(), hwProto.getProductName(),
hwProto.getProductVersion(), hwProto.getSystemSerialNumber(),
firstChassisSerialNumber, firstBaseboardSerialNumber);
@ -609,6 +632,14 @@ public class IdentityClaimProcessor extends AbstractProcessor {
return dvReport;
}
/**
* Helper method that generates digest records using the provided device's manufacturer and model
* information.
*
* @param manufacturer device manufacturer
* @param model device model
* @return boolean that represents that status of the digest records generation
*/
private boolean generateDigestRecords(final String manufacturer, final String model) {
List<ReferenceDigestValue> rdValues = new LinkedList<>();
SupportReferenceManifest baseSupportRim = null;
@ -620,7 +651,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
.findByManufacturerAndModel(manufacturer, model);
Map<String, ReferenceDigestValue> digestValueMap = new HashMap<>();
expectedValues.stream().forEach((rdv) -> {
expectedValues.forEach((rdv) -> {
digestValueMap.put(rdv.getDigestValue(), rdv);
});
@ -709,35 +740,60 @@ public class IdentityClaimProcessor extends AbstractProcessor {
return true;
}
private void savePlatformComponents(final Certificate certificate) {
/**
* Helper method that saves the provided platform certificate's components in the database.
*
* @param certificate certificate
*/
private void savePlatformComponents(final Certificate certificate) throws IOException {
PlatformCredential platformCredential;
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);
componentResult.setDelta(!platformCredential.isPlatformBase());
componentResultRepository.save(componentResult);
if (platformCredential.getPlatformConfigurationV1() != null) {
for (ComponentIdentifier componentIdentifier : platformCredential
.getComponentIdentifiers()) {
componentResult = new ComponentResult(platformCredential.getPlatformSerial(),
platformCredential.getSerialNumber().toString(),
platformCredential.getPlatformChainType(),
componentIdentifier);
componentResult.setFailedValidation(false);
componentResult.setDelta(!platformCredential.isPlatformBase());
componentResultRepository.save(componentResult);
}
} else if (platformCredential.getPlatformConfigurationV2() != null) {
for (ComponentIdentifierV2 componentIdentifierV2 : platformCredential
.getComponentIdentifiersV2()) {
componentResult = new ComponentResult(platformCredential.getPlatformSerial(),
platformCredential.getSerialNumber().toString(),
platformCredential.getPlatformChainType(),
componentIdentifierV2);
componentResult.setFailedValidation(false);
componentResult.setDelta(!platformCredential.isPlatformBase());
componentResultRepository.save(componentResult);
}
}
}
}
private int handleDeviceComponents(final String hostName, final String paccorString) {
int deviceComponents = 0;
/**
* Helper method that attempts to find all the provided device's components.
*
* @param hostName device's host name
* @param paccorString string representation of the paccor tool output
*/
private void handleDeviceComponents(final String hostName, final String paccorString) {
Map<Integer, ComponentInfo> componentInfoMap = new HashMap<>();
try {
List<ComponentInfo> componentInfos = SupplyChainCredentialValidator
.getComponentInfoFromPaccorOutput(hostName, paccorString);
// check the DB for like component infos
List<ComponentInfo> dbComponentInfos = this.componentInfoRepository.findByDeviceName(hostName);
dbComponentInfos.stream().forEach((infos) -> {
dbComponentInfos.forEach((infos) -> {
componentInfoMap.put(infos.hashCode(), infos);
});
@ -753,7 +809,5 @@ public class IdentityClaimProcessor extends AbstractProcessor {
} catch (IOException ioEx) {
log.warn("Error parsing paccor string");
}
return deviceComponents;
}
}

View File

@ -16,7 +16,6 @@ import java.util.List;
public final class CredentialManagementHelper {
private CredentialManagementHelper() {
}
/**
@ -48,7 +47,7 @@ public final class CredentialManagementHelper {
);
}
log.info("Parsing Endorsement Credential of length " + endorsementBytes.length);
log.info("Parsing Endorsement Credential of length {}", endorsementBytes.length);
EndorsementCredential endorsementCredential;
try {
@ -58,16 +57,18 @@ public final class CredentialManagementHelper {
log.error(iae.getMessage());
throw iae;
}
int certificateHash = endorsementCredential.getCertificateHash();
EndorsementCredential existingCredential = (EndorsementCredential) certificateRepository
.findByCertificateHash(certificateHash);
if (existingCredential == null) {
log.info("No Endorsement Credential found with hash: " + certificateHash);
log.info("No Endorsement Credential found with hash: {}", certificateHash);
endorsementCredential.setDeviceName(deviceName);
return certificateRepository.save(endorsementCredential);
} else if (existingCredential.isArchived()) {
// if the EK is stored in the DB and it's archived, unarchive.
log.info("Unarchiving credential");
// if the EK is stored in the DB and it's archived, un-archive it.
log.info("Un-archiving endorsement credential");
existingCredential.restore();
existingCredential.resetCreateTime();
certificateRepository.save(existingCredential);
@ -89,28 +90,37 @@ public final class CredentialManagementHelper {
final byte[] platformBytes, final String deviceName) {
if (certificateRepository == null) {
log.error("The provided certificate repository is null.");
throw new IllegalArgumentException("null certificate manager");
}
if (platformBytes == null) {
log.error("The provided platform credential byte array is null.");
throw new IllegalArgumentException("null platform credential bytes");
}
if (platformBytes.length == 0) {
log.error("The provided platform credential byte array is null.");
throw new IllegalArgumentException(
"zero-length byte array given for platform credential"
);
}
log.info("Parsing Platform Credential of length " + platformBytes.length);
log.info("Parsing Platform Credential of length {}", platformBytes.length);
try {
PlatformCredential platformCredential =
PlatformCredential.parseWithPossibleHeader(platformBytes);
if (platformCredential == null) {
log.error("The platform credential that was parsed with the provided"
+ "byte array was null");
return null;
}
PlatformCredential existingCredential = (PlatformCredential) certificateRepository
.findByCertificateHash(platformCredential.getCertificateHash());
if (existingCredential == null) {
if (platformCredential.getPlatformSerial() != null) {
List<PlatformCredential> certificates = certificateRepository
@ -121,10 +131,10 @@ public final class CredentialManagementHelper {
if (pc.isPlatformBase() && platformCredential.isPlatformBase()) {
// found a base in the database associated with
// parsed certificate
log.error(String.format("Base certificate stored"
log.error("Base certificate stored"
+ " in database with same platform"
+ "serial number. (%s)",
platformCredential.getPlatformSerial()));
+ "serial number. ({})",
platformCredential.getPlatformSerial());
return null;
}
}
@ -133,8 +143,8 @@ public final class CredentialManagementHelper {
platformCredential.setDeviceName(deviceName);
return certificateRepository.save(platformCredential);
} else if (existingCredential.isArchived()) {
// if the PC is stored in the DB and it's archived, unarchive.
log.info("Unarchiving credential");
// if the PC is stored in the DB and it's archived, un-archive it.
log.info("Un-archiving platform credential");
existingCredential.restore();
certificateRepository.save(existingCredential);
return existingCredential;
@ -142,10 +152,14 @@ public final class CredentialManagementHelper {
return existingCredential;
} catch (DBManagerException dbEx) {
log.error("Error retrieving or saving platform credential", dbEx);
log.error("Error retrieving or saving platform credential to the database", dbEx);
} catch (Exception e) {
log.error("Error parsing platform credential", e);
}
log.error("Due to an exception being thrown while "
+ " attempting to store platform certificate(s) "
+ "this method will return a null platform certificate.");
return null;
}
}

View File

@ -32,6 +32,7 @@ import org.apache.logging.log4j.Level;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.HashMap;
@ -108,7 +109,8 @@ public class SupplyChainValidationService {
public SupplyChainValidationSummary validateSupplyChain(final EndorsementCredential ec,
final List<PlatformCredential> pcs,
final Device device,
final List<ComponentInfo> componentInfos) {
final List<ComponentInfo> componentInfos)
throws IOException {
boolean acceptExpiredCerts = getPolicySettings().isExpiredCertificateValidationEnabled();
provisionSessionId = UUID.randomUUID();
PlatformCredential baseCredential = null;
@ -153,6 +155,7 @@ public class SupplyChainValidationService {
pcErrorMessage = String.format("%s%s%n", pcErrorMessage,
platformScv.getMessage());
}
// set the base credential
if (pc.isPlatformBase()) {
baseCredential = pc;
@ -407,9 +410,9 @@ public class SupplyChainValidationService {
}
/**
* Helper function to get a fresh load of the default policy from the DB.
* Helper function that retrieves the default policy settings from the database.
*
* @return The default Supply Chain Policy
* @return The default Supply Chain Policy Settings
*/
private PolicySettings getPolicySettings() {
PolicySettings defaultSettings = this.policyRepository.findByName("Default");

View File

@ -98,9 +98,10 @@ public final class ValidationService {
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL;
if (platformCredential == null) {
log.error("No platform credential to validate");
log.error("No platform credential to validate while evaluating platform credential status");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Empty Platform credential", null, Level.ERROR);
AppraisalStatus.Status.FAIL, "Empty Platform credential", null,
Level.ERROR);
}
log.info("Validating Platform Credential");
@ -139,12 +140,13 @@ public final class ValidationService {
final ComponentResultRepository componentResultRepository,
final ComponentAttributeRepository componentAttributeRepository,
final List<ComponentInfo> componentInfos,
final UUID provisionSessionId, final boolean ignoreRevisionAttribute) {
final UUID provisionSessionId, final boolean ignoreRevisionAttribute) throws IOException {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
if (platformCredential == null) {
log.error("No platform credential to validate");
log.error("No platform credential to validate while evaluating platform credential attributes "
+ "status");
return buildValidationRecord(validationType,
AppraisalStatus.Status.FAIL, "Platform credential is missing",
null, Level.ERROR);

View File

@ -110,9 +110,9 @@ public final class AcaPciIds {
component.getComponentRevision(),
component.getComponentManufacturerId(),
component.getFieldReplaceable(),
component.getComponentAddress(),
component.getCertificateIdentifier(),
component.getComponentPlatformUri(),
component.getComponentAddresses(),
component.getComponentPlatformCert(),
component.getComponentPlatformCertUri(),
component.getAttributeStatus());
}

View File

@ -58,9 +58,15 @@ public final class CredentialHelper {
public static byte[] stripPemHeaderFooter(final String pemFile) {
String strippedFile;
strippedFile = pemFile.replace(CertificateVariables.PEM_HEADER, "");
strippedFile = strippedFile.replace(CertificateVariables.PEM_FOOTER, "");
int keyFooterPos = strippedFile.indexOf(CertificateVariables.PEM_FOOTER);
if (keyFooterPos >= 0) {
strippedFile = strippedFile.substring(0, keyFooterPos);
}
strippedFile = strippedFile.replace(CertificateVariables.PEM_ATTRIBUTE_HEADER, "");
strippedFile = strippedFile.replace(CertificateVariables.PEM_ATTRIBUTE_FOOTER, "");
int attrFooterPos = strippedFile.indexOf(CertificateVariables.PEM_ATTRIBUTE_FOOTER);
if (attrFooterPos >= 0) {
strippedFile = strippedFile.substring(0, attrFooterPos);
}
return Base64.decode(strippedFile);
}

View File

@ -6,6 +6,7 @@ import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentAttributeResult;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentClass;
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;
@ -23,6 +24,7 @@ import org.apache.logging.log4j.util.Strings;
import org.bouncycastle.asn1.ASN1UTF8String;
import org.bouncycastle.asn1.DERUTF8String;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@ -80,8 +82,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
deviceBaseboardSerialNumber = null;
} else {
deviceInfoSerialNumbers.put("board serial number", deviceBaseboardSerialNumber);
log.info("Using device board serial number for validation: "
+ deviceBaseboardSerialNumber);
log.info("Using device board serial number for validation: {}", deviceBaseboardSerialNumber);
}
if (StringUtils.isEmpty(deviceChassisSerialNumber)
@ -89,16 +90,15 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
log.error("Failed to retrieve device chassis serial number");
} else {
deviceInfoSerialNumbers.put("chassis serial number", deviceChassisSerialNumber);
log.info("Using device chassis serial number for validation: "
+ deviceChassisSerialNumber);
log.info("Using device chassis serial number for validation: {}", deviceChassisSerialNumber);
}
if (StringUtils.isEmpty(deviceSystemSerialNumber)
|| DeviceInfoEnums.NOT_SPECIFIED.equalsIgnoreCase(deviceSystemSerialNumber)) {
log.error("Failed to retrieve device system serial number");
} else {
deviceInfoSerialNumbers.put("system serial number", deviceSystemSerialNumber);
log.info("Using device system serial number for validation: "
+ deviceSystemSerialNumber);
log.info("Using device system serial number for validation: {}", deviceSystemSerialNumber);
}
AppraisalStatus status;
@ -169,7 +169,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
final ComponentResultRepository componentResultRepository,
final ComponentAttributeRepository componentAttributeRepository,
final List<ComponentInfo> componentInfos,
final UUID provisionSessionId, final boolean ignoreRevisionAttribute) {
final UUID provisionSessionId, final boolean ignoreRevisionAttribute) throws IOException {
boolean passesValidation = true;
StringBuilder resultMessage = new StringBuilder();
HardwareInfo hardwareInfo = deviceInfoReport.getHardwareInfo();
@ -233,29 +233,132 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
passesValidation &= fieldValidation;
// Retrieve the list of all components from the Platform Credential
List<ComponentIdentifier> allPcComponents
= new ArrayList<>(platformCredential.getComponentIdentifiers());
if (platformCredential.getPlatformConfigurationV1() != null) {
// All components listed in the Platform Credential must have a manufacturer and model
for (ComponentIdentifier pcComponent : allPcComponents) {
fieldValidation = !hasEmptyValueForRequiredField("componentManufacturer",
pcComponent.getComponentManufacturer());
// Retrieve the list of all version 1 component identifiers from the Platform Credential
List<ComponentIdentifier> allPcComponents
= new ArrayList<>(platformCredential.getComponentIdentifiers());
if (!fieldValidation) {
resultMessage.append("Component manufacturer is empty\n");
// All V1 components listed in the Platform Credential must have a manufacturer and model
for (ComponentIdentifier pcComponent : allPcComponents) {
fieldValidation = !isRequiredASN1StringFieldBlank("componentManufacturer",
pcComponent.getComponentManufacturer());
if (!fieldValidation) {
resultMessage.append("Component manufacturer is empty\n");
}
passesValidation &= fieldValidation;
fieldValidation = !isRequiredASN1StringFieldBlank("componentModel",
pcComponent.getComponentModel());
if (!fieldValidation) {
resultMessage.append("Component model is empty\n");
}
passesValidation &= fieldValidation;
}
passesValidation &= fieldValidation;
} else if (platformCredential.getPlatformConfigurationV2() != null) {
// Retrieve the list of all version 2 component identifiers from the Platform Credential
List<ComponentIdentifierV2> allV2PcComponents
= new ArrayList<>(platformCredential.getComponentIdentifiersV2());
fieldValidation = !hasEmptyValueForRequiredField("componentModel",
pcComponent.getComponentModel());
if (!fieldValidation) {
resultMessage.append("Component model is empty\n");
// All V2 components listed in the Platform Credential must have a manufacturer and model
for (ComponentIdentifierV2 pcComponent : allV2PcComponents) {
fieldValidation = !isRequiredASN1StringFieldBlank("componentManufacturer",
pcComponent.getComponentManufacturer());
if (!fieldValidation) {
resultMessage.append("Component manufacturer is empty\n");
}
passesValidation &= fieldValidation;
fieldValidation = !isRequiredASN1StringFieldBlank("componentModel",
pcComponent.getComponentModel());
if (!fieldValidation) {
resultMessage.append("Component model is empty\n");
}
passesValidation &= fieldValidation;
if (pcComponent.getComponentClass() == null) {
passesValidation = false;
} else {
ComponentClass pcComponentClass = pcComponent.getComponentClass();
// Component Class Registry Type field
fieldValidation = !isRequiredStringFieldBlank("registryType",
pcComponentClass.getRegistryType());
if (!fieldValidation) {
resultMessage.append("Component class registry type is empty or null\n");
}
passesValidation &= fieldValidation;
// Component Class Component Identifier field
fieldValidation = !isRequiredStringFieldBlank("componentIdentifier",
pcComponentClass.getComponentIdentifier());
if (!fieldValidation) {
resultMessage.append("Component class component identifier is empty or null\n");
}
passesValidation &= fieldValidation;
// Component Class category field
fieldValidation = !isRequiredStringFieldBlank("category",
pcComponentClass.getCategory());
if (!fieldValidation) {
resultMessage.append("Component class category is empty or null\n");
}
passesValidation &= fieldValidation;
// Component Class Category String field
fieldValidation = !isRequiredStringFieldBlank("categoryStr",
pcComponentClass.getCategoryStr());
if (!fieldValidation) {
resultMessage.append("Component class category string is empty or null\n");
}
passesValidation &= fieldValidation;
// Component Class Component String field
fieldValidation = !isRequiredStringFieldBlank("componentStr",
pcComponentClass.getComponentStr());
if (!fieldValidation) {
resultMessage.append("Component class string is empty or null\n");
}
passesValidation &= fieldValidation;
// Component Class Component field
fieldValidation = !isRequiredStringFieldBlank("component",
pcComponentClass.getComponent());
if (!fieldValidation) {
resultMessage.append("Component class component is empty or null\n");
}
passesValidation &= fieldValidation;
}
}
passesValidation &= fieldValidation;
}
// populate componentResults list
@ -263,18 +366,24 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
.findByCertificateSerialNumberAndBoardSerialNumber(
platformCredential.getSerialNumber().toString(),
platformCredential.getPlatformSerial());
// first create hash map based on hashCode
List<ComponentResult> remainingComponentResults = checkDeviceHashMap(
componentInfos, componentResults);
//this is used to get a unique count
List<UUID> componentIdList = new ArrayList<>();
int numOfAttributes = 0;
if (!remainingComponentResults.isEmpty()) {
List<ComponentAttributeResult> attributeResults = checkComponentClassMap(
componentInfos, remainingComponentResults);
numOfAttributes = attributeResults.size();
boolean saveAttributeResult;
for (ComponentAttributeResult componentAttributeResult : attributeResults) {
saveAttributeResult = true;
if (ignoreRevisionAttribute) {
@ -293,6 +402,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
}
StringBuilder additionalInfo = new StringBuilder();
if (numOfAttributes > 0) {
resultMessage.append(String.format("There are %d component(s) not matched%n "
+ "with %d total attributes mismatched.",
@ -435,7 +545,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
for (ComponentInfo cInfo : allDeviceInfoComponents) {
for (ComponentIdentifier cId : fullDeltaChainComponents) {
ciV2 = (ComponentIdentifierV2) cId;
if (cInfo.getComponentClass().contains(
if (cInfo.getComponentClassValue().contains(
ciV2.getComponentClass().getComponentIdentifier())
&& isMatch(cId, cInfo)) {
subCompIdList.remove(cId);
@ -455,7 +565,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
if (ci.isVersion2() && PciIds.DB.isReady()) {
ci = AcaPciIds.translate((ComponentIdentifierV2) ci);
}
log.error("Unmatched component: " + ci);
log.error("Unmatched component: {}", ci);
fullDeltaChainComponents.add(ci);
invalidPcIds.append(String.format(
"Manufacturer=%s, Model=%s, Serial=%s, Revision=%s;%n",
@ -513,25 +623,34 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
log.info("Validating the following Platform Cert components...");
pcComponents.forEach(component -> log.info(component.toString()));
log.info("...against the the following DeviceInfoReport components:");
allDeviceInfoComponents.forEach(component -> log.info(component.toString()));
Set<ASN1UTF8String> manufacturerSet = new HashSet<>();
// create a set of component manufacturers
pcComponents.forEach(pcComp -> manufacturerSet.add(pcComp.getComponentManufacturer()));
// Create a list for unmatched components across all manufacturers to display at the end.
List<ComponentIdentifier> pcUnmatchedComponents = new ArrayList<>();
for (ASN1UTF8String derUtf8Manufacturer : manufacturerSet) {
// look for all the component identifiers whose manufacturer matches that of the current
// manufacturer
List<ComponentIdentifier> pcComponentsFromManufacturer
= pcComponents.stream().filter(compIdentifier
-> compIdentifier.getComponentManufacturer().equals(derUtf8Manufacturer))
.collect(Collectors.toList());
String pcManufacturer = derUtf8Manufacturer.getString();
// look for all the component infos whose manufacturer matches that of the current
// manufacturer
String currentPCManufacturer = derUtf8Manufacturer.getString();
List<ComponentInfo> deviceInfoComponentsFromManufacturer
= allDeviceInfoComponents.stream().filter(componentInfo
-> componentInfo.getComponentManufacturer().equals(pcManufacturer))
-> componentInfo.getComponentManufacturer().equals(currentPCManufacturer))
.collect(Collectors.toList());
// For each component listed in the platform credential from this manufacturer
// find the ones that specify a serial number so we can match the most specific ones
// first.
@ -539,7 +658,8 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
= pcComponentsFromManufacturer.stream().filter(compIdentifier
-> compIdentifier.getComponentSerial() != null
&& StringUtils.isNotEmpty(compIdentifier.getComponentSerial().getString()))
.collect(Collectors.toList());
.toList();
// Now match up the components from the device info that are from the same
// manufacturer and have a serial number. As matches are found, remove them from
// both lists.
@ -560,6 +680,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
}
}
}
// For each component listed in the platform credential from this manufacturer
// find the ones that specify value for the revision field so we can match the most
// specific ones first.
@ -567,7 +688,8 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
= pcComponentsFromManufacturer.stream().filter(compIdentifier
-> compIdentifier.getComponentRevision() != null
&& StringUtils.isNotEmpty(compIdentifier.getComponentRevision().getString()))
.collect(Collectors.toList());
.toList();
// Now match up the components from the device info that are from the same
// manufacturer and specify a value for the revision field. As matches are found,
// remove them from both lists.
@ -608,8 +730,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
if (!pcUnmatchedComponents.isEmpty()) {
untrimmedPcComponents.clear();
StringBuilder sb = new StringBuilder();
log.error(String.format("Platform Credential contained %d unmatched components:",
pcUnmatchedComponents.size()));
log.error("Platform Credential contained {} unmatched components:", pcUnmatchedComponents.size());
int unmatchedComponentCounter = 1;
for (ComponentIdentifier unmatchedComponent : pcUnmatchedComponents) {
@ -617,8 +738,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
unmatchedComponent =
AcaPciIds.translate((ComponentIdentifierV2) unmatchedComponent);
}
log.error("Unmatched component " + unmatchedComponentCounter++ + ": "
+ unmatchedComponent);
log.error("Unmatched component {}: {}", unmatchedComponentCounter++, unmatchedComponent);
sb.append(String.format("Manufacturer=%s, Model=%s, Serial=%s, Revision=%s;%n",
unmatchedComponent.getComponentManufacturer(),
unmatchedComponent.getComponentModel(),
@ -670,7 +790,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
private static boolean isMatchOrEmptyInPlatformCert(
final String evidenceFromDevice,
final ASN1UTF8String valueInPlatformCert) {
if (valueInPlatformCert == null || StringUtils.isEmpty(valueInPlatformCert.getString())) {
if (StringUtils.isBlank(valueInPlatformCert.getString())) {
return true;
}
return valueInPlatformCert.getString().equals(evidenceFromDevice);
@ -756,7 +876,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
final String platformCredentialFieldName,
final String platformCredentialFieldValue,
final String otherValue) {
if (hasEmptyValueForRequiredField(platformCredentialFieldName,
if (isRequiredStringFieldBlank(platformCredentialFieldName,
platformCredentialFieldValue)) {
return false;
}
@ -794,11 +914,10 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
* @param fieldValue value of the field
* @return true if fieldValue is null or empty; false otherwise
*/
private static boolean hasEmptyValueForRequiredField(final String description,
final String fieldValue) {
if (StringUtils.isEmpty(fieldValue)) {
log.error("Required field was empty or null in Platform Credential: "
+ description);
private static boolean isRequiredStringFieldBlank(final String description,
final String fieldValue) {
if (StringUtils.isBlank(fieldValue)) {
log.error("Required string field was empty or null in Platform Credential: {}", description);
return true;
}
return false;
@ -829,15 +948,15 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
String trimmedOtherValue = otherValue.trim();
if (!trimmedFieldValue.equals(trimmedOtherValue)) {
log.debug(String.format("%s field in Platform Credential (%s) does not match "
+ "a related field in the DeviceInfoReport (%s)",
platformCredentialFieldName, trimmedFieldValue, trimmedOtherValue));
log.debug("{} field in Platform Credential ({}) does not match "
+ "a related field in the DeviceInfoReport ({})",
platformCredentialFieldName, trimmedFieldValue, trimmedOtherValue);
return false;
}
log.debug(String.format("%s field in Platform Credential matches "
+ "a related field in the DeviceInfoReport (%s)",
platformCredentialFieldName, trimmedFieldValue)
log.debug("{} field in Platform Credential matches "
+ "a related field in the DeviceInfoReport {}",
platformCredentialFieldName, trimmedFieldValue
);
return true;
@ -850,11 +969,10 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
* @param fieldValue value of the field
* @return true if fieldValue is null or empty; false otherwise
*/
private static boolean hasEmptyValueForRequiredField(final String description,
final ASN1UTF8String fieldValue) {
if (fieldValue == null || StringUtils.isEmpty(fieldValue.getString().trim())) {
log.error("Required field was empty or null in Platform Credential: "
+ description);
private static boolean isRequiredASN1StringFieldBlank(final String description,
final ASN1UTF8String fieldValue) {
if (fieldValue == null || StringUtils.isBlank(fieldValue.getString().trim())) {
log.error("Required ASN1 string field was empty or null in Platform Credential: {}", description);
return true;
}
return false;
@ -871,16 +989,17 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
final List<ComponentInfo> componentInfos,
final List<ComponentResult> compiledComponentList) {
Map<Integer, List<ComponentInfo>> deviceHashMap = new HashMap<>();
componentInfos.stream().forEach((componentInfo) -> {
List<ComponentInfo> innerList;
componentInfos.forEach((componentInfo) -> {
List<ComponentInfo> innerList = new ArrayList<>();
Integer compInfoHash = componentInfo.hashCommonElements();
if (deviceHashMap.containsKey(compInfoHash)) {
innerList = deviceHashMap.get(compInfoHash);
innerList.add(componentInfo);
} else {
innerList = new ArrayList<>(0);
innerList.add(componentInfo);
}
innerList.add(componentInfo);
deviceHashMap.put(compInfoHash, innerList);
});
@ -910,23 +1029,37 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
// 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();
componentInfos.forEach((componentInfo) -> {
List<ComponentInfo> innerList = new ArrayList<>();
String componentClass = componentInfo.getComponentClassValue();
if (componentDeviceMap.containsKey(componentClass)) {
innerList = componentDeviceMap.get(componentClass);
innerList.add(componentInfo);
} else {
innerList = new ArrayList<>(0);
innerList.add(componentInfo);
}
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 == null) {
log.error("The retrieved list of component class info is null. The null list"
+ "is associated with the component result's component class value of {}",
componentResult.getComponentClassValue());
//move on to the next iteration since there is nothing we can do with the null
// component class info
continue;
}
if (componentClassInfo.size() == 1) {
attributeResults.addAll(generateComponentAttributeResults(
componentClassInfo.get(0), componentResult));
@ -1000,11 +1133,13 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
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) -> {
componentClassInfo.forEach((componentInfo) -> {
componentSerialMap.put(componentInfo.getComponentSerial(), componentInfo);
});
// see if the serial exists
ComponentInfo componentInfo = componentSerialMap.get(componentResult.getSerialNumber());

View File

@ -35,7 +35,7 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
*
* @param ec the endorsement credential to verify.
* @param trustStore trust store holding trusted certificates.
* @param acceptExpired whether or not to accept expired and not yet valid certificates
* @param acceptExpired whether to accept expired and not yet valid certificates
* as valid.
* @return the result of the validation.
*/
@ -100,7 +100,7 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
*
* @param pc The platform credential to verify.
* @param trustStore trust store holding trusted certificates.
* @param acceptExpired whether or not to accept expired certificates as valid.
* @param acceptExpired whether to accept expired certificates as valid.
* @return The result of the validation.
*/
public static AppraisalStatus validatePlatformCredential(final PlatformCredential pc,
@ -183,21 +183,24 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
final ComponentResultRepository componentResultRepository,
final ComponentAttributeRepository componentAttributeRepository,
final List<ComponentInfo> componentInfos,
final UUID provisionSessionId, final boolean ignoreRevisionAttribute) {
final UUID provisionSessionId, final boolean ignoreRevisionAttribute) throws IOException {
final String baseErrorMessage = "Can't validate platform credential attributes without ";
String message;
if (platformCredential == null) {
message = baseErrorMessage + "a platform credential";
return new AppraisalStatus(FAIL, message);
}
if (deviceInfoReport == null) {
message = baseErrorMessage + "a device info report";
return new AppraisalStatus(FAIL, message);
}
if (endorsementCredential == null) {
message = baseErrorMessage + "an endorsement credential";
return new AppraisalStatus(FAIL, message);
}
if (componentInfos.isEmpty()) {
message = baseErrorMessage + "a list of device components";
return new AppraisalStatus(FAIL, message);

View File

@ -38,6 +38,7 @@ import static hirs.attestationca.persist.enums.AppraisalStatus.Status.PASS;
public class FirmwareScvValidator extends SupplyChainCredentialValidator {
private static PcrValidator pcrValidator;
private static ReferenceManifest supportReferenceManifest;
/**
* @param device device
@ -54,16 +55,11 @@ public class FirmwareScvValidator extends SupplyChainCredentialValidator {
final ReferenceDigestValueRepository referenceDigestValueRepository,
final CACredentialRepository caCredentialRepository) {
boolean passed = true;
String[] baseline = new String[Integer.SIZE];
AppraisalStatus fwStatus = null;
String hostName = device.getDeviceInfo().getNetworkInfo().getHostname();
// ReferenceManifest validationObject;
List<BaseReferenceManifest> baseReferenceManifests = null;
BaseReferenceManifest baseReferenceManifest = null;
ReferenceManifest supportReferenceManifest = null;
EventLogMeasurements measurement = null;
//baseReferenceManifests = referenceManifestRepository.findAllBaseRims();
log.info("Validating firmware...");
// This block was looking for a base RIM matching the device name
// The base rim might not have a device name associated with it- i.e. if it's uploaded to the ACA
@ -90,7 +86,7 @@ public class FirmwareScvValidator extends SupplyChainCredentialValidator {
String failedString = "";
if (baseReferenceManifest == null) {
failedString = "Base Reference Integrity Manifest\n";
failedString = "Base Reference Integrity Manifest not found for " + hostName + "\n";
passed = false;
} else if (measurement == null) {
measurement = (EventLogMeasurements) referenceManifestRepository.findByHexDecHashAndRimType(
@ -103,195 +99,247 @@ public class FirmwareScvValidator extends SupplyChainCredentialValidator {
}
if (measurement == null) {
failedString += "Bios measurement";
failedString += "Bios measurement not found for " + hostName;
passed = false;
}
if (passed) {
List<SwidResource> resources =
baseReferenceManifest.getFileResources();
fwStatus = new AppraisalStatus(PASS,
SupplyChainCredentialValidator.FIRMWARE_VALID);
// verify signatures
ReferenceManifestValidator referenceManifestValidator =
new ReferenceManifestValidator();
referenceManifestValidator.setRim(baseReferenceManifest.getRimBytes());
//Validate signing cert
List<CertificateAuthorityCredential> allCerts = caCredentialRepository.findAll();
CertificateAuthorityCredential signingCert = null;
for (CertificateAuthorityCredential cert : allCerts) {
signingCert = cert;
KeyStore keyStore = null;
Set<CertificateAuthorityCredential> set = ValidationService.getCaChainRec(signingCert,
Collections.emptySet(),
caCredentialRepository);
try {
keyStore = ValidationService.caCertSetToKeystore(set);
} catch (Exception e) {
log.error("Error building CA chain for {}: {}", signingCert.getSubjectKeyIdentifier(),
e.getMessage());
}
ArrayList<X509Certificate> certs = new ArrayList<>(set.size());
for (CertificateAuthorityCredential cac : set) {
try {
certs.add(cac.getX509Certificate());
} catch (IOException e) {
log.error("Error building CA chain for {}: {}", signingCert.getSubjectKeyIdentifier(),
e.getMessage());
}
}
referenceManifestValidator.setTrustStore(certs);
try {
if (referenceManifestValidator.validateXmlSignature(
signingCert.getX509Certificate().getPublicKey(),
signingCert.getSubjectKeyIdString(), signingCert.getEncodedPublicKey())) {
try {
if (!SupplyChainCredentialValidator.verifyCertificate(
signingCert.getX509Certificate(), keyStore)) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: invalid certificate path.");
}
} catch (IOException ioEx) {
log.error("Error getting X509 cert from manager: {}", ioEx.getMessage());
} catch (SupplyChainValidatorException scvEx) {
log.error("Error validating cert against keystore: {}", scvEx.getMessage());
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: invalid certificate path.");
}
break;
}
} catch (IOException ioEx) {
log.error("Error getting X509 cert from manager: {}", ioEx.getMessage());
}
}
for (SwidResource swidRes : resources) {
supportReferenceManifest = referenceManifestRepository.findByHexDecHashAndRimType(
swidRes.getHashValue(), ReferenceManifest.SUPPORT_RIM);
if (supportReferenceManifest != null) {
// Removed the filename check from this if statement
referenceManifestValidator.validateSupportRimHash(
supportReferenceManifest.getRimBytes(), swidRes.getHashValue());
}
}
if (passed && signingCert == null) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: signing cert not found.");
}
if (passed && supportReferenceManifest == null) {
fwStatus = new AppraisalStatus(FAIL,
"Support Reference Integrity Manifest can not be found");
passed = false;
}
if (passed && !referenceManifestValidator.isSignatureValid()) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: Signature validation "
+ "failed for Base RIM.");
}
if (passed && !referenceManifestValidator.isSupportRimValid()) {
passed = false;
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: Hash validation "
+ "failed for Support RIM.");
}
if (passed) {
TCGEventLog expectedEventLog;
try {
expectedEventLog = new TCGEventLog(supportReferenceManifest.getRimBytes());
baseline = expectedEventLog.getExpectedPCRValues();
} catch (CertificateException | IOException | NoSuchAlgorithmException cEx) {
log.error(cEx);
}
// part 1 of firmware validation check: PCR baseline match
pcrValidator = new PcrValidator(baseline);
if (baseline.length > 0) {
String pcrContent = "";
pcrContent = new String(device.getDeviceInfo().getTpmInfo().getPcrValues(),
StandardCharsets.UTF_8);
if (pcrContent.isEmpty()) {
fwStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: Client did not "
+ "provide pcr values.");
log.warn("Firmware validation failed: Client ({}) did not "
+ "provide pcr values.", device.getName());
} else {
// we have a full set of PCR values
//int algorithmLength = baseline[0].length();
//String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength);
//pcrPolicy.validatePcrs(storedPcrs);
// part 2 of firmware validation check: bios measurements
// vs baseline tcg event log
// find the measurement
TCGEventLog actualEventLog;
LinkedList<TpmPcrEvent> failedPcrValues = new LinkedList<>();
List<ReferenceDigestValue> rimIntegrityMeasurements;
HashMap<String, ReferenceDigestValue> expectedEventLogRecords = new HashMap<>();
try {
if (measurement.getDeviceName().equals(hostName)) {
actualEventLog = new TCGEventLog(measurement.getRimBytes());
rimIntegrityMeasurements = referenceDigestValueRepository
.findValuesByBaseRimId(baseReferenceManifest.getId());
for (ReferenceDigestValue rdv : rimIntegrityMeasurements) {
expectedEventLogRecords.put(rdv.getDigestValue(), rdv);
}
failedPcrValues.addAll(pcrValidator.validateTpmEvents(
actualEventLog, expectedEventLogRecords, policySettings));
}
} catch (CertificateException | NoSuchAlgorithmException | IOException exception) {
log.error(exception);
}
if (!failedPcrValues.isEmpty()) {
StringBuilder sb = new StringBuilder();
sb.append(String.format("%d digest(s) were not found:%n",
failedPcrValues.size()));
for (TpmPcrEvent tpe : failedPcrValues) {
sb.append(String.format("PCR Index %d - %s%n",
tpe.getPcrIndex(),
tpe.getEventTypeStr()));
}
if (fwStatus.getAppStatus().equals(FAIL)) {
fwStatus = new AppraisalStatus(FAIL, String.format("%s%n%s",
fwStatus.getMessage(), sb));
} else {
fwStatus = new AppraisalStatus(FAIL,
sb.toString(), ReferenceManifest.MEASUREMENT_RIM);
}
}
}
AppraisalStatus rimSignatureStatus = validateRimSignature(baseReferenceManifest,
caCredentialRepository, referenceManifestRepository);
fwStatus = rimSignatureStatus;
if (rimSignatureStatus.getAppStatus() == PASS) {
AppraisalStatus pcrStatus = validatePcrValues(device, hostName, baseReferenceManifest,
measurement, referenceDigestValueRepository, policySettings);
fwStatus = pcrStatus;
if (pcrStatus.getAppStatus() == PASS) {
EventLogMeasurements eventLog = measurement;
eventLog.setOverallValidationResult(PASS);
referenceManifestRepository.save(eventLog);
fwStatus = new AppraisalStatus(PASS, SupplyChainCredentialValidator.FIRMWARE_VALID);
} else {
fwStatus = new AppraisalStatus(FAIL, "The RIM baseline could not be found.");
failedString = pcrStatus.getMessage();
log.warn("PCR value validation failed: " + failedString);
passed = false;
}
} else {
failedString = rimSignatureStatus.getMessage();
log.warn("RIM signature validation failed: " + failedString);
passed = false;
}
EventLogMeasurements eventLog = measurement;
eventLog.setOverallValidationResult(fwStatus.getAppStatus());
referenceManifestRepository.save(eventLog);
} else {
fwStatus = new AppraisalStatus(FAIL, String.format("Firmware Validation failed: "
+ "%s for %s can not be found", failedString, hostName));
}
if (!passed) {
if (measurement != null) {
measurement.setOverallValidationResult(fwStatus.getAppStatus());
referenceManifestRepository.save(measurement);
}
}
return fwStatus;
}
private static AppraisalStatus validateRimSignature(
final BaseReferenceManifest baseReferenceManifest,
final CACredentialRepository caCredentialRepository,
final ReferenceManifestRepository referenceManifestRepository) {
List<SwidResource> resources =
baseReferenceManifest.getFileResources();
AppraisalStatus rimSignatureStatus = new AppraisalStatus(PASS, "RIM signature valid.");
boolean passed = true;
log.info("Validating RIM signature...");
// verify signatures
ReferenceManifestValidator referenceManifestValidator =
new ReferenceManifestValidator();
referenceManifestValidator.setRim(baseReferenceManifest.getRimBytes());
//Validate signing cert
List<CertificateAuthorityCredential> allCerts = caCredentialRepository.findAll();
CertificateAuthorityCredential signingCert = null;
for (CertificateAuthorityCredential cert : allCerts) {
signingCert = cert;
KeyStore keyStore = null;
Set<CertificateAuthorityCredential> set = ValidationService.getCaChainRec(signingCert,
Collections.emptySet(),
caCredentialRepository);
try {
keyStore = ValidationService.caCertSetToKeystore(set);
} catch (Exception e) {
log.error("Error building CA chain for " + signingCert.getSubjectKeyIdentifier() + ": "
+ e.getMessage());
}
ArrayList<X509Certificate> certs = new ArrayList<>(set.size());
for (CertificateAuthorityCredential cac : set) {
try {
certs.add(cac.getX509Certificate());
} catch (IOException e) {
log.error(
"Error building CA chain for " + signingCert.getSubjectKeyIdentifier() + ": "
+ e.getMessage());
}
}
referenceManifestValidator.setTrustStore(certs);
try {
if (referenceManifestValidator.validateXmlSignature(
signingCert.getX509Certificate().getPublicKey(),
signingCert.getSubjectKeyIdString(), signingCert.getEncodedPublicKey())) {
try {
if (!SupplyChainCredentialValidator.verifyCertificate(
signingCert.getX509Certificate(), keyStore)) {
passed = false;
rimSignatureStatus = new AppraisalStatus(FAIL,
"RIM signature validation failed: invalid certificate path.");
}
} catch (IOException ioEx) {
log.error("Error getting X509 cert from manager: " + ioEx.getMessage());
} catch (SupplyChainValidatorException scvEx) {
log.error("Error validating cert against keystore: " + scvEx.getMessage());
rimSignatureStatus = new AppraisalStatus(FAIL,
"RIM signature validation failed: invalid certificate path.");
}
break;
}
} catch (IOException ioEx) {
log.error("Error getting X509 cert from manager: " + ioEx.getMessage());
}
}
for (SwidResource swidRes : resources) {
supportReferenceManifest = referenceManifestRepository.findByHexDecHashAndRimType(
swidRes.getHashValue(), ReferenceManifest.SUPPORT_RIM);
if (supportReferenceManifest != null) {
// Removed the filename check from this if statement
referenceManifestValidator.validateSupportRimHash(
supportReferenceManifest.getRimBytes(), swidRes.getHashValue());
}
}
if (passed && signingCert == null) {
passed = false;
rimSignatureStatus = new AppraisalStatus(FAIL,
"RIM signature validation failed: signing cert not found.");
}
if (passed && supportReferenceManifest == null) {
rimSignatureStatus = new AppraisalStatus(FAIL,
"Support Reference Integrity Manifest can not be found");
passed = false;
}
if (passed && !referenceManifestValidator.isSignatureValid()) {
passed = false;
rimSignatureStatus = new AppraisalStatus(FAIL,
"RIM signature validation failed: Signature validation "
+ "failed for Base RIM.");
}
if (passed && !referenceManifestValidator.isSupportRimValid()) {
rimSignatureStatus = new AppraisalStatus(FAIL,
"RIM signature validation failed: Hash validation "
+ "failed for Support RIM.");
}
return rimSignatureStatus;
}
private static AppraisalStatus validatePcrValues(
final Device device,
final String hostName,
final ReferenceManifest baseReferenceManifest,
final EventLogMeasurements measurement,
final ReferenceDigestValueRepository referenceDigestValueRepository,
final PolicySettings policySettings) {
String[] baseline = new String[Integer.SIZE];
TCGEventLog logProcessor;
AppraisalStatus pcrAppraisalStatus = new AppraisalStatus(PASS, "PCR values validated.");
log.info("Validating PCR values...");
try {
logProcessor = new TCGEventLog(supportReferenceManifest.getRimBytes());
baseline = logProcessor.getExpectedPCRValues();
} catch (CertificateException cEx) {
log.error(cEx);
} catch (NoSuchAlgorithmException noSaEx) {
log.error(noSaEx);
} catch (IOException ioEx) {
log.error(ioEx);
}
// part 1 of firmware validation check: PCR baseline match
pcrValidator = new PcrValidator(baseline);
if (baseline.length > 0) {
String pcrContent = "";
pcrContent = new String(device.getDeviceInfo().getTpmInfo().getPcrValues(),
StandardCharsets.UTF_8);
if (pcrContent.isEmpty()) {
pcrAppraisalStatus = new AppraisalStatus(FAIL,
"Firmware validation failed: Client did not "
+ "provide pcr values.");
log.warn(String.format(
"Firmware validation failed: Client (%s) did not "
+ "provide pcr values.", device.getName()));
} else {
// we have a full set of PCR values
//int algorithmLength = baseline[0].length();
//String[] storedPcrs = buildStoredPcrs(pcrContent, algorithmLength);
//pcrPolicy.validatePcrs(storedPcrs);
// part 2 of firmware validation check: bios measurements
// vs baseline tcg event log
// find the measurement
TCGEventLog tcgMeasurementLog;
LinkedList<TpmPcrEvent> tpmPcrEvents = new LinkedList<>();
List<ReferenceDigestValue> eventValue;
HashMap<String, ReferenceDigestValue> eventValueMap = new HashMap<>();
try {
if (measurement.getDeviceName().equals(hostName)) {
tcgMeasurementLog = new TCGEventLog(measurement.getRimBytes());
eventValue = referenceDigestValueRepository
.findValuesByBaseRimId(baseReferenceManifest.getId());
for (ReferenceDigestValue rdv : eventValue) {
eventValueMap.put(rdv.getDigestValue(), rdv);
}
tpmPcrEvents.addAll(pcrValidator.validateTpmEvents(
tcgMeasurementLog, eventValueMap, policySettings));
}
} catch (NoSuchAlgorithmException e) {
log.error(e);
} catch (CertificateException cEx) {
log.error(cEx);
} catch (IOException e) {
log.error(e);
}
if (!tpmPcrEvents.isEmpty()) {
StringBuilder sb = new StringBuilder();
sb.append(String.format("%d digest(s) were not found:%n",
tpmPcrEvents.size()));
for (TpmPcrEvent tpe : tpmPcrEvents) {
sb.append(String.format("PCR Index %d - %s%n",
tpe.getPcrIndex(),
tpe.getEventTypeStr()));
}
if (pcrAppraisalStatus.getAppStatus().equals(FAIL)) {
pcrAppraisalStatus = new AppraisalStatus(FAIL, String.format("%s%n%s",
pcrAppraisalStatus.getMessage(), sb.toString()));
} else {
pcrAppraisalStatus = new AppraisalStatus(FAIL,
sb.toString(), ReferenceManifest.MEASUREMENT_RIM);
}
}
}
} else {
pcrAppraisalStatus = new AppraisalStatus(FAIL, "The RIM baseline could not be found.");
}
return pcrAppraisalStatus;
}
private static void logAndReportError(final AppraisalStatus status, final String errorString) {
status.setMessage(errorString);
log.error(errorString);
}
}

View File

@ -93,7 +93,9 @@ public class SupplyChainCredentialValidator {
throw new SupplyChainValidatorException("Truststore is empty");
}
} catch (KeyStoreException ksEx) {
log.error("Error accessing trust store: " + ksEx.getMessage());
log.error(
"Error accessing trust store while trying to verify the X509 Attribute"
+ " Certificate Holder: {}", ksEx.getMessage());
}
try {
@ -134,7 +136,8 @@ public class SupplyChainCredentialValidator {
throw new SupplyChainValidatorException("Truststore is empty");
}
} catch (KeyStoreException ksEx) {
log.error("Error accessing trust store: " + ksEx.getMessage());
log.error("Error accessing trust store while trying to verify the X509 Certificate: {}",
ksEx.getMessage());
}
try {
@ -147,8 +150,9 @@ public class SupplyChainCredentialValidator {
return validateCertChain(cert, trustedCerts).isEmpty();
} catch (KeyStoreException ksEx) {
log.error("Error accessing keystore", ksEx);
throw new SupplyChainValidatorException("Error with the trust store", ksEx);
log.error("Error accessing keystore while trying to verify the X509 Certificate", ksEx);
throw new SupplyChainValidatorException(
"Error accessing keystore while trying to verify the X509 Certificate", ksEx);
}
}
@ -191,7 +195,7 @@ public class SupplyChainCredentialValidator {
if (issuerMatchesSubject && signatureMatchesPublicKey) {
if (isSelfSigned(trustedCert)) {
log.info("CA Root found.");
log.info("CA Root found while validating the X509 Attribute Certificate Holder.");
return "";
} else {
foundRootOfCertChain = intCAError;
@ -244,7 +248,7 @@ public class SupplyChainCredentialValidator {
trustedCert);
if (issuerMatchesSubject && signatureMatchesPublicKey) {
if (isSelfSigned(trustedCert)) {
log.info("CA Root found.");
log.info("CA Root found while validating X509 Certificate.");
return "";
} else {
foundRootOfCertChain = intCAError;
@ -270,7 +274,7 @@ public class SupplyChainCredentialValidator {
* Parses the output from PACCOR's allcomponents.sh script into ComponentInfo objects.
*
* @param hostName the host machine associated with the component
* @param paccorOutput the output from PACCOR's allcomoponents.sh
* @param paccorOutput the output from PACCOR's allcomponents.sh
* @return a list of ComponentInfo objects built from paccorOutput
* @throws java.io.IOException if something goes wrong parsing the JSON
*/
@ -296,17 +300,23 @@ public class SupplyChainCredentialValidator {
getJSONNodeValueAsText(next, "REVISION")));
} else {
// version 2
String componentClass = StringUtils.EMPTY;
String componentClassValue = StringUtils.EMPTY;
String componentClassRegistry = StringUtils.EMPTY;
for (JsonNode subNode : compClassNodes) {
componentClass = getJSONNodeValueAsText(subNode,
componentClassValue = getJSONNodeValueAsText(subNode,
"COMPONENTCLASSVALUE");
componentClassRegistry = getJSONNodeValueAsText(subNode,
"COMPONENTCLASSREGISTRY");
}
componentInfoList.add(new ComponentInfo(hostName,
getJSONNodeValueAsText(next, "MANUFACTURER"),
getJSONNodeValueAsText(next, "MODEL"),
getJSONNodeValueAsText(next, "SERIAL"),
getJSONNodeValueAsText(next, "REVISION"),
componentClass));
componentClassValue,
componentClassRegistry));
}
}
}
@ -314,6 +324,13 @@ public class SupplyChainCredentialValidator {
return componentInfoList;
}
/**
* Helper method that attempts to retrieve the value as text from the provided Json Node.
*
* @param node json node
* @param fieldName field name
* @return string json node value
*/
private static String getJSONNodeValueAsText(final JsonNode node, final String fieldName) {
if (node.hasNonNull(fieldName)) {
return node.findValue(fieldName).textValue();
@ -398,8 +415,7 @@ public class SupplyChainCredentialValidator {
} catch (NoSuchProviderException e) {
log.info("Incorrect provider for cert signature validation");
} catch (SignatureException e) {
log.info(String.format("%s.verify(%s)", cert.getSubjectX500Principal(),
signingCert.getSubjectX500Principal()));
log.info("{}.verify({})", cert.getSubjectX500Principal(), signingCert.getSubjectX500Principal());
}
return false;
@ -444,8 +460,7 @@ public class SupplyChainCredentialValidator {
return cert.isSignatureValid(contentVerifierProvider);
} catch (OperatorCreationException | CertException e) {
log.info("Exception thrown while verifying certificate", e);
log.info(String.format("%s.isSignatureValid(%s)", cert.getSerialNumber(),
signingKey.getFormat()));
log.info("{}.isSignatureValid({})", cert.getSerialNumber(), signingKey.getFormat());
return false;
}
}

View File

@ -3,10 +3,11 @@ package hirs.attestationca.persist.entity.userdefined.certificate;
import hirs.attestationca.persist.entity.userdefined.AbstractUserdefinedEntityTest;
import hirs.attestationca.persist.entity.userdefined.Certificate;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfigurationV1;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformProperty;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.TBBSecurityAssertion;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.URIReference;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.PlatformConfigurationV2;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.util.encoders.Base64;
@ -439,10 +440,10 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
PlatformConfigurationV1 platformConfigV1 = platformCert.getPlatformConfigurationV1();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
List<ComponentIdentifier> allComponents = platformConfigV1.getComponentIdentifiers();
if (allComponents.isEmpty()) {
Assertions.fail("Component Identifier is empty.");
}
@ -472,14 +473,14 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
component = allComponents.get(component5Position);
Assertions.assertEquals("Ethernet Connection I219-LM", component.getComponentModel()
.getString());
Assertions.assertEquals("8c:0f:6f:72:c6:c5", component.getComponentAddress().get(0)
Assertions.assertEquals("8c:0f:6f:72:c6:c5", component.getComponentAddresses().get(0)
.getAddressValue()
.getString());
Assertions.assertEquals("ethernet mac", component.getComponentAddress().get(0)
Assertions.assertEquals("ethernet mac", component.getComponentAddresses().get(0)
.getAddressTypeValue());
//Check Platform Properties
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
List<PlatformProperty> platformProperties = platformConfigV1.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
@ -499,7 +500,7 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
Assertions.assertEquals("true", property.getPropertyValue().getString());
//Check Platform Properties URI
URIReference platformPropertyUri = platformConfig.getPlatformPropertiesUri();
URIReference platformPropertyUri = platformConfigV1.getPlatformPropertiesUri();
Assertions.assertNotNull(platformPropertyUri);
Assertions.assertEquals("https://www.intel.com/platformproperties.xml",
@ -522,13 +523,13 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
PlatformConfigurationV1 platformConfigV1 = platformCert.getPlatformConfigurationV1();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
List<ComponentIdentifier> allComponents = platformConfigV1.getComponentIdentifiers();
Assertions.assertTrue(allComponents.isEmpty());
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
List<PlatformProperty> platformProperties = platformConfigV1.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
@ -560,10 +561,10 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
PlatformConfigurationV1 platformConfigV1 = platformCert.getPlatformConfigurationV1();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
List<ComponentIdentifier> allComponents = platformConfigV1.getComponentIdentifiers();
if (allComponents.isEmpty()) {
Assertions.fail("Component Identifier is empty.");
}
@ -589,7 +590,7 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
.getString());
//Check Platform Properties
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
List<PlatformProperty> platformProperties = platformConfigV1.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
@ -597,7 +598,7 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
Assertions.assertEquals(platformProperties.size(), 2);
//Check Platform Properties URI
URIReference platformPropertyUri = platformConfig.getPlatformPropertiesUri();
URIReference platformPropertyUri = platformConfigV1.getPlatformPropertiesUri();
Assertions.assertNotNull(platformPropertyUri);
Assertions.assertEquals("https://www.intel.com/platformproperties.xml",
@ -629,10 +630,10 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
PlatformConfigurationV1 platformConfigV1 = platformCert.getPlatformConfigurationV1();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
List<ComponentIdentifier> allComponents = platformConfigV1.getComponentIdentifiers();
if (allComponents.isEmpty()) {
Assertions.fail("Component Identifier is empty.");
}
@ -651,15 +652,15 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
//Check component #7
final int component7Position = 6;
component = allComponents.get(component7Position);
Assertions.assertTrue(component.getComponentAddress().size() > 0);
Assertions.assertEquals("8c:0f:6f:72:c6:c5", component.getComponentAddress().get(0)
Assertions.assertFalse(component.getComponentAddresses().isEmpty());
Assertions.assertEquals("8c:0f:6f:72:c6:c5", component.getComponentAddresses().get(0)
.getAddressValue()
.getString());
Assertions.assertEquals("ethernet mac", component.getComponentAddress().get(0)
Assertions.assertEquals("ethernet mac", component.getComponentAddresses().get(0)
.getAddressTypeValue());
//Check Platform Properties
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
List<PlatformProperty> platformProperties = platformConfigV1.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
@ -667,7 +668,7 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
Assertions.assertEquals(platformProperties.size(), 2);
//Check Platform Properties URI
URIReference platformPropertyUri = platformConfig.getPlatformPropertiesUri();
URIReference platformPropertyUri = platformConfigV1.getPlatformPropertiesUri();
Assertions.assertNotNull(platformPropertyUri);
Assertions.assertEquals("https://www.intel.com/platformproperties.xml",
@ -700,17 +701,17 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
PlatformConfigurationV2 platformConfigV2 = platformCert.getPlatformConfigurationV2();
//Check component identifier
List<ComponentIdentifier> allComponents = platformConfig.getComponentIdentifier();
List<ComponentIdentifierV2> allComponents = platformConfigV2.getComponentIdentifiers();
Assertions.assertFalse(allComponents.isEmpty());
final int component6Position = 5;
ComponentIdentifier component = allComponents.get(component6Position);
ComponentIdentifierV2 component = allComponents.get(component6Position);
Assertions.assertTrue(component.isVersion2());
List<PlatformProperty> platformProperties = platformConfig.getPlatformProperties();
List<PlatformProperty> platformProperties = platformConfigV2.getPlatformProperties();
if (platformProperties.isEmpty()) {
Assertions.fail("Platform Properties is empty.");
}
@ -749,15 +750,15 @@ public class PlatformCredentialTest extends AbstractUserdefinedEntityTest {
Path certPath = Paths.get(resource.toURI());
PlatformCredential platformCert = new PlatformCredential(certPath);
PlatformConfiguration platformConfig = platformCert.getPlatformConfiguration();
PlatformConfigurationV2 platformConfigV2 = platformCert.getPlatformConfigurationV2();
Assertions.assertInstanceOf(PlatformConfigurationV2.class, platformConfig);
Assertions.assertEquals(platformConfig.getPlatformPropertiesUri()
Assertions.assertInstanceOf(PlatformConfigurationV2.class, platformConfigV2);
Assertions.assertEquals(platformConfigV2.getPlatformPropertiesUri()
.getUniformResourceIdentifier().toString(),
"https://www.intel.com/platformproperties.xml");
// Assertions.assertNotNull(platformConfig.getComponentIdentifierUri());
// Assertions.assertNotNull(platformConfigV1.getComponentIdentifiersUri());
// Assertions.assertEquals(platformConfig.getComponentIdentifierUri()
// Assertions.assertEquals(platformConfigV1.getComponentIdentifiersUri()
// .getUniformResourceIdentifier().toString(),
// "https://www.intel.com/platformidentifiers.xml");

View File

@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@ -16,292 +17,313 @@ public class ComponentClassTest {
private static final String JSON_FILE = "/config/component-class.json";
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentNoneUNK() throws URISyntaxException {
String componentIdentifier = "00000001";
final String componentIdentifier = "00000001";
ComponentClass instance = new ComponentClass("TCG",
Paths.get(this.getClass().getResource(JSON_FILE).toURI()),
Paths.get(Objects.requireNonNull(this.getClass().getResource(JSON_FILE)).toURI()),
componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("Unknown", resultComponent);
assertEquals("None", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentNoneOther() throws URISyntaxException {
String componentIdentifier = "00000000";
final String componentIdentifier = "00000000";
ComponentClass instance = new ComponentClass("TCG", Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("Unknown", resultComponent);
assertEquals("None", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentBlank() throws URISyntaxException {
String componentIdentifier = "";
final String componentIdentifier = "";
ComponentClass instance = new ComponentClass(Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("Unknown", resultComponent);
assertEquals("None", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentNFEx() throws URISyntaxException {
String componentIdentifier = "99999999";
final String componentIdentifier = "99999999";
ComponentClass instance = new ComponentClass(Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("Unknown", resultComponent);
assertEquals("None", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentNull() throws URISyntaxException {
String componentIdentifier = null;
final String componentIdentifier = null;
ComponentClass instance = new ComponentClass(Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("Unknown", resultComponent);
assertEquals("None", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class where the
* registry type is of type TCG.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentStandardQueryTCG() throws URISyntaxException {
String componentIdentifier = "0x00040002";
final String componentIdentifier = "0x00040002";
ComponentClass instance = new ComponentClass(Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("SAS Bridgeboard", resultComponent);
assertEquals("Modules", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class where the
* registry type is of type SMBIOS.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentStandardQuerySMBIOS() throws URISyntaxException {
String componentIdentifier = "0x00040003";
ComponentClass instance = new ComponentClass("2.23.133.18.3.3", Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x00040003";
ComponentClass instance = new ComponentClass("2.23.133.18.3.3", Paths.get(
Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
final String resultRegistry = instance.getRegistryType();
assertEquals("SMBIOS", resultRegistry);
assertEquals("Central Processor", resultComponent);
assertEquals("Processor", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Test of getComponent method, of class ComponentClass where the
* registry type is of type PCIE.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentStandardQueryIntTCG() throws URISyntaxException {
String componentIdentifier = "0x00040002";
ComponentClass instance = new ComponentClass("2.23.133.18.3.1", Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
assertEquals("SAS Bridgeboard", resultComponent);
assertEquals("Modules", resultCategory);
public void testGetComponentStandardQueryPCIE() throws URISyntaxException {
final String componentIdentifier = "0x00080004"; // TODO placeholder for now
ComponentClass instance = new ComponentClass("2.23.133.18.3.4", Paths.get(
Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultRegistry = instance.getRegistryType();
assertEquals("PCIE", resultRegistry);
//TODO Once the component-class.json file is updated to reflect the two new component
// registries, we will then write tests that test the component class' category/component
// properties.
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class where the
* registry type is of type STORAGE.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentStandardQueryIntSMBIOS() throws URISyntaxException {
String componentIdentifier = "0x00040003";
ComponentClass instance = new ComponentClass("2.23.133.18.3.3", Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
assertEquals("Central Processor", resultComponent);
assertEquals("Processor", resultCategory);
public void testGetComponentStandardQuerySTORAGE() throws URISyntaxException {
final String componentIdentifier = "0x00080004"; // TODO placeholder for now
ComponentClass instance = new ComponentClass("2.23.133.18.3.5", Paths.get(
Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultRegistry = instance.getRegistryType();
assertEquals("STORAGE", resultRegistry);
//TODO Once the component-class.json file is updated to reflect the two new component
// registries, we will then write tests that test the component class' category/component
// properties.
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentStandardQueryIntOther() throws URISyntaxException {
String componentIdentifier = "0x00040000";
ComponentClass instance = new ComponentClass("2.23.133.18.3.1", Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x00040000";
ComponentClass instance = new ComponentClass("2.23.133.18.3.1", Paths.get(
Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("Other", resultComponent);
assertEquals("Modules", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentStandardQueryIntUnk() throws URISyntaxException {
String componentIdentifier = "0x00040001";
ComponentClass instance = new ComponentClass("2.23.133.18.3.1", Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x00040001";
ComponentClass instance = new ComponentClass("2.23.133.18.3.1", Paths.get(
Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("Unknown", resultComponent);
assertEquals("Modules", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentStandardQuery2() throws URISyntaxException {
String componentIdentifier = "0x00060015";
ComponentClass instance = new ComponentClass(Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x00060015";
ComponentClass instance = new ComponentClass(Paths.get(Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("DDR3 Memory", resultComponent);
assertEquals("Memory", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentStandardQueryUNK() throws URISyntaxException {
String componentIdentifier = "0x00060001";
ComponentClass instance = new ComponentClass(Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x00060001";
ComponentClass instance = new ComponentClass(Paths.get(Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("Unknown", resultComponent);
assertEquals("Memory", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentNonStandardQuery() throws URISyntaxException {
String componentIdentifier = "0x00040002";
ComponentClass instance = new ComponentClass("2.23.133.18.3.1", Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x00040002";
ComponentClass instance = new ComponentClass("2.23.133.18.3.1", Paths.get(
Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("SAS Bridgeboard", resultComponent);
assertEquals("Modules", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentNonStandardQuery2() throws URISyntaxException {
String componentIdentifier = "0x00040002";
ComponentClass instance = new ComponentClass("2.23.133.18.3.1", Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x00040002";
ComponentClass instance = new ComponentClass("2.23.133.18.3.1", Paths.get(
Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("SAS Bridgeboard", resultComponent);
assertEquals("Modules", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentNonExistentValue() throws URISyntaxException {
String componentIdentifier = "0x00040014";
ComponentClass instance = new ComponentClass(Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x00040014";
ComponentClass instance = new ComponentClass(Paths.get(Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertNotNull(resultComponent);
assertEquals("Unknown", resultComponent);
assertEquals("Modules", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentNonExistentValue2() throws URISyntaxException {
String componentIdentifier = "0x0004FF14";
ComponentClass instance = new ComponentClass(Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x0004FF14";
ComponentClass instance = new ComponentClass(Paths.get(Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertNotNull(resultComponent);
assertEquals("Unknown", resultComponent);
assertEquals("Modules", resultCategory);
}
/**
* Test of getComponent method, of class ComponentClass.
* Tests the getComponent method from the ComponentClass class.
*
* @throws URISyntaxException if there is a problem constructing the URI
*/
@Test
public void testGetComponentNonExistentCategory() throws URISyntaxException {
String componentIdentifier = "0x0015FF14";
ComponentClass instance = new ComponentClass(Paths.get(this.getClass()
.getResource(JSON_FILE).toURI()), componentIdentifier);
String resultCategory = instance.getCategoryStr();
String resultComponent = instance.getComponentStr();
final String componentIdentifier = "0x0015FF14";
ComponentClass instance = new ComponentClass(Paths.get(Objects.requireNonNull(this.getClass()
.getResource(JSON_FILE)).toURI()), componentIdentifier);
final String resultCategory = instance.getCategoryStr();
final String resultComponent = instance.getComponentStr();
assertEquals("Unknown", resultComponent);
assertEquals("None", resultCategory);
}

View File

@ -83,10 +83,6 @@ dependencies {
testImplementation libs.xmlunit.core
}
test {
useJUnitPlatform()
}
task buildVersion() {
doLast {
def verFile = new File(projectDir, "build/VERSION")

View File

@ -19,6 +19,7 @@ import hirs.attestationca.persist.entity.userdefined.certificate.IDevIDCertifica
import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
import hirs.attestationca.persist.util.CredentialHelper;
import hirs.attestationca.portal.datatables.DataTableInput;
import hirs.attestationca.portal.datatables.DataTableResponse;
@ -348,7 +349,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
records.setRecordsFiltered(caCredentialRepository.findByArchiveFlag(false).size());
log.debug("Returning the size of the list of certificate trust chains: {}", records.size());
log.debug("Returning the size of the list of trust chain certificates: {}", records.size());
return new DataTableResponse<>(records, input);
}
case ISSUEDCERTIFICATES -> {
@ -957,7 +958,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
}
this.certificateRepository.save(certificate);
handlePlatformComponents(certificate);
parseAndSaveComponentResults(certificate);
final String successMsg
= String.format("New certificate successfully uploaded (%s): ", fileName);
@ -971,6 +972,11 @@ public class CertificatePageController extends PageController<NoPageParams> {
messages.addError(failMessage + dbsEx.getMessage());
log.error(failMessage, dbsEx);
return;
} catch (IOException ioException) {
final String ioExceptionMessage = "Failed to save component results in the database";
messages.addError(ioExceptionMessage + ioException.getMessage());
log.error(ioExceptionMessage, ioException);
return;
}
try {
@ -1019,7 +1025,7 @@ public class CertificatePageController extends PageController<NoPageParams> {
*
* @param certificate certificate
*/
private void handlePlatformComponents(final Certificate certificate) {
private void parseAndSaveComponentResults(final Certificate certificate) throws IOException {
PlatformCredential platformCredential;
if (certificate instanceof PlatformCredential) {
@ -1028,19 +1034,38 @@ public class CertificatePageController extends PageController<NoPageParams> {
.findByCertificateSerialNumberAndBoardSerialNumber(
platformCredential.getSerialNumber().toString(),
platformCredential.getPlatformSerial());
if (componentResults.isEmpty()) {
ComponentResult componentResult;
List<ComponentIdentifier> componentIdentifiers = platformCredential.getComponentIdentifiers();
if (platformCredential.getPlatformConfigurationV1() != null) {
for (ComponentIdentifier componentIdentifier : componentIdentifiers) {
componentResult = new ComponentResult(platformCredential.getPlatformSerial(),
platformCredential.getSerialNumber().toString(),
platformCredential.getPlatformChainType(),
componentIdentifier);
componentResult.setFailedValidation(false);
componentResult.setDelta(!platformCredential.isPlatformBase());
componentResultRepository.save(componentResult);
List<ComponentIdentifier> componentIdentifiers =
platformCredential.getComponentIdentifiers();
for (ComponentIdentifier componentIdentifier : componentIdentifiers) {
componentResult = new ComponentResult(platformCredential.getPlatformSerial(),
platformCredential.getSerialNumber().toString(),
platformCredential.getPlatformChainType(),
componentIdentifier);
componentResult.setFailedValidation(false);
componentResult.setDelta(!platformCredential.isPlatformBase());
componentResultRepository.save(componentResult);
}
} else if (platformCredential.getPlatformConfigurationV2() != null) {
List<ComponentIdentifierV2> componentIdentifiersV2 =
platformCredential.getComponentIdentifiersV2();
for (ComponentIdentifierV2 componentIdentifierV2 : componentIdentifiersV2) {
componentResult = new ComponentResult(platformCredential.getPlatformSerial(),
platformCredential.getSerialNumber().toString(),
platformCredential.getPlatformChainType(),
componentIdentifierV2);
componentResult.setFailedValidation(false);
componentResult.setDelta(!platformCredential.isPlatformBase());
componentResultRepository.save(componentResult);
}
}
} else {
for (ComponentResult componentResult : componentResults) {

View File

@ -11,7 +11,9 @@ import hirs.attestationca.persist.entity.userdefined.certificate.IDevIDCertifica
import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfiguration;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.PlatformConfigurationV1;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.PlatformConfigurationV2;
import hirs.attestationca.persist.util.AcaPciIds;
import hirs.utils.BouncyCastleUtils;
import hirs.utils.PciIds;
@ -401,22 +403,39 @@ public final class CertificateStringMapBuilder {
data.put("componentResults", compResults);
//Get platform Configuration values and set map with it
PlatformConfiguration platformConfiguration = certificate.getPlatformConfiguration();
if (platformConfiguration != null) {
//Component Identifier - attempt to translate hardware IDs
List<ComponentIdentifier> comps = platformConfiguration.getComponentIdentifier();
if (certificate.getPlatformConfigurationV1() != null) {
PlatformConfigurationV1 platformConfigurationV1 = certificate.getPlatformConfigurationV1();
List<ComponentIdentifier> componentIdentifiersV1 =
platformConfigurationV1.getComponentIdentifiers();
if (PciIds.DB.isReady()) {
comps = AcaPciIds.translate(comps);
componentIdentifiersV1 = AcaPciIds.translate(componentIdentifiersV1);
}
data.put("componentsIdentifier", comps);
//Component Identifier URI
data.put("componentsIdentifierURI", platformConfiguration
.getComponentIdentifierUri());
//Component Identifiers
data.put("componentsIdentifier", componentIdentifiersV1);
//Platform Properties
data.put("platformProperties", platformConfiguration.getPlatformProperties());
data.put("platformProperties", platformConfigurationV1.getPlatformProperties());
//Platform Properties URI
data.put("platformPropertiesURI", platformConfiguration.getPlatformPropertiesUri());
data.put("platformPropertiesURI", platformConfigurationV1.getPlatformPropertiesUri());
} else if (certificate.getPlatformConfigurationV2() != null) {
PlatformConfigurationV2 platformConfigurationV2 = certificate.getPlatformConfigurationV2();
//Component Identifiers
List<ComponentIdentifierV2> componentIdentifiersV2 =
platformConfigurationV2.getComponentIdentifiers();
data.put("componentsIdentifier", componentIdentifiersV2);
//Component Identifier URI
data.put("componentsIdentifierURI", platformConfigurationV2
.getComponentIdentifiersUri());
//Platform Properties
data.put("platformProperties", platformConfigurationV2.getPlatformProperties());
//Platform Properties URI
data.put("platformPropertiesURI", platformConfigurationV2.getPlatformPropertiesUri());
}
//TBB Security Assertion
data.put("tbbSecurityAssertion", certificate.getTBBSecurityAssertion());

View File

@ -36,9 +36,9 @@
<PackageReference Include="paccor.HardwareManifestPlugin" Version="2.0.5" />
<PackageReference Include="paccor.HardwareManifestPluginManager" Version="2.0.5" />
<PackageReference Include="paccor.paccor_scripts" Version="2.0.5" />
<PackageReference Include="paccor.pcie" Version="0.5.0" />
<PackageReference Include="paccor.smbios" Version="0.5.0" />
<PackageReference Include="paccor.storage" Version="0.5.0" />
<PackageReference Include="paccor.pcie" Version="0.7.6" />
<PackageReference Include="paccor.smbios" Version="0.7.6" />
<PackageReference Include="paccor.storage" Version="0.7.6" />
<PackageReference Include="Packaging.Targets" Version="0.1.226">
<PrivateAssets>all</PrivateAssets> <!-- These assets will be consumed but won't flow to the parent project -->
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@ -16,10 +16,6 @@ dependencies {
testAnnotationProcessor libs.lombok
}
test {
useJUnitPlatform()
}
//publishing {
// publications {
// maven(MavenPublication) {

View File

@ -42,10 +42,6 @@ dependencies {
testAnnotationProcessor libs.lombok
}
test {
useJUnitPlatform()
}
jar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {

View File

@ -9,6 +9,7 @@ plugins {
id 'com.github.spotbugs' version '6.0.13' apply false
id 'org.owasp.dependencycheck' version '11.1.1'
id 'java'
id 'jacoco'
}
// Global checkstyle file
@ -19,6 +20,7 @@ subprojects {
apply plugin: "java"
apply plugin: "checkstyle"
apply plugin: "org.owasp.dependencycheck"
apply plugin: "jacoco"
repositories {
flatDir { dirs "lib" }
@ -31,6 +33,20 @@ subprojects {
}
}
jacoco {
toolVersion = '0.8.12'
}
if (project.name != 'tcg_rim_tool') // run tests on every subproject except for rim_tools
test {
useJUnitPlatform() // Use JUnit platform
finalizedBy jacocoTestReport // Generate the JaCoCo report after running tests
}
jacocoTestReport {
dependsOn test // tests are required to run before generating the report
}
checkstyle {
toolVersion = '10.20.0'
configFile file("${rootDir}/config/checkstyle/checkstyle.xml")
@ -61,7 +77,6 @@ subprojects {
}
}
dependencies {
repositories {
// Use Maven Central for resolving dependencies.

View File

@ -1,45 +1,56 @@
package hirs.swid;
import hirs.utils.rim.ReferenceManifestValidator;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.test.context.event.annotation.AfterTestClass;
import org.springframework.test.context.event.annotation.BeforeTestClass;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertTrue;
//TODO tests are broken
public class TestSwidTagGateway {
private static final String ATTRIBUTES_FILE = Objects.requireNonNull(
TestSwidTagGateway.class.getClassLoader()
.getResource("rim_fields.json")).getPath();
private static final String CA_CHAIN_FILE = Objects.requireNonNull(
TestSwidTagGateway.class.getClassLoader()
.getResource("RimCertChain.pem")).getPath();
private static final String SUPPORT_RIM_FILE = Objects.requireNonNull(
TestSwidTagGateway.class.getClassLoader()
.getResource("TpmLog.bin")).getPath();
private static SwidTagGateway gateway;
private static ReferenceManifestValidator validator;
private final String DEFAULT_OUTPUT = "generated_swidTag.swidtag";
private final String BASE_USER_CERT = "generated_user_cert.swidtag";
private final String BASE_USER_CERT_EMBED = "generated_user_cert_embed.swidtag";
private final String BASE_DEFAULT_CERT = "generated_default_cert.swidtag";
private final String BASE_RFC3339_TIMESTAMP = "generated_timestamp_rfc3339.swidtag";
private final String BASE_RFC3852_TIMESTAMP = "generated_timestamp_rfc3852.swidtag";
private final String ATTRIBUTES_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("rim_fields.json").getPath();
private final String JKS_KEYSTORE_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("keystore.jks").getPath();
private final String SIGNING_CERT_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("RimSignCert.pem").getPath();
private final String PRIVATE_KEY_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("privateRimKey.pem").getPath();
private final String CA_CHAIN_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("RimCertChain.pem").getPath();
private final String SUPPORT_RIM_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("TpmLog.bin").getPath();
private final String RFC3852_COUNTERSIGNATURE_FILE = TestSwidTagGateway.class.getClassLoader()
.getResource("counterSignature.file").getPath();
private SwidTagGateway gateway;
private ReferenceManifestValidator validator;
private final String JKS_KEYSTORE_FILE = Objects.requireNonNull(TestSwidTagGateway.class.getClassLoader()
.getResource("keystore.jks")).getPath();
private final String SIGNING_CERT_FILE = Objects.requireNonNull(TestSwidTagGateway.class.getClassLoader()
.getResource("RimSignCert.pem")).getPath();
private final String PRIVATE_KEY_FILE = Objects.requireNonNull(TestSwidTagGateway.class.getClassLoader()
.getResource("privateRimKey.pem")).getPath();
private final String RFC3852_COUNTERSIGNATURE_FILE = Objects.requireNonNull(
TestSwidTagGateway.class.getClassLoader()
.getResource("counterSignature.file")).getPath();
private InputStream expectedFile;
@BeforeTestClass
public void setUp() throws Exception {
@BeforeAll
public static void setUp() {
gateway = new SwidTagGateway();
gateway.setRimEventLog(SUPPORT_RIM_FILE);
gateway.setAttributesFile(ATTRIBUTES_FILE);
@ -48,7 +59,7 @@ public class TestSwidTagGateway {
validator.setTrustStoreFile(CA_CHAIN_FILE);
}
@AfterTestClass
@AfterEach
public void tearDown() throws Exception {
if (expectedFile != null) {
expectedFile.close();
@ -87,6 +98,7 @@ public class TestSwidTagGateway {
gateway.setPemPrivateKeyFile(PRIVATE_KEY_FILE);
gateway.setEmbeddedCert(true);
gateway.generateSwidTag(DEFAULT_OUTPUT);
final String BASE_USER_CERT_EMBED = "generated_user_cert_embed.swidtag";
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_USER_CERT_EMBED);
assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
@ -103,6 +115,7 @@ public class TestSwidTagGateway {
gateway.setDefaultCredentials(true);
gateway.setJksTruststoreFile(JKS_KEYSTORE_FILE);
gateway.generateSwidTag(DEFAULT_OUTPUT);
final String BASE_DEFAULT_CERT = "generated_default_cert.swidtag";
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_DEFAULT_CERT);
assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
@ -121,6 +134,7 @@ public class TestSwidTagGateway {
gateway.setTimestampFormat("RFC3339");
gateway.setTimestampArgument("2023-01-01T00:00:00Z");
gateway.generateSwidTag(DEFAULT_OUTPUT);
final String BASE_RFC3339_TIMESTAMP = "generated_timestamp_rfc3339.swidtag";
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_RFC3339_TIMESTAMP);
assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
@ -139,6 +153,7 @@ public class TestSwidTagGateway {
gateway.setTimestampFormat("RFC3852");
gateway.setTimestampArgument(RFC3852_COUNTERSIGNATURE_FILE);
gateway.generateSwidTag(DEFAULT_OUTPUT);
final String BASE_RFC3852_TIMESTAMP = "generated_timestamp_rfc3852.swidtag";
expectedFile = TestSwidTagGateway.class.getClassLoader()
.getResourceAsStream(BASE_RFC3852_TIMESTAMP);
assertTrue(compareFileBytesToExpectedFile(DEFAULT_OUTPUT));
@ -150,10 +165,10 @@ public class TestSwidTagGateway {
* This test corresponds to the arguments:
* -v <path>
*/
public void testvalidateSwidtagFile() {
String filepath = TestSwidTagGateway.class.getClassLoader()
.getResource(BASE_USER_CERT).getPath();
@Test
public void testValidateSwidtagFile() {
final String filepath = Objects.requireNonNull(TestSwidTagGateway.class.getClassLoader()
.getResource(BASE_USER_CERT)).getPath();
System.out.println("Validating file at " + filepath);
validator.setRim(DEFAULT_OUTPUT);
assertTrue(validator.validateRim(SIGNING_CERT_FILE));
@ -178,13 +193,7 @@ public class TestSwidTagGateway {
return false;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (NullPointerException e) {
} catch (IOException | NullPointerException e) {
e.printStackTrace();
return false;
} finally {