disc: collapse decrypt_keys_for_title twin into one method
Removed the test-only unchecked wrapper and renamed decrypt_keys_for_title_checked -> decrypt_keys_for_title (one method returning (keys, title_is_clear)). Production already used the checked form; the _checked suffix had no counterpart. Callers + docs updated; two tests take .0.
This commit is contained in:
+13
-23
@@ -2572,35 +2572,25 @@ impl Disc {
|
|||||||
///
|
///
|
||||||
/// `batch_sectors` sizes the crack's batched reads (file-safe value for
|
/// `batch_sectors` sizes the crack's batched reads (file-safe value for
|
||||||
/// an ISO; `detect_max_batch_sectors` for a live drive).
|
/// an ISO; `detect_max_batch_sectors` for a live drive).
|
||||||
pub fn decrypt_keys_for_title(
|
/// Also returns the per-title encryption verdict the gate needs to AVOID A
|
||||||
&self,
|
/// FALSE ERROR on a genuinely-clear extra title.
|
||||||
idx: usize,
|
|
||||||
reader: &mut dyn SectorSource,
|
|
||||||
batch_sectors: u16,
|
|
||||||
) -> crate::decrypt::DecryptKeys {
|
|
||||||
self.decrypt_keys_for_title_checked(idx, reader, batch_sectors)
|
|
||||||
.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// [`Self::decrypt_keys_for_title`] plus the per-title encryption verdict the
|
|
||||||
/// gate needs to AVOID A FALSE ERROR on a genuinely-clear extra title.
|
|
||||||
///
|
///
|
||||||
/// On a multi-VTS CSS DVD that ALSO carries a clear, unencrypted stub title
|
/// On a multi-VTS CSS DVD that ALSO carries a clear, unencrypted stub title
|
||||||
/// (a 0.5 s menu loop, an FBI-warning nav title) living in its own VTS, the
|
/// (a 0.5 s menu loop, an FBI-warning nav title) living in its own VTS, the
|
||||||
/// re-crack over that stub's extents finds NO scrambled sector and recovers
|
/// re-crack over that stub's extents finds NO scrambled sector and recovers
|
||||||
/// no key. The bare `decrypt_keys_for_title` collapses that to
|
/// no key. Returning ONLY the keys would collapse that to
|
||||||
/// `DecryptKeys::None`, indistinguishable from "scrambled but uncrackable",
|
/// `DecryptKeys::None`, indistinguishable from "scrambled but uncrackable",
|
||||||
/// so [`Self::ensure_decryptable_keys`] (which fails whenever `css.is_some()`
|
/// so [`Self::ensure_decryptable_keys`] (which fails whenever `css.is_some()`
|
||||||
/// and the key is `None`) wrongly raised `E7023` for a title that needs no
|
/// and the key is `None`) would wrongly raise `E7023` for a title that needs
|
||||||
/// key at all. That is the false error the multi-title mux must never emit.
|
/// no key at all — the false error the multi-title mux must never emit.
|
||||||
///
|
///
|
||||||
/// This variant runs the re-crack via [`crate::css::crack_key_outcome`] and
|
/// So the re-crack runs via [`crate::css::crack_key_outcome`] and ALSO
|
||||||
/// returns `title_is_clear == true` when the title's own extents showed NO
|
/// returns `title_is_clear == true` when the title's own extents showed NO
|
||||||
/// scrambling (`CrackOutcome::Unencrypted`) — the gate then treats that title
|
/// scrambling (`CrackOutcome::Unencrypted`) — the gate then treats that title
|
||||||
/// as needing no key and passes it cleanly. A title that genuinely IS
|
/// as needing no key and passes it cleanly. A title that genuinely IS
|
||||||
/// scrambled but uncrackable returns `(None, false)` and still hard-fails.
|
/// scrambled but uncrackable returns `(None, false)` and still hard-fails.
|
||||||
/// The returned bool pairs with [`Self::ensure_title_decryptable`].
|
/// The returned bool pairs with [`Self::ensure_title_decryptable`].
|
||||||
pub fn decrypt_keys_for_title_checked(
|
pub fn decrypt_keys_for_title(
|
||||||
&self,
|
&self,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
reader: &mut dyn SectorSource,
|
reader: &mut dyn SectorSource,
|
||||||
@@ -2664,7 +2654,7 @@ impl Disc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Per-title decrypt gate that honours the `title_is_clear` verdict from
|
/// Per-title decrypt gate that honours the `title_is_clear` verdict from
|
||||||
/// [`Self::decrypt_keys_for_title_checked`].
|
/// [`Self::decrypt_keys_for_title`].
|
||||||
///
|
///
|
||||||
/// Identical to [`Self::ensure_decryptable_keys`] EXCEPT it does not raise
|
/// Identical to [`Self::ensure_decryptable_keys`] EXCEPT it does not raise
|
||||||
/// `E7023` when the chosen title proved genuinely clear (`title_is_clear`):
|
/// `E7023` when the chosen title proved genuinely clear (`title_is_clear`):
|
||||||
@@ -5134,8 +5124,8 @@ mod tests {
|
|||||||
// ── Fix 2/3: a genuinely-clear extra title on a CSS disc never E7023s ──────
|
// ── Fix 2/3: a genuinely-clear extra title on a CSS disc never E7023s ──────
|
||||||
|
|
||||||
/// Reader that serves clear (unscrambled) sectors for one extent range and
|
/// Reader that serves clear (unscrambled) sectors for one extent range and
|
||||||
/// CSS-locked errors elsewhere — enough to drive `decrypt_keys_for_title_
|
/// CSS-locked errors elsewhere — enough to drive `decrypt_keys_for_title`'s
|
||||||
/// checked`'s per-title re-crack to `Unencrypted` for a clear stub.
|
/// per-title re-crack to `Unencrypted` for a clear stub.
|
||||||
struct ClearStubReader {
|
struct ClearStubReader {
|
||||||
clear_range: (u32, u32),
|
clear_range: (u32, u32),
|
||||||
}
|
}
|
||||||
@@ -5195,7 +5185,7 @@ mod tests {
|
|||||||
let mut reader = ClearStubReader {
|
let mut reader = ClearStubReader {
|
||||||
clear_range: (0, 100_000),
|
clear_range: (0, 100_000),
|
||||||
};
|
};
|
||||||
let (keys, title_is_clear) = disc.decrypt_keys_for_title_checked(stub_idx, &mut reader, 8);
|
let (keys, title_is_clear) = disc.decrypt_keys_for_title(stub_idx, &mut reader, 8);
|
||||||
assert!(
|
assert!(
|
||||||
!keys.is_encrypted(),
|
!keys.is_encrypted(),
|
||||||
"a clear stub needs no key (got encrypted keys)"
|
"a clear stub needs no key (got encrypted keys)"
|
||||||
@@ -5617,7 +5607,7 @@ mod tests {
|
|||||||
let mut src = RecordingSource {
|
let mut src = RecordingSource {
|
||||||
reads: std::cell::RefCell::new(Vec::new()),
|
reads: std::cell::RefCell::new(Vec::new()),
|
||||||
};
|
};
|
||||||
match disc.decrypt_keys_for_title(0, &mut src, 16) {
|
match disc.decrypt_keys_for_title(0, &mut src, 16).0 {
|
||||||
crate::decrypt::DecryptKeys::Css { title_key } => {
|
crate::decrypt::DecryptKeys::Css { title_key } => {
|
||||||
assert_eq!(title_key, [0xAB; 5], "same-VTS title reuses cracked key");
|
assert_eq!(title_key, [0xAB; 5], "same-VTS title reuses cracked key");
|
||||||
}
|
}
|
||||||
@@ -5642,7 +5632,7 @@ mod tests {
|
|||||||
let mut src = RecordingSource {
|
let mut src = RecordingSource {
|
||||||
reads: std::cell::RefCell::new(Vec::new()),
|
reads: std::cell::RefCell::new(Vec::new()),
|
||||||
};
|
};
|
||||||
let keys = disc.decrypt_keys_for_title(1, &mut src, 16);
|
let keys = disc.decrypt_keys_for_title(1, &mut src, 16).0;
|
||||||
assert!(
|
assert!(
|
||||||
matches!(keys, crate::decrypt::DecryptKeys::None),
|
matches!(keys, crate::decrypt::DecryptKeys::None),
|
||||||
"a re-crack miss in a provably-different VTS must be a hard failure (None), \
|
"a re-crack miss in a provably-different VTS must be a hard failure (None), \
|
||||||
|
|||||||
+1
-3
@@ -344,9 +344,7 @@ pub fn input(url: &str, opts: &InputOptions) -> io::Result<Box<dyn crate::pes::S
|
|||||||
// unchanged (decrypt_keys_for_title short-circuits to decrypt_keys).
|
// unchanged (decrypt_keys_for_title short-circuits to decrypt_keys).
|
||||||
let (keys, title_is_clear) =
|
let (keys, title_is_clear) =
|
||||||
match crate::io::file_sector_source::FileSectorSource::open(path) {
|
match crate::io::file_sector_source::FileSectorSource::open(path) {
|
||||||
Ok(mut crack_reader) => {
|
Ok(mut crack_reader) => disc.decrypt_keys_for_title(idx, &mut crack_reader, 64),
|
||||||
disc.decrypt_keys_for_title_checked(idx, &mut crack_reader, 64)
|
|
||||||
}
|
|
||||||
Err(_) => (disc.decrypt_keys(), false),
|
Err(_) => (disc.decrypt_keys(), false),
|
||||||
};
|
};
|
||||||
// Per-title decrypt gate (parallel to the disc-wide gate above): on
|
// Per-title decrypt gate (parallel to the disc-wide gate above): on
|
||||||
|
|||||||
Reference in New Issue
Block a user