css: redact CssState Debug (test-guarded)
CssState is reachable via the public Disc.css field; #[derive(Debug)] leaked the
raw CSS title key on any {:?} of a Disc. Manual Debug prints crack_span only.
This commit is contained in:
+30
-1
@@ -29,7 +29,7 @@ use crate::sector::SectorSource;
|
|||||||
const CSS_LOCKED_BAIL: u32 = 64;
|
const CSS_LOCKED_BAIL: u32 = 64;
|
||||||
|
|
||||||
/// CSS decryption state for a DVD title.
|
/// CSS decryption state for a DVD title.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CssState {
|
pub struct CssState {
|
||||||
/// 5-byte CSS title key (from SCSI auth or the crack fallback).
|
/// 5-byte CSS title key (from SCSI auth or the crack fallback).
|
||||||
pub title_key: [u8; 5],
|
pub title_key: [u8; 5],
|
||||||
@@ -43,6 +43,18 @@ pub struct CssState {
|
|||||||
pub crack_span: Option<(u32, u32)>,
|
pub crack_span: Option<(u32, u32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Redacting `Debug`: `CssState` is reachable via the public `Disc.css` field, so
|
||||||
|
// a `{:?}` on a `Disc` would otherwise print the raw CSS title key. Print only
|
||||||
|
// the (non-secret) crack span. Guarded by `css_state_debug_is_redacted`.
|
||||||
|
impl std::fmt::Debug for CssState {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("CssState")
|
||||||
|
.field("title_key", &"<redacted>")
|
||||||
|
.field("crack_span", &self.crack_span)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Recover the CSS title key with no keys, by scanning scrambled sectors and
|
/// Recover the CSS title key with no keys, by scanning scrambled sectors and
|
||||||
/// running the Stevenson known-plaintext attack (see the [`stevenson`] module).
|
/// running the Stevenson known-plaintext attack (see the [`stevenson`] module).
|
||||||
///
|
///
|
||||||
@@ -364,6 +376,23 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
|
|
||||||
|
/// `CssState` is reachable via the public `Disc.css` field, so a `{:?}` on a
|
||||||
|
/// `Disc` must not print the raw CSS title key. Sentinel byte 213 (0xD5);
|
||||||
|
/// `crack_span` is non-secret and none of its values are 213.
|
||||||
|
#[test]
|
||||||
|
fn css_state_debug_is_redacted() {
|
||||||
|
let s = CssState {
|
||||||
|
title_key: [0xD5; 5],
|
||||||
|
crack_span: Some((10, 20)),
|
||||||
|
};
|
||||||
|
let dbg = format!("{s:?}");
|
||||||
|
assert!(
|
||||||
|
!dbg.contains("213"),
|
||||||
|
"CssState Debug leaked the title key: {dbg}"
|
||||||
|
);
|
||||||
|
assert!(dbg.contains("redacted"), "CssState Debug missing marker: {dbg}");
|
||||||
|
}
|
||||||
|
|
||||||
// ── is_scrambled ───────────────────────────────────────────────────────
|
// ── is_scrambled ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
/// is_scrambled returns false for any buffer shorter than one sector,
|
/// is_scrambled returns false for any buffer shorter than one sector,
|
||||||
|
|||||||
Reference in New Issue
Block a user