diff --git a/Cargo.toml b/Cargo.toml index d7d72b7..75e635d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,20 +22,14 @@ codegen-units = 1 serde = { version = "1", features = ["derive"] } serde_json = "1" sha1 = "0.10" -sha2 = "0.10" -aes = "0.8" -cbc = "0.1" +aes = "0.9" # Interim path dep for local cross-repo dev; the release script re-pins this to # `{ git = ".../freemkv-unlock", tag = "vX.Y.Z" }` before tagging libfreemkv (so # the released tag resolves freemkv-unlock from git, not a sibling path). freemkv-unlock = { path = "../freemkv-unlock" } -num-bigint = "0.4" -num-traits = "0.2" -num-integer = "0.1" -rand = "0.8" -cmac = "0.7" -zip = { version = "2", default-features = false, features = ["deflate"] } -base64 = "0.22.1" +rand = "0.10" +zip = { version = "8", default-features = false, features = ["deflate"] } +base64 = "0.23" # Read-only XML DOM parser (pure Rust, forbid(unsafe_code), entity-expansion # bounded). Parses the HD-DVD Advanced-Content playlist `ADV_OBJ/VPLST000.XPL` # — untrusted disc bytes — into authoritative titles/clips/chapters. A real diff --git a/src/aacs/content.rs b/src/aacs/content.rs index 044f73f..7c87148 100644 --- a/src/aacs/content.rs +++ b/src/aacs/content.rs @@ -4,7 +4,7 @@ #[cfg(test)] use aes::Aes128; #[cfg(test)] -use aes::cipher::{KeyInit, generic_array::GenericArray}; +use aes::cipher::{Array, KeyInit}; use super::crypto::{aes_cbc_decrypt, aes_cbc_encrypt, aes_ecb_encrypt}; // Only this module's test fixtures build CBC ciphertext by hand now — the @@ -418,7 +418,7 @@ pub(crate) fn decrypt_bus(unit: &mut [u8], read_data_key: &[u8; 16]) { mod tests { use super::super::crypto::aes_ecb_decrypt; use super::*; - use aes::cipher::BlockEncrypt; // test fixtures build ciphertext directly + use aes::cipher::BlockCipherEncrypt; // test fixtures build ciphertext directly /// [`encrypt_unit`] is the exact inverse of [`decrypt_unit`]: whatever an /// authoring caller encrypts, the read path must recover byte-for-byte. @@ -725,7 +725,7 @@ mod tests { } // CBC encrypt bytes 16..6143 - let cipher = Aes128::new(GenericArray::from_slice(&encrypt_key)); + let cipher = Aes128::new(&encrypt_key.into()); let mut prev = AACS_IV; let num_blocks = (ALIGNED_UNIT_LEN - 16) / 16; for i in 0..num_blocks { @@ -733,7 +733,9 @@ mod tests { for j in 0..16 { plain[off + j] ^= prev[j]; } - let mut block = GenericArray::clone_from_slice(&plain[off..off + 16]); + let mut chunk = [0u8; 16]; + chunk.copy_from_slice(&plain[off..off + 16]); + let mut block: Array = chunk.into(); cipher.encrypt_block(&mut block); plain[off..off + 16].copy_from_slice(&block); prev.copy_from_slice(&plain[off..off + 16]); @@ -1496,7 +1498,7 @@ mod tests { let plain = unit.clone(); // Forward: CBC-encrypt unit[s+16 .. s+2048] per sector under AACS IV. - let cipher = Aes128::new(GenericArray::from_slice(&rdk)); + let cipher = Aes128::new(&rdk.into()); for s in (0..ALIGNED_UNIT_LEN).step_by(SECTOR_BYTES) { let mut prev = AACS_IV; let body = s + 16; @@ -1507,7 +1509,9 @@ mod tests { for j in 0..16 { unit[off + j] ^= prev[j]; } - let mut blk = GenericArray::clone_from_slice(&unit[off..off + 16]); + let mut chunk = [0u8; 16]; + chunk.copy_from_slice(&unit[off..off + 16]); + let mut blk: Array = chunk.into(); cipher.encrypt_block(&mut blk); unit[off..off + 16].copy_from_slice(&blk); prev.copy_from_slice(&unit[off..off + 16]); diff --git a/src/aacs/crypto.rs b/src/aacs/crypto.rs index 87f963a..9a50c14 100644 --- a/src/aacs/crypto.rs +++ b/src/aacs/crypto.rs @@ -8,7 +8,7 @@ //! content / keys / variant modules. use aes::Aes128; -use aes::cipher::{BlockDecrypt, BlockEncrypt, KeyInit, generic_array::GenericArray}; +use aes::cipher::{Array, BlockCipherDecrypt, BlockCipherEncrypt, KeyInit}; /// Fixed IV used by AACS for all AES-CBC operations. [C] §2.1.2 (default CBC IV, `iv0`). pub(crate) const AACS_IV: [u8; 16] = [ @@ -39,13 +39,13 @@ pub(crate) fn new_cipher_for(key: &[u8; 16]) -> Aes128 { fn new_cipher(key: &[u8; 16]) -> Aes128 { #[cfg(test)] KEY_EXPANSIONS.with(|c| c.set(c.get() + 1)); - Aes128::new(GenericArray::from_slice(key)) + Aes128::new(&(*key).into()) } /// AES-128-ECB encrypt a single 16-byte block. [C] §2.1.1 (`AES-128E`). pub(crate) fn aes_ecb_encrypt(key: &[u8; 16], data: &[u8; 16]) -> [u8; 16] { - let cipher = Aes128::new(GenericArray::from_slice(key)); - let mut block = GenericArray::clone_from_slice(data); + let cipher = Aes128::new(&(*key).into()); + let mut block: Array = (*data).into(); cipher.encrypt_block(&mut block); let mut out = [0u8; 16]; out.copy_from_slice(&block); @@ -54,8 +54,8 @@ pub(crate) fn aes_ecb_encrypt(key: &[u8; 16], data: &[u8; 16]) -> [u8; 16] { /// AES-128-ECB decrypt a single 16-byte block. [C] §2.1.1 (`AES-128D`). pub(crate) fn aes_ecb_decrypt(key: &[u8; 16], data: &[u8; 16]) -> [u8; 16] { - let cipher = Aes128::new(GenericArray::from_slice(key)); - let mut block = GenericArray::clone_from_slice(data); + let cipher = Aes128::new(&(*key).into()); + let mut block: Array = (*data).into(); cipher.decrypt_block(&mut block); let mut out = [0u8; 16]; out.copy_from_slice(&block); @@ -88,7 +88,7 @@ pub(crate) fn aes_cbc_encrypt(key: &[u8; 16], data: &mut [u8]) { for j in 0..16 { block[j] = data[offset + j] ^ prev[j]; } - let mut ga = GenericArray::clone_from_slice(&block); + let mut ga: Array = block.into(); cipher.encrypt_block(&mut ga); data[offset..offset + 16].copy_from_slice(&ga); prev.copy_from_slice(&ga); @@ -140,7 +140,9 @@ pub(crate) fn cbc_decrypt_blocks(cipher: &Aes128, data: &mut [u8]) { p.copy_from_slice(&data[(i - 1) * 16..i * 16]); p }; - let mut block = GenericArray::clone_from_slice(&data[offset..offset + 16]); + let mut chunk = [0u8; 16]; + chunk.copy_from_slice(&data[offset..offset + 16]); + let mut block: Array = chunk.into(); cipher.decrypt_block(&mut block); for j in 0..16 { data[offset + j] = block[j] ^ prev[j]; diff --git a/src/disc/mod.rs b/src/disc/mod.rs index f3d53cd..5f50fd9 100644 --- a/src/disc/mod.rs +++ b/src/disc/mod.rs @@ -5416,7 +5416,7 @@ mod tests { use crate::aacs::content::ALIGNED_UNIT_LEN; use crate::aacs::crypto::AACS_IV; use aes::Aes128; - use aes::cipher::{BlockEncrypt, KeyInit, generic_array::GenericArray}; + use aes::cipher::{Array, BlockCipherEncrypt, KeyInit}; let mut unit = clear[..ALIGNED_UNIT_LEN].to_vec(); // Flag the unit encrypted (CPI bits on byte 0) before key derivation so // the recovered plaintext header matches and `decrypt_unit`'s CPI gate @@ -5424,14 +5424,14 @@ mod tests { unit[0] |= 0xC0; let mut header = [0u8; 16]; header.copy_from_slice(&unit[..16]); - let cipher = Aes128::new(GenericArray::from_slice(uk)); - let mut blk = GenericArray::clone_from_slice(&header); + let cipher = Aes128::new(&(*uk).into()); + let mut blk: Array = header.into(); cipher.encrypt_block(&mut blk); let mut dk = [0u8; 16]; for i in 0..16 { dk[i] = blk[i] ^ header[i]; } - let bc = Aes128::new(GenericArray::from_slice(&dk)); + let bc = Aes128::new(&dk.into()); let mut prev = AACS_IV; let mut i = 16; while i + 16 <= ALIGNED_UNIT_LEN { @@ -5439,7 +5439,7 @@ mod tests { for j in 0..16 { b[j] = unit[i + j] ^ prev[j]; } - let mut g = GenericArray::clone_from_slice(&b); + let mut g: Array = b.into(); bc.encrypt_block(&mut g); for j in 0..16 { unit[i + j] = g[j]; diff --git a/tests/crypto_tests.rs b/tests/crypto_tests.rs index 1a32452..ec0016f 100644 --- a/tests/crypto_tests.rs +++ b/tests/crypto_tests.rs @@ -85,7 +85,7 @@ fn css_is_scrambled_detection() { #[test] fn aacs_decrypt_unit_roundtrip() { use aes::Aes128; - use aes::cipher::{BlockEncrypt, KeyInit, generic_array::GenericArray}; + use aes::cipher::{Array, BlockCipherEncrypt, KeyInit}; let unit_key = [0xAAu8; 16]; let aacs_iv: [u8; 16] = [ @@ -113,8 +113,8 @@ fn aacs_decrypt_unit_roundtrip() { let header: [u8; 16] = plain[..16].try_into().unwrap(); // Step 1: AES-ECB encrypt header with unit key - let cipher_header = Aes128::new(GenericArray::from_slice(&unit_key)); - let mut block = GenericArray::clone_from_slice(&header); + let cipher_header = Aes128::new(&unit_key.into()); + let mut block: Array = header.into(); cipher_header.encrypt_block(&mut block); let mut derived = [0u8; 16]; derived.copy_from_slice(&block); @@ -126,7 +126,7 @@ fn aacs_decrypt_unit_roundtrip() { } // Step 3: AES-CBC encrypt bytes 16..6144 - let cipher = Aes128::new(GenericArray::from_slice(&encrypt_key)); + let cipher = Aes128::new(&encrypt_key.into()); let mut prev = aacs_iv; let num_blocks = (aacs::content::ALIGNED_UNIT_LEN - 16) / 16; for i in 0..num_blocks { @@ -134,7 +134,9 @@ fn aacs_decrypt_unit_roundtrip() { for j in 0..16 { plain[off + j] ^= prev[j]; } - let mut blk = GenericArray::clone_from_slice(&plain[off..off + 16]); + let mut c_blk = [0u8; 16]; + c_blk.copy_from_slice(&plain[off..off + 16]); + let mut blk: Array = c_blk.into(); cipher.encrypt_block(&mut blk); plain[off..off + 16].copy_from_slice(&blk); prev.copy_from_slice(&plain[off..off + 16]); @@ -215,7 +217,7 @@ fn aacs_disc_hash_deterministic() { #[test] fn aacs_decrypt_unit_key_roundtrip() { use aes::Aes128; - use aes::cipher::{BlockEncrypt, KeyInit, generic_array::GenericArray}; + use aes::cipher::{Array, BlockCipherEncrypt, KeyInit}; let vuk = [ 0x11u8, 0x14, 0x36, 0x0B, 0x10, 0xEE, 0x6E, 0xAC, 0x78, 0xAA, 0x4A, 0xC0, 0xB7, 0x52, 0xEA, @@ -227,8 +229,8 @@ fn aacs_decrypt_unit_key_roundtrip() { ]; // Encrypt: AES-ECB encrypt the unit key with VUK - let cipher = Aes128::new(GenericArray::from_slice(&vuk)); - let mut block = GenericArray::clone_from_slice(&original_unit_key); + let cipher = Aes128::new(&vuk.into()); + let mut block: Array = original_unit_key.into(); cipher.encrypt_block(&mut block); let mut encrypted_uk = [0u8; 16]; encrypted_uk.copy_from_slice(&block); @@ -340,9 +342,9 @@ fn aacs_clear_unit_reports_not_encrypted() { /// Independent AES-128-ECB encrypt (uses `aes` crate directly, NOT our library). fn ref_aes_ecb_encrypt(key: &[u8; 16], data: &[u8; 16]) -> [u8; 16] { use aes::Aes128; - use aes::cipher::{BlockEncrypt, KeyInit, generic_array::GenericArray}; - let cipher = Aes128::new(GenericArray::from_slice(key)); - let mut block = GenericArray::clone_from_slice(data); + use aes::cipher::{Array, BlockCipherEncrypt, KeyInit}; + let cipher = Aes128::new(&(*key).into()); + let mut block: Array = (*data).into(); cipher.encrypt_block(&mut block); let mut out = [0u8; 16]; out.copy_from_slice(&block); @@ -352,8 +354,8 @@ fn ref_aes_ecb_encrypt(key: &[u8; 16], data: &[u8; 16]) -> [u8; 16] { /// Independent AES-128-CBC encrypt (uses `aes` crate directly, NOT our library). fn ref_aes_cbc_encrypt(key: &[u8; 16], iv: &[u8; 16], data: &mut [u8]) { use aes::Aes128; - use aes::cipher::{BlockEncrypt, KeyInit, generic_array::GenericArray}; - let cipher = Aes128::new(GenericArray::from_slice(key)); + use aes::cipher::{Array, BlockCipherEncrypt, KeyInit}; + let cipher = Aes128::new(&(*key).into()); let mut prev = *iv; let num_blocks = data.len() / 16; for i in 0..num_blocks { @@ -361,7 +363,9 @@ fn ref_aes_cbc_encrypt(key: &[u8; 16], iv: &[u8; 16], data: &mut [u8]) { for j in 0..16 { data[off + j] ^= prev[j]; } - let mut block = GenericArray::clone_from_slice(&data[off..off + 16]); + let mut c_block = [0u8; 16]; + c_block.copy_from_slice(&data[off..off + 16]); + let mut block: Array = c_block.into(); cipher.encrypt_block(&mut block); data[off..off + 16].copy_from_slice(&block); prev.copy_from_slice(&data[off..off + 16]);