Commit Graph
35 Commits
Author SHA1 Message Date
Matthew Jackson d05b9bce18 Version sync to 1.6.4 2026-08-15 08:14:31 -07:00
Matthew Jackson 6a8253f889 Release 1.6.3
Version bump and changelog for the 1.6.3 sync. All eight crates ship the
same version, so the crates with no functional change this cycle say so
rather than carrying an empty section.
2026-08-09 20:01:33 -07:00
Matthew Jackson 2684f5f28e base64: match the workspace on 0.23
Every other crate declares 0.23; this one alone said 0.23.1. Cargo
unifies them, so this is uniformity rather than a fix -- but a lone
pinned patch version is the kind of thing that quietly becomes a real
split at the next major.
2026-08-09 18:43:09 -07:00
Matthew Jackson f0d936f4b6 Move to rand 0.10 and aes 0.9
Both are API renames rather than behaviour changes, but this is the AACS
and CSS crypto path, so it is verified by output rather than by the fact
that it compiles.

rand: `RngCore` no longer sits at the crate root -- `fill_bytes` moved to
the re-exported `Rng` trait -- and `thread_rng()` is now `rng()`.

aes: the cipher traits gained their `BlockCipher` prefix and
`generic_array::GenericArray` became `Array`. The obvious translation
uses `Array::from_slice`, which is deprecated in the new version and
would fail clippy's `-D warnings`; these use the `From<[T; N]>`
conversion the crate points at instead.

The proof this is byte-exact is `test_aes_cmac_nist_kat_full_block`,
which checks the exact MAC from NIST SP 800-38B Appendix D.1 -- a wrong
byte order or a mis-sized array cannot produce that value. All 95 tests
pass in both debug and release.
2026-08-09 17:50:01 -07:00
dependabot[bot] 5fd090fc8e build(deps): update sha2 requirement from 0.10 to 0.11 (#5)
Updates the requirements on [sha2](https://github.com/RustCrypto/hashes) to permit the latest version.
- [Commits](https://github.com/RustCrypto/hashes/compare/groestl-v0.10.0...sha2-v0.11.0)

---
updated-dependencies:
- dependency-name: sha2
  dependency-version: 0.11.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-09 16:58:59 -07:00
dependabot[bot] 44bd80e8df build(deps): update num-bigint requirement from 0.4 to 0.5 (#3)
Updates the requirements on [num-bigint](https://github.com/rust-num/num-bigint) to permit the latest version.
- [Changelog](https://github.com/rust-num/num-bigint/blob/main/RELEASES.md)
- [Commits](https://github.com/rust-num/num-bigint/compare/num-bigint-0.4.0...num-bigint-0.5.1)

---
updated-dependencies:
- dependency-name: num-bigint
  dependency-version: 0.5.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-09 16:58:55 -07:00
dependabot[bot] fb3d045509 build(deps): update base64 requirement from 0.22.1 to 0.23.1 (#4)
Updates the requirements on [base64](https://github.com/marshallpierce/rust-base64) to permit the latest version.
- [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.22.1...v0.23.1)

---
updated-dependencies:
- dependency-name: base64
  dependency-version: 0.23.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-09 16:58:52 -07:00
Matthew Jackson 65e02f4b79 v1.6.2: bump version (unified release) 2026-08-08 22:18:13 -07:00
Matthew Jackson 887d154014 v1.6.1: bump version (unified release) 2026-08-07 19:08:30 -07:00
Matthew Jackson 3c535ec874 Sweep the pinned toolchain to Rust 1.97
The Windows UI needs current winsafe, whose real minimum is 1.89 (its manifest
under-declares 1.87 while it uses NonNull::from_ref). Rather than stop at the
minimum, this goes to current stable and fixes what that costs.

The counter-intuitive result: 1.97 is CHEAPER than 1.89. libfreemkv had 54
clippy errors at 1.89 and 6 at 1.97, because clippy tightened the noisy
collapsible_if lint in between. Stopping at the minimum would have been the most
expensive choice available.

Roughly 47 lints across the eight repos, the large majority auto-fixed:
libfreemkv 6, freemkv-engine 14, bdemu 8, freemkv-keysources 7, autorip 6,
freemkv-unlock 3, freemkv-i18n 3. The hand-fixed ones are a descending sort to
sort_by_key(Reverse), four manual checked-division sites, a loop counter replaced
by enumerate, and a loop whose first let-else became a while-let.

Worth recording for whoever bumps next: clippy is MSRV-AWARE. Those 54 lints only
appear once the crate DECLARES 1.89 or later, because let-chains become
available. A bare `cargo +1.89 clippy` against a manifest still pinned at 1.87
reports clean and is meaningless — gate with the real precommit script, which is
also the only thing that covers build scripts.

The pin still sits below the Mac default, so it keeps doing its job: catching
lint drift locally before CI sees it.
2026-07-29 21:00:55 -07:00
Matthew Jackson 21cfb17d11 Pin the toolchain to Rust 1.87
The Windows UI needs winsafe, whose current release requires rustc 1.87. The
alternative was pinning winsafe back to an older release, which would bake a
stale API surface into a brand-new UI permanently to dodge one minor version.

The pin's purpose is to sit BELOW the Mac default so clippy drift is caught
locally before CI, not to stay on 1.86 specifically, so 1.87 preserves the
discipline exactly.

Verified before moving anything, not after: `cargo +1.87 clippy -- -D warnings`
and `cargo +1.87 fmt --check` are clean across all eight repos, and the full
precommit gate (fmt + clippy + tests) passes on libfreemkv, autorip, bdemu,
freemkv-engine and freemkv-keysources. Zero new lints, zero formatting drift.
2026-07-29 20:02:02 -07:00
Matthew Jackson ac94c80163 1.6.0: version sync + fix stale docs
Bump to 1.6.0 (workspace sync, no functional change). Fix the README
example that called the removed matches()/unlock() API — rewrite to the
real unlock_features()/unlock_bus() contract (+ ld/README).
2026-07-28 15:35:19 -07:00
Matthew Jackson 295046054b Rename the DVD read-unlocker: CSS -> DVD
The unlocker performs the DVD bus-auth that clears the drive's
scrambled-read barrier, letting a protected DVD be read at all. That is
a property of the DVD medium, not of the CSS scheme — the descramble key
is recovered keylessly downstream — so naming it "CSS" conflated the
read-enable with the encryption. Rename the struct to DvdUnlocker, its
registry name to "DVD", and the tests to match. Bump 1.5.2.
2026-07-22 13:48:56 -07:00
Matthew Jackson d339108719 v1.5.1: bump version (unified release) 2026-07-20 17:02:02 -07:00
Matthew Jackson c1447a3dae v1.5.0: bump version (unified release) 2026-07-19 15:37:17 -07:00
Matthew Jackson f073c2c3f9 v1.4.5: bump version (unified release) 2026-07-18 16:07:53 -07:00
Matthew Jackson 9e84eeb284 v1.4.4: bump version (unified release) 2026-07-16 21:43:57 -07:00
Matthew Jackson 5aed39a109 v1.4.3: bump version (unified release) 2026-07-16 21:05:53 -07:00
Matthew Jackson 876943a554 v1.4.2: bump version (unified release) 2026-07-15 19:37:43 -07:00
Matthew Jackson 7c3a46897f v1.4.1: bump version (unified release) 2026-07-14 14:45:21 -07:00
Matthew Jackson f2747d5a72 v1.4.0: bump version (unified release) 2026-07-13 19:28:44 -07:00
Matthew Jackson ef432b43ca 1.3.2: version sync
Inherits libfreemkv 1.3.2.
2026-07-10 14:00:35 -07:00
Matthew Jackson fe23557555 1.3.1: relicense to MIT
Relicensed from AGPL-3.0 to MIT, effective 1.3.1 (<=1.3.0 remain AGPL).
Version sync to 1.3.1.
2026-07-10 12:31:19 -07:00
Matthew Jackson 2d7c6b3cec release: bump to 1.3.0 2026-07-08 14:48:50 -07:00
Matthew Jackson 6279fa7fec unlock: split Unlocker into unlock_features/unlock_bus; add Renesas unlocker
Replace the single matches()+unlock() contract with two capability methods — unlock_features (drive riplock/speed/OEM VID at drive-prep) and unlock_bus (AACS/CSS bus-encryption removal for the mounted disc) — each defaulting to NotApplicable so an unlocker implements only what it does.

Add the renesis module: the Renesas-platform unlocker (Pioneer + HL-DT-ST Renesas), detected via the READ_BUFFER 0x02/0xF1 identity probe (ASCII "SAT" marker). Features only; the cert handles the bus.

Add product_id to DriveId. Bump to 1.2.3.
2026-07-07 16:35:57 -07:00
Matthew Jackson 67919326f1 v1.2.2: bump version (unified release) 2026-07-03 20:50:05 -07:00
Matthew Jackson d39b9b8a82 v1.2.1: bump version 2026-07-01 17:30:25 -07:00
Matthew Jackson b91ccfa4f8 Cargo: publish = false (firmware crate — git-tag-only, never crates.io) 2026-06-29 21:04:05 -07:00
Matthew Jackson 817c7285f4 ld: public profile catalog API + emulation feature; clippy-clean
Expose the LibreDrive profile catalog as a curated public API on `ld`:
`ld::profiles()` returns the `Profiles` object (with `.get(drive_id)`) and
`ld::profile(filter)` finds one — the catalog of supported drives, queried
without unlocking. The unlock mechanism (firmware blobs, upload sequence, CDB
wire format) stays private; `LibreDrive` is pub(crate), reached only via
`all_unlockers()`.

The unlock-handshake wire format the bdemu test-emulator needs to impersonate a
drive (`UNLOCK_MARKER`, `is_unlock_read_buffer`) is behind a non-default
`emulation` feature; the `cdb` module compiles only under it. Rename the
`ScsiError` error variant to `Scsi` (matches css), gate the test-only
`load_bundled` and `SCSI_STATUS_CHECK_CONDITION`. Clippy-clean in both feature
configs; 86/89 tests pass.
2026-06-29 20:44:52 -07:00
Matthew Jackson 6c75592387 aacs: relocate the AACS cert handshake into freemkv-unlock
Stage 2: the AACS host-certificate handshake (the AKE + bus-key derivation +
P-160/P-256 EC crypto, ~2050 lines) moves out of libfreemkv into the
self-contained src/aacs module, with its own error type (the Aacs* failure
points + structured ScsiError) and an aes_ecb_decrypt helper. AacsCert impls
crate::Unlocker — matches DiscKind::Aacs, runs run_cert_handshake against the
host certs the consumer passes via UnlockCtx, and returns Unlocked { vid,
bus_key }. collect_host_certs stays in libfreemkv (it reads keysources). The
SCSI contract gains ScsiSense + the AACS/REPORT-KEY opcodes. libfreemkv is
untouched (still green); it rewires onto this in stage 4.

72 tests pass (the handshake brought its full EC-crypto test suite).
2026-06-29 19:33:07 -07:00
Matthew Jackson 7ec8f0316e collapse freemkv-unlock into one crate; ld becomes a module
Replace the ld/aacs/css member-crate workspace with a single freemkv-unlock
crate: the generic Unlocker contract + SCSI transport contract at the crate
root (lib.rs, scsi.rs, error.rs), and the firmware unlocker as the self-
contained src/ld module. The contract is repo-agnostic raw types (DriveId,
HostCert, DiscKind, Unlocked, UnlockError) with NO libfreemkv dependency, so
libfreemkv will depend on this crate (one-way, no cycle) and dispatch via
all_unlockers(). ld now impl crate::Unlocker, takes its own DriveId (4 raw
fields, no INQUIRY parsing), and returns a raw Option<[u8;16]> VID. The old
aacs/css plugin wrappers are removed; their crypto moves in from libfreemkv in
the next stages. 31 tests pass.
2026-06-29 19:11:21 -07:00
Matthew Jackson 06a259f60e aacs: new freemkv-unlock-aacs plugin crate
The AACS host-certificate bus-auth unlocker as a first-class external plugin,
peer to freemkv-unlock-ld and freemkv-unlock-css. AacsUnlocker impls
libfreemkv::Unlocker — matches DiscKind::Aacs, self-guards against the hardware
(refuses NotApplicable without issuing a handshake CDB if the drive reports a
non-Blu-ray profile), gathers host certs from the scan options, and runs the
libfreemkv cert-handshake primitive to learn the Volume ID + bus key. libfreemkv
keeps the handshake + AACS content decryption; this crate owns the unlocker.
Additive: a consuming binary opts in with one register_unlocker(...) line.
2026-06-29 17:33:27 -07:00
Matthew Jackson ed54b2bb01 css: new freemkv-unlock-css plugin crate
The CSS (DVD-Video) bus-auth unlocker as a first-class external plugin, peer
to freemkv-unlock-ld. CssUnlocker impls libfreemkv::Unlocker — matches
DiscKind::Css, self-guards against the hardware (refuses NotApplicable without
issuing a CSS CDB if the drive reports a non-DVD profile), then runs the
libfreemkv bus-auth primitive (unlock_css_reads). libfreemkv keeps the bus-auth
+ keyless descramble; this crate owns the unlocker impl. Additive: a consuming
binary opts in with one register_unlocker(CssUnlocker::new()) line; the in-tree
built-in stays until clients are rewired.
2026-06-29 17:22:50 -07:00
Matthew Jackson 32c14a092d Restructure into freemkv-unlock workspace (ld member + room for more)
libfreemkv owns the Unlocker trait + registry; this repo holds the concrete
unlocker plugins. LibreDrive moves to the ld/ member (package freemkv-unlock-ld
unchanged). Workspace root + repo README describe the general-unlocker model;
adding an unlocker = a new member + one register_unlocker line in the consumer.
libfreemkv dep is the crates.io version; local dev resolves it via the
gitignored .cargo/config.toml patch.
2026-06-22 16:02:57 -07:00
Matthew Jackson 5cec84dfc6 Initial commit: LibreDrive unlocker plugin for libfreemkv
New crate freemkv-unlock-ld — the LibreDrive Unlocker implementation,
split out of libfreemkv so the library stays firmware-clean on crates.io.

Owns everything about HOW MediaTek MT1959 drives are firmware-unlocked:
  - profiles.json (the bundled drive-profile database + DriveProfile parse)
  - src/platform/mt1959/* (variant-A/B firmware upload + unlock handshake)
  - WRITE_BUFFER / MODE SELECT upload, unlock CDBs, disc-speed calibration

Exposes LibreDrive::new() implementing libfreemkv::Unlocker (name/matches/
unlock). Plug it in with one line at process start:

  libfreemkv::register_unlocker(Box::new(freemkv_unlock_ld::LibreDrive::new()));

Depends on libfreemkv (path-patched via gitignored .cargo/config.toml in
dev) for the trait, ScsiTransport, DriveId, and Result. README notes it's
the LibreDrive unlocker (attribution to be added by owner).
2026-06-22 10:32:00 -07:00