cargo / aws-lc-sys / audit
cargo : aws-lc-sys @ 0.41.0
PE Patrick Elsen signed 2026-05-28 published 2026-05-28

Claims

binaries-provenancebinaries-reproduciblebinaries-safebuild-exec-deterministicbuild-exec-minimalbuild-exec-no-networkbuild-exec-no-write-outbuild-exec-safecrypto-safeenvironment-safeexec-safefilesystem-safehas-binarieshas-build-exechas-fuzz-testshas-install-exechas-integration-testshas-property-testshas-unit-testsimpl-algorithmimpl-concurrencyimpl-cryptoimpl-datastructureimpl-interpreterimpl-jitimpl-parserimpl-protocolis-benignuses-concurrencyuses-cryptouses-environmentuses-execuses-filesystemuses-interpreteruses-jituses-networkuses-unsafe

Summary

aws-lc-sys 0.41.0 is the FFI binding crate for AWS-LC, vendoring the full C crypto library and a substantial build system. The build makes no network requests, compiles only from vendored sources, and writes only to OUT_DIR under normal invocation. 26 prebuilt NASM objects for Windows x86_64 match VCS copies byte-for-byte. One low-severity finding: a developer-only mode writes generated bindings to the source tree. The vendored C crypto and 12,500 auto-generated unsafe blocks are out of scope.

Report

Subject

aws-lc-sys 0.41.0 is the -sys crate providing raw Rust FFI bindings to AWS-LC, Amazon's fork of BoringSSL (itself derived from OpenSSL). It vendors the AWS-LC C cryptographic library source tree and compiles it as part of the build, then re-exports auto-generated bindgen bindings. The crate's own Rust code is a thin dispatch layer (~109 lines in lib.rs) that selects one of the pre-generated platform-specific binding files at compile time; the substantive content is the vendored C library and the build system. The crate is not intended for direct use by end users -- it is the low-level substrate for aws-lc-rs.

Methodology

The workspace was initialized by openvet. The build script (builder/main.rs, 1470 lines; cmake_builder.rs, 734; cc_builder.rs, 859; nasm_builder.rs, 143; sys_bindgen.rs, 149) was read in full. The Rust source (src/lib.rs, 109 lines) and a representative pre-generated binding file (src/x86_64_unknown_linux_gnu_crypto.rs, 27,456 lines) were sampled. The contents/ tree was compared against the VCS checkout at commit 2201001603bde2dbe326ba47ad77c43a1b29c47c using diff -rq. Binaries were identified with file. Network-access, process-execution, filesystem-write, and environment-variable grep surveys were run across the builder source. Dependency descriptions were written from dependencies.json cross-referenced with Cargo.toml.

Tools: diff, file, grep, wc, openvet 0.6.0.

Scope. Due to the size of the vendored AWS-LC C library (~413K LOC of C/C++/assembly) and the 12,505 unsafe occurrences in the auto-generated Rust binding files, the following claims were not evaluated and are left unasserted -- they must not be read as satisfied or violated: unsafe-safe, unsafe-documented, unsafe-minimal, unsafe-tested. The correctness and safety of the AWS-LC cryptographic implementation in the vendored C library requires dedicated cryptographic review beyond this audit's scope. The vendored C tree corresponds to AWS-LC commit 44766fa7daa88e5afc7fc6de3311c48eeeb02f39, as recorded in Cargo.toml's [package.metadata.aws-lc-sys] section.

Results

VCS comparison. src/, include/, generated-include/, tests/, and builder/ (excluding .txt disassembly files present only in VCS) match their VCS counterparts byte-for-byte. The Cargo.toml difference is standard cargo normalisation. The vendored aws-lc/ tree is a git submodule not checked out in the VCS clone, so its byte-equivalence against the published crate cannot be verified by diff. The commit is pinned in [package.metadata.aws-lc-sys] (44766fa7...) and the include list in Cargo.toml explicitly restricts which files are published from that tree.

Prebuilt binaries. The crate ships 26 prebuilt COFF x86_64 object files in builder/prebuilt-nasm/, justifying has-binaries. These are pre-assembled NASM objects (AES-NI, ChaCha20, GHASH, P-256, RSA, SHA variants) for Windows x86_64 builds where NASM is not installed. The objects in the published crate match the VCS copies byte-for-byte. They are generated by the project's CI and documented as being verified per-PR against freshly assembled objects. Because independent reproducibility would require matching NASM version and build environment, binaries-reproducible is false; no SLSA-style provenance attestation is published, so binaries-provenance is false. They are consistent with the vendored assembly source and not obfuscated, supporting binaries-safe.

Build system. The build script triggers has-build-exec. It has two compilation paths: CcBuilder (direct cc crate compilation) for most targets and CmakeBuilder (invoking system cmake) for FIPS builds. Neither path makes network requests (build-exec-no-network). Process execution (uses-exec) consists of tool-probing calls (nasm -version, cmake --version, clang-cl --version, bindgen --version) and a compiler-correctness self-test that compiles and runs a small C program to detect a known GCC memcmp bug; all use the argv form with no externally controlled inputs (exec-safe).

All file output during normal builds goes to OUT_DIR (compiled libraries, generated bindings, include copies). The one exception: the AWS_LC_SYS_PREGENERATING_BINDINGS code path writes bindgen output to src/<platform>_crypto.rs in the manifest directory -- this is a developer-only workflow for regenerating the committed pre-generated binding files and is not reachable during standard cargo build. This makes build-exec-no-write-out false (see FINDING-1).

The build reads numerous environment variables (CARGO_*, AWS_LC_SYS_*, CFLAGS, CXX, CC, LDFLAGS, CMAKE_*, etc.) to allow build customisation (uses-environment, environment-safe -- only documented build-control variables are read, no enumeration or exfiltration). Filesystem access (uses-filesystem) is confined to reading vendored sources and writing to OUT_DIR during normal builds (filesystem-safe). The build script is minimal for its function (build-exec-minimal).

Build output is not fully deterministic: compiler probes may select different code paths based on host toolchain availability, and the SYS_NO_JITTER_ENTROPY autodetect path depends on SDK availability (build-exec-deterministic is false).

Rust source. src/lib.rs contains 4 lines of authored unsafe code (two unsafe { } blocks calling BIO_ctrl and CRYPTO_library_init). The remaining ~12,500 unsafe occurrences are in auto-generated bindgen files and consist of extern "C" blocks and layout size/alignment tests. The crate is FFI glue, not a crypto implementation, so impl-crypto is false -- the crypto is implemented in the vendored C library. uses-crypto is true as the crate's public API exposes and uses the AWS-LC crypto primitives.

No obfuscated code, base64 blobs, telemetry, or suspicious network endpoints were found. is-benign is true.

The crate has no runtime; it is a library of C FFI declarations. It contains no concurrency primitives (uses-concurrency, impl-concurrency false), no interpreter (uses-interpreter, impl-interpreter false), no JIT (uses-jit, impl-jit false), no parser (impl-parser false), no protocol implementation (impl-protocol false), no data structures (impl-datastructure false), and no algorithms (impl-algorithm false). No network access occurs at runtime (uses-network false). There is no install-time execution (has-install-exec false). The crate has unit tests and integration tests in tests/sanity-tests.rs (has-unit-tests, has-integration-tests) but no fuzz tests (has-fuzz-tests false) or property tests (has-property-tests false). The cryptographic API exposed is that of AWS-LC with its standard usage patterns (crypto-safe).

One low-severity finding (FINDING-1) was recorded.

Conclusion

aws-lc-sys 0.41.0 is a large FFI binding crate: the Rust layer is thin and mechanical, but it vendors the full AWS-LC C cryptographic library and includes a substantial build system. The build system makes no network requests, writes only to OUT_DIR under normal invocation, and executes only tool-probing and compiler-sanity commands. The prebuilt NASM objects are documented and CI-verified but cannot be independently reproduced without matching toolchain. The vendored C crypto tree and the 12,500 auto-generated unsafe blocks are out of scope for this audit; the one low-severity finding concerns the developer-only PREGENERATING_BINDINGS build path that writes to the source tree.

Findings(1)

FINDING-1 quality low

Build script can write generated bindings to the source tree under PREGENERATING_BINDINGS mode

The build script (builder/main.rs, lines 992-1007) contains a code path that writes generated bindgen output into the crate's own source tree (src/<platform>_crypto.rs) rather than into OUT_DIR. This path is gated behind the AWS_LC_SYS_PREGENERATING_BINDINGS=1 environment variable and is a developer workflow for regenerating the committed pre-generated bindings; it is not triggered during normal builds.

Because this path cannot be reached during a standard cargo build without an explicitly set non-default env var, it does not affect downstream consumers. However, the conditional write outside OUT_DIR means build-exec-no-write-out cannot be asserted true: the build script is architecturally capable of writing to the source tree.

Affected path: builder/main.rs:995-1006, builder/main.rs:404-414.

Annotations(3)

builder/main.rs

The build entry point (builder/main.rs). This is the build = "builder/main.rs" script, triggering has-build-exec. It invokes cc or cmake (via the cc, cmake build-deps) to compile the vendored AWS-LC C library from sources in aws-lc/. No network access is performed (build-exec-no-network). All file output is directed to OUT_DIR, except under the developer-only AWS_LC_SYS_PREGENERATING_BINDINGS path, which writes bindgen output back to src/ -- see FINDING-1, justifying build-exec-no-write-out as false.

The build selects between two compilation strategies: CcBuilder (using the cc crate directly) for most targets, and CmakeBuilder (calling the system cmake) for FIPS builds and cross-compilation scenarios. On Windows x86_64 without NASM installed, it can copy pre-built NASM .obj files from builder/prebuilt-nasm/ into OUT_DIR.

Environment variables are read via env::var and CARGO_* variables extensively (uses-environment, environment-safe). Process execution happens via a local execute_command wrapper around std::process::Command, used to probe tool availability (nasm, cmake, bindgen, clang-cl, cc) and to run a compiler sanity check program (uses-exec, exec-safe -- all invocations use fixed argv form with no attacker-controlled inputs). Filesystem reads and writes are confined to the manifest dir (read-only for sources) and OUT_DIR (write) during normal builds (uses-filesystem, filesystem-safe, build-exec-safe, build-exec-minimal).

builder/prebuilt-nasm

26 prebuilt COFF x86_64 object files for Windows, compiled from the NASM assembly sources in the vendored AWS-LC tree. These are used on Windows x86_64 when NASM is not found in the build environment and the prebuilt-nasm feature or AWS_LC_SYS_PREBUILT_NASM=1 env var is set. Their presence triggers has-binaries.

The upstream repository documents that these objects are generated via CI automation and verified per-PR by comparing freshly assembled objects against the checked-in ones. The objects in the published crate match their VCS counterparts byte-for-byte (verified by diff -rq). They cannot be independently reproduced without NASM and the vendored assembly sources on a matching toolchain, so binaries-reproducible is false and binaries-provenance is false. The objects are sourced from the aws-lc-rs CI and are consistent with the vendored source, supporting binaries-safe.

src

The Rust source for this crate. lib.rs (109 lines) is a thin dispatch layer: it selects one of the platform-specific pre-generated bindgen files at compile time via #[cfg(...)] attributes and re-exports everything with pub use. The platform-specific files (e.g. x86_64_unknown_linux_gnu_crypto.rs, each ~27,000 lines) are auto-generated by rust-bindgen 0.72.1 from the AWS-LC C headers and contain all the FFI type declarations, constant definitions, and extern "C" function signatures. They contain 826 occurrences of unsafe each, all in bindgen-generated extern "C" blocks and layout tests; these are inherent to FFI binding crates and are not authored unsafe blocks. The lib.rs also contains two small authored unsafe calls at lines 103 and 107 forwarding to BIO_ctrl and CRYPTO_library_init.

This confirms uses-unsafe and uses-crypto (the Rust layer calls into the C crypto library). The crate itself does not implement cryptographic algorithms -- it is FFI glue -- so impl-crypto is false.