Security - Remove the unsafe Vec::set_len over recycled sector buffers — UB reachable from safe code (GHSA-j8ww-f5fg-9pmh, low). Uses Vec::resize; pooling unchanged. CI / tooling - clippy on stable with the MSRV single-sourced from Cargo.toml; cargo-deny dependency-audit gate with first-party git sources allowed (#15); audience-based comment-guard (#17). Docs - README (keydb ownership, BD-J parser count), drive-access transport/reset notes, mux timeline module-doc links.
1.8 KiB
DecryptingSectorSource
Why this decorator is the single source of truth for decrypt-on-read
Every decrypt-on-read caller (e.g. DiscStream) wraps its source in this
decorator rather than calling the cipher helpers directly. The actual cipher
code lives in crate::aacs and crate::css; the decorator just calls the
existing crate::decrypt::decrypt_sectors helper that drives both of them
in-place after each read. Centralizing the call site means callers can wire
the decorator unconditionally and keep their pipeline shape uniform
regardless of encryption state — for DecryptKeys::None discs it is simply
a pass-through, so there is no branch in caller code for "is this disc
encrypted?".
KeyFetch: why two explicit operations
KeyFetch exposes unit_keys and fmts_indexes as two separate operations
rather than one generic callback, so the "one base key vs. a whole forensic
set" contract lives in the type instead of a caller guessing at the return
length:
unit_keysresolves the base Unit Key(s) for a CPS unit from real encrypted samples drawn from it. The non-forensic path: one key per CPS unit (the pool grows by whatever it returns). Used by the mux's base / multi-CPS map resolution and by the sweep/patch recovery decorator.fmts_indexesresolves the disc's AACS 2.1 forensic index keys from an index-1 single-phase anchor batch. The source hands back the COMPLETE set (ordered index 1..N); the caller sizes the forensic map tolen()and never assumes a fixed N (32 is all we've seen, but the contract is "whatever the source returns, >= 1, is all of them").
KeyFetch is a stateless, shared pair of Arc<Fn>, so one instance is built
once and cloned cheaply (two Arc bumps) into every read path; it is
Send + Sync so it can ride the mux highway's producer thread.