mirror of
https://github.com/freemkv/freemkv-unlock.git
synced 2026-10-07 18:13:11 +00:00
eaa158c3792857a46f7916dbfc446858a42f1845
The 2.0 host-cert handshake is now live and cert-agnostic (works when a cert is supplied), with the same chain-of-trust hardening as 1.0; the SECURITY note is resolved by fixing, not by leaving dead. - Remove the module-level #[allow(dead_code)]; the P-256/v2 AKE is now reachable from run_cert_handshake. - run_cert_handshake selects the P-256 AKE per host cert: the 1.0 cert is tried first (an AACS 2.0 drive accepts it for the VID); if the drive refuses it AND the supplied HostCert carries AACS 2.0 (P-256) credentials, fall back to the native P-256 AKE. No possession/feature gate — it consumes whatever the HostCert carries, exactly as the 1.0 path consumes hc.certificate. A 1.0-attempt transport fault short-circuits the fallback so a dead bus is not hammered. - Chain-of-trust hardening on the now-live v2 path, mirroring 1.0: drive-cert TYPE gate (only 0x11 accepted, else rejected), cert verify is FATAL (verify_cert_p256 under the real 2.0 LA anchor), ECDSA-P256 point validation on every attacker-supplied point (point_on_curve in ecdsa_verify_p256 + compute_bus_key_p256), and AGID release on every exit. - The 2.0 cert byte layout/signed-range is documented as PROVISIONAL: no genuine 2.0 host/drive AKE cert exists to pin it, and the draft spec implies extra Host-ID/paired-DKS fields. A wrong signed range fails CLOSED (fatal verify rejects), never trusts. An #[ignore] slot awaits a real cert. - Tests: synthetic test-LA-signed 2.0 certs prove accept + bus-key derivation, bad-signature fatal reject, unknown-type reject, and off-curve/identity rejection (each red-before-green per guard); a genuine AACS 2.0 content cert verifies under the published CC key, proving the P-256/SHA-256 primitive against real material.
freemkv-unlock
The unlock layer for the freemkv toolchain.
An unlocker removes a drive-level bus-encryption barrier so the drive serves readable (de-bus'd / de-scrambled) sectors. Content-key decryption is a separate concern — the consumer's job.
This crate defines the Unlocker contract and a generic SCSI transport
contract, and holds the self-contained unlocker modules. The consumer
(libfreemkv) depends on this crate and
dispatches through all_unlockers(); it never names an individual unlocker, and
clients of libfreemkv are oblivious to unlockers entirely (as they are to the
SCSI layer).
use freemkv_unlock::UnlockError;
// Drive-prep: try each unlocker's feature unlock until one claims the drive.
// `NotApplicable` means "not this unlocker's drive" — move on; a transport
// error means a dead bus — abort. `unlock_bus` follows the same contract for
// removing per-disc bus encryption.
for u in freemkv_unlock::all_unlockers() {
match u.unlock_features(&mut scsi, &ctx) {
Ok(unlocked) => return Ok(unlocked),
Err(UnlockError::NotApplicable) => continue,
Err(e) => return Err(e),
}
}
To remove an unlocker, delete its module directory and its one line in
all_unlockers() — nothing else changes.
License: MIT.
Languages
Rust
100%