v0.25.14: rename Drive raw-read API to remove third-party project breadcrumbs
Pure rename pass — no behavioral change: - Drive::is_libredrive_active() → Drive::is_raw_read_active() - PlatformDriver::is_libredrive_active() trait method (same rename) - Mt1959 struct field libredrive_active → raw_read_active - Error::AacsLibredriveUnsupported → Error::AacsRawReadUnsupported (numeric code E7016 unchanged) - All callers, tests, and doc comments updated to the new name. Old identifiers removed entirely; downstream consumers must update. Mirrored in bdemu, freemkv, autorip, freemkv-tools.
This commit is contained in:
+1
-1
@@ -858,7 +858,7 @@ fn resolve_keys_classical(ctx: &ResolveContext<'_>, version: AacsVersion) -> Opt
|
||||
}
|
||||
|
||||
// Paths 2-4 all consume the Volume ID. Without it (handshake
|
||||
// skipped, libredrive bypass failed, etc.) every downstream
|
||||
// skipped, raw-read bypass failed, etc.) every downstream
|
||||
// derivation produces garbage. Caller stamps `[0u8; 16]` as the
|
||||
// sentinel "no VID" — short-circuit here so we don't surface a
|
||||
// misleading "all paths failed" log when really the math is
|
||||
|
||||
+7
-8
@@ -17,10 +17,10 @@ impl Disc {
|
||||
/// SCSI handshake — AACS mutual auth via host certs from the keydb,
|
||||
/// returning VID (and bus keys when applicable) on success.
|
||||
///
|
||||
/// `Drive::is_libredrive_active()` is logged for diagnostics but no
|
||||
/// `Drive::is_raw_read_active()` is logged for diagnostics but no
|
||||
/// longer alters the auth path. v0.25.11 introduced a "raw-read VID"
|
||||
/// shortcut that issued `READ_DISC_STRUCTURE` format 0x80 with
|
||||
/// AGID=0 on libredrive-active drives, on the hypothesis that the
|
||||
/// AGID=0 on raw-read-active drives, on the hypothesis that the
|
||||
/// firmware-uploaded drive would serve VID without cert auth. The
|
||||
/// BU40N returned 0x05/0x6F/0x02 (`KEY NOT ESTABLISHED`) to that
|
||||
/// CDB — the AACS spec requires an AGID established via successful
|
||||
@@ -33,7 +33,7 @@ impl Disc {
|
||||
/// Returns `(handshake, error)`:
|
||||
/// * `(Some(_), None)` — VID acquired
|
||||
/// * `(None, Some(_))` — specific failure mode (see
|
||||
/// `AacsHostCertRejected` / `AacsLibredriveUnsupported` /
|
||||
/// `AacsHostCertRejected` / `AacsRawReadUnsupported` /
|
||||
/// `AacsVidUnavailable` variants in `error.rs`)
|
||||
/// * `(None, None)` — handshake not attempted (no keydb;
|
||||
/// resolution will proceed with VID=zero and rely on path 1
|
||||
@@ -45,7 +45,7 @@ impl Disc {
|
||||
tracing::warn!(
|
||||
target: "freemkv::disc",
|
||||
phase = "handshake_entry",
|
||||
libredrive_active = session.is_libredrive_active(),
|
||||
raw_read_active = session.is_raw_read_active(),
|
||||
"do_handshake entered"
|
||||
);
|
||||
|
||||
@@ -101,10 +101,9 @@ impl Disc {
|
||||
|
||||
if host_cert_count == 0 {
|
||||
// No host certs in keydb -> cert auth cannot proceed.
|
||||
// Surface as
|
||||
// LibredriveUnsupported so the caller knows neither path
|
||||
// is available on this configuration.
|
||||
return (None, Some(Error::AacsLibredriveUnsupported));
|
||||
// Surface as RawReadUnsupported so the caller knows
|
||||
// neither path is available on this configuration.
|
||||
return (None, Some(Error::AacsRawReadUnsupported));
|
||||
}
|
||||
|
||||
// v0.25.7 wedge fix. Pre-0.25.7 this loop fired up to 16 AACS
|
||||
|
||||
+2
-2
@@ -1044,7 +1044,7 @@ impl Disc {
|
||||
/// All disc reads use standard READ(10) via UDF -- no vendor SCSI commands.
|
||||
pub fn scan(session: &mut Drive, opts: &ScanOptions) -> Result<Self> {
|
||||
// AACS handshake (Blu-ray/UHD). Cert-based mutual auth; logs
|
||||
// is_libredrive_active() as a diagnostic but the auth path no
|
||||
// is_raw_read_active() as a diagnostic but the auth path no
|
||||
// longer branches on it.
|
||||
let (handshake, handshake_error) = Self::do_handshake(session, opts);
|
||||
|
||||
@@ -1133,7 +1133,7 @@ impl Disc {
|
||||
/// Core scan pipeline — works with any SectorSource.
|
||||
///
|
||||
/// `handshake_error` is plumbed from `do_handshake` so failures
|
||||
/// (cert rejected, libredrive unsupported, VID read failed) are
|
||||
/// (cert rejected, raw-read unsupported, VID read failed) are
|
||||
/// preserved as `disc.aacs_error` for callers to render. When key
|
||||
/// resolution succeeds despite the handshake failure (built-in
|
||||
/// keys + disc-hash lookup hit) the error is dropped.
|
||||
|
||||
+5
-5
@@ -432,7 +432,7 @@ impl Drive {
|
||||
}
|
||||
}
|
||||
|
||||
/// True if the drive is currently in libredrive raw-read mode.
|
||||
/// True if the drive is currently in raw-read mode.
|
||||
///
|
||||
/// Detected by the platform driver during `init()` from the unlock
|
||||
/// response's mode markers. When true:
|
||||
@@ -444,11 +444,11 @@ impl Drive {
|
||||
///
|
||||
/// AACS layer code should branch on this: if true, skip
|
||||
/// `aacs::handshake::aacs_authenticate` (the cert dance) and read
|
||||
/// VID via the libredrive alternate path. If false, fall back to
|
||||
/// the standard cert-based handshake.
|
||||
pub fn is_libredrive_active(&self) -> bool {
|
||||
/// VID via the alternate VID read path. If false, fall back to the
|
||||
/// standard cert-based handshake.
|
||||
pub fn is_raw_read_active(&self) -> bool {
|
||||
match self.driver {
|
||||
Some(ref d) => d.is_libredrive_active(),
|
||||
Some(ref d) => d.is_raw_read_active(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -72,7 +72,7 @@ pub const E_AACS_DATA_KEY: u16 = 7011;
|
||||
pub const E_DECRYPT_FAILED: u16 = 7013;
|
||||
pub const E_CSS_AUTH_FAILED: u16 = 7014;
|
||||
pub const E_AACS_HOST_CERT_REJECTED: u16 = 7015;
|
||||
pub const E_AACS_LIBREDRIVE_UNSUPPORTED: u16 = 7016;
|
||||
pub const E_AACS_RAW_READ_UNSUPPORTED: u16 = 7016;
|
||||
pub const E_AACS_VID_UNAVAILABLE: u16 = 7017;
|
||||
pub const E_AACS_MK_UNAVAILABLE: u16 = 7018;
|
||||
pub const E_AACS_VUK_NOT_IN_KEYDB: u16 = 7019;
|
||||
@@ -230,11 +230,11 @@ pub enum Error {
|
||||
/// Host certificate rejected by the drive's revocation list (HRL hit).
|
||||
/// All available host certs failed mutual auth on this drive.
|
||||
AacsHostCertRejected,
|
||||
/// Drive cannot be put into libredrive raw-read mode and standard
|
||||
/// AACS cert auth failed. No path to decryption remains.
|
||||
AacsLibredriveUnsupported,
|
||||
/// Drive cannot be put into raw-read mode and standard AACS cert
|
||||
/// auth failed. No path to decryption remains.
|
||||
AacsRawReadUnsupported,
|
||||
/// Volume ID could not be retrieved from the drive (neither via cert
|
||||
/// auth nor via the libredrive alternate path). Downstream of step 1
|
||||
/// auth nor via the alternate VID read path). Downstream of step 1
|
||||
/// of the AACS chain.
|
||||
AacsVidUnavailable,
|
||||
/// No available path produced a Media Key (no MK+VID in keydb, no
|
||||
@@ -329,7 +329,7 @@ impl Error {
|
||||
Error::DecryptFailed => E_DECRYPT_FAILED,
|
||||
Error::CssAuthFailed => E_CSS_AUTH_FAILED,
|
||||
Error::AacsHostCertRejected => E_AACS_HOST_CERT_REJECTED,
|
||||
Error::AacsLibredriveUnsupported => E_AACS_LIBREDRIVE_UNSUPPORTED,
|
||||
Error::AacsRawReadUnsupported => E_AACS_RAW_READ_UNSUPPORTED,
|
||||
Error::AacsVidUnavailable => E_AACS_VID_UNAVAILABLE,
|
||||
Error::AacsMkUnavailable => E_AACS_MK_UNAVAILABLE,
|
||||
Error::AacsVukNotInKeydb => E_AACS_VUK_NOT_IN_KEYDB,
|
||||
|
||||
+8
-8
@@ -19,17 +19,17 @@ pub(crate) trait PlatformDriver: Send {
|
||||
/// True after successful init().
|
||||
fn is_ready(&self) -> bool;
|
||||
|
||||
/// True if the drive is currently in libredrive raw-read mode (the
|
||||
/// per-drive runtime firmware has been uploaded AND the drive
|
||||
/// confirms active mode via the `MMkv` / `LbDr` markers in the
|
||||
/// unlock response). When true the host can read sectors without
|
||||
/// AACS bus encryption and retrieve VID without cert-based mutual
|
||||
/// auth — the cert/HRL gate on the drive's standard AACS path is
|
||||
/// effectively bypassed by the alternate data path.
|
||||
/// True if the drive is currently in raw-read mode (the per-drive
|
||||
/// runtime firmware has been uploaded AND the drive confirms
|
||||
/// active mode via the marker bytes in the unlock response). When
|
||||
/// true the host can read sectors without AACS bus encryption and
|
||||
/// retrieve VID without cert-based mutual auth — the cert/HRL gate
|
||||
/// on the drive's standard AACS path is effectively bypassed by
|
||||
/// the alternate data path.
|
||||
///
|
||||
/// Default `false` — platforms that don't implement this mode are
|
||||
/// always reported as inactive.
|
||||
fn is_libredrive_active(&self) -> bool {
|
||||
fn is_raw_read_active(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
+32
-29
@@ -52,10 +52,10 @@ pub struct Mt1959 {
|
||||
pub(crate) buffer_id: u8,
|
||||
pub(crate) unlocked: bool,
|
||||
/// True when the unlock response carried both the per-drive
|
||||
/// signature AND the active-mode markers (`MMkv` at [12..16],
|
||||
/// `LbDr` at [16..20]). When true the drive will accept raw-read
|
||||
/// SCSI traffic without AACS bus encryption / cert auth.
|
||||
libredrive_active: bool,
|
||||
/// signature AND a 4-byte marker at offset 12 plus a secondary
|
||||
/// 4-byte marker at offset 16. When true the drive will accept
|
||||
/// raw-read SCSI traffic without AACS bus encryption / cert auth.
|
||||
raw_read_active: bool,
|
||||
probed: bool,
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ impl Mt1959 {
|
||||
mode,
|
||||
buffer_id,
|
||||
unlocked: false,
|
||||
libredrive_active: false,
|
||||
raw_read_active: false,
|
||||
probed: false,
|
||||
}
|
||||
}
|
||||
@@ -152,14 +152,15 @@ impl Mt1959 {
|
||||
}
|
||||
|
||||
// Raw-read mode is active when BOTH the per-drive signature
|
||||
// matched AND the response carries the secondary `LbDr` marker
|
||||
// repeated through bytes 16..64. The active-mode signature at
|
||||
// [12..16] checked above is the primary gate; the [16..20]
|
||||
// marker is the redundant confirmation Mt1959 firmware writes
|
||||
// through the rest of the response. Requiring both before we
|
||||
// tell the AACS layer "skip the cert dance" keeps any partial
|
||||
// / corrupted response from steering us into the bypass.
|
||||
self.libredrive_active = response.len() >= FIRMWARE_MODE_OFFSET + 4
|
||||
// matched AND the response carries the secondary 4-byte marker
|
||||
// at offset 16, repeated through bytes 16..64. The active-mode
|
||||
// signature at [12..16] checked above is the primary gate; the
|
||||
// [16..20] marker is the redundant confirmation the firmware
|
||||
// writes through the rest of the response. Requiring both
|
||||
// before we tell the AACS layer "skip the cert dance" keeps
|
||||
// any partial / corrupted response from steering us into the
|
||||
// bypass.
|
||||
self.raw_read_active = response.len() >= FIRMWARE_MODE_OFFSET + 4
|
||||
&& response[FIRMWARE_ACTIVE_OFFSET..FIRMWARE_ACTIVE_OFFSET + 4] == FIRMWARE_ACTIVE_SIG
|
||||
&& response[FIRMWARE_MODE_OFFSET..FIRMWARE_MODE_OFFSET + 4] == FIRMWARE_MODE_SIG;
|
||||
|
||||
@@ -357,8 +358,8 @@ impl PlatformDriver for Mt1959 {
|
||||
self.unlocked
|
||||
}
|
||||
|
||||
fn is_libredrive_active(&self) -> bool {
|
||||
self.libredrive_active
|
||||
fn is_raw_read_active(&self) -> bool {
|
||||
self.raw_read_active
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,14 +418,15 @@ mod tests {
|
||||
r[0..4].copy_from_slice(&signature);
|
||||
// bytes [4..12] left as zeros (version + reserved per format)
|
||||
r[12..16].copy_from_slice(&mode_marker);
|
||||
// Real firmware repeats LbDr through [16..64]; the parser only
|
||||
// checks [16..20], so we just write the marker once.
|
||||
// Real firmware repeats the secondary marker through [16..64];
|
||||
// the parser only checks [16..20], so we just write the marker
|
||||
// once.
|
||||
r[16..20].copy_from_slice(&id_marker);
|
||||
r
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn do_unlock_sets_libredrive_active_when_both_markers_present() {
|
||||
fn do_unlock_sets_raw_read_active_when_both_markers_present() {
|
||||
let sig = [0x99, 0x9E, 0xC3, 0x75];
|
||||
let response = build_response(sig, FIRMWARE_ACTIVE_SIG, FIRMWARE_MODE_SIG);
|
||||
let mut transport = ScriptedTransport { response };
|
||||
@@ -434,16 +436,16 @@ mod tests {
|
||||
assert_eq!(raw.len(), 64);
|
||||
assert!(mt.unlocked, "unlocked flag set after success");
|
||||
assert!(
|
||||
mt.is_libredrive_active(),
|
||||
"both MMkv and LbDr present -> libredrive_active"
|
||||
mt.is_raw_read_active(),
|
||||
"both markers present -> raw_read_active"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn do_unlock_unlocked_but_not_libredrive_when_id_marker_missing() {
|
||||
fn do_unlock_unlocked_but_not_raw_read_when_id_marker_missing() {
|
||||
// Active-mode primary marker present (so unlock passes) but the
|
||||
// secondary LbDr marker is replaced with zeros — drive isn't
|
||||
// serving raw-read traffic on this path.
|
||||
// secondary marker is replaced with zeros — drive isn't serving
|
||||
// raw-read traffic on this path.
|
||||
let sig = [0x99, 0x9E, 0xC3, 0x75];
|
||||
let response = build_response(sig, FIRMWARE_ACTIVE_SIG, [0u8; 4]);
|
||||
let mut transport = ScriptedTransport { response };
|
||||
@@ -452,8 +454,8 @@ mod tests {
|
||||
mt.do_unlock(&mut transport).expect("unlock should succeed");
|
||||
assert!(mt.unlocked);
|
||||
assert!(
|
||||
!mt.is_libredrive_active(),
|
||||
"missing LbDr marker -> raw-read not active"
|
||||
!mt.is_raw_read_active(),
|
||||
"missing secondary marker -> raw-read not active"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -470,13 +472,14 @@ mod tests {
|
||||
let err = mt.do_unlock(&mut transport).unwrap_err();
|
||||
assert!(matches!(err, Error::SignatureMismatch { .. }));
|
||||
assert!(!mt.unlocked);
|
||||
assert!(!mt.is_libredrive_active());
|
||||
assert!(!mt.is_raw_read_active());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn do_unlock_rejects_inactive_mode_marker() {
|
||||
// Signature matches but [12..16] is NOT MMkv -> drive is not in
|
||||
// active mode; both unlock and libredrive flag must stay false.
|
||||
// Signature matches but the primary marker at [12..16] is
|
||||
// missing -> drive is not in active mode; both unlock and the
|
||||
// raw-read flag must stay false.
|
||||
let sig = [0x99, 0x9E, 0xC3, 0x75];
|
||||
let response = build_response(sig, [0u8; 4], FIRMWARE_MODE_SIG);
|
||||
let mut transport = ScriptedTransport { response };
|
||||
@@ -485,6 +488,6 @@ mod tests {
|
||||
let err = mt.do_unlock(&mut transport).unwrap_err();
|
||||
assert!(matches!(err, Error::UnlockFailed));
|
||||
assert!(!mt.unlocked);
|
||||
assert!(!mt.is_libredrive_active());
|
||||
assert!(!mt.is_raw_read_active());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user