diff --git a/.github/actions/apt-retry/action.yml b/.github/actions/apt-retry/action.yml deleted file mode 100644 index a12ff60f6..000000000 --- a/.github/actions/apt-retry/action.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: apt install with retry -description: >- - Install apt packages with bounded retries and an Acquire timeout, so a slow - or flaky mirror retries instead of cancelling the job. Used by the jobs that - cannot move into the ghcr CI image (mixed-OS matrices, version-specific - compilers, large niche package sets). Jobs whose deps are baked into - ghcr.io/wolfssl/wolftpm-ci use `container:` instead of this action. - -inputs: - packages: - description: Space-separated list of apt packages to install. - required: true - retries: - description: Number of attempts before failing. - required: false - default: "3" - retry-delay: - description: Initial delay between attempts (seconds, grows each attempt). - required: false - default: "10" - sudo: - description: Prefix apt with sudo (set "false" when already root). - required: false - default: "true" - -runs: - using: composite - steps: - - name: Install ${{ inputs.packages }} - shell: bash - run: | - set -u - export DEBIAN_FRONTEND=noninteractive - SUDO="" - if [ "${{ inputs.sudo }}" = "true" ] && command -v sudo >/dev/null 2>&1; then - SUDO="sudo" - fi - RETRIES="${{ inputs.retries }}" - DELAY="${{ inputs.retry-delay }}" - TIMEOUT="-o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30" - for i in $(seq 1 "$RETRIES"); do - if $SUDO apt-get $TIMEOUT update -q && \ - $SUDO apt-get install -y ${{ inputs.packages }}; then - exit 0 - fi - if [ "$i" -eq "$RETRIES" ]; then - echo "::error::apt-get failed after $RETRIES attempts" - exit 1 - fi - echo "::warning::apt-get failed (attempt $i/$RETRIES), retrying in ${DELAY}s..." - sleep "$DELAY" - DELAY=$((DELAY * 2)) - done diff --git a/.github/actions/setup-ibmswtpm/action.yml b/.github/actions/setup-ibmswtpm/action.yml index 72c3ea806..8a7ac4001 100644 --- a/.github/actions/setup-ibmswtpm/action.yml +++ b/.github/actions/setup-ibmswtpm/action.yml @@ -57,7 +57,7 @@ runs: VARIANT="mlo${VARIANT}" fi echo "sha=$SHA" >> "$GITHUB_OUTPUT" - echo "cache-key=ibmswtpm2-${{ runner.os }}-${SHA}-${VARIANT}-v1" >> "$GITHUB_OUTPUT" + echo "cache-key=ibmswtpm2-${{ runner.os }}-${SHA}-${VARIANT}-${WOLFTPM_CI_IMAGE:-native}-v1" >> "$GITHUB_OUTPUT" echo "ibmswtpm2 ${{ inputs.ref }} -> $SHA (variant $VARIANT)" - name: Restore ibmswtpm2 build cache diff --git a/.github/actions/setup-wolfcose/action.yml b/.github/actions/setup-wolfcose/action.yml index ca7f98e3e..4bafecdeb 100644 --- a/.github/actions/setup-wolfcose/action.yml +++ b/.github/actions/setup-wolfcose/action.yml @@ -68,7 +68,7 @@ runs: "${{ inputs.make-target }}" \ "${{ inputs.cc }}" | $HASH_CMD | cut -c1-16) echo "sha=$SHA" >> "$GITHUB_OUTPUT" - echo "cache-key=wolfcose-${{ runner.os }}-${SHA}-${CFGHASH}-v1" >> "$GITHUB_OUTPUT" + echo "cache-key=wolfcose-${{ runner.os }}-${SHA}-${CFGHASH}-${WOLFTPM_CI_IMAGE:-native}-v1" >> "$GITHUB_OUTPUT" echo "wolfCOSE ${{ inputs.ref }} -> $SHA (cfg $CFGHASH)" - name: Restore wolfCOSE build cache diff --git a/.github/actions/setup-wolfssl/action.yml b/.github/actions/setup-wolfssl/action.yml index 1098b13b7..164102f2d 100644 --- a/.github/actions/setup-wolfssl/action.yml +++ b/.github/actions/setup-wolfssl/action.yml @@ -72,7 +72,7 @@ runs: "${{ inputs.cc }}" \ "${{ inputs.prefix }}" | $HASH_CMD | cut -c1-16) echo "sha=$SHA" >> "$GITHUB_OUTPUT" - echo "cache-key=wolfssl-${{ runner.os }}-${SHA}-${CFGHASH}-v1" >> "$GITHUB_OUTPUT" + echo "cache-key=wolfssl-${{ runner.os }}-${SHA}-${CFGHASH}-${WOLFTPM_CI_IMAGE:-native}-v1" >> "$GITHUB_OUTPUT" echo "wolfSSL ${{ inputs.ref }} -> $SHA (cfg $CFGHASH)" - name: Restore wolfSSL build cache diff --git a/.github/docker/wolftpm-ci/Dockerfile b/.github/docker/wolftpm-ci/Dockerfile index 0843b758f..a330f065b 100644 --- a/.github/docker/wolftpm-ci/Dockerfile +++ b/.github/docker/wolftpm-ci/Dockerfile @@ -1,37 +1,73 @@ -# wolfTPM CI base image. -# -# Bakes the apt dependencies that wolfTPM CI jobs install on every run so -# the apt mirror is never contacted on the happy path (the source of the -# intermittent `apt-get update` timeouts). Mirrors the wolfBoot CI image -# model (ghcr.io/wolfssl/wolfboot-ci-*): jobs run inside this image via -# `container: image: ghcr.io/wolfssl/wolftpm-ci:` instead of calling -# `sudo apt-get install`. -# -# Built and pushed by .github/workflows/publish-ci-image.yml. Pin consumers -# to a version tag (e.g. :v1.0), never :latest, and bump the tag when this -# file changes. +# Shared image for every wolfTPM Linux CI workload. +# Install system dependencies here, never in workflows or composite actions. +# Publish and verify the versioned image before updating its consumers. FROM ubuntu:24.04 -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install --no-install-recommends -y \ - autoconf \ - automake \ - build-essential \ - ca-certificates \ - clang \ - clang-tools \ - cmake \ - git \ - iproute2 \ - libclang-rt-18-dev \ - libssl-dev \ - libtool \ - libtss2-tcti-mssim0 \ - openssl \ - pkg-config \ - sudo \ - tpm2-tools \ - valgrind \ - zip \ +ENV DEBIAN_FRONTEND=noninteractive \ + WOLFTPM_CI_IMAGE=v1.1 \ + CARGO_HOME=/opt/cargo \ + RUSTUP_HOME=/opt/rustup + +# Allow image builders to use another official Ubuntu mirror. +ARG UBUNTU_ARCHIVE_MIRROR=http://archive.ubuntu.com/ubuntu/ +RUN sed -i "s|http://archive.ubuntu.com/ubuntu/|${UBUNTU_ARCHIVE_MIRROR}|g" \ + /etc/apt/sources.list.d/ubuntu.sources \ + && apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=30 -o APT::Update::Error-Mode=any update \ + && apt-get -o Acquire::Retries=3 -o Acquire::http::Timeout=30 install --no-install-recommends -y \ + autoconf automake bison build-essential ca-certificates ccache \ + clang clang-14 clang-15 clang-17 clang-tools cmake curl \ + device-tree-compiler dfu-util file flex g++-11 g++-12 g++-13 \ + g++-multilib gcc-11 gcc-12 gcc-13 gcc-arm-none-eabi gcc-multilib \ + git gperf iproute2 jq libcapstone-dev libclang-18-dev \ + libclang-rt-18-dev libdw-dev libmagic1 libnewlib-arm-none-eabi \ + libsdl2-dev libssl-dev libtool libtss2-tcti-mssim0 \ + mono-mcs mono-tools-devel ninja-build nunit nunit-console openssl \ + patch pkg-config procps psmisc python3 python3-dev python3-pip \ + python3-venv rsync sudo tpm2-tools unzip util-linux valgrind wget \ + xxd xz-utils zip \ && rm -rf /var/lib/apt/lists/* + +# Keep the Python tools away from Ubuntu's externally managed interpreter. +RUN python3 -m venv /opt/ci-python \ + && /opt/ci-python/bin/pip install --no-cache-dir \ + 'semgrep==1.166.0' 'spdx-tools==0.8.*' 'codespell[toml]==2.4.3' + +# Zephyr retains its existing release and SDK. Its Python dependencies are +# isolated from the scanners and SBOM validator. +RUN git clone --depth 1 --branch v3.4.0 \ + https://github.com/zephyrproject-rtos/zephyr.git /tmp/zephyr-deps \ + && python3 -m venv /opt/zephyr-python \ + && /opt/zephyr-python/bin/pip install --no-cache-dir \ + -r /tmp/zephyr-deps/scripts/requirements-base.txt \ + -r /tmp/zephyr-deps/scripts/requirements-build-test.txt \ + && rm -rf /tmp/zephyr-deps + +RUN curl -fsSL --retry 3 \ + https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64_minimal.tar.xz \ + -o /tmp/zephyr-sdk.tar.xz \ + && tar -xJf /tmp/zephyr-sdk.tar.xz -C /opt \ + && cd /opt/zephyr-sdk-0.16.1 \ + && ./setup.sh -h -c -t x86_64-zephyr-elf \ + && rm /tmp/zephyr-sdk.tar.xz + +# rustup lives outside HOME, which GitHub overrides for container jobs. +RUN curl -fsSL --retry 3 https://sh.rustup.rs -o /tmp/rustup.sh \ + && sh /tmp/rustup.sh -y --no-modify-path --profile minimal \ + --default-toolchain stable --component clippy --component rustfmt \ + && rm /tmp/rustup.sh + +ENV PATH=/opt/ci-python/bin:/opt/cargo/bin:${PATH} + +# Include the STM32 emulator in this image rather than installing dependencies +# in a second CI container. Pin the source so image rebuilds are reproducible. +ARG M33MU_REF=7ff584479f8cb53c5016a5a429484e82b498b289 +RUN git init -q /tmp/m33mu \ + && git -C /tmp/m33mu remote add origin https://github.com/danielinux/m33mu.git \ + && git -C /tmp/m33mu fetch --depth 1 origin "$M33MU_REF" \ + && git -C /tmp/m33mu checkout -q --detach FETCH_HEAD \ + && cmake -S /tmp/m33mu -B /tmp/m33mu/build \ + -DM33MU_BUILD_TESTS=OFF -DM33MU_ENABLE_WOLFSSL=OFF \ + -DM33MU_ENABLE_RUST_PLUGINS=OFF \ + && cmake --build /tmp/m33mu/build --target m33mu -j4 \ + && cmake --install /tmp/m33mu/build \ + && rm -rf /tmp/m33mu diff --git a/.github/workflows/cmake-build.yml b/.github/workflows/cmake-build.yml index 890f947a8..730a77c08 100644 --- a/.github/workflows/cmake-build.yml +++ b/.github/workflows/cmake-build.yml @@ -18,6 +18,11 @@ jobs: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ${{ matrix.config.os }} + container: + image: ${{ startsWith(matrix.config.os, 'ubuntu-') && 'ghcr.io/wolfssl/wolftpm-ci:v1.1' || '' }} + defaults: + run: + shell: bash strategy: fail-fast: false matrix: @@ -141,14 +146,6 @@ jobs: with: submodules: true -# Install cmake (matrix includes a Windows leg, so this job stays on the host -# runner; apt is made resilient instead of moving into the Linux CI image) - - name: Install cmake - if: runner.os == 'Linux' - uses: ./.github/actions/apt-retry - with: - packages: cmake - #pull and build wolfssl # Every matrix entry builds the identical wolfSSL (only the wolfTPM options # vary), so cache the install prefix keyed on the resolved wolfSSL commit + @@ -164,7 +161,7 @@ jobs: uses: actions/cache@v4 with: path: install - key: wolfssl-cmake-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1 + key: wolfssl-cmake-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1-ci-v1.1 - name: Checkout wolfssl if: steps.wolfssl_cache.outputs.cache-hit != 'true' @@ -221,12 +218,11 @@ jobs: name: CMake static export check if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest - # cmake baked into the CI image — no apt mirror on the happy path. + defaults: + run: + shell: bash container: - image: ghcr.io/wolfssl/wolftpm-ci:v1.0 - credentials: - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 steps: - uses: actions/checkout@master with: @@ -244,7 +240,7 @@ jobs: uses: actions/cache@v4 with: path: install - key: wolfssl-cmake-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1 + key: wolfssl-cmake-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1-ci-v1.1 - name: Checkout wolfssl if: steps.wolfssl_cache.outputs.cache-hit != 'true' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 09f2d2a0a..4520b700a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -23,6 +23,11 @@ jobs: name: CodeQL (C, security) if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 40 steps: - name: Checkout wolfTPM @@ -30,13 +35,6 @@ jobs: with: submodules: true - # CodeQL's action is fiddly inside a custom container, so keep this job - # on the host runner and just make apt resilient to mirror timeouts. - - name: Install build tools - uses: ./.github/actions/apt-retry - with: - packages: autoconf automake libtool - # Full-feature wolfSSL so every wolfTPM code path is compiled and # therefore visible to CodeQL. - name: Setup wolfSSL diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 266601c06..c7cc58911 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -18,6 +18,11 @@ jobs: name: Check spelling if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 5 steps: - name: Checkout wolfTPM @@ -26,7 +31,7 @@ jobs: submodules: true - name: Run codespell - uses: codespell-project/actions-codespell@v2 - with: - skip: .git,./IDE,./certs,./m4,*.der,*.pem,*prebuilt_bindings.rs - ignore_words_list: inh,inout,keypair,nd,parm,rcv,ser,loadIn,importIn,certifyIn,bu,fo,daa,pris,hsi,fram,hart,cna + run: | + codespell --count \ + --skip '.git,./IDE,./certs,./m4,*.der,*.pem,*prebuilt_bindings.rs' \ + --ignore-words-list 'inh,inout,keypair,nd,parm,rcv,ser,loadIn,importIn,certifyIn,bu,fo,daa,pris,hsi,fram,hart,cna' diff --git a/.github/workflows/coverity-scan-fixes.yml b/.github/workflows/coverity-scan-fixes.yml index 6c88d058a..684d11a72 100644 --- a/.github/workflows/coverity-scan-fixes.yml +++ b/.github/workflows/coverity-scan-fixes.yml @@ -9,6 +9,11 @@ jobs: coverity: if: github.repository_owner == 'wolfssl' runs-on: ubuntu-22.04 + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 5 steps: - uses: actions/checkout@v4 @@ -27,7 +32,7 @@ jobs: uses: actions/cache@v4 with: path: wolfssl - key: wolfssl-coverity-fixes-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1 + key: wolfssl-coverity-fixes-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1-ci-v1.1 - uses: actions/checkout@master if: steps.wolfssl_cache.outputs.cache-hit != 'true' diff --git a/.github/workflows/freestanding-build.yml b/.github/workflows/freestanding-build.yml index d260e400e..c5d91943b 100644 --- a/.github/workflows/freestanding-build.yml +++ b/.github/workflows/freestanding-build.yml @@ -21,6 +21,11 @@ jobs: freestanding: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index aea3a3d54..343afa05a 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -43,6 +43,13 @@ jobs: fuzz: needs: select runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + # Preserve the kernel ASLR workaround used by these tests. + options: --privileged + defaults: + run: + shell: bash timeout-minutes: 30 strategy: fail-fast: false diff --git a/.github/workflows/fwtpm-test.yml b/.github/workflows/fwtpm-test.yml index 3f351aea5..90e2363e2 100644 --- a/.github/workflows/fwtpm-test.yml +++ b/.github/workflows/fwtpm-test.yml @@ -20,12 +20,19 @@ jobs: fwtpm-examples: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ${{ matrix.os }} + container: + image: ${{ startsWith(matrix.os, 'ubuntu-') && 'ghcr.io/wolfssl/wolftpm-ci:v1.1' || '' }} + options: --cap-add=SYS_ADMIN --cap-add=NET_ADMIN --cap-add=NET_RAW + defaults: + run: + shell: bash strategy: fail-fast: false matrix: include: # fwTPM with socket/swtpm transport - name: fwtpm-socket + extra_ldflags: '' os: ubuntu-latest wolftpm_config: --enable-fwtpm --enable-swtpm --enable-debug wolfssl_config: --enable-wolftpm --enable-pkcallbacks --enable-keygen @@ -285,14 +292,6 @@ jobs: with: submodules: true - # Matrix includes a macOS leg, so this job stays on the host runner; - # apt is made resilient rather than moving into the Linux CI image. - - name: Install tpm2-tools - if: ${{ !matrix.build_only && runner.os != 'macOS' }} - uses: ./.github/actions/apt-retry - with: - packages: tpm2-tools libtss2-tcti-mssim0 - - name: macOS build deps (skip tpm2-tools) if: ${{ !matrix.build_only && runner.os == 'macOS' }} run: | @@ -402,6 +401,11 @@ jobs: fwtpm-gated-runtime: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash strategy: fail-fast: false matrix: @@ -492,6 +496,11 @@ jobs: # ---------------------------------------------------------------- fwtpm-da-retry: runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash steps: - name: Checkout wolfTPM uses: actions/checkout@v4 @@ -529,19 +538,16 @@ jobs: ibmswtpm-tpm2tools: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest - # Host runner: tpm2-tools activatecredential hits a tpm2-tools OpenSSL - # credential-integrity quirk inside a container, so stay on the host - # (where it passes) and just make apt resilient to mirror timeouts. + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash steps: - uses: actions/checkout@master with: submodules: true - - name: Install tpm2-tools - uses: ./.github/actions/apt-retry - with: - packages: tpm2-tools libtss2-tcti-mssim0 - - name: Build IBM SW TPM uses: ./.github/actions/setup-ibmswtpm with: @@ -556,12 +562,10 @@ jobs: run: | ibmswtpm2/src/tpm_server & TPM_PID=$! + trap 'kill "$TPM_PID" 2>/dev/null || true; wait "$TPM_PID" 2>/dev/null || true' EXIT sleep 1 kill -0 "$TPM_PID" scripts/tpm2_tools_test.sh --no-start - rc=$? - kill "$TPM_PID" 2>/dev/null || true - exit $rc # ---------------------------------------------------------------- # fwTPM STM32 emulator test (m33mu Cortex-M33 simulator) @@ -569,7 +573,10 @@ jobs: fwtpm-emulator: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest - container: ghcr.io/wolfssl/m33mu-ci:1.9 + defaults: + run: + shell: bash + container: ghcr.io/wolfssl/wolftpm-ci:v1.1 steps: - name: Checkout wolfTPM uses: actions/checkout@v4 @@ -589,14 +596,6 @@ jobs: ref: fwtpm_stm32h5 path: wolftpm-examples - # Runs inside the m33mu CI container (already root, no sudo); just make - # apt resilient to mirror timeouts. - - name: Install build dependencies - uses: ./.github/actions/apt-retry - with: - packages: autoconf automake libtool - sudo: "false" - - name: Install STM32Cube H5 SDK run: | SDK=$HOME/STM32Cube/Repository/STM32Cube_FW_H5_V1.5.1 @@ -650,13 +649,11 @@ jobs: fwtpm-valgrind: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest - # Deps baked into the CI image — no apt mirror on the happy path. The added - # caps let the fwtpm tests create a network namespace (unshare --net). + defaults: + run: + shell: bash container: - image: ghcr.io/wolfssl/wolftpm-ci:v1.0 - credentials: - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 options: --cap-add=SYS_ADMIN --cap-add=NET_ADMIN --cap-add=NET_RAW timeout-minutes: 30 strategy: diff --git a/.github/workflows/make-test-swtpm.yml b/.github/workflows/make-test-swtpm.yml index 7525b1294..f7883a2f4 100644 --- a/.github/workflows/make-test-swtpm.yml +++ b/.github/workflows/make-test-swtpm.yml @@ -24,6 +24,11 @@ jobs: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false needs: discover runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash strategy: fail-fast: false matrix: @@ -35,7 +40,6 @@ jobs: # wolftpm_cflags: "" # test_command: "true" # needs_swtpm: true - # needs_mono: false # needs_dist: false # needs_install: false # csharp_test: false @@ -43,6 +47,7 @@ jobs: include: # Default build with simulator - name: default + wolftpm_cc: '' test_command: "make check && WOLFSSL_PATH=./wolfssl ./examples/run_examples.sh" needs_dist: true needs_install: true @@ -55,7 +60,6 @@ jobs: # CSharp wrapper tests - name: csharp test_command: "true" - needs_mono: true needs_install: true csharp_test: true @@ -417,7 +421,7 @@ jobs: uses: actions/cache@v4 with: path: wolfssl-old - key: wolfssl-old-${{ runner.os }}-v4.7.0-stable-${{ hashFiles('.github/workflows/wolfssl-v4.7.0.patch') }}-v1 + key: wolfssl-old-${{ runner.os }}-v4.7.0-stable-${{ hashFiles('.github/workflows/wolfssl-v4.7.0.patch') }}-v1-ci-v1.1 - name: Checkout old wolfSSL if: matrix.name == 'old-wolfssl' && steps.wolfssl_old_cache.outputs.cache-hit != 'true' uses: actions/checkout@master @@ -447,6 +451,10 @@ jobs: - name: Setup ibmswtpm2 if: matrix.needs_swtpm == true || matrix.needs_swtpm == null uses: ./.github/actions/setup-ibmswtpm + with: + # The shared image includes tpm2-tools, so make check also runs + # its compatibility suite. ESYS needs extra transient object slots. + max-loaded-objects: 7 - name: Generate TPM port if: matrix.needs_swtpm == true || matrix.needs_swtpm == null @@ -458,21 +466,6 @@ jobs: echo "TPM2_SWTPM_PORT=$TPM_PORT" >> $GITHUB_ENV echo "Generated TPM port: $TPM_PORT (matrix: ${{ matrix.name }})" - - name: Start TPM simulator - if: matrix.needs_swtpm == true || matrix.needs_swtpm == null - working-directory: ./ibmswtpm2/src - run: | - echo "Starting TPM simulator on port $TPM_PORT" - ./tpm_server -port $TPM_PORT & - - # Mono is a large, niche package set not baked into the CI image; just - # make apt resilient to mirror timeouts. - - name: Install mono - if: matrix.needs_mono == true - uses: ./.github/actions/apt-retry - with: - packages: mono-mcs mono-tools-devel nunit nunit-console - - name: Build wolfTPM run: | ./autogen.sh @@ -498,29 +491,42 @@ jobs: fi make -j"$(nproc)" - - name: Run tests - if: matrix.test_command && matrix.test_command != 'true' - run: ${{ matrix.test_command }} - - - name: Install - if: matrix.needs_install == true - run: | - sudo make install - sudo ldconfig - - - name: Build CSharp wrapper - if: matrix.csharp_test == true - working-directory: ./wrapper/CSharp - run: | - mcs wolfTPM.cs wolfTPM-tests.cs -r:/usr/lib/cli/nunit.framework-2.6.3/nunit.framework.dll -t:library - LD_LIBRARY_PATH=../../src/.libs/:../../wolfssl/src/.libs/ nunit-console wolfTPM.dll -run=tpm_csharp_test.WolfTPMTest.TrySelfTest - LD_LIBRARY_PATH=../../src/.libs/:../../wolfssl/src/.libs/ nunit-console wolfTPM.dll - - - name: Make dist - if: matrix.needs_dist == true + - name: Test, install, and check distribution + env: + NEEDS_SWTPM: ${{ matrix.needs_swtpm == true || matrix.needs_swtpm == null }} + TEST_COMMAND: ${{ matrix.test_command || 'true' }} + NEEDS_INSTALL: ${{ matrix.needs_install == true }} + CSHARP_TEST: ${{ matrix.csharp_test == true }} + NEEDS_DIST: ${{ matrix.needs_dist == true }} run: | - make dist - make distcheck + if [ "$NEEDS_SWTPM" = true ]; then + (cd ibmswtpm2/src && exec ./tpm_server -port "$TPM_PORT") > /tmp/ibmswtpm.log 2>&1 & + server_pid=$! + trap 'kill "$server_pid" 2>/dev/null || true; wait "$server_pid" 2>/dev/null || true' EXIT + for _ in $(seq 1 500); do + ss -tln | grep -q ":$TPM_PORT " && break + sleep 0.01 + done + kill -0 "$server_pid" + ss -tln | grep -q ":$TPM_PORT " + fi + bash -eo pipefail -c "$TEST_COMMAND" + if [ "$NEEDS_INSTALL" = true ]; then + sudo make install + sudo ldconfig + fi + if [ "$CSHARP_TEST" = true ]; then + ( + cd wrapper/CSharp + mcs wolfTPM.cs wolfTPM-tests.cs -r:/usr/lib/cli/nunit.framework-2.6.3/nunit.framework.dll -t:library + LD_LIBRARY_PATH=../../src/.libs/:../../wolfssl/src/.libs/ nunit-console wolfTPM.dll -run=tpm_csharp_test.WolfTPMTest.TrySelfTest + LD_LIBRARY_PATH=../../src/.libs/:../../wolfssl/src/.libs/ nunit-console wolfTPM.dll + ) + fi + if [ "$NEEDS_DIST" = true ]; then + make dist + make distcheck + fi - name: Upload failure logs if: failure() diff --git a/.github/workflows/multi-compiler.yml b/.github/workflows/multi-compiler.yml index 89096123b..2ffb8f38c 100644 --- a/.github/workflows/multi-compiler.yml +++ b/.github/workflows/multi-compiler.yml @@ -18,6 +18,11 @@ jobs: name: Build wolfSSL if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 5 steps: # Cache the built wolfSSL tree keyed on the resolved upstream commit so it @@ -31,7 +36,7 @@ jobs: uses: actions/cache@v4 with: path: wolfssl - key: wolfssl-multicompiler-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1 + key: wolfssl-multicompiler-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1-ci-v1.1 - name: Checkout wolfSSL if: steps.wolfssl_cache.outputs.cache-hit != 'true' @@ -69,8 +74,11 @@ jobs: name: ${{ matrix.cc }} if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest - # Headroom for an occasionally-slow apt mirror installing a version-specific - # compiler (apt-retry handles real failures; this avoids a hard cancel). + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 12 needs: build_wolfssl strategy: @@ -91,19 +99,11 @@ jobs: cxx: clang++-17 steps: - # Checkout first so the local apt-retry composite action is on disk. - name: Checkout wolfTPM uses: actions/checkout@v4 with: submodules: true - # Version-specific compilers are not baked into the CI image; keep this - # job on the host runner and just make apt resilient to mirror timeouts. - - name: Install compiler - uses: ./.github/actions/apt-retry - with: - packages: ${{ matrix.cc }} - - name: Download wolfSSL uses: actions/download-artifact@v4 with: diff --git a/.github/workflows/pqc-build-matrix.yml b/.github/workflows/pqc-build-matrix.yml index 54f701640..e9f0b411b 100644 --- a/.github/workflows/pqc-build-matrix.yml +++ b/.github/workflows/pqc-build-matrix.yml @@ -26,6 +26,11 @@ jobs: build: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 25 strategy: fail-fast: false @@ -149,6 +154,11 @@ jobs: # Build-only -- no TPM is reachable over the SPI HAL on a runner. if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 15 strategy: fail-fast: false @@ -188,6 +198,11 @@ jobs: # message (no PQC algorithm). Verifies the guard, not just that it builds. if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 15 steps: - name: Checkout wolfTPM diff --git a/.github/workflows/pqc-examples.yml b/.github/workflows/pqc-examples.yml index 946210538..2af479125 100644 --- a/.github/workflows/pqc-examples.yml +++ b/.github/workflows/pqc-examples.yml @@ -17,9 +17,12 @@ jobs: pqc-examples: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest - # Host runner: tpm2-tools make-check (activatecredential) hits a tpm2-tools - # OpenSSL credential-integrity quirk inside a container, so stay on the host - # (where it passes) and just make apt resilient to mirror timeouts. + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + options: --cap-add=SYS_ADMIN --cap-add=NET_ADMIN --cap-add=NET_RAW + defaults: + run: + shell: bash timeout-minutes: 30 steps: @@ -28,11 +31,6 @@ jobs: with: submodules: true - - name: Install tpm2-tools - uses: ./.github/actions/apt-retry - with: - packages: tpm2-tools libtss2-tcti-mssim0 - - name: Setup wolfSSL with PQC uses: ./.github/actions/setup-wolfssl with: @@ -64,71 +62,39 @@ jobs: ip link set lo up make check ' - # make check runs as root via sudo -E unshare; restore ownership of - # any files left in the workspace so later steps (running as the - # unprivileged runner) can rewrite them — otherwise stale root-owned - # blobs (e.g. eccblob.bin) silently break run_examples.sh later. - sudo chown -R "$(id -u):$(id -g)" . - # ----- Tier 2: per-example standalone runs ----- - # Each example gets its own GitHub Actions check so a regression - # surfaces with a clear failure signal — not buried inside make check. - - name: Start fwtpm_server for standalone example runs + # Standalone examples share one simulator lifetime in this step. + - name: PQC standalone examples and control tool run: | rm -f fwtpm_nv.bin ./src/fwtpm/fwtpm_server > /tmp/fwtpm_server.log 2>&1 & - echo $! > /tmp/fwtpm_server.pid + server_pid=$! + trap 'kill "$server_pid" 2>/dev/null || true; wait "$server_pid" 2>/dev/null || true' EXIT sleep 1 - kill -0 $(cat /tmp/fwtpm_server.pid) - - - name: PQC keygen — every parameter set - run: | + kill -0 "$server_pid" + echo '::group::PQC keygen: every parameter set' for ps in 44 65 87; do - ./examples/keygen/keygen mldsa_sk.bin -mldsa=$ps || exit 1 - ./examples/keygen/keygen hmldsa_sk.bin -hash_mldsa=$ps || exit 1 + ./examples/keygen/keygen mldsa_sk.bin -mldsa=$ps + ./examples/keygen/keygen hmldsa_sk.bin -hash_mldsa=$ps done for ps in 512 768 1024; do - ./examples/keygen/keygen mlkem_sk.bin -mlkem=$ps || exit 1 + ./examples/keygen/keygen mlkem_sk.bin -mlkem=$ps done - - - name: ML-DSA sign + verify example (standalone) - run: ./examples/pqc/mldsa_sign - - - name: ML-KEM encap + decap example (standalone) - run: ./examples/pqc/mlkem_encap - - - name: PQC control tool (pqc_ctrl.sh suite + argument validation) - # pqc_ctrl.sh runs the full command set and the argument-validation - # negatives, exiting non-zero on any failure. PQC_CTRL_CLEAR is left off - # so the shared Tier-2 fwtpm_server is not wiped mid-sequence; the - # destructive --clear / --pcrextend paths are exercised on hardware. - run: ./examples/pqc/pqc_ctrl.sh - - - name: Stop Tier 2 fwtpm_server (free port 2321 for E2E) - run: | - if [ -f /tmp/fwtpm_server.pid ]; then - kill "$(cat /tmp/fwtpm_server.pid)" 2>/dev/null || true - rm -f /tmp/fwtpm_server.pid - fi - # Defensive: kill any other default-port server lingering. - pkill -f "fwtpm_server$" 2>/dev/null || true - sleep 1 + echo '::endgroup::' + echo '::group::ML-DSA sign and verify' + ./examples/pqc/mldsa_sign + echo '::endgroup::' + echo '::group::ML-KEM encapsulate and decapsulate' + ./examples/pqc/mlkem_encap + echo '::endgroup::' + # Leave PQC_CTRL_CLEAR off so the shared server is not wiped. + echo '::group::PQC control tool and argument validation' + ./examples/pqc/pqc_ctrl.sh + echo '::endgroup::' - name: PQC mssim E2E (MLKEM-768 + HashMLDSA-65 round-trips) run: ./tests/pqc_mssim_e2e.sh - - name: Restart fwtpm_server for Tier 5 (run_examples.sh) - run: | - # pqc_mssim_e2e.sh started + stopped its own server; Tier 5 needs - # one again. Reuse the same default-port launch as Tier 2. - pkill -f "fwtpm_server" 2>/dev/null || true - sleep 1 - rm -f fwtpm_nv.bin - ./src/fwtpm/fwtpm_server > /tmp/fwtpm_server.log 2>&1 & - echo $! > /tmp/fwtpm_server.pid - sleep 1 - kill -0 "$(cat /tmp/fwtpm_server.pid)" - - name: Doc constants parity check run: | ./tests/check_doc_constants.sh @@ -141,13 +107,19 @@ jobs: # ----- Tier 5: full run_examples.sh sweep ----- # run_examples.sh does not start its own TPM — it expects one already - # listening. Reuse the fwtpm_server started in Tier 2. Trace each + # listening. Start a fresh server in the same step. Trace each # command (set -x) so the failing call line is in the CI log; on # failure, dump run.out (where the script redirects example stdout). - name: run_examples.sh full pass (auto-detects v1.85, runs 18-way matrix) env: WOLFSSL_PATH: ${{ github.workspace }}/wolfssl run: | + rm -f fwtpm_nv.bin + ./src/fwtpm/fwtpm_server > /tmp/fwtpm_server.log 2>&1 & + server_pid=$! + trap 'kill "$server_pid" 2>/dev/null || true; wait "$server_pid" 2>/dev/null || true' EXIT + sleep 1 + kill -0 "$server_pid" set +e bash -x ./examples/run_examples.sh rc=$? @@ -160,14 +132,6 @@ jobs: fi exit $rc - - name: Stop fwtpm_server - if: always() - run: | - if [ -f /tmp/fwtpm_server.pid ]; then - kill $(cat /tmp/fwtpm_server.pid) 2>/dev/null || true - rm -f /tmp/fwtpm_server.pid - fi - - name: Upload failure logs if: failure() uses: actions/upload-artifact@v4 @@ -190,11 +154,11 @@ jobs: contents: read if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + defaults: + run: + shell: bash container: - image: ghcr.io/wolfssl/wolftpm-ci:v1.0 - credentials: - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 timeout-minutes: 30 steps: @@ -245,16 +209,13 @@ jobs: # example client/server, so point it at the clone built above export WOLFSSL_PATH="$GITHUB_WORKSPACE/wolfssl" ./src/fwtpm/fwtpm_server >/tmp/fwtpm_tls.log 2>&1 & - echo $! > /tmp/fwtpm_tls.pid + server_pid=$! + trap 'kill "$server_pid" 2>/dev/null || true; wait "$server_pid" 2>/dev/null || true' EXIT sleep 2 ENABLE_PQC_TLS=1 ./examples/run_examples.sh rc=$? exit $rc - - name: Stop fwtpm_server (PQC TLS) - if: always() - run: kill "$(cat /tmp/fwtpm_tls.pid)" 2>/dev/null || true - - name: Upload failure logs if: failure() uses: actions/upload-artifact@v4 diff --git a/.github/workflows/publish-ci-image.yml b/.github/workflows/publish-ci-image.yml index 49fc77d38..9f4b3a071 100644 --- a/.github/workflows/publish-ci-image.yml +++ b/.github/workflows/publish-ci-image.yml @@ -1,24 +1,11 @@ name: Publish wolfTPM CI image -# Builds .github/docker/wolftpm-ci/Dockerfile and pushes it to -# ghcr.io//wolftpm-ci:. CI jobs consume this image via -# `container: image: ghcr.io/wolfssl/wolftpm-ci:v1.0` -# so they no longer run `sudo apt-get install` on every run (the source of -# mirror-timeout flakes). -# -# Mirrors the wolfBoot CI image model: pin a version tag and bump it when -# the Dockerfile changes (do not rely on :latest). The image namespace follows -# the repository owner, so a fork publishes to ghcr.io//wolftpm-ci -# and the consumer workflows pull from that same owner automatically. -# -# ONE-TIME MANUAL SETUP after the first successful push: make the -# `wolftpm-ci` package PUBLIC (Profile/Org > Packages > wolftpm-ci > package -# settings > change visibility) so fork PRs can pull it anonymously. Until -# then, only same-owner runs can pull it and forks fall back to apt. -# -# Triggers: -# - push to master/main when the Dockerfile or this workflow changes -# - workflow_dispatch for manual rebuilds +# Publish v1.1 before merging workflows that consume it. Consumers use the +# canonical ghcr.io/wolfssl/wolftpm-ci package, including on forks. A fork of +# this publisher writes to its own namespace for image testing only. +# The canonical package must be public so fork PRs can pull it anonymously. +# Dependencies are installed only when baking this image; consumers have no +# package-manager fallback. Keep versioned tags rather than using :latest. on: push: @@ -44,7 +31,7 @@ jobs: # (GITHUB_TOKEN has packages:write to the owner running it), so forks can # publish their own wolftpm-ci image for testing. runs-on: ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 60 steps: - uses: actions/checkout@v4 with: @@ -65,13 +52,51 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push image + - name: Build image uses: docker/build-push-action@v6 with: context: .github/docker/wolftpm-ci file: .github/docker/wolftpm-ci/Dockerfile - push: true + platforms: linux/amd64 + load: true + push: false # ghcr image paths must be lowercase (the wolfSSL org has a capital S). - tags: ghcr.io/${{ steps.owner.outputs.lc }}/wolftpm-ci:v1.0 - cache-from: type=registry,ref=ghcr.io/${{ steps.owner.outputs.lc }}/wolftpm-ci:v1.0 + tags: ghcr.io/${{ steps.owner.outputs.lc }}/wolftpm-ci:v1.1 + cache-from: type=registry,ref=ghcr.io/${{ steps.owner.outputs.lc }}/wolftpm-ci:v1.1 cache-to: type=inline + + - name: Check baked tools + env: + CI_IMAGE: ghcr.io/${{ steps.owner.outputs.lc }}/wolftpm-ci:v1.1 + run: | + docker run --rm "$CI_IMAGE" bash -euo pipefail -c ' + for tool in autoconf automake libtoolize cmake ninja pkg-config \ + gcc-11 gcc-12 gcc-13 g++-11 g++-12 g++-13 \ + clang-14 clang-15 clang-17 arm-none-eabi-gcc \ + rustc cargo mcs nunit-console tpm2_activatecredential \ + xxd semgrep pyspdxtools codespell m33mu; do + command -v "$tool" + done + cargo clippy --version + cargo fmt --version + python3 -c "import spdx_tools" + /opt/zephyr-python/bin/west --version + test -x /opt/zephyr-sdk-0.16.1/x86_64-zephyr-elf/bin/x86_64-zephyr-elf-gcc + ' + + - name: Push verified image + env: + CI_IMAGE: ghcr.io/${{ steps.owner.outputs.lc }}/wolftpm-ci:v1.1 + run: docker push "$CI_IMAGE" + + - name: Verify anonymous access for fork PRs + if: github.repository_owner == 'wolfssl' + env: + CI_IMAGE: ghcr.io/${{ steps.owner.outputs.lc }}/wolftpm-ci:v1.1 + run: | + registry_config=$(mktemp -d) + trap 'rm -rf "$registry_config"' EXIT + if ! docker --config "$registry_config" manifest inspect "$CI_IMAGE" > /dev/null; then + echo '::error::Make the wolftpm-ci package public in its GHCR package settings before merging the consumer workflows.' + exit 1 + fi diff --git a/.github/workflows/release-checks.yml b/.github/workflows/release-checks.yml index 81f5850ea..3b27a367f 100644 --- a/.github/workflows/release-checks.yml +++ b/.github/workflows/release-checks.yml @@ -25,6 +25,11 @@ jobs: name: Build wolfSSL if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 10 steps: # Cache the wolfSSL install prefix keyed on the resolved upstream commit @@ -38,7 +43,7 @@ jobs: uses: actions/cache@v4 with: path: /tmp/wolfssl-install - key: wolfssl-release-checks-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1 + key: wolfssl-release-checks-${{ runner.os }}-${{ steps.wolfssl_rev.outputs.sha }}-v1-ci-v1.1 - name: Checkout wolfSSL if: steps.wolfssl_cache.outputs.cache-hit != 'true' @@ -73,6 +78,11 @@ jobs: name: C++ build (CC=g++) if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 10 needs: build_wolfssl steps: @@ -113,12 +123,11 @@ jobs: name: scan-build (clang static analysis) if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest - # clang-tools (scan-build) baked into the CI image — no apt mirror. + defaults: + run: + shell: bash container: - image: ghcr.io/wolfssl/wolftpm-ci:v1.0 - credentials: - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 timeout-minutes: 15 needs: build_wolfssl steps: @@ -165,6 +174,11 @@ jobs: name: Source distribution build if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 20 steps: - name: Checkout wolfTPM diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index e41a9d13f..2fb4c3c40 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -26,6 +26,11 @@ jobs: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false needs: discover runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash strategy: fail-fast: false matrix: @@ -53,35 +58,24 @@ jobs: configure-flags: --enable-wolftpm --enable-pkcallbacks --enable-keygen cflags: -DWC_RSA_NO_PADDING - # Use the runner's preinstalled rustup rather than a mutable third-party - # action, so no external action code runs with the job token. - - name: Install Rust - run: | - rustup toolchain install stable --profile minimal --component clippy --component rustfmt - rustup default stable - - name: Generate TPM port run: | MATRIX_HASH=$(echo -n "rust-${{ matrix.name }}" | cksum | cut -d' ' -f1) TPM_PORT=$((40000 + (MATRIX_HASH % 1000) * 2)) - echo "TPM_PORT=$TPM_PORT" >> $GITHUB_ENV - echo "TPM2_SWTPM_PORT=$TPM_PORT" >> $GITHUB_ENV - echo "TPM2_SWTPM_HOST=localhost" >> $GITHUB_ENV + { + echo "TPM_PORT=$TPM_PORT" + echo "TPM2_SWTPM_PORT=$TPM_PORT" + echo "TPM2_SWTPM_HOST=localhost" + } >> "$GITHUB_ENV" # Build wolfTPM with our in-tree firmware TPM (fwtpm_server) as the # software TPM the Rust tests run against — no external simulator. - name: Build wolfTPM (swtpm + fwtpm) run: | ./autogen.sh - ./configure --enable-swtpm --enable-fwtpm --with-swtpm-port=$TPM_PORT + ./configure --enable-swtpm --enable-fwtpm --with-swtpm-port="$TPM_PORT" make -j"$(nproc)" - - name: Start fwTPM server - run: | - ./src/fwtpm/fwtpm_server --clear --port "$TPM_PORT" \ - --platform-port "$((TPM_PORT + 1))" & - sleep 1 - - name: Build Rust wrapper working-directory: ./wrapper/rust/wolftpm run: cargo build --locked --all-targets --features swtpm-tests @@ -100,7 +94,18 @@ jobs: - name: Test against fwTPM working-directory: ./wrapper/rust/wolftpm - run: cargo test --locked --features swtpm-tests -- --test-threads=1 + run: | + ../../../src/fwtpm/fwtpm_server --clear --port "$TPM_PORT" \ + --platform-port "$((TPM_PORT + 1))" > /tmp/rust-fwtpm.log 2>&1 & + server_pid=$! + trap 'kill "$server_pid" 2>/dev/null || true; wait "$server_pid" 2>/dev/null || true' EXIT + for _ in $(seq 1 500); do + ss -tln | grep -q ":$TPM_PORT " && break + sleep 0.01 + done + kill -0 "$server_pid" + ss -tln | grep -q ":$TPM_PORT " + cargo test --locked --features swtpm-tests -- --test-threads=1 - name: Docs working-directory: ./wrapper/rust/wolftpm @@ -111,6 +116,11 @@ jobs: rust-devtpm-compile: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash steps: - name: Checkout wolfTPM uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -121,10 +131,6 @@ jobs: with: ref: master configure-flags: --enable-wolftpm --enable-pkcallbacks - - name: Install Rust - run: | - rustup toolchain install stable --profile minimal - rustup default stable - name: Build wolfTPM (devtpm) run: | ./autogen.sh diff --git a/.github/workflows/sanitizer.yml b/.github/workflows/sanitizer.yml index 50b669bef..f611630bc 100644 --- a/.github/workflows/sanitizer.yml +++ b/.github/workflows/sanitizer.yml @@ -26,9 +26,13 @@ jobs: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false needs: discover runs-on: ubuntu-latest - # Host runner: tpm2-tools make-check (activatecredential) hits a tpm2-tools - # OpenSSL credential-integrity quirk inside a container, so stay on the host - # (where it passes) and just make apt resilient to mirror timeouts. + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + # Preserve the kernel ASLR workaround used by these tests. + options: --privileged + defaults: + run: + shell: bash timeout-minutes: 30 strategy: fail-fast: false @@ -106,11 +110,6 @@ jobs: with: submodules: true - - name: Install tpm2-tools - uses: ./.github/actions/apt-retry - with: - packages: tpm2-tools libtss2-tcti-mssim0 - - name: Setup wolfSSL with ${{ matrix.name }} uses: ./.github/actions/setup-wolfssl with: diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml index 6fb660453..4419da0ca 100644 --- a/.github/workflows/sbom.yml +++ b/.github/workflows/sbom.yml @@ -23,6 +23,11 @@ jobs: sbom: name: wolfTPM SBOM generation (linux) runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 20 steps: - name: Checkout wolftpm @@ -43,14 +48,6 @@ jobs: ref: ${{ github.event.inputs.wolfssl_ref || 'master' }} path: wolfssl - - name: Install build tooling and SBOM validator (pyspdxtools) - run: | - sudo apt-get update - sudo apt-get install -y build-essential autoconf automake libtool \ - pkg-config - python3 -m pip install --user 'spdx-tools==0.8.*' - echo "$HOME/.local/bin" >> "$GITHUB_PATH" - - name: Build and install wolfssl working-directory: wolfssl run: | @@ -152,6 +149,11 @@ jobs: # differs from that revision. wolfglass_drift: runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 10 steps: diff --git a/.github/workflows/seal-test.yml b/.github/workflows/seal-test.yml index 497a9bc9b..f3663fe4b 100644 --- a/.github/workflows/seal-test.yml +++ b/.github/workflows/seal-test.yml @@ -10,6 +10,8 @@ on: - 'src/tpm2_wrap.c' - 'src/fwtpm/**' - 'wolftpm/tpm2_wrap.h' + - '.github/workflows/seal-test.yml' + - '.github/docker/wolftpm-ci/**' pull_request: branches: [ '*' ] types: [opened, synchronize, reopened, ready_for_review] @@ -20,6 +22,8 @@ on: - 'src/tpm2_wrap.c' - 'src/fwtpm/**' - 'wolftpm/tpm2_wrap.h' + - '.github/workflows/seal-test.yml' + - '.github/docker/wolftpm-ci/**' repository_dispatch: types: [nightly-trigger] @@ -31,6 +35,11 @@ jobs: seal-test: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash steps: - name: Checkout wolfTPM uses: actions/checkout@v4 @@ -49,12 +58,13 @@ jobs: ./configure --enable-fwtpm --enable-swtpm --enable-debug make -j"$(nproc)" - - name: Start fwtpm_server + - name: Run seal tests against fwtpm_server run: | rm -f fwtpm_nv.bin ./src/fwtpm/fwtpm_server > /tmp/seal_fwtpm.log 2>&1 & - echo $! > /tmp/seal_fwtpm.pid - for i in $(seq 1 500); do + server_pid=$! + trap 'kill "$server_pid" 2>/dev/null || true; wait "$server_pid" 2>/dev/null || true; rm -f fwtpm_nv.bin' EXIT + for _ in $(seq 1 500); do ss -tln 2>/dev/null | grep -q ':2321 ' && break sleep 0.01 done @@ -64,17 +74,7 @@ jobs: exit 1 fi - - name: Run seal tests - run: bash examples/seal/seal_test.sh - - - name: Stop fwtpm_server - if: always() - run: | - if [ -f /tmp/seal_fwtpm.pid ]; then - kill "$(cat /tmp/seal_fwtpm.pid)" 2>/dev/null || true - rm -f /tmp/seal_fwtpm.pid - fi - rm -f fwtpm_nv.bin + bash examples/seal/seal_test.sh - name: Upload failure logs if: failure() diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 0fbf5d0c4..833d5f041 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -19,20 +19,19 @@ jobs: name: Semgrep (wolfTPM security rules) if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 10 steps: - uses: actions/checkout@v4 with: submodules: true - - uses: actions/setup-python@v5 - with: - python-version: '3.12' - # Pin Semgrep so the gate is deterministic: a future release cannot # change rule behavior or fail the build out from under a PR. - - name: Install Semgrep - run: pip install --quiet semgrep==1.166.0 # --error makes the job fail on any finding. The rules self-scope via # their `paths:` blocks, so scanning the whole tree is fine. diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index e00df5ad2..b4a12f7d5 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -27,6 +27,11 @@ jobs: empty-brace-scan: name: Empty Brace Scope Scan runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 5 steps: - name: Checkout wolfTPM @@ -39,6 +44,12 @@ jobs: smoke: runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + options: --cap-add=SYS_ADMIN --cap-add=NET_ADMIN --cap-add=NET_RAW + defaults: + run: + shell: bash timeout-minutes: 15 strategy: fail-fast: false @@ -69,12 +80,6 @@ jobs: if: matrix.config.needs_swtpm uses: ./.github/actions/setup-ibmswtpm - - name: Start TPM simulator - if: matrix.config.needs_swtpm - working-directory: ./ibmswtpm2/src - run: | - ./tpm_server & - - name: Build wolfTPM (${{ matrix.config.name }}) run: | ./autogen.sh @@ -87,7 +92,17 @@ jobs: # the full fwtpm-test.yml matrix, too heavy for a preflight signal. - name: Run unit.test (swtpm) if: matrix.config.needs_swtpm - run: ./tests/unit.test + run: | + (cd ibmswtpm2/src && exec ./tpm_server) > /tmp/ibmswtpm.log 2>&1 & + server_pid=$! + trap 'kill "$server_pid" 2>/dev/null || true; wait "$server_pid" 2>/dev/null || true' EXIT + for _ in $(seq 1 500); do + ss -tln | grep -q ':2321 ' && break + sleep 0.01 + done + kill -0 "$server_pid" + ss -tln | grep -q ':2321 ' + ./tests/unit.test - name: Run unit.test (fwtpm) if: ${{ !matrix.config.needs_swtpm }} @@ -99,7 +114,8 @@ jobs: rm -f fwtpm_nv.bin ./src/fwtpm/fwtpm_server > /tmp/fwtpm_server.log 2>&1 & SERVER_PID=$! - for i in $(seq 1 500); do + trap "kill $SERVER_PID 2>/dev/null || true" EXIT + for _ in $(seq 1 500); do ss -tln 2>/dev/null | grep -q ":2321 " && break sleep 0.01 done @@ -109,9 +125,6 @@ jobs: exit 1 fi ./tests/unit.test - rc=$? - kill "$SERVER_PID" 2>/dev/null || true - exit "$rc" ' - name: Upload failure logs diff --git a/.github/workflows/spdm-test.yml b/.github/workflows/spdm-test.yml index af52a4e4c..1bc0964ef 100644 --- a/.github/workflows/spdm-test.yml +++ b/.github/workflows/spdm-test.yml @@ -20,6 +20,8 @@ on: - 'src/tpm2.c' - 'configure.ac' - '.github/workflows/spdm-test.yml' + - '.github/docker/wolftpm-ci/**' + - 'scripts/ci/spdm.sh' - 'tests/unit_tests.c' pull_request: branches: [master] @@ -69,51 +71,38 @@ jobs: submodules: true persist-credentials: false - - name: Setup wolfSSL - uses: ./.github/actions/setup-wolfssl - with: - configure-flags: --enable-wolftpm --enable-pkcallbacks --enable-keygen --enable-aescfb - cflags: -DWC_RSA_NO_PADDING - prefix: $HOME/wolfssl-install - - - name: Build wolfTPM (${{ matrix.name }}) + - name: Resolve wolfSSL master + id: wolfssl_rev run: | - ./autogen.sh - ./configure ${{ matrix.wolftpm_config }} \ - --with-wolfcrypt=$HOME/wolfssl-install - make -j"$(nproc)" + set -euo pipefail + sha=$(git ls-remote https://github.com/wolfSSL/wolfssl.git refs/heads/master | awk 'NR==1 {print $1}') + test -n "$sha" + echo "sha=$sha" >> "$GITHUB_OUTPUT" + + - name: Cache wolfSSL build + id: wolfssl_cache + uses: actions/cache@v4 + with: + path: wolfssl + key: wolfssl-spdm-docker-v1.1-${{ steps.wolfssl_rev.outputs.sha }} - - name: Compile against the installed headers (${{ matrix.name }}) - run: | - set -e - make install DESTDIR="$PWD/inst" >/dev/null - printf '%s\n' '#include ' \ - '#include ' '#include ' \ - 'int main(void) { return 0; }' > consumer.c - cc -c consumer.c -o consumer.o -I"$PWD/inst/usr/local/include" \ - -I"$HOME/wolfssl-install/include" - printf '%s\n' '#include ' \ - 'int main(void) { return 0; }' > consumer2.c - cc -c consumer2.c -o consumer2.o -I"$PWD/inst/usr/local/include" \ - -I"$HOME/wolfssl-install/include" - - - name: Test unavailable vendor rejection (${{ matrix.name }}) - if: matrix.name == 'spdm-nuvoton' || matrix.name == 'spdm-nations' + - name: Build and test SPDM in Docker (${{ matrix.name }}) + env: + CI_IMAGE: ghcr.io/wolfssl/wolftpm-ci:v1.1 + WOLFSSL_SHA: ${{ steps.wolfssl_rev.outputs.sha }} + WOLFSSL_CACHE_HIT: ${{ steps.wolfssl_cache.outputs.cache-hit }} + SPDM_NAME: ${{ matrix.name }} + SPDM_CONFIG: ${{ matrix.wolftpm_config }} + SPDM_MODE: build run: | - set -eo pipefail - if [ "${{ matrix.name }}" = "spdm-nuvoton" ]; then - vendor=nations - expected="Nations adapter is not available in this build" - else - vendor=nuvoton - expected="Nuvoton adapter is not available in this build" - fi - if output=$(./examples/spdm/spdm_ctrl \ - "--vendor=$vendor" --status 2>&1); then - echo "Expected unavailable vendor rejection" - exit 1 - fi - grep -F "$expected" <<< "$output" + mkdir -p "$RUNNER_TEMP/spdm-logs" + docker run --rm --user "$(id -u):$(id -g)" \ + --env WOLFSSL_SHA --env WOLFSSL_CACHE_HIT --env SPDM_NAME \ + --env SPDM_CONFIG --env SPDM_MODE \ + --env GIT_CONFIG_GLOBAL=/tmp/wolftpm-ci.gitconfig \ + --mount "type=bind,source=$GITHUB_WORKSPACE,target=/workspace" \ + --mount "type=bind,source=$RUNNER_TEMP/spdm-logs,target=/tmp" \ + --workdir /workspace "$CI_IMAGE" bash scripts/ci/spdm.sh # End-to-end matrix: same protocol coverage as the old hw-spdm-test, but # against fwtpm_server instead of real silicon. fwtpm-tcg covers pinned and @@ -144,41 +133,38 @@ jobs: submodules: true persist-credentials: false - - name: Setup wolfSSL - uses: ./.github/actions/setup-wolfssl - with: - configure-flags: --enable-wolftpm --enable-pkcallbacks --enable-keygen --enable-aescfb - cflags: -DWC_RSA_NO_PADDING - prefix: $HOME/wolfssl-install - - - name: Build wolfTPM with full SPDM + vendor support - # spdm_ctrl's --connect/--status/--lock CLI dispatch is gated on - # WOLFSPDM_NUVOTON (TCG flow) and the --psk-set/--psk-clear CLI - # on WOLFSPDM_NATIONS (PSK flow). Build with both vendor flags so - # the same binary drives both fwtpm-tcg and fwtpm-psk sequences. - run: | - ./autogen.sh - ./configure --enable-fwtpm --enable-spdm \ - --enable-tcg --enable-psk \ - --enable-nuvoton --enable-nations \ - --enable-debug --enable-swtpm \ - --with-wolfcrypt=$HOME/wolfssl-install - make -j"$(nproc)" - - - name: Run wolfTPM make check (unit tests) - env: - LD_LIBRARY_PATH: ${{ format('{0}/wolfssl-install/lib', env.HOME) }} + - name: Resolve wolfSSL master + id: wolfssl_rev run: | - set -eo pipefail - make check 2>&1 | tee make-check-${{ matrix.name }}.log + set -euo pipefail + sha=$(git ls-remote https://github.com/wolfSSL/wolfssl.git refs/heads/master | awk 'NR==1 {print $1}') + test -n "$sha" + echo "sha=$sha" >> "$GITHUB_OUTPUT" + + - name: Cache wolfSSL build + id: wolfssl_cache + uses: actions/cache@v4 + with: + path: wolfssl + key: wolfssl-spdm-docker-v1.1-${{ steps.wolfssl_rev.outputs.sha }} - - name: Run spdm_test.sh ${{ matrix.mode }} + - name: Build and test SPDM in Docker (${{ matrix.name }}) env: - LD_LIBRARY_PATH: ${{ format('{0}/wolfssl-install/lib', env.HOME) }} + CI_IMAGE: ghcr.io/wolfssl/wolftpm-ci:v1.1 + WOLFSSL_SHA: ${{ steps.wolfssl_rev.outputs.sha }} + WOLFSSL_CACHE_HIT: ${{ steps.wolfssl_cache.outputs.cache-hit }} + SPDM_NAME: ${{ matrix.name }} + SPDM_CONFIG: '' + SPDM_MODE: ${{ matrix.mode }} run: | - set -eo pipefail - ./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl ${{ matrix.mode }} 2>&1 \ - | tee spdm-${{ matrix.mode }}.log + mkdir -p "$RUNNER_TEMP/spdm-logs" + docker run --rm --user "$(id -u):$(id -g)" \ + --env WOLFSSL_SHA --env WOLFSSL_CACHE_HIT --env SPDM_NAME \ + --env SPDM_CONFIG --env SPDM_MODE \ + --env GIT_CONFIG_GLOBAL=/tmp/wolftpm-ci.gitconfig \ + --mount "type=bind,source=$GITHUB_WORKSPACE,target=/workspace" \ + --mount "type=bind,source=$RUNNER_TEMP/spdm-logs,target=/tmp" \ + --workdir /workspace "$CI_IMAGE" bash scripts/ci/spdm.sh - name: Upload logs on failure if: failure() @@ -190,5 +176,5 @@ jobs: config.log test-suite.log tests/*.log - /tmp/fwtpm_spdm_test.* + ${{ runner.temp }}/spdm-logs/fwtpm_spdm_test.* retention-days: 14 diff --git a/.github/workflows/wolfhal-build.yml b/.github/workflows/wolfhal-build.yml index 6ccdfadcf..5b537abe2 100644 --- a/.github/workflows/wolfhal-build.yml +++ b/.github/workflows/wolfhal-build.yml @@ -21,6 +21,11 @@ jobs: name: Cross compile (arm-none-eabi) if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 10 steps: - name: Checkout wolfTPM @@ -28,11 +33,6 @@ jobs: with: submodules: true - - name: Install ARM toolchain - uses: ./.github/actions/apt-retry - with: - packages: gcc-arm-none-eabi - - name: Checkout wolfHAL uses: actions/checkout@v4 with: @@ -123,6 +123,11 @@ jobs: name: Autotools (--enable-wolfhal) if: github.event_name != 'pull_request' || github.event.pull_request.draft == false runs-on: ubuntu-latest + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash timeout-minutes: 15 steps: - name: Checkout wolfTPM diff --git a/.github/workflows/wolfssl-versions-pqc.yml b/.github/workflows/wolfssl-versions-pqc.yml index fd76005c9..696123894 100644 --- a/.github/workflows/wolfssl-versions-pqc.yml +++ b/.github/workflows/wolfssl-versions-pqc.yml @@ -59,12 +59,11 @@ jobs: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false needs: discover-versions runs-on: ubuntu-latest - # Build tools baked into the CI image — no apt mirror on the happy path. + defaults: + run: + shell: bash container: - image: ghcr.io/wolfssl/wolftpm-ci:v1.0 - credentials: - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 timeout-minutes: 25 strategy: fail-fast: false @@ -82,7 +81,7 @@ jobs: uses: actions/cache@v4 with: path: ~/wolfssl-install - key: ${{ matrix.cache-key }} + key: ${{ matrix.cache-key }}-ci-v1.1 - name: Build wolfSSL ${{ matrix.wolfssl-version }} if: matrix.wolfssl-version == 'master' || steps.cache-wolfssl.outputs.cache-hit != 'true' diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index 8049d6dc3..f726e8128 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -23,36 +23,24 @@ jobs: - zephyr-ref: v3.4.0 zephyr-sdk: 0.16.1 runs-on: ubuntu-22.04 + container: + image: ghcr.io/wolfssl/wolftpm-ci:v1.1 + defaults: + run: + shell: bash # This should be a safe limit for the tests to run. timeout-minutes: 25 + env: + ZEPHYR_SDK_INSTALL_DIR: /opt/zephyr-sdk-${{ matrix.config.zephyr-sdk }} + ZEPHYR_TOOLCHAIN_VARIANT: zephyr steps: - # Checkout first so the local apt-retry composite action is on disk. - name: Checkout wolfTPM uses: actions/checkout@v4 with: submodules: true - # Large, version-pinned zephyr package set — not baked into the wolfTPM - # CI image; just make apt resilient to mirror timeouts. - - name: Install dependencies - uses: ./.github/actions/apt-retry - with: - packages: >- - zip bridge-utils uml-utilities - git cmake ninja-build gperf ccache dfu-util device-tree-compiler wget - python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file - make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 - autoconf automake bison build-essential ca-certificates cargo ccache chrpath cmake - cpio device-tree-compiler dfu-util diffstat dos2unix doxygen file flex g++ gawk gcc - gcovr git git-core gnupg gperf gtk-sharp2 help2man iproute2 lcov libcairo2-dev - libglib2.0-dev libgtk2.0-0 liblocale-gettext-perl libncurses5-dev libpcap-dev - libpopt0 libsdl1.2-dev libsdl2-dev libssl-dev libtool libtool-bin locales make - net-tools openssh-client parallel pkg-config python3-dev python3-pip - python3-ply python3-setuptools python-is-python3 qemu-kvm rsync socat srecord sudo - texinfo unzip wget ovmf xz-utils - - - name: Install west - run: sudo pip install west + - name: Use the image's Zephyr environment + run: echo "/opt/zephyr-python/bin" >> "$GITHUB_PATH" - name: Init west workspace run: west init --mr ${{ matrix.config.zephyr-ref }} zephyr @@ -74,17 +62,6 @@ jobs: working-directory: zephyr run: west zephyr-export - - name: Install pip dependencies - working-directory: zephyr - run: sudo pip install -r zephyr/scripts/requirements.txt - - - name: Install zephyr SDK - run: | - wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${{ matrix.config.zephyr-sdk }}/zephyr-sdk-${{ matrix.config.zephyr-sdk }}_linux-x86_64_minimal.tar.xz - tar xf zephyr-sdk-${{ matrix.config.zephyr-sdk }}_linux-x86_64_minimal.tar.xz - cd zephyr-sdk-${{ matrix.config.zephyr-sdk }} - ./setup.sh -h -c -t x86_64-zephyr-elf - - name: Build wolftpm tests id: wolftpm_build working-directory: zephyr diff --git a/scripts/ci/spdm.sh b/scripts/ci/spdm.sh new file mode 100755 index 000000000..e0bddd0e2 --- /dev/null +++ b/scripts/ci/spdm.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# Run inside the shared CI image; Harden-Runner monitors Docker from the host. +set -euo pipefail + +: "${WOLFSSL_SHA:?}" "${SPDM_NAME:?}" "${SPDM_MODE:?}" +prefix="$PWD/wolfssl-install" +# Checkout and cache files belong to the host runner, not the container user. +git config --global --add safe.directory "$PWD" +git config --global --add safe.directory "$PWD/wolfssl" +if [ "${WOLFSSL_CACHE_HIT:-false}" != true ]; then + rm -rf wolfssl + git init -q wolfssl + git -C wolfssl remote add origin https://github.com/wolfSSL/wolfssl.git + git -C wolfssl fetch --depth 1 origin "$WOLFSSL_SHA" + git -C wolfssl checkout -q --detach FETCH_HEAD + ( + cd wolfssl + ./autogen.sh + ./configure --enable-wolftpm --enable-pkcallbacks --enable-keygen \ + --enable-aescfb CFLAGS=-DWC_RSA_NO_PADDING --prefix="$prefix" + make -j"$(nproc)" + ) +fi +make -C wolfssl install +export LD_LIBRARY_PATH="$prefix/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" + +./autogen.sh +if [ "$SPDM_MODE" = build ]; then + read -r -a config <<< "${SPDM_CONFIG:?}" +else + config=(--enable-fwtpm --enable-spdm --enable-tcg --enable-psk + --enable-nuvoton --enable-nations --enable-debug --enable-swtpm) +fi +./configure "${config[@]}" --with-wolfcrypt="$prefix" +make -j"$(nproc)" + +if [ "$SPDM_MODE" = build ]; then + make install DESTDIR="$PWD/inst" >/dev/null + printf '%s\n' '#include ' \ + '#include ' '#include ' \ + 'int main(void) { return 0; }' > consumer.c + cc -c consumer.c -o consumer.o -I"$PWD/inst/usr/local/include" \ + -I"$prefix/include" + printf '%s\n' '#include ' \ + 'int main(void) { return 0; }' > consumer2.c + cc -c consumer2.c -o consumer2.o -I"$PWD/inst/usr/local/include" \ + -I"$prefix/include" + case "$SPDM_NAME" in + spdm-nuvoton) + vendor=nations + expected='Nations adapter is not available in this build' ;; + spdm-nations) + vendor=nuvoton + expected='Nuvoton adapter is not available in this build' ;; + *) exit 0 ;; + esac + if output=$(./examples/spdm/spdm_ctrl "--vendor=$vendor" --status 2>&1); then + echo 'Expected unavailable vendor rejection' >&2 + exit 1 + fi + grep -F "$expected" <<< "$output" +else + make check 2>&1 | tee "make-check-$SPDM_NAME.log" + ./examples/spdm/spdm_test.sh ./examples/spdm/spdm_ctrl "$SPDM_MODE" \ + 2>&1 | tee "spdm-$SPDM_MODE.log" +fi