Require a pack start code before descrambling a sector
css::is_scrambled reads bits 4-5 of byte 0x14 and nothing else. That is a sound test once a caller has committed to a title's VOB data, where every sector is an MPEG-2 PS pack and byte 0x14 always means what it says. descramble_region is not such a caller: it is handed arbitrary regions of a disc, so it also sees IFO, UDF and ISO 9660 sectors — raw structures where byte 0x14 is whatever that format happens to store there. Measured on a real disc: the second sector of VIDEO_TS.IFO holds 0x15 at offset 0x14 while starting 00 26 00 00, which is not a pack. The flag test read it as scrambled, descrambled it, and destroyed 1912 of its 2048 bytes. That sector carries TT_SRPT, so the title table went with it — the disc enumerated 38 titles and an image decrypted from it enumerated 10, silently, at exit 0. is_scrambled_pack already existed with the right predicate. Use it here. It costs nothing: a genuinely scrambled VOB sector always carries the pack start code, and no IFO sector does. Verified end to end — the decrypted image's `info` output is now identical to the source disc's, 38 titles both, differing only in the CSS: Encrypted line. The fixtures moved with it. Four of them built a sector by setting byte 0x14 alone, which no real scrambled sector looks like; they now build packs.
This commit is contained in:
@@ -987,6 +987,12 @@ mod tests {
|
||||
/// scramble flag.
|
||||
fn make_css_sector(title_key: &[u8; 5], seed: &[u8; 5], body_fill: u8) -> (Vec<u8>, Vec<u8>) {
|
||||
let mut sector = vec![body_fill; 2048];
|
||||
// A real scrambled DVD sector is an MPEG-2 PS pack, so it begins with
|
||||
// the pack start code. The descrambler requires it before trusting
|
||||
// byte 0x14 — without it this fixture is a sector shape that cannot
|
||||
// occur on a disc, and the test would pass while the production gate
|
||||
// rejected every sector like it.
|
||||
sector[0x00..0x04].copy_from_slice(&[0x00, 0x00, 0x01, 0xBA]);
|
||||
sector[0x14] = 0x30; // scramble flag (bits 4-5)
|
||||
sector[0x54..0x59].copy_from_slice(seed);
|
||||
let plaintext = sector.clone();
|
||||
@@ -1064,6 +1070,9 @@ mod tests {
|
||||
period: usize,
|
||||
) -> (Vec<u8>, Vec<u8>) {
|
||||
let mut plaintext = vec![0u8; 2048];
|
||||
// Real scrambled DVD sectors are MPEG-2 PS packs; the scramble policy
|
||||
// requires the pack start code as well as the flag bits.
|
||||
plaintext[0x00..0x04].copy_from_slice(&[0x00, 0x00, 0x01, 0xBA]);
|
||||
plaintext[0x14] = 0x10; // scramble flag
|
||||
// Periodic run from 0x59 (just above the seed) through 0x80 and on into
|
||||
// the encrypted region; phase anchored to offset 0 so it is continuous
|
||||
|
||||
Reference in New Issue
Block a user