chore: scrub non-shippable references from tests/comments
This commit is contained in:
+20
-20
@@ -448,9 +448,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_disc_entry() {
|
||||
let line = r#"***REMOVED*** = DUNE_PART_TWO (Dune: Part Two) | D | 2024-04-02 | M | ***REMOVED*** | I | ***REMOVED*** | V | ***REMOVED*** | U | 1-***REMOVED*** ; MKBv77"#;
|
||||
let line = r#"0x000102030405060708090A0B0C0D0E0F10111213 = SAMPLE_FILM (Sample Film) | D | 2024-01-01 | M | 0x000102030405060708090A0B0C0D0E0F | I | 0x101112131415161718191A1B1C1D1E1F | V | 0x202122232425262728292A2B2C2D2E2F | U | 1-0x303132333435363738393A3B3C3D3E3F ; MKBv77"#;
|
||||
let entry = KeyDb::parse_disc_entry(line).unwrap();
|
||||
assert_eq!(entry.title, "Dune: Part Two");
|
||||
assert_eq!(entry.title, "Sample Film");
|
||||
assert!(entry.media_key.is_some());
|
||||
assert!(entry.vuk.is_some());
|
||||
assert_eq!(entry.unit_keys.len(), 1);
|
||||
@@ -459,7 +459,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_device_key() {
|
||||
let line = "| DK | DEVICE_KEY ***REMOVED*** | DEVICE_NODE 0x0800 | KEY_UV 0x00000400 | KEY_U_MASK_SHIFT 0x17 ; MKBv01-MKBv48";
|
||||
let line = "| DK | DEVICE_KEY 0x000102030405060708090A0B0C0D0E0F | DEVICE_NODE 0x0800 | KEY_UV 0x00000400 | KEY_U_MASK_SHIFT 0x17 ; MKBv01-MKBv48";
|
||||
let dk = KeyDb::parse_device_key(line).unwrap();
|
||||
assert_eq!(dk.node, 0x0800);
|
||||
assert_eq!(dk.u_mask_shift, 0x17);
|
||||
@@ -472,9 +472,9 @@ mod tests {
|
||||
// candidate: it lands in `processing_keys` and the brute walker
|
||||
// handles it.
|
||||
let cfg = r#"
|
||||
| DK | DEVICE_KEY ***REMOVED*** ; orphan from HKD\x02 corpus
|
||||
| DK | DEVICE_KEY ***REMOVED*** | DEVICE_NODE 0x0800 | KEY_UV 0x00000400 | KEY_U_MASK_SHIFT 0x17 ; positioned MKBv01-MKBv48
|
||||
| PK | ***REMOVED*** ; legacy PK row still works
|
||||
| DK | DEVICE_KEY 0xDEADBEEF0001020304050607080900AA ; orphan, no position fields
|
||||
| DK | DEVICE_KEY 0x000102030405060708090A0B0C0D0E0F | DEVICE_NODE 0x0800 | KEY_UV 0x00000400 | KEY_U_MASK_SHIFT 0x17 ; positioned MKBv01-MKBv48
|
||||
| PK | 0xCAFEBABE0001020304050607080900BB ; legacy PK row still works
|
||||
"#;
|
||||
let db = KeyDb::parse(cfg);
|
||||
assert_eq!(
|
||||
@@ -488,29 +488,29 @@ mod tests {
|
||||
2,
|
||||
"orphan DK row + legacy PK row both belong in processing_keys"
|
||||
);
|
||||
assert_eq!(db.processing_keys[0][..4], [0xC5, 0xDD, 0xB5, 0xB4]);
|
||||
assert_eq!(db.processing_keys[1][..4], [0x76, 0xDD, 0xD7, 0x09]);
|
||||
assert_eq!(db.processing_keys[0][..4], [0xDE, 0xAD, 0xBE, 0xEF]);
|
||||
assert_eq!(db.processing_keys[1][..4], [0xCA, 0xFE, 0xBA, 0xBE]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_orphan_dk_rejects_lines_with_position_fields() {
|
||||
// The parser must NOT pick up a positioned DK row as an orphan
|
||||
// (that would double-count). parse_orphan_dk explicitly checks.
|
||||
let positioned = "| DK | DEVICE_KEY ***REMOVED*** | DEVICE_NODE 0x0800 | KEY_UV 0x00000400 | KEY_U_MASK_SHIFT 0x17";
|
||||
let positioned = "| DK | DEVICE_KEY 0x000102030405060708090A0B0C0D0E0F | DEVICE_NODE 0x0800 | KEY_UV 0x00000400 | KEY_U_MASK_SHIFT 0x17";
|
||||
assert!(
|
||||
KeyDb::parse_orphan_dk(positioned).is_none(),
|
||||
"positioned DK must not match orphan parser"
|
||||
);
|
||||
let orphan = "| DK | DEVICE_KEY ***REMOVED***";
|
||||
let orphan = "| DK | DEVICE_KEY 0xDEADBEEF0001020304050607080900AA";
|
||||
let key = KeyDb::parse_orphan_dk(orphan).expect("orphan should parse");
|
||||
assert_eq!(key[..4], [0xC5, 0xDD, 0xB5, 0xB4]);
|
||||
assert_eq!(key[..4], [0xDE, 0xAD, 0xBE, 0xEF]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_host_cert() {
|
||||
let line = "| HC | HOST_PRIV_KEY ***REMOVED*** | HOST_CERT ***REMOVED*** ; Revoked";
|
||||
let line = "| HC | HOST_PRIV_KEY 0xDEADBEEF000102030405060708090A0B0C0D0E0F | HOST_CERT 0x000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B ; Revoked";
|
||||
let hc = KeyDb::parse_host_cert(line).unwrap();
|
||||
assert_eq!(hc.private_key[0], 0x90);
|
||||
assert_eq!(hc.private_key[0], 0xDE);
|
||||
assert_eq!(hc.certificate.len(), 92);
|
||||
}
|
||||
|
||||
@@ -528,15 +528,15 @@ mod tests {
|
||||
assert!(!db.host_certs.is_empty());
|
||||
assert!(db.disc_entries.len() > 170000);
|
||||
|
||||
// Look up Dune: Part Two
|
||||
let dune = db
|
||||
// Look up any disc entry carrying a full key set.
|
||||
let entry = db
|
||||
.disc_entries
|
||||
.values()
|
||||
.find(|e| e.title.contains("Dune: Part Two") && e.vuk.is_some())
|
||||
.expect("Dune: Part Two not found");
|
||||
assert!(dune.media_key.is_some());
|
||||
assert!(dune.vuk.is_some());
|
||||
assert!(!dune.unit_keys.is_empty());
|
||||
.find(|e| e.vuk.is_some() && e.media_key.is_some() && !e.unit_keys.is_empty())
|
||||
.expect("no disc entry with a full key set");
|
||||
assert!(entry.media_key.is_some());
|
||||
assert!(entry.vuk.is_some());
|
||||
assert!(!entry.unit_keys.is_empty());
|
||||
|
||||
eprintln!(
|
||||
"Parsed {} disc entries, {} DK, {} PK",
|
||||
|
||||
+33
-36
@@ -1163,8 +1163,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_vuk_derivation() {
|
||||
// Civil War UHD: known MK, VID, VUK from KEYDB
|
||||
// MK = 15665F98..., VID (disc_id) = from entry, VUK = F96D7908...
|
||||
// Pick any UHD entry with a known MK, VID, and VUK from KEYDB.
|
||||
// VUK = AES-DEC(MK, VID) XOR VID
|
||||
let path = match keydb_path() {
|
||||
Some(p) => p,
|
||||
@@ -1237,7 +1236,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_decrypt_real_unit() {
|
||||
// Try decrypting a real encrypted aligned unit from Civil War UHD
|
||||
// Try decrypting a real encrypted aligned unit from a UHD sample.
|
||||
// This disc is AACS 2.0 (BEE) so unit key alone won't work —
|
||||
// we need bus decryption first. But this verifies the pipeline.
|
||||
let unit_path = std::path::Path::new("/tmp/encrypted_unit.bin");
|
||||
@@ -1258,20 +1257,17 @@ mod tests {
|
||||
};
|
||||
let db = KeyDb::load(&kp).unwrap();
|
||||
|
||||
// Civil War UHD entries
|
||||
let civil_war_entries: Vec<&DiscEntry> = db
|
||||
// Candidate entries: any UHD entry that carries unit keys.
|
||||
let candidate_entries: Vec<&DiscEntry> = db
|
||||
.disc_entries
|
||||
.values()
|
||||
.filter(|e| e.title.contains("CIVIL WAR") && !e.unit_keys.is_empty())
|
||||
.filter(|e| !e.unit_keys.is_empty())
|
||||
.collect();
|
||||
|
||||
eprintln!(
|
||||
"Found {} Civil War entries with unit keys",
|
||||
civil_war_entries.len()
|
||||
);
|
||||
eprintln!("Found {} entries with unit keys", candidate_entries.len());
|
||||
|
||||
// Try each entry's unit keys
|
||||
for entry in &civil_war_entries {
|
||||
for entry in &candidate_entries {
|
||||
let keys: Vec<[u8; 16]> = entry.unit_keys.iter().map(|(_, k)| *k).collect();
|
||||
let mut unit = original.clone();
|
||||
|
||||
@@ -1304,10 +1300,11 @@ mod tests {
|
||||
#[test]
|
||||
fn test_disc_hash_hex() {
|
||||
let hash = [
|
||||
***REMOVED***,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
|
||||
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
|
||||
];
|
||||
let hex = disc_hash_hex(&hash);
|
||||
assert_eq!(hex, "***REMOVED***");
|
||||
assert_eq!(hex, "0x000102030405060708090A0B0C0D0E0F10111213");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1601,29 +1598,26 @@ mod tests {
|
||||
assert_eq!(selected, only07, "fallback returns the 0x07 body");
|
||||
}
|
||||
|
||||
/// Locate a captured MKB research sample, if the private research tree
|
||||
/// is checked out alongside the crate. Returns `None` (skip) otherwise.
|
||||
/// Locate a captured MKB sample under the optional `MKB_SAMPLE_DIR`.
|
||||
/// Returns `None` (skip) when the directory or file is absent.
|
||||
fn mkb_sample(rel: &str) -> Option<std::path::PathBuf> {
|
||||
let p = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.parent()? // freemkv/
|
||||
.join("(internal)/research/aacs/mkb-samples")
|
||||
.join(rel);
|
||||
let dir = std::env::var("MKB_SAMPLE_DIR").ok()?;
|
||||
let p = std::path::Path::new(&dir).join(rel);
|
||||
if p.exists() { Some(p) } else { None }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn real_aacs2_samples_select_large_0x05_not_small_0x07() {
|
||||
// Real in-drive AACS 2.x UHD MKBs (Wicked / Civil War / MOVIE)
|
||||
// carry BOTH a small 0x07 Explicit-Subset-Difference record (96
|
||||
// 16-byte entries) AND the large 0x05 Media Key Data / cvalue table
|
||||
// (181270 entries, 1:1 with the 0x04 index). The production selector
|
||||
// must return the LARGE 0x05 body, not the small 0x07 one. This is
|
||||
// the exact regression #259 found. Skips when the research tree is
|
||||
// absent.
|
||||
// Real in-drive AACS 2.x UHD MKBs carry BOTH a small 0x07
|
||||
// Explicit-Subset-Difference record (96 16-byte entries) AND the
|
||||
// large 0x05 Media Key Data / cvalue table (181270 entries, 1:1
|
||||
// with the 0x04 index). The production selector must return the
|
||||
// LARGE 0x05 body, not the small 0x07 one. This is the exact
|
||||
// regression #259 found. Skips when no sample dir is present.
|
||||
let samples = [
|
||||
"wicked/MKB_RO.inf",
|
||||
"civilwar-uhd/MKB_RO.inf",
|
||||
"movie-uhd-2.1/MKB_RO.inf",
|
||||
"sample-a/MKB_RO.inf",
|
||||
"sample-b/MKB_RO.inf",
|
||||
"sample-c/MKB_RO.inf",
|
||||
];
|
||||
let mut checked = 0;
|
||||
for rel in samples {
|
||||
@@ -1707,29 +1701,32 @@ mod tests {
|
||||
};
|
||||
let db = KeyDb::load(&path).unwrap();
|
||||
|
||||
// Find V for Vendetta BD — has VUK and unit keys
|
||||
// hash: ***REMOVED***
|
||||
let entry = db.find_disc("***REMOVED***");
|
||||
// Find any BD entry that carries a VUK and unit keys, then exercise
|
||||
// the lookup-by-hash + VUK-derivation chain against it.
|
||||
let entry = db
|
||||
.disc_entries
|
||||
.values()
|
||||
.find(|e| e.vuk.is_some() && !e.unit_keys.is_empty() && e.disc_id.is_some());
|
||||
if entry.is_none() {
|
||||
return;
|
||||
}
|
||||
let entry = entry.unwrap();
|
||||
let vuk = entry.vuk.unwrap();
|
||||
let vid = entry.disc_id.unwrap();
|
||||
let hash_hex = format!("0x{}", entry.disc_hash.trim_start_matches("0x"));
|
||||
|
||||
// We need the actual Unit_Key_RO.inf from the disc to compute disc hash.
|
||||
// Since we don't have it, we can at least test that the KEYDB lookup
|
||||
// works with a known hash.
|
||||
let hash_hex = "***REMOVED***";
|
||||
let found = db.find_disc(hash_hex);
|
||||
let found = db.find_disc(&hash_hex);
|
||||
assert!(found.is_some());
|
||||
assert_eq!(found.unwrap().vuk, Some(vuk));
|
||||
|
||||
// Verify VUK derivation if we have MK + VID
|
||||
if let Some(mk) = entry.media_key {
|
||||
let derived = derive_vuk(&mk, &vid);
|
||||
assert_eq!(derived, vuk, "VUK derivation mismatch for V for Vendetta");
|
||||
eprintln!("V for Vendetta VUK derivation verified");
|
||||
assert_eq!(derived, vuk, "VUK derivation mismatch");
|
||||
eprintln!("VUK derivation verified");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user