diff --git a/src/aacs/handshake.rs b/src/aacs/handshake.rs index 011573f..fbbbe95 100644 --- a/src/aacs/handshake.rs +++ b/src/aacs/handshake.rs @@ -18,9 +18,8 @@ //! - AACS 2.0: drives accept AACS 1.0 host certs for backward compatibility //! (full P-256/SHA-256 AACS 2.0 handshake prepared but rarely needed) -use crate::drive::Drive; use crate::error::{Error, Result}; -use crate::scsi::DataDirection; +use crate::scsi::{DataDirection, ScsiTransport}; use num_bigint::BigUint; use num_traits::{One, Zero}; use sha1::{Digest, Sha1}; @@ -45,16 +44,16 @@ fn handshake_err(err: Error, fallback: Error) -> Error { } /// Execute a SCSI command that reads data from the device. -fn scsi_read(session: &mut Drive, cdb: &[u8], len: usize) -> Result> { +fn scsi_read(session: &mut dyn ScsiTransport, cdb: &[u8], len: usize) -> Result> { let mut buf = vec![0u8; len]; - session.scsi_execute(cdb, DataDirection::FromDevice, &mut buf, 5_000)?; + session.execute(cdb, DataDirection::FromDevice, &mut buf, 5_000)?; Ok(buf) } /// Execute a SCSI command that writes data to the device. -fn scsi_write(session: &mut Drive, cdb: &[u8], data: &[u8]) -> Result<()> { +fn scsi_write(session: &mut dyn ScsiTransport, cdb: &[u8], data: &[u8]) -> Result<()> { let mut buf = data.to_vec(); - session.scsi_execute(cdb, DataDirection::ToDevice, &mut buf, 5_000)?; + session.execute(cdb, DataDirection::ToDevice, &mut buf, 5_000)?; Ok(()) } @@ -881,7 +880,7 @@ impl std::fmt::Debug for AacsAuth { /// Requires a host private key (20 bytes) and host certificate (92 bytes) /// from the KEYDB.cfg HC entry. pub fn aacs_authenticate( - session: &mut Drive, + session: &mut dyn ScsiTransport, host_priv_key: &[u8; 20], host_cert: &[u8], ) -> Result { @@ -1018,7 +1017,7 @@ pub fn aacs_authenticate( /// Falls back to aacs_authenticate (AACS 1.0) if AACS 2.0 host credentials /// are not available. pub fn aacs2_authenticate( - session: &mut Drive, + session: &mut dyn ScsiTransport, host_priv_key_v1: &[u8; 20], host_cert_v1: &[u8], host_priv_key_v2: Option<&[u8; 32]>, @@ -1044,7 +1043,7 @@ pub fn aacs2_authenticate( /// Native AACS 2.0 handshake using P-256/SHA-256. /// Same SCSI protocol, larger payloads (32-byte keys, 132-byte certs). fn aacs2_authenticate_p256( - session: &mut Drive, + session: &mut dyn ScsiTransport, host_priv_key: &[u8; 32], host_cert: &[u8], ) -> Result { @@ -1169,7 +1168,7 @@ fn aacs2_authenticate_p256( } /// Read Volume ID after successful authentication. -pub fn read_volume_id(session: &mut Drive, auth: &mut AacsAuth) -> Result<[u8; 16]> { +pub fn read_volume_id(session: &mut dyn ScsiTransport, auth: &mut AacsAuth) -> Result<[u8; 16]> { // REPORT DISC STRUCTURE format 0x80 let cdb = cdb_report_disc_structure(auth.agid, 0x80, 36); let response = @@ -1191,7 +1190,10 @@ pub fn read_volume_id(session: &mut Drive, auth: &mut AacsAuth) -> Result<[u8; 1 } /// Read data keys after successful authentication (for AACS 2.0 bus encryption). -pub fn read_data_keys(session: &mut Drive, auth: &mut AacsAuth) -> Result<([u8; 16], [u8; 16])> { +pub fn read_data_keys( + session: &mut dyn ScsiTransport, + auth: &mut AacsAuth, +) -> Result<([u8; 16], [u8; 16])> { // REPORT DISC STRUCTURE format 0x84 let cdb = cdb_report_disc_structure(auth.agid, 0x84, 36); let response = diff --git a/src/disc/encrypt.rs b/src/disc/encrypt.rs index 96d35ce..c94171d 100644 --- a/src/disc/encrypt.rs +++ b/src/disc/encrypt.rs @@ -118,23 +118,29 @@ impl AacsCertUnlocker<'_> { if idx > 0 { std::thread::sleep(std::time::Duration::from_millis(PER_CERT_BACKOFF_MS)); } - match aacs::handshake::aacs_authenticate(session, &hc.private_key, &hc.certificate) { + match aacs::handshake::aacs_authenticate( + session.scsi_mut(), + &hc.private_key, + &hc.certificate, + ) { Ok(mut auth) => { - let volume_id = match aacs::handshake::read_volume_id(session, &mut auth) { - Ok(vid) => vid, - Err(e) => { - tracing::warn!( - target: "freemkv::disc", - phase = "handshake_vid_read_failed", - cert_index = idx, - error_code = e.code(), - "auth ok but volume ID read failed" - ); - return Err(UnlockError::VidUnavailable); - } - }; + let volume_id = + match aacs::handshake::read_volume_id(session.scsi_mut(), &mut auth) { + Ok(vid) => vid, + Err(e) => { + tracing::warn!( + target: "freemkv::disc", + phase = "handshake_vid_read_failed", + cert_index = idx, + error_code = e.code(), + "auth ok but volume ID read failed" + ); + return Err(UnlockError::VidUnavailable); + } + }; let (read_data_key, read_data_key_err) = match aacs::handshake::read_data_keys( - session, &mut auth, + session.scsi_mut(), + &mut auth, ) { Ok((rdk, _)) => (Some(rdk), None), Err(e) => {