name: Security validation
on:
push:
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: security-validation-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: "1"
jobs:
assurance-ledger:
name: Atomic public API assurance ledger
runs-on: ubuntu-24.04
timeout-minutes: 120
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Verify v4 release profile and preserved certification foundations
run: |
PYTHONDONTWRITEBYTECODE=1 python3 -B assurance/release-profile/selftest.py
PYTHONDONTWRITEBYTECODE=1 python3 -B assurance/release-profile/verify.py --phase foundation
PYTHONDONTWRITEBYTECODE=1 python3 -B tools/replay-historical-advisories.py --check
PYTHONDONTWRITEBYTECODE=1 python3 -B tools/generate-release-sboms.py --self-test
PYTHONDONTWRITEBYTECODE=1 python3 -B tools/verify-repeatable-packages.py --self-test
PYTHONDONTWRITEBYTECODE=1 python3 -B tools/run-v4-lab-simulation.py --self-test
PYTHONDONTWRITEBYTECODE=1 python3 -B tools/generate-v4-assurance-report.py --self-test
PYTHONDONTWRITEBYTECODE=1 python3 -B assurance/threat-models/generate-threat-models.py --check
PYTHONDONTWRITEBYTECODE=1 python3 -B assurance/threat-models/verify-threat-models.py --self-test
PYTHONDONTWRITEBYTECODE=1 python3 -B assurance/threat-models/verify-threat-models.py --mode ci
set +e
PYTHONDONTWRITEBYTECODE=1 python3 -B assurance/threat-models/verify-threat-models.py --mode release
threat_model_release_rc=$?
set -e
test "$threat_model_release_rc" -eq 1
bash tools/release-dcrypt.sh --self-test
implementation-boundary:
name: Zero unsafe / zero FFI implementation boundary
runs-on: ubuntu-24.04
timeout-minutes: 90
env:
DCRYPT_ASSEMBLY_TOOLCHAIN: 1.93.1
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
fetch-depth: 0
- name: Install stable Rust and every supported compilation target
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.93.1
targets: aarch64-unknown-linux-gnu,wasm32-unknown-unknown,thumbv7em-none-eabihf
- name: Audit compiled and packaged implementation boundaries
run: |
python3 tools/verify-implementation-boundary.py --self-test
python3 tools/verify-remote-release-ready.py --self-test
tools/verify-implementation-boundary.sh
- name: Inspect optimized BLS secret-scalar assembly
run: tools/verify-bls-secret-assembly.sh
- name: Inspect optimized owned GHASH assembly
run: tools/verify-ghash-assembly.sh
format-and-check:
name: Format and all-target workspace check
runs-on: ubuntu-24.04
timeout-minutes: 45
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install stable Rust
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.93.1
components: rustfmt
- name: Check formatting
run: |
cargo fmt --all -- --check
cargo fmt --manifest-path verification/Cargo.toml -- --check
cargo fmt --manifest-path fuzz/Cargo.toml -- --check
cargo fmt --manifest-path migration/legacy-xchacha20poly1305/Cargo.toml -- --check
cargo fmt --manifest-path tools/bench-processor/Cargo.toml -- --check
- name: Check every workspace target with every feature
run: |
cargo check --workspace --all-targets --all-features
RUSTFLAGS="-Dunsafe-code" cargo check --locked --all-targets --all-features \
--manifest-path migration/legacy-xchacha20poly1305/Cargo.toml
cargo check --locked --all-targets --all-features \
--manifest-path tools/bench-processor/Cargo.toml
workspace-tests:
name: Workspace crate tests
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install stable Rust
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.93.1
- name: Run workspace library and integration tests
run: |
cargo test --workspace --all-features --exclude dcrypt-tests --no-fail-fast
cargo test -p dcrypt-tests --lib --all-features
cargo test --locked --all-features \
--manifest-path tools/bench-processor/Cargo.toml
acvp-and-aes-cbc-properties:
name: Complete ACVP and AES-CBC property gates
runs-on: ubuntu-24.04
timeout-minutes: 180
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install stable Rust
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.93.1
- name: Run every repository ACVP-format and regression-vector test
run: >-
cargo test --release -p dcrypt-tests --test acvp_tests
-- --test-threads=1 --nocapture
- name: Run the AES-CBC property suite
run: >-
cargo test --release -p dcrypt-tests --test property_aes_cbc
-- --test-threads=1 --nocapture
candidate-comparators:
name: Candidate comparators (not independent assurance evidence)
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
fetch-depth: 0
- name: Install stable Rust
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.93.1
- name: Install the candidate replay sandbox tools
run: |
sudo apt-get update
sudo apt-get install --yes bubblewrap strace
sudo sysctl --write kernel.unprivileged_userns_clone=1
sudo sysctl --write kernel.apparmor_restrict_unprivileged_userns=0
test "$(sysctl --values kernel.unprivileged_userns_clone)" = 1
test "$(sysctl --values kernel.apparmor_restrict_unprivileged_userns)" = 0
- name: Acquire the exact verification closure without using Cargo's cache
run: >-
python3 -B verification/oracle-provisioning/acquire.py
--manifest verification/oracle-provisioning/manifest.json
--lock verification/Cargo.lock
--output "$RUNNER_TEMP/oracle-archives"
- name: Materialize and replay six exact candidate comparator targets offline
run: |
python3 -B verification/oracle-provisioning/selftest.py \
--manifest verification/oracle-provisioning/manifest.json \
--lock verification/Cargo.lock \
--archives "$RUNNER_TEMP/oracle-archives" \
--repo-root "$GITHUB_WORKSPACE"
python3 -B verification/oracle-provisioning/materialize.py \
--manifest verification/oracle-provisioning/manifest.json \
--lock verification/Cargo.lock \
--archives "$RUNNER_TEMP/oracle-archives" \
--output "$RUNNER_TEMP/oracle-materialized" \
--repo-root "$GITHUB_WORKSPACE"
python3 -B verification/oracle-provisioning/replay.py \
--manifest verification/oracle-provisioning/manifest.json \
--lock verification/Cargo.lock \
--archives "$RUNNER_TEMP/oracle-archives" \
--materialized "$RUNNER_TEMP/oracle-materialized" \
--toolchain-root "$HOME/.rustup/toolchains/1.93.1-x86_64-unknown-linux-gnu"
- name: Test the isolated decrypt-only legacy migration tool
run: |
cargo fetch --locked --manifest-path migration/legacy-xchacha20poly1305/Cargo.toml
cargo test --release --locked --offline --manifest-path \
migration/legacy-xchacha20poly1305/Cargo.toml
statistical-timing:
name: Repository statistical timing regressions (not dudect or ctgrind)
runs-on: ubuntu-24.04
timeout-minutes: 60
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install stable Rust
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.93.1
- name: Run the in-repository statistical timing suite serially
env:
VERBOSE: "1"
run: >-
cargo test -p dcrypt-tests --test constant_time_tests
-- --test-threads=1 --nocapture
dependency-policy:
name: RustSec and workspace dependency policy
runs-on: ubuntu-24.04
timeout-minutes: 45
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install stable Rust
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: 1.93.1
- name: Install pinned security tools
run: |
cargo install --root "$RUNNER_TEMP/security-tools" cargo-audit --version 0.22.2 --locked
cargo install --root "$RUNNER_TEMP/security-tools" cargo-deny --version 0.20.2 --locked
echo "$RUNNER_TEMP/security-tools/bin" >> "$GITHUB_PATH"
- name: Audit resolved dependencies against RustSec
run: |
cargo audit
while IFS=$'\t' read -r category workspace; do
test -n "$category" && test -n "$workspace"
cargo audit --file "$workspace/Cargo.lock"
done < <(python3 tools/verify-implementation-boundary.py --list-classified-workspaces)
cargo audit --file tools/bench-processor/Cargo.lock
- name: Enforce advisories, licenses, bans, and sources for all workspace roots
run: |
cargo deny --workspace --all-features check
while IFS=$'\t' read -r category workspace; do
test -n "$category" && test -n "$workspace"
cargo deny --manifest-path "$workspace/Cargo.toml" \
--all-features check
done < <(python3 tools/verify-implementation-boundary.py --list-classified-workspaces)
cargo deny --manifest-path tools/bench-processor/Cargo.toml \
--all-features check
miri:
name: Miri (${{ matrix.crate }})
runs-on: ubuntu-24.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
crate: [dcrypt-api, dcrypt-common]
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install nightly Rust with Miri
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: nightly-2026-08-07
components: miri
- name: Prepare Miri's sysroot
run: cargo miri setup
- name: Run the public memory-handling tests under Miri
run: cargo miri test -p ${{ matrix.crate }} --lib --all-features
miri-crypto-boundaries:
name: Miri cryptographic parser and key boundaries
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install nightly Rust with Miri
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: nightly-2026-08-07
components: miri
- name: Prepare Miri's sysroot
run: cargo miri setup
- name: Exercise ML-KEM canonical decoder boundaries
run: cargo miri test -p dcrypt-kem --lib --all-features miri_
- name: Exercise ML-DSA expanded-key coherence checks
run: >-
cargo miri test -p dcrypt-sign --lib --all-features
expanded_key_decoder_rejects_malformed_or_incoherent_components
- name: Exercise Ed25519 strict verification
run: >-
cargo miri test -p dcrypt-sign --lib --all-features
rejects_identity_public_key_and_universal_forgery
- name: Exercise the high-level BLS secret owner
run: >-
cargo miri test -p dcrypt-sign --lib --all-features
secret_key_is_canonical_nonzero_and_debug_redacted
- name: Exercise both protected BLS scalar bridges
run: >-
cargo miri test -p dcrypt-algorithms --lib --all-features
secret_big_endian_bridge_matches_g1_and_g2_scalar_multiplication
- name: Exercise RFC 9380 and BLS subgroup rejection
run: |
cargo miri test -p dcrypt-algorithms --lib --all-features rfc9380_g1_random_oracle_vectors
cargo miri test -p dcrypt-algorithms --lib --all-features rfc9380_g2_random_oracle_vectors
cargo miri test -p dcrypt-algorithms --lib --all-features checked_decoders_reject_on_curve_non_subgroup_point
bounded-fuzz:
name: Deterministic semantic fuzz smoke
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install nightly Rust
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772
with:
toolchain: nightly-2026-08-08
- name: Install pinned cargo-fuzz
run: cargo +nightly-2026-08-08 install cargo-fuzz --version =0.13.2 --locked --force
- name: Provision the exact locked fuzz dependency closure
run: cargo +nightly-2026-08-08 fetch --locked --manifest-path fuzz/Cargo.toml
- name: Build and run every classified fuzz target through the sealed private-corpus runner
run: |
classified_workspaces=$(mktemp)
trap 'rm -f -- "$classified_workspaces"' EXIT
python3 -B tools/verify-implementation-boundary.py \
--list-classified-workspaces >"$classified_workspaces"
test -s "$classified_workspaces"
test "$(awk -F '\t' '$1 == "fuzz" { print }' "$classified_workspaces")" = \
$'fuzz\tfuzz'
python3 -B assurance/fuzzing/run-fuzz-smoke.py --mode pr --execute