mirror of
https://github.com/freemkv/freemkv-unlock.git
synced 2026-10-07 18:13:11 +00:00
Move to rand 0.10 and aes 0.9
Both are API renames rather than behaviour changes, but this is the AACS and CSS crypto path, so it is verified by output rather than by the fact that it compiles. rand: `RngCore` no longer sits at the crate root -- `fill_bytes` moved to the re-exported `Rng` trait -- and `thread_rng()` is now `rng()`. aes: the cipher traits gained their `BlockCipher` prefix and `generic_array::GenericArray` became `Array`. The obvious translation uses `Array::from_slice`, which is deprecated in the new version and would fail clippy's `-D warnings`; these use the `From<[T; N]>` conversion the crate points at instead. The proof this is byte-exact is `test_aes_cmac_nist_kat_full_block`, which checks the exact MAC from NIST SP 800-38B Appendix D.1 -- a wrong byte order or a mis-sized array cannot produce that value. All 95 tests pass in both debug and release.
This commit is contained in:
+2
-2
@@ -24,5 +24,5 @@ num-bigint = "0.5"
|
||||
num-traits = "0.2"
|
||||
sha1 = "0.10"
|
||||
sha2 = "0.11"
|
||||
aes = "0.8"
|
||||
rand = "0.8"
|
||||
aes = "0.9"
|
||||
rand = "0.10"
|
||||
|
||||
+21
-21
@@ -391,8 +391,8 @@ fn ecdsa_sign(priv_key: &[u8; 20], data: &[u8]) -> ([u8; 20], [u8; 20]) {
|
||||
// two); a biased ECDSA nonce is a known key-recovery weakness, so
|
||||
// we reject and redraw any candidate >= n instead.
|
||||
let mut k_bytes = [0u8; 20];
|
||||
use rand::RngCore;
|
||||
rand::thread_rng().fill_bytes(&mut k_bytes);
|
||||
use rand::Rng;
|
||||
rand::rng().fill_bytes(&mut k_bytes);
|
||||
let k = BigUint::from_bytes_be(&k_bytes);
|
||||
if k.is_zero() || k >= n {
|
||||
continue;
|
||||
@@ -490,8 +490,8 @@ fn ecdsa_sign_p256(priv_key: &[u8; 32], data: &[u8]) -> ([u8; 32], [u8; 32]) {
|
||||
// (avoid the modulo bias that reducing raw RNG bytes mod n would
|
||||
// introduce).
|
||||
let mut k_bytes = [0u8; 32];
|
||||
use rand::RngCore;
|
||||
rand::thread_rng().fill_bytes(&mut k_bytes);
|
||||
use rand::Rng;
|
||||
rand::rng().fill_bytes(&mut k_bytes);
|
||||
let k = BigUint::from_bytes_be(&k_bytes);
|
||||
if k.is_zero() || k >= n {
|
||||
continue;
|
||||
@@ -703,8 +703,8 @@ fn generate_host_key_pair_p256() -> ([u8; 32], [u8; 32], [u8; 32]) {
|
||||
|
||||
let (d, q) = loop {
|
||||
let mut priv_bytes = [0u8; 32];
|
||||
use rand::RngCore;
|
||||
rand::thread_rng().fill_bytes(&mut priv_bytes);
|
||||
use rand::Rng;
|
||||
rand::rng().fill_bytes(&mut priv_bytes);
|
||||
// d == 0 (prob ~1/n) would yield the point at infinity / an
|
||||
// all-zero key and degenerate the bus key — reject and retry,
|
||||
// matching the AACS 1.0 sibling generate_host_key_pair.
|
||||
@@ -735,8 +735,8 @@ fn generate_host_key_pair() -> ([u8; 20], [u8; 20], [u8; 20]) {
|
||||
|
||||
let (d, q) = loop {
|
||||
let mut priv_bytes = [0u8; 20];
|
||||
use rand::RngCore;
|
||||
rand::thread_rng().fill_bytes(&mut priv_bytes);
|
||||
use rand::Rng;
|
||||
rand::rng().fill_bytes(&mut priv_bytes);
|
||||
let d = BigUint::from_bytes_be(&priv_bytes) % &n;
|
||||
if d.is_zero() {
|
||||
continue;
|
||||
@@ -771,13 +771,13 @@ fn generate_host_key_pair() -> ([u8; 20], [u8; 20], [u8; 20]) {
|
||||
/// padding.
|
||||
fn aes_cmac_16(data: &[u8; 16], key: &[u8; 16]) -> [u8; 16] {
|
||||
use aes::Aes128;
|
||||
use aes::cipher::{BlockEncrypt, KeyInit, generic_array::GenericArray};
|
||||
use aes::cipher::{Array, BlockCipherEncrypt, KeyInit};
|
||||
|
||||
let cipher = Aes128::new(GenericArray::from_slice(key));
|
||||
let cipher = Aes128::new(&(*key).into());
|
||||
|
||||
// For single-block CMAC:
|
||||
// 1. Generate subkey K1
|
||||
let mut l = GenericArray::clone_from_slice(&[0u8; 16]);
|
||||
let mut l: Array<u8, _> = [0u8; 16].into();
|
||||
cipher.encrypt_block(&mut l);
|
||||
|
||||
let mut k1 = [0u8; 16];
|
||||
@@ -795,7 +795,7 @@ fn aes_cmac_16(data: &[u8; 16], key: &[u8; 16]) -> [u8; 16] {
|
||||
for i in 0..16 {
|
||||
block[i] = data[i] ^ k1[i];
|
||||
}
|
||||
let mut ga = GenericArray::clone_from_slice(&block);
|
||||
let mut ga: Array<u8, _> = block.into();
|
||||
cipher.encrypt_block(&mut ga);
|
||||
|
||||
let mut mac = [0u8; 16];
|
||||
@@ -903,8 +903,8 @@ pub fn aacs_authenticate(
|
||||
|
||||
// Step 3: Generate host nonce and ephemeral key pair
|
||||
let mut host_nonce = [0u8; 20];
|
||||
use rand::RngCore;
|
||||
rand::thread_rng().fill_bytes(&mut host_nonce);
|
||||
use rand::Rng;
|
||||
rand::rng().fill_bytes(&mut host_nonce);
|
||||
let (host_key, host_key_point_x, host_key_point_y) = generate_host_key_pair();
|
||||
|
||||
// Step 4: Send host certificate + nonce (SEND KEY format 0x01)
|
||||
@@ -1066,8 +1066,8 @@ fn aacs2_authenticate_p256(
|
||||
|
||||
// Step 3: Generate host nonce + P-256 ephemeral key pair
|
||||
let mut host_nonce = [0u8; 20];
|
||||
use rand::RngCore;
|
||||
rand::thread_rng().fill_bytes(&mut host_nonce);
|
||||
use rand::Rng;
|
||||
rand::rng().fill_bytes(&mut host_nonce);
|
||||
let (host_eph_key, host_eph_pub_x, host_eph_pub_y) = generate_host_key_pair_p256();
|
||||
|
||||
// Step 4: Send AACS 2.0 host certificate + nonce
|
||||
@@ -1490,8 +1490,8 @@ mod tests {
|
||||
|
||||
// Generate random P-256 key pair
|
||||
let mut priv_bytes = [0u8; 32];
|
||||
use rand::RngCore;
|
||||
rand::thread_rng().fill_bytes(&mut priv_bytes);
|
||||
use rand::Rng;
|
||||
rand::rng().fill_bytes(&mut priv_bytes);
|
||||
let d = BigUint::from_bytes_be(&priv_bytes) % &n;
|
||||
let priv_key: [u8; 32] = to_bytes_be_padded(&d, 32).try_into().unwrap();
|
||||
|
||||
@@ -1514,9 +1514,9 @@ mod tests {
|
||||
|
||||
let mut pa = [0u8; 32];
|
||||
let mut pb = [0u8; 32];
|
||||
use rand::RngCore;
|
||||
rand::thread_rng().fill_bytes(&mut pa);
|
||||
rand::thread_rng().fill_bytes(&mut pb);
|
||||
use rand::Rng;
|
||||
rand::rng().fill_bytes(&mut pa);
|
||||
rand::rng().fill_bytes(&mut pb);
|
||||
let da = BigUint::from_bytes_be(&pa) % &n;
|
||||
let db = BigUint::from_bytes_be(&pb) % &n;
|
||||
let priv_a: [u8; 32] = to_bytes_be_padded(&da, 32).try_into().unwrap();
|
||||
|
||||
+3
-3
@@ -9,7 +9,7 @@ mod error;
|
||||
mod handshake;
|
||||
|
||||
use aes::Aes128;
|
||||
use aes::cipher::{BlockDecrypt, KeyInit, generic_array::GenericArray};
|
||||
use aes::cipher::{Array, BlockCipherDecrypt, KeyInit};
|
||||
|
||||
use crate::scsi::ScsiTransport;
|
||||
use crate::{DiscKind, UnlockCtx, UnlockError, Unlocked, Unlocker};
|
||||
@@ -17,8 +17,8 @@ use crate::{DiscKind, UnlockCtx, UnlockError, Unlocked, Unlocker};
|
||||
/// AES-128-ECB decrypt a single 16-byte block — used to decrypt the bus key /
|
||||
/// read_data_key the drive returns after the handshake.
|
||||
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<u8, _> = (*data).into();
|
||||
cipher.decrypt_block(&mut block);
|
||||
let mut out = [0u8; 16];
|
||||
out.copy_from_slice(&block);
|
||||
|
||||
+2
-2
@@ -299,8 +299,8 @@ fn establish_authenticated_session(scsi: &mut dyn ScsiTransport) -> Result<u8> {
|
||||
// handshake.
|
||||
let mut host_challenge = [0u8; 10];
|
||||
{
|
||||
use rand::RngCore;
|
||||
rand::thread_rng().fill_bytes(&mut host_challenge);
|
||||
use rand::Rng;
|
||||
rand::rng().fill_bytes(&mut host_challenge);
|
||||
}
|
||||
let mut hc_buf = [0u8; 16];
|
||||
hc_buf[0] = 0x00;
|
||||
|
||||
Reference in New Issue
Block a user