Subject
rustls 0.23.40 is a pure-Rust TLS library implementing TLS 1.2 and TLS 1.3
for both client and server roles. It does no network or file I/O itself: callers
feed it ciphertext via read_tls/write_tls and exchange plaintext through
ClientConnection and ServerConnection. Cryptographic primitives (AEAD,
hashing, HMAC, signatures, key exchange) are delegated to a pluggable
CryptoProvider; the default is aws-lc-rs, with ring available behind a
feature, and certificate-path validation is delegated to rustls-webpki. The
crate is #![no_std] (with alloc) and spans roughly 47.6K lines across 107
source files: the handshake state machines (client/, server/), the record
layer, message parsing/encoding (msgs/), and the key schedule (tls13/).
Methodology
Tools: openvet 0.6.0, ripgrep, diff, git, cargo, sha/wc. I compared the
published crate (contents/) against the pinned VCS checkout (vcs/, git
b44c09fb "Prepare 0.23.40") with diff -rq. I surveyed the capability
surface (network, filesystem, environment, process, concurrency, RNG, unsafe,
FFI) by grep, and read in full the record layer (record_layer.rs), the
deframer entry path and the wire Codec/Reader primitives (msgs/codec.rs,
msgs/deframer/), the fragmenter, the message types, build.rs,
key_log_file.rs, the downgrade-sentinel logic, and the crate root. I checked
RUSTSEC for advisories against this version.
Scope (Methodology Scope note). Per the runbook's scoped-audit guidance for
security-critical TLS, the cryptographic primitives are out of scope: they live
in the provider crate (aws-lc-rs / ring), audited separately, and certificate
validation lives in rustls-webpki, audited separately. The following claims
were therefore not evaluated and are left unasserted; they must not be read as
either satisfied or violated: crypto-impl-safe, crypto-impl-correct,
crypto-impl-tested. The crate orchestrates crypto but does not implement the
math, so uses-crypto is asserted while impl-crypto is false. The deepest
protocol/parser quality sub-claims (protocol-impl-correct, protocol-impl-safe,
protocol-impl-tested, parser-impl-correct, parser-impl-safe, parser-impl-tested)
were not exhaustively evaluated across all four state machines and the full
extension grammar, and are left unasserted.
Results
The published src/ tree is byte-identical to VCS; the openvet vcs check
section confirms this. The only differences are Cargo.toml (cargo
normalisation), a single CRLF line ending in .clippy.toml (content-identical),
and tests/ plus src/testdata/, which are absent from the package because the
manifest sets exclude = ["src/testdata", "tests/**"]. No source file diverges
and nothing exists only in the package. No obfuscation, telemetry, or hidden
network endpoints were found. Justifies is-benign.
The crate root carries #![forbid(unsafe_code)]; a tree-wide search finds no
unsafe block, unsafe fn, or extern "C" (the matches are doc-comment prose).
Justifies uses-unsafe. The library performs no network or file I/O of its own,
so uses-network holds; the sole filesystem and environment access is the
opt-in SSLKEYLOGFILE key-log facility in key_log_file.rs, which reads one
documented variable and appends to the named path, justifying uses-filesystem,
uses-environment, filesystem-safe, and environment-safe. The crate spawns no
processes and contains no scripting, bytecode, or machine-code generation, so
uses-exec, uses-interpreter, uses-jit, impl-interpreter, and impl-jit are
all false. Internal state is shared through Arc, Mutex, and RwLock
(session caches, config), so uses-concurrency, concurrency-safe, and
concurrency-documented hold while the crate consumes rather than defines
synchronisation primitives, leaving impl-concurrency false. Randomness and all
AEAD/sign operations are obtained from the provider, so uses-crypto and
crypto-safe hold for the orchestration layer; the crate implements none of the
primitives, so impl-crypto is false. It implements no general-purpose algorithm
or data structure as its product, so impl-algorithm and impl-datastructure are
false.
rustls implements the TLS protocol itself: the record layer, handshake state
machines, alert handling, and session resumption. Justifies impl-protocol and
impl-parser. The record layer bounds sequence numbers with
SEQ_SOFT_LIMIT/SEQ_HARD_LIMIT and refuses to encrypt past the hard limit,
so nonce/sequence reuse cannot occur by wraparound; trial decryption for
rejected 0-RTT is bounded by a byte budget. The deframer rejects oversized
records (PeerSentOversizedRecord, MAX_FRAGMENT_LEN = 16384), records
interleaving non-handshake content inside a fragmented handshake, and malformed
headers, latching a fatal error so the connection cannot silently recover.
Downgrade protection is present: the TLS 1.2 path writes DOWNGRADE_SENTINEL
into the server random and the client detects it when it had offered TLS 1.3.
The wire Reader is bounds-checked and read_bytes rejects trailing data.
build.rs is conditional on the read_buf feature and, only on nightly, prints
cargo:rustc-cfg=read_buf; it opens no sockets, reads no files, and writes
nothing outside cargo's stdout protocol. Justifies has-build-exec,
build-exec-safe, build-exec-no-network, build-exec-deterministic,
build-exec-minimal, and build-exec-no-write-out. The package ships no compiled
binaries, so has-binaries is false, and there is no install-time execution, so
has-install-exec is false. The crate has extensive #[test] unit tests in
src/ and (in VCS, excluded from the package) integration tests, BoGo shim
tests, and six libFuzzer fuzz/ targets, but no proptest/quickcheck
property tests. Justifies has-unit-tests, has-integration-tests,
has-fuzz-tests, and has-property-tests.
The thirteen declared dependencies are enumerated with descriptions. RUSTSEC
advisories against rustls (RUSTSEC-2024-0336 complete_io infinite loop,
RUSTSEC-2024-0399 Acceptor::accept panic) were fixed in releases well before
0.23.40; no advisory affects this version.
No findings were recorded.
Conclusion
rustls 0.23.40 is a #![no_std], #![forbid(unsafe_code)] TLS 1.2/1.3
implementation with no unsafe, no FFI, and no network or file I/O beyond the
opt-in SSLKEYLOGFILE key-log path. Its published source is byte-identical to
the tagged VCS checkout. The record layer enforces 64-bit sequence limits to
prevent nonce reuse, the deframer bounds record sizes and rejects handshake
interleaving, and the TLS 1.2 path carries the RFC 8446 downgrade sentinel. The
cryptographic primitives and certificate-path validation are delegated to the
provider and rustls-webpki and were not evaluated here. No security, safety,
or correctness findings were recorded.