Subject
curve25519-dalek 4.1.3 is a pure-Rust, no_std implementation of group operations on Curve25519 and ristretto255, the elliptic-curve arithmetic underlying X25519 key agreement and Ed25519 signatures. It exposes four public types: Scalar (arithmetic mod the group order l = 2^252 + 27742317777372353535851937790883648493), EdwardsPoint and MontgomeryPoint (the two forms of Curve25519), and RistrettoPoint (the prime-order ristretto255 group), along with constants and traits modules. It is a foundational dependency of ed25519-dalek, x25519-dalek, and much of the Rust cryptography ecosystem. Source is roughly 32K LOC across src/.
Methodology
Tooling: openvet 0.6.0, ripgrep/grep, diff, the Read tool, and manual review. I read Cargo.toml, Cargo.toml.orig, build.rs, src/lib.rs, src/backend/mod.rs, src/backend/vector/packed_simd.rs, and the SIMD field-arithmetic files in full, and surveyed field.rs, scalar.rs, edwards.rs, ristretto.rs, and montgomery.rs. I enumerated every unsafe site (37 total) and read each one.
The shipped crate omits a vcs/ checkout, so byte-for-byte diff against a VCS tree was not possible. Integrity was instead checked against the workspace manifest.json, which records a per-file blake2b-256 digest for all 60 packaged files plus a whole-archive digest; .cargo_vcs_info.json records upstream git sha1 5312a0311ec40df95be953eacfa8a11b9a34bc54. The contents/ tree matches the manifest.
Scope. This is a cryptographic crate whose field-arithmetic correctness and side-channel resistance need dedicated cryptographic review. The following claims were not evaluated and are left unasserted; they must not be read as either satisfied or violated: crypto-impl-safe, crypto-impl-correct. The crate documents constant-time intent (per-operation # Preconditions/# Postconditions bounds on limb sizes, pervasive use of subtle) but this audit does not independently vouch for constant-time behavior or field-arithmetic correctness. This audit verifies supply-chain integrity, the capability surface, build-time execution, the unsafe surface, and dependency enumeration.
Results
The contents/ tree matches every per-file digest in manifest.json; no source-file divergence or unexpected binaries were found, and the crate contains no obfuscated payloads, base64 blobs, network endpoints, or telemetry, so it is benign (is-benign). The crate ships only Rust source plus docs, a Makefile, a vendor/ristretto.sage reference script, and tests/build_tests.sh, with no precompiled assets (has-binaries).
The capability surface is narrow. No std::net, std::fs, std::process, or std::env appears in src/, giving uses-network, uses-filesystem, uses-exec, and uses-environment; the only environment reads are in build.rs at build time. There is no threading or shared-mutable state (uses-concurrency), and no JIT or interpreter (uses-jit, uses-interpreter). The crate implements elliptic-curve group arithmetic and uses subtle constant-time primitives throughout, supporting uses-crypto, impl-crypto, and impl-algorithm. It is not a parser, protocol, interpreter, JIT, data structure, or concurrency-primitive implementation, giving impl-parser, impl-protocol, impl-interpreter, impl-jit, impl-datastructure, and impl-concurrency.
The build.rs script gives has-build-exec; cargo has no install-time hook, so has-install-exec. The script reads CARGO_CFG_TARGET_ARCH, CARGO_CFG_TARGET_POINTER_WIDTH, and the CURVE25519_DALEK_BACKEND/CURVE25519_DALEK_BITS overrides, validates them against fixed allow-lists, calls rustc_version, and emits only cargo:rustc-cfg directives selecting the field-arithmetic backend (simd for x86_64 plus 64-bit pointer width, else serial) and limb width. It opens no files, makes no network calls, and spawns no processes, supporting build-exec-safe, build-exec-no-network, build-exec-no-write-out, build-exec-deterministic, and build-exec-minimal.
The crate confines unsafe to the SIMD backend; 37 unsafe sites exist (uses-unsafe). 34 are in src/backend/vector/ (packed_simd.rs 17, ifma/field.rs 9, avx2/field.rs 8): AVX2 and AVX512-IFMA intrinsics plus two core::mem::transmute array-to-SIMD reinterprets in const constructors, each with a // SAFETY: comment. The module header documents the single shared invariant: the code assumes the host CPU supports at least AVX2, an invariant the dispatcher in src/backend/mod.rs upholds by gating each entry point behind a cpufeatures CPUID token (cpuid_avx2, cpuid_avx512ifma) and falling back to the serial backend when absent. The three remaining sites are a 'static reference reinterpret for the precomputed basepoint table at constants.rs:88 and two core::ptr::read_volatile(&local) optimization barriers in the serial scalar code; all read through valid live references. No raw-pointer dereferences or get_unchecked appear. Each site was reviewed and its invariant holds, supporting unsafe-safe, unsafe-documented, and unsafe-minimal.
Testing is inline: 86 #[test] functions across 21 #[cfg(test)] modules covering field, scalar, Edwards, Montgomery, and Ristretto operations, including encode/decode round-trips and known-answer vectors (has-unit-tests; crypto-impl-tested given the known-answer coverage). There are no Rust integration tests (the tests/ directory holds only build_tests.sh), property tests, or fuzz harness in the published crate, giving has-integration-tests, has-property-tests, and has-fuzz-tests.
Conclusion
The audit found no security or safety issues and produced zero findings. curve25519-dalek 4.1.3 implements Curve25519 / ristretto255 group arithmetic with a compile-time-selected backend; build.rs emits cfg directives choosing the serial 32/64-bit path or an x86_64 simd path. The unsafe surface is 37 sites, concentrated in the AVX2/AVX512-IFMA vector backend as intrinsic calls and two const transmutes, with the AVX2-presence invariant enforced at run time via cpufeatures CPUID dispatch; each site was reviewed and its invariant holds. The crate performs no network, filesystem, process, or environment I/O at run time. Field-arithmetic correctness and constant-time / side-channel resistance were scoped out and left unasserted; the crate documents constant-time intent and uses subtle, but this audit does not independently vouch for those properties.