aacs: remove the mod.rs facade — module paths are the public API
Delete the pub-use re-export facade; consumers now import from the owning module (aacs::content::decrypt_unit, aacs::mkb::MkbType, aacs::derive::derive_vuk, aacs::boil::mk_from_dk, aacs::resolve::resolve_keys_v2, ...). Internal callers repointed accordingly. Path-only change; logic hash identical (95fb9924); 2210 tests green.
This commit is contained in:
@@ -10,8 +10,8 @@
|
||||
pub fn collect_host_certs(
|
||||
opts: &crate::disc::ScanOptions,
|
||||
mkb: Option<u32>,
|
||||
) -> Vec<crate::aacs::HostCert> {
|
||||
let mut host_certs: Vec<crate::aacs::HostCert> = Vec::new();
|
||||
) -> Vec<crate::aacs::types::HostCert> {
|
||||
let mut host_certs: Vec<crate::aacs::types::HostCert> = Vec::new();
|
||||
if let Some(c) = &opts.credentials {
|
||||
host_certs.extend(c.host_certs.iter().cloned());
|
||||
}
|
||||
|
||||
+15
-57
@@ -50,62 +50,21 @@ pub const PATH_MKB_RW: &str = "/AACS/MKB_RW.inf";
|
||||
pub const PATH_CONTENT_CERT: &str = "/AACS/Content000.cer";
|
||||
pub const PATH_CONTENT_CERT_ALT: &str = "/AACS/Content001.cer";
|
||||
|
||||
// Boil-down derivation primitives (thin newtypes + wrappers over the crypto).
|
||||
pub use boil::{
|
||||
KeyCandidate, MediaKey, ProcessingKey, ResolvedChain, UnitKey, Vid, Vuk, mk_from_dk,
|
||||
mk_from_pk, resolve_candidate, uk_from_vuk, vuk_from_mk,
|
||||
};
|
||||
// Structured, English-free resolution trace.
|
||||
pub use trace::{KeyNode, KeyOutcome, KeyStep, ResolutionTrace, UnlockOutcome, UnlockStep};
|
||||
|
||||
// Explicit re-exports — only items needed by external consumers and sibling crate modules.
|
||||
// AES primitives (aes_ecb_encrypt, aes_ecb_decrypt, aes_cbc_decrypt) are pub(crate) in decrypt.rs.
|
||||
pub use content::{
|
||||
ALIGNED_UNIT_LEN, ALIGNED_UNIT_SECTORS, UnitKeyResult, aacs_unit_encrypted,
|
||||
aacs_unit_needs_decrypt, aacs_unit_still_ciphertext, decrypt_bus, decrypt_unit,
|
||||
decrypt_unit_checked, decrypt_unit_full, decrypt_unit_try_keys, fill_null_ts_unit,
|
||||
is_unit_aligned, ts_packet_total, ts_sync_count, ts_sync_destroyed, unit_is_clean_ps,
|
||||
unit_is_clean_ts, unit_key_validates,
|
||||
};
|
||||
// `probe` is a reproduction-harness helper (see keys.rs), not part of the
|
||||
// documented 1.0 surface; keep it reachable but off the rendered docs so we
|
||||
// don't commit semver stability to test primitives.
|
||||
#[doc(hidden)]
|
||||
pub use derive::probe;
|
||||
pub use derive::{decrypt_unit_key, derive_vuk};
|
||||
pub use derive::{
|
||||
derive_media_key_and_pk_from_dk, derive_media_key_from_dk, derive_media_key_from_pk,
|
||||
recover_dk_position,
|
||||
};
|
||||
pub use inf::{
|
||||
ContentCert, UnitKeyFile, disc_hash, disc_hash_hex, parse_content_cert, parse_unit_key_ro,
|
||||
read_mkb_from_drive,
|
||||
};
|
||||
pub use mkb::{
|
||||
AACS_MAJOR_BD, AACS_MAJOR_UHD, AacsVersion, MKB_20_CATEGORY_C, MKB_21_CATEGORY_C,
|
||||
MKB_TYPE_3_RECORDABLE, MKB_TYPE_4_PRERECORDED, MKB_TYPE_10_CLASS_II, MkbRecord, MkbType,
|
||||
mkb_content_len, mkb_is_uhd, mkb_type, mkb_type_raw, mkb_version, trim_mkb, walk_mkb,
|
||||
};
|
||||
pub use provider::KeyProvider;
|
||||
pub use resolve::{
|
||||
ResolveContext, ResolveFailure, ResolvedKeys, resolve_keys_v1, resolve_keys_v2,
|
||||
resolve_keys_v21, resolve_keys_with_reason,
|
||||
};
|
||||
pub use types::{DeviceKey, DiscEntry, HostCert};
|
||||
pub use variant::{
|
||||
KEY_CORRECTION_DATA_PLACEHOLDER, MediaKeyVariantError, ProcessingKeyMatch,
|
||||
derive_media_key_variant, is_variant_mkb, variant_nonce, walk_processing_key,
|
||||
};
|
||||
// No facade: the module structure IS the public API. Consumers import from the
|
||||
// owning module directly — e.g. `aacs::content::decrypt_unit`, `aacs::mkb::MkbType`,
|
||||
// `aacs::derive::derive_vuk`, `aacs::boil::mk_from_dk`, `aacs::resolve::resolve_keys_v2`.
|
||||
// The `derive::probe` reproduction harness stays reachable via its module path.
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
//! Re-export surface guards. The module's public API is the set of
|
||||
//! `pub use` items above. A regression that drops or renames an export
|
||||
//! (the class of bug that shipped in 0.31.0 by silently changing a
|
||||
//! surface) breaks compilation of these references, so they act as a
|
||||
//! compile-time contract for the crate's AACS surface.
|
||||
//! Surface guards. The public API is the module tree itself (no facade).
|
||||
//! Touching one representative item per module keeps these as a
|
||||
//! compile-time contract that the module paths stay stable.
|
||||
|
||||
use super::*;
|
||||
use super::content::{ALIGNED_UNIT_LEN, ts_sync_destroyed};
|
||||
use super::inf::{disc_hash, disc_hash_hex};
|
||||
use super::mkb::{AacsVersion, mkb_content_len, walk_mkb};
|
||||
use super::variant::{KEY_CORRECTION_DATA_PLACEHOLDER, is_variant_mkb};
|
||||
|
||||
#[test]
|
||||
fn aligned_unit_len_is_three_2048_byte_sectors() {
|
||||
@@ -134,14 +93,13 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn public_helpers_are_callable_through_the_facade() {
|
||||
// Touch a representative function from each re-export group so a
|
||||
// dropped/renamed export fails to compile. These are smoke calls, not
|
||||
// behavioural assertions (behaviour is covered in each module).
|
||||
fn public_helpers_are_callable_by_module_path() {
|
||||
// Touch a representative function from each module so a dropped/renamed
|
||||
// item fails to compile. Smoke calls, not behavioural assertions.
|
||||
let _ = ts_sync_destroyed(&[0u8; ALIGNED_UNIT_LEN]);
|
||||
let _ = mkb_content_len(&[]);
|
||||
let _ = is_variant_mkb(&walk_mkb(&[]));
|
||||
let _ = disc_hash_hex(&disc_hash(b"x"));
|
||||
let _ = mk_from_pk(&[[0u8; 16]], &[]);
|
||||
let _ = super::boil::mk_from_pk(&[[0u8; 16]], &[]);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-15
@@ -1068,7 +1068,7 @@ mod tests {
|
||||
disc_entry: None,
|
||||
};
|
||||
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
@@ -1111,7 +1111,7 @@ mod tests {
|
||||
};
|
||||
|
||||
let vid = [0u8; 16];
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
@@ -1153,7 +1153,7 @@ mod tests {
|
||||
};
|
||||
|
||||
let vid = [0u8; 16];
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
@@ -1193,7 +1193,7 @@ mod tests {
|
||||
};
|
||||
|
||||
let vid = [0u8; 16];
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
@@ -1240,7 +1240,7 @@ mod tests {
|
||||
media_keys: vec![km],
|
||||
disc_entry: None,
|
||||
};
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
@@ -1627,7 +1627,7 @@ mod tests {
|
||||
mkb.extend_from_slice(&[0x2f, 0x00, 0x00, 0x14]);
|
||||
mkb.extend_from_slice(&[0x55; 16]);
|
||||
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
@@ -1663,7 +1663,7 @@ mod tests {
|
||||
}),
|
||||
};
|
||||
let mkb = vec![0x10, 0x00, 0x00, 0x08, 0, 0, 0, 1];
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
@@ -1697,7 +1697,7 @@ mod tests {
|
||||
let mut cc = vec![0u8; 20];
|
||||
cc[0] = 0x10;
|
||||
cc[1] = 0x80;
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: Some(&cc),
|
||||
@@ -1731,7 +1731,7 @@ mod tests {
|
||||
unit_keys: Vec::new(),
|
||||
}),
|
||||
};
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &data,
|
||||
content_cert: None,
|
||||
@@ -1769,7 +1769,7 @@ mod tests {
|
||||
unit_keys: Vec::new(),
|
||||
}),
|
||||
};
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
@@ -1786,7 +1786,7 @@ mod tests {
|
||||
fn resolve_keys_returns_none_when_no_provider_has_anything() {
|
||||
// Empty provider array + VID present + no MKB → all paths miss → None.
|
||||
let uk_ro = minimal_unit_key_ro();
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
@@ -1969,7 +1969,7 @@ mod tests {
|
||||
#[test]
|
||||
fn classify_processing_keys_zero_vid_is_vid_unavailable() {
|
||||
let prov = material_provider(Vec::new(), vec![[0u8; 16]]);
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&prov];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&prov];
|
||||
let uk_ro = minimal_unit_key_ro();
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
@@ -1994,7 +1994,7 @@ mod tests {
|
||||
#[test]
|
||||
fn classify_vid_present_with_material_is_no_material_not_vid() {
|
||||
let prov = material_provider(vec![one_device_key()], vec![[0u8; 16]]);
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&prov];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&prov];
|
||||
let uk_ro = minimal_unit_key_ro();
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
@@ -2017,7 +2017,7 @@ mod tests {
|
||||
#[test]
|
||||
fn classify_vid_present_no_material_is_no_material() {
|
||||
let prov = material_provider(Vec::new(), Vec::new());
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&prov];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&prov];
|
||||
let uk_ro = minimal_unit_key_ro();
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
@@ -2055,7 +2055,7 @@ mod tests {
|
||||
unit_keys: Vec::new(),
|
||||
}),
|
||||
};
|
||||
let providers: &[&dyn super::super::KeyProvider] = &[&keydb];
|
||||
let providers: &[&dyn super::super::provider::KeyProvider] = &[&keydb];
|
||||
let ctx = ResolveContext {
|
||||
unit_key_ro: &uk_ro,
|
||||
content_cert: None,
|
||||
|
||||
Reference in New Issue
Block a user