Skip to main content

oxideav_aacs/
lib.rs

1//! Pure-Rust, clean-room AACS (Advanced Access Content System)
2//! decryption library, implementing the publicly-published AACS LA
3//! technical specifications **Common Final 0.953** (Oct 2012) and
4//! **BD-Prerecorded Final 0.953** (Oct 2012).
5//!
6//! See the crate `README.md` for an overview, the per-module spec
7//! mapping, and the legal-hygiene notes. The full pipeline is:
8//!
9//! ```text
10//! Device Key + MKB              KEYDB.cfg
11//!     |  (subdiff)                  | (direct)
12//!     v                              v
13//!   Media Key (K_m)                  |
14//!     |  AES-G(K_m, ID_v)           |
15//!     v                              |
16//!   Volume Unique Key (K_vu)  <-----+
17//!     |  AES-128D(K_vu, EncCpsUnitKey)
18//!     v
19//!   CPS Unit Key (K_cu)
20//!     |  BlockKey = AES-128E(K_cu, seed) XOR seed,
21//!     |  then AES-128-CBC-decrypt under BlockKey with IV0
22//!     v
23//!   Decrypted Aligned Unit (6144 B)
24//! ```
25//!
26//! This crate has **no real-disc fixtures**, no embedded Device Keys,
27//! no embedded Processing Keys, and no disc-specific test vectors —
28//! every test constructs its own key material and roundtrips through
29//! encrypt → parse → decrypt.
30
31#![forbid(unsafe_code)]
32#![deny(missing_docs)]
33#![deny(rust_2018_idioms)]
34
35pub mod aes;
36pub mod ake;
37pub mod cht;
38pub mod content;
39pub mod content_certificate;
40pub mod crl;
41pub mod ec;
42pub mod ecdsa;
43pub mod error;
44pub mod keydb;
45pub mod mkb;
46pub mod mmc;
47pub mod self_check;
48pub mod subdiff;
49pub mod unit_key;
50pub mod volume;
51pub mod vuk;
52
53pub use crate::ake::{
54    aacs_la_pub_point, build_signed_certificate, bus_key_from_point, host_authenticate,
55    read_verified_volume_id, AkeResult, Certificate, DriveAuthState, HostCredentials,
56    AACS_LA_PUB_X, AACS_LA_PUB_Y, BUS_KEY_LEN, CERT_TYPE_DRIVE, CERT_TYPE_HOST,
57};
58pub use crate::cht::{
59    hash_value_of_unit, ClipDescriptor, ContentHashTable, HASH_UNIT_SIZE, HASH_VALUE_SIZE,
60    LOGICAL_SECTORS_PER_HASH_UNIT, LOGICAL_SECTOR_SIZE,
61};
62pub use crate::content::{decrypt_aligned_unit, encrypt_aligned_unit, ALIGNED_UNIT_SIZE};
63pub use crate::content_certificate::{
64    usage_rules_hash, BdFormatSpecificSection, ContentCertificate, ContentCertificateId,
65    ContentSequenceNumber, CERTIFICATE_TYPE_FIRST_GEN, CONTENT_HASH_TABLE_DIGEST_LEN,
66    SIGNATURE_DATA_LEN,
67};
68pub use crate::crl::{
69    ContentRevocationList, CrlSegment, ManagedCopyServerCertificateId, RecordableMediaRevocation,
70    RecordableMediaType, RevocationRecord, CRL_HEADER_LEN, LIST_TYPE_FIRST_GEN,
71    RECORD_TYPE_CONTENT_CERTIFICATE_ID, RECORD_TYPE_MANAGED_COPY_SERVER_ID,
72    RECORD_TYPE_RMRR_PART_1, RECORD_TYPE_RMRR_PART_2, RECORD_TYPE_RMRR_PART_3,
73    REVOCATION_RECORD_LEN, SEGMENT_1_SIZE_MAX, SEGMENT_SIGNATURE_LEN,
74};
75pub use crate::ec::{Fp, Point, U160};
76pub use crate::ecdsa::{sign, sign_with_k, verify, Signature};
77pub use crate::error::AacsError;
78pub use crate::keydb::{
79    DeviceKeyRecord, DiscRecords, DriveCertRecord, HostCertRecord, KeyDb, KeyDbEntry, ParseReport,
80    ProcessingKey, SkippedLine,
81};
82pub use crate::mkb::{
83    Mkb, MkbType, RevocationEntry, RevocationSignatureBlock, SubsetDifferenceEntry,
84};
85pub use crate::mmc::{
86    build_send_disc_structure_write_data_key, build_send_key_host_cert_chal,
87    build_send_key_host_key, parse_bus_encryption_sector_extents_response,
88    parse_data_keys_response, parse_media_id_response, parse_media_serial_response,
89    parse_mkb_pack_response, parse_report_key_agid, parse_report_key_binding_nonce,
90    parse_report_key_drive_cert, parse_report_key_drive_cert_chal, parse_report_key_drive_key,
91    parse_send_disc_structure_write_data_key, parse_send_key_host_cert_chal,
92    parse_send_key_host_key, parse_volume_id_response, AgidResponse, BindingNonceResponse,
93    BusEncryptionSectorExtent, BusEncryptionSectorExtentsResponse, DataDirection, DataKeysResponse,
94    DriveCertChallengeResponse, DriveCertResponse, DriveCommand, DriveKeyResponse,
95    MediaIdentifierResponse, MediaSerialNumberResponse, MkbPackResponse, ReadDiscStructure,
96    ReportKey, ScsiResponse, SendDiscStructure, SendKey, VolumeIdResponse,
97};
98// `MockDrive` is a `test-util`-gated synthetic-drive fixture, not part of
99// the default public API. See the `test-util` cargo feature.
100#[cfg(any(test, feature = "test-util"))]
101pub use crate::mmc::MockDrive;
102pub use crate::self_check::{aacs_la_pub_self_check, ake_ecdh_self_check, curve_self_check};
103// `ake_full_self_check` + `all_self_checks` drive the `test-util`-gated
104// `MockDrive`, so they are gated together behind `test-util`.
105#[cfg(any(test, feature = "test-util"))]
106pub use crate::self_check::{ake_full_self_check, all_self_checks};
107pub use crate::subdiff::{
108    aes_g3, applies_to_device, apply_key_conversion_data, derive_processing_key, SubsetDifference,
109};
110pub use crate::unit_key::{CpsUnitRecord, UnitKeyFile, UnitKeyFileHeader};
111pub use crate::volume::{AacsVolume, CpsUnit, DeviceKey, TitleKey};
112pub use crate::vuk::{derive_vuk, Vuk};
113
114/// Result alias used throughout the crate.
115pub type Result<T> = core::result::Result<T, AacsError>;