0.27.5 (step 2, Phase 1): expose AACS inputs (uk_ro, mkb) on AacsState
scan now stashes the raw Unit_Key_RO.inf + MKB bytes on AacsState (via resolve_vid_only, the disable_keydb path), so an external key-resolver can derive unit keys from a resolved VUK without re-reading the disc — the foundation for moving lookup/derivation out of libfreemkv. Additive: the keydb path is untouched, all existing constructors default the new fields empty. 584 lib tests green. Builds on the KeyOrigin rename + the Key/decrypt_with API.
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfreemkv"
|
name = "libfreemkv"
|
||||||
version = "0.27.4"
|
version = "0.27.5"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
rust-version = "1.86"
|
rust-version = "1.86"
|
||||||
license = "AGPL-3.0-only"
|
license = "AGPL-3.0-only"
|
||||||
|
|||||||
+9
-3
@@ -465,6 +465,8 @@ impl Disc {
|
|||||||
unit_keys: resolved.unit_keys,
|
unit_keys: resolved.unit_keys,
|
||||||
read_data_key,
|
read_data_key,
|
||||||
volume_id,
|
volume_id,
|
||||||
|
uk_ro: Vec::new(),
|
||||||
|
mkb: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,6 +529,8 @@ impl Disc {
|
|||||||
unit_keys: vec![(1, unit_key)],
|
unit_keys: vec![(1, unit_key)],
|
||||||
read_data_key: handshake.and_then(|h| h.read_data_key),
|
read_data_key: handshake.and_then(|h| h.read_data_key),
|
||||||
volume_id: handshake.map(|h| h.volume_id).unwrap_or([0u8; 16]),
|
volume_id: handshake.map(|h| h.volume_id).unwrap_or([0u8; 16]),
|
||||||
|
uk_ro: Vec::new(),
|
||||||
|
mkb: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,12 +567,12 @@ impl Disc {
|
|||||||
None => 1,
|
None => 1,
|
||||||
};
|
};
|
||||||
// MKB_RO is the correctly-sized copy; avoid reading the padded RW region.
|
// MKB_RO is the correctly-sized copy; avoid reading the padded RW region.
|
||||||
let mkb_ver = udf_fs
|
let mkb_bytes = udf_fs
|
||||||
.read_file(reader, "/AACS/MKB_RO.inf")
|
.read_file(reader, "/AACS/MKB_RO.inf")
|
||||||
.or_else(|_| udf_fs.read_file(reader, "/AACS/MKB_RW.inf"))
|
.or_else(|_| udf_fs.read_file(reader, "/AACS/MKB_RW.inf"))
|
||||||
.ok()
|
.ok()
|
||||||
.as_deref()
|
.unwrap_or_default();
|
||||||
.and_then(aacs::mkb_version);
|
let mkb_ver = aacs::mkb_version(&mkb_bytes);
|
||||||
|
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
target: "freemkv::disc",
|
target: "freemkv::disc",
|
||||||
@@ -590,6 +594,8 @@ impl Disc {
|
|||||||
unit_keys: vec![],
|
unit_keys: vec![],
|
||||||
read_data_key: handshake.and_then(|h| h.read_data_key),
|
read_data_key: handshake.and_then(|h| h.read_data_key),
|
||||||
volume_id: handshake.map(|h| h.volume_id).unwrap_or([0u8; 16]),
|
volume_id: handshake.map(|h| h.volume_id).unwrap_or([0u8; 16]),
|
||||||
|
uk_ro: uk_ro_data,
|
||||||
|
mkb: mkb_bytes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -893,6 +893,13 @@ pub struct AacsState {
|
|||||||
pub read_data_key: Option<[u8; 16]>,
|
pub read_data_key: Option<[u8; 16]>,
|
||||||
/// Volume ID (16 bytes) -- from SCSI handshake
|
/// Volume ID (16 bytes) -- from SCSI handshake
|
||||||
pub volume_id: [u8; 16],
|
pub volume_id: [u8; 16],
|
||||||
|
/// Raw `Unit_Key_RO.inf` bytes (encrypted unit keys + CPS map). Stashed at
|
||||||
|
/// scan so an external resolver (key-resolver) can derive the unit keys
|
||||||
|
/// from a VUK without re-reading the disc. Empty when not captured.
|
||||||
|
pub uk_ro: Vec<u8>,
|
||||||
|
/// Raw MKB bytes (`MKB_RO.inf`). Stashed at scan so an external resolver can
|
||||||
|
/// walk it (device/processing key → media key). Empty when not captured.
|
||||||
|
pub mkb: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How AACS keys were resolved. Variants are ordered root-of-trust →
|
/// How AACS keys were resolved. Variants are ordered root-of-trust →
|
||||||
@@ -1555,6 +1562,8 @@ impl Disc {
|
|||||||
unit_keys: keys,
|
unit_keys: keys,
|
||||||
read_data_key: None,
|
read_data_key: None,
|
||||||
volume_id: [0u8; 16],
|
volume_id: [0u8; 16],
|
||||||
|
uk_ro: Vec::new(),
|
||||||
|
mkb: Vec::new(),
|
||||||
});
|
});
|
||||||
// The prior resolution error (e.g. KeydbLoad) is now moot — we have
|
// The prior resolution error (e.g. KeydbLoad) is now moot — we have
|
||||||
// the decryption key. Clear it so callers don't treat the disc as
|
// the decryption key. Clear it so callers don't treat the disc as
|
||||||
@@ -2833,6 +2842,8 @@ mod tests {
|
|||||||
unit_keys,
|
unit_keys,
|
||||||
read_data_key: None,
|
read_data_key: None,
|
||||||
volume_id: [0u8; 16],
|
volume_id: [0u8; 16],
|
||||||
|
uk_ro: Vec::new(),
|
||||||
|
mkb: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user