Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/cifuzz.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Fuzz

permissions:
contents: read

on:
push:
branches: ["main", "ci/*"]
pull_request:
merge_group:

concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
fuzz:
name: Fuzz Testing
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v6
with:
persist-credentials: false

- name: Install nightly toolchain
uses: dtolnay/rust-toolchain@nightly

- name: Install cargo-fuzz
run: cargo install cargo-fuzz

- name: Build seed corpus for certificate fuzzers
run: |
mkdir -p fuzz/seed-certs
find tests -name "*.der" ! -path "*/crls/*" ! -name "*.crl.der" -exec cp {} fuzz/seed-certs/ \;

- name: Fuzz CRL parsing
working-directory: fuzz
run: |
mkdir -p corpus/crl
cargo fuzz run crl corpus/crl ../tests/crls -- -max_total_time=60

- name: Fuzz certificate parsing
working-directory: fuzz
run: |
mkdir -p corpus/cert
cargo fuzz run cert corpus/cert seed-certs -- -max_total_time=60

- name: Fuzz trust anchor extraction
working-directory: fuzz
run: |
mkdir -p corpus/anchor
cargo fuzz run anchor corpus/anchor seed-certs -- -max_total_time=60
4 changes: 4 additions & 0 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
target
artifacts
corpus
seed-certs
136 changes: 136 additions & 0 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "webpki-fuzz"
version = "0.0.1"
publish = false
edition = "2021"

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.4"
pki-types = { package = "rustls-pki-types", version = "1" }
webpki = { package = "rustls-webpki", path = "..", default-features = false, features = ["alloc"] }

# Prevent this from interfering with workspaces
[workspace]
members = ["."]

[[bin]]
name = "crl"
path = "fuzzers/crl.rs"

[[bin]]
name = "cert"
path = "fuzzers/cert.rs"

[[bin]]
name = "anchor"
path = "fuzzers/anchor.rs"
35 changes: 35 additions & 0 deletions fuzz/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Fuzz Testing

Webpki supports fuzz testing using [cargo-fuzz]. See the [cargo-fuzz setup]
instructions for requirements (requires nightly Rust).

## Fuzz Targets

- `crl` - Fuzz `BorrowedCertRevocationList::from_der()`
- `cert` - Fuzz `EndEntityCert::try_from()`
- `anchor` - Fuzz `anchor_from_trusted_cert()`

## Running Locally

```shell
$ cargo fuzz list
anchor
cert
crl

# Fuzz CRL parsing (uses tests/crls as seed corpus)
$ mkdir -p corpus/crl
$ cargo fuzz run crl corpus/crl ../tests/crls -- -max_total_time=120

# Fuzz certificate parsing (build seed corpus first)
$ mkdir -p corpus/cert seed-certs
$ find ../tests -name "*.der" ! -path "*/crls/*" ! -name "*.crl.der" -exec cp {} seed-certs/ \;
$ cargo fuzz run cert corpus/cert seed-certs -- -max_total_time=120

# Fuzz trust anchor extraction (reuses seed-certs)
$ mkdir -p corpus/anchor
$ cargo fuzz run anchor corpus/anchor seed-certs -- -max_total_time=120
```

[cargo-fuzz]: https://github.com/rust-fuzz/cargo-fuzz
[cargo-fuzz setup]: https://rust-fuzz.github.io/book/cargo-fuzz/setup.html
12 changes: 12 additions & 0 deletions fuzz/fuzzers/anchor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![no_main]

#[macro_use]
extern crate libfuzzer_sys;
extern crate webpki;

use pki_types::CertificateDer;
use webpki::anchor_from_trusted_cert;

fuzz_target!(|data: &[u8]| {
let _ = anchor_from_trusted_cert(&CertificateDer::from(data));
});
12 changes: 12 additions & 0 deletions fuzz/fuzzers/cert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![no_main]

#[macro_use]
extern crate libfuzzer_sys;
extern crate webpki;

use pki_types::CertificateDer;
use webpki::EndEntityCert;

fuzz_target!(|data: &[u8]| {
let _ = EndEntityCert::try_from(&CertificateDer::from(data));
});
11 changes: 11 additions & 0 deletions fuzz/fuzzers/crl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![no_main]

#[macro_use]
extern crate libfuzzer_sys;
extern crate webpki;

use webpki::BorrowedCertRevocationList;

fuzz_target!(|data: &[u8]| {
let _ = BorrowedCertRevocationList::from_der(data);
});