CSS DVD mux: per-title key via scan-key reuse + playback-order crack
A CSS DVD whose main title was mis-detected as unencrypted (the up-front crack scanned the largest cell first and starved its budget in that cell's clear prefix) muxed scrambled sectors as plaintext at exit 0. CSS leaves the pack/PES header clear, so an un-descrambled sector muxes as a structurally-valid but corrupt PES packet with zero loss reported. decrypt_keys_for_title resolves a DVD title's CSS key two ways: - Fast path: reuse the scan's cracked key when its crack_span covers this title's VTS (no re-read; on a live drive no second bus-auth). - Crack: on a detection miss or a different VTS, crack from the title's OWN extents in a SINGLE scan in natural PLAYBACK ORDER (never largest-first). One scan = one CSS-locked early-bail, so a locked title is not re-hammered per cell against a live drive (hard rule #2); the 50k-sector budget is the same accepted bound the disc-wide scan uses. Cracked -> key; Unencrypted -> clear; ScrambledUncracked -> hard-fail. ensure_title_decryptable hard-fails an uncrackable DVD title even when detection missed, and passes a title that resolved its OWN valid key regardless of the disc-wide css_error. descramble_region is unchanged from v1.5.1 (validated-key seed). Also rename the unlocker report's DVD entry CSS -> DVD. Bump 1.5.2.
This commit is contained in:
+17
-5
@@ -409,11 +409,23 @@ pub fn input(url: &str, opts: &InputOptions) -> io::Result<Box<dyn crate::pes::S
|
||||
// avoids disturbing the mux reader below. 64 sectors is a
|
||||
// file-safe batch for an ISO. AACS / single-VTS paths are
|
||||
// unchanged (decrypt_keys_for_title short-circuits to decrypt_keys).
|
||||
let (keys, title_is_clear) =
|
||||
match crate::io::file_sector_source::FileSectorSource::open(path) {
|
||||
Ok(mut crack_reader) => disc.decrypt_keys_for_title(idx, &mut crack_reader, 64),
|
||||
Err(_) => (disc.decrypt_keys(), false),
|
||||
};
|
||||
//
|
||||
// Only a DVD needs this fresh reader (its per-title crack reads the
|
||||
// title's sectors); AACS / unencrypted resolve their keys from
|
||||
// `decrypt_keys()` with NO read, so we must not open — and fail on —
|
||||
// a probe handle for them (v1.5.1 tolerated an open blip on non-DVDs).
|
||||
// For a DVD the reader IS required, so a failed open is PROPAGATED as
|
||||
// a real, loud, retryable I/O error — never guessed into a
|
||||
// `title_is_clear` verdict: guessing `true` would mux a
|
||||
// detection-miss scrambled DVD keyless (silent garbage); guessing
|
||||
// `false` would falsely hard-fail an unencrypted DVD.
|
||||
let (keys, title_is_clear) = if disc.format == crate::disc::DiscFormat::Dvd {
|
||||
let mut crack_reader = crate::io::file_sector_source::FileSectorSource::open(path)
|
||||
.map_err(|e| -> io::Error { e.into() })?;
|
||||
disc.decrypt_keys_for_title(idx, &mut crack_reader, 64)
|
||||
} else {
|
||||
(disc.decrypt_keys(), false)
|
||||
};
|
||||
// Per-title decrypt gate (parallel to the disc-wide gate above): on
|
||||
// a multi-VTS CSS disc, the per-title re-crack may return `None` when
|
||||
// the chosen title's VTS could not be re-cracked. Muxing that would
|
||||
|
||||
Reference in New Issue
Block a user