Commit Graph
181 Commits
Author SHA1 Message Date
Matthew Jackson 11d6e19ae2 ci: consumers path-patch; monthly grouped dependabot; actions/checkout 7
The consumers job path-patches this commit into libfreemkv and bdemu.
Dependabot runs monthly with grouped version updates.
actions/checkout 5 -> 7 in ci and qa (#15).
v1.7.7-rc4
2026-10-03 11:15:58 -07:00
Matthew Jackson 2ee8c0b0a6 stop: Stop-aware unlock operations
ScsiTransport gains Stop methods; AGIDs are handed off by AgidGuard,
CSS is defused on Stop and MT1959 critical spans are guarded, and the
post-upload readiness poll waits via pause so a Stop ends it.
A test guards the op paths against bare sleeps.
2026-09-28 08:42:29 -07:00
Matthew Jackson 8473c89201 mt1959: run_init confirms the unlock, then waits for media ready
run_init returns Ok once load_firmware confirms the unlock, then polls
for media ready, bounded by stalls rather than a total. The poll never
undoes a confirmed unlock and treats MMC-6 terminal states as final.
2026-09-28 00:01:08 -07:00
Matthew Jackson 5c4a6c4094 firmware: gate recipes and freemkv unlock on a supported IDENTITY
Firmware recipes and the freemkv unlock run only for a supported
IDENTITY, with an accurate fw 0.7/0.8 rationale and reply shape.
css and renesas share is_dead_bus; no P-256 retry is claimed for 0x11
drive certs; handshake diagnostics log below WARN; tests pin the error
variants, the v2 cert gate and the 132-byte v2 boundary.
CI: doc-links, doctests, a consumers job, read-only token; rand 0.10.3.
2026-09-27 17:50:56 -07:00
Matthew Jackson 0a37381a63 aacs, ld, css: tighter drive-cert handling and exact product matching
The AACS cert loop classifies failures more tightly, carries forward only
a recognised drive-cert failure and gates the read data key on BEC.
ld: an exact product_id match wins across all profile sections.
css: crypt_key bounds tests assert the panic message.
2026-09-27 00:28:28 -07:00
Matthew Jackson 1d20be4a41 Prepare 1.7.7 with concise comments and shared CI policy v1.7.7 v1.7.7-rc1 2026-09-26 11:46:30 -07:00
Matthew Jackson 965c1f984c v1.7.6: bump version (unified release) v1.7.6 v1.7.6-rc6 2026-09-26 04:05:33 +00:00
Matthew Jackson e51fda9bcd docs: move drive/firmware internals notes to the private repo; drop their pointers [skip-media] v1.7.6-rc5 2026-09-25 16:48:30 -07:00
Matthew Jackson 35cb630af9 docs(changelog): 1.7.6 entry names the Feature::Bd retirement + Uhd→Unrestricted rename [skip-media] v1.7.6-rc4 2026-09-25 12:59:30 -07:00
Matthew Jackson e6786692b3 chore: absorb qa into dev for lockstep promote [skip-media] v1.7.6-rc3 2026-09-25 12:25:42 -07:00
Matthew Jackson 8caf9e7b69 v1.7.6: bump version (unified release) v1.7.6-rc2 2026-09-25 05:31:54 +00:00
Matthew Jackson b77e7e8aac chore(qa): gate 1.7.6 promote — media matrix not needed [skip-media]
The 1.7.6 unified release ships no rip-path change (Linux desktop shell,
notifications, menu_layout refactor, XDG paths). Real-media QA on EC2
adds ~2h + real money to the release cycle to prove code that never
enters the rip pipeline. This empty commit puts `[skip-media]` in qa's
HEAD so the media matrix in qa.yml auto-skips per the documented bypass;
the full-platform builds/tests still run.
v1.7.6-rc1
2026-09-24 21:37:24 -07:00
Matthew Jackson 94471641e3 chore(qa-sync): absorb qa's post-1.7.5 release commits into dev
Release-orchestrate committed to qa (v1.7.5 version bump, etc.) but did
not push those commits back to dev, so promote's fast-forward gate
refused (qa was diverged from dev). This is an ours-merge: the commit
records qa as an ancestor of dev without applying its content, since
dev has already moved past 1.7.5 to 1.7.6 with the equivalent
information in place.
2026-09-24 21:21:10 -07:00
Matthew Jackson c7e7aa63a0 unlock: trim Unrestricted doc + Recipe NOTE to satisfy comment-guard 2026-09-24 20:43:05 -07:00
Matthew Jackson 89861e6f40 unlock: drop Feature::Bd, rename Uhd→Unrestricted (mirror fw 0.9.2 ABI) 2026-09-24 20:40:56 -07:00
Matthew Jackson eef8e958fc chore(release): bump to 1.7.6, follow the CI-required release-notes shape
Bumps Cargo.toml + Cargo.lock to 1.7.6. Also fixes a CI-shape defect the
previous release left behind: dev's CHANGELOG still said
`## [1.7.5] — UNRELEASED` after 1.7.5 shipped (release-orchestrate dated
main but did not push a fresh UNRELEASED heading back to dev). Corrects
that here so the changelog job accepts 1.7.6 on the way to qa:

  ## [1.7.6] — UNRELEASED
    - Version aligned; unified release driven by freemkv 1.7.6.
  ## [1.7.5] — 2026-09-23
    - Version aligned (or actual content, per the shipped main entry).

The driver for 1.7.6 is the freemkv Linux desktop shell (GTK4 +
libadwaita) + rip-finished desktop notification (issue #56).
2026-09-24 20:23:08 -07:00
Matthew Jackson d6607ba963 v1.7.5: bump version (unified release) v1.7.5 v1.7.5-rc1 2026-09-23 04:40:48 +00:00
Matthew Jackson 89f202edbc style: trim three comment blocks under the central guard caps v1.7.4-rc7 2026-09-22 20:39:41 -07:00
Matthew Jackson e107c699d1 firmware: retire Ake+Bus into one Encryption lever (fw 0.9.0 ABI)
Firmware 0.9.0 consolidates the Ake (0x06) and Bus (0x07) features into a
single Encryption (0x06) lever; wire id 0x07 no longer exists. The separate
Bus lever was proven inert on BU40N/MT1959 — the one Encryption lever
de-busses on its own — so the unlock recipe now sets one flag where it used
to set two, and the trailing best-effort Set(Bus, off) is gone.

Set(Encryption, STATE_OFF) is the load-bearing step: the drive acts
pre-authenticated, so a bare 0xAD returns the VID with no cert and no AKE,
and content comes back de-bussed. Failure still maps to VidUnavailable.

Hardware-validated against fw 0.9.0 on BU40N 1.00 with a UHD disc: every
sampled unit returns de-bussed and opens with the AACS unit key resolved
from the live keyserver.
2026-09-22 20:32:22 -07:00
Matthew Jackson d257d40de9 v1.7.4: bump version (unified release) v1.7.4 v1.7.4-rc6 2026-09-21 23:03:29 +00:00
Matthew Jackson 56c69e8877 docs: mark 1.7.4 changelog heading UNRELEASED (release workflow dates it) v1.7.4-rc5 2026-09-21 15:07:05 -07:00
Matthew Jackson 2c9d76235d docs: 1.7.4 changelog + consumer release notes v1.7.4-rc4 2026-09-21 11:47:20 -07:00
Matthew Jackson 1a916f0855 docs/ci: drop stale local-precommit/release.sh references — CI is the only gate v1.7.4-rc3 2026-09-21 09:11:34 -07:00
Matthew Jackson 609f3bc0bc ci: adopt central reusable guards + top-level concurrency
Replace comment/leak/identity guard workflows with thin callers into
freemkv/.github reusable guards (guard-comment/leak/identity @v1); fork
PRs still run, same-repo pushes aren't double-run. Delete now-unused
local ci/comment-guard.py and ci/leak-guard.sh. Add top-level
concurrency (cancel-in-progress) to ci.yml and qa.yml and standardize
actions/checkout to @v5.
v1.7.4-rc2
2026-09-21 08:47:07 -07:00
Matthew Jackson 58c667314c freemkv-unlock 1.7.4: Hrl=off in arm_bypass recipes + version
arm_bypass_bd/arm_bypass_uhd now also Set(Hrl, off) (revocation skip) so a
revoked/absent cert never trips the HRL check on a keyless bypass rip; tests
updated for the new SET/verify order.
v1.7.4-rc1
2026-09-19 14:00:25 -07:00
Matthew Jackson 98ef26f78c v1.7.3: bump version (unified release) v1.7.3 v1.7.3-rc1 2026-09-19 05:31:07 +00:00
Matthew Jackson 93d9517964 merge: record v1.7.2 release into dev (-s ours; keep path deps + dev's next-cycle work) v1.7.1-rc10 2026-09-18 21:39:15 -07:00
Matthew Jackson 64a53b8349 firmware: mirror fw 0.8.3 RESET ABI — RESET_TO_DEFAULTS (0x01) + reset_to_defaults(), true-OEM/marker-gated docs 2026-09-18 21:23:07 -07:00
Matthew Jackson f434298e0d v1.7.2: bump version (unified release) v1.7.2 v1.7.2-rc4 2026-09-18 18:37:18 +00:00
Matthew Jackson a18bc90164 freemkv: source the SET data-in buffer from MIN_ALLOC_LEN (single source for the transfer length) v1.7.1-rc9 2026-09-18 09:52:27 -07:00
Matthew Jackson 79f3324488 changelog: 1.7.2 — record the SET data-phase unlock fix + READ CAPACITY/empty-ISO hardening v1.7.1-rc8 2026-09-18 06:54:58 -07:00
Matthew Jackson 0842babe2d freemkv: SET must issue the data-in phase the firmware requires
FreemkvUnlocker::set sent the vendor SET with DataDirection::None + an
empty buffer, but the SET CDB advertises a MIN_ALLOC_LEN (64B) data-in
allocation and the drive ABORTS a no-data transfer (CHECK CONDITION /
Aborted Command — HW-confirmed on BU40N fw 0.8.1). Every Set(feature)
failed, so the load-bearing Set(Ake,off) failed and the whole freemkv
unlock aborted, silently falling back to the AACS/online key route
(autorip showed 'Unlockers — freemkv: no'). Mirror the working
FirmwareControl::set (exec_in): read the state table back over a
FromDevice phase and ignore it. Adds a regression test modelling the
drive's abort-without-data-phase contract.
v1.7.1-rc7
2026-09-18 06:19:49 -07:00
Matthew Jackson 638b86acb6 merge: record v1.7.1 main into dev (dev already at 1.7.1; keep path deps) v1.7.1-rc6 2026-09-17 23:08:04 -07:00
Matthew Jackson 3c0c335840 deps: sha1 0.10→0.11 (RustCrypto 0.11 wave; MSRV-safe, 1.85) 2026-09-17 22:18:07 -07:00
Matthew Jackson f97ebb450b changelog: open 1.7.2 (firmware ABI v2); comment-guard: trim inline blocks to cap (comments only) 2026-09-17 14:35:43 -07:00
Matthew Jackson 47bb6a7ac3 firmware: mirror ABI v2 — Save + RESET modes, region/speed encodings, HRL/AKE/BUS off=unlock; flip full_unlock default profile
Mirrors freemkv-fw/src/abi.rs; drift-guard pins updated. 310 tests green.
2026-09-16 11:18:44 -07:00
Matthew Jackson eeb36bf389 expose read_aacs_vid — public bare VID read for the hw-tester no-cert-sent assert 2026-09-15 20:41:44 -07:00
Matthew Jackson 4459af4e2f firmware: SET/RESET need a data-in phase (drive aborts no-data verbs); IDENTITY is a version banner, not a binary state table 2026-09-15 18:02:22 -07:00
Matthew Jackson f1801351e2 firmware: floor vendor-command allocation to MIN_ALLOC_LEN — drive aborts sub-16-byte data-in (HW-confirmed) 2026-09-15 17:20:51 -07:00
Matthew Jackson 7da4b3bba4 freemkv-unlock: de-expose HRL wipe-once — deferred, removed from public ABI
Remove the HRL_WIPE_ONCE const, the wipe_hrl_once() setter, and their tests/doc references from the host library so wipe-once is no longer part of the host-facing firmware ABI. HRL exposes only skip (0x01).
2026-09-15 17:06:14 -07:00
Matthew Jackson b4e5d90c81 firmware: mirror BD-disable wire change to STATE_BD_DISABLE (0x02)
Lockstep with freemkv-fw BD-refuse stealth fix: the BD force-disable wire
value moves from STATE_OFF (0x00, the SRAM boot value) to a distinct
sentinel STATE_BD_DISABLE (0x02), so an unarmed firmware image stays
OEM-identical. disable_bd() now sends 0x02; add the const and align the
Feature::Bd / Feature::Uhd ABI-mirror docs (enable dir / STATE_OFF are
OEM no-ops).
2026-09-15 14:15:39 -07:00
Matthew Jackson bce5f36ef2 aacs: honor allow_p256 in up-front cert-skip gate + zeroize key material
Fix two re-audit findings:

1. LOW (correctness): run_cert_handshake_with_anchors computed the
   up-front cert-skip has_v2 gate WITHOUT allow_p256, unlike
   attempt_one_cert. In production (allow_p256=false) a dead-v1 cert
   carrying v2 creds was not skipped up front, reached the drive, failed
   the step-7 self-verify, and consumed a MAX_CERT_ATTEMPTS slot -- so
   [dead+v2 x3, valid] exhausted the cap and never tried the valid cert.
   Mirror attempt_one_cert's gate exactly. Add a regression test.

2. LOW (key hygiene): add the zeroize crate and wipe sensitive key
   material on drop -- HostCert private keys, AacsAuth/CertHandshake
   derived bus_key/volume_id/read_data_key (ZeroizeOnDrop, non-secret
   fields skipped), the ephemeral AKE scalars and raw private-scalar byte
   buffers (Zeroizing). BigUint scalars/shared-x are a documented
   best-effort residual (num-bigint exposes no zeroization). Debug
   redaction and the EC math are untouched.
2026-09-15 14:02:45 -07:00
Matthew Jackson 8d60463539 aacs+css: fix v1.6.0→dev audit findings
MEDIUM (coupled):
- aacs/handshake: on the AACS 1.0 path a type-0x11 drive cert is now
  REJECTED (verify_cert + step-6 drive-key signature always run) instead
  of accepted unverified — the old 0x11-skip did neither yet still ran
  ECDH, an attacker-chosen-bus-key hole. run_cert_handshake routes a
  genuine 0x11 drive to the native P-256 AKE via the v2-cred fallback.
- aacs/handshake: a post-auth VID/MAC failure (AacsVidMac) with v2 creds
  present now falls through to aacs2_authenticate_p256 instead of a
  terminal VidUnavailable, so a backward-compat 2.0 drive that fails the
  1.0 VID MAC still reaches the P-256 path.

LOW:
- Gate the native AACS 2.0 (P-256) path behind AACS2_P256_EXPERIMENTAL
  (default off) at the run_cert_handshake boundary: its cert offsets are
  provisional, so production can't silently mis-verify a real disc.
- Release the AGID on the fully-successful handshake too (was leaked,
  slowly draining the drive's 4-AGID pool).
- Rejection-sample the ephemeral ECDH private key (drop the modulo bias
  of raw % n) in both generate_host_key_pair{,_p256}.
- Guard shared.infinity in compute_bus_key{,_p256} (return None).
- Remove the dead, truncating AacsAuth.drive_cert field.
- Wire UnlockError::NoUsableHostCert for the all-certs-skipped / empty
  path (more accurate than HandshakeRejected).
- css: promote crypt_key's debug_assert! bounds checks to real assert!.

Handshake tests reworked onto an anchor-parametrised seam
(run_cert_handshake_with_anchors / *_with_anchor) so the DriveEmu drives
a genuine LA-signed 1.0 AKE under a self-generated test anchor; adds the
0x11-rejection, VID-MAC→P-256 fallback (HybridDrive), AGID-release,
infinity-guard, NoUsableHostCert and crypt_key-assert tests.
2026-09-15 10:31:26 -07:00
Matthew Jackson a7622678f3 firmware: typed FirmwareControl API mirroring the abi.rs vendor grammar
Add src/firmware: a hand-kept mirror of freemkv-fw/src/abi.rs (Verb/Feature
enums with pinned repr(u8) values, state constants, CDB builders) plus an
ergonomic FirmwareControl<&mut dyn ScsiTransport> with identity/get/set/reset/
dump, typed setters, states(), and the named recipes (arm_oem_bd, arm_oem_uhd,
arm_bypass_bd, arm_bypass_uhd, arm_stealth_oem). A drift test pins every wire
value against abi.rs.

Migrate FreemkvUnlocker off the old SubFn frame onto the new verb/feature
grammar via the shared builders (region-free=Set(Region,on),
riplock=Set(Speed,max), transport unlock=Set(Ake,null), bus-off=Set(Bus,off)).

Wire opt-in arming into AacsUnlocker::arm_before_unlock (OFF by default): when
set, unlock() detects freemkv via IDENTITY and applies a recipe before the AKE;
a non-freemkv drive or a refused recipe is left untouched.
2026-09-15 00:02:47 -07:00
Matthew Jackson ef3a32eca2 aacs: host-cert keypair-validity check + cert-selection fallback
Add `aacs1_keypair_matches(private_key, cert)` — true iff a stored AACS 1.0
host private key matches its certificate's public key (`priv·G ==
cert_pub_key`), reusing the live handshake's own curve math. A genuine,
LA-signed cert can still be paired in a keydb with the wrong private key,
which never establishes a bus key ("KEY NOT ESTABLISHED"); this primitive
distinguishes that DEAD pairing from a live one. Exposed for the key
service's host-cert health gate. Add `AacsHostSignVerify` (code 7016) for a
host-side self-verify guard on our own produced signature.

Also rework `run_cert_handshake` cert selection: on a rejected/revoked cert
the handshake now backs off and tries the next candidate instead of failing,
with a `cert_host_id_hex` helper and DriveEmu extensions + tests covering
single-valid, back-off-to-second, and roll-past-revoked paths.
2026-09-14 23:25:39 -07:00
Matthew Jackson edb8be09ec v1.7.1: bump version (unified release) v1.7.1 v1.7.1-rc5 2026-09-14 03:34:43 +00:00
Matthew Jackson 32a41fe939 freemkv: trim bus-off comment blocks to comment-guard caps v1.7.1-rc4 2026-09-13 20:21:59 -07:00
Matthew Jackson 8533038e62 freemkv: issue trailing best-effort Raw Read 04 03 (bus-off) in full_unlock; add set_bus_off 2026-09-13 20:20:38 -07:00
Matthew Jackson 6b6c3be1dc docs(changelog): 1.7.1 release notes (LibreDrive unlock fix) v1.7.1-rc3 2026-09-13 20:01:00 -07:00
Matthew Jackson 422147f6ad ci: bump actions/checkout v4->v7 in identity-guard (dependabot) v1.7.1-rc2 2026-09-13 18:30:58 -07:00