From f9d9b1cd5677f430d2b38082a7860714aa9caf82 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 00:14:13 +0300 Subject: [PATCH 01/33] Add the nRF52840 MDK dongle as the primary board - New board folder firmware/boards/nrf52840-mdk-dongle: USB CDC, flash via the factory UF2 bootloader, image through llvm-objcopy; vkey check passed. - Argon2 cost is the board's: Device::new takes KDF_COST (20 passes on the nRF52840, 48 on the C6-Zero); Cost::CURRENT is gone. - INFO gains a chip line on the nRF52840 (build code, UICR APPROTECT, last reset cause); vkey info and vkey check print it. The chip is revision 2. - CLI: refuse to guess between two plugged-in keys; refuse auth enable on a key without a chip key before writing anything; extract file::replace. - Build: radio_base search for boards whose radio driver hides in the HAL; sign only Secure Boot boards; CI clippy over every board folder. - Ignore RUSTSEC-2026-0344 (ruzstd via espflash, unreachable) with its exit condition in cli/.cargo/audit.toml. - Docs: two boards in CLAUDE.md and the README, the nRF section of the threat model with the accepted revision-2 risk, docs2/roadmap.md. - Re-sign the C6 images. --- .github/workflows/ci.yml | 10 +- CLAUDE.md | 126 ++++-- README.md | 9 + cli/.cargo/audit.toml | 12 + cli/src/auth.rs | 43 +- cli/src/check.rs | 8 +- cli/src/device.rs | 53 ++- cli/src/file.rs | 28 ++ cli/src/main.rs | 4 + cli/src/op.rs | 4 +- cli/src/setup.rs | 7 +- cli/src/shell.rs | 2 +- cli/src/sources.rs | 4 +- docs/threat-model.md | 50 +- docs2/makerdiary.md | 421 +++++++++++++++++ docs2/roadmap.md | 232 ++++++++++ firmware/Cargo.lock | 264 ++++++++++- firmware/boards/esp32c6-zero/board.toml | 3 +- .../images/bootloader-sb.signed.bin | Bin 45056 -> 45056 bytes .../boards/esp32c6-zero/images/vaultkey.bin | Bin 263568 -> 263936 bytes .../esp32c6-zero/images/vaultkey.signed.bin | Bin 270336 -> 270336 bytes firmware/boards/esp32c6-zero/src/main.rs | 15 +- .../nrf52840-mdk-dongle/.cargo/config.toml | 3 + .../boards/nrf52840-mdk-dongle/Cargo.toml | 65 +++ .../boards/nrf52840-mdk-dongle/board.toml | 29 ++ firmware/boards/nrf52840-mdk-dongle/build.rs | 13 + .../nrf52840-mdk-dongle/images/vaultkey.bin | Bin 0 -> 77100 bytes firmware/boards/nrf52840-mdk-dongle/memory.x | 17 + .../boards/nrf52840-mdk-dongle/src/main.rs | 428 ++++++++++++++++++ firmware/core/src/device.rs | 21 +- firmware/core/src/hal.rs | 6 +- firmware/core/src/item.rs | 2 +- firmware/core/src/proto.rs | 9 +- firmware/core/src/store.rs | 128 ++++-- firmware/core/src/vault.rs | 34 +- firmware/core/src/wire.rs | 2 + firmware/core/tests/key.rs | 49 +- rust-toolchain.toml | 7 +- tools/build-vaultkey.sh | 63 ++- tools/checks.sh | 13 +- tools/sign-vaultkey.sh | 10 +- 41 files changed, 2003 insertions(+), 191 deletions(-) create mode 100644 cli/.cargo/audit.toml create mode 100644 cli/src/file.rs create mode 100644 docs2/makerdiary.md create mode 100644 docs2/roadmap.md create mode 100644 firmware/boards/nrf52840-mdk-dongle/.cargo/config.toml create mode 100644 firmware/boards/nrf52840-mdk-dongle/Cargo.toml create mode 100644 firmware/boards/nrf52840-mdk-dongle/board.toml create mode 100644 firmware/boards/nrf52840-mdk-dongle/build.rs create mode 100755 firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin create mode 100644 firmware/boards/nrf52840-mdk-dongle/memory.x create mode 100644 firmware/boards/nrf52840-mdk-dongle/src/main.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad8b97d..56b6fe1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,9 +45,13 @@ jobs: cargo fmt --check --manifest-path cli/Cargo.toml - name: clippy - firmware core run: cargo clippy -p vaultkey-core --all-targets --locked -q --manifest-path firmware/Cargo.toml -- -D warnings - - name: clippy - board - working-directory: firmware/boards/esp32c6-zero - run: cargo clippy --locked -q -- -D warnings + - name: clippy - every board folder + run: | + for d in firmware/boards/*/; do + [ -f "$d/board.toml" ] || continue + echo "== $d" + (cd "$d" && cargo clippy --locked -q -- -D warnings) + done - name: clippy - cli run: cargo clippy --all-targets --locked -q --manifest-path cli/Cargo.toml -- -D warnings - name: rustdoc diff --git a/CLAUDE.md b/CLAUDE.md index bd4002c..16f028d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,7 +1,9 @@ # Project rules -**vaulttecdev** — a hardware key on ESP32-C6: TOTP codes, passwords and project `.env` -files. One board, own code. +**vaulttecdev** — a hardware key for TOTP codes, passwords and project `.env` files, own +code. Two boards: the Makerdiary nRF52840 MDK USB Dongle (primary, not yet for real +secrets) and the Waveshare ESP32-C6-Zero (fallback, holds the maintainer's secrets until +the migration in `docs2/roadmap.md`). | Part | What it is | |---|---| @@ -13,7 +15,16 @@ files. One board, own code. Decision of 2026-09-07. The key is built for the maintainer's own accounts. Sales, production runs, enclosures, provisioning, certifications and marketing are **not built and -not proposed** unless the maintainer says otherwise. Passkey/WebAuthn is closed permanently. +not proposed** unless the maintainer says otherwise. Passkey/WebAuthn was closed because the +C6 has no USB HID; reopened 2026-10-03 for the nRF52840 board on Trussed + +`fido-authenticator`, not an own CTAP2 (maintainer's decision, `docs2/makerdiary.md`). It +never exists on the C6. + +**The nRF52840 board is the primary board; the C6 is the fallback** (maintainer's +decision, 2026-10-13). Code is shaped for the nRF first. Nothing is kept only so the C6 +works. A C6 need that remains is driven by its board folder or `board.toml`, not by +shared code. Real secrets move to the nRF at security parity, not when features are done +(`docs2/roadmap.md`). Consequence for code: "convenience for a buyer" is not an argument; security of the maintainer's own secrets and minimal code are. @@ -98,8 +109,11 @@ This is a security device. The rules below are not recommendations. that as dead code). - **Never log** keys, PINs or secrets. Not even in a debug build: a debug build eventually ships. -- **Randomness comes only from `Trng` with `TrngSource` enabled.** Without it the RNG - register is not random. The handle lives for the whole runtime. +- **Randomness comes only from the chip's hardware RNG, set up as the chip requires.** On + the nRF52840 it is the RNG peripheral with bias correction, which + `nrf52840_hal::rng::Rng::new` switches on. On the C6 it is `Trng` with `TrngSource` + enabled - without it the RNG register is not random - and the handle lives for the whole + runtime. - **Validate every input** that arrives over USB. The host is assumed hostile. - **Fail closed.** If anything goes wrong, the operation does not happen. - **Spend the PIN attempt before checking, not after.** Otherwise cutting power mid-check @@ -121,29 +135,47 @@ This is a security device. The rules below are not recommendations. ### A board is a folder A new board is `firmware/boards//` and nothing else: copy an existing folder, -**measure the pins with a probe** (never copy from the datasheet — silent breakage), fix -`main.rs`, the chip crates, the target and `board.toml`. `./tools/build-vaultkey.sh` builds +**confirm every pin on the board itself** - with a probe, or by watching it work (the LED +lights, the button registers) - never trust the datasheet or wiki alone (silent breakage), +fix `main.rs`, the chip crates, the target and `board.toml`. There is no SWD probe and +there will not be one: anything that needs it is off the table. `./tools/build-vaultkey.sh` builds it and embeds its images into the CLI. Acceptance is the same as for any board. Core requires flash with a 4 KiB sector and word-aligned 4-byte reads and writes (checked in `Store::new`; the fake flash in tests rejects unaligned access too, because `esp-storage` -without `bytewise-read` behaves that way). Everything else is the board folder's business. - -The one board today is the Waveshare ESP32-C6-Zero: USB is a fixed Serial/JTAG -(`303a:1001`), HID is impossible, so passkey will never exist here; one port carries both -the protocol and logs — hence the `VTC2` magic word in frames. Pins and pitfalls: -`docs/hardware.md`. +without `bytewise-read` behaves that way), and writes a word at most twice between erases +(the nRF52840's limit; the fake flash refuses a third write). Everything else is the board +folder's business. + +The boards: + +- **`nrf52840-mdk-dongle`**, the primary. USB CDC-ACM from the firmware (`1209:0001`), + polled; the factory UF2 bootloader (Adafruit-based, 0x1000..0xF4000 is the application) is + how it is flashed: hold the button while plugging in, copy a UF2 (family `0xADA52840`, + base 0x1000) to `UF2BOOT`, replug. No chip key, so it holds no real secrets yet. `vkey + info` prints the chip's build code, UICR `APPROTECT` and last reset cause. Notes, + measurements and factory state: `docs2/makerdiary.md`; the plan: `docs2/roadmap.md`. +- **`esp32c6-zero`**, the fallback, holding the maintainer's secrets until the migration. + USB is a fixed Serial/JTAG (`303a:1001`), HID is impossible, so passkey will never exist + here; one port carries both the protocol and logs — hence the `VTC2` magic word in + frames. Pins and pitfalls: `docs/hardware.md`. ### Firmware design -- Crates: `esp-hal` (features `esp32c6`, `rt`, `unstable`), `esp-storage`, - `esp-hal-smartled`, `esp-println` (`jtag-serial`), `esp-backtrace`; RustCrypto: - `aes-gcm`, `argon2`, `hmac`, `sha1`, `sha2`, `subtle`, `zeroize`; `ed25519-dalek` (built on - RustCrypto's `signature` and `sha2`) for `vkey auth`; `crc`. Not - `esp-idf-hal`, not own crypto, not `esp-radio`. Toolchain: stable rustup with target - `riscv32imac-unknown-none-elf`; no espup, no compiler fork. Read exact API signatures in - `~/.cargo/registry/src/*/esp-hal-*/src/` rather than recalling them. -- Keys: pre = Argon2id(PIN, salt; 128 KiB, `t` measured for ~1 s on the board); KEK = +- Core crates: RustCrypto `aes-gcm`, `argon2`, `hmac`, `sha1`, `sha2`, `subtle`, + `zeroize`; `ed25519-dalek` (built on RustCrypto's `signature` and `sha2`) for `vkey + auth`; `crc`. Not own crypto. Toolchain: stable rustup, no compiler fork. + - nRF52840: `nrf52840-hal`, `cortex-m`, `cortex-m-rt` (`set-vtor`), `usb-device`, + `usbd-serial`, `static_cell`, `heapless`; target `thumbv7em-none-eabihf`. No radio + driver (`radio_base` below). + - C6: `esp-hal` (features `esp32c6`, `rt`, `unstable`), `esp-storage`, + `esp-hal-smartled`, `esp-println` (`jtag-serial`), `esp-backtrace`; target + `riscv32imac-unknown-none-elf`; no espup. Not `esp-idf-hal`, not `esp-radio`. + + Read exact API signatures in `~/.cargo/registry/src/*/-*/src/` rather than + recalling them. +- Keys: pre = Argon2id(PIN, salt; 128 KiB, `t` measured for ~1 s on the board - the + board's `KDF_COST`, handed to `Device::new`: 20 on the nRF52840, 48 on C6-Zero); KEK = `DeviceKey::mac`(pre) — HMAC with the eFuse key when burned (2026-09-08), otherwise `Unbound`; DEK = HMAC(KEK, "vaultkey/dek/v1"); verifier = HMAC(KEK, "vaultkey/verify/v1"); AEAD with the entry name in the AAD. The header remembers the cost and whether the key is @@ -199,10 +231,12 @@ the protocol and logs — hence the `VTC2` magic word in frames. Pins and pitfal ends the claim that a seed never leaves — `docs/threat-model.md` says what it costs. - Secrets and PINs never come from command arguments or environment variables: the CLI asks hidden or reads a line from stdin, and holds them in `Zeroizing`. -- Flash: `store.rs` knows *how*, the board says *where* (`Layout` in its `main.rs`; on +- Flash: `store.rs` knows *how*, the board says *where* and *how big* (`Layout` in its + `main.rs`, checked by `Layout::fits` at compile time and again in `Store::new`; on C6-Zero 0x110000..0x17B000, raw flash past the `factory` partition, which the stock partition table does not describe). Three regions: one sector of attempt words and two - image copies of `STATE_SECTORS` = 53 each, filling the region exactly. + image copies of `state_sectors` each - 53 on C6-Zero, 32 on the nRF52840, whose 1 MiB + also holds the firmware, Trussed and the bootloader - filling the region exactly. - The image is the PIN header and every item, **packed** - `name_len | category | sealed_len | name | pad | sealed | pad` - not fixed slots: a seed is twenty bytes and an SSH key three kilobytes, and slots would make every write cost what the biggest item @@ -222,7 +256,8 @@ the protocol and logs — hence the `VTC2` magic word in frames. Pins and pitfal open or build an item in, one for the items carried across while the image is rewritten. The attempt counter is a separate sector; an attempt is one word write with no erase, only via `NorFlash::write`. -- Entropy: `TrngSource::new(RNG, ADC1)` before `Trng::try_new()`; do not drop the handle. +- Entropy on the C6: `TrngSource::new(RNG, ADC1)` before `Trng::try_new()`; do not drop + the handle. - Acceptance happens on the board, in two tiers, because the full test wipes the device and a working key cannot be wiped after every change: - After **any** firmware change: `vkey totp selftest` green — one tap, destroys nothing, @@ -230,14 +265,20 @@ the protocol and logs — hence the `VTC2` magic word in frames. Pins and pitfal - Before a **release**, and on every new board: `vkey check --wipe-everything` green too (it says when to tap, when to double tap and when to hold). It leaves the device with no PIN and no entries, so run it on an empty board — never on a key holding secrets. - Without a spare board, say plainly in the release that the full lifecycle test was not - re-run, rather than pretending it was. + There is no spare board: until the migration the empty nRF takes this test, afterwards + the wiped C6 does for core changes. A release that could not re-run it says so plainly + rather than pretending it was. Gesture rules are proven on the host (`firmware/core/tests/key.rs`); the board verifies the hardware honours them. ### Points of no return +**On the nRF52840, without a probe, the bootloader and UICR are irreversible.** A broken +bootloader is a board no USB tool reaches, and UICR `APPROTECT` once written stays. Each +such step happens only while the board holds nothing, and only on the maintainer's +explicit go for that step (`docs2/roadmap.md`, phases 3 and 4). + **eFuses are irreversible.** Secure Boot, Flash Encryption and HMAC keys burn the chip forever. Never burn an eFuse without a direct instruction from the maintainer — and even then the maintainer runs `espefuse.py` personally, following `docs/hardware.md`, after @@ -249,12 +290,18 @@ and not one line away from an everyday `setup`. The firmware detects a burned ke After any change under `firmware/`, run `./tools/build-vaultkey.sh`: it builds each board folder (from that folder, so its `.cargo/config.toml` applies), fails if a radio crate -appeared in `firmware/Cargo.lock`, writes `images/vaultkey.bin` and rebuilds the CLI, since +appeared in `firmware/Cargo.lock`, writes `images/vaultkey.bin` (through espflash or the +toolchain's llvm-objcopy, as `image_tool` in `board.toml` says) and rebuilds the CLI, since images are embedded in the binary; then `cli/target/release/vkey install`. Commit images with the firmware change. After a change under `cli/`, `cargo build --release` and `vkey -install`. - -Bootloaders and the partition table are built from the board's `bootloader/` folder in an +install`. The no-radio check reads the lock file, which proves nothing on the nRF52840: +its radio driver would sit inside `nrf-hal-common`. There `board.toml` names the radio's +peripheral slot (`radio_base`), and the build fails if any data word or `movw`/`movt` pair +in the image builds an address in it. The same search finds the slots the firmware does +use. It catches a driver that addresses the radio directly, not an address computed from +another peripheral's base plus an offset. + +The C6's bootloaders and partition table are built from its `bootloader/` folder in an ESP-IDF 5.5 Docker image by `./tools/build-bootloader.sh`, only when `bootloader/` changes. There are two: a plain bootloader, and a Secure Boot v2 one for a chip where `SECURE_BOOT_EN` is already burned. `vkey setup` asks the ROM (`GET_SECURITY_INFO`) which to @@ -277,6 +324,13 @@ Both `Cargo.toml` files carry the same `[lints]` table: `unsafe_code = "forbid"` targeted `#[expect(lint, reason = "...")]` (`#[allow]` is denied by `allow_attributes`): when the reason disappears, the compiler says the `expect` is no longer needed. +One exception, the maintainer's decision of 2026-10-04: `nrf52840-mdk-dongle` carries its +own copy of the table with `unsafe_code = "deny"`, because its flash driver takes the +vault region as a `&'static mut [u8]` and memory-mapped flash cannot be named in safe code. +The one `unsafe` is `vault_region` in its `main.rs`, under `#[expect]` and a `SAFETY` +comment. `tools/checks.sh` fails if that copy differs from the workspace's in anything +else. + Invalid state does not exist as a value: `Pin`, `Name`, `Params`, `Entry`, `Record` are built only by constructors returning `Option`; in the CLI likewise `EnvBlob`. Parsing from the wire and from flash happens once, at the edge (`proto.rs`, `store.rs`), and nothing @@ -286,16 +340,20 @@ cable. Add a new validity condition to the type's constructor, not to the call s ### Working with the board -- Do not hardcode the port: after flashing or a reset `ttyACM0` may become `ttyACM1`. Find - it by VID `0x303A`. +- Do not hardcode the port: after flashing or a reset `ttyACM0` may become `ttyACM1`. The + CLI finds it by the VID/PID in each `board.toml`, and refuses to guess when two keys are + plugged in; `--port` names one. The nRF also has + `/dev/serial/by-id/usb-vaulttecdev_vkey-if00`. - `pkill -f ` matches the shell that contains the pattern and kills the session. Kill by PID. - After a `cd` in a command, relative paths do not lead where they seem to. Use absolute. - A session without the `dialout` group cannot open the port; espflash says "busy or doesn't exist" and `vkey` says "no permission". Fix: re-login after `usermod`; in scripts, `sg dialout -c '...'`. -- Firmware logs go to the same USB port as the protocol. Watch with `espflash monitor`; - `cat /dev/ttyACM0` stays silent. +- C6 firmware logs go to the same USB port as the protocol. Watch with `espflash monitor`; + `cat /dev/ttyACM0` stays silent. The nRF firmware logs nothing. +- After a UF2 copy the nRF's warm start does not enumerate (`descriptor read -110`): + replug it. A copy makes `sync` hang while the bootloader resets; use `timeout 20 sync`. - Before a physical test, confirm the board runs the intended firmware: `info` returns the version and the board name. - Do not guess the device PIN: every wrong attempt costs one of eight. Only the maintainer diff --git a/README.md b/README.md index b9159a8..dbe80f6 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,13 @@ single-binary host CLI, and a press of the board's button for every secret that > batch, no certification. Read [docs/threat-model.md](docs/threat-model.md) before relying on it, > and keep the recovery codes your services give you. +> **Two boards** (2026-10-13). Development now targets the Makerdiary nRF52840 MDK USB Dongle +> (`firmware/boards/nrf52840-mdk-dongle`), the board passkeys will come to. It runs the same +> core and passes the full lifecycle test. It has no chip key yet, though, and its bootloader +> flashes anything and reads the flash back. So it is **not for real secrets** until the steps +> in [docs2/roadmap.md](docs2/roadmap.md) are done, and `vkey setup` does not flash it yet. +> Everything below describes the ESP32-C6-Zero, the key in use today. + ## In ten seconds ```console @@ -231,6 +238,8 @@ that is not in it exists on neither side. The device has no clock — the host s |---|---| | [docs/threat-model.md](docs/threat-model.md) | what it protects against and what it does not. **Read first** | | [docs/hardware.md](docs/hardware.md) | the C6-Zero board: measured pins, traps, bringing up a new one | +| [docs2/roadmap.md](docs2/roadmap.md) | the nRF52840 board, from bring-up to daily use | +| [docs2/makerdiary.md](docs2/makerdiary.md) | the nRF52840 board: why this one, its factory state, what was measured | ## Security and licence diff --git a/cli/.cargo/audit.toml b/cli/.cargo/audit.toml new file mode 100644 index 0000000..d03b6a7 --- /dev/null +++ b/cli/.cargo/audit.toml @@ -0,0 +1,12 @@ +# Advisories cargo audit skips for cli/Cargo.lock. Every entry says why it cannot reach +# vkey and when it goes; docs/threat-model.md lists the same ones. + +[advisories] +ignore = [ + # RUSTSEC-2026-0344, ruzstd 0.8 <- object 0.39 <- espflash 4.x: a malformed zstd + # section in an ELF. vkey never parses an ELF - it hands espflash finished images + # through Connection, Flasher and Segment - so the decoder is linked but never fed. + # Goes when `cargo tree -i ruzstd` shows 0.9.1 or later, or when espflash leaves + # the CLI (docs2/roadmap.md, phase 5). + "RUSTSEC-2026-0344", +] diff --git a/cli/src/auth.rs b/cli/src/auth.rs index 2ab1b05..0f43c98 100644 --- a/cli/src/auth.rs +++ b/cli/src/auth.rs @@ -15,9 +15,8 @@ //! the tap on this board is the whole proof. Anything that goes wrong is a refusal, and //! PAM asks for the password as it always did. -use std::fs::{self, DirBuilder, OpenOptions}; -use std::io::Write; -use std::os::unix::fs::{DirBuilderExt, MetadataExt, OpenOptionsExt, PermissionsExt}; +use std::fs::{self, DirBuilder}; +use std::os::unix::fs::{DirBuilderExt, MetadataExt}; use std::path::{Path, PathBuf}; use data_encoding::HEXLOWER; @@ -28,6 +27,7 @@ use crate::device::{ AUTH_CHALLENGE_LEN, AUTH_SECRET_LEN, AUTH_SIGNATURE_LEN, AUTH_SIGNED_PREFIX, Category, Class, Device, Error, FieldKind, }; +use crate::file; use crate::item::{Item, OwnedField}; use crate::prompt::with_unlock; @@ -94,7 +94,7 @@ impl Enrolled { .mode(0o755) .create(KEY_DIR)?; let text = format!("{}\n{}\n", self.name, HEXLOWER.encode(self.key.as_bytes())); - replace_file(&Self::path(user), text.as_bytes(), 0o644) + file::replace(&Self::path(user), text.as_bytes(), 0o644) } } @@ -130,6 +130,15 @@ pub fn enable(dev: &mut Device) -> Result { let user = sudo_user()?; let name = format!("{user}@{}", hostname()?); crate::device::name(&name)?; + // The login secret is sealed under the chip key alone. A board without one refuses + // it as `Incompatible`, which reads as "wipe it" - asked first, before anything on + // this host is written. + if !dev.pin_status()?.chip_bound { + return Err(Error::Value( + "this key has no chip key, so it cannot hold a login secret; nothing was enabled" + .into(), + )); + } install_self()?; @@ -250,7 +259,7 @@ fn add_line(path: &Path) -> Result { if !Path::new(&before).exists() { fs::copy(path, &before)?; } - replace_file(path, out.as_bytes(), 0o644)?; + file::replace(path, out.as_bytes(), 0o644)?; } Ok(true) } @@ -265,7 +274,7 @@ fn remove_line(path: &Path) -> Result<(), Error> { out.push_str(line); out.push('\n'); } - replace_file(path, out.as_bytes(), 0o644) + file::replace(path, out.as_bytes(), 0o644) } /// This binary copied to where PAM runs it, unless it already is that copy. @@ -274,27 +283,7 @@ fn install_self() -> Result<(), Error> { if fs::canonicalize(&me)? == Path::new(INSTALLED) { return Ok(()); } - replace_file(Path::new(INSTALLED), &fs::read(&me)?, 0o755) -} - -/// `path` replaced whole: written beside it and renamed over it, so a crash leaves the -/// old file or the new one - for a PAM file, never half of `sudo`'s configuration. -/// The source map in `sources.rs` is written the same way, for the same reason. -pub(crate) fn replace_file(path: &Path, contents: &[u8], mode: u32) -> Result<(), Error> { - let mut tmp = path.as_os_str().to_owned(); - tmp.push(".vkey-new"); - let mut f = OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .mode(mode) - .open(&tmp)?; - f.write_all(contents)?; - f.sync_all()?; - // The mode given at creation is narrowed by the umask; this is the mode meant. - fs::set_permissions(&tmp, fs::Permissions::from_mode(mode))?; - fs::rename(&tmp, path)?; - Ok(()) + file::replace(Path::new(INSTALLED), &fs::read(&me)?, 0o755) } /// The user who ran sudo: the one whose logins the key will answer. diff --git a/cli/src/check.rs b/cli/src/check.rs index 5dfd160..9e772eb 100644 --- a/cli/src/check.rs +++ b/cli/src/check.rs @@ -82,7 +82,11 @@ pub fn run(d: &mut Device) -> Result { failures: 0, button: boards::button(Some(&version)), }; - println!("device: {version}\n"); + println!("device: {version}"); + for line in d.chip_report()? { + println!("chip: {line}"); + } + println!(); clean_start(d, &mut rep)?; println!("\n=== no PIN yet ==="); @@ -199,7 +203,7 @@ fn provisioning(d: &mut Device, rep: &mut Report) -> Result<(), Error> { d.pin_unlock(pin(PIN)?)?; let took = started.elapsed(); rep.check( - "key derivation under 2 s (1.2 s of Argon2 plus the round trip)", + "key derivation under 2 s (the board's ~1 s of Argon2 plus the round trip)", took.as_millis() < 2000, &format!("{} ms", took.as_millis()), ); diff --git a/cli/src/device.rs b/cli/src/device.rs index 50f0683..d911702 100644 --- a/cli/src/device.rs +++ b/cli/src/device.rs @@ -121,6 +121,9 @@ impl PartialEq for String { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Error { NoBoard, + /// More than one key answers to a known USB identity: picking one would be a guess, + /// and a PIN or a wipe sent to the wrong key is not undone. + ManyBoards(Vec), Permission(String), /// Another program holds the port exclusively. Busy(String), @@ -148,6 +151,11 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Error::NoBoard => write!(f, "no board found - is it plugged in?"), + Error::ManyBoards(ports) => write!( + f, + "more than one key is plugged in ({}) - unplug the others or name one with --port", + ports.join(", ") + ), Error::Permission(p) => write!( f, "cannot open {p}: no permission.\n sudo usermod -aG dialout $USER # then log out and back in" @@ -265,30 +273,35 @@ pub struct Stored { pub category: Category, } -/// The board's serial port, or None. Never hardcoded: the number changes after a reset. +/// The board's serial port. Never hardcoded: the number changes after a reset. /// Matching on the USB identity each board folder declares, rather than "first /// ttyACM", keeps a second serial gadget - a Pico, a modem - from being mistaken for -/// the key. -pub fn find_port() -> Option { - if let Ok(ports) = serialport::available_ports() { - for p in &ports { - if let SerialPortType::UsbPort(u) = &p.port_type - && crate::boards::BOARDS +/// the key. Two matches are an error, not a pick: the other one may be a key holding +/// secrets, and `check` wipes whatever it reaches. +pub fn find_port() -> Result { + let mut found: Vec = serialport::available_ports() + .unwrap_or_default() + .into_iter() + .filter(|p| { + matches!(&p.port_type, SerialPortType::UsbPort(u) + if crate::boards::BOARDS .iter() - .any(|b| b.usb_vid == u.vid && b.usb_pid == u.pid) - { - return Some(p.port_name.clone()); - } - } + .any(|b| b.usb_vid == u.vid && b.usb_pid == u.pid)) + }) + .map(|p| p.port_name) + .collect(); + match found.len() { + 0 => Err(Error::NoBoard), + 1 => Ok(found.remove(0)), + _ => Err(Error::ManyBoards(found)), } - None } /// `path` as given, or the board's port by USB identity. pub fn port_or_find(path: Option<&str>) -> Result { match path { Some(p) => Ok(p.to_string()), - None => find_port().ok_or(Error::NoBoard), + None => find_port(), } } @@ -525,7 +538,19 @@ impl Device { Ok(b[0]) } + /// INFO's first line: the version, ending with the board's folder name. pub fn info(&mut self) -> Result { + let text = self.info_text()?; + Ok(text.lines().next().unwrap_or_default().to_string()) + } + + /// INFO's further lines: what the board says about its own chip, if anything. + pub fn chip_report(&mut self) -> Result, Error> { + let text = self.info_text()?; + Ok(text.lines().skip(1).map(str::to_string).collect()) + } + + fn info_text(&mut self) -> Result { Ok(String::from_utf8_lossy(&self.request(Cmd::Info, &[])?).into_owned()) } diff --git a/cli/src/file.rs b/cli/src/file.rs new file mode 100644 index 0000000..37d2732 --- /dev/null +++ b/cli/src/file.rs @@ -0,0 +1,28 @@ +//! A file replaced whole, never half-written. + +use std::fs::{self, OpenOptions}; +use std::io::Write; +use std::os::unix::fs::{OpenOptionsExt, PermissionsExt}; +use std::path::Path; + +use crate::device::Error; + +/// `path` replaced whole: written beside it and renamed over it, so a crash leaves the +/// old file or the new one - for a PAM file, never half of `sudo`'s configuration; for +/// the source map or an `op` cache, never a file that no longer parses. +pub fn replace(path: &Path, contents: &[u8], mode: u32) -> Result<(), Error> { + let mut tmp = path.as_os_str().to_owned(); + tmp.push(".vkey-new"); + let mut f = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .mode(mode) + .open(&tmp)?; + f.write_all(contents)?; + f.sync_all()?; + // The mode given at creation is narrowed by the umask; this is the mode meant. + fs::set_permissions(&tmp, fs::Permissions::from_mode(mode))?; + fs::rename(&tmp, path)?; + Ok(()) +} diff --git a/cli/src/main.rs b/cli/src/main.rs index d3efa79..8d0ee5e 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -25,6 +25,7 @@ mod backup; mod boards; mod check; mod device; +mod file; mod import; mod install; mod item; @@ -446,6 +447,9 @@ fn run_info(dev: &mut Device, version: &str) -> Result { let st = dev.pin_status()?; println!("port: {}", dev.path); println!("device: {version}"); + for line in dev.chip_report()? { + println!("chip: {line}"); + } println!( "pin: {}, {}, {} attempts left", if st.has_pin { "set" } else { "NOT SET" }, diff --git a/cli/src/op.rs b/cli/src/op.rs index ae97bac..2b5581c 100644 --- a/cli/src/op.rs +++ b/cli/src/op.rs @@ -12,8 +12,8 @@ use std::time::Instant; use serde::Deserialize; use zeroize::Zeroizing; -use crate::auth::replace_file; use crate::device::{Category, Class, Device, EnvBlob, Error, FieldKind, Reach}; +use crate::file; use crate::import::{Summary, entry_name, truncate, unique_name}; use crate::item::{Item, OwnedField, class_of, field_kind_name, field_kind_of, op_category}; use crate::prompt::SyncUi; @@ -421,7 +421,7 @@ pub fn save_saved_env(name: &str, id: &str) { let _ = std::fs::create_dir_all(parent); } if let Ok(json) = serde_json::to_vec_pretty(&map) { - let _ = replace_file(&path, &json, 0o600); + let _ = file::replace(&path, &json, 0o600); } } diff --git a/cli/src/setup.rs b/cli/src/setup.rs index 8ce649c..0f44deb 100644 --- a/cli/src/setup.rs +++ b/cli/src/setup.rs @@ -187,7 +187,12 @@ pub fn wait_for_firmware(port_hint: &str, timeout: Duration) -> Result p, + Err(Error::NoBoard) => port_hint.to_string(), + Err(e) => return Err(e), + }; let mut dev = match Device::open(Some(&port)) { Ok(d) => d, Err(e) => { diff --git a/cli/src/shell.rs b/cli/src/shell.rs index 3fa52d3..8c38b85 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -930,7 +930,7 @@ impl Shell { /// whatever port it has now. fn reconnect(&mut self) -> bool { self.dev = None; - let Some(port) = find_port() else { + let Ok(port) = find_port() else { return false; }; let Ok(mut d) = Device::open(Some(&port)) else { diff --git a/cli/src/sources.rs b/cli/src/sources.rs index 64f8b78..39e6913 100644 --- a/cli/src/sources.rs +++ b/cli/src/sources.rs @@ -19,8 +19,8 @@ use std::time::{Duration, Instant}; use serde::{Deserialize, Serialize}; -use crate::auth::replace_file; use crate::device::{Category, Device, Error, Reach, Stored}; +use crate::file; use crate::import::Summary; use crate::prompt::SyncUi; @@ -78,7 +78,7 @@ impl Manifest { } let json = serde_json::to_vec_pretty(self) .map_err(|e| Error::Value(format!("cannot write the source map: {e}")))?; - replace_file(&path, &json, 0o600) + file::replace(&path, &json, 0o600) } /// This name now belongs to this bucket. The last sync to write a name owns it. diff --git a/docs/threat-model.md b/docs/threat-model.md index 4de9a4c..67ed4a9 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -5,8 +5,50 @@ > There is no sale today, and the document holds all the same: the owner must not rely > on guarantees the device does not give. -Last reviewed 2026-09-12. Revisited on every hardware or firmware change. Reporting -policy: [`SECURITY.md`](../SECURITY.md). Board details: [`docs/hardware.md`](hardware.md). +Last reviewed 2026-09-12; the nRF52840 board section added 2026-10-13. Revisited on every +hardware or firmware change. Reporting policy: [`SECURITY.md`](../SECURITY.md). Board +details: [`docs/hardware.md`](hardware.md). + +## The nRF52840 board: not for real secrets yet + +The rest of this document describes the ESP32-C6 key. The second board, +`firmware/boards/nrf52840-mdk-dongle` (Makerdiary MDK USB Dongle), runs the same core and +passed `vkey check --wipe-everything` on 2026-10-13. Its protection is much weaker today, +and every guarantee below that rests on the eFuse key, JTAG being off or Secure Boot does +**not** hold on it: + +- **No chip key.** `DeviceKey` is unbound, so the data key comes from the PIN and Argon2 + alone (128 KiB, 20 passes - about a second on this 64 MHz core). The eight-attempt wipe + only guards the device's own PIN check. Whoever copies the flash can try every PIN on + their own hardware. Measured 2026-10-13 with the same `argon2` crate on one laptop core: + 0.97 ms per guess at 20 passes (2.4 ms at the C6's 48). All 10^8 PINs then take about + 28 core-hours, a few hours on an ordinary laptop, and less on a GPU. The "years for + eight digits" figure is for the C6 with the counter erased; it does not apply here. +- **The flash can be copied.** The factory UF2 bootloader serves `CURRENT.UF2`, the whole + application area, to anyone who holds the button while plugging the key in. Verified + 2026-10-13: the vault's region came back with its contents. SWD reads it too: the chip + reports revision 2 (build code `AAD0`) with UICR `APPROTECT` erased, which on revision 2 + leaves the debug port open. Revision 2 also predates Nordic's fix for the published + APPROTECT voltage glitch (IN-133), so even with the port closed in UICR, someone with + glitching gear can open it and read the flash, a chip key in it included. +- **Any firmware is accepted.** UF2 flashes whatever it is given, with no signature. + Firmware that records the PIN on its next use is one file copy away. +- **`vkey auth` does not exist here.** Its secret is sealed under the chip key, and the + CLI refuses to enable it. +- **A backup made on this board uses its own cost** (20 passes). It is still guarded by + the passphrase's entropy, at less than half the C6's work per guess. + +**Accepted, not fixed** (maintainer's decision, 2026-10-13): this revision-2 chip will hold +everything once the steps below are done. The glitch above stays open after them. Someone +who takes the key and has the gear reads the flash and finds the PIN offline in hours. For +a personal key, that risk is accepted rather than paid for with a revision-3 dongle. + +Before this board holds a real secret, all three are required: our own fork of the UF2 +bootloader (signed images only, no read-back, writes only to the application region), +APPROTECT, and a chip-bound key (a secret in a flash page locked by the ACL until reset). +The plan is in `docs2/roadmap.md`. Nordic's secure bootloader was dropped from it: there is +no SWD probe, and installing it moves the bootloader address in UICR, a one-shot change +with no way back. ## What the device is @@ -365,6 +407,9 @@ Listed openly so nobody has to discover them. 7. **No display** — the device cannot show what it is confirming. 8. **No recovery mechanism** beyond the encrypted backup (`vkey backup` / `vkey restore`). Lose both the key and the backup and access is gone. Keep a second key. +9. **One known advisory is ignored** (`cli/.cargo/audit.toml`): RUSTSEC-2026-0344, a zstd + decoder bug in `ruzstd` pulled in by `espflash`. vkey never parses an ELF, so the decoder + is never fed. It goes when a fixed `ruzstd` arrives or `espflash` leaves the CLI. ## Honest comparison @@ -426,3 +471,4 @@ A link to this document belongs on the product page, not buried in the repositor - [Espressif Security Advisory AR2023-007](https://www.espressif.com/en/news/ESP32_FIA_Analysis) - [EUCLEAK Side-Channel Attack on the YubiKey 5 Series — NinjaLab](https://ninjalab.io/wp-content/uploads/2024/09/20240903_eucleak.pdf) - [Security Overview — ESP32-C6, ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/security/security.html) +- [Nordic IN-133 — APPROTECT bypass by fault injection](https://infocenter.nordicsemi.com/pdf/in_133_v1.0.pdf) · [CVE-2020-27211](https://nvd.nist.gov/vuln/detail/CVE-2020-27211) · [IN-141 — nRF52840 revision 3](https://infocenter.nordicsemi.com/pdf/in_141_v1.1.pdf) diff --git a/docs2/makerdiary.md b/docs2/makerdiary.md new file mode 100644 index 0000000..2d1ffa6 --- /dev/null +++ b/docs2/makerdiary.md @@ -0,0 +1,421 @@ +# Next board: Makerdiary nRF52840 MDK USB Dongle + +Research notes of 2026-10-03. The board was ordered on 2026-10-03. Decided: passkey is back, +on Trussed. Since 2026-10-04 the board folder builds vkey for the chip (no Trussed yet); it +has not run on a board. + +## Goal + +One key that does both: what vkey does today (TOTP, passwords, `.env`, `vkey auth`) and +passkey/FIDO2 over USB HID. NFC is optional, nice to have later. + +The C6-Zero cannot do passkey: its USB is a fixed Serial/JTAG, so HID is impossible. That +is the hardware reason passkey was closed. A board with native USB removes that reason. + +**Passkey reopened 2026-10-03, maintainer's decision.** README, `docs/hardware.md` and +`docs/threat-model.md` still describe the C6 truthfully and change in the same change set as +the passkey code. + +## Passkey stack: Trussed (decided 2026-10-03) + +**Maintainer's decision 2026-10-03: passkey is built on Trussed + `fido-authenticator`.** No +own CTAP2 implementation; project rules change where Trussed requires it. + +| Option | Fit | Verdict | +|---|---|---| +| **Trussed + `fido-authenticator`** (Nitrokey 3, Solo 2) | Rust, `no_std`, `heapless`; CTAP2.1 in production on Nitrokey 3A Mini, which is an nRF52840 | **chosen** | +| Google OpenSK | Rust, complete | rejected: built around Tock OS and `alloc`; development has slowed | +| Own authenticator on `ctap-types` | least code on the device | rejected: see below | + +Why not our own, so it is not re-argued: + +| | Own CTAP2 | Trussed | +|---|---|---| +| Code we write | ~3–5k lines (more than the whole current firmware) | ~1–2k lines of glue | +| First browser login | ~1–1.5 months | ~2–4 weeks | +| Production-hardened | months to years of platform quirks (Windows, macOS, iOS, Android) | already, on Nitrokey 3 and Solo 2 | +| Hardest part | PIN protocol 2 (ECDH, HKDF, AES-CBC, permission tokens): a bug is a silent UV bypass | dependency versions: Nitrokey pins git revisions | +| Reviewed by | nobody | Nitrokey, SoloKeys and their users | + +Correctness and security rank above simplicity: a vetted stack beats fresh code of our own, +even a bigger one. The price is accepted: a large dependency tree, littlefs in C, two +storages, two PINs, no passkey backup. + +Plan: + +1. Run the plain Nitrokey nRF52 firmware (NK3 Mini runner) on the Makerdiary board: pins, + button, LED, flash layout. Prove a passkey login in a browser. +2. Only then embed vkey next to it: its own USB interface, its own flash region. +3. Rewrite CLAUDE.md rules that change (storage, C dependency, crypto backends) in the same + change set as the first Trussed code. + +What Trussed brings, and the rules it changes: + +- **Its own storage:** littlefs (a C library behind `littlefs2`) in a flash region of its + own. The board layout splits flash into the vkey region and the Trussed region. Changes the + rules "core requires … / `store.rs` knows how" (two storage engines) and the implicit + pure-Rust firmware. +- **Its own crypto service and key store** for FIDO keys. "Crypto from RustCrypto" holds + only if the RustCrypto backends are chosen in Trussed features; check before building. +- **Its own architecture:** apps (FIDO, maybe later vkey itself) talk to the Trussed + service; USB goes through `usbd-ctaphid` + `ctaphid-dispatch`. The vkey protocol keeps its + own USB interface next to CTAPHID. +- **Its own user presence hook:** Trussed's `UserInterface` asks for a touch; map it to the + tap (amber). `reset` must be the 5 s hold. +- Start from the Nitrokey nRF52 runner (`nitrokey-3-firmware`, NK3 Mini), not from scratch. + +Open questions before code: + +- **No `DeviceKey` on nRF52840.** There is no eFuse HMAC key, so the KEK is `Unbound` and + `Auth` items are refused. Candidate: a secret in a flash page that boot code reads and then + locks with the ACL peripheral until reset, plus APPROTECT. CryptoCell-310 KDR needs + Nordic's closed binary library — rejected unless nothing else works. + Trussed needs a device secret too, so one mechanism serves both. +- **CTAP PIN vs vault PIN.** With Trussed they are separate by default: the FIDO PIN lives + in Trussed's store, the vault PIN in `store.rs`. Merging them means changing Trussed. +- **Backup.** Passkeys in Trussed's store are not in the `.vkb` backup. Losing the key means + re-enrolling passkeys on every site; keep a second factor registered everywhere. + +## Memory map (decided 2026-10-03) + +The Makerdiary dongle has no external flash: 1 MiB flash and 256 KiB RAM, all inside the +nRF52840. Sizes are taken from Nitrokey's own nRF52840 devices (`memory-regions` in +`nitrokey-3-firmware`): NK3 Mini splits 0x1000..0xEC000 into firmware and an 80 KiB +filesystem and claims up to 100 passkeys; the FIDO-only Nitrokey Passkey firmware is +≈230 KiB (v1.1.0 release, from its Intel HEX size). + +| Range | Size | What | +|---|---|---| +| 0x00000..0x01000 | 4 KiB | MBR | +| 0x01000..0x97000 | 600 KiB | firmware: vkey + Trussed + FIDO, ≈420 KiB by the fit check below | +| 0x97000..0x98000 | 4 KiB | vkey attempt counter | +| 0x98000..0xB8000 | 128 KiB | vkey image copy A (32 sectors) | +| 0xB8000..0xD8000 | 128 KiB | vkey image copy B (32 sectors) | +| 0xD8000..0xEC000 | 80 KiB | Trussed littlefs (passkeys), as on NK3 Mini | +| 0xEC000..0x100000 | 80 KiB | Nordic secure bootloader, MBR params, bootloader settings | + +- **Vault: 128 KiB per copy** (32 sectors, C6 has 53). The maintainer's backup of + 2026-09-14 was 15 KB; 100–200 entries are expected. `STATE_SECTORS` stops being a core + constant: the board gives the region size in `Layout`, because a second board with a + different value now exists. +- **No A/B updates.** Two firmware copies need over 800 KiB and do not fit at any vault + size. The bootloader updates in place; an interrupted update leaves the board in the + bootloader until a valid signed image arrives. +- **Bootloader: Nordic secure bootloader**, as Nitrokey uses on this chip (C, nRF5 SDK, + built in Docker like the C6 bootloader; Nitrokey's `utils/nrf-bootloader` is the + reference). The CLI speaks Nordic DFU to it. `NRF_DFU_APP_DATA_AREA_SIZE` must cover the + vault and littlefs, 0x97000..0xEC000 (340 KiB): otherwise an update erases the secrets. + Open: where the DFU signing key (ECDSA P-256) lives. +- **RAM: decided after the stack is measured on the board.** `MAX_ENTRIES` stays 256 + (100–200 entries expected). If RAM is short, the candidates are the item size (8 → 4 KiB + frees ≈12 KiB) and, last, Argon2 memory (128 → 64 KiB frees 64 KiB but halves the cost of + each PIN guess after a flash dump, and C6 backups open only if both boards change). + +### Fit check, measured 2026-10-03 + +Nitrokey Passkey v1.1.0 built for thumbv7em-none-eabihf (stable 1.97.1, Arm GNU toolchain +14.2.rel1 for its C code): the whole Trussed + `fido-authenticator` + USB + RTIC firmware. +vkey from the current C6 build (`firmware/target/riscv32imac-unknown-none-elf/release`). + +| Flash, 600 KiB firmware region | KiB | How | +|---|---|---| +| Trussed, FIDO, USB, RTIC | 223 | measured: `.text` + `.rodata` + `.data` + vectors | +| vkey without ESP code | ≈185 | measured on RISC-V (209 KiB code, 20 KiB of it ESP crates); Thumb-2 is similar | +| nRF HAL, USB CDC | ≈10–20 | estimate | +| **Total** | **≈420** | ≈180 KiB headroom | + +| RAM, 256 KiB | KiB | How | +|---|---|---| +| vkey statics: Argon2, item buffer, index | 156 | measured: C6 `.bss` + `.data` | +| Trussed, FIDO, USB statics | 44 | measured: `.data` + `.bss` + `.uninit`, incl. NFC/CCID channels | +| nRF extras | ≈2 | estimate | +| **Statics total** | **≈202** | **≈54 KiB left for the stack** | + +The stack is the one unknown: vkey's peak is ≈12–16 KiB (an 8 KiB frame on the stack plus +crypto), Trussed's is not measured. With vkey and FIDO served from one loop the peak is the +larger of the two plus interrupts, so 54 KiB is likely enough. Measure on the board by +painting the stack at boot and reading the high-water mark over SWD. + +Found while building: + +- **Trussed's P-256 on this chip is C and assembly**, not RustCrypto: `p256-cortex-m4` + uses `p256-cortex-m4-sys` (P256-Cortex-M4) whenever it builds for a Cortex-M4 and falls + back to RustCrypto `p256` only elsewhere. Keeping "crypto from RustCrypto" means patching + that crate; accepting it adds a second C dependency next to littlefs. +- **The firmware build needs an ARM C toolchain** (`arm-none-eabi-gcc` with newlib + headers) for those C parts; clang alone fails on `string.h`. `tools/build-vaultkey.sh` + has to provide it, like the Docker image does for the C6 bootloader. + +## Linux login (`sudo`, lock screen) + +Decided 2026-10-03: the new key is the base. `sudo vkey auth enable` stays the one command +a user runs, but on the nRF52840 it sets up **`pam_u2f` over FIDO2**, the scheme every +other key uses (YubiKey, Nitrokey, SoloKeys, Token2): a FIDO2 credential with RP ID +`pam://`, the mapping in `/etc/u2f_mappings`, one `sufficient` line in PAM, originals +kept as `*.before-vkey`. The same FIDO2 credential type also gives SSH (`ed25519-sk`) and +LUKS unlock (`systemd-cryptenroll --fido2-device`, needs `hmac-secret`). + +Why not keep the current `vkey auth` on the new board: it needs the chip key, which the +nRF52840 lacks, so the firmware refuses it (`Incompatible`). pam_u2f needs no chip key, no +`pam_exec`, and no copy of `vkey` in `/usr/local/bin`. + +Other schemes, not chosen: `pam_yubico` (Yubico OTP or HMAC-SHA1 challenge-response, +legacy), `pam_p11`/sssd smartcard (PIV certificates, enterprise setup). + +The current Ed25519 `vkey auth` stays only while the C6 is in use, and is isolated so it can +be cut in one change. Its whole surface (2026-10-03): + +| Where | What | +|---|---| +| `cli/src/auth.rs` | the whole feature: PAM lines, `/etc/vkey/auth/`, challenge, verification | +| `cli/src/main.rs` | `Auth` subcommand dispatch; `USED_BY_AUTH` refusal on `get` | +| `cli/src/shell.rs` | `USED_BY_AUTH` refusal | +| `cli/src/check.rs` | the auth section of the lifecycle test | +| `cli/src/device.rs` | `respond` | +| CLI, by category | `Category::Auth` in `item.rs`, `sources.rs`, `op.rs`, `backup.rs`, `main.rs` | +| `firmware/core/src/wire.rs` | `Respond` command, `AUTH_CHALLENGE_LEN`, `AUTH_SIGNATURE_LEN`, `AUTH_SIGNED_PREFIX` | +| `firmware/core/src/item.rs`, `oath.rs` | `Category::Auth`, `AUTH_SECRET_LEN` | +| `firmware/core/src/vault.rs` | `auth_key` | +| `firmware/core/src/device.rs` | `item_key`, the carry-over in `reseal_all`, the refusal in `open_named`, `respond`/`sign_with` | +| `firmware/core/src/proto.rs` | parsing of `Respond` | + +Removing `Category::Auth` makes the compiler list every remaining site. The general atomic +file write that used to live in `auth.rs` moved to `cli/src/file.rs`, so nothing unrelated +depends on the auth module any more. + +## Why nRF52840 + +| | nRF52840 | RP2350 | ESP32-S3 | +|---|---|---|---| +| USB HID | yes | yes | yes | +| NFC | built-in NFCT (ISO 14443-A), antenna only | no | no | +| Vault storage | internal flash | external QSPI flash | external flash | +| Chip-bound key | none comparable to the C6 eFuse HMAC key | OTP with page locks | eFuse HMAC | +| Secure Boot | no (own signed bootloader instead) | yes | yes | +| Rust on stable, no compiler fork | yes | yes | **no** — Xtensa needs espup | +| Existing Rust FIDO2 | Trussed (`fido-authenticator`, Nitrokey 3A Mini) | C only (pico-fido) | none | + +- **Internal flash.** The PIN attempt counter cannot be reset by desoldering or rewriting + an external flash chip. On RP2350 it can. +- **Core fits unchanged.** 4 KiB pages, 4-byte word writes — exactly what `Store::new` + checks. The new board is a folder under `firmware/boards/`. +- **ESP32-S3 is rejected** by the project rule: no espup, no compiler fork. + +## Why Makerdiary over other nRF52840 dongles + +| Board | USB | Case | Button | LED | Verdict | +|---|---|---|---|---|---| +| **Makerdiary MDK USB Dongle w/ Case** | A | plastic 50.8×21.1×7.6 mm | 1 | **RGB** | **chosen** | +| Nordic PCA10059 | A | none (3D-printed OpenSK case) | 1 | RGB | cheaper, no ready case | +| Raytac MDBT50Q-RX | A | plastic | 1 | blue only | one colour is not enough for gestures | +| Raytac MDBT50Q-CX | C | stick, case unconfirmed | 1 | 2 separate | only option worth a look if USB-C matters | +| I-SYST USB-C dongle | C | optional, unconfirmed | 1 | RGB + 1 | small maker, low stock | +| Ebyte E104-BT5040U | A | blue removable shell | 2 (one reset) | — | looks like a generic BT adapter | +| Holyiot HOLYIOT-nRF52840-USB | A | — | unknown | unknown | no schematic, SWD-only, not a PCA10059 | + +Makerdiary is the only one with all of: RGB LED (amber/red/blue gestures), a button, NFC +tuning capacitors already fitted (100 pF; only the coil is missing), UF2 bootloader, an +open schematic and a presentable case. + +Pins from the Makerdiary wiki (still to be **measured with a probe**, per project rules): + +| Function | Pin | +|---|---| +| USER/RESET button | P0.18, active low | +| LED red / green / blue | P0.23 / P0.22 / P0.24, active low | +| NFC1 / NFC2 | P0.09 / P0.10 | + +## Known limits + +- **The case protects nothing.** It is a removable plastic shell. Opening it exposes the + chip and SWD. +- **No secure element and no eFuse-style chip key.** APPROTECT on early nRF52840 revisions + was bypassed by voltage glitching. Buy the newest revision. `docs/threat-model.md` must + say what this costs before the board holds real secrets. +- **Epoxy potting** (electronics-grade compound) is the only way to get closer to a + YubiKey physically. Pot only after final flashing and APPROTECT, leaving the button and + USB free. +- **`vkey auth` does not migrate.** Its key is sealed under the C6 eFuse key; it must be + re-created and `vkey auth enable` repeated. Items move over a `.vkb` backup (passphrase + only, no chip key). The Secure Boot signing key held in vkey needs a plan before the move. +- **FIDO2 is the biggest piece of code in the project** (CTAP2.1, COSE, P-256, resident + keys, PIN protocol). Every line is attack surface. + +## Rejected + +- **SoloKeys Solo 2 Hacker** (LPC55S69, $35–46, injection-moulded case, Rust/Trussed): + strong fit on paper, but LPC55 flash has ECC with 512-byte program pages — rewriting a + word in a programmed page is not allowed, which breaks the one-word attempt counter in + `store.rs`. Vendor development has slowed. Not chosen for now. +- **Tillitis TKey Unlocked** (RISC-V on iCE40 FPGA): strongest key derivation (own UDS + + app measurement), but tens of MHz and ~128 KiB app RAM — Argon2id at 128 KiB does not + fit; apps load from the host each time. Would be a rewrite. +- **Nitrokey 3**: production firmware is signed by the vendor; no hacker edition found. + +## To buy + +- ~~Makerdiary nRF52840 MDK USB Dongle w/ Case~~ — ordered 2026-10-03. +- An SWD probe (Raspberry Pi Debug Probe or a Pico with debugprobe firmware): needed for + APPROTECT and recovery. Check that SWD pads are reachable on the Makerdiary board. + +## Board folder: `firmware/boards/nrf52840-mdk-dongle` (built 2026-10-04) + +vkey alone, no Trussed yet: the same core as the C6, behind the four HAL traits. + +| Part | What it is | +|---|---| +| HAL | `nrf52840-hal` 0.19, `cortex-m-rt` with `set-vtor` (the MBR hands over to 0x1000) | +| Port | USB CDC-ACM through `usb-device` + `usbd-serial`, polled from the main loop; VID/PID `1209:0001`, pid.codes' test pair | +| Clock | SysTick exception, 1 ms. Not a counter read on demand: the auto-lock compares times only when the next request comes, so a counter that wraps between requests would keep an idle key unlocked | +| Ui | button P0.18, LEDs P0.23/P0.22/P0.24, all active low, from the wiki; amber = red + green | +| Flash | `Nvmc` over 0x97000..0xD8000 behind a wrapper that fences after every erase and write | +| Entropy | the RNG peripheral, bias correction on | +| DeviceKey | none: `bound() == false`, PIN only, `vkey auth` refused | + +Measured on the build: 72 KiB of code, 154 KiB of statics, ≈101 KiB left for the stack. + +Rules changed for it (maintainer's decision 2026-10-04): the board has its own lint table +with `unsafe_code = "deny"` for the one `unsafe` in `vault_region`; `tools/checks.sh` +keeps the rest identical. Core changes that came with it: the image copy's size moved from +the `STATE_SECTORS` constant into `Layout::state_sectors` (C6 keeps 53), and the test +flash refuses a third write to a word between erases, the nRF52840's limit. + +Known gaps, by design until the board is in hand: + +- **USB is serviced only between operations.** During Argon2 (expected ≈3 s at 64 MHz) + or a flash write the host waits; a control request in that window waits too. If that + breaks enumeration or `vkey`, USB moves to an interrupt, which is a second `unsafe` + (unmasking it). +- ~~Argon2 cost is the C6's~~ Done 2026-10-13: the cost is a board value (`KDF_COST` in + each `main.rs`, handed to `Device::new`). Here it is 20 passes. 48 had measured 2645 ms + through `vkey check`. With 20 the same unlock takes 1128 ms. The C6 keeps 48. +- **No chip key.** The ACL-locked secret is the next design step. +- **No radio code**: the lock-file check proves nothing here. Since 2026-10-13 + `build-vaultkey.sh` searches the image for the radio's slot (`radio_base` in + `board.toml`) and finds nothing. The same search finds 24 references to USB, 10 to the + flash controller and 4 to the RNG. It catches direct addressing only, not a base plus + offset from a neighbouring peripheral. + +## Factory state (board arrived 2026-10-13) + +Seen on the bus: `1915:c00a` "nRF52 Connectivity" (Nordic's connectivity firmware for +nRF Connect), one CDC-ACM port. Holding the button while plugging in starts the UF2 +bootloader instead (drive `UF2BOOT`, green LED). Its layout, from the Makerdiary wiki: + +| Region | Address | Size | +|---|---|---| +| MBR | 0x00000 | 4 KiB | +| Application | 0x01000 | 972 KiB | +| UF2 bootloader | 0xF4000 | 38 KiB | +| Bootloader config | 0xFD800 | 2 KiB | +| MBR parameters | 0xFE000 | 4 KiB | +| Bootloader settings | 0xFF000 | 4 KiB | + +No SoftDevice. The application starts at 0x1000, as `memory.x` assumes, and the vault +(0x97000..0xD8000) misses the bootloader, so the board folder needs no change to run under +it. A UF2 is made from `images/vaultkey.bin` with family `0xADA52840` and base 0x1000 +(`uf2conv -f 0xADA52840 -c -b 0x1000`). Until our own fork of this bootloader replaces it +(`docs2/roadmap.md`, phase 3; Nordic's secure bootloader was dropped for want of a probe) +the board holds no real secrets, because UF2 flashes anything and its `CURRENT.UF2` reads +the vault's ciphertext out. + +Open questions only the board answers: + +- ~~Is P0.18 the pin reset?~~ No (2026-10-13): pressing the button under the factory + firmware did not re-enumerate the board (`udevadm monitor` stayed silent), so UICR + `PSELRESET` is not set and P0.18 is a plain GPIO. Adafruit's `board.h` marks it + "unusable: RESET", but that does not describe this unit. +- ~~Is the vault region blank?~~ Yes: the factory `CURRENT.UF2` (bootloader 0.7.1, dated + 2023-07-20, S132 5.1.0 plus the connectivity app in 0x1000..0x35000 and one page at + 0x50000) is all 0xFF over 0x97000..0xD8000. Kept at `~/mdk-factory/`, sha256 + `3022eb28...6aab`; it restores through the same drive. +- ~~Green LED on P0.22?~~ Yes, as far as `vkey check` shows: Adafruit's `board.h` lists + only red P0.23 and blue P0.24, but amber is red plus green, and the taps on amber went + through. Red alone (the 5 s hold) has not been watched yet. + +- ~~Which revision?~~ **Revision 2** (2026-10-13, the `chip:` line after a replug): + `nRF52840 AAD0, UICR APPROTECT 0xffffffff, last reset: power-on`. On revision 2 an erased + `APPROTECT` means the debug port is open: anyone with an SWD probe reads the whole flash + today. Revision 2 also lacks the fix for the published APPROTECT glitch (IN-133), so + closing the port in UICR stops a probe but not someone with glitching gear. The bootloader + reports nrfx 2.0.0 in `INFO_UF2.TXT`. + +### Reading the `chip:` line of `vkey info` + +The firmware reads three things at boot and `vkey info` prints them (phase 1 of +`docs2/roadmap.md`), so the questions a probe would answer need none: + +- **Build code** (FICR `INFO.VARIANT`, ASCII): `AAC0` is revision 1, `AADx` revision 2, + `AAF0` revision 3 (IN-141). Anything else: Nordic's IC revision overview. +- **UICR `APPROTECT`**, the word as stored. Its low byte decides, and what it means depends + on the revision: + + | Low byte | Revision 1-2 | Revision 3 | + |---|---|---| + | `0xFF` (erased) | debug port open | closed | + | `0x5A` (HwDisabled) | not a defined value; unverified | open only if the firmware also writes `APPROTECT.DISABLE` at every boot | + | `0x00` (Enabled) | closed | closed | + + Our firmware never writes `APPROTECT.DISABLE`. The factory bootloader runs first, and + Nordic's `SystemInit` writes it when UICR holds `0x5A`; whether this build does is not + checked, so `0x5A` counts as open on every revision. +- **Last reset**, from `RESETREAS`, cleared once read. `soft reset` is either our panic + handler or the bootloader restarting after a flash. A power-on reset clears every bit, + so a board that has to be replugged reports `power-on` and nothing about what came + before. The case behind the first unexplained failure (a reset with the button down, + the board left in the UF2 bootloader, then replugged) is exactly that, so this line + cannot explain it. It does catch a lockup, a watchdog or a panic the board recovered + from by itself. + +First run, 2026-10-13. `images/vaultkey.bin` was converted to UF2 (family `0xADA52840`, base +0x1000) and copied to `UF2BOOT`. Read back through `CURRENT.UF2`, it matched byte for byte. +The warm start straight from the bootloader after the copy did not enumerate (`device +descriptor read -110`). A replug did: `1209:0001 vaulttecdev vkey`, and `vkey info` answered +`vaultkey 0.9 nrf52840-mdk-dongle`, PIN not set, 8 attempts, PIN only. After flashing, replug. + +`vkey check --wipe-everything`, the same day, second run: every check passed but one. That +covers tap (amber), one tap refused for a backup and two taps accepted (blue), backup and +restore, lock, the attempt counter, the wipe after 8 wrong PINs, `auth` refused without a +chip key, and selftest against an independent HMAC. So the button on P0.18 and the red and +green LEDs work. The one failure is Argon2: the key derivation with the C6's cost takes +2645 ms against the 2 s limit, so the cost has to become a board value. + +The first run died at "no code from a password". That step lights amber with no prompt in +the CLI. The board left the bus and came back in the UF2 bootloader, which starts when the +button is held at reset. The second run passed the same step, and an untapped amber at +"no code from an env" ended in a plain `Refused`. The cause is unknown. Suspects: a reset +while the button was down, and USB going unserviced for up to 30 s while a tap is awaited. +- **ModemManager** is active on the maintainer's machine and may probe a new CDC-ACM port. + +## First steps when it arrives + +> Superseded 2026-10-13 by `docs2/roadmap.md`. The board ran over UF2 without a probe, +> step 4's reset question is answered (P0.18 is a GPIO), and the order of everything after +> step 5 is in the roadmap. Kept for the record. + +1. Confirm the chip revision and that the board is genuine. +2. Wire the SWD probe. Save what is on the board first: the factory UF2 bootloader is + erased by the next step and only comes back from Makerdiary's published hex. +3. Erase the chip and write Nordic's MBR (from the nRF5 SDK) plus + `images/vaultkey.bin` at 0x1000. With no bootloader address in UICR, the MBR starts + the application at 0x1000. +4. Check UICR `PSELRESET`: if P0.18 is the pin reset, switch it to a plain GPIO, otherwise + tap, double tap and hold cannot work. Measure the button and LED pins with a probe. +5. `vkey info` must answer with `nrf52840-mdk-dongle`; then `vkey totp selftest` and, on + the still-empty board, `vkey check --wipe-everything`. +6. Measure the stack's high-water mark and the Argon2 time. +7. Replace the MBR-only setup with the Nordic secure bootloader that accepts only firmware + signed by the maintainer's key. UF2 flashes anything - on a key holding secrets that + is a hole. +8. Record the choice and the rejected options in `docs/hardware.md`. + +## Sources + +- https://makerdiary.com/products/nrf52840-mdk-usb-dongle-w-case +- https://wiki.makerdiary.com/nrf52840-mdk-usb-dongle/hardware/ +- https://www.aliexpress.com/item/32971420565.html (52Pi) +- https://www.thingiverse.com/thing:4132768 (OpenSK case for PCA10059) +- https://www.raytac.com/news/ins.php?index_id=176 (MDBT50Q-CX) +- https://www.adafruit.com/product/5199 (MDBT50Q-RX) +- https://solokeys.com/collections/hacker +- https://www.tillitis.se/products/tkey-unlocked/ diff --git a/docs2/roadmap.md b/docs2/roadmap.md new file mode 100644 index 0000000..266fdbd --- /dev/null +++ b/docs2/roadmap.md @@ -0,0 +1,232 @@ +# Roadmap: the nRF52840 key, from bring-up to daily use + +Written 2026-10-13, after the first green `vkey check --wipe-everything` on the Makerdiary +dongle. Revised the same day for a constraint the maintainer set: **no SWD probe and no +spare board, now or later.** Decided already, not reopened here: the nRF52840 is the +primary board and the C6 the fallback; Trussed + `fido-authenticator` for passkeys. Board +notes, measurements and the factory state: `docs2/makerdiary.md`. + +## What "no probe, no spare" changes + +- **Everything happens through USB.** That means the UF2 bootloader and our own firmware. + Firmware can read FICR and UICR itself, so the chip revision and the protection state + need no probe. +- **A bootloader bug cannot be undone.** A broken bootloader means a dead board and a new + dongle. So every bootloader and UICR change is done **while this board is still empty**: + losing it then costs the dongle, never the secrets. +- **The Nordic secure bootloader is dropped** - a change to the decision recorded in + `makerdiary.md`. Installing it moves the bootloader address in UICR, which without a + probe is a one-shot operation with no way back. A fork of the bootloader already on the + board installs through its own update path at the same address. +- **UF2 stays the transport for good.** `vkey setup` for the nRF copies a signed UF2 to + the bootloader's drive. That is no longer throwaway work. +- **Test without a spare.** The nRF is empty now, so it is the test board until migration. + Afterwards the C6, wiped and kept as the fallback, takes the full + `check --wipe-everything` for core changes. nRF-only changes get `selftest` and a `.vkb` + backup before each update. A release then says plainly that the full lifecycle test was + not re-run on the nRF, as `CLAUDE.md` requires. + +## The rule that orders everything + +**Secrets move to the nRF at security parity, not when features are done.** Today the C6 +is the stronger key: the eFuse HMAC key, Secure Boot v2 and JTAG off. The nRF has no chip +key, and its bootloader flashes anything and serves the flash back (`CURRENT.UF2`). A copy +of its flash gives up the PIN offline in hours (`docs/threat-model.md`). Until phases 3-5 +are done, real secrets stay on the C6. `espflash` stays in the CLI and the audit exception +stays open until the migration. + +The order is fixed by what each step depends on. First the **bootloader** with no read-back +and signed images only: APPROTECT means nothing while UF2 hands out the flash. Then +**APPROTECT**. Then the **chip key**. + +--- + +## Phase 0 - close the current work (now) + +1. ~~**Audit exception.**~~ Done 2026-10-13: `cli/.cargo/audit.toml`, item 9 of the + threat model's known limitations. RUSTSEC-2026-0344 (`ruzstd` 0.8 via `object` 0.39 via + `espflash`). + - **No upstream fix yet:** `espflash` 4.6.0 still pins `object` 0.39. + - **Not reachable here:** vkey uses only `Connection`, `Flasher` and `Segment` and + never parses an ELF. + - **The change:** `cli/.cargo/audit.toml` with the reason and the exit condition - + `cargo tree -i ruzstd` shows ≥ 0.9.1, or `espflash` leaves the CLI. One line in the + threat model. +2. **Live check of the two-key guard.** With the nRF plugged in, plug in the C6 and run + `vkey info`. It must say "more than one key". +3. **Re-sign and flash the C6.** Unplug the nRF. Then `./tools/sign-vaultkey.sh`, + `cargo build --release` in `cli/`, `vkey install`, `vkey setup` **without** + `--erase`, and `vkey totp selftest`. +4. **`auth enable` on the nRF.** `sudo vkey --port auth enable` must refuse at once + and write nothing to `/usr/local/bin/vkey`. +5. **Commit.** `git add` the whole `firmware/boards/nrf52840-mdk-dongle/` folder with + `images/`, then commit (the maintainer). + +## Phase 1 - true docs and a board that reports itself + +- **The docs pass.** Done 2026-10-13 for `CLAUDE.md`, the README (a "two boards" note; the + full rewrite waits for the migration, since the C6 is the key in use until then) and the + core comments. `docs/hardware.md` and moving the C6 docs into its folder are deferred: + they describe the C6 correctly as they are. + - README, `CLAUDE.md` and `docs/hardware.md` put the nRF first. + - The C6 docs move into its folder. + - Numbers that hold only for the C6 are marked: "four years for eight digits", 1.3 s a + try, 300 KiB of stack, 512 KiB of RAM, `TrngSource`. + - Core comments become chip-neutral: `proto.rs`, `wire.rs`, `hal.rs`, `PIN_LEN`, + `item.rs`. +- **What `vkey info` shows from the nRF** (code done 2026-10-13). At boot the firmware + adds a second line to INFO's answer, which `vkey info` and `vkey check` print as + `chip:`. The command and the first line are unchanged, and there is no new `unsafe`. + - the build code from FICR `INFO.VARIANT` - `AAF0` means revision 3; + - the UICR `APPROTECT` word, raw; + - the last reset cause from `RESETREAS`, cleared after reading. + + How to read them: `docs2/makerdiary.md`, "Reading the `chip:` line". This answers the + revision question without a probe. It does **not** explain the first unexplained + failure. A panic and the bootloader's post-flash restart both read as `soft reset`, and + the replug that failure needed is a power-on reset, which clears the register. It + catches a lockup, a watchdog or a panic that the board recovers from by itself. + +Acceptance: `vkey info` shows the `chip:` line. `selftest` needs a PIN, and the board has +none after `check`, so on the empty board the acceptance is `check --wipe-everything`. + +## Phase 2 - the revision gate + +**Read 2026-10-13: build code `AAD0`, revision 2.** So the second case below applies. +**Decided the same day by the maintainer: everything moves to this board, and the glitch +risk is accepted** - the key is for personal use. Phases 3-5 still close what a probe and +UF2 open; what stays open is the lab attacker of IN-133. + +- **Revision 3 (build code F).** APPROTECT holds against the published glitch (IN-133, + mitigated in revision 3). Go on. +- **Older.** Someone who takes the key and has a lab can still open the debug port with a + glitch. Read the flash out, and the PIN falls offline in hours. The maintainer decides: + accept it as a physical attack on a key in their own pocket, or keep the important + secrets on the C6. A revision-3 dongle would be a purchase, so that is the maintainer's + call too. + +## Phase 3 - our own UF2 bootloader (while the board is empty) + +A fork of the bootloader already on the board (Makerdiary's build of +`Adafruit_nRF52_Bootloader` 0.7.1, MIT), with three changes: + +1. **No read-back.** `CURRENT.UF2` and every other path that serves flash to the host are + removed. +2. **Signed images only.** The bootloader keeps the incoming image invalid until a + signature over the whole image verifies. An image that fails never runs, and the board + stays in the bootloader. The signing key lives in vkey, like the C6's. +3. **Writes only to the application region** (0x1000..0x97000). A UF2 cannot touch the + vault, the settings or the bootloader itself. + +**Built** reproducibly in Docker, like the C6 bootloader. **Installed** with the bootloader +update file its own build produces - the path Makerdiary documents for bootloader updates +from 0.4.0 on. Before installing, read in its source how the copy survives a power cut. +Nordic's MBR offers a power-safe copy, but whether this updater uses it is not confirmed. + +**`vkey setup` for the nRF** writes the signed UF2 to the bootloader drive. + +**The risk, stated plainly.** A bug in the new bootloader leaves a board no USB tool can +reach. Without a probe that is a new dongle. That is acceptable only because the board +holds nothing yet. + +Acceptance: + +- an unsigned or altered UF2 is refused and never runs; +- the drive offers no `CURRENT.UF2`; +- a UF2 aimed at the vault region is refused; +- `check --wipe-everything` passes; +- the threat model loses the "flashes anything" and `CURRENT.UF2` lines. + +## Phase 4 - APPROTECT, from the firmware + +- **Firmware writes the protection itself.** It writes UICR `APPROTECT` to Enabled once, + verifies the word, and never loops on it. A reset loop has been reported with ad-hoc + write sequences on Fx parts, so the values come from the product specification and + errata 249, not from forum posts. +- **It is the last UICR change.** With APPROTECT on, UICR can no longer be changed at + runtime. +- **Irreversible without a probe.** Recovery would be a full erase over SWD. With no probe + ever, that costs nothing, and it closes the debug port to anyone who has one. +- **What it changes depends on the revision.** On revision 1-2 an erased word (`0xFF`) + leaves the port open, and this write is what closes it. On revision 3 the port is + already closed unless UICR holds `0x5A`. There the write takes away the one value that + would open it. + +Acceptance: after a reset, the `chip:` line shows the `APPROTECT` low byte at `0x00`; the +board still updates through UF2; `selftest` green. + +## Phase 5 - chip key, then move daily use + +**Chip key.** On this chip any secret is loaded by software, so a chip key is only as +strong as phases 3-4. Two options, decided by the maintainer: + +- **A. Secret page plus ACL (recommended).** A random 32-byte secret in its own flash + page, outside the application region the bootloader may write, created on first boot. + At boot the firmware copies it to RAM and locks the page with the ACL, read and write, + until reset. Then neither code nor a debugger can read it. `DeviceKey::mac` becomes HMAC + with it, `bound() = true`, and `vkey auth` works again. RustCrypto only. **On this + revision-2 chip** a glitch opens the debug port at boot, before the ACL lock runs, and + reads the page. Against a lab attacker A then adds almost nothing, and mainly brings + `vkey auth` back. `vkey info` would print "chip-bound (a copy of the flash is useless + without this chip)", which is false here, so that text changes with it. +- **B. CryptoCell-310 KDR.** A write-only key register used only by the hardware - closer + to the C6's eFuse HMAC. It needs Nordic's closed library or undocumented registers, + which goes against "crypto from RustCrypto". + +The existing nRF vault is unbound, so it reads as `Incompatible`. It is wiped, which costs +nothing while it is empty. + +**Migration:** + +1. Back up the C6 to a `.vkb`. +2. Restore onto the nRF. The cost travels in the file, so this works across boards. +3. Check that the signing keys are on the nRF, and write down where their backups live. + Losing the C6 Secure Boot key ends C6 updates forever. +4. Wipe the C6. It becomes the fallback and the test board for core changes. +5. C6 flashing moves out of the CLI into a script in its folder. `espflash` leaves, and the + audit exception goes. + +Acceptance: the threat model's nRF section is rewritten to match; `selftest` green on the +nRF; `check --wipe-everything` green on the C6. + +## Phase 6 - passkeys (FIDO2) + +- **USB moves to interrupts.** CTAPHID must send keepalives while it waits for a touch, and + a composite device (CDC for vkey + CTAPHID) must serve both interfaces during any wait. + This is also the real fix for "USB unserviced during the tap wait". +- **Runtime: RTIC (Nitrokey's choice) or Embassy.** Before choosing, check whether its + macro-generated `unsafe` trips the board's `unsafe_code = "deny"`. +- **Trussed + `fido-authenticator`**, with littlefs at 0xD8000..0xEC000 and P-256 from + `p256-cortex-m4`. Re-measure the fit and the stack high-water mark. +- **Then Linux login moves to `pam_u2f`**, and the old `vkey auth` is removed, recorded in + `docs/` with the commit it can be restored from. +- **This is done on the daily key** (no spare). Every update starts with a `.vkb` backup. + The vault region is out of the bootloader's reach, so a firmware update cannot overwrite + it. + +Acceptance: registration and login on webauthn.io and with `fido2-token`; `pam_u2f` with +`sudo`; `selftest` green; core changes pass `check` on the C6. + +--- + +## Decisions needed from the maintainer + +| When | Decision | +|---|---| +| Phase 0 | ~~the audit exception for RUSTSEC-2026-0344~~ - done 2026-10-13 | +| Phase 2 | ~~if the chip is older than revision 3: accept the glitch risk or keep the important secrets on the C6~~ - revision 2; everything moves here, risk accepted (2026-10-13) | +| Phase 3 | ~~own bootloader instead of the Nordic secure bootloader~~ - own fork chosen (2026-10-13); installing it still needs its own go | +| Phase 5 | chip key option A or B; wiping the C6 after migration | +| Phase 6 | RTIC or Embassy, and the `unsafe` rule if the runtime needs it | + +## Sources + +- Nordic IN-141, nRF52840 revision 3 and the APPROTECT changes: https://infocenter.nordicsemi.com/pdf/in_141_v1.1.pdf +- nRF52840 revision 3 errata 249: https://infocenter.nordicsemi.com/topic/errata_nRF52840_Rev3/ERR/nRF52840/Rev3/latest/config_840_249.html +- APPROTECT revision 3 vs 2: https://devzone.nordicsemi.com/f/nordic-q-a/100570/access-port-protection-nrf52840-rev3-vs-rev2/430101 +- Reset loop on Fx parts when writing UICR.APPROTECT: https://devzone.nordicsemi.com/f/nordic-q-a/114591/nrf52840-critical-reset-loop-when-updating-uicr-approtect/502068 +- Writing UICR from application code: https://devzone.nordicsemi.com/f/nordic-q-a/82409/example-code-to-write-to-uicr/367066 +- ACL, nRF52840 product specification: https://infocenter.nordicsemi.com/topic/ps_nrf52840/acl.html +- Bootloader update over UF2: https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather/update-bootloader +- Makerdiary UF2 bootloader: https://wiki.makerdiary.com/nrf52840-mdk-usb-dongle/programming/ +- Nordic bootloader and the MBR's power-safe copy: https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.0.0/lib_bootloader.html diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index 6f2caec..5a07c59 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -57,12 +57,33 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "az" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + [[package]] name = "base64ct" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + [[package]] name = "bitfield" version = "0.19.5" @@ -129,6 +150,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cfg-if" version = "1.0.4" @@ -152,6 +179,52 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" +[[package]] +name = "cortex-m" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "844b9697e922c99847eed515c6eb6d101e7ce62ff556fcaec243798291427ee8" +dependencies = [ + "bare-metal", + "bitfield 0.13.2", + "cortex-m-macros", + "critical-section", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "volatile-register", +] + +[[package]] +name = "cortex-m-macros" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1922be58519ad40368fc4ca595a2cefa51a7abf947be3b0c90586dc7dbd0e2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f0f27b7ecbb9fad6702c8764d11d0b7245437de1575e34e39b2af95382f096" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cf9e0f899304705b85fda7b178fc383f2529ec2479693248b600e530d2327a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.5", +] + [[package]] name = "cpubits" version = "0.1.1" @@ -197,6 +270,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.7" @@ -245,7 +324,7 @@ dependencies = [ "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "rustc_version", + "rustc_version 0.4.1", "subtle", "zeroize", ] @@ -507,6 +586,15 @@ dependencies = [ "nb 1.1.0", ] +[[package]] +name = "embedded-dma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "embedded-hal" version = "0.2.7" @@ -668,7 +756,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a2d6e99b6ccfad5c8067025c7b4d13eb8b5f21e288f7a3e204c114e8ab5dcf8" dependencies = [ - "bitfield", + "bitfield 0.19.5", "bytemuck", "critical-section", "delegate", @@ -947,6 +1035,18 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "fixed" +version = "1.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9af2cbf772fa6d1c11358f92ef554cb6b386201210bcf0e91fb7fba8a907fb40" +dependencies = [ + "az", + "bytemuck", + "half", + "typenum", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1017,6 +1117,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hash32" version = "0.3.1" @@ -1204,6 +1315,61 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "nrf-hal-common" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8100d0bf6d732ea9b0a294fa2d2dad9cba4fbc5bb655d0afaa984d03d528fe" +dependencies = [ + "cast", + "cfg-if", + "cortex-m", + "embedded-dma", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-io 0.7.1", + "embedded-storage", + "fixed", + "nb 1.1.0", + "nrf-usbd", + "nrf52840-pac", + "rand_core 0.9.5", + "void", +] + +[[package]] +name = "nrf-usbd" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf862f941154442271ae9914777bd1c93f6d2e0dc9db4cafa160e55ffb9085" +dependencies = [ + "cortex-m", + "critical-section", + "usb-device", + "vcell", +] + +[[package]] +name = "nrf52840-hal" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2297dc31df743012c721033a962ae21813611ee6b8062577b36031baa641d331" +dependencies = [ + "nrf-hal-common", + "nrf52840-pac", +] + +[[package]] +name = "nrf52840-pac" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30713f36f1be02e5bc9abefa30eae4a1f943d810f199d4923d3ad062d1be1b3d" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "vcell", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1371,13 +1537,22 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1376b15f3ff160e9b1e8ea564ce427f2f6fcf77528cc0a8bf405cb476f9cea7" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.28", ] [[package]] @@ -1392,12 +1567,27 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "serde" version = "1.0.229" @@ -1702,6 +1892,28 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "usb-device" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98816b1accafbb09085168b90f27e93d790b4bfa19d883466b5e53315b5f06a6" +dependencies = [ + "heapless 0.8.0", + "portable-atomic", +] + +[[package]] +name = "usbd-serial" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065e4eaf93db81d5adac82d9cef8f8da314cb640fa7f89534b972383f1cf80fc" +dependencies = [ + "embedded-hal 0.2.7", + "embedded-io 0.6.1", + "nb 1.1.0", + "usb-device", +] + [[package]] name = "vaultkey-core" version = "0.9.0" @@ -1734,6 +1946,23 @@ dependencies = [ "vaultkey-core", ] +[[package]] +name = "vaultkey-nrf52840-mdk-dongle" +version = "0.9.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "embedded-hal 1.0.0", + "embedded-storage", + "heapless 0.8.0", + "nrf52840-hal", + "static_cell", + "usb-device", + "usbd-serial", + "vaultkey-core", +] + [[package]] name = "vcell" version = "0.1.3" @@ -1752,6 +1981,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + [[package]] name = "winapi-util" version = "0.1.11" @@ -1816,6 +2054,26 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "zerocopy" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df92bf3d9227be3d53173901ddbffac2babc27ae50f397776ffd6dc33f800cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "zeroize" version = "1.9.0" diff --git a/firmware/boards/esp32c6-zero/board.toml b/firmware/boards/esp32c6-zero/board.toml index 9ff96a0..258cfda 100644 --- a/firmware/boards/esp32c6-zero/board.toml +++ b/firmware/boards/esp32c6-zero/board.toml @@ -1,10 +1,11 @@ # One board = one folder. This file is the board's identity for everything outside the # firmware: the CLI reads it at build time and embeds the images listed here, and -# tools/build-vaultkey.sh reads `chip` and `target` to build and flash. +# tools/build-vaultkey.sh reads `chip`, `target` and `image_tool` to build. name = "esp32c6-zero" chip = "esp32c6" # as espflash names it target = "riscv32imac-unknown-none-elf" # rustup target the firmware is built for +image_tool = "espflash" # the ESP-IDF app image the bootloader checks # How the CLI recognises the board on the USB bus. usb_vid = 0x303A diff --git a/firmware/boards/esp32c6-zero/images/bootloader-sb.signed.bin b/firmware/boards/esp32c6-zero/images/bootloader-sb.signed.bin index fbdd66e9ccd0a5652512beeb95224bd4dfbe76ed..36478c1d864b14a120eb87adac2c4a3341626df3 100644 GIT binary patch delta 406 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 z zerl341g&uyWnjWjUv3XS$cD4rzyewqB#eb*{Pk?yBD+fffC?#Ax;>C z=zLb@AI%Ag2*T|_VCGg)D=V|t&{PW^O!V{UGz(7d=AI+o9@mT1{5XBd0`{o2n08pe zv_kV~$Ow4)r_z)WID@$VhfW%S#}U&+x)YwU{&5>?8rEgLvjrK~I0dJRXRQlhrrZWP=p_X!}}9U6Dp-iy}#3s3h+zB z>ZA{k#80N`yJy4AART{fnZ#d~N3%z;Q|b{bUHp8wwK`yg#GVM#izBh&{_SEk<{3|f z-2@)jkD3bLUvVEzryI&u+G-}N2+~rqo&BkGZ8|;%Nu^SmX)&Exh_kaBZ(N^&YzuP2 zSbS&`7>C(#y-~-XIUvLFuoULm*ZP*AQ(i!_kocYMFN83%bD!Mm5vkRP{hPbAvi}-( zioL2Pjabtxx1A^lj#@5sY3u!I%z}z9HXf_{y!A6U7w(xwcK z?op7C4`<9_Z_<*{pcwd(j=tq8*W#Y2z`6R=D5oRItg>-UXj@gC9hBt>bXHPJdUPYPq)4U|&+SnqC=) z`-XeZr;9HajCCGzO2Qt5>%by>oakrJknz|;(EW7Wc;HXB38v`bBf87?AQqZ0L=u|N zkrZUGE09ys{%Y-wB}Eb$=jQLsPbgr-JjvoZJ_7&a7tUZoJA)ckza!iCGnLVnOw|=+ zn|5BwuJTxdZNGk@h|9hH)b&W)50@2<#WT>iD~~8YD|_!d+oC9JvvQB{&Z!^0XuAlR z*$)xh#UN}eozJ$-iGoeMeS>Ae>oow%qL28 ze=9xv2$&ptN<$`Mqt>z=B1c+KNp2C0Tv{*@C#P}Attw-Uix-eCq6OI&HK9Jjj(RRh z6Xg2JhmP=#gSMk>>ul`@(9SCQ3iKc*6>Xk~M=9ZmRRzDJAH_z35Y2lOZY7Lut9{I| zMNn~DoGPx?r%J8XfO1Q?#m%O^GZD+T%5a-f$cP@6jlxdzUdvd)^>h?+eylqOs(*y7 z_Z0$hMSTOD5w^k^;SkI`f%od6=9P=c7I%fHyVSmqR=at#ZREOg2s~7y0q*vN$FDh| z!TZqt1awb@?hS}{!%p2QYe2Z(rMPlaZEpX*{7-{kgLaNi8292h^2l%bQwykm5`KzU zzoIWqf<;?rQST(!6f}eWFo|jX3pC_098FLMO@0igM7phw{G<46O}ch9C{c;9^*_;R zkKt!hEZf3BS(u1~c+(Zhh_t-T%CK-k-VpC4s+f$^v{}oyRi#$t!7J*_iMQ*hX);_L znMLPL1|mTZ(2B_bj^9JKO$OR<@AQ!W!6}&dC(<-49@@jQg9$#-KM=RsdWb$}#fc%C z*Tq99m8m4_blPCWTT{v-k2ptFNVbZ%h_8w`z&!igUPgIpUx=-PzAyz3FEIgjUw10G zM+L%MU$`81etJ;I7xYAb8QY{_SBZ7}4tBuC>5sJRyzc&fWSfrQ!o8j@KyNWTV`gl-7w8HpEQrk|0v&B&>uuh+9WPnp~}P39=UtQ z3StBVIn4vyoKUJt;9UxEZZBQz?y6CM-3N!yC!840`Tm5?jrrciFHphj zv=A8d2NwLV5(8PS*hKp9A=>>&LcCrb;d3dI-?pztV0&|v(E+hppH4U6i)<%0bv(5L1`9`4i&F1XFGq3L$AIR5d8 zJ-ezh%8k{jRivea>?f_HZ6?|y$ZI?4xT{*jrL@AO>;@3*KEnyEY6nO_u3xKWQ}@*XXen3&5gm>9 zxREMMS0Y&`;=0`5WrMe>Q=YAWsWHfDa=;QD#+(63mYbZMpo!8cE^rK2v4E@CJ8;zi zxQZ2V1vDg$`K=-45im|>;S6D~FxK*&#h~8;;_y8XhX)|Uk@FRpO;tD~j3HR&f)j?2 zd$<4+%Wp6|80462?TxNn@LEB)k^SjEr{lYb{uosi!wE$N-1*aj=z;k~Mdx22DZh&M z*};<`a`N49!26$S%V?j-GbMJvqBE+s)5JVXhrmazKH%ab05K6UT{?=B8&rJc|33iK z76)8l9W7qIqZu=B@5joydLCYH6*Q?;Gqp^ryBgnfE?Ph0ggxYugRUxt+QolH zW-{}iOata)(h>b*CNtI)R%Wb8JNUsIG+#T42@A$xchQC!IM(QXjJZQ|#I{m9{kt=P z$pRJ;7VdMO2V#>#>GZc5cuYz2&Z>qL9H1+-IHSgq#@mf6Z1xaMsTrFS1V<{^EIG#g z4#A0xEnKP(@$gQ%P933G@~A5qM1AB6&IVs+vXyC+w&znrxi=0*&UGGl=2~`I*t@z+ zPgw`sqNWE`xw*|NZoiv%!53nC&hn0;k*`5{VC=$mJaKKNdamwZcC~?4WfqH*6)y~3cB?&@E&i9{fw0vU$Ae9gWzPeArKsuc3XsJMf z)~G+cCey9y>SG=`X7gbnW&@_GWQYyBU71Lw-l1~)4|GZ%?gK%DM{I4nS9Y^#gq`%r z*~|-@R9k92@P!O;VVkodWT#Wsy$KA1sGaQ=>KFFC^a&8>Zl^3@^y~Oa_OXpkDs?UG zHXGLw?^kr!Y&^t>mh!?M4cW(3Ryd>M!Ohy^=nJAnsYcQa{AJz(K?*UTV)~r+dYsu@ zrF7KecscRDLBDw%f)&*5Xq&_(*%8cX7A8r$)czxV_X&KKfT(rP#X||2OHaJ(Gp+XSMM`wi93!-MV?hw&B5bN+NVr!r@f#Us9O=-e~LQnpks5#J*6RntZADKleG zbM`*MK8!Ll$ubb!i(B|kl7Q3P^xh(3T&iyEX21XzGqR*7Me49^hQi|XnR zDj8QPz?Bor(EzfCd`x^~pMr4=(FG$S23*8i{oQo_d>lE--5&yEyg{`=TOZ4ua(k%M zTc4Jq*%~YR?8Wu5X&QQ1w4NVGiG_0Mci-D*^rz6H^VucMWH#SK=Sdk7Yf>e^jJQLA zd?L&l^zU=}6Y6ixX?mr>Fl9S`xOVb${=#NW*KXAghefmZmpoOVg?n9+V9;z(<*8t=MM($*EE1l5 zT7xq?5`rO0%SGrZz7b))=X`7-$QkfVr2Q{ZrSyaNKiQOv$^qmaC$I`I=*Rv~O zFqO*fQX&<68G-YRg$PwyZnQLsQd^bhf!8lwOP3xrq+y-G_*oBw{0qHzaNdHzcR-fNw>FMHo^qBpA{@OUR3pfH6&zu%({`kgpQY>rQy) zF2wH>;{A-KK853m|5KXx6fP{_k4uVF`3)EboFrbXPfN(>zm=72yNkCgr8@Uwsm^&? zVnzQ1Ie&(pdjg2uxpGuei&JFW?w+fE~S3*k%zla|ureONw zi@2D074**+nae|HoC{}Y^*8H-#TSz1GrqImpp#uVq0n?KrRUaokzmAf)4w1vX@NZ3 zHL=A1hf6L2Ls2Y2e;5!Rk`~N*k#T`i_Z8aa0(oY-NXZ&JCsqG58%b=XkouW^V*TpD z3X*1!$Nz!8vSp=4rBFF6UE87{(p#Z z7%+lL^Q0Q@hg%UT0{=@w%?I^NXx&1U`~CXRtzwB>{~oQUcnz^{r^8;tu|4eD>O;CB z#QPSV{Sr>hvw{LD&11`Nl^0@aU`tD2VO?=1(-vrP`?kDMAIjRW`K31K4SM_~Se5fE z9kvdqg$psfg)b;@maSXxhop{#&GdzJ;Eoo>(6#HZKGzqsDL4mbwXyGBWgH2#Nl`&i zdbB7m^OF9MSUf2v1wpBmm7>zV*QHWt486JzNDlqoGj=_GVa&jaC{GG7TIJRFsu4O> z`E}24I2Rc4gf6K3njx|Fnj!hyPk75q4c2Jjq1NB)6dC+->w->OXL7X5@vtfP~z;Wk3g(bVg3yfJ+WJ$xOGzF)WwCpm%4yVn8P zQf3GddeV>^5D$WU-VMAw+8O!=dhw zhD>C|slmh;%^x}gah&oSK!7(4$?x2d3GW1*A50=i%crywT6Ggn=#+{Zp36Y66_&4Q zb1=Cd22zEPG&WFH2uUXVOLTGw%oEXzmW7Z8(z}<(7)quy(p=Mxq_cJ{-Nn zZ4cttdj|I*#vtN5bYou_8=kFwNd~d6@!aT3PH2g} z!gFE>vEdT$bryn|pBG){T$K}U%37=ShACF_?Xk5t@}ikx4l+Y*<9~v+k<^rTr^~6} zbxt)en(k8l<1Y9dn9f-hlnvjugHIxDlk};+-yCK-5oS}cxvaCG4Jj1Ire64{5(E@x z(!E0g(`Xu1-Uk@)PNAvy5i4;&N|&>|^%1)LK3Jb=JpJxIVjOIG2wYUcj(+S!8dN`4 z$E*3};57zH&=_bFv^=J>#Qz}88%A0S$~SAop5T#6i_g_*zy*h%W7!dfv>201jm5={ zx>e>LUM~U-noC;9Fgj^Cnb^ZWxKf-2j3lXVHr+p*oFx9fwBAH4#G2&kFp)@5p*pI{ zB}0f_OU=2>0r=ma!bnzW~s7h%u=75E(Zjw$yAHTO}7s9Nwhz?9C+|I6?n?WoQVz zSrh22KVJ`;)=mOz(4V76&Ez>^{U;qQkfB7_L01YSA=>nnPNC4WM-05_#<23So_j#P zRpsxX`vqc-w13_nZ~m8fxWV246Q@K+Xo7`IHX%52!~c^#5VluQzPamM?p9DBzr?Ha2DEj>#uZ29LPqusaGcCr3ce6Fxce|=W_&jjqJIhQT(aAH&cLZ&xxif)) z?V!tMl3!B1ujQdOv9}oVC1OOPv!E7*YR<$3Ba^hKZ$t>K`Yu$!@zul*;-% zytRjP6Uxrj_b7y}CNO42RKGy2kCRv9#f*QU%s?Ng;uu^~6YrBWb`FUjBQ~+mhtN%W zy(R=2FwcOEVVbAoPh~u70YJn&nhW`K7=U3x8hDOQT^f5{DKAzmb3aZi=a3V`{}`S2 z1T5AHbpHhTjaUn*eJ%+PMIbkz%_{{XoI z4+r+gU#?m#TVLuEs!PcI6$$d4h4 zjl;n-Vl(*PwZ*6rc<_~)+O?%5+S>01UziPS1>c=%_QZgdw9>^8ePC;UsxWZD4AX z?#}M|9)a%ET1K`JXEW70NVqX+WNNdqMT#w)X_c9>B@J$PFhuHC%Z|MmKq<1&u?{l0 zIBBF-C8_j^W2r}t$1}dnI+5^A*2!$1MJSGqmPgqawlN!AOfdQm*d zv9}bM_+0M&DeZu{9{#_#7S_nE554M+msKp^ZakcNM5o$=J@92?S7pjbtv2BIJ*@IX zF`8X^jM~ddc!6^6kZ*>a-01yiZ$tA(E!+0*Y?bh~xLq2z;#``RS{Wv+&&u9sP{e`1 zS_wT_PGU=x2N&=DtJ=Y;=TUY!SX2td+yKUg0LDJ@Zrm%)$nTd|()QNwQo#dvfOv~| z18Cpn+D%JaY8Ptx=N2ZzSAF32&!(ly+EQO1@e8}Uh+Sw&X_1~bci|9y15lT;`Bh9!Yrn6MAx7^+PwtkNS7Xbo3+^FWA0sIuWh@H%z=*R-I5 znE%??+gL#!!El4Af;V;U!s3M>lG4^<=< zk8{q4yB*lG7SLaj+?v{A+@H~!)g}?1vrX=Oeh!k*t?$v5@O%P5zf`(_l)Sf8$Sw!6 zQZ(1nhnJBN!NI&mqB96(G%O=R=oQX4Fr0~7o%%qn=h`wd218J7)C$rQRxo=7Spd0j zq}k-K1+6RU_R zvHj~Z`?CvVI!OLjkdX1zU8gJ$BM*e#fL`a*VXH}8WKwJASCr4}lacnlXZ~uk9`|zo zAQiNvLXd$-42-r**HDBjG{r@7!xtwU6eN?;{>-hK7hK@hch;aMJ>r!g;fkY$k5G3a z_o9nT3A@6zB*6h;NB3JeFJ1$7>lNC%hK%feW#RK6qwzsp-rGFWj%edxxQNoM!j zGP^4hJ~|uCVp4fm=;@cq`pCuIT>NPGypAYC&jrv)*SrFo{s#T<6|xk-F~3Ugg$sH1 zSD8N$LhE0JGvX^$^%~iwU)+;j$r_CUa!VI<0jKUYHfL`J8N#1Y(vz=|$k+1 zbnG^E89}?fP6hz6n_ee+V!2AEzD_1!_|DPmcQ#vF{QH znL(TBwby~TYiXpL^o8aoH|cYCYp6xOdD0gbcve8jaK*veh0n2FUXf&2eqU0|9(bv% zm%IlZbd?*dp70Cw9XH9ztmRsc!DqAiWt%FF)y8}buWH8f)du*@?n`c};A;aP3WuR% zK`mDo0G)0CQ+yD72}nYpo0qryR*799l^lx&?h{dL<)o6No}Ri59z*^kf zDez{g%(_A<^Ff(ZVp=YhMCb!0`ejndnfMKI8&oZo4C>|LtxBn%w^Ax|_6oFeFNG4G znGn6`)c43^xQ=??BhksipVCs4*Wfh(j;1pd+mj`A(5VbOH{K&EOqAfoe*m_7?K*n; z1JGGlJi|UDFB72Z6CaT&@EE$AL=(#&bo_2|I&1uJ4}?HKz?Nl$zSODehkJ&BUR-%{ zc#dU7Ug(1d-C=xcvj;v3?^+sVz7-Ui?#`?9h3OZ|#-vR`8TD$AsP@80T1fAEsj1Y!z|@A-nk zIOCiI|VMyO+!+R*q^v1}9yJqPZWF`=HqV zG1-|cJSHKt#R@d3l#uC{>2L8wsm?NqKHN-R45^q83P?1VW}Ky$n?X*s6w_Wl5D(RPqjOdfdLGxP!p=UBYl|2o5+{=&vDG^dK z?v=wF>-1}Ek%P*0NRb2nA{^X`C8mLt9OjI%Xn;=OshY!L2ZZX`nC^jOA2~oiAqR6TGu1GYSc)>w-`2{MK@h5lis9H5E9zjqn+nx#*i<_SLAE*t+*_4GJP*t*V1=c0-CqUXl+UjL^|L9pjw7W_Z0aE zyPOU=$BicL59so99Ncr?MZY`8on=SEt>+={eT3@2=T2+AE>-k#xYZ)Tsdv%vAGl#! z|4LOfyXzvAnpV=OKXA_wcLn|C2X01?mLberLJNN6R!bSvQ}nwZxi5)zCjIay2(6&W z5V^v0v^k*9S!47Ved=cpE-p@>tv_>V#6ON+{h1q*q92o@PJ@V!U8xH$RZDIC52l2$ zeMw{y9kDmuxu5t8_f#|*0k5>qa&jqgY3$fkA-5Ok`CquWXz%^*n3D%id~$oOJD0}& z%Hj28dO^-A>K3p0vQ9erTFA#hC9Q=|lOHvc`e{#P!Q=(Fk3UpW&&nKZJ4ODOTC zr}PkECDOd!yX#R}59r6sd1DF^udzv^^xwpd;ic6fc_w#Sy?A~aSeLaQI7Fe+YW25P zi&8mZLFn8GHy++otWzNsyk^YNg}Sg3u2|th*iDsG>fT7>{@~K4d0&Utqa*+##&%MP>9t!uWIEKp%Eo0Q z1n>&ia^;foGQj@zY_9#<-hAbbQFB+Nck)ANEtC$R41so5AQ$iH>9`M46Bo*y}7f$FJ zqJZ~yf;_E6kqAQd|LiO9+7K2UriM?`Ud7O{#ot%82sLbSeN0mZ>SZI=zddWyzhqtl~1(2cE_wc6TV;J`IG0{ zh`VDu2W~i8P`XQjvwxd%c&Us%fBQR77I^-)Zy+D2|1Zzd|CpQ&&;jY+19A4{P@Fvg zo;%byduA5SR%)at`yC(B_nYPWr`<}NeH{9}0M7<^PKJfpAoXt}{Vx5zLY)0IOcWD_ zvkQZ8_A+?(4#3$zJ%+Q-LOKoU2T14T->JXg?EL?d8ZN^)kOJ-22Y#3SmyUrB|C^^f zFlfIqS3}vpH6;6RHOVfA)C4IUQZJ;`8j@Z5F8r7cKgPhb5S|2{iI9fE?~Bl}0e*i0 z&$IB%hO%-<-SArr&k{)MA-3#^bd>7ITNK+v1CF2aP4WXH>Un!!r zBma#M%7ipJ1Z59`X99;%WWW5~1j-;E9FDTX;2G)~88K}5N%$23sZ1-Co`T=3S0I1d z^?1avQLin**-(hEoSu^NfwIEiWa+=g3SZ81i?)%8it1QN5cH9B^o zf@EKCRSl2R^jrYu{}~wgV(YHqn>Cv7c9OlUoMbC1T4yH5aYW;7Ex)sqvxTRjY?ue> z*lY z?t2ibsPh%JCy;|K}7&`O0Cw z7Fj{E|4&ls|J6YMAIB;EKUu~9a&jD|JQ8;}u`}=B~HT%IJ zab))j7rA%jVDYzk6<_o4M=6z02vnN&Nmt&z6Qw%alYC9+-o84+6z*CZgSF1Yxk3fj#m&Yuz{n2w|zm0Al^ zJwTJLs*X#UnE-ZB5OVQ5NQsIf*56HBJ1m0-yPZ~};uAORF1-OrnSsCFRBcqK-7bT0 z`(QUO7!_~Gb%trT*7fh_c;Gj6(C;0&pMUcIT!$w0s|$C%EzG#@@@P;sz)~Y1jf3=c zGRjuofwG4}icCS-BjK3?X*#6kke-F~I;0r`9p?S;{0!11NUW{GHOu-)=q)3*p0qxS zT?IMurO6=1ew%WBr|h?F{*Usp|1tTTev@zbJjRur>n0_;TaV>V+`XaucBKJ<2L)llQx|%L*9AxBUx>6GbvcQu<UrtJ|&*ck_JL!Z!LDhxPas+QZ?5iLd8=pyM}a%7lf0n;X}^ zayV3>URJW%NedWO3@@s`VR<9s5p<8Ozv1+7K8t?rUJ37pXY2Bh=F@o!99No_J{P;v z_2{v6VdoN^)W-U|jTOQyjn2v6uy?(oaYZDcOr@wQ2JNa}n^o@YI{(Hf4e#M$ubje= zlzLSbads&b1r?SJnpNRlOX?=;_)VH^PCzpoZE%;8pWLOWo7`NZ^Ig1Qs_Pn{$XCzh zd3&z2l(44FbzEmS;syIGflI03dc_aeOBmykt5n zf9z8K{=zpkYN< zDg)$Sl$IgjR%beWP>F|?cISx85a&V5)pK<`L&zq?s7juFe%G@JKeH8tT@U?WxM0_A zUBT#LlhEbh^EoS{4ln?&UypdhYJcL?vhO|HoMjfSQP5O0IyGVQbjprYO@lFUTevZ4 zcX&;%u09@ZV2BrL>r?2@N*qz@_~+AtDofrC0etqbZ7 z>U#G4-Snp*?66q$8y<13IgnaQjoS{y7@J;?F*bh{W8D66jIkv%*65x%Y~$xkkhYX- zFVt7G&(W{6GW<7cHT6A35>L9lbhiqRE-;*Sf!5Y3y9ai?&1Qs9av3zl|EQ!irk zzE(h-1li;@$Jfwq#x=IhQkzzO6XJY4x_>X%9)Y++bi5i5;dgV5?Ge2v=JKx*qY(I%|vs1{CiqzoPyM1{b*J<)w0>CpDIuPe$?kn42XLp7y6IV z@fUvqC3M+7yDe1`yNs1wN<{1nPNle%-9dK#RLb=To3qR4Ty*$KapE(^xSfjbzBc^?bV6Kx5` zdLz)X$`ypTIC)WM1t(|_fUb29;c}x#%gkXKCxw5t}AbH)d znQ9r%Mfeqr0e8eQjBa)o%YYd+sq=WNU8)O$w48o1k(4xLh~wa+<#mZTa++P^%< z`bOy*(oqAyt3CyYV>w}?x|Hif?3E{>RvQ^|KM+D`u|NVm1$swBm;c9GIfyOtX!!9C z&KH52JGny%NFtkrv6^}&z}mF6^|ZSe^r`pB>HwtlMBSngA8DNj(_qXm(3 zdBtw4eGW`-@T1zo;#{tgSLn|dHPb)djfa%>u@wLxq830iCUe#enl7YF2JN`2%ETn` zHZojr0cyL{{7@!`oIKb)*H=Z1nAr8z`Q9?7xMD?#4GNM;YY*u8S;;meH$W+6xg<%G74QZjn2H+@S(bI7Q@W>(0^QMmD8K1_T-Q#WE z_ip>Xj$NIMow&|9dRjGr83v$A0w@(_#;7z9Q`?-KRg>39+S!}H$g680pTh}2T!IOK zTmhCZ1}?EZqwXgPyjK{SfP;pa1P&OSudzq)<3rlUAiLR&t?G@}78zEP)vf_{ewep=Hi}ff?aSo|LZR-t2 z$2nx5)6QBv>T=dypHdGdbEyc6?Vdbf{H<)N6={4e(ka7{PF-`|h|;mEvXU^2bq!Wu z?&BUT3n2H$wT1U=7grm~M{|cHa_Qruz-rBzury78e~iF6TgnCXhPkDndG2CV1X3ht zq(z#5(HYPN+L0s&UAvfL9!*C#>IU;}+FHEth476Qw zZbf6In%kz(Nc}YRvL?KpEzNZ)DGCf}725a_m#9G%R4?CR+mxKFuC zzx=t1j&?-X55nQ4%`*S7b%X&CN`txgz;tt93C$Tm^pb&}aH9ffNi7(+ZPf%w*!weR z|Dd*1UKrjIVFCTFt7qElkFf#+^z){^rLhg~Z<>aEFPe{~4#%JW(*hQ4&QxXrJ01jq zFLIiBY+zEypLFS$Zmf#X&5b}ZxH~0*P%zyEa%{LY(8uv(?$(>XfzO%3aPgqWZGnW#a4x$0h;KHGlGxFw1Hn8 z*v(w4M__WmDc6`)v^X4_OKpD*D6^6b*0zY#t??oImyAKRX&XWBbdLt-rVjGjg3(<2 z36$t`Ri3+HzgP(+scG-FR|r1Ta=f`?EZ^J-2DBssqnO4j7}@M?*;lsql(4xz07s%M z!BCc1avPYPfF~4dv4^u&q^9U)3(&oZp;an9noP|RKvia$u{HJjiAHn|)Js6Jl#C5b zP$e)2n=RgbNyHt9G6~1EfI}^j5%aT-Umwy?WUpik^UezN))c}LL=rL2lgbzcGb0uj z6s9dOa)%;rsunJfo{0dh`8}7Q&^LF0sq(Pw#6D4d`0!yJkc31?jx|fPC3lL@fJ9(B zStakJ;af)iY&Sz0#oWd_-aT%A<~uE{3~UJ|Gml1Tins(JxVcjoaTn6*A3~$*n{T31 zr*sfOT9V_O46p(KZl5C~hsnzI`T!!>)Zhh*=rMo6N`0xV>P^U4UPC|7gNj9ddPa|< zOU-Aw_GK^x*eZj!_OrmjKoPOyE#Q2);r1YK#STpm=QQ`Esgi8lEt8A+* zlEfb9$^IfKVJC^lL>h`M@0ZM~8HX*^aB6^p^bsV(edlHy#k(OqEg9371H zv9=PfQ8Zxc^-}{PrLEUK=fiv~{DpFn_^vENlS#CrTWUlm9nx0J31HYNd9W3kSsSpy znK2bm1KvXtay0cul1@t_aa5_z#|gC@xPZ}ZN-h_KAXuew0V(p;=E@}oL!rpL(z0eB zYwCk~=kCCAy)&gXK8#_5*z}(`ENj&_4*rOCU#fY3YiEj&%3_8himY_|8 zt=I9t-Y}A_S`m3SY5%wOkG~9X5N;3UEu2soULnj0m#iNqfk57-MF^tkLr04fEOAb@ z>u@duAkp^8LFsMXLMxnm#lX=d$tbDn7EJFi$jk zd4+veeI)b4HB&>TRwQZ&m#Eb5uHRNAb4~|n0&SZ}z`j%sSkbpEYF~IN zL^HJ_Ua42}&F#7>AIiveDZfEGg+yoOZDKgLmHKZ$(AKchSXGI(RK;VR^GhkBa9?db z*k$5g88!hp@w~n`HvrBpa#sl;p+8Th_YT2Xi3UHj;b3uuIW$1yl1pPSh+fb7)uKzY znikxRqiOpP9GSJiE$xc9N8Nw@j*HJj(ZZ=Ba9Tx@^LOwQ*{%V84UA-pxK}OqIZOb! zt(u~W1fC9$!MY6F3C_}q?1Sn+y+SA><&J*Fj0m-Ce2Bln+?B z!92jOSAD%T!r>E*Z*x%^x?~uR#t+llVR$r7pdSpwu~Fu7PIw7}##q6P$ird6I>A2s zofTY?hTa&4@4yZ84g*eCxvr!m`?KoBbfEzcyHoMWjkLLMqN&!b=RSE(_puYT&b@@v z&UK)7kL#ueVV!0S+SOTRm3YtgDt*_0N0p{MdJ+Yw!M4{JKbIGCAgyHWCnC=w@Iu$0 z-^df|GBx%0TR~`uHU4{9884Y!ia@C&TgRIfcFP;gTnO1*6KHeX33Ma&bDPDo(tFZC zp)S#)(PH+d1ZLKUmy?>J@k|44t_1lzl?i^}P74dJupSAL&maML7b{_8Z6wZ+Eu=oA zwon?CStU0&_$QE&3NcoeUC~$y0SRVGjNl!1r8*H$D$DKc1fS+V-8Jp{C+%Op1E3xq z-^$MwqXSM*GR&lqSCm#EJWaqS(2IsZeWNV0O${=INI;0p?EVsfP__+S^02mhY|HV3 z0dc0)jt#`7O2%+~QeU)L3o;?XO6sOD`Mn0 z?$l2QHkM>inyIR#N^Aq#f0r|(YFky@8aZ;-DGF#2v)zf(s5)gk+9~V=S3p(^J7u-- zlQ>_gE&BK73(RInzBwE0^3B-{Otso(w5$nWDs>n`aD>ACC0Kyk_0vG9+{Q~rT$Z%+ zQ>q%KN-IFm2C#K>NbSA-yuPWqPPH!hS<)3g_Mgni95*RIF#dDE%ldg!QyThsH!#Th zD7tVwXiA;Bdmtcuh@_i}b3r@dw#5+FShPv_q!Ge;BGBICk$V}aMV$RhP&C?-37d~g z8qmeJi(JS8x4OWJn|CQ$u}Q+I(aCHbFiy_!N}qC#U#f@Fde5+A%Jq)sF5 zqrkAe(mF*}Glt7FSR@;?iVaGKCgNfE5*?q2SEm^boyZv1jEwQ$B4gqiu)~nbnAFUk zoYBoR|y2Hjm z7l9ciF&#e|4EmeMmTH*Kks#;`A(nGHqwru>%;cQNr6X(WSr}MU?56@XarLJJIz9tqPf^Urw+;-%U~3dmHkUu z|7`+`dyC$5E5l#zC5~B6a+4>H)ak9dqAD4rb^vLs432F+>s}Smsehd+@DLyPqR8lI z1ahC%)iO<~L>khS4i44Xt_XUkq7JumRa_G~UNN8FtXZ z^G5f7_73!M@kkNpw9k2q@t>mA`35poRdlG4Q@u)WbpI1AzshZcIZNm1VbTu~%Y@cG zc2>Q%rDkP!e{cc=ip=OQJs$=K4eq;sPmI9z4G3Wwn-u*-2eUXbWZ~g{S>_PKP3HDL zI^pBrSIypH`{j4?T=ip-u3B(U>@AWdfgJE* zazKt+Xx%Z}ypzvX&{@gglzBHmxY8!lB`7?}Sx>kpU{d;@-^C#aCE~EH-D%ALNAZ*}xk^@yyXjHpFZpd1?G~^fmTPB0Mf7E2$q|FaXuB9)NNk306 zg!F0-Rf4~i$!w_F!nK7=uInFsw_aMPzqUA6R_#YWxUMNGWv0<@HsGizXiIc(FeTM6 z%RkO}Mt0N8q%V@svnvF=rG<@$WA^02uOQz-R|vD36sT~9-kyTj;Aa*t~3MWuL;ra`7fnZ5h817mWjuMJ|CsW_UrAD}bX(|QUQG|mhX!b}Pms8X9yMih>AgbnwdY2b%N?BBiI6!83t?f)y z!TfKJ1j}o(6PzK*Rz1xu5O%m1n6>`KlB0ib4loE@7?|5O3g`4Ae4zWTb$n9UL{}X< z9crm_@sE(SHQ=hYgMoD7+>KWip$gZ<_F>D{ZlhqSlg+ftb*|UtJfL76azWymR5<#+ zUnBu%F0&wuol-=bua=RYraLtU%@*da(_OsCrKy|g^P_N7+;Jy$iwDk&wv<&y2Bb_U zb8N-6dQ)iUC>*UvcZhY9WLHqEbKFj^j>1Wah7qnqFeLvHXi%`~P#b8UG7xpr2km6!zBa_p~}%Xj+l$6X*8ay z*qxg=iI$JXcj19_&uBbkNT>*(?8)$xYQbfd=MSM5!Og~M8l8?4H359Ml{7CMrxMuA zXZn{r5Zw;>yB*^saF~!`n=cMO0VKKzmf@P12RDUDO0dyI?^&v|U8Msu@Q}%ujqcIB zaq}EeS~1}uI?-ZxcTWJ?`>o;tSGOo zgc)mbUoa&5!Pe#9p)b_*d?p^2dhQKrzB%%Inr4MgnJRk1CnGfVfh8GE8pf-h`Kc%7y` zAlU;ge5?h57UIOtL7I9Izo0K+>sXLNqE|6$&5Qbum5Uo3&NM}wS{85a1Jp7Wn~1-i zmW;)b;pY8pASUjNaMhbvbj5D%rFE=@?E~r^i(?`;Kge203P)cwyo@%a=PrbW;I_L1rb+}Fx#{;Ly^bG(rsnY)BOL1* zo4`12wn!5Ho&eJ;izH0C8(5&()b9cagEB(V#})R{t%Xc$V*w3{=1}q+NEWb$k zPIkz_E?L+y9}{T8>HiZfswn_xV@?2hf zOoioy=;E=6-fsyGIgP{uL{=vg*^J+#GHZ-=9swNG-?0i31CixA7UUUHDxFe*;1)$RoT&xWd0Q{o zY&Y%@mNyvkA9)rWI*orLeeTxHgRnW_evu$M&b{3$pm-$FVLMQqC_^>hYU8vQ_ zu_vmWfHO3HcvGpSQ$2 z;XC&CgKq5j6{Ri~Kl3m7#-j%ly{f86uqG{pX%rN4d`<&-I5!VR#g~b0JRVJ;6e8^5yjR z;Dlyq7LL{#j?0}_NrR_2%jl#m@DCmTlIN(9VB0MZB<`<;&lfA>Os2NnTcg1nH$Vd6?2r_pP9U zr6&!z@78kWRf!SSz4DkIX(TM{k!!pk1aK4yaj*ARy^j!kuO+TMabIR3+F@ zPEXZ6`OA-|PvLKe*BICEZo2GV{N!M_G3d0rA~8?>{YysE8CBSio1QfWsoa!Uz!L1( zK@%-_DDgf?tronSID%=f1sA9KuapU3`WP~+*kq~`KeMSOo`0F0oP__L4EVUA5r{8IFqr9u?x9U1rG)7gyRtM_KXhcoUsz z#Vf-3;Ohc4GyB;*g%+@<PV17-CyU7fu9b@joKo88?VJ?h*RhL_BqzdsZwXk_TEfK9u%WGfJsjC*;YoP4lA_ zxoQ>?;&{7mp_1T)He5=j+V{vR`8{Rkl=0zuouJQ@P-~`Sa=JT)eo{@q$i+ zjVcvTlY<4by|Y485Puc@R{skw#RUumU`Pa`fr@&-uuG@85XZ_Szn9Uasj#33KT?&q=FFP7YH1Sl_q2Tyevx?V>CAlm zgvqVSgu6oEuh&YfXMHGhB0B>=u-3(wz>UO_6J;L1O0VW))YdjGSGk9*_X{vy= z#r<`B)?BI5);eK*1ZgDz{Z$(wvK@t_QW|@w+eX2d=B+Bs)7vkze_NoPy_b2mg3lFcU#aZo|Q{+`4v*>|L zmvU}fn9w!s)U|A@XZN)mx-~sFMp3xipy-Yy;>7FC@(G-POUdIlPO@s(2|94PkJs)>CCGbQK@oW ziU#v|!{?Ko6$uuVoohoaHOVtHPVk74C~3Qi5V05JKxi9^6Lb&3Nd=#l?nb7Ub$kJ5 zpZ6xx1s8B(Zam3oU^nr@xck`gtB6YfIF*Xg%gy{)UHw(O%Gp}_jDR<^!(~4%>Kvap z(v9=VCgJ>acW7QtWR?}!N9=CStawv_x$PG0a#mt#D5=Jso&zs%I795g%#&-!F1}LP zXYUvj3$ZaN9vi{=HYV3$hEt=`!U6TQNxt!6dY+Zq#6y&cw<~8uj4BfAtIVO8%E| z0IxI}d@5tyNtI`AIGn__scHmc0yx?EJ~p7l`_86JcvBDF4{8Q%DCl}dun@4DG7b3F z`w4w!8qSC|{DT`&8RT+mu!t89l#zs$B+ub#Sc{3*OV3V+4rnh`72_$y|2CabjK>jM zFnzHY7n=-!bvg6U`TFk2Jm+SaD^N#s<*K5thOIw*9SNr3dM4j(2WZSgU|7IKrR;}r zinik~5Mk1SUU7?Hji-)>aAGpsI01>C)Uq}-TyVO%1Wgb>ZSG*ypxHp_CQ)Ld^iVtwD<2I(< z;H+Ar)Wks(|i9M$D?(ag$E<%Z(aK*X$Rs zF=4Q)Ag=I*LNfiQT>A9Gcm;9)lm7HDEC`j-=$TBiK0_@tu_4CRy=sPis1q-Kxs`tz z&xA#ss*?7|`vY}AOTBqTEB_EaU!SVo0D4fW^M6bC%*0P6b-Wn{@*dtb6VZ%%B*U;{ zJ1fHiM83sx$3;5xk2qO73QmPgH90EU&D?r#Bz@_R_>QRg*B>%<%siOGM1a|>0@iek z`g=C@{}BLo@1`mnP=;-%XNCi;wz7Z@Tw^D z=TOCLygjKs;yBwJ(cEwp@--2MSSa9@*G-;05MsYTPtV2^iVJv)eZ5n~JtPq3Aj8eN zZ{`Mt+|SMf>LAu!sTLz4;u0L}hDCIng54O_@jF40i6IaPev=E%UKm$Tl_|kMm)PNT zIrl&KnkXN(7&re787m*cuX=dP7RR&bom;$;zIFLqA|9{$`{s|feb{;E$bsX&Q~O83 z3s|N~Sw)O*?z=Y~4xl8kla{oqM#Nb=D&THW_$jo>a*rEAsgCCQ95||Dw`W8M{lhq+ z9nJvvf^d%LW_sn0b$pHbqrX@Zou{0==Eat?mdUw$a#QkN%ew>Ez9IoGw!;a(3QHU4 zHfRJ`Klp`C%SbmTWU1nKmjc|^OBV;a>J?ze!CN|KoVY8>clA|^PNN|9>xH-!JRXTL z#sYhaX!QRn>jM=Ai7DpHiT}%Chx#rapEx^5g{Ps-u)m!$n*Dci0#;R6!c<)DaMk_a zxcHGO9X}kRjefT9QZO@YAc!|8wxHqsB2_iG%S?h8f+Bn_MWs3bp7+kcZF4YJL<`*e z1gw^CQ^0DQ;6@;0Ox?5q{q z*wv*94Dd#z1YOo#0{OAQ!fuaH#S!8=@P z5I_~7no+f7ma_ao0$c<@`B^D&71oJT+AB;x#KY@DE(q4999%WS6%2xZ@Ex2z;w8?` z1uL@!`?cl}?ly&fGMwm+vTnAXg1296QiCypHoFVMhtFDGuuh<8MLU^w|B2e#rp3Yu~lS>B) zAz9xXd%^mt6{2%WIHSLOK*2ydnqARR1yNFIG)FSL6*Hji^1~iU9V`D9h|`>sN!50D zAXEffqQ!zlsOT=a{ku9P4>zA6sv{D%W31#{CBg?B$e^rEys$;}hT8+5xd83BU)r*5 zZ|Zn(Bpr+q%p=0Sk-z-0$0^Gh8|ACnS2MP#)NX2f6mKKwG*vCa<5CQ-@WPem%#$h` zs3;z+o4pkyYLHQ>M$!zA0v;NwE80qlJs{2;4(gFUEPq>!Y2EaZ;pVzr-xk_auZFlAYrHhH94J z^ThE3{b>oln|Pm~sU=t+353mwePR; zoZlYJs?M5Wm0lR+z4u$o*T^N}t3yH!?I^+7DQos+9v~17cztw&bu>zG-o&?20ZMy zT`&SK6x4}WYql6wv%+-2I2h`*x7`W?8c!3Sz=?5=yBGk)&a?6)j&apY1apB&9b@U@C%`pE zW12KDRyP~h@laFjc8CkG-~K0>q9KAH{x&>uFm!wD4tYk$yy}p{p;83HQ0r2cMI8)X z8zQxIENO}bD8*jh#j4oDp*vzFI1Mj^!~(l`+1TDHRVafFU>Pi7;LhrpES9XM9nv`7+0D+R zD0!Um)zQq?g?G`!1-RL4Ot6$X{P3L64Uy8sm<| z8RPfH<%G);Z5~6&03gBz0Lyv?g5iSa(`EQw!j6<*d=g$J@t&u_D}o-b z!*TfrUDA;4u_8@~<%U5JPqadwZH!pr1(hY0fK@1#_y-yh9+%Aci;%)Vsbc^gR}V7F z5KK$z@uF~~U?YjG6jDC}N4x9cb~bz(N7;af&hXw~BQynVkCkWYO$tsP3}teA@Acop zV!IZAg*n`89gbfaEULj0Gyzx)S3Qmf=2JPoqRkWpDEfku7Xc}bf6|37;!%UpX<+)$ zt)XyKCk|u&n6|u#6SKW1#7GKQIb}Igjr$+l5h(&MOG3u+CMJq*BFAy8DRjG7BG(_K z`i;1bfZM)(BaR+q^EHL^M}fPYp5BP#bIki-X*q29o$^8qd)dweQ zsp4g9NERZu1ZUxl!|XFvqmBpqB&i^pT)eZ}`3Yyc%4hG_1yx=%#&5l5OgwSTnDo{)qv^!8%u5)g z@Z5IK6W`-iJibV~e*(JR=Jrhf8C-dd5ILAb=n-^pImiMM3ssTKg+59-tfRQkg@gvg70FPru?XNn|-a zeGNitk@+;`I-V9?Ri{&W!^S&bldUwvAnDMks*bv^V|}=@UJ@f{h;Ob`V||f!UdM;Y z;PdpwUO29B=F#yt;572zy>J2($RystdO0(W_@e03Hz4E#mAh}?wUPYbhuyKC!(k4B z;0!t~i=Y*Q>x;>FVvVeSi6oJt!S(GVo}>@1|CWq_9F4~$jsWg+Ff@uB;i+a%;u}m4 za?lR8@dpmN36V5XK~l7hgVomZh7t0X!B$OGkk_IkBGp!PQ+}2z>xBHW|0N)l@&-78 zDd6A(Q}H}`csP756Eyat5VX8@7QSTx!4gp{o400u#cI}6(9Jv<|6j(6q=S?snfy7% zV^)$cF)ZDas3P0&04H2dZ@=!*6F9v*@1keaB$^2D$tN{Q{JlDZ@QN|%Vz1G(wKtOo z%b7p9>{2TO&BMb8PQd6K4J;d;&uPeaKpESENi?ksCfPtt^mH)b%;~1rg2@D^yE}vw zv*H&+NJ^yh@Hq(VRQ3X8_8Jr4>Xj*SKRp{l^u&6E_CTuvbNB0%ie66-P;%A0b~-AQ z+zSI4eufi07-(xKNhHn&dN>s3sgI%Ep`@9u`IP}=E+f6b0V1~4&p>?=?2$6BafHND|GPX-TkvP0zm?zajx^Wyr)uAEax&}I< z8%>~g9VD;@)JwCiCz6?F{}*u9_s2~5W}i->*xG+|$LF9;X7w+z`JwF`RuUKmedbBYAx{|+ zZ66|0;41-H*;;y09kCE8>C9u~RQCVt}CIlLQu`iYxs&xG4qgGl2 zfcPsRp9%wrVH`G#w?d~bi~d^Kf3c2o+VdDWL%hrA@x`!MGf?_s@{`GIudwXQ_%}pt zq%r7vHiCbajz2cWCC($2cx@hi2{}7}IbJ=hfyg5E(D9|PxxPzub}7j*G)~W~DL0!s zQw}d(2H%XaME%AWrJbc@sGetDrw+HH?+F5ly=F}wjV>c8#JP#)m61um?`v0W7k%v# zW>mZP-{NbFtM-n()z=QE-Wrly11M~+9rL)=Vy)u+^N<3JyGB;)Z|{;l+OtYRD5t| z=eL#Y)R~Q6@lo`qE!DM~q|rKA99{x^m;J?1am40L8@)^2A*sBgE3Ecf0FU&1Ik~rV z6Q8@KdISI{-=mHWR0nq08zrK-TJ0{Ax2sGjvxp08kAjK&`WgoRwlC8Ezx8EENqhr7 zCMuJX?zi0yg96>@kqXjc;r9<-dgBJ1yEkNok$pMH<77Hm7;S1#>5$?K=Q?HXZBK@a z9->dQL3Z**y>`+o0ms%_J!sXT)j9lyQ@sghKSQ1%I{2z_Q1a~%^O9QWz?vzxtp_BFTf z>1a8)t20wV>ZQ-6X_V)awbaHCV_PZNRsNueL%+8$nqNht7gl|^{Da@C9iw^%WmdwJ ziueZu2pk6p+~eK6Pnyx$Aup`+FCUZ%9=HL-TgCf72YTFF)^xa+YWb&^CTgE%cYn65 zQM&2TDqg4D;!xKVm8R)dA6 z;jvWEK|Ir*CDC|5<8-*hfjtdu3#_fwv6kqgm0vAF5+)6U`jePop*z-+2$-*9Etwds z;jI!0LBJw%9T7r%IN#`SCS-N$LvGK)b>w~wv9tG{BSWCe>F3Dfkjr~s%*}hAJRjRr zVY#T=GH~l4d``zZ6j5$=c7HPlGH5+{l!e~blW{To2TD6?h-Kk$b|oy&E8TPvdgzJu zq%-{7P*69bHSLI!)}B6$?%F^m8=S*x4~a+y)cn zygrhO^xnT;S9c)oj7N5;W%ouKL5jfAY4uXd3K5{R8nr-*G1moI!5~B9Po25hLZTXS*ZUPlv z_alwlOtRA4T*pcH1UCQdma3EPsQvJfglN9j2*25_$Sqa88~Y^N1%{3W-CUao1iKlG z^R`G(oFYoyyi5U6ff9#8Dk+KrHWb^~IH{yD$`ihYT;%kuyK|CM>6IlZALSYPI+?8O zx4WJde<9Tz@h@xG$&5F>Cw?a>AR$#FJ)j2Q67NW39Cfskd8Ba<{koM5wJ8T3R#CIK z(=SU?I=_>-?|axqFtWrQ*(irQ&&iD{DS!`~spbtet+5Xa4W zYbtH<5D52t;pz4eD<)#>ol{UtL2opoG?&l;>FU2|q-XfLR)=6c; zP}mKzm3ggHQh&3=@T^oaH)fOE2GvR>Z80w1rj+`5tEDnNHqgqw21jCeb~M{zg=oRQ*g>ya!f%dpVu*KB%T1&-VAp%LGV2$4h1n zagVDqq9C+ta97Ok-g1XpD0fKXbo@fwz2wV`Q}=ivNCHy!(M(X3I#tqm&v;OX&&?d4 zWnGsO`iGC)VZ5o`10Q#Ht)baB!zO3FWs+OykXT z>pmcf<@eGf`^ZbA>LN<*PhmX7v0yYtnY@#)Pr*k?$PFd&DwH+jKYT!fn)*|Uc_Y-Gt za6ciG7nwdyIVIDzW zL^U6Rb~g`YwXrvA#Si?5ExZP5`w*nIV?e`U2*r8-OcM_S#vO1Ta+vIjwh`>ZRyMGa z)WH9FpuqCLp)}?r@>!6XX?Rpl$q_PBBRnD_cfM!g5%M01Ik0I8oW{;%cR$2kKyzE3 zm9TkWvnTr)@pHsI&=Y@>lt5rwGl`Y_Zgz z`}HlY47qgu=Uk;2wE2QdF?sL#yTS&@taa-fW}Kean5RbvLUbPqEia#igNUTK*k3 zUh8dCMIOIdYG|ZKzvG@Fj#p{kzqv<(#HR2L*4zK)Hb@!6I$H2Ocbb?>sp$uZl=zoH z=m{^8KYLD)ctTWHAJKg zaU^d6)nDLD1Wl&d7hn(lxwP^E7q`$oF=>#vAR^7^wl<;ULC_Db6)_0hLJ|`1s!5|* zws80J5( zJI(nL%Cf?BNO5fQC-k|?Tpn?ppl8_A`*)gng|iX&A(l^}yRQJt`P=Dc$#dMhp*6g@zyOGt(nlPI zwwpamgWG3Rl6{6@;6mhUY!W*SUS*qAUe2;R+0BvD~bHHFGHd@XGK47zBw-`Y8Ca z-0nQL4YUt>6D{ff`$y85@6EI0kHxcN#5fLJlFyS*OJklKm>)&O8k<9|`J~>ah|I4# z4p$x6tugq|WmreY1!+*>s0VH~gERei>8*w}$9w`mPp9nB!N&_kSq7%0_%wUv0sm3o zuBarA`)D3ktR-#>J&hHK#E{)U6bFeToput%>_O;Gz|Pz=Y!Ag{nSq2k1)KofPD?n2 zV-UP2BFW9wf%ilxQ7A?e+fdIKg#wPa%pr6puSg~~HC+o&jaeDEN=NtcprpJUJO*SRw|YZ|5wTi{;8C=HjK?ax_IK!%c;-m|9N)rprH7|sRyR3+dh7E`u_tLo#u7` diff --git a/firmware/boards/esp32c6-zero/images/vaultkey.signed.bin b/firmware/boards/esp32c6-zero/images/vaultkey.signed.bin index 9f1d6700bd6015268e4af7d7c4f380707d306885..045671edd2f16d7485e932859ad689c645a89a61 100644 GIT binary patch delta 29354 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 = @@ -189,6 +197,7 @@ fn main() -> ! { Uptime, ChipKey::detect(p.HMAC), KDF_MEM.take(), + KDF_COST, VAULT.init_with(store::Index::empty), BUF.take(), ); diff --git a/firmware/boards/nrf52840-mdk-dongle/.cargo/config.toml b/firmware/boards/nrf52840-mdk-dongle/.cargo/config.toml new file mode 100644 index 0000000..387ca1e --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/.cargo/config.toml @@ -0,0 +1,3 @@ +# Build from inside this folder so this file applies: `cargo build --release`. +[build] +target = "thumbv7em-none-eabihf" diff --git a/firmware/boards/nrf52840-mdk-dongle/Cargo.toml b/firmware/boards/nrf52840-mdk-dongle/Cargo.toml new file mode 100644 index 0000000..39de912 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/Cargo.toml @@ -0,0 +1,65 @@ +[package] +name = "vaultkey-nrf52840-mdk-dongle" +version = "0.9.0" +edition = "2024" +rust-version = "1.95" +description = "vaulttecdev hardware key on the Makerdiary nRF52840 MDK USB Dongle" +publish = false + +[[bin]] +name = "vaultkey-nrf52840-mdk-dongle" +path = "src/main.rs" +test = false +bench = false + +[dependencies] +vaultkey-core = { path = "../../core" } + +# Everything below is what this chip needs; the key itself knows none of it. +nrf52840-hal = "0.19.0" +cortex-m = { version = "0.7", features = ["critical-section-single-core"] } +# The MBR at 0x0 hands over to 0x1000; `set-vtor` points the core at this image's +# vector table instead of relying on the MBR to forward exceptions. +cortex-m-rt = { version = "0.7", features = ["set-vtor"] } +critical-section = "1" +embedded-hal = "1.0" +embedded-storage = "0.3" +usb-device = "0.3" +usbd-serial = "0.2" +static_cell = "2" +# The INFO text, built at boot; already in the tree through usb-device. +heapless = "0.8" + +# The workspace's table with one difference: `unsafe_code` is `deny`, not `forbid`, so +# the one place that must name memory-mapped flash (`vault_region` in src/main.rs) can +# say why with #[expect]. tools/checks.sh keeps it identical otherwise; it stays last +# in this file because the check reads from here to the end. +[lints.rust] +unsafe_code = "deny" +rust_2018_idioms = { level = "deny", priority = -1 } +trivial_casts = "deny" +trivial_numeric_casts = "deny" +unused_import_braces = "deny" +unused_lifetimes = "deny" +unused_macro_rules = "deny" +unused_qualifications = "deny" +non_ascii_idents = "deny" +explicit_outlives_requirements = "deny" + +[lints.clippy] +all = { level = "deny", priority = -1 } +pedantic = { level = "deny", priority = -1 } +# Restriction lints that pay for themselves here. +unwrap_used = "deny" +allow_attributes = "deny" +allow_attributes_without_reason = "deny" +dbg_macro = "deny" +todo = "deny" +unimplemented = "deny" +mem_forget = "deny" +exit = "deny" +missing_assert_message = "deny" +undocumented_unsafe_blocks = "deny" +# Pedantic lints that only ask for boilerplate. +missing_errors_doc = "allow" +missing_panics_doc = "allow" diff --git a/firmware/boards/nrf52840-mdk-dongle/board.toml b/firmware/boards/nrf52840-mdk-dongle/board.toml new file mode 100644 index 0000000..981728b --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/board.toml @@ -0,0 +1,29 @@ +# One board = one folder. This file is the board's identity for everything outside the +# firmware: the CLI reads it at build time and embeds the images listed here, and +# tools/build-vaultkey.sh reads `chip`, `target` and `image_tool` to build. + +name = "nrf52840-mdk-dongle" +chip = "nrf52840" +target = "thumbv7em-none-eabihf" # rustup target the firmware is built for +# How the ELF becomes images/vaultkey.bin: a raw image of the flash from 0x1000, which +# is what an SWD probe writes and what the bootloader's update package wraps. +image_tool = "objcopy" + +# How the CLI recognises the board on the USB bus: pid.codes' test pair, for a key +# nobody else gets. src/main.rs announces the same pair. +usb_vid = 0x1209 +usb_pid = 0x0001 + +# What is printed on the button the user is asked to press. +button = "USER" + +# The radio peripheral's 4 KiB slot. Its driver ships inside the HAL crate, so the lock +# file cannot show it is absent. tools/build-vaultkey.sh fails if anything in the image +# reaches this address. +radio_base = 0x40001000 + +# Flashed through the factory UF2 bootloader for now (docs2/makerdiary.md). `vkey setup` +# talks only to the ESP ROM loader, so it never picks this board. +[[image]] +offset = 0x1000 +file = "images/vaultkey.bin" diff --git a/firmware/boards/nrf52840-mdk-dongle/build.rs b/firmware/boards/nrf52840-mdk-dongle/build.rs new file mode 100644 index 0000000..908621a --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/build.rs @@ -0,0 +1,13 @@ +use std::path::PathBuf; +use std::{env, fs}; + +fn main() { + // cortex-m-rt's link.x includes memory.x; this puts the board's copy where the + // linker looks for it. + let out = PathBuf::from(env::var_os("OUT_DIR").expect("cargo sets OUT_DIR")); + fs::write(out.join("memory.x"), include_bytes!("memory.x")).expect("OUT_DIR is writable"); + println!("cargo:rustc-link-search={}", out.display()); + println!("cargo:rustc-link-arg=-Tlink.x"); + println!("cargo:rerun-if-changed=memory.x"); + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin new file mode 100755 index 0000000000000000000000000000000000000000..2b6df7291f29262b2eafaba69a4c47ec1a1a29a4 GIT binary patch literal 77100 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 z%0D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 Y&ENPz<1c;R9IsqCE#Bz*OY> = StaticCell::new(); + +/// RESETREAS bits, named as the product specification names them. None set means a +/// power-on reset, which also clears them all. +const RESET_CAUSES: [(u32, &str); 9] = [ + (1 << 0, "reset pin"), + (1 << 1, "watchdog"), + (1 << 2, "soft reset"), + (1 << 3, "lockup"), + (1 << 16, "wake from off"), + (1 << 17, "lpcomp"), + (1 << 18, "debug interface"), + (1 << 19, "nfc"), + (1 << 20, "vbus"), +]; + +/// pid.codes' test pair, for a key nobody else gets. board.toml names the same pair so +/// the CLI finds the port. +const USB_VID: u16 = 0x1209; +const USB_PID: u16 = 0x0001; + +/// The vault's flash, 0x97000..0xD8000: past the end of FLASH in memory.x, before +/// Trussed's filesystem. `LAYOUT` counts from its start. +const VAULT_BASE: u32 = 0x9_7000; +const VAULT_LEN: u32 = 0x4_1000; + +/// One attempt sector and two copies of 128 KiB: the sizes decided in +/// docs2/makerdiary.md, smaller than the C6's because this chip has 1 MiB in all. +const LAYOUT: Layout = Layout { + attempts: 0x0_0000, + state_a: 0x0_1000, + state_b: 0x2_1000, + state_sectors: 32, +}; +const _: () = assert!( + LAYOUT.fits() && LAYOUT.state_b + store::SECTOR * LAYOUT.state_sectors == VAULT_LEN, + "the attempt sector and the two copies fill the vault region exactly" +); + +/// The core runs at 64 MHz on this chip, whatever the clock source. +const CYCLES_PER_MS: u32 = 64_000; + +/// Argon2 over all 128 KiB, with as many passes as fit in about a second on this core. +/// 48 passes took 2645 ms through `vkey check` (2026-10-13), about 50 ms each, so 20 is +/// ≈1 s. There is no chip key here, so this cost alone is what a copy of the flash is +/// guessed at. +const KDF_COST: Cost = + Cost::from_wire(128, 20).expect("128 KiB and 20 passes is a cost Argon2 runs"); + +/// Argon2 working memory, in RAM for the life of the program: the key derivation has +/// no allocator, and 128 KiB does not belong on the stack. +static KDF_MEM: ConstStaticCell<[Block; KDF_BLOCKS]> = + ConstStaticCell::new([Block::new(); KDF_BLOCKS]); + +/// Where every item sits in the image, ~10 KiB: same reason, same place. +static VAULT: StaticCell = StaticCell::new(); + +/// Two item-sized halves, 16 KiB: one to open or build an item in, one for the items +/// carried across while the image is rewritten. +static BUF: ConstStaticCell<[u8; device::BUF_LEN]> = ConstStaticCell::new([0; device::BUF_LEN]); + +/// The clock tree outlives everything: USB holds a reference to it. +static CLOCKS: StaticCell> = StaticCell::new(); + +type Bus = Usbd>; +static USB_BUS: StaticCell> = StaticCell::new(); + +/// Milliseconds since boot, counted by the `SysTick` exception. +static MILLIS: Mutex> = Mutex::new(Cell::new(0)); + +#[exception] +fn SysTick() { + critical_section::with(|cs| { + let ms = MILLIS.borrow(cs); + ms.set(ms.get() + 1); + }); +} + +/// Milliseconds since boot. A tick that counts itself, not a counter read on demand: +/// the auto-lock compares times only when the next request arrives, so a counter that +/// wraps between two readings would let an idle key stay unlocked. A flash erase +/// stalls the core and swallows ticks, so the clock runs slow by that much - which only +/// ever delays a timeout by a fraction of a second. +#[derive(Clone, Copy)] +struct Uptime; + +impl Clock for Uptime { + fn now_ms(&self) -> u64 { + critical_section::with(|cs| MILLIS.borrow(cs).get()) + } +} + +/// USB CDC-ACM, polled: every read and write services the bus first. Nothing runs from +/// an interrupt, so the bus waits while the key computes - Argon2, a flash write - and +/// the host's bulk transfers simply wait with it. +struct Usb { + dev: UsbDevice<'static, Bus>, + serial: SerialPort<'static, Bus>, +} + +impl Usb { + /// How long a write may make no progress before the host counts as gone. + const STALL_MS: u64 = 1000; + + fn poll(&mut self) { + self.dev.poll(&mut [&mut self.serial]); + } +} + +impl Port for Usb { + fn read_byte(&mut self) -> Option { + self.poll(); + let mut byte = [0u8]; + matches!(self.serial.read(&mut byte), Ok(1)).then_some(byte[0]) + } + + // A host that stopped reading has nobody to tell: what it does not take is dropped. + fn write(&mut self, data: &[u8]) { + let mut rest = data; + let mut since = Uptime.now_ms(); + while !rest.is_empty() { + self.poll(); + match self.serial.write(rest) { + Ok(n) if n > 0 => { + rest = &rest[n..]; + since = Uptime.now_ms(); + } + Ok(_) | Err(UsbError::WouldBlock) => { + if Uptime.now_ms() - since > Self::STALL_MS { + return; + } + } + Err(_) => return, + } + } + } + + fn flush(&mut self) { + let since = Uptime.now_ms(); + loop { + self.poll(); + match self.serial.flush() { + Err(UsbError::WouldBlock) if Uptime.now_ms() - since <= Self::STALL_MS => {} + _ => return, + } + } + } +} + +/// The vault region as the slice the flash driver wants. Taken once: two slices over +/// the same flash would be two owners of it. +#[expect( + unsafe_code, + reason = "the flash driver takes its region as a &'static mut slice, and memory-mapped flash cannot be named in safe code" +)] +fn vault_region() -> &'static mut [u8] { + static TAKEN: AtomicBool = AtomicBool::new(false); + assert!( + !TAKEN.swap(true, Ordering::Relaxed), + "the vault region is taken once" + ); + let base = core::ptr::with_exposed_provenance_mut::(VAULT_BASE as usize); + // SAFETY: 0x97000..0xD8000 is flash outside the image - memory.x ends FLASH at + // 0x97000 - so nothing the compiler knows of lives there; it is page-aligned, as + // the driver asserts; and the flag above makes this the only reference to it. The + // flash controller rewrites these bytes on erase, which is why every access goes + // through `Flash` and its fences. + unsafe { core::slice::from_raw_parts_mut(base, VAULT_LEN as usize) } +} + +/// The flash controller over the vault region, with a compiler fence after every +/// change. The region is memory the compiler takes for an ordinary slice, and an erase +/// rewrites it behind the compiler's back: the fence keeps a later read from being +/// answered with bytes loaded before the erase. +struct Flash(Nvmc); + +impl ErrorType for Flash { + type Error = NvmcError; +} + +impl ReadNorFlash for Flash { + const READ_SIZE: usize = as ReadNorFlash>::READ_SIZE; + + fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), NvmcError> { + compiler_fence(Ordering::SeqCst); + self.0.read(offset, bytes) + } + + fn capacity(&self) -> usize { + self.0.capacity() + } +} + +impl NorFlash for Flash { + const WRITE_SIZE: usize = as NorFlash>::WRITE_SIZE; + const ERASE_SIZE: usize = as NorFlash>::ERASE_SIZE; + + fn erase(&mut self, from: u32, to: u32) -> Result<(), NvmcError> { + let r = self.0.erase(from, to); + compiler_fence(Ordering::SeqCst); + r + } + + fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), NvmcError> { + let r = self.0.write(offset, bytes); + compiler_fence(Ordering::SeqCst); + r + } +} + +/// No chip key yet. This chip has no eFuse key, and its replacement - a secret in a +/// flash page locked by the ACL until reset - is not built (docs2/makerdiary.md). The +/// vault is protected by the PIN alone, and `vkey info` says so. +struct NoChipKey; + +impl DeviceKey for NoChipKey { + fn bound(&self) -> bool { + false + } + + fn mac(&mut self, msg: &[u8; 32], out: &mut [u8; 32]) -> bool { + *out = *msg; + true + } +} + +/// USER button on P0.18 and the RGB LED on P0.23 (red), P0.22 (green), P0.24 (blue), +/// all active low, from the Makerdiary wiki. Confirmed on the board: P0.18 is a plain +/// input, not the chip's reset, and the tap (amber) and the double tap (blue) worked +/// under `vkey check`. Red alone, the 5 s hold, has not been watched yet. +struct Panel { + // embedded-hal reads a pin through `&mut`, and `Ui::pressed` takes `&self`. + button: RefCell>>, + red: Pin>, + green: Pin>, + blue: Pin>, +} + +impl Ui for Panel { + fn set(&mut self, state: State) { + // Three plain LEDs and no PWM: amber is red and green together. + let (r, g, b) = match state { + State::Idle => (false, false, false), + State::Waiting => (true, true, false), // amber: a tap approves a code or a password + State::Export => (false, false, true), // blue: two taps let a backup out + State::Ok => (false, true, false), + // Red both ways, told apart by how long it stays: held while a wipe counts + // down, a blink when nothing was confirmed. + State::Danger | State::Refused => (true, false, false), + }; + light(&mut self.red, r); + light(&mut self.green, g); + light(&mut self.blue, b); + } + + fn pressed(&self) -> bool { + let Ok(low) = self.button.borrow_mut().is_low(); + low + } +} + +/// One active-low LED on or off. +fn light(pin: &mut Pin>, on: bool) { + let Ok(()) = if on { pin.set_low() } else { pin.set_high() }; +} + +/// What the chip says about itself, for a maintainer with no probe: the build code from +/// FICR (`AAF0` - the third letter is the revision), the UICR `APPROTECT` word as stored, +/// and why the chip last reset. The first two stay raw, because what an `APPROTECT` +/// value means depends on the revision; docs2/makerdiary.md reads them together. The +/// factory bootloader leaves the reset cause for the application, and it is cleared +/// here, so each boot reports only what happened since the last one. +fn chip_report( + out: &mut impl Write, + ficr: &pac::FICR, + uicr: &pac::UICR, + power: &pac::POWER, +) -> core::fmt::Result { + let code = ficr.info.variant.read().bits(); + match core::str::from_utf8(&code.to_be_bytes()) { + Ok(s) if s.bytes().all(|b| b.is_ascii_alphanumeric()) => write!(out, "nRF52840 {s}")?, + _ => write!(out, "nRF52840 variant {code:#010x}")?, + } + write!( + out, + ", UICR APPROTECT {:#010x}, last reset: ", + uicr.approtect.read().bits() + )?; + + let causes = power.resetreas.read().bits(); + power.resetreas.write(|w| { + w.resetpin().detected(); + w.dog().detected(); + w.sreq().detected(); + w.lockup().detected(); + w.off().detected(); + w.lpcomp().detected(); + w.dif().detected(); + w.nfc().detected(); + w.vbus().detected() + }); + if causes == 0 { + out.write_str("power-on")?; + } + let mut sep = ""; + for (bit, name) in RESET_CAUSES { + if causes & bit != 0 { + write!(out, "{sep}{name}")?; + sep = "+"; + } + } + let unnamed = causes & !RESET_CAUSES.iter().fold(0, |all, (bit, _)| all | bit); + if unnamed != 0 { + write!(out, "{sep}{unnamed:#x}")?; + } + Ok(()) +} + +/// Fail closed: a panic resets the chip. The vault comes back locked, and the statics +/// that held keys are zeroed again at boot. +#[panic_handler] +fn panic(_: &core::panic::PanicInfo<'_>) -> ! { + SCB::sys_reset() +} + +#[entry] +fn main() -> ! { + let p = pac::Peripherals::take().expect("the peripherals are taken once, here"); + let mut cp = cortex_m::Peripherals::take().expect("the core peripherals are taken once, here"); + + let info = INFO.init(heapless::String::new()); + writeln!(info, "{VERSION}") + .and_then(|()| chip_report(info, &p.FICR, &p.UICR, &p.POWER)) + .expect("256 bytes hold the version and the longest chip report"); + let info: &'static heapless::String<256> = info; + + cp.SYST.set_clock_source(SystClkSource::Core); + cp.SYST.set_reload(CYCLES_PER_MS - 1); + cp.SYST.clear_current(); + cp.SYST.enable_counter(); + cp.SYST.enable_interrupt(); + + let port0 = p0::Parts::new(p.P0); + let mut panel = Panel { + button: RefCell::new(port0.p0_18.into_pullup_input().degrade()), + red: port0.p0_23.into_push_pull_output(Level::High).degrade(), + green: port0.p0_22.into_push_pull_output(Level::High).degrade(), + blue: port0.p0_24.into_push_pull_output(Level::High).degrade(), + }; + panel.set(State::Idle); + + // USB runs from the crystal, not the internal oscillator. The classes take their + // endpoints before the device is built. + let clocks = CLOCKS.init(Clocks::new(p.CLOCK).enable_ext_hfosc()); + let bus = USB_BUS.init(UsbBusAllocator::new(Usbd::new(UsbPeripheral::new( + p.USBD, clocks, + )))); + let serial = SerialPort::new(bus); + let usb = UsbDeviceBuilder::new(bus, UsbVidPid(USB_VID, USB_PID)) + .strings(&[StringDescriptors::default() + .manufacturer("vaulttecdev") + .product("vkey")]) + .expect("one language") + .max_packet_size_0(64) + .expect("64 bytes is a valid control packet size") + .device_class(usbd_serial::USB_CLASS_CDC) + .build(); + + let store = Store::new(Flash(Nvmc::new(p.NVMC, vault_region())), LAYOUT); + let mut dev = Device::new( + store, + panel, + Rng::new(p.RNG), + Uptime, + NoChipKey, + KDF_MEM.take(), + KDF_COST, + VAULT.init_with(store::Index::empty), + BUF.take(), + ); + + let mut proto = Proto::new(Usb { dev: usb, serial }, Uptime, info.as_str()); + proto.run(&mut dev) +} diff --git a/firmware/core/src/device.rs b/firmware/core/src/device.rs index f58445d..d111ca9 100644 --- a/firmware/core/src/device.rs +++ b/firmware/core/src/device.rs @@ -90,6 +90,9 @@ pub struct Device<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: D key: K, /// The Argon2 working memory, owned by the board for the life of the program. mem: &'m mut [Block], + /// What a new vault and a new backup are derived at: the board's measure of about a + /// second. An existing vault opens at the cost its header records. + cost: Cost, /// Where every item is, as last read from flash. The bodies stay in flash; this is /// ~10 KiB and the board owns it. Every operation reloads it before looking at it. index: &'m mut Index, @@ -132,9 +135,14 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> clock: C, key: K, mem: &'m mut [Block], + cost: Cost, index: &'m mut Index, buf: &'m mut [u8; BUF_LEN], ) -> Self { + assert!( + mem.len() >= cost.m_kib as usize, + "the Argon2 memory holds the board's own cost" + ); let now = clock.now_ms(); Device { store, @@ -143,6 +151,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> clock, key, mem, + cost, index, buf, dek: None, @@ -229,10 +238,10 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> fn install_pin(&mut self, pin: Pin<'_>) -> Result { let mut salt = [0u8; SALT_LEN]; self.rng.fill_bytes(&mut salt); - let keys = self.derive(pin, &salt, Cost::CURRENT)?; + let keys = self.derive(pin, &salt, self.cost)?; let header = Header { salt, - cost: Cost::CURRENT, + cost: self.cost, bound: self.key.bound(), verifier: vault::verifier_of(&keys.kek), }; @@ -429,7 +438,11 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> if at.is_some() && !replace { return Err(Fail::Exists); } - if !self.index.room_for(name, plain.len() + vault::OVERHEAD, at) { + let capacity = self.store.capacity(); + if !self + .index + .room_for(name, plain.len() + vault::OVERHEAD, at, capacity) + { return Err(Fail::Full); } let key = self.item_key(&dek, category.wire())?; @@ -784,7 +797,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> } let mut salt = [0u8; SALT_LEN]; self.rng.fill_bytes(&mut salt); - let cost = Cost::CURRENT; + let cost = self.cost; let key = vault::backup_key(pass, &salt, cost, self.mem).ok_or(Fail::Internal)?; self.backup = Some(Session::Export { key, diff --git a/firmware/core/src/hal.rs b/firmware/core/src/hal.rs index 7e7529c..18f2424 100644 --- a/firmware/core/src/hal.rs +++ b/firmware/core/src/hal.rs @@ -29,12 +29,12 @@ pub trait Ui { } /// A secret only this chip has, mixed into the key derivation so that a copy of the -/// flash is worthless without the chip: on ESP32 boards, HMAC-SHA256 under a key burned -/// into an eFuse block that software can use but never read. +/// flash is worthless without the chip: HMAC-SHA256 under a key the chip can use but +/// software never reads, such as one burned into its fuses. pub trait DeviceKey { /// Whether `mac` really mixes in a chip-only key. Recorded in the vault so that a /// firmware with the other answer refuses the vault instead of burning attempts. - /// A board answers false until its eFuse key is burned: the PIN alone, and said so. + /// A board answers false until it has such a key: the PIN alone, and said so. fn bound(&self) -> bool; /// HMAC-SHA256 of `msg` under the device key into `out` - or `msg` itself when /// not bound. False when the chip should have a key and cannot use it: an error, diff --git a/firmware/core/src/item.rs b/firmware/core/src/item.rs index 69d2406..8685b0a 100644 --- a/firmware/core/src/item.rs +++ b/firmware/core/src/item.rs @@ -10,7 +10,7 @@ //! class guards the next read, not this write. //! //! An item is never a struct in RAM: at 32 fields of 4 KiB a struct would be 128 KiB, -//! and the chip has 512 KiB for everything. It lives packed in a buffer, and [`Item`] +//! and a board has a few hundred KiB of RAM for everything. It lives packed in a buffer, and [`Item`] //! is a view over those bytes - parsed once, at the edge, and trusted afterwards, the //! way `Name` and `Entry` already are. diff --git a/firmware/core/src/proto.rs b/firmware/core/src/proto.rs index a656203..134f816 100644 --- a/firmware/core/src/proto.rs +++ b/firmware/core/src/proto.rs @@ -1,6 +1,6 @@ -//! Host protocol over whatever byte stream the board provides (on the C6-Zero: the -//! built-in USB-Serial/JTAG port). The byte layout is in [`crate::wire`], which the -//! host CLI compiles too. +//! Host protocol over whatever byte stream the board provides (a USB serial port on +//! every board so far). The byte layout is in [`crate::wire`], which the host CLI +//! compiles too. //! //! The port may also carry log output, so frames start with a magic word the host //! scans for. Log lines are plain ASCII and never contain it. USB already guarantees @@ -43,7 +43,8 @@ pub struct Proto { } impl Proto { - /// `version` is what INFO answers - build it with `vaultkey_core::version!`. + /// `version` is what INFO answers. Its first line is `vaultkey_core::version!`; a + /// board may add lines about its chip after it. pub fn new(port: P, clock: C, version: &'static str) -> Self { Proto { port, diff --git a/firmware/core/src/store.rs b/firmware/core/src/store.rs index 4c61cb9..81339fe 100644 --- a/firmware/core/src/store.rs +++ b/firmware/core/src/store.rs @@ -1,7 +1,7 @@ //! Persistent state in raw flash, power-cut safe, no filesystem. //! -//! The board says where (a [`Layout`]: three regions the bootloader will never touch); -//! this module says how: +//! The board says where and how big (a [`Layout`]: three regions the bootloader will +//! never touch); this module says how: //! //! attempts one word per failed PIN, cleared 1->0 without an erase //! state A \ salt, KDF cost, verifier and every item, packed, as ONE image, @@ -29,6 +29,10 @@ //! does read-erase-rewrite of the sector would turn the attempt counter's "one word, //! no erase" into "erase first" - and a power cut between that erase and the write //! would hand every attempt back. +//! +//! Every word is written once between erases. Some flash controllers allow a word two +//! writes before an erase and promise nothing after that, so the test flash refuses a +//! third. use crc::{CRC_32_ISO_HDLC, Crc}; use embedded_storage::nor_flash::NorFlash; @@ -39,10 +43,8 @@ use crate::vault::{Cost, KEY_LEN, SALT_LEN}; pub const MAX_ENTRIES: usize = 256; pub const MAX_ATTEMPTS: u8 = 8; -/// Every region below is this many bytes; flash erases in these units. +/// Every region below is a whole number of these; flash erases in these units. pub const SECTOR: u32 = 4096; -/// One image copy. Two of these and the attempt counter are the whole store. -pub const STATE_SECTORS: u32 = 53; /// A sealed item with room for the AEAD overhead: what the board's buffer holds. pub const ITEM_BUF_LEN: usize = (crate::wire::BACKUP_ITEM_MAX + 3) & !3; const _: () = assert!( @@ -50,13 +52,61 @@ const _: () = assert!( "item bodies are written in words and hold the longest backup item" ); -/// Where the three regions live. Each must start on a sector boundary; `state_a` and -/// `state_b` are `STATE_SECTORS` long, `attempts` one sector. +/// Where the three regions live and how big an image copy is: `attempts` is one +/// sector, `state_a` and `state_b` are `state_sectors` each. How much flash a board can +/// spare differs, so the board says; [`Layout::fits`] says whether what it said works. #[derive(Clone, Copy, Debug)] pub struct Layout { pub attempts: u32, pub state_a: u32, pub state_b: u32, + pub state_sectors: u32, +} + +impl Layout { + /// Whether every region starts on a sector, none overlaps another, and one copy + /// holds the largest item. A board asserts it at compile time; `Store::new` checks + /// it again, so a layout that does not fit never reaches the flash. + #[must_use] + pub const fn fits(&self) -> bool { + const fn apart(a: u32, a_end: u32, b: u32, b_end: u32) -> bool { + a_end <= b || b_end <= a + } + let Some(copy) = self.state_sectors.checked_mul(SECTOR) else { + return false; + }; + let (Some(a_end), Some(b_end)) = ( + self.state_a.checked_add(copy), + self.state_b.checked_add(copy), + ) else { + return false; + }; + let Some(attempts_end) = self.attempts.checked_add(SECTOR) else { + return false; + }; + self.attempts.is_multiple_of(SECTOR) + && self.state_a.is_multiple_of(SECTOR) + && self.state_b.is_multiple_of(SECTOR) + && Image::HEAD + Image::item_len(NAME_MAX, ITEM_BUF_LEN) + 4 <= copy as usize + && apart(self.state_a, a_end, self.state_b, b_end) + && apart(self.attempts, attempts_end, self.state_a, a_end) + && apart(self.attempts, attempts_end, self.state_b, b_end) + } + + /// Bytes in one copy. A `u32` because `fits` proved the product is one. + const fn capacity(&self) -> u32 { + self.state_sectors * SECTOR + } + + /// Sectors that hold `bytes`, never more than a copy has. + const fn sectors_of(&self, bytes: u32) -> u32 { + let n = bytes.div_ceil(SECTOR); + if n < self.state_sectors { + n + } else { + self.state_sectors + } + } } const CRC: Crc = Crc::::new(&CRC_32_ISO_HDLC); @@ -215,16 +265,22 @@ impl Index { self.slots[..self.count].iter() } - /// Whether one more item of this size would fit, counting the item it replaces - - /// `replacing` - as room that comes back. + /// Whether one more item of this size would fit a copy of `capacity` bytes, + /// counting the item it replaces - `replacing` - as room that comes back. #[must_use] - pub fn room_for(&self, name: Name<'_>, sealed_len: usize, replacing: Option) -> bool { + pub fn room_for( + &self, + name: Name<'_>, + sealed_len: usize, + replacing: Option, + capacity: usize, + ) -> bool { let freed = replacing.and_then(|i| self.get(i)).map_or(0, Slot::packed); if replacing.is_none() && self.count >= MAX_ENTRIES { return false; } let want = Image::item_len(name.as_bytes().len(), sealed_len); - self.bytes_used() + want - freed + 4 <= (SECTOR * STATE_SECTORS) as usize + self.bytes_used() + want - freed + 4 <= capacity } /// The image's length as the slots describe it, CRC excluded. @@ -294,10 +350,6 @@ const _: () = assert!( Image::HEAD.is_multiple_of(4), "images are written in whole words, one piece at a time" ); -const _: () = assert!( - Image::HEAD + Image::item_len(NAME_MAX, ITEM_BUF_LEN) + 4 <= (SECTOR * STATE_SECTORS) as usize, - "one item of the largest size must fit an image" -); const _: () = assert!( ITEM_BUF_LEN <= u16::MAX as usize, "an item's length is a u16 in the image" @@ -305,11 +357,10 @@ const _: () = assert!( /// An offset within a region, as a flash address needs it. fn off32(off: usize) -> u32 { - const _: () = assert!( - (SECTOR * STATE_SECTORS) as usize <= u32::MAX as usize, - "every offset into a region is cast to a flash address" - ); - #[expect(clippy::cast_possible_truncation, reason = "asserted above")] + #[expect( + clippy::cast_possible_truncation, + reason = "offsets stay inside a copy, and Layout::fits keeps a copy's size a u32" + )] { off as u32 } @@ -323,11 +374,6 @@ fn at(base: u32, off: usize) -> u32 { base + off32(off) } -/// Sectors that hold `bytes`, never more than a copy has. -fn sectors_of(bytes: u32) -> u32 { - bytes.div_ceil(SECTOR).min(STATE_SECTORS) -} - pub struct Store { flash: F, at: Layout, @@ -369,12 +415,10 @@ impl Store { 4_usize.is_multiple_of(F::WRITE_SIZE) && 4_usize.is_multiple_of(F::READ_SIZE), "store reads and writes in 4-byte words" ); - for region in [at.attempts, at.state_a, at.state_b] { - assert!( - region.is_multiple_of(SECTOR), - "regions start on sector boundaries" - ); - } + assert!( + at.fits(), + "regions on sector boundaries, apart, each copy big enough" + ); Store { flash, at, @@ -383,6 +427,12 @@ impl Store { } } + /// Bytes one image copy holds: what [`Index::room_for`] measures against. + #[must_use] + pub const fn capacity(&self) -> usize { + self.at.capacity() as usize + } + fn read(&mut self, addr: u32, buf: &mut [u8]) -> Result<(), Error> { self.flash.read(addr, buf).map_err(Error::Flash) } @@ -429,7 +479,7 @@ impl Store { } let seq = u32::from_le_bytes(word(&head[4..8])); let used = u32::from_le_bytes(word(&head[8..12])); - if (used as usize) < Image::HEAD + 4 || used > SECTOR * STATE_SECTORS { + if (used as usize) < Image::HEAD + 4 || used > self.at.capacity() { return Err(Error::Corrupt); } Ok(Some((seq, used))) @@ -612,9 +662,9 @@ impl Store { // even if the new image is shorter, so no tail of the old one stays readable. // Unreadable contents mean erasing the copy whole - it is not ours to trust. let stale = match self.image_head(target) { - Ok(Some((_, used))) => sectors_of(used), + Ok(Some((_, used))) => self.at.sectors_of(used), Ok(None) => 0, - Err(_) => STATE_SECTORS, + Err(_) => self.at.state_sectors, }; let source = current.map(|(_, addr)| addr); self.current = None; // nothing is newest until this write is whole @@ -662,10 +712,10 @@ impl Store { fn room(&mut self, bytes: usize) -> Result<(), Error> { let s = self.saving.as_ref().ok_or(Error::Corrupt)?; let (mut erased, target, end) = (s.erased, s.target, s.at + bytes + 4); - if end > (SECTOR * STATE_SECTORS) as usize { + if end > self.capacity() { return Err(Error::Full); } - let want = sectors_of(off32(end)); + let want = self.at.sectors_of(off32(end)); while erased < want { self.erase(target + erased * SECTOR, 1)?; erased += 1; @@ -771,7 +821,7 @@ impl Store { chunk.zeroize(); self.write(at(target, body_end), &digest.finalize().to_le_bytes())?; - let full = sectors_of(used); + let full = self.at.sectors_of(used); if stale > full { self.erase(target + full * SECTOR, stale - full)?; } @@ -816,8 +866,8 @@ impl Store { self.current = None; let mut first = Ok(()); for (from, sectors) in [ - (self.at.state_a, STATE_SECTORS), - (self.at.state_b, STATE_SECTORS), + (self.at.state_a, self.at.state_sectors), + (self.at.state_b, self.at.state_sectors), (self.at.attempts, 1), ] { if let Err(e) = self.erase(from, sectors) { diff --git a/firmware/core/src/vault.rs b/firmware/core/src/vault.rs index 0b5252c..acfd461 100644 --- a/firmware/core/src/vault.rs +++ b/firmware/core/src/vault.rs @@ -28,11 +28,13 @@ pub const SALT_LEN: usize = 16; pub const NONCE_LEN: usize = 12; pub const TAG_LEN: usize = 16; pub const OVERHEAD: usize = NONCE_LEN + TAG_LEN; -/// Eight digits, no fewer and no more. Whoever holds the board erases the attempt -/// counter through ROM download mode and guesses through the real firmware at about -/// 1.3 s a try: six digits fall in a fortnight, seven in five months, eight in four -/// years. No key derivation rescues a shorter PIN - a second per unlock is already as -/// slow as the device may be, so length is the only lever left. +/// Eight digits, no fewer and no more. Whoever holds a board with a chip key can still +/// erase the attempt counter - every board so far can be rewritten by whoever holds it - +/// and guess through the real firmware. At the 1.3 s a try measured on the first board, +/// six digits fall in a fortnight, seven in five months, eight in four years. No key +/// derivation rescues a shorter PIN - a second per unlock is already as slow as the +/// device may be, so length is the only lever left. Without a chip key a copy of the +/// flash is guessed offline instead, and no length rescues that (docs/threat-model.md). pub const PIN_LEN: usize = 8; /// A backup file has no attempt counter: whoever holds it guesses forever, at the speed /// of their own hardware, and 128 KiB of Argon2id is not much of a brake. Twelve is a @@ -50,15 +52,18 @@ pub const ENV_KEY_AAD: &[u8] = b"vaultkey/env-key/v1"; /// moved, repeated or dropped from the middle fails to open on the way back in. pub const BACKUP_AAD: &[u8] = b"vaultkey/backup/v1"; -/// Argon2id cost: memory in KiB and passes over it. Stored per vault, so it can be -/// raised later without breaking existing ones. +/// Argon2id cost: memory in KiB and passes over it. Stored per vault and per backup, so +/// a board can change its own without breaking either. /// -/// The memory is what the board can spare beside an 80 KiB vault and a 300 KiB stack, -/// not what a passphrase would like: 128 KiB fits in the cache of any desktop core, so -/// it costs an attacker time, not the memory bandwidth Argon2 is meant to cost them. -/// Against the PIN that changes nothing - eight digits behind the attempt counter and -/// the eFuse key is what protects it. Against a stolen `.vkb` it is the whole defence, -/// which is why the passphrase must carry the entropy itself. +/// The board decides what a new vault and a new backup get - as many passes as fit in +/// about a second on its core - and hands it to `Device::new`. +/// +/// The memory is what a small board can spare, not what a passphrase would like: 128 KiB +/// fits in the cache of any desktop core, so it costs an attacker time, not the memory +/// bandwidth Argon2 is meant to cost them. Against the PIN that changes nothing where a +/// chip key is mixed in; without one, a copy of the flash is guessed at the speed of +/// this cost alone. Against a stolen `.vkb` it is the whole defence, which is why the +/// passphrase must carry the entropy itself. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct Cost { pub m_kib: u32, @@ -66,9 +71,6 @@ pub struct Cost { } impl Cost { - /// What a new vault gets: all the memory the board offers, and as many passes as - /// fit in about a second on the ESP32-C6 - 48 passes measured at 1.2 s there. - pub const CURRENT: Cost = Cost { m_kib: 128, t: 48 }; /// The most this firmware will run whatever flash says: a tampered header must not /// be able to park the key for hours. pub const MAX: Cost = Cost { m_kib: 128, t: 256 }; diff --git a/firmware/core/src/wire.rs b/firmware/core/src/wire.rs index 15194a8..a13facf 100644 --- a/firmware/core/src/wire.rs +++ b/firmware/core/src/wire.rs @@ -72,6 +72,8 @@ const _: () = assert!( #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[repr(u8)] pub enum Cmd { + /// Text, no PIN: the version line, which ends with the board's folder name, then + /// whatever lines the board adds about its own chip. Info = 0x01, /// A whole item in; the PIN is enough - nothing comes out. ItemPut = 0x10, diff --git a/firmware/core/tests/key.rs b/firmware/core/tests/key.rs index 499f7aa..6b4d7b0 100644 --- a/firmware/core/tests/key.rs +++ b/firmware/core/tests/key.rs @@ -29,17 +29,29 @@ use vaultkey_core::wire::{ // --- the hardware, faked ------------------------------------------------------------- +/// Few passes: these tests are about what the key does, not how long it takes, and a +/// board's own cost is its measure, not theirs. +const COST: Cost = Cost::from_wire(128, 2).expect("a cost Argon2 runs"); + const LAYOUT: Layout = Layout { attempts: 0x0000, state_a: 0x1000, state_b: 0x36000, + state_sectors: 53, }; +const _: () = assert!(LAYOUT.fits(), "the test layout is one a board could use"); const FLASH_BYTES: usize = 0x6B000; - -/// A flash chip with NOR semantics: erase sets 0xFF, a write can only clear bits. -/// Shared by reference so a "power cycle" is just a second `Device` on the same chip. +/// How many times a word may be written between erases: the strictest flash +/// controller a board has. A third write is a fault here, so it cannot pass on the +/// host and corrupt a word on the chip. +const WRITES_PER_WORD: u8 = 2; + +/// A flash chip with NOR semantics: erase sets 0xFF, a write can only clear bits, and a +/// word takes `WRITES_PER_WORD` writes between erases. The bytes, then the writes each +/// word has taken since its last erase. Shared by reference so a "power cycle" is just a +/// second `Device` on the same chip. #[derive(Clone)] -struct MemFlash(Rc>>); +struct MemFlash(Rc>>, Rc>>); #[derive(Debug)] struct Fault; @@ -83,6 +95,7 @@ impl NorFlash for MemFlash { fn erase(&mut self, from: u32, to: u32) -> Result<(), Fault> { self.0.borrow_mut()[at(from)..at(to)].fill(0xFF); + self.1.borrow_mut()[at(from) / 4..at(to) / 4].fill(0); Ok(()) } @@ -90,6 +103,14 @@ impl NorFlash for MemFlash { if !offset.is_multiple_of(4) || !bytes.len().is_multiple_of(4) { return Err(Fault); } + let words = at(offset) / 4..(at(offset) + bytes.len()) / 4; + let mut writes = self.1.borrow_mut(); + if writes[words.clone()].iter().any(|w| *w >= WRITES_PER_WORD) { + return Err(Fault); + } + for w in &mut writes[words] { + *w += 1; + } let mut chip = self.0.borrow_mut(); for (cell, b) in chip[at(offset)..].iter_mut().zip(bytes) { *cell &= *b; @@ -100,7 +121,10 @@ impl NorFlash for MemFlash { impl MemFlash { fn blank() -> Self { - MemFlash(Rc::new(RefCell::new(vec![0xFF; FLASH_BYTES]))) + MemFlash( + Rc::new(RefCell::new(vec![0xFF; FLASH_BYTES])), + Rc::new(RefCell::new(vec![0; FLASH_BYTES / 4])), + ) } fn word(&self, offset: u32) -> u32 { @@ -179,6 +203,7 @@ impl MemFlash { clock, key, mem, + COST, index, buf, ) @@ -561,10 +586,9 @@ fn the_chip_key_changes_every_derived_key() { let mem = &mut vec![Block::new(); KDF_BLOCKS]; let salt = [1u8; vault::SALT_LEN]; - let a = vault::derive(pin("12345678"), &salt, Cost::CURRENT, &mut plain, mem) + let a = vault::derive(pin("12345678"), &salt, COST, &mut plain, mem) .expect("derives without a chip key"); - let b = vault::derive(pin("12345678"), &salt, Cost::CURRENT, &mut chip, mem) - .expect("derives with one"); + let b = vault::derive(pin("12345678"), &salt, COST, &mut chip, mem).expect("derives with one"); assert_ne!(a.dek, b.dek, "the same PIN and salt, a different data key"); assert_ne!(a.kek, b.kek, "and a different verifier key"); assert!( @@ -573,14 +597,7 @@ fn the_chip_key_changes_every_derived_key() { ); let mut short = vec![Block::new(); 8]; assert!( - vault::derive( - pin("12345678"), - &salt, - Cost::CURRENT, - &mut plain, - &mut short - ) - .is_none(), + vault::derive(pin("12345678"), &salt, COST, &mut plain, &mut short).is_none(), "too little memory is an error, not a cheaper derivation" ); } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index a68af93..0ba40c1 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -5,7 +5,10 @@ # rustc emits different code, so a floating `stable` would make the image reproducible # for nobody. Bumping this line is a deliberate change - it rewrites the image, and the # signed images then have to be produced again (tools/sign-vaultkey.sh, PIN and a tap). +# +# `llvm-tools` brings the llvm-objcopy that turns an ELF into a raw image for boards +# whose image is plain flash contents, pinned with the compiler for the same reason. [toolchain] channel = "1.97.1" -targets = ["riscv32imac-unknown-none-elf"] -components = ["rustfmt", "clippy"] +targets = ["riscv32imac-unknown-none-elf", "thumbv7em-none-eabihf"] +components = ["rustfmt", "clippy", "llvm-tools"] diff --git a/tools/build-vaultkey.sh b/tools/build-vaultkey.sh index 0fef32e..16bfaee 100755 --- a/tools/build-vaultkey.sh +++ b/tools/build-vaultkey.sh @@ -9,10 +9,10 @@ # # Flashing is `vkey setup` (on a Secure Boot chip after tools/sign-vaultkey.sh). # -# A board is a folder under firmware/boards with a board.toml (chip, target, images). -# Nothing here names a chip. Needs rustup with the board's target, and espflash -# (`cargo install espflash`). The port is found by espflash itself; override with -# PORT=/dev/ttyACM1. +# A board is a folder under firmware/boards with a board.toml (chip, target, +# image_tool, images). Nothing here names a chip. Needs rustup with the board's target, +# and espflash (`cargo install espflash`) for boards whose image_tool is espflash. The +# port is found by espflash itself; override with PORT=/dev/ttyACM1. set -euo pipefail @@ -27,7 +27,37 @@ if [[ -d "$ROOT/.git" ]] && [[ "$(git -C "$ROOT" config --get core.hooksPath || echo "git hooks enabled: .githooks (pre-commit, commit-msg, pre-push)" fi -command -v espflash >/dev/null || { echo "espflash is missing: cargo install espflash" >&2; exit 1; } +# The objcopy and objdump that ship with the pinned toolchain (rust-toolchain.toml lists +# llvm-tools), so a raw image is the same bytes on every machine. +LLVM="$(rustc --print sysroot)/lib/rustlib/$(rustc -vV | sed -n 's/^host: //p')/bin" +OBJCOPY="$LLVM/llvm-objcopy" + +# Where a radio driver ships inside the chip's HAL crate, the lock file proves nothing, +# so board.toml names the radio's 4 KiB peripheral slot and the image is searched for +# it: no data word in the slot, and no movw/movt pair that builds an address in it. That +# catches a driver addressing the radio's registers directly - the same search finds +# every slot this firmware does use (USB, flash controller, RNG). It does not rule out +# an address computed from a neighbouring peripheral's base plus an offset. +radio_refs() { # elf image base + local slot words pairs + slot=$(printf '%x' $(($3 >> 12))) + words=$(od -An -v -tx4 -w4 "$2" | grep -c "^ *0*${slot}[0-9a-f]\{3\}$" || true) + pairs=$("$LLVM/llvm-objdump" -d --no-show-raw-insn "$1" | grep -E $'\tmov[wt]\t' | { + declare -A low + n=0 + while read -r _ op reg val; do + reg=${reg%,} + val=${val#\#} + if [[ $op == movw ]]; then + low[$reg]=$((val)) + elif [[ -n ${low[$reg]:-} ]] && ((((val << 16 | low[$reg]) >> 12) == ($3 >> 12))); then + n=$((n + 1)) + fi + done + echo "$n" + } || true) + echo $((words + pairs)) +} # A panic location carries the path of the file it came from, and for a dependency that is # an absolute path into the builder's ~/.cargo. Left alone it would put the builder's home @@ -69,6 +99,7 @@ for dir in "${dirs[@]}"; do [[ -f "$dir/board.toml" ]] || { echo "$name: no board.toml" >&2; exit 1; } chip="$(toml_value "$dir/board.toml" chip)" target="$(toml_value "$dir/board.toml" target)" + image_tool="$(toml_value "$dir/board.toml" image_tool)" elf="$ROOT/firmware/target/$target/release/vaultkey-$name" echo "== $name ($chip, $target)" @@ -77,10 +108,28 @@ for dir in "${dirs[@]}"; do # from the old file while a different tree gets compiled. (cd "$dir" && cargo build --release --locked) mkdir -p "$dir/images" - espflash save-image --chip "$chip" "$elf" "$dir/images/vaultkey.bin" >/dev/null + # espflash wraps the ELF in the ESP-IDF image format its bootloader checks; objcopy + # gives the raw flash contents, for chips that boot straight from them. + case "$image_tool" in + espflash) + command -v espflash >/dev/null || { echo "espflash is missing: cargo install espflash" >&2; exit 1; } + espflash save-image --chip "$chip" "$elf" "$dir/images/vaultkey.bin" >/dev/null + ;; + objcopy) "$OBJCOPY" -O binary "$elf" "$dir/images/vaultkey.bin" ;; + *) echo "$name: board.toml image_tool must be espflash or objcopy, not '$image_tool'" >&2; exit 1 ;; + esac echo " image: $(stat -c %s "$dir/images/vaultkey.bin") bytes -> firmware/boards/$name/images/vaultkey.bin" + radio_base="$(grep -E '^radio_base\s*=' "$dir/board.toml" | sed 's/^[^=]*=\s*//; s/\s*#.*//' || true)" + if [[ -n "$radio_base" ]]; then + refs="$(radio_refs "$elf" "$dir/images/vaultkey.bin" "$radio_base")" + if ((refs > 0)); then + echo "*** $name: $refs reference(s) to the radio at $radio_base in the image - this build could transmit ***" >&2 + exit 1 + fi + echo " no-radio: nothing in the image reaches $radio_base" + fi done -echo "no-radio check: passed" +echo "no-radio check: passed (no radio crate in the lock file; radio_base boards searched)" # The images are compiled into the CLI, so it is rebuilt right after - once every # image board.toml names exists; the signed ones come from tools/sign-vaultkey.sh, diff --git a/tools/checks.sh b/tools/checks.sh index c0e9e7f..87f7204 100755 --- a/tools/checks.sh +++ b/tools/checks.sh @@ -67,11 +67,20 @@ check_scripts() { } check_lint_tables() { - step "the [lints] tables of firmware/ and cli/ are identical" - local a b + step "the [lints] tables of firmware/, cli/ and every board with its own are identical" + local a b d a=$(sed -n '/^\[workspace\.lints\.rust\]/,$p' "$ROOT/firmware/Cargo.toml" | sed 's/^\[workspace\.lints\./[lints./') b=$(sed -n '/^\[lints\.rust\]/,$p' "$ROOT/cli/Cargo.toml") diff <(echo "$a") <(echo "$b") || fail "the [lints] tables differ - one strictness for both crates" + # A board whose flash driver needs memory-mapped flash as a slice carries its own + # copy, identical but for `unsafe_code = "deny"`, so that one place can say why + # with #[expect]. Nothing else may differ. + for d in $(boards); do + grep -q '^\[lints\.rust\]' "$d/Cargo.toml" || continue + b=$(sed -n '/^\[lints\.rust\]/,$p' "$d/Cargo.toml") + diff <(echo "${a//unsafe_code = \"forbid\"/unsafe_code = \"deny\"}") <(echo "$b") \ + || fail "$(basename "$d"): its [lints] table differs from the workspace's in more than unsafe_code" + done } check_no_radio() { diff --git a/tools/sign-vaultkey.sh b/tools/sign-vaultkey.sh index d1d258f..a8efffd 100755 --- a/tools/sign-vaultkey.sh +++ b/tools/sign-vaultkey.sh @@ -2,7 +2,7 @@ # # Sign a board's firmware images for Secure Boot v2 with the key that lives on the vkey. # -# ./tools/sign-vaultkey.sh every board folder +# ./tools/sign-vaultkey.sh every board whose board.toml has Secure Boot images # BOARD=esp32c6-zero ./tools/sign-vaultkey.sh # # Reads images/vaultkey.bin and images/bootloader-sb.bin, writes vaultkey.signed.bin @@ -31,7 +31,13 @@ done if [[ -n "${BOARD:-}" ]]; then dirs=("$BOARDS/$BOARD") else - dirs=("$BOARDS"/*/) + # Only boards that boot through ESP Secure Boot have anything to sign here: their + # board.toml lists an image for a chip with it burned. + dirs=() + for d in "$BOARDS"/*/; do + grep -q '^secure_boot = true' "$d/board.toml" 2>/dev/null && dirs+=("$d") + done + ((${#dirs[@]})) || { echo "no board with Secure Boot images" >&2; exit 1; } fi tmp="$(mktemp -d /dev/shm/vkey-sign.XXXXXX)" From ad4d08767d532ed853fbfb6094f6661140d28db0 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 01:06:08 +0300 Subject: [PATCH 02/33] Build the nRF52840 UF2 bootloader baseline in Docker - Upstream Adafruit_nRF52_Bootloader 0.9.2 at a pinned commit, built with arm-gnu-toolchain 12.3.rel1 (sha256-checked) on Debian pinned by digest. - Board definition read back from the factory 0.7.1 binary: 2886:F00F, UF2BOOT, the button on P0.18, the RGB LED. - Patch 0001 drops CONFIG_GPIO_AS_PINRESET and CONFIG_NFCT_PINS_AS_GPIOS, so SystemInit writes no UICR. - check.py fails the build on a UICR address in the code or a CF2 block that differs from the factory one. Two builds are byte-identical. - tools/build-bootloader.sh builds by chip; nRF outputs stay in a temp dir until the fork is complete. - Roadmap: phase 3 findings, constraints, milestones; check run 4 notes. --- CLAUDE.md | 7 ++ docs2/makerdiary.md | 8 ++ docs2/roadmap.md | 97 +++++++++++++++++++ .../nrf52840-mdk-dongle/bootloader/Dockerfile | 32 ++++++ .../bootloader/board/board.h | 71 ++++++++++++++ .../bootloader/board/board.mk | 1 + .../nrf52840-mdk-dongle/bootloader/build.sh | 55 +++++++++++ .../nrf52840-mdk-dongle/bootloader/check.py | 56 +++++++++++ .../patches/0001-no-uicr-writes.patch | 20 ++++ tools/build-bootloader.sh | 97 +++++++++++++------ 10 files changed, 413 insertions(+), 31 deletions(-) create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.mk create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/check.py create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0001-no-uicr-writes.patch diff --git a/CLAUDE.md b/CLAUDE.md index 16f028d..535a024 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -312,6 +312,13 @@ signed image is the unsigned one plus a signature under `firmware/secure-boot/pu The partition table sits at 0xC000, because the Secure Boot bootloader does not fit below 0x8000. +The nRF52840's UF2 bootloader fork is built by the same script from its `bootloader/` +folder: upstream Adafruit_nRF52_Bootloader at a pinned commit, the board definition read +back from the factory binary, a patch series, a pinned Arm toolchain, all in Docker. +`bootloader/check.py` fails the build on any UICR address in the code. Until the fork is +complete the outputs stay in a temporary directory, and installing it is never part of a +build (`docs2/roadmap.md`, phase 3). + Compilation is the **only** exception to the check rule. Linters, formatters, tests and static analysers are not run without a direct request: git hooks in `.githooks/` (`tools/checks.sh`) run them on pre-commit and pre-push. When the maintainer sends the diff --git a/docs2/makerdiary.md b/docs2/makerdiary.md index 2d1ffa6..a1e69a3 100644 --- a/docs2/makerdiary.md +++ b/docs2/makerdiary.md @@ -387,6 +387,14 @@ button is held at reset. The second run passed the same step, and an untapped am while the button was down, and USB going unserviced for up to 30 s while a tap is awaited. - **ModemManager** is active on the maintainer's machine and may probe a new CDC-ACM port. +With the board cost and the `chip:` line (2026-10-14), run 4 passed 48 checks with +Argon2 at 1126 ms. The one failure, "backup refused for one tap", was the operator: they +double-tapped where the step wants one tap, and confirmed it. Run 3 stopped earlier +because the tap reached the board too late (the prompts were relayed through chat). +Both runs tripped on the same trap. The "no code from" steps for a password, an env and +`auth` light amber with no `>>>` prompt, and they expect a tap: untapped, the key answers +`Refused` instead of `BadArg`. + ## First steps when it arrives > Superseded 2026-10-13 by `docs2/roadmap.md`. The board ran over UF2 without a probe, diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 266fdbd..d863939 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -125,6 +125,103 @@ Nordic's MBR offers a power-safe copy, but whether this updater uses it is not c **`vkey setup` for the nRF** writes the signed UF2 to the bootloader drive. +**What reading the source found (2026-10-14; desk research, nothing flashed).** Base: +upstream `Adafruit_nRF52_Bootloader`. The factory 0.7.1 source is unpublished, but its +binary is in `makerdiary/nrf52840-mdk-usb-dongle` and its submodules match upstream 0.6.4-0.9.2. +The board definition is Makerdiary's, not upstream's: `UF2BOOT`, `2886:F00F`, the button on +P0.18 as a pull-up GPIO, LEDs 23/22/24. Before anything is built: + +- **PSELRESET trap.** Upstream's Makefile defines `CONFIG_GPIO_AS_PINRESET` and + `CONFIG_NFCT_PINS_AS_GPIOS`. nrfx 2.0.0's `SystemInit` then writes UICR `PSELRESET` = P0.18 + on first boot, which turns the only button into a reset pin for good. The factory build + has neither define (its `SystemInit` was disassembled). The fork drops both, and its + `SystemInit` is disassembled before install. +- **Board ID.** The factory bootloader takes a self-update UF2 only with board ID + `0x2886F00F`, or with none. Upstream's dongle builds carry `0x239A0029` and are refused. + Upstream's "connect-kit" update UF2s carry `0x2886F00F` and would be accepted, with wrong + pins and the PSELRESET write, so they must never be used. +- **Every write path has to go or be signed.** + - The UF2 self-update (family `0xD663823C`) is unauthenticated: anyone holding the + button can put the stock bootloader back. + - Serial DFU over CDC writes the app, the bootloader and the SoftDevice. Its pre-erase + reaches the vault, and its only check is public constants plus a CRC16. + - BLE OTA. + + Removing serial DFU and BLE OTA is also what frees room for the signature check. +- **Read-back is more than `CURRENT.UF2`.** The generator behind it serves any address + under 1 MiB, so a raw read past the file's end returns the bootloader and the settings + too. The generator branch goes, not just the directory entry. +- **A partial UF2 boots.** The settings change only when the transfer completes, so a torn + upload followed by a replug runs half-new code as valid. The fork verifies the signature + on every boot in `bootloader_app_is_valid()` and fails closed. +- **Size.** The factory image is 33 044 B, leaving 5 868 B before 0xFD800. Signature check + code sizes are not measured yet. +- **Install.** A self-update UF2 is the bootloader hex itself. The running bootloader stages + it at 0xE0000 and has the MBR copy it with `SD_MBR_COMMAND_COPY_BL`, which Nordic calls + power-fail safe; that claim is not tested here. The update is padded to the whole region. +- **Before installing,** the fork's USB and UF2 logic runs as an ordinary application at + 0x1000 under the factory bootloader, which stays in place and makes this step + reversible. +- **Self-update in the fork: signed** (maintainer's choice, 2026-10-14). Removing it would + leave a bug in the bootloader unfixable forever. The update is signed with the same key as + the app images. A signed image can still be downgraded to an older signed one: a known + limitation, deferred. + +Constraints that come with it: + +- **Staging must avoid the vault and Trussed.** Upstream stages a self-update at + 0xE0000..0xEA000, inside the 0xD8000..0xEC000 kept for Trussed in phase 6, so a later + self-update would erase the passkeys. The fork stages inside the application region, and + the app is flashed again after a bootloader update. +- **The signing key must exist in two places.** Once everything moves here, a broken app + leaves the board in the bootloader waiting for a signed image. If the only copy of the key + is on this board, nothing can sign it. Before the key is generated, decide its second home: + the wiped C6 as the signing device, or a `.vkb` that restores onto it. +- ~~**The page at 0xFD800**~~ is the CF2 config page (`.bootloaderConfig`, 88 B: board ID, + family, flash and RAM size), part of the bootloader image inside the 40 KiB that `COPY_BL` + copies. `check.py` pins it to the factory's words. The code region is 0xF4000..0xFD800. +- **A verify bug is the brick.** If the check rejects valid images, no app boots and no fixed + bootloader is accepted. So the test build at 0x1000 runs the exact same verify code against + images from the real signing pipeline, altered ones and a self-update image, with + `COPY_BL` compiled out and its write window on a scratch area. + +Milestones, one commit each: + +1. A Docker build that reproduces a factory-equivalent binary: same `SystemInit`, no UICR + writes, the same board ID. **Done 2026-10-14**: + - `BOARD=nrf52840-mdk-dongle ./tools/build-bootloader.sh` builds upstream 0.9.2 with + arm-gnu-toolchain 12.3.rel1, the board definition read back from the factory binary + and `patches/0001-no-uicr-writes.patch`. + - The code is 31 312 B, the factory's size, with the same INFO string format and + submodule versions. + - `SystemInit` stores only to peripherals, and FICR is only read. + - `check.py` finds no UICR address in the code and the CF2 block equal to the + factory's. + - Two builds are byte-identical: `bootloader.bin` sha256 `61aec000…9d73`. + - The bytes differ from the factory's (another compiler), so "equivalent" means the + same configuration, not the same binary. +2. The removals (serial DFU, BLE OTA, the read-back generator, single-tap and double-reset + entry) and the write window. +3. The signed trailer, with length and version inside the signed bytes, checked on every + boot; the host signing tool. The signature scheme is chosen by measuring the code size + and boot time of each verify-only candidate. +4. The on-device test as an application. + +Install needs its own go and a checklist: + +- no UICR address (0x10001xxx) and no NVMC `CONFIG` write in the binary; +- `SystemInit` disassembled; +- the board ID confirmed; +- the update padded to the whole region; +- the UF2 actually installed is checked block by block. Every target address falls in the + MBR, 0xF4000..0xFE000, the settings page at 0xFF000 or the two UICR words, and its + 0xF4000.. payload equals the checked `bootloader.bin`; +- the MBR: the update carries Nordic's MBR 2.4.1 and a whole settings page. Read in the + update handler what happens to those blocks, and compare the chip's own MBR (the app can + read 0x0..0xB00) with 2.4.1; +- a signed app already on the board; +- the key reachable from two places. + **The risk, stated plainly.** A bug in the new bootloader leaves a board no USB tool can reach. Without a probe that is a new dongle. That is acceptable only because the board holds nothing yet. diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile b/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile new file mode 100644 index 0000000..a0944bd --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile @@ -0,0 +1,32 @@ +# The UF2 bootloader for this board: upstream Adafruit_nRF52_Bootloader at a pinned +# commit, with this folder's board definition and patches laid over it (build.sh), built +# with a pinned Arm toolchain. tools/build-bootloader.sh runs it. Nothing here touches a +# board: what comes out is installed, if ever, by hand and after its own checklist +# (docs2/roadmap.md, phase 3). +FROM debian:bookworm-slim@sha256:7c7b2c966bc9ee8cedfeef67e0e279108992c77681fa595db4a9d65c06ccc587 + +ARG TOOLCHAIN=arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi +ARG TOOLCHAIN_SHA256=12a2815644318ebcceaf84beabb665d0924b6e79e21048452c5331a56332b309 +# Adafruit_nRF52_Bootloader 0.9.2. Its nrfx (7a4c9d9), tinyusb (9775e76) and uf2 +# (adbb8c7) are the commits the factory 0.7.1 bootloader reports in INFO_UF2.TXT. +ARG UPSTREAM=https://github.com/adafruit/Adafruit_nRF52_Bootloader.git +ARG COMMIT=eefbe6bda98b80cb296e2f1bb1c982d58fe4c12d + +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates curl git make patch python3 python3-intelhex xz-utils \ + && rm -rf /var/lib/apt/lists/* + +RUN curl -fsSL -o /tmp/tc.tar.xz "https://developer.arm.com/-/media/Files/downloads/gnu/12.3.rel1/binrel/$TOOLCHAIN.tar.xz" \ + && echo "$TOOLCHAIN_SHA256 /tmp/tc.tar.xz" | sha256sum -c - \ + && mkdir /opt/arm \ + && tar -xJf /tmp/tc.tar.xz -C /opt/arm --strip-components=1 \ + && rm /tmp/tc.tar.xz +ENV PATH=/opt/arm/bin:$PATH + +RUN git clone -q "$UPSTREAM" /src \ + && git -C /src checkout -q "$COMMIT" \ + && git -C /src submodule update -q --init lib/nrfx lib/tinyusb lib/uf2 \ + && chmod -R a+rwX /src \ + && git config --system --add safe.directory '*' +# The build runs as the host user, so its outputs are the host user's; the tree is +# writable to it, and git does not refuse a repository it does not own. diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h new file mode 100644 index 0000000..a665c30 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h @@ -0,0 +1,71 @@ +/* + * The Makerdiary nRF52840 MDK USB Dongle as its factory UF2 bootloader (0.7.1) sees it, + * read back from that binary: the same pins, USB identity and drive. Derived from + * Adafruit_nRF52_Bootloader's src/boards/mdk_nrf52840_dongle/board.h, whose own values + * (VID 239A, P0.18 "unusable: RESET") do not describe this unit. + * + * The MIT License (MIT) + * Copyright (c) 2018 gpshead (krypto.org) for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this + * software and associated documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following + * conditions: The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _NRF52840_MDK_USB_DONGLE_H_ +#define _NRF52840_MDK_USB_DONGLE_H_ + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +/*------------------------------------------------------------------*/ +/* LED: one RGB LED, active low. The factory build drives it as an RGB status LED (green + * while the drive is mounted) and also inits red as the primary LED. + *------------------------------------------------------------------*/ +#define LEDS_NUMBER 1 +#define LED_PRIMARY_PIN _PINNUM(0, 23) +#define LED_STATE_ON 0 + +#define LED_RGB_RED_PIN _PINNUM(0, 23) +#define LED_RGB_GREEN_PIN _PINNUM(0, 22) +#define LED_RGB_BLUE_PIN _PINNUM(0, 24) +#define BOARD_RGB_BRIGHTNESS 0x404040 + +/*------------------------------------------------------------------*/ +/* BUTTON: the USER button on P0.18, a plain input (UICR PSELRESET is not set on this + * unit, and nothing here may set it). P0.19 is not connected; upstream needs a second + * button, and with the pull-up it never reads as pressed. + *------------------------------------------------------------------*/ +#define BUTTONS_NUMBER 2 +#define BUTTON_1 _PINNUM(0, 18) +#define BUTTON_2 _PINNUM(0, 19) +#define BUTTON_PULL NRF_GPIO_PIN_PULLUP + +/*------------------------------------------------------------------*/ +/* USB: the strings double as the BLE ones upstream. + *------------------------------------------------------------------*/ +#define BLEDIS_MANUFACTURER "Makerdiary" +#define BLEDIS_MODEL "nRF52840-MDK-USB-DONGLE" + +/* Also the CF2 board ID (VID << 16 | PID) the factory bootloader checks before it + * accepts a self-update: 0x2886F00F. */ +#define USB_DESC_VID 0x2886 +#define USB_DESC_UF2_PID 0xF00F +#define USB_DESC_CDC_ONLY_PID 0xF00F + +#define UF2_PRODUCT_NAME "Makerdiary nRF52840 MDK USB Dongle" +#define UF2_VOLUME_LABEL "UF2BOOT " +#define UF2_BOARD_ID "nRF52840-MDK-USB-DONGLE" +#define UF2_INDEX_URL "https://wiki.makerdiary.com/nrf52840-mdk-usb-dongle" + +#endif /* _NRF52840_MDK_USB_DONGLE_H_ */ diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.mk b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.mk new file mode 100644 index 0000000..9d29ac6 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.mk @@ -0,0 +1 @@ +MCU_SUB_VARIANT = nrf52840 diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh new file mode 100644 index 0000000..7af0da3 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# Runs inside the image built from Dockerfile, started by tools/build-bootloader.sh: +# /work/in is this folder (read-only), /work/out receives +# +# bootloader.hex the bootloader, with Nordic's MBR (what a probe would write) +# update-bootloader.uf2 the same as a self-update UF2 (family 0xD663823C) +# bootloader.bin the bootloader region alone, from 0xF4000, for check.py +# systeminit.txt SystemInit disassembled, read before any install +# +# The tree is the image's pristine upstream checkout, so every run starts from the same +# sources. The version and the build date are fixed, so the same inputs give the same +# bytes. + +set -eu + +BOARD=nrf52840_mdk_usb_dongle +VERSION=0.9.2-vkey +# What `git submodule status` reports for the pinned commits today, as the factory +# 0.7.1 bootloader reports it too. Fixed here because the uf2 part names an upstream +# branch, and a fresh clone after that branch moves would change the INFO text. +SUBMODULES="lib/nrfx (v2.0.0) lib/tinyusb (0.12.0-145-g9775e7691) lib/uf2 (remotes/origin/configupdate-9-gadbb8c7)" + +cd /src +mkdir -p "src/boards/$BOARD" +cp /work/in/board/board.h /work/in/board/board.mk "src/boards/$BOARD/" +# The CF2 block (board ID = VID:PID, family, flash and RAM size) is generic; upstream's +# copy for this dongle is the one the factory build carries. +cp src/boards/mdk_nrf52840_dongle/pinconfig.c "src/boards/$BOARD/" +# GNU patch, not git apply: editors and hooks strip the lone space of a blank context +# line, which git apply rejects. --fuzz=0 still demands every context line match. Some +# upstream files have CRLF endings and the patches are LF, so a file is made LF before +# it is patched. +for p in /work/in/patches/*.patch; do + sed -n 's|^+++ b/||p' "$p" | while read -r f; do + sed -i 's/\r$//' "$f" + done + patch -s -p1 --fuzz=0 --no-backup-if-mismatch -i "$p" +done + +SOURCE_DATE_EPOCH="$(git log -1 --format=%ct)" +export SOURCE_DATE_EPOCH +out="_build/build-$BOARD/${BOARD}_bootloader-$VERSION" +make -s BOARD="$BOARD" GIT_VERSION="$VERSION" GIT_SUBMODULE_VERSIONS="$SUBMODULES" \ + "${out}_nosd.hex" "_build/build-$BOARD/update-${BOARD}_bootloader-${VERSION}_nosd.uf2" + +cp "${out}_nosd.hex" /work/out/bootloader.hex +cp "_build/build-$BOARD/update-${BOARD}_bootloader-${VERSION}_nosd.uf2" /work/out/update-bootloader.uf2 +# The two UICR words (bootloader and MBR-params addresses, already on the chip) are +# programmer data, not code; left in, the binary would span up to 0x10001018. +arm-none-eabi-objcopy -O binary -R .uicrBootStartAddress -R .uicrMbrParamsPageAddress \ + "$out.out" /work/out/bootloader.bin +arm-none-eabi-objdump -d --disassemble=SystemInit "$out.out" > /work/out/systeminit.txt +arm-none-eabi-size "$out.out" +python3 /work/in/check.py /work/out/bootloader.bin diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py b/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py new file mode 100644 index 0000000..13d1437 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py @@ -0,0 +1,56 @@ +"""Fail closed on a bootloader that would be dangerous to install on a board with no +SWD probe. Takes bootloader.bin, the region from 0xF4000 (code, then the CF2 page at +0xFD800). Run by build.sh after every build. + +- No UICR address anywhere in the code: the bootloader must never write UICR. A write + there (PSELRESET, NFCPINS, APPROTECT) is permanent without a probe. +- The CF2 block is the factory one, word for word. Its board ID is what the factory + bootloader checks before it accepts this one as a self-update, and what a later + self-update of this one is checked against. +""" + +import struct +import sys + +BASE = 0xF4000 +CF2_AT = 0xFD800 +UICR = range(0x10001000, 0x10002000) + +# What the factory 0.7.1 image holds at 0xFD800: magic, 5 of 100 entries used, +# flash 1 MiB, RAM 256 KiB, board ID 2886:F00F, UF2 family, 32 pins per port. +CF2 = [ + 0x1E9E10F1, 0x20227A79, 5, 100, + 204, 0x100000, + 205, 0x40000, + 208, 0x2886F00F, + 209, 0xADA52840, + 210, 0x20, + 0, 0, 0, 0, 0, 0, 0, 0, +] + + +def main() -> int: + data = open(sys.argv[1], "rb").read() + code = data[: CF2_AT - BASE] + # Halfword steps: Thumb literal pools are word-aligned, but a constant built from + # two halves or packed in data need not be. + hits = [ + BASE + i + for i in range(0, len(code) - 3, 2) + if struct.unpack_from("/dev/null || { echo "docker is missing" >&2; exit 1; } toml_value() { grep -E "^$2\s*=" "$1" | head -1 | cut -d'"' -f2; } -if [[ -n "${BOARD:-}" ]]; then - dirs=("$BOARDS/$BOARD") -else - dirs=("$BOARDS"/*/) -fi - -for dir in "${dirs[@]}"; do - dir="${dir%/}" - name="$(basename "$dir")" - [[ -d "$dir/bootloader" ]] || continue - chip="$(toml_value "$dir/board.toml" chip)" - echo "== $name ($chip)" +build_esp() { + local dir="$1" name="$2" chip="$3" work table work="$(mktemp -d)" cp "$dir/bootloader/partitions.csv" "$dir/bootloader/sdkconfig.plain" "$dir/bootloader/sdkconfig.secure" "$work/" # The hello_world example is only a project skeleton the bootloader target needs; # nothing of it ends up in the outputs. - docker run --rm -v "$work:/work" "$IMAGE" bash -c ' + docker run --rm -v "$work:/work" "$IDF_IMAGE" bash -c ' set -e for v in plain secure; do rm -rf /work/p @@ -85,5 +83,42 @@ for dir in "${dirs[@]}"; do cp "$work/partition-table-plain.bin" "$dir/images/partition-table.bin" rm -rf "$work" ls -l "$dir/images/bootloader.bin" "$dir/images/bootloader-sb.bin" "$dir/images/partition-table.bin" + echo "sign the Secure Boot bootloader next: tools/sign-vaultkey.sh" +} + +build_uf2() { + local dir="$1" name="$2" out log + docker build -q -t "vkey-bootloader-$name" "$dir/bootloader" >/dev/null + out="$(mktemp -d)" + log="$out/build.log" + # As the host user, so the outputs are the host user's. The log keeps newlib's + # "is not implemented" linker warnings out of sight; build.sh fails on anything real. + if ! docker run --rm -u "$(id -u):$(id -g)" -v "$dir/bootloader:/work/in:ro" -v "$out:/work/out" \ + "vkey-bootloader-$name" sh /work/in/build.sh >"$log" 2>&1; then + cat "$log" >&2 + echo "$name: the bootloader build or its checks failed" >&2 + exit 1 + fi + grep -E "^ *(FLASH|BOOTLOADER_CONFIG):|^check:" "$log" || true + (cd "$out" && sha256sum bootloader.bin update-bootloader.uf2) + echo "$name: outputs in $out - not installed, not copied into images/" +} + +if [[ -n "${BOARD:-}" ]]; then + dirs=("$BOARDS/$BOARD") +else + dirs=("$BOARDS"/*/) +fi + +for dir in "${dirs[@]}"; do + dir="${dir%/}" + name="$(basename "$dir")" + [[ -d "$dir/bootloader" ]] || continue + chip="$(toml_value "$dir/board.toml" chip)" + echo "== $name ($chip)" + case "$chip" in + esp32*) build_esp "$dir" "$name" "$chip" ;; + nrf52840) build_uf2 "$dir" "$name" ;; + *) echo "$name: no bootloader build for chip $chip" >&2; exit 1 ;; + esac done -echo "sign the Secure Boot bootloader next: tools/sign-vaultkey.sh" From 0b8dee301322188799668bf716879b283004468e Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 01:53:25 +0300 Subject: [PATCH 03/33] Strip the UF2 bootloader fork down to the drive - 0002: no CDC, so no serial DFU; no BLE OTA, no SoftDevice update, no double reset, single-tap or skip magic. DFU mode only with the button at reset, no valid app, or the app's GPREGRET 0x57. - 0003: the drive serves no flash; CURRENT.UF2 and its generator are gone. - 0004: app blocks only to 0x1000..0x97000 (BOARD_APP_FLASH_END); a self- update stages at 0x8D000, below the vault. - check.py also reads the disassembly for UICR immediates and movw/movt. - Version 0.9.2-vkey.2 in INFO_UF2.TXT. Code 31312 -> 18096 B. - Not installable yet: the self-update is unsigned and a partial UF2 still boots (milestone 3). --- CLAUDE.md | 4 +- docs2/roadmap.md | 23 +- .../bootloader/board/board.h | 7 + .../nrf52840-mdk-dongle/bootloader/build.sh | 9 +- .../nrf52840-mdk-dongle/bootloader/check.py | 61 +- .../bootloader/patches/0002-drive-only.patch | 912 ++++++++++++++++++ .../bootloader/patches/0003-no-readback.patch | 113 +++ .../patches/0004-write-window.patch | 21 + 8 files changed, 1135 insertions(+), 15 deletions(-) create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0002-drive-only.patch create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0003-no-readback.patch create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0004-write-window.patch diff --git a/CLAUDE.md b/CLAUDE.md index 535a024..a612222 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -315,7 +315,9 @@ The partition table sits at 0xC000, because the Secure Boot bootloader does not The nRF52840's UF2 bootloader fork is built by the same script from its `bootloader/` folder: upstream Adafruit_nRF52_Bootloader at a pinned commit, the board definition read back from the factory binary, a patch series, a pinned Arm toolchain, all in Docker. -`bootloader/check.py` fails the build on any UICR address in the code. Until the fork is +`bootloader/check.py` fails the build on a UICR address in the code - as a word, an +immediate or a movw/movt pair; like the radio search, not one computed from another base +plus an offset. Until the fork is complete the outputs stay in a temporary directory, and installing it is never part of a build (`docs2/roadmap.md`, phase 3). diff --git a/docs2/roadmap.md b/docs2/roadmap.md index d863939..eb75dc2 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -201,7 +201,28 @@ Milestones, one commit each: - The bytes differ from the factory's (another compiler), so "equivalent" means the same configuration, not the same binary. 2. The removals (serial DFU, BLE OTA, the read-back generator, single-tap and double-reset - entry) and the write window. + entry) and the write window. **Built and checked statically 2026-10-14; not run on a + board** (that is milestone 4). Three patches: + - `0002-drive-only`: no CDC interface, and with it no serial DFU. No BLE OTA, no + SoftDevice update path, no double reset, single-tap flag or skip magic. DFU mode is + entered only with the button held at reset, with no valid application, or on the + application's GPREGRET `0x57`. + - `0003-no-readback`: the drive holds `INFO_UF2.TXT` and `INDEX.HTM` and reads as + zeros everywhere else; `CURRENT.UF2` and its generator are gone. + - `0004-write-window`: app blocks are written only to 0x1000..0x97000 + (`BOARD_APP_FLASH_END` in `board.h`); the disassembly compiles it to + `addr - 0x1000 < 0x96000`. A self-update stages at 0x8D000, inside the window. + + Code: 31 312 → 18 096 B, leaving about 20 KiB for the signature check. `check.py` now + also reads the disassembly for UICR addresses built as immediates or movw/movt pairs. + The fork's revision is in its version string (`0.9.2-vkey.2`, shown in + `INFO_UF2.TXT`), the only way to tell builds apart on a board with no probe. + Reproducible: `bootloader.bin` sha256 `76c90d5b…6064`. **Not installable yet**: + - the self-update is unsigned, so once installed it would accept upstream's + connect-kit UF2s (same board ID) and the stock bootloader; + - a partial app UF2 still boots under the old "valid" flag. + + Milestone 3 closes both. 3. The signed trailer, with length and version inside the signed bytes, checked on every boot; the host signing tool. The signature scheme is chosen by measuring the code size and boot time of each verify-only candidate. diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h index a665c30..6e9c9f3 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h @@ -63,6 +63,13 @@ #define USB_DESC_UF2_PID 0xF00F #define USB_DESC_CDC_ONLY_PID 0xF00F +/*------------------------------------------------------------------*/ +/* Flash: the drive writes 0x1000..BOARD_APP_FLASH_END and nothing else. Above it lie + * the vault (0x97000..0xD8000) and the filesystem a firmware keeps (0xD8000..0xEC000). + * The same boundary as FLASH in the firmware's memory.x and VAULT_BASE in its main.rs. + *------------------------------------------------------------------*/ +#define BOARD_APP_FLASH_END 0x97000 + #define UF2_PRODUCT_NAME "Makerdiary nRF52840 MDK USB Dongle" #define UF2_VOLUME_LABEL "UF2BOOT " #define UF2_BOARD_ID "nRF52840-MDK-USB-DONGLE" diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh index 7af0da3..fe7da66 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh @@ -6,6 +6,7 @@ # bootloader.hex the bootloader, with Nordic's MBR (what a probe would write) # update-bootloader.uf2 the same as a self-update UF2 (family 0xD663823C) # bootloader.bin the bootloader region alone, from 0xF4000, for check.py +# bootloader.dis its disassembly, for check.py # systeminit.txt SystemInit disassembled, read before any install # # The tree is the image's pristine upstream checkout, so every run starts from the same @@ -15,7 +16,10 @@ set -eu BOARD=nrf52840_mdk_usb_dongle -VERSION=0.9.2-vkey +# Upstream's version, then the fork's revision, bumped with every change to this folder: +# with no probe, INFO_UF2.TXT on the drive is the only way to tell which build a board +# runs. The Makefile takes the bootloader version number from the part before "-". +VERSION=0.9.2-vkey.2 # What `git submodule status` reports for the pinned commits today, as the factory # 0.7.1 bootloader reports it too. Fixed here because the uf2 part names an upstream # branch, and a fresh clone after that branch moves would change the INFO text. @@ -51,5 +55,6 @@ cp "_build/build-$BOARD/update-${BOARD}_bootloader-${VERSION}_nosd.uf2" /work/ou arm-none-eabi-objcopy -O binary -R .uicrBootStartAddress -R .uicrMbrParamsPageAddress \ "$out.out" /work/out/bootloader.bin arm-none-eabi-objdump -d --disassemble=SystemInit "$out.out" > /work/out/systeminit.txt +arm-none-eabi-objdump -d --no-show-raw-insn "$out.out" > /work/out/bootloader.dis arm-none-eabi-size "$out.out" -python3 /work/in/check.py /work/out/bootloader.bin +python3 /work/in/check.py /work/out/bootloader.bin /work/out/bootloader.dis diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py b/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py index 13d1437..ee3bcc7 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py @@ -1,14 +1,18 @@ """Fail closed on a bootloader that would be dangerous to install on a board with no SWD probe. Takes bootloader.bin, the region from 0xF4000 (code, then the CF2 page at -0xFD800). Run by build.sh after every build. +0xFD800), and bootloader.dis, its disassembly. Run by build.sh after every build. -- No UICR address anywhere in the code: the bootloader must never write UICR. A write - there (PSELRESET, NFCPINS, APPROTECT) is permanent without a probe. +- No UICR address the code could write through: the bootloader must never write UICR. + A write there (PSELRESET, NFCPINS, APPROTECT) is permanent without a probe. Searched + three ways: as a word anywhere in the code, as an immediate in any instruction but a + comparison, and as a movw/movt pair. Like the radio search in build-vaultkey.sh, it + catches direct addressing, not an address computed from another base plus an offset. - The CF2 block is the factory one, word for word. Its board ID is what the factory bootloader checks before it accepts this one as a self-update, and what a later self-update of this one is checked against. """ +import re import struct import sys @@ -28,19 +32,54 @@ 0, 0, 0, 0, 0, 0, 0, 0, ] +# objdump --no-show-raw-insn: " f5f2a:\tcmp.w\tr3, #268439552\t@ 0x10001000" +INSN = re.compile(r"^\s*([0-9a-f]+):\s+(\S+)\s*(.*)$") +NUMBER = re.compile(r"(? int: - data = open(sys.argv[1], "rb").read() - code = data[: CF2_AT - BASE] - # Halfword steps: Thumb literal pools are word-aligned, but a constant built from - # two halves or packed in data need not be. - hits = [ - BASE + i + +def words_in_code(code: bytes) -> list[str]: + # Halfword steps: Thumb literal pools are word-aligned, but a constant packed in + # data need not be. + return [ + hex(BASE + i) for i in range(0, len(code) - 3, 2) if struct.unpack_from(" list[str]: + hits = [] + last_movw: dict[str, int] = {} + for line in dis.splitlines(): + m = INSN.match(line) + if not m: + continue + addr, op, args = m.group(1), m.group(2), m.group(3) + text = f"{op} {args}" + if not op.startswith(("cmp", "cmn")): + for n in NUMBER.findall(args): + if int(n, 0) in UICR: + hits.append(f"{addr}: {text}") + break + if w := MOVW.match(text): + last_movw[w.group(1)] = int(w.group(2)) + elif t := MOVT.match(text): + low = last_movw.get(t.group(1)) + if low is not None and (int(t.group(2)) << 16 | low) in UICR: + hits.append(f"{addr}: {text} (with movw #{low:#x})") + return hits + + +def main() -> int: + data = open(sys.argv[1], "rb").read() + dis = open(sys.argv[2]).read() + code = data[: CF2_AT - BASE] + + hits = words_in_code(code) + immediates_and_pairs(dis) if hits: - print("UICR addresses in the code at " + ", ".join(hex(h) for h in hits)) + print("UICR addresses the code could write through:\n " + "\n ".join(hits)) return 1 cf2 = list(struct.unpack_from(f"<{len(CF2)}I", data, CF2_AT - BASE)) diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0002-drive-only.patch b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0002-drive-only.patch new file mode 100644 index 0000000..616dcc1 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0002-drive-only.patch @@ -0,0 +1,912 @@ +diff --git a/Makefile b/Makefile +index edaedf9..625a1c8 100644 +--- a/Makefile ++++ b/Makefile +@@ -129,8 +129,6 @@ endif + + # all files in src + C_SRC += \ +- src/dfu_ble_svc.c \ +- src/dfu_init.c \ + src/flash_nrf5x.c \ + src/main.c \ + src/screen.c \ +@@ -144,15 +142,11 @@ C_SRC += $(NRFX_PATH)/drivers/src/nrfx_power.c + C_SRC += $(NRFX_PATH)/drivers/src/nrfx_nvmc.c + C_SRC += $(NRFX_PATH)/mdk/system_$(MCU_SUB_VARIANT).c + +-# SDK 11 files: serial + OTA DFU ++# SDK 11 files: the bootloader core. Serial and BLE OTA DFU are removed: the drive is ++# the only way to write flash. + C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader.c + C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader_settings.c + C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader_util.c +-C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_serial.c +-C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_transport_ble.c +-C_SRC += $(SDK11_PATH)/libraries/bootloader_dfu/dfu_single_bank.c +-C_SRC += $(SDK11_PATH)/ble/ble_services/ble_dfu/ble_dfu.c +-C_SRC += $(SDK11_PATH)/ble/ble_services/ble_dis/ble_dis.c + C_SRC += $(SDK11_PATH)/drivers_nrf/pstorage/pstorage_raw.c + + # Latest SDK files: peripheral drivers +@@ -161,9 +155,6 @@ C_SRC += $(SDK_PATH)/libraries/scheduler/app_scheduler.c + C_SRC += $(SDK_PATH)/libraries/util/app_error.c + C_SRC += $(SDK_PATH)/libraries/util/app_util_platform.c + C_SRC += $(SDK_PATH)/libraries/crc16/crc16.c +-C_SRC += $(SDK_PATH)/libraries/hci/hci_mem_pool.c +-C_SRC += $(SDK_PATH)/libraries/hci/hci_slip.c +-C_SRC += $(SDK_PATH)/libraries/hci/hci_transport.c + C_SRC += $(SDK_PATH)/libraries/util/nrf_assert.c + + # UART or USB Serial +@@ -195,7 +186,6 @@ C_SRC += \ + $(TUSB_PATH)/common/tusb_fifo.c \ + $(TUSB_PATH)/device/usbd.c \ + $(TUSB_PATH)/device/usbd_control.c \ +- $(TUSB_PATH)/class/cdc/cdc_device.c \ + $(TUSB_PATH)/class/msc/msc_device.c \ + $(TUSB_PATH)/tusb.c + +diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +index 749347d..fe321ce 100644 +--- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c ++++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +@@ -52,7 +52,6 @@ static bootloader_status_t m_update_status; /**< Current update stat + static bool m_cancel_timeout_on_usb; /**< If set the timeout is cancelled when USB is enumerated. Otherwise, the timeout is only cancelled when DFU update is started. */ + + APP_TIMER_DEF( _dfu_startup_timer ); +-volatile bool dfu_startup_packet_received = false; + + /**@brief Function for handling callbacks from pstorage module. + * +@@ -87,16 +86,11 @@ static void dfu_startup_timer_handler(void * p_context) + } + #endif + +- // nRF52832 forced DFU on startup +- // No packets are received within timeout, exit DFU mode +- // dfu_startup_packet_received is set by process_dfu_packet() in dfu_transport_serial.c +- if (!dfu_startup_packet_received) +- { +- dfu_update_status_t update_status; +- update_status.status_code = DFU_TIMEOUT; ++ // Not mounted within the timeout: exit DFU mode ++ dfu_update_status_t update_status; ++ update_status.status_code = DFU_TIMEOUT; + +- bootloader_dfu_update_process(update_status); +- } ++ bootloader_dfu_update_process(update_status); + } + + /**@brief Function for waiting for events. +@@ -130,7 +124,6 @@ static void wait_for_events(void) + if ( tusb_inited() ) + { + tud_task(); +- tud_cdc_write_flush(); + } + #endif + +@@ -184,21 +177,10 @@ bool bootloader_app_is_valid(void) + + static void bootloader_settings_save(bootloader_settings_t * p_settings) + { +- if ( is_ota() ) +- { +- uint32_t err_code = pstorage_clear(&m_bootsettings_handle, sizeof(bootloader_settings_t)); +- APP_ERROR_CHECK(err_code); +- +- err_code = pstorage_store(&m_bootsettings_handle, (uint8_t *) p_settings, sizeof(bootloader_settings_t), 0); +- APP_ERROR_CHECK(err_code); +- } +- else +- { +- nrfx_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS); +- nrfx_nvmc_words_write(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4); ++ nrfx_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS); ++ nrfx_nvmc_words_write(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4); + +- pstorage_callback_handler(&m_bootsettings_handle, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_settings, sizeof(bootloader_settings_t)); +- } ++ pstorage_callback_handler(&m_bootsettings_handle, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_settings, sizeof(bootloader_settings_t)); + } + + +@@ -219,81 +201,10 @@ void bootloader_dfu_update_process(dfu_update_status_t update_status) + m_update_status = BOOTLOADER_SETTINGS_SAVING; + bootloader_settings_save(&settings); + } +- else if (update_status.status_code == DFU_UPDATE_SD_COMPLETE) +- { +- settings.bank_0_crc = update_status.app_crc; +- settings.bank_0_size = update_status.sd_size + update_status.bl_size + update_status.app_size; +- settings.bank_0 = BANK_VALID_SD; +- settings.bank_1 = BANK_INVALID_APP; +- settings.sd_image_size = update_status.sd_size; +- settings.bl_image_size = update_status.bl_size; +- settings.app_image_size = update_status.app_size; +- settings.sd_image_start = update_status.sd_image_start; +- +- m_update_status = BOOTLOADER_SETTINGS_SAVING; +- bootloader_settings_save(&settings); +- } +- else if (update_status.status_code == DFU_UPDATE_BOOT_COMPLETE) +- { +- settings.bank_0 = p_bootloader_settings->bank_0; +- settings.bank_0_crc = p_bootloader_settings->bank_0_crc; +- settings.bank_0_size = p_bootloader_settings->bank_0_size; +- settings.bank_1 = BANK_VALID_BOOT; +- settings.sd_image_size = update_status.sd_size; +- settings.bl_image_size = update_status.bl_size; +- settings.app_image_size = update_status.app_size; +- +- m_update_status = BOOTLOADER_SETTINGS_SAVING; +- bootloader_settings_save(&settings); +- } +- else if (update_status.status_code == DFU_UPDATE_SD_SWAPPED) +- { +- if (p_bootloader_settings->bank_0 == BANK_VALID_SD) +- { +- settings.bank_0_crc = 0; +- settings.bank_0_size = 0; +- settings.bank_0 = BANK_INVALID_APP; +- } +- // This handles cases where SoftDevice was not updated, hence bank0 keeps its settings. +- else +- { +- settings.bank_0 = p_bootloader_settings->bank_0; +- settings.bank_0_crc = p_bootloader_settings->bank_0_crc; +- settings.bank_0_size = p_bootloader_settings->bank_0_size; +- } +- +- settings.bank_1 = BANK_INVALID_APP; +- settings.sd_image_size = 0; +- settings.bl_image_size = 0; +- settings.app_image_size = 0; +- +- m_update_status = BOOTLOADER_SETTINGS_SAVING; +- bootloader_settings_save(&settings); +- } + else if (update_status.status_code == DFU_TIMEOUT) + { +- // Timeout has occurred. Close the connection with the DFU Controller. +- uint32_t err_code; +- if ( is_ota() ) +- { +- err_code = dfu_transport_ble_close(); +- }else +- { +- err_code = dfu_transport_serial_close(); +- } +- APP_ERROR_CHECK(err_code); +- + m_update_status = BOOTLOADER_TIMEOUT; + } +- else if (update_status.status_code == DFU_BANK_0_ERASED) +- { +- settings.bank_0_crc = 0; +- settings.bank_0_size = 0; +- settings.bank_0 = BANK_INVALID_APP; +- settings.bank_1 = p_bootloader_settings->bank_1; +- +- bootloader_settings_save(&settings); +- } + else if (update_status.status_code == DFU_RESET) + { + m_update_status = BOOTLOADER_RESET; +@@ -320,38 +231,19 @@ uint32_t bootloader_init(void) + } + + +-uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout_on_usb) ++void bootloader_dfu_start(uint32_t timeout_ms, bool cancel_timeout_on_usb) + { +- uint32_t err_code; ++ m_cancel_timeout_on_usb = cancel_timeout_on_usb; + +- m_cancel_timeout_on_usb = cancel_timeout_on_usb && !ota; +- +- // Clear swap if banked update is used. +- err_code = dfu_init(); +- VERIFY_SUCCESS(err_code); +- +- if ( ota ) +- { +- err_code = dfu_transport_ble_update_start(); +- }else ++ // DFU mode with a timeout: entered on the application's request, but USB never ++ // enumerated (battery power) ++ if ( timeout_ms ) + { +- // DFU mode with timeout can be +- // - Forced startup DFU for nRF52832 or +- // - Makecode single tap reset but no enumerated (battery power) +- if ( timeout_ms ) +- { +- dfu_startup_packet_received = false; +- +- app_timer_create(&_dfu_startup_timer, APP_TIMER_MODE_SINGLE_SHOT, dfu_startup_timer_handler); +- app_timer_start(_dfu_startup_timer, APP_TIMER_TICKS(timeout_ms), NULL); +- } +- +- err_code = dfu_transport_serial_update_start(); ++ app_timer_create(&_dfu_startup_timer, APP_TIMER_MODE_SINGLE_SHOT, dfu_startup_timer_handler); ++ app_timer_start(_dfu_startup_timer, APP_TIMER_TICKS(timeout_ms), NULL); + } + + wait_for_events(); +- +- return err_code; + } + + void bootloader_app_start(void) +@@ -402,62 +294,6 @@ void bootloader_app_start(void) + } + + +-bool bootloader_dfu_sd_in_progress(void) +-{ +- bootloader_settings_t const * p_bootloader_settings; +- +- bootloader_util_settings_get(&p_bootloader_settings); +- +- if (p_bootloader_settings->bank_0 == BANK_VALID_SD || +- p_bootloader_settings->bank_1 == BANK_VALID_BOOT) +- { +- return true; +- } +- +- return false; +-} +- +- +-uint32_t bootloader_dfu_sd_update_continue(void) +-{ +- uint32_t err_code; +- +- if ((dfu_sd_image_validate() == NRF_SUCCESS) && +- (dfu_bl_image_validate() == NRF_SUCCESS)) +- { +- return NRF_SUCCESS; +- } +- +- // Ensure that flash operations are not executed within the first 100 ms seconds to allow +- // a debugger to be attached. +- NRFX_DELAY_MS(100); +- +- err_code = dfu_sd_image_swap(); +- APP_ERROR_CHECK(err_code); +- +- err_code = dfu_sd_image_validate(); +- APP_ERROR_CHECK(err_code); +- +- err_code = dfu_bl_image_swap(); +- APP_ERROR_CHECK(err_code); +- +- return err_code; +-} +- +- +-uint32_t bootloader_dfu_sd_update_finalize(void) +-{ +- dfu_update_status_t update_status = { 0 }; +- update_status.status_code = DFU_UPDATE_SD_SWAPPED; +- +- bootloader_dfu_update_process(update_status); +- +- wait_for_events(); +- +- return NRF_SUCCESS; +-} +- +- + void bootloader_settings_get(bootloader_settings_t * const p_settings) + { + bootloader_settings_t const * p_bootloader_settings; +diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h +index 132df8d..2175786 100644 +--- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h ++++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.h +@@ -38,11 +38,10 @@ uint32_t bootloader_init(void); + */ + bool bootloader_app_is_valid(void); + +-/**@brief Function for starting the Device Firmware Update. +- * +- * @retval NRF_SUCCESS If new application image was successfully transferred. ++/**@brief Function for running the Device Firmware Update over the drive, until it ++ * completes, is reset, or times out (timeout_ms 0: never). + */ +-uint32_t bootloader_dfu_start(bool ota, uint32_t timeout_ms, bool cancel_timeout_on_usb); ++void bootloader_dfu_start(uint32_t timeout_ms, bool cancel_timeout_on_usb); + + /**@brief Function for exiting bootloader and booting into application. + * +@@ -67,28 +66,6 @@ void bootloader_settings_get(bootloader_settings_t * const p_settings); + */ + void bootloader_dfu_update_process(dfu_update_status_t update_status); + +-/**@brief Function getting state of SoftDevice update in progress. +- * After a successfull SoftDevice transfer the system restarts in orderto disable SoftDevice +- * and complete the update. +- * +- * @retval true A SoftDevice update is in progress. This indicates that second stage +- * of a SoftDevice update procedure can be initiated. +- * @retval false No SoftDevice update is in progress. +- */ +-bool bootloader_dfu_sd_in_progress(void); +- +-/**@brief Function for continuing the Device Firmware Update of a SoftDevice. +- * +- * @retval NRF_SUCCESS If the final stage of SoftDevice update was successful. +- */ +-uint32_t bootloader_dfu_sd_update_continue(void); +- +-/**@brief Function for finalizing the Device Firmware Update of a SoftDevice. +- * +- * @retval NRF_SUCCESS If the final stage of SoftDevice update was successful. +- */ +-uint32_t bootloader_dfu_sd_update_finalize(void); +- + + void bootloader_mbr_addrs_populate(void); + +diff --git a/src/boards/boards.h b/src/boards/boards.h +index e60b822..e8496b4 100644 +--- a/src/boards/boards.h ++++ b/src/boards/boards.h +@@ -112,7 +112,6 @@ void led_tick(void); + void button_init(uint32_t pin); + bool button_pressed(uint32_t pin); + +-bool is_ota(void); + + //--------------------------------------------------------------------+ + // Display +diff --git a/src/main.c b/src/main.c +index 92ad020..c72cf43 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -73,7 +73,7 @@ + #include "nrf_usbd.h" + #include "tusb.h" + +-void usb_init(bool cdc_only); ++void usb_init(void); + void usb_teardown(void); + + // tinyusb function that handles power event (detected, ready, removed) +@@ -81,7 +81,7 @@ void usb_teardown(void); + extern void tusb_hal_nrf_power_event(uint32_t event); + + #else +-#define usb_init(x) led_state(STATE_USB_MOUNTED) // mark nrf52832 as mounted ++#define usb_init() led_state(STATE_USB_MOUNTED) // mark nrf52832 as mounted + #define usb_teardown() + + #endif +@@ -95,59 +95,20 @@ extern void tusb_hal_nrf_power_event(uint32_t event); + * - Fatal Error : LED Status & Conn blink one after another + */ + +-/* Magic that written to NRF_POWER->GPREGRET by application when it wish to go into DFU +- * - DFU_MAGIC_OTA_APPJUM : used by BLEDfu service, SD is already inited +- * - DFU_MAGIC_OTA_RESET : entered by soft reset, SD is not inited yet +- * - DFU_MAGIC_SERIAL_ONLY_RESET : with CDC interface only +- * - DFU_MAGIC_UF2_RESET : with CDC and MSC interfaces +- * - DFU_MAGIC_SKIP : skip DFU entirely including double reset delay, +- * Can be used with systemoff or quick reset to app +- * +- * Note: for DFU_MAGIC_OTA_APPJUM Softdevice must not initialized. +- * since it is already in application. In all other case of OTA SD must be initialized ++/* The ways into DFU mode: the button held at reset, no valid application, or the ++ * application writing DFU_MAGIC_UF2_RESET to NRF_POWER->GPREGRET before a reset. The ++ * rest upstream offers - BLE OTA, serial DFU, double reset, the single-tap flag, the ++ * skip magic - is removed: each was another way to write flash, or into the mode ++ * that does. + */ +-#define DFU_MAGIC_OTA_APPJUM BOOTLOADER_DFU_START // 0xB1 +-#define DFU_MAGIC_OTA_RESET 0xA8 +-#define DFU_MAGIC_SERIAL_ONLY_RESET 0x4e + #define DFU_MAGIC_UF2_RESET 0x57 +-#define DFU_MAGIC_SKIP 0x6d +- +-#define DFU_DBL_RESET_MAGIC 0x5A1AD5 // SALADS +-#define DFU_DBL_RESET_APP 0x4ee5677e +-#define DFU_DBL_RESET_DELAY 500 +-#define DFU_DBL_RESET_MEM 0x20007F7C + + #define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0] +-#define DFU_SERIAL_STARTUP_INTERVAL 1000 +- +-// Allow for using reset button essentially to swap between application and bootloader. +-// This is controlled by a flag in the app and is the behavior of CPX and all Arcade boards when using MakeCode. +-// DFU_DBL_RESET magic is used to determined which mode is entered +-#define APP_ASKS_FOR_SINGLE_TAP_RESET() (*((uint32_t*)(DFU_BANK_0_REGION_START + 0x200)) == 0x87eeb07c) +- +-// These value must be the same with one in dfu_transport_ble.c +-#define BLEGAP_EVENT_LENGTH 6 +-#define BLEGATT_ATT_MTU_MAX 23 +-enum { +- BLE_CONN_CFG_HIGH_BANDWIDTH = 1 +-}; + + //--------------------------------------------------------------------+ + // + //--------------------------------------------------------------------+ +-uint32_t* dbl_reset_mem = ((uint32_t*) DFU_DBL_RESET_MEM); +- +-// true if ble, false if serial +-bool _ota_dfu = false; +-bool _ota_connected = false; +-bool _sd_inited = false; +- +-bool is_ota(void) { +- return _ota_dfu; +-} +- + static void check_dfu_mode(void); +-static uint32_t ble_stack_init(void); + + // The SoftDevice must only be initialized if a chip reset has occurred. + // Soft reset (jump ) from application must not reinitialize the SoftDevice. +@@ -175,16 +136,6 @@ int main(void) { + PRINTF("Bootloader Start\r\n"); + led_state(STATE_BOOTLOADER_STARTED); + +- // When updating SoftDevice, bootloader will reset before swapping SD +- if (bootloader_dfu_sd_in_progress()) { +- led_state(STATE_WRITING_STARTED); +- +- bootloader_dfu_sd_update_continue(); +- bootloader_dfu_sd_update_finalize(); +- +- led_state(STATE_WRITING_FINISHED); +- } +- + // Check all inputs and enter DFU if needed + // Return when DFU process is complete (or not entered at all) + check_dfu_mode(); +@@ -199,19 +150,16 @@ int main(void) { + * - sd_softdevice_vector_table_base_set(APP_ADDR) + * - jump to App reset + */ +- if (bootloader_app_is_valid() && !bootloader_dfu_sd_in_progress()) { ++ if (bootloader_app_is_valid()) { + PRINTF("App is valid\r\n"); + if (is_sd_existed()) { +- // MBR forward IRQ to SD (if not already) +- if (!_sd_inited) mbr_init_sd(); ++ // MBR forward IRQ to SD ++ mbr_init_sd(); + + // Make sure SD is disabled + sd_softdevice_disable(); + } + +- // clear in case we kept DFU_DBL_RESET_APP there +- (*dbl_reset_mem) = 0; +- + // start application + bootloader_app_start(); + } +@@ -220,161 +168,29 @@ int main(void) { + } + + static void check_dfu_mode(void) { +- uint32_t const gpregret = NRF_POWER->GPREGRET; +- +- // SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC +- _sd_inited = (gpregret == DFU_MAGIC_OTA_APPJUM); +- +- // Start Bootloader in BLE OTA mode +- _ota_dfu = (gpregret == DFU_MAGIC_OTA_APPJUM) || (gpregret == DFU_MAGIC_OTA_RESET); +- +- // Serial only mode +- bool const serial_only_dfu = (gpregret == DFU_MAGIC_SERIAL_ONLY_RESET); +- bool const uf2_dfu = (gpregret == DFU_MAGIC_UF2_RESET); +- bool const dfu_skip = (gpregret == DFU_MAGIC_SKIP); +- +- bool const reason_reset_pin = (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk) ? true : false; +- +- // start either serial, uf2 or ble +- bool dfu_start = _ota_dfu || serial_only_dfu || uf2_dfu || +- (((*dbl_reset_mem) == DFU_DBL_RESET_MAGIC) && reason_reset_pin); +- +- // Clear GPREGRET if it is our values +- if (dfu_start || dfu_skip) NRF_POWER->GPREGRET = 0; +- +- // skip dfu entirely +- if (dfu_skip) return; +- +- /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ +- // DFU button pressed +- dfu_start = dfu_start || button_pressed(BUTTON_DFU); +- +- // DFU + FRESET are pressed --> OTA +- _ota_dfu = _ota_dfu || (button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET)); ++ // The application asked for DFU mode: clear the request, so the next reset boots it ++ bool const uf2_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET); ++ if (uf2_dfu) NRF_POWER->GPREGRET = 0; + ++ bool const dfu_start = uf2_dfu || button_pressed(BUTTON_DFU); + bool const valid_app = bootloader_app_is_valid(); +- bool const just_start_app = valid_app && !dfu_start && (*dbl_reset_mem) == DFU_DBL_RESET_APP; +- +- if (!just_start_app && APP_ASKS_FOR_SINGLE_TAP_RESET()) dfu_start = 1; +- +- // App mode: Double Reset detection or DFU startup for nrf52832 +- if (!(just_start_app || dfu_start || !valid_app)) { +-#ifdef NRF52832_XXAA +- /* Even DFU is not active, we still force an 1000 ms dfu serial mode when startup +- * to support auto programming from Arduino IDE +- * +- * Note: Double Reset WONT work with nrf52832 since all its SRAM got cleared with GPIO reset. +- */ +- bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL, false); +-#else +- // Note: RESETREAS is not clear by bootloader, it should be cleared by application upon init() +- if (reason_reset_pin) { +- // Register our first reset for double reset detection +- (*dbl_reset_mem) = DFU_DBL_RESET_MAGIC; + +- // if RST is pressed during this delay (double reset)--> if will enter dfu +- NRFX_DELAY_MS(DFU_DBL_RESET_DELAY); +- } +-#endif +- } +- +- if (APP_ASKS_FOR_SINGLE_TAP_RESET()) { +- (*dbl_reset_mem) = DFU_DBL_RESET_APP; +- } else { +- (*dbl_reset_mem) = 0; +- } +- +- // Enter DFU mode accordingly to input + if (dfu_start || !valid_app) { +- if (_ota_dfu) { +- led_state(STATE_BLE_DISCONNECTED); +- if (!_sd_inited) mbr_init_sd(); +- _sd_inited = true; +- ble_stack_init(); +- } else { +- led_state(STATE_USB_UNMOUNTED); +- usb_init(serial_only_dfu); +- } ++ led_state(STATE_USB_UNMOUNTED); ++ usb_init(); + +- // Initiate an update of the firmware. +- if (APP_ASKS_FOR_SINGLE_TAP_RESET() || uf2_dfu || serial_only_dfu) { ++ if (uf2_dfu) { + // If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app. +- bootloader_dfu_start(_ota_dfu, 3000, true); ++ bootloader_dfu_start(3000, true); + } else { +- // No timeout if bootloader requires user action (double-reset). +- bootloader_dfu_start(_ota_dfu, 0, false); ++ // No timeout when a person asked (the button) or there is nothing valid to boot. ++ bootloader_dfu_start(0, false); + } + +- if (_ota_dfu) { +- sd_softdevice_disable(); +- } else { +- usb_teardown(); +- } ++ usb_teardown(); + } + } + +-// Initializes the SotdDevice by following SD specs section +-// "Master Boot Record and SoftDevice initializaton procedure" +-static uint32_t ble_stack_init(void) { +- // Forward vector table to bootloader address so that we can handle BLE events +- sd_softdevice_vector_table_base_set(BOOTLOADER_REGION_START); +- +- // Enable Softdevice, Use Internal OSC to compatible with all boards +- nrf_clock_lf_cfg_t clock_cfg = { +- .source = NRF_CLOCK_LF_SRC_RC, +- .rc_ctiv = 16, +- .rc_temp_ctiv = 2, +- .accuracy = NRF_CLOCK_LF_ACCURACY_250_PPM +- }; +- sd_softdevice_enable(&clock_cfg, app_error_fault_handler); +- sd_nvic_EnableIRQ(SD_EVT_IRQn); +- +- /*------------- Configure BLE params -------------*/ +- extern uint32_t __data_start__[]; // defined in linker +- uint32_t ram_start = (uint32_t) __data_start__; +- +- ble_cfg_t blecfg; +- +- // Configure the maximum number of connections. +- varclr(&blecfg); +- blecfg.gap_cfg.role_count_cfg.adv_set_count = 1; +- blecfg.gap_cfg.role_count_cfg.periph_role_count = 1; +- blecfg.gap_cfg.role_count_cfg.central_role_count = 0; +- blecfg.gap_cfg.role_count_cfg.central_sec_count = 0; +- sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &blecfg, ram_start); +- +- // NRF_DFU_BLE_REQUIRES_BONDS +- varclr(&blecfg); +- blecfg.gatts_cfg.service_changed.service_changed = 1; +- sd_ble_cfg_set(BLE_GATTS_CFG_SERVICE_CHANGED, &blecfg, ram_start); +- +- // ATT MTU +- varclr(&blecfg); +- blecfg.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_HIGH_BANDWIDTH; +- blecfg.conn_cfg.params.gatt_conn_cfg.att_mtu = BLEGATT_ATT_MTU_MAX; +- sd_ble_cfg_set(BLE_CONN_CFG_GATT, &blecfg, ram_start); +- +- // Event Length + HVN queue + WRITE CMD queue setting affecting bandwidth +- varclr(&blecfg); +- blecfg.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_HIGH_BANDWIDTH; +- blecfg.conn_cfg.params.gap_conn_cfg.conn_count = 1; +- blecfg.conn_cfg.params.gap_conn_cfg.event_length = BLEGAP_EVENT_LENGTH; +- sd_ble_cfg_set(BLE_CONN_CFG_GAP, &blecfg, ram_start); +- +- // Enable BLE stack. +- // Note: Interrupt state (enabled, forwarding) is not work properly if not enable ble +- sd_ble_enable(&ram_start); +- +-#if 0 +- ble_opt_t opt; +- varclr(&opt); +- opt.common_opt.conn_evt_ext.enable = 1; // enable Data Length Extension +- sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt); +-#endif +- +- return NRF_SUCCESS; +-} +- + //--------------------------------------------------------------------+ + // Error Handler + //--------------------------------------------------------------------+ +@@ -388,83 +204,6 @@ void assert_nrf_callback(uint16_t line_num, uint8_t const* p_file_name) { + app_error_fault_handler(0xDEADBEEF, 0, 0); + } + +-/*------------------------------------------------------------------*/ +-/* SoftDevice Event handler +- *------------------------------------------------------------------*/ +- +-// Process BLE event from SD +-uint32_t proc_ble(void) { +- __ALIGN(4) uint8_t ev_buf[BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX)]; +- uint16_t ev_len = BLE_EVT_LEN_MAX(BLEGATT_ATT_MTU_MAX); +- +- // Init header +- ble_evt_t* evt = (ble_evt_t*) ev_buf; +- evt->header.evt_id = BLE_EVT_INVALID; +- +- // Get BLE Event +- uint32_t err = sd_ble_evt_get(ev_buf, &ev_len); +- +- // Handle valid event, ignore error +- if (NRF_SUCCESS == err) { +- switch (evt->header.evt_id) { +- case BLE_GAP_EVT_CONNECTED: +- _ota_connected = true; +- led_state(STATE_BLE_CONNECTED); +- break; +- +- case BLE_GAP_EVT_DISCONNECTED: +- _ota_connected = false; +- led_state(STATE_BLE_DISCONNECTED); +- break; +- +- default: +- break; +- } +- +- // from dfu_transport_ble +- extern void ble_evt_dispatch(ble_evt_t* p_ble_evt); +- ble_evt_dispatch(evt); +- } +- +- return err; +-} +- +-// process SOC event from SD +-uint32_t proc_soc(void) { +- uint32_t soc_evt = 0; +- uint32_t err = sd_evt_get(&soc_evt); +- +- if (NRF_SUCCESS == err) { +- pstorage_sys_event_handler(soc_evt); +- +-#ifdef NRF_USBD +- /*------------- usb power event handler -------------*/ +- int32_t usbevt = (soc_evt == NRF_EVT_POWER_USB_DETECTED) ? NRFX_POWER_USB_EVT_DETECTED : +- (soc_evt == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY : +- (soc_evt == NRF_EVT_POWER_USB_REMOVED) ? NRFX_POWER_USB_EVT_REMOVED : -1; +- +- if (usbevt >= 0) tusb_hal_nrf_power_event((uint32_t) usbevt); +-#endif +- } +- +- return err; +-} +- +-void proc_sd_task(void* evt_data, uint16_t evt_size) { +- (void) evt_data; +- (void) evt_size; +- +- // process BLE and SOC until there is no more events +- while ((NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc())) { +- // nothing +- } +-} +- +-void SD_EVT_IRQHandler(void) { +- // Use App Scheduler to defer handling code in non-isr context +- app_sched_event_put(NULL, 0, proc_sd_task); +-} +- + //--------------------------------------------------------------------+ + // RTT printf retarget for Debug + //--------------------------------------------------------------------+ +diff --git a/src/usb/tusb_config.h b/src/usb/tusb_config.h +index b7c93a4..0f7094d 100644 +--- a/src/usb/tusb_config.h ++++ b/src/usb/tusb_config.h +@@ -52,17 +52,15 @@ + #define CFG_TUD_ENDOINT0_SIZE 64 + + //------------- Class enabled -------------// +-#define CFG_TUD_CDC 1 ++// No CDC: the serial port carried legacy serial DFU, which writes the app, the ++// bootloader and the SoftDevice with no signature. The drive (MSC) is the only interface. ++#define CFG_TUD_CDC 0 + #define CFG_TUD_MSC 1 + + /*------------------------------------------------------------------*/ + /* CLASS DRIVER + *------------------------------------------------------------------*/ + +-// FIFO size of CDC TX and RX +-#define CFG_TUD_CDC_RX_BUFSIZE 1024 +-#define CFG_TUD_CDC_TX_BUFSIZE 1024 +- + // Buffer size for each read/write transfer, the more the better + #define CFG_TUD_MSC_BUFSIZE (4*1024) + +diff --git a/src/usb/usb.c b/src/usb/usb.c +index 30d91c0..c4f6f5c 100644 +--- a/src/usb/usb.c ++++ b/src/usb/usb.c +@@ -53,7 +53,7 @@ void USBD_IRQHandler(void) { + } + + //------------- IMPLEMENTATION -------------// +-void usb_init(bool cdc_only) { ++void usb_init(void) { + // 0, 1 is reserved for SD + NVIC_SetPriority(USBD_IRQn, 2); + +@@ -93,7 +93,7 @@ void usb_init(bool cdc_only) { + tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY); + } + +- usb_desc_init(cdc_only); ++ usb_desc_init(); + uf2_init(); + tusb_init(); + +diff --git a/src/usb/usb_desc.c b/src/usb/usb_desc.c +index 535bb52..3c6aa51 100644 +--- a/src/usb/usb_desc.c ++++ b/src/usb/usb_desc.c +@@ -29,13 +29,9 @@ enum { + STRID_MANUFACTURER , + STRID_PRODUCT , + STRID_SERIAL , +- STRID_CDC , + STRID_MSC + }; + +-// CDC + MSC or CDC only mode +-static bool _cdc_only = false; +- + // Serial is 64-bit DeviceID -> 16 chars len + static char desc_str_serial[1+16]; + +@@ -48,11 +44,10 @@ tusb_desc_device_t desc_device = + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + +- // Use Interface Association Descriptor (IAD) for CDC +- // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) +- .bDeviceClass = TUSB_CLASS_MISC, +- .bDeviceSubClass = MISC_SUBCLASS_COMMON, +- .bDeviceProtocol = MISC_PROTOCOL_IAD, ++ // One interface, so its class is the device's: no IAD ++ .bDeviceClass = TUSB_CLASS_UNSPECIFIED, ++ .bDeviceSubClass = 0, ++ .bDeviceProtocol = 0, + .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + + .idVendor = USB_DESC_VID, +@@ -78,31 +73,17 @@ uint8_t const * tud_descriptor_device_cb(void) + //--------------------------------------------------------------------+ + + enum { +- ITF_NUM_CDC = 0 , +- ITF_NUM_CDC_DATA , +- ITF_NUM_MSC , ++ ITF_NUM_MSC = 0 , + ITF_NUM_TOTAL + }; + +-uint8_t desc_configuration_cdc_msc[] = ++uint8_t const desc_configuration_msc[] = + { + // Interface count, string index, total length, attribute, power in mA +- TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN, 0, 100), +- +- // Interface number, string index, EP notification address and size, EP data address (out, in) and size. +- TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, STRID_CDC, 0x81, 8, 0x02, 0x82, 64), ++ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUD_CONFIG_DESC_LEN + TUD_MSC_DESC_LEN, 0, 100), + + // Interface number, string index, EP Out & EP In address, EP size +- TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC, 0x03, 0x83, 64), +-}; +- +-uint8_t desc_configuration_cdc_only[] = +-{ +- // Interface count, string index, total length, attribute, power in mA +- TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL-1, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN, 0, 100), +- +- // Interface number, string index, EP notification address and size, EP data address (out, in) and size. +- TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, STRID_CDC, 0x81, 8, 0x02, 0x82, 64), ++ TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC, 0x01, 0x81, 64), + }; + + +@@ -112,20 +93,11 @@ uint8_t desc_configuration_cdc_only[] = + uint8_t const * tud_descriptor_configuration_cb(uint8_t index) + { + (void) index; // for multiple configurations +- return _cdc_only ? desc_configuration_cdc_only : desc_configuration_cdc_msc; ++ return desc_configuration_msc; + } + +-// Enumerate as CDC + MSC or CDC only +-void usb_desc_init(bool cdc_only) ++void usb_desc_init(void) + { +- _cdc_only = cdc_only; +- +- if ( cdc_only ) +- { +- // Change PID to CDC only +- desc_device.idProduct = USB_DESC_CDC_ONLY_PID; +- } +- + // Create Serial string descriptor + uint8_t const* device_id = (uint8_t const*) &NRF_FICR->DEVICEID; + +@@ -153,8 +125,7 @@ char const* string_desc_arr [] = + BLEDIS_MANUFACTURER, // 1: Manufacturer + BLEDIS_MODEL, // 2: Product + desc_str_serial, // 3: Serials, should use chip ID +- "nRF Serial", // 4: CDC Interface +- "nRF UF2", // 5: MSC Interface ++ "nRF UF2", // 4: MSC Interface + }; + + // up to 64 unicode characters +diff --git a/src/usb/usb_desc.h b/src/usb/usb_desc.h +index 3b318c2..df4d070 100644 +--- a/src/usb/usb_desc.h ++++ b/src/usb/usb_desc.h +@@ -28,6 +28,6 @@ + #include "tusb.h" + #include "boards.h" + +-void usb_desc_init(bool cdc_only); ++void usb_desc_init(void); + + #endif /* USB_DESC_H_ */ diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0003-no-readback.patch b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0003-no-readback.patch new file mode 100644 index 0000000..c470b98 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0003-no-readback.patch @@ -0,0 +1,113 @@ +diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c +index d748904..7f1bbab 100644 +--- a/src/usb/uf2/ghostfat.c ++++ b/src/usb/uf2/ghostfat.c +@@ -133,12 +133,11 @@ const char indexFile[] = + "" + "\n"; + ++// No CURRENT.UF2: the drive never serves flash back. The two text files are all it ++// holds; every other sector reads as zeros. + static struct TextFile const info[] = { + {.name = "INFO_UF2TXT", .content = infoUf2File}, + {.name = "INDEX HTM", .content = indexFile}, +- +- // current.uf2 must be the last element and its content must be NULL +- {.name = "CURRENT UF2", .content = NULL}, + }; + STATIC_ASSERT(ARRAY_SIZE(infoUf2File) < BPB_SECTOR_SIZE); // GhostFAT requires files to fit in one sector + STATIC_ASSERT(ARRAY_SIZE(indexFile) < BPB_SECTOR_SIZE); // GhostFAT requires files to fit in one sector +@@ -164,17 +163,6 @@ STATIC_ASSERT( CLUSTER_COUNT >= 0x1015 && CLUSTER_COUNT < 0xFFD5 ); + + + #define UF2_FIRMWARE_BYTES_PER_SECTOR 256 +-#define TRUE_USER_FLASH_SIZE (USER_FLASH_END-USER_FLASH_START) +-STATIC_ASSERT(TRUE_USER_FLASH_SIZE % UF2_FIRMWARE_BYTES_PER_SECTOR == 0); // UF2 requirement -- overall size must be integral multiple of per-sector payload? +- +-#define UF2_SECTORS ( (TRUE_USER_FLASH_SIZE / UF2_FIRMWARE_BYTES_PER_SECTOR) + \ +- ((TRUE_USER_FLASH_SIZE % UF2_FIRMWARE_BYTES_PER_SECTOR) ? 1 : 0)) +-#define UF2_SIZE (UF2_SECTORS * BPB_SECTOR_SIZE) +- +-STATIC_ASSERT(UF2_SECTORS == ((UF2_SIZE/2) / 256)); // Not a requirement ... ensuring replacement of literal value is not a change +- +-#define UF2_FIRST_SECTOR ((NUM_FILES + 1) * BPB_SECTORS_PER_CLUSTER) // WARNING -- code presumes each non-UF2 file content fits in single sector +-#define UF2_LAST_SECTOR ((UF2_FIRST_SECTOR + UF2_SECTORS - 1) * BPB_SECTORS_PER_CLUSTER) + + #define FS_START_FAT0_SECTOR BPB_RESERVED_SECTORS + #define FS_START_FAT1_SECTOR (FS_START_FAT0_SECTOR + BPB_SECTORS_PER_FAT) +@@ -282,7 +270,7 @@ void uf2_init(void) + } + + /*------------------------------------------------------------------*/ +-/* Read CURRENT.UF2 ++/* Read the drive: boot block, FAT, root directory, the text files + *------------------------------------------------------------------*/ + void padded_memcpy (char *dst, char const *src, int len) + { +@@ -315,19 +303,13 @@ void read_block(uint32_t block_no, uint8_t *data) { + if (sectionIdx == 0) { + // first FAT entry must match BPB MediaDescriptor + data[0] = BPB_MEDIA_DESCRIPTOR_BYTE; +- // WARNING -- code presumes only one NULL .content for .UF2 file +- // and all non-NULL .content fit in one sector +- // and requires it be the last element of the array ++ // The two reserved entries, then one end-of-chain cluster per file: ++ // every file fits in one sector + uint32_t const end = (NUM_FILES * FAT_ENTRY_SIZE) + (2 * FAT_ENTRY_SIZE); + for (uint32_t i = 1; i < end; ++i) { + data[i] = 0xff; + } + } +- for (uint32_t i = 0; i < FAT_ENTRIES_PER_SECTOR; ++i) { // Generate the FAT chain for the firmware "file" +- uint32_t v = (sectionIdx * FAT_ENTRIES_PER_SECTOR) + i; +- if (UF2_FIRST_SECTOR <= v && v <= UF2_LAST_SECTOR) +- ((uint16_t *)(void *)data)[i] = v == UF2_LAST_SECTOR ? 0xffff : v + 1; +- } + } else if (block_no < FS_START_CLUSTERS_SECTOR) { // Requested root directory sector + + sectionIdx -= FS_START_ROOTDIR_SECTOR; +@@ -346,7 +328,7 @@ void read_block(uint32_t block_no, uint8_t *data) { + remainingEntries > 0 && i < NUM_FILES; + i++, d++) { + +- // WARNING -- code presumes all but last file take exactly one sector ++ // every file takes exactly one sector + uint16_t startCluster = i + 2; + + struct TextFile const * inf = &info[i]; +@@ -360,31 +342,17 @@ void read_block(uint32_t block_no, uint8_t *data) { + d->updateTime = __DOSTIME__; + d->updateDate = __DOSDATE__; + d->startCluster = startCluster & 0xFFFF; +- d->size = (inf->content ? strlen(inf->content) : UF2_SIZE); ++ d->size = strlen(inf->content); + } + + } else if (block_no < BPB_TOTAL_SECTORS) { + + sectionIdx -= FS_START_CLUSTERS_SECTOR; +- if (sectionIdx < NUM_FILES - 1) { ++ if (sectionIdx < NUM_FILES) { + memcpy(data, info[sectionIdx].content, strlen(info[sectionIdx].content)); +- } else { // generate the UF2 file data on-the-fly +- sectionIdx -= NUM_FILES - 1; +- uint32_t addr = USER_FLASH_START + (sectionIdx * UF2_FIRMWARE_BYTES_PER_SECTOR); +- if (addr < CFG_UF2_FLASH_SIZE) { +- UF2_Block *bl = (void *)data; +- bl->magicStart0 = UF2_MAGIC_START0; +- bl->magicStart1 = UF2_MAGIC_START1; +- bl->magicEnd = UF2_MAGIC_END; +- bl->blockNo = sectionIdx; +- bl->numBlocks = UF2_SECTORS; +- bl->targetAddr = addr; +- bl->payloadSize = UF2_FIRMWARE_BYTES_PER_SECTOR; +- bl->flags = UF2_FLAG_FAMILYID; +- bl->familyID = CFG_UF2_BOARD_APP_ID; +- memcpy(bl->data, (void *)addr, bl->payloadSize); +- } + } ++ // Past the files: zeros. Upstream generated CURRENT.UF2 here from any address ++ // under 1 MiB - the application, the vault, the bootloader and its settings. + + } + } diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0004-write-window.patch b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0004-write-window.patch new file mode 100644 index 0000000..4e00b9d --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0004-write-window.patch @@ -0,0 +1,21 @@ +diff --git a/src/usb/uf2/uf2cfg.h b/src/usb/uf2/uf2cfg.h +index e5a6398..41a7309 100644 +--- a/src/usb/uf2/uf2cfg.h ++++ b/src/usb/uf2/uf2cfg.h +@@ -21,9 +21,14 @@ + #define CFG_UF2_FLASH_SIZE (512*1024) // 512 kB + #endif + +-// Application Address Space ++// Application Address Space: the board's window, not everything below the bootloader. ++// A UF2 block outside it is never written. A bootloader self-update is staged at the ++// top of this window (BOOTLOADER_ADDR_NEW_RECIEVED below), so the application is ++// flashed again after one. + #define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex +-#define USER_FLASH_END (BOOTLOADER_REGION_START - DFU_APP_DATA_RESERVED) ++#define USER_FLASH_END BOARD_APP_FLASH_END ++STATIC_ASSERT(USER_FLASH_END <= BOOTLOADER_REGION_START); ++STATIC_ASSERT(USER_FLASH_END - DFU_BL_IMAGE_MAX_SIZE >= USER_FLASH_START); + + // Bootloader start address + #define BOOTLOADER_ADDR_START BOOTLOADER_REGION_START From a8b50cd809bbce3cbe97b8eeb1ed1bab7d7cf78e Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 10:53:49 +0300 Subject: [PATCH 04/33] Sign every image the UF2 bootloader fork runs or copies - src/signature.c: Monocypher's Ed25519 check with the message streamed from flash (slot header, then the image in 4 KiB pieces, watchdog fed). - 0005: the app runs only if its signature verifies, checked once each boot with nothing written before the jump; DFU mode ends in a reset; a bootloader update is copied only if signed; the jump is always 0x1000, no SoftDevice is looked for; INFO_UF2.TXT names the key. - test/run.sh, before every build: signature.c for Cortex-M4 under qemu-arm, 17 openssl-signed cases, streamed vs one-shot agreement. - sign.sh + signed_image.py: sign, verify, wrap into a UF2; a test-key bootloader is signed only with ALLOW_TEST_KEY=1. - The build needs bootloader/signing-key.pem or BOOTLOADER_TEST_KEY. - memory.x ends the firmware at 0x96000 for the slot; image unchanged. - roadmap: the key's second home is a .vkb that restores onto the C6; the key is an item on the nRF, backed up right after it is made. - Version 0.9.2-vkey.3. Not run on a board yet (milestone 4). --- CLAUDE.md | 9 +- docs2/roadmap.md | 89 +++- .../nrf52840-mdk-dongle/bootloader/Dockerfile | 11 +- .../bootloader/board/board.h | 4 + .../nrf52840-mdk-dongle/bootloader/build.sh | 50 ++- .../patches/0005-signed-images.patch | 391 ++++++++++++++++++ .../nrf52840-mdk-dongle/bootloader/sign.sh | 37 ++ .../bootloader/signed_image.py | 109 +++++ .../bootloader/src/signature.c | 75 ++++ .../bootloader/src/signature.h | 35 ++ .../bootloader/test/cases.py | 125 ++++++ .../bootloader/test/run.sh | 26 ++ .../bootloader/test/verify.c | 53 +++ firmware/boards/nrf52840-mdk-dongle/memory.x | 14 +- .../boards/nrf52840-mdk-dongle/src/main.rs | 6 +- tools/build-bootloader.sh | 23 +- 16 files changed, 1019 insertions(+), 38 deletions(-) create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0005-signed-images.patch create mode 100755 firmware/boards/nrf52840-mdk-dongle/bootloader/sign.sh create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/signed_image.py create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/src/signature.c create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/src/signature.h create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/test/cases.py create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/test/run.sh create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/test/verify.c diff --git a/CLAUDE.md b/CLAUDE.md index a612222..8dcbd47 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -317,9 +317,12 @@ folder: upstream Adafruit_nRF52_Bootloader at a pinned commit, the board definit back from the factory binary, a patch series, a pinned Arm toolchain, all in Docker. `bootloader/check.py` fails the build on a UICR address in the code - as a word, an immediate or a movw/movt pair; like the radio search, not one computed from another base -plus an offset. Until the fork is -complete the outputs stay in a temporary directory, and installing it is never part of a -build (`docs2/roadmap.md`, phase 3). +plus an offset. The fork runs only images signed with one Ed25519 key, checked on every +boot (`bootloader/src/signature.c`, tested under qemu-arm by `bootloader/test/run.sh` +before every build); `bootloader/sign.sh` makes the signed UF2. The build needs +`bootloader/signing-key.pem`, or `BOOTLOADER_TEST_KEY` for a build that names itself a +test build. Until the fork is installable the outputs stay in a temporary directory, and +installing it is never part of a build (`docs2/roadmap.md`, phase 3). Compilation is the **only** exception to the check rule. Linters, formatters, tests and static analysers are not run without a direct request: git hooks in `.githooks/` diff --git a/docs2/roadmap.md b/docs2/roadmap.md index eb75dc2..6e331a6 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -175,8 +175,10 @@ Constraints that come with it: the app is flashed again after a bootloader update. - **The signing key must exist in two places.** Once everything moves here, a broken app leaves the board in the bootloader waiting for a signed image. If the only copy of the key - is on this board, nothing can sign it. Before the key is generated, decide its second home: - the wiped C6 as the signing device, or a `.vkb` that restores onto it. + is on this board, nothing can sign it. Decided 2026-10-14: the second home is a `.vkb` + that restores onto the C6, which is the test board, not a signing device. The key is an + item on this board, made with a `.vkb` right after; a wipe test here (phase 3 + acceptance) is followed by a restore. - ~~**The page at 0xFD800**~~ is the CF2 config page (`.bootloaderConfig`, 88 B: board ID, family, flash and RAM size), part of the bootloader image inside the 40 KiB that `COPY_BL` copies. `check.py` pins it to the factory's words. The code region is 0xF4000..0xFD800. @@ -226,7 +228,77 @@ Milestones, one commit each: 3. The signed trailer, with length and version inside the signed bytes, checked on every boot; the host signing tool. The signature scheme is chosen by measuring the code size and boot time of each verify-only candidate. -4. The on-device test as an application. + + **Measured 2026-10-14.** Each verify-only path was compiled `-Os` for Cortex-M4. For + speed, qemu-arm counted the instructions of one verify of a real openssl signature over + 1 KiB: + + | Candidate | Code | Instructions | At 64 MHz (≈1.3 CPI) | + |---|---|---|---| + | Monocypher 4.0.2, Ed25519 (SHA-512) | 10.5 KiB | 1.8 M | ≈ 40 ms | + | micro-ecc 1.1, P-256 + SHA-256 | 4.4 KiB | 7.6 M | ≈ 150 ms | + | compact25519, Ed25519 | 4.9 KiB | 90 M | ≈ 1.8 s | + + **Chosen: Monocypher Ed25519.** It is the fastest of the three, and the scheme is the + RFC 8032 one that openssl signs and `ed25519-dalek` in the CLI already verifies. + Hashing costs ≈113 instructions a byte: ≈0.2 s a boot for today's 77 KiB image, ≈0.7 s + for a 300 KiB one with Trussed. A SHA-256 pre-hash would be 1.6× faster to hash, but it + puts a second hash function in the bootloader, so plain Ed25519 it is. + + **Format.** One signature slot per image, the first 256 bytes of a page that the image + never reaches: + - for the app at 0x96000, so the app must end by 0x96000 and `memory.x` loses a page; + - for a bootloader update at 0xFDF00, the end of its CF2 page. + + The slot holds magic `VKS1`, kind (1 app, 2 bootloader), version, length, then the + signature over `slot[0..64] || image[0..length]`. The bootloader checks it on every + boot, streaming SHA-512 over the slot header and the flash, so a torn or unsigned + upload never runs and no "valid" flag is trusted. It checks a bootloader update in + staging before `COPY_BL`; there the length must cover the whole region up to the slot. + A bootloader update lands its staging on the app's slot, so the app is flashed again + after one. The public key is compiled in. The build fails without it, and + `INFO_UF2.TXT` shows its fingerprint, so a test-key build cannot pass for a real one. + + **Built and tested 2026-10-14 with a throwaway key; not run on a board.** + - **`src/signature.c`.** Monocypher's own `crypto_ed25519_check`, with the message + streamed: the slot header, then the image from flash in 4 KiB pieces, with the + watchdog fed between them. + - **`patches/0005-signed-images`:** + - the app is valid only if its signature verifies, checked on every boot, once, with + nothing written between the check and the jump; + - DFU mode always ends in a reset; + - a bootloader update is copied only if signed; + - the jump address is always 0x1000, and no SoftDevice is looked for; + - `INFO_UF2.TXT` names the key. + - **`test/run.sh`, run before every build.** It compiles `signature.c` for Cortex-M4 + and runs it under qemu-arm on 17 openssl-signed cases: valid app and bootloader; + a flipped bit in header, image, R or s; wrong key; s + L; wrong kind; length + edges; reserved or tail bytes. The streamed check must agree with the one-shot one, + and a deliberately wrong expectation does fail. + - **Size and stack.** 28 384 B of code, 10.5 KiB to spare. Stack on the verify path + ≈1.8 KiB of the 8 KiB reserved. + - **Signing.** `sign.sh` signs with openssl, checks the signature before writing, and + wraps the image and slot into a UF2. By the factory bootloader's code it accepts that + UF2 too, the slot being ordinary app space to it; not tried yet. It refuses to sign + a bootloader that trusts a test key unless `ALLOW_TEST_KEY=1`. `memory.x` now ends + the firmware at 0x96000; its image did not change. + - **The build refuses to run without `bootloader/signing-key.pem`.** A test build + names its key with `BOOTLOADER_TEST_KEY`, and `INFO_UF2.TXT` then says "TEST KEY". +4. The on-device test as an application. The plan: + - a build flag (`VKEY_AS_APP=1`) in the same patch series, not separate code; + - linked at 0x1000, `COPY_BL` compiled out; + - its write window and verify target on a scratch area (0x40000..0x80000), clear of + itself; + - marked a test build in its INFO text. + + With no serial port the drive is the only output, so it writes its results into + `INFO_UF2.TXT`: + - accept or refuse on a real-pipeline signed app, an altered one and a signed + self-update image; + - DWT cycle counts for a boot verify, turning the qemu estimate into a measurement on + the chip. + + The factory bootloader stays in place throughout, so this milestone is reversible. Install needs its own go and a checklist: @@ -240,8 +312,14 @@ Install needs its own go and a checklist: - the MBR: the update carries Nordic's MBR 2.4.1 and a whole settings page. Read in the update handler what happens to those blocks, and compare the chip's own MBR (the app can read 0x0..0xB00) with 2.4.1; -- a signed app already on the board; -- the key reachable from two places. +- the key reachable from two places, and `signing-key.pem` committed with its + fingerprint recorded here; +- the bootloader being installed names that fingerprint in its INFO text, not "TEST KEY" + (`sign.sh` refuses a test-key bootloader unless told); +- the order: first copy the signed app (real key) through the factory bootloader and + confirm it boots under it. Then install the fork, and the board must boot straight + into that app. If it stays in DFU mode instead, copying the signed app UF2 again is + the next step. **The risk, stated plainly.** A bug in the new bootloader leaves a board no USB tool can reach. Without a probe that is a new dongle. That is acceptable only because the board @@ -334,6 +412,7 @@ Acceptance: registration and login on webauthn.io and with `fido2-token`; `pam_u | Phase 0 | ~~the audit exception for RUSTSEC-2026-0344~~ - done 2026-10-13 | | Phase 2 | ~~if the chip is older than revision 3: accept the glitch risk or keep the important secrets on the C6~~ - revision 2; everything moves here, risk accepted (2026-10-13) | | Phase 3 | ~~own bootloader instead of the Nordic secure bootloader~~ - own fork chosen (2026-10-13); installing it still needs its own go | +| Phase 3 | ~~the signing key's second home~~ - a `.vkb` that restores onto the C6; the C6 is the test board, everything else is on the nRF (2026-10-14) | | Phase 5 | chip key option A or B; wiping the C6 after migration | | Phase 6 | RTIC or Embassy, and the `unsafe` rule if the runtime needs it | diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile b/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile index a0944bd..06fecb6 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile @@ -12,8 +12,15 @@ ARG TOOLCHAIN_SHA256=12a2815644318ebcceaf84beabb665d0924b6e79e21048452c5331a5633 ARG UPSTREAM=https://github.com/adafruit/Adafruit_nRF52_Bootloader.git ARG COMMIT=eefbe6bda98b80cb296e2f1bb1c982d58fe4c12d +# Monocypher 4.0.2 for the signature check: Ed25519 (RFC 8032) from monocypher.c and +# optional/monocypher-ed25519.c, CC0/BSD-2. +ARG MONOCYPHER=https://github.com/LoupVaillant/Monocypher.git +ARG MONOCYPHER_COMMIT=0d85f98c9d9b0227e42cf795cb527dff372b40a4 + +# qemu-user and openssl run test/run.sh: the signature check, compiled for the same +# core, against images openssl signed. RUN apt-get update \ - && apt-get install -y --no-install-recommends ca-certificates curl git make patch python3 python3-intelhex xz-utils \ + && apt-get install -y --no-install-recommends ca-certificates curl git make openssl patch python3 python3-intelhex qemu-user xz-utils \ && rm -rf /var/lib/apt/lists/* RUN curl -fsSL -o /tmp/tc.tar.xz "https://developer.arm.com/-/media/Files/downloads/gnu/12.3.rel1/binrel/$TOOLCHAIN.tar.xz" \ @@ -26,6 +33,8 @@ ENV PATH=/opt/arm/bin:$PATH RUN git clone -q "$UPSTREAM" /src \ && git -C /src checkout -q "$COMMIT" \ && git -C /src submodule update -q --init lib/nrfx lib/tinyusb lib/uf2 \ + && git clone -q "$MONOCYPHER" /src/lib/monocypher \ + && git -C /src/lib/monocypher checkout -q "$MONOCYPHER_COMMIT" \ && chmod -R a+rwX /src \ && git config --system --add safe.directory '*' # The build runs as the host user, so its outputs are the host user's; the tree is diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h index 6e9c9f3..7760d70 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h @@ -70,6 +70,10 @@ *------------------------------------------------------------------*/ #define BOARD_APP_FLASH_END 0x97000 +/* The app's signature slot (src/signature.h): the last page of the window, which the + * app itself never reaches - memory.x ends its FLASH here. */ +#define BOARD_APP_SLOT (BOARD_APP_FLASH_END - 0x1000) + #define UF2_PRODUCT_NAME "Makerdiary nRF52840 MDK USB Dongle" #define UF2_VOLUME_LABEL "UF2BOOT " #define UF2_BOARD_ID "nRF52840-MDK-USB-DONGLE" diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh index fe7da66..5791434 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh @@ -1,13 +1,13 @@ #!/bin/sh # # Runs inside the image built from Dockerfile, started by tools/build-bootloader.sh: -# /work/in is this folder (read-only), /work/out receives +# /work/in is this folder (read-only), /work/key.pem the Ed25519 public key the +# bootloader will trust, KEY_KIND `real` or `test`. /work/out receives # -# bootloader.hex the bootloader, with Nordic's MBR (what a probe would write) -# update-bootloader.uf2 the same as a self-update UF2 (family 0xD663823C) -# bootloader.bin the bootloader region alone, from 0xF4000, for check.py -# bootloader.dis its disassembly, for check.py -# systeminit.txt SystemInit disassembled, read before any install +# bootloader.bin the bootloader region from 0xF4000 (code, then the CF2 page): what +# the signing step signs and wraps into the self-update UF2 +# bootloader.dis its disassembly, for check.py +# systeminit.txt SystemInit disassembled, read before any install # # The tree is the image's pristine upstream checkout, so every run starts from the same # sources. The version and the build date are fixed, so the same inputs give the same @@ -19,18 +19,38 @@ BOARD=nrf52840_mdk_usb_dongle # Upstream's version, then the fork's revision, bumped with every change to this folder: # with no probe, INFO_UF2.TXT on the drive is the only way to tell which build a board # runs. The Makefile takes the bootloader version number from the part before "-". -VERSION=0.9.2-vkey.2 +VERSION=0.9.2-vkey.3 # What `git submodule status` reports for the pinned commits today, as the factory # 0.7.1 bootloader reports it too. Fixed here because the uf2 part names an upstream # branch, and a fresh clone after that branch moves would change the INFO text. SUBMODULES="lib/nrfx (v2.0.0) lib/tinyusb (0.12.0-145-g9775e7691) lib/uf2 (remotes/origin/configupdate-9-gadbb8c7)" +# The signature check first, on its own: a check that refuses valid images makes a +# board that can never be updated again. +sh /work/in/test/run.sh + +# The key, compiled in. Its fingerprint goes into INFO_UF2.TXT, and a test key says so +# there, so a test build cannot pass for a real one on a board with no probe. +openssl pkey -pubin -in /work/key.pem -noout -text 2>/dev/null | grep -q '^ED25519 Public-Key' \ + || { echo "/work/key.pem is not an Ed25519 public key" >&2; exit 1; } +raw="$(openssl pkey -pubin -in /work/key.pem -outform DER | tail -c 32 | od -An -v -tu1 | tr -s ' \n' ',' | sed 's/^,//; s/,$//')" +fingerprint="$(openssl pkey -pubin -in /work/key.pem -outform DER | tail -c 32 | sha256sum | cut -c1-16)" +case "$KEY_KIND" in + real) ;; + test) fingerprint="$fingerprint TEST KEY" ;; + *) echo "KEY_KIND is real or test, not '$KEY_KIND'" >&2; exit 1 ;; +esac + cd /src mkdir -p "src/boards/$BOARD" cp /work/in/board/board.h /work/in/board/board.mk "src/boards/$BOARD/" # The CF2 block (board ID = VID:PID, family, flash and RAM size) is generic; upstream's # copy for this dongle is the one the factory build carries. cp src/boards/mdk_nrf52840_dongle/pinconfig.c "src/boards/$BOARD/" +cp /work/in/src/signature.c /work/in/src/signature.h src/ +printf '#define SIGNING_PUBLIC_KEY_BYTES {%s}\n#define SIGNING_KEY_FINGERPRINT "%s"\n' \ + "$raw" "$fingerprint" > src/signing_key.h + # GNU patch, not git apply: editors and hooks strip the lone space of a blank context # line, which git apply rejects. --fuzz=0 still demands every context line match. Some # upstream files have CRLF endings and the patches are LF, so a file is made LF before @@ -44,17 +64,15 @@ done SOURCE_DATE_EPOCH="$(git log -1 --format=%ct)" export SOURCE_DATE_EPOCH -out="_build/build-$BOARD/${BOARD}_bootloader-$VERSION" -make -s BOARD="$BOARD" GIT_VERSION="$VERSION" GIT_SUBMODULE_VERSIONS="$SUBMODULES" \ - "${out}_nosd.hex" "_build/build-$BOARD/update-${BOARD}_bootloader-${VERSION}_nosd.uf2" +out="_build/build-$BOARD/${BOARD}_bootloader-$VERSION.out" +make -s BOARD="$BOARD" GIT_VERSION="$VERSION" GIT_SUBMODULE_VERSIONS="$SUBMODULES" "$out" -cp "${out}_nosd.hex" /work/out/bootloader.hex -cp "_build/build-$BOARD/update-${BOARD}_bootloader-${VERSION}_nosd.uf2" /work/out/update-bootloader.uf2 # The two UICR words (bootloader and MBR-params addresses, already on the chip) are # programmer data, not code; left in, the binary would span up to 0x10001018. arm-none-eabi-objcopy -O binary -R .uicrBootStartAddress -R .uicrMbrParamsPageAddress \ - "$out.out" /work/out/bootloader.bin -arm-none-eabi-objdump -d --disassemble=SystemInit "$out.out" > /work/out/systeminit.txt -arm-none-eabi-objdump -d --no-show-raw-insn "$out.out" > /work/out/bootloader.dis -arm-none-eabi-size "$out.out" + "$out" /work/out/bootloader.bin +arm-none-eabi-objdump -d --disassemble=SystemInit "$out" > /work/out/systeminit.txt +arm-none-eabi-objdump -d --no-show-raw-insn "$out" > /work/out/bootloader.dis +arm-none-eabi-size "$out" python3 /work/in/check.py /work/out/bootloader.bin /work/out/bootloader.dis +echo "key: $fingerprint" diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0005-signed-images.patch b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0005-signed-images.patch new file mode 100644 index 0000000..41b4688 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0005-signed-images.patch @@ -0,0 +1,391 @@ +diff --git a/Makefile b/Makefile +index 625a1c8..27710bf 100644 +--- a/Makefile ++++ b/Makefile +@@ -137,6 +137,13 @@ C_SRC += \ + # all files in boards + C_SRC += src/boards/boards.c + ++# The signature check every image passes before it runs or is copied: src/signature.c ++# over Monocypher's Ed25519 ++C_SRC += src/signature.c ++C_SRC += lib/monocypher/src/monocypher.c ++C_SRC += lib/monocypher/src/optional/monocypher-ed25519.c ++IPATH += lib/monocypher/src lib/monocypher/src/optional ++ + # nrfx + C_SRC += $(NRFX_PATH)/drivers/src/nrfx_power.c + C_SRC += $(NRFX_PATH)/drivers/src/nrfx_nvmc.c +diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +index fe321ce..97a4999 100644 +--- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c ++++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +@@ -31,6 +31,7 @@ + #include "app_timer.h" + + #include "boards.h" ++#include "signature.h" + + #ifdef NRF_USBD + #include "tusb.h" +@@ -138,40 +139,12 @@ static void wait_for_events(void) + } + + ++// Valid means signed, checked now, on every boot: a torn or unsigned upload never runs, ++// and no "valid" flag in the settings page is trusted. + bool bootloader_app_is_valid(void) + { +- bool success = false; +- uint32_t const app_addr = DFU_BANK_0_REGION_START; +- +- bootloader_settings_t const *p_bootloader_settings; +- bootloader_util_settings_get(&p_bootloader_settings); +- +- enum { EMPTY_FLASH = 0xFFFFFFFFUL }; +- +- // Application is invalid if first 2 words are all 0xFFFFFFF +- if ( *((uint32_t *)app_addr ) == EMPTY_FLASH && +- *((uint32_t *)(app_addr+4)) == EMPTY_FLASH ) +- { +- return false; +- } +- +- // The application in CODE region 1 is flagged as valid during update. +- if ( p_bootloader_settings->bank_0 == BANK_VALID_APP ) +- { +- uint16_t image_crc = 0; +- +- // A stored crc value of 0 indicates that CRC checking is not used. +- if ( p_bootloader_settings->bank_0_crc != 0 ) +- { +- image_crc = crc16_compute((uint8_t*) app_addr, +- p_bootloader_settings->bank_0_size, +- NULL); +- } +- +- success = (image_crc == p_bootloader_settings->bank_0_crc); +- } +- +- return success; ++ return signature_valid((uint8_t const *) MBR_SIZE, (uint8_t const *) BOARD_APP_SLOT, ++ SIGNATURE_KIND_APP, BOARD_APP_SLOT - MBR_SIZE, false); + } + + +@@ -256,29 +229,17 @@ void bootloader_app_start(void) + NVIC->ICPR[1]=0xFFFFFFFF; + #endif + +- uint32_t fwd_ret; +- uint32_t app_addr; +- +- if ( is_sd_existed() ) ++ // The app starts right after the MBR, always: there is no SoftDevice on this board, ++ // and asking the app region whether there is one would let unsigned bytes pick the ++ // address jumped to. ++ uint32_t const app_addr = MBR_SIZE; ++ sd_mbr_command_t command = + { +- PRINTF("SoftDevice exist\r\n"); +- // App starts after SoftDevice +- app_addr = SD_SIZE_GET(MBR_SIZE); +- fwd_ret = sd_softdevice_vector_table_base_set(app_addr); +- }else +- { +- PRINTF("SoftDevice not exist\r\n"); +- +- // App starts right after MBR +- app_addr = MBR_SIZE; +- sd_mbr_command_t command = +- { +- .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, +- .params.irq_forward_address_set.address = app_addr, +- }; ++ .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, ++ .params.irq_forward_address_set.address = app_addr, ++ }; + +- fwd_ret = sd_mbr_command(&command); +- } ++ uint32_t const fwd_ret = sd_mbr_command(&command); + + // unlikely failed to forward vector table, manually set forward address + if ( fwd_ret != NRF_SUCCESS ) +diff --git a/src/main.c b/src/main.c +index c72cf43..050c27a 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -108,15 +108,7 @@ extern void tusb_hal_nrf_power_event(uint32_t event); + //--------------------------------------------------------------------+ + // + //--------------------------------------------------------------------+ +-static void check_dfu_mode(void); +- +-// The SoftDevice must only be initialized if a chip reset has occurred. +-// Soft reset (jump ) from application must not reinitialize the SoftDevice. +-static void mbr_init_sd(void) { +- PRINTF("SD_MBR_COMMAND_INIT_SD\r\n"); +- sd_mbr_command_t com = {.command = SD_MBR_COMMAND_INIT_SD}; +- sd_mbr_command(&com); +-} ++static void dfu_mode(bool asked_by_app); + + //--------------------------------------------------------------------+ + // +@@ -136,59 +128,38 @@ int main(void) { + PRINTF("Bootloader Start\r\n"); + led_state(STATE_BOOTLOADER_STARTED); + +- // Check all inputs and enter DFU if needed +- // Return when DFU process is complete (or not entered at all) +- check_dfu_mode(); +- +- // Reset peripherals +- board_teardown(); +- +- /* Jump to application if valid +- * "Master Boot Record and SoftDevice initializaton procedure" +- * - SD_MBR_COMMAND_INIT_SD (if not already) +- * - sd_softdevice_disable() +- * - sd_softdevice_vector_table_base_set(APP_ADDR) +- * - jump to App reset +- */ +- if (bootloader_app_is_valid()) { +- PRINTF("App is valid\r\n"); +- if (is_sd_existed()) { +- // MBR forward IRQ to SD +- mbr_init_sd(); +- +- // Make sure SD is disabled +- sd_softdevice_disable(); +- } +- +- // start application +- bootloader_app_start(); +- } +- +- NVIC_SystemReset(); +-} +- +-static void check_dfu_mode(void) { + // The application asked for DFU mode: clear the request, so the next reset boots it + bool const uf2_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET); + if (uf2_dfu) NRF_POWER->GPREGRET = 0; + +- bool const dfu_start = uf2_dfu || button_pressed(BUTTON_DFU); +- bool const valid_app = bootloader_app_is_valid(); ++ // The signature is checked once, here, and nothing writes flash between this check ++ // and the jump below. DFU mode writes flash, so it always ends in a reset, and the ++ // next boot checks again. ++ if (uf2_dfu || button_pressed(BUTTON_DFU) || !bootloader_app_is_valid()) { ++ dfu_mode(uf2_dfu); ++ NVIC_SystemReset(); ++ } + +- if (dfu_start || !valid_app) { +- led_state(STATE_USB_UNMOUNTED); +- usb_init(); ++ // Reset peripherals, then the application (no SoftDevice on this board) ++ board_teardown(); ++ bootloader_app_start(); + +- if (uf2_dfu) { +- // If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app. +- bootloader_dfu_start(3000, true); +- } else { +- // No timeout when a person asked (the button) or there is nothing valid to boot. +- bootloader_dfu_start(0, false); +- } ++ NVIC_SystemReset(); ++} ++ ++static void dfu_mode(bool asked_by_app) { ++ led_state(STATE_USB_UNMOUNTED); ++ usb_init(); + +- usb_teardown(); ++ if (asked_by_app) { ++ // If USB is not enumerated in 3s (eg. because we're running on battery), we restart into app. ++ bootloader_dfu_start(3000, true); ++ } else { ++ // No timeout when a person asked (the button) or there is nothing valid to boot. ++ bootloader_dfu_start(0, false); + } ++ ++ usb_teardown(); + } + + //--------------------------------------------------------------------+ +diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c +index 4b6817f..0edd872 100644 +--- a/src/usb/msc_uf2.c ++++ b/src/usb/msc_uf2.c +@@ -28,6 +28,7 @@ + #if CFG_TUD_MSC + + #include "bootloader.h" ++#include "signature.h" + + /*------------------------------------------------------------------*/ + /* MACRO TYPEDEF CONSTANT ENUM +@@ -198,11 +199,20 @@ void tud_msc_write10_complete_cb(uint8_t lun) + + // Location of current stored new bootloader + uint32_t * new_bootloader = (uint32_t *) BOOTLOADER_ADDR_NEW_RECIEVED; ++ uint8_t const * staged = (uint8_t const *) new_bootloader; ++ uint32_t const signed_length = DFU_BL_IMAGE_MAX_SIZE - SIGNATURE_SLOT_SIZE; + + PRINT_HEX(new_bootloader); + ++ // Copied only if signed under the key this bootloader carries, over everything ++ // the MBR copies but the slot; the slot's own unsigned tail must be erased. ++ if ( !signature_valid(staged, staged + signed_length, SIGNATURE_KIND_BOOTLOADER, ++ signed_length, true) ) ++ { ++ PRINTF("bootloader update is not signed\r\n"); ++ } + // skip if there is no bootloader change +- if ( memcmp(new_bootloader, (uint8_t*) BOOTLOADER_ADDR_START, DFU_BL_IMAGE_MAX_SIZE) ) ++ else if ( memcmp(new_bootloader, (uint8_t*) BOOTLOADER_ADDR_START, DFU_BL_IMAGE_MAX_SIZE) ) + { + PRINTF("Coyping new bootloader\r\n"); + +diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c +index 7f1bbab..dc00338 100644 +--- a/src/usb/uf2/ghostfat.c ++++ b/src/usb/uf2/ghostfat.c +@@ -35,6 +35,7 @@ + + #include "bootloader_settings.h" + #include "bootloader.h" ++#include "signing_key.h" + + //--------------------------------------------------------------------+ + // +@@ -117,11 +118,14 @@ STATIC_ASSERT(FAT_ENTRIES_PER_SECTOR == 256); // FAT + #define STR0(x) #x + #define STR(x) STR0(x) + +-char infoUf2File[128*3] = ++// The key's fingerprint tells a board running a test-key build from one running the ++// real key; there is no SoftDevice line, since there is no SoftDevice. ++static char const infoUf2File[] = + "UF2 Bootloader " UF2_VERSION "\r\n" + "Model: " UF2_PRODUCT_NAME "\r\n" + "Board-ID: " UF2_BOARD_ID "\r\n" +- "Date: " __DATE__ "\r\n"; ++ "Date: " __DATE__ "\r\n" ++ "Key: " SIGNING_KEY_FINGERPRINT "\r\n"; + + const char indexFile[] = + "\n" +@@ -231,43 +235,6 @@ static inline bool in_uicr_space(uint32_t addr) + // + //--------------------------------------------------------------------+ + +-void uf2_init(void) +-{ +- strcat(infoUf2File, "SoftDevice: "); +- +- if ( is_sd_existed() ) +- { +- uint32_t const sd_id = SD_ID_GET(MBR_SIZE); +- uint32_t const sd_version = SD_VERSION_GET(MBR_SIZE); +- +- uint32_t ver[3]; +- ver[0] = sd_version / 1000000; +- ver[1] = (sd_version - ver[0]*1000000)/1000; +- ver[2] = (sd_version - ver[0]*1000000 - ver[1]*1000); +- +- char str[10]; +- utoa(sd_id, str, 10); +- +- strcat(infoUf2File, "S"); +- strcat(infoUf2File, str); +- strcat(infoUf2File, " "); +- +- utoa(ver[0], str, 10); +- strcat(infoUf2File, str); +- strcat(infoUf2File, "."); +- +- utoa(ver[1], str, 10); +- strcat(infoUf2File, str); +- strcat(infoUf2File, "."); +- +- utoa(ver[2], str, 10); +- strcat(infoUf2File, str); +- strcat(infoUf2File, "\r\n"); +- }else +- { +- strcat(infoUf2File, "not found\r\n"); +- } +-} + + /*------------------------------------------------------------------*/ + /* Read the drive: boot block, FAT, root directory, the text files +diff --git a/src/usb/uf2/uf2.h b/src/usb/uf2/uf2.h +index 081280c..8c985ce 100644 +--- a/src/usb/uf2/uf2.h ++++ b/src/usb/uf2/uf2.h +@@ -79,6 +79,5 @@ typedef struct { + uint32_t magicEnd; + } UF2_Block; + +-void uf2_init(void); + + #endif +diff --git a/src/usb/usb.c b/src/usb/usb.c +index c4f6f5c..c1e41f2 100644 +--- a/src/usb/usb.c ++++ b/src/usb/usb.c +@@ -58,32 +58,18 @@ void usb_init(void) { + NVIC_SetPriority(USBD_IRQn, 2); + + // USB power may already be ready at this time -> no event generated +- // We need to invoke the handler based on the status initially +- uint32_t usb_reg; +- uint8_t sd_en = false; ++ // We need to invoke the handler based on the status initially. No SoftDevice on this ++ // board: the power events come from nrfx directly. ++ const nrfx_power_config_t pwr_cfg = {0}; ++ nrfx_power_init(&pwr_cfg); + +- if (is_sd_existed()) { +- sd_softdevice_is_enabled(&sd_en); +- } +- +- if (sd_en) { +- sd_power_usbdetected_enable(true); +- sd_power_usbpwrrdy_enable(true); +- sd_power_usbremoved_enable(true); +- sd_power_usbregstatus_get(&usb_reg); +- } else { +- // Power module init +- const nrfx_power_config_t pwr_cfg = {0}; +- nrfx_power_init(&pwr_cfg); ++ // Register USB power handler ++ const nrfx_power_usbevt_config_t config = {.handler = power_event_handler}; ++ nrfx_power_usbevt_init(&config); + +- // Register USB power handler +- const nrfx_power_usbevt_config_t config = {.handler = power_event_handler}; +- nrfx_power_usbevt_init(&config); ++ nrfx_power_usbevt_enable(); + +- nrfx_power_usbevt_enable(); +- +- usb_reg = NRF_POWER->USBREGSTATUS; +- } ++ uint32_t const usb_reg = NRF_POWER->USBREGSTATUS; + + if (usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk) { + tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED); +@@ -94,7 +80,6 @@ void usb_init(void) { + } + + usb_desc_init(); +- uf2_init(); + tusb_init(); + + #ifdef DISPLAY_PIN_SCK diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/sign.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/sign.sh new file mode 100755 index 0000000..4c5fbce --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/sign.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# +# Sign an image for this board's bootloader fork and wrap it into the UF2 to copy onto +# the UF2BOOT drive: +# +# sign.sh app VERSION images/vaultkey.bin PRIVATE.pem OUT.uf2 +# sign.sh bootloader VERSION bootloader.bin PRIVATE.pem OUT.uf2 +# +# PRIVATE.pem is an Ed25519 private key. tools/sign-vaultkey.sh fetches the real one +# from the vkey into tmpfs and calls this; a test key works the same way, and the +# bootloader built with its public half (BOOTLOADER_TEST_KEY) is the only one that +# accepts the result. The signature is checked against the key's public half before +# the UF2 is written, so a bad signature never reaches a file. + +set -euo pipefail + +[[ $# -eq 5 ]] || { sed -n '3,13p' "$0" >&2; exit 2; } +kind="$1" version="$2" image="$3" key="$4" out="$5" +here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# A bootloader built with a test key trusts a key that lives in a temporary directory. +# Installed, it would freeze the board for good, so it is signed only on purpose. +if [[ "$kind" == bootloader ]] && grep -qa 'TEST KEY' "$image" && [[ "${ALLOW_TEST_KEY:-}" != 1 ]]; then + echo "$image trusts a test key; it is never installed (set ALLOW_TEST_KEY=1 for a test)" >&2 + exit 1 +fi + +work="$(mktemp -d)" +trap 'rm -rf "$work"' EXIT + +python3 -I "$here/signed_image.py" message "$kind" "$version" "$image" "$work/message" +openssl pkeyutl -sign -inkey "$key" -rawin -in "$work/message" -out "$work/signature" +openssl pkey -in "$key" -pubout -out "$work/public.pem" +openssl pkeyutl -verify -pubin -inkey "$work/public.pem" -rawin -in "$work/message" \ + -sigfile "$work/signature" >/dev/null +python3 -I "$here/signed_image.py" uf2 "$kind" "$version" "$image" "$work/signature" "$out" +echo "$kind: $(basename "$out"), signed by $(openssl pkey -pubin -in "$work/public.pem" -outform DER | tail -c 32 | sha256sum | cut -c1-16)" diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/signed_image.py b/firmware/boards/nrf52840-mdk-dongle/bootloader/signed_image.py new file mode 100644 index 0000000..7b895a8 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/signed_image.py @@ -0,0 +1,109 @@ +"""Signed UF2 images for this board's bootloader fork (src/signature.h has the format). + + signed_image.py message KIND VERSION IMAGE OUT + writes what gets signed: the slot header, then the image (a bootloader padded to + its fixed length). Sign it with openssl pkeyutl -sign -rawin. + signed_image.py uf2 KIND VERSION IMAGE SIGNATURE OUT + writes the UF2 to copy to the drive: the image and its slot. + +KIND is `app` (images/vaultkey.bin, flashed from 0x1000) or `bootloader` (the build's +bootloader.bin, from 0xF4000). Only the private key is outside this file: the signature +arrives as a file from whoever holds it. +""" + +import struct +import sys +from pathlib import Path +from typing import NamedTuple + +BLOCK = 256 +MAGIC = 0x31534B56 # "VKS1" +HEADER = 0x40 +SLOT = 0x100 + +UF2_MAGIC = (0x0A324655, 0x9E5D5157, 0x0AB16F30) +UF2_FAMILY_FLAG = 0x2000 + +# The two UICR words a bootloader update must carry: the factory bootloader and this +# fork compare them with their own and refuse anything else. Nothing writes them. +UICR = 0x10001000 +UICR_WORDS = {0x14: 0xF4000, 0x18: 0xFE000} + + +class Kind(NamedTuple): + number: int + base: int # where the image starts in flash + slot: int # where its slot is written + family: int # the UF2 family the bootloader routes it by + exact: bool # signed up to the slot, whatever the image's own size + + +# An app ends before the page that holds its slot. A bootloader fills its region up to +# its slot at the end of the CF2 page, so everything the MBR copies is signed, the +# signature, or erased. +KINDS = { + "app": Kind(1, 0x1000, 0x96000, 0xADA52840, False), + "bootloader": Kind(2, 0xF4000, 0xFDF00, 0xD663823C, True), +} + + +def kind_of(name: str) -> Kind: + if name not in KINDS: + raise SystemExit(f"kind is app or bootloader, not {name!r}") + return KINDS[name] + + +def image_for(k: Kind, raw: bytes) -> bytes: + room = k.slot - k.base + if not raw or len(raw) > room: + raise SystemExit(f"the image is {len(raw)} bytes; 1 to {room} fit before its slot") + return raw.ljust(room, b"\xff") if k.exact else raw + + +def header(k: Kind, version: int, image: bytes) -> bytes: + return struct.pack("<4I", MAGIC, k.number, version, len(image)).ljust(HEADER, b"\0") + + +def uf2(blocks: list[tuple[int, bytes]], family: int) -> bytes: + out = bytearray() + for n, (addr, data) in enumerate(blocks): + assert len(data) == BLOCK and addr % BLOCK == 0 + head = struct.pack("<8I", UF2_MAGIC[0], UF2_MAGIC[1], UF2_FAMILY_FLAG, addr, BLOCK, + n, len(blocks), family) + out += head + data.ljust(476, b"\0") + struct.pack(" bytes: + if len(signature) != 64: + raise SystemExit(f"an Ed25519 signature is 64 bytes, not {len(signature)}") + slot = (header(k, version, image) + signature).ljust(SLOT, b"\xff") + padded = image.ljust(-(-len(image) // BLOCK) * BLOCK, b"\xff") + blocks = [(k.base + i, padded[i:i + BLOCK]) for i in range(0, len(padded), BLOCK)] + blocks.append((k.slot, slot)) + if k.exact: + uicr = bytearray(b"\xff" * BLOCK) + for off, word in UICR_WORDS.items(): + uicr[off:off + 4] = struct.pack(" int: + args = sys.argv[1:] + if len(args) == 5 and args[0] == "message": + k, version = kind_of(args[1]), int(args[2], 0) + image = image_for(k, Path(args[3]).read_bytes()) + Path(args[4]).write_bytes(header(k, version, image) + image) + return 0 + if len(args) == 6 and args[0] == "uf2": + k, version = kind_of(args[1]), int(args[2], 0) + image = image_for(k, Path(args[3]).read_bytes()) + Path(args[5]).write_bytes(build_uf2(k, version, image, Path(args[4]).read_bytes())) + return 0 + print(__doc__, file=sys.stderr) + return 2 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/src/signature.c b/firmware/boards/nrf52840-mdk-dongle/bootloader/src/signature.c new file mode 100644 index 0000000..5457e44 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/src/signature.c @@ -0,0 +1,75 @@ +/* + * The signature check, built from Monocypher's own crypto_ed25519_check: the same + * SHA-512 over R || A || message, reduced and checked with crypto_eddsa_check_equation + * (which also rejects s >= L). Only the message is fed in pieces - the slot header, + * then the image from flash - because the two are not one buffer. + */ + +#include +#include + +#include "monocypher.h" +#include "monocypher-ed25519.h" +#include "signature.h" +#include "signing_key.h" + +/* test/verify.c builds this file for qemu-arm, where there is no watchdog. */ +#ifndef SIGNATURE_QEMU_TEST +#include "nrf_wdt.h" +#endif + +/* signing_key.h, generated by build.sh, holds the key as SIGNING_PUBLIC_KEY_BYTES */ +static uint8_t const SIGNING_PUBLIC_KEY[32] = SIGNING_PUBLIC_KEY_BYTES; + +#define SLOT_MAGIC 0x31534B56u /* "VKS1", little endian */ +#define SLOT_HEADER 0x40 +#define SLOT_SIGNATURE 0x40 +#define SLOT_TAIL 0x80 +#define CHUNK 4096 + +static uint32_t le32(uint8_t const *p) { + return (uint32_t) p[0] | (uint32_t) p[1] << 8 | (uint32_t) p[2] << 16 | (uint32_t) p[3] << 24; +} + +/* An application may have started the watchdog, and it survives the reset into the + * bootloader; hashing a large image must not let it fire. */ +static void feed_watchdog(void) { +#ifndef SIGNATURE_QEMU_TEST + if (nrf_wdt_started(NRF_WDT)) { + for (uint8_t i = 0; i < 8; i++) nrf_wdt_reload_request_set(NRF_WDT, (nrf_wdt_rr_register_t) i); + } +#endif +} + +bool signature_valid(uint8_t const *image, uint8_t const *slot, uint32_t kind, + uint32_t max_length, bool exact) { + uint32_t const length = le32(slot + 0x0C); + + if (le32(slot) != SLOT_MAGIC || le32(slot + 0x04) != kind) return false; + if (length == 0 || length > max_length || (exact && length != max_length)) return false; + for (uint32_t i = 0x10; i < SLOT_HEADER; i++) { + if (slot[i] != 0) return false; + } + for (uint32_t i = SLOT_TAIL; i < SIGNATURE_SLOT_SIZE; i++) { + if (slot[i] != 0xFF) return false; + } + + uint8_t const *signature = slot + SLOT_SIGNATURE; + crypto_sha512_ctx ctx; + uint8_t hash[64]; + uint8_t h_ram[32]; + + crypto_sha512_init(&ctx); + crypto_sha512_update(&ctx, signature, 32); /* R */ + crypto_sha512_update(&ctx, SIGNING_PUBLIC_KEY, 32); /* A */ + crypto_sha512_update(&ctx, slot, SLOT_HEADER); + for (uint32_t done = 0; done < length; done += CHUNK) { + feed_watchdog(); + uint32_t const n = (length - done < CHUNK) ? length - done : CHUNK; + crypto_sha512_update(&ctx, image + done, n); + } + crypto_sha512_final(&ctx, hash); + crypto_eddsa_reduce(h_ram, hash); + + return crypto_eddsa_check_equation(signature, SIGNING_PUBLIC_KEY, h_ram) == 0; +} diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/src/signature.h b/firmware/boards/nrf52840-mdk-dongle/bootloader/src/signature.h new file mode 100644 index 0000000..e479ac0 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/src/signature.h @@ -0,0 +1,35 @@ +/* + * Signed images: the only thing between the drive and running code. + * + * Every image carries a 256-byte slot at a fixed address past its end: + * + * 0x00 magic "VKS1" + * 0x04 kind SIGNATURE_KIND_APP or SIGNATURE_KIND_BOOTLOADER + * 0x08 version the signer's number; carried and signed, not yet compared + * 0x0C length bytes of the image signed, from its first byte + * 0x10 zero reserved, signed + * 0x40 Ed25519 signature (RFC 8032) over slot[0x00..0x40] || image[0..length] + * 0x80 0xFF never signed, so it must be erased + * + * The public key is compiled in: signing_key.h, generated by build.sh, defines + * SIGNING_PUBLIC_KEY_BYTES and SIGNING_KEY_FINGERPRINT (shown in INFO_UF2.TXT). + */ + +#ifndef SIGNATURE_H_ +#define SIGNATURE_H_ + +#include +#include + +#define SIGNATURE_KIND_APP 1 +#define SIGNATURE_KIND_BOOTLOADER 2 + +#define SIGNATURE_SLOT_SIZE 256 + +/* True only if the slot at `slot` is well formed, of `kind`, signs at most `max_length` + * bytes from `image` - exactly `max_length` when `exact` - and the signature verifies + * under the compiled-in key. Feeds the watchdog while it hashes. */ +bool signature_valid(uint8_t const *image, uint8_t const *slot, uint32_t kind, + uint32_t max_length, bool exact); + +#endif /* SIGNATURE_H_ */ diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/cases.py b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/cases.py new file mode 100644 index 0000000..b897e26 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/cases.py @@ -0,0 +1,125 @@ +"""Cases for test/verify.c: images signed by openssl the way signed_image.py and the +signing tool do it, each with the answer the bootloader must give. Writes cases.h and +signing_key.h into DIR, which holds key.pem and other.pem. + + cases.py DIR +""" + +import os +import random +import struct +import subprocess +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) +import signed_image as si # noqa: E402 + +L = 2**252 + 27742317777372353535851937790883648493 # the Ed25519 group order + + +def raw_public(pem: Path) -> bytes: + der = subprocess.run(["openssl", "pkey", "-in", str(pem), "-pubout", "-outform", "DER"], + check=True, capture_output=True).stdout + return der[-32:] + + +def sign(pem: Path, message: bytes, work: Path) -> bytes: + msg = work / "msg.bin" + msg.write_bytes(message) + return subprocess.run(["openssl", "pkeyutl", "-sign", "-inkey", str(pem), "-rawin", + "-in", str(msg)], check=True, capture_output=True).stdout + + +def slot(head: bytes, signature: bytes) -> bytes: + return (head + signature).ljust(si.SLOT, b"\xff") + + +def flip(data: bytes, index: int) -> bytes: + b = bytearray(data) + b[index] ^= 1 + return bytes(b) + + +def c_array(name: str, data: bytes) -> str: + return f"static const uint8_t {name}[{len(data)}] = {{{','.join(map(str, data))}}};\n" + + +def main() -> int: + work = Path(sys.argv[1]) + key, other = work / "key.pem", work / "other.pem" + rng = random.Random(1) + app, boot = si.KINDS["app"], si.KINDS["bootloader"] + app_max, boot_len = app.slot - app.base, boot.slot - boot.base + + image = bytes(rng.getrandbits(8) for _ in range(5000)) + head = si.header(app, 7, image) + sig = sign(key, head + image, work) + good = slot(head, sig) + + boot_image = si.image_for(boot, bytes(rng.getrandbits(8) for _ in range(0x9858))) + boot_head = si.header(boot, 3, boot_image) + boot_good = slot(boot_head, sign(key, boot_head + boot_image, work)) + + s = int.from_bytes(sig[32:], "little") + malleable = sig[:32] + (s + L).to_bytes(32, "little") + as_boot = si.header(boot, 7, image) + short_boot = boot_image[:boot_len - 256] + short_head = si.header(boot, 3, short_boot) + reserved = bytearray(head) + reserved[0x20] = 1 + long_head = struct.pack("<4I", si.MAGIC, 1, 7, len(image) + 1).ljust(si.HEADER, b"\0") + zero_head = struct.pack("<4I", si.MAGIC, 1, 7, 0).ljust(si.HEADER, b"\0") + tail = bytearray(good) + tail[0xF0] = 0 + + # (name, image, slot, kind, max, exact, expected) + cases: list[tuple[str, bytes, bytes, int, int, int, int]] = [ + ("valid app", image, good, 1, app_max, 0, 1), + ("header bit", image, flip(good, 0x08), 1, app_max, 0, 0), + ("image bit", flip(image, 2500), good, 1, app_max, 0, 0), + ("R bit", image, flip(good, 0x40 + 5), 1, app_max, 0, 0), + ("s bit", image, flip(good, 0x60 + 5), 1, app_max, 0, 0), + ("wrong key", image, slot(head, sign(other, head + image, work)), 1, app_max, 0, 0), + ("s + L", image, slot(head, malleable), 1, app_max, 0, 0), + ("bootloader kind in the app slot", image, + slot(as_boot, sign(key, as_boot + image, work)), 1, app_max, 0, 0), + ("length one past the image, signed", image + b"\xff", + slot(long_head, sign(key, long_head + image + b"\xff", work)), 1, app_max, 0, 1), + ("length one past what was signed", image + b"\xff", + slot(long_head, sig), 1, app_max, 0, 0), + ("length over the window, signed", image, good, 1, len(image) - 1, 0, 0), + ("zero length, signed", image, slot(zero_head, sign(key, zero_head, work)), + 1, app_max, 0, 0), + ("reserved byte set, signed", image, + slot(bytes(reserved), sign(key, bytes(reserved) + image, work)), 1, app_max, 0, 0), + ("tail not erased", image, bytes(tail), 1, app_max, 0, 0), + ("valid bootloader", boot_image, boot_good, 2, boot_len, 1, 1), + ("bootloader short of its slot, signed", short_boot, + slot(short_head, sign(key, short_head + short_boot, work)), 2, boot_len, 1, 0), + ("app slot offered as bootloader", image, good, 2, boot_len, 1, 0), + ] + + out = ["#include \n"] + rows = [] + for n, (name, img, sl, kind, mx, exact, expect) in enumerate(cases): + out += [c_array(f"I{n}", img), c_array(f"S{n}", sl)] + rows.append(f' {{"{name}", I{n}, S{n}, {kind}, {mx}, {exact}, {expect}}},\n') + out.append("struct test_case { const char *name; const uint8_t *image; const uint8_t *slot;" + " uint32_t kind, max_length; uint8_t exact, expect; };\n") + out.append("static const struct test_case CASES[] = {\n" + "".join(rows) + "};\n") + # The two valid messages whole, for the one-shot crypto_ed25519_check to agree with. + out += [c_array("APP_MESSAGE", head + image), c_array("BOOT_MESSAGE", boot_head + boot_image)] + (work / "cases.h").write_text("".join(out)) + + pub = raw_public(key) + (work / "signing_key.h").write_text( + "#define SIGNING_PUBLIC_KEY_BYTES {" + ",".join(map(str, pub)) + "}\n" + '#define SIGNING_KEY_FINGERPRINT "test"\n') + print(len(cases)) + os.remove(work / "msg.bin") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/run.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/run.sh new file mode 100644 index 0000000..f968984 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/run.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# The signature check against images openssl signed, with a throwaway key: src/signature.c +# compiled for the board's core (-mcpu=cortex-m4) and run under qemu-arm. Run by build.sh +# before every build is accepted; a check that refuses a valid image is a board that can +# never be updated again. + +set -eu + +work="$(mktemp -d)" +trap 'rm -rf "$work"' EXIT + +openssl genpkey -algorithm ed25519 -out "$work/key.pem" 2>/dev/null +openssl genpkey -algorithm ed25519 -out "$work/other.pem" 2>/dev/null +cases="$(python3 -I /work/in/test/cases.py "$work")" + +arm-none-eabi-gcc -Os -mcpu=cortex-m4 -mthumb -mfloat-abi=soft -std=gnu11 -Wall -Werror \ + -ffunction-sections -fdata-sections -Wl,--gc-sections -nostartfiles -static \ + --specs=nano.specs -Wl,-e,_start -DSIGNATURE_QEMU_TEST \ + -I"$work" -I/work/in/src -I/src/lib/monocypher/src -I/src/lib/monocypher/src/optional \ + /work/in/test/verify.c /work/in/src/signature.c \ + /src/lib/monocypher/src/monocypher.c /src/lib/monocypher/src/optional/monocypher-ed25519.c \ + -o "$work/verify.elf" + +qemu-arm -cpu max "$work/verify.elf" +echo "signature test: $cases cases decided right, streamed and one-shot checks agree" diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/verify.c b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/verify.c new file mode 100644 index 0000000..8e87176 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/verify.c @@ -0,0 +1,53 @@ +/* + * src/signature.c against the cases test/cases.py made, compiled for the board's core + * and run under qemu-arm. Exits 0 when every case is decided as expected and the + * streamed check agrees with Monocypher's one-shot crypto_ed25519_check; otherwise + * prints the case and exits 1. + */ + +#include +#include + +#include "cases.h" +#include "monocypher-ed25519.h" +#include "signature.h" +#include "signing_key.h" + +static uint8_t const KEY[32] = SIGNING_PUBLIC_KEY_BYTES; + +static void sys_write(char const *s) { + int const n = (int) strlen(s); /* before the register variables: a call clobbers r0-r3 */ + register int r0 __asm__("r0") = 1; + register char const *r1 __asm__("r1") = s; + register int r2 __asm__("r2") = n; + register int r7 __asm__("r7") = 4; + __asm__ volatile("svc 0" : "+r"(r0) : "r"(r1), "r"(r2), "r"(r7) : "memory"); +} + +static void sys_exit(int code) { + register int r0 __asm__("r0") = code; + register int r7 __asm__("r7") = 1; + __asm__ volatile("svc 0" :: "r"(r0), "r"(r7)); + for (;;) {} +} + +static void fail(char const *what, char const *name) { + sys_write(what); + sys_write(name); + sys_write("\n"); + sys_exit(1); +} + +void _start(void) { + for (unsigned i = 0; i < sizeof CASES / sizeof CASES[0]; i++) { + struct test_case const *c = &CASES[i]; + bool const got = signature_valid(c->image, c->slot, c->kind, c->max_length, c->exact); + if (got != (c->expect != 0)) fail(got ? "accepted: " : "refused: ", c->name); + } + /* The streamed hash must be exactly the one crypto_ed25519_check computes */ + if (crypto_ed25519_check(CASES[0].slot + 0x40, KEY, APP_MESSAGE, sizeof APP_MESSAGE) != 0) + fail("one-shot refused: ", CASES[0].name); + if (crypto_ed25519_check(CASES[14].slot + 0x40, KEY, BOOT_MESSAGE, sizeof BOOT_MESSAGE) != 0) + fail("one-shot refused: ", CASES[14].name); + sys_exit(0); +} diff --git a/firmware/boards/nrf52840-mdk-dongle/memory.x b/firmware/boards/nrf52840-mdk-dongle/memory.x index 9208c40..b7d6a13 100644 --- a/firmware/boards/nrf52840-mdk-dongle/memory.x +++ b/firmware/boards/nrf52840-mdk-dongle/memory.x @@ -2,16 +2,20 @@ * FLASH below is only this firmware's part of the map (docs2/makerdiary.md): * * 0x00000..0x01000 MBR - * 0x01000..0x97000 this firmware + * 0x01000..0x96000 this firmware + * 0x96000..0x97000 its signature slot, which the bootloader fork checks on every + * boot (bootloader/src/signature.h) * 0x97000..0xD8000 the vault (VAULT_BASE in main.rs) * 0xD8000..0xEC000 Trussed's filesystem, not used yet - * 0xEC000..0x100000 bootloader and its settings + * 0xEC000..0xF4000 free + * 0xF4000..0x100000 the UF2 bootloader, its CF2 page, MBR parameters and settings * - * RAM starts 8 bytes in, the way Nordic's own images on the MBR are linked: the MBR - * keeps its forwarding address there. To be confirmed against the MBR on the board. + * The bootloader writes only 0x01000..0x97000 (BOARD_APP_FLASH_END in bootloader/board), + * so a firmware update cannot reach the vault. RAM starts 8 bytes in, the way Nordic's + * own images on the MBR are linked: the MBR keeps its forwarding address there. */ MEMORY { - FLASH : ORIGIN = 0x00001000, LENGTH = 0x96000 + FLASH : ORIGIN = 0x00001000, LENGTH = 0x95000 RAM : ORIGIN = 0x20000008, LENGTH = 0x3FFF8 } diff --git a/firmware/boards/nrf52840-mdk-dongle/src/main.rs b/firmware/boards/nrf52840-mdk-dongle/src/main.rs index eb67450..9384908 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/main.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/main.rs @@ -63,8 +63,8 @@ const RESET_CAUSES: [(u32, &str); 9] = [ const USB_VID: u16 = 0x1209; const USB_PID: u16 = 0x0001; -/// The vault's flash, 0x97000..0xD8000: past the end of FLASH in memory.x, before -/// Trussed's filesystem. `LAYOUT` counts from its start. +/// The vault's flash, 0x97000..0xD8000: past the end of FLASH in memory.x and the +/// signature slot after it, before Trussed's filesystem. `LAYOUT` counts from its start. const VAULT_BASE: u32 = 0x9_7000; const VAULT_LEN: u32 = 0x4_1000; @@ -205,7 +205,7 @@ fn vault_region() -> &'static mut [u8] { ); let base = core::ptr::with_exposed_provenance_mut::(VAULT_BASE as usize); // SAFETY: 0x97000..0xD8000 is flash outside the image - memory.x ends FLASH at - // 0x97000 - so nothing the compiler knows of lives there; it is page-aligned, as + // 0x96000 - so nothing the compiler knows of lives there; it is page-aligned, as // the driver asserts; and the flag above makes this the only reference to it. The // flash controller rewrites these bytes on erase, which is why every access goes // through `Flash` and its fences. diff --git a/tools/build-bootloader.sh b/tools/build-bootloader.sh index 318ddfe..4c876d5 100755 --- a/tools/build-bootloader.sh +++ b/tools/build-bootloader.sh @@ -26,7 +26,9 @@ # # nRF52840 boards: the UF2 bootloader, upstream Adafruit_nRF52_Bootloader at a pinned # commit with bootloader/'s board definition and patches, built and checked by -# bootloader/build.sh in bootloader/Dockerfile. Until the fork is complete +# bootloader/build.sh in bootloader/Dockerfile. It trusts one Ed25519 public key: +# bootloader/signing-key.pem, or with BOOTLOADER_TEST_KEY= a throwaway key, which +# INFO_UF2.TXT then names as a test key. Until the fork is installable # (docs2/roadmap.md, phase 3) the outputs stay in a temporary directory: nothing goes # into images/, and nothing is installed. @@ -87,20 +89,31 @@ build_esp() { } build_uf2() { - local dir="$1" name="$2" out log + local dir="$1" name="$2" out log key kind + if [[ -n "${BOOTLOADER_TEST_KEY:-}" ]]; then + key="$BOOTLOADER_TEST_KEY" kind=test + else + key="$dir/bootloader/signing-key.pem" kind=real + fi + [[ -f "$key" ]] || { + echo "$name: no $key. The real key is not made yet (docs2/roadmap.md, phase 3);" >&2 + echo " a test build: BOOTLOADER_TEST_KEY= $0" >&2 + exit 1 + } docker build -q -t "vkey-bootloader-$name" "$dir/bootloader" >/dev/null out="$(mktemp -d)" log="$out/build.log" # As the host user, so the outputs are the host user's. The log keeps newlib's # "is not implemented" linker warnings out of sight; build.sh fails on anything real. - if ! docker run --rm -u "$(id -u):$(id -g)" -v "$dir/bootloader:/work/in:ro" -v "$out:/work/out" \ + if ! docker run --rm -u "$(id -u):$(id -g)" -e KEY_KIND="$kind" -v "$key:/work/key.pem:ro" \ + -v "$dir/bootloader:/work/in:ro" -v "$out:/work/out" \ "vkey-bootloader-$name" sh /work/in/build.sh >"$log" 2>&1; then cat "$log" >&2 echo "$name: the bootloader build or its checks failed" >&2 exit 1 fi - grep -E "^ *(FLASH|BOOTLOADER_CONFIG):|^check:" "$log" || true - (cd "$out" && sha256sum bootloader.bin update-bootloader.uf2) + grep -E "^ *(FLASH|BOOTLOADER_CONFIG):|^check:|^signature test:|^key:" "$log" || true + (cd "$out" && sha256sum bootloader.bin) echo "$name: outputs in $out - not installed, not copied into images/" } From b102168681e175b7968370d3a0ed25f5dc93b737 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 13:23:01 +0300 Subject: [PATCH 05/33] Make the nRF52840 the key and the C6 a test board - No board holds real secrets (2026-10-14); every feature is built for the nRF, with no fallback. - The C6 takes check --wipe-everything for core changes once a .vkb holds vkey-signing, its Secure Boot key. - roadmap: the migration shrinks to moving vkey-signing and taking C6 flashing out of the CLI; the nRF bootloader key is an item on the nRF with a .vkb right after. --- CLAUDE.md | 29 ++++++++++++++++------------- README.md | 2 +- docs2/roadmap.md | 45 +++++++++++++++++++++++---------------------- 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8dcbd47..01c9c05 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,9 +1,9 @@ # Project rules **vaulttecdev** — a hardware key for TOTP codes, passwords and project `.env` files, own -code. Two boards: the Makerdiary nRF52840 MDK USB Dongle (primary, not yet for real -secrets) and the Waveshare ESP32-C6-Zero (fallback, holds the maintainer's secrets until -the migration in `docs2/roadmap.md`). +code. Two boards: the Makerdiary nRF52840 MDK USB Dongle (the key, not yet for real +secrets) and the Waveshare ESP32-C6-Zero (a test board, not a fallback). Neither holds +real secrets yet. | Part | What it is | |---|---| @@ -20,11 +20,11 @@ C6 has no USB HID; reopened 2026-10-03 for the nRF52840 board on Trussed + `fido-authenticator`, not an own CTAP2 (maintainer's decision, `docs2/makerdiary.md`). It never exists on the C6. -**The nRF52840 board is the primary board; the C6 is the fallback** (maintainer's -decision, 2026-10-13). Code is shaped for the nRF first. Nothing is kept only so the C6 -works. A C6 need that remains is driven by its board folder or `board.toml`, not by -shared code. Real secrets move to the nRF at security parity, not when features are done -(`docs2/roadmap.md`). +**The nRF52840 board is the key; the C6 is a test board, not a fallback** (maintainer's +decisions, 2026-10-13 and 2026-10-14). Every feature is built for the nRF. Nothing is kept +only so the C6 works. A C6 need that remains is driven by its board folder or +`board.toml`, not by shared code. Real secrets go onto the nRF when phases 3-5 of +`docs2/roadmap.md` are done, not when features are done. Consequence for code: "convenience for a buyer" is not an argument; security of the maintainer's own secrets and minimal code are. @@ -155,8 +155,10 @@ The boards: base 0x1000) to `UF2BOOT`, replug. No chip key, so it holds no real secrets yet. `vkey info` prints the chip's build code, UICR `APPROTECT` and last reset cause. Notes, measurements and factory state: `docs2/makerdiary.md`; the plan: `docs2/roadmap.md`. -- **`esp32c6-zero`**, the fallback, holding the maintainer's secrets until the migration. - USB is a fixed Serial/JTAG (`303a:1001`), HID is impossible, so passkey will never exist +- **`esp32c6-zero`**, the test board (2026-10-14): nothing is built for it, and it takes + `check --wipe-everything` for core changes. Secure Boot v2 is burned, so before its + first wipe a `.vkb` holding `vkey-signing` (its Secure Boot key) must exist: losing that + key ends its updates for good. USB is a fixed Serial/JTAG (`303a:1001`), HID is impossible, so passkey will never exist here; one port carries both the protocol and logs — hence the `VTC2` magic word in frames. Pins and pitfalls: `docs/hardware.md`. @@ -265,9 +267,10 @@ The boards: - Before a **release**, and on every new board: `vkey check --wipe-everything` green too (it says when to tap, when to double tap and when to hold). It leaves the device with no PIN and no entries, so run it on an empty board — never on a key holding secrets. - There is no spare board: until the migration the empty nRF takes this test, afterwards - the wiped C6 does for core changes. A release that could not re-run it says so plainly - rather than pretending it was. + There is no spare board: the C6 takes this test for core changes, once a `.vkb` + holds its `vkey-signing`, and the nRF only while it holds nothing a `.vkb` cannot + restore. A release that could not re-run it on + the nRF says so plainly rather than pretending it was. Gesture rules are proven on the host (`firmware/core/tests/key.rs`); the board verifies the hardware honours them. diff --git a/README.md b/README.md index dbe80f6..55f5795 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ single-binary host CLI, and a press of the board's button for every secret that > core and passes the full lifecycle test. It has no chip key yet, though, and its bootloader > flashes anything and reads the flash back. So it is **not for real secrets** until the steps > in [docs2/roadmap.md](docs2/roadmap.md) are done, and `vkey setup` does not flash it yet. -> Everything below describes the ESP32-C6-Zero, the key in use today. +> Everything below still describes the ESP32-C6-Zero, which is now only a test board. ## In ten seconds diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 6e331a6..a102d01 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -2,8 +2,9 @@ Written 2026-10-13, after the first green `vkey check --wipe-everything` on the Makerdiary dongle. Revised the same day for a constraint the maintainer set: **no SWD probe and no -spare board, now or later.** Decided already, not reopened here: the nRF52840 is the -primary board and the C6 the fallback; Trussed + `fido-authenticator` for passkeys. Board +spare board, now or later.** Decided already, not reopened here: the nRF52840 is the key +and the C6 a test board, not a fallback (2026-10-14); Trussed + `fido-authenticator` for +passkeys. Board notes, measurements and the factory state: `docs2/makerdiary.md`. ## What "no probe, no spare" changes @@ -20,20 +21,21 @@ notes, measurements and the factory state: `docs2/makerdiary.md`. board installs through its own update path at the same address. - **UF2 stays the transport for good.** `vkey setup` for the nRF copies a signed UF2 to the bootloader's drive. That is no longer throwaway work. -- **Test without a spare.** The nRF is empty now, so it is the test board until migration. - Afterwards the C6, wiped and kept as the fallback, takes the full - `check --wipe-everything` for core changes. nRF-only changes get `selftest` and a `.vkb` +- **Test without a spare.** Neither board holds real secrets (2026-10-14). The C6 takes + the full `check --wipe-everything` for core changes, once a `.vkb` holds its Secure Boot + key `vkey-signing`; the nRF takes it while it holds nothing a `.vkb` cannot restore. + nRF-only changes get `selftest` and a `.vkb` backup before each update. A release then says plainly that the full lifecycle test was not re-run on the nRF, as `CLAUDE.md` requires. ## The rule that orders everything -**Secrets move to the nRF at security parity, not when features are done.** Today the C6 -is the stronger key: the eFuse HMAC key, Secure Boot v2 and JTAG off. The nRF has no chip -key, and its bootloader flashes anything and serves the flash back (`CURRENT.UF2`). A copy -of its flash gives up the PIN offline in hours (`docs/threat-model.md`). Until phases 3-5 -are done, real secrets stay on the C6. `espflash` stays in the CLI and the audit exception -stays open until the migration. +**Real secrets go onto the nRF when phases 3-5 are done, not when features are done.** +No board holds real secrets today, and the C6 is a test board, not a fallback +(2026-10-14), so every feature is built for the nRF alone. The nRF has no chip key, and +its bootloader flashes anything and serves the flash back (`CURRENT.UF2`). A copy of its +flash gives up the PIN offline in hours (`docs/threat-model.md`). `espflash` stays in the +CLI while the C6 is flashed through it, and the audit exception with it. The order is fixed by what each step depends on. First the **bootloader** with no read-back and signed images only: APPROTECT means nothing while UF2 hands out the flash. Then @@ -65,7 +67,7 @@ and signed images only: APPROTECT means nothing while UF2 hands out the flash. T ## Phase 1 - true docs and a board that reports itself - **The docs pass.** Done 2026-10-13 for `CLAUDE.md`, the README (a "two boards" note; the - full rewrite waits for the migration, since the C6 is the key in use until then) and the + full rewrite waits until the nRF takes real secrets) and the core comments. `docs/hardware.md` and moving the C6 docs into its folder are deferred: they describe the C6 correctly as they are. - README, `CLAUDE.md` and `docs/hardware.md` put the nRF first. @@ -369,17 +371,15 @@ strong as phases 3-4. Two options, decided by the maintainer: to the C6's eFuse HMAC. It needs Nordic's closed library or undocumented registers, which goes against "crypto from RustCrypto". -The existing nRF vault is unbound, so it reads as `Incompatible`. It is wiped, which costs -nothing while it is empty. +The existing nRF vault is unbound, so it reads as `Incompatible`. It is wiped and its +signing key restored from the `.vkb`, which costs nothing while it holds nothing else. -**Migration:** +**What is left of the migration.** No board holds real secrets (2026-10-14), so nothing +moves but the keys: -1. Back up the C6 to a `.vkb`. -2. Restore onto the nRF. The cost travels in the file, so this works across boards. -3. Check that the signing keys are on the nRF, and write down where their backups live. - Losing the C6 Secure Boot key ends C6 updates forever. -4. Wipe the C6. It becomes the fallback and the test board for core changes. -5. C6 flashing moves out of the CLI into a script in its folder. `espflash` leaves, and the +1. Put `vkey-signing`, the C6's Secure Boot key, on the nRF next to the bootloader key, + back up to a `.vkb`, and write down where it lives. Losing it ends C6 updates forever. +2. C6 flashing moves out of the CLI into a script in its folder. `espflash` leaves, and the audit exception goes. Acceptance: the threat model's nRF section is rewritten to match; `selftest` green on the @@ -413,7 +413,8 @@ Acceptance: registration and login on webauthn.io and with `fido2-token`; `pam_u | Phase 2 | ~~if the chip is older than revision 3: accept the glitch risk or keep the important secrets on the C6~~ - revision 2; everything moves here, risk accepted (2026-10-13) | | Phase 3 | ~~own bootloader instead of the Nordic secure bootloader~~ - own fork chosen (2026-10-13); installing it still needs its own go | | Phase 3 | ~~the signing key's second home~~ - a `.vkb` that restores onto the C6; the C6 is the test board, everything else is on the nRF (2026-10-14) | -| Phase 5 | chip key option A or B; wiping the C6 after migration | +| Phase 5 | ~~wiping the C6 after migration~~ - the C6 is a test board, not a fallback, and neither board holds real secrets (2026-10-14) | +| Phase 5 | chip key option A or B | | Phase 6 | RTIC or Embassy, and the `unsafe` rule if the runtime needs it | ## Sources From 11977536b52d01fc41585b427167160d2ecdae8e Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 13:37:56 +0300 Subject: [PATCH 06/33] Test the UF2 bootloader fork on the board as an app - 0006: tinyusb no longer asks a SoftDevice about the USB clock. It did whenever the app's word at 0x3004 held the SoftDevice magic, which would hang DFU mode. The only svc left is sd_mbr_command. 0.9.2-vkey.4. - 0007 + VKEY_AS_APP in board.h: the same sources linked at 0x1000 to run under the factory bootloader: no COPY_BL, no settings write, a drive window of 0x40000..0x80000, label VKEYTEST. The real bootloader.bin is byte-identical with these hooks. - test/app_test.c reports the bootloader's own signature checks with DWT cycles in INFO_UF2.TXT; test/board.py and board.sh make the UF2s and copy each only to the drive it is meant for. - check.py --as-app: UICR search, no svc, ends below 0x40000. A movt of 0x1000 whose low half is unknown now counts as a UICR address. - On the board: the signed app accepted in 15.13 M cycles (~236 ms), an altered one refused; a signed self-update staged and accepted, an altered one refused. vkey restored from its signed UF2. --- CLAUDE.md | 6 +- docs2/roadmap.md | 61 +++++++--- .../bootloader/board/board.h | 12 +- .../nrf52840-mdk-dongle/bootloader/build.sh | 18 ++- .../nrf52840-mdk-dongle/bootloader/check.py | 48 ++++++-- .../patches/0006-no-softdevice.patch | 80 ++++++++++++++ .../bootloader/patches/0007-as-app.patch | 104 ++++++++++++++++++ .../bootloader/test/app.ld | 68 ++++++++++++ .../bootloader/test/app_test.c | 89 +++++++++++++++ .../bootloader/test/board.py | 103 +++++++++++++++++ .../bootloader/test/board.sh | 52 +++++++++ 11 files changed, 614 insertions(+), 27 deletions(-) create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0006-no-softdevice.patch create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0007-as-app.patch create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/test/app.ld create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.py create mode 100755 firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.sh diff --git a/CLAUDE.md b/CLAUDE.md index 01c9c05..1e250c1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -324,7 +324,11 @@ plus an offset. The fork runs only images signed with one Ed25519 key, checked o boot (`bootloader/src/signature.c`, tested under qemu-arm by `bootloader/test/run.sh` before every build); `bootloader/sign.sh` makes the signed UF2. The build needs `bootloader/signing-key.pem`, or `BOOTLOADER_TEST_KEY` for a build that names itself a -test build. Until the fork is installable the outputs stay in a temporary directory, and +test build. A test-key build also makes `as-app.bin`: the same sources as an application +at 0x1000 that runs under the factory bootloader and reports its verdicts in +`INFO_UF2.TXT` (`bootloader/test/app_test.c`). `bootloader/test/board.sh copy` puts a UF2 +only on the drive it is meant for: a bootloader UF2 on the factory `UF2BOOT` would be +installed. Until the fork is installable the outputs stay in a temporary directory, and installing it is never part of a build (`docs2/roadmap.md`, phase 3). Compilation is the **only** exception to the check rule. Linters, formatters, tests and diff --git a/docs2/roadmap.md b/docs2/roadmap.md index a102d01..2e5103d 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -270,8 +270,11 @@ Milestones, one commit each: nothing written between the check and the jump; - DFU mode always ends in a reset; - a bootloader update is copied only if signed; - - the jump address is always 0x1000, and no SoftDevice is looked for; + - the jump address is always 0x1000, and the boot path looks for no SoftDevice; - `INFO_UF2.TXT` names the key. + + tinyusb's USB clock code still looked for one, at an address in the app, until + milestone 4's `0006`; the message of commit a8b50cd overstates this for vkey.3. - **`test/run.sh`, run before every build.** It compiles `signature.c` for Cortex-M4 and runs it under qemu-arm on 17 openssl-signed cases: valid app and bootloader; a flipped bit in header, image, R or s; wrong key; s + L; wrong kind; length @@ -281,26 +284,50 @@ Milestones, one commit each: ≈1.8 KiB of the 8 KiB reserved. - **Signing.** `sign.sh` signs with openssl, checks the signature before writing, and wraps the image and slot into a UF2. By the factory bootloader's code it accepts that - UF2 too, the slot being ordinary app space to it; not tried yet. It refuses to sign + UF2 too, the slot being ordinary app space to it (confirmed in milestone 4). It refuses to sign a bootloader that trusts a test key unless `ALLOW_TEST_KEY=1`. `memory.x` now ends the firmware at 0x96000; its image did not change. - **The build refuses to run without `bootloader/signing-key.pem`.** A test build names its key with `BOOTLOADER_TEST_KEY`, and `INFO_UF2.TXT` then says "TEST KEY". -4. The on-device test as an application. The plan: - - a build flag (`VKEY_AS_APP=1`) in the same patch series, not separate code; - - linked at 0x1000, `COPY_BL` compiled out; - - its write window and verify target on a scratch area (0x40000..0x80000), clear of - itself; - - marked a test build in its INFO text. - - With no serial port the drive is the only output, so it writes its results into - `INFO_UF2.TXT`: - - accept or refuse on a real-pipeline signed app, an altered one and a signed - self-update image; - - DWT cycle counts for a boot verify, turning the qemu estimate into a measurement on - the chip. - - The factory bootloader stays in place throughout, so this milestone is reversible. +4. The on-device test as an application, and one fix it turned up. **Run on the board + 2026-10-14, with the factory bootloader in place throughout.** + - **`patches/0006-no-softdevice`, a change to the bootloader itself.** tinyusb's USB + clock code asked a SoftDevice about the clock whenever the word at 0x3004 held its + magic number. Here that word is the app's, so an app holding it there would have + sent DFU mode into an SVC nothing serves: a hang on the drive, and an app no update + could replace. Found by the test build's `svc` check. The clock is now the CLOCK + peripheral's alone, and the only `svc` left is `sd_mbr_command`. Version + `0.9.2-vkey.4`. + - **`patches/0007-as-app` and `VKEY_AS_APP` in `board.h`: the test build.** The same + sources linked at 0x1000 (`test/app.ld`) to run under the factory bootloader. + `COPY_BL` is compiled out, the settings page is never written, the drive writes only + 0x40000..0x80000 and stages a self-update at 0x76000, and its label is `VKEYTEST`. + Built only with a test key, after the real build. With these hooks the real + `bootloader.bin` stayed byte-identical. `check.py --as-app` puts it through the same + UICR search, and it must contain no `svc` and end below 0x40000. + - **`test/app_test.c`** makes the bootloader's own `signature_valid` calls before the + drive starts and writes each verdict with its DWT cycle count into `INFO_UF2.TXT`. + **`test/board.py`** moves the real-pipeline signed app into the scratch window (the + signature covers no address). **`test/board.sh copy`** reads the target drive's + `INFO_UF2.TXT` first: a bootloader UF2 goes only to `VKEYTEST`, never to the factory + `UF2BOOT`, which would install it. + + On the chip: + + | Check | Result | + |---|---| + | the signed app, 77 100 B | accepted, 15.13 M cycles, ≈ 236 ms at 64 MHz | + | the same with one bit of R flipped | refused | + | the app checked as a bootloader | refused, 88 cycles | + | a signed self-update copied to `VKEYTEST` | staged by the fork's own write path, accepted at the next boot | + | the same with one bit flipped at 0xF4110 | refused | + + The fork's USB drive works on this board. The measured ≈1.44 cycles an instruction + matches the qemu estimate, so a 300 KiB image with Trussed would take ≈ 0.8 s. The + instruction cache was off (`ICACHECNF` 0). Turning it on in the fork before the check + is an open speed-up, not done. The vkey firmware was then restored from its signed UF2 + through the factory bootloader, which runs it with the slot at 0x96000: the first + install step, rehearsed with the test key. Install needs its own go and a checklist: diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h index 7760d70..6d6cf72 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h @@ -67,15 +67,25 @@ /* Flash: the drive writes 0x1000..BOARD_APP_FLASH_END and nothing else. Above it lie * the vault (0x97000..0xD8000) and the filesystem a firmware keeps (0xD8000..0xEC000). * The same boundary as FLASH in the firmware's memory.x and VAULT_BASE in its main.rs. + * + * The on-board test build (VKEY_AS_APP, bootloader/test/) runs from 0x1000 under the + * factory bootloader, so its drive writes only a scratch window above itself and stages + * a self-update at the top of it. Its own label tells its drive from a bootloader's. *------------------------------------------------------------------*/ +#ifdef VKEY_AS_APP +#define BOARD_TEST_SCRATCH 0x40000 +#define BOARD_APP_FLASH_END 0x80000 +#define UF2_VOLUME_LABEL "VKEYTEST " +#else #define BOARD_APP_FLASH_END 0x97000 +#define UF2_VOLUME_LABEL "UF2BOOT " +#endif /* The app's signature slot (src/signature.h): the last page of the window, which the * app itself never reaches - memory.x ends its FLASH here. */ #define BOARD_APP_SLOT (BOARD_APP_FLASH_END - 0x1000) #define UF2_PRODUCT_NAME "Makerdiary nRF52840 MDK USB Dongle" -#define UF2_VOLUME_LABEL "UF2BOOT " #define UF2_BOARD_ID "nRF52840-MDK-USB-DONGLE" #define UF2_INDEX_URL "https://wiki.makerdiary.com/nrf52840-mdk-usb-dongle" diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh index 5791434..8b07046 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/build.sh @@ -8,6 +8,7 @@ # the signing step signs and wraps into the self-update UF2 # bootloader.dis its disassembly, for check.py # systeminit.txt SystemInit disassembled, read before any install +# as-app.bin/.dis with a test key only: the on-board test build (test/app_test.c) # # The tree is the image's pristine upstream checkout, so every run starts from the same # sources. The version and the build date are fixed, so the same inputs give the same @@ -19,7 +20,7 @@ BOARD=nrf52840_mdk_usb_dongle # Upstream's version, then the fork's revision, bumped with every change to this folder: # with no probe, INFO_UF2.TXT on the drive is the only way to tell which build a board # runs. The Makefile takes the bootloader version number from the part before "-". -VERSION=0.9.2-vkey.3 +VERSION=0.9.2-vkey.4 # What `git submodule status` reports for the pinned commits today, as the factory # 0.7.1 bootloader reports it too. Fixed here because the uf2 part names an upstream # branch, and a fresh clone after that branch moves would change the INFO text. @@ -76,3 +77,18 @@ arm-none-eabi-objdump -d --no-show-raw-insn "$out" > /work/out/bootloader.dis arm-none-eabi-size "$out" python3 /work/in/check.py /work/out/bootloader.bin /work/out/bootloader.dis echo "key: $fingerprint" + +# With a test key, also the on-board test build (test/app_test.c, patches/0007): the +# same sources as an application at 0x1000, run under the factory bootloader. It runs +# on the chip too, so it passes the same UICR search. +[ "$KEY_KIND" = test ] || exit 0 +cp /work/in/test/app_test.c src/ +cp /work/in/test/app.ld linker/ +printf 'CFLAGS += -DVKEY_AS_APP\nC_SRC += src/app_test.c\n' > Makefile.user +app="_build/app/${BOARD}_bootloader-$VERSION.out" +make -s BOARD="$BOARD" BUILD=_build/app LD_FILE=linker/app.ld GIT_VERSION="$VERSION" \ + GIT_SUBMODULE_VERSIONS="$SUBMODULES" "$app" +arm-none-eabi-objcopy -O binary -R .uicrBootStartAddress -R .uicrMbrParamsPageAddress \ + "$app" /work/out/as-app.bin +arm-none-eabi-objdump -d --no-show-raw-insn "$app" > /work/out/as-app.dis +python3 /work/in/check.py --as-app /work/out/as-app.bin /work/out/as-app.dis diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py b/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py index ee3bcc7..da8fe61 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py @@ -5,11 +5,17 @@ - No UICR address the code could write through: the bootloader must never write UICR. A write there (PSELRESET, NFCPINS, APPROTECT) is permanent without a probe. Searched three ways: as a word anywhere in the code, as an immediate in any instruction but a - comparison, and as a movw/movt pair. Like the radio search in build-vaultkey.sh, it - catches direct addressing, not an address computed from another base plus an offset. + comparison, and as a movw/movt pair or a movt of 0x1000 whose low half it cannot + see. Like the radio search in build-vaultkey.sh, it catches direct addressing, not an + address computed from another base plus an offset. - The CF2 block is the factory one, word for word. Its board ID is what the factory bootloader checks before it accepts this one as a self-update, and what a later self-update of this one is checked against. + +With --as-app it checks the on-board test build (test/app_test.c), an application from +0x1000 that runs on the chip as well: the same UICR search, no CF2 block, an image that +ends below the scratch window its drive writes, and no `svc`, since its own vectors +handle that and the MBR's commands are compiled out of it. """ import re @@ -19,6 +25,8 @@ BASE = 0xF4000 CF2_AT = 0xFD800 UICR = range(0x10001000, 0x10002000) +APP_BASE = 0x1000 +APP_END = 0x40000 # BOARD_TEST_SCRATCH in board/board.h # What the factory 0.7.1 image holds at 0xFD800: magic, 5 of 100 entries used, # flash 1 MiB, RAM 256 KiB, board ID 2886:F00F, UF2 family, 32 pins per port. @@ -39,11 +47,11 @@ MOVT = re.compile(r"^movt\S*\s+(r\d+|ip|lr|sl|fp), #(\d+)") -def words_in_code(code: bytes) -> list[str]: +def words_in_code(code: bytes, base: int) -> list[str]: # Halfword steps: Thumb literal pools are word-aligned, but a constant packed in # data need not be. return [ - hex(BASE + i) + hex(base + i) for i in range(0, len(code) - 3, 2) if struct.unpack_from(" list[str]: if w := MOVW.match(text): last_movw[w.group(1)] = int(w.group(2)) elif t := MOVT.match(text): + # A high half of 0x1000 with a low half that did not come from a movw into + # the same register (a mov.w, a mov from another register) could still be + # UICR, so it counts as one. low = last_movw.get(t.group(1)) - if low is not None and (int(t.group(2)) << 16 | low) in UICR: - hits.append(f"{addr}: {text} (with movw #{low:#x})") + high = int(t.group(2)) << 16 + if (low is None and high == UICR.start & 0xFFFF0000) or ( + low is not None and (high | low) in UICR + ): + hits.append(f"{addr}: {text} (with movw #{low:#x})" if low is not None + else f"{addr}: {text} (low half unknown)") return hits +def check_as_app(data: bytes, dis: str) -> int: + hits = words_in_code(data, APP_BASE) + immediates_and_pairs(dis) + if hits: + print("UICR addresses the code could write through:\n " + "\n ".join(hits)) + return 1 + if APP_BASE + len(data) > APP_END: + print(f"the test build ends at {APP_BASE + len(data):#x}, inside its scratch window") + return 1 + svc = [line.strip() for line in dis.splitlines() if re.search(r"\tsvc", line)] + if svc: + print("the test build calls svc:\n " + "\n ".join(svc)) + return 1 + print(f"check: no UICR address and no svc in the {len(data)}-byte test build") + return 0 + + def main() -> int: + if sys.argv[1] == "--as-app": + return check_as_app(open(sys.argv[2], "rb").read(), open(sys.argv[3]).read()) + data = open(sys.argv[1], "rb").read() dis = open(sys.argv[2]).read() code = data[: CF2_AT - BASE] - hits = words_in_code(code) + immediates_and_pairs(dis) + hits = words_in_code(code, BASE) + immediates_and_pairs(dis) if hits: print("UICR addresses the code could write through:\n " + "\n ".join(hits)) return 1 diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0006-no-softdevice.patch b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0006-no-softdevice.patch new file mode 100644 index 0000000..75d51e5 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0006-no-softdevice.patch @@ -0,0 +1,80 @@ +--- a/lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c ++++ b/lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c +@@ -848,44 +848,13 @@ + //--------------------------------------------------------------------+ + // HFCLK helper + //--------------------------------------------------------------------+ +-#ifdef SOFTDEVICE_PRESENT +- +-// For enable/disable hfclk with SoftDevice +-#include "nrf_mbr.h" +-#include "nrf_sdm.h" +-#include "nrf_soc.h" +- +-#ifndef SD_MAGIC_NUMBER +- #define SD_MAGIC_NUMBER 0x51B1E5DB +-#endif +- +-static inline bool is_sd_existed(void) +-{ +- return *((uint32_t*)(SOFTDEVICE_INFO_STRUCT_ADDRESS+4)) == SD_MAGIC_NUMBER; +-} +- +-// check if SD is existed and enabled +-static inline bool is_sd_enabled(void) +-{ +- if ( !is_sd_existed() ) return false; +- +- uint8_t sd_en = false; +- (void) sd_softdevice_is_enabled(&sd_en); +- return sd_en; +-} +-#endif ++// No SoftDevice: the clock is the CLOCK peripheral's alone. Upstream asked one about it ++// whenever the word at 0x3004 was its magic number, and in this bootloader that word is ++// the application's, so an app holding it there would have sent USB into an SVC that ++// nothing serves. + + static bool hfclk_running(void) + { +-#ifdef SOFTDEVICE_PRESENT +- if ( is_sd_enabled() ) +- { +- uint32_t is_running = 0; +- (void) sd_clock_hfclk_is_running(&is_running); +- return (is_running ? true : false); +- } +-#endif +- + return nrf_clock_hf_is_running(NRF_CLOCK, NRF_CLOCK_HFCLK_HIGH_ACCURACY); + } + +@@ -894,28 +863,12 @@ + // already running, nothing to do + if ( hfclk_running() ) return; + +-#ifdef SOFTDEVICE_PRESENT +- if ( is_sd_enabled() ) +- { +- (void)sd_clock_hfclk_request(); +- return; +- } +-#endif +- + nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED); + nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART); + } + + static void hfclk_disable(void) + { +-#ifdef SOFTDEVICE_PRESENT +- if ( is_sd_enabled() ) +- { +- (void)sd_clock_hfclk_release(); +- return; +- } +-#endif +- + nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP); + } + diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0007-as-app.patch b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0007-as-app.patch new file mode 100644 index 0000000..17086ec --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/patches/0007-as-app.patch @@ -0,0 +1,104 @@ +--- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c ++++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +@@ -150,8 +150,12 @@ + + static void bootloader_settings_save(bootloader_settings_t * p_settings) + { ++ // The on-board test build runs under the factory bootloader, whose settings page ++ // this is: it writes nothing outside its scratch window. ++#ifndef VKEY_AS_APP + nrfx_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS); + nrfx_nvmc_words_write(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4); ++#endif + + pstorage_callback_handler(&m_bootsettings_handle, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_settings, sizeof(bootloader_settings_t)); + } +--- a/src/main.c ++++ b/src/main.c +@@ -110,10 +110,20 @@ + //--------------------------------------------------------------------+ + static void dfu_mode(bool asked_by_app); + ++#ifdef VKEY_AS_APP ++void app_test_run(void); ++#endif ++ + //--------------------------------------------------------------------+ + // + //--------------------------------------------------------------------+ + int main(void) { ++#ifdef VKEY_AS_APP ++ // The on-board test build (bootloader/test/app_test.c) runs from 0x1000 under the ++ // factory bootloader: its interrupts go to its own vectors, whatever the MBR forwards. ++ SCB->VTOR = MBR_SIZE; ++#endif ++ + // Populate Boot Address and MBR Param into MBR if not already + // MBR_BOOTLOADER_ADDR/MBR_PARAM_PAGE_ADDR are used if available, else UICR registers are used + // Note: skip it for now since this will prevent us to change the size of bootloader in the future +@@ -128,6 +138,14 @@ + PRINTF("Bootloader Start\r\n"); + led_state(STATE_BOOTLOADER_STARTED); + ++#ifdef VKEY_AS_APP ++ // It is the application, so there is none to check or start: it checks its test ++ // images, then serves the drive until a reset. ++ app_test_run(); ++ dfu_mode(false); ++ NVIC_SystemReset(); ++#endif ++ + // The application asked for DFU mode: clear the request, so the next reset boots it + bool const uf2_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET); + if (uf2_dfu) NRF_POWER->GPREGRET = 0; +--- a/src/usb/msc_uf2.c ++++ b/src/usb/msc_uf2.c +@@ -211,6 +211,9 @@ + { + PRINTF("bootloader update is not signed\r\n"); + } ++ // The on-board test build never copies: its next boot reports the staged ++ // image's verdict from the same check (bootloader/test/app_test.c). ++#ifndef VKEY_AS_APP + // skip if there is no bootloader change + else if ( memcmp(new_bootloader, (uint8_t*) BOOTLOADER_ADDR_START, DFU_BL_IMAGE_MAX_SIZE) ) + { +@@ -226,6 +229,7 @@ + // on success, COPY_BL won't return but run the new bootloader right away. + sd_mbr_command(&command); + } ++#endif + + PRINTF("bootloader update complete\r\n"); + }else +--- a/src/usb/uf2/ghostfat.c ++++ b/src/usb/uf2/ghostfat.c +@@ -119,8 +119,13 @@ + #define STR(x) STR0(x) + + // The key's fingerprint tells a board running a test-key build from one running the +-// real key; there is no SoftDevice line, since there is no SoftDevice. ++// real key; there is no SoftDevice line, since there is no SoftDevice. The on-board test ++// build appends its results (bootloader/test/app_test.c). ++#ifdef VKEY_AS_APP ++char infoUf2File[BPB_SECTOR_SIZE - 1] = ++#else + static char const infoUf2File[] = ++#endif + "UF2 Bootloader " UF2_VERSION "\r\n" + "Model: " UF2_PRODUCT_NAME "\r\n" + "Board-ID: " UF2_BOARD_ID "\r\n" +--- a/src/usb/uf2/uf2cfg.h ++++ b/src/usb/uf2/uf2cfg.h +@@ -25,7 +25,11 @@ + // A UF2 block outside it is never written. A bootloader self-update is staged at the + // top of this window (BOOTLOADER_ADDR_NEW_RECIEVED below), so the application is + // flashed again after one. ++#ifdef VKEY_AS_APP ++#define USER_FLASH_START BOARD_TEST_SCRATCH // the on-board test build's window ++#else + #define USER_FLASH_START MBR_SIZE // skip MBR included in SD hex ++#endif + #define USER_FLASH_END BOARD_APP_FLASH_END + STATIC_ASSERT(USER_FLASH_END <= BOOTLOADER_REGION_START); + STATIC_ASSERT(USER_FLASH_END - DFU_BL_IMAGE_MAX_SIZE >= USER_FLASH_START); diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app.ld b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app.ld new file mode 100644 index 0000000..c59c2bf --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app.ld @@ -0,0 +1,68 @@ +/* The on-board test build (VKEY_AS_APP, test/app_test.c): this bootloader linked as an + * application at 0x1000, below the scratch window its drive writes (board/board.h). + * Otherwise upstream's linker/nrf52840.ld. The CF2 block keeps its address but is not + * loaded: the self-update path compares block addresses with it exactly as the + * bootloader does, and the image holds nothing at or above 0x40000. + */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x1000, LENGTH = 0x40000 - 0x1000 + + BOOTLOADER_CONFIG (r): ORIGIN = 0xFE000 - 2K, LENGTH = 2K + MBR_PARAMS_PAGE (rw) : ORIGIN = 0xFE000, LENGTH = 0x1000 + BOOTLOADER_SETTINGS (rw) : ORIGIN = 0xFF000, LENGTH = 0x1000 + + RAM (rwx) : ORIGIN = 0x20008000, LENGTH = 0x20040000-0x20008000 + DBL_RESET (rwx) : ORIGIN = 0x20007F7C, LENGTH = 0x04 + NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80 + + UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04 + UICR_MBR_PARAM_PAGE(r) : ORIGIN = 0x10001018, LENGTH = 0x04 +} + +SECTIONS +{ + .fs_data_out ALIGN(4): + { + PROVIDE( __start_fs_data = .); + KEEP(*(fs_data)) + PROVIDE( __stop_fs_data = .); + } = 0 + + .bootloaderConfig (NOLOAD) : + { + KEEP(*(.bootloaderConfig)) + } > BOOTLOADER_CONFIG + + .bootloaderSettings(NOLOAD) : + { + } > BOOTLOADER_SETTINGS + + .uicrBootStartAddress : + { + KEEP(*(.uicrBootStartAddress)) + } > UICR_BOOTLOADER + + .mbrParamsPage(NOLOAD) : + { + } > MBR_PARAMS_PAGE + + .uicrMbrParamsPageAddress : + { + KEEP(*(.uicrMbrParamsPageAddress)) + } > UICR_MBR_PARAM_PAGE + + .dbl_reset(NOLOAD) : + { + } > DBL_RESET + + .noinit(NOLOAD) : + { + } > NOINIT +} + +INCLUDE "nrf_common.ld" diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c new file mode 100644 index 0000000..e8d7a8d --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c @@ -0,0 +1,89 @@ +/* + * The on-board test of this bootloader fork (docs2/roadmap.md, phase 3, milestone 4). + * + * Built with VKEY_AS_APP (patches/0007-as-app.patch), the bootloader runs as an + * application from 0x1000 under the factory bootloader, which stays in place, so a + * failure here costs a replug with the button held. Before it serves its drive, it + * checks with the calls the bootloader itself makes: + * + * - the app the real signing pipeline signed, which test/board.py places in the + * scratch window with its slot, and the same slot with one bit of R flipped; + * - whatever a bootloader self-update, copied onto this build's own drive, left + * staged there. + * + * Each verdict and the cycles DWT counted for it go into INFO_UF2.TXT: with no serial + * port and no probe, the drive is the only way out. + */ + +#include +#include +#include +#include + +#include "nrf.h" +#include "app_util.h" +#include "boards.h" +#include "uf2/uf2.h" +#include "signature.h" + +/* Where test/board.py puts the app: the image, then its slot and the altered slot. */ +#define TEST_APP_IMAGE BOARD_TEST_SCRATCH +#define TEST_APP_SLOT (BOARD_TEST_SCRATCH + 0x20000) +#define TEST_APP_ALTERED (TEST_APP_SLOT + SIGNATURE_SLOT_SIZE) + +/* What the installed bootloader allows an app: everything up to its slot at 0x96000. */ +#define REAL_APP_MAX (0x96000 - MBR_SIZE) + +_Static_assert(TEST_APP_ALTERED + SIGNATURE_SLOT_SIZE <= BOOTLOADER_ADDR_NEW_RECIEVED, + "the test app overlaps the staging area"); +_Static_assert(USER_FLASH_END <= 0x97000, "the test window reaches the vault"); + +/* ghostfat.c: one sector, the header already in it. */ +extern char infoUf2File[]; +#define INFO_SIZE (512 - 1) + +__attribute__((format(printf, 1, 2))) +static void say(char const *format, ...) { + size_t const used = strlen(infoUf2File); + va_list args; + va_start(args, format); + vsnprintf(infoUf2File + used, INFO_SIZE - used, format, args); + va_end(args); +} + +static void check(char const *what, uint8_t const *image, uint8_t const *slot, + uint32_t kind, uint32_t max_length, bool exact, char const *want) { + uint32_t const start = DWT->CYCCNT; + bool const valid = signature_valid(image, slot, kind, max_length, exact); + uint32_t const cycles = DWT->CYCCNT - start; + char const *verdict = valid ? "accepted" : "refused"; + say("%s: %s, %lu cycles%s\r\n", what, verdict, (unsigned long) cycles, + want == NULL ? "" : strcmp(verdict, want) == 0 ? " - ok" : " - WRONG"); +} + +void app_test_run(void) { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CYCCNT = 0; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + + say("Test: as app at 0x%X, ICACHECNF 0x%lX\r\n", MBR_SIZE, + (unsigned long) NRF_NVMC->ICACHECNF); + + uint8_t const *image = (uint8_t const *) TEST_APP_IMAGE; + check("app", image, (uint8_t const *) TEST_APP_SLOT, SIGNATURE_KIND_APP, REAL_APP_MAX, + false, "accepted"); + check("app, R altered", image, (uint8_t const *) TEST_APP_ALTERED, SIGNATURE_KIND_APP, + REAL_APP_MAX, false, "refused"); + check("app as bootloader", image, (uint8_t const *) TEST_APP_SLOT, + SIGNATURE_KIND_BOOTLOADER, REAL_APP_MAX, false, "refused"); + + /* The same check msc_uf2.c makes before COPY_BL, on what the last copy staged. */ + uint8_t const *staged = (uint8_t const *) BOOTLOADER_ADDR_NEW_RECIEVED; + uint32_t const signed_length = DFU_BL_IMAGE_MAX_SIZE - SIGNATURE_SLOT_SIZE; + if (*(uint32_t const *) staged == 0xFFFFFFFF) { + say("staged update: none\r\n"); + } else { + check("staged update", staged, staged + signed_length, SIGNATURE_KIND_BOOTLOADER, + signed_length, true, NULL); + } +} diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.py b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.py new file mode 100644 index 0000000..ede2b90 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.py @@ -0,0 +1,103 @@ +"""The UF2s of the on-board test (test/app_test.c), from what the real pipeline made: + + board.py AS_APP.bin APP.uf2 BOOTLOADER.uf2 OUTDIR + +APP.uf2 and BOOTLOADER.uf2 come from sign.sh. Writes into OUTDIR: + + m4.uf2 for the factory bootloader's drive: the test build at 0x1000, and + APP.uf2's image and slot moved into the scratch window where + app_test.c looks, with a second copy of the slot that has one bit of + the signature's R flipped. The signature covers the slot header and + the image, never their addresses, so moving them keeps it valid. + bl-altered.uf2 BOOTLOADER.uf2 with one bit flipped at 0xF4110, a vector-table word + no interrupt uses: the signature covers every byte, used or not. For + the test build's own drive; it must be staged and then refused. +""" + +import struct +import sys +from pathlib import Path + +BLOCK = 256 +UF2_BLOCK = 512 +FAMILY_APP = 0xADA52840 +FAMILY_BOOT = 0xD663823C +UF2_MAGIC = (0x0A324655, 0x9E5D5157, 0x0AB16F30) +UF2_FAMILY_FLAG = 0x2000 + +APP_BASE = 0x1000 +APP_SLOT = 0x96000 # signed_image.py, kind app +# app_test.c: TEST_APP_IMAGE, TEST_APP_SLOT, TEST_APP_ALTERED +TEST_IMAGE = 0x40000 +TEST_SLOT = 0x60000 +TEST_ALTERED = TEST_SLOT + BLOCK +SIGNATURE_R = 0x40 + + +def blocks_of(uf2: bytes) -> list[tuple[int, int, bytes]]: + out = [] + for i in range(0, len(uf2), UF2_BLOCK): + m0, m1, _, addr, size, _, _, family = struct.unpack_from("<8I", uf2, i) + assert (m0, m1) == UF2_MAGIC[:2] and size == BLOCK, f"not a UF2 block at {i}" + out.append((family, addr, uf2[i + 32:i + 32 + BLOCK])) + return out + + +def uf2(blocks: list[tuple[int, bytes]], family: int) -> bytes: + out = bytearray() + for n, (addr, data) in enumerate(blocks): + assert len(data) == BLOCK and addr % BLOCK == 0 + head = struct.pack("<8I", UF2_MAGIC[0], UF2_MAGIC[1], UF2_FAMILY_FLAG, addr, BLOCK, + n, len(blocks), family) + out += head + data.ljust(476, b"\0") + struct.pack(" bytes: + return data[:at] + bytes([data[at] ^ 1]) + data[at + 1:] + + +def m4(as_app: bytes, app: list[tuple[int, int, bytes]]) -> bytes: + if APP_BASE + len(as_app) > TEST_IMAGE: + raise SystemExit("the test build reaches its scratch window") + padded = as_app.ljust(-(-len(as_app) // BLOCK) * BLOCK, b"\xff") + blocks = [(APP_BASE + i, padded[i:i + BLOCK]) for i in range(0, len(padded), BLOCK)] + slot = None + for family, addr, data in app: + assert family == FAMILY_APP + if addr == APP_SLOT: + slot = data + elif TEST_IMAGE + addr - APP_BASE + BLOCK <= TEST_SLOT: + blocks.append((TEST_IMAGE + addr - APP_BASE, data)) + else: + raise SystemExit(f"the app reaches past {TEST_SLOT:#x} once moved") + if slot is None: + raise SystemExit("the app UF2 has no slot") + blocks += [(TEST_SLOT, slot), (TEST_ALTERED, flip(slot, SIGNATURE_R))] + return uf2(blocks, FAMILY_APP) + + +def altered(bootloader: list[tuple[int, int, bytes]]) -> bytes: + # 0xF4110: past the 48 interrupts the vector table serves, well before the CF2 page + # and the slot. + assert all(family == FAMILY_BOOT for family, _, _ in bootloader) + blocks = [(addr, flip(data, 0x10) if n == 1 else data) + for n, (_, addr, data) in enumerate(bootloader)] + return uf2(blocks, FAMILY_BOOT) + + +def main() -> int: + if len(sys.argv) != 5: + print(__doc__, file=sys.stderr) + return 2 + as_app = Path(sys.argv[1]).read_bytes() + app = blocks_of(Path(sys.argv[2]).read_bytes()) + bootloader = blocks_of(Path(sys.argv[3]).read_bytes()) + out = Path(sys.argv[4]) + (out / "m4.uf2").write_bytes(m4(as_app, app)) + (out / "bl-altered.uf2").write_bytes(altered(bootloader)) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.sh new file mode 100755 index 0000000..b945ba1 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# +# The on-board test (test/app_test.c, docs2/roadmap.md phase 3, milestone 4): +# +# board.sh make TEST.pem OUTDIR sign with the test key and write the test's UF2s +# into OUTDIR, the output of a test-key build: +# app.uf2, bl.uf2, m4.uf2, bl-altered.uf2 +# board.sh copy FILE.uf2 copy one onto the drive it is meant for, or refuse +# +# bl.uf2 is a real self-update: signed for a bootloader that trusts the test key, with +# the board ID and UICR words the factory bootloader checks. On the factory drive it +# would be installed, and the board would then trust a key that lives in a file. So +# `copy` reads the target's INFO_UF2.TXT first: a bootloader-family UF2 goes only to the +# test build's drive (VKEYTEST, "Test: as app"), an app-family one only to the factory +# bootloader's (UF2BOOT, "UF2 Bootloader 0.7.1"). + +set -euo pipefail + +here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +usage() { sed -n '3,15p' "$0" >&2; exit 2; } + +make_uf2s() { + local key="$1" out="$2" image + image="$here/../../images/vaultkey.bin" + [[ -f "$out/as-app.bin" && -f "$out/bootloader.bin" ]] \ + || { echo "$out has no as-app.bin: build with BOOTLOADER_TEST_KEY first" >&2; exit 1; } + "$here/../sign.sh" app 1 "$image" "$key" "$out/app.uf2" + ALLOW_TEST_KEY=1 "$here/../sign.sh" bootloader 1 "$out/bootloader.bin" "$key" "$out/bl.uf2" + python3 -I "$here/board.py" "$out/as-app.bin" "$out/app.uf2" "$out/bl.uf2" "$out" + ls -l "$out"/*.uf2 +} + +copy_uf2() { + local file="$1" family mount marker + family="$(od -An -tx4 -j28 -N4 "$file" | tr -d ' ')" + case "$family" in + d663823c) mount="/media/$USER/VKEYTEST" marker='^Test: as app' ;; + ada52840) mount="/media/$USER/UF2BOOT" marker='^UF2 Bootloader 0\.7\.1 ' ;; + *) echo "$file: UF2 family $family is not this test's" >&2; exit 1 ;; + esac + grep -q "$marker" "$mount/INFO_UF2.TXT" 2>/dev/null \ + || { echo "$file goes only to $mount, whose INFO_UF2.TXT matches '$marker'" >&2; exit 1; } + cp "$file" "$mount/" + timeout 20 sync || true + echo "$(basename "$file") copied to $mount" +} + +case "${1:-}" in + make) [[ $# -eq 3 ]] || usage; make_uf2s "$2" "$3" ;; + copy) [[ $# -eq 2 ]] || usage; copy_uf2 "$2" ;; + *) usage ;; +esac From 36d3614c520c6bd9b9f87a16083f68abfc13457b Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 21:32:18 +0300 Subject: [PATCH 07/33] Add tools for the UF2 bootloader fork's real signing key --- .githooks/pre-commit | 2 +- .gitignore | 6 +- CLAUDE.md | 18 +++-- docs/threat-model.md | 14 +++- docs2/roadmap.md | 64 ++++++++++++++--- .../bootloader/sign-vaultkey.sh | 51 ++++++++++++++ .../nrf52840-mdk-dongle/bootloader/sign.sh | 8 +-- .../bootloader/signed_image.py | 23 ++++++ .../bootloader/signing-key.sh | 70 +++++++++++++++++++ tools/build-bootloader.sh | 26 +++++-- tools/checks.sh | 51 +++++++++++++- 11 files changed, 304 insertions(+), 29 deletions(-) create mode 100755 firmware/boards/nrf52840-mdk-dongle/bootloader/sign-vaultkey.sh create mode 100755 firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh diff --git a/.githooks/pre-commit b/.githooks/pre-commit index bb80890..3e0422e 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -11,7 +11,7 @@ ROOT="$(git rev-parse --show-toplevel)" # shellcheck source=tools/checks.sh . "$ROOT/tools/checks.sh" -paths=('*.rs' '*.toml' '*.lock' '*.sh' '*.py' '.githooks/*' 'firmware/boards/*/images/*') +paths=('*.rs' '*.toml' '*.lock' '*.sh' '*.py' '*.pem' '.githooks/*' 'firmware/boards/*/images/*') git diff --cached --quiet && fail "nothing staged" diff --git a/.gitignore b/.gitignore index 690d6b8..a541b76 100644 --- a/.gitignore +++ b/.gitignore @@ -6,11 +6,13 @@ __pycache__/ .mypy_cache/ # Keys, should any ever appear in the tree: they do not belong in the repository. -# The one exception is the public half of the firmware signing key -# (tools/signing-key.sh) - it is not a secret. +# The exceptions are the public halves of signing keys - the firmware's +# (tools/signing-key.sh) and a bootloader fork's (bootloader/signing-key.sh in a board +# folder, which the git hooks check holds nothing more). Neither is a secret. *.key *.pem !firmware/secure-boot/public.pem +!firmware/boards/*/bootloader/signing-key.pem *.vkb # Editors diff --git a/CLAUDE.md b/CLAUDE.md index 1e250c1..05599c1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -322,14 +322,22 @@ back from the factory binary, a patch series, a pinned Arm toolchain, all in Doc immediate or a movw/movt pair; like the radio search, not one computed from another base plus an offset. The fork runs only images signed with one Ed25519 key, checked on every boot (`bootloader/src/signature.c`, tested under qemu-arm by `bootloader/test/run.sh` -before every build); `bootloader/sign.sh` makes the signed UF2. The build needs -`bootloader/signing-key.pem`, or `BOOTLOADER_TEST_KEY` for a build that names itself a -test build. A test-key build also makes `as-app.bin`: the same sources as an application +before every build); `bootloader/sign.sh` makes the signed UF2. The real key is made +once by `bootloader/signing-key.sh` and lives on the nRF itself as the `.env` +`vkey-signing-nrf`, with a `.vkb` as the second copy. Its public half, +`bootloader/signing-key.pem`, is committed. `bootloader/sign-vaultkey.sh` signs +`images/vaultkey.bin`, and `images/bootloader.bin` once there, into `*.signed.uf2` (PIN +and a tap). A hook (`check_signed_uf2`) checks each against its unsigned twin and the +pem, and checks that `bootloader.bin` names that key. So once the pem exists, every +firmware change is signed again too. The build needs the pem, or `BOOTLOADER_TEST_KEY` +for a build that names itself a test build; either is refused if it holds more than a +public key. A test-key build also makes `as-app.bin`: the same sources as an application at 0x1000 that runs under the factory bootloader and reports its verdicts in `INFO_UF2.TXT` (`bootloader/test/app_test.c`). `bootloader/test/board.sh copy` puts a UF2 only on the drive it is meant for: a bootloader UF2 on the factory `UF2BOOT` would be -installed. Until the fork is installable the outputs stay in a temporary directory, and -installing it is never part of a build (`docs2/roadmap.md`, phase 3). +installed. A real-key build writes `images/bootloader.bin`, which no `board.toml` names. +A test build's outputs stay in a temporary directory. Installing the fork is never part +of a build (`docs2/roadmap.md`, phase 3). Compilation is the **only** exception to the check rule. Linters, formatters, tests and static analysers are not run without a direct request: git hooks in `.githooks/` diff --git a/docs/threat-model.md b/docs/threat-model.md index 67ed4a9..dfc064e 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -5,7 +5,8 @@ > There is no sale today, and the document holds all the same: the owner must not rely > on guarantees the device does not give. -Last reviewed 2026-09-12; the nRF52840 board section added 2026-10-13. Revisited on every +Last reviewed 2026-09-12; the nRF52840 board section added 2026-10-13, its signing key +2026-10-14. Revisited on every hardware or firmware change. Reporting policy: [`SECURITY.md`](../SECURITY.md). Board details: [`docs/hardware.md`](hardware.md). @@ -35,6 +36,17 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure Firmware that records the PIN on its next use is one file copy away. - **`vkey auth` does not exist here.** Its secret is sealed under the chip key, and the CLI refuses to enable it. +- **The bootloader fork's signing key lives on this board.** It is the `.env` + `vkey-signing-nrf`, made by `bootloader/signing-key.sh`, with a `.vkb` as its second + copy. Everything above applies to it: + - until the fork is installed, `CURRENT.UF2` and the offline PIN search hand it to anyone + who holds the board for a minute and then computes for a few hours; + - after that, SWD does the same until APPROTECT, and the glitch after that. + + Whoever has the key signs firmware the fork runs. By design, the fork moves to a new key + only through a self-update signed with the old one. A leak is mended only while the + owner still holds the key. So the time from making the key to installing the fork is + kept short. - **A backup made on this board uses its own cost** (20 passes). It is still guarded by the passphrase's entropy, at less than half the C6's work per guess. diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 2e5103d..34479a9 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -328,6 +328,29 @@ Milestones, one commit each: is an open speed-up, not done. The vkey firmware was then restored from its signed UF2 through the factory bootloader, which runs it with the slot at 0x96000: the first install step, rehearsed with the test key. +5. The real key's tools. **Written 2026-10-14; the key is not made yet.** + - **`bootloader/signing-key.sh`** makes the Ed25519 key on tmpfs and stores it on the + board as the `.env` `vkey-signing-nrf`. It talks to the board through the firmware's + own port, so a C6 plugged in beside it never gets the key. It needs a PIN on the board + first, writes `signing-key.pem` and prints the fingerprint. + - **`bootloader/sign-vaultkey.sh`** takes the key off the board (PIN, one tap). It + refuses the key unless its public half is `signing-key.pem`. It then signs + `images/vaultkey.bin`, and `images/bootloader.bin` once there, into `*.signed.uf2`. + Both are signed as version 1, since the field is not compared yet. + - **`tools/build-bootloader.sh`** refuses a key file that is not exactly a public + Ed25519 key before it reaches Docker. A build with the real key writes + `images/bootloader.bin`. + - **The hook's `check_signed_uf2`** makes four checks: + - the pem is a public Ed25519 key and nothing else; + - each UF2, rebuilt from its unsigned twin with the version and signature from its own + slot (`signed_image.py verify`), matches byte for byte; + - the signature verifies under the pem; + - `bootloader.bin`'s INFO line is `Key: `, with no `TEST KEY`. + + Tried on the milestone-4 files and on a real-key-mode build with the test key. It + passes on those, and fails on a stale image, an altered UF2, a test-key bootloader, a + foreign key, and a private, mixed or empty pem. + - **`board.toml` names none of these files**, so the CLI embeds none of them. Install needs its own go and a checklist: @@ -335,16 +358,39 @@ Install needs its own go and a checklist: - `SystemInit` disassembled; - the board ID confirmed; - the update padded to the whole region; -- the UF2 actually installed is checked block by block. Every target address falls in the - MBR, 0xF4000..0xFE000, the settings page at 0xFF000 or the two UICR words, and its - 0xF4000.. payload equals the checked `bootloader.bin`; -- the MBR: the update carries Nordic's MBR 2.4.1 and a whole settings page. Read in the - update handler what happens to those blocks, and compare the chip's own MBR (the app can - read 0x0..0xB00) with 2.4.1; +- the UF2 actually installed is checked block by block. It has 161 blocks: + - 159 of the bootloader at 0xF4000..0xFDF00; + - its slot at 0xFDF00; + - one UICR block with the two words already on the chip. + + There is no MBR and no settings page in it, and its 0xF4000.. payload equals the checked + `bootloader.bin`; +- the factory bootloader's handling of it. In the published 0.7.1 hex, the handler writes + each block 0x14000 lower, to 0xE0000..0xEA000. That is the reserve above the vault, not + the vault. It calls `COPY_BL` only if the staged image differs from the running one. + Still open: the chip's own bootloader against that hex, and its MBR against 2.4.1. The + as-app build can read both; - the key reachable from two places, and `signing-key.pem` committed with its - fingerprint recorded here; -- the bootloader being installed names that fingerprint in its INFO text, not "TEST KEY" - (`sign.sh` refuses a test-key bootloader unless told); + fingerprint recorded here (not made yet): + - the `.vkb` is made right after the key; + - prove it by restoring it onto the same board and signing again. Ed25519 is + deterministic, so `images/` must not change; + - restoring it onto the C6, the decided second home, comes only after a `.vkb` of the + C6 holding `vkey-signing` exists. A restore replaces everything on the board, + `vkey-signing` included. `sign-vaultkey.sh` talks only to this board, so signing from + the C6 needs a change made at that point; + - the commit that brings the key carries `signing-key.pem`, `images/vaultkey.signed.uf2` + and the fingerprint here together. Once the pem is tracked, the hook demands the + signed UF2; +- the bootloader being installed names that fingerprint in its INFO text, not "TEST KEY". + `sign.sh` refuses a test-key bootloader unless told, and the hook refuses one in + `images/`; +- `images/bootloader.bin` is what the committed sources and pem build: + `tools/build-bootloader.sh` again, then `git diff --exit-code`. The hook does not + rebuild it; +- the time from making the key to installing the fork kept short. Until the fork is in, + `CURRENT.UF2` hands the vault, key included, to anyone holding the board + (`docs/threat-model.md`); - the order: first copy the signed app (real key) through the factory bootloader and confirm it boots under it. Then install the fork, and the board must boot straight into that app. If it stays in DFU mode instead, copying the signed app UF2 again is diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/sign-vaultkey.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/sign-vaultkey.sh new file mode 100755 index 0000000..48179fc --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/sign-vaultkey.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# +# Sign this board's images for its bootloader fork with the key that lives on the board. +# +# bootloader/sign-vaultkey.sh +# +# Writes next to each image in images/ its signed UF2: vaultkey.signed.uf2, the app to +# copy onto the drive, and bootloader.signed.uf2, the fork's self-update, once a build +# with the real key has left bootloader.bin there. The unsigned images stay what the git +# hooks compare the UF2s against; the signatures they verify under signing-key.pem, +# which needs no secret. Signing itself needs the key: the PIN and one tap. +# +# The private key comes off the board into tmpfs for the seconds of signing and is +# removed; see signing-key.sh for where it lives. + +set -euo pipefail + +here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +board="$(basename "$(dirname "$here")")" +images="$(dirname "$here")/images" +PUBLIC="$here/signing-key.pem" +NAME="vkey-signing-nrf" +# The firmware's own USB identity (src/main.rs), as in signing-key.sh. +PORT="/dev/serial/by-id/usb-vaulttecdev_vkey-if00" +vk() { vkey --port "$PORT" "$@"; } + +for tool in openssl vkey base64 python3; do + command -v "$tool" >/dev/null || { echo "$tool is missing" >&2; exit 1; } +done +[[ -f "$PUBLIC" ]] || { echo "no $PUBLIC: run signing-key.sh first" >&2; exit 1; } +[[ -d /dev/shm ]] || { echo "no /dev/shm: the key would have to touch the disk" >&2; exit 1; } +[[ -f "$images/vaultkey.bin" ]] || { echo "no images/vaultkey.bin - build first" >&2; exit 1; } +grep -qE "^device:.* $board\$" <<<"$(vk info)" || { echo "$PORT is not $board" >&2; exit 1; } + +tmp="$(mktemp -d /dev/shm/vkey-sign.XXXXXX)" +trap 'rm -rf "$tmp"' EXIT + +echo "the signing key comes off $board: PIN if asked, then one tap" +vk get "$NAME" | sed -n 's/^SIGNING_KEY=//p' | base64 -d \ + | openssl pkey -inform DER -out "$tmp/key.pem" 2>/dev/null +# sign.sh signs with whatever key it is given and checks only against that key's own +# public half; a UF2 signed by any other key than the one the fork trusts is refused. +openssl pkey -in "$tmp/key.pem" -pubout | cmp -s - "$PUBLIC" \ + || { echo "'$NAME' on $board is not the key in signing-key.pem" >&2; exit 1; } + +# The slot's version is carried and signed but not compared yet (src/signature.h). +"$here/sign.sh" app 1 "$images/vaultkey.bin" "$tmp/key.pem" "$images/vaultkey.signed.uf2" +if [[ -f "$images/bootloader.bin" ]]; then + "$here/sign.sh" bootloader 1 "$images/bootloader.bin" "$tmp/key.pem" "$images/bootloader.signed.uf2" +fi +echo "commit the signed UF2s with the images they sign" diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/sign.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/sign.sh index 4c5fbce..7b81cb6 100755 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/sign.sh +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/sign.sh @@ -6,10 +6,10 @@ # sign.sh app VERSION images/vaultkey.bin PRIVATE.pem OUT.uf2 # sign.sh bootloader VERSION bootloader.bin PRIVATE.pem OUT.uf2 # -# PRIVATE.pem is an Ed25519 private key. tools/sign-vaultkey.sh fetches the real one -# from the vkey into tmpfs and calls this; a test key works the same way, and the -# bootloader built with its public half (BOOTLOADER_TEST_KEY) is the only one that -# accepts the result. The signature is checked against the key's public half before +# PRIVATE.pem is an Ed25519 private key. sign-vaultkey.sh next to this file fetches +# the real one from the board into tmpfs and calls this; a test key works the same way, +# and the bootloader built with its public half (BOOTLOADER_TEST_KEY) is the only one +# that accepts the result. The signature is checked against the key's public half before # the UF2 is written, so a bad signature never reaches a file. set -euo pipefail diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/signed_image.py b/firmware/boards/nrf52840-mdk-dongle/bootloader/signed_image.py index 7b895a8..bd5cb63 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/signed_image.py +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/signed_image.py @@ -5,6 +5,10 @@ its fixed length). Sign it with openssl pkeyutl -sign -rawin. signed_image.py uf2 KIND VERSION IMAGE SIGNATURE OUT writes the UF2 to copy to the drive: the image and its slot. + signed_image.py verify KIND IMAGE SIGNED OUTDIR + fails unless SIGNED is exactly what `uf2` makes of IMAGE with the version and + signature in SIGNED's own slot, then writes OUTDIR/message and OUTDIR/signature + for openssl pkeyutl -verify -rawin. The git hooks run it. KIND is `app` (images/vaultkey.bin, flashed from 0x1000) or `bootloader` (the build's bootloader.bin, from 0xF4000). Only the private key is outside this file: the signature @@ -89,6 +93,15 @@ def build_uf2(k: Kind, version: int, image: bytes, signature: bytes) -> bytes: return uf2(blocks, k.family) +def slot_of(k: Kind, signed: bytes) -> tuple[int, bytes]: + """The version and signature in a signed UF2's slot block.""" + for at in range(0, len(signed) - 511, 512): + if struct.unpack_from(" int: args = sys.argv[1:] if len(args) == 5 and args[0] == "message": @@ -101,6 +114,16 @@ def main() -> int: image = image_for(k, Path(args[3]).read_bytes()) Path(args[5]).write_bytes(build_uf2(k, version, image, Path(args[4]).read_bytes())) return 0 + if len(args) == 5 and args[0] == "verify": + k = kind_of(args[1]) + image = image_for(k, Path(args[2]).read_bytes()) + signed = Path(args[3]).read_bytes() + version, signature = slot_of(k, signed) + if build_uf2(k, version, image, signature) != signed: + raise SystemExit(f"{args[3]} is not {args[2]} plus its slot: it was signed from another image") + Path(args[4], "message").write_bytes(header(k, version, image) + image) + Path(args[4], "signature").write_bytes(signature) + return 0 print(__doc__, file=sys.stderr) return 2 diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh new file mode 100755 index 0000000..9c57dff --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# +# The signing key of this board's bootloader fork: made once, kept on the board itself. +# +# bootloader/signing-key.sh generate it, store it on the board, write its public half +# +# The private key never reaches the disk. It is an Ed25519 key generated on tmpfs, +# stored on the board as the .env `vkey-signing-nrf` (one line: SIGNING_KEY=), and the tmpfs copy is removed. Signing then takes the key and a tap +# (sign-vaultkey.sh). The second copy is the owner's `vkey backup` file. +# +# The public half lands in signing-key.pem and is committed: the bootloader build +# compiles it in, and the git hooks verify signed UF2s with it. Neither is secret. Its +# fingerprint, printed at the end and shown by the fork's INFO_UF2.TXT, goes into +# docs2/roadmap.md. +# +# Once a bootloader that trusts this key is installed, losing the private key freezes +# the board - no firmware and no bootloader update ever again - so run `vkey backup` +# right after this and keep the backup passphrase somewhere other than the backup file. + +set -euo pipefail + +here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +board="$(basename "$(dirname "$here")")" +PUBLIC="$here/signing-key.pem" +NAME="vkey-signing-nrf" +# The firmware's own USB identity (src/main.rs): with the C6 plugged in too, the CLI +# would refuse to guess, and the key must never land on the other board. +PORT="/dev/serial/by-id/usb-vaulttecdev_vkey-if00" +vk() { vkey --port "$PORT" "$@"; } + +for tool in openssl vkey base64; do + command -v "$tool" >/dev/null || { echo "$tool is missing" >&2; exit 1; } +done +[[ -d /dev/shm ]] || { echo "no /dev/shm: the key would have to touch the disk" >&2; exit 1; } +if [[ -e "$PUBLIC" ]]; then + echo "$PUBLIC exists: the signing key was made already." >&2 + echo "A second one would not be the key a built bootloader trusts." >&2 + exit 1 +fi + +# Captured first: grep -q on a pipe can close it under the CLI, which then fails. +info="$(vk info)" +grep -qE "^device:.* $board\$" <<<"$info" || { echo "$PORT is not $board" >&2; exit 1; } +grep -qE '^pin: +set,' <<<"$info" || { echo "$board has no PIN yet: vkey --port $PORT pin set" >&2; exit 1; } + +# The device must be open before the blob is piped in: with stdin taken by the blob, +# the CLI has nowhere to read a PIN from. +grep -q '^unlocked: true' <<<"$(vk pin status)" || vk pin unlock +if grep -qE "^$NAME\s" <<<"$(vk list)"; then + echo "$board already holds '$NAME'" >&2 + exit 1 +fi + +tmp="$(mktemp -d /dev/shm/vkey-signing.XXXXXX)" +trap 'rm -rf "$tmp"' EXIT + +echo "generating an Ed25519 key" +openssl genpkey -algorithm ed25519 -out "$tmp/key.pem" +der="$(openssl pkey -in "$tmp/key.pem" -outform DER | base64 -w0)" + +echo "storing it on $board as '$NAME'" +printf 'SIGNING_KEY=%s\n' "$der" | vk env add "$NAME" >/dev/null +unset der + +openssl pkey -in "$tmp/key.pem" -pubout -out "$PUBLIC" +echo "public key: bootloader/signing-key.pem, fingerprint" \ + "$(openssl pkey -pubin -in "$PUBLIC" -outform DER | tail -c 32 | sha256sum | cut -c1-16)" +echo +echo "next: vkey --port $PORT backup - the backup is now the only other copy" diff --git a/tools/build-bootloader.sh b/tools/build-bootloader.sh index 4c876d5..211119e 100755 --- a/tools/build-bootloader.sh +++ b/tools/build-bootloader.sh @@ -28,9 +28,10 @@ # commit with bootloader/'s board definition and patches, built and checked by # bootloader/build.sh in bootloader/Dockerfile. It trusts one Ed25519 public key: # bootloader/signing-key.pem, or with BOOTLOADER_TEST_KEY= a throwaway key, which -# INFO_UF2.TXT then names as a test key. Until the fork is installable -# (docs2/roadmap.md, phase 3) the outputs stay in a temporary directory: nothing goes -# into images/, and nothing is installed. +# INFO_UF2.TXT then names as a test key. Either must be a public key and nothing else. +# A build with the real key copies bootloader.bin into images/, for bootloader/ +# sign-vaultkey.sh to sign and the git hooks to check; a test build leaves its outputs +# in a temporary directory. Nothing is ever installed (docs2/roadmap.md, phase 3). set -euo pipefail @@ -38,7 +39,9 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" BOARDS="$ROOT/firmware/boards" IDF_IMAGE="espressif/idf:v5.5" -command -v docker >/dev/null || { echo "docker is missing" >&2; exit 1; } +for tool in docker openssl; do + command -v "$tool" >/dev/null || { echo "$tool is missing" >&2; exit 1; } +done toml_value() { grep -E "^$2\s*=" "$1" | head -1 | cut -d'"' -f2; } build_esp() { @@ -100,6 +103,13 @@ build_uf2() { echo " a test build: BOOTLOADER_TEST_KEY= $0" >&2 exit 1 } + # Checked before it is mounted into the build: a file equal to its own public + # re-encoding holds no private key. + if [[ "$(openssl pkey -pubin -in "$key" -noout -text 2>/dev/null)" != "ED25519 Public-Key:"* ]] \ + || ! openssl pkey -pubin -in "$key" 2>/dev/null | cmp -s - "$key"; then + echo "$name: $key must be an Ed25519 public key and nothing else" >&2 + exit 1 + fi docker build -q -t "vkey-bootloader-$name" "$dir/bootloader" >/dev/null out="$(mktemp -d)" log="$out/build.log" @@ -114,7 +124,13 @@ build_uf2() { fi grep -E "^ *(FLASH|BOOTLOADER_CONFIG):|^check:|^signature test:|^key:" "$log" || true (cd "$out" && sha256sum bootloader.bin) - echo "$name: outputs in $out - not installed, not copied into images/" + if [[ "$kind" == real ]]; then + cp "$out/bootloader.bin" "$dir/images/bootloader.bin" + echo "$name: images/bootloader.bin (the rest in $out), not installed" + echo "sign it next: firmware/boards/$name/bootloader/sign-vaultkey.sh" + else + echo "$name: outputs in $out - a test build, not installed, not copied into images/" + fi } if [[ -n "${BOARD:-}" ]]; then diff --git a/tools/checks.sh b/tools/checks.sh index 87f7204..41d99ed 100755 --- a/tools/checks.sh +++ b/tools/checks.sh @@ -4,8 +4,8 @@ # the hook at the first failure and says what to do. # # pre-commit fmt, clippy, rustdoc, tests, shellcheck, mypy, lint tables, no radio, -# forbidden marketing claims, and the firmware image must be the one -# these sources build +# forbidden marketing claims, the firmware image must be the one these +# sources build, and every signed image must be signed from it # pre-push the same on a clean tree and only for HEAD, so what is pushed is what # was checked # @@ -138,6 +138,52 @@ check_signed_images() { done } +# A board's UF2 bootloader fork runs only images signed with one Ed25519 key, whose +# public half the board commits as bootloader/signing-key.pem. Checked without the +# secret: that file is a public key and nothing more, every signed UF2 is its unsigned +# twin plus a slot whose signature verifies under it, and a bootloader.bin trusts that +# key and not a test one - installed, a bootloader trusting the wrong key freezes the board. +check_signed_uf2() { + step "signed UF2s match their unsigned twins and bootloader/signing-key.pem" + local pem dir name signed plain kind tmp fp ok + for pem in "$ROOT"/firmware/boards/*/bootloader/signing-key.pem; do + [[ -f "$pem" ]] || continue + dir="$(dirname "$(dirname "$pem")")" + name="$(basename "$dir")" + # A file equal to its own public re-encoding holds no private key. + if [[ "$(openssl pkey -pubin -in "$pem" -noout -text 2>/dev/null)" != "ED25519 Public-Key:"* ]] \ + || ! openssl pkey -pubin -in "$pem" 2>/dev/null | cmp -s - "$pem"; then + fail "$name: bootloader/signing-key.pem must be an Ed25519 public key and nothing else" + fi + [[ -f "$dir/images/vaultkey.signed.uf2" ]] \ + || fail "$name: no images/vaultkey.signed.uf2: bootloader/sign-vaultkey.sh" + for signed in "$dir"/images/*.signed.uf2; do + plain="${signed%.signed.uf2}.bin" + case "$(basename "$plain")" in + vaultkey.bin) kind=app ;; + bootloader.bin) kind=bootloader ;; + *) fail "$name: $(basename "$signed") is neither the app nor the bootloader" ;; + esac + [[ -f "$plain" ]] || fail "$name: $(basename "$signed") has no unsigned twin" + tmp="$(mktemp -d)" + ok=0 + if python3 -I "$dir/bootloader/signed_image.py" verify "$kind" "$plain" "$signed" "$tmp" >/dev/null 2>&1 \ + && openssl pkeyutl -verify -pubin -inkey "$pem" -rawin -in "$tmp/message" \ + -sigfile "$tmp/signature" >/dev/null 2>&1; then + ok=1 + fi + rm -rf "$tmp" + ((ok)) || fail "$name: $(basename "$signed") is stale or not signed by bootloader/signing-key.pem: bootloader/sign-vaultkey.sh" + done + [[ -f "$dir/images/bootloader.bin" ]] || continue + # INFO_UF2.TXT names the key the build compiled in; a test key's line goes on + # with " TEST KEY" before it ends. + fp="$(openssl pkey -pubin -in "$pem" -outform DER | tail -c 32 | sha256sum | cut -c1-16)" + grep -qa "^Key: $fp"$'\r$' "$dir/images/bootloader.bin" \ + || fail "$name: images/bootloader.bin does not trust bootloader/signing-key.pem ($fp)" + done +} + # docs/threat-model.md calls breaking its wording rules a failure of the project, by the # definition the project gave itself. Only claims that can never be true here are matched: # phishing, certification and FIDO appear throughout the docs as denials ("does not @@ -176,4 +222,5 @@ check_all() { check_wording check_images check_signed_images + check_signed_uf2 } From 2ba479c1a48b77707dce7363475206ae63d239c0 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 21:58:06 +0300 Subject: [PATCH 08/33] Add the nRF52840 bootloader fork's real signing key --- docs/threat-model.md | 4 ++-- docs2/roadmap.md | 14 ++++++++++---- .../bootloader/signing-key.pem | 3 +++ .../nrf52840-mdk-dongle/images/bootloader.bin | Bin 0 -> 39000 bytes .../images/bootloader.signed.uf2 | Bin 0 -> 82432 bytes .../images/vaultkey.signed.uf2 | Bin 0 -> 155136 bytes 6 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.pem create mode 100755 firmware/boards/nrf52840-mdk-dongle/images/bootloader.bin create mode 100644 firmware/boards/nrf52840-mdk-dongle/images/bootloader.signed.uf2 create mode 100644 firmware/boards/nrf52840-mdk-dongle/images/vaultkey.signed.uf2 diff --git a/docs/threat-model.md b/docs/threat-model.md index dfc064e..5786bd8 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -37,8 +37,8 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure - **`vkey auth` does not exist here.** Its secret is sealed under the chip key, and the CLI refuses to enable it. - **The bootloader fork's signing key lives on this board.** It is the `.env` - `vkey-signing-nrf`, made by `bootloader/signing-key.sh`, with a `.vkb` as its second - copy. Everything above applies to it: + `vkey-signing-nrf`, made by `bootloader/signing-key.sh` on 2026-10-14 (fingerprint + `a1700ebd539b0bfc`), with a `.vkb` as its second copy. Everything above applies to it: - until the fork is installed, `CURRENT.UF2` and the offline PIN search hand it to anyone who holds the board for a minute and then computes for a few hours; - after that, SWD does the same until APPROTECT, and the glitch after that. diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 34479a9..7285272 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -328,7 +328,8 @@ Milestones, one commit each: is an open speed-up, not done. The vkey firmware was then restored from its signed UF2 through the factory bootloader, which runs it with the slot at 0x96000: the first install step, rehearsed with the test key. -5. The real key's tools. **Written 2026-10-14; the key is not made yet.** +5. The real key's tools. **Written 2026-10-14; the key was made the same day, fingerprint + `a1700ebd539b0bfc`.** - **`bootloader/signing-key.sh`** makes the Ed25519 key on tmpfs and stores it on the board as the `.env` `vkey-signing-nrf`. It talks to the board through the firmware's own port, so a C6 plugged in beside it never gets the key. It needs a PIN on the board @@ -351,6 +352,11 @@ Milestones, one commit each: passes on those, and fails on a stale image, an altered UF2, a test-key bootloader, a foreign key, and a private, mixed or empty pem. - **`board.toml` names none of these files**, so the CLI embeds none of them. + - **The key itself**, 2026-10-14: made on the board, then a `.vkb` of it at once. + The `.vkb` was restored onto the same board and `vaultkey.signed.uf2` signed again + came out byte for byte the same. `images/bootloader.bin` was built with + `signing-key.pem`: its INFO line names `a1700ebd539b0bfc`, and the raw key is in it + once. Not installed. Install needs its own go and a checklist: @@ -371,10 +377,10 @@ Install needs its own go and a checklist: Still open: the chip's own bootloader against that hex, and its MBR against 2.4.1. The as-app build can read both; - the key reachable from two places, and `signing-key.pem` committed with its - fingerprint recorded here (not made yet): - - the `.vkb` is made right after the key; + fingerprint recorded here, `a1700ebd539b0bfc`: + - the `.vkb` is made right after the key (done 2026-10-14); - prove it by restoring it onto the same board and signing again. Ed25519 is - deterministic, so `images/` must not change; + deterministic, so `images/` must not change (done 2026-10-14); - restoring it onto the C6, the decided second home, comes only after a `.vkb` of the C6 holding `vkey-signing` exists. A restore replaces everything on the board, `vkey-signing` included. `sign-vaultkey.sh` talks only to this board, so signing from diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.pem b/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.pem new file mode 100644 index 0000000..b9ac2ad --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.pem @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEA8z+5X2PBcYxFOrNm8BvOadfalh+2h0fSspaZRdIM+sM= +-----END PUBLIC KEY----- diff --git a/firmware/boards/nrf52840-mdk-dongle/images/bootloader.bin b/firmware/boards/nrf52840-mdk-dongle/images/bootloader.bin new file mode 100755 index 0000000000000000000000000000000000000000..f2d9410f1f6e592d68cd30c93fa7e39b9e90d7ea GIT binary patch literal 39000 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∋gZ(v^XXBbG1 zaL_+Ic;f7R?p8>-H~Nly(r<~%^POf|7l}ImmpkyC@s>EU z{C^2|0fv@`5e&j`Fdvfdw0rbDAHXujnp>Zyqkp@h$5Vl|@L1oMYYoD?@W5x_$*fQe z2aklm@x%mTp|{fd9bw+pCB|yFwp%(!vAjaDn07t=4^P6I%$$rjrQ7C|NStz=WDoIw zaZRq@1+V|P1CRXGi4`VMsH&O?E}N=ywLb*Q3cd3ybIP&HO$9f^vaFuIg?d5^2OVL) zndE)khqs|mKI}_)b1`sdm%J`cG(<`7YT#7|af7EcCq^tqe~SU_H@j z6-cRZR;JO$Ae9)3*{9emi?n0aNJ2?=1WWz3Z2fBXKAJFB_}+9O(6{4i#Tfz40EcutM*`X$lU*=pOhf<8M<#>)*3&Eq`^ z;(x|LIrCMK(LDNXUjFUwuQugHq-v{;e$lnLovsG+D##0pH?bz*b}SppWGk@-48wnk znW*@pb;XRL)~eB!V3b?xzkL=~`QNAC+}65cx)4<~Teukz*cXCwc-CO5Y&Hx!*!?5v6gpWjeseVh-(F~h+N!z7pcVpMZnfLlQ^)0<7* z1GnuTpF3a3p2pmHlFC8M{#tj;)O9%bzW8`MkGeN1kwo1IL*b1bJ{L|xKs zilyJs#o6fi_n4vU6th?b;TN$EH{|hT%nzOUmxrC4)NO>n5Uq3N#Md4}hq4G?Fg
a`27z+eq5YQ??3$==Ot5DF2U`4DKKrB|EXzK;9 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 GSNbOqc-kxg literal 0 HcmV?d00001 diff --git a/firmware/boards/nrf52840-mdk-dongle/images/bootloader.signed.uf2 b/firmware/boards/nrf52840-mdk-dongle/images/bootloader.signed.uf2 new file mode 100644 index 0000000000000000000000000000000000000000..a5cc8d17d938c021e7daf61b10a846845c6b86ab GIT binary patch literal 82432 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�bY;+RqST}lIlrnR5>F$8TX(cj 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 N_M-y&H*c2Y|4$ad$OHfY literal 0 HcmV?d00001 diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.signed.uf2 b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.signed.uf2 new file mode 100644 index 0000000000000000000000000000000000000000..795b4a8b2366c1f015dd9112dc17bca6de4d74b5 GIT binary patch literal 155136 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 literal 0 HcmV?d00001 From 9e510760baf83b89e81528aa00228a8859cbb7f1 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 22:37:42 +0300 Subject: [PATCH 09/33] Check the nRF52840's MBR and factory bootloader before the install --- docs2/makerdiary.md | 5 ++ docs2/roadmap.md | 72 +++++++++++++++---- .../bootloader/test/app_test.c | 21 +++++- 3 files changed, 84 insertions(+), 14 deletions(-) diff --git a/docs2/makerdiary.md b/docs2/makerdiary.md index a1e69a3..dbccbc2 100644 --- a/docs2/makerdiary.md +++ b/docs2/makerdiary.md @@ -329,6 +329,11 @@ Open questions only the board answers: 2023-07-20, S132 5.1.0 plus the connectivity app in 0x1000..0x35000 and one page at 0x50000) is all 0xFF over 0x97000..0xD8000. Kept at `~/mdk-factory/`, sha256 `3022eb28...6aab`; it restores through the same drive. +- ~~Is the chip's bootloader the published 0.7.1?~~ Yes (2026-10-14, `docs2/roadmap.md` + phase 3 checklist). Its code equals the published `-nosd.hex` byte for byte, and the + MBR page is Nordic's 2.4.1 with 0xFF8/0xFFC erased. Beside the settings page at + 0xFF000, one thing differs: a Nordic FDS swap-page tag at 0xFD000 that an earlier + application wrote into the bootloader's last page, below its CF2 block. - ~~Green LED on P0.22?~~ Yes, as far as `vkey check` shows: Adafruit's `board.h` lists only red P0.23 and blue P0.24, but amber is red plus green, and the taps on amber went through. Red alone (the 5 s hold) has not been watched yet. diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 7285272..5690900 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -307,6 +307,8 @@ Milestones, one commit each: UICR search, and it must contain no `svc` and end below 0x40000. - **`test/app_test.c`** makes the bootloader's own `signature_valid` calls before the drive starts and writes each verdict with its DWT cycle count into `INFO_UF2.TXT`. + Since the install checklist, the file also carries a `Chip:` line: the leading bytes + of the SHA-512 of the chip's MBR page and of its factory bootloader. **`test/board.py`** moves the real-pipeline signed app into the scratch window (the signature covers no address). **`test/board.sh copy`** reads the target drive's `INFO_UF2.TXT` first: a bootloader UF2 goes only to `VKEYTEST`, never to the factory @@ -360,22 +362,62 @@ Milestones, one commit each: Install needs its own go and a checklist: -- no UICR address (0x10001xxx) and no NVMC `CONFIG` write in the binary; -- `SystemInit` disassembled; -- the board ID confirmed; -- the update padded to the whole region; -- the UF2 actually installed is checked block by block. It has 161 blocks: +- no UICR address (0x10001xxx) in the binary (`check.py`), and no erase beyond a page. + Done 2026-10-14 on the real-key build. Three functions use the NVMC: + - `nrfx_nvmc_page_erase` sets `CONFIG` to 2 and erases through `ERASEPAGE`; + - `nrfx_nvmc_words_write` and `nvmc_word_write` set it to 1, then back to 0. + + They are called only from `flash_nrf5x_flush`, the app window, and from + `bootloader_dfu_update_process`, the settings page. No store reaches `ERASEALL` or + `ERASEUICR`; +- `SystemInit` disassembled. Done 2026-10-14: as in milestone 1, it stores to CLOCK, + POWER, errata registers and `CPACR`, reads FICR, and never touches UICR; +- the board ID confirmed. Done 2026-10-14: the CF2 block is the factory's (`check.py`), + and the update UF2 carries 0x2886F00F; +- the update padded to the whole region. Done 2026-10-14: 0xF4000..0xFE000 is covered + with no gap; +- the UF2 actually installed is checked block by block. Done 2026-10-14 on + `images/bootloader.signed.uf2`. It has 161 blocks: - 159 of the bootloader at 0xF4000..0xFDF00; - its slot at 0xFDF00; - - one UICR block with the two words already on the chip. + - one UICR block holding 0xF4000 and 0xFE000 at 0x14 and 0x18 and 0xFF everywhere + else. The factory handler only compares those two words with its own constants and + writes nothing to UICR. There is no MBR and no settings page in it, and its 0xF4000.. payload equals the checked - `bootloader.bin`; + `bootloader.bin` (`signed_image.py verify`). The headers, which decide when the factory + flushes and calls `COPY_BL`, are also right: `blockNo` runs 0..160 in order, + `numBlocks` is 161 and the payload 256 in every block, with flag 0x2000 and both + magics; +- the jump into the app, which never ran in milestone 4, put next to the factory's. + Done 2026-10-14. `board_teardown`, the cleared NVIC lines, `sd_mbr_command` 6 with + 0x1000, and `bootloader_util_reset` (MSP from 0x1000, PC from 0x1004) are the factory's + instructions one for one. The only change is that the SoftDevice branch is gone. The + factory takes it only when 0x3004 holds the SoftDevice magic, and vkey does not, so + vkey already boots today through the path the fork keeps; - the factory bootloader's handling of it. In the published 0.7.1 hex, the handler writes each block 0x14000 lower, to 0xE0000..0xEA000. That is the reserve above the vault, not the vault. It calls `COPY_BL` only if the staged image differs from the running one. - Still open: the chip's own bootloader against that hex, and its MBR against 2.4.1. The - as-app build can read both; + + **The chip against the published files, 2026-10-14.** Two readings agree: + - the as-app build hashed the chip's MBR page and 0xF4000..0xFE000 with SHA-512; + - `dd` of those sectors of the factory drive returned the same bytes. The drive serves + flash past `CURRENT.UF2`, and only 0xF4000..0x100000 was read. + + What they showed: + - **MBR.** The page is Nordic's 2.4.1 byte for byte (`0a1d2691`), with 0xFF8 and 0xFFC + erased. So it boots the bootloader from UICR `NRFFW[0]`, and `COPY_BL` takes its + parameter page from `NRFFW[1]`. The MBR header says `COPY_BL` returns + `NRF_ERROR_NO_MEM` without either. UICR itself was not read, since `check.py` keeps + every UICR address out of the test build. + - **Bootloader.** The code is the published 0.7.1 hex (Jul 20 2023, "SoftDevice: not + found") byte for byte. Only 34 bytes differ: + - at 0xFD000, `0xDEADC0DE 0xF11E01FF`, a Nordic FDS swap-page tag that some earlier + application wrote. The bootloader's code holds neither word. The CF2 block at + 0xFD800 is intact, and `COPY_BL` overwrites the page; + - at 0xFF000, the bootloader's own settings page. + + The handler analysed in the hex is the one on the chip. - the key reachable from two places, and `signing-key.pem` committed with its fingerprint recorded here, `a1700ebd539b0bfc`: - the `.vkb` is made right after the key (done 2026-10-14); @@ -393,18 +435,22 @@ Install needs its own go and a checklist: `images/`; - `images/bootloader.bin` is what the committed sources and pem build: `tools/build-bootloader.sh` again, then `git diff --exit-code`. The hook does not - rebuild it; + rebuild it. Done 2026-10-14, twice, the second time after the as-app readback change; - the time from making the key to installing the fork kept short. Until the fork is in, `CURRENT.UF2` hands the vault, key included, to anyone holding the board (`docs/threat-model.md`); - the order: first copy the signed app (real key) through the factory bootloader and - confirm it boots under it. Then install the fork, and the board must boot straight + confirm it boots under it (done 2026-10-14: `vaultkey.signed.uf2`, `vkey info`, the + PIN and its 8 attempts intact). Then install the fork, and the board must boot straight into that app. If it stays in DFU mode instead, copying the signed app UF2 again is the next step. **The risk, stated plainly.** A bug in the new bootloader leaves a board no USB tool can -reach. Without a probe that is a new dongle. That is acceptable only because the board -holds nothing yet. +reach. Without a probe that is a new dongle. Since 2026-10-14 the board holds the signing +key. A brick therefore costs the board but not the key: the `.vkb` is proven by a restore +and opens on any vkey, including a new factory dongle, which then takes this same fork. +The power-fail safety of `COPY_BL` is Nordic's claim, untested here, so the board stays +plugged in until it comes back. Acceptance: diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c index e8d7a8d..df80095 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c @@ -12,7 +12,9 @@ * staged there. * * Each verdict and the cycles DWT counted for it go into INFO_UF2.TXT: with no serial - * port and no probe, the drive is the only way out. + * port and no probe, the drive is the only way out. So does what the install leans on: + * the leading bytes of the SHA-512 of the chip's MBR page and of its factory bootloader, + * for the host to compare with Nordic's MBR 2.4.1 and the published 0.7.1 hex. */ #include @@ -24,6 +26,7 @@ #include "app_util.h" #include "boards.h" #include "uf2/uf2.h" +#include "monocypher-ed25519.h" #include "signature.h" /* Where test/board.py puts the app: the image, then its slot and the altered slot. */ @@ -61,6 +64,17 @@ static void check(char const *what, uint8_t const *image, uint8_t const *slot, want == NULL ? "" : strcmp(verdict, want) == 0 ? " - ok" : " - WRONG"); } +/* The first four bytes of the digest in byte order, as `sha512sum | cut -c1-8` prints. */ +static void digest(char const *what, uint32_t start, uint32_t end) { + uint8_t const *flash = (uint8_t const *) start; + // The MBR starts at address 0, which C calls null: hidden from the compiler, the + // pointer is read like any other instead of becoming a trap. + __asm__ volatile("" : "+r"(flash)); + uint8_t hash[64]; + crypto_sha512(hash, flash, end - start); + say(" %s %02x%02x%02x%02x", what, hash[0], hash[1], hash[2], hash[3]); +} + void app_test_run(void) { CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; @@ -68,6 +82,11 @@ void app_test_run(void) { say("Test: as app at 0x%X, ICACHECNF 0x%lX\r\n", MBR_SIZE, (unsigned long) NRF_NVMC->ICACHECNF); + // Before the checks, so that if INFO_UF2.TXT runs out of room it cuts those instead. + say("Chip:"); + digest("MBR", 0, MBR_SIZE); + digest("BL", BOOTLOADER_REGION_START, BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS); + say("\r\n"); uint8_t const *image = (uint8_t const *) TEST_APP_IMAGE; check("app", image, (uint8_t const *) TEST_APP_SLOT, SIGNATURE_KIND_APP, REAL_APP_MAX, From b5d50b3fd21b8a6bf1d17545ec05f47d11c4fd34 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 23:02:43 +0300 Subject: [PATCH 10/33] Install the UF2 bootloader fork on the nRF52840 --- CLAUDE.md | 12 +++--- README.md | 5 ++- docs/threat-model.md | 38 +++++++++++-------- docs2/makerdiary.md | 2 +- docs2/roadmap.md | 20 ++++++++-- .../boards/nrf52840-mdk-dongle/board.toml | 5 ++- 6 files changed, 54 insertions(+), 28 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 05599c1..5a71816 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -150,9 +150,10 @@ folder's business. The boards: - **`nrf52840-mdk-dongle`**, the primary. USB CDC-ACM from the firmware (`1209:0001`), - polled; the factory UF2 bootloader (Adafruit-based, 0x1000..0xF4000 is the application) is - how it is flashed: hold the button while plugging in, copy a UF2 (family `0xADA52840`, - base 0x1000) to `UF2BOOT`, replug. No chip key, so it holds no real secrets yet. `vkey + polled; our UF2 bootloader fork (installed 2026-10-14, below) is how it is flashed: hold + the button while plugging in, copy `images/vaultkey.signed.uf2` to `UF2BOOT`, replug. It + runs only images signed with the key in `bootloader/signing-key.pem`; the app ends by + its signature slot at 0x96000. No chip key, so it holds no real secrets yet. `vkey info` prints the chip's build code, UICR `APPROTECT` and last reset cause. Notes, measurements and factory state: `docs2/makerdiary.md`; the plan: `docs2/roadmap.md`. - **`esp32c6-zero`**, the test board (2026-10-14): nothing is built for it, and it takes @@ -279,8 +280,9 @@ The boards: **On the nRF52840, without a probe, the bootloader and UICR are irreversible.** A broken bootloader is a board no USB tool reaches, and UICR `APPROTECT` once written stays. Each -such step happens only while the board holds nothing, and only on the maintainer's -explicit go for that step (`docs2/roadmap.md`, phases 3 and 4). +such step happens only while the board holds nothing a `.vkb` cannot restore, and only on +the maintainer's explicit go for that step (`docs2/roadmap.md`, phases 3 and 4). The +bootloader fork went in this way on 2026-10-14. **eFuses are irreversible.** Secure Boot, Flash Encryption and HMAC keys burn the chip forever. Never burn an eFuse without a direct instruction from the maintainer — and even diff --git a/README.md b/README.md index 55f5795..e74f7b2 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,9 @@ single-binary host CLI, and a press of the board's button for every secret that > **Two boards** (2026-10-13). Development now targets the Makerdiary nRF52840 MDK USB Dongle > (`firmware/boards/nrf52840-mdk-dongle`), the board passkeys will come to. It runs the same -> core and passes the full lifecycle test. It has no chip key yet, though, and its bootloader -> flashes anything and reads the flash back. So it is **not for real secrets** until the steps +> core and passes the full lifecycle test. Its bootloader is now our own fork, which runs +> only signed firmware and serves no flash back. It has no chip key yet, though, and its debug +> port is open. So it is **not for real secrets** until the steps > in [docs2/roadmap.md](docs2/roadmap.md) are done, and `vkey setup` does not flash it yet. > Everything below still describes the ESP32-C6-Zero, which is now only a test board. diff --git a/docs/threat-model.md b/docs/threat-model.md index 5786bd8..109522f 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -6,7 +6,7 @@ > on guarantees the device does not give. Last reviewed 2026-09-12; the nRF52840 board section added 2026-10-13, its signing key -2026-10-14. Revisited on every +and bootloader fork 2026-10-14. Revisited on every hardware or firmware change. Reporting policy: [`SECURITY.md`](../SECURITY.md). Board details: [`docs/hardware.md`](hardware.md). @@ -25,28 +25,36 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure 0.97 ms per guess at 20 passes (2.4 ms at the C6's 48). All 10^8 PINs then take about 28 core-hours, a few hours on an ordinary laptop, and less on a GPU. The "years for eight digits" figure is for the C6 with the counter erased; it does not apply here. -- **The flash can be copied.** The factory UF2 bootloader serves `CURRENT.UF2`, the whole - application area, to anyone who holds the button while plugging the key in. Verified - 2026-10-13: the vault's region came back with its contents. SWD reads it too: the chip - reports revision 2 (build code `AAD0`) with UICR `APPROTECT` erased, which on revision 2 - leaves the debug port open. Revision 2 also predates Nordic's fix for the published - APPROTECT voltage glitch (IN-133), so even with the port closed in UICR, someone with - glitching gear can open it and read the flash, a chip key in it included. -- **Any firmware is accepted.** UF2 flashes whatever it is given, with no signature. - Firmware that records the PIN on its next use is one file copy away. +- **The flash can be copied over SWD.** The chip reports revision 2 (build code `AAD0`) + with UICR `APPROTECT` erased, which on revision 2 leaves the debug port open. Revision 2 + also predates Nordic's fix for the published APPROTECT voltage glitch (IN-133), so even + with the port closed in UICR, someone with glitching gear can open it and read the + flash, a chip key in it included. + + The USB drive no longer hands it out. The factory UF2 bootloader served `CURRENT.UF2`, + the whole application area, to anyone who held the button while plugging the key in. + On 2026-10-13 the vault's region came back with its contents. Our bootloader fork + replaced it on 2026-10-14, and its drive holds only `INFO_UF2.TXT` and `INDEX.HTM`. Its + code (`0003-no-readback`) returns zeros for a raw read past them, but that has not been + read back on the board yet. +- **Only firmware signed with the fork's key runs** (since 2026-10-14). The fork checks + the signature on every boot. The check was proven on this chip as an app in milestone 4, + and the installed fork verified and ran the signed vkey. Whoever holds the button can + still write the application region, so a bad copy leaves the board in the bootloader + until a signed image is copied. Refusing an unsigned or altered UF2 on the installed + fork is phase-3 acceptance and has not been run yet. - **`vkey auth` does not exist here.** Its secret is sealed under the chip key, and the CLI refuses to enable it. - **The bootloader fork's signing key lives on this board.** It is the `.env` `vkey-signing-nrf`, made by `bootloader/signing-key.sh` on 2026-10-14 (fingerprint `a1700ebd539b0bfc`), with a `.vkb` as its second copy. Everything above applies to it: - - until the fork is installed, `CURRENT.UF2` and the offline PIN search hand it to anyone - who holds the board for a minute and then computes for a few hours; - - after that, SWD does the same until APPROTECT, and the glitch after that. + - for 1 h 17 min, until the fork was installed, `CURRENT.UF2` and the offline PIN search + handed it to anyone who held the board for a minute and then computed for a few hours; + - since then, SWD does the same until APPROTECT (phase 4), and the glitch after that. Whoever has the key signs firmware the fork runs. By design, the fork moves to a new key only through a self-update signed with the old one. A leak is mended only while the - owner still holds the key. So the time from making the key to installing the fork is - kept short. + owner still holds the key. - **A backup made on this board uses its own cost** (20 passes). It is still guarded by the passphrase's entropy, at less than half the C6's work per guess. diff --git a/docs2/makerdiary.md b/docs2/makerdiary.md index dbccbc2..23f15d3 100644 --- a/docs2/makerdiary.md +++ b/docs2/makerdiary.md @@ -317,7 +317,7 @@ it. A UF2 is made from `images/vaultkey.bin` with family `0xADA52840` and base 0 (`uf2conv -f 0xADA52840 -c -b 0x1000`). Until our own fork of this bootloader replaces it (`docs2/roadmap.md`, phase 3; Nordic's secure bootloader was dropped for want of a probe) the board holds no real secrets, because UF2 flashes anything and its `CURRENT.UF2` reads -the vault's ciphertext out. +the vault's ciphertext out. The fork replaced it on 2026-10-14. Open questions only the board answers: diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 5690900..03c38c0 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -33,7 +33,8 @@ notes, measurements and the factory state: `docs2/makerdiary.md`. **Real secrets go onto the nRF when phases 3-5 are done, not when features are done.** No board holds real secrets today, and the C6 is a test board, not a fallback (2026-10-14), so every feature is built for the nRF alone. The nRF has no chip key, and -its bootloader flashes anything and serves the flash back (`CURRENT.UF2`). A copy of its +its debug port is open. Until 2026-10-14 its bootloader also flashed anything and served +the flash back (`CURRENT.UF2`); our fork has replaced it since (phase 3). A copy of its flash gives up the PIN offline in hours (`docs/threat-model.md`). `espflash` stays in the CLI while the C6 is flashed through it, and the audit exception with it. @@ -445,6 +446,18 @@ Install needs its own go and a checklist: into that app. If it stays in DFU mode instead, copying the signed app UF2 again is the next step. +**Installed 2026-10-14, 22:53,** on the maintainer's go. +- `bootloader.signed.uf2` was copied onto the factory drive once its `INFO_UF2.TXT` showed + 0.7.1 with no SoftDevice. +- The board left USB at once and came back by itself 2 s later, running vkey + (`last reset: soft reset`). +- With the button held, the drive showed `0.9.2-vkey.4`, `Key: a1700ebd539b0bfc` and only + `INDEX.HTM` and `INFO_UF2.TXT`. +- Replugged without it, the first cold boot (`power-on`) verified vkey and ran it, with + the PIN and its 8 attempts intact. + +The key had spent 1 h 17 min on a board that served `CURRENT.UF2`. + **The risk, stated plainly.** A bug in the new bootloader leaves a board no USB tool can reach. Without a probe that is a new dongle. Since 2026-10-14 the board holds the signing key. A brick therefore costs the board but not the key: the `.vkb` is proven by a restore @@ -455,7 +468,8 @@ plugged in until it comes back. Acceptance: - an unsigned or altered UF2 is refused and never runs; -- the drive offers no `CURRENT.UF2`; +- the drive offers no `CURRENT.UF2` (seen 2026-10-14; that a raw read past its files + returns zeros is not read back yet); - a UF2 aimed at the vault region is refused; - `check --wipe-everything` passes; - the threat model loses the "flashes anything" and `CURRENT.UF2` lines. @@ -536,7 +550,7 @@ Acceptance: registration and login on webauthn.io and with `fido2-token`; `pam_u |---|---| | Phase 0 | ~~the audit exception for RUSTSEC-2026-0344~~ - done 2026-10-13 | | Phase 2 | ~~if the chip is older than revision 3: accept the glitch risk or keep the important secrets on the C6~~ - revision 2; everything moves here, risk accepted (2026-10-13) | -| Phase 3 | ~~own bootloader instead of the Nordic secure bootloader~~ - own fork chosen (2026-10-13); installing it still needs its own go | +| Phase 3 | ~~own bootloader instead of the Nordic secure bootloader~~ - own fork chosen (2026-10-13), installed on the maintainer's go (2026-10-14) | | Phase 3 | ~~the signing key's second home~~ - a `.vkb` that restores onto the C6; the C6 is the test board, everything else is on the nRF (2026-10-14) | | Phase 5 | ~~wiping the C6 after migration~~ - the C6 is a test board, not a fallback, and neither board holds real secrets (2026-10-14) | | Phase 5 | chip key option A or B | diff --git a/firmware/boards/nrf52840-mdk-dongle/board.toml b/firmware/boards/nrf52840-mdk-dongle/board.toml index 981728b..9476879 100644 --- a/firmware/boards/nrf52840-mdk-dongle/board.toml +++ b/firmware/boards/nrf52840-mdk-dongle/board.toml @@ -22,8 +22,9 @@ button = "USER" # reaches this address. radio_base = 0x40001000 -# Flashed through the factory UF2 bootloader for now (docs2/makerdiary.md). `vkey setup` -# talks only to the ESP ROM loader, so it never picks this board. +# Flashed through its UF2 bootloader fork as images/vaultkey.signed.uf2 (bootloader/, +# docs2/roadmap.md phase 3). `vkey setup` talks only to the ESP ROM loader, so it never +# picks this board. [[image]] offset = 0x1000 file = "images/vaultkey.bin" From 7c50caf6a0914e89b485893236cc4d0178628b03 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Wed, 14 Oct 2026 23:34:49 +0300 Subject: [PATCH 11/33] Accept the UF2 bootloader fork on the nRF52840 --- docs/threat-model.md | 19 ++++++++++--------- docs2/roadmap.md | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/docs/threat-model.md b/docs/threat-model.md index 109522f..c0d6b2d 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -34,20 +34,21 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure The USB drive no longer hands it out. The factory UF2 bootloader served `CURRENT.UF2`, the whole application area, to anyone who held the button while plugging the key in. On 2026-10-13 the vault's region came back with its contents. Our bootloader fork - replaced it on 2026-10-14, and its drive holds only `INFO_UF2.TXT` and `INDEX.HTM`. Its - code (`0003-no-readback`) returns zeros for a raw read past them, but that has not been - read back on the board yet. + replaced it on 2026-10-14, and its drive holds only `INFO_UF2.TXT` and `INDEX.HTM`. Raw + sectors past them read as zeros: checked on the board where the factory's drive had + served its own code. - **Only firmware signed with the fork's key runs** (since 2026-10-14). The fork checks - the signature on every boot. The check was proven on this chip as an app in milestone 4, - and the installed fork verified and ran the signed vkey. Whoever holds the button can - still write the application region, so a bad copy leaves the board in the bootloader - until a signed image is copied. Refusing an unsigned or altered UF2 on the installed - fork is phase-3 acceptance and has not been run yet. + the signature on every boot. On the board it refused an image with one bit flipped and + an image signed with another key, and it ran the signed vkey. Whoever holds the button + can still write the application region, so a bad copy leaves the board in the + bootloader until a signed image is copied. - **`vkey auth` does not exist here.** Its secret is sealed under the chip key, and the CLI refuses to enable it. - **The bootloader fork's signing key lives on this board.** It is the `.env` `vkey-signing-nrf`, made by `bootloader/signing-key.sh` on 2026-10-14 (fingerprint - `a1700ebd539b0bfc`), with a `.vkb` as its second copy. Everything above applies to it: + `a1700ebd539b0bfc`), with a `.vkb` as its second copy. That copy was proven twice, each + time by a restore that signed byte for byte the same, the second after the wipe test. + Everything above applies to it: - for 1 h 17 min, until the fork was installed, `CURRENT.UF2` and the offline PIN search handed it to anyone who held the board for a minute and then computed for a few hours; - since then, SWD does the same until APPROTECT (phase 4), and the glitch after that. diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 03c38c0..9c3bf8c 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -458,6 +458,12 @@ Install needs its own go and a checklist: The key had spent 1 h 17 min on a board that served `CURRENT.UF2`. +The as-app harness (`test/board.sh`, `m4.uf2`) ran under the factory bootloader. The fork +runs an app only with a slot at 0x96000 signed by the real key. `board.sh copy` also +looks for 0.7.1 in the drive's INFO, so it now refuses the fork's drive, which fails safe. +Before the fork's next change, the harness has to be adapted: the test build is signed as +an app with the real key, while its test images keep the test key. + **The risk, stated plainly.** A bug in the new bootloader leaves a board no USB tool can reach. Without a probe that is a new dongle. Since 2026-10-14 the board holds the signing key. A brick therefore costs the board but not the key: the `.vkb` is proven by a restore @@ -467,12 +473,32 @@ plugged in until it comes back. Acceptance: -- an unsigned or altered UF2 is refused and never runs; -- the drive offers no `CURRENT.UF2` (seen 2026-10-14; that a raw read past its files - returns zeros is not read back yet); -- a UF2 aimed at the vault region is refused; -- `check --wipe-everything` passes; -- the threat model loses the "flashes anything" and `CURRENT.UF2` lines. +- an unsigned or altered UF2 is refused and never runs. Done 2026-10-14 with two images, + each copied onto the fork's drive and then cold-booted without the button: + - `vaultkey.signed.uf2` with one bit flipped at 0x9010; + - the same app signed with the test key. + + Both times the board came back as the bootloader (`2886:f00f`), not vkey. Then the + real `vaultkey.signed.uf2` brought vkey back at once, with the PIN and its 8 attempts + intact; +- the drive offers no `CURRENT.UF2`. Done 2026-10-14: the drive holds only `INDEX.HTM` and + `INFO_UF2.TXT`. The same 192 raw sectors that gave the factory bootloader's code back + (`dd`, skip 4411) now read as 98 304 zero bytes; +- a UF2 aimed at the vault region is refused. Done 2026-10-14 at the boundary, with one + block at 0x97000, the first address past the app window and the vault's attempt + sector. It was all 0xFF but a zero first word, so a write would have shown as one spent + attempt without the PIN. The fork did not count the block as part of a transfer, so + the copy ended no session and caused no reset. After a cold boot, vkey still showed 8 + attempts; +- `check --wipe-everything` passes. Done 2026-10-14 under the fork: every line PASS, + backup, restore, rekey, the live HMAC selftest and the wipe after 8 wrong PINs + included. The signing key then came back from its `.vkb` (on the second try, after a + mistyped passphrase). Signing again gave `vaultkey.signed.uf2` and + `bootloader.signed.uf2` byte for byte; +- the threat model loses the "flashes anything" and `CURRENT.UF2` lines. Done + 2026-10-14. + +**Phase 3 accepted 2026-10-14.** ## Phase 4 - APPROTECT, from the firmware From c4862cf1b0f3e4254caf8028e14f76a48c8078b5 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 00:42:52 +0300 Subject: [PATCH 12/33] Group /list by vault, add /settings, drop 1Password documents --- cli/src/import.rs | 12 ++- cli/src/main.rs | 26 +++-- cli/src/op.rs | 262 ++++++++++++++++++++++----------------------- cli/src/shell.rs | 210 +++++++++++++++++++++++++++++------- cli/src/sources.rs | 5 +- docs/items-v2.md | 5 + 6 files changed, 335 insertions(+), 185 deletions(-) diff --git a/cli/src/import.rs b/cli/src/import.rs index 9590103..2235169 100644 --- a/cli/src/import.rs +++ b/cli/src/import.rs @@ -259,9 +259,10 @@ pub(crate) fn entry_name(title: &str, url: &str) -> Option { Some(truncate(&name)) } -/// At most `NAME_MAX` bytes, never mid-character. +/// At most `NAME_MAX` bytes, never mid-character, and never ending in a space the cut +/// laid bare: a name may not, so the item would be refused. pub(crate) fn truncate(s: &str) -> String { - cut(s, NAME_MAX) + cut(s, NAME_MAX).trim_end().to_string() } /// The first `max` bytes of `s`, never mid-character. @@ -492,6 +493,13 @@ mod tests { assert_eq!(parsed.dropped, vec!["Bank".to_string()]); } + #[test] + fn a_cut_title_never_ends_in_a_space() { + let name = truncate("Indie Hackers: Work Together to Build Profitable Online Businesses"); + assert_eq!(name, "Indie Hackers: Work Together to"); + assert!(crate::device::name(&name).is_ok()); + } + #[test] fn a_name_that_does_not_fit_loses_the_site_and_never_the_login() { let mut taken = BTreeSet::new(); diff --git a/cli/src/main.rs b/cli/src/main.rs index 8d0ee5e..a267404 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -642,19 +642,21 @@ fn run_op( } } - if item.is_none() && env_pairs.is_empty() && prompt::is_tty() { - println!(" ● 1Password Developer Environments (.env)"); - if !saved.is_empty() { - println!(" Saved environments:"); - for (name, id) in &saved { + // `op` cannot list Developer Environments, so the saved ones are the whole known set: + // a run that names none takes all of them, and a new one is only ever added. + if item.is_none() && env_pairs.is_empty() { + env_pairs.extend(saved); + env_pairs.sort_by(|a, b| a.0.cmp(&b.0)); + if prompt::is_tty() { + println!(" ● 1Password Developer Environments (.env)"); + for (name, id) in &env_pairs { println!(" • {name} (ID: {id})"); } - if prompt::yes_no("update saved environments?") { - env_pairs.extend(saved); - } } - - if env_pairs.is_empty() { + // With some saved, the run just takes them; a new one comes in through -E. + if !env_pairs.is_empty() && prompt::is_tty() { + println!(" (another one: vkey op -E name:ID)"); + } else if prompt::is_tty() { println!( " (in 1Password: Developer -> View Environments -> View environment -> Manage environment -> Copy environment ID)" ); @@ -679,7 +681,9 @@ fn run_op( } (trimmed.to_string(), id_trimmed) }; - env_pairs.push((name, id)); + if !env_pairs.iter().any(|(n, _)| *n == name) { + env_pairs.push((name, id)); + } } } } diff --git a/cli/src/op.rs b/cli/src/op.rs index 2b5581c..0fdc0c3 100644 --- a/cli/src/op.rs +++ b/cli/src/op.rs @@ -3,7 +3,7 @@ //! Pulls passwords, TOTP credentials and `.env` documents directly from //! 1Password in memory (`Zeroizing`), without writing cleartext files to disk. -use std::collections::{BTreeSet, HashMap}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::io::Write; use std::path::PathBuf; use std::process::{Command, Stdio}; @@ -18,8 +18,8 @@ use crate::import::{Summary, entry_name, truncate, unique_name}; use crate::item::{Item, OwnedField, class_of, field_kind_name, field_kind_of, op_category}; use crate::prompt::SyncUi; use crate::sources::{ - Manifest, OP_DOC, OP_ENV, OP_ITEM, Outcome, Phase, SyncRun, absorb, claim_written, config_path, - finish, keep_unlocked, survivor, + Manifest, OP_ENV, OP_ITEM, Outcome, Phase, SyncRun, absorb, claim_written, config_path, finish, + keep_unlocked, survivor, }; use crate::totp; @@ -131,6 +131,19 @@ fn op_list( pub(crate) struct OpListEntry { pub(crate) id: String, pub(crate) title: String, + #[serde(default)] + pub(crate) category: String, + #[serde(default)] + pub(crate) vault: Option, +} + +#[derive(Deserialize, Debug)] +pub(crate) struct OpVaultRef { + #[serde(default)] + pub(crate) id: String, + /// Empty in a document listing, which names the vault by id alone. + #[serde(default)] + pub(crate) name: String, } #[derive(Deserialize, Debug)] @@ -241,7 +254,11 @@ pub(crate) fn item_of(detail: &OpItemDetail) -> Result<(Item, Vec), Erro } // `purpose` is 1Password's own word for what a field is for, and both // PASSWORD and NOTES fields hold secrets that must not leak without a tap. - let class = if matches!(f.purpose.as_deref(), Some("PASSWORD" | "NOTES")) { + // An SSH key item's private key is type SSHKEY with no purpose; its public + // key and fingerprint are plain strings and stay open. + let class = if matches!(f.purpose.as_deref(), Some("PASSWORD" | "NOTES")) + || f.field_type.eq_ignore_ascii_case("SSHKEY") + { Class::Secret } else { class_of(kind) @@ -425,6 +442,34 @@ pub fn save_saved_env(name: &str, id: &str) { } } +/// Which 1Password vault each entry came from, by entry name, for `/list` to group by. +/// The key does not know vaults; this host remembers them the way it remembers sources. +#[must_use] +pub fn load_vault_map() -> BTreeMap { + let map: BTreeMap = config_path("op_vaults.json") + .and_then(|p| std::fs::read(p).ok()) + .and_then(|d| serde_json::from_slice(&d).ok()) + .unwrap_or_default(); + // A nameless vault is what a run before document listings were resolved by id + // left behind: no vault at all rather than a row with no name. + map.into_iter().filter(|(_, v)| !v.is_empty()).collect() +} + +/// Folds what a run learned into the vault map on disk, readable only by its owner. +fn save_vault_map(learned: BTreeMap) { + let Some(path) = config_path("op_vaults.json") else { + return; + }; + let mut map = load_vault_map(); + map.extend(learned); + if let Some(parent) = path.parent() { + let _ = std::fs::create_dir_all(parent); + } + if let Ok(json) = serde_json::to_vec_pretty(&map) { + let _ = file::replace(&path, &json, 0o600); + } +} + /// Returns true if an `op` error is critical (missing binary, session locked, auth failure). #[must_use] pub(crate) fn is_critical_op_error(msg: &str) -> bool { @@ -535,39 +580,6 @@ pub(crate) fn process_item( put_item(dev, &name, &stored, replace, ui, run) } -/// Imports an `.env` document from 1Password. -pub(crate) fn process_document( - dev: &mut Device, - doc_id: &str, - title: &str, - replace: bool, - ui: &mut dyn SyncUi, - run: &mut SyncRun, -) -> Result<(), Error> { - let name = env_entry_name(title); - let content = match op_exec(&["document", "get", doc_id]) { - Ok(b) => b, - Err(e) => { - ui.info(&format!(" failed to get document '{title}': {e}")); - run.summary.skipped += 1; - run.saw(&name, Outcome::Offered); - return Ok(()); - } - }; - - let blob = match EnvBlob::new(content) { - Ok(b) => b, - Err(e) => { - ui.info(&format!(" document '{title}' is not a valid .env: {e}")); - run.summary.skipped += 1; - run.saw(&name, Outcome::Offered); - return Ok(()); - } - }; - - put_item(dev, &name, &blob.item(), replace, ui, run) -} - /// Imports a 1Password Developer Environment by its ID. pub fn process_environment( dev: &mut Device, @@ -732,27 +744,6 @@ pub fn pull_item( } } - // If item get was not found, try as a document - match op_exec(&["document", "get", item_query]) { - Ok(raw_doc) => { - let blob = EnvBlob::new(raw_doc).map_err(|e| { - Error::Value(format!( - "content of '{item_query}' is not a valid .env: {e}" - )) - })?; - let name = env_entry_name(item_query); - put_item(dev, &name, &blob.item(), replace, ui, &mut run)?; - claim_written(&mut run, OP_DOC)?; - return Ok(run.summary); - } - Err(e) => { - let msg = e.to_string(); - if is_critical_op_error(&msg) { - return Err(e); - } - } - } - // If item and document not found, try as an environment read let Ok(raw_env) = op_exec(&["environment", "read", item_query]) else { return Err(Error::Value(format!( @@ -799,9 +790,34 @@ struct Mirror<'a> { /// Set once the key has no room left. The phases go on naming what the source /// offers - otherwise the rest would read as withdrawn - but write nothing more. full: bool, + /// The vault each name this run gave out came from, for `/list`. + vaults: BTreeMap, + /// Vault names by id, from the item listing, for the documents that lack them. + vault_names: HashMap, } impl Mirror<'_> { + /// Files under `vault` every name taken since `before` was. + fn note_vault(&mut self, pending: Option<(&OpVaultRef, BTreeSet)>) { + let Some((vault, before)) = pending else { + return; + }; + let Some(vault) = self.vault_name(vault) else { + return; + }; + for name in self.taken.difference(&before) { + self.vaults.insert(name.clone(), vault.clone()); + } + } + + fn vault_name(&self, vault: &OpVaultRef) -> Option { + if vault.name.is_empty() { + self.vault_names.get(&vault.id).cloned() + } else { + Some(vault.name.clone()) + } + } + /// Passwords, TOTP secrets and the `.env` an item may carry in a note. fn items(&mut self, items: &[OpListEntry], blocked: Option) -> Result { // Two items of the same title are told apart by their login, so their names @@ -813,10 +829,15 @@ impl Mirror<'_> { let mut offered = BTreeSet::new(); let mut unread: Option = None; + // The names an entry gets are only known once it is through, and the body + // leaves early in many places: each entry's are settled when the next begins. + let mut pending: Option<(&OpVaultRef, BTreeSet)> = None; for entry in items { - // Every category is mirrored now: a passport and a credit card go on the - // key like a login does. What an item is decides nothing about whether it - // is stored - only its fields' classes decide what comes back out. + self.note_vault(pending.take()); + pending = entry.vault.as_ref().map(|v| (v, self.taken.clone())); + // Every category but a Document is mirrored: a passport and a credit card + // go on the key like a login does, and only their fields' classes decide + // what comes back out. let is_dup = counts.get(entry.title.as_str()).copied().unwrap_or(0) > 1; let base_name = truncate(entry.title.trim()); @@ -883,6 +904,7 @@ impl Mirror<'_> { } absorb(self.run, OP_ITEM, self.map, &mut offered)?; } + self.note_vault(pending.take()); Ok(Phase { bucket: OP_ITEM, @@ -891,58 +913,6 @@ impl Mirror<'_> { }) } - /// `.env` files kept as 1Password documents. - fn documents( - &mut self, - documents: Option<&[OpListEntry]>, - blocked: Option, - ) -> Result { - let mut offered = BTreeSet::new(); - for doc in documents.unwrap_or_default() { - let name = env_entry_name(&doc.title); - if self.full { - offered.insert(name); - self.run.summary.left += 1; - continue; - } - if !self.replace && self.existing.contains(&name) { - self.ui - .info(&format!("syncing document '{}'...", doc.title)); - self.ui - .info(&format!(" skipped env '{name}' (already exists)")); - self.run.summary.skipped += 1; - offered.insert(name); - continue; - } - - keep_unlocked(self.dev, self.ping.as_ref(), &mut self.last_ping); - self.ui - .info(&format!("syncing document '{}'...", doc.title)); - match process_document( - self.dev, - &doc.id, - &doc.title, - self.replace, - self.ui, - self.run, - ) { - Ok(()) => {} - Err(Error::Full) => { - self.full = true; - offered.insert(name); - } - Err(e) => return Err(e), - } - absorb(self.run, OP_DOC, self.map, &mut offered)?; - } - - Ok(Phase { - bucket: OP_DOC, - blocked, - offered, - }) - } - /// 1Password Developer Environments, named by this host's saved map. fn environments( &mut self, @@ -1016,25 +986,22 @@ pub fn sync( let account = (!selection).then(op_account).flatten(); let account_id = account.as_deref(); let item_blocked = why_not_prune(&map, OP_ITEM, account_id, selection); - let doc_blocked = why_not_prune(&map, OP_DOC, account_id, selection); let env_blocked = why_not_prune(&map, OP_ENV, account_id, selection); ui.info("fetching items from 1Password..."); let items_out = op_list("item", tag, vault)?; - let items: Vec = serde_json::from_slice(&items_out) + let mut items: Vec = serde_json::from_slice(&items_out) .map_err(|e| Error::Value(format!("failed to parse 1Password item list: {e}")))?; - - // A listing that failed is not an empty listing: told apart, because treating a - // failure as "1Password has no documents" would delete every blob that came from - // one. - let documents: Option> = op_list("document", tag, vault) - .ok() - .and_then(|out| serde_json::from_slice(&out).ok()); + // A Document is a file - a signing key, a backup - and the key is no file store + // (maintainer's decision, 2026-10-15). Left out of the listing, one stored by an + // earlier run is no longer offered, so this run removes it. + let all = items.len(); + items.retain(|e| !e.category.eq_ignore_ascii_case("DOCUMENT")); ui.info(&format!( - "found {} items and {} documents in 1Password", + "found {} items in 1Password ({} documents left there)", items.len(), - documents.as_ref().map_or(0, Vec::len) + all - items.len() )); // There is no listing to ask 1Password for environments, so the whole of this @@ -1058,6 +1025,13 @@ pub fn sync( ui, replace, full: false, + vaults: BTreeMap::new(), + vault_names: items + .iter() + .filter_map(|e| e.vault.as_ref()) + .filter(|v| !v.name.is_empty()) + .map(|v| (v.id.clone(), v.name.clone())) + .collect(), }; let phases = [ @@ -1069,14 +1043,6 @@ pub fn sync( .then(|| "1Password listed no items at all".to_string()) }), )?, - mirror.documents( - documents.as_deref(), - doc_blocked.or_else(|| match &documents { - None => Some("the document listing failed".to_string()), - Some(d) if d.is_empty() => Some("1Password listed no documents at all".to_string()), - Some(_) => None, - }), - )?, mirror.environments( environments, env_blocked.or_else(|| { @@ -1089,6 +1055,7 @@ pub fn sync( // Everything the phases still hold, taken before the key and the screen are needed // again: `mirror` borrows both. let (full, ping) = (mirror.full, mirror.ping.take()); + save_vault_map(std::mem::take(&mut mirror.vaults)); if full { ui.info("the device is full: nothing more was written"); @@ -1336,6 +1303,35 @@ mod tests { ); } + #[test] + fn an_ssh_private_key_is_behind_a_tap_and_its_public_half_is_not() { + let json = r#"{ + "id": "s", + "title": "server", + "category": "SSH_KEY", + "fields": [ + { "id": "private_key", "label": "private key", "type": "SSHKEY", "value": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEI\n-----END PRIVATE KEY-----\n" }, + { "id": "public_key", "label": "public key", "type": "STRING", "value": "ssh-ed25519 AAAAC3Nza" }, + { "id": "fingerprint", "label": "fingerprint", "type": "STRING", "value": "SHA256:abc" } + ], + "urls": [] + }"#; + let detail: OpItemDetail = serde_json::from_str(json).expect("valid JSON"); + let (item, _) = item_of(&detail).expect("an item"); + assert_eq!( + item.by_label("private key").expect("kept").class, + Class::Secret + ); + assert_eq!( + item.by_label("public key").expect("kept").class, + Class::Open + ); + assert_eq!( + item.by_label("fingerprint").expect("kept").class, + Class::Open + ); + } + #[test] fn an_item_with_nothing_in_it_says_so() { let json = @@ -1412,7 +1408,7 @@ mod tests { // A duplicate title qualified by login: unguessable, only the map knows it. map.claim("AWS:alice", OP_ITEM); map.claim("AWS:bob", OP_ITEM); - map.claim("elsewhere", OP_DOC); + map.claim("elsewhere", OP_ENV); let github = item_names(&map, "GitHub"); assert!(github.contains(&"GitHub".to_string())); diff --git a/cli/src/shell.rs b/cli/src/shell.rs index 8c38b85..69dab8c 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -7,7 +7,7 @@ //! frame from a known geometry and drawing it again - nothing is left to a widget //! library's guesses. -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::time::{Duration, Instant}; @@ -39,6 +39,14 @@ const COMMANDS: &[(&str, &str)] = &[ ), ("unlock", "enter the PIN now"), ("lock", "forget the key until the next PIN"), + ( + "settings", + "PIN, backup and restore, self-test, setup, factory reset", + ), +]; +/// Behind `/settings`: what is done to the key rather than with an entry. They still +/// resolve when typed, so `/pin` and `/backup` work as before. +const SETTINGS: &[(&str, &str)] = &[ ("pin", "set or change the PIN"), ( "wipe", @@ -169,13 +177,14 @@ fn resolve_command(word: &str) -> Option<&'static str> { if let Some(n) = LIST_COMMANDS .iter() .copied() - .chain(COMMANDS.iter().map(|(n, _)| *n)) + .chain(COMMANDS.iter().chain(SETTINGS).map(|(n, _)| *n)) .find(|n| *n == w) { return Some(n); } let hits: Vec<&str> = COMMANDS .iter() + .chain(SETTINGS) .map(|(n, _)| *n) .filter(|n| n.starts_with(&w)) .collect(); @@ -414,6 +423,18 @@ enum Tab { Of(Category), } +/// The level above the tabs: the 1Password vaults the entries came from, then one of +/// them. `In(None)` is what no vault owns - added by hand, imported from a CSV, or a +/// Developer Environment, which belongs to the account rather than a vault. +#[derive(Clone, PartialEq, Eq)] +enum Shelf { + Vaults, + In(Option), +} + +/// The row that stands for entries no vault owns. +const NO_VAULT: &str = "(no vault)"; + impl Tab { fn label(self) -> &'static str { match self { @@ -476,6 +497,10 @@ pub struct Shell { known: HashMap, /// Which tab of `/list` is showing. tab: Tab, + /// The 1Password vault each entry came from, as the last sync on this host saw it. + vaults: BTreeMap, + /// Whether `/list` shows the vaults or the inside of one. + shelf: Shelf, unlocked: bool, has_pin: bool, retries: u8, @@ -498,6 +523,8 @@ pub fn run(dev: Device, version: Option) -> Result { entries: Vec::new(), known: HashMap::new(), tab: Tab::All, + vaults: BTreeMap::new(), + shelf: Shelf::Vaults, unlocked: false, has_pin: true, retries: MAX_ATTEMPTS, @@ -678,7 +705,16 @@ impl Shell { if listing { let open = self.tab; let mut parts = vec![(Color::Reset, " ".to_string())]; - for (i, t) in self.tabs().iter().enumerate() { + // The vault level has no tabs; inside a vault its name leads them. + let place = match &self.shelf { + _ if self.vaults.is_empty() => None, + Shelf::Vaults => Some((ACCENT, "vaults".to_string())), + Shelf::In(v) => Some((DIM, format!("{} ▸ ", v.as_deref().unwrap_or(NO_VAULT)))), + }; + let at_vaults = self.at_vaults(); + parts.extend(place); + let tabs = if at_vaults { Vec::new() } else { self.tabs() }; + for (i, t) in tabs.iter().enumerate() { if i > 0 { parts.push((DIM, " · ".into())); } @@ -718,6 +754,10 @@ impl Shell { // like the firmware label above, so the keys show whatever the status row's // width leaves. let legend = match (self.letters_act(), listing) { + _ if listing && self.at_vaults() => " Enter open · type to search ", + (true, true) if !self.vaults.is_empty() => { + " Enter use · type to search · a e d i · ← → tab · Esc vaults " + } (true, true) => { " Enter use · type to search · a add · e edit · d delete · i import · ← → tab " } @@ -845,6 +885,7 @@ impl Shell { /// the whole of it. fn relist(&mut self) -> Result<(), Error> { self.entries.clear(); + self.vaults = op::load_vault_map(); let entries = self.dev()?.list()?; // One request per item, and what it says changes only when the item is // rewritten - where `forget_logins` drops it. Asking again for what is already @@ -1205,12 +1246,20 @@ impl Shell { /// why the list holds nothing but items. The category is a column, not a tab: /// there are twenty-four of them now, and an item can be a login and a TOTP code /// at once. - fn cmd_list(&mut self) -> Result<(), Error> { + /// `/list [vault]`: the vaults, or straight into one. Enter on a vault runs this + /// too, so a key that locked meanwhile asks for the PIN before the vault opens. + fn cmd_list(&mut self, vault: &str) -> Result<(), Error> { self.ensure_unlocked()?; self.relist()?; if self.entries.is_empty() { self.line(DIM, " nothing stored yet - a adds, i imports"); } + self.shelf = match vault.trim() { + "" => Shelf::Vaults, + NO_VAULT => Shelf::In(None), + v => Shelf::In(Some(v.to_string())), + }; + self.tab = Tab::All; self.open_list(); Ok(()) } @@ -1219,14 +1268,62 @@ impl Shell { fn open_list(&mut self) { self.input.clear(); self.cursor = 0; + let items = if self.at_vaults() { + self.vault_groups() + .into_iter() + .map(|(vault, n)| Row { + text: vault.unwrap_or_else(|| NO_VAULT.to_string()), + login: String::new(), + what: format!("{n} item{}", if n == 1 { "" } else { "s" }), + }) + .collect() + } else { + self.tab_entries() + }; self.menu = Some(Menu { - items: self.tab_entries(), + items, selected: None, first: 0, kind: MenuKind::List, }); } + /// Whether `/list` shows the vaults. Never before a sync has named any: then the + /// level would hold one row, and the tabs are what was always shown. + fn at_vaults(&self) -> bool { + self.shelf == Shelf::Vaults && !self.vaults.is_empty() + } + + fn vault_of(&self, e: &Stored) -> Option { + self.vaults.get(&e.name).cloned() + } + + /// The vaults the key's entries came from with how many each, by name, and what no + /// vault owns last. + fn vault_groups(&self) -> Vec<(Option, usize)> { + let mut counts: BTreeMap = BTreeMap::new(); + let mut loose = 0; + for e in &self.entries { + match self.vault_of(e) { + Some(v) => *counts.entry(v).or_default() += 1, + None => loose += 1, + } + } + let mut groups: Vec<(Option, usize)> = + counts.into_iter().map(|(v, n)| (Some(v), n)).collect(); + if loose > 0 { + groups.push((None, loose)); + } + groups + } + + fn in_shelf(&self, e: &Stored) -> bool { + match &self.shelf { + Shelf::Vaults => true, + Shelf::In(v) => self.vault_of(e) == *v, + } + } + /// Whether `/list` is what is showing. fn listing(&self) -> bool { self.menu @@ -1865,41 +1962,29 @@ impl Shell { let done = if query.is_empty() { self.line(Color::Blue, " ● 1Password Developer Environments (.env)"); - let saved = op::load_saved_envs(); - let mut env_pairs = Vec::new(); - - if !saved.is_empty() { - let mut env_list: Vec<(String, String)> = saved.into_iter().collect(); - env_list.sort_by(|a, b| a.0.cmp(&b.0)); - - let prompt_label = format!("include {} saved Environment(s)?", env_list.len()); - let include_saved = self.choose( - &prompt_label, - &[ - (true, "update saved", "include all saved environments"), - ( - false, - "custom / add new", - "add or enter environments manually", - ), - ], - ); - if include_saved == Some(true) { - env_pairs.extend(env_list); - } + // `op` cannot list Developer Environments, so the saved ones are the whole + // known set: every sync takes all of them, and a new one is only ever added. + let mut env_pairs: Vec<(String, String)> = op::load_saved_envs().into_iter().collect(); + env_pairs.sort_by(|a, b| a.0.cmp(&b.0)); + // With some saved, the run just takes them: asking every time for one more + // is a question nobody needs. A new one comes in through /op env. + for (name, id) in &env_pairs { + self.line(DIM, &format!(" saved: {name} ({id})")); } - if env_pairs.is_empty() { self.line( DIM, " (in 1Password: Developer -> View Environments -> View environment -> Manage environment -> Copy environment ID)", ); - while let Some(pair) = self.ask_env("add Environment (name or name:ID, Enter to proceed): ") { - env_pairs.push(pair); + if !env_pairs.iter().any(|(n, _)| *n == pair.0) { + env_pairs.push(pair); + } } + } else { + self.line(DIM, " (another one: /op env)"); } let env_refs: Vec<(&str, &str)> = env_pairs @@ -2170,6 +2255,19 @@ impl Shell { } } + /// `/settings`: one of the commands that act on the key itself. + fn cmd_settings(&mut self) -> Result<(), Error> { + let options: Vec<(usize, &str, &str)> = SETTINGS + .iter() + .enumerate() + .map(|(i, (name, desc))| (i, *name, *desc)) + .collect(); + let Some(at) = self.choose("settings:", &options) else { + return Ok(()); + }; + self.dispatch(&format!("/{}", SETTINGS[at].0)) + } + /// A `/command [arg]` runs the command; anything else is the name of an entry to /// use, and an empty line offers the list of them. Leaving is Ctrl-D, not a command. fn dispatch(&mut self, line: &str) -> Result<(), Error> { @@ -2207,7 +2305,7 @@ impl Shell { } let r = match cmd { "use" => self.cmd_use(arg), - "list" => self.cmd_list(), + "list" => self.cmd_list(arg), "add" => self.cmd_add(arg), "edit" => self.cmd_edit(arg), "rm" => self.cmd_rm(arg), @@ -2220,6 +2318,7 @@ impl Shell { } } "lock" => self.dev()?.lock().map(|()| self.refresh()), + "settings" => self.cmd_settings(), "pin" => self.cmd_pin(), "wipe" => self.cmd_wipe(), "setup" => self.cmd_setup(arg), @@ -2299,6 +2398,9 @@ impl Shell { } fn in_tab(&self, e: &Stored) -> bool { + if !self.in_shelf(e) { + return false; + } match self.tab { Tab::All => true, Tab::Totp => self.known.get(&e.name).is_some_and(|k| k.has_seed), @@ -2311,11 +2413,12 @@ impl Shell { /// drawn, so a tab never outlives what put it there. fn tabs(&self) -> Vec { let mut tabs = vec![Tab::All]; - if self.entries.iter().any(|e| self.in_seed_tab(e)) { + let shown = || self.entries.iter().filter(|e| self.in_shelf(e)); + if shown().any(|e| self.in_seed_tab(e)) { tabs.push(Tab::Totp); } let mut counts: Vec<(Category, usize)> = Vec::new(); - for e in &self.entries { + for e in shown() { match counts.iter_mut().find(|(c, _)| *c == e.category) { Some((_, n)) => *n += 1, None => counts.push((e.category, 1)), @@ -2395,8 +2498,9 @@ impl Shell { } fn letters_act(&self) -> bool { + // A vault row is not an entry: e or d on it would edit or delete by its name. self.menu.as_ref().is_some_and(|m| match m.kind { - MenuKind::List => true, + MenuKind::List => !self.at_vaults(), MenuKind::Names => m.selected.is_some(), MenuKind::Commands => false, }) @@ -2468,7 +2572,40 @@ impl Shell { .map_or(self.cursor, |c| self.cursor + c.len_utf8()) } + /// The keys the vault level of `/list` answers differently: Enter goes into the + /// highlighted vault, Esc inside one steps back out to the vaults. + fn vault_key(&mut self, code: KeyCode) -> Option { + if !self.listing() { + return None; + } + match code { + KeyCode::Enter if self.at_vaults() => { + // A vault is a place to go into, not a name to run. + let Some(vault) = self + .menu + .as_ref() + .and_then(|m| m.selected.map(|at| m.items[at].text.clone())) + else { + return Some(Key::Redraw); + }; + self.input.clear(); + self.cursor = 0; + self.menu = None; + Some(Key::Submit(format!("/list {vault}"))) + } + KeyCode::Esc if matches!(self.shelf, Shelf::In(_)) && !self.vaults.is_empty() => { + self.shelf = Shelf::Vaults; + self.open_list(); + Some(Key::Redraw) + } + _ => None, + } + } + fn handle_key(&mut self, k: KeyEvent) -> Key { + if let Some(key) = self.vault_key(k.code) { + return key; + } let ctrl = k.modifiers.contains(KeyModifiers::CONTROL); match k.code { KeyCode::Enter => { @@ -2515,8 +2652,9 @@ impl Shell { } // In the list the arrows turn the tab; a highlighted name there is not // something to edit in place. - KeyCode::Left if self.listing() => self.shift_tab(Dir::Prev), - KeyCode::Right if self.listing() => self.shift_tab(Dir::Next), + KeyCode::Left if self.listing() && !self.at_vaults() => self.shift_tab(Dir::Prev), + KeyCode::Right if self.listing() && !self.at_vaults() => self.shift_tab(Dir::Next), + KeyCode::Left | KeyCode::Right if self.listing() => {} KeyCode::Left => self.cursor = self.prev_char(), KeyCode::Right => self.cursor = self.next_char(), KeyCode::Home => self.cursor = 0, diff --git a/cli/src/sources.rs b/cli/src/sources.rs index 39e6913..f986927 100644 --- a/cli/src/sources.rs +++ b/cli/src/sources.rs @@ -27,7 +27,6 @@ use crate::prompt::SyncUi; /// The buckets a name can belong to. A name has exactly one owner: the sync that /// wrote it last. pub const OP_ITEM: &str = "op:item"; -pub const OP_DOC: &str = "op:doc"; pub const OP_ENV: &str = "op:env"; pub const FILE: &str = "file"; @@ -423,7 +422,7 @@ mod tests { #[test] fn prunes_only_what_the_bucket_owns_and_the_source_dropped() { - let m = manifest(&[("gone", OP_ITEM), ("kept", OP_ITEM), ("doc", OP_DOC)]); + let m = manifest(&[("gone", OP_ITEM), ("kept", OP_ITEM), ("doc", OP_ENV)]); let prune = m.to_prune(OP_ITEM, &set(&["kept"]), &set(&["gone", "kept", "doc"])); assert_eq!(prune, vec!["gone".to_string()]); } @@ -498,7 +497,7 @@ mod tests { ("AWS:alice", OP_ITEM), ("AWS:bob", OP_ITEM), ("AWSomeApp", OP_ITEM), - ("AWS:doc", OP_DOC), + ("AWS:doc", OP_ENV), ]); let family = m.family(OP_ITEM, "AWS"); assert!(family.contains(&"AWS".to_string())); diff --git a/docs/items-v2.md b/docs/items-v2.md index d70840c..510a2f3 100644 --- a/docs/items-v2.md +++ b/docs/items-v2.md @@ -152,6 +152,11 @@ will not take them back as that item's attachment. Items that are only an attach the maintainer's three signing-key documents - are named in the import summary and left where they are. +Since 2026-10-15 (maintainer's decision) the sync leaves every Document item in +1Password: it is a file, and the key is no file store. The separate pass that read +documents as `.env` files is gone too; a `.env` comes in as a Secure Note. Both can be +restored from commit `7c50caf` (`cli/src/op.rs`, `Mirror::documents`, `process_document`). + ## What this costs, honestly - ~3-4k lines of the 12.5k in the repo are touched. From 624fb91c523b8571d1df4b90806f054f4d344e17 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 01:14:39 +0300 Subject: [PATCH 13/33] Close the nRF52840 debug port with APPROTECT at boot --- docs2/roadmap.md | 23 ++++++++++++++- .../nrf52840-mdk-dongle/images/vaultkey.bin | Bin 77100 -> 77164 bytes .../images/vaultkey.signed.uf2 | Bin 155136 -> 155136 bytes .../boards/nrf52840-mdk-dongle/src/main.rs | 27 ++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 9c3bf8c..94ead40 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -518,8 +518,28 @@ Acceptance: Acceptance: after a reset, the `chip:` line shows the `APPROTECT` low byte at `0x00`; the board still updates through UF2; `selftest` green. +**Written 2026-10-15** (`protect` in the board's `main.rs`, run at boot before INFO is +built). It writes only while the low byte is not 0x00: +- `NVMC.CONFIG` = WEN, then one store of `0xFFFF_FF00` to 0x10001208, then + `CONFIG` = REN, waiting for READY around each step; +- no retry and no reset. A word that did not stick shows in `vkey info`. + +The disassembly holds that sequence and no other store to UICR. The PAC's `write` +starts from the register's reset value, 0xFFFF_FFFF, so only PALL changes. + ## Phase 5 - chip key, then move daily use +**Skipped on this chip (2026-10-15; the maintainer left the call to the analysis).** +Once APPROTECT is on, a copy of the flash needs the boot-time glitch. A and B both start +from a secret the firmware loads out of flash at boot - B only moves it into CryptoCell's +write-only register afterwards - so the same glitch, before the ACL lock, reads it too. +Neither adds protection against the one attack left. A would mostly bring `vkey auth` +back, and phase 6 removes `vkey auth`. B would also break "crypto from RustCrypto". The +vault stays PIN-only, as `docs/threat-model.md` says. A revision-3 chip would change the +answer, since its glitch fix leaves the ACL lock standing. + +The C6 steps below are not done either: the C6 is left alone (maintainer, 2026-10-14). + **Chip key.** On this chip any secret is loaded by software, so a chip key is only as strong as phases 3-4. Two options, decided by the maintainer: @@ -579,7 +599,8 @@ Acceptance: registration and login on webauthn.io and with `fido2-token`; `pam_u | Phase 3 | ~~own bootloader instead of the Nordic secure bootloader~~ - own fork chosen (2026-10-13), installed on the maintainer's go (2026-10-14) | | Phase 3 | ~~the signing key's second home~~ - a `.vkb` that restores onto the C6; the C6 is the test board, everything else is on the nRF (2026-10-14) | | Phase 5 | ~~wiping the C6 after migration~~ - the C6 is a test board, not a fallback, and neither board holds real secrets (2026-10-14) | -| Phase 5 | chip key option A or B | +| Phase 5 | ~~chip key option A or B~~ - neither on this revision-2 chip: the boot-time glitch reads either (2026-10-15) | +| Phase 6 | ~~passkey backup~~ - a deliberate export into the `.vkb`, outside FIDO's no-export rule (2026-10-15) | | Phase 6 | RTIC or Embassy, and the `unsafe` rule if the runtime needs it | ## Sources diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin index 2b6df7291f29262b2eafaba69a4c47ec1a1a29a4..16303a9509a90db22abc6f30a22001aba07c2b17 100755 GIT binary patch delta 3772 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 delta 3696 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 D(7Tmg diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.signed.uf2 b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.signed.uf2 index 795b4a8b2366c1f015dd9112dc17bca6de4d74b5..6106f27ab39557a8a6cb8e92774d58f60837e778 100644 GIT binary patch delta 11258 zcmbW6dt4Ot`p4%xEbDTa1sO!Z+b(wyw2yfCVP<8EaT4&Plb?*IIG>iGGw-Wu!L_y2rs*^YB2uF)X%mL}aL#eoWG z4NwZ~SNWTSRM9%!D3WIP^GzY-ZJMR;H{dsCSffeGbIc~am3KNnYvzK)dW&S1rb|A` z2KuzVFPQ$SpGIcbf7ZW8$T0dh!wAwuzc9p;kL}{di!smH5-ER9aZ$Ie>ADG`v#==_#JK+ z?s2nFe9#z8o}hD#gLT15h)OGrkz^I!XBZJ9-aY+r%RH>IbX=X3AXriyOy@N=#`J6si`FUM>)ifz($3?Y)3sQ_uaGA*u z)Ja095E9MnoHRXTB>93q8Db9D>`brpRVH^}Iom_}k(2ar$YiLrmk9G#MMs1_NOI}& z&?ztxUx!AM9Q&W450F7sGin_q!1rgI#FF}5YJKp&X2NaAEBtn7Wsvd%%?&eyd0tqw zZ)rP5el=_m`I7Df^;230|7X!Z!y?E8yIkS*nbWmOUO|=IC2m~o)DQxC|w?z)#qqu#(uv>-fWRb6c^1a2RqU7-;rZU zfjyvKG{MoP_TNC(&`aM6mDyc0Y%5E6YpOE7;cHrRHcU7S|)o7NC_jFT&qY|Xv zN|l;Y$(g_SU8lE5Nm4jO{hlr#7@I~h_Kezm96P7yl#gx1e4-IGUo&bJiB~pv@V`w` zd;_jr!#chm7@JzsmLTbr%GTO^63gigHItOCVHPP7*wr1EuJh*ZnBac?YB?-MLlo=P zpxAIVz6#eyGfi=13!QC>AlK=0rg+jt-!MhTKG=cXH=O@Y zZ3s?)CEe1!O_b@j1hD2i zmb3n&y5B{jZ#HryBBB!41m6$VL{Y>RqY~16$X2P@q*sEzKD?4wE_c)(?3G|qtS<$c z(|6*`evwLe7{r(9@#Kd6&-6Kj?4gr0pm6$ZMpp0pZRwT5JzL>4>43U7-$%)@pU7BF z;6NBLd@}i({&je4@3n33HWzW`?!Kf#U!rKu@DY8cwr3YZIPC0H5 z7!g584vo!B6ooB@n`8UBi0vjgjRq?%c6;_MLOSUiqbHC{_FJRhBXDZ-QRxm# zg86pWd;RkqIo!*6HbqIdXHpORsS$M?uAO((bOAZ-W6tZA#_KA`}p$Y^P7=MZko=lJ_`y#NM2j zMS?6{;XB@KzQj%Io|!!~%ZlfZY1RRxkUndD-8e+;RVlTE5B*6!Q+v|Ej=eEM07;Zy zg#~?BN+hN9-_j6r$S#Z>Lt+Gvqec+6eiuTzT3Q#3pEERX>|O!G%}MuKW>=+ z+*Xs630k;HkB-YD+4hcc6A1Z;jxTru0v;|%6u(x>94tyKC+Evio0KDhgfb5=VqMN}Fkt^#Mdx0DX^ z948r-tMqC~KjHhfq{``146r`RXuIE(2Z)YWIF(warjt1PGgF(%sHz#zZl8?(oCyzW zAC=o38BS7739aYhpjIqhDV50;o%gGbB*J&Rq1aD($JtxrOr|J5WjFn2X}|a_PT%H0 z5@^CJ06*o`?!A-l+Lrn$FFV0e1h2_{$}9G(rN0w@e`h$HPW|9Jkv2@vAZP4;GlmfO z5+5-$ja1UdXAU9NRGv9Ryrbr|WOKaPTvC6$=1$6M2IXJ$`5B+v;NOJ!Ry#c z!Ee-A50V>n!mN1GK%bd4o{YC2pS6pSHaeqh8l1ommyN)yhq5(f$`Mt#7r1Jgfu#S>3g1zqV(2S1IgCmjq=l zt(iNCY_SK;izNXsbSA)QJqoO;G-rO_2}{~j;d=(R2X$@w0M3)TUat#|nR)ukM5*p~ z&d(&(sRmo1GNVgyEQXUyaFkK;@5*z;a<(z%3w}2Z9O${I!Z*zPF#)SpgYrd3ya}e6 zHqSR3KkBd@eoFeF<;as#%h8_iEu4`BgULLawIKF|A~n}xNa$UD!oeAAcY-%uQsF{R zA5mZE;4G&cgd+>T>eXIP%(benH~ajQ(nZdwTrk_>JoZ=}r#KRI(g6|ft$X_XjY&D& zV2eW6ow$*o!VPXY&zWoP%zmv_<$6Eln3h}X;7ESHL(QvGWBTMfR?dONMTC2A&#O~S zeezojX}Aq9-k?0#!NGa_H=D(w3(jvbr9rWr?f|!tiyEuy0$qI;t&o^-Tn4#cA3MED>qr zVhc4b*$h{#A1>+Be@_tv<47F3(oJ=0rD2l7fp@DR*yOT_-;jAJ6PrUiR`(@-V$uKDhVGYBHB9aZ$d}bt-4; zx<8MmEq#FWqmM0po<(>jmNqVhnwOoRQRFgSCyNtU#8F-mmjSb))}3`CW3s)N6~L@? zGgMdw^RW`NRc=izWWLc}zE!}i?qSwIJ*#1Rt=mHd8^l=)n(aVHO!42;aU9GlFI4zM z2UO@x?vf_6(79frZD3pH5$YufwGOnG+?x0>^W}T_UIJ!)5AzC?v>vuMEFeedD;wg; z3i{y&kG5}wm>XdKMlI%47E|(yxe$jEpA4f&f*k!#n}SPRyRY1Z4hTGXxrSHIFtFXlkS7MaT_p|Jv*{d;+F=mPvvlp26-3%4>L+tlK+rJKG;;sD; zvbFXBRIwk_10G~GkOx4k9!<{B+0`$)SLNd@&or+*)j%H94!A{(!A5H1J_yVqj|?9} zhC`rz+~fNMs`wbTk7#k8WN{w#igN^3-O-xvgS(B0R5%84j)L!)JGS@~^I_Yx{KtU# zyeD=Ig0YA&a{lzQXIbgogn3arK=*4^kOud_-!Uc$3588zu?OQ10f+Y!mVH%Xb zw4KQJ(?1Fqx4Lu_{&3@C%s$Zu#oVn=KA-OhD5eDsvq&HMUPFqZLq%M7-c|X4=UD|$ zcvRrqoIy-d`~7<=ZE6@!O&2|CxdgRbgl1o=aYYc!A}i|g{FlBL<;mBxrvu%|f$&A}*#XtKD2nXzqJ zjUh;dGD>##!D2#D3iHUilNqsZnlTKia4oznL}J!(lp{Um{wPPH++UN$f3ldbdByCH z)Ie7;gRq!^D0y^Be1jSP?qxI~6{Urjg&52lg>sB0i*GSA^)kmG6{k_MkbvemloMRV zBw{fMC?$E4$w(%loUF;>yDW|Dl_nY6K9sc`uQg>M70pA@oa#!GhG|k!O4s7aLI#rQ zC}(K0xR0fI-78H7Qp17jS(>ttiRR%bXL^`FVCG$3=1i<{q-$x8!eU0EG26rVAv0nF zwbhV~)M$;81q)^!jj~0P#gCX7o2Z#BNabmiELhQ;hq9H)vU3a;V?{~wB*!5sp*&8L z#ltMkJ6>tVAyuGJvM>?N1t?F{WbqSb#wKbtPDHAZQL=Lq7E_2)k%#e9W_-`f2)DFk zQ?W+LLJ4LqM!7_j#m|@-d#YtEL29Zi>m!(TDoUju#^cP0{nU)5NKMx$S(u4gr=vVm zlf@cl#-3{CnMlpjC|M{&^DLChm@GTzU@>JV&DBWpB#U>@E8bkB=4+HJEWmj4QC^_Q z;wff6QZPF-N*o@{)C~wwe@e(s*=e3b+Myi5Qvh(j)Z3RkO zJdBr_5xcG#w;;7uqhw(lX5EVNHcb|PWM=HVX5NNWrAEoZ4m4Myyo1TI^K~p{2TD6V z$tomwqFklPVk1j~t=7_1A+=khWZ_LT??(AeSDLpl&6_B_?b*;hNWM+7buoFyt+Hv4 z7DfDpT95-I-58UHKQrQ*biT!l>r~lPO&0Mn7I{-ODRG%);ULDYCgFTczT8$# z;$+i7Qj8nR4#Lyro~NY|O)LjC-<2cGn%@$WCtp8EM#`o`B%6ngS%=8d;FvLx)>nVi zFW}abF-^Q4gUHUqIJ1Xv3?GvOWD7nfD@-wP%a3rDCH#(3Yn^JTD6>X28GRG1#wH*5 zzrM*;fcOV102h#}0J-sF40i-;FOWwbfu~G8<;ucQ9MutG;bX?gQAbH05(|#PGvyva zyv^cW@rrj8;~n#y`Ok?Ma?w|)8fFcGm+wu39tJ%|b{r!^Wz*+mBF10xIa$iaSVLm< z2LEp2`sX+;wKy$feA9PabZua-?`Nf|EUb!XwBpSz@USkhV2A4}*w zOQK}cIb4TUdD%H_9h&d6e7||*Yw(TS8EXxMSNAY(pCjqA=^G;9#4r4YEb(Vk3BB{v zvejd@Z*ZRKNit?BtS2k_yGVbS^ae|vI?guHs=FEJ8`l(|V^eY-r=%Wz7l;Xcc^BCH z9=$-~wD1iW{sOUt9FanIu5Y@ekFySP&2xGKS&j2p-9S=Z4$;ZRb<<;9a$^Ir7^YhF zI4+Bva1j$(4wmAUSBgt` zd3%{Wg#9SL43EcvmYqM~C@-pE* z%Qck6(0RqsBW&RJhL=7Drx#zJ%A+?5Ig3>!fk+uWsBlIZyeK15!5SqCAvnTdltWxuMa&ukQf&wyET@L@)vV?| zV$ZAvc*P7wbC_q$aEuv-a=0do16V=0CbaQ}BNeGpvd|yRktp|f6*K?~>W|Vu7dgmP z3-(_NHxQwo&a>a^Q5epIa+J#pkBp*NEjS*{9EDVjD`_kyjp5-aj^iJKd%kjc9RGCp zFAZnBC>s;_5V+ldjs%amu`DjOR*Rbe)HMsADVHYk8{F-WV`!KcnuGz9wSclP6zfk$ zd8n(h6s&A0N~ta~4Jt|p@@gud1GgbuGK@5drHS-PlaA&L4{9)@`gu_qK%GwJr^~B` z^9!(U**OAJ4@Y;VhkFQfV}rF(XCgJyMU8UxYoHf25}|Atg!flQ<9M@C9<9k@D$8K< zGLHu8P!gXl&$RF_V`pS%F4kv3cb?{kTN4;G4`r)M9^)z~+AF3NA;|?{LF3RXp*&8L z#bK-<{m_{S188!#kcKpM%dr_h+74 z@78tPreUOe-rFYdaeaci0R#6s06yKHgSq$Rdj?o!W^rejH^C{O2WKQYbV1BuV#Avm3BmYBW?pWO{N zADy?U;LZ~d=DzTa-=n2hMyRRnSs7<`j=UJ}KR@(XgK)8=dHIPgS9Zu^EMe`HvTVeoG&Q= delta 11236 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 diff --git a/firmware/boards/nrf52840-mdk-dongle/src/main.rs b/firmware/boards/nrf52840-mdk-dongle/src/main.rs index 9384908..a690954 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/main.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/main.rs @@ -360,6 +360,30 @@ fn chip_report( Ok(()) } +/// Closes the debug port for good: UICR `APPROTECT` goes from erased to Enabled, the low +/// byte 0x00 and the rest left at 0xFF. On revision 1-2 an erased word leaves SWD open; +/// on revision 3 it is closed unless UICR holds 0x5A, and 0x00 takes that away. It takes +/// effect at the next reset. Irreversible with no probe, and harmless to the owner, who +/// never has one - so the firmware does it itself, the first time it boots. +/// +/// One attempt, no retry and no reset: a loop around a write that does not stick is how +/// boards have been reported to hang. A word that did not change shows in `vkey info`. +/// Nothing else writes UICR, and with the port protected nothing can afterwards. +fn protect(nvmc: &pac::NVMC, uicr: &pac::UICR) { + if uicr.approtect.read().pall().is_enabled() { + return; + } + let ready = || while nvmc.ready.read().ready().is_busy() {}; + ready(); + nvmc.config.write(|w| w.wen().wen()); + ready(); + // `write` starts from the register's reset value, 0xFFFF_FFFF: only PALL changes. + uicr.approtect.write(|w| w.pall().enabled()); + ready(); + nvmc.config.write(|w| w.wen().ren()); + ready(); +} + /// Fail closed: a panic resets the chip. The vault comes back locked, and the statics /// that held keys are zeroed again at boot. #[panic_handler] @@ -372,6 +396,9 @@ fn main() -> ! { let p = pac::Peripherals::take().expect("the peripherals are taken once, here"); let mut cp = cortex_m::Peripherals::take().expect("the core peripherals are taken once, here"); + // Before INFO is written, so the chip line shows the word as it now stands. + protect(&p.NVMC, &p.UICR); + let info = INFO.init(heapless::String::new()); writeln!(info, "{VERSION}") .and_then(|()| chip_report(info, &p.FICR, &p.UICR, &p.POWER)) From b68930302cb70c1bc859de86cf4b93032eacfb30 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 01:18:48 +0300 Subject: [PATCH 14/33] Accept APPROTECT on the nRF52840 and skip its chip key --- README.md | 5 +++-- docs/threat-model.md | 27 +++++++++++++++++---------- docs2/makerdiary.md | 3 ++- docs2/roadmap.md | 9 +++++++++ 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e74f7b2..4b3f474 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,9 @@ single-binary host CLI, and a press of the board's button for every secret that > **Two boards** (2026-10-13). Development now targets the Makerdiary nRF52840 MDK USB Dongle > (`firmware/boards/nrf52840-mdk-dongle`), the board passkeys will come to. It runs the same > core and passes the full lifecycle test. Its bootloader is now our own fork, which runs -> only signed firmware and serves no flash back. It has no chip key yet, though, and its debug -> port is open. So it is **not for real secrets** until the steps +> only signed firmware and serves no flash back, and APPROTECT closes its debug port. This +> revision-2 chip can still be glitched open, though, and it has no chip key +> ([docs/threat-model.md](docs/threat-model.md)). So it is **not for real secrets** until the steps > in [docs2/roadmap.md](docs2/roadmap.md) are done, and `vkey setup` does not flash it yet. > Everything below still describes the ESP32-C6-Zero, which is now only a test board. diff --git a/docs/threat-model.md b/docs/threat-model.md index c0d6b2d..387a4e4 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -25,11 +25,12 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure 0.97 ms per guess at 20 passes (2.4 ms at the C6's 48). All 10^8 PINs then take about 28 core-hours, a few hours on an ordinary laptop, and less on a GPU. The "years for eight digits" figure is for the C6 with the counter erased; it does not apply here. -- **The flash can be copied over SWD.** The chip reports revision 2 (build code `AAD0`) - with UICR `APPROTECT` erased, which on revision 2 leaves the debug port open. Revision 2 - also predates Nordic's fix for the published APPROTECT voltage glitch (IN-133), so even - with the port closed in UICR, someone with glitching gear can open it and read the - flash, a chip key in it included. +- **The flash can be copied only with a glitch.** The chip is revision 2 (build code + `AAD0`). Since 2026-10-15 its firmware has written UICR `APPROTECT` to Enabled + (`0xffffff00`, phase 4), which closes the debug port from the next reset on, for good. + Revision 2 predates Nordic's fix for the published APPROTECT voltage glitch (IN-133), + so someone with glitching gear can still open the port at boot and read the flash. A + chip key would fall the same way, which is why there is none (roadmap, phase 5). The USB drive no longer hands it out. The factory UF2 bootloader served `CURRENT.UF2`, the whole application area, to anyone who held the button while plugging the key in. @@ -51,7 +52,8 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure Everything above applies to it: - for 1 h 17 min, until the fork was installed, `CURRENT.UF2` and the offline PIN search handed it to anyone who held the board for a minute and then computed for a few hours; - - since then, SWD does the same until APPROTECT (phase 4), and the glitch after that. + - then SWD did the same, until APPROTECT closed it on 2026-10-15 (phase 4); since then + it takes the glitch. Whoever has the key signs firmware the fork runs. By design, the fork moves to a new key only through a self-update signed with the old one. A leak is mended only while the @@ -64,10 +66,15 @@ everything once the steps below are done. The glitch above stays open after them who takes the key and has the gear reads the flash and finds the PIN offline in hours. For a personal key, that risk is accepted rather than paid for with a revision-3 dongle. -Before this board holds a real secret, all three are required: our own fork of the UF2 -bootloader (signed images only, no read-back, writes only to the application region), -APPROTECT, and a chip-bound key (a secret in a flash page locked by the ACL until reset). -The plan is in `docs2/roadmap.md`. Nordic's secure bootloader was dropped from it: there is +Before this board holds a real secret, two things are required: +- our own fork of the UF2 bootloader, which runs signed images only, serves no read-back + and writes only to the application region (accepted 2026-10-14); +- APPROTECT (written 2026-10-15). + +A chip-bound key, a secret in a flash page locked by the ACL until reset, was the third. +It was dropped on this revision (2026-10-15): it loads from flash at boot, so the glitch +above reads it as well, and it would protect nothing the PIN does not already. On a +revision-3 chip it would be worth having. The plan is in `docs2/roadmap.md`. Nordic's secure bootloader was dropped from it: there is no SWD probe, and installing it moves the bootloader address in UICR, a one-shot change with no way back. diff --git a/docs2/makerdiary.md b/docs2/makerdiary.md index 23f15d3..bdca64b 100644 --- a/docs2/makerdiary.md +++ b/docs2/makerdiary.md @@ -343,7 +343,8 @@ Open questions only the board answers: `APPROTECT` means the debug port is open: anyone with an SWD probe reads the whole flash today. Revision 2 also lacks the fix for the published APPROTECT glitch (IN-133), so closing the port in UICR stops a probe but not someone with glitching gear. The bootloader - reports nrfx 2.0.0 in `INFO_UF2.TXT`. + reports nrfx 2.0.0 in `INFO_UF2.TXT`. Since 2026-10-15 the firmware has written + `APPROTECT` to `0xffffff00` (roadmap phase 4), and the port is closed from the next reset on. ### Reading the `chip:` line of `vkey info` diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 94ead40..a154497 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -527,6 +527,15 @@ built). It writes only while the low byte is not 0x00: The disassembly holds that sequence and no other store to UICR. The PAC's `write` starts from the register's reset value, 0xFFFF_FFFF, so only PALL changes. +**Installed and accepted 2026-10-15,** on the maintainer's go: +- copied as `vaultkey.signed.uf2` through the fork; the first boot showed + `UICR APPROTECT 0xffffff00`, with the PIN and its 8 attempts intact; +- after a reset with the button held, the fork took the same signed UF2 again and ran it, + so updates go on with the port closed; +- `selftest` green (device 627642 against the independent HMAC). + +**Phase 4 accepted 2026-10-15.** + ## Phase 5 - chip key, then move daily use **Skipped on this chip (2026-10-15; the maintainer left the call to the analysis).** From b446afd7d795c41907c850f59a09532e2fdba2e7 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 09:42:18 +0300 Subject: [PATCH 15/33] Serve USB during waits and add CTAPHID to the nRF52840 --- docs2/roadmap.md | 66 ++- firmware/Cargo.lock | 525 +++++++++++++++++- .../boards/nrf52840-mdk-dongle/Cargo.toml | 3 + .../nrf52840-mdk-dongle/images/vaultkey.bin | Bin 77164 -> 81068 bytes .../images/vaultkey.signed.uf2 | Bin 155136 -> 162816 bytes .../boards/nrf52840-mdk-dongle/src/main.rs | 126 ++++- 6 files changed, 684 insertions(+), 36 deletions(-) diff --git a/docs2/roadmap.md b/docs2/roadmap.md index a154497..24b7121 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -581,11 +581,12 @@ nRF; `check --wipe-everything` green on the C6. ## Phase 6 - passkeys (FIDO2) -- **USB moves to interrupts.** CTAPHID must send keepalives while it waits for a touch, and - a composite device (CDC for vkey + CTAPHID) must serve both interfaces during any wait. - This is also the real fix for "USB unserviced during the tap wait". -- **Runtime: RTIC (Nitrokey's choice) or Embassy.** Before choosing, check whether its - macro-generated `unsafe` trips the board's `unsafe_code = "deny"`. +- ~~**USB moves to interrupts.**~~ CTAPHID must send keepalives while it waits for a touch, + and a composite device (CDC for vkey + CTAPHID) must serve both interfaces during any + wait. That is now done by polling during every wait, not by an interrupt: see "No + runtime and no interrupt" below. It is also the fix for "USB unserviced during the tap + wait". +- ~~**Runtime: RTIC (Nitrokey's choice) or Embassy.**~~ Neither: see "No runtime" below. - **Trussed + `fido-authenticator`**, with littlefs at 0xD8000..0xEC000 and P-256 from `p256-cortex-m4`. Re-measure the fit and the stack high-water mark. - **Then Linux login moves to `pam_u2f`**, and the old `vkey auth` is removed, recorded in @@ -595,7 +596,58 @@ nRF; `check --wipe-everything` green on the C6. it. Acceptance: registration and login on webauthn.io and with `fido2-token`; `pam_u2f` with -`sudo`; `selftest` green; core changes pass `check` on the C6. +`sudo`; `selftest` green. Core changes pass `check --wipe-everything` on the nRF, followed by +a restore from the `.vkb` and a 1Password sync; the C6 is left alone (2026-10-14). + +**What is available (checked 2026-10-15).** The whole stack is on crates.io, recent, and +agrees with the firmware's own versions: `trussed` 0.2, `fido-authenticator` 0.3, +`usbd-ctaphid` 0.5, `ctaphid-dispatch` 0.4 and `littlefs2` 0.8, on `usb-device` 0.3.2 and +`heapless` 0.9. littlefs and `p256-cortex-m4` are C and assembly, built with the host's +clang. + +**No runtime and no interrupt (decided 2026-10-15).** +- `nrf-usbd` never enables the USBD interrupt, and enabling it means stealing the + peripheral back in `unsafe`. +- Polling from `SysTick` fails as well: `usb-device`'s types are not `Send`, so they cannot + sit in a static behind a critical section without an `unsafe impl`. + +So the device is polled in the main context, wherever the key waits: +- for the next request (the protocol's port); +- on every look at the button, which covers a tap wait of seconds; +- in milestone 3, while Trussed waits for user presence. + +The bus waits only through Argon2 and flash writes, as it does today. There is no RTIC or +Embassy, and no new `unsafe`. + +**The passkey backup is a deliberate export into the `.vkb`** (maintainer, 2026-10-15). +FIDO's rule is non-exportable credentials plus a second key. There is no second key, so +the passkeys go into the backup under its passphrase like every other item, and +`docs/threat-model.md` says what that costs. + +Milestones, one commit each, each leaving a key that works: + +1. **USB served during waits.** CDC alone, behaviour unchanged: the button check polls the + device too. Acceptance: `selftest`, and a tap wait of several seconds that no longer + stalls the bus. +2. **A composite device.** CDC plus CTAPHID (`usbd-ctaphid`) answering INIT and PING. The + board's port serves the FIDO dispatch whenever vkey's line has been quiet for 50 ms, so + a request that waits for a touch never holds up a vkey frame half read. The core is not + touched. Acceptance: `fido2-token -L` lists the key, and vkey works. + +**The core stays as it is through this phase.** A change there rebuilds the C6's image +too, and its `vaultkey.signed.bin` can only be signed again with the C6's own key, which +lives on the C6. The C6 is left alone (2026-10-14), so the hook would refuse the commit. +Everything FIDO needs lives in the nRF's board folder, or that conflict goes to the +maintainer first. +3. **Trussed and `fido-authenticator`.** littlefs on 0xD8000..0xEC000. The factory's stale + staging bytes sit at 0xE0000..0xEA000, so a mount that fails formats instead of assuming + blank flash. User presence is the amber tap, on the same button and LED as vkey. + Acceptance: registration and login on webauthn.io and with `fido2-token`, and the fit + and the stack high-water mark measured. +4. **`pam_u2f` for `sudo` and the lock screen**, and `vkey auth` removed, recorded in + `docs/` with the commit it can be restored from. +5. **The passkeys in the `.vkb`**: backup and restore carry the Trussed filesystem, sealed + under the passphrase like the items. --- @@ -610,7 +662,7 @@ Acceptance: registration and login on webauthn.io and with `fido2-token`; `pam_u | Phase 5 | ~~wiping the C6 after migration~~ - the C6 is a test board, not a fallback, and neither board holds real secrets (2026-10-14) | | Phase 5 | ~~chip key option A or B~~ - neither on this revision-2 chip: the boot-time glitch reads either (2026-10-15) | | Phase 6 | ~~passkey backup~~ - a deliberate export into the `.vkb`, outside FIDO's no-export rule (2026-10-15) | -| Phase 6 | RTIC or Embassy, and the `unsafe` rule if the runtime needs it | +| Phase 6 | ~~RTIC or Embassy~~ - neither: USB is polled wherever the key waits, so no new `unsafe` (2026-10-15) | ## Sources diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index 5a07c59..f26cfac 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -39,6 +39,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + [[package]] name = "argon2" version = "0.6.0" @@ -51,6 +60,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "1.5.1" @@ -110,6 +128,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" + [[package]] name = "blake2" version = "0.11.0" @@ -156,6 +180,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cc" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -295,6 +329,30 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "ctaphid-app" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc7bdd7194322583c6f3ec411713cb555da3ab9b97414a322639ca4adc728c7" +dependencies = [ + "heapless-bytes", + "trussed-core", +] + +[[package]] +name = "ctaphid-dispatch" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147f7046a868d513bfa57c04417a585cc9d5de126556cf6814318d5393901b87" +dependencies = [ + "ctaphid-app", + "delog", + "heapless-bytes", + "interchange", + "ref-swap", + "trussed-core", +] + [[package]] name = "ctr" version = "0.10.1" @@ -414,7 +472,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" dependencies = [ - "bitflags", + "bitflags 1.3.2", "defmt-macros", ] @@ -450,6 +508,15 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "delog" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed991f9823b19e8a0380e198dcbb6aa6ac82727b40bfecd2c6cc634f46b7e01c" +dependencies = [ + "log", +] + [[package]] name = "digest" version = "0.10.7" @@ -665,6 +732,15 @@ dependencies = [ "embedded-storage", ] +[[package]] +name = "embedded-time" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58" +dependencies = [ + "num", +] + [[package]] name = "enumset" version = "1.1.14" @@ -1035,6 +1111,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "find-msvc-tools" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" + [[package]] name = "fixed" version = "1.31.0" @@ -1097,6 +1179,19 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1128,6 +1223,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hash32" version = "0.3.1" @@ -1143,13 +1247,27 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.1", + "serde", + "spin", + "stable_deref_trait", +] + [[package]] name = "heapless" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "hash32", + "hash32 0.3.1", "stable_deref_trait", ] @@ -1159,10 +1277,20 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4" dependencies = [ - "hash32", + "hash32 0.3.1", "stable_deref_trait", ] +[[package]] +name = "heapless-bytes" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774f9dbf3f3a66edc65579e68b9f564ad5ec52e770a755af46b87d40909b8024" +dependencies = [ + "heapless 0.9.3", + "serde_core", +] + [[package]] name = "heck" version = "0.5.0" @@ -1234,6 +1362,15 @@ dependencies = [ "syn 3.0.5", ] +[[package]] +name = "interchange" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634507a34bf3bfcc64d375e947113c1fd6a1f346a04aff8a24094fcc8ff99dd8" +dependencies = [ + "loom", +] + [[package]] name = "itoa" version = "1.0.18" @@ -1276,6 +1413,12 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "lazy_static" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" + [[package]] name = "libc" version = "0.2.189" @@ -1288,12 +1431,53 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +[[package]] +name = "littlefs2-core" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c0f7acafcb6c9dfcbc3c7c54aa7b8e04367d535daeb4be0e7131f93e4587dd2" +dependencies = [ + "bitflags 2.13.2", + "serde", +] + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.8.3" @@ -1370,6 +1554,67 @@ dependencies = [ "vcell", ] +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "num" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +dependencies = [ + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1388,6 +1633,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + [[package]] name = "paste" version = "1.0.15" @@ -1427,6 +1678,23 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "postcard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a25c0b0ae06fcffe600ad392aabfa535696c8973f2253d9ac83171924c58a858" +dependencies = [ + "heapless 0.7.17", + "postcard-cobs", + "serde", +] + +[[package]] +name = "postcard-cobs" +version = "0.1.5-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c68cb38ed13fd7bc9dd5db8f165b7c8d9c1a315104083a2b10f11354c2af97f" + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -1472,6 +1740,29 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" +[[package]] +name = "ref-swap" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c30c54dffee5b40af088d5d50aa3455c91a0127164b51f0215efc4cb28fb3c" + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + [[package]] name = "rgb" version = "0.8.53" @@ -1567,6 +1858,18 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "semver" version = "0.9.0" @@ -1598,6 +1901,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-indexed" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fca2da10b1f1623f47130256065e05e94fd7a98dbd26a780a4c5de831b21e5c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "serde_core" version = "1.0.229" @@ -1664,12 +1978,33 @@ dependencies = [ "digest 0.11.3", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +[[package]] +name = "smallvec" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" + [[package]] name = "smart-leds" version = "0.4.0" @@ -1729,6 +2064,15 @@ dependencies = [ "somni-parser 0.3.1", ] +[[package]] +name = "spin" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" +dependencies = [ + "lock_api", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -1828,6 +2172,15 @@ dependencies = [ "syn 3.0.5", ] +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -1858,6 +2211,81 @@ dependencies = [ "winnow", ] +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "trussed-core" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad3077bed1856e91ddc734fbce89d7b04c736056e91446eb8716c97707ccc70" +dependencies = [ + "heapless-bytes", + "littlefs2-core", + "postcard", + "rand_core 0.6.4", + "serde", + "serde-indexed", +] + [[package]] name = "typenum" version = "1.20.1" @@ -1902,6 +2330,23 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "usbd-ctaphid" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35793a1b9c6ae908defdef01fab01a4192e5415ca0609b56c778e5751cf64adb" +dependencies = [ + "ctaphid-dispatch", + "delog", + "embedded-time", + "heapless-bytes", + "interchange", + "ref-swap", + "serde", + "trussed-core", + "usb-device", +] + [[package]] name = "usbd-serial" version = "0.2.2" @@ -1914,6 +2359,12 @@ dependencies = [ "usb-device", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "vaultkey-core" version = "0.9.0" @@ -1953,12 +2404,14 @@ dependencies = [ "cortex-m", "cortex-m-rt", "critical-section", + "ctaphid-dispatch", "embedded-hal 1.0.0", "embedded-storage", "heapless 0.8.0", "nrf52840-hal", "static_cell", "usb-device", + "usbd-ctaphid", "usbd-serial", "vaultkey-core", ] @@ -1999,6 +2452,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-link" version = "0.2.1" @@ -2014,6 +2476,63 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "winnow" version = "1.0.4" diff --git a/firmware/boards/nrf52840-mdk-dongle/Cargo.toml b/firmware/boards/nrf52840-mdk-dongle/Cargo.toml index 39de912..bc4985f 100644 --- a/firmware/boards/nrf52840-mdk-dongle/Cargo.toml +++ b/firmware/boards/nrf52840-mdk-dongle/Cargo.toml @@ -26,6 +26,9 @@ embedded-hal = "1.0" embedded-storage = "0.3" usb-device = "0.3" usbd-serial = "0.2" +# CTAPHID, the HID interface FIDO2 speaks (docs2/roadmap.md, phase 6), beside the CDC one. +usbd-ctaphid = { version = "0.5", default-features = false } +ctaphid-dispatch = { version = "0.4", default-features = false } static_cell = "2" # The INFO text, built at boot; already in the tree through usb-device. heapless = "0.8" diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin index 16303a9509a90db22abc6f30a22001aba07c2b17..68528179ac8945c78830eeb19186ef24f8ee5409 100755 GIT binary patch delta 19982 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 delta 16203 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 delta 26900 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 KMnA{>@c#g3d*%ZG diff --git a/firmware/boards/nrf52840-mdk-dongle/src/main.rs b/firmware/boards/nrf52840-mdk-dongle/src/main.rs index a690954..638effb 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/main.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/main.rs @@ -17,6 +17,7 @@ use cortex_m::peripheral::SCB; use cortex_m::peripheral::syst::SystClkSource; use cortex_m_rt::{entry, exception}; use critical_section::Mutex; +use ctaphid_dispatch::{Channel, DEFAULT_MESSAGE_SIZE as CTAP_MESSAGE, Dispatch}; use embedded_hal::digital::{InputPin, OutputPin}; use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; use nrf52840_hal::clocks::{Clocks, ExternalOscillator, Internal, LfOscStopped}; @@ -29,6 +30,7 @@ use static_cell::{ConstStaticCell, StaticCell}; use usb_device::UsbError; use usb_device::bus::UsbBusAllocator; use usb_device::device::{StringDescriptors, UsbDevice, UsbDeviceBuilder, UsbVidPid}; +use usbd_ctaphid::CtapHid; use usbd_serial::SerialPort; use vaultkey_core::device::{self, Device}; use vaultkey_core::hal::{Clock, DeviceKey, Port, Ui}; @@ -134,37 +136,82 @@ impl Clock for Uptime { } } -/// USB CDC-ACM, polled: every read and write services the bus first. Nothing runs from -/// an interrupt, so the bus waits while the key computes - Argon2, a flash write - and -/// the host's bulk transfers simply wait with it. -struct Usb { +/// The USB device with its two interfaces - CDC-ACM for vkey's protocol and CTAPHID for +/// FIDO (docs2/roadmap.md, phase 6) - polled from the main loop: nothing runs from an +/// interrupt. The bus is served wherever the key waits - for the next request (`Usb`) and +/// for the button (`Panel`), which together cover all but Argon2 and flash writes, when +/// the host's transfers simply wait. Shared by both through one `RefCell`, borrowed only +/// for a poll, a read or a write. +struct UsbStack { dev: UsbDevice<'static, Bus>, serial: SerialPort<'static, Bus>, + ctaphid: CtapHid<'static, 'static, 'static, Bus, CTAP_MESSAGE>, +} + +impl UsbStack { + fn poll(&mut self) { + self.dev.poll(&mut [&mut self.serial, &mut self.ctaphid]); + // The pipe times out a request whose packets stop arriving; it compares wrapping + // millisecond stamps, so the low half of the uptime is all it needs. + #[expect( + clippy::cast_possible_truncation, + reason = "a wrapping stamp, on purpose" + )] + self.ctaphid.check_timeout(Uptime.now_ms() as u32); + } +} + +static USB_STACK: StaticCell> = StaticCell::new(); + +/// CTAPHID requests on their way to the FIDO side, and its answers back: one message each +/// way, up to the 7609 bytes CTAPHID can carry. +static CTAP_CHANNEL: Channel = Channel::new(); + +/// The protocol's side of the stack, and FIDO's: requests that come through CTAPHID are +/// answered while vkey's line is quiet. +struct Usb { + stack: &'static RefCell, + fido: Dispatch<'static, 'static, CTAP_MESSAGE>, + /// When vkey's last byte arrived. + last_rx: u64, } impl Usb { /// How long a write may make no progress before the host counts as gone. const STALL_MS: u64 = 1000; - - fn poll(&mut self) { - self.dev.poll(&mut [&mut self.serial]); - } + /// How long vkey's line must be silent before FIDO is served. A frame's bytes come + /// in back to back, so this never lands in the middle of one, and a CTAP request + /// that waits for a touch never holds up a frame half read. + const QUIET_MS: u64 = 50; } impl Port for Usb { fn read_byte(&mut self) -> Option { - self.poll(); - let mut byte = [0u8]; - matches!(self.serial.read(&mut byte), Ok(1)).then_some(byte[0]) + let byte = { + let mut usb = self.stack.borrow_mut(); + usb.poll(); + let mut byte = [0u8]; + matches!(usb.serial.read(&mut byte), Ok(1)).then_some(byte[0]) + }; + let now = Uptime.now_ms(); + if byte.is_some() { + self.last_rx = now; + } else if now - self.last_rx > Self::QUIET_MS { + // No FIDO application yet: the pipe answers INIT and PING itself, and + // anything that reaches the dispatch is refused as an unknown command. + self.fido.poll(&mut []); + } + byte } // A host that stopped reading has nobody to tell: what it does not take is dropped. fn write(&mut self, data: &[u8]) { + let mut usb = self.stack.borrow_mut(); let mut rest = data; let mut since = Uptime.now_ms(); while !rest.is_empty() { - self.poll(); - match self.serial.write(rest) { + usb.poll(); + match usb.serial.write(rest) { Ok(n) if n > 0 => { rest = &rest[n..]; since = Uptime.now_ms(); @@ -180,10 +227,11 @@ impl Port for Usb { } fn flush(&mut self) { + let mut usb = self.stack.borrow_mut(); let since = Uptime.now_ms(); loop { - self.poll(); - match self.serial.flush() { + usb.poll(); + match usb.serial.flush() { Err(UsbError::WouldBlock) if Uptime.now_ms() - since <= Self::STALL_MS => {} _ => return, } @@ -275,6 +323,9 @@ impl DeviceKey for NoChipKey { struct Panel { // embedded-hal reads a pin through `&mut`, and `Ui::pressed` takes `&self`. button: RefCell>>, + /// Served on every look at the button: a tap wait lasts seconds, and a host whose + /// requests go unanswered that long resets the device. + usb: &'static RefCell, red: Pin>, green: Pin>, blue: Pin>, @@ -298,6 +349,11 @@ impl Ui for Panel { } fn pressed(&self) -> bool { + // The protocol never holds the stack while the key waits for the button; if it + // ever did, this poll is skipped rather than borrowed twice. + if let Ok(mut usb) = self.usb.try_borrow_mut() { + usb.poll(); + } let Ok(low) = self.button.borrow_mut().is_low(); low } @@ -411,22 +467,18 @@ fn main() -> ! { cp.SYST.enable_counter(); cp.SYST.enable_interrupt(); - let port0 = p0::Parts::new(p.P0); - let mut panel = Panel { - button: RefCell::new(port0.p0_18.into_pullup_input().degrade()), - red: port0.p0_23.into_push_pull_output(Level::High).degrade(), - green: port0.p0_22.into_push_pull_output(Level::High).degrade(), - blue: port0.p0_24.into_push_pull_output(Level::High).degrade(), - }; - panel.set(State::Idle); - // USB runs from the crystal, not the internal oscillator. The classes take their // endpoints before the device is built. let clocks = CLOCKS.init(Clocks::new(p.CLOCK).enable_ext_hfosc()); let bus = USB_BUS.init(UsbBusAllocator::new(Usbd::new(UsbPeripheral::new( p.USBD, clocks, )))); + // The serial class first, so it keeps interface 0 and the port its by-id name. let serial = SerialPort::new(bus); + let (requester, responder) = CTAP_CHANNEL + .split() + .expect("the CTAPHID channel is split once, here"); + let ctaphid = CtapHid::new(bus, requester, 0); let usb = UsbDeviceBuilder::new(bus, UsbVidPid(USB_VID, USB_PID)) .strings(&[StringDescriptors::default() .manufacturer("vaulttecdev") @@ -434,8 +486,25 @@ fn main() -> ! { .expect("one language") .max_packet_size_0(64) .expect("64 bytes is a valid control packet size") - .device_class(usbd_serial::USB_CLASS_CDC) + // Two functions on one device: the CDC class announces itself with an interface + // association, which the device class has to say is there. + .composite_with_iads() .build(); + let usb: &'static RefCell = USB_STACK.init(RefCell::new(UsbStack { + dev: usb, + serial, + ctaphid, + })); + + let port0 = p0::Parts::new(p.P0); + let mut panel = Panel { + button: RefCell::new(port0.p0_18.into_pullup_input().degrade()), + usb, + red: port0.p0_23.into_push_pull_output(Level::High).degrade(), + green: port0.p0_22.into_push_pull_output(Level::High).degrade(), + blue: port0.p0_24.into_push_pull_output(Level::High).degrade(), + }; + panel.set(State::Idle); let store = Store::new(Flash(Nvmc::new(p.NVMC, vault_region())), LAYOUT); let mut dev = Device::new( @@ -450,6 +519,11 @@ fn main() -> ! { BUF.take(), ); - let mut proto = Proto::new(Usb { dev: usb, serial }, Uptime, info.as_str()); + let port = Usb { + stack: usb, + fido: Dispatch::new(responder), + last_rx: 0, + }; + let mut proto = Proto::new(port, Uptime, info.as_str()); proto.run(&mut dev) } From 4bd49f38e68a28264e3cac809898b71d7c4aa746 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 15:10:07 +0300 Subject: [PATCH 16/33] Add passkeys to the nRF52840: Trussed and fido-authenticator Milestone 3 of phase 6. fido-authenticator speaks CTAP2 over the CTAPHID interface, Trussed runs inline in the main loop and keeps its keys in a littlefs at 0xD8000..0xEC000. User presence is the vault's tap; authenticatorReset takes the wipe's 5 s hold. U2F is not served. Passkeys need more stack than the board had left beside Argon2's static 128 KiB, so the core now takes that memory on the stack for one derivation, and the nRF puts a 200 KiB stack at the bottom of RAM, where an overflow resets instead of corrupting the statics. The C6's image changed with the core; its stale signed copy leaves the repository and vkey setup refuses a Secure Boot chip without one. Accepted on the board: webauthn.io registration and login, fido2-token, ctap2.py with signatures checked, check --wipe-everything with a restore and a 1Password sync. --- CLAUDE.md | 33 +- cli/src/check.rs | 5 +- cli/src/setup.rs | 22 +- docs/hardware.md | 6 +- docs/threat-model.md | 34 +- docs2/makerdiary.md | 45 +- docs2/roadmap.md | 59 +- firmware/Cargo.lock | 757 +++++++++++++++++- firmware/boards/esp32c6-zero/board.toml | 13 +- .../boards/esp32c6-zero/images/vaultkey.bin | Bin 263936 -> 264128 bytes .../esp32c6-zero/images/vaultkey.signed.bin | Bin 270336 -> 0 bytes firmware/boards/esp32c6-zero/src/main.rs | 11 +- .../nrf52840-mdk-dongle/.cargo/config.toml | 6 + .../boards/nrf52840-mdk-dongle/Cargo.toml | 30 +- .../nrf52840-mdk-dongle/c-headers/inttypes.h | 8 + .../nrf52840-mdk-dongle/c-headers/string.h | 20 + .../nrf52840-mdk-dongle/images/vaultkey.bin | Bin 81068 -> 267748 bytes .../images/vaultkey.signed.uf2 | Bin 162816 -> 536064 bytes firmware/boards/nrf52840-mdk-dongle/memory.x | 24 +- .../boards/nrf52840-mdk-dongle/src/fido.rs | 393 +++++++++ .../boards/nrf52840-mdk-dongle/src/main.rs | 237 +++++- firmware/core/src/device.rs | 34 +- firmware/core/src/vault.rs | 5 +- firmware/core/tests/key.rs | 5 +- 24 files changed, 1620 insertions(+), 127 deletions(-) delete mode 100644 firmware/boards/esp32c6-zero/images/vaultkey.signed.bin create mode 100644 firmware/boards/nrf52840-mdk-dongle/c-headers/inttypes.h create mode 100644 firmware/boards/nrf52840-mdk-dongle/c-headers/string.h create mode 100644 firmware/boards/nrf52840-mdk-dongle/src/fido.rs diff --git a/CLAUDE.md b/CLAUDE.md index 5a71816..24b5081 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -120,8 +120,9 @@ This is a security device. The rules below are not recommendations. yields free attempts. In flash this is one word write without an erase. - **A claim in the protocol must hold in the code.** Advertising a guarantee only half the paths enforce is worse than not advertising it. -- **Irreversible actions get their own gesture.** Code, password and a `vkey auth` login — a tap (amber); wipe — - hold 5 s (red); backup — double tap (blue). A tap never wipes and never exports; a hold +- **Irreversible actions get their own gesture.** Code, password, a `vkey auth` login and + a passkey on the nRF52840 — a tap (amber); wipe, and erasing every passkey + (authenticatorReset) — hold 5 s (red); backup — double tap (blue). A tap never wipes and never exports; a hold never exports; a double tap never wipes. Password on a tap is the maintainer's decision of 2026-09-08 — do not reintroduce a separate hold. A new command with consequences gets a new gesture, not an existing one. @@ -149,15 +150,19 @@ folder's business. The boards: -- **`nrf52840-mdk-dongle`**, the primary. USB CDC-ACM from the firmware (`1209:0001`), - polled; our UF2 bootloader fork (installed 2026-10-14, below) is how it is flashed: hold +- **`nrf52840-mdk-dongle`**, the primary. USB from the firmware (`1209:0001`), polled: + CDC-ACM for vkey and CTAPHID for passkeys (Trussed + `fido-authenticator` in + `src/fido.rs`, their littlefs at 0xD8000..0xEC000). The stack sits at the bottom of RAM, + 200 KiB, so an overflow resets the chip ("lockup" in `vkey info`). Our UF2 bootloader fork (installed 2026-10-14, below) is how it is flashed: hold the button while plugging in, copy `images/vaultkey.signed.uf2` to `UF2BOOT`, replug. It runs only images signed with the key in `bootloader/signing-key.pem`; the app ends by its signature slot at 0x96000. No chip key, so it holds no real secrets yet. `vkey info` prints the chip's build code, UICR `APPROTECT` and last reset cause. Notes, measurements and factory state: `docs2/makerdiary.md`; the plan: `docs2/roadmap.md`. - **`esp32c6-zero`**, the test board (2026-10-14): nothing is built for it, and it takes - `check --wipe-everything` for core changes. Secure Boot v2 is burned, so before its + `check --wipe-everything` for core changes. Its signed app image left the repository on + 2026-10-15, when the core changed while the C6 was left alone; `vkey setup` refuses a + Secure Boot chip until `tools/sign-vaultkey.sh` runs on it again. Secure Boot v2 is burned, so before its first wipe a `.vkb` holding `vkey-signing` (its Secure Boot key) must exist: losing that key ends its updates for good. USB is a fixed Serial/JTAG (`303a:1001`), HID is impossible, so passkey will never exist here; one port carries both the protocol and logs — hence the `VTC2` magic word in @@ -168,9 +173,12 @@ The boards: - Core crates: RustCrypto `aes-gcm`, `argon2`, `hmac`, `sha1`, `sha2`, `subtle`, `zeroize`; `ed25519-dalek` (built on RustCrypto's `signature` and `sha2`) for `vkey auth`; `crc`. Not own crypto. Toolchain: stable rustup, no compiler fork. - - nRF52840: `nrf52840-hal`, `cortex-m`, `cortex-m-rt` (`set-vtor`), `usb-device`, - `usbd-serial`, `static_cell`, `heapless`; target `thumbv7em-none-eabihf`. No radio - driver (`radio_base` below). + - nRF52840: `nrf52840-hal`, `cortex-m`, `cortex-m-rt` (`set-vtor`, `paint-stack`), + `usb-device`, `usbd-serial`, `usbd-ctaphid`, `ctaphid-dispatch`, `static_cell`, + `heapless`; for passkeys `trussed`, `trussed-staging`, `fido-authenticator`, + `littlefs2`; target `thumbv7em-none-eabihf`. littlefs and `p256-cortex-m4` are C, + built by the host's clang with the headers in `c-headers/`. No radio driver + (`radio_base` below). - C6: `esp-hal` (features `esp32c6`, `rt`, `unstable`), `esp-storage`, `esp-hal-smartled`, `esp-println` (`jtag-serial`), `esp-backtrace`; target `riscv32imac-unknown-none-elf`; no espup. Not `esp-idf-hal`, not `esp-radio`. @@ -187,6 +195,9 @@ The boards: the real firmware with the counter erased was costed: a fortnight for six digits, four years for eight). A backup passphrase is 12–128 bytes, and the CLI asks for five or six random words, because 128 KiB of Argon2id does not make up for a phrase a person invented. + Argon2's 128 KiB is taken on the stack for one derivation (`device::with_kdf_memory`, + never inlined), not held in a static (2026-10-15): passkeys on the nRF52840 need the + same RAM between derivations. - **A field's class decides what may leave the device**, not the item's category (2026-09-19, maintainer's decision; `docs/items-v2.md`). An item is a name, a category and up to 32 fields; a field is `class | kind | section | label | value`, the value up @@ -355,9 +366,9 @@ when the reason disappears, the compiler says the `expect` is no longer needed. One exception, the maintainer's decision of 2026-10-04: `nrf52840-mdk-dongle` carries its own copy of the table with `unsafe_code = "deny"`, because its flash driver takes the -vault region as a `&'static mut [u8]` and memory-mapped flash cannot be named in safe code. -The one `unsafe` is `vault_region` in its `main.rs`, under `#[expect]` and a `SAFETY` -comment. `tools/checks.sh` fails if that copy differs from the workspace's in anything +data region (the vault and Trussed's filesystem) as a `&'static mut [u8]` and +memory-mapped flash cannot be named in safe code. The one `unsafe` is `data_region` in its +`main.rs`, under `#[expect]` and a `SAFETY` comment. `tools/checks.sh` fails if that copy differs from the workspace's in anything else. Invalid state does not exist as a value: `Pin`, `Name`, `Params`, `Entry`, `Record` are diff --git a/cli/src/check.rs b/cli/src/check.rs index 9e772eb..e5d8a85 100644 --- a/cli/src/check.rs +++ b/cli/src/check.rs @@ -360,7 +360,10 @@ fn backup( ) -> Result<(), Error> { const PASS: &str = "correct horse battery staple"; let dir = std::env::temp_dir().join(format!("vkey-check-{}.vkb", std::process::id())); - println!(" >>> tap {} ONCE when the light turns blue", rep.button); + println!( + " >>> blue asks for two taps, but this step proves one is refused: tap {} only ONCE", + rep.button + ); rep.expect( "backup refused for one tap", &backup::export(d, &dir, passphrase(PASS)?), diff --git a/cli/src/setup.rs b/cli/src/setup.rs index 0f44deb..caf5de2 100644 --- a/cli/src/setup.rs +++ b/cli/src/setup.rs @@ -137,19 +137,33 @@ fn flash( .flags & SECURE_BOOT_EN != 0; + let state = if secure { "on" } else { "off" }; log(&format!( - " chip {chip}, board {}, secure boot {}", - board.name, - if secure { "on" } else { "off" } + " chip {chip}, board {}, secure boot {state}", + board.name )); + let images: Vec<&'static Image> = board.images_for(secure).collect(); + // Every place the board writes gets an image on this chip too, checked before + // anything is erased: a signed image the folder does not have yet would leave a + // Secure Boot chip with a bootloader and nothing to boot. + if let Some(gap) = board + .images + .iter() + .find(|i| !images.iter().any(|j| j.addr == i.addr)) + { + return Err(Error::Value(format!( + "{}: no image at {:#x} for a chip with secure boot {state} - sign one first: tools/sign-vaultkey.sh", + board.name, gap.addr + ))); + } + if erase { log(" erasing the whole flash - every secret and the PIN are gone"); flasher .erase_flash() .map_err(|e| Error::Value(format!("erase failed: {e}")))?; } - let images: Vec<&'static Image> = board.images_for(secure).collect(); let chip_id = flasher.chip(); let mut progress = Progress { log, diff --git a/docs/hardware.md b/docs/hardware.md index e7c0b19..541d20d 100644 --- a/docs/hardware.md +++ b/docs/hardware.md @@ -212,7 +212,11 @@ Signing costs a PIN and a tap (`tools/sign-vaultkey.sh`), which writes board that trusts it; leaking it removes Secure Boot. Public half and digest: `firmware/secure-boot/public.pem` and `digest.bin`, in the repository. `images/vaultkey.bin` stays unsigned and reproducible (a hook rebuilds and compares), with `vaultkey.signed.bin` -beside it, verified by the hook with the public key. +beside it, verified by the hook with the public key. Since 2026-10-15 it is not: the core +changed for the nRF52840's passkeys while this board was left alone, so the stale signed +app left the repository and its `board.toml` entry was commented out. `vkey setup` +refuses a Secure Boot chip until `tools/sign-vaultkey.sh` runs with this board plugged in +and the entry is restored. **A fork enables Secure Boot with its own key, never this one.** The private half exists only on the maintainer's device, so the committed `public.pem`, `digest.bin` and diff --git a/docs/threat-model.md b/docs/threat-model.md index 387a4e4..ab1d0c1 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -6,7 +6,7 @@ > on guarantees the device does not give. Last reviewed 2026-09-12; the nRF52840 board section added 2026-10-13, its signing key -and bootloader fork 2026-10-14. Revisited on every +and bootloader fork 2026-10-14, its passkeys 2026-10-15. Revisited on every hardware or firmware change. Reporting policy: [`SECURITY.md`](../SECURITY.md). Board details: [`docs/hardware.md`](hardware.md). @@ -60,6 +60,31 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure owner still holds the key. - **A backup made on this board uses its own cost** (20 passes). It is still guarded by the passphrase's entropy, at less than half the C6's work per guess. +- **Passkeys (FIDO2) live outside the vault** (since 2026-10-15, roadmap phase 6). + Trussed and fido-authenticator keep them in a littlefs of their own at + 0xD8000..0xEC000: + - **They are not sealed under the PIN.** Trussed writes its keys as they are: the + passkeys' private keys, and the key that wraps the credential IDs of the + non-resident ones (`pam_u2f`'s among them). The glitch above reads them straight + off the flash. No PIN search is needed, so a passkey falls in the minutes the glitch + takes, where the vault takes hours more. + - **A tap is enough, locked or not.** Registration and login take the vault's tap + (amber, a fresh press after the request), never the vkey PIN. A FIDO PIN, if one is + set through a browser or `fido2-token`, belongs to fido-authenticator. It gates what a + site asks it to gate and encrypts nothing. + - **Nothing leaves over USB.** No CTAP command returns a private key. U2F (CTAP1) is + not served at all: its presence check polls every 250 ms, and a tap that must start + after the request cannot answer that. + - **Erasing them takes the wipe's gesture.** authenticatorReset erases every passkey, + so it needs the 5 s hold (red), not a tap, and fido-authenticator accepts it only in + the first 10 s after the key is plugged in. The vault's own wipe, + `check --wipe-everything` included, does not touch them: they sit in another region. + - **Origin binding.** The browser binds a passkey to its site's origin, so a look-alike + site gets nothing it can use: the property WebAuthn has and TOTP lacks. TOTP codes and + passwords from the vault stay as phishable as anywhere. + - **No backup yet.** Milestone 5 puts the passkeys into the `.vkb`, a deliberate break + from FIDO's rule that they never leave. Until then, losing the key loses them, so + every site keeps a second way in. **Accepted, not fixed** (maintainer's decision, 2026-10-13): this revision-2 chip will hold everything once the steps below are done. The glitch above stays open after them. Someone @@ -121,7 +146,7 @@ An unlock is checked against the verifier; nothing derived from the PIN is store | Choice | Reason | |---|---| -| Argon2id, 128 KiB, no allocator | Memory hardness costs an attacker more than PBKDF2 does — but 128 KiB is what the board can spare beside an 80 KiB vault and a 300 KiB stack, and it fits in the cache of any desktop core, so it buys time, not the memory bandwidth Argon2 is meant to charge for. Against the PIN that changes nothing (the counter and the eFuse key do the work); against a stolen `.vkb` it is the whole defence, hence the passphrase rule below | +| Argon2id, 128 KiB, no allocator | Memory hardness costs an attacker more than PBKDF2 does — but 128 KiB is what the board can spare beside an 80 KiB vault and a 300 KiB stack (since 2026-10-15 it is taken on the stack for each derivation and scrubbed after it; the nRF52840 paints its stack at boot, so a reset mid-derivation leaves nothing behind), and it fits in the cache of any desktop core, so it buys time, not the memory bandwidth Argon2 is meant to charge for. Against the PIN that changes nothing (the counter and the eFuse key do the work); against a stolen `.vkb` it is the whole defence, hence the passphrase rule below | | Cost `t` in the vault header, bounded above | A forged header cannot park the key for hours | | Not `scrypt`, not `balloon-hash` | `scrypt` needs `alloc`; `balloon-hash` doubles the crypto crates | | PIN exactly 8 digits (0.9; was 6–8) | The counter can be erased through download mode, so the real cost of a guess is one firmware unlock, ~1.3 s. That is a fortnight for six digits, five months for seven and four years for eight — the only lever is length, because a slower KDF makes every honest unlock slower too. A PIN of the wrong length is refused before the wire and costs no attempt | @@ -291,7 +316,7 @@ of it); a PAM `cdylib` (`pam_exec` needs no C and no `unsafe`). | Threat | Why not | |---|---| -| Phishing | A TOTP code typed into a fake site works on the real one. That is a property of TOTP, not of the device; only WebAuthn/passkey stops phishing, and it is **not** here and never will be on this board | +| Phishing | A TOTP code typed into a fake site works on the real one. That is a property of TOTP, not of the device; only WebAuthn/passkey stops phishing, and the C6 never will have it (no USB HID). The nRF52840 board has passkeys since 2026-10-15 (its section above) | | The code, password or `.env` you just received | It passes through USB, the terminal and optionally the clipboard; host malware sees it at that moment, and it outlives the moment in the terminal's scrollback and in a clipboard manager's history (below) | | A host fully compromised at the moment of use | It waits for your press and takes the result; with no display the device cannot show what you are confirming | | A breach at the service | TOTP is a shared secret: the service stores it too | @@ -464,7 +489,8 @@ Suits: a second factor for personal accounts when you do not want secrets on a p in a cloud backup — **this is the main scenario**; and anyone who wants open hardware and control over the firmware. -Does not suit: anyone expecting phishing protection (**get a passkey/WebAuthn key**); +Does not suit: anyone expecting phishing protection from the C6 (**a passkey/WebAuthn +key**, which the nRF52840 board now is, with the limits in its section); anyone expecting resistance to physical seizure of the key (**a certified key with an SE**); use as a sole factor or without the services' own recovery codes — the wipe after 8 wrong PINs is final, and a backup exists only if one was made and the passphrase not diff --git a/docs2/makerdiary.md b/docs2/makerdiary.md index bdca64b..5954214 100644 --- a/docs2/makerdiary.md +++ b/docs2/makerdiary.md @@ -106,10 +106,11 @@ filesystem and claims up to 100 passkeys; the FIDO-only Nitrokey Passkey firmwar reference). The CLI speaks Nordic DFU to it. `NRF_DFU_APP_DATA_AREA_SIZE` must cover the vault and littlefs, 0x97000..0xEC000 (340 KiB): otherwise an update erases the secrets. Open: where the DFU signing key (ECDSA P-256) lives. -- **RAM: decided after the stack is measured on the board.** `MAX_ENTRIES` stays 256 - (100–200 entries expected). If RAM is short, the candidates are the item size (8 → 4 KiB - frees ≈12 KiB) and, last, Argon2 memory (128 → 64 KiB frees 64 KiB but halves the cost of - each PIN guess after a flash dump, and C6 backups open only if both boards change). +- **RAM: decided 2026-10-15, once passkeys ran out of it.** `MAX_ENTRIES` stays 256 and + Argon2 keeps 128 KiB, since every `.vkb` made so far needs it to open. What changed is + where the 128 KiB lives: on the stack, for one derivation at a time + (`device::with_kdf_memory`), not in a static. Argon2 and a passkey request never run at + once, so they take turns in the same RAM. "Passkeys on the board" below has the numbers. ### Fit check, measured 2026-10-03 @@ -268,15 +269,16 @@ vkey alone, no Trussed yet: the same core as the C6, behind the four HAL traits. | Port | USB CDC-ACM through `usb-device` + `usbd-serial`, polled from the main loop; VID/PID `1209:0001`, pid.codes' test pair | | Clock | SysTick exception, 1 ms. Not a counter read on demand: the auto-lock compares times only when the next request comes, so a counter that wraps between requests would keep an idle key unlocked | | Ui | button P0.18, LEDs P0.23/P0.22/P0.24, all active low, from the wiki; amber = red + green | -| Flash | `Nvmc` over 0x97000..0xD8000 behind a wrapper that fences after every erase and write | +| Flash | `Nvmc` over 0x97000..0xEC000 behind a wrapper that fences after every erase and write, split into the vault's region and Trussed's (`Region`), each refusing access past its end | | Entropy | the RNG peripheral, bias correction on | | DeviceKey | none: `bound() == false`, PIN only, `vkey auth` refused | Measured on the build: 72 KiB of code, 154 KiB of statics, ≈101 KiB left for the stack. Rules changed for it (maintainer's decision 2026-10-04): the board has its own lint table -with `unsafe_code = "deny"` for the one `unsafe` in `vault_region`; `tools/checks.sh` -keeps the rest identical. Core changes that came with it: the image copy's size moved from +with `unsafe_code = "deny"` for the one `unsafe` in `vault_region` (`data_region` since +2026-10-15, when Trussed's region joined the vault's); `tools/checks.sh` keeps the rest +identical. Core changes that came with it: the image copy's size moved from the `STATE_SECTORS` constant into `Layout::state_sectors` (C6 keeps 53), and the test flash refuses a third write to a word between erases, the nRF52840's limit. @@ -296,6 +298,35 @@ Known gaps, by design until the board is in hand: flash controller and 4 to the RNG. It catches direct addressing only, not a base plus offset from a neighbouring peripheral. +### Passkeys on the board (2026-10-15) + +Trussed 0.2 and `fido-authenticator` 0.3 run in `src/fido.rs`, served from the protocol +port's idle reads like the rest of USB (roadmap, phase 6): + +| What | Measured | +|---|---| +| Image | 267 748 B, 261 KiB of it code | +| Statics | 46 KiB: the vault's index and buffer, USB with 3 KiB CTAP buffers, Trussed's channel, 4 KiB of RAM filesystem | +| Stack | 200 KiB, at the bottom of RAM so an overflow locks the core up and resets the chip instead of running into the statics | +| Deepest key derivation | ≈166 KiB, 128 KiB of it Argon2's memory | +| Deepest passkey request | ≤ ≈154 KiB, from the image's call graph (frame sizes summed along the deepest direct calls, so an upper bound) | + +How it got there: +- The first build kept Argon2's 128 KiB in a static, which left 64 KiB of stack. A CBOR + getInfo locked the core up: the stack ran off the bottom of RAM, where the layout above + turned it into a reset. Trussed's request loop alone has 10-25 KiB frames. +- Nothing smaller fits in the board folder: Argon2 cannot shrink, because every `.vkb` + needs 128 KiB to open. So the core takes that memory on the stack for one derivation, + and passkeys use the same RAM between derivations (maintainer's decision, 2026-10-15). +- `opt-level = "z"` barely moved the frames and slows Argon2, so the profile stays `s`. + What did help: `fido::start` is never inlined, so boot-time temporaries leave `main`'s + frame (27 → 9 KiB), and CTAP messages are capped at 3072 bytes, not 7609. +- The C parts (littlefs, p256-cortex-m4) are built by the host's clang (18 here), with + the two C library headers they include in `c-headers/`. `C_INCLUDE_PATH` in + `.cargo/config.toml` also reaches the host C a build script compiles, such as + littlefs's bindgen run. The image is then only the same bytes on machines with the + same clang. + ## Factory state (board arrived 2026-10-13) Seen on the bus: `1915:c00a` "nRF52 Connectivity" (Nordic's connectivity firmware for diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 24b7121..aabebeb 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -588,7 +588,7 @@ nRF; `check --wipe-everything` green on the C6. wait". - ~~**Runtime: RTIC (Nitrokey's choice) or Embassy.**~~ Neither: see "No runtime" below. - **Trussed + `fido-authenticator`**, with littlefs at 0xD8000..0xEC000 and P-256 from - `p256-cortex-m4`. Re-measure the fit and the stack high-water mark. + `p256-cortex-m4`. Done 2026-10-15 (milestone 3). - **Then Linux login moves to `pam_u2f`**, and the old `vkey auth` is removed, recorded in `docs/` with the commit it can be restored from. - **This is done on the daily key** (no spare). Every update starts with a `.vkb` backup. @@ -628,24 +628,58 @@ Milestones, one commit each, each leaving a key that works: 1. **USB served during waits.** CDC alone, behaviour unchanged: the button check polls the device too. Acceptance: `selftest`, and a tap wait of several seconds that no longer - stalls the bus. + stalls the bus. **Accepted 2026-10-15** (`b446afd`): `selftest` green with a wait of + several seconds before the tap. 2. **A composite device.** CDC plus CTAPHID (`usbd-ctaphid`) answering INIT and PING. The board's port serves the FIDO dispatch whenever vkey's line has been quiet for 50 ms, so - a request that waits for a touch never holds up a vkey frame half read. The core is not - touched. Acceptance: `fido2-token -L` lists the key, and vkey works. - -**The core stays as it is through this phase.** A change there rebuilds the C6's image -too, and its `vaultkey.signed.bin` can only be signed again with the C6's own key, which -lives on the C6. The C6 is left alone (2026-10-14), so the hook would refuse the commit. -Everything FIDO needs lives in the nRF's board folder, or that conflict goes to the -maintainer first. + a request that waits for a touch never holds up a vkey frame half read. Acceptance: + `fido2-token -L` lists the key, and vkey works. **Accepted 2026-10-15**: INIT and PING + answered by `b446afd`. A CBOR request got no answer until the pipe's finished answers + were picked up on every poll, not only on bus events. That fix ships with milestone 3. 3. **Trussed and `fido-authenticator`.** littlefs on 0xD8000..0xEC000. The factory's stale staging bytes sit at 0xE0000..0xEA000, so a mount that fails formats instead of assuming blank flash. User presence is the amber tap, on the same button and LED as vkey. Acceptance: registration and login on webauthn.io and with `fido2-token`, and the fit - and the stack high-water mark measured. + and the stack measured. **Accepted 2026-10-15**: + - registration and login passed on webauthn.io in Chrome, with a discoverable + credential and a FIDO PIN Chrome had set; + - `fido2-token -L` and `-I` read the key; + - makeCredential and getAssertion, resident and not, passed through + `ctap2.py` with the signature checked against the credential's public key; + - keepalives say "touch needed" every 100 ms while the key waits; + - authenticatorReset was refused while only tapped and erased after the 5 s hold; + - `vkey check --wipe-everything` passed, then the restore from the `.vkb`, the + 1Password sync and `selftest`. Its one FAIL, "backup refused for one tap", was the + maintainer tapping twice: the device rightly took the second tap. The prompt now + says why a blue light asks for one tap there. + + What changed on the way, and what it leaves: + - **The core changed after all.** With Argon2's 128 KiB in a static, passkeys had 64 KiB + of stack and needed more than twice that; the first getInfo locked the core up. The + core now takes the 128 KiB on the stack for one derivation (`with_kdf_memory`), and + the stack is 200 KiB at the bottom of RAM, where an overflow resets the chip instead + of corrupting the statics (`docs2/makerdiary.md`, "Passkeys on the board"). The + C6's image changed with it. Its signed copy can only be made on the C6, which is + left alone, so it left the repository, and `vkey setup` refuses a Secure Boot chip + until it is signed again (maintainer's decision, 2026-10-15). + - **The stack is bounded, not measured.** Its high-water mark cannot be read without a + second `unsafe` or a probe. The bound comes from the image's call graph, and a lockup + in `vkey info`'s reset cause would show an overflow. + - **CTAP2 only.** U2F's MSG is refused. getInfo still lists `U2F_V2`, as + fido-authenticator always does. The AAGUID is its placeholder `AAGUID0123456789`, + since no attestation certificate is loaded. + - **CTAPHID_CANCEL is not honoured during the 30 s touch wait.** A browser that cancels + and asks again gets CHANNEL_BUSY until the wait ends: the first webauthn.io login + failed that way, the second passed. Ending the wait early from the board would mean + moving the core's clock, and a cancel during a reset's hold would then complete it, + so the fix is a cancel hook in the core's `ui` with host tests (milestone 4). 4. **`pam_u2f` for `sudo` and the lock screen**, and `vkey auth` removed, recorded in - `docs/` with the commit it can be restored from. + `docs/` with the commit it can be restored from. Two core fixes ride along, because + this milestone changes the core anyway: + - the cancel hook above; + - `ui::await_release`, which takes one "not pressed" sample for a release. A bounce in + the middle of a press could then count as two taps, and two taps at blue let a + backup out. It gets the same debounce `released` already has. 5. **The passkeys in the `.vkb`**: backup and restore carry the Trussed filesystem, sealed under the passphrase like the items. @@ -663,6 +697,7 @@ maintainer first. | Phase 5 | ~~chip key option A or B~~ - neither on this revision-2 chip: the boot-time glitch reads either (2026-10-15) | | Phase 6 | ~~passkey backup~~ - a deliberate export into the `.vkb`, outside FIDO's no-export rule (2026-10-15) | | Phase 6 | ~~RTIC or Embassy~~ - neither: USB is polled wherever the key waits, so no new `unsafe` (2026-10-15) | +| Phase 6 | ~~RAM for passkeys~~ - Argon2's memory moves to the stack in the core; the C6's stale signed image leaves the repository (2026-10-15) | ## Sources diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index f26cfac..06bae75 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -2,6 +2,16 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common 0.1.7", + "generic-array", +] + [[package]] name = "aead" version = "0.6.1" @@ -9,7 +19,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99" dependencies = [ "crypto-common 0.2.2", - "inout", + "inout 0.2.2", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher 0.4.4", + "cpufeatures 0.2.17", ] [[package]] @@ -18,7 +39,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" dependencies = [ - "cipher", + "cipher 0.5.2", "cpubits", "cpufeatures 0.3.1", "zeroize", @@ -30,9 +51,9 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f2b8006a0c83f52b62ba44a97b58bf76fe2f70a329e588f67f89691d93d498f" dependencies = [ - "aead", - "aes", - "cipher", + "aead 0.6.1", + "aes 0.9.3", + "cipher 0.5.2", "ctr", "ctutils", "ghash", @@ -48,6 +69,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "apdu-app" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe0bbbf8e3c1034ec9b1d1f9f50ab634e65a8249972f2a34ada1cf115efb0a9" +dependencies = [ + "heapless 0.9.3", + "iso7816", +] + [[package]] name = "argon2" version = "0.6.0" @@ -96,6 +127,24 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags 2.13.2", + "cexpr", + "clang-sys", + "itertools", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex 1.3.0", + "syn 2.0.119", +] + [[package]] name = "bitfield" version = "0.13.2" @@ -143,6 +192,15 @@ dependencies = [ "digest 0.11.3", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -162,6 +220,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + [[package]] name = "bytemuck" version = "1.25.2" @@ -180,6 +247,27 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher 0.4.4", +] + +[[package]] +name = "cbor-smol" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6dd31f7069836e87169bc5910212571b873cebe389c7c7f2d8b1fb3e55c80d" +dependencies = [ + "delog", + "heapless 0.9.3", + "heapless-bytes", + "serde_core", +] + [[package]] name = "cc" version = "1.8.0" @@ -187,7 +275,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838" dependencies = [ "find-msvc-tools", - "shlex", + "shlex 2.0.1", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", ] [[package]] @@ -196,6 +293,41 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher 0.4.4", + "cpufeatures 0.2.17", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead 0.5.2", + "chacha20", + "cipher 0.4.4", + "poly1305", + "zeroize", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common 0.1.7", + "inout 0.1.4", + "zeroize", +] + [[package]] name = "cipher" version = "0.5.2" @@ -204,7 +336,18 @@ checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" dependencies = [ "block-buffer 0.12.1", "crypto-common 0.2.2", - "inout", + "inout 0.2.2", +] + +[[package]] +name = "clang-sys" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" +dependencies = [ + "glob", + "libc", + "libloading", ] [[package]] @@ -259,6 +402,17 @@ dependencies = [ "syn 3.0.5", ] +[[package]] +name = "cosey" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "540d9a2a9f2d35a876fedb35f4c0b51c7a69f71f042252cf34fc159708f962d4" +dependencies = [ + "heapless-bytes", + "serde", + "serde_repr", +] + [[package]] name = "cpubits" version = "0.1.1" @@ -310,6 +464,18 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-bigint" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8658c15c5d921ddf980f7fe25b1e82f4b7a4083b2c4985fea4922edb8e43e07d" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -329,6 +495,35 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "crypto-mac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctap-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab74c7ac39f3bde2a13960ab8257975a35cfcc3d45420ca59b21b55dcbadc6f9" +dependencies = [ + "bitflags 1.3.2", + "cbor-smol", + "cosey", + "delog", + "heapless 0.9.3", + "heapless-bytes", + "iso7816", + "serde", + "serde-indexed", + "serde_bytes", + "serde_repr", +] + [[package]] name = "ctaphid-app" version = "0.2.0" @@ -359,7 +554,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baaca1c4b237092596f64d571e9db6ce4109c4ef9742e27590f1709594461f21" dependencies = [ - "cipher", + "cipher 0.5.2", ] [[package]] @@ -371,6 +566,12 @@ dependencies = [ "cmov", ] +[[package]] +name = "cty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -517,6 +718,37 @@ dependencies = [ "log", ] +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +dependencies = [ + "crypto-bigint", + "der_derive", +] + +[[package]] +name = "der_derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aed3b3c608dc56cf36c45fe979d04eda51242e6703d8d0bb03426ef7c41db6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.7" @@ -525,6 +757,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "crypto-common 0.1.7", + "subtle", ] [[package]] @@ -548,13 +781,25 @@ dependencies = [ "litrs", ] +[[package]] +name = "ecdsa" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43ee23aa5b4f68c7a092b5c3beb25f50c406adc75e2363634f242f28ab255372" +dependencies = [ + "der", + "elliptic-curve", + "hmac 0.11.0", + "signature 1.3.2", +] + [[package]] name = "ed25519" version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "signature", + "signature 2.2.0", ] [[package]] @@ -570,6 +815,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "either" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" + +[[package]] +name = "elliptic-curve" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e5c176479da93a0983f0a6fdc3c1b8e7d5be0d7fe3fe05a99f15b96582b9a8" +dependencies = [ + "crypto-bigint", + "ff", + "generic-array", + "group", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "embassy-embedded-hal" version = "0.6.0" @@ -1105,12 +1371,47 @@ dependencies = [ "vcell", ] +[[package]] +name = "ff" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f40b2dcd8bc322217a5f6559ae5f9e9d1de202a2ecee2e9eafcbece7562a4f" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "fido-authenticator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a71f10c27a05873e7020d4c54eb8318236f35c60821b6d65b0a59b9ee8d821c" +dependencies = [ + "apdu-app", + "cbor-smol", + "cosey", + "ctap-types", + "ctaphid-app", + "delog", + "heapless 0.9.3", + "heapless-bytes", + "iso7816", + "littlefs2-core", + "serde", + "serde-indexed", + "serde_bytes", + "sha2 0.10.9", + "trussed-core", + "trussed-fs-info", + "trussed-hkdf", +] + [[package]] name = "find-msvc-tools" version = "0.1.14" @@ -1212,6 +1513,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "group" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c363a5301b8f153d80747126a04b3c82073b9fe3130571a9d170cacdeaf7912" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "half" version = "2.7.1" @@ -1278,6 +1596,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4" dependencies = [ "hash32 0.3.1", + "serde_core", "stable_deref_trait", ] @@ -1297,6 +1616,34 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "hmac" version = "0.13.0" @@ -1340,6 +1687,16 @@ dependencies = [ "rustversion", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + [[package]] name = "inout" version = "0.2.2" @@ -1371,6 +1728,24 @@ dependencies = [ "loom", ] +[[package]] +name = "iso7816" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cedf53c7a948f16076ec811512f186a90009540f3cdfdb8263737244485a9015" +dependencies = [ + "heapless 0.9.3", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" @@ -1425,12 +1800,36 @@ version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "litrs" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +[[package]] +name = "littlefs2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162d215700412b0173e3c8cfde130176fb799beccdd3d8db7cee57be3fb72ada" +dependencies = [ + "bitflags 2.13.2", + "delog", + "generic-array", + "heapless 0.9.3", + "littlefs2-core", + "littlefs2-sys", +] + [[package]] name = "littlefs2-core" version = "0.1.3" @@ -1438,9 +1837,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c0f7acafcb6c9dfcbc3c7c54aa7b8e04367d535daeb4be0e7131f93e4587dd2" dependencies = [ "bitflags 2.13.2", + "heapless-bytes", "serde", ] +[[package]] +name = "littlefs2-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "999d08bb7fae46d63ecb98d2474d28f7af1a6c928a51b4dfe5f1804abf9afc46" +dependencies = [ + "bindgen", + "cc", + "tinyrlibc", +] + [[package]] name = "lock_api" version = "0.4.14" @@ -1484,6 +1895,12 @@ version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "nb" version = "0.1.3" @@ -1499,6 +1916,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nrf-hal-common" version = "0.19.0" @@ -1639,6 +2066,49 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "p256" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d053368e1bae4c8a672953397bd1bd7183dde1c72b0b7612a15719173148d186" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2 0.9.9", +] + +[[package]] +name = "p256-cortex-m4" +version = "0.1.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "647353e42d97cbbc7018cb27c0258a7f5ec1db69a0ac336bd954f468a66af38a" +dependencies = [ + "der", + "ecdsa", + "elliptic-curve", + "p256", + "p256-cortex-m4-sys", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "p256-cortex-m4-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a73da4b90c4bb139ff5cca5526f796451cfeea58f5915bc739df36803977de" +dependencies = [ + "cc", + "cty", +] + [[package]] name = "paste" version = "1.0.15" @@ -1651,6 +2121,17 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash 0.5.1", +] + [[package]] name = "polyval" version = "0.7.3" @@ -1659,7 +2140,7 @@ checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd" dependencies = [ "cpubits", "cpufeatures 0.3.1", - "universal-hash", + "universal-hash 0.6.1", "zeroize", ] @@ -1695,6 +2176,15 @@ version = "0.1.5-pre" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c68cb38ed13fd7bc9dd5db8f165b7c8d9c1a315104083a2b10f11354c2af97f" +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -1722,6 +2212,16 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + [[package]] name = "rand_core" version = "0.6.4" @@ -1746,6 +2246,18 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09c30c54dffee5b40af088d5d50aa3455c91a0127164b51f0215efc4cb28fb3c" +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + [[package]] name = "regex-automata" version = "0.4.18" @@ -1828,6 +2340,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1376b15f3ff160e9b1e8ea564ce427f2f6fcf77528cc0a8bf405cb476f9cea7" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.2.3" @@ -1858,6 +2376,17 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "salty" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b947325a585e90733e0e9ec097228f40b637cc346f9bd68f84d5c6297d0fcfef" +dependencies = [ + "ed25519", + "subtle", + "zeroize", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -1901,6 +2430,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-byte-array" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63213ee4ed648dbd87db6fa993d4275b46bfb4ddfd95b3756045007c2b28f742" +dependencies = [ + "serde", +] + [[package]] name = "serde-indexed" version = "0.1.1" @@ -1912,6 +2450,16 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + [[package]] name = "serde_core" version = "1.0.229" @@ -1932,6 +2480,17 @@ dependencies = [ "syn 3.0.5", ] +[[package]] +name = "serde_repr" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.5", +] + [[package]] name = "serde_yaml" version = "0.9.34+deprecated" @@ -1956,6 +2515,19 @@ dependencies = [ "digest 0.11.3", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.9" @@ -1987,12 +2559,28 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "shlex" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +[[package]] +name = "signature" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2807892cfa58e081aa1f1111391c7a0649d4fa127a4ffbe34bcbfb35a1171a4" +dependencies = [ + "digest 0.9.0", + "rand_core 0.6.4", +] + [[package]] name = "signature" version = "2.2.0" @@ -2121,6 +2709,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.119" @@ -2143,6 +2742,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -2181,6 +2792,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "tinyrlibc" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9af8adde15cc59c61328c5d709b41b8464522a733033584d33def687b26bd009" +dependencies = [ + "cc", +] + [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -2272,6 +2892,37 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "trussed" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5782830442198b88886b5e165b61b4626cda85316b7912e563950e65fa5e20" +dependencies = [ + "aead 0.5.2", + "aes 0.8.4", + "bitflags 2.13.2", + "cbc", + "cbor-smol", + "chacha20poly1305", + "cipher 0.4.4", + "cosey", + "delog", + "heapless-bytes", + "hmac 0.12.1", + "interchange", + "littlefs2", + "littlefs2-core", + "p256-cortex-m4", + "postcard", + "rand_chacha", + "rand_core 0.6.4", + "salty", + "serde", + "sha2 0.10.9", + "trussed-core", + "zeroize", +] + [[package]] name = "trussed-core" version = "0.2.3" @@ -2286,6 +2937,48 @@ dependencies = [ "serde-indexed", ] +[[package]] +name = "trussed-fs-info" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f29e12a051798fc37e531379862a23ac62a1ca38e2357684cd04fc69dc4f1d9" +dependencies = [ + "serde", + "serde-byte-array", + "trussed-core", +] + +[[package]] +name = "trussed-hkdf" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31644e234cbfa703017f13d98b643851d814c45f90d969ce0bbbb3cb28879edc" +dependencies = [ + "serde", + "trussed-core", +] + +[[package]] +name = "trussed-staging" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ecfbae9d6f86498ea3a9635a6b3d3897d2591efa7f398cabd21390cf5535d" +dependencies = [ + "delog", + "digest 0.10.7", + "hkdf", + "littlefs2-core", + "rand_core 0.6.4", + "salty", + "serde", + "serde-byte-array", + "sha2 0.10.9", + "trussed", + "trussed-core", + "trussed-fs-info", + "trussed-hkdf", +] + [[package]] name = "typenum" version = "1.20.1" @@ -2304,6 +2997,22 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common 0.1.7", + "subtle", +] + [[package]] name = "universal-hash" version = "0.6.1" @@ -2374,7 +3083,7 @@ dependencies = [ "crc", "ed25519-dalek", "embedded-storage", - "hmac", + "hmac 0.13.0", "rand_core 0.9.5", "sha1", "sha2 0.11.0", @@ -2404,12 +3113,24 @@ dependencies = [ "cortex-m", "cortex-m-rt", "critical-section", + "ctaphid-app", "ctaphid-dispatch", "embedded-hal 1.0.0", "embedded-storage", + "fido-authenticator", "heapless 0.8.0", + "heapless-bytes", + "littlefs2", + "littlefs2-sys", "nrf52840-hal", + "rand_core 0.6.4", + "rand_core 0.9.5", "static_cell", + "trussed", + "trussed-core", + "trussed-fs-info", + "trussed-hkdf", + "trussed-staging", "usb-device", "usbd-ctaphid", "usbd-serial", @@ -2598,3 +3319,17 @@ name = "zeroize" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] diff --git a/firmware/boards/esp32c6-zero/board.toml b/firmware/boards/esp32c6-zero/board.toml index 258cfda..3524f9b 100644 --- a/firmware/boards/esp32c6-zero/board.toml +++ b/firmware/boards/esp32c6-zero/board.toml @@ -40,7 +40,12 @@ offset = 0x10000 file = "images/vaultkey.bin" secure_boot = false -[[image]] -offset = 0x10000 -file = "images/vaultkey.signed.bin" -secure_boot = true +# The app signed for a Secure Boot chip is not here (2026-10-15): the core changed for +# the nRF52840's passkeys, and the key that signs this board's images lives on this +# board, which is left alone. Until tools/sign-vaultkey.sh runs with it plugged in and +# the entry below comes back, `vkey setup` refuses a Secure Boot chip: +# +# [[image]] +# offset = 0x10000 +# file = "images/vaultkey.signed.bin" +# secure_boot = true diff --git a/firmware/boards/esp32c6-zero/images/vaultkey.bin b/firmware/boards/esp32c6-zero/images/vaultkey.bin index 0c05e3979262899a6e69a9bbe1507f5db3119649..f7779c3883bfe56681ac306211da71fedd1fb2d5 100644 GIT binary patch delta 25459 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 Jmy5mje*ic=eo6oU delta 25127 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

7s?x&_=+!`u;GBSdw~`r&^}2&`R>^Lz@*R`X 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�ly`?x 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

4_OzGlFOKKa{hmdy!*t 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 diff --git a/firmware/boards/esp32c6-zero/src/main.rs b/firmware/boards/esp32c6-zero/src/main.rs index 9239160..bbaa4cc 100644 --- a/firmware/boards/esp32c6-zero/src/main.rs +++ b/firmware/boards/esp32c6-zero/src/main.rs @@ -29,7 +29,7 @@ use vaultkey_core::hal::{Clock, DeviceKey, Port, Ui}; use vaultkey_core::proto::Proto; use vaultkey_core::store::{self, Layout, Store}; use vaultkey_core::ui::State; -use vaultkey_core::vault::{Block, Cost, KDF_BLOCKS}; +use vaultkey_core::vault::Cost; // The ESP-IDF second-stage bootloader wants an application descriptor in the image. esp_bootloader_esp_idf::esp_app_desc!(); @@ -59,12 +59,8 @@ const _: () = assert!( const KDF_COST: Cost = Cost::from_wire(128, 48).expect("128 KiB and 48 passes is a cost Argon2 runs"); -/// Argon2 working memory, in RAM for the life of the program: the key derivation has -/// no allocator, and 128 KiB does not belong on the stack. -static KDF_MEM: ConstStaticCell<[Block; KDF_BLOCKS]> = - ConstStaticCell::new([Block::new(); KDF_BLOCKS]); - -/// Where every item sits in the image, ~10 KiB: same reason, same place. The bodies +/// Where every item sits in the image, ~10 KiB, in RAM for the life of the program: the +/// firmware has no allocator, and the stack carries Argon2's 128 KiB. The bodies /// stay in flash. Filled in at boot rather than a `const`: a constant with padding in /// it is not "all zeros" to the linker, and this one would be copied out of the /// firmware image byte for byte. @@ -196,7 +192,6 @@ fn main() -> ! { trng, Uptime, ChipKey::detect(p.HMAC), - KDF_MEM.take(), KDF_COST, VAULT.init_with(store::Index::empty), BUF.take(), diff --git a/firmware/boards/nrf52840-mdk-dongle/.cargo/config.toml b/firmware/boards/nrf52840-mdk-dongle/.cargo/config.toml index 387ca1e..53547ff 100644 --- a/firmware/boards/nrf52840-mdk-dongle/.cargo/config.toml +++ b/firmware/boards/nrf52840-mdk-dongle/.cargo/config.toml @@ -1,3 +1,9 @@ # Build from inside this folder so this file applies: `cargo build --release`. [build] target = "thumbv7em-none-eabihf" + +# littlefs and p256-cortex-m4 are C, compiled by the host's clang. This target has no C +# library, so the two headers they include come from c-headers/. +[env] +CC_thumbv7em_none_eabihf = "clang" +C_INCLUDE_PATH = { value = "c-headers", relative = true } diff --git a/firmware/boards/nrf52840-mdk-dongle/Cargo.toml b/firmware/boards/nrf52840-mdk-dongle/Cargo.toml index bc4985f..4c49946 100644 --- a/firmware/boards/nrf52840-mdk-dongle/Cargo.toml +++ b/firmware/boards/nrf52840-mdk-dongle/Cargo.toml @@ -20,7 +20,9 @@ nrf52840-hal = "0.19.0" cortex-m = { version = "0.7", features = ["critical-section-single-core"] } # The MBR at 0x0 hands over to 0x1000; `set-vtor` points the core at this image's # vector table instead of relying on the MBR to forward exceptions. -cortex-m-rt = { version = "0.7", features = ["set-vtor"] } +# `paint-stack` fills the stack before main: a reset in the middle of a key derivation +# would otherwise leave Argon2's blocks for the next run to find in RAM. +cortex-m-rt = { version = "0.7", features = ["set-vtor", "paint-stack"] } critical-section = "1" embedded-hal = "1.0" embedded-storage = "0.3" @@ -29,12 +31,36 @@ usbd-serial = "0.2" # CTAPHID, the HID interface FIDO2 speaks (docs2/roadmap.md, phase 6), beside the CDC one. usbd-ctaphid = { version = "0.5", default-features = false } ctaphid-dispatch = { version = "0.4", default-features = false } +ctaphid-app = "0.2" +heapless-bytes = "0.5" +# Passkeys: Trussed holds the keys in a littlefs of its own, fido-authenticator speaks +# CTAP2 over it. Only the mechanisms fido-authenticator's bounds name, no logging. +trussed = { version = "0.2", default-features = false, features = [ + "certificate-client", "crypto-client", "filesystem-client", "management-client", + "ui-client", "serde-extensions", + "aes256-cbc", "chacha8-poly1305", "ed255", "hmac-sha256", "p256", "sha256", + "log-none", +] } +trussed-core = "0.2" +# The two Trussed extensions fido-authenticator asks for, and the backend that has them. +trussed-staging = { version = "0.5", default-features = false, features = ["fs-info", "hkdf", "log-none"] } +trussed-fs-info = "0.3" +trussed-hkdf = "0.4" +# `dispatch`, not `ctaphid-dispatch`: 0.3 compiles its CTAPHID `App` only under the +# feature that also brings the APDU one, which nothing calls and LTO drops. +fido-authenticator = { version = "0.3", features = ["dispatch", "log-none"] } +littlefs2 = "0.8" +# littlefs calls a few C string functions; tinyrlibc has them in Rust (c-headers/). +littlefs2-sys = { version = "0.4", features = ["tinyrlibc"] } +# The chip's RNG speaks rand_core 0.9, like the core; Trussed asks for 0.6. +rand_core = "0.9" +rand_core_06 = { package = "rand_core", version = "0.6" } static_cell = "2" # The INFO text, built at boot; already in the tree through usb-device. heapless = "0.8" # The workspace's table with one difference: `unsafe_code` is `deny`, not `forbid`, so -# the one place that must name memory-mapped flash (`vault_region` in src/main.rs) can +# the one place that must name memory-mapped flash (`data_region` in src/main.rs) can # say why with #[expect]. tools/checks.sh keeps it identical otherwise; it stays last # in this file because the check reads from here to the end. [lints.rust] diff --git a/firmware/boards/nrf52840-mdk-dongle/c-headers/inttypes.h b/firmware/boards/nrf52840-mdk-dongle/c-headers/inttypes.h new file mode 100644 index 0000000..6ef5c5d --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/c-headers/inttypes.h @@ -0,0 +1,8 @@ +/* littlefs includes this for the format macros of its log lines, which are compiled + * out (LFS_NO_DEBUG, LFS_NO_WARN, LFS_NO_ERROR); the integer types are all it gets. */ +#ifndef VKEY_INTTYPES_H +#define VKEY_INTTYPES_H + +#include + +#endif diff --git a/firmware/boards/nrf52840-mdk-dongle/c-headers/string.h b/firmware/boards/nrf52840-mdk-dongle/c-headers/string.h new file mode 100644 index 0000000..992b87b --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/c-headers/string.h @@ -0,0 +1,20 @@ +/* The C library header littlefs and p256-cortex-m4 include, for a target with no C + * library. Only what they call: the memory functions come from Rust's + * compiler-builtins, the string ones from tinyrlibc (littlefs2-sys's `tinyrlibc` + * feature) and littlefs2's own stubs. A call to anything else fails to compile here + * instead of linking against something nobody chose. */ +#ifndef VKEY_STRING_H +#define VKEY_STRING_H + +#include + +int memcmp(const void *a, const void *b, size_t n); +void *memcpy(void *dst, const void *src, size_t n); +void *memset(void *dst, int c, size_t n); +char *strchr(const char *s, int c); +char *strcpy(char *dst, const char *src); +size_t strcspn(const char *s, const char *reject); +size_t strlen(const char *s); +size_t strspn(const char *s, const char *accept); + +#endif diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin index 68528179ac8945c78830eeb19186ef24f8ee5409..2fbe167fbebcd15b9c5c30f83b1d26adbf0992e6 100755 GIT binary patch literal 267748 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 z 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

yNgPI)^VY~Ce`H1i|lF#m~M%)#v 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 delta 29392 zcmbTe3w#q*-Zy^EZ}|TI!?*Wm6aN1h zV0dx=uYGv`$XD3EwK!oG^~ACP#ae8gMQoKW8qoUtTH=c1XT{%G=@J6Q4~+iame}Hw zOBGZocePVN@HG8U@?RzjSFh`u)j(TH#Uw|h1v>+sC?_QP^< zXK3laez5wMz4LA-p}{tiM)POHhKc4lE`2{(*ZGdt)M-<_i7YGPJ4!?nGRg^Z$t5~B zmffRR*zSSz=NsM@-r95dnVYva#D*PlJ~{5Pc7ANw85ehXtur=kkE7QmR%yetNCG~6 z#EQ>bNIX96Bo3b{J=l5X6lO(_j2S(~<{ z*sB(##D}g z99hGr4AiVNPSR@FuKt?c#^hgVSV#Y;kSM!4@1luJKX^Dy;ztCWvLxSz*6aIM94vSP z&q#ty75XNL?Yr& zda35Bm=WIEuW43epjk;FRI2`(FL3Gr|3#!{zy6Qy+|IX?x1CB3*}(dHXLdSDCnwz$ zCT546E#EE+?B)StC(N}bchhNQXTyK=SHV%9{6vR9{494(UY+4uHocG7+XH!Zf@EOl zdjF%#L+X@u1~#!zIat6s<+tDwea*2&qrKOx!g7+6@9UtNk=H*GCPMfehGemQnR3DI zosIu7mOA~qv3GZvX<_Hn`PSseJ1F^|vxLPR&8wrB|JmN$Z5Occ`j*3CWBf3lovdIL zcorKQ_ms4VIvi7DvV1IimG^Rs@`+Ar`CK8^Q-;34@dfU# zTd#SqbKax7T-pGYGGrn9Y_R(4BzJB-Nz3rc0Y&StQmmne86~B?YuNgthF%}TG-*y# z(u}00I7W4x+LD?U%emE560-LPmwkOWoD}b8HLEWuA-_S|9j+wS@MF01-0BpjAx`%6 z>Z#jb>!eoeWuG^_>CJFGo^4fm|Td{G26bwprij^zgf704k?K`M0-y#zfR8%^%d-l}4>ek-j81LUVVE3~ZeLzFQORAV~vY4lHt5azugYkp*+T73R{Zp6ukyE)(aI;2^0z@K$5FQ7 zP;`B-@%0Uf06+UZmdAy_)9Ui-D)+hw+f=z4%QMUEGwkksH(l|p3)ruuj@%k6dqi!w zrZRu~X5~AP0KuQGNyl=tt5UJx%~B9`W4Q`YidC6~mxs}}47#S5LamDMir_gdOfNlC|XB1l!r1aiu5 zY%+ri#vh9=?yA*ZfLRnI4k9a9gQ}{DPgUh|cCKGz%r*syWXvM$!8JKA-M)zCIc|uV z*maIzkh?)jKMELQFe+XmtA@o(_qiw}(07RFj{2fR7lp+;KG2*OSl!;kiS8|*PKAXL z``Lv@oN&xCC%FyEv_Hg#3*sslI^3>uZVUL^$Q%AP%^SnSIBQLAb&4zkx7jbI+CY$= zL^iXRk3cp?39|T}Vdms&8)LXcS;y8#yu+-<@ih0uVOp zX)3+a!Vw@y6n2A#ZC8eu{-4%Br2DsrIebbk8Ou2RC9<78`Srug|ELnnFHN;&0ltZB zQxBIdM1%xd^i%1Q?*+NeP?!Bva@}8-ltb@)aPrs9FhhyNA@W#D)Yfsb2P^HWP~VRI zZCC!;kjN(Va9sn+apJGgr#!m{e0CCLGJF17~Fj z?2kRa_>yK+$jgD!2l|i0R^13e<~LyZ*1zvlQPr-2as<5Eb;Q{&h;f&_+PTK2l1n5l z$!+x*Wg=K3 zC_f?7|Ak6#R(@1$Y2H;ZfY|#Ac7VZBR^1E}hl(fg$(h&T;f$NVg|9tBHSGOulN0=H zxe1>rgc5sSfLqY${W6EhCyG(GU_Q;WX8kKjMgFA1BZPP8Zy zdy_#8Ym~nSXTj*sMFJ$#qm?W2X&TKie4u5^Rm;T5mZ(}T zzn)7On`}(ev5A92cq@zb0%bte;^>X?#=~JDJ~NP2H^r7wpTOovM%9nrVu0Am-?nar zXkc4+V&M-0l}mT1}d9xncj!H)q+zQ<#6T|$=l&nrhtD?YVA&3$qB=h*)#<|9(UZVnH^<{Yur$L!4A zL@?CwC|v9<@m~ZyE-FVnMGN*qBfsE#8zPW)zV*~a#c$=bl3lIuSWDC3NNT-zLRDMR zH!qcswEmj>`uJA$6VNEFQf@7iCReiRr?6+ODE(FzL0V@AML7>%i$OWCD1rU=;F6EH z-O8c2#J}XDC9q%rt4vyPYBH^GvUhwj5M5@7uBTn&c5)%dg;>*<=ap7cuE?-mGl9L=v7J12uQMT;uWS!{a;L6>0wR~JjEIqA|1}l4ZkZYn@ zt7+I`c6DAuDqWRq>Qh|EPhXwC74Z8V{GB+Or41~5VqIz#;1IW(Bf_GR@szK1s(jk7 z`%)(reNz)RI<+QqY@Anxtg5{PHc|CBiF6UmB?{f)N}_pYw-}gl+mas#W&&l_HZBXatI#OUt|DtdB z?n#=8jpzcF$wmLrNr_*XGWc(2UsQ~c)>y0~ zdFL9Xbp)X9Cam4ZaoM2EU;GZJjdXtHv+N|B30UDJIiQICi*2d&Znu_gQM#U+ zqZLO=ZnczE$#$>d=$9mp{1XGYkZz@rENL>w5U}Fbu~9=@nhXNDT_&5YL%ur4&zsPX zuFk84hcD52M)#`ZEr8t1zTB;X19%h0Aa)X`Ss+`a!S4No=5U;sdqLDDKc~bxpHnQQ z3GAr>kcXRd9mqq=CtdQ9QC{M|UAC>`({nj5fIQYZvmxj0aehTFjk1k_<z#}IPGEN@RRyRKmO1!bMTFeSb24EQBxmn(&cXWDWE3Nn81 zgWatUk{9u}9)HQZ_`RQ6B;$6aZKJUCe(nXOZ|AH|JLA?w(F-Jr-0ko0`|GzZQ2kn0 z!sj`4q(gU;`6Y!SBofn{UX@dqU7h=)^9~Km>v?ydA=}CBs+?3$Mb8fgI@rCnY1}R% zVyYQG_53)$!DPpx3U=2djZN{Yw0mWPQR=1Qt=7i=+}^2UeT&4lQuUmAFWuf3#wtZgAyUeOonzI5pSE~U;uKSjF#aY!c> zcy~v-pFAW$WSxYJ^jp2*f^@NY1oJzx`2z9Q-D)?!I!$;t&maD8QNeDOY}7 zC3CF~fCYI^^qQY7lduIkIG$Ci{_u8X8a05_S}Wmfiquvbg53fb!nUsTMs2MO`A;y0 z6WA^2;G4tQ$(XiRS&mR)bVzQO$EeQacBPzhJ3aR0^${>)d-fbm-`K0gYhLU zpg@^^E~E-}e-5rCnHojEW7`-yq{VV)hRqMylfQWFhoYN>hr_0L%Boh~CTqdlkN5Fm&0(q` zl1&Z!}M-MsDY3A^SdV8jdXu^Fn`-7s(IuXT&mc z>$A6T+diHh?v0VT=_NjuUVjQ!Zpu^KHy%7lCFPqjRSB}!@x(|u38B?EG+xsiXgu9E zg7RN<%osH!B8&w|m5zBap4~Boe@;yLKoZQ#Uq}4=IAIm9u}Jw_Ilwv6ILJBDxDrEj z6o^?3#Oza1#);e!_=%k^uXI|xM7VAABFNjY^8o4}syiF8K}=rW>KNEYI~k?t7PlOvgc<-7$j z`?BR!kB&)w)C;$fD^LB7RafX5KwNfm20$oqr}3p#e^)F-up0mcGo~|l5P`!%2@2we zcoOMee1H?###RGl#@ZQ|t~R_U%3L25?2c#uQvKTP$}H6Y&t0VfEgVzLJ>G)*C#B!D z{3u{3qX#A4*}U@90(qr><*Ajhy;hQy{;224g~na0qK@+fc%BK&iHHc784D3$+BrkR zu7U(`#Bs*OUT=pJ1&ljc_S2uk_=D|LYFv9~FM~(ay>Y~bM?6eY7WG7FXRGg7 zSMG~G7XNgGd!fAYHE(ls%c(#Z zu$Q?R;pgf$x`&gzGfd&A(YM-Xltn3l{SQ3vQX;7ap92QpL;N?KE0r+00W!xSPdhp7 zIR7Inj1}7zqg$E;qtTaNCrJS>u%A}tfOz>sPd37BYB#4OUyT8EtV`kMJr}77a~p4zmA&;aWD`pX@8Kp7D%fa?B3FgMGToF|J}n!T?psrX(u;JbnL^S zQSBJj8y)s(C)rHdjcVL#?%GCG7f;6udDrZhFsumoj=RN$kcBK>^{4zZIEFc}r>>0x z{{rBayCn{Ml3qvit6bhoBi`b8pCo&b^Z2ljx8mq-wGQjieX*)ohypl$ZH-4v_C_-P z4mC&Fte%~XQ5EN7XP(Zl%jVl_0Bu4BTWCCs?-{LpWPvOSz6OpO6$0X={B5H{oEbQv z0&TyzFQD{0b0Mh`2afMEK+sZ$2-}Urb=D{jI^=JQO-!p6L8RGebFX3!YshP1 zjhRk%BB&4>9vL@AwE#zgh;P9N<#A4qU^h2oZ@yV^=lD8bS~aF#g#1ci(^ZTE-(~ml zO$$?kc%Q*9Ge*#tu$E*Q-v(yoW?E$wW5B;zgl=JB8}NnSRufH zo!OR{tBsY@>M*D!9iOEZS7#wv;4Wc;dE`$9llWk>$)qO&H95A?-bvpDv>`qXozxPf z=^Qt9S)2^46cP5=nvWGl{8%A*<_>{=tQe1vaW8i3;Wlw;^xzs`iAJwyuT876gXFbz zOjUN>$I7M9$4Y-``liu}e-Tm4POZGaozNkeS5*{M_}JBJqw*|wt=E&ZR2~Nz=J8wE z>*z|t>Oz7u`eM(i7A}CQiUql3{b8zGq zE_S8t4N9rxV_TjY0g|+`km^@ABPhUqYH0NX15;Y34|XN5b0d~RN9tj0f)^#p<|UAsYjgNdJ6L63!hn9{%tB8 z%?W_X_Q5gR;G}Q2q@~rp*`cF=f+gKs#{uJz2fFuxE)F2dE+GT)_)}a8NLTjt^k5Ql zP0eH>B(j!WP#r|T2I=5r$bPbkusb7uLwO*-?lzeVDozu8OQdtoQxJm=h~qpC+oYE? z%r=0YFiJJ>(r!!g(mXM%C+MG{k%q!ZdHGxCh4SmEJ$++ISO0PhqYWzG_=C!N2jBG~ zg<6Y)JP1rW4NpDmDmn`rP{huK(``xfEFJF(FDjXi7uOrE*5s!#jmE|_g3zHc>%*x6 zuH&+|81nJ0zdl5zmVd;0hqTRFmobfOjAP3qhB_`XhK0rMucD?R){KBP-_x+U%rkRT z%H76WN4k$5ie!<_?A3fRKTgFH<4Kzg`6P=^$vuZLHI{HX3@?XbznxCCD&EX#y0Av4 zYuD;DVS|RRIN6=;{#S6!OG0=yQN9|9oKxj`^5B^2q^hjCRN(Q*K>l`ws*rGMp1rU9 z6M)xIPVL&@m~EU#oSmN4aGcmThuvMiLLH|p1jq~Gsu2i!RbG!zE_h4YUrO}1-JC6Y zbnG4AbdjaTUOfm_#){n-q-16PJ#fCwN;&oaN#3qJ4AVRb{B$pkMxeAEX5y2cW7Bo;&d2gZ+#mW4lT(`i z>owSKrSurqwO-zhPkzO}x3@m2x`^xXjbRA2aV9gfU5Y4QC&jb7B4f6^CMVUG3eNTq z$t-~!Dr`SnW;%4DEe_L`*4#8{-1vL76pJ*o)oL6X3)K*DgYqz)uZULDp&2#i>^$#$ z#GaJ?-H1>g;bt4QxAHi@T8YrvljODj7rhgOT_mHb)Rz4EItc^q-k zKL6HpE)f$JRkA5GVLo*@VFYuW80(@qaR4VPy{I=>1GKCJTD0>?2IO{%BvTt#4Q7_0 zc<%7A2Z`qvdX00k+TD3UN%vy_@|vtJW#?iUQ8*{3w3WvxLS6p0UySw0OXWx97#0S0 znrRFKpgnHUDZc!@@*dq=JL3a5DiZ|t!z>M`8HzZNKdOa*K?g!O1K4nt+dkb1FToj1SGVc?@LpI z_Sy9pl=*&O%rQ&g*dmAGyoei^4!zr!iV2!22j2#HFFyGd|K`ispprl-JjrtCCQb-X zyJOgz$ZmO&GLeu&ZhS&=d{rG^f{IFR)|c|-1=@@a7A(+%-26(CHnhAo zv?Lzu`(BqV7a zBe?^J={b6w(wVmThhyuKK>V-t@$F)U&>g2Pf$jnEQ~a|!O6`C$|ukECT?FKzuc!w z`^*R_sd>3$26cDc#B;%#g^Tj$)9VuCe+7qvPgi0AT(}Y2U^i*fASRM_G`@#vs2&iBGr7QH`@qD8t>4$Kzy9dW`K%_|*d z!RppJ*171X8fnp&lb{}H&@BDemymh3)cR{-8Clso+-+(=)^JJsb~vJ?N%gw0h2#UC zyLvh1epFbm_vY56$=UU3TeNJjhr1WV@zF~ z94&%KK-4P@!aJT#fFE>wkULfu*`c~t1KqzwKt_U49@m=x@cr%IPSqCBZA00I;i3N?Zq)@#v4JK)pX}h9Pz}#s2%k2kR|;-YR7)> zxGEvieLsRh9LyZVpn;m(9a$q1hr(r_{AhRc)?RLkKq9GjKIq;2@9_`H>`HFkq^g1L zElpXdBQ(y9VeP#MG7&}a@;`bl;zBt#M8qt)tA&5^Ym;Qev%mF%@~B1RwTCe*p!O-b zz3U5k1*sH_><(5`1}BW z3+4A}ewFuUOAIUNO+uP1hRy4($pyu{LXlz)oxg*1R>jjTkt#>f~y9mCQ$4c!z|ECJxs8?heN!Ey$GEg8@-K+DZ&e?Q*lCeI8v_ zq{vsvdfvt80G$mC)O>bFw#Xl7WsXMvVA(rJp5Mv?QlhMpv~1ZxP5Pb7?=CpNr^Yx( z(R}HZ=5*OR$dL^-r)ZuwFjFnElfy(WBG_;>9NOg(Pvh`)Uc_VT&owk90IaG8&Q|4y}jS0tzW3lluaGB&-99@s`W;>D88rKY&Fn6OnV%5m%*yqtKQ1bQRO?BL)3@eam><@gvWbv?nE8P~2K`bxc@Gjn&3or`x=y`dIeYz8PJt!pP#aq}@nND39!K zjO|=fbRuk}_A&93)-@4WT}KA&NEh-z?ym>I>i;&7>6TdbW}gE@&RZ-RT)ziuS!;L+ z3v}sGeFZnbB*ND-`eIq#AVx>%$ZCuCvYCUf&I|xsI&11MVn0ie3Xf;g22tWG88?+9 zi{E&ed3%G#okY@IW);L{tg4*P6B~WFr$ZLy^>B*zkDN5)*-=+#0ol=EguQN+OzdF9 z#DswfqKTbUIpD^wl_KX9fdpDha{a9{#!n{`A&d_Cj+)p%`=j;4XKvomaAVi+Y{TA| zASA3n?lH&-I2}X%9yFFvabwq$HVjmg@ZRXrCR73yb{f+YDvoy&txD+SM4wbM>%H+_ z$wSLe8TtbRPNp^?dR^32<>B%k%mLHSyntL@wUpX|ttD8ElXa{<-Z~?fOzcAG6lYRU zSi+o6!(u<`qTQVb@=ew5&IM)Mjx@e$taf)z;#p9hQWH$<@qPl;*5Pw@YOU@rw{#pa zBE%!NK0(R}>`JGFHzkMWRE_Nc5$BlC&vU(G&;-guG+&$jKmd0gWa8cDyIZ>U!RyyN ze}{JRh=69YE+9;PD5yaTntyXhlYL*{_7$O=k%8}XQi8Yd8xdX{zv%N{;QqqE9V=K) zY~WJP*x+yWjS4S~_m+N6v*$FALzFV4*)efeFgx_eaFsqc$K9L|dM*5=?)H6_$z#rr z2p7iRfRP|@t2z^`-0v+H6ffF z|F5%iI^PBrIRQk1Y|QEWlQ3*Kk~nZVl7<1C6ym`gtr&OtnL>AGQ$7be>eCy59uM#P zpZ&bt1LK(~^E?yVgZf=QfQTxzX9_XFz5JQGvnAi?;Y;8{U^*=yhEL6V4Non~CfL%} z#wnn{IfKqlk{r*AV^HTko_wZ|)gLHCa{wh}qk`vA5VIrPLlZ7ndRx4ox;v9xAU>>g z-XfZ3%u1Wj8xYi-oxt}cwLZoXXGet1T6}GEGXUG zdE^>*=hyH7pW#NN7JoYYA&9JQv6OU}=*jZp{m+)09!P9A#zVf$q2o}Rvpmke3!M~RkVGY7GR{iUJ~`UObP<#CjQc!qs*R+S0T_h5KQ{OMo`WE6k)*RD_n zho2R)icf6x@TE%u`>yEN{2m|)UisYR&uOD009x#yP!7)Mg#V6L6Z;YsmEKEpYYgvS z?FBfIbL>M!B9#DE1YAF_;7jB(gCKWnSmkeZjVIY%sy&p+(KMekDwp3!`-;1qCRN6m zOyPnneZH?8?!#La%fI=EFY`D4jjg}oB4GY+{6vBg;W^b7Q}g!wBfO$K3kCc7v`BXd zg@`gue@B~M;+JDUW$g6R%Vw8y9fCMb%({U zKN6c2Bhe$@Y9YF+IXel8f!&?=&)~4t+Cama_uDl2g`K7}XQ#>O_u|H0#iHRs(IjxF zr|kW_uF*Vd=a2u?C-?0wnrpfo8MQ?Beh*7ThLnD zK$u-kaK&Ekz10cBZ-deyIOGX7l)9<+ot^&zx$RY=VH9s+S9!$-WwcsHYIko?5)<;U zqxVqkHQP6< zsLiu3JwcuzV6{)}jLvaR57JnQPwU2dqD zv#YSnc=yS+TXE-mfH)cyGMBnK`xBw78em*N6Nh?AvEb_lYv!C1y)eYJuEoV&D~vNr zOPKEwC{ClWcm_h)s}?7U2Bp}Ngin{HuyeF$g5tJ_2#n7@f_TV!4f97L-QV_cOu9Rl zpuF^%A`W(5mu48exl>z;nl?^G9?Gmrq(fJds#x7y$qX}s)?9>|%+x-FnM zI#Zc6DG1T0-!ii;?l21U5q@xzJVeoB4$M>>llr?geesa8%ll01!M>;g{YQm}{OV=d z;W_#(*UPyt zo>$gbVZ$V!XcNW2Q6H=nM<4GRQ*LXlZnc#9_}@`(vrOu%34Azmd_1%D_>Nj3AH}{Q zW8J)}Ayz#xh5giMKKip)!)_eRfECQkxirj;!Y-kKTfj$KnN!1rV?+JopK1swDLx7| zAgb_K?V~*8`KU2GUyHGHfi_`FN&CA`SRFzY9AO6ti5P)T0nF5_G?N3$G><>*qm8b( zv(3tRYfQ2)f1fMUdrpK=J|3lt%_RERbFOmCbxoC7i_hAUG&_yq>*&?M*qoki;6DT` zo3<&jR+1$I797;p!C)8B(`t0{Ax~nAbuIzM56RSrZcOoI{o?H6MKtrIavrU)Y-ldN ztf)N?CsADegV(xFe|R61kEbJsTs^fSOh|f@fNa{b0bXWp4n%FaVUO}axieWQuPQX5 z#GJ!n`lV;zGO>hS`qF!Cf`|}*L)4fo0uly$_&GD5&BQME3`4QH!L;WY8RC+Tlzqqz z>%1`~%!yJ00d&cwHYDz$!R`~0ZIHteds#rUcN4hJw8sIt&0Fy2T-u^Xj6SUlxi{ZX z+ZzH|@@ohxCRwUm$B?__G4JYdY9`9NpF!eR94_pNlp0~8Z^77H%v3C;jyccb2WNVY ztJKq}{!Oi^B-L+(DA=m9JrDqi`#)tT+brATP*ds?*D9KZ*A&{|s7M&vEvNaq9uwQp zQ#0vIx){gKL_St_dn$8E&h8w;U0xDS7v2y1G}@h%-LBMBoJrPFHe0FLa7M(%^-9gY zGj^?sW%bltJd>o2V^2hCde6+(B9+u%bK_r~coanAzb1(q_V=D050G-sJNCwxz0`KJ zH2^vd9JFB#2bG%l|LVi}wC8$iZVVJ?1$L&XW>ug87t13xQ-WJHW|q4DS~ zLDWh{RzIK>jcofsf^1|j4RB7RKXW_QSmt>4pE!$Qg0!S1ZSnz%1*xM=OIDfsf3H;xtb#e`$XfA6x` z;+VaUD@rXqw>ZBx{3oK>_{n-N1?K0&8juZ>K8M7am?Bm5!Wai z=ALMqc*_ap)zVj$7lc=p^*AM?c`{0}M)pR(i2c0PPs>dzfEybtAB&Rzje0{(eQTD+ z$bMJz<>jxj%wP5HKiMTvuaT|mBjPOCX)_`^=8zHSV5{+M#J5+KPQ_i2v8pXhE)xg0 zgz^CqZUrep4uxR|ys2;q7Is-Y!>ucw|9k6=ipo+oW0j2Y@{Uu;6g{KJB4P7;ilIEp zdg@w#M~da&`Ej@AE@iZJLQq2V;$-P-Pn=h@KBK#4jgsx295gr7;hz~HgF{@mJ1mbgmV$57YM7ob1 z^J4_m8yZOmHR+f76ymcuC=~sXxp6E;5i)t-XB6V`Jmj01=@G|qc^2niqqu#sV~2)f zIF(xn)E}H{WMA}fP=R18FvNf8uQ}0|nITiG5L9_6e0}`LvvU!TX^8Mh zUZIk1wgTe3>FJvI{;LvVQ7IoCAbR&u%{Bd5Qw;2ZK^|tj0lYQ_MiO>b76n>j&(JOr zy|@9K7t_PrB||RhdiLuFzvFzGpcqxIOi;L)@!`Y3S)6s^)N|Gwwz#G=2bC3moT8kA z6O?hNBzF8ACny&wLMRobfN24oq`Vp@DIeKhG(LE@8?^y(XBDIWNVqh9%sHf3ttQR- zqLIz>9;4|mD%w!>V`m?m)2>MaW%y^b)55}bA!#vAP89}@;%rEWcNZid8d6W7c9w-o zRH}W*LdT?RjTq~+o01v@`)K&0>tSw-A>&R7485|yc87&#PFyeQ%o<%%6Ya2Gv&m&| zx=Pk<8o85XjF2)svFz_W(HJ92r2y^6wa`0Rnpk$Qc3do7s*Ob&vi8MTTHx(DL^5w~ z8P>>qI+x#!x@?@vpa?A=4OwKUS?S|8-Oi8Ok{`f%j^5)lOnN74^tGbR_W>OJSYz1j zNzsMJ(VL)-bq|`tT4RnkmR&c%?H)-UTjlP2mDhce*|y}WWBjV>Oa(Q@oU4u?8M|DsvTiX9|+juKU zBQ~#?^>SFG*WsM+Iu}1wJg;5QQXCMLLc1OYB3wX%FrxhLh`dqvuR#r>P0WmCH}w-7 z+}7sUo3x^EF1wuO>jN}zO0v#v%<2ppB_R~aTGwPm{Me}4&(T=-l-*7R(7Vu#i;`K+t+PrBW%taFy~k(YgUWt?@jYjhbi z9{yqcH3J7X7p-gBS~RvQ6N<44+Ra1~FBx%?-tIGP9Of3v%T*DP>xNZv4%YUpt4g&b-;_5JN<$I<07{Xr>lN?L2R3 zJ4{3ixJ>W5?JYn+JrzF>)!+>eGm!|HrM=HFYgml8HQ`(a0&ruUR#bvSF1g=AegBN+ zl$l-qON~x**gz>;sdu>Pm|d;~&E`7fFMJS9-Z_B@J9X8fgc!^{clAEkb3Y(@yjQ40 znsSOQ$+&UCZbMBH{K_=M?n#w?bENyRLA|UdE%Sps!enNF9?$**fJAPyv11()+jd`? zyjM1M9H&b^#3Cle$V=a?X(RlZxdHRkRl z&+;M;lMC2A;5MS^(zv%)wg{Pg#LvGKGC%v)iOh&^sez5?pD-l(4caSGKPMFW4fKs@ zbklK-9l~^Elg0GfvJrHwcjTvwAJ_$->3m!2v!I@9oDg9MMWzvUgTfVqKBxmL&|h{2 zi)Haw5fQR$D9r`dH?L~|Bj^KdsZWvgHhIn&EzHZ)ZQ3bNBAJm)5R=u^aRMiM;5?_{ zH5<^;;Tg2Rq|cL$O=?BFSC97)$eKwVL73E>D$VRDSKp{j`Xxkx^@gPv%6i; zzhj6_JDE>=C(Xp9ac5xd&FJd?ZGm%K0Mp*T$%sjRdk$oCr=nN2R!RF)md1{!;*+7( zEP^IG@l)+IO<1eZ;f*Iw#p2^O%mW zT|wJP3}s8l2_XCZ3w`$0|tJ>?zVau67 z=r`+Rp~|q6gtaD7It!0;Lb1Ekony6T0Tvvx$f2h@cakSQXz zUGv|BDouwf-PCfh90yr8uPT}t@RrJDI3?wb(QhG{m2#$P` zH7>2|?347?@5G8oG>>-y zabN8gQ~BJ5H$A!G$^AptSmw{HuwrMG%Mb*3MI+3eVh^ob=h21)QL{ym5Q*voRpn9aQ^(Tt^9n0UUqkVW97E(%+6A+sfq`i z^&JE$o}KF56PzdwYo;zi|8j)#BvBJB?y))_DD(@i{dj;5t~KERWbuE?^g8N5qFi@GRN zt#J&s$75Klu2<-s)h?K-XS`86eGHv&JF0rHSz}PxUfgaXVA~MU#v(pBGW2()feMny zwB$p6wVfZ(v4%LW2$HS}PSPb(q2;^OtVi;AyRt#h*t3HCU~5UG2A{KQ|1ySNld&CP z9G*)_TNSZwK%))H3$`y>6IdqIkvZggl1YJw+O%YPtyjNi{c4_Iz8{*<>)fDJxi%>4 zU3<|9IRK}9Okufw;WH1cn`tbtPU;SJaO4#7=nu64Jt(a>uJ}dXpRWbe2pSaXZ4mwz z($!&aI$?7Wq~=}iA5=UZ(AD`3iNU+tPgXn}h}pSR{w?Z+$9V_0DS6}_dC-1eAZF_Y zC1=M`B%iJh3H60t%PV|oKggD(!mjldaY->S1@jTutV9nxq4wDU^Oj0D^=YeOz?3F- z-vA#eVt1mdw+LJwl_6f}&{9q9I z;T&4&Lu}y)T(g`Vh?>Tr+R?lROCp&u8?896r>TsAEqxnK-V~PKrs&B{4=$DKW{T^K zQ*a1_#S*Q(Bd|4eQNFAF6izum@7o-@t33uMSFBYtkhV-RQy7kdNmoaJd7`z{eleEb zK()1FQ|MH$uwB20q(@I%$Bt3#OfHA>Zh6>qH(-&Z_TQ#aUs zra#s@WZxbGTF6*?gEo|XzA?y-TcmMD&v%SQKL_xC+I zQS^P+BGe(onf6>TVCdO5a;{R>3V9KO%-ri-dX{;Cl~$+JF&cLjn2*=$Js zYs*F1`$?lOXL?sI^6O`SrZa65^#(N6d(Hq^yo=PL-xc#l1%z164vv$UjRW0v1N&O^ zBFW^>&nOL^ufOGFP~6Bj5yi(VLB8N$4Qy|LS#RB@MBbvd1v0osBx#4SkLQ$hYjpkowu$*&-x}@3 zXMcp(@?~=s(Zh-L5Fo^16WV(Sy-K;6EWLsK3)xr6QNnv*25OBWorJLYE~WN5k^T}_>y+BZMFf8I?Av}d)rP?C$+CHi65QO*)Jz;1 zbav7aH9jG2LW)9R@OKkkd47}n+%oh$(!Hrq z&jxz<$UL%r*9*>au1LvD<{he8GCQZd<>;AhG=wQt=?M|($FR-WXg`@`onS03M{ z%qEUTGlB)Pz<*wdmn89xNlqa;mM#Pq9_6(WdwD7CP z)OH=gXq%+wnD7cgn?`C(Y`VtqfzYv9aChFV7FuRNo{UGlD$*TdV4{P2|# zCz^g~v#>oqNFY%sUgNP9=R&qEL3RvvG_C+&?)o0SAeu%q4Ih*ZcGpJK^NYbPI8|>9 zi#lgxO!#{UYP{BSK0o>_!r`DOc6}Dl`4bVt|E`CZXGSwfJbga=0+SEgCe>c$p&2PZ z1y7L*o=kv82%QQWO|>2m&Gb61#A)|8_+(y5`78ou&{~py&qh=P@dcc2GbX^&Oh8d$^?-10q|97ZKKZDu{)dgVG|R4ANM?xKls(fD12{Az0#(+OS+dqI&Vjc>}iWpRpKEox0_Vn-!W zf|She<#`7QQg+<1OJ=@`mjx`lQcNo>dj|&+>(r7&xeC}!R`{B#FF>P0+KINQ){&wwou~YS6K!_sL|e8M=gI4E3epjcU_?`;Wy*otyY8ko zH^K^n#jhOj3t0&GN+fN@eEyb|ayXGV;BWOS7XM)PBmJBJdH7Q;w0A^HlB<;OtYwWP z{C#cpSj~udfqMyYbCmFS$D3%Y+i*Q@vD@5s- zAK~u_{#e_*wIN0RTbnSCCl-9T((1uviK+voFNO0S!-{wi5oYS-pmt9T4kC(p`H~r# zotUr)>L`}I{6`jC?nS4f0X)14%kS>|#>I)GRE{4al89miZu zd5ChF=0^~)VD2-2trPo%rL0u6#0Ye8>25p8tgvOQ+wOJ zRCKptZSR-!SJ8}Zc9m-$9~wc=M|dBnn5oER9c%^1`M{S5J4A)`i%|Jx*dv{*XX}+( z|GhL-JJ3!0Yrnde-amp~=ig_xuYnKgJL>M*&hvD&9lxj7X!^U$YSVVmB5i+n%dy%e zJLntJBHgJ?#&uDnF{#OS)QA#bpR>RF!(-eV_Tk`Wty=V3g_QECebw;JeMfnVNO$R> z+PN>&>$FC8vA=f1%QU6H$czKr$G!unv?ka@mG#plO`4It+t2Tp;kf39`NQ`G+<&LP z_TtM_L^A!=TKWndJJQHDsZG;^I=nVcl>54u_SZUIp(*J`_Gk5p1y7vnlZEPUEq)iM zzsve-D_)`YTE}a2@alPw-+pk!<8-1C1#sGX{EOzTTkX;|RXwJ+lR(8x<2o%$6M6LC z-Faz7qoVh77@c~B=6U$d;d%9;fM{Efv5Fo#=tbf= z_q>Snh)%|Q;<&2TNo3Od&<;N&)Y+b_aZL&G;lK8Y4;)oyTS@o^{RUSVGOvfq*13Ev zj1;d|y$bn6H;={3jvK&5llr-~6d$Ex=3>$FUdY6}!o1XkiQ}3}*c8hbtr~W#WSS$D zNjG_==s#CcaS6NDGAl$S4J!MlQl5u@*`tO10J^{~KIq#Kx*_}8!1QbZDTAq&g3$Er zjdC+cb-KlwJ^3uK%KH)YlXiHh_*Dzf&sHPzT%oYXv$g^X@kCU-MVPZmX$3rU`qt!198U=}$m(Yp# z1$j9-nb;jf_+a8Mf%}7{t6a6MuhN`ZGM@2Li|$~mTD5>AH=UXt`{`8M)C@EGZ68Gl zOB@$15<(p4(Tv40Av0>%5_a+JPV3c#c*=jE8prc^H}7pMG$%j>1iOL zjqD-SsvH5P5{H;dk_=uv$WR{`zyL`q15ouh4G0YlM^V6tdjjNRgR`&u(m@_6*J2-! z_we&40p~#Xkwe4Le;-~0<>PNydyLDOB7P3VRHSIlQFG7p^TR%;NZq{JX! z{u>;SaUdp**MH(La~{uU-5rCPquN^yg4=Sgr(Dz_pQdA<^whp)5NtU0RnuGhkwM7E z)r#Ifqiog_r!g_Pw(()jRke?g5?VDe?8e&rMhiEig-xk_XS7gUXkz^l6U^`9MO%Y! z?AGrJfcs4BH@z3y4$%kqY*Q-k@r^lDRfsal!+3K8uR(1`rAo2M4(gnRmM_#!PZDNk znAovMF&50LAMcCspqMs%QvbYCvAPWTbh?!f`g-k~Nx~1P?aK#OjS=iv+{xP0V}zSA z=q1#lmZ`m88bq&}g*ekVvP!glCKsdU7qvGeBLjwY)n<(q{%fp>-7xric!$;}@o{e$ zd}EJ^e2{kj{r}U}wZ}zO znF^UVL(WueLUloiO&-_~Wf^#6c_5VN zkNim{iM!6#pF5Ei{zXb@o@|S+$q~}Y$d2pDt(Y7FigUN5HYfj*SgWsV_PWGFL>k^Y ztb2dkYy(8#bxTb3=Z1B^&<5lPaKToI-`X`fm`Iz*$hPZIFfV69e+hzT;MSLXwhNrC zglM1`$kf3@apli?`@F8+Qdn<;X_UeXkpAhj7lF;C0-}=Q~8m1g= z`nE^>S+JV1IZPgi)@GOynf*0`7FYmcO^JND#g}^mGMXNlNZ0DZaV(k7 z>yA7@H}MMhG-3}Pen58cYUNZ~dY|&v)DWe{ zW|^Hn%g?0qW*&RLGt)Es3Alm^=lA%~BfR0HEcy+vrpIW~9+^fb#qqN?$K2an-+s8%@`NQ1X?+*e+)7EL!DQG0aG?Kdxy79i;XR|}1G$n4KqBRWlUwHRg$KML~E7TQQ^|khH6y9 zW`uZZqk3>gh)Ns$@R=bhtx`RcR^Hd6cV=j;(J-1(1F3hFneH{&rWO`mmgr@S@ybvR;GGbo8${**2v~TD)5wE#56i z+mT$3kumtE00f`=IABeaut$Z}hH=ZOTv=5w_v+y$TYZKkws?0gZ1Gkj?MC|D!u2uS zSrpL`1J-nDtcr!Hq^~|@3j@(>y-lwa(7i&EsQeyp0An8x`ks~ZU_#SD zNe_`0yd=EzVAJ9v8qfn#KDC=IEu}>$MRc{gA<9hP4T)PRm zfE~3?PvR-Nrpa4fY|k2M2i@K-c5Mw^fQ4zUpCznCNmOiI>^Xpeam?s%Io$#1&wES9S#1 z*JX6n5J71Sa3{C~nMY{huDZ$5{QS}&OK{Qy5HT>w&N=Bgl>7nqKPPPk&B1`9J!4_! z7+mVGurD^&FVc3zcLdni>*+Z0V30+Y)9A^7GzKhf_2%hv2{sJ`r3GPA%v-qSLr~^n z3-5coJAPU%tubTMVV5#hpLLwaa!JP7J-w``oH|Td!F&W~;eG(Dp`4BpM?mXxIx9|4 z{@YvjX}(<6T=wZne7_1z_YRm&G8XbXF=qqK5kCvCnhi8X{7Zm+w1JM91IuR+HnV}b znySzC=HZoIlklSNX*-ad!4&}ZBP25}wt2IJWvZYQVOh!*yy?w4V(L@yo_e)CY|2Kc zw;+%Q^|0j{WCu3VQR3qPc77wxh!z03bW6kHU-Vst$upkZ^v=o_l++$(sGt+X&R%A( zphaPVa-!!`=2?R|*X0U27z6x#5BqloP0?>I-IZmy!6GVYf;AE##X++5rMZe^!W$ft zE9pUD5&Nu?#tCEDkCn7!RKks9xi~?9qo5m3|1Cbd(b8eXl#{@MiA$j2kWML> z@(FO)(@1hvbpS}#gCw8xPr{4RAKq%Mv!W9wzYeH995o(?YLejW+#8W24-Qz|i&S%@0B#jezujJg4wC-F9ahsv4r+$;$No-?Y zHR}5~a$3$616{~-#41bp60z-w5`n;pc8jH>wv@fUnGSa4VlFHwJK^YjtD$Rb7HxGOsZAzKIaOQo_<^&P%f03$+6S z;*|?OEGNsGL*I4U(*O;MF-dhnRCYK2=Or%S$1WmS+KMB&P|oD4tz5o{05;pMguai$ z>3{o`OC^TU(Q@qv21x?IsWvA7XLh@% zHrw8=R1bKYNF-ibpTA%+?6llM`RMUm=l#Amw?P2-F{);7_KL5fYDvQ6QbNtZtP&%V znRRcW@vc?6cp!F+*4j$k!_7Jyz6ZwOH*HOeFM{WVI0_ge@e0c4@Ncvh0F=QOJ1bPR z*QePPp$m~N;x9nv!?D7UaIq~s%HDpqnzR`ZiJ{s_lsBqVOD^6KO(~8?@+3!9iCkci z2g|oSK&=+jGx8;N{5d)e)mS&6@og{{S`7f0pYRhg z>GW%UK{VGI9G+YY=6V-(dXk9_+Giqv@`dL|Tk} z;L*{e@&OgoFDaR4pMko;R#DP``)Sv0DwG%e)kdH(QVM zpiHI?H*oa=nInIf?fS)a_NFhk2EACNJ$#Q|0JO^Wi}#HFxUXb4B5;0l=0Zt5TJO!8 z`vq=YH-Oq2Tjdk}q!puFDB%H_0|RnOelnZ8osL-Dsjkzk>>Hx*-{-^!gdGT0@w>Y} zaNd8bAQl!eJXwQ%u$Zk6s%J0RB)|G@m#&Vq(mG3L5AmxfyWEmH-mkvXH2~+{>x#km z8Fq6!%^5|M{XxS!Z?wf45fa2;O)$XJg5?oR_|DV!BS+ zF6u8aUni}KympZX1ZmBA&+(?Lkn&c1&&@x0s zvZ8E2u0u*f*@T?eQ&H9<=M)oBwrFLM$oG%y$Sjlr@4&}EmY__vvX!hsSw~_BX}%&6 zcL5n)Ram*M0xFCzUb%LBRWf@pNE44_=%gd(f%J;bhWQwjTBC}UD~eZEX?%zknH8=! z$ZW|escGpG9?O_mScC?vn&PhLf_bsr3Kh}F*eEa{OpYeP9e`&MtIrN>*9mp^D!-o^@>We?{BK(O2;`pb| zN}DZsNAR^u>a5h+%vn_;1jWX#OUbiRW|#2~isHZRvyx^f-C9+m2^!xsHg;Z0oK<#Z zg`lY{xh!Zj-iB|=e%0{J!@s(TFX?2T8UM<{Dy@OGmj6L385yV#-{XJ(l_Rn(IL7z- z!}9D_W$xd7Q659+Ssmin!QRo`0>l^$43SH@1pw^6AMZ{Y{h6^5m1Rnij}I{M(c| zHcL)_s)*NhmbEvo(DP~Hzqj8|_$SBkC#sL*A6?=0IAwDS6Q~cT@mD(0PoDgjXUi*` zl020!xHkKcpI1VOOWIuc_`o3mH6R{O^Iw5{+_^}7_O8TV9zxEtIlPzNA@_U z@h3Xx)}Lr%i9C*=;l=v2gJ+wCWZ^)S?2=tPSGlOn-@jL>@Ewb25`|E)d{cPYFl}8H z&VH~{7s(ecDr*|85w~sJnMdSt?^HMag#F~5y~?xpxra5m1);sl^Q>dM#^w5GukxHd znrjNBIUZL8yC6NTFqTKH8~6z!HyzuLMTA5iy7%%2EB+dMtLY9#PkTq>zNQ-r|CAX1 z+CKRInEklX6wxv50qS*kCqv(fzRxbDIzG8XBky)a+_t~oe9$MKZDz^KfZNUdY}8!4 zS8;na`Oe_7VHy>$l+L}%8g}}y;LvDnm*Cst_2puT|>B=`H5n=j5EtzMI6Z#vGLV5-?VXF%SZTJJLseI zJm*K+G0~AYn#6EWn=BW4h98%X8SL%h88L^kTz>R87U$(mTbRv{GT`-t;lv zXo2p6^Kg3UG`_iGoL2}(3l3f|wu&W{vfwcD$CZ=QP5S3T#F}L^R0$j9B)RO0FfWIv zcIWW9opjz-xw^!7PLN-2(XjO;#tWy@r}6zbK1pWMeR2+uUd!Q=J7d&6V8O?O^}|0c zhQF>4{^E&)ZB-BHWtMZ`uyL8NbJpS1Lg6Lm+_tDTT`2OGjvi6@vXn64M(5x2KdOf%=W_XWJBsS=(Lq0$$PGIGyR;q4UZX ziM9xi0xtE?wh^HnO0Bw0gKdwf+cI(7R&|>e+qSFQl0$T!=y1vf{26tNDI`Yx16l#> zhyS1${`x-nQ?KaIOAn|$Yz)q97gihqAGQL^nDo|+G6v}=y`uAT~ zY}Vgxs9kwdZLww;uY_E2nFQBu!HY`%0&Go{n#;AQ*eZH-ZN4Rt1I7)`vGQ+XsRwpDv|ts9CrIH&T{y`L4mhXW}iBb+9)osH2$nNv!>tENra?rlA^QVyNBs_jy;&_ugo0n*G1Bq z{ITXFM+2d&+e~-pJ%&(2uS%zPXY+;3Xf0Yfwdp&dD{Yy3y?{-#z z_m^2N-k)Wo{1|%)u*b{~^Sew%J6MiKW=@thO1ALPosEX8!3CXFtwR+(d$n_2>zP;Y zGF6rQHT08AvEcH#F$X-d*11jjaQ{K&gZ&o%>kj7nEOVt)sAPD9C^tx-I7jl^1*igo!$$P;$8aV6&(a6~-)-pC$~0 zh~?HuCFyO&I{wQ}>g#=qTOb^C8(abUJ+x-H^DU*Ycq;dI7X?b%Ckr<#7v_|-i<+Qv zffX;(Oh|92N-qc`^1rHjzrd%jgTAL>QeS*7eo0&!9H8o3KHbQ}Rm7>s@l#Q1@sp}U zC5(SuwO$?_n6cP(Q{$`Mu14(1xw>)%3$RJw0#c`Z62)ranWGq z<9vaSJ03%&_B*KT>_z2gDk|GmRGw5(vB;OFyGn~nh1E}#H1et{!99-uNImKoRe3v9 z9YbPyjK8t*Y;%@)0()^m}d$xhcTD&uQrU{bI&57 z&^;+(WcxYjp8T^n`)U%#P)v{bk9Bc9;_A5=`i%b-M-qp5!}l$RxuNjCDTaUIckqA3 z7vr!`_YjAz^AY|=VEG$tx5!rT%c4ES3tXk!mC3&;sU-Oc=_x<0^4oWt*^BQsYhMJ< z*Z{sO565WEermY$HH_$~+;ol3W;l6?%^%~f`Hs9Q z-n_XY!S2$u>U@MpMdmJr)dP`58`EEJGu~@akTKHw(PoSMeB@@qTRN4ebz&<<{*k#eJSQ`@bINoHwT70uWJGIQ~6&zi)x8; zY*&8r8hxHuo@LvWNAIMO`~{@aqc%$p_{Vg{UwbotmFZO@`d$T^-+S;7pAO^v;wt69 zbo$(f>r^RqcM>1jT}Ah0g~wvxzWR-SC!Q7KpV9#0_`7Tt2XuRNtmJ-K1}l&B^xyR~ z8j5y5%msE59@+BFjU1TS>pOk?(^sET!cy5~?ewzC<@WRjmSw+ehQ;Q#c`j=tAU_Y5 z{uP#$UTXImW#$mGw3jq0;@w{{sc?~$8@+Pm;M&}2S6)9TxYy5UgXO166i;Kb{lPfD zKH|$!(Ts8H`&Fxh@FGvs|6t+mbwQ$>j9$0#RLv3N-}eW2DDq{IZ|Wu*dLA}UrR}_O z9@fpkMgJd+|Ew7Plm-yTfAb8x^WElx7jxxzn@7Kx!Jq9u-^>IWWA8Q(Bd?3!<~@fhhzJSmQ3ZEPRQ^|4RQgP ztBf0&vB4sZsxg*Ahf{?8CFw$;lnX1p7HtTFfc^&Muy=z}Uw^7O_r+7n%loJD&pW>B znIsgEF{FAYPc>_j2iKC7YFG1C-tQnPaFC^sCs2JwcL$q?y>54sfB4M~;z7&-{bc~Z z`i=kW82*$75XWD9y+}^aD*TE@m(D?>i+bkRm$|#YYn^K(XaM$8;Go1G-n*u9^IbxdC%BKw5|54_Qt%2T>EvKg^@x_XA(^Ev5$U-!UEr+Q(=tt+Y} zO@g!x&m!{Mja+wL*b$%vAjq&W~K7~QmuRVBYJhkIK5Ra z(Trj|VVx^*i!%p4qSB7^njyOl%KqhBR-3l?R}=)2d_-r48%zJoiQ%8t2me35X@Cxu z$oF><5+-=b;Ipw4#uf0~GCkuz-dq$&<)?duoXyMBXI0x;wu3*pZO&b=CoPaT^NGj2+4K-|$Pb;Y#pgpO z_bGSJbre+bts8-|p7PhG^3#f2cF1|MK{>K$Dt`#S;O&Am9JsH3<9`I66;DiQ0P*p^ z{5196@{`L?FGsI^e=b{nrogzu!&gDia@ow#vo@EIG$;aZ-8B7?FFsTL%*GyADCha7 z@*1VMovk1&z&9A7DbB_9z?CiX@>7GHY)jrA$wwGx?>(s`m!E|mc?*BNi|mIrJ|SW; zm$Z&!RV7t?+(wqWDwt768XM7;0R3R$D|vzK!%Kd#t0a15{wu;SZ0@w`Bw3WxV1u0K zJaYJ_L#gGn&B?-&A*68@VS9~g*X>g#3kH`ym=>_`zkqWX&|dAPnBCax%Pb{Mr?xh5 z;qUMNxjBYEr2)k8&)(|^>(o&hz53cw!kj^ii(yWP_qDFR)xfmys}Je*tH&fMMPbeS z8EEdzk+8gXXQ5lLPo$r-pN z+i?pY4vs?d;x|5_#mq`t$7t4NJbXpCb2s=&jc<_*DWVZ0HZ6;2%x>A@=(&1dw?1N{ zNS5G~AAMxpBUAYAdmyJ)qIC_pzA#o^c4mi6)&bG+Kz{X;|9LU|DGeZwzi~@Z&CAe& z$xh1JLt{3ioVPbB`a;5CP!@9YZWH+)6$Nj|vB!!W+P>UBD}dY)8}aet%)9_e)soDj zKx1?67a4LR^tFUK$n!aGHr>WEf@0e*wAh#}BG}%FNQv#x?H{!{_u)QD zzH50D)w~Xh6I$@g3ELv+dn#xSM6DB z;Z2=yziPW&6#g(Tdj=`l^W#(EPyrJ;VkKs>g0CD_@50Vy+5iw)^j4J+1*xi4I zwiL^*StzrJ1vNk8_}5CzlS7)dhfl9UPLCuwifSvu46^kv$K!rjU9UGcM<(Ch6uuc2 zy6+B>x5lhP%A*){u`82A*Y#!-R0?GAzfeUj6b1TN^Gi~>rHd$wMlEp$!gCq?3M2kP z_pRC_kTF3^o?j^VSW)U3@&z;n9{z`_zBx%E|3raaiZ()3w|^-(dgD)X@TAfWg?~W| ze@X+0B5-TRIU5yVd_~1pYSHx0>7N4MbMCEP6^%Qr%_61+_XEFYV6Dj zd}DM>n8qrdLmD8}@X?v8-iTZMOd`*m1sb3QHD;8Fqkz+UY{w&}L>yTx@Wv`PsACF$ zR?R0fM+9wNO_8iu%y#BT;H#t5BDF?mshs;d$1))|yAax?3BRIO?>w3x%QCQ& z*3#yKw?Y%kG5|f6PvH&7Ft{0+1*yECGrv}lZz%jn#qg&zfH?l7s}=L_S0R3?)7;WK zI?D^8m5t@CYHT*EhV1DrB_4kB`l0|lD7({kQC`njJ~XP8ZQ!Dezpx=YKv9+7Y@pl= z_fY{n;nQQfoH%wdox4cZVBETGYy`B%J0;Wt<;lanseB`H3RIb*==ZN1BHZ%Eb^DL; zg;n8Y8rbsr*X_2|z*!@Omqf2-zqzByz;ux-TEjbZUGnIWCtxgRy;0@aYM#Ouwv`*hphTy3A0yW0VDW2y?3>zP6Nctv)Znva)NO zmb|B?@E=2?A8XSb!zhOb{!yFh7&3m68=I}kv_*1E;nA+9%$FisoiNJ7#~~(@YD-gd z%~KuD9aA{(A`Q(0PPDmH0)J@gIvy!a^tEo^kX9psKBw?caD*yNe!%#=6GUq<4>ra% z|HTmp*&F6HXDZ}1jcd-VftPX(Thmw+@T-{%$Y1dlA>EI^)I-E3kHFiC1HKZ@3flWg{pHbR=n1Rr=pIWS}kWgWDTvHV5UqkLd7xP*|9Q~7yb z;N#{gw|%T!^P0h_PQGf$eE{1H&U-#5`7Ss_XegkxIgD?7OXGk&sEui{aZg0g)q5J? z{TRTne)eA>9v1#zM<4vrzuNyzR8EkF$cV%xwvj!|%XfSk9GjieJ|zlxOc`Ia&U*%KZA7%A7ZyJ7y~7 zb7m^DmJ@}LwLg|`>>jK%Sc->hay93)s9F*w-Sod-%C4d6h7{Pgl{Nv_@hL*Rb_H3t zGn1d+{68&#-n2OJUT!IAEoR12tzRQ$t2v>uUR_ANx||`NwjMqp z-yPK7`;?}X!oxx?9bpJ*N3{gSFnt$BeH9W$WbZi+i=OchHj)GY#>F8;kwOX+LW=QZ zO}bFJq*PycSoI?v+xSUl?A!N|Ju=pIR+)udlTEj!`Lk+2MU*+kKUitBIQ^e0qVTD5 zC7c95q39P|wCt<-&OPf^Okd&SlQ&Z=inWg4>`h-OpH;RrPT{w8LX#9|yN{3BoVHt3 z%+mJsAI$Ky=53C7utwnMl$sj~|1mNADGeZw{}g^p=i$tf)@f`L@-%PS?A-n9JD*JV z@l5oNSd;zq6h5L;8@LEm(4S@>A~-8AW!Dl?ls&zv*Z{iOpNWj!MF!{1$~nu7*1J8> z_R8OBoi3eJu3%(Rl=b|}E_nza*GV+uk~PjDsQ$`Aj(`(e^EzqYUpt~XMYXCHsCpKr zBOl;f&qB0-EC5?j)gHms#XI}@ph&xnUJW1ruGfH$jq@b3L2%Z*?|Ll{=xD_$7*3kTHp+9?ou_=Dx=PPJ?cYPMz59}6_LH0@fJmVDfS!7 z%ww%HHl^%#?tKE(c%VwtvQEt!M$WMP4D7ipRc6PKuW*JPXOtT&vizho{MAQ3NaFJU z{aQC|dU8g?mHh`8)`mJ8hX`5 znRIr<3DgWRE#G*J=;N!GvvRaYp;Y}z6g4` z2wETslNGSxiWM`~UK#QVjq`$ljX&LmE7-sFAjjgvs&C=C5BN>^fd84L5rs#4Q_1ar z$%MT(0@1E1intdU4Erou&Kpbr|6UA#N&|@F|5A$%^0~~C6(C9OmbJw%z? zto8K`+e036jv(4HcWwR9)}6(*T8V2}dTFxX92w5=9lDCa zjZgC}VZrgU{~}Ic%p&c@dSm7Pj*sC_X#jEjsj?3dx9VK@`)-HFW|qwmNZN~SbM}1! zoHXCnm;}UE7d1q4S!>HW>RUn}*1z!kJY{gRT+K53*c#SF5w&?VK3tenZ9;c7Y5nla5L=|7v*5qpa1Fk@3 z&1C*VM5xpD7*Lm{My4glGUTmI7IMWBHN zB1_o@dA(eXp7%Mn;@#FFvJHHi4ql_7KgHZF$vY-ACwh<2! zNXMfquE7=8;EHRmU$H_KoTK?=HI{|v0Cl4)2JEY!{x=biih)RJ0CD`cD-R3zD3aZD ztOW0ZTj#o}ddg>!l{LQnHQQJuf4x@_Cth zdd00)gGd8Y@~bw z3sFHWt{~tFbWehV<-l8!=>V4ST`U^S*D2n`KK=mn-X)Cl6ex7=%8N>4BhChWlHZqX z125tYm`xB?z$TC2{E6JyJY}f&#)|(;is4Ub0CD_Rf(PD*F?~TWsk+=E(zNFsk{7{W zzDV_}Eo$`2i_XM;=VJStO^exLAWiQvq#u=0e{27+*^be-ROJoHJ*4lYLT}jYnas^S zs41`${ZP#>jnISu(S%Q0bMkwR?aFGw9+=E0cW3P;tg~rkyJKS-c+X?UOviA4wzr#y z+f!?<$ZO8LjB{h})u6PM@>aa#s-l3*|53aPJWH)tFPX34NkP{m8EKZsBf7-4kX=r# zp|+_dT)iA!F<@W)#{XnID#kyh0mShqRMudumJ7jVV|}*Yd>xrAAhSWR0hzyFgAeuc zZPI>sZ?6H9*&2-haPj3&!FLH6qM*0XuUln8hrZG0J|NSJ4l?vc@q=VjXkwgXDg5!< zl~;s$D)*WG9qwZ!?lZ3h+$Ra#CsU2{q6O{SsMoOWj&D!xVt_cqKz{YZe@YC0N&|@FkDg*=ldWl_Z!|LKbInPnnD@s< zO===V?A81W5A_?4zGJ1zRg=NpH_choh&T(7LdGrP`>BZU>!Cq9Ym3{z{IMh9-p;Bn z@L|OJS>o6rTRn`H+N$5P0HMX|hos@n&qEEChx^?xFs~KO*&a9?NGO?kw)ia{8 zHBs-mto3*<3to1tzNbw4aqfX#YU2ke}(&XZ^_tFOl|{mg&N9%>9}>Ul^Yx zx2kvi-E0Ax1B4-CrRVDU25k;SA?7%;Z!G(7Y7Bo$1Bm0V(VCHk*O*}}72W<4;S;T+ z{PQgM?SzooaoguESj?F8a)3}ygWD5up>)h+x*UVX&ECi7je8r-%V(h=u7 z91_Og)7SE9vSjCO7yL&l{Fx3jqWkCV8j8olVqgzy`6CMDbbgHp-v#!MYKX1;LXY5R zd^L*LGv*B{^zc9WsFgf;AjCU~e>el%mGMG;;2qeO66BB8anYN?y}h#&Fy7$n8<(Vf z?|5ADaJXtnK_Gcgnry>;peqLKtKayahDQber!;^#{^Z|#RMq%YEB|gc@EdbYtgVpq zYR14npTdhfG;%Vm{MbApl$kpcw&Fa@_fQcckI|Eu6PSEP-B+LMM1>7B^ptC)4>(mn zk+Y+y)+}Gg{vMSQ_%}Fv?Uff^{^$5td^rl-U$5!>M=j*nlJ5_i1nw2G#r)sv z3rzfMcm9sZzH7m+4CpkV@f$DW(y&{IUG(?6&@8}U*^r>%Q-gjfelFSA0 zLm6;&9p(yWVS^N#Wqiks0Si7JtRMa*G5jeFAdY{^M+S#ZvDht$mRFb9KGHeYFNsPI z%>NtkT`4>HvYvEQ?K*j0)GK!aTjlz!@ayXJvavG#xJCY>VnhTkS}4gLMI1Uz_Bni1 zH&8K{TQJ9`CRn&4nqvqnm3*ZbakIlKpI1bm+bdO$TZMd3ucmj#cPC#Ty-p+l^x8;X z>Am)69se)azDvD!0oIW?*mh!ZRsGZQIvLeUni~rL=`s8%4IqxcwQb0CWEi6EE~5!^^%^k?c-fUf_nlClntf5(v0yTPuR}A+ zyz`)v=Q*gjytbe)%Ge+kSb~_a&+#5Kvk{-;IFp9H+ojJf1+5`VAm5eVK=VsEk?%cZ zsSzB<7|GX2az6h|*{k?X6wytpvPRNvOEPV3feQL&Yx_U*C0O^9`G0nNs@RdjbXwV9 zUvbzP$+Vdxse-Mo_D<&9zG$yHXZa}1S&seeQzhMKafuC|Dz!$t%Z9sJsooX1zQa48 zvYNX>Hx&M*G5jeF;5z=X-YpM>sh`g(>HE>=3wrx};RW=fxjj>3^3Rgz%AYE!rRjV= zvi65~XUhrvE2XTR!*`shBj2$-pIsK2!LQq4IcLE9Ekk}}Zd+gJmWzSxA3BW@yU{+G ze2bYtv$mW?L}v8wJ!}Zzs3n$kQ;UxMK4KRp^CQYEwN867AKDRXDWAXIX$qjNm1t)r z>_(m7vAYb_=5rUD4I8K>s_f3^zwWe;J%VS%I?U8F#H-;VRt3@5N?sbH3ACmMMrkLgM&$wJR`712 zcU74@$;toLy%6vFuaVq{@pk><&Gk>oTZ;aq>~LFToosl|+J0&%q>q=I{(>(6GbuGG@|;$CPH%A9SC2=LzNA zWvJH%x4%<4ih2C4;P*w|gNoaq6g&#;N^Fp2slXOA?-s!I;h_^=1=l}q5*)t=*MIqQ zS+*4LkS(D1-{kVNzEmZG%NZ8~vVGL)`;DPUPg}HGk2k9 zlm4XCmbzr)Q|bJK0-Wu+vWb^PNm?Yd?WiPaL06VMkR5sxGIG8y7v1*!1ixWN!Z}kd z&d8X7b-r@JMaFm7$Jr+ zeM_hr?_MZp@EvNqW}cWp?V2w$(4A@sc{eKo772|(AKH~VxGW8#L zcZYqfeX4?$I#}YMV8Zpjeh+=kT8yHuC4o)imwV{wdFbuiulM#PbxaxHnR})@MhB-d z2qiW`Gi+T`i7{8!FDXY0=M-VwT(p+Y7c1qmz<(7bgze5UZZ}Tik6=xyn0NW>Ub!#{ z^+m?L7U`5?6vbAHXJ-?tg&W1Tr@W_>ts8bXjbfu3nKZ&{Qka+O%1BDk*sdvG6<#Sl z6t)yR08jM(h@`7PI|;nJQ*hlEvJ|Wg?ZK5mt#(_Z;25yr{j>>aRel`u14S@W}TdN<=I1!2;qPvI8Lb%Mg3w!uQs5^ zd{vUe$*Vg_FZiO%0w6*QI$J%!4Zu)HndVA)+-^|=@*)Qj!c8F+TpW-tLu;zBccW<{94#P3! zo>t4e4Ve;I6>npT^%ZR)M-w((;@g8yu_9-j1^TMzTb;Yv9FSc$a zjyPan{qVmHj|%)L4IqyHr^pziKIPFLPU2U(ALbe+mRLeS$_=ELQ+fhgp0(}k#k$@RZo~|~ILkq2 zP2!(+)4dfF-QBfKsra!=&ciBH)P^R1I3$7Hc2TK-G}v<&DoS)lSeu}&xo4G9&xzqrX#jEjd(o(S2eUOkx_%OWrTb=BV!j`|W0niBh5vz|T=DV6GeYu$F`ffQZDDooWvV=T{te$a9btmg+Yak}hD{OY4PA z;zzC-!NZHN{=ylBfp;)mCxBJm=sKxEQ?2nJ>69j3-b34HMK|Pq88i)6ARJqP&IIJU zI|%>Ij$RM(iB0u`Fc%!*4zx9uG|Oaz#+kt<;ts*&T=t-__s23JY~t&$G4%;&9o4*) z_ z+$5~b_x3jY0&O&lZ&R=9tB3UV`g^@}F*s=2M|cv)|7|Z__>M}$bgDPOcb{qBB<{X8 z!fQn<-(v79^&YmW_n?mL)~&a%m-p5UlLyHb%n8#0YFVw(prVsyGwCUKDl<)E9kU?+ ze*oDtY_&rsT@fpb?fkWzjCm_BHt!Xg>#?A4AoaznCa)2GYr$Al-Bihpt=8Piw>8eY zLDQ+Cv2ERo8w&rj82*$75XWEdC)ud;52<6V){&xH^s{X6P$MF%hKa!;b*Tr^VOj50 zR?LeQd=G0dF5Rywm<+F;hzcwXxcix|;}~yy6pj6H{2jpeZHjOHS>@4RZ#;ZaSv{84 z6V&f6#B6K+=wL<4{61C`)Z`8e&bllZ^1?I$qt+ltWlb@*@E~m;?^{Bnd7K}(O^fhK;(yJJg`Npvh560vU%)#mSMXp?e z8j%W_?Mmjq>bltcjOyLn=hGZ8?yPDm7sJXUWsY7jwe9RIet)taM$R+(-x zV`Lgoy&P}@RdaKi$SB0?$_kY zpixsVjb80M0=f(keXel%wkiJ7v&x2F*B(Anc@f(O?yH~vHy6(e{l6F=@$tW9ETSY1 z%I(QU4ejPWWAx_WZI=aeRjEC!3p{h6WSKtTpXpI!DrUa7LvW1>nj(Tp2qPX~rg3}Z z5+N~|f6;mLQaVOs4`ROtpkd$txa?1q^7|{W2Af3N2Zy!$G^2*8#|Wc9 zhXJu6VKvK}cIEC@GQy9`bd^uR8|YYL!{Zp!WD`JB^jkrXy{psKsCz-d#=x{I6JIg& zvW^%9)A3(jBHLd?Wx@{_W`w;UxHsUNi1k1jG>RQcxnba<{}1&4c`^Jc4Iqxc##M`T zmp7m%f+yn9_k-a{`?>!v@Vfs`qz9|XLl*KFQpm2O+4)y z?IG+*^xF&EHtzDAwpyr;c#36oCaO32g^Xr^dm+XnCQ#%*EO8k&*oSH8+htS&n@ zcb#8ZF@$^&40XQSeVA#aSxjnd)+gQU5LO8eVTHy)dwn>nuF^NtRXLdd5u9ctVt=_9 z|7*Lb{T{S`v+G|%x;k(bK{u=nE8F5e;fsci*7) z{l@>Dcvg&mN&|@FU)=r|^oC$RtGLlKg6DLrAYrX;(bKMXH@1%SVqIWyDQ5BC_@ktJ z-8t&(Bqah>s zr)G`tC(KX_x)wBb#h7(qestiX{}0Ch{22a}1`x-8uY#4`T~mVK#IWaRBwH|&jH(@` zfgLs`L_H-qg{&dm0vSt3kLYvsT^$%r z`+;j^@BN(Wj@f!Q2Zen&CZQQVWqJa0N6g;iM=vTyf4QvNCpeHH{E`n>c-KpJ#Cq@O z7dMvtzbl46r2)k8XVQ+Vp}A*<|Z z|9w_U9T52D+|ss7+Ha9gB34U6O@DBR~9W#>a_`%btTnm@|EDIVb<0; z9^wUs;LI;5VMAUBTZ&!q>=J+2rz8b%HRB7BN?~SmhSwwOP{sfK=JfkF!B6O#o)R=h zOsL`zjnkZim5Mo}cYdUpA|_TWPjj9@J@Vu51Wv-7|AO>5?%0ZZhrVDYo8Q6z*d6B` z2iwsV1NPOA|KE*A1^*|fR~-NRf+|RQ(Lb~GIYewy87ePc)>eDkFDw!L`-i2X0z(v% zoo5wk##tr%{z?4bl-n`e$6boi+-MjP+}V_fzJ2ybY*#M-RITTKAcTn0jPs}mNr1n$ zzRmaWzcpM`veSe}l5vDAE28<|8df;;N&+NK_Qr%rk~z?D97iR7a(j4?G_$oG+WiR3 z@Pm9Z`-ovU=Jhh3mVj+WPkY@GH_h8GkUY6Z`2?OkaFqH+gB=_q9ezc+kHq(LvHCB? zt#Z^mp|+*Ugm6M6S-qQ#3+-s#Y=<`)lLBif6?VYB`r-e5JSy;~G=Mn%=;5>~%)mrA zIlNM7ar|lDU&Gv$mMvY5#gj0&02*i3}hyNU2d|HqM*w z(tk8`>~C>&(}e^@#|+_2_1EVYm?qtwhb>I1Z`m<=toK4_NoJ*#09`(8{H3eV8@wR5 zuSk|#D^q^o{^M05M)9o}w{uJ1ZGS{tql}ZpNP^Doz0K=sy;>;brG&PY{4Q9I>>y_M zw0`B@P%_T@%7p~vkC`I3fHo%bvr)QlF}$_pH^FxGIBI$4=yBdXp-&XIr!sRHw(4+p z`;CQvMGSumdd2bIR^s;hFL>IGE6dffWpe5w3C4;1r6`b`_O8NwwvX^_?a+_X^K(B! zkGVINOuMrB6I}vr|umP-bAF+dXcaaUy z*+qQlYFDrPHgB)jRc?`k&DuhFS-D~y{a3@7pynWSK~u00)I*ah~qC5HdbQXsQT~_J_lC38yfz|pmkr& zi?4&l?^dk=3#pvXAi*bKraevOB zZJ)JQ6BQL}tv3@>j}G8hKm6~B;ZJD*ar|?kiBI-;pmk5=Uv_Kq1;khk;aI$Ua&c_? zAG=SJ9~~$GLqkl59v4Rsk=XMOS)NXnQ5Uw}ddTD_uRN{q2lS+b3asxJ5zXeO-0%mJ z1;=(IJdN7h9_!wM!-Z)3O%IL!=ew=#rv~9yF}MixLEk*RU?ShsO*y5^aTb|G+nPk1 zWw-d$F;J^cqVo*Z4xnw^H3a#;dzClApJswTHI~wqC?DL&--}+vnZ%!(j^m8mh(ncK zc?SIH^y~_>`e65{x&aJ-|M>r+82*$75XXOktXI8cqjr!?y{|hVP=49SQi8cdM%5+p zm#(EBAB7l=6E&Y*SLa?EwR>lY{erbFPZoyJ@waxH0;5!kJdu|I!}CNTiTniBd^z}S zh}ptl(@C6rZzpl?-SPOnI_7B*;sL&Kn8QT?u)(G4 zyy0>+M%9a`@wZ@(4dR;5UOQ1~jz}W;^dx5*|H(D|YnXvijlo0i){WuGSY`L`K~3%P zrZQG`D)zpo>0$QpDd6dtg{lrCR+SLdRV9Y@`T%JUG&`jp@tO_wR=J~6lvNEQi+Ilv z)Sbk1jHEs~#_ziO>KI~!SYLmFc+J14d}rzPCpy^n8Y=#5^3i2a$yKuBa7LX3D{f&UMd)M2{pv1d&H7!+crDEgl3qR7ZwyiU-ZKU+`v1WH?~UPK-UokwNvy|~YTcEB%N1Hx>3mJa z0dm&X_I$bVsR{i1-I-ycghJ%wfEtjwFT!riIG|>RRY3c;Q*|Kp?FYNA{;czb&u6v^ zD<~7>*PmlWKmW(d7U4$Ibtdwo54;Be>2g<1s({QeR5-+2*8igV5qqhv_NJYx=g| zt|SVdz+0~o6dzt? zlvtgBTwILmRvGKb?JXz1+tUdv&qTaqmr@CA7X4K3wm1th-Xoo8XCckcRO&3J@!y#c zDaCw59KR>>9i2v0r5J6_gP_Z~uo0S_K3Mu}0z5;y$W|OzhvUvF_Ns~emz}!Ec{W$x zg5MSR{nJjWXi2xNMgDTlTytQB^Ot^0;4!~7a6{pLUkrar1Bm0l#%~IoZT`6@HLy+j zFJ#icxncspm!!Q-*VeuQymc=1>56p|QTIDY?f*kqjlqgN`{u&evuYxr)tRJj-==(^ z1;%re1Cq1VpAv}p2jiNJ+BCessnxa0?rq9hWDyI?Ch|3%iGkVjHYK7>cBW(h-?etU z{|!eyfTQ?pu+2J$pl&aH?lwh)reSThAZN$20W`G@HOjZUc(S@)wHUP35VtYbxTIC?@hV9b#Lx z*VMY9cmu}h+a1!d*{Tl^DB-+gIM1%G*j@wvLDgB+^SZ94p!%9}%H62X5JSlRu-8Fa zfXmg{x_s->UJ(H+y!$UgRP6!nmVec{F_SWyoLNz3SFjL9S1P=I=GCl1Q zWsnHRDrYLGnJ+|K*qV;dY?b+BIoe^!lo3hxVOciyMg=ar~luNXNCSxX#jEj z#V7go5puA7^|1dPT4Vn|M~f;52(6kpTDUjZs=aqx(9DpJAU-A>y7#iMjK+Tuk*YM% zs~a336FTa$9s%^47%Ch#{SfgI@>V^ftl#ZHhR7h~HVByEZi_THJaEzf2m1eyV)#=U zKpcNaM)&Qlzqy;n(@|Jr%zu0P5<7k|V}l+!^{Ar6sA?pyKRmiyBzSxtgO3lM{OdUs zZKlVpDi0PbDLW?vJ_8AT{A{-%*LV6jD=52MZZ8e7+>+3W;o?DzSd)AR@)_EjXtcH& zevX+KkkPAss^qu}Gfw34r+QE=>dFhb;bDl$fkDb9WEqJKCt%5qMy_}{#(EK=dSCaz z`b^g3CI>geQ~cD?Gsp#qWifrw<2kC`{fA3*MQ9H7L-?xbIhyY)EZ`YT^bGJ*`d+`G z@c)+>{*(p~$DbrNzT)NPfOaY!mO*krTcI0|pD>d-gP%G>~)|=gF z&5X6{JHaBW1?FT~@68v+ct&=G)Z-l3q8z!&H@>QTeY#lW$?FWo+dfeV`LL7m`;|t6 zJ}6bzl}u|W$#f#8K~USdPOt5YrmRC2d%8QJjgv(*U|;?Ce24EM{xMs3#l1uYTkIff)Xj1`x*|@-TbbYLfi#uNIz$_rwoB z-u%SiZSro^SqLL<3(>yCsPlvV{4=#S%zT?Hh8N4R?<|WsAiYiE?&8ZP;nyu@O?3%t z{gqGHjo5oiLW^10rsPN?WzFtwO17lkt*h1@*rrHQ3C7?EjQ*^~ZHm*oO>u;yR}b}^ zoNm$^LNTg(5jjN*U-3(KUW!rMd!6y^YujhNGUpOTwsv=kJ`}qX)S%!_j$fj?wWBgc zkA0RTzqYWV|wf;qM>+eK3YUr2)k8*XONmANm|19vth56B%rsmcvQHzbA1QPD#KbYLN?pyyQGbn z^skn%eQU2o4pE=ee%f28XflQDTaU3^I!o>Qq7=CjdYHuD>=U2)GvYHotR*d=MnC|6 z$LuUW%T#%MX zO?FczxXS1287$b&?rzi|lN`XA_u@S71b(c0MW+77ivKQ;;ZJD*ar}*tk?1w_%mjXz z@;tm-ARBe4>WaGYtsYyLwe8Q>{V#FZu)ZF%0^eOF_pbV`U-ibv&1|9X8~YZ_AnC|N z?Zsezx02Rk)Rnd*h_jI6l?4g?f^%v)=GyYa)JldjRcb=Pt zvtjumia1NwI0o}V<@#|Iu{NM*D2+$4b)DL>unsL>|239=Wn?UE5wxijABiwcM7`n) zW%c3f*HPP>H56SjU|;?C|3i3G=zo+35Xb+%7Nc;ig|T0>2<+TP`Y@q4h<8LU0-O3v zcrPN&>Nemem}kigWUVUOPc(54<6j;jG{1>gi5fr=cac81PR2Ytx>!&Dp%+<}eH1OM z2D+{WA$$0_av`2RSDKcxZ0@sIbO z7$3<-wa4zJQ6|Y+(843pnXT^ff^<2;^tA5!7}RpV6CM9r{JSq|y#D=n(F?sJ485L0 z*GOucwQ72VY3nk6iZy#DH_-VKu5f?UeK>xF+Nj`QVTQE>2$vXbjXToIY0NbH`1QLJ zR=t5dv-@LrCpd`O261O}NQ>Syqs55(qnQArS09ObarM}Dx7t$d`@dXo3G`!DTN=Ow z&=3EIWB5}VKpcO@ncCAt2U}#F;|TPp^ajzPL%+87pzq5uiq@}s1LKMzTQ+$;FpX`& zFPVP*Fk@Hou1P-y#;xaE$j2PS|J37Ak?i9mYF%^ta{1wJwBmD^E!u*W9y3ixv1*&} z36uUE_586l-+lay4_af95!pdWvIV&%i?NoEWQ63F-F%#~^N>G>q546x`mCm7cl&r0bifOGLs?&^Ba$Zy_MAkAisj8%r|I&A)@`8Lkl9b3I7QMd3 ztQ#w*o-4aNH0h#JDw?Ztm16k#tBnUR%j%EZJmK1O%=U;`7me()nT<^+y2=h(TbIv1 zjTo{C6#_>hiHTbpm}3HO=$r+tN`TCYE>!CEzg~?SGrG+N-zb4ipJ|%F7j@|axZe`P zp1Jb2redS9t`u{Mxp@#Xh%Lvp>`tPI*+xw9LZStNN?gJuH6iMeX`Qa zk&(N}rUdF~JnJx??WhDqWG&l01eVp3@qF1evCX&iw{2`%TPXJ|@eD|F9cGSU@V)c5 zI$nsR+q4N9^ytqUV|(H3x5~SKQe&n^_}XL=xFVx;8XNJ+jX9 z<+5f+A^#QXirLhCikJCbvqn6ayHr5F0vjheU7&}P$S07HAT~?=?g9r`bb0{8-(UW( zis4Ub0CE1m=%gR(yp_v~PI}r;--jrhMsg%(Asf^0<};!+=h|G^gAw$bP8va#^B+)G zZ0!sQ@T4CU9G)FlzXP z=TNt9M{QEpN2pO-D}EwKPf&G?;Ff5EqV3uF+OTy;T4iP zi{t<%fPUlukr@7z1`x-e*5%u`SWj9#^l9of-GP_l8a;CR-yCL*%r~#2xz%W#Wigr$ zLXY)Rvr_p1;4_~AtCd?yrUXx5)MX$W@IL#&|4ZJxKu1+x{ln+XoSDo$lMpZo37nZg zm~iXlLO`WD3E>b>A>m>JA`TYqV9^HD7A<|50JVrfC)`XBXlT6zC77W01r!NtZ4l7} zP@|Q%WBXRf(6@aONpf=ke*2tE2uAH2Rweu0pnh1MX(V+6p8O z?DVhzeMgijUjUo$NJ?YY&XTG(uPg&=oWL!srfXT* zhi@NX#ev6f%w6#YsvQf@6)IYeC0Z(oJ5G6{p@jcqD*hA((1(8#uORAD5cL32cQ2yT zf#`HD4v5|cL??o7d7C^LIemoa?Oxlyn^|d_IB^0Hos6SS$`kFgXDW*YYjZkV&|Y4Zl4wyP34CXKeUSv(AmXwVJSnCC zzM$TfUuxgj!Z-KR&zv8kzOPvqMzi;A3M4)B^YiYL$ood14i zAj6-s{GY*3R#QFVZUlbS8B3#wTZIa-;CrbCawGJx)S`4hko@m1VZQ^jwEyN(*mkh< zuHYP!ANn#yb|t1tUVL+7g~;XA1#P`;oY*+5Ejj&G{AeypRyw9a=xf(%zvEKc_5XCC z_vmfcZdj?MN~>OmR(&UDft8xuYo+eQYEuu^k5q2i=`r#(*Tb*>~*pJO>R zr11ZRia&(`gz>+bWy&!}QqV4k`Q50*a2qnF@(_U?i4mSUn$iV__adcmZuePZ8eLK5 z&_3tz{nOZ=kd2M~x_^ajGvaf8^{};h!-K>V;>n7^9D#Jl4gR1~$;HGjpW@d~hfi+< zR*W$*am}cG+ow6q@28A|2=oprv&^LijU%h+pM^LZrK>Hc=)O^o*)s)Xqw``p&U6M3 zUN!Pns266FUTis?8r3}gXTteE;&);_m#hzR*o!Cerb*M-DU4}RGopFJ@_E;$-%sA{ z!TT9t|JUMOG5@15fH3}ocN+T%u%l7D6^LQ1q-5!iX76=Q5J$7q{c5Wmymuq&W}WcC z1NZa>$p~MrXQl?DZjIv?L90Y7Z`z$dL@wWk6`q!VrxM!H$mMoX_E1Z#Cm-3GNkH2S zv||yU$FZw^M3>%4I&u!H^W?9IVD(tTw?BUZbv#;>jB=cbnp2dU7LzlLMfcnn`k?T( zI-wlfm59D+%+Mp6F5&zWJ{~g?Zp<+-P*5GyiNUXqW`#ItN^)I=9EE_-ZSpWg{cZ3f z%g`ts8UgQ+pQb{C_A>zgC-ADkpTYpb_~)WcT<+c`+jG*u-(+90O^!MCdMvSc46EM( z-meW_ZK)fzVW+{%nhYyp&oKwrJ9xxU9lTdv3t%Vd=-XR<`6{6fWEusVioLD5XrYTu z=%iVfRK+>sWM2F+=8xO6<5$ad$>0`?H4wg-511)`1Ubgg6V7=LwB#uAy+}(6C{FuM z5t{K?o66vjQzy-Q#G6xxN>7ouUMO$0>#+*K!M9^U22pc1az6z(we)q}*tSZ!eslKy z`BE*e`bW||aMDkrs}^9NY0!d?7aM^8lPdlc1`x&{xwev?9Y#KEtbwAxJ#T__Q$SrE z@Gy{!L`d>S-I0@S`rLR`k3Qb+oXXzrnO4P%KXk0S%!}(CPhd6o7ney>vfwlJ%gtcw z9?f2W$Ib2-FO5cifD!-iSMtTtvxB)=K(v{F$gZ2%-w|s>mj60ivz|@t{yw(m(d7`MpT<}h zW`1@$i;f>s`2SMHpTYpb_@fP?s!{?tT(`+Ct0;m`#Yz#B;Qu~^*1kBFRioY;Me9$~ z^RAyDM^7+05>1U7Jvd{c-H`GK#Evakftn2XpR~n>%SeESpJiJbhqJbbWixGZdY?{k85P@cvoB<&Gso5VcxZ}`zQIPu^q_nUf|7__}#I{ zGrlCdt(WACL_gDLqGrUNx-V2+XsAOUpv)4j&<)kAfvgWJdVN%cpPqP0_Dq6@`G;FE zp5?`c%R>tPbt?W81`x)d+Um!BS^3qKk049iWqKN|C=Z^P;nGx8%*|>#Mr=>qsG3pl z2d<3bIC0ebFB`$Pfti+%v)AIA=tD%`1oq3Wc`en2RA9)Ydu+o?ge&B9_TJ7V>V7ORfX{ z@B{=5&;e5(=Ig6!R>5lw-cE7VX)f6z&5{c(t_#fWsCSs&t$m{ z9De!}sMh3`CRbC{Cfv(3xte?dv*a8LFV2#4EpFm#U|)8c8(o|(aN9?>RqwfS8+TiE zfpqN3Bitj^CCYDW^S(v8#yrmBn94FyiE6Qwhu&y2?2W;e0(2ILVgKQ z`61XKJvtGwfug~Mmj85T9y~JB*spz1P&F~mDi6O!uwT3gn}fe$uw(1MQ_8-V|M6@Ll?2;)zdvwz)RSkT8} z5Sw>WUc2%|*vuFFRQXq5PPHJXvGX08$$nPm*B{D7f4?+Zw|g3^!Rq?6cVk^91@%5K zzi(?zhNmx8u^_3}EeQOriUomZE=!tTGaVLWI>(FCPjh2Z`&*DZC$Rbsw_-uui}(!B zM8$%bkHc~lz=D+GFIf-VGyl5%C{XOjTi^?bRdnz;&nCaaIbZ!Y`pHY zt+{Mre~TgvE&rci#h=0e!uYG!G_p%X51r?%f%WuajP>jyhZMk?=~TA3>kHZLfz`!Y zoqw6BF-FIUzc+42Z7m08TO|u_v>iAzF9o*a7ad{SK{Xz47gAzTTOfEzUT1{2&p#tb zl|u22zb#0N(oWcivCty_GD6iOl{j(z84~Uu-vuios8)o=mJfCmC|2bD4t-;u&Mhs$ z*)dG&d=nl^WC`O6bFnH!H7x0>Ldka7uqlRRcIx(17T}*`!5{W-&V>%SU?(7oLHild z{)_Ocu>Y&^CyamjfT;h9<}s+D`;=q{TS`pYjBG>kFh^|4DEQXma)zaFtgxs!E~;(V z($xvvq^656HV)Ii*ch!Du0#sQ%e)lFifgucN7^*JmCBBFsaD6_XQxNfenxHaVbBo62&@R>#2Sl*$V zlyGW-L?gM$MG0+M5Av2$?@iz)HeEFCn+FzxxVXP38dLWzB?dzV*C+GS~EppBK60 z+kz3w9X|Tj9p0xqd>c>WxA8m^NB77Do=5y;SB=2a2s{sgwH{FbKZ`zp9KX4yGTaGo zV;mOLm#0ZwvzYf7EXRy?UVKr~2WaaYY_%&}!3sKvKLhaJh?hnCr!asp{v?%%fFbx& zV;Pq%k)$RolF|j;2 z^HCihz8%za0P6@iU>Zz$ytqxyH45SG}IZ=Z)3v713Ky0DiHi+RL zIR4wD;!j}!Vf-PHJj7A0&`h@1>Gx{HU0z>slaqr_|0CHTene|?=nulY@Fa2cq!d$y z>VD)+o887wz6&)rhkI$C9yLBWinqC+JVUoCa!!9Zd-_e^`rV#NU4;!b_9h~BBOuLV6OGeYavNq@;P@Av!&sYa zfh>WC-Hy6H+2Gv(E{ipcYqP^*XzQX%yk1_^2cuts2hS3DR-K!P-Vx-{!5S0g^Paro z_jI%#eLMWUvo$^(_YF@^Eaq!5Qc0Rs+DLw$=Gc`qTe&Dd?}pAiNq!#64O0C)!`S_Z z_VBN~duB4`_OUe2=V_&n<}EtZu-|a#lDuj0G`3of*o`YakR?^f@nwit9>kvk_Wvoo zEbKpp0fh0dkYl}*nHRoP|H>D8dr}kDPN^qNF5;3c7`1OQqOz~QRk8IcXyHO0t*_iE z3yqt(i*mUi_Tyk}gJvwn_(ntecAHRq8W9_ZVJBkp>ZJ?P4#eV5W9hO`I$!!idRMBE zL?67%mAose?jo{`Xq0HHeH!N&!1Ptd#b9JVjg6F@n3eFz)#Q+?$x~fAGy0r|fZv03 z7v%NF>k-9+CqiXc!^_YP6RtX*?9Vp2>qm|7N@@+W%Vo3F9x=G>TN_Ln`AGsTga8QeHd_j~m)q-|Ud2O|q^75_R&JQAOEt z^*}Ap#!9<|{r=;$pL+Udm2p9>96JZS3OAMAjMxJ7Ekga}3F0WWw{sL*AC4oBe67;j zxYh6s^2M+s$D=3VJ@Dyvx4ztUsUgYEgM9!N993TIMtGJq)6Ps&A_P6)8WIBJ=e-ZH z93sw{gShfU`8~;U=&dVHa3<-Acj)gE@9ewsgl7YO_(oAfvFCTSImBC5qL=c+k{BZ# z3B+JNh(81He;O|f{3#3|j6WB*7$b9@jqOQ5uPxLi!mmnEv=PBkuV59}Le=)vzB^sX z{JWmh^DfXkYAYM;zhQ|iIFY0VNFiwbO|L87&uh)s}jI%wQ>zi85 z;RzL9C&l?2FmxL9Y0lCAH{aVE8pF^p%aldAw+`2^C?=eeL)vS&G`!JWt!f0sQpZ~S3ml}qwmts zjw_FHkG^|f`&Om}`=&j}HN_RZ)OgMC*DD;;lrQ})dgwAEs;?EGABV@EEtQiiD9V%a zF{ZL7x+(I^jn&`Na`=clWSp-vH#&Nc`AN4Pl_^tj%&YPxIS=zo+{Z+*M&}xmD|NN0 zSi36Y=HO~VcjCSbFpIh{g79-rZ0Uga(9hS%6XCyf>s`|HGc-b&{(dn$&uxzB?{mmN zfG7s-XF&UZ2Cs_tPhkMz_8%etK4IRqqSfQ%=fSsD#y=mtTk4OP7BRRyY^;bi9Y;4} zLwHn&>hs^@+v)kh_9$BSzj|U08x-7VBw+5I`=J@gsnMi!t0yCSqaa#aivGXLGiG-X z_kc~F4V}>74g!A+m>8t#)%16IbqQibHHGRqQ`xg!jxp(a-2zUv93Ihn^|LwNqRoc?BuIp_H0a?Iv5qaXj zr!8IXZA&-ml9xxU{-Nn-)b^HqX!`p#va3wXMzv9OE@Q2>bQ6s-%0>ox@wa4W_z^+U z1Qm5ypgH9K2bU)*i5WOl8G!!4zI&#!$SzLJ?SKvc_A1|Bz!J1WzSp=@+9JWTTuZTD z8rPhYU8t6cUN>9HN^-OL=&|!_QxdBX8|XS6@$wUAgtRB#dE(3y7>Usct3FsDkv#Kc zVdS}nIsBYMuoUd?h~4{=E2-keO^%EpDopH|dL&;KCb%UT{Lr+|`x@=LD@ZZMNkJOr zVXjtoNe)(98`s%xK4WcMYFs0|1qPp+ai^QPo8K`sPUP;uQwRquucYyRz)#>xCYSlH z;nWEn^@Cbo-0Hx}G@l%#nB)OhGu?PKJ+8KZu2wW?!N-dYz<)b70)Gkv2;&cFY9LKb zSenNm%?w4FdRkrQ@97;kjXU&quZ2FKSZIu?x#P;WQsuWGPOYF;!u@ z*?)fd&Q~zHx15nVzdF8t7*U{GX&>(k`wk}Ewl;5H5sk_{94{j4 zw!8Ia_?sSk?~+^?qmDAsQzR@5lJ^H3z{+f|;7kEp{$fto7{f1qht40rQiKoLQaz4M z>7X8g17GcI%qzsC&Q?dyZh1IjySK04U4}aIAyFC!R`8MF{E1>?hUWQX^Or~qXqJa{oG|)--q7vp{G-zt}>Sc=;wQ0=tVZBmjtcT=F z4a0hM3FE`+RE#1GytZ7ENaK`#V--|{B>UlUCDc)t@l-@68-`Z<-=X49VE|$LH!ep+ z4LmIKFl$O>TRMusupx4W=HD!*tvSlp^&K?djy=V>jCFfO_ymw$y#*_`VV??(+Aqm> zV(eCHd;H9!(&O(we&+Fai?2M+J^t>PBkshvl~_*o_W|X5i5zD*CkLu|*ND1d74@=R zG{DZgV4MGp6(*4z533Fh@oLLCj2_&mG0Qo&$UOJ%<=={LU+-m_^}n(RjRND zk@6Y3TmKE6$U(e1JQ$RfrvG7(ycd+!08b*<>4Xo%Kb2i=6Gez((0&H=|2y%j=>I7U zAdJ7T$JiKz?^R<*rkpc}+GTPIEF<;&BinOIFi+RZ5#5o#&!#C^T(-WLU_1OoG3+lL6AqAn{haLDJF8*bq0A~`--q{r zOT#E575pzA%`7YBD4L)Zz1AgZB3YNr z6xbGw93ylDpx32w5-w41Xb+xVq zTcHFirKx+s%Zs^RVP(=t&!gIU-L9$Z=Q6Ps{6)5x=@qsD+`kOmGyk#f3`8+#KLhaJ zgI5Lq6b2B+-}XI>4TaLELn^>`XBWIc7+?K1%)Vek<_NJbm?&$2)&W@Ou`3UOaqPov4cG@BLVm|X z_-&US`tTvJ572iFMgb?3Z+n&BVeWyoXEd-RYr#FRmRl^Xt(Fec-47vVIsZuqa+b!i z1>L}UthIUNTHH|wMhb4(xndWTPdkajEmg|J_amKH zUop%EJKs3=CRXc2lZ5KZ`S|a3WPdy_WWj?#`QM2+=kQDi;t5<}c*8mR#mcn~c1yk5 zvyYB9&?+Has~Ov~TCO;Op9VE1u_da9vcp|0qRra0H5a*t_EP*{rmVgCgmt)8)aUs8?M9DAVkQ-=}dCrLXle|)YauCBmu>UVn@ux6=F#aSF zGbCc}lgLYrOZm63%4(37qP;BT;3u;ztsXBe{@^hDF+1?HmHaaM#Kai(Z)AG(X9d$^ z?6*tVMm&3_zH5qJD=avA3-HN(|7=j76wP`%|M%HoMble%QJ)ouOzz=z=P|F_A$bt_ zhkPDo9dqIl#HS{?(KFO{Uuu}B^TQMUfLAPxfLe=%zZDTngui=5FP;jb7_^@O?Y|VS z3j0rC0Ac*!x=TexC?~(U;NIud?#g8U)s2{4F#9YzY-;|^s#P^;+hF0eHiv$xX8x@@ zoh7|>O&BSV)d{t0_9D*&%wOZ!f44tyc(Gyuet`UtalQS^nvSfd*mz>7 zp*|%I`}1KBR&~dAwAdJ7Y`Dagxjy&LUtQ%ZOdT=FaAXPot-aN!@q_X&qe5~U>+3^i(BP}A}1;g1gy zmM&J`{%^%k`v@vb^2zbCksB@>?YW+;Y{QJ|qnkpt_Hk@(yRnfs>OIG?UhzMu6f};_ zYzLdC(=2Q3=BpYl4>n7=PK(Ij>Z6=1s*t=&d4-&4fZxJ!mDAANRj%v)dPw2_oQgk% z0fg}ndu=Pg0{9!m!`$@X7Su@Y^`@w7YRKu!m*AUwl%j9(_pxYpxC6|Li(kmjQ8-!z zB|9*az1yXk$fK_6*H2WzASS!yDSx%sgzyzm=UWG zN_N>!Wj*3HWU11aB9r|b<3sz+pZtUmEdL(>V702wm{|{Bl1VewX`l2 zj=9465N6v4`Z5Q?o}XTZ0V6TIB8Sv5h1J3C4CEJBBnv+cGYlLxM)qqjQzuQLpIMd(>uH!%#5hl$=!>i2dNy62u7V)#?G1MEMA0fg}n zTWidhxf)pr^v{o^l^%tE;Ra9IAK*#bfr$L`4Ni@t;){kcnPe9zhuGB{iw_&|1hfad z3!6O719#4h2S-~#;b_|djy69R2adK43P&5Vbt=I-5V$1o^k=fhPJW`{lsH*eOZlOX z1kvW7dL&2|eiHcGHsA_~@CVD^zl_$Ff8t92jEiu`9m-^%bbf&+JtzPBY2G!m?hAOQ z?XJ7(_R1#C=sY1CaE8rfZLz?MXo-(-n;IiAMlpLb+3`;B+z#T;fd2o0ia&(`gz=A@ zV-Av6XKIil>tYca+)Z3<)|P~okfy^3=4fkR7<;yj zGP>toV{0-|VfPEU#6ubQ+(eGqHkuHf&pEP}J{rrXZUyU8Tb&q@;WYu@)ef5yUtn$i zL!U>^ooERdF<&?1x0f^Fw+H!s@IZ6)1O{Y!`SYx(5o>qj+Y;RWmk|Nch#6gTaILUQ zhuYtnku9RK}J z#h=0e!uY$TVJx#PVlOv_xLFbLk@HT2CT9c_Iv2}hxJB|9jJsyy8=qmA*j#52;bAR{ z4VX)!0+$-V!vMyov~E|)JXU?{Ja&7=JjQOD$0DbjLzTP`s&q!>=Fn?;A@rK)&Y9s^;>q{8ify6vR7)s*epF8KUUTTERtOzUPS2rzxt?(WODHYh z7D{uE-OJ}ZFJV7N``tMs0(qWcfh-U1n7P=4c=5F4;!6#VEL`7a!SxGq{g|ElP&z$N zCjKtP^JQAD+O*L-&7mrrK2(+TXwLARLkj;g75_j#{5OVpTXg9qd1>|b5U(xpBn8Z& z*ExOY^`zJwl5Gwo9C@ogl#y-@W#q?U+wJMOo?)f_kcD#uw4tL(`cSId97@eMU|)4A zA3Dm%<&1c4jwjDk;Gv_&2K2zs97>yS&xzTa2UN|W+wy7880@*tZO9p3>cv*t;zWG! zVp+5=l0~%FnfS)L4QQ{iB|h*4K37Eg_GB07o2qA*8j_=-AsNuHVbHM5^c?8Qh~%7& zAbf(`Pt3=aSe zH}<4%4^4->lXh~U%wc>eQ<1k`;Bki$r5i&TGd70IS_k%~4I5rUEqp^LRl2Eku4gL{ zS?qZ#WY!mjP*ALRQ|Pv=v3s&S_)pP@g744>(uC$t(u7V}9&LZi69vnY7L`*J;()) z!1e-h?4_1Hmi9t+Rgm3?oj_ghc%=|BOb(dO!kWY0zc%U`*^7*gA&WL<=a{{MYI!s8 zcOmdee=G-A7^MwWrIXbqtAnl37(vU2DwVU6V3#Y0;TpFl;YyLy3t%VQ8EDn{j+~qJ zE%sPKnG2SC9L45PW-89jBwN%8Z9F4p3MCEwY$&dE#5MzERi|BsVk396q8Wjclj zHia@Kz($DAgi_~j4`n91_Kd(NU~HK`UqVhc{c>?@D-_#AU{NLwQ{3#3|jQ?Hf|$UHx~a1CCRCQ@ zd=`oF`+0FCYKP(#Fkj(05p&LDHlZtU{2?E)2Z)k@Rq0BPoy|GPDMtz%@8kkh**Lb# zP^A$ggE&qbd6qk&4H!<~I)nBzVE*?4UKR6y3Ihn^uL;;s@PXJ9Two=9uXd-MP3{s< zm7DxE#Mb)0!q#eq^lCd*u2vo9;ykBuU<&7*8RSdWR`ITxb;RbK%--%j##+lC@cAmU zN1PW#W03Z7;2BrX7nJkG)f#bZP;*1vPGT^{=O4Kx4iTXua?zFAF2v*QU$6h%D*od# z@ws4aLPnfwGHHzd5VU8_gWgQU5b~nvl`2s`?oCuN5nsKm)*~mTS$g(0z0ajl?kxoQ z(uaIovbA`+K?^=!Yykc*Vk7XUFn}=r-a=lC3A%jqFdA_g^VrDiPH^2i3VIzxn5p0ARZ^w z=fNS1?drO|ra+qUtCcp1v_jE^7}AWb+2T+ z#3tkJDXh3hqiBPw7yk#H@Y`8ASgix&Rh`%jj`*$d(1i|RFEj&hy6YBbMf;G#zg)$? zq#yp&D$pimVEqi*#32jI?&+@+3%*w;-t6wD6VE^=4t>8)9O$G~|4o(mwHI~%^@@cF zg55Y;n9T8xfD;k?(P_abDPHNhYdu}9#uFDBvOl`ekQ1|0j!VUp#Y9P(o%c(RB4QK% z{owcQ?P@*WWBuN}J*~zzp|bYm#f!u?6Mm8*h5sQHe+mN#w|~Jb(1+7F;m%3Yc(c44 zz5bJg266LrwO)JkMtKR5!%;i|W2#={`XAeL>iT(K_Fbd9Re;RH;|cJz&pmS#t@+)P zEB|_hhbEYX5&f>G_TWEU9wq&`K{NM$iTr=vHEV~-Le z>R}uFZl4Iw#v(uJFd9VU;!VLyA;pS{&dI3u;E{g79z@<~A=oQ`j0XfX`O0r|q(ppdJ}EVkqD>c5-{p=i?`gfcJGO*X#g$A7s?YDN zqvM@miKjE7$Q3$hKLf^pui#ZN{-ZE}F#Z%!-)VHic)Ood|#LZf$xi{JpDnJKA!8o37mVdu+hO6BjSi z+#qa+Ac{fz8G!#`yejagFn}=rns-&Kj6#$mF}^V1$nsXgQmXcs=F;7*W8c2<|2-#e zly}(Xs%Q7Nxpb!5mvpz5K=#+ih6gb=B)gNSSRLCB2{rUXy;g_n%Y<|LcVD>!D}XuX zc`ZF_x8ZvfqKsA6w+_e(~n^N{V*ha80+swSnJ_kpP+ioIr-J6?Jip_=b8)adQPrK2FOMH z)Z*tu9|@HK&9yyeR{92a2PDRKth8g*&fL4o z-U2N!Bhn6Q?^wkfw$AP<3TgSM$F3p!a&pZf#ClP@ms@%ozfGtK9?jOYfs?}!QR12T zb{%Evqt=&q$|v($f`x`sswu*SOdNleqv#JeJ<*ajJoA*jUQt-L0SW^$lIE-8b|Nm+#%E^bOj^&AL&@5TtRbZA$Nz`g(}VeHF-bjdm?E zhU3vgJP~=8m_eydNw|+#)P`yX#@v~sYE7sk9f3?Ssw3?$ox&dK7*hCGs`!`n!#~WP zJwjp6PWXI_Xa!qB7GmkF&0+bfJ;G}zh`(RW0=Uqoo$I2#d# zH`RUG%LW>wM3xe_*9dTd5}(UnoDXq26$Lo< zSdq)etuP(DePUT*l>r7qTUY{=jw)!E3|4|ix3Ihn+e{T`iT;iXJ zh2P&zX#5A}%T$|lf6=9eI6g9E#wB~o^4fUReOT|0Ms0xS{GOKj<bN9aO!c z*dH6@#(UVWi&QDk=tXo-?WKlzUgy-gT&L_3mlBKLWXZKNe*Bc{$>v9<4S}84-J_a^t6;OxA&fRZ%5^uQ6*N~e@Nl~nu5)9EEh3ZoMR-ry{$SzSL|W# zA|7qhhND@Qq4((Ij)E!|bj#6xdWKQI{+jjG6OFuS{k8G0{yrF4q5*bed+#6Fi@(_K z{*i&pmr1Xj>>aG)k)^o(TIdK_9fQvl$n_Zln|%?18lPUV0DP}yICnV@8O`%*1zi2# zemY-(W;lB_!^8gOM}JU>eq#`S2F(9nSMjGXfH3}?0d}_XTtocka}BYZ-<`>^=lv?8 zpUQ;qc|Y;w=@CV3clo7%!A5(z)d_qcraaO)g_X4Nie-+(?3%0G*^AR7eK_q=a6-M{ zN-a>*041Yht9i6(%nkxiDrabb%qLhK_M**t*lvGZ$wR&ku+5vHjnVOT7smX`y5!w; zQ8I6ibkg0YVD!(!+AqGW6<2&6RchH=1Y3f5a(`Y(qtlldPN7zKAflvRqHm~hp=>b( zOv+zVz;J53WZ3~ulR^9$fd3nKSU>UqkBEYI&tLJ5n|leF^;sL&^VQg zIYhdmX|urMqi_G|dky+LUCAa{;&}YdVCRAn4s4@QgXmcE7V15yPZT4*ahbeSn<~#7 z&9CB9Y+$pEkWC4kW0q_Lw}gqe1UbhbhJT>{=Z`A>6b2B+f151Wx#E?QKB$3obc%F@ zgeOMx&aq%!p2vDpIall{jl+P|Ie#A?Q$=$SGqlg3C721`?U!mIFwSo-x+hL5hF2hl zwJP~m89r2vUD!Qo7-Dw7@Fwj08_go)uzwiX0;r~}2x~s3uF%I*#a8>)zr~ajmyqE0 zG{t030snu@E^G5=E5I5S^QjyM_NG-as1q%(6huS-`4&d72f8oG$H4RRqq=$QDbq?^ z-@ojxraPuoH}Sf=nr4hSAUn9bnij0a|Hu{P`TN@a9d|W7j9T(MM>PiwL#zG&r;0y? z0fh0_VVwT^Lc^(f*Pbt2B6D8DDGNsBWwVO#yL?u4#MrvKn*QY7BHh(g6-81bDXNm= zam40XI^}2@aaV4ClN9{V&hqq-h?+w%pizy=Qqb zr!asp{%^}pPX^ZO=CKVX9B`rOZi|9^@ z@=U>BUgXBil3f<$TRLaSW9}Tsv^_4RQm3o8QYZOTjv@Nf*8Jf;1=3uwZcr^o(gV(k zni8lmd|KXYr2lCJXB_)`_hRX##-L%{83QW+uEU+yaaq#3YSilNt=hTnG>)dKzk&yR zvKj0anefYVX0WX?Rf!JZ+izr4_SN4P+8a&d`3O1Bl0$m3AbS4=IoEtazH_8M_Fa6V z3b(i$_b#@iAY=Ub?s+W`#i0ER!2bkZ75GyaKp20uS~q#tP3(3P)#-EvA-lX=I zaeCAmfoC4cd_E%TR>V-0uFLFC;hO9lICuu^8%V006Vf+6J=2dB81AYO*}%Lpesv2* z_|d5Plfg2&fy`kXX(B{RoZw%;))bkTIgy`h$Y8%fr3lfH!5&3zX9v7~u;4vZ*;9ls z@_J=Y9W=#(njhOyCD_h#QJ*Hkb{vrbXzTf;e+I-Tf4FcJD#fniR#g+ruPBXSZly0c z0PUl`>SEDyi~w`Nd^2dl$BPZX|4nQJ{uBlf#-G~M6x47oLd93A%AjSfZTN37RnVsS z-#bNfKXjob?^0TFo;3GdIAfR>skg8Yv6eug{s?S3B=B- zr=Em!-tiHw-=fz|ieaC%#n2w!L!QDlkNGm#AG&y~8@`1R-ZA}wui*(UqqCH;BXlO% z=k1ThYJ`88xtMcom%oh5YWZsQp{qO(oqR5;x#zxWHnS)O90Uorm{dzKQ0AdAW$15pgx&j9@2!m9#*3Ihn^Pc4Q|wL&)M^R3NwOY%}}kjsbp z)Q_S&_Iwa?@6iV_miFfLlt3 zeW(7M>a?e`429V<@6 zaZ4s$xFoy%;C8X3!VVPO<3auT!)V)7fqpA~ux9`wneE zFXQfd9(8HJ`fIQU&HLzTw@*x#O!c+{+}J@2K3;49{wG!ZDGVTtzooP=&IudvkIsoX zklP|BtpE8%M~!x+2fYAkUXXL*ssHqtlnU|qk9y#7OsDWLfPq1vwOO~vb^yF8JnH=5 zYL>33=Lo^uCu$pcEl`{jwezMrLW;Kbq7|>AMOOt3ROzQ~(E z$EPS2p=(h^CSA!ep+4d(aF69G(PtU#FP(;c1>h`opvR~N_nZS7Lg%SmMWVRsG_lTI zf(E0{KoxO2tLVyuF4g9*su@!Fzpdg=VE}#jORK=UvI;hN)qAGBW7xiqo8(*z=gO|t zmm-&Ezv#5@J9JfNd@wG99qc5grSZUbU#GPsAFVZmJqsTJZyd!^n#K#!doSWQ`hQ+XRcb}rssErjJ)Du(-MXSvMEy<;)dMWs^fl&& zdfxfq*W<;Jh(H*I-|N~&B0?a%hV*M>1l7u1*={-C|Fq_2X8Y}&`rXQ5En>X--7=WrAK3oM+X4GeVE|$Lc`z(vwk3YFluy@9 zaObqwRW|!?k2#Ou>&Kjrb!DFayn!2moQxPg^NcKb&Aw#`FJ@=f+q`i(9#+QLgW>(U z@czUXvy+wm+=_>bVnio#RQI#k~3;j*aR&PSbnb0UXDF zt`Tny(vh6zn0vE7tqL;`2WE@PdctJX7;le^sLhqMjwQ%5TBmGHs)H6NTYDT}GiIxm zt+92qq8L#-J~3D7#uXad2D1VTu>aL6{+0dkrxh7%9aoZ9rE8q1$(6bsI>n1iYyKSj z>UfW+{?ATQ)TBi+`i>vZYFen{9m^NZX(?O&P7`XnujP`Ws@hu{yZB&xYf_KHmvY?C zcy4(d=QI^oo*c>cC^i2mpR590(1K)GXRqSH@;)xems=&RI|^e!0Y0C?jz@f1EqtMC z!ydWNcK!S=ylyY420=PmJY0|16i!j{LL-yc~G_ zh;3SpBA)=OvAo}%qaGf3=OKmvX%+vfe)va$r^^tX!O|i5nJv7xzvRdFmwbyknj}B^ zJ0!oePx4U@UzhxtaGgi9S`Fms@2mzg8$O&grJ#b|a zx9DBW7pNkLX2MFU{(;#>bz5sv_qS_*jA2iAQ0Ho8l#{gJ`Wv{UVmF|4lrdhHLY zeKDl)e@Dfi!T`edpK5==|JRP3%5T;F$YA%hU$6a_etY-M4!j+_2T*13GVYaBZkhf z_MYLcw|G->W-yP=7NmVTbzdS~&8h55q#h-2$yn=ZhjN5gIpUwn{i2j37Gq!HiAfgp zCV7#{F&gEV!^$z#lT@ChyCiA~rfj3i#e?`W!2Z9h;!j}!Vf?w7i8(X94&S-hHz4JR z`t&MqY?LIpg0hzhB zMqVJirUCs&bFxAfK5lgs;gCT%s7Gj&BgQF5+!^8>SuB<>^@|QZw8N5rbVKN?=(?k^ zDYm}r#`$s+Fdq4ttv=RU5PN4x!}I;F8Ry%q>?Le#Pxc<6T(ijEgDv6ABRs zv#-bKnRH{DESA+a*)vJ)EvP+iAm$FLBV~_~R>I?NaE@UMJMG}%ARd8*s0vBGehuav zl^z=_e5-eUZ?0(m^TWd=6Do<-Ht_Hi%z8q5s|e0|?EkfFxqnFE z|7R6{3Ihn^p8;MD#Ld7P_UDIB_SMY6Ol@05Gv6P9CLve9(gOq#8?@q*Eaa#d*p=#? zSCC)fX%e#2+36k^}uFf)6v z_tiSzWZ&q?hI&p+mqt&}*Z(t?PZw8D@XD7((dBhajyYc*chRR!d>^Yj1}P5l3e^!j zq6>7v@xIM*f$Wk~F3bhhUIAWZhlo+?rjFi`z&63RnbsVZqt?mLTK^|+C;UGY1`x)7 ztj`4IZ-?(tcJu{r+?%;$a9=9z1s1II)Z7=k#&m3rXoErFd7 z7r{Q&{fr6RJf<;<-g(!wg-f8Vf{_PbwPp=6j9!~PwD3Qp;!j}!Vf@qCmG1p=l1?+} zr0f{JO(w<_&VE-dkNSutrF2%0{Thy9a!z8;HXOULyaLB+-Kg(4VjJX)^`Y0&S#-}H znF|=2H~bv-*9<U+D*A7Kmy+nEBEy@MMSH2wrK=d<_g&o zz46c{*)l(!HFUox$NXX5HK|a*m94-V777(4CW!H@xt|`a`c)D1AVD$*o?D3?!D~at zP!!e@NDG$gdt5)Q4OGBa5V(k+Ec8MAo*L}AQ_uu@ToA>e{S27@eSlX*`=>B~F#h+{ znoH0lj)7H2G_=Mf?4nxEx&X=1RLm#pi@ByKhrw+KxDt)U5rH=wHOR;~JEfr< z9(x+w3zh)Gslt)MzCZ=%O8&$gRE`~sWBCo)LY;clZ+dDFJ)R{gn7wX73x5-y-4n+D*8N*|UYn)oQQRY0>rd3pH4qBowwW6JqrnPpJt#xePCZ|ES-F7;U-!~lmHMD=w zf{zy)fd5$)e+mN#<4^LrtjLEnK$Q()9G2F(TG9$=gU<@KEiFb_>FndK{g9<<5!|o{ z_vx)oE4&r*y(6^liw%6tHhJkE)0wFow&3vq)`S)&Q~dpywHmgyjaKRSTO=uUjDRfIhxM?)$Z1v8-&hiY&#D3ISf5ci!T0$`dv0azswd38AsWgeb(rzwI zlXk+Qcr)%=HP*ou>r2mJesHneQd&OiA~Kg2*M3rZbCqrHXC?EILm-^`bZ;P=uT7SO zpiq*=mUkyhB~?@vLVZJ1I&Spb zq_fXajsE}Eb1|gwuT}A{?uY+%&&`UC8$CBmd!_sTx928~jqCX?&kcDl?rHyj>$!+y zT;J8mb1|gwuT$}-Fo1CT|NqK!6UW}`?i;T+CG>i3G*9&N+?aC_^G$R1m`xPBqgQ-4 znz3Qe4g9=1pW>6iOy&0}7?V7MJoB4`W0Oh>B+8y;~~pYWnH?e}7~5ulXa6)kLl3Q-nJIH}=g#3jYf#{uBlf z#(#_$$L{Fi9Z`jMH9a(+WJ6L>B{ggFJLmdY9cCDIT${(!a)Oid&63>~?!*UpV!T6M9DBNJR?{0XLkjngn0g*v3aS7p=eixu+$V4c)^P7A)mc4Ji{A(*7ZZ z|0gQ`6b2B+A1fx@pCE^8b>PMeU=D5MMet+gf6xG)HMA3ho8-O<`5PByAfyKi2%=~{ zUV^PuBUXnW6Jf0j3K>l5gHt2Dm6+}LNnX%DgJl?n}vbJts3o9f`@o`JA&>k{yq$zYq zCtaQA>58eImYVsbbEGX^DvE(j{$~MTen+z+Je%okl%;-D* zUq#{L$>!%u%g!xBHQ{B1^rB_e990YPo@p@IdGQQ9`3A?+@X#ZPa{B$6fZ!%XY{>C_PWd~&-0w(ZbK6YH-#KmBq=in>BCf@n z6&?>fP}DabXt8BoA15sD+di*leHNasfVc;UW1yx%L)M0LC!b@N+rE%vV5Pp0W4SLH zw9!H!ubg8)9a{1K^(y`p1`x)7zxV-?6S^)ItFFJ9phQ<2AeE2{R4b8_rp8xMcZHu)!5eY!u=)AVnw z0C^*I%}c#Ji%}Ru45DV=cKPmubbbvgQ67;O5|cw-4YGcazkmw131#X&Lm8f|OwC%= zHBRSB6mZM!)G_rfV!f z-R)fm)7Y1?4q4qMNU5eF^W`-3|GMVa3-hoFIP?CRh5~FkD@T-|dc(_pdEf7`s?L7i z;c3b(v^f5R7L1iu4fP_``5&X=$GmHPZFZj4IlC$E!EDMI(a*?3Kk}$%`HZ{`%d?uI z3s1L<;LvJctdWUbbW0wOjD*=u9`rzD3GA%0?XD&PGd+y-IP^tqc}Gv{`p$XRUdGDN zO^)zcxWYl6wYN(x`@m1SLBzSxkFqq_0b!OLGttws_I^|qj>ovfPU8mZw+8QL0RCU# zU4cJ^0fg~4DC2fi&0?;Omex>@hJ}!`y9L?cF3HIL-a$R5kqzs?$SM1dmYRG>R6|ld zk1^v}^r9)!*#_OqXB)JlzT~W&0RE=44F-$|Yq+zr%ll31FS;W!PCw8Q$98p``sN3} zjb-bR2fU?#L;lVWev3BB9sXMRA7caMe>?U3e%YE(_BBPDBUViIbAH5$`B6zK^87`4 zljw+zju)jg_Q&pv*oQ54&S{8$uR%m4ncoq|F7~Y?6;~Q7o|e!{A=XO(XQ&QY#~vD? zfWL%B3+TfJ@n-=3e^K$LFn}=r+=-Uf_d52|I0|fes03%A-q~1zde7A)BS`23N=C^0edI){MJIELG&oFOz$<2>lu-)pcONMlW1ez1Yf-uk>eYb$udEK$A8Vx&uQ zdmQ_h;`=fAoK?kFEO~zVIXMpdzE-wZ$se8eH1!PIH&dvcckQ2R(%8?t{3q?0H+~V; z4D*IcEA&FnAH?tv9RGc(;!j}!Vf?8r_$Aff6GIUc(d5_3YTE3M0@HSOBW8Svq~fTh z?BUoV`JIS_Q#zR+`8x7E8tXV@`BCgHhiss;NA(lTb>x%VP#Gcf6Q3MqbnrYZF*@SxjFI|;Q>qv6@23z6fPM5I$GBs?zW$RNzyLk7>2A-vO*6z17!?Tc zE>a!82xlVriF9ro+txLu2&;k7aP z-{R*=fc!$dx$tSkki!3xia&(`gz>L!&>ZI0agLQm_FZaPNY|C0+@annwL!1Fxz@e?FdthU_L zIGxwBJa9W&Fjo{#?U$`~E=5yYa9k)s#+it-?S>q>?gzNe=4>szePl6=!8r;3lq|Xu zEC_GNTKa)pkE0R03eOJtEa*9*wHw#`@gf+eHbQ4d*B!lT=Dk;qT>8z0jT|@T)FpVd zbl??RR;B7Uj#RY!n9mb0`vO_U3yMw*S``>z|Nl$HpTYpb_~R@1R5!ee^_e#AIq-CW ztt*`II};XljZ6``erFt8(U(d46k4WXvsKC(rA(e zVQ0fhmk@9HV)^(XSQCHSBE9evH)fUfVB6aqPGlr2TxkVi}S(>@DmSI9Jtv zWP*1)mah>Dqk@zD)_zB6*vrZ>oa>)dyOsS!?h(Cf^u2W-btOfL25K+3l_xgKpEOK} zHst(CK8%Rsh6{S+v%37EL{E8Z=ik9h6O<@}-SarG3pNqzT*IH56?_aVyn zPK*k0aqu@#bP6k}OgPan6qc{o@~ zizIH0eWI<_9XDRe^0^nAADWGIMZ|<~h768bIl=Ys+JiyglfEk2Hh4b+@DJi$fj@-- zgz?8$MIs(n>d(cx9A~Efv#0gMsgx(npLhe~wbifjDN(hWlq+?-Yg(-q$de8Js&3_G z-ubz_S;Mp6@>cdu`|6=FEF$G9dv2CU9mF;^dVH zPz#E662c)UNTO(=Y8?>mfT)3LFIp{=5GV-P0f8pGHCnYn1ro3pP)tDT6%{)J=nX3E zc-tBR?Y$?FBquK^<1IWN=bI3z#&{6ezrtO2>DT+#D#5ZWoWmg>NpK%0u2t6a zsp>U`g|w}!_VJ=a-I5p@V)%ch;UE4E{6~fhQSs~6-X|L?mFM}nwbXLY^Tx>ZmN{4z zLQ8WNA6bTlm=%7|Q9qR#ZoTB&r&)f{b^VPs2I;+TjA9TqcX{{1FFE(WfdRfKd=R~i z@^Bl<0wRa1ZzgCCTTl=!wBBIZs+{J?7hvAFLGiM!N{HL4gyXgF2ub%gz-zf#BYun!|HQh+(J91=dib4At(EtAvKNbD|6h5N;-@Z+k;caOzwN=Dc z<^^IaO5Fk3TZ$3cSq=7IDYSl}RPdF~Jv|ib7Q$~SA96LVY{i2rrcuqYt<($Id9kNg z-11cv>tHDmW3c#x0n}#D5PwVg!1(e6>|MS-e&GxE5DFij3oV zu`jSJ$brZDg82m||9fDf|A7C-MJy|^PM69uk%>5kC)5=+*|?%6EBDvP zpama4Yykd$#YW&yG=M1nQM@LVGBMzc4d%5)7EnKgf0wrgbtz`_Q$EOvcJRDYIWB0f zwrz}cQg74+-SUsSwH`I9)LyAiua|!aIpUt;a=E4Fn(X4yGACPC2+O`=} z;^*Wi*|%@YzqQV`-I2Cyj(z)-y0WBg$n_pmiupNgfS>hn)gsmdnmd3d=WufpYDYM| zwZN6U>sX&Su_# zIr;|7_c*5mN5ls=D8szS&gFxiCe0n$pcsobD25u$?CagABtnw(WSBINaGLbVQ z^?|-0GyBrqJ6KA!k}AI1oT`tnWlllLjtpY>2loHJYxollAd3IoY55^RO6cIOuWjzV z^`reMUluIa$z!-krhv?Tai`0c%bC1eb_6 zf&S=g&dJ0zN@~$-(=hTlCe__dSnJm`+P3p)I!|dnw8gg6(;M?$4Yq9@#`O_Ju^SyZ zmXJ2STOhB&>82Y=ioOYj8+8@%Ds9YPq{}d!anQRrUGB5ujB9Ehlhz`disGin%X^TY7yJxYoLqwSpj3vM z4)Sjm_=!KPBy8H4&YK>s)5=VJUP8bB0(i`yLPbqk>$w>8X*qR$@TDml>@IoHI0 z!o+h;LJAk5to`NZbw$VVjau?boc^BHdmeohD=Tgw@B_6yd*A_}>m)_EUA=B=Xc(?b z8KiNZZ}z3Yf?T-<83A;-rh45puzU>2^o2FQ5%abERahUor!S9KpD!4>2)^Hc9}C^b z*OQ|Q_h5}6hR=zdQ-nZo&UK-roMGC%+Wcy4Dtt}2-*R}2;`t*=+%Uuynh{etl8+!) zy{R`%OtuXz{`YwR5BwYO5yjshM@(s2m&uhML`ywvK7tlPyDoTHu?;I%VtE_d9)5Mi z;eQtz@4>hG-Dq6@ooM9#OEj*2nxy~R(;%bZmit%NM5XZO^gQg_QW$@g6jC06T=}0p zniQfb2JLG=|EJYX;7>GwDE~YPxm?wXxWf!J(&Hp)Y#z z7xFVk_M;zDUR4vat3Kx>O`$~vX?Y(<_xIrRYcLw6Y6?pz#%)o1@9&y}Ea1wOcl052 z?Gs`zY7^$l8}NLiuhkNegs3*M%k7Y!fpU;=l^kf=X3&C5Y}?il#x&r6H(mapZ3o(4 zb{Sl>f1wrrft(}PYK1`yK7QB${QsfhPc(oi{$!(#x~84UM*H!ld& zwC}+I?M(NH9dMtF|K&cTuDZ{)TH}}M9d!L#sQB`n9X?*n-*7zs^Z&pc z!J}#Ut8E6mJdW=29rLr{SIy5f?nq2Jx6uwB0Oy)|->8Co%m;^AV$zlHMv-OET#ncz z-ZpPBS4|w$M0s;G&v5L~n%_2a_HEJ&SOI(&QGw#wytc$7j6!2^WX$!*IEiWnhMb(( zFzV6^Y%HHWnwG)_?Q1~)|1bPh=zpRCMDdqK{%qP!ryjgNNzsek_qOF<3Y8?W2=AGe z^yIX^pSDB{VdQ#X`E5B1f?#JDBBJ_%Dss zIm(dnD=|pb!A5RLMTV{twKiDE-Q4%Q*-F^f?6)31pM&}vIrZD{3Eg7JsprH+k_*{9 zIM+#KeO0RbdDq*hAd|YAQ|p0k$KTJ?o1{bPXQlQHvy38_M_!My1AO1A$$ip9+5^1b zALIFB!0oczn`8J>h$g)2(6RGV|HLwtF!2e3U>iP<|A8aKH@$9X;ZMI7{Xc?_DEbp2W=Hy@y126K4G_ou4XaN=fpzD5p0*yC+vdQw-YI zfd1c%p9=iH!bcQ;j%t1pyK`G>dp+jm-D=d-Zvw;u{Lv}Q5!D^~<^{WNQ+S-{elhwo@(c{5s`9DlsU!0A#vzCIR* z@2HZHYe6*;-64ywKIQiLT#5y;dhAZ(bj14}mwR=e&dt_$e@cHLmf)dJi>&_mL%7le ztB;MP&sp=WJ}X_P*y`h)#VR|&D_r+BQyQXauQP)Y=mv`?v`8U0yc%A&Rnr9=M zGIh2cx0!>sJ%Q18<+2~{23(l&VaEibgS z-`Hi_l~$XcoKrns%9V$A+FIV3ma`kaWO#>8D)kF zV=DB)gZ{~j3_%5T;fo~G7Ki*h_>2$2D)>og+zwo4hHXzFat!shKiZ9^7__ee{r?;M zRNzlEfGGaw&~CiDJ;dDig)Pm3i7N7uXAHGo3y>#GKHFib$k~j_;4D6rJ2I!*Bs&o? zIwPD@=|vUQ39u2~S8{f|n*Y59vbPAS`VO?PmuxegIpPOYn zy+T|Mjvyx{L~^QeY@Q2ez0yH@F*K!qtO(v1pnUlJFW4_&DbPE^8Hn459AWJTxgBAZ z;O^JS+b+jK(*C>0jQ4-^Wa7Oknq>r4N2;?+r9}T)iw`GDYoxms;qe*O>B)FD z*r|_nyh=S{(7p!XPuVVkKhXf9_;X$dDk~UHy@mI?8d#b!!cc3;*7~V$#%@A$UdQgO zyZ3sMv88W)rl@0Wbsmt8m4AgfT`JGHb3@PVvbCl!r@VT-?W;R?qdvS6DtvqGUK6A# z;CgL`2UnWdA!fP4$)Ef~nlB|E-FiNmB_EAx7ExJNn;oQf&^n)knGr>@2-`LRp-~++ zps2CT2bOc}O%L z-k`WqT{7Ka3e%i~LmXQM?l5S<#}6BTKUKQ{{zLMepY0wGB=Qh^>R*neGBE& zffqlQYp&upDA^A2fKAM6OO1OY_=vbc$-z2oCb5G!D@M=6jwk%%MK1VyHSc68F2n%- zri-|NDWMhM4^kgrOZ^u3X#JM1T^G6m*P9Z@1(#lPy*OM?RwkuQ7P+ma=1bg*ce{PN z8(-gvEDcqbi-Ps-*7OzDhB>wRixvh>3aZ4D-uMsYa|!tiYG|*sfv!I~gsgF_2H)Rl z$dWA0!wdzAU|s5b3tI%m;;3z)yNd<%8{&o*|A$sPfj`jzqWI^^Zz-1Mc$VX%7W-|( z(MD>?6>X31+Zknsqkm;S%e{gAwMf7SQHCByBf~Z&*FRR=zi6u>dRY3f!yFhsZV!5x zD20~!`R1|u-{VU923M`noX+5zg&&Ewu$H#K*s(3h_#Q9RTpTt#v2J=B_tQl1H7^9b zEiZ|yz#02{pgO76U!HjV;Wu%H8%!cDXlTf&^%lT4sc@S`Nf)6#tR)m!wx~Rj{x&v@ zugzUVN6fnBh`PX5#p&SFO*Fps^?Q%}Ppm@!9&(SS7__ee{l6VQ75EbkAc}uVjYZn3 zqw>lQRvn=dgF*eP@sKI_Ug zzK?6z3`_d2F=)ZZ4;z3#NjvZ-8bB2PacDzNUmM22tFjMms3GBM5Uy^+>{~BAurG>u z0$OpHu+&NYj*y5^b*hGS9QkH&m3UP)EN54UE9bLvQt**6mCq2W!6;NXH28acmN zjrFLlEqzLxAKqp#ev9R=AHYN}nNFSy7pwyDN-p@eXKeaC0VxLFKwge0vt^IRw) zbrqIK9{C7t!=IZDBahz^<*CFCip2IP1rEgbsWs#tjUcbLcNlCiywkNjNEnTnmtf&^~T5yhA4 zaAyQ|mmvH2%cj$tcRO6Bf~sZ*XR973|Gl^HfPnhavGQ2>hnE=0W<95rZ1oH+|4*le zKhXf9_|E`}AEWJ~C=z06z><9DR3n41{9zB}ekN?N7SNB);jksLxfG5eo4u-wW@kIE^wHK=?_X78cq0IQ-&*OYBI-m$7>e>F*!mwMw^X!e zYLdCW%bo00X9ylSzK0jhs&syArK-LSHd||xPm|C;0oOt!N$8YPR3V;D*P_ZoJ?$^! z*EKxalhYpR&0(^qG(Gv_J~{pPcF)kV|GPB&i3SkGzX_T5zp(K+N0hV4uxEP$mUn}XDw*oiamVK_dw?-*^~mLyg-YTfPK2)q@`0=T zA#hF!-L9|TJbL(*NEZGB*SaDLuLaVR(G-LBHDLTFZx_aYq5(wl*Q&gnQ>ZUIc=<4} z;&ZkEDUyL17!h)G>k-lEo{F5S0X~aX*(qm74w%}MA?Vfnqp`x%cN5knNnEbC#p>Fr zBo%v*VR3^p>25=7*)neD2Bm=dh~j@+$qcmV*WJ{nre-}us}@tM_O-sxBd1*ke;V!kK~u3{YJIf?ZH(MH)W#om zKikMx^3eDzP~-dG8cExycapYG>(8@6^`7~?F{t2lOI|=Ss5Y0T*~h?p3tM9mvheZ@ zF-FAr9xrvbFD8C3e6=@*xLy1k@a3T2=A+*x@ICNT_PVn}Sh;s6hWNep#*twU&We?9 z!kUB$=Ol%6JGk$WPUva>s{6`0@!%~rsHS8Y>{tb4em3TUjy*(!LJ4WL<5N8 zPt~%o_}4z{AoTvdqc0W!RrsW5ZLPv`0TBTdb#wdWa@5$EfNXxNN~rF~>Llt(9!Ss& z-CT99v`YQ%#`ksI<$E>H9_=mfKE93O2n_ODs3Oceu{tyUWo30jx$=-ut`rEz6(!}k zvIFZ5Gvkgc1zgp9aekGLkGMo}DOiPI>PdZ1+4p4dNu0RK5mmXe;Xj2cK?Q-`y z#i3{JABSvh72e$Ba`jnAV@!i|$EX@(H?%|9veilSOgDA&c;X?2f3Jo=(Ey_OtN6(i zkzMVjg<54EYO$l;8sUysZ`;C3;`?->>EpbFivK}MM&&Q*0<7y3EhSv2Z=GOH~Hz-N-PAZ8rY^XR` zQ;WECXoC^qv&wo0YR%M|n}a-!CGq!}E;2obXrj!e3fL>OZScMZ^ndF7_(w)>6o14} z_OTN?4~9Bzy$T{E@PQ|45mMd~XGDA1R5Bj}!;~oA94GvKuw5 z++vzG{wwPE-_I)A)A|->d$v}~!sn!wG|xk|M^Sbng3M&Mw90;a>!!OoSDustkBwb^ z7Hsptk9VQ=6lt0`Xd089&c#thl3%k0rbA~`nW8#|FV*iw{1E5q(=ji@m$0If&dHTf zmk{})#=yIQGyHsx(641~#0u9+-~436o((Z%*29em1;o#hAgh zwilp>(eW{uH@s-#DL1e~)8%jV&lb$hypRLL%1~P>7rpfftnTk9iO%yM#Y|wio^$^W zcbq#t6})|uCk-}7&4aNYZ8#r`J2`QuOYI%q30Nl{4Q83i4usv1k~uUtY;JccSLEoY zA;fvL28)+`umnss@X3zyW3TVid1>MxhJT>{SEu1mG=M1nwT<6yJ-PjNh`@{X!Z{(T z-xVw>#7Jy1%R^pE%d}jli_2P5Hx_we|8$QB zd3$#%0VD0F>Ju9mP{z6El}`+FapiR#bD(oZsO$eD)b;-nSpO%l@DAy1KlAe!x!eU( zjQpqW`u+SQ$`m4i_jm37A%(x7;ZHPxDE`zwy`A4~ALN2iqjUtx>#sUgMSQN@`Mxaq zZDqbc!Bv*e!JjkVSKkcBE3)@7cVQhT)yIa8jF4Yc+aLDcoof4!H|t{LyldK@*!OhZ zx!QHdFYsl``VLO=fxG4NeV|_D7wXzR#f=?9o<@o{ntiE!=?Gx{P>0{I9I95IXpwI* zv`41g)49mc-1JO~e5NzRGv_L}bUktw#e_L0AHmvmggKo{MW4z8M$Ezpc~*}blB1&; z@t}PT(EoZ3e{y<6@u%KUE}^H0HLZaM;u;S5>steNK8IWjaZ+CGmkJXd1@Q`($xUW> z@4y^7a0KYW0}!}#g#5Y6$-Mgf!*qV}wdXt3^L5{G{^9PZG+ZrZCP>YR-xoNy!Vuh!26|=;dsALl7RO}Nj%;^ zD;b9Ok4xz3;(`ewQ_i66{P0D{$g{gWk_n%;t9mNG&EeH*MX}aWFV(0Re`rYIZ_@B5r$-cjt=@(f8=*1nN634l zvp3`FnsUTa?Kr=*;Jh?dT8U3itZ$jjbSWp`Z!MH6k&O-UKe=m_DI$~a>L`RCzo?@E zoXtY%7xma$WgvZkY#q_u0fGd(z?~L$KJx0%&nQBGYl~5l5HieR!9`4MiXE6xOK}83 zrV^r9f!GLbH!bIpWz_T(hdA-Vr`)ylse^A2D~=H@x@Uv`_pRQ?jb~|Vxk521^sMHH zfc*b4xfxhpYU!bU(=Hgi$D2500=<7|`G3qB{zL6SrkO+Eor0=cF9MGl;ELad&zT7RyfNuLxJAr)TaaI1QR z*8g_)W&fnVe;weR)K|F-ul$=pv_8zb2#5GB9`9tEsxs-C@2m1zMVE@bh{y!*qvYAv ze&4Et>1%Z^daAq&hP)Sj|JC>^aubV>peY9JYk>Z@X!sKiAc}u&XKC{cbGb4tDX7H6 zP(QQCf5Ch}fIkSW(-uP&SjJKBWNPoE=$r|)6sZ&Kod&gcG8ea;FX7W~3;!M~g$L0O zZv`8Z#Tr8BeVkui+nvzEMaWh-qj-XqeRnIWO^08Hxvoa5x4rINFufRb3~UR|L~LO1 zg0+g^1DiB3PLA#2)96W27k-KFk-+pcpO~!Gl)+lU`skI2B~DBc?}8Dsp_8OLrjxYE ze?@tX#!avY2QB#cVFU2DYWNckAc{Zp>)f6YW#@b);Fnml-h8w3VSk}?Mv18!yLPkU zKzl!a*>m`nix!>*i<0x)8=$qvotlynkT(Sm183IqLg2$z?}OXG+uR-yz|Lhryb#*f z+=J*F&QZM>ndJ~4+H5pWcD{+6orTgXPe1G*Cr`z7S@4zS8(IB+i~ELCd2LxsiIr=* zFC{`(ez?Kg_P(cV+M-i*)tg<>>z=zDy{=hXgI-quc3g$mErm_cIpPzR=9}5% z$V12-x~+3tGqS}yNDA@f7?%z=-xQm0>P|f0Aw&=kDg2R)o9sWL0Yve4N_k4E)lr=< zQCl`)&D4vPleiGI<`~TO5+jpcj^@q!Adg8$IxfwQDK}QkwMnn-%kG!P=GP3}CV4Z!xgN_*`jgZH8(0p)zYv9&| zQ+Qu-!>QR9@{$rWCZ9so&_r%xfp4V0Fo~GTlN%C!a}#G?;JNq+_T6D`*6XJF&M2%t z2CLX~gu6lX2^VA73~t!rdPOge%H@{2>DY-nT<5fUq;4?7Kd}GXH2lfw5yhWcD!yR` zm*~@>twy4a;trc*s?cMGscprpZN5frbM7pU3M*>6%Zc2H{dpI7XDPCHqv{G~j$#{4AB2}4S%8mMDb7b^`d2>K9aRHHb3Gm)Dit%jNYi51~191{qPcS zrgTe~Wsf_v3v7BWeL~pe#GG;cvbT_*Up5LXI}Llr6#d=%Pvh8-wuhxJ1dDeGqC&># zF-J74k{$Yq{?tx=>pzVThD^xW`*y%^u~e9&O#JU%)9mCQaL$eFQbg2<(BX5m<16n8 zBeoWEf!PuGb0)0wPC%6ClBu|wPS;xaq-l$;b?TEwy#L@y1KuY;smJ@oCk4EZds2t@ zj3;%iV}HuMz`f3IVPo%7oSsp>_aKeaTW0F$DnknYSPg%o0YvfFHUEv*T`bk*E6yTr z>{KQ7zB|!IU(h@}1=~E-b5nde+1iK21pd85SG0^J%Qb?OJqpQS#!`N@~?<#a*+p4OOhYixb(#SGKB^2 z!CYVOM3hKXnWC>*yZ_UrKU%a}hE~5|)(w*bdZCVUxqM&jH@OaUuKXt7$6TM_+I-2q zX1C$NZya7z!6z8s55YsQWE$?M|5TY6*){FfwmJKdnFP zhZOz}4S%u$`tjeVM(DQQc>mfO)bt9Vb^@yHkmWvN<8{H4%0l6~>XV93(1R0fYu$jA z!Ey3zthH}=1eKq#@^kh_bCCn0SkkgUOgZ|*;)%%B?8YkM2A>PZPVSmVHKK6j!TXk+ zu(h%u`=llH8_zERdoZqeN&NzeLrvk2l{vGPf4IDU)A{9$b1koL6rWc%33T-AOQj_r zEAH&QN>Jdi+V`=Nwc#+1T8_w2ddK|0V^2P*lnBUQ(wwFLSSiZhpgfUkMb=`l*ae1J z;z`9XP|aU`dSXFm7=G?sO{eg_BKB0Gdr09Qr{T|Ch5x)$oYN~;F(JYZpH$|v!=m1~ zLGdAOW?=&2at!dpa&5G?6t=05FgG#HsgxM$z@pi-{2$3qAZ5vP$S;` z4CN&FLzxX#B(ZP4w*9frC4TZ(yUT_Y{=+oU+xXKr=A#H@rfR zyA`v_81OZ*`X<6h=vWKJhz)usI!B8; z`9i7ThX?)sFO)a)bIO8B$s+Y>bG-6hW$5GFFi0Y6b{M#2TnTc(E8`u4lUqH!^8F@0 zfp@;B6mY5e^77k-MEmZHG>O@`;_{D4w2QhWX(g@3$;KhXf9`rj(Q3C!Z=+ymYO zA$adK2*z&*e#i&LSrQ_IQ%y5x0ZzqX#giSkDXdJ)cHn(dc37E`9J|TBF|m%0J=c`L zr%T8hVxV4WlV1d%K$8k$^)!RklL%H%+&zSNNXeQ-eBI0KMg4c?Av<)8w%={5H+to> zrH3<++IIUxUQE8X!;iNh}5ayp&Rz=lQ9_)ic00jKNuV9#h=O!zzy{S+?X8Zy?fq zBmSpL>+$XZZzR$=qJllmLE;^yLkj-{4S%8mMDeF~j;o+HBaQ{{Bv}ah92Fs7Y=vXK zy`pG-FUDezRpWgeQ%rHsD{gZiI>ip32-em(u(qz?TUtsw*qOXK$=hZc=79~cs)LTt z1!Mp09NH#g+t0!Ih$~7*7KhIEoNLaX|DEy?BR>z_enq!XZSQXa8Ng5u(A9CzNAN3t zWJQcGaZXY7b;0M5t#Psfu34ge9^JhNmOz1BUWdwdqVTzrnh*e^aqzwd%>RaK_!A8v zia#nSO=a>Y0qSEP^|fSN5nA$|yq1qf&z9{m>C$IP)|>Fl**{a+eu z$h}fY~1ZQU|>(f_rbM`@M#Sxp5zf5L(0VD;dq~v9D<}IY>W@;ux7wpwQzq7PIWs%VxYgFK6O?^yNMeleMg7{UgZjX8@)q8`hTjtfR`L zfIhSpyiVXc<5K%Cx;|Bw=lxMxUdm?~LWb6=pT>Tq?OECttrr;eSN*akMlwH*b>yl^ zX)GPq$EA0E7C>GpH~W!dD5CFgmhjnP$bwq7mC8+AL+#ln_T#fnd`zkz*Now-hZO#a z8vaBBh~kepjvCZYHf2aZl@z}od}$^>p-iep`!VEt1{>o8urG9x30K8TMI$nX%Rg45 zdco5}_Go1GZeob>5)q5DrdPzgYev}T_qK7lPO{ras&;#NK3L|WtG-F+v^rt4JGl~G z&B{g=c@<_9B4!j970N#8gf+Suab1+JxjkgXYD5F_1-QpnC?+3r(Z*113aSMLjGrtl zE*$A?VR7{>99Q4O9jjL+#W5%DlIz4e@QA+p1tgF2x=A+g=_aYX3*4|Fh5twmf1&|I z@z;_6$GE4>Z8O4leoo?~XBKhdj`Kdp$tJzm)>`h{aDItHhYFl?q2ER5cTea)nha~P zXCX3nsq?(UM8!EX7@DFDPoc3z2qU4J@Zyj&)&Y;faQWrV8mtZJ{a}OogNG5U_s(=XR+EQw?ZcbaOdko&Ryaj ziWBc{pV=#_ImfCFQLPz2s{cB7<;Y!^#T-+35j2wM%8~PXqU>L~!`N zyC?U(mb;d&$sZP`xbC9#*wddXL2;OFW4@&UoO;)bK4MTABb>;i$AVek7oRKC)by_* z63?3X*GP!Q4xee_9J-BMnlX5$$yLO1ILWvz5zO-4`KCI(WU6+e?sISZ>%FE5VM}5y zJ;@m*$Y6y;XdjdJb(zqw^@t=&Wl?4^`EAw&%oVzzr6SyDsoB?uyULX;R2MU^$&vrN8@8R}c$0$@nhTKwG>2)~!gK0piu%gqO`{y5bi65P4RdPp zpt1XE53{scQC?TAw+NZ?4A7S4Su1knSG!>cc;-nXgLy3s zj9P)sbR`B8tNE?Qt;pTr)ywyFjoOPbV7>?aYfJax=9#gh&yIRywmj4P+C{Sodwd6x zUDRC{kc0{sc*N$5jMGC8TQFXb{wWD3qPOQmw=wCvamz93t1t#ltb~)-kXn#mAVG+CcltUgh*mB=6B5^uic@z zm+s(&K0|+xA#G-|TA?XoF2;F+&=f-o|1lc=L<5N8?~qpKTh0m>S*~!=FkWl3rXFgu zw6K0JeRoPTQ^rdcIZJKH>%-K))8}OL^>5zEiA_GP((Pjve{A9e^fdY35rY%OZ)SRD zxK}hsIBY?FW`%cHFY-EW{LBng1VBH9&4+xxWZAFjtKlX(bL5t;GfFu)d&^mdBx0P- zQRRdSan6LuVo4m!oSBl4?XDA2_|pk~ZlWQ?<^FTjr~*@Z3wS9!>OZcj!zW_?IMH-v zY%-SBu;%6Z7-@D}_fp*j&M?H{e?$#`q5(wlClA>KDF}SKDM}Bs>^r7ik4(=T`Y*G% z;hz^$PQt%pk^iCYj}4n;9dEj5fL!Fr6^OVHke}5FX%O5UK$-z*)k|}Q^MB;DpQXKZ zG5&!`;ZurGpR7x|s28Txz2J|(sJG{w%5Qno@caCX)5HD45rLL=YU+g;L(bI4zZr9* z;q4vyYwEt9meinc4czkv{(gAch=#q>epR2#c|VawQvq(re2Y7dVaE49gB=oZdh`WPN6v|CUN%%-*_$WoX=+2 zM|Y_2hMmYGQp2EQd~+6H)R+RTLz(P!VHx~{jp1XB`E7b8?w(r^>&jW0BfrzBtJFhZ z(MrhReGRbxTpIpF1Bl|ExI4csi7h!Xw?Jd%EU7nE7T9V%A;naYo=9?Fk-zF9t?>{n^k9Hbt8R88*Si?&tUID?67yT~m}8Wqm3yG~ zQqjIp(sXEDtT8kjIZl2?mspTDQeRP;e`{O*KJa#{j9U%^?^`e3yl?Cq$U2uRI(3^! z;+AwWSPjO?sS;OEh}lAAk3k~V$%;#9`$Tw=#>#JX7al-%nR+#MVT0x3bI?u8PgpP3 zGhSMLY$IugV}>34PTe-A|DkEd?cA=i@}0^?aY8`=GC6o(1MpAL@FyBT6#uk(i6sA>C}PrLLrakc|X6Xe&T+19N>zh#{ri9AMgFH-@RTziqf zl|$rJN<@5o_Jz2~c0KGZU1FW?V%+47)7*6%rP68fXXh{4jr=hX~gJ{#FpGU1~UolD~)T(%XwP@m7~JB}Eh<5(j$Aqrny>huYbAC2ZS znqc9JKGkP~s$9|4oL|9n5S_J|B6ey1<2n)c|B9r#4nG*dVK{VEYjJ8@cL{faS!tvY zf+mTFMsdnIQ(_&h{v*SaMU*O~;mAkQ+n(A>bG;6KBpmT$tvbNFp<7=6BoujUjl_cb zp|$=qR>PlY08#v@?urNxNM|7r&Iq;%+Zjm=qz z8Xl|){nxDDGeNRkv?9(Y1AT3@+JA2gAM`h1tHH`|w_Y@H2B}c(-LdN4o5RQ`apfxq2oAa*+RDS7}A8&v;m!r0p$ovpT+v2s6$ead+3()*gNbkUk6LamJ^LipTJ~g8=d~aiV zvLJG>NOGmrp_TtXO~apP08#uCnPhz~2GWbv? zpYjOjE`&|j>oL5c@An8`jF>NA?eJWaaa)f3f^ryj0w#x`nYSA-mb1l%=H;jw=fEmH zGgn_U8*seOd{NI))e(1{K`O#L1M(yv?jUPoR(LLEC6EDmTyJf`QPd$Mgf+`f^9L|- zS^>@T;Vaq>Sy*fbns_?)J$!!qNIDMpXXFz|hg@0YU#fRWgjYdu4BpZIJNO?rX!sKi zAd0`)f7`R`p54~xRY^HydG^kHULM1TyleeGRK%=8Z!kX=8Qs>M=M07jCqC7vQ!{>I zUcJ-?dC@d7FFvYz-)Jl;tATw6-O$O7QZFrC`0+~A@0Ur5f}-u9B7zcx~QnCME7U+SVrqdVGSiau#!tnQoH zzvBFYtG=c4PVQ1ud zt>I5JfGGaRq%2!|^IE)!t0~fvchAy#@59KJ@6BrweDs~7H$GE>n^3!}N{j0`t<*66 z=6YjN__Si;>W#_x6gb3P+<{~5^~N!EOhk+gcNRVJfeZD^Zp8iuFn&!-%}bKy zHljg}<OXx?cI3c!_>2qY~!iZj}( zY~^+C^e{_j@;#+Gyx&!dDuelu&A_s^P-l>j@2eCTkII5~&8J#{@f0C}wCQT)*Dg!j!Mp!*K2FZ$^z06H6UzjX zGdPUeF50?0|E9#!)~z_EyzKc1@6{eI<>ZQUi26&a<1en%KlUIu!Iaq=W~tUa>sL}c zKa3gV3h#QQB7eQIIsXmZ={4oxEceJfzkA-=MQf&;COWd(!!qK_mgLc0wCpa+-a4w( ziyBVqv++8Sp7P6xu>#T~z{6ApMuA1Q6vh+Xnb$OtwfH?7_{EKHuK$3rH}VY=F1 z?%;RsRMNpBdKfF&V%0e%EqFvp^^T7S6@ipN4FACOpG*yZq5<^d-*$W+Yy0wU6a1kW z$eR5$^6iOOho2oXZ!1NN|J`NOimCEn!MaFiz2I0DN>{fcYJ>EQytHCAlfPFgR0<-$ z6S(bsQF(XPQRVQS7nOsy*%wCodfe`Y6W%qDcbaZ=uVJ!{3GRP{K92A^QAM)EE593f zKk~o@iD2`+9d=zyod_a{(CW&JhwPk3aavUDI6OyUohc_A%%aI zhCk5&qWD{{X`v6VY9T{k8`?q-%PaI(x1;5e^!|3txL~$W>yNJEZk&B#hS`x*54&2o z*t&U7l|{rAJ+%9UQ0T_`%VfPW({uar%nO?XkU| zfgvo8dgvm@Eu6Fz>27a0Jzm_Ak2FYXxb&8H`YhZz4iTf?7d08#u$g{*rf zIjO2@w*39eB}p5U35@Khx1D>GT&%u*t}NudDH{}z!_sl^-Zp2?Q$>;hglaFw&$ddNd#8Q#zuCmKK$|ARJaw>Q2f?e49O>erp{k#@BoR4N;>?&8>~q_MmMT>5p$sA;NW?u+4_ z9WD_)xpdiEyd29|25a6JFu4Qr*#Im(p6o2X_1R_5M*;^d?la*dimRwM``)vB1-FKi zZJdz4;?kr0K548zU;uy6Q+YR=IUysr1To&T3|OJAP&YiZ8L9V{Ejf&uI%)0vssuE_v!zZ*Y@pZN5bS#d% z2`Qqxc=qWkH!7R?jmnl`c~lB%(7p!Pf8#X#i3SkG-^-}gn21(S=3Hp?Y(Cvx$0K5X zp&ji#+AZCVn!JvzyF+Gm9G!=8^tL|zUvF#)@fE^$evOc^;*zir{W=N!3|caALi^8D;Ex^!d{RO1Rh zKA%74KWnjVoGwGlCP@2Zu%D^>hZO#~8vf3!@Tc~Li;zV_*DpWhXa3Lt8n^bvaZ z`pJLBruWH+aZhXBqk2DlXQD2sZ;P36_WbNv9@!YzNIEq-{KWaZ*p6Ck9mA(0wqta-$+|a2*Em$74V7-s0G^9T@CEXGBww$ z{u4C(i3SkGpP|xfk)%~|BQ9-k`=8#e=oc_i8*xXv^czmg;;An(B5r*c(!nT=W# z+48auI*-f8Q9SCNN%o=T|Cy-aPc(oi{wJG$_)1s%pS$0ox?b?0h~`|iE=Qr1E#Hfb zeKVwQ+Lv^A4ruN6!`;+!)NWnv$HCNo2UR)}P@g#(b00t(dplm*Te!WL@^VY2EiLVJ zz2}-&?Bl`8Yo+*84mXUH7hzZM&Ih zxi9m+A9=^m;XI-nT+`O?KmBHf5Pav2-=k(_V5u(n7V?ZRbZz6lYBuzKg;`JHT6fk3qIl|_K;bAMd94{hE3J)pz`mIWm)oT zo$u@wo!|t@9f}Fn*yzlY%DXB;#vMZNJw$mx3ouC9L+6_6ww-G_x-Lte)Mz4_L4!8qR1w2-lcP!IY9#^vByiR=u7$|Y3-N%~>9y;DM180|@)=XC4 zx}^cWp~3qaF#g}D;h%OD{#0Kn>lrco-SfAz1=8)ucH#5(V=>`(&fmedRo_v+1D|)) zXEeskZz7UA9ywD*F?rw&Z|AsN9nfey}2IJ36xw^mcH<)wS$EFxFGkz%~ z8UMgOw;j{f>(&@QHxA=}#@)$&$T5-0_tx23tL_-Q=zquj@B145L<5NSfAi+8iX$JM zbIbF}Z>AH5pD8ip4Xvw}0m-6bc!7|Y2V3bIW`<_YohK^+OJ%QUDmkhMK~8?`NIF_` zVx4xbkc%Vl9-nO8y;U*gkr&Bx_4%m0ohLt0YN_PpTi*VHY(BL<6t9jwg?6gsYj53| zXKOCP9S=-9s+g?qWU#upEO~P;-NCw>Bn(jjShxOt&s9%$k3Wf%o#kpJSj2$ZTfaZY z+mf(Al(OW1>*cfaf(mI*S2lq?QQkNe`=GLnzk;TI{U(=k>;*Z%($_j#p|qZiRB8X8iI*W>x1Ts5RE0Z zY`M-|Dt}gvh%Nc>N<2jo?*81ex9}YBMnAm_l2^=9+`#g^-kOV6{y99+(u*eksQi98 z?KkaWUBm9e)xiac<#7a?5B}MKd|emcVmeiHfzxqvZMmy}n>4?faol+0uBl0R%}hVO zU`X}<$r}Dd1Bl{3wS_(WQvSy+4@uA0jV}N{Rx(tS<%1Ex;K>mWUDR>-n?ocwzdMiq zngrij##G|dvh+N8YndLAfZM~f+ngnw{J`6qUf2qK5P?1@wAUh&j}SnQMh?g#JLQo% zFwNsDMm%0`yYcd8=-sH>gbe?yMNa!3meqqyz>5E(h(Hl zZEt;b8jbQV;!0WaFBNm8zI6xYfn~5M0;*QP2!o>@xU)|~%z>4Fh(Z&xfX%+-z)_DP zD^#ITsHeGM4@Z_@B58bB0(Q|g3dv@vRF8f9mvWmf}QgmU;?x7yTf(#3wXmg?;R zozAzfMW=cIIuHJmkg>J)K6C|{o324-!v6^wu@4#FNbSj7Qd|4;y;q*>!&O(F3_MPG z&y^=DoTyeQ{!#SVAbliZUU@hqhw59CQx$Tx6*i&rsbLh!y zOVg80%{t~qRn{!T|ND~iByWomf9rY>V<10sh|Zus{=nVT$Mrx;vn?1ZxOwHHt4YdW zIV3;}6pT+6f&FKAfT&nD+L!+~8LI86P+nGX@qqK))_&+RaWyPE0*EQGOwEJ$ zr^e6855pGd(-U*4?tF9SwR&RDs)^E{_mV!R{_H`2UWI2d^xFWxP)7jmS$5)y9n1cR zyAaEP>P0>d`6#k)R@@_np=JO7K*OJC08#v@e;n{;0EzLvmK~o$zw*$pTLPa#zjCtc zV5<23U;FIwRoB?#dFpK7XEeX+=w@9b@?m|atb$!`*##S1_oJyPDHBRCis+2*aq^eY z`$d>p((LfSG@2cfUZ?g0@R#&{_s%L>d2IPFJCQ}3gr2J)@_5f^W%pN=>NBB_!A8vioa$LXUczvW+i*r6-Ssw zb>_?6SM09mSCTf>EJ7W|@}(-KSM2pMQEa@SKCA2Vauu7lgDN&O>h8Y=nb-d%GSMfi zfQH~xKI^kQXx^XEVW})EF^Zl4c|~`Tbo?3i$hFc@sXoCSd#=dF(rcbz@zBcuh^5Hr$S@W#j$JS7d`-B^zLF%YRk%x7OdU_6Bvf?}qNxEI!QX;SKW2 z%T`&oF?rJw+TM4@9MTZ5-Cq)+BVx)r+nEVwd$^gZXt>g*D~ukSgBl>X1x@FyBT6o0S$%ayjaNn@k7 z6k+thH5kqPPK;*tVdNfuEk>nkPrVwW-c?bIV(!e6SM*^Ni@%@h)B~fIBcC;`6b-HV zrCXJR8zFBFc%PSAt4*@Klk`J%`EarPD|o4gVfz#CPH!sln>W&)UzB^KxBOBqX$}TH z2%e;9JnWHPRTfFIf%9#&*8vX**y z?h929;m#SPpP`!zp?|DiNhhCIEIY|NFbiIszF7e>OZT*Yt@@D#66xyBSgDxN+56vfkgR2(Vu{!9axv5hUJe}>2cO&&Qut5T@FyBT6n_)2DD1P+%lfhSGc2U&%0Q<4AHCmY zrGMN3U7#oFasDFvCw1 zdgH}M|Jsk1Ix4iQvrg!R{t!)Wdthwk?5mb?KcKrR_@6)LyYS zYn_s$1Fsshy&}7{RSyf`0OY8AS)OW5OorFJ>W;USokHkz>1$iF z2yPC|r}laKP$?EXrrb>VgsM?#b#SM;CpX!$w_a&LMX3jX-xyTj{l_SrHIpzk?KZSN zaL@C~rOA0Mn;&~z7AW6@9sU`Q?R8!2fvH^UzPx&+d-1H6eK(@+=tWy|0nTSPgS~GE zDGlk6tf}>iJc?!2E0;d3SCrShZJ{DugR$VOmZwT^95dBbBiok&>%ic5yT`!S*5=y8k4(u0-f&6Hp7 z;Zb96=1Rohq)`vI?6@Aa0WTF(TZ$!Suqp+#;B9EZz>mun$AVqTFTfd92Z2j!%rtzm4_=vPm6&AQdXjy*Y^+?^2mkI@ zB$-V+b2`?qBxwq)G&JVic#QIWpRi9e@eZ#&79}-E^!`cq#hv)%-l$zCS!)91K7W#Z zgE~M0hu-bhoQ@+(ogvaOC)pLVv-1l@rbBDwKoi`q%63cpq?lT;hj|X)I?@Cup$Tl# zNp`LQPnLg@1=i!L%c-w`Q$p^KJr0#BXx8~r6GX2>2M;*$e_5o;{%?DQET`-!A5{3? zqvB6AfC&Bqvf!z5TFK|Cb>$TWX!{6X=C_J`wL?yxy>736to%1+rT@Qe>`eJ^|H{=O zEV_hlbp@Nt!lL$nkp!>eiiiUYNCJ`qBn@c&&wxi~KQLMhhcrjbJGZ8V#V6ep6ie<# zc~btrUd4{9SobC2DuKf!M~tPj+*Vv=P~ksI#h+*Z5&R>*U-f|Rmnpk{g!H`L8-2e_ zc@{Ld9Sn*|aij&V?a=I0WbHMd&nf@WlV9S74JnqMzv%3+iKyF>MspxKCL5O6tuC@B z#>(ly?XDO-ERmStsQbtoAx_7#UIF_}A9}(fSs-nJ2_@dCT*vV;?d>9JlcH0k{FB}Z zCFULU?%^^Xo{TF7UW}1s5pQKjxITm0=$tD&{L&(xAe> zK*gVE01^CK6DyL(%9DCa6EmdW;;-9!qs4U>$@Ws&TO+Yz?mkQr!lpKXKi$UNkszLK z6J~$VCfxBsn|AhQCB{OWKa6@#!IiQ_V`WRPx(^qXJ61OI3Zmx{t<-!lZ$0?5vFBlT ztoZ9ow~E%%LienTMzPRsEuDVxT8wzOn0wu;5#rA-Ms|?2xZ-C$kzKyA^0}T-Vj-SD z^V_|RdBIe1H z6!HI4PZX_9DF_>$z~O>{R+V7hHL6)lT+T^akY~{3|;$oPNK+_G{_4Q`*ZK&ed5&3U?;JSmImNSRjDHQD#eo1}uHKvcPG!F+XRIt>AHs-k z;;}Hb;!vYD}RNk33Xwo zansMCF~s;4(%d+Y&be1yHsDTj`n1wVSH*T4xZZ?qO&p{JuvPs(M1V^7!vAXnx~87R zu+rl(;+{n@!7;!ig415ykKQMi#-4l?iMkvo?)TEbClqUV6MMJnleq9nHSS$MYc8_* z>Aan+3D)R_ZevX$b{C9%RPZ_Q|H(t~bZ>+|dJ6l*=2{DMLcEgaqvW|v#ZzFG(R_Zi zI}UYC2ATe!t>RBKfC&CB#QvfOWHN62VnnqABWW}B75F~+&;@dttWjjdvWZk zjmQXy5{G{^Q;d`MBSSw&ij(g{&44)h&2S2Sz7p;W?e30L57-mD{h1m`C;et0)eAU` zK2zh-QqX6()BlTQ;qmK_p##KuK21n@A+UwrJgKO={L0(i6<3y+jK_w5t=0dk<0Zp~So4_D{VAps6`Ei5k7isw?=ZLX z+P8B%Tj-4X19O-=Ru}x@;bkR8C+`^2qTih@X@i-i9icMxi9v>mR}l5yf-B=!E%C;C z$*Xvy=kPLpgJ#!s3Dw5y(Rpeq?6-}*p;%OhNkATo1=XiVI*wf8((LHjXTe-j>kZR9 z`Q;@;4WHJ%%*%cjS0;yfbFQW3spZD1pDsstfI|JQQF3n2yQoAuF>Ng7-)EO5rhIy> zLs+nO!LyC=yY+*M|5c>oPc(oC{;}w>F-m^A*Al#Qsk8IvIl5p4#a?(#@+kRl{q`i1 z{N<3UbGm?CP+s25JW;$@$u?Om9cxMpQ8RML*3OW%zmBajP~Ol}Wfz#|5nOFqJ~F|( zLSLeujcb{LVt}9A%YBmFzzLe8V1A6i3-7 zqwpE(5M>?3>q@prvxm8d>QM{c0{kMiB!<*jI@jZBuCnucxQ>~HTyU3L@CqFk5w%K! zu2PfN)UM-9tn@GWQe5qP%)U|R z6S^LAiBFy(ndIM~&+z(KnoA$ys7(*$!_(^u&FsN^0XIE_-tkWP19Yr6TS=4S%qLHv zB5B2pvGO_wWLHwPzcqJ{f)2aD*8ky9yAaFCyFJDlXU9(_=xZ?>-x@0)VHa4UkL;G4 z82%gi-}kBb6Ad7Ozp3^!*7W(2)-~Lkch#ReTA$&bc^9>kl84m9ZpV7x{w_vzW}ulJ z`L2>xyvfO1`#F2A|IPMv^!iDQ)tx?!pHH7FKox0SAg-3MoR7787o)#kZ_nq~oLKX& zSGfZ^KzNX0XfeZ9!fU(Vt9?L&78yyh}z-RZ)a0%DTU*a>QU>g4X$ zr?}1d-h}V`#1n{EIdS&yx^z3~E~xP$AH)o?depgdJ1YHddWb%uxl_yt>7A@Pr$6fo zoehJCTc{)$z%G+`lDU|?=_mK!*9uKru~^# z5>dIwByWLk_dvI2`fYWh(&@J=^bJ${Hz!b}LG9mMmnm-#$Br9vo)?!%6|gU~?Xx&* za;E%QSPSi+BPrdSH&V@_??WSwap)4B2}`u9ho0su^bU`c|6A#7f#*2-T;pj2x(AB4 z1#GAoKcwBLPirw||GiB+VNl^eSH+)b01^DD|FX8>?`^_V?EFtCkQL4rRpCoE$xrmv zF)NTt@auMH(P`U;wPb@vwxUv3$giz=*AUa<`+*a=04M&r`?>aMCZqFOALcmuWd()$ z>-vjCKckf%mw67p0IG?-%d)hbII?88^ghei@fn#db4#2D_-YMy=+Kce!4h2b8+d@` zGhilUpdSe5ohyBhs-&OS@Q!FymzoEi9)7zSYx_AL8lr8FYTSzvy0z&czvl&-V^0{O76o6Ad7OzpfoMlY{c2vn>Bvha`vI z>iWD+7$;DNm)muL>?EO~;L1Z7bZm7b1M#@!)x9${YJFTQji7Q)FE6fm4d~uRFu$ z7EM);?I_NnV>5B=lZaRwW1_d?l6}~}*|9lmHq5(wkuWDU^9vdrs zXV@C;htSM(_i2OPgk(wFGqd6~5>i5$`&#z6*>NuJD=KT^ynG0d|UwF;U?A94-6>j%!fn zN#qJEe1xB={VZw;q~K_-Kc*(%JEW$PJ;o2MIaE@~9_8clY6TyQpGmy6236kBc`Okg zVq+;P(Ug(>Udik)HM62d<1wRXo@>mD-^^zYZIRGPY^L|u2k8E^ca1wiDrCr>@L6RR*vc=Tf)V(qt#bc6NA3O-52_@_2VyD<7?EkB1%h zKC^l=<*9vI*m2Nb50i4U0|Os#b-+|0AbSJU7<91Z0B@%e;D^QFYpt7@KeTk z+!Rj!uH0vM)GsvP+VA7qUvijnbbZ_p=NC1WEB$STHE`a8B^LB0qyN|XRvyu4V@w_7 z+RgiQga5xk#h+*Z5&T!!>e!>%)~)dJhm&Ly&eMGNVAg`Z~|BhO@9Ox%PAV zv*@@+D>`cHEiFfZhLQGb(RI8AbIB;+8i@Z9|J3Wk^Q_2_E{9rrh6UD&OW;=uqS0+$ zxi~;a(3yuy=y>&5ZbGJ{-71Hk8}Rh#&Qc5Ju8U;EF6r4sbhL*|DM#&(O!;W*rSco~2)670B z&y@er8&yN2f6~h#3h2<}ef=DFima+R2Z3wCF^{8?WozuH8`>4R?dm+>?L$z3lYDTK z5VuXR#ks93Ey1P*nt`1K72PcHy#QTX<#l+m^O&(JucWylQy$(+lHipN-ie;jkLypr zt>la~csNl^j}0hNWS7>F3~c${w}Y$KHnVf!1k`x6?V?^p-1zW9G1-!2sXjf$V=mKHLuaV-2IqvM&D7zJPAVtVJsqVhHm zeJyycHI{7)-*v+0`YyB#oI%=`^SXqRKayA8eh;ERvobyMo-$61^6CS$@BVtbkBi!z zsl;XS>#c~q*?H zA5R`sQ4b<~M)MXkyh3{43~ZwkYDCAIOTsTN3R0c*o%r&Bjr(H3$y}B|7uA8 zue%2o{tH$73$Mc;=$V8xx3aR7QNoyxlnu%#We<$f-@Ao0l9m(w2TS}cfnR;#Pzm)2 zT%oKZ;&FNB!m@%yIOwWKMm*OA9owyM-vq4x?8?JC>+3V+w-t_ozWod=^?k1Oc-Ig7 zcOe?Mg0Ewb#TlK#F^^P^y}IzF=$eLo@02(@B!{zOYPKq=UlWbTUbPXrLm2OkONa>` zagkT|aW}~c&J+hGi8jUvPvl@>MY6+fsKFk#j&`>*xvbBEOh zyc`&LV~oD@TiAI=;FmwgzNyWWf7LCB&#_oD^?H1bS}uk|%Wwd$LifPaU6e-2$q5e&pwD z%M*q?HEJK9y*{_Ag_n%C-eo^=T4>}^>WXk{91v{)%2;AMtmx>+>kXgXA zhvlP$m@U#r!cc(-AXi@tnbP>H7>Ob{@aI#!Qpa3aV=E`-8IM)l5c!Q>Iro8OJ6au9 z&5M=z84e|NH|}$GEOV%5d>}fCQ6=^?FGdFpE!cekKg7^-2tPG`O@My4w{W7C>`KGc z&hmymo%SS4uzaaj@=DJmUty#i=!f^PT(f&n;lD)1pJ)IP{Q2ausHI#8|9di`{n3c_ zFY{}6(pZt-%|cdK-d3%;?>evLY9`2{3#bqe{SVDt?zTyqts~`htTs9_9eZ!3I-emK z{oX6!g?r$&uTHzb*4z%=4viq7{;N?Q0dHS4^7aWhIyE2f;(j*VuNnG4G}8Sp;5T{+ z!*39lOatFn1ZvM>r#OM5SbqwxQHGu31YE<4V-xd5oE>DGz1z>*g<}>VuFe6HAP@GF zG?DYt#e+Y2t z=a6|*?!ivky?<}hTPxX#EIt`H-WxUGt6Mss;F?)eRtENneOZ>^%thMG8dUL5!)$s2 z*l_Y^V1%p&!ZS;p3c}klPkhmYFnxL&pPq;|dM~gKqoeTCA8p3ZGtnmR17H&&(%}6E z(^`p76yIV5mncJO56$l;)*0>^Ex>#6MH8c_ncW%F%vkhX_yKFd6r5QCA3(6|s$_S$ zo#-TPd7wLFgn!_hxeIK8rs6tw;z$KDP;Tb08~neARs4wt5W(L*WoAqCz)o2icG?~2 zxv6!l%sj_=+Cf8pCc5vS3-iF=W6_C6%O!$6$>2xNUxiZq=n8lu*;CBPyq>&1vK2_v z|BMmChV;KH`2%#^%#q| zvNjmoO}xo*E3USPRkHlXkE9E2Lmi*6SA0XZ4Xd?Qo7;=DpD>rFvUMmJ=Gju*7IS-p z4$-6Ho{+VRv#-Qn|ICN2V3?)ADmaN*!+E|Bz1MXCGmGZopu+zV6@Q`uMDXYAkN9Z~ zUvD3c1CM6KfPJLe2dQinxO}ATiCdq9SZs;sV7n9Xo`daT>`Z9fC@@9VL?74N%`Olt0bfZoRL}u_rc&-JA_o}ltOU$_Xw?<64 zWa(Vv#PxEt4%#PJ5ylf^^XumQx?%m7sQ42NAcB9PL^$TPjCv!gj^6_8Qp|O!6ND|M zIw0sE1cBUa6}i7d-x6|9_(_7|Ge~suzmH))L~vWyLY2g5Mh&1=oFV@t{KQCSR?N9a z_bCW;KEXTk5U+J)$g2s1ndz`Ugg~K`lXcH&RGI$(T z`L15F=YM*Q%@OkgmXfaxr$0CZN{DnT21UJ8C}P;!F>Dr&uikJh2{@_1$N8k1(! z8oe*I^G0)(v1S@PIbww7|0zS3`VHF<$9uRAqk9yi>n$xE?VK9tsbocWpZqAQfv%4{ zarvb%XMeB7T=QJ6p~bun@4BOQ+2yTx_b<@XmzN;QKSp0mmcAEOVro6j0#C!f1I@7;nq$cd)k7ia<5uiR(i%HFx*F0Os`ObhGec&|J{A5ah&!#reo%3Kf{bc# zh!}pxZtC#wjq%@Ks`wKPAcDVOk5M9~cEoAdAveao$}ayCTtHoLQ>j57+I33dd4q6i$GBMk_KKpX`N1 z#|o8>;HTbOg%4JIZwnH3kFyHmlZ1hL<5N6 zulmcAudux&<4<;zy#LQg_6|C|<~|CB;4*mKy5W*m;$F0aNjDLDD7G+SYer&FyaZ`n zUP2j~f}SiyLVi=9fNpM)h+BqS(T6MOGZYJwK3~&U4Mrzbb$AwgbhCJ&!J3>QuY`Y= zV6>tOr~|PjYqDK_9!%q>{eP6^!xw~Ka-API4P3R4`&B`A zO;7)swkG~e+k4b~4v~j)_cY9&PrAWi)be&0tcmy~gG&BCs^U*HfC&EDVD9Qjv?qi* z%QQA>^u?<68FE@aL4^hZU7t_3aVceBTnJO*{Mz=CXpDC}x&&%T)*flShr8$99m-GI z`TY)ZK^<*5R6&0&u4b-BVowR<*JD4fK+fi?*@NgWG|6VLuRk`yrU~%kS{om@-G&@) z%s4e}!-?z?%|@=9W@cYkBzCj0Q7ajx(TL<(z*Css{q7W#{?-;^lxCxf%sFnlB+9eG zK0~~pUKLysXP3|2AM~u9ajq&?I?Z1$Oh1{X6X+pn3hx`*nl;|CowD(EuX& zn_9Hs?+T*36t;h9)WCkcU2-w&ZG7hVmVM|3b~wmClyT0qd>wXwJ`_jhJ%FxmA2aH^ zKDy;B`;-&*@Ln7GcxK33dmX@kwlo&VyxJv5QBs^VO5(R80)ri9oBS8xqV;oP1tM2wY z{=cyQA6M}w8bAd9?=C&my+JnE4d?SQ)@R`<^@OH&8`3|&M1M_G#_4j4dd#qM=UFvp zmM8Ph&bwx7Q#h<8Q~P>UWYG#bIT4+`1-tPWass*1mU6^t4E%glb`q+lA^yf8pJM^X z$zOGiV8ts&um_4qum#ZJe9Ifs?o0R#+P%&Q9l~j{e*s-^xkuArU^|LAFv^^gfz_=@ zmc5AXN~r3BT5er<5-Z)C4|-+k1^9F!a1z{oefo{p0z&@- zo3U3jGY>R+q!xCD!|tppM&fM4Fn5e`R>Yk3anqzkNhg2QPaR`kZ-2&|iI|>Hl})qD z>%y$K6LV|LkrC`Sm|M?aZW&qxaXsT*>)D;$ddQ#q1FyFq)tcKie0?I#v7e$Y^`OFk zC4k4jh4_xFf7nIsyUhl6q}afY9zopH>Ov3Y3^}_er}NuIO21Y?v<*pt{H_<}BjK%B zL10y3h3Wt03VRNp(Q=FU3`(|eoplja7Y<1Sh>Ftg~L zYx683xk)R~u5YxIoH6wDaEX@^&^;t3obwyax^ji0kH(Js-hW5O}{s7K)HAt>zi!a~s{lOy5e?uf{!3}iYul|{H4t0W zJ*|UtPwQ|l+`y_`Tv2 zGW7l|8<#SrC>L{KHKYt`K3aXq)3l=gb5fXWfC8B+JW_nubCmAkWdUp9KCb;Db*cOx zR~96^7c-l^GFcc~&h83W`~@;<434GqqoWt)aVY`=SLr7Hx&i-RsrVBOAcB9(01oe6 z!yywmz~Wz5R0hqt8k&eb&qX83Bo+!UN^^Cax$*b-g&LrW+Hsr-^<9VfS#-U=ihmk=j#Ye?_L#0F ze`<2X?k~)li{1ij7oB^4s`Ion?_=p@X*aSN*PJlyisYjjcHPAA-x&XSLdBnG01^D} zlRgEmOQjB}7@3;<>}W`Wo=|O9Y(QV*+4l}C|GUqTjjyl0fE^rYS~Ic%a73D7|HrqO z+If?)-EN#U^{*|}``~d|>GST;q23>_S6BpM+<+Y})bJ%-Mk}y9Uh-$$A@N*piRNj# z3$CwM&ku&*-Or0*>@3o1KkW}(QhkJ2S?uG)Ld*(&b}TsP9BMhSOMcA5a`=VZdOd1J zP!>W7B0gM7SIC1s0th|37L_D;P8%?YLcl1Bs3|5i`XNIG75-1E_!A8vg8$iaR{gOCi`fGUY; zrCH7iB~`g5>>6{?8*=rh$?{&uv_8Qdy2QIVk&dCR!dK6D{Qu*O$JH|iEP%>Ao$DWc z6p<)9_=h?~ayYKvt|7LtLv-I3;CF`MQNUmcWZIJu;U7^#@d>IrTX3a*QHH#Vz22Ux zBkn-yGCN{Hn+8|^uV1V96Ad7O|NU(yy+k8z5&bS@dPqcxMue2+&&U_&}y$3esE zQQwcNYMsf=^dY1EQE2#$Dzgd}6*9c}J<*Z}>(PVC3&UZNRkJh9napFSr+#G)q&}kU zea_CGI-Q*vIq($8TjZ76KEP0$oPc`Yw2MgD7#VUhQ?t6SULQO^?K1-Qn5e(o`(bFA zlqq|`Mp3%ZI;30WJG<9yqkVt`xvozfxQ<=!M|@xVjB1MvXp|`RN-<-cT2E3CoFPLJH#)mFG-d6_Vbdvgm<{zCu03aV`byj zY5`g)zeGN?zQh8{Eu1}ETIQzcQH_);PwZb-(%2rJ%(wIWGPnN1L1daC$HzA1J*R~1 z^EAv-mpU(FCQ_fY-7y;J2meLucy^T1Jq3jftA{zLa< zElffE&mWJ}!K>qW{gKHlQ;`4r<0D_bwl~~yWkH#g*Wm2flw+3zj1#AK_#cLMNgjnB z8C)ECwYqtmzqQ~tF4HNWE%&wN-pXZmLT0aD?Z7_4rrcvcJoG#C5RenPzzJUI>=-)5 z*>UewXU9jAoE<;>%!r6#H(17v@sK=)$Jy>wEm+BKYvV=K2S#0aUWacjzN3z_SK@_T z$615+INS8LKKOe#7~pxwS#=Ru$&&^Z{!gj+6Ad7O|8ce>^*F0ft!llC<7{{NFxKGQ z_fI&^KGn|XJm@;k&cp*V4*c+V>aq5?%uNZW9cTVj9^-uiWBB2umezvF+*ovSEPuCk z%5B`(&KANBEN^pdYZk{#Tx!<4dSsRBgCY=HuhqAEG?)X}qdCrwOghedc!H*Q?bdMU zcEpEE{Z43us)fQ%yF7&%+dUjI&vZu7h}j9wpN<&fVEy5DH+~<{#bfX1AYOT}xBIqE zi&u@<0otv@jBx^goPAdk0?c_){}`1+PDH_y!mM`)L(_q5(wkr}1gU_|((5 zI-1!x7?*zh4(NcivzdLW3u8pj>5M_IyP2KAZxN&J*HJ|O3!GQ8G)4YrFZKc3LuJ|; z8+dwT|XSD>8wzDN>>B&(@h8C9dObZ&M72?XFbUZqpDSu)?~X zP3ZLZ(YiI2QC&m8gG%m-A9fCPvHn&G>`1Frj3ko6bjKto%yHAdu;=5#hKRNplukC7h&r+|~U zdGZ>BT^h%r(*Mt>_!A8vf(jI~s@SG+#cVQEARi(M@vI)H+*0>8g*XF2xAI~?j^|~3I zCtP$s7yMxnpVGwE;2h7hO~@5#Vw;wpZY_A68$Yw)A@v7<{s` zi=y;LTRqOMP`wf@)|F_bk`nJB(#gx+Zg?LJB`=jMa;L~F9PuVf;2oC0J8Xn^_*56g znANjt=&Xsq#95_>%o3fq*qtiR>iSpbE$C9cKqKl9EQa(FS{AwylL+iXom;2LUCM#& z;6Hli%uNjcjq%^LD*i+Rh~OWIx9;r}frSpL92TZhO6+&s?0-OK-tH*qE| zS(m{HBGqg>eQ}>Ok7>tpnVkFqdN34$gTuup9t*DE#&NQ*jLUG!hswYWvvL`n{LeD= zEQk2#i~GR=Q_tIj^NJPgG4a?|_LxZ5dRaMhN7+{PxHV3mtou)@^E1Yt62`vMohebd zoc#N8^;%BRd$GFfL8}pcPq3S09#r^yRQ!ns5W(NqU5Fi+zXxdK*OaA8_kn4r4}P(H zoT`)pi?dW4m` zrU9?|A6@G(dPQ2%-&gC#=L0jLaG-{R3$r2UC+sK-ahG!BQhGKQ-C=V#4{v}oQ{{eZ z3`rDuz`gC3Q(p@LmOs5gG$%;QH_R)70)t&Vb4`e;Z;pcN;f;{V8&noI)2#_oq zRO`Q7#h+*Zk@c_2)O8-n)B#!i}UK3Sa1X;0AkrUeB7swMbIfu8HYe`}x(q3_nVf_o z_J_5E?+B#|{1QhZGJ6hC_rC}K(Z*%$WOJ?M$kTLvZQ?k&uZ+$Z)nKS1%uNncw!S)E zx)s>p+uhtYYMPnW|}? z{HiB1PsAHE%eEe6p5zkhiiC1ivKnzZ$*3tTBt~Y*cA6#6E3+gDvt+q4OQIW0S7!;$ zkoUSw+b*=lIx5+nVq9%yt41qIG23op_;0lTDpdT51`xsDT>CL|`TqQ9b6YfW?$CdM z#rwKKzf!8S&nSNh)m5!AQ9H2O=0v}7FLvR$tv0DIbeEDpvy-_v4mme3l#y=DNTPZg z#Q(R;o4S@>ttVlZpY4inm?q7Vz74(HO?z~Gp~t(30q)$#*{GIt1td&1K7E@-?I7u1 z!CbF%sRzEK*`rDs$d{$&&8n;!s?44Y%$$$A|M!{Ghn{n$>ZOPgE-k{-EvaNXY+!~% zwmge00~vK=VTs%~$m;(+tKv^IfC&C9oz{(gic@aH3dXuuBmjphtJkEykU6>2`qnix zOj`(#g#)Yk8XhnFKk)by@Ss_;6dCzDY-AlQEn=a`gvDzSELi#moA_i0qX9kl5ohJVJU4vMBsh z%rfvrFvq}KOyIr^@t9>?+L^Wl9`o$}LACy$Q}HJnKm`A?uT8vRhX>l#I3-S5S!C^J zpc>CS3D!P#1<1}{%|ml@6qPMREg;BXF0}zN_?50um_0A8d`u^izc#1r&yT%!RqMLS z{;X)-^4(lI4_2q^q9u3$sA`prepPF)2BJIWRI+*?YOKR%fwgeJtpR_aGlX0(r5YRgW=?r8vcsr0TOs%1m#L__NmUxh$i3mzYIFvz zp7a=ZS!+6kc@lN5XkY3sWP9hqZ*+{2FC#PD>&=%?(?^*_|9o@QE@-NNF*|jy7W+ej zyQ($X`ay|#r?Cc}#=H7j>=~h#ZC7XuvIHLWza&NN$cDWCCe+_MY8TC;8JI~!F_YF_ zng7;+_Ccq+L52T%6@Q`uMDUNu#cx8v{-_;`m(!G%^zcKRjVRPLmVE%3Bbtb~!?+yJbOe?eOYcucp z+6;*^q{XDvbom}#nj^aW$KJv;Ty;bjDtAJ2F9?%$(Eg<=2|yqIlAeO>j!E!DA)CVF ziB3X{e%ZD={8bNJM7Xw%_XF-D$;T=p3GzFtl=29*EpO*{c^u>YS|@h2KU z1pf)h`)ziOktc?;&6Jb>4eBl*eHeSfI`F|T8}_hohgGugQAf`RKf9T_=dFUKT{1@g zu-^pc)ih*-c7~=R$6A#KBpXO3XsTgh3nUNLT=ndEJLQ@F7_(4+1hWoU^9K<%dgans zAf)T<|Lj_9^7w+X#wzyYZ&C5BJ&axBa?h4!F_N`}c5*x(+CzGz%!^k}d2yL*IsJa9 z%({$zKY(aqso^v#+c@vM^B5BkGG=K>HqFXDT z4A43{?(vs2qOS57W!w_PV*z+bW8*Swj>RQg?L(!6V;fQki=h(Ldx}e`MTOw<7PG?zY}jxP0C| z>$3cPu4Q0nAM-A^+D8Bn(LGTtSCG9!{67J+5_5ERHccSya6N-=LYzs{cM@Wafr> zQl>-1S%V7yO)CCG1Bl@Nm%am%luWhO%$wCpYf-^37V?f;py4OG>2D4i`n!+_W)9u~ z1M5l@W!uY9q^Fx%iKQ8}7UoLna$cB@mXbNJG7Ps=vQ*BnOQ^9@?ma5`Om=JDV4;_l zxj}lM^exP;DD-aReR}@PL~+?AeNb9yzHAbVCFQwBWe$of(S39QKae#5X@b52V`-Lo zzYD#MUOocmi)|%!9}?Yd$Q6%~mv@uycqCH4Aa+k@p5=7gl4)Kk&O4-G1~Q71VMm z<+R>V4eVx(|HS?~>~~=2Z`5ucd00cMPTH>wu3K)mY{v;4YAeGM^H z&W_(quwm8e`(n_q=~jPt?K{xjIzQF%OmC@SyZHPA4#`r*LV5jxLmv-xZT%QsTYm^m z>+%_f_-_-322d?tw7TO~>H`Jxc#~S68g=SWnI_Mo?n(2aA&@0Ts>*jKT*NW*fApSX2Yt;f%bVEFb8}Ghq$KJHo@7w1{})vJi3SkCf4cu1^I<(Z zeWuO1`;6^P$gEw%jgc4hB3g=f&#^B8%}fmZRneZt_Evme%&h{hGkY(z89!H#G4h=4 zZst$)?lT6TTlspsU-KIJ2UZsEP`dG?p&QQ=h_^YB2WtEr$3>rG#f5WlY$J}n3zetF z$Z1!vX4-O&9dXq#PgM;osEc6v!v4cqjRxmxY}Gcs_FRm5@PC~p<6(F8uCh#n8O zOI*tF;;73SEkCg~HyvGz#!L6$uA+BT)rGcE8}a`_9byL)R*Wi*#eA_(*HP?zpUwT^+Pi+`-8If4tf7y3OsM937ymxwpGBXhXW5nNSs%{wRU_LMD^WWOcSvMNw}cE~aJ_dJ{qa_l#;-G@A3GFLZJoI+CV9 z?lkvyeI+6W6eG)5Ye(z}-m>7gjayd;?K6$*q|puWuumqUS_li>kGeDMFOwWf#C{f% zSnW44{5RVFUKM}Ob@&@w&afjI?>;c6IK+22s`MH8J4@WC>;v7hz%ZbLleT~}5q+lZ z%9b;2-=f~?3Ur4R+Agpsyl2|Fva8t-r0uQw&>+wq#n2tk^@h5c&!G3yHE}g7-Q(<~ zgoeawPpcTcQ98qRqpE*uOJa?mH45B;#M;cgmiE;~J~-|P^Z*=1z5l5CFXwfjgTOnz znKe0yWrC zgpbNk1Nb!NX|qORq|B<(TuD9{fo{Hs*_i3Si^{}=;deXhR60Mre7eB+hLug(7I zQe%>?WmGNUW^|{Ew|rjBzPVQzN8OiUIhjXzh1B8Rp9HGecQ3aZlEAn5cBt`I-~K*( z!s*Ca@UA{TKcLsoL$7xrf-`EH&wy+41@cHP&Yf`VHt~zkIa{sLmCJyue6Jzzpv6Pg zh(GX{|`i+#n=2d^|{HsFXw7uwP{WDhR+zgfkfXaEuX?Wps~ZNMsi;Bu(2&$PSPyj z*($h@8=l@~Pg|5&=2DbT_;^=Z8yl_c=InP_6$LRs7dohktYo)oZ2kM`Ul27M0%e zOUKBcbzyW%UTH5wrBqLB?CG*Bk377LON$STtf87cyg1=fWYuMfmWxWns55^hT_;&e zgFSZ?n3#*`eY{ubNv6G{1L)UdL`@E(!;{?1qUVp1-{>Mlcto7H&uL~xv!%0IoCZDp zb`NHacHnGRE-?HiwCYDQ=e@F$Wij4{WfpJiGIaV|9_1ZgW3DzHpmV6_%y#q!(V_0U zy8EzNLp-rhFxzNmSnKim+$_lnJvFHCuU7FV8bD6Q!rDlEPf9{e z$SF4|>l1V02^vwFDKtxT%LvVxT_WPH2g}EQXbEPzF<+LChn+Vb)nmu|&a-@1A-alv z!17UVDS`VYbX-Aicr}hiFRmBZ>L~;07P%A0$WJIU1Cm2Gti}?|DiORBr4coW*wfKy z<7@a}!zvv-zG_kLbxOnK5$G#sF3Q2~&Tx5JUra4siNn64m!sZL+vo6A$x?K!P!(0H zsTvIifYwSiEL%fkug)Nv4Yo3x>w^maEh_#*1Bl?SLr27lM2hm#c#e^80}^@IIiYvP z$o4MMqp8rNPI-%mW(X{8j4&`-0u1JJ;`=QA)>cIA-)9N2qBKlC-bHmE^jCE<^^#if zC5<%o>GGiKQ?zG{yq9T%n^uk9m5+U;zjx)MmS{6-xU*14w{Jh`|6yS8B*aXkdliY; zLpV3kNlsnIO`h{??g;y`^Q?Fbhgjs2WN)rV?opnPp8f*M`vqdqbA_a7SmP{I42EN3 z%xJI(f0&mmI>WQzxGp%fO4=Vh(s`wKPAcDV$D$1TkW8|gC(WSmTrdmE3n8wn2 zpFz5Ox=vm(F#08m6#YwCR*49m`nw*rcBoVSD@Hy6%-$zZQ9qSrD>$8nu-5;Ms-OAj z*idk#Vo^GJ%;v|2df=1QGcxSvAi&!%~x zb!6@-XCID054+&@*?6~5d;5EA<`?v|@3BSIc#e643jg1$_!A8vf`1un{)yE_EBif` z7ylkAr;cu*{hRk#u{K|Nk2x#6_~|Noj}?TDb1*DWYbeu z$49(-z*OnxJ8vj(DqD@%vVmF(U9 z#30#*y3YBHLWWlHGQvMi@>U|cdxBY`-ss?!-jAl!?_iH&a_4{T9Z}7RNmWAvcJbIH zTHi@v`~BdeJ8K=dcj0VlM0L9SRM;iq{5KP}RU}Z?NXxlJ`{-yKTWHL?WpM5P*Qodt z4IqNQ){!p%DU1=CA%bf`BQ&}5rM*C*fJR9N7Cy!__~cTpL+cF~#y7{-7>~g^-va4B z$BMr-lJKJO*nElK9EVrP^{z@#{A$`8&V~&5sQVm?|6RjCmq`8TgYC0ok6kIrBqhm&pP6w_DG5$6UGCQ@oiFm4yTwO^_RV!&VK-v11}8hM3WY|7oU>7GpN>o zt%^U<03!ISBa0E5qeVp=@|8ASwUX3sii%a}@}ZmJT`i-)5Fv~HBkb>LbEz&&x_qKv z+YwW$+I8u2Y&cQr73WHBV$n;Qn6(16IlS7AcxO85|0}CASm~zqNwT4dEqNtfe!ZV^ z`d?w=4Z~|Hn8lD(L*9M`i#CKqPOvsCa(|BrKYMyC@~hb4vB;f01Ka>qsJ{5978N72 zw1OiFn4<5eX$nO$%3gflPj{=Er=F<$QDW7)_b~P4YZ=jy*=v}Al*2-4d5AI0ky1FE1 zM<4Rp`!WVu{?B$5f1&|I@K2XLeIEmFX9v}Ja9T#S<3l;O;^VgaW3byIP^_J|ao}R` z6KD^Jem67EJYkP6_yYWZgvCO8z0k}mYTs|;vMbrtaR>KRGAT*0Epr!KnY!L47z*t}oY=+%x(- zDu_*WL&EDuNdn^^5Zs*nV)=&Ansz~l{NC9G@*joyrJVeH`N`225`|3ly+yjZ(&%=b z?gOTE`Q+b}>wY>v=}8Hn*`$tT&X<{n6B<5dOKgK`{qF#__(wE=2>uvxmw>99hRvbS z4yC4_Q(jUI3>=1<`Phl~$qVpG3;u+mPUB4|(QeL^bYA_7>GHNdZH<0g&Mmqc?y^qv z9?<9HyUPpYCD92IdW689)CM@lpZaUNHr9%6teQG|9tWulL^z*3q5R{v`8tv#25b`8H0p=fz30OXwOeTK`< zZbyPK6~?ENpT#Hc4A^RgsM|<-09m0pBX0rTUqU+SN+^gfR5Ks%ACEJ}b8`B# zHgxv<4zfmAg&pPvkZ1V3AXXTEl-+Y{C0nlB!%BuZ<*CU3rM;)|VjDW#Wr6ATfZyDa zy?RjLzf;AZXaEuXO}n*TcVZ55=(aJ({ps>syoZJ#3^qW~62e}4wWrf? zWKt0ii)Ku^JPp{>D!zs}W&)UlFCY$VsOku55CWFINrzYwxN33OxXh>g#9Rr6 zPW6?1{;!_;5yYB}O04;XximM?r5sN>sPO-Tia*f+BKQ+-POzf%z-rHc<*#D(Yr+b? zUu50Uy1KURmRH!WVTD!qKKgfETXlkE595-Ya+L>rfHtrmjm5w|rMy3l|B#k19CcZ*5)4zBvoFRA!fU57u7J9cX~lI~8I zKgSFximzkSdH$zIS-y=h5G7zR2NDA5!@HGuCA%&4mVu=PjHjmq&|CE`7R)+T56r;u+-*VlmAi3)pS~@Hx%s*eqBzL7Z3p&=(Lvy z9WVubmy4F2f-7^~^sC zORY|^*eY*Xh8~W;i*jM^ZTjUf`9j~cso<#8P6x7Ufh;G_D<7Y(T+dB1;qd@;m6d$h zGVBDsj3*cC?@7edEJjv96;&FX>%YE-m>Km74BpY$^Bh$8zpUaH#u$u+Vy_X; z``gg&9+IV$1NOpf!A8E53-SNeaaD`sunxzsN|XIPG>&Mobj9q282` zfv#YpA(QF{aDjMHu#sK|!d6Rg|J7;)baj&aG%IzN1 z=2UEg0So;PSee&W{rAZ9|8A)s8N9b9*RlLcJNQ(2u+*!&#H_VfZrcl1hle`Bi}i60 zSs!Hi?)u;^AI?}}UjO{+veL7=1doVWq=nxw4rr7b$;%ujf7gqM0y>Q9u@?=Evix~T z>jkUZt5Wg9Y%<>eX7_{>X0&_OJ^1glV9nbrsz_V zxDu*C9P|^8*$R3h_G_9kb`ktu0DjL)2C)1M-d8TEy4Hbx|5U8O?_i5RkwJQagXSf) zQ^3hdC^2B4IR#i~<#o^!(e)9n^D|(qY8_&3s~-QXp6ln}IK|o{%>x;5AMIW{l4xF} z%j=M_Y((Z-(Grq3*^gD|JPLfi3SkCUsLxE zBEDw7vG&&FcM%uiJF-j55DAFel`ijMQ5}*qZr82J>GI3)4HFhd1sh8FVCTw$E3YBi zQZfVnKO?)JPlk^-k$gPWvzuB3?=BVI-NXT(FK58Z%iQ<{N#uoy!2f1Ky1W{*NR`Qk zT9V2nkyVK#z-Ck>(tZ!2OQ@=|;XX)?YZB=-57iSu@8TtjL|Pz{M0zw`p25WN(_3P| zO`7eF@e$+Pw*HT+jX^XY_mr1vYw+~H1xvCC&P4wD9k-v0lSy$a$#90w&Tq^18(sD8&v#>1`xrY zbEaYc|G&PB6{F=-$c>MdParowLy89LhZ9jpIXPN>q$gVb)3w_Eoz*`_PvBo}*sTX+ zY#t=I8*A0BaBtr((+1yuYU2)lyJ+69hxU`NgtEFe)s!VNKkwk=*UK)nVfQiF-)`ns zUFJFAG@tIUZN7MY_E&r8B&;|Ay*Y2QJ$rG(o_XlxgH9oG(bc<@m2KQ1;>welVDDDE zk>8Xl@oA;C^aJ+KYzm>^yM*e zsZL;non2!kOLp#IA~y(L|Qms334ue!85>sSJ+lc4&%XHen)hKfJY z0IuSXmGnbso-%Tc(4EosbHU{FA)`ZAi;kcvEd!ljHemb^9e^#auJmJ`jXTs8{zK>o z8n@RdEFIG|BoxY=;2VM=XhH*cf3u{ zJ%`#&&mnKTafuWD;!Axb6F5aCOz&2&_V0d@Ic_8UUoyg~R48o$qufLJD<8Kd)J#Iv z`7A|Gap_HM37qL`BiF?8mkuiY-&FA@8bAbp-Z6!GKOvG+f=EslVu2fKQsvLWHQ-hn z{krXESdFV>BJg`4_SEH2V^?dPFiz*+hCbf(-sRBiU7xhg=09n3QRWv#q8@Hy))nQ}{L-(jzzof5z=q7z7gAo*sm@n0d-V+@Ds7^Yu|0#QR%N9uZ z#=~b>h2ic_KJHcK9pPoABdG?(%EK8pFoc%ytH5lyiN9{p|GQQEi3V^L|5Cw5W8%Ts zoK@;_oJCy@Ud{+ViXA|kB*>@xsY+fyvOYLb2!xR-z@rO*?5Cc37L0e}(F{mkLgLMC zLZv~$(!*x zV6B56XyPyf%1SpD6($zQeAFHm&skts)PPeYROxqdb{xa;IG@f(JJ2GdRcEb|3F;UBPLfTX=58yXZ!XTJ`!N&JHjiZsM;S@ZY22Pc(oC{uq(C z3vK#4n%JjSb24As#13Mdn%LW%AilOZ{L>3cU)LRtix)Sc>RVGAzZBZsR>A&Z17H$2UuYr#zn|Bd;-dsY02 z1`xrYcp5_&?qPBKEle*GUt@;ERbLK`?wJY>E!O%Sn(^%|o58`>ay)8gQPdytd!G28 zY4UXV3RLseg7N+_0`F5dPSJwsuO6BL=aP=urP*vv9xZY51HIZeV^6)C>cX_wB z+rzXCRo!Jh8K}{6FGY+G_J&e=?_=61?HhU9HOK?vUijjY?-)#r~j7z}^t+$=&&S`z5 zerJaLnA3JwMwI_28P*o+)VCOsUoLPNzPm9Xh^2R5|K7M>>bUATO6XAE$nwVZk{&Z8 zURov%#V(JQOwjs0DP9jMr;ga9`%wz+KKHul{`;+7ao88%S&P>kx z^ZA_5Ip=*oAH`0wh|0u)yY~{Wjo(&Nsgi1Iq0=PQ9*)U4r9SW7 z_=AAIXf-F=0+p)ATdAgpE7gn^&&e39DK_&bF0=_Cx_{dsh#ro8P0#lMc7Iz!vRLhhtbY&${n^FAtm6*2vZ11EMrk^d4u(c0#om>!DX zz#t-dK)u6z`U`;xsKxxKa0qv<%$RW2lri$78r8!uc(4Y~Wyq+(lWhc_ltOvi@WTJ7 zjz6IRMDh2W93@t*f1}eFJN@K(F@HU$Woxb>=39CS9|wkqeZ z5^N+@;%G;U~5rgE#lgUUi|5WD`k*_xOv>5loC4XM@iGPmH0g zh#8Y)<3&?yj5^}s(aN{4oXR(wz8CVBGw$@Km{g5*j0gY}O`;5qR?4*RSA}xBcyJY= z(M+1lkUCl!tz9n-2|cBG(d!JZ$7Ze5(XT0*W^-7h9kHmT175hRrDJJa zOGi#zqk4yv_7OY1_!zO$F(FuK+v4htd597Bgvmo}6<5uAE``W^Pv}Wpe^fQKKo$&i zXPV>nPIs&a(E{DJsqY=RFqP6@Nfd!o9TRQI)kiSibD|}1;zBbl67$9|%m4k7jz6IR zMDf4DzG{6ROc+yuDp`7&E3MIRM%$#q34~O(eqihrEuCzSENQ(-gwiN#~%CXP8*tW2~0^@2gU(`CNhRpOfO(tmOb=H9&8 z|25L~hR}gPB~A|12P~szBV)*a4x#jL zxLBEObK>4Z$CM?L|D( z=#S#+aKh1@6ZZKl^KK2j-ua!_9Mm6H_`jm#PiO#9{HLJ*d@t$!C%mNf->q~;KKhU3 zW9|)&4YP>Q#&yQfGcxQS&2Y~cKVBKrN9J4nn0*%`NzkXS;FI$xV|_<+6KR} z&k*LZLfhSYcVFV*+~LcTa(jDAx3HSxXSuA(tCxvSF$+G$OP5JjKm1>9RSsV!+2o#W zC$FEh>%Kd}f zQM(?45h+<4k%kriztZvl`E~fetc}=o8`Io;!q}OHK4E}Zvv8sJ7kUnN;OXk);T5(C z-My=i6D02Kue|#2FPuBp{c4`c+%~r>d9g$J5&c#dV_5wK=Njo_!*jcqkk7QmH}h!a zc83zn(5Z%grmH5ua^sFKoYes>7vP`Zf4h$+z)Eu`8&$65xZi4WB2pM@SlnNAk?OQK zsLrtlW|H%Rvo9JlMz<9!76+d?C48+!0!oZS3Cr2!4Ya$tKcFN}ceR~4)@c*@rKcN9c^}j$iGNURSD%C>lae~8@ z`qoO?Z98gknZl=+R21YY9322Ql-nsbYqR&s9aQY$?#!pD3`!Zhxk_wPsj@beqw{*Q z7MmqW{8+WoTSZQq+jBqtvFfD7uE!R|NL1R#Y9fu(U2!JqogO~xV>OxnP0#8Cqx7+w zLbG_~X#-x`5<-)~hHo&rCkrL|*$TdXatHPm~gMbhn3tD4i;sunz3B_;-^Nbvb;X4G(X zQ)_3}=GIQCO{i~Gr-OyJr1FedviH{AnKe1Pzg^SXamSrAcYmj5{@(POR`qhr-8g@I zuBBD=qP3QmZ`Dqg3W4*6=HvoI8x90y8_h;C^A-!P-Bcud|HU5q}=$(=8x*BT>PcN!xV ztE=Q0YpjuMaf@8xL$5DdQd=cw=M~FYYfOaTj1(F!_)+HA#ug?`2 z4f|V%u=h&yH0-m2nf3X}rI3`zfIVfJj#H`A?${;MTy`D7K1;*C1lZpW>}lgv{9RKE ze8SC({@3{b$94P(4Iqj?L4W!X`cpOZR{;HQY3ScGh<@fbqQBy6(O<5iU%I-SQ=r0>WKW7O2X;P7f{*2(af&QI9|6vXNIYa0d zYv|9=(4Q3)lNSZI$dqw5zMopKNk&K9#6LIa|7$w_ga&Xu{&R-#pRM7)v~E}OD553o zszLm}T?^e_#6&6{sFHK?w!i|6tR=cSss@&za5J%qQs1+bYwRJfJ_bM8JKg7TpoFCVT2IE*Nu( z?%xrRvELlIiQ&I-|L=7je?kL@;_ofZC+HVCB2&w93Hpog4UVmI76gF)N`gLYC_{gz zhKgjav_;nYV8_c$u)$UG`ZYkIls>iv$0cQvEw-+GK0*-IBfZl;RG^0fQe$g~F_LyK4L^Xx6g9WoBg z-F?1;Uo&|>xjONn39XP8*z0Of)M}&VeWZm=C^zolWKz34y&?5L#vW4BeQ?tLudDm3 z;T8Y!gpNO<0Yvd9Jx}^>(jL-tWA>vDA0|DYj?tG~nZBPzpMMMepL2gU-V>{-qn16? z@6)xqDWvZGr0%zfZ>QDH(rSCP+Ec$&J8P)+RIT>tq1xWPnXvuj-gC6tBemMIzEpeG zQ0+Nd?NOw*pWGWBrB-)_R(G0KclMX+&d}fNjajEtWHJH51=@5nb>$%}dCw`HnOpNKc<2J#*1=xG>oG z+@sRO;3LwK;D7G9Wq)hO!(lP_kdz&KP+Aczm$HI>_ygaSW(6ORmIm*aW(4oU_^?LG z3$B*#4VFnl&?n6g{!mH}J}nglpOS73{y-`TJ}G4epOEGSH%K|b|B#A<-rm6B9J{z#e~+#;!oi6>!i|PP?{F}FKH37_Z@uxJYxK`cI*w@8Qde?7Thg)g0-ld zOy7yu6nc?#cTmDRo-V~}8vV>}%rRdqmiAwGkb3a+h+tA3>&@+?!173PzSS`wxhR~$ z7o=ZGzrd{ai1eKFbIe2!ONqhfrG(%i$sTNyY{8#Nj^IzFil$+Oe~XSkp#enk_Z=xn zemq%Nwp691Rg&M2RU6a264q%(H2Lo+xJSC+Un%+gcT0`_6;jy0TnaQ5B%cQ_D{q<4 zf0raRQ4!kuVF%MxxU8}1&mHu_5|s{f1mA>3L7}QpLf$>V<;$)Jarnumrz7)S{phztgBYgUjm4JDw^D zF4x|rP>X{rw0FtWlHlFiyF_YfaFzDXNnzEgWMw^8n!Kc*jl$|w$vyR0adMK+9KL@< zxVQez;l=+trQ=U%08#w){$Z(SEXQ{85mk3Tj&fiO^LfidX=pEku^WE9(Yf|qyn;5N7ntw zsvlYLD<~vw4_r+Br5&q?I%|xuy)B3jNKT$ulozf>Swe@q*{7MqCb1g({~nwJq0=t) z=Jn@xo%7{2V9ys3WJz9#46uj$RJ+&`lN8E-J`+0+ym+a13d$+Ijn|cPquf7Kr$V#b z$@Bs{POl*5-A(*+!~E~Gjz6IRMDe$yhjrG};O=hhyUiwzsmr(ytD|vtb__-FL9qsW ziE&PQ=V*&j;+{7m=JptBeoEm=$^~|xdpmN%jc6OCTKP=zRYdPr{RZsBfVmO8)H|xb zsDZ?R(0aem+DRii;6K}#FdH;@J`TOs$x!5c$h=fn)0(gYq+404ZVsOAdz#_ zl#aF_Po9ayd9y%*zkw4Lf$JWZhD zFnox@CPbArPFYnX7SzLPOyN$lUdm4oFaFP4I{t(P5XIlvmwb%QF-+c2A}yQN?NnoPq5rB!w0FhE<#wg5C(*cAFZO~)<#tsQX0Ab( zhny9ZpGZJ%J$KS7=0SS+QAB#M7c>(xFiMx8*{Ic|NsulZC1dT~?lMT$SfS_dniL_5 z^cr1?hz!|#W=}xgKMV3yV*e>^8|3a0B1`i$SsGUOzoX+%XaG_CiI&*I$nH#o!|xNo z>OZf}uE*ZqiZtbJm6=S1(!yJs@Ld`CE=`Ne82fAi&IVXRg$Ex%#z55US>nsWSdouh z+cctjgIminc%=~@8okfc&_7}|vQ;Zi4{U*iv3ZE;Qj(@*sMhW(AL@hk5m*Pmd=q^2 z`_h!Lxc(DdpN)}%)EuF1SCfDKo|?E1We0u6sK0W!+xT?;^F}cU9=S#H>AHHqf9ZTj zK1TQ?_yL@m#EL+!a*Eu8coV70=L2~S=uD0Fqq41ga(@`h)?V)XQ8U#3is z&`^nZ@+~)db;LwBM=aD@?B8Gb;2gX-+Dp!%;Mrr86Bgw!L#Nd%$vG4)Gx+xd+eF;E zl-#?K+?y^^!`5M?|7Udk2@N2MzuvPr>3b|mBz;TH)^zuNHt?Z(AKlU!pm*k(Kl%{S z7PF2DVrTEPzH8SV;`EbK#JHC-lc%4oOwT_n6qLgEN>z4gb-e{R!9|nSdU`{b1Y~uY z_zCHK{eGnPUo0SZCHFi$dNf#Oq~z-;Nqa_o{N<7;r{R7yVx?9`%ye7#lgJQ4QPsKh z2h`-Bg}@^9A`|%F3?ksRD2_`OWo1+bVx;DPD2tX(C*=^mt{OaJ-T?gDhfBdBA6EFk ztK&~-08#u|+x`oasmZ4(eyPekEfM5U^KzcJGB79k#pqjq@j1Q=q-6O7_)ozEhbV8y6zBnsy^^&((#Z9gza2 zyNb}_U$4%?eC}EJ{kI%9hR>+en?1<&F}qPO`wCVQs#Sry6Mu#IxQJKsm-U8dWF6w& zsmk%IBgqrr#6LI8|9`9FPiO#9{Ha()?bNG{Jb#j+$Wfs@qX?# zVlh9#3N7!$3U8R^4;ChTu%qBe#6a&Tbey}RixS?#xmw!)Zp`I2pP!1@XeUmCr7Bym zB0smE&UE?OV3YSmb2eaZZ$y4poc_}6^5n`ts)4EG9$ufJ`xYMa5SwYJF?Bz`ma8GYOH7SHJH<>`tL~#{;Z`O?ZHt5n zD;Uf`je-70bw{D0le1Ej*0r^&EOHh(9f*8?6aU)1*Xh1Ka)Y1%(J7fw@cNlQqm|c{r{1I6u zIfn-;6#s>|J~6n`dZk#&u$*nTG!fZ=l&mAq;khyfKIwp^SlMSL_aOJ%IlSl3TfJ;Cu(Y1zLLN-oY3#22X0pa)`|D zMyxh=-*R87vik~&1MYMfAvZ*4g`V%mdtd{8bmhYf#jysDImGfr8{fK+8yoi$u8lLK zt8IkcjdqQQ%wQ(p+B_*C@|ha61GaQC^39WPh-RS$z3?3fR%qYM+1K4NDx zoh)POq)kOALv-*0kR$!c@IVAo0Ti6@pl~vr;#t=y?A$C;EqEDF(%M-3#fq3phovH!fGc711puNmh$&~Ar?!YtEh$&({_pq3V{623l z*^@`UGa#cA?v{BmL}qr)0w-3?B{GHYK6OMG+v})jJGbI!9HfSxNvRI+U@Zq~eM+nh zDS?&|0f1mmq83a%nz$im_RIa7F5YLR!&DlTI;`}+O~;?m0HXNM?`garvvK33ir=7r zNIzfc-L9SCo{V!IA2e^&PF2~FVJ(@iQCC)$97W!zwUqlIao5WI$#j;KH(_mGh>|=w z$!QP$L1iU!veQapO3`sm^WgzZzXW@3Gm%w6n}Mtf+VIYdSVKowOD$2zI%!)tlUrc7jm=#9n@jJ28mS&~Wwjq{Ihsf=*L|A$mVz`V}my2Zg zzXp+&oH_iYhg-NH)k#yF^sf;1RzE7oZV{Phn=aW0TV!1E%9;V9!&}fMYopx8+U+ZC zuo-lgGouePb0^Aw-fu#j5K@Xn6zK0wel7YQQN)gs_r(_*z1Jd%9PZ|yW}dernn>}* zWJDMaLgvo)A80bTuo@*&doT1JzjD6g0L{Jhrw&7wy?fMCKR&qQLOxaBG!lQsu)_bW zjz6IRMDb6)(h?KXR^MbtJWUyKH^Gb$ZQ=SO$Njlj52lsNmsqkcjBo#pZ%u7<8jn?C zevmVeF7|3?GZSHB+hAj>u-Yp4rDMd_Vw}!u^sn}P{GuKgW~}m`m!l)}nOLT|?Sxs` zHV~Dv!`+6bU&N^+8&-_Ig;>*7Kj;vt35~06^^6HEL*$+;F+rJ+$dWAb2#s$etNGA# zvb&2o#N4x~im~5=9i3L}829%+(@%StP+Vsmm5BI7&4qu)`jJcQ?_H1U#?YgRlj24Z z&VeaR@xu!L4|Mzq4Iqj?8>V@(uSVgw9T@1kPqeJ6ne3;~q92)9U&Kj%mZIvI>0}>3 zFq23=q|6t+538pkGiJjzjs2o`^{Ye{h$Q%qH4>jai%7v(g})Aeg1&Xo77#y<25$ts z4li;5N^H{_+%p$(=MpJ)=$^zX3`$E(kk}8i1G~~WSP2Y@NznOoU@9!MxUi>_EtWv< z`+Gm=JKvE&t4A$ZANUi_FglJLM3e!n39ysi5_+buYe58&VTJ#PI{t(P5XJu!)#;6` z$rK%uAO`1Fi~BCjp(@dTb6QHEG5h<7CSm+FQ{i0f^d=KaKDfq9qBwn>?cLKy?LBaq zhV{k#A2CCIaG6-&mZLvzAXcRw_i62DNXQfu%7vb%Gz|3nIw%%394#K$nx8>a=@6Yp z?s~nwA^3mOeV1wXMQoYU=$+^MAMQM?@c)C3KcN9c@h6C1-}C|gJD@5S$wlL&G7u+?Lgtp2tB=FWlJXz&Bq z`eM#EA*Yy8e5->gp^MT~sxH&9YU;@%&8_vyRKE7y$Beztz^@y%=3KePS*vfX#?{LlY* z=!xZbl`bx>*|_S_A5q*>+uQ?KrDIPPJ+(0}4r{OnRb*a#tW10Z`vyN%X^QZC{#HTu zUfs$>bqeCmuJ%o+&^e|9lM_P&Zc@@+LAj%)EvSuFyrj-s*t_|k3b*1=|IvPx=PUl! zJ~{QR_KB&d+b5;Aw2w=Dqdg<__4f4C(%TFNz2Ko?R}eAhjUr(v6dt*j>%%L? zBP#%lT9i8*^%T@|qMp6Yh&&fc@BLRuJ^xs;`eVoQVK#dc|J<_D#q&!7bq0vqRVPy|^&hi<|Sd%7%UZ=3}`%1?#~N z(qeHo`4_7$Zv4Ubhm>5H!WUE7&6D?7A1etk-(f;r7)VW!OHlljAdB!8OWlQ+c?HI!R_wnx(c5x zmQVjs=;9W=-9<4>ckX(oTX+IH#I_`bj~yl6AsUr&M&=|+EJX>^YVi&117YRJ!JW(! z9f-GfhnVDxcW-`@w01To1<||t*lXqQ6R8ZefJksT;=3<85G&5@JN;yQw9Im}XMu|6SAfm;c<2J@_sq3E%JXO_z5HRZ+3&_GfpBRp zzSZaUx18s4>|Ked8Cd7Vy1ZNY7IFe5veMB5Y7$$G`0iONX%X4NGWtW+W8Xztvx#mvWLq)PG`&SudOEQZlaS zy9Gn*_F#Ux!2C>liZJ#Z-EXg`#HliyXqfB~Js6SC9Hqf9{9_0GlFs~$Tc-Fa$%TEy z72-d8XJ0W)rW8|U%w$1Hto&GQveI62i2mD$>V}wp_lN3Jw|w3^S#61lZ5zY)ewyEP zC;xVjSn)1=PKMtK3CZtTiW7xK>T~1(S02O}p$Zm}LWdRpVI6-$1Bl{ZD#q=Bro&Gv zilsf2@@M32UwAKi=P`0R8XgmJuNK9UyiMfW-*2>cKYl;O;|x`-z3a1*DXpy?_N<*3 zrckWAwZocJDzbZ!xH@tdw|KWmLkh58coYBJ;QxK9;~%;X|IhZKm;I&im47$Xzsolg z{Y0Muh1mp^??YFY5nHYFJ`HQD%L75O1=-#TQQGN1smIO(bw@W{dPaRdh6fYB=`M?M z9zW`8r*OD=64`AsZ*bi;(XPF+-av|w(1a^Q z+HidwCDRO@^+j6%*~8-UDP>DlON^y6nR>dd_+rUg2Iso>xR$B3GbZz~5T0Y)O3_w> zXBlV3>#}i{no`kzFr*eW6FY%e1jB3p_kVQ!2@N2M|2E|G20Aaa_dbsObEl?%^m5(} zhJ}%6=(jYjZ0O&v5F23crtab0XVlghXOQ+gg1gkmD062znSJ z9@-y+$Pgt2W7zNv)@{NrGo?%&vIi3g&c#H-V-M=1!{{M9PUK)@72%K(I}Sf@H7V;> zYWsfLIgfI77R3gXe^<_%6j01nRGRXsn;&q!t1=YEd8ZvdM$91N2&2^+@>fw4xV^FO zVbpqbCo&hp+PNJ;BO(Erq?_3M-#GvKyN*Ah0Yve)1!E*)k*x>WeYBF$M-V=!maqhY zKUAJ0wqa=W{^JlnB&Wl>+W8!Uk)!)JQH)-2D*{*-HYetM4H#K)Hn^xFt`1{u8KsOF z!oCSv-gWGCMNh?tOU}5Sku|#ot3dCFaGEV@#i`1d?+9Sz7(gC)rz7s5qr1I?>Xg__>^*$ZYq|8w!{=2`z@O55-!kk7xA#7U z6YIkY|9|NC6B)j(!b>QY4yWI&WqkJCB5H*Ud8DeR)!kj{QLW|?^#wb*PLSKB?p*cH z-fe@@fHT_AQs)8V9(?y$?0cleNBlc46ywZM`yw7l{jK+RgJtQ^1m4_EB9c4{KjL4@ ziZ52K;}AjSgu3vgTM21*rVxXMcOOw-JwfibOKox3J5%tiNH0Iet(;WT{cPuWipP^4 zQ$HSF{@*`!{0R*piobI_)0u1fRrgPxv7DQKl(}rx(s;eb zmrHw4`ukrg-59X!ha_wu`TG9Z`^pvFBFxgHgvbW0fGzgDofjT;5`A}xn8hjEaKznNq@PNzYRpk zSM%9nroAh5sZy>xPFOr|CWM^NI;I=ZPPqy$fV z{L&(~OF543I7j?pA{j($Jw$64fvdC6t}w{fW1Fbk zKQ8Ngf|ENatX93gY7;mpPOL#0M6CU%wv77g1xhhKQFPz1!vBJfKcN9c@pte0arql_ z>^*0udcgPl%cb%$GSHWV1YCU+)U7?vLEpYHl51rclcM!J0pUJOq$Io(q`xr^4}1aEK>#x%a1iST7`} z_xUMWTOLGjs!_G4=&@ec)*7_+{kFkpz&9>sh1M3!FAei!F87}4GxCoj=ii2yxn15x zA*=@dtM}(%EU#|U+rO3P*ZPK@wja^M^m_~|{5y2~2@N2M|Mh*Gi9Rm)QXhM?J~r@a zVGg+b5Hsu9T7SCM&KT;;OTBA#yt+2#UBljrw#G)=!Z$93(b_WeU~id557qAPwGE>E zX4bXZpIv39#F9M-NX90W4H&{4P7KHJJWhAMzKR`Wq58%^9(&%*aw#8PC8Z|#{;jc( zbfyv64~p&!k>3N?eI{JCMDc3x;{IWUKZ$pbe}o1Q#s74SMdVI`0nV65!!o)!%&BQA zPHfY-)?ieec=Bi>`2Qq242j`4(0e;rUooNFqdW3!AJ_}-8`Xtfe!?PW@SiZrv6qkh zejHiZ7dd5~wy#9mA+a3GjuL+VBU)Pnz2~r+Lt@A#K?5h!IG&w+yK`L%&EgGYOv}#N9 zu);s0<46 z8GtKA8{b!MIc$~4?p&g1Lw0DF@~92G8klcn$bClihE1n4D~98vFwHI_$YwN%>7G$;{3MC!prcE7XLas?Wc=Nj>6c zkX7E}e@jifk1(<}p`|8&V6Ml1rT2@gzg5|iZ7Sun136%c(`Uqo+jz}(^l)}o{BK}6 z7Pg3>Y0}WNd?a+yJRe93+q)}$agaloa)boAd0`HG1kL9$>`rlupe4gA)$vyYCC~0<>SkJey{evRAn1n%Gt}F zr<_M=-dBO~zx%YWT-zml!|zhwzFgImiTGVCM*5SNA0hJM#dhqVya=x)fp2rV%)5@} zy%i=zVj{bX@2ED3SDLPxx=j^TT2we*dG_iSHDwE<#fsQ+os5)Syyb?TMkIHC2}#daS{tRwMQ#rrcdfOWW1K5*-8V_b zLtko-in2~(Pc>IT$1z5wVf+?mg)TtKD0gZv5`%HJUw82K$~M&-{{ zPcG5n>#gwED}y7okUO};LgeQKmGJJa+21i5;?PppHN+1cv$#$VB0iF7RL#yCEyBMq zUvCjMeWlewIr@@)sW}$!I_>)=Ir`0)+FPj(&M8h@d(sKvVWt0_I{t(P5Y>NTvoTg* zrNR-7Ot#CgTbqmjhGL(qa0HNXGTnyk@Ykb-#*8McPn* zAMURF-nBj_qq7~OGondr-a=2mX3?+HSoN6g%N9M4%rySiZ-QLLus4oQiwExwZ|{52 z`^PAMkDe{ZOpp5B)$&T%3cEHRxPCS;tnf#aKBE7G1`x%caH9~rk1q%xE608b;`q9h z!~H|E0qxsq@bv;^gzHCU110_1Y=FNu8}PrDi1`|u!o$0R#ANXmWKMuNKo+TiIYLUg z_$QTbBr}4{{!QxmpOV$Xv`t@~2mJdIqP>?;xFq;t}e+y zsn)(ffm8C!!BR12U&AgknfH@fKg~ZKp7GExIvc4KDEVsNu)_bMjz6IRMDf>Hver7B zl7L^O_0adA?ayK+&czY!ZN<8(OIg~N*Muvjx&ss`bhD8qM=>35~88WL?0(SrRnG|I`>mVM;)4u)(=V)sk18l>Vuoy^j^(NZ?<>W z0N=x^8!Jq{2$Xs^5L+ZFN71^1ga{`P*tEwW0j&j&zf;^LgrRH3%tQuNu4eX%h3c`aC4+ zA(ajeEBt$O{0R*pivMQSYt%JnGc@L7O=Acv;!3ZlAER;O;Aq^lV@z~iE=KwFmFPwy*3{Uzc%Vi^RZ3t*Zro>pc(VAMwj9O zjwI*H^zwJ{EF17@qh7_UlTz`TNKJq6T|_0O(%w~*sSS9a0(SQnb#~=D>Z`(6XDh$y zdk>Pd9pzm^vy~WSnHDdA#J0)pA>Po<`*Q>Tw^zrX&;X+NBN_)y;%vnz-#!*awY_<( zNIw+7sl5R8yZrFcmQKO8y3qL1Pa-zMZP~wy>>hW^2Z;O4t}YyLcEwRwa*|kwXpZ!E z5Q*=hjk3vLMnt~u(3a$_e`7jtqka{U#>Ji`c4qXI1>%I2w0Fz~!Lvm+nhYr46GE%Z zrv;318`auD^O6~>`W&ScSKfkCz`K4xjc>&&A=dp%y`tdam46Jpdf_SRm-rw39lY=~ zwH^QOtasLy)SvH|mzz|(q&}e*ypd1Ocg$@(uTDQzdhooOQ@OAneCC?Cnx%D%8xm_+ zSN!e;4L2|PUz7hEwwOpfp#enkAF(^O##xY1m(-9eATwwF3c*oJMY2llT3%mgU4n%C z%=eRs?3FTQFz-da-drnkd2+Oc0J zuW%AR%`8DC-}%lOl5I4hVT6Qi^{6$cl#8rI*7@u;W-TZETI33b@m35W!h4YY@~|}k#%c^75;rX{)7e)#ebtb>j5e<4LQ8mk$kNs zz$+iwyB{H0ymz6G%nk9#;Jwc8sNaZBwg%E?$lm<`9hru#uv(oJ+fav;PuxdGvXP%T zs}y~`I<}6U@yx}N7m6gJ$4S8w$q8AxQv%<+GBJ2wO$;oq8Bwv*2gfEU8&oJ8w_vK4c0ywG8q5@5T%yu3&){$=~Ve4t*l76<>!XcRbH?%j31W6ksDJMO+azUH2~B-rHpVY!zTIBRyu6zzaL*e)|{>>etTQ{vDpf<;QG z`z#r`#ve%xZj)I9GCGBe3SgTUE|OieS>`Oz`&=6=l$o{?3$+w>qO?-ZUSO|D3PLvL zji}=yv;5VtLHWt?b;An(OFI691`x#`7TX4Xc4T&8KsK_5NX}w|W{qc*k>0P8b!$9A z>wD7c#3Jv4E#4^4o}ZxEVoL)j88us+Q)(Kt#lQjBf?c@}_6Rm7Yf;>8a|3Kqd2Bs*fPA(OS)-qb*V&`R z8|7&voBVyardgx-J-FLLPR$;bzR(K!yX*OcAmzFrIe~{2{+D(92@N2M|8nF;en3h> z7Up|*-6M_A?D7iOf{8kNRiWwW|8BX|vRfrvr+yE1MLe*-(_uWB%obYmn7&%s)4*edD zNUjscRAQ~MvCIpL^t~(OSA^aB5z$9~coZ{Q{-;&Yr~rGL{gl7Gh0Inw6v|Dr;in=Nf$Laq*4qocrMYRZAALh(EpqQAcrwcDi+W%b_5B zzW&~S4-jc%+xGHg6$mSRkT)CTZ6f5Y@zIR0$ea6;y~|WGByXCf=atq=*W3AbE)hE) zwR0ygQD_-!!1ybOr5jfGQ#kGl>_uz6mRsT zoMgqSJWt!0yL>6sGXsU(^QTu z+i!pmN@6xy+s=2er)fShtY3d|@VYs)lW+DhJmq=^=L9*zECTPBl%@Fd9j458I+)Y% zVAuKcsN}(Z*WesShX_1b!U^Uz8?IZh<(KxV$v>reY9GlIHMb*HoY6K{&9M=iwijnU zspE6iG#iIkkIjkKNw#FXdTqlBe{$Rz*b^E+6#rjz&W0X(p@;pwnVRlpgfhypx=xdC z`g^~nUE@P{bvSrr(57qhMxAqZa&jtFzIuOM_ptD zVJVVr{l|SoqpcV}sUNV_SN+p>iAlC~0{{|>q` z@2}+gBs$gDy{TgH5;~LImE1+{eN=1z_o2P2^C#q)OT|d9p`YCIZPF&YDKF#P%NVQD zVLLWqta6Pi(#9$lJWz~PH}TI6<3FS0PiO#9{HZ;gQoaXfEE%hLjLt9gGgA?9WpLzf z>W8mH4SuUU+fUHr%oM-B-K4C%YEtShP2^3=3)gmcduFe)A}YJRXS!3fADu>y?L_o& z&5oF0M=0gTfdh9{z>;*sk~nJD!IId&#*$F!ceK&zf>IqIZP^dWz5BpUpKhi+KMWz# z$R5gdzQdkQry^7FyNDCe!E|yKtoWK4rzR7*s9Nt19OUs*dJYRhw`?E!xT}zvy$+)f}}4=^2h1%oQiv zr5BIV8Rn3F2h#qlr2QGpL|e$Ve;0psJUJDVyaf57SLwS_B-1;&Z}}J!MJ9(5x(xAS zAkAlR7Tr#ZvUy&CY+ZnSBk&+=@;+(XxRlPKCiZ@qJND*9|7+I&NxB1IPiO#9{3(9> zN_r+naFZyvIMtBB(|Xq4eZeOky686S<&i(j-ZdL+fE=3iDX*0F4dC#!rQv)BmuIcx z0+el`&$hq1qF5d+R6kZMj})rcv)G$`7Q3>iRIc$^tiz(cGWXhx?$nA+sx!bVxAw6? zv|5HN^IEHh;9D32kbU0CE06ZEU2%LY*x&{?O0VV-wabL>6WPt}3T>=0)wx9m7*BT+ zS>%b@m~) zM1e4@@HguC6B3p*7~uj6u#baB=PnrXXJ+;N%(9Zpl6MusoPn-uB0k&UY@XT1Oa^Wf!q&=1pJ*P)IF{bms zVLfi*pBwDINynei0HXLSLag%f8x&9C>qR;7WL567-m)Q9$fjn@!J94RclfL1yV($8 ze5NVSWrtK-V57_!=a(DyR>@0Q#L^gBa=OfGGn`(&yh9!Q)N`$7P-K% zQ4X?I@+$qdaOv zrM#J*07=*`?=o$aZHA3y$QGPcC2urrkrU$GiUNrd%b0^(Wb=rd7yYjp|2Z9hOv8ro ze+N3S30gHmlYw%9F54#C;wqsZ473C+jX2t899*rB@2*RZcJM4T>;$_^*d){D1gSzWOJ><(<^*dER|kdx#T<;^&B{iD zQ7RG~bz5bFd5df{(9$ksf(1jtu|U9nAZ?K-*+G>EG%Q9y#)8it)Maf!Lrp+t&=WWB z&kg#IVVd}Vga#1R|MMMAp4;sdcF88jRBI7R1RMIrLba;SaD{MQrNZbf`g}*cH)gLv zhz-&Q@&#j%;Dw&&Hln|QF_SO2WzKBCm1>zaZk0JILoghGzMC1*h`mE#1r&_XM&xZ1 z4A4>zI!hUWuOX&>lwhdcA~V)%nKpR^?EW`HdN?*%4V+lnVxmxA6lf_H`?ppTGSK>n z-a}eU&LE5Du13oyvR@pGt@%Rq2u{cYTT9S22Mw~7u^{hnT+qA+WgMnpTrCGC3#68E zpxn)i{@3WgMaQ4e0HXLqSFBw9cJ$EuYKp+@w;W6q%;?iK&^pExzh4yISDilVK?`)- zesHR=4SjuwV5r*&Y>jm`jP56z zEDm)T&xF*J@FsZ?jS*$0p%$C~W;47Ij7qb1$cxGE9A@7p_yfD(du*1iMvOQ!Hp{g% zy?ZO9cv#_Y)$u1ZfGGYh<^9Z!@;=Ay0vUNRRtJb~SIL#OjTnKq$h#PLW77%VoZ-!~ zDmf(qK9)X0m%+Nm=fTUG&oFhB@&XeLPp#HiDHpI*9r6Dv<$16UCRm9*bd|iBA@^DU z-A^8|Nv#To= zY~W&R+B(=zw?m2w;hnN(U`i+Kp=H+OtbuIPJHTp)+p|!Juh{}_NNk;@woI_?Av`t5 z-gQEuIIQru>G%^GKooyyuE7Ky-Y8oPvGC%o2H-(MyRD4Ou~wOOm}@rSO6-2{wgMQ5 zImdn@cv_oao9`E_`_>9vEyi_IYz;<#plmh7gIi~z+1&=%4@>Fdl^FGGKr$(SiD6bPdQC0JN0!)lByRd`SDVPyvkS#U728UCch z#Nx>eX5*e=g}+_LpU?oJ_-_KrW_WPS9*o=^MoSjI>3E<`h0U;~=KX9IL_|B2R@kvGd_-fK)3@Qx$_{^Fa>ithiNUW0Ce@>NWs`pDlqk>0>&R; zZet7w!BA}=Gef#8TZlinURX@L36tnczQH$DhyuqWFg^C|3#iI!nRpSs{oTbB6=3$BX`nxq?`V%PQr#ct(kJ zS7Js`DrA;mpWpLEi0y8yut{upa|PSovX<>`Tkm&Mdk_uWiCD|Ei@~&93btk`TI8Ly zmjhcfIasW;%sJnY^s{2+wi$-q#TZu{ax-m~o855*X8Cw3SbSE8e4HLxP^`pe5i4S? zDHkl530P@P&dg@y%tcJZV7sNkA-}|!<(Jaj1uNj`l?XBLF>Ta3u}Dak&UeHKoaB&S zwwdLZr#K=uIw1(Dfabq~d%fb0mEsB#am8qBRTIO*O8;YZ{0R*pia*9sc;ODxzgg(@ z>G-{PR6(hLSr}6)#MJ<^OcN}86enQh*aiCw^k%|l(`>!DW3(l)4 zfro?@!Y#F^n`M@drZVzTl#iV;s$f3+K+M4m)j(?*W*2;mMfT>HWpAmgz_PzgC=y0U z#vpl~--!fK_@!2YzD3SNsmv0-V3`2v$u1I1b%|0neE1^4Aiti9Rx;5Fq=Pn-yE5|Y zOl;k#0%9>R3&C8&Ocx0Ws9}Wf$&NBn>-cc0>}7uJ*7F!HN6v;kGVk0mv?V zNJs>8l&mA^@@oke`L(H4GG(4vfOP_R zck=~v?N<1kupQ9Q?5V`c<2SU{XuIWrLw*HyU&(P7U?mbZ-K5#{WxAyBh*B-Tm}rq- zgoUxlM{}?~#X01o38@$>l$_-PvGK&BI|Eov#2sR%$4X?~kd?D@I63>yNwE2A1Y_+A z*bhT?96XukcmtmFW)^@O)_>x4{0R*pihq|#tR%7NR)WhcSW1Rz;A$5OvGrD9guYuc zsQ_L$yN2{!&MmuvK>{nkn1eo^nF?eX&eRal=JaM3^9ITX%VCwhQ(;RMWx(Rc)Rn-h zvq8)&$fz-=2qS>mO8k9?oP|k}pTa#*W_4a!1&aM2mFMTCT9(zq+` zPkv9GSP)xBygnM5Y-UQJ$#_24bp!23%}mtP$1vTlSs>GBFOxhEv1{CrUHh+oXK+~I zpP=JUXaG_Ct#!%MEAv{EKLl*wVB61k+ydldX8=2R2i|y$v)Ra~&@!rklXDWxat_gP z$HamW;N-Kg=(z$X&vu&S+1c~O~W{)f&Rv&t8h>=#}8I-A5lcG(vWXC8o7b``QQJ&@GXJ$VymJ%djw`ax^%Ry%1X82c` zh2=s5PVKPtd~Gx-5#ljQ8z?fOSiUr(e9~tN+Uo+-4Gqrvzzm!aoaG4eGXvAZf2Y1d z0_kAfp@H6k{*i+#fg9XLWlZ!8vbDH}f50kkNcWuFkoxzU!r89>W{z*Figa#1Be~BtAY|G`9%U&P!Hh{GN zD(PXtBnR;76YfAivDy5@zlN|=j#B}gxWQ#qej4rj*uG}O{x;je$P`SJRD7{*tydg} zED}Xvlx4tk{8Tk}@~jcDSa_Vb9_U3xhVeM3VJTLeR#GNO>AGx=SU7UlWT4l6>0F1C z=BA$ONJ@P-za{?+KDFh4l<#n#=}4l}#pUWmDsWK{=HYh{TKnO^@$Qyq#yXmAqX4~0t=p#4LDUU`VGBo8+&w1-lLB(&$W z37D0tONqnz#MF&aS|ke*bp2fpw{?^}lB;`}2YjePw~3_Cj}80W5z zox%RTcqMiwbMqZ>LAWE%^T+Vo9f%s;f%W6qnanbr9p=zaB)PjJ`PU2gq;1Kx!heQ_ zKgj@e{L^|FbZ7p?S9d6Pd|(j2i|!v5XgFhMY}`)l!{{Al+^hJR`aiSebt$*HH(;=> zB>9VvcjC2b^m%5P-Cb>KRhqMOttzCfoh_rwE%SC0&*979LO&wkKeXBzG@ zIfn7`*`EgZq`*gg#$gtK<%Wu<+HFYwXgq-bkB%FX=RVal&(Dm#o2lPr=ID?qPqD%3 z1lwfnG5OHP%w4s9wzNLQ+@=H*Zw|D|4cHIJRJ|o|82UxTd%2DNzr->>3U8`b`^vcS zu4#q8q~T9803H9WcxoQ$%24bKzv!`T4S`vqTbOC<@3ZEGo)|aCvDBPHH@o<815*+f zSj8{(fI|v$!p^G5`?EL4 z?X|V>9QjUGC_XXHepVANsaYhIcN@l8T}{F)RD|*qHskDGWRLAvMr)u+n}hdRY|ZhN zES4%iB*)+Fm2K*wKpt=Op~ z1mw*OV&;ySJv&(<>wDwkH|M&9adEqSC-rMsxudB2Hg8_SBq|B3&?dXPDO*(Blgk5} zO@(|-+}S>>r$DMrm`$~8DC>!FVOeE2!??(E&FwEd*c`9po8!N}`#a;}cN!8*@Vg4S zjpJfzGxS_a{112U@j4O~Hg6y|RFmMDbvwKTme>1N8dS$v7^Q-sY;s9T46a zHD9YuVAR}U`zmFcH?tAK_2*AWY@EM2^NxnE(#Q*Va}zc*{8^zX!K{zOO&Aq6w~RaP zV1@jlaWUxWv5ZeE{0lVvNd}Xt)>adFFATi1Grq+i@o zmoSJ3ZCor<*yBR_Z00i=BilQl0&h*8uAv*-#X?%d+!eet5UxxLPW!L%%4 zH1A|jE8iREcS;GP;Z*7+)DnlcKuahnDN{>x{N1~O-+KyHg_Zs-axJ@Btc&N=6^b?S z{F-0fjjX5qX0f8{CcN|Hy%k^w`I{HmEGP(=uu2Owy%iiC^V9szBjf!F>d_j&$5E}t1P@Y zZv6ANwtNX=7$a#DK8dw?8#mDyuE9vCiJ#cB>T-tv()fR|hCj&wbo?=&I$m!t2}{vO z+FN8#)YUgRTV$rrmiUQ|r(9Kom@NzCgi&;&Usr8Hu$TAc_CsM~+=H{k*J%!l56^@) zKrlV-%Il}KItQZ)oWORgjBYNXo0sExTTyzAwb%TE;VdV{9UC_vt^>YJSOuIw?129P zcx)I4cLuz#`zfk?D~f?(Z4{^Ii=%Ku`tG>#KN_|W!?bS!zH3ScoC!OBU^B(~{odDM zFRVr&c)wW150pXuX;vDSzlh_avlJe#Q#e){7D9&i;r&nCKOuD@fv)_$=$$uBgGvJ zSQGN=GH<`xh5Pt3?!(s{H-i5=>Cd6vc4gSw7OW<$Z zJ|12z!&&_QJ3p^-!q1!apZIwd6Mo(ms-HJ!ik~-kik~NboBX_aX+IBD3Z9ESz1ga# zCxf4gt94%oXRRV{=W_nKWd6G~{7D9&<3H8g!!v0oe-F>8?Z5W;W`EA(t5Q9_Sn8q9 zJlDMcw%7NiwAY7OIX`EL--qkSy4PpE$m_!qjKHApQqK>suEtRwRSPB=5d~r;RR00x z;*jP8n$=Y(XS3!38bUSkX@$Q>!=GdTI{vwvegMDPZnPlAQ_>Sl?e`MH%I_vG&~vcE zI|K8~#B#u{(mr70m%0mJi*+9m?|?;p^w?XeM-NSUg5(9_)t0)1%`hb4r-kGT;#}3D z+y$ohn|tATbm5iNV-lE|9bVyVoLB0@YL3{E0To1|1CfK_yL<^N?*uEgnVaKgcpkZJ zXi3Dw(|D~m?%EWTvbzl9{ATbCJ`3E`W-Nu35Nw%)K174carbt7noaWwYl*8^7Na_R z#NNZi6VgM|3;$9Lf06;{_}eu<7|}K18}I|~6vu@P6qS?u4da%7l;cH>TfDjbnolSi zfFeH+eA)z`(EN9O!g=rsMYEEyo3^kgRG-iV-Uy$NEHr#V5k8?=)_p>a*_+@O?v$r` zg~u>zzyn^N;uk(NZ}1pK4DtD6sUT$sRNwGe>Y)XDWXDC`A!?7g4xDB4T- zqVSBa_43TVZ(yz!qbr}St}gEIf#nZi%*Yj84(K$ud2eOzuJ4Ysn=~Jh^f^BsO8ba+ z9RepbjGGKspsI&qZlBbBL_`QBAiNBn!^lhA=B-6W*>1Q39bA8Nue)nD;*GgG_plk! z$H(oDm-E(f`$EKuwwEC8&;-viFJVDu-^62tAnqU=U_23bUrYQuUXQr5NUy9Ue1!=#^gVGn3DV*~yXD zi1|4GKl2-BUE()Z{Qu@R;x9pNfounB*L}y!82(HB{|XI%k^$)W+c8h}17Grva=4$!**hsZGam<5lxV-I#n-8rGAvF$Ct8uL~|!yj~pl(9$I@i9Ync1UzTmKtHo*i8A=v8C0H zP~F+DyMKPx?#K!?pWR*k)3KeBmLd+4p) zeD=DQH_kSr?|aSJQUA}!ic#IsIQ9+yFUD@KHiuT8z1{!Xm>DYE;Rw2i3NI@IUu~JqRtj-TX zPk_vlS6Pp49=So5yn39upGa6l!fkDBZu0BM6u<4r9&R2B?m}PbT^@OdnD+K$)7 zQMa{K*>NoN{tjjtb+aAEHYhue?-=UD??KOwA?zDusKk}-xj@RSU}B_V9~yO=HdYQLUk{4?2I$84&>x<3qvtOw)(#8k6`vbwRi04p zJB~XupH!ZvZsf=5|4#HGmpzZ-f8ECX1omZG;a{cUPci@pV%9j|NSk;dY*!he>AKgj@e{4d=^H@-7w~Rj#lgC*f)$;>|dRIY5u1Z<0$i^ zS@(T1F@jDisfm#@HZfj4oERl%C&or{Vr={kV?$#GpG}O@@rlv-@x+)sH!%`Fnizi{ zOpLnGP(w1BV#pW#f1amdDxefHEd9*j6z5&A!SELHiqVKm4J|5$%U zny}g!Vb1#0CY#O;G13;)rvf&e9TIb_PwlYj3=vni)~7mbI!An}yFPU%e$%YkWeoqN z{@)x8f06;{_!EDwPwlnoJh?t~pG~*w^{Jpu=Y{pDhip1CtWWL7>l&M`Pd#eW`E-3M zWYalgeX7T%GsOB-*rqec`c%KICOrpR*^|h_wEtckG;evMexbua&C+b4^94TIG4tAz=Sv6{*x{USqAm#bcOAU-J;)^49!7N`ymj<@fvqsY_uf*J zFrwy=<8Sq@?fC}OA#LG&{_0L-ceb=g%J~}T46Up-?rigQdJ`7zA;}A05>&Ak$KTuQNEmIm4$8eg#Luxt@`$4>KwmB+R!CoMFQO<5 z9z~u7wtV;eZutAYf0SV3+ZJ>pGO(b$*XM0UO)WaJ2)9K__$47t8MvY|J7HsAiTL6< zZOc2idS`Yyr5#~lD10??V<;%C>)haFu4}uNg}l&uzmr~E6v|fK zLFcD;QrF1uq>8GGdMiWBHM@JYchlgUuFcV)s|90_H-izb0t?7#?FHjph}CJ!TdB%F zB6_p{RmOJo9zKjX#@)yZpaT&@&jHbhQDU3h^C&7uw?wYuZ|JO@UirUj4S$jW==kTg z&EaL~_DF3!e^V3Ynwcx?DaUN%G28518D?8Smqq-I0`(QLJ90c*{yjQ+xG?8TEIZ@_ z%IK$ox%yVB|L`NqA5!HlvpT;Vardn6+v?rWk1UW$>ZVJT)Rh4- zx!g7xOrxAMCWt|;q3Tg^yBzSjg};%&7uw%Sg%2U>ROUs^9_678=>B76r&57$pGxh( z-cxLLQ#`l5oUb|vjnL)-+|e?qmhyTPWV8jAkM3@}Wk)wB+ItrbdgD&-vOY~k2F}xo zp5Y*yf|9lO9k^$)WI}f6cTFmK$8qc;mk_9yeRm?VqYZC@kUvQOgrKE3D z9;hMi2rwwSvN!GwH--wOJHpFC9p0NI(plUjmxTOsarYFJfV>DJ#KzZPc9*IO0>p^B ze5|4yR{3kHRlc_%To?(+tJGdTD+hh-ngJZ!tsd*>h^+2BF74`D)xF1?onU6nc2iy? zr!RN#W@$#`+WuYMC4-jEyX4wIYxkYJ`cf}X-&5%mh1ZrRbcJG>{d1owFPqW=Z`{}yQYlMFz|-^^+;>rIH7ZVLx#l@+q_ zRLl%&K#ta611z)!oV*5agSEA;wC|r(8@0sDeUi4_;n^+*M>1l!CE_<{& zBWmBdO!WFHKLlm? zW~wU5-iT2N1*wU@Su%D)&%sHZ4XFD!a{1ljL5o<95u;lrJB>FJGS!F&I>MGnW>C-1(QwBUR03@-%(xGOTP@L#CmPci@<|LcK1FCLSw3*YHI zm3sG&K*+K@I5}HZCPd)?bo&Ml zb>5w*2j@%&1yL9<^aH;dv*?XGn$WfT5IS~p8C~eV$eY8?gvm^u1~IZsTsL|!3%0Pe zm%4-^4mtEz>irQTPuHd~;P69;F|6{v-p?@sI7% zEbiJ!ag=siepp%)-Ay*vPFx;)CPvp`m&}}KQ-ZT*MU1`Z0%pjKW~1LDFV2D{J8g68 zzJ-~Lsu4cBtHAsUi%#U@7R1} zIHOyZ)@N)r#hVuVE*!P;OoM1(MOW;W{d zQgM(vjbx&J#IadrDt>R|xFq+rduE9~(x+Z2}87@^Lb$E9U`$k-j8U}~Z% zV(c>y9+&d_jGYbe0J3mAH+Y+z-FK_J5K7X#<#S2tukti_8G^n0Ht;l)aFg62=l8n0 z$@)9nslLq7c0;%c7Q>8H+_rC{Hz)yl_>MM=NfSe_8TczyJ6Z&*Va3XygYM3-8hkEx zng&a;IKr(mhjq-tvbwE(J|+!La!e(XdGNS2t?>V{hCj&wbo}f3X7=y#S_aM1YSdI1 z?RkUlff7V@(3{^z^PCjC+hi4yO&TJr!?|6uv?`L*v%%{GV-y)yWKIIhx3N63{F-7`%#0nmkqVb1*p@E-KklR8If$P+)$MYWw0JK2@y4fl|jTI ztmWwL$_rf7sg6{Ou?2l$XY?AO2_`LYIoXgcE5hZyva~#s(Y4jPNcCQg@LZ`IyrGv9 z`N5*7H=g6A8Zk#BVpHG{oIwnua>YKa@V`dGpJV_N_@lOy`tUPOK<^(rBg>q<$;^Yd z?eM~)%PJeN!E%e}wkPmKuoF3A0hIF^yK{Ogz`N|QAy)9NjkJQW&oQt2bHceQ^D?pG zH1o2BFb~trV|Anu%)>GAu(V2J9#$|9lQZIou7R&-iZ&)VOJ;=c0cJ*f#D?DDoM8b* zS=x%!QHNRdb;Nkc$Le7L^XQOsduMd195T&3>cjTV2G|iRb99lnGbFWoS41-riJDgU zU#sCyG5{U_;aua%**Nu8wbI>Oj%*i05}(y9o9U(#Zx>zL(~b+ z0sSCEb9j|>ix=L5%^EHlY>_Fx3(w9>d%BSB)=rEbUR~BfjGXo*k?ih=rP^p4A_(Ny zxm3T-2EWcCN_|r-NLLA%s14SGD$L3wyvpCPlgtP)c#NSm_h^jdMIV-yMQ`$&>3U*m z6!l5wMNt>(iSwqg50g>qy-T%bdF}IXM~*Gi3jgag{7D9&%zz*iB{N+9je{1h25wgX7-t3L~<~0?1ERmRVKTUw}pDfWN%&?arBap zk#n%kyBt*sMs)Tg`$9e9b9-_T`^#3$X^+8%@x^S2I)N3M!a_uhQb${ty8cYAJ=adJ z_|Fmzf06;{_~*lJUW0YlMu>7{#I?*7u$vZRelPmG!)r5Q?YA0S2e-p+{<|^}m)X2F zyrz%2OuZYtvTN6b-5{$`Fi5>ZDh{faqoHU3J1+=)Kd~)C1im?MM&3X)FG9ywJ9Y3y zeHMpEzGFM1__BX>WSMK#fPxrdrnDTaq6irC*ttXCiwAR1FKqLYM~JQ^HN-m>b&?Hn zt3ATCn9oGS=YB^xC*qgOu&V)L4PgHT2Z4M#!n`7qIdEKB-Z!o0|MeRFBm>a#C#|LG zx!K^kTk<33J_};(u87dxfQXMB9$xOqO7!<$AyXfSyav^Ct3#bPMSF}{y<@N+R0V z1FVJ?Np@^p8kRbPupQ2WyS+8U5fIt5bDq$&!hflTKgj@e{K;#xhwvTiZ=x z%u$oIs{$xknGmgGGq48df~nVz)J^cN8!$dhL0W?`dPKWa8X;TGSg^ew-M_jJF`dYqzL-g&D#|)wjPfidFQg^3zta z5Q+h3jcSopkHrG+VdqMxSN!J&4S$jW==c+Z)8anmldU!zT8&J+ z5xHZ;Z4A^$YOCy%XB^DrCFB*Heu^<H+GwU+6mK1z*^gc$ z)64&tHT+2ipyO{tyeBtd7qxhgsK$F}rJq>m+gsre%2ErsSF86`SbL)y@0qE_d-5-e z_mC<;w3!f#hkdn^-N?iakQOcvYp-WY^?Y;w57ixPO5z(38TYHIbk-t`k{k5!|y`MZb z2{|@>2G*#No?PUZe3OwLgEb;V&4Uk1c~POW5ga57U8l06Z7SbzE+>nfzY;MX9^JY{ zN6!}AqXm4U9izj@H$^7L=?&p5R2{>fV3amu%o5vJ2DV{W*@g*`4T^7wp&4PTnpu*N zSwf8XGXA;*f1idw$pCcxncW#K?!jJ)h?!^iQf_Un>ZzT)i}K`@TU!@4QEpA7+?wX8 zxx%H`4~|(&R8I~34<7ysIe)@ab8cQ7b@raX49`8-?p=e`-N?Jp!NJOt^`FsGggHtb zoicl&5A#V~PSsQ6;Hg={HjD;}*UwCQ{NfPCPdY|?ZA9}{Zt|AHYP5MV2F(?Hu7t^8 zBNdB49lo%t!*jV)wP3kh)adZ$dNsz;5V0I=_4*JaG{SDImosoj(`^3NX!w&1K*wJk z(PF=AzzEL>EQ)>msl!6pd0`EAa`YLwt z4Kqec-z`#p#ENJG<)#Jn6ygkyh`n!~*d)U)ET?#XUJYfYu{W&2d2lYUw?YjRkn;}~ z^pbbroL=$2S`B}a0qFQ^Ii1POd@j5-tN~JebeGqT_;^FqrpAZSO$YW9v9wTL*wIUT zt2k^LL<9$M;bJI(awsnk9njJ#(cuh4d9GKZ!nEGtu0(PWA+C#N_iR&R#9~_e12%ye@uats3C>|No5R*FWT-8)(*SuZ3OEWU z%!s%q6+d^a2vdg0m*9l5i0s;fY!_!;G`-?KbsGL81JLm=#;hYxjdE``euX@vbDg{- zG6(h=alkfNs*RA+$BbNC-j*isKG<>|)|0$Otnmg*uTji^&!6Wj8WbZG8*s=16okx# z>_6C-1iMk2uvqynL;?-Qa3em=&IEXXc{@~Jt^G%c+LsJAdjEoT-NtCYX5t^kA)8nP zRj0F7^Vo=e*wJ;+3id(FgLGr=uEM@XL=%Visy5{QY?Xaj&=H3CNf~n0ly#o)TRK!b zGNMPOnRP~FwU-~fjFwgptf06;{_~#?LhG@^A0*yyj#5TARs=0KmN6XTy`8D)$ zHD>qbBPs~%phkNr1DiD^+H+%gotj_E0o!s)H>k0mrU~|CS9Lwa!Sd6(o&rtRgDA0! zqQsQ3PqU9^#EB=_$4an|(m~=MR-J#?Gs81gZI2z=9;2-hdwkgpQ`yIgXzsxii0wIg zb@ow!{iL8Y;3Y&5^CxNtoO0&$ivQGW_>&Ak$G;A_c0_<8V#o~t89Oe*KQc4npqgDv zXK1}@c8xN@< zJ!aDOsQD#FqY*pGT6koZjOZt97Y7V#beN*RWNS!?JfT4L*C4;-OY3?}T$@~?>UxT& z=z8>=v<-Yii*Qg*dP;-?zDh2bWh%g`>HlweZx|$f^#oQPW;O8n?jnw)44NYoO`TbbwM% z(S#1rf&8yy^U}WS`)MbhY|18ava8jbg@}@^bEB#O)H2cJspTC+Mu~HU`A$;vIK!Sn z$|dE5Pok!|WK_f`Z z#_!4xEAanipRlUAB}WrCfPK6KM4Wj8)I4V7fDK0SU>HX` zS*dZJS&i}RZK|FHN@6=#+rJ##lk}~)1Fm>_#eW+${7D9&<4?IYba966J}~n6?3zi< zt{K&cj|EX;iuZtTP55j%sNbl=IsmrSJrV1_-T%jTduz{)1wUVgMu3CgdM9@Q%)j ztWNvl@O5Avc9x514=R_WR`3pku?2eKtnOW^Eup9nIzok{u%#FAX=@Seg-^{dmGnFe zTQaTYf0Kqk$pCcxk$XD`{sl$#+KUv`WJgN}^tjKRYKGpP=3QFNhNh{`gZ-d>?UeVs zF`A92&$>Q4qCP!T6TnL<@3QfEJvm|p)@R+4kk`hU%*ZkzCV>6h8?fuB4VJ_QrRik6 zXLV!-#*m2o(kgssLpOP?uqGl`9)(iT(kMd_Xlz8U&<=Tr?83;H(TiT<>6lMV*w8-& zmSFB}@_H!(rFtzE)+iSaQf|rFNS=jb<+Q?oxrRT<0CfB_psBX=M&#=(0<0=xX(FOM zHq%z9fXIGM&CIWeJnULNhedvUa<5l`HtaxW|F#^<@0JvrQUJF%E7TCu%#4o@;NY5o0X&g901&9v2@RM|CWrDXlqHEH`Ao$4NZ;*5PNylNX^9OuL*(3FkXy=y#jxAV$N(WnVW&Nct;~q5 zwA9xqH-iCc%A(%YfbEL8;su-~&C@~L2IE;B%YlO6-1v*32A<#~Em+#jl z@&AFqa%^r4n|gw&e641?KGUd(kx!S=zl@|XS0Ss$pCcxz43enJ2M*&psF&f^G*0{ zJm;4sRZo@I!}E5`((E>sKW|zZzFt-IkcQgA39iMk9M?^$-J%FFDTrqv5(nKb6vU5! znP+w@-t6#-NQay;;OtTN-@v{r;E_=BtU^Q<$cQ%Rcy95|M13e{%7qrlU@JwJVGcHf z`T!f$=rX{hnxF4`AZh&D0zfKOfm zCBwABzeU5JWB@w;Vo+CB#dbseg-SZ8uTWXLpW^kfod$CSDs>Gal+=bT-fc2=VLF)K zORP_;&vdpoMosYbmPO0E8@u3C;AKR{O6Jg^%b>1l@%E8750BJzb~JD?=iZHJy)(p7+Z z1%g_~l&<~E3C~dTOBSZ(mndtkDFLSy{;eARBm>a#AMR+5WcDAIR;o2xYIe<%J-8am zIyYdGG#9oY6``}JFYhbgc0!-I$9f;eE$lHk7J)5DavBF1#3J^TJ1?#aBD?F|5 zP>&!hZ($p}L8&pi)k`%O%c9nFPD$q)d11SnQ$kL@4?F|0<@$nFHF#L@uBR4orGNqMj=P0eE{% zl!A-A6s-bbTH(K1!=GdT`uwN5EsvU$r}~SjjLQMWMfEmzR;XzJCv4_$$I^%u>gntI zGEqB7I{RE$3?pfUgAco0gGT6h$YPKM*(qo1R-;j?`b30SwHl5oRwEZyQ(w3uD%`3H} ztF}a;6mcEiTA|h;z+dB+A>T;Vo_Sq}BvEW9UG2FzY=X~tUBryqg9qWI@Tzv$jJp9d zh;mfnvrN?i%7ys5%m#iCb!n&-FGK}`5E3y0jHnp5bEi_D9=eR-zcl~5R>PlU06PA} zu#MPRV@iIly$M#0-6t`UM#P7$moxmA;=fMApJV_!{>7-@vUawp^;`CCn-}K%o8+urHxq z-q&zdo|Pe3f^YNWlj>@WxBLH(P`)tmrow{*ne ztrVfNgzl}_q5oU$)ndb(Wd_E84Y6UWTe1#h_OC$Q(sH?q)`N6>82*5P>VC2iZ&KsK z+_b`fy@o%@0CfEQa-*D&y3ZNth3M2Q<|eY3L05L?O}xV_oAwc zLZ|>Ubrtm>aW6;Meo*6H&NTN@F0vLg`<+r9X#rKA4fUkNz3iy@q;3<4^N`PG=IXrL z)rwDD1y~cwgTLmB=JXKrpjvT}o2k}{qvHg0fKxpdD;T5MW<#|nERVTt(qs7?>$owJ zi<-xEY1T2V@ZX@}Pci@{yAyH;d>geGvV_268&(04hy(P0Dq6{*997x~jS z6tdl>Zmq|LfIR>y+PhoM=q-ebxTtSJ&9jmeAYfz2C6R&{9w4F3QFQoXUu`L}2G=8N zV8;qho|@KOq7Yu<)b0|b93~|XDTgTsJ=IIe3FoD|0_eRZa#824uMaE21+WQHkd&Xa zHaOr*@D?+eAT#8K1@am$a#r&=v|^@pLR5mB!d@yc#gYh^E|D1R<+ zq^@3emJ_Na?KJaI-9=AvNL@$OTCJQ-tD~#1j%LB0TZC-a+NdM6-n*u6m1GXpcrl_- zp@q0Ubi?`R!9jf`W@x>6P~k~cB9u=uGuL1)BKlMFNsBQu)CwWd3a$SdOT zN$o6w+_Fi_Cz&SlNlrDN)ELf(Z?G(~QLPZ7e3A|PVm;~)Kd&0Lqf&{VUi#mgHT+2i zpyLl#Y_Wk~kurn&@{o@vQD2^PXN@J1nSIo$W3{(j?aN~jq2VztQhV}9TFwSO+Ff!s z?1iS|QFXmr>e12fBWvL(W;e@^-pV8^qBC)H3#{K317z3|5E;c zi-teR0CfDxf)}a0+CC)!xI( zC#wzYD$ghmXZ6Bb+fmsW(W;fGR%sn;y-2mv5|$#+tQc(23d76CSY=ky|CJ6VR&iX-c)0rrWWqx}DFdcC6F`a5?xJMTE_4 zifTve%hFM=s&-6=Db7yzFDwT1~AjW02P=5!53ycd7QKk0h!`ZG==pQ@-yn|E(c2tO) z1ayZ)*Ew(!m3cUbdGLkEOOvnSL|4EpwR1qm^y>fd6%Buq0qFRf2BEo|jHtlB_Ndvw zJy2dzPRG_aa}XI@TV@}1^wQ?7o!#PXQ!6afy*~W(+|j|2b4sMQqzZA=31hXN3D%X5 zDo;JDltU^W^b!>ju_g7N6U>9^e{0a0u~p8Co{U*{{;(YXi*XlpDPG6Jx`QeVW@Zc&@|4IEO%BR$S=0!|>w?W&Jt=50qBWux{ zSP*mj9OzAqz5*yjzl|FHBm>a# z$NHb{wAvibOLu23RBJ$;=*}#4H=#RoP|8i$&^N1U>XqouoK39EToSe+-bWcYurbtW zkfOQ?y_qL8CA+MM6Kk3hCvtALc-_A$#MVXXC+g;xs>;mk z(NX7A>Y8Jm*i12>ba!T~4R-W}LMO;vMBP`yhx4eF7?yBAp6s^)d(-9(%V7FzG0JRM zF-S8;s?TOz8~aRLll3iXz9F5E!Ss5ZFs+C)(uH5B)iw4wOqLxkSXpDHE|D#UC zEuEB4VwMWZCt0)m)<|WMiXL>c;`1Wqlu0t?M{?1ZhBHtv;%S9{yM{l>0CfD*KHD;A zd4xxhE1l=Us&DF$v3~|nyV+EU+6wMc{gm9wPQt9CmjtLp7Ha_Ml$8FpNBru#zd^>nCcoW4m$?BVLLf z!I_~nd~>>!`;zdr$O|*`HDO!@RU~F)m+ag+j49&x`Tj+G9d;ec-m*HP^d6U1^=6KY6Qd&{lp-u%vy(Kx_9h*YW`*Bw;YiV?|Jhy+Xd^b~|(_Izy%d7iaO1aco8`uSI(xz3X1S@q182`^@#FtWwkEt5y&kOWVSK_>{dJ5!VKXwa zZ(?`3Jq)|CbX?uHUamqU*v{TeRU;E*Vy$3t7EZPB>5h%FA~(tF`WoaL@%_zIxw`@X zyV*U5wf+5kf$tm{{t^G&aEgt5XOy!YKYFKv=wv#U0@Raj($D!q}Tt>>3_zZT88^^29Gm%!;D$<{$IS~^so`Z<n9FC8(=DkdbW4LGVIxvJoW zqd>Caaw!_L;wMuK2(ltV50mcGL@>iBsMUUK(do` z$ru3|HnXR#c2_N|zw?6U<@bkWlhRSI%{WoXQ!GjV`|Dmf_x1DI+~L)+;~3$>hsF(@ z`A9Z!tt;ZLHx9dT)~pLO7tal|5e@y|kM2-dlBMYTd*=o|P5wxDZtfYD^^L)S>z&i@X9zLv41VMU*19#t z(+dA>8vY~$(D8pVWBDsrrTE#bG@$*on3Yv#G|+30yl(~*_bf_`FeV^+M)dzoK8s$u-%HyY-<2MW03UC~%Rtgk@%F>hrYs+p9H@WKhEd8{o<%2YvG9(F{f`IZY;rw zu-&XUKj!YpAN6Lv{)!Dek6Szzi;Wyk*@tN6&l%_>&Ak$Nz(O|KsS$-1vzf75(+}8$}dn zFHH)jBhdO;p^~;G1>O|H^R#D=&{JilPoo+nGP0bou;+fv-H@XqVF$P37LA>3j`y2c z=sQQ6$3ETjFJl+>2#6}w)ZSLY%JM(vzLKY&%Pr)tI~Nn^dbT@9Sebw*GT-UIPd9w> zVDg4fx<^g5-$!MbJ#oNPkQ9t8!DL&)v3yDFCqQ`7@J~jEvffZCUujMbS(-n*ufq{P zAiSph+przG#ymUfK(mpxDM$0K&v1_SYT|)0vl8#gEl-}ms;u_Snm?OsQRk-guY#Y^;)D)WPJs-^YG*8a{exCe{WU zcHk02EPjCfBkQPTrNYeBDKSf2dI#dZ&GA^aH?CcYuRR;P;gbh|V;6ALv4hSg{J_IK zb(tsl&f_0=cYP;ev)u8)S2nOK{_TA(na$g?*D1D<;WLas8MsLiCai^2Kl76Vqbp4~ zvIgVDbol7ZPxg=Q^O;VRZmm?7DWQ6@H>~pPaP9~nsZ{=icZcgce)1F|hU|)&p9E8f zkIHq{iL<#ytn#B_co%7}5v$E*{B=qE|En7QBm>a#CqGHI!Th=Z_n^=G$&_U z^FL&H%}Gu$VWwSJ%&MeUwr2|1v6FtEYn{*YZ!?dv(>YS6+;U`12^u^rum}1apU*8m z7vn|-73SGrd#7UTI*b+l^}6g6qug6(#5c;`ehs7G`-tdZ6s!ZXW*P^r{7OEeET?g> z?k0ux%vX$kBT6M$LomfEH^n{(R4QI&m69=Kd<>uATW?bEj_>iE%yWEfWS0=ClD$dR z>P=R2`~0k@1y`AmYutuw_+t1>_5+2Lf8*$(qfhz}4Y-WIF2R4NhCj&wbo>`=ZBeQ{ zp?dBrni&g5PMr~*Ey@RhaJ~PbmpJm<`zbMAIG+j z{N<>WGWf-L(y%bkJj~Av#BMD*=xaZ*@82b zcRBE%E}VP*!hxSW;+uh|uRYOsPdP`(&&rP-@D-iV-goAdG;+XKkVZ((dgEXJIQP%zpO5_#XaDvzjxz1+zm037 zB9Z=nI{p1m>F@uhet+mNACSj>+@3jVvOlV1xM7zBPT`YT%xRWxu_LDS?NN?>6l;Lx zDsT>sni=96XGNYbd+Q8y_!Z7`;oO6tiHD~Z{<}5&Nd}ZXQNgy1bJ~7d zMCZEZAHvyOhk8Cfolk!{U&Wo^-NBdlmn=_8+e8>YBcJ~STe&tJaSa3lurB_ammJ_X@&nD4S$jW==g8*djrRh@Ice+=aCyJ z8quB$y}mX5`j`ht3bWKB2a4#3hJk5>5Ab-OhnMD;;_35v`mpXVCe;j4uKM)p*{@Nb zz4XfAmq(8Bm6q7#CwzP26D(6cci9p3ZUVK*4>|f|y6)kZdHhRzD%S5ITEs&86{A8i z0daVKasHEyh#fuf@txb|95IeoawSie;`gt8T=JByhkFt$oNezLY_yu&d#vmIy^M{T z_`SzYd-8uUt?<87!=GdTI{uHP);XF#+_&qQ)EWmOc_C74@BYQ^SG(We&33=)Ro+U? z8DdE>bp`Qt>twv{8;3)w){sE~4u|*S|H?zGG?Z#Vwl9=gCI4jf0(%VIKOakF9hQ(k zd@N;WKOFspX+LMOYK6_yenv0ZCr#Bgw{Y_fRRy)5#AM_YE}VPuJjITMVLeK?^oR_L zy#O3xp_<`28~bEV#;~jio>IJ4rM~t);zJj*=+z6JM!Z_0zIrM~(Zh`4S;ew)9vPxt z>Z>PWFW^1x zI4aF{(mHVUj-p!sNvs2u8(chG6nJ)&GkBr*z11&bt`_-o$iCO`u^gGs3X@G&o&T76 zOtU_RUzT8f)HTRMSJmzRq?O2peZaeTZozK9FYv|@A;4W%5%BrlrEPJJ6L7bJe_G*x zw}wB-0CfDT72Y!oHkwywoGJF3Gb~tH+u?r)(Z28330P^hdH+s|`8~z6lxkSjfzQ6~o#p zr>$nRro4B0o-(cQ{~sFuBm>a#=iTd4!_Uzw+MG0S>rxFbnP9KiBXVouDT{Zv`fOwL zB!!!b=t(Yno-{VXLhx%_yT7gMB|Pcf3Yg&#*6PK)-*r;B_SY$CpM6x|kxBF@XSd4F zf{(i~(tNn$3iXOl(iI(Yt>51m@YNCa|MzKA;H@(pXZYw_yI7Y`k&jALSy4 z5V!NzzKZu$4Nu++tNQn0x*J3KZZ_d=#Eb6c#7V=o_ECd=C)KZw-Qo8rzr_7i7PDl| zC({c5y&C=`1JLoOnfUb&+n%FUa@Ivp_DBE4ll|^RPj;u{wX(``(=vJ>u4774DS80d^iad&@2bos*-=pDAG5{U_tv{Kx zk(WM8jdhcUh;_7#!0xtcoQM1V3-(_l*dpZm>!=&-4mkdf{BAdiA^Miu~&7<^O$6!=GdTI{xkI z+PHIA2#5>FqPO|mOJ5olvan*$CYvt!{U`arw?{?WuT!?GVnwj%Mamdd)WO@`p^gXR zf7<=KELtc2eVk@(lWNs{SSLt#S2Ju4h}ERV^!wZ0>8o0g;i^{u)hDfi@8GJ2j~?*< zz6k2DIm+0cY*+AhPo%>GD={lI?|HgnX&NWG&)*#};x3y?=pKdHM%-bI-{^Oo#Jykp z2fDM3HD~v>L_4HlWwB?%Ua;icAMd=g?)PnVP1g8WRdFeJpOo~R|2``B=BIhz#e8hvVMD;E?8h?|RX%x>dQD-NOXqnE z34_}>Dq7HSH`p8xnrU6X0y-ZCA+g2^z3MyOi@kG($(6OQr$n|T@T@QYf1hV{6QQ=fGdTG4~oDm`$0*&zglt6b|dO^`F>rJ|GQ7apJV_!{(Pa^PwdMwlC8K)rQ~y; zeRs5!8AnSwdaimr=kxQ1{O$|q-d9)h|9aefa1*BIELS0-28OIZUO(Y?m>xXIdg zI7o9*uqm1k!KyY78v>0b!YFU_`M3C+lixAUQo!K0^Zxb22TGnT5*PBbVA0!}lWoSG z9qs-VC&g>YH=I?h`xJp7c@zsU4$IY1b3LsTA%@DMpQXe@ze|aSpRZeR@^`Q>xO;8^ zbOcgz=+hUm7wx=SKXS4GWD@p`|z zHsJpaVnP}($RD{n;2o=T%VQ0#upNx-$B(h1Bc_XaR*IQsRgtW6y{4`r8do4Bze%=P z5Woq42_9Gzu#$aVOm!qR{){q;ARsTB#rq90Q}HfXoFM$YcmMehsy)X$+}^;Y_9lqj zK=5Tv$3z;D?;XyZSOdI)Hb1LcJFNK&rn0Jl7Nuw?S~5(UqiKbIP{W^O06PBs{mXa! zIwb}PJp z)no3+&H#P7DgEjB<0*H^Q@B2p&vJfTopEk+$o!2bEG5{Ta?OAB6ddp8PwzV}Ap1!4Q!p}F_ z$c9_9N}+&d}{BRy^daf*6e$B-t+W5&MxT{p)|Xb zhh~vmkk!r4rtkJ%o^nnLGJE(r^!>~|qGIcuR`@@l;ZHIE9e?c^RejBxep*|(a#Zk&dD`UIUx#)}Eed|8%T0Y?QJ0c&>r*Wlv0@E%3|Dc9H$pCcxwcH3xuJ})% z?$Y$rtv`Dgr)B!_boq5fTla23W{p83ICq~hP@!G!|x)!uKy@xM$QKOMBCj}K2dern?QZ-dtK^{3VRe+a;HjFAjL$A4q``I_AkBaP(06s2xY|P>*hliRw|Y z56pC<_Fe~$`qiU1#{~7LfcHL|e($ux{~H?qBm>a#&%@JcRiDoC7_UAZ9#7||>8DeO zqdxWM^)U`dZ}_m`Sq{hlkUn05;|tW|l+T$xB^K{V$6db2TIVC8Ot!lI?B+>pl8)Et ze9$p=PfCe!l4Zx!iyL`}v}2h5t7-{7D9&>UYYXnRQ8|Auq~2>?%saMnj(4o7 z68C#K!+&Y~=YMMWlMFz|zd6}%hn=+HpNV4f3x|JyhPB^XPqt-OVB_;EO78Ms z9S|4d_iC|fwgNm83;phsCo+&1;(Ur>R5VDhv?;m!;qAA6f0Q$K?u~R51%GoI*TTHk z5c*YdCj>WV=ZSvkYbUS^8mOc{<~kpfA19hEv0-H zs&_+dmVbC%$x6RHAfT(pW{Sufz~XMU`_~L-1`G>(kuhm66XqEZp;_tA^e;pH&T!oy zD0A0_e4sZNAK9&C?~WlKc>dh))m7okQ?hsao;L;zYW8kZsW_3ntAL7t(AA@hzLZ$# zQFuR8eCK|r#&z>z$o^Pf92KpRm~F}m^Tp%II%TEMs>|U$uHqK>{M*s7ge9{cu<<=t=&+|p(~fcbN<{{RMh3<|0eIv>awMd^f4 zf@{#|;NCFcG_HxG@8C)Yf^P(z>99>F5Z<^9lPHh`bVg8ypvZuV(;d`_OSBzFLcn>a z5)-;0+wVD5-2uh#@B96m@cDG5yXw}h;y&k|d+#~VJ*TYYrZ%_Y8!YJ z{s~K`h1=bko(P>|PiRqVXPe@6Z;I88dNsachwUZvIIn%H^lvank{4lEE>W|GlbLQLpTkg6&wJN*cmRy-rB|VhE|TZ_1{$b#M!B8+ucnKaRQ(tL>2= zNmSyHL?uF^5=f%p^>Qe0djZ3L{`kLI#h+*Zar_hE^&25gLyt;?$1f39e6>d<#jslF z<*W03ZJ48x4My^VZP!e;bl3w|r^N6&TZRz(N-0D0`pmA+a$hmDuL(Ub-rIQd`>$lO(A3+f3e`2S?>|Npb@1CwACypusO4ZFGqq8BN3Uq&8E zPcA%^*l_@_Kk->6MZg;h%oC?7+TuXpYlsM8LIi4JwcLBALV|@!*@rZ&@c*5PKhXf< z_+P8+=VCeE4YA`b=j_B{IiJNmr*qEPi}e#Xe*2?RZ;c#6WHlbq zp~9>^a%m8IOf4)MME%Y$0H)r+5!zPEUii ziAjI+GaUc!zck2AH@R7tt&F0P>3)03d`IPG->c)y!DfR;;>&D7=IoC?)7xy&R>BjB zdOi>RCqnZXkMx7zhR7gH`pxM!Ii&bGnY4*&3><1_lZF-kzgO`m8bBO>kMwPW1jwGG<%vop;Gozjo2ftlTxHShwMK};9aMr!1b8Sf;X(DPsjT@zbt6GE4SjKRcu zDrW*$Y>sP$G^5uPd|rOEk)c06FPAb)@UVP+t@^73wLLFC!mPl8u0G7P`27$w$9_M^ zSnzO%!^q*7rsr`?*J^OTj~xKRlb(_)?2UcX2H$L-FYb!{atKZB6gRNEQ7g{z`I^i= zZu%Ur4^cw;qtP>J+&Y~Sw@!yBWP*2C;a{oZPc(oy{^p1#C^R_)?4K@mdNmO~$T?|@ z)Ha6VyKN11jVaLYq(eh;8!)Vqi~Quz)r2|Wd71OOB1EYjqm%dwh{Bid9yEXD=`@AMTXENG;3p+kN+3h}BBiGmmb4=k>r&14O3JQi~3Kl^w zCmrYafD0sr?>+Hh$-hH?J$@r(%gt_V-g5k5_HeVQQ^&Y^dg>=<7~Vtc|Ek^L{7l*T zv0Oplv&-nSiEOFI#Jg=FtvfwTu|Ku0{^%G*66Wv5*mD8@J8%8JR>hxa0CD^UuR|CS zp?2ZXF3C!}c$z3CD04c!W~Gl91bsw}?TJ{i=rbBYD5ZFwrcq10IX;pWW1-vI)1L3U zy@?nkyf0hLC7ya^%|(aesM<9iVkUu?8> z-epv0CD`E_{Ue@p7oKClbM8Jzhh4z%pTGWJr{YgEfH?kFMbd*uI(RQ%$E1;`n}0Ak zn|Drc8gwUwRXvM-WuF+~&~JI@=542&4f!FX_*FY*atRoL%{NJBEck9^+1gj3mp#z_ z+>-Z~V3++9?1}xR&PnXB>~4M&efP%Zpwe%jmv3%-UY=L`yj&D<#zqi^2(ZSmR-|V< zdD?~%{*I7ae69V=xWSz9vGWg~rjeia{>&G*w12SEA!sL7w{os(PqLJjxFN*XS)rl+ zBA4xK-f2PZ~A48E@+@S77d|vbBOMq+i(^o zmVI-CW%uWJfY68?%dztWb9d$aIFuBW_sbKX%h2Yj?|0kj5wZ81r@Y@~^8TGky9RS6 zhOxWHY;ITQhkCq?Hug42(kss?q-SsGW;p}&@NT1N>1_w;+o8EZFFL_L!6C6f}n0ME*7W)O}_zs;j zerI6(o)ETmYE3kP&w)mt0hs{vcsIY9jeou1O6Uvb?2GmeVs#J}rd$=mYM*hJaivl_ zSEr6{S;`$n7~L>)a8_Uzi_Zo8@4WGUql!P#0OI&#tsDWTwnP`8oo-=@Q#QBt;^Xt z!5%S#Jv>4x#~y7q-dvAeU0x%+?hhV*u(|U1gY3a(hFTaqq|Dj#5%q!dnU>BqaXHq| zH@lgWW%nU+&)l8OhV&4ZJu1RwYn&q@h$4pb&jIPA@S$0UclvWG_8A4}A1x`JNw%6ICXi(&aXa<_1(;yQ$Ak}TH{$KExR zx(=3_O@6Y}+@=|mmsH56c%*g8>VGhr+n>0FO}R5<4{8IZjbFk7)zO44{A`x z5-YcT0VFPSziqJ&Nw5!8<_@2D^~l5 zkaJ0gql1}nOvkGKketE3z&L{%v8Mkx_RS&u{hYY8+qvXw}fUW1>C4=MnT#70`n41LoJ<^fL z=s2wKuTt?R8bBQXWR?bt>tOV|-dd#}>&s~7Y$|&Z{n&_p{Ge)a-8Ozj>RX4azGNwi zRd7LB8f>bA(O_R~RZ1oK+D`aige|YNeGq;9=CU-*;~zfL{6nJi;LgD*O!AarW#KVY zY65?2r$`eXoN1HiH-eevx*eMMHXwSv2H7~Iyt0q69x*LJ+$n#;`qaSmU2XC-KN~+- zcRS`5|JygX88)2tWT$-3|Ek!x-BD$6xy3Z;=ztl|+3h#NDv%>uTotl50GaZnNe2gv zopvL4S!(cBv9aLuFv-fcjMU&OuA>2Ac z8}58zptxPNy&qA_LNkBYPkol`$Kx7aBzEjvIkzo=#br>s9dWVs{f6l`g?Y~sOYrBKoZ6f9m2SfrcEh@@_)fO3VWs~!tN0TQAdY|Kx#Mil zh-VhRtO!~zReE-yxv4P1CV1ehQfoHH-t^T_TgQEz#-(w) z_t`~?S#K9<9?FmT#l@qr=i4LI_|>K z`z7^aB>z-yk~P-Sa|ispA2|V*wEkI&!X&+YxzOmA`n+e;J{?y~L& z8*(C#oG{^z#mXHopMD-zJEOR)``(6(2%*KK4}fxwygrF{-x#uWeuz~D8(EsUU-XMb z;=9lo|L&Uy@8Ti&7qtPtj?QfCd#jVPEbG3pfly2dEvn<|>HMlbR+SLJ+tbVswn*NT z643}b?KcQDskDtNow9m2pd`b9dk@7UR#5tO~jhqzukjPXCf^N$Ti ziY*`h1AZ`fcZ9=O!K97;!EERRa|bL(gRmD58cP&i@q2%+k1aLF^h9pU9Mseo{ku{R zd7oGKx#|-50-B{K{dtNP;2^vJWc`^SGeuMUm!Ed6OvCOJ?EIU`Ra6#ahqwytQ{yWO zaznKLjE_m`ulj?#1Za&#Vf87*Q@D`P|C#mQ|ETyA4Iqv`=PrWIkwLIVG?oPTow>%rY_sxPXVK#?bFL6I z%5Q^(Ibq|K7!Mnw=bN3zLS1ZC`Z6qngV|C$m3~+J9)B@cv9u5Qh*mb97+&-LS`~ky z0mShqovQ_Nr!VS=^A|jt=T#J#;F+^wjF|1z$9mq@KA{P<1h^SrLpC^po2+dm55t^W zxl6m-dE^0L8>){RSOq?MU~Pwmp#pugLN?mtSmyiSJy!gRrXjx~6L=+yE9G(}zayAI z@;e5^uf*)bzn9`ytKP`##w24uDm;-{-8uSDPYyhjunwv@U@v41aGw3|MHPRd0mSi# zjTK&5PS85lNPLsAFaMjy>(8;aRAAMVi&-GCCh|CSH6VO*18jv66TjZn$!l$$Z)5Bw ztBb*l%x(e04t)T*q67_Wgn3};{blfa#kR0tu@Ua~-vHZ!2DSxWu`TeIW&BaEtme-6 z4Om$YMBjz&DHroZ513y$nF3fvY0|f6D0%~Z`|1oQ=mX()opMh^xd-v*;NMm6c|*A; z8zm2)DMBU~`gQ>K=mLL<*&Yu1ZzS$g05O6tWcbhb|GuQ+Pc(ob{4v|E_ajOYgSJ$d z5@XmR&ph^3WW`+j0Q@U=K$3qDe&|cP4i$H%)4% z`*_^^_IoyBZ)eUa-hct2@U=rkA9Q~^7CCR!63p_+FldF`cX z$iT)6M%V<5rS^!%X{M`526zBfz7{dYw8+Ma@`Bx)RJtHGN~?D{gl~t&<^Kjhgpc`X z<^n}Xi!!Igssgr%@`wf=glDmGFp{m;jCmz75RA00dn)9{e9{t|Pr5Llq;=;-N*&DI z7S<^1PT$e9tIi7;{`33)D=Pj(1Bl~42kled57w9aUd#hEoHi#X#OLIOSq0)Y=T{U= z3{SfVq46flYPq5l9G?~POB^%K8WARo-}Oqlfv9y5eM{lmUKT=zufUjy z=Tz}LZEQZUunheV~IgGFY2fZN&RM)`AP#nPTtx?p%9E*T>Hc zEBybc;!iYyIR3VtRg3jly;;HUgRd1H@*)IWFk!5pr{$e_-rQ0fT1j0Gw#mg>TTkl} zTi5G8bsfiJ?d}5Shli)d*0rq&`))a*GCzaQO$flU$Wj8njN||lG6KAi88}jB3Gms@ zN{YvqR9Tb{x-ZB zal-2r4@Euv2gO=$x*78b=kl+Q+a(K2;9g)avrMF&n$GpH2e>ELb=(+bmSA7*Qf3yN zREuMb;;~q%)G(~@->TwIG=Mn%Ebvi#y3$4iWvT1uh_20AmlKj;gCsQT$rkq??By(K zY?BZC`G`Efmh67!jaec47B&uuAu8lx^yPtH%9FN@klmZ94>M^=*;sJGEf_m0WII;> z_m-7p=HvHsu;(09tPM}g+@fA zeR2r=4f>TPd1ZKgx1R`~x(#h+*Zar}*yzlGn%)Ah^bG$~J>(>_9J)1~Me6_~wi zU4;2uu{XL>X>F0^=Y8nS=4$&I=foW4<t|WQ)mw?KEWI6_NqS>jnJpy!l_9ia*f+;`sCEuN(cQ%4|gnu1ijpb_~9E zY$Voe9;wH#^epL0*zHO8&g_0{$4Ip4Jgqjc>)2b!wnN@PS8y;YE56=)&-i=k>_Z{) z_Uhs7tv!~h)D%)`8jQXJ8^e4pYIE@JJ3@xalugN1nSoIiMqk|jbe-dfJV(1-F3f&G z7N_}-jZ)BURNn-Bd_O$JY9F7ngV5#C$43PoJZ9URFIpk3um4#PQ>E(%t{)f%G?r`Fvh!uJ?!U_(>W2Mg$QxwB$s{QlszruaXVN z6IeoXNoIDvr;8-XG^p>o)&5)j`XzqxgZiFHC82uKh9J{i#)!e3o z^1ri2;@9_CqpJ^goX%p^rcG_~b&i7_-ODp^{=+N-jt8Gb;nfx3hFO zHfN>dxXoomnPT_{#q3K;_sWIS+8|8_A!{v4Fw(`=QGT=Ja!_pD)s z|EntgL<5N9|NHN1C((TM*&{D9rMu86sKN z%YIJaFpgZ}cK1I@hx9#SPa-IG@<{a5D15++0~ODg>Kx z*OENs<5^Hq&=DpJKJR`eOmg#ZNcGKT#(a~E*7u5kazcdSOx_Q_0{Id5^+BKep}XvK z_Vy50si`Z?oCQt)VSlRPYaEDP)9Zk*vAC9jZ45h+xgcbQy+9vHt-7d=txc7N75>{) z{D}q-$Nw+=gx~H?&P2={9(FNZh+5MgCYwq!v^}vrgwkKftTh^8@R&~MKV}emk2&fz z_0-ze^t0ea^|gz%o!7IQy8Y1ZSNC&4N4)?K>n!pw`ctJ9{b+YqE?>`mhIyL?$)&&- zsio0`{EL5wfAJ{dypebD(2yNyd(YTsW^7xI)#+-i3wopPVjdzv3(+2)PH3T3uqeF` zd*ajIw8`Dd$c3E+WkRMY;LS8ZCVA{D=Ew2bU!WXmqr1z#fSnWeqI0+j!wUcHD*i+R zh~q!8Wd@jaz0nOy+cI}Jd{s5I7x`RgQ+wHI@6`wJy3VNUi~dKRq3Gl*%Gx@v;w<3( zJ>}Qt+ySlZk)HL(ZAKnxsXtxO%$Js_weN``_YySo)tuI){Ruxqvt+J+0aJGzKZ~cT zcs-=xrCOyavk%#&A5d!4LUYfEy|G8Sr|hcW5m~4uEm0;G&1O;)_6RX&Z?qdb!adS4 z{~qKWX3{r)Q;^AK#JK0obHt8z(nrGz{~ap+L<5N9zho*j@WRT1@rpiv7!m#-f)8&* zn4j#CE?3%`NvnHj)YQn`b{=c_cl@L3SmmYA^~Fw=kK>U3+%GlFhYU3-(Vv!ePi@!` z;lTqPsoXyh)t#A9MI2E>*;QM%c9y~3?@t`r;-516GcL%+^MPk0v_j`&Pb==7u~~T< z*5|AJn#zfFhAPrB3;XVmEW>VsRO#-%JdqoZs8UG_A|zitq~Q&$ETGIGA^-57mEaHk zss!sds51OgXFfxu;YD`HgQX>Zf`54F{{|I*q5;J5f6qT-8~Tk2+1drAP1!FZGqzPi z-=<1AeXoeNo-dz$`}kF?RJ>|G{k>}c=Ht(>XZ9yYOjUGEzk%AbTYUQPw&PDT^;n4# zYw&49pDY!z6WIE5SK-C0ffad?G4N(5XI$33ZHEz~j|SPkMu*w>F&G)3+gYkWTHXRy z&vO`e%8xmmR4Y$s?R4FSF+#OY8idD>&8S;e?}w~B+sjYp!fc#2a(CS*WsG{f7yrwI zMv=4mGAq&-A|Bu5oULt-hO$#@e&fzOmilTo3=;TC76|RR?w&oaGoj z4}Xvr{-6ZtnEmiZ+G8t`B+LPvCEgNZBsyZ_f17_$uyxwaJS@(zQJV(GX#y(OC<3n0 zkH`LLEwENy!2iy(|1_!i6Ad7ae;(TO4@#Rd_a|XpjBWM)Ic%#Ul=xvltBm{2Sc~Zz zlic$|R(F2L;=UWa%%Y_Eu^7${DX%Ym7cn)@o^kgv_qE|WmD#|{{vz-JV5f~?ScBPs z{^w=`;@BC}uxEs9P&NKIQ!G#6YvwC!0{q4%xtFYsaue675#M+8xSMS05e|RTWRg9}l-^UBQ z`>GJd^U%aJ`m6@cCax+tCVih#>_D_9u)D?q9ge=iN?_uv!|GX=26J*9Mj$%NoV<%4 zH?Fi?)&yQc?{=1$hSnZ>`1rK&=JC)Ii%WQn5#=%$5K8{tu7NaQ{ZPUMPtiJ}gb#Kd z%kSbng8%EG^+e5&Y#N*4%PhK(;Xfb$T`K-W1Bl}vx9M<-COu9z9mVg;q)+{XhZ3_1 z_MBHSXVz4zR-KRjk5-*W)iy=H-R+NC6aMleYeH}INWW@L*sj=hG&xhDLo$Z!2KL_C zx9p0x_#eea(;HQBB2U!saYvfsbG=Mn%z0pqyD8Fx``764 zIU-rej0&cl`=*eJ=#A&FCrE=XR`8r1N~`A9ztpMj5Z1OhCy0pOp$TYVX~`8eu(T{c zorf7lZbIhaZgJc3Oje1Hwtfwc-QwFgW@2VZNALqT^8rm2`4X3P&uX~$#G#VJ5LqUy zA?@}Tz1mJIyYa}4%^Q>*$4o%Bw}2&*Dj2{wna8x4De@7Wz#<00Tf#vTWX80ILpXI# zY?u;cqh(8Hx`!41Z>aba4IqxcwRN`1Cr$v4>(Pf8quucwt#ZByIGLpdeu;iSSub{dBY}m4{GtmY&7|ppMm?M#EP07Nvhi21ZzCzY59q% zM?He&HeTeWr{LG=wwF4wx3_bKX4Y&&%c0xsI5({=2*wu^Mnx_T*J0I0D>fZCV)=>L zEu@t+5j*l!rAq&h_h6>#6YpuJzxRN>L~~V606)pN1gjDgV$z?#G7(574AS0-!mz^s z&no^z1Bm0_8x8dvMX<2RqS8;1v((s0MTne5QGCoa-Hoi|_!A8v zjz4F?n!EDvp_?P*$ypHAf=kgKy&GQi@=7|BPVF4n*Pf11^k(HMlWv6w)A{DN(L(XVru$u5-i-oEj1IBSNf34?o}o$-Yd7)IX>Ru9TnPESM{< zl$UZGem$B09#)d?b=(!;gYHsT535iIBQ_yoP{qERORYoSH9=#kF5(y;zm`yHgOsV3 zfcQCw@O@lIC2sGz^ch>v+fS)dIA1&y&43gx@Q#hUQq5bsV8Y23zr z>R#J`UsE+7oS@7z@FrK*$WJ@z{5>IK9k+I#NSHg*-it zEMhEiPDoeBqpSt1G~eL6?QF{8ux7Itexdx3fH9k*xm_KePmEyKndol#{D7kSn()2B z1-`O^i;?BoG)i#mPcj}6!JIEc@*KjI5mrtALp(!~$zMd+W?j9-r5#@O-`y(yL<5N9 zzu4}OE*A3~x!gjBbYy_rz(oos3oTszeC!!`+vkuTAJ7T&#MSa zV~>hI(E#H3Z!K}6S859!(jv6RtKNL^di1+{2I3i)CJMdLeZ6PL@;_p~pV1c(SBuLF zjGxt=WZe8hZLR}3**}2(*1{&*-c}o=E7E1kPQtuWZcM$CISjK^RD6 zcXA>Icr*Kqo6MQP>s}3eE|YHg>yeJJK4;x+vb7-#5^$SrTti%xjk4~Jjq<3c$NrahEZ$vHR5t7| z&iB}$vofpRnA;o8?js46Pnc z+aC(V_41Veo?Dn5$S)Mus`yrpnc4k719v%a=3R<}*bTs9bXGlKH~L^N#eiSdJ-vZunx>Gp z%l2qioeq{oAy$531L+g$tp?o1A-G`Buw%R@bRvuS2f8RlB5vo~QpPe6|F$X}s>T_S4ufcI)THGKBkW@%=b=JJ1LP;_Xp z06m||L8r#~3M`LVbq>^grBX9tI0;OnEX?zcVos19cx868^u&tffWGIW(sZ9oOhMKN z$GZ;c&WJ;!rGHs?j7V6zjRk^0h1Q2Sd^VE-Z17?FEY+tr=4u~BI*>@ z64`-f>6R743jbymf1&}z@lUOuGxqjOw3Z#*Ogq>=MOpRl0tbE1t0leBNdwfPgfi17 zhQ|gMi8MwCW#+C)1vHBHMz2%)6Vo#(wd|1iaYUIfFq$v4$xjE+;+QWu1E#JIi;i@R zEkH$v$E4G`ux|O-ZmoZOd-gZ?M0^X0$QRsdN4NU7}%Cs%}+3dh86z%Rs4wt z5XV2OP7f3>ip}JH*p?BT)1*K3ujH&c1I~XLYpwQeGzS|UoZdv5wl{i8IgdPl%SS1# zm{n)OS*=owM`~F`y&l=;b`BZ)rYZGpKj_6v4k?Dcmn86{(U@eUSH2Zf} z^6SU8;Ow%iTPQ1_9~^JW_t;TZoUwe&YZ-GTKS!GE2=dY|DfuA6XMMKw*?)4*VTJ!Y zD*i+Rh~vLtwx`R#oCynI5&g|Tai-p#y}nucsI2PD^PTU>yuDh{|I}*B$1W*(Eptai z2gDvYj0kw2ZcvR5S zWbRp7Nq)&S6vPn?v0uU)jEb1{_m>z6Ad7a z|FZ6<8fecSvMfQX-vF&{L90h%E#{FvEK5TV_ek%S9sDMtQ_u7{G;T)9ChU1v=7l@3 zQpkda+^|1Qs|ipBY-7L{U;ppIg} z-3l(?JXx?`D|s1m!C5|(S#HsoteOwuiOLRsB5NDjNwYS4{n6QpM?Zm8>Soa+I;6d) zUpr~$jVH~T`r)kfev+AhLCqR3Aqm1Yt>6S8mr&UW)zs6!0=^8c43gqh*zXRF& zJg0*9<)3eNZt5zI?xFALIWS2dA(_zF2Cp?j9*rGXUX1C3T4;eelIc3IH zhPWg*1H(H{Z^bp;Nizovqi*aLibrvvJ%Oyiii9SX-5!(8344&G+L&y;!#^tX&IpY+ zX=MUmhh3@jb6$zDh6M#zNy$rjaK_q?C% zb-Vmon^kMyJARiBD+6=_%(T+2G=b9S&79MVy_?xc>gsSA{bIB&fxgLYWJ^+cmaMAyn_-_YQ{D}q-$A2qqvQLEhDK^C_H&vu|sa1M% zVtA`a92`y9qQvH))?1C%(>ZTeN?kv&RU}*79pUV%`hq(?n;A-~h_!B8 zn088ekRMAMp>MQ%Zka$OxNKy6a9*ELINRJxSIP^tpE*a74=6>ta}b^%&$t-hit=yj zI}dOZ5WUGEY2;VYKTRifN(N4v<>^DCs%R!AE31RQV1DOm`pwXc&^$=8wGDH*+@^G; z+!W=^%i$3yx9fgdpU~Xylp?Faa2i$|mplO5gmU(za&}qw>iSfySscp!3zhqqb(htr z;9RnD?%ly*h5sQHf1&}z@uyZ^*8SW1q+n6g*q{ZiH|rrn<^5O--d~Sw3~pn{Uaj`L zwXrq#J@tvo9X8zYu5w3H?2dW$3CfiOs_S8@>y_A*!g`x>C6Vq?uKXc(-EYV4&{zD${oWB|HCT&L<5N9e_O1@PSxp@wm~jFwB~xHZRW(T9k0`%$M9&&zG#2U zQt(wBr<5O|l&@3D=f=v1>X;%k3^J1rZLRk3W!(qr;Ij#q73f>laXKTi@7S5>+h@j9 zFE|#@{G&q@x-{{5k?rE#OTrW_uBqTRh~sr#hDX+3xj`-#9`qFy>++fke66qgviBS) zT9f{I0kI6dt%y?4l0Mw!bswqDWX zDI8Y#zpvs?G=Mn%I?VS{q}K-o5pC#cEV!x#xs+N@JZO|LCgf6E;XG5@O4nJ0vRh(h zUoW_*^%J?sskEokmb#u-OH-uZ4P76B>&4^fdUES3w6(71wFOP>K!ufO0)y5$g`Z%o ze?!&@d|AGio)3lyG7iOLA#wYuMVU#k^=QSSF^`V1P8i+#^>JP@h?mT|Yy3i83i2C%m7rtYJU*2oWSNRjvf ze%!L3-0?c$MbF0_qhfcAcd6x1^qa>08qd*;^Zn$mS%}{gzv~9<$U4nu5q+aZF8O1PT)JVe{4m;h zT|Z>OdsBDPqpYX3l&edTX7pPlsti0FL$s`4H;$Nu_*k^C2Cc<2jy_s0n-F*0So?~s z_m|7M#_^@&yeZNH{o0<^5)LJj@D^$PHs}JCKlc7pmZvNeb>RuSuYF20L5nPZIgtsw za-G?ca0h#rn~)viCuD|APaAV`kR5WBC%OB;vh0v&qVU;f*(2mnT~{zVOmTrdHeXt#ZInd(8)bka*YS=Z0!^{T;I=}J?$=M zCqA6_KXKlk<+;W(F+nsw5fJA-!K7B1+s=bcj(s&!mCRulFg|>lZ@jdO`Q2Q&%#|3~ z+T$;2>{)gb*RtGYjNEi;uoP!CMB-|MQWGKhXf<_@kYa)k zM&R-HPT$wKR}f2K)6mJx#buejC|#g)LY}9V;VnM?cv$KGzpMBY4Iqv`X~K7RmVK}qJUVqmV&>S9St(9ilF?|)Ke5K{kp$-7I|5O{b@-&?lY);1A1yxE46>KUM~{yc zpEP{(@S%F4kCSi7*acQ!atQOdiOIY9iN6w0g$db=Wl3S{$(E!hNS76%pByc`3(;U) z%$Zb3=L{|RUfyYlC|J$l9>vq0+@lPb`u8@$%g427TpjH?7rxJ&zEA5qH+nFhd%LNV z(+0#<;tKG@VSyOq2q6ail_|UV98QdenX~DneVKM2J2|ZI52^SQ4IqyH(c~udGJQzr zLW~#tYS}1U5n(QV2S>T_ge8c$T>v(J#Q|{&wPT=-= z%jeM4#0}pT81<^>_#je$#-b>-_`ffKX>Sq z*tEIg>F5FM8m~Z(IEq2`yauDb*IoKd zitPF}=)-C<4LcQ#`)Ci)L&z+Q9n6vk5oCrH{$UmW{paBS{4TXsZwY-}*OXy#rASi{ zDT6bAspL+(Bi2&OvE!#=U5&hE1?}eeMM#S{TiDGrHANcH`?q%5H$F?r4?ahxedB)( zO$Pga%`Fp@9pz&}_2A{IS$@4I%nXs&!`$YtmE9Mmuo|8^qg-%>7@?6O8u$LS-S5?Q+tuH+<1@aa z&EpF+(e9CaQz|l6B!+#E5v}X=@Y?_1qT)|9fO!8OiC)E+8u6Jj_ELThjT0>{7$`?Z z72>-}+vK0@=R0+m&DQh55;arU9Q4go*dsh2(SoUO-mX`3M6CYSn`sHO$#>~(J@+k5 zSU-9j7(hi#NCF#s1U{qi8HtZ0zyv$~9_dKN3@;Vm(s3p&Kr#P&qaz2~P%{s2)7s_a zb6N}T{#|-AqCWo-QJv+X^Vw+rY-`9~;_xq8yrgx7sq(8j#02NYLYo-Qa6mWM zj*OtF_d4|s^t-!b62qjcm6{ExIW17$o*r!8Nhn^nd~~ocS~GxLE`0jh@<>vU*nksp zmN`#jPdYvSAIs;ANvdq#sc{b?|9r+j)u^>2V{auvyQ}YRqbJ;ktaW<$qsOz!*u8ie zq~Shz1)m#M`u}4Uf1&}z@kfsU@(=!*NzeHmPRi80Z8_y+u3ye3!h(iA=aF7sZd*GA zr2^|f^G8Jw1^{i{%z%amU7;))*MNRoo`gmk5JC1tZg>T?C#t#|DVKC{aqP@ zov#)=1D~kF8!o-?l~{aAT?;t=%UIW1A`hSSH5$SmFPvia*f+;`l$kpW5Q- z{Z&d-x6$ixB)yM!;i&?-^Djye?Hzl5fp~W+ibs;MhqQ@E|%;`W)`LG7C zb+G@*iPdw(KXu+^eFBl?o?z;+^7s=T&bbChg_%%k4w2N6%o!Dl+l0CjA#un+7Dz;G z^B{AgO#j2%#UKAqIg}td99H=ML&cwH0CD_nJ?j>rf875WVz7`Ls7E!%ACTmVfMl}t z=^!D2p5wFiY$miTwIG=Mn%G;`Y-aX1?>^P~7b&4&MgVZpn<54FkD zYxmZ#aGARn+mof2F%O>ve;Tv!LDHP7`FQ^MaRW19 z!}mW*Q2}##bC0bg8GFpN!5TyboUZY^I3=RsNL*z~T)_&gHR@#6xJsV3D_I&f$nZ29 zp0)<@;MBN+0ptZ-g)$Y5Z!4Lq)FZ_xBlvsIlWXTa%7sp{A|FV1K{k?{+hOE#gL?mA#xck|ZX?GJn~yepJ`( zaj$4=8 zrXjX)Vi@+^>nQJ&1?{^5?Q4V%K|Qb_phos>J101@=^M^@zC0)HRuFNwRD_d(uLE`% zLRXG{(oc4X08rs5s;Ac+p=jV5K_3xNg27irzYXwCD$%H_=`4?TYlJ7~u{Yy#RPle5 zqvI&=QJz$*JSqJxk0>~~EyD``FI4=A1`x+TS(-7xvd{LTJJ0Dy!cae2A_~CSsq`a4 zjQY{jN;|6Y!Z=|6V>#k}B1gt^2aDFy5Igz7t^2AZwRBBxL4gmgAYj3jZ%v{D}q- z$A1ap|0g0^w^`|lObWzW$P7y!$5=#9Jq|t3)p)n8eM{QQzotb*wZsqB90zp*9y^C{ zaL5<@j?()M?TYts-kpIyKH*0?{2N$hw5)kI>F})uSH`q=Z69Tb_D{MzWIPFu=`^lX zYLDydL&_a-ef?88`;g{Nh`116Jz1LE&%nDu zA8GT470=3?-3}oMk>XT+u}C>5C>mam2tis{m+$wjD$uoP&WSVV_T4;AGc?}be#pN!s3h|*GO1@Aznun)QBv38ncb*cBZrwL$ zW18l|mXH`=LJB?!_#ijo1^n;4`QKM6{zLn>Q5 zZY)#loEXFGk4oMiqs#b{><|sQcb5hh6n#oEX{lm-u^R2gB5bM8edCvNVfkO-U*uj8wkoX_^%G+K(Fca^x*m6#a2M>pek<&T z9A)*1<&;o!{KRug%naL=IzEZjF?Xnr38;f|HKLAyJuo$b{rNy>f2`c4L*>#?P7jnV zD4UF&vP;}T=wWwC*rt@PkCo3HDnGCT-VC+gMq5CSjM8%S>)4Lwt{r=@2kFw#1>F75 zkN+1@@h2KU9DjX#qSAV+l-6U&*cq3HuhDuuS{pgvpflUs6HxBI!YckJ;WaE$q~=4E z;!sM1QVD^Nk=ut^@kwA=jJSRlHXhbJ=M@o+@aD0kpk3mu=3x51a?wiP6HNI2oM;ao z=`iiaZ;cLlTyp(M8`Jk`L>raRF_h4W$@JZ#$M+Rt0)5wW_^uaIf`%&mViaLKv5K!w zLfpypeMzuN3jt&^t}|61=rCuQakNgc;;1ocJ00vmN5Z6}YX5PM)e;<5_rLdi&)JtazD`Yb?(r+be%gu9Q$J?L|M@tCm2AH{@C1hy88^1aal z`Ts2*?C&vNn`7hk?T{pQY`o4<#_RS7EKL}TXx|=_KJl9Z<{gLys^kEJL>aM0h>cRM zh(mrh+qaroPLAd(HBx3dODwb8fgeR6m!oS2%t|(cJ&1ZTtnmM*ia*f+;`m#TS?@-S z&eK9%&dp)AbcuU3bm|S^Un?W@Yf5}|IeJG7CCaR4{ke<{88^@T1v4p{WSw$PfAlkq z&IqrKk!5Xz1vfjyuqy%MeNuV|qm+*pR`&f(#BOtQ-w7c8*o# zl(oDZy&1UB`dmY+Pdk_cSjF@1__CB`bfrZJW1dq8BN3~C2k6SInR*I z$r(K-Z%kX`72EvakJ*sTNRDQs?&GN20LFNY+`$gPVo`yoUAX_woB#hy#h+*Zas0Jx z#y3|6tvhI}CI%fo$mwn^8XU(%9+;p9ABS@3nF5x8IUvB3OS^Bc04hw{<0nSW9{-g= z6Zkl`GUDUtes#&!_WydJXwyZ+3ZtxE*5E+&?E&J2eI4SyQKJM${Z=rG2BSZmX_Jo! zYUJ;+OPiwf{oBt~Ce$s+Tmj3>{ipxdj*L(W8{})hHP{ruAg{428GLUYs2D*9yL7}R%N2;0ZY_{{O`Q}e@w-nXaI5ijfjM{!UbIzNS2ypW9R>{ zsqp+HONiJKtdN_T0mpqzi{loi$FYX#a11bLeQ3}9jTQ1=iz?*JwTC)f_7UJ}+9NhG z0k(S7$Wn!mklm}JNFQ+^6B{p}z3m$CH@NS%UF(PLvdYBXr27rHhY$Rvoo0F-ME7_H zYcspQm3kiVSdMRuy%_WOje!l(BLxxRB_E!eX!JS-d*&_)1GU{O`{mhJhp-FH8I2l| ziOM6D`@!*gle?9h_MdjTkH>u%$L=du?xSbTpMCvNJjq^r(!#it7XA?I!mo94 z9{cc$|9V`-pJ)Ja{QZv@THZn{X1881(j1^p)WJ@2hgc^jN%e!*!)uaH%&CP*Qt_Z3 zyRUL%ziz-aeO;dND+ETziX}uSx;<%h43*j#O-KIl12_{d&!jw7SHmW%_RK$#uc<1g~v>DD(741y*6Vf{?FWJ zyfCc#e}{@c(E#H3TOz#IShz`kI^|^-Un;;y_L5>D(}d!4_K(qS=eF9vTImkXxkjVfOH$GQ}&Fu)}m~pQcj0*!wUbCD*i+Rh~w||24n4XdWYKD zDg4q)R`}6x)@e@iMvB%zJ?6P|!jLj;%t5T5Bx&@(VPJ^7tIayt>m1E=b>^vm?4Y=B z&-n$P5gLK_E%46Ezz#iJd4GpSTsVG~tR20jSTohwsnL@Lz7I07cLzKM;ypL>UPJJw zGC}od`Lh~(=BceaNc$)j)sk$7wJOY_P|CMvn}WWwBfEo1^L zp4`QlGyJ}P8$}ZFY9gvc+_-~0N0hnerxKA5iC7Sm2p$r_4@tzd9SJoLkH4o_p zb_|lHVbTpTi{B+X@E!|t3UeV{?4-{4CUCd3-rAH~XsyyB5@C{bLqBQzv$9DgW}Y(b zuxxs&$rdDQA`4LLK>@SOVb%Ztt>RBKfH?m5VZ_fwOsCfo2X0xnj@tG|mv|DNM(DpAdJ6Hj4jpn4@ z_zu>XmdZy9zvytKYB%UlFdaLgVRePCiq?Ss1gG;9x(m4z8qTo6Sg5J|LJryKES+%| z@|9o&=)aKDlPq8>ic+mUt+clZZ}QG988r6%%B#oNuHw95`!R80){U}uwPtF9tj}HO z?TSfr#dc_#SyNgSq>iu=gz*5J}63;Or`dAP1Qr;kgMV(*!{-GJ<70ewl6Hkf~E zo|6TJ75@KG@h2KU9Dh|0a;{5&=Eztp@!K^)YM~!%N-ANDmFV1N>1@?M-jsk=ycw-{ zZY^qT@MYa!Z{tym4JC?)N?4TVd>8Ye~?woP&&&S`LNP3+tr zl=I*mxIfaLV&@vSS$Y~D6+|7*?T($>y3Gu`v@v7`J5-PJi(?~3^)?gYmziL32EQ$K zF0f6nlpR+1ODg_E1Bm0VM_U=uRyW1krF@$akrXXmv!@E83Fo)P&M)1jQ`$?1@@Aa> zMeO{8z~L_7z&q9Tq8eLe)|(XnA=JULxJzbvX!M9COm^ab2;DR=2??-<|X8Hh^z$jH`A?PZF)Lzl`i1 zBs;I?2gQ$v`8U>cI4--W<)#z)8R-))Z$bM`EaI<_T!!o`HCgD|!D)OGsB=&gs+dE|MeD?0UxvO;$$ zSJai*DD+6DQi5=__|(;Tl2T$MuEp_7RLT&37N5E@Rq>-|B=PB3g~XBj`8T&IZ?3-e zPv7)xO$AanM;Zd2;|uuTdHw$f6@Q`u4B?MH@bfKcIj1GViOWy?^U=M>L!QB?30b~E zLz;DYBkul@ZoO8~t*O3|rQGC;Nw;5*)q-xeH%q)l);^%>-|4N(o#VV!unuAV$-)>srz$-r1t}VGhdWdoT4pm_fQ|Wa~8Vl)_n(M|U|% z%Qx3SgFPl9*WZ(xOpcG&XOVq!DsyH3>OlVvp$weQBGfu%{AWEuY#dm?N%i@If|?xH`xiQ&Id|Bp)elP~}oe9b#v6M(Su|b?wmJ1b0)&v{ul70bKsw_9W!!--$+I!3@{KFFdBn&{t zKP<1JF#M;Wbzi{v{jsFef~x#0?uW1l)lXt90g!sY~`-ECE-+GRsh3AJ28v@9|%q_YWc+NwT)-*S^Zt2TYA zlya)nuvkwl>e-l1Y9Tu5m(WSkQ{@y><+_t*75-xq{v-@Q#-G^S1jC-+ZB9srX0}!R z-2H*o>{rqR;fks`7ZxA4v76!DC3@K=q+h3(d#3FGH5u(`yd1sskt${N55=C>bU{;P zWy$P~viAH4wKbM~s4A}-`JhqrHCfEVe1au#aq3ln~$<^`HDD%uh zjK%CPqUi!{_Fb<38E|n@CP}(_BRmDFQ}p9hmTG{0;>;WstOED%sK+V96(KsDu9$EK zk5AMESLl$_D?n4y*niOoh1FsD>Ss8tBiEmRo>?KN{A)O~{~m?TuSj}(cvj&*F5yqY z0A&1k>RuY&scXlv7f0n;%$s{?{~qNg!9o47dZpl~q6>`K8>%i1tOO007)}g7PQMeR zqh7^l1CHl#D3DE?(k>jL(rCp0DzO81pu}`e;V+`J{!-<9EW_UjY&QxN!JNlB^6ZZ{>kb5O6yi`1Nh*L;m2-f_;0lT zCM5hx7=VobWAAx~A5-ncaprhwN*Q0SC72}wF@>$A#PT_)l?d9=L_5EUY%4lH9sSe3 zR($(upOgDLGO6M&u2L54&)~n7i{od#1`^vh2f??HdBrw5J7z#%z2i8Ytr>W>y7-~S zBJIG6>ScL~p}4#i)iy^|pm9=*cy7$d*cRKbdG3ymZuzN-c&7}epjL~Vq?T=1$A4w) zpA(8s#GMR0ovt0KN=6hT&4ivT=n#zMmcZRtGpf>SO?Xlo?@dP+j^_VV)2QbDb3|jP z=l&CW#~qwq`JW;Z{v-@Q#$WB(y={(X**2|5sD8di<$0r8>B%{+4X&b%-44zY`1}fq z(1Uy%4NY_=KB?FNMATXOg_C{TP)@6OxSLA-W99o+daf3N!H~K>D&t9b*FI2W$=>pGG>7QYTIEumwus7+3poA8_A zEY={?tGbKu9?e&gT6_2N$$6GBwQF~k$^eBFDguK;| z_*NS6t?-QD7xgrG*6=xU!%!J`QhzfmfE&jDmnHm37=VmFojDJb`^?hS@(k#9LD5B4 z0$}yt*~&{I?QAmb^t-q&iF$g4ZPlUu!c$7@9YVPsSYv-WDo`@14n9x);t=cj0GW9# zf!nXBgP&1d;_tIvmO$YZ_2~1ipW$~D^8YA(>d_w8LC1cfa&uJRmPy+C@SzWcVOl*J zcCijiAO)pOE~A(^=mR0I$P$RZqVdvcDxV$Cu*DxByNtrC_U#vzDAl2oy#2zmt(HK= zl{sD`?r%d*n*GR9qs93_rFyi|wO{yAvEFBb{FCTFGDl$vd{?wxXBGZeB>YJjfQ&z~ zY5e@?sOG2iQ8(g0^YZ#fl#oT5(qh&AIdLflP z{>4Ju*jWCAC7nA)?nb4%5UJTlXD`vjpQ) zsPYmr$37htk||Q+>jB-7ZJfhF=2pKLm$2OfY;V83a?0B})%zNN zOcK#8z$WRJezT79o0Y!}&WX}ps4ZD>mP+4rUvBny&(ej5O2!AALtiAN1(d2U6O{vp z(C<@e`XQ-A7D^l`8W*p!C9xM$HYO)LTzw#rTX4j$P!tsJ59BUA;@4;ji?f+?#W8q8 zdO*8m@s*>xZh4Sym(wada^dH zJ1X$v6;se-Xd71Q^h4)`YWn<0<#P&@uAylUS=XT-f^M>;byLtt+HM#6l4p>=M(H6s zUKRAvp5axLD%e4->O-%PZ+A2c4>mRn+g`E+-ixTbF2_FM9jss3C$wYz3VEaIHM0tT zN-56&k}v=n|My26vDZRET%3D>X@OD+v-nwBLE9I?}_E1z{!fz$oSWZ^gIVDm0fxtXF?x^Q!yld+O;g9iWT{_K>D-w2};CtDn--}oF+sIP~NDbkGVvBzy*TZ`$awd1nE}a#x z9K?4nyidHoPb|M*JWKDe2j2;|TtHblwxhSljNH%F#HOf?gRSt{L{$pBnombx7{+Q< z2AQ8Nf%hlK+91j5a7}z5P)=s5cbZl5kF-f7{)2=8$oS{k!ej2MGA-Ao9E8Ru`|Q%$ zQ3DJ|+q1c-!0#iazqJoJ!`tl)M=ULJ?d^!`HN2PY_-YaJ<<$zo2PmaIJ8?xKWS$%@Sa5-no6aBJ3AXK%IVyE3dO8BOP-Wb`2R zBPUPXYO}fj_KyegmW$-K{N2$})lW6tb1CI1bawvP_R4sU{_d?g!oaI3bf*67UB6|* z3!Hh$_iS# z+{)wSDe+u>C6$Ho0ynuxfw=_-Y&Xibzi7_c{Pmw7r}K^nC+`^h0((3R4U1CCp!IRs zj`49M!~k`E~RmSU0di6AQSLoMm>||0)T85(XgS-^e{%r1`WwkqXSA zEQ!4VpZhtkxG0{hOwgajZp|wC_BerFb!$#|U{k__oPtdqQY}*^-&+#@IsCZ{{C;Zf zvUP&0a$n%qWrzJ*%@SDPw=O*_THra%m&I|gz`r`%h}~Kr1V?Q-o`N|DNNeW!z=tfyj$?n0)ZQjW?dXWECSL6DpG z?*{*mTEd@%0m%55CmkqK3@E!XmY!4|S%E$B$Ot=rQqe)^o(aj%tdecM%xMfh5oqLo zMD};sfEO-D<9zqdiq$q`_)^OdK4t!5j2R+dF=9KCE`>K1K5GscknpfT3;0Rxz$GS4fty${7D#qjK6+}#=3khg%#1XYUs3}wJ029b+mQ{t;sCfM?I#XSLfz*K^yff zx5^$58{pEoGxP>>{S&#;1v7P(rz`tB!ve?Dos<O{t~ExSQ`}r<7E@bJVC}GmxF0y@Q&l-DMxK~ z(!Z4oNnS19a&ScdCWGC`6x}O0%vasSe>dPiN5Y?k0m%3(1E-PMlODPwleyrw>##=N znS?nWMN+*xa0hJx1znR#?Joy!qqLdYa}v#zfn%4+`u?cEqvLH8&jsdtT9J<>(ZfJz z6YT!|a&h+?-~*bg?DOKYvX8Qt3wFeWl;BL~YqQ1%Xm1K+J1Q_XdDqm4lCkgj2V)P9 zJtk@r!gIgwp^s{~XJ8j(BLA>9@Y5?A>_w{UCf|Q@#qP-D;<2Y+MGAKH%hqEry2Qiw zRK$=Obcg41*zND$%9MEQIGBn%{UgzIDfGlVk273jGX<;lglA2`gSwj-{u}52uqcMu z|0E1R#=n0gc5d{c{*ibVnpd0b=^sh7DAK5ma*hrf75&2f?xY4pc39r6F6BIT4kF73 ziLg`T7zZqVErn-P%5x{lUWx;XG&e^Nx#71B%)uOsW&`)vvx*#MV2&*X^{2QU-SZA# z9@{$MfPOB-9s}OjtgU1p#+avb2NHbG7A^dAb)u&v^Md0@%2Dhz&8A=;S_@zFf&&R2 zy{l z3o&}QZ@Pc-_B;a5avnI!$Z0X3b@Tq+ApZ!@BKVUq02%*JFRLI^mLoQJaJ7MtFXw&? z8KZK0n}&07CN?<(DNUQSexpCw+cPj?$aTZJr&B8Yja%-1C^hg@u_N%*Dzm@g{UY)`1pcP z6|4N8x+sq=@DyX@|F%=ZD42|51HL(m)yxtD#p@`R-?Q9|E9u1z#v?kG*ZfeAU$$a~ z-(Q6+4{HZT6q}g@(!2lAuc8p8Mpc4;(6_6@&2Lxpo(&-5r z_opK&=Z6=48oftV-xZ;0jbEq!RIm-b$o)N{qEBB;h^u7H{ueZK)2BjG@5>QQsjk`B zp>63Gmh>9^&l^dOfi$ZVvi|9aaqd~H_Dve1{ms$F`avOc=r0i?Gf=JbKLcH)?b7(8 z?Q{nnbU)cI7<*rhC^j!mD0Qk^jz#oy2S>CoQ=V5MM&pKgIF_%Jv=3A9DYU=wpzHr|Z>-ssyO@=n}R&8Ebb$R|08ue!itBNYQRH!`E3% zzGD#@Wwk?m#1NxP(6(=P{xf2Z`4yg&o-(zQXA-tb&*)ppQ*(ST;we6&is_CR#B%?P z=AmiUK@#2KO`MR zuhN<$O7T;JGW&p|24&I$gG*j!)hMBf=)$BFjZzO4nqys3N1J-aC;lcEqRbHr}Dr%N=jAl0=MZjgTmz@ z&qUWn+V=>4&no=Q68#DKuZKQt$X+iTH9L3Yw2310=O2`>wK!VIy`-A<2I%a z@>pi+9Z}~0bzt$U`p&42G(n4z>_g(5()465687IGltZ1Jc($b^@odt# zB9AVh7KT4N=2w`FeueS~)*-_=@qNmkB;ek6XBGZY68^~+65_LVu{b!tqgYKD*2{0VQT;17`JUWhxWi}T6% z*TxkbdDfO_Kc$72C{v7KATeK=r=kL<-m;7D_|r+Z-R&5iUHd;+B>aijTgLx!i+u#XM zoClsjMO9Fq$KvT7kY`%=rV}}Q^0{TFu-9MU0Wm^|aY%DG1e2)1uD2+g6cIK$R)Dv$ z1Jlv5MUzwGkU2+s=wsxK7<(SteIP>F)e-~Ud;b-jmArU$2F!ZVdwW2^YLr+$H-z+SY{mUf1Z zaXG`o4ss>g6QJRlQ!xCRD)KwU(~a*f<>dPUPpOjO&okt^%~NG?cx)=P#;oAT6=M6* zfnN*d@Ifv=y&Qh%r>Ju5QJQ$f8GfIvHBs1c|Nj==9KHuJg!lBeiaQ>r9-CG8$4K~- zFaTNp?eK)H#7ys7;`}QWuwBg|y(!}MWk0~*dQ77S9`DEefX(jVN+E+UO*lgrXfhK3 zy3%@X_lLWC8-{mNyL)v(hN?MJ(_24W13|9A?<#C3@!W(dXf&*VTyMbBdHD6b&M9i{ zs6f^PJV9C#?LFsg8GnI#1DfWMbKQt0pob_MvOd-$V`!xonI%s%WL*#D1h4j<=nW!r zo9G;)!B3GjBuXk{wUEKA5i-j6WAs4tdU_SJjVZ#lVj;sqFV*ILJ%ClJMqA$7K~>b> z22zhHj}#xxpI!66u@e3y3_!-;0pB_m`1h+sue;&t`^$JHJo^q@YrabMSR~i}6Y-yv zeJyjirrMrmp_uUBtpSX|l9D;3<7SO32U=sepJ+fr5LKL!Y*82`KLF%zf6E@DxE zljB>b>@=HwbZn0p%|X2UFJZJsS!i&M!ea{N=$D^11#2+tV+yV^Ebl7|T+w=lms898 zSn!_BPU=lOOWu?0?yL)}nOwnb;A+mijQn4!9EtNPxSC#EJ6!`UP(#)9Sx+f)<_@F} zA(Cb4sby17frD=1zZ?92aT5L{3_!-8(tbP52(6<6$Ho<{5}oH=UBQ)u&Qj@`UMlDH zfpTDE)YhDKauTIM^FH!a<2cp6fhz(Z=>m}}8=#S8EKq}3V$V47I+vr2F2G+QI(dVr zlkcJK0diE}|M$ z{%b2i3oD_6>|uBl|J{Ipyo5gq1Ca4Y9PE1ZpDeuP%o6=B^=ZMzaQyiUb$dpjiaRYN zRUK2QIyk;*sr1`g^_7z2*KyLXxT;+Iid}!NqL@ForhzWv>$jYtoUpOTePS&*0#!w% ze?Bc(s^DeLgBRXLJn}Q=mkEB)_RvSnu=3LEHjd0K2QeE=*`aT2>!5QK{&JTUKEA3V zqI2kcT~=^_KE!}iPF$WD6(H%8*lI)Lxe@w%pHvTw&?Sj2zltaioD+;5YjeNghKJa& z$=sCGf>@!Uk;qL9|Bds1b0z#q7=VnwYEx9>Irzx?g$?k{E8&&T9O@U+daTH->1ctc zms`+eZ+R(V<`#6oqsAq1No_0rN{yop{@eqDLRBw3!Cn4{xzW*R$2HZO!I9)I7c|=& z4cp8e^BVsi(SP|;M1Sx5Re1W#c)wQ7`3=gL#v>8^GWhpdTg-Od z_H~@SA-?_uhxIEhm;+cpzkNaDFC&T^t&iSp^0|krkYymw{KBw86YZn7#Q2wOwz{?|9?{j@sDHz=&?()#I}dIOLf^uJZYpM(L(_|Nfa zn_rBmwwjv$5>an8_+DW9g`AZNYFoGdMgKBaBj8vtgVS{x=u(SaH;A2TSOBxxARvKLm_ye=ZrO~ zZM!qB!yi$`B(%L0Q7`FF+~QZM4n>TyNv+AvDNSET6tTS{DX}XOwmNN%CX_LhU}<F`@oJWd2C3e+5*E zZC%TaL=3Tm0@L$iM8EwR@Pl6I2S(iyGk#g?2S?`H(HH1J@vRGd_SV1R)8UJ6#qT<6 z>s&;GZgfVsX@1m}5Yy@WQLXb_;&wl+-E+U%m)x4twmMPc>lIeHpL4z(F>a1+ABm__ zzl@kSzZy}mGIsQ0-^Qg0PR!x{J)+y3(6K8)bHA;Vdmyp1*6F-|ru9eq{9pFW^V}Jp zUsFGvPW6S>=G-0n@7wyqqbr=@a|SA641ZkR8)`HRanUWXOICuzyZDGsfw{@GvkL!2 z34am>Amh(OG5os}lfe2{?*OGP#x}xgV~ayAYx=_fSo0;Qg#O@>_c*bfabQHH<|9hA zJE6pH)>x3~iNkZ9Tq;LJv|&(N3p#6!jdKZ|xv%i_ad_l4>-&Xe9;t@A!X@Q>;fv*b zgj)Y{#LO&8a5+aJ+VXhx7L0$j3&<5>9w`L$O5z(}J>G>lfgXQEU9}@>U_`sVi0?Hr zp}R3ltXPk_R->-fKz{p65k(P@&t8aO~yNZo-EBSB0{5E}tvK}2_CdR~p_i~fdhRL}jW87-|xE9<|G zXo}E+1}$igL^SKky*R&CMNk96TY%_NAnX9D+?L|goMj3{4YLKDVO~4qzgR23>7j^z z3+l&v{bN&*I|@GVNA#=l{+v`hnGnBu|8D62lO+7fe=XxLQ`cBSXnS|frs61(uAp`S zC|!j9GB3I{&aYT&Xf5%_6cQwd(WA{Y%D-Jn&Ez)m}cJJPQ& ztw3-qT1YJcnp=yBloJVmp(dK>n^mYa_MZ_obAJ@e_o@_4MlI&vM{^SfMr><~{MZ#DSgwt2GCrbgTJ?yk z>G?<0O&>p^X)^wJPSdI%Ynz_`v99Uk9~+u(Ui7IO$A8HZ{v-@Q#{c7o=_Waho^N)nonL{#af_7zc1zL(B0#J5}hsAhwZ{wWgvBn&{tzl={QAe1t6BsIx2N@+2Q zG+Gf=#wQib^()uJb`l!yaGtSF(YJU-)PhD_qimjeUh5$$@Q7fa;gN$)X833u9kgf= zi#g)@*9jW)^QVjW^Q(&<+fM1W7x8gB_Uv@f&Yu+V8@KFvw2VI!;})pi zBEEC=9?T!UpeW)mYFAEAqoWBwrGqv#edHMqdET&JaF#f`m@;lc6tNaQ|02xRP=UGQrqRDXVY8Qmi=K*< zW2RseqR;<6S;0kjSDvZF{9z^L4=a1g{Tkd~f%QGwz`swHa|uT)PiJ9W30Y@Uj!&E2 z9Jn`vnib_(bF2;g9Cet2`wW$5HgMP1Q;K@B#CDEPW*sg^ZVRk(JUy%Mw@dhwFaR0< z>nXW3f*D&{8>|8~wSf-M+Z24?PYJjfQ-K^Y4t~J zkhRw*OrtOE-gww1%2M*A4RfsW+?`FFyE6w~hK}6`sn!NelXgyzC;)j@kj(g#S{f%v z4J$-ilM>g*1dtMYP=`}Q%zyQskM)QWxCbjv$n0MQW}GRnIgpGuNf5JjO-CXa4o+u< zO0w6Zmj7$wb0Nt>+5Wn%BC#q+DL#rS=8K@UoX|>}is#h77>uPqoVQl6A@`)M3bqT% zJTt!paY9=VsZQs8IB!notinH4!k>fz$oT)yz#K33)APu^ZxnjpD9p}D{XWUs{356> z^}P3tOT8-_ar8);e~Ity^PbG3MoxqHtW4;9Q(zk+wDPS58&*`uAQyC2d6re1$7HTV z2GO#x+ch|n*-F-MS`ojEz2oZ!N0us0!65_k`cy|DnsNR_E5gXh;GH2_uV{WWP%|pA3B8cc)wCq$C_i!R|QW#Hb z=j5N!QrKmJ8a75-@w{v-@Q#^2_N_Ac;P zylEbt7jtJHqlm#OZby802%)x-m7r(3AMMhRe&BVwqU#!Q^p_MS-~iIy<#t~ zSF*fMrR25Be!=73gfhC=V&3{_zfj}ZieIJov;60ATbXm#QfG|cOuL+RPm0%3Z}FQk zHca-qoKcGwcvcTAJ7!LODQKdoKol^`vl#rn6jS}-9C&5+BbH zcO`q08lS#I{XhG-C~vP-+ZN?9c^`Go>2zC79;5djXR41%FhWbHT1%a=9=+G*Q?@f! zJ<&71QfD;uOq$Q)*Hb!Z8tl>8#b6e}>@j#PejR1-#Ne9M!(cUF473tswRqyZ)y_DN z!<*ozbawAbKO+CKpT1OgEXtdCbSc_if>sOAP9AE`MLjuqE*tGHMvH|l`J@%}Ew`fP zMX2jLjSI2zpdYYJjfQ&!sqw~x2r~7Da;Av{(lqYAQ?b4X@ z%2XVv!PB$+^e|_J-A1Boms1QrC&$W=;nSwe{iKx3?QId)43}d3&0a<>@N_!Eib$UX zWD723oJHE=-V^)zvzDu4fe5`s!`O2EXCRNWh?WM41iw1=Cw^qetP#2r6*H!H^3G+H@N|0N^O8e z^qFb&%_k~PS4@py9_X&@tAO=7Ikpz}Z1!1&f2M>#2?LPvHwE4XWp^t!h-0}5(9Cg} z(CqHVD^IVOq8Ucg7-yRTzXnxTh-0)rMK*E|AFVu-Ib#$@=-z@7S*SxR(w(0{ce#%J zC_!2oySx#tOnhS`Nb1;$5>9S4$_z$GdvaD0xrY12w;&_Ae!PWgRQ)Y=te$+}FsVfw zcnfuyMoqgbPnQKI^veVd!5v_p7ty2~!|NEKf%5|0ZI!{4|v-m0#ZX*}w|!l_NE0FmAj~ zHdP`vL^>Z9pOMFxQuL@PaOvt}z>bU_?-Q|0exe4_J2S%66!_~^)99ae6HX#+uRyux zW6MwHPidwN_#|)lA6GYE<%u@noceF1HzE+~0eM#{a!k#tTg1feDd1tw`~2 zBKvPwAD%)sFtL$)rMu>gimQ2_= zYkIZZ8~D7L|8B7V7E1V&FaR0NE zRBFHQJYslVJqHo*QR>NSLZ+dAB5T0?#%3yT_vQTV3XbKZRT}w+E4XwodE#u(dhF8D zL*;wyu;LfMx+js|OD|`6^A989*lp(qg=!C#sujy1GPEm?o8N)wu;0YTT?MGwc6kxX zX85So%uZS?b&EIa&=Sl?3<|q@7PnxBxE?BCx@>EoRroKG@F!saGX81an*A!V->f#fG z{$>xITEkX9Y5|$lG}ZyTc=p9(C97`$|<9px{% zw5_S_q}_h3CqT=!SzbkbzhLPRx$Y)b05|miw@UbvFaQ~UNv3VyJ&^q5RtfvyF5;^J z;;!T1hM;Q^K7sWPf=xohk_PCF9U9I7{6}5U4T~G{4;!ZN|E~!X zdWCA>e#w>Q(}*n~cN1_P1qawWY%_Sk;w7zRh!_)D5AP)Pk+zaL@dgqX?$&v4fdq$f zo$$p)R|;AUJWBY%BIEAEd+?1c_-xv{t%qck&5Dh}KLCEE3O{*uLL=%K}>b<(fK0&iw?yA1w|?q_`yV??{jzz)u4aSWy9K$Oi>pQvjkXhTM#`#w9F;E1;IMxQbCRdmmP01vD<(io^Tc61;nKA7e$?56?uTXL*&sYkq@#C zB~HCV{6w@@kva&wg}k*A?~vx6Rru#i_>(XI8Gj=2h==b16?Z@$Ajzbk2hN@(5d$Lo zqb?hI>d@nvtqHgma-{)7!V$n?mn@;F;x&Ru1X2r4?O6g|xa3L@@d&%3MSgHJQGs*g z7E!y5x(YcHdY5bcK}xH7iW{vSi5usM??AM8(51!s655+^Wr$A^4I#Kr6As)tUwkjI zb@0Q*Clu)UcXyGp^QYcp-qd?oM4q4mzZg&UDN@a|tN$;M@F!saGX7Xc;~~^d!|dKu z;DT|NmT1>qSzdjstwrL7@U&h?CDQ6j2hA@5Wg?S7m&2DST2zEnCZ33zMnb^dFz^by z(nJg(XI z8Gplgf>)VJ>^Z@uX-!1WPVA&A59nWO!5nT5u$E+<^ti#@q@N{{E$L$-aio737ja(f z$?{4Z6Lgt;vIdd*5>byl_AGS#sLL^hf4?vfZO2UEpV>o@2aY>Zyh#mput$i*kApMZ z9`X)iKQFdTdK}44AlhGWN#mBq9-;*#Z6a|*cxOfv(LopyOuZNBzw(hO1oAH=qwT2H zS%v=+34am>AmcAl_^%5+_(b|IgEMFOaoTmK&XpgM!MTil`N^a1c*zggTRkQ;f z_&$o(LbZvgQ^3;!^z}ipt#PrfTX6jnzDya_Ab68tS_LRqa9@@ap zD*Ts9_>(XI8UIAAm!XOgrC*_C;gtcs)!GzhKmQu7@L$@3?3|hc*3PJbL@lEQa<3s~ z;v`C)q~|iQ6RQxRV{z#jZC46m5joFamy~& zF}v{pj)Xr61Ca6G%fGGK$D37lAo#W_i`~b+rlS3!&1;zq5z{^VYskZRTumfzBct`d zt?V69tWJQ;g*W$(P;;dnon&2crYGUpbI9;Va>J{UgrQ zti$~yxgR8V>=~vwTdT5pNpt>DRb&51F`dt*bS`LH^?|klex{L}eb@=uZ3=#-RkzG( zw0Al>Qrip-2QjyCOKWUPdZ(^AvqRsQ(MHwJD*0a~;ZMQ@+v-I}jiB!LmKIx04J3MgB^TEc10TNSpH$$W7*9{;kITaUk@r!k zx4g11n^XC;Eb=mY?he0__euCS7K4?bOMNCl#~Nwjfg@2b$fw)ev8ErWv5y^>S= z7?$!lLqW?2;h)y$hmF*ZYz3?qwU>m?SA7^x%9Cp^no;}8u-Dcf zo{12gbY;huOjVOIr=&I#(=+Bf)+bf8(&%%sOCHCF=b=8^h7kQ*^ z6Y4gjbXjPp<>OG>G*^5zA#;WEP-X9J-G#4Gp4+kCHxgXk{XTsm75#J4*SA`zl9EUaw+#iPXX-V@)ZI;bwvnX`h^-)Mk zNo~f7eESF2N8ybwxy@y0GryZe7u)Zx%~ZbPI)F==yePb%ITPApyGHTnrzuYKC($27mWlrOWE{3TJvdUV_%L(|SUXz? z#$4#G&8CJA!-+uKLwDKo*yU3gmxNwIA5r7F*5aD!7G>>0G#1ew z&1f+JEiP8{hZ>@hH(tUxl(w00vTp`g{}D1X(*HQC@V{NcpM(L(_!FsG z8FC?O4%TB&Nir2koTm6~z&OAAn(nL|Ulp1QN`FVu7k(L^g(Ahdu+|yd&=>yB42lba zEXQ|-R=M5{mAbBR)m`D=Fz1sO%|YatXpYozCj43vGza}&I4Op3)XMNm z`}^Sw(`^xLLIrxK+glYbvwaY5&%4$h7ryBFeK>c(4TJ`;LJA+{FwI~N`KFjVf8`ypr&FBK?9d(#$2 zXe{re@VL|$9VIqvi268GTP1NYvGH#c1~E#>^|35w>ci!6RFl-L{#)`UNN;^K=uN_v$hf*r8YfQeZkZANf!2$ zftP7dAv_8v=N{lMW&F1K0KfCWyV!hoBb&wk+1)Hn9q19Nb$4Pla+XU%PlO ze|(LdsYO~Vcn7PbXv3+uoAaN@TKL5Xb$=PZv*Zi-3vb@P8{$7034am>AmeZBMT||! ze!eLah;0N)U&4DIUB~~%S;wEJSFoP~<+kbs*2(sPy0yi7`5=yZdl|nApJ5y=i2b<) zR8MjT_|G(j>^gQKaK0M9pMR%hZ`FSO&*~g@6>A4dW&ES4^&*Z&JRgeP%b&pW=M+Zd zAV`#vnvr=N-lQYXiryp}tV?6yN0IJolK(m0bACiw1&`7~c$eDGW52Mu9vT|yuY2|W zgBIdbB0G!d-ejj^J?FPShPg&pv6u z&Q9NpBYr1il08f-IUVZOiz9W}!z9(cbw=ISJWQl+;*YxK zVUp@zHC^{L57SD{h`Ncl=bDE}s=IKyZrQ^WBicEWV?Vh{JWR7n{);92Nf>~P|F?SB z7|FvHGbNLgV=+@SubK9*+1Q%CmEZ8MNff_)MUq0vzjn>PG&%PDtN*Ki3FCapza(ja z$+6GHyzzuPW$zNP=A{;|d6%RX-;(QgEVze=$wx1k3bLEX)L ze`azlg!N!D%Ce8Cl=u-bc9T6!*sDuPR*%L3p+8}DXr|~#lzmJ@Ydg_u(v@%cm_*+t z@iE0r`Iw}3C&%8H(WdNWl6{vmd`ven1KeQ$a}xd}3_!-8&|H$NF3?<(ELn?6Ube}x zzh3^|ylk;kUN%{>eg>LLl6Ae8?VDaEiL-u$7G)28&HGM~vkHOn;mb39OcG}i4^!Nf zhe_tFLU2~e43uR*lgL@{P|IE>iL;2d$({ZmW&iX|4F8Ss-*-y*lP~}oe?wuU_ z6ze->?IHV`WJzXbc$%d4-bQ;fJx!8#dU9+s@@<}`S%rV8gg*%bknz9fX(QAlp0>%c zwi)zZ`7bY=MCj}ogrJF(YC>S1d=c9XZQ5&Zzy)_iKP7ikvOfo)_{TS+w2 z>$A)LUm@X7!T@Ca5y@#!Yp>&XZ5|Ywy0mPDFRH=9I>SAy%@~Q7c99H!N%hgy7?lsT zU_@r}WP)xz@DK&;b-Zh{qrSj5zdqlWSfA&!*Wc>1)#v&aAR05JKF60_ztERZpY4l7 zENE z_jt@YM3n^{xrh^_)wwLqQ|di@?G_RXsL=lzk!89@J@QQ_wGq!DGCuXDvc!9s$l8#F z3h`k)O?*pj@FqTJZSTjfA_~7otM#iiR`$<=C2v;A|4Ipe5(XgS4;jGTFLTjtgNGrLT;saucP%PlDWONoQZF>G1jI;rW{_`lZrk3&H}{zt+ueH z);|kzc^1~vZbY7*OI#|rX0R*AkcBn0TG#`)`wqPQSJU_NKdb&+$Sb#@mLuQ~v-${TYc%Qy zfQ428G_jMntI*i6pYN&M2W_rq?AW7oGvp2EGx%q(;kIirM(aD^+s$Vn~NCcy}XcG z2tGC9+wQG}EN>3;usbSXanO)mgT5vc`kh3a zZvq!Sn!g3-*DA6}KLWm_zzYh$-UyyhB!U~4_iks9sj`do9yqYG7tjS?Ujkq6teM|h z#_zx^R|rQ#I##pb&YMMh_&;GM^qcqZ2K?`l@F!saGX7ZK)3t+L4GC21iPcB!y$sNH zbq(2fXEj>{O`rk}+3a3OOcOZbxI*e{t)e!qMi2dDiG@|S?&l*VSije+VE6NFnN4gG zthcu;fEFkZtrW2DDp_b}2X7%|fXa`QX#;u!;KI8pu(qizAO!iIRF#ESMNN;H1Tyq|9cw(nqG@oMT`=%Q%c zzlfR1*Dy2rsV1o{g|*>8Yin}Zq!zTO9K5L$0NsFpnS?(H1Ca5D>?-&2uEntRdkSG= zn>BX>>7F$ht3g{9LdqGetI%rDr$b*yLtm>}5?BK$`y}>a+viRI^&_A@t;Z@$(E7I= z&<6@{#vb55hqj#n5>IS3G)7NRo?{8!bJ^&Y^MDid=C3}tD9Fq zc8@EK&`Gt66{3dU!X&a$ZHDGp_MgxxyCB8k5+dLG`4(gf6=l3S7BU{f8=L^z=QN3} z_po!taSY*TjbCk8_b_w`c=yqQ`&g`MSgpp6P`R@!|7W>`KM4bn@mFC?r2_rQcuEVM zOleZk$Gf0QS+|8XV~qu58`fGGzZ+B+K=rplbuXxX8JhK}ZE@F89sBjL^KrC}5R)9oxVavWPDM zKZCP0q(^f@vmD@Sm)^YE|6At&DmdKM%M*G~YEbLs@x2iT)&8tX%B{3F<{wdZb@NVGIQBXSKJLahSD!CR{R z{I0?!;IIAs>+7l*RYN9g=wK5F&al|bDPkW24Q?Slh?~D^i$UIjpKV90=sQk8^PfXT z8Vh=dnY{+{h@y1^aArJJtOGhE6PinjGqMJu@6dyDPonSGnU~JwqlS~^+t6b@UZQ1{ z$VxL_GOO@kE#XhX0A&1;#j95f9q!BChd!B%$jDd>qp<3kaX={@S?JHRu%hMa9m zX@;cf|0GmfV0raqL4#=2(XjZ9h~R^*j`Kc@A`Sxk9$FgTlkwYj*o9{B)|2oh7~Ro8 zD8gY6R>c9JZR>=5gSSH9xgFcEt{C562cP{>y`Zy@jmCjq$nYnjru;sP3UaXr{X!zq z)1v~CdFuL6K@GE@C6!gTC$WpcVblD)Jq7>eW6&I))0M~K&&M7q92nCAp`-lhDdfUs|5XX#j&BruQx-&G>GS0N=Ao>16xl!=xdS5F1nESy_)a|GpQ$n9b!gksdhFC2*jxT2?8JDkMr_-tA<~^IN_Q^! zizb>L(%pl$T}#PW@&MnnejD1h^yah4o%!tZX!+WhlJp?cxI>dgz+rFAF8N<8;ZMQ< zWc(95_w)ayE@b0Gn(H(+(0q6K0Q$>pBG0h<$=Ewv9D5_il1SN<{jU=3{~9K_#lb4u z&r%1FXBRtVIJ1^`5-o)~rDa*vK13dy+ zJ`P!~T}u2q#3p$FvYgio`?OgtIrG1gYq?9h2QA438%rAhnA)BC(++z+)1pn zCrT1nWg8jQld&cl)ngy;E{rh^W&B&Q@ZQYb%STcV@NaT^`6m%c{wIyS?H*Pd*`r@k zV$`AgRPdC`76BR29$zE%UIz3a2C?@d9wc}TZsNZi@c)5?KM4bn@zci!qOFM?E;?_6Xje3EnDE&;$(-2&9E9q*Y%=LdRi6p%M9NhA_}V2HX?uvbU7@)ToN|1vJmMzaBQn}1 zBTeGBOJ!B4_wka{DK1cI3GVRKqg?^*?%p1C9oiNkop?RkhR=j9u^%D5mlhJOooSCw zb5*ivkG=+b)Y6p4DkZ)`-!{$J+mdHj{@;xf{v-@Q#-FT$nOXsoo^l=Cqd@cd*VA49 zneZ~Sc{%#gnSD4x0I~-ipabn?%OPRP9*=6u$Cv^=NJ%~rkCc$Txg;Oqw0v(fT-S06 zT1~pXWgy;N4lYs|!A1A6TbXRk`CYS46FSk0LAoW|R1fJsz8W&mCbEh)%=yAQu%s&y zT-ln2nFZZUE9E9u|2M{eZIbXOVE{7z1|aiW%#y`)?&ZfZN4A%Ld~0q3k@1u%2|vQ* z!v7CTtY-V&HX-+ z)EIfH$o#GjXSH9iA|B~N(Ic&H(y|uB|D)F+(hU#BRd_IdR-J;JV6{L!h@(EuhF?Ln zdmQZ!sO^|-ip4Rj@V{5WpM(L(_=E0KGj1yVfN&CYmpnH8!u>sK(X;ndsQgBC7W(pZ zGV&H_uT^1o9kb65&KrY>-UMiob_6?ctjDcV_mJFyh)#7@kHH%UXr z2Ct(p38(GjcM&fZzW)aAbzWsg>_Qxl7pE7m_gnBuVtnXC{K?uYt}NLGwr9 z&$&kP1)#SH2eNb#&*54d@f^Z#=taBByU6uxlC1%EVOKVl+OH!cP&J7bP%(OVi+k2> zVbtx}(BnBn4)E6#EMj^LM6*MuXU#|N@fIXIlD_}{C-2?kqbSn;(dwR_neLg%WD;%( z1n5Zs10p*K$fEMHJ-M_2FG&zIAZoY>6F>-{zClqY+!hdY!flgqS#Z51+)Pk+1;GRt zU2(z9DElt%$}!#`nPIUfkW7;ane(mb4C3PZJLmjy{vpYyXR5oat9t5N_0&^Oed{UT z^9yd&S^7d>v2^JyG~ep1GwKQHe&lM=4}m5+xO=t#$29yY4IqlYInt)x(3~+oLJK~G zQeS*$Pl-XPADTQJD5ciJz6;y$&#h?@s|!j$GAbC6MEmdSnqohcIOXOb#T!Q8pF~>t zX?2-rQr0M7SZkmy+l;;hwJkCi6N6et$NerT3vDsH8Fh^SM$A#sojraXKp1b+7T?;~M^y1`x&H%0)-u z+!i|i?we)Z-Z$$HDD~%1;*s_>EDoi9-QM=IQjbT8+kaN-CjN}tAW@A+GtZC2~ zbdcP19_SEwdbFnfyoQ-~3`M&h(?~tgEk(O#(5@qB59{&2w(B_LY5RG;K>G}8YmWQI z)~(fUD$TUoU5nbi=uRrlpa)0y-)%h6P?fQR{CF|hCihNMDbseKxgyMsiWM{9vmK? zd!rYhzsC2T+;hho-&w;DjQcff%ZRLq1s(l&;|=5fr(xY20S0Mw+z%ZcGwpPQNF_U! z>MqH;Q_SkQjrjEzgWm#~^BnAn?KmojoCD_v_D4wdE0F3>7s9^R?DC2;kgoaBY;g99CPdq zJP_lL>ovQmTj4)l!=KUsqWI_finCYy6dazx15h#wcoj9krNPj*{NXIa^>G<&Y^Daa zsgSZdAI^FlRzGW`^*Q1=y`wqfL^mdFuDI0VJ@Ew4D zDmv?n*T~+dW?&^>J8w^^=aUNx_Npm_EQ^T$D6_28t z)hb`jq`8p(v+9!}*C|8rx?Sf<+m0U87J#x2Wup%P2HSyw<|)JunL@2RU;%Qpb|LSF zp`#oAN4=6aIqR9M^D=aIFv16C_1FQc0GOT(9UpSNkmKS}447z?quy_)9X;2o`k1WP z3JX|X7ztn;5*oD1_dHNug8u9>j?M5<62SFZguUGVsH)Aj3wA8bXmzXhKU2e>(g33P zKQ7y|`tPvAnr7w_vo6cy;i(0yq~H&jYE6va0(S4a;BY*XHXL#seqr(pr9WaFP~VFF zo3j!UFz0)HEf8&0PIzj^Q8`qsXu)hz0MeuuZQe^~gd%nZui9aY-JXbkn&{H924X&O zH7v&CvxZ2{tYPriLwr`O5?L%EXSCdRkn_`NtKgR!UZ?X1gFiB$GI6^Jti)-Jy(Rb@ zM^Ao;c?R#bIBf;yF{r(ur!*9t^wSCU?IWb#kS*^rPvibGX_QU+ZhmhMwG^=Ut$M65 zut?ns|5+OTlm-yRzb8tl)-V(O&G%d>>-(#Vw=FJAety`(&$ z0&Dov8CkU%nwem(DdZ$!sH=Od7it{!eQ7QyM@Ne_iqi@Tk9WJ=O%ok>JAO=BEn zSjY&&f|1*x-@96!1_#F@4@H+~#m9AgWt?-|%;ZJD*QT%U2k+wAW%0G6X zm3^UyY=Y-4tgy972e~4Ly!+mB%@W6?GG1n|t>xv~Cn~da@D)ixY zqNJ;@lq-kLjbNP&`lrf~6&ZT(KUHG$RtbvnYC)~JDow7s{*E7d;bC6n3$2KsGx%IH zXS*6yI}AH=udG1G{EM15JJ%z9Gcla4$T4hmuQaGNWqYN%X; zx-eW9PVLjcrVea~2_*0?8Ty58DEz;r!_S8$Y$#_^d9T=?4{!{v7XtQ`r~6RjH<7}^ zNbNw5k9Dv4pCS!^N&|@E&%LBXB;x}&w2uF0Bu;exzeVCNoi`)#)-NIveG@+NCU-Ow z^MSU4{+z5E#(!y+(^SrEII>XbL2SO>xk5v(5_X904Ps$o3}VqUw4I!LV8!oEZor*;)T@4R|A6(j}=lHQ`{e1(4H~~NnJ5Gp-)#RMu_hU zS%jFbkWS#cLV}>{3h9O1ma3VrwmoM1TU&TZd4}P03E>qPbyqgNMF#5{UGgwlP-b>= z0ShUTrM80j(H238>3mI{Rdk}6S^b(yJj*Uzm+g@{!>@I=ty;3)1*xU0RcEamsoDyA z^_SYF*;Z%h&nDMe(p*T>e~s&2_|Mbur!;^l{B#%^; zv5BMr2Mb9SjyTJbWZUiKb+$n}GI})}pZ0iC?CosBNSO?6YX}c>oHYxK63Zm1I!BVq z*!E4@m%ye^DIO_*ci~X0dwKuQcS2ql)b3Onl2^-$!=^DZ9c#3E*A6(5#5OX6NFzH4 zZy(V_1?Bl`=xdx=HQL)J$8J?ev#)tM)%%!=KUsqWDA38XKDRa;aRC zv^%5E+5WPj)xBh`{D%y?Jf<#DUYRlA3!(4E4Aa>!Rom`3w8gwELD_MwDycMaPloPG zR)p+@&)zpOVm>#i22zYv1cZn?ES^*oY(HK|mX)A<)d7t`2^u41PW$^6H4Q4MKMGB8 zcteBA)i+?p$d&BdKi3znDMBrJxtD5@xY1OTY=5xikmsUh*btMD;IG?cLSN!I?m24{_wIh4(-a$6o>83 z#qP*%YN#=>n`;`H*{u!D+=C6xWJW`?Vf`wfz^sQwExrs)K+DTM9;>k}`q<5@aXqfA z6jr_U2vOe;JX;~_dN9% zeS^(=>LMzwTOB{v?owiKm|4*=@5W zW*eThT6ZyEYP<}KZv2knlCU#I(pLa&3+DIhQFl0F#Rk-#xE&1Yl(2buAZ1UF**Q#_DzV%1rP4z9U#^Ukn9484`=p(uEE#2 zkA0fZ(7z;gY#kejB_*ksz9_LP!Nn@=o#`kbw@sXFmP>}F)|I3{LwwfYUuhx!QY%Tx zRXWDxD#~5CO8w|P0UMqj_<53FNBT89uIh-@uj81sNvd>zgHu#G9EB3^b8~`^^qMaj zd~SReN)L9g@n5lqKcxXg@z)VxhZQ zJ+$-y8Fae&`K;5;OL4q_V|i9;Vw!AA78Fm&HcA{G^u`1@VQF=a+#EdDZV1@8(t~91 z>E@M_PdAt1SdHVilZzAWk!PL_+3pnY2zrHpXeh0A;F&+S^Mf$1Fy$&Xa}M-|aPWz+ zfR)GkfJDN<|LXjEvyI_L{k^$Y%E`?7%#U!^koje%HTk3FUW{FyqTWv2S0rgXzH{*G zqv0d1^~(n|Xer$t)&~laN?)XsfK<9w`(LEtPiX*A{QutEzpE4zBBf|RDfVZyvKkjQ z2ja}stK<6@q&D)P)IvrHfkH+INNld6v(&f5j;n8r%_4)BOj+scVZ+=VX5dMW0?F<3 z=yb|R?7zN}6iCJS91yrQj0yGI`lFqV(Jv^Gw`H~{IzvsiHsuOYTP`W(wDBa_{}6(kQefFWF3ZENH5X3Q&L zZx}{&c$@i@8eH)<$2_^vr$b5Hx_>vV|5~i!PiX*A{1^II_BhI9A=c|Jgx|m8%`qv> zUZ$Fkp%hrnrnJXE2545)E{PobN{#V=MP@v482vQ|FJ2|$B>35!tcqg3lpWb~gHLVs zasju23ly5UfFy7M(Zq{nivhO0aB$i+Yk98nn{klakl(RmA;U*meKmF-K0@NMawNUS z;&V*oe2$TQvtrN>S$%IO^S-wU<^_E^7UyLaUwS_0OHZfXo^o*i5S~4RdE*K2OBjQv z)AQ(E>YvO>?~3$pLYB^hT4I6489l#+v6R7b-Q(6ppWM9uV~K|U%p35x`f5k;SU1D^ zt+49Erk6r9;>uWG+T%ba9p7n-verUp0$yp1uO=Co(QhU$i-pdG^%lx+9N4{w5z2_~ z9Xswi@D1q@>xjdAJI52>n2AUUSI3OfmxH?vtn($#H#XfV8Osn4sg2ElO^(abRpM#f zLyE}v?PLx+5hrJH@T%$O zc!J)(Yaf{Zte1vzS1M6q zc)my9EN)Ytr1Ll>OIhDj2Hz+L?;Dj=m~}$VlGrW0Z)Ae0((M}sO>E?--QfA8^`zP( zT5eK-BzTavL(FmlN$Ru3N{sLmtV4*#PaicaYX;gmy>7-BFkNCRwKJ1vt#716@wXC+ z{*+&kN>u(NMSinx6xAQQ75>j?_){7{6n|h(*>lk-yg^ESgrGP zmIX)}c*tfO>l^bh-Uu>aOgdKXD!S1#(9SzX8GJSLEqe~hVlhUfl1JyjIFuDO5npXO zVn907_M{Ra8M1-+(k3AlTuU3xm5)M=!P%$`$+(H;4*4^h^^KkQTK8K2`>cjPr2$0o z*X>A;l#Ol_PI2eP0vOA1ijN_W$1+{*(p~#h=R5 z0+a^D?%`j+&QR_iZ4S82LclGU0&bJ&*zp4qhZdCj;^J8)7T!DAxO{179_J8KFMBD{ z|86Jc#7Ug4XnU+Z%VgO$Da7|Pf99@10q(Kx$v0c<>* zVCBo!4OdQ$ItOd=Y+Q*Ou)?>B9ib@W*1)!ON=+(U;Y;idn@`*j^mV7yo;I!m9LHPu z??t)tT<^QjphJJ`Wc29mx51lp21@qSohy80+&pOzN_7Tw=2gr} zU%X9(RLzu5sTRjNAK&8?e5kMSt%i?pVq58p>wOCB4V3TbC5XX0V3o6-f{i8iKX!;b zR%7ra?#EpJZoOx%i}QTqVmuPB^AKehW}s|@^$1llfh^wUhzV>l)4FN&m;*NS9K?FM z`L;__o+SUXS@#+C8#IuV z(MOQd$XgixoAv*t8vc|95XB#*H&S=IzG14GLhi%Cj0|2#-S()wxhaK}Wov-3u0hBN zzuv6yscLJqrI$4o5pmc$eE!ob95hrUg9jE4F6uB=#2wI=i^;_Aj7yby#RThtjSxFZ zIqo$XdpX3tfloFLImS(q`=8w3)Sr~$SR`-2=M|X|?kh5M$xGi|2y(j+F`Hca*M zyXuX6z@`WCi20+}xO2M9A(vTLQIKupm49^V%9%TjTdOjbUs>=LQ%S_r&A%e2o9`fA zj@_){7{6n`cWEdpAf`G_u+ z)&kLXKMuwbyzmE^49ZIa=48<3JNKS$zB3DL(R8}`*I733aqfcM@1Cq3O>@cI`aJ9! z7!E3-Gx8k=cQoBW(&Rgi(|z1*$-MI0PT-HYgR}ZUGNe6*eiz@&DBJKh?_gLNXq;y{ z|LZ^G!<#jF&q63~HXmc#EbGd0eM}rzmIVe`PfwryF@YpgPL{z#hU`uh{04@m@ldC2 zv^1j4`_0e4{$)7 zN{7%jBF5V1PP={Dut|(#-X!KOJ~ik)*UYAX&&MElMnvv*)lgFtopp@t+xsCA&uI*|nz&n=r~XH?ejOQf z%|)+{cuXA8t=j)G4Sz}lh~ghWsr}f%jCvzG=ykR&efq(cwT5ax$Ndd6E$?JBez9I= zpM~rm3(5U>eKWW2%L{Y{eNVv7#s|b$9W7l;p$wikW@Cuu!)fBM;1|n>wKgy#D>8y! zwnQBE?}m(oc$FD`C?HxA>Q>1YB3vChvtxjbQOsK_rxnzK-65XcQ_J{ENtsLrpCH@R zAvXKa_|Mm6>%9)_DK2V)Bo{9k#e3D!D?^5)t3TMBDZa`!#Q@ z(aX#*JJ@5>wuxBV zuIIMBX1=`evW|OQW?I!{I?raA+qbfK7)z+8Y=BnQ2vu<77`$3Fh%ij_3LY z#63gDm)HK$taJ5JV!0k*{z|430UKlTbA(s6hxE`Hl4Uy6lZQTLdj`V=tq@Wnmo+n4*Jx#xgQdH-z}WVxS2F@XuG#>b!;-Rubd`N%bdidt(nB!%?}NFiM^l7h?&!1 zfx=ZAuIS1w)l|>>I`n2B3AN_uGg5!3!47mLGH4wbiE(nCY)RgzPLK|$uxltEhbCeM zd%~xyRm-L9vJsxOHc_F6te2GO~DNA+ZN+1(LrfCQ*7=9J&CR0iOhC`#C=3v2*hNx>eERp#-sE4cug*k>Ivt>&eo zo!&_b?Nl#FZhL0A&SQogUZwoTkg=1fOusbT&2M+H#u1Y51lhcwIikaAQ%RJ3f6rr& zn1PAT)AuY}_LabjehQES|*j^z%$8qxdS^)7RY1lM&+K4bIpvMK6$!% zjQuNcL;g=sxk4M&3%kw!^@PkPN5-qeh$+CBjs*DFE8dt^-E)Ug!*1ojo7(>h4Sz}l zh~l3oKUiN8X=##3?Ds)30&$je6sD@su_ahk`jX3emh-8Qr zy$6#VyR9P_8%h9&*saVZJieL8h#vLM^x$dwo?E+8UQ#{M!-(mgJUrDAY;B(?KUlr= zQznpV+26F3Y{FrJO=&4Ph1#){EJbUlpHv3qB^wnbgb`-XoQQ-N)84J{U#a0wX#hXr zKVJ5rw|qo0D&K`>R*80A841pZxkQ9?<&`_ywbp&EIb$o;vS{m$w(Xf$bA97Qt#y0a z-Jx7xHrn==c?e$xYl!GQea=plHv^ju=zD>|r(O6+OfvA1Xq=AV*7m$e+kPNK&(W^8 z=VRq)kEP2_p2Aa*2GAvzL6=x2jR&gB@N7r$`F5-`_PZHjzHlTbVz1&+znt>Cs*;m< z_vcx;eN5*)x(vM>B0-+eZfRb|&io>tlO@Xzr@j}kp zO#V`K(}H;5q0RNQdEZB=&#az*JhC6~amh}SCqSz+`57ITRyY*$#cm1|vXC%wF5F>} z0;}WF*TU*cwM!~{?q5rLn0Z%E{i0QGChW}*p3b>08OFs0*K_zYmb5iZz z%~dhb8Gf!W9%x-RV?$h3j4axF%eKwA3iw>gz^nJSCFaGn+NOWh*66_AyNBV^QOIanYCGQY zBF^uxhF>?~fwq0N<83R8bKBg{!4I!+U)#LAzqL6XOd!V$ud;&Nwt<{%(>s8<03T#H zA1Hm;HqHSZ1o2aa?3U%?M=e$x{EJnbRtE_=Ene}{w)1%yZ{S?S>an}?K5faxd0`RO z3<#Mmfx?g4`WM5$%Xq93!2QLJKesKAW{rS0E9AD_PX5-mr4V5^b_x-?75-~9{3#6} zivNVR)rEg;o8y2-RbfKQJ;k52d@7w*dEvp9IfWm$3F2v$6Yg)zvHh*(7{WxzRg$ot z`xAV#1baf`y9d4t@Xg>mM_>Z8i2ci<@+^$i)~RlB3LO^;s3V0WnWRt*eZixlHv+Sm zS$D=M%S}iN-eJ8q8!XB0#lU=V9QK)I1Y6@!tmNgDIjRBUJ;WM6ype#nwRt52&Y;_* z_tz)Z)FR#4Cm8HeClIg(vJy#(8^1&noB@Kj$r2o}Mf-xQLhd`=WBpz_Coxe*TGhOA z4{U#*jL&WBR`~x`!=KUsqWHU?qwOrFHE+62Ts9mC$K3YiiGW*AHF+ymd-2K;^?xs4 zit7}V@I#^30?XJ%iC7sxYsXL~s{l_5kuv5Q@577_H;Q6NQ(ZLN{)KH9&10CHhOtCj z`2RWm6r^8_^b06@LygK;VPm7M!Uk>bA7MIQjH?30ll~6U^*aXt>~|R9o8Xu8xpiy6 zP4a)OhCihNMDf?!NfgH)+i%9vsJtH5FckYo%Net*s42^a4~>*DN_{p(HVyT~sJ#5Y zlrwFQ(R|+j#e5dQg7}GGh}0LcKTVb9hi9hKZ-?BFjG3JpqY`@+NXEppmd{1}2hi^O zlSH)on66eIlP9||R?G_{g~DX`1<2v^FoR%JF2fF3FA!LLK8eYfb7VK_&#jC8FW7(A zY4}qbKotMxPFhOiF^?8br>p0E!Ka}8=S|O($DSOEQQBDOdLlEnp2iX#V?P-SU3x6+ zv15-PX&Ohy)oY)Xk+C2UndP>NDCzjHgt0j--@{nz9}}2mrDaaj_{6bDJ{%e2Yo8Sn zd(ZnW{`Lg9ybc_3rGqce?*FBJhuObUB!h|Fj2+^5u=w2zKWrwGgI;s1d)~_I7H@gB z)Y4KKw+}NxcCol%($oaaqPXja_d;sG%`+iB5bIf+{p8u$a*{l@h$z1yL}&Iu&oJXK z?eX(WUQ)Nhf4zo3r2$0ox0cy9fw8#-*cDQJ$WcXme+fQw@}A`EwD-4_KZ`!Ro`V+- zwP#}P6*sgj3;mvst2K}V%|@jXwa8Yevk#*yuV*#~V>-oAxl*lR3L%zDa|UC6^9%@1C#)jjKv@{v}u@DS#N z&78F&rjpBAo4xx>inbN&I+!#G*5kw~DiLDKhgKv1C&?f(q&`#1GI<#E2^>DbF{OA5 z#YqN_ZJUGoD4G7NEntU?Kiz!$y3@@=-|JTRzog+$X#i3D4N4j0WO*Si8H4gtII^A} zp*7(@wy(KNXH8Ll3=WpBb7B^ijg@@@8B@n3KPvQ(SNJ}=>a=SwtRJ1{aUpFT`(3Ld={yB*Re4eLzp ztjG+GDeKi3yS<=R7ZQ}i?dw{QziFZ%Y|0qGZZPVBG<063XDQ zjH#r1PloQm20f#aj7X@{h1dZ0w7ol_&LrPeWZne6!Y%xFQ~$p~ z!=KUsqWHUSFO_4;UA29c<($E*A%eCvqba!fnxl&NPY_+>PD zh4kvSYnJlTY@$@UZ54+@s`3eN>)@r9t?qN!%iUUeIMksKMF%augZE@e%1iEQX#07y zDZ`l9Mkb^ez)q=u)Riw$n9ogB1fOSE!O(={yyOJlF+PGueqk%t z>A4Hz_M**mRLU@R5o5smtmfdd4l2p#CS32?iRyjdg%qEp*Ikq5qBo~~{#EbQ9}1J= zszvA$-*mulQ*k(W@O_7PDfqg|RggwqMNC@w0HXMtWk#m_2}62kkh{78GiLVNBP zj2Uw{I$s#m`q6Z~hb!CB^c3b15-d+0k7*e@V+YuyadHvD_s`Ckjpc^z8=DxN0~$t> zr!)9(cnKr+hhayYq}m-!+Ei&`#wMpHlN)-4S_aMk3J_+Ub8V&@HV4LDe@M!3JMBK| zXD$b|Y~A#oYR)8b$0V=?ZS|J^`f|h8H;{4;x1(tRS#ZL*3*KV~vHsq1Wf@O>aSMz8 zo9(}^X!uhaKotLMxmJE!jvEpGMH;McPp>(xmh_HknGfBr7~%PHXYlooAxbPUD6s+$ ziAyztAq}z|(=yG4dO%KseQ`Jt8@slSV9Yf&Bthm=u9mrjvC}&6Q+hP*XqwM=II(tg zf?R``Z6U)>I-bmV4PIkv7)MR3vivIM=hhXz?=n`HzyTpc2=t2_4(xz*5uQcqy_i}? z`~0amRJWNlYNmWZ6pwm4YeIt?>6~_){7{ z6#uno`xeaqTXEQM#AkH|%~#LJmt;Cez8G`mOJu%!bJLS#11$eflGx<6)69?YlbKOq zXy46atv|mn_OA~U+2?(BJTYu@`WhDL%f5_t`Xp%J1w`_FUaV6{Mux9+afZ)1eWHx@ zV%0`?5Tv{w0qB-|2y~nK;z&q7f@>w1L8PA~<3?M!{*(p~#h-y)WdLSY2M}iPfO;}0p^K&M%-}QY53Tbx*n+`?FauBT z;&27)dxF8ZFh!$w(%T8NHMV=}50TV_I!27AObvM9qf8BWcsfQ}#mSsZz|l^HWDr8B zqyN|{J`wb8Rma+hm|DmVjc>?k;~0``&ssa_C8S2N&1l1r+%9I3l(JX#i3DKXyA%F4Zb6mwI<9!heW_ zk3c`Z>$yBw=o#gC6*fQv9nCSyGpe(tJPwkS8H+Y0ff!D0glY0vtO8+_5s@<8;Wo9V zK9dSvkWns$$RO|r42D1z(M#E-Q)Dnd-Klk= zoz6H~8YuU;b}xKJ)qOmTxd*-cymrJJ7^^>9Tg7J`hh@^Jh*zukUv-JlIs=`14%Whh z46S$MYQ=$6^b<7PuEw;?Oo-&EOab3)M&!2;R+r zRI5#itYIs9`@KMC?69-Upl48*oR54{YrD!9?vd6fcB}TkRl}ds0HXNE4%2@{u1bf6;4+iQ`LjD(4|XsSieQaIvzM8LJy^_zLV$?C1C{O8)G>NZkkc z)&&^d$6a2eq8fmwhJ)md0gC_ERr2-%*?{)yz#I`#2C47}Lx!Tw_UROJ^~vbB!VxpGM_-m54U#)e+jjnKMyY|EC(pV{`SuS~12R z6F6$Zc#zGL;XQg2ql7w))qVCc0nx03#6piJa2{w4HPtw~mH%$i|F&uPQyM@N|7!Si zk_4>#BZe|Y8Hhbsro@3M$4*u4wuyq+PW%64k?I5Xc0MruvXdm^o56a@!vS}! zWSXi4dPIRd1?j%n(Fb-6lFXpDx!fLoS3`LYfZPtk_| zHC98MA{|AYA}#qe)ZzOJG3XuOe!U*-0Y=oD2iE+-=bn2&vbLx*iy9@1-^1 zCAmvwJ|OB-$uUx~Q(g33Pw|fVU(4Q6j7IF&h!Ju4)Ja&R5LzJ%(8V~)6D1Sm|Xe9La zPNzH{{9SFeJ+aTPhqV3=Sv|B?f}A!e9$4}C#vF{n4a#~*clx~s(w+G^qaR~+i+t4; z6W|3sM)l=beH0Ep-kDbm?CMj2f4ZCr8wEKT4wi=b#?(kUGrH1y9O?bXxO1aHw!s_q zTGW9QRWBFT($#~>NONwdBhu6Cz9!)cfe+(Uxtsa_uh8(PG=M1n9Q^->gWuFe+tq=V z;Sa2o6R@(jm%KhwN_1rKh5G}S17};WY2&AYNMF718XX@HW!^Pv_hpn{MMe(C+^H_c z{$^mTK>Oev)Et67_^!|+>R1bhy*^?I8L|-G17lj3l)%Fym;tABr0$s{i*GVFMdc($ zNn!`Jvn{M*V{HnDRX?YA$}*KuBPq)?AK#e2 z-aY>$HT)?JAd0^exb0BMAl{FaGl4>k zjK*V(W>6kOYXNeRFdGMF_MtPc_mxym>J=$f?g z!$P$$=G)XSE?3!9L5j7D2FBM|JUxSv+=`Wm5}!#FE7Hn~q*V~fS?v54HYqyp+|!R;%{7HPGX!T_?VTNtt>136?D; z@H0p(FC}bN2R0%X$Et)?s^~xtI_B<`D$^L>mBYWi4L^+mjGh|%?F+srl`GMQti?J~ z5i1V|!oIjriPe3S&`XV-wrbkONv9K-yY*`9{YV4(-@@?U-2d;;@TW9@DE^Et;Dr=a zQak8AZD}RkP@VTkz!{s^Fusv~GfF3zABJIZ4MzfY$_0VPW_H+EFZ4oIf~>I7-rPv{ zfg?)j13oa2NOqJr`)_snWF7367yGY;-93v5Hqhjz5O#YaJy->0}H; zIqzA_;^#>9Myr?KPxTI1qe4$%j)?Zu?}w=VL6qg4w1sOq(y`wi%}Op8*}p0W{mLEc z)+XZiN4myv6sDciBs}VPzNj31dH2}<NhjK?B{tofp zM7%#C-kgGqeQ3P>h;tNi<|7X3lj{S-IgdDV5NFxF7e~)E;=S@O+Ds2!j2kxjV*G?h zF7}v9@dVzMehK$GCp%?luCoBUK2O0Kf~f&wdNe@H(*nfOmM{m`SzOl%Q~j*zQNJ#7 zy<6e`dkud|1Bl}Po4zG}hF=N}=5v0X>3NjaGL+WDi=+FZ9o;b}n@;c0TW<&%N*G%vH`>=Mm=;#H2Z3 zufZ`(1L3=#3xw~cxfTZqwb+zh&kHNZ>FqX>!r|weG@L);7geBjiDJE3j93(O=$W{yF;%ukV264KV{b#p^KcxXg@ox;xLb=S0l*_lF8QUQfQJ(tpZ*cwFuIseCAQ5Pp z3g3jDEdMq%Ye!>fb|o!KtQp-7iGXK}xHlWE_({ump;^4-#8c*PLURy%cI9`WCr?iE zTOc!L9sL&9z6;H+CduE2o_uwx-(*5eNSisS--l*zqG|pRda|0Nd>@)K=7-Si^haq* zn|}z+SwXQpADTVpV91(%J~Ss|7QK@*(Rl&)Ci<;x&c)FaAR&fLylCtD2=Il3nA_u$ zZ9=Z|VdrGntM7N_IUn^i=4pP`LS@60KsUpGkA^>`0YveCJV319Cl;ezc$ACLGS$zU zrudBly)N~A-p`ts`FYE8XwyqkS})>i!Nt+fK{gEQ;kPo61c;HgIvShGgK5~OeX8Gp z6!gL(=R!zaD?c$n;167jGu5w^`gG^LxX1AsPWt3wNR(>lo6Zu*?Zt>qb9p}yb}S2o z$3i}gqB%o082%e=zXapS#gH9{W2{fa8#9yqMixlw9`2G3Q~m#Vw!m+MbSP_5jfa|a z3H|zRa6aQV>!0;o44ZKNTjWG#o*6Q)Tgm@dHT)?JAd0`m^gJYI55JjA@|&5-elv@5 z)B#tn0Hr;}|F37K`pw4Tdp9+8=xUpor1*q~{3adZa+CcQeHltq>v7HK7c9aP(9>v( zJ`@P2LyC`l8t6TPbe`4FGXgzcllsII4_{133;3B>Nc9MQ$X8$B|L3z){3hfHo`*9W z+z93_aleNrvDU!dM(3DHaVH}j{4pGUr%2}E`RUGULJc`~M|0STIY7P{*1k))7Y;7$ z3Sm86#&quVApLB<_&>eWxE>eeLxTXJY zvj4oM;ZJD*QT%BEgz*=`(MbdNyM_bvY~+sSK<-;Dscbm7x`XbaNLvma4btn85#c)) z{4>dxcjltSE$QGRd+q%cOL2OdI+-W1Q>)N-g>$9zC!DA(XN*+dyPfs1NVBwa``4FN zU;7nfpWpZEiTcD$`X15uq3;Mb0U__kw&YEyY$DTYAUhU8UM+@ZxCE9cP0obx)Z~m- z1B#$Yn6M+6*(aDS*!|1u6Rb8omyhQnIxC)=)V<{Y>l*%)1`x$xfE*X}koks3{DKiO zpQmy(kh{HRy)0BErM=a%1NeU$a>?=4u`Lbh;oyl-WmA}e6dq6m{_i44@WtpgmcTZL zYmYze7r1AzSJSh8v*Ev?qnAJf2nSyc(^em`C2n7LLoEuQq-{DJ+!X%L`n5sc)TG27 zZNh9pVo_uqv7<>rAH{3$>o?(j%|`S$5s3i*!^mOb&r%^NcQmW_a`0Z|Gv3kcGZH)d z&Ze&LrW*Qt`a%BCYIUpr-PHcy(D0`;fGGZt!M0X}*1I}92$nqMwCHzGP71Q;8qIQrzI>k1Btrt)E)*h)?3a z?^7s|evHql|977vX?#EF(?{k$ExjPkm&89?-#OIei=8gbl%AAkOLMRz0LQQMaRT;{ zGztCw;C$WrMns3?pxJTI>^RdZ?DvPU;Q*5SYKT4B7@9evG4$jI`$LvHF?t!-7@G6= z{?M(8J^fub;s2(FKcxXg@wd!rgq@}_RP!RbrnU@sKht__I_7)PZ?!J;S*`5R zJx!ctPg7H#)`$FWi1)bx@l8#abkn67H(@UHd)4`$h`;81!guCH$P>%g%@g)r3e8Qr z6q+~u>*nz^JQm?;mqN4V<5-3`7<10ufbfoPg@2WXKcxXg@!uOVeSkJ{a9_xr1bfK` zXe9&CLQ>FD&{}4XLpU2PAzwGAtV8TKaP^PxW6b$=vwc0zdoRM8BGkYkSlM|O?v2JF(>&&& zRuz4W5&rqb(Bzh2?4k8Af_@oBt1tQm>j%!So2^1y?D zSMI~{DD7i#^(exhNk`ouztJ=pV9!L_~#Fv+4140hcB<%)#uFv z?dOkDy^H?Qa*2LZ=}a}bd~m-LGR4f)Oh@LJ%sluA?a}a7OBShtE>H{n7Gos0#BT;d z7B2Ra)y|ilzr#pd7uE4z`TE$2p)NqVe87U*Xbtg9J1MG(Umt{&+rxu+$8_^YWPzcKooy6fT`PpeSEk2 zO!{ru5&3sM3$^HAmX8tRs7CM#sf*%3zi%uis*}@ecQm)=u7ySw4xaDWiE_vKzb;(P z0GFeopRkx7!G$7biHGmc$Q?Rj4+rfX(Xn|rxTPJMWNf*Q@N8WLcJHn9v8L_VBbr`i z>dMjYS77JoN}mB&jpl?pc#_AOAgaY2>LA*i>J-1r;Cj9ql_){7{6#sDWF<_;&l=!Pr42tAA#=w{o441Z?xeF-<|p= ze51H0d?R&F_|n-Yd}&Os&q02wZG*4p6At z=|TT4ya+uLBTO@T6$_1>a<~kiZXBjYGU&AsH}!nxg-qxTV-_lm;D*gNVhPM80g2m! zG34;fQJG^iCt;uQNsx1sd?p-bj`N0tAB4G@8_Vlf3*UtQ0S$jj1Bl{JTXE>H)`kmE z3;0M|jfu2hinvfArO{rLQzPvPEqpH41Yd(akhX8FhLFa!H9X=`IWQV%B&pg(-Q zPDIk^41OE2`^9yo@vq34Eg}(yp?+wRCLHXA6cQ@gfW&kLPa+>$6Scb3uOk0&BGSr0 z>PLTeCn1vKp~yA*)=XwxW@4s2b7*E-WmRjxQk_uQ8Jv5)1{BE&=uiHH64&I2t%^$FSK4WvqS%Fl)j!?Cv*F;L zh`dhdsw>%%y3)5C*8aUVAo$)@ir_1eXQIC#>3WZ}wuV9Np|x?LiW;41%lt`eeW(F7 zt|}ZXYo~orXZN!Iyrtn!X#i3D6VPU|+`p_H)2qLv9Wo>hdjHr$IRB5emFK-3{zS93 z3$Ux2*oQCzn1p$s$${{l5xXKR@(G{AW>%e9|#`t+u zT99PhCa1g~Yr!b9o9Y;f^FzeqhlKmpHrZ@%H;K~g&Z-c1FXo!>ebH~RR)s8J6D|15 zZrsK06b3`B?*g7IW$$ae@K#IxL+37#I)br}f|(A+c&g}&qW&^wm$SbM8M~MNml_R! zN&|@E5C5Gy*z7LHxO%%_v3powc%N%>B$QqFl51-u1P`IEzehqJ6`G5B6-DArzprR= zB$Pe+q)>%^=3%7?#&R{hgrPc>wP8@ zEDxVu2yvAcLi+s|LWa+Bkwf82NPGK*(5!tILQftA!`r>q$MY9Lvp;(UcS$+!uK(#S z?^)*)1bX*x^zJ&`MQYJ!E!Uro#oPVov$n2hZ zEVp@pW^<^{Rka3m1h>MDvEKf@fi$1gmi0u2+e{oxSs9? zHOUQz*3t)DE3lh9?#wWNi8t#udTnDg_7Gg5Jg%juT|b0o&czv6e6GqE@cU*ykF)JK z+jqK1=UV0CIHWPixM_XSeMQGz--V{j--f2++38D}BAhM2*)p6}I_cSqINO1?oLH2PuOLseWcGClw6XD?@aveR}<+kPf>E_P|QFh8L~f%l>;v!=KUsqWJSF zc4Q#AzC7}MXl6oJ+4oG&f-OIl-J#pb!COwxMzpM)=FrRnUudSwADa2H;rG!0JQqVV zUo6f#sV0$=YC`cz)P$3&t?(rF{5h%e(n*yQPlDBJrc(U(u-!bdx`ua6aJ}R@<%%hK zuxNLPEuri!SRGN%W~_%?@G!sI9paXPs}6+XxNJGtJ`0}H z{qCPxuM~Mv?{FF`zR6vz(7(F5oFAI9%JQ4Dp9%ABAQ2{)>>{O|UON?l)j{!4Tu6kP+)hqAm2N z8VVjrBT##pzA18Bu{cYQ+Q~J33|u{R zQ}snVnk+V~7O#U>t`-)%IO0q^(PAU;FQ(_kdh9R7d!)8IB)X1Q@Fa*I;-1N4se=EZ zZ{dGvtl1M^ZP+WyI;_>Tx7Q!0`B0|8M)mPLMoDNdIn0Q9c=QZAup&?&U(F#d&PH-u z*{!;*I%UMQzCZ038T-4)Zz{xZl9W%~&X$tM3S{gQ#n1l)>lh=uLfmSY-}rlO!v9?j ze@X+0;!k&4ntz=0Z~=#z8H}>L8^>L=lzWvslalIsSHxk}22r-TbF%rme0Xf!@6JPL zJVI}}^_5#QIPY9S2CtV(W&NfowlN-FwBn$M6A#vWdU9K)0CgSVD&ccIll9P5rtmzz z#B$KGMYm0-c(MNEzt0pjEWG@CQECaNt<9L&aIQI)LF|kZu;>zzcnnnuDNOXq#i%>F zgdyxUR=EvcN2Z+Fy}(fEe9CMgL$N|7v+ z$$x267Vnu$e5`P|l?*hNNnTkYd6L5Gcu`+X>l7J$x|y-XRo}Yk|HAzLpEUd_4IqmD zUs_^Wl;~DgSp{kS=^1!c;2{AVJbW}$8LRJ-u$p}BL`!?mdrTbzpD+uRA>@#Er+N=0 z{z0!e54)`>#OaRg)D3@N0phgJ+^8m#1Mn?zLQQqcid&MD<%N341A`~7nx;&BG8|Bi z6(n`fj169jRT5H)+slm6(lSMd^`L3vFqT-?2pRBTQ+Ag|;;PnG1Ky zpI@j-YViJAoo&&i_NNWERSYaIMO%ce#oVLuoVvSS+`bQ>1-kHUWE;Gq!=%S`DXG2UghxU4R63 zx_eepALO*2cPso4Yxq+dKoozpahPH>EsCz3hi~`YIt5$}=uGR}$JF^7e zaKCSz*spP+(nHUp6)#kJ>W5ws=b;a_EP8$k0|; z^M_Q9V9p2C7rE_EsJq{{UNm|32VN{ZrylhXJL-U0!Zq{;i=c~|=^mxSYphax@Xc$E zOye$kuUp}NM8lub0HXLq-x>n#TaZx}lH$&juDG!ysEs$253GhaP&2I?`V^u}MK9d5 zV$Te{{N;IlIk4m-y=)1vTwHZnoM%%SbK{`B?Sl8F6U`PT!?#A=xY? zozi|)eE&Vy-i3Qur_Ye@fp*Bs8EECGP05lXJw!xyQ$)-1=&R|TPIT`G&dn+lRq7{> zJ%@OruCX+Uws>fV5#G3RjP5K?y}mT4C5`8^$KqZ;;y(5lTshX{hQGJ;4`_@PHF(3Z zbT27VuTxSx*&6pxJ^*50s_73;K&5iI(X>hb_Z%QUy@U2}PkG;S5jz*)c@8_kqlV^x zGxJ1q4_mit{~*IqB0Z%6MDaK6&4DKL5Xz|@U`UIPS!Dml{IL|IiSBNOiq@D`Ss{-<3 zWa3Jw-JQ|y6Z5LXTfg(rSEj(`nzyA(LTJ2W` znRUG9wa*iuT5mM{J;U{-TH+X%waHbPL0ZL!VttpVv|A)R*i*0K&j9+#u{6Em}r!;^l{?M@v4`SrhIBTI|HjKYO1_KRv0wVbm zdT^(2jh$))Tp7V`oCb3?uIbBYug*o}h7P^@1J?|4l7mX}6ayKt{7ULu85qg;Go)Og zJ+nnd+gB_q`~fp2S#TxR?m?Ti|KH@j30PCt);GS-$w_iD0AWxOQ4>%K;t)__dMVKdnC_uAUR{Qe|xXJ_FBKSmdQ7%^eAzVL!MlbE06`Oz!j}g z$OCG1xQ1~g-PUCUmc`s4I$es&eoDfh3lpAm@ji?`xWaDIAU_Rfg9g}^pXLsKRNMNvtiip>h0f+mXej<&PraSJ8J*v3xCZ8DnkBF}#kh8XnzOJNplfc!T_> zGyo6&T87&pwf~TA&x~=9iFBmBogX@fN(E9-Q_uJ_me__Rkn?$oXX{xe9T{1o1Qw`Q z--T2S-)GagCGBDNx|?cNUTzercC}K@3G#Dv%}z7$YRV|X#Br2;+;a+Q1mh- zn18tA$Xd5#$S5`HakN9>e?r8c(f~a8-r4~4Y0dgA6_@`z0qEex#!ge zQ+N{HKM*L#^7rq94Yxl$0L1OV+hZ z83>Dh>#!}Z6tbv{W@bZ;N7w-{25F^8Gwg*}*I$G6;CJhb_6fIm;qz-gva|KRsonPY z!tR6FAKJnZ_!h>(SFn#H9MERaJA1qZqJ6)Y+iK{))5mQoTI1Si-s4)2Z{?Fp99x=u z!R}-_0uMu*S3tam-c6T6YmW#5(1*1Vo@OSd0kvPDt?~uZBKa=*2^yrYqCi%}g(?f& z8XrAJtJ;}-oc5m%h5tzre@X-J;P1VGI5L|Dw5^`owDC2RLCee3f_$xf7c#uMZEB^E zv}0jLy7CJ@rspA51a+I()(9in9bnIY63+W^%g z(SIr#$0^vFdqBnzx8DiJdFd{C)ZNSO_pq3IN#(WBK;MBK39`nlOJTJ;(@S0^T3yly zGsMgTG$&xVp1>AGZ3FpOXYeLX64B<2dXOi6IrK}KA$Y=#WiMMGp*j@)pNaTW8h{7? zCvTUeo64B*PBzrjbnz;~t;c~V#~1`j2=EL4Y@K-_l<1bJ8*|+7xk|sqC zf7DzcN+317Wc8~3ON_oY`|J7xG;{12kCZs<@hY&6@9&nB6WuoRs{QngSjg_1F1{=; zSYg|i&*~W`!)!BOu$H7V`jQ!7Ahh*KqP=}ZwEGbqQ!wGyat1sChJoFZP<;cwLmsmR zwE}u_7;h+DEr9Let5`>WiI;PbVo}vve4|AtloP z38GRK(w@emS6y}mmL=i4<^{h5Uv&aOy#n4G|8-3O_LbfwuivmK3Q4%r>iz|fa0h6& z{`*42pV9z4_@mB-MnrFv&4b+y+fP^gi!Rs8QxbwN*GrcLR|FKo-on0qW6nNh;fnM( z51<_vGvU2$`V4X--xoQ#M|#=5saNV{(9r*i#lKwV%jsDb4O)Jr8fSS)+Ml(|Whj5# z1ddPtYMTVJ$7Dh?y>@Do0Mw4e33;;;GL-2*&N_5pRfaw3@PU=-KPI<^NF2|#Y|FBz ztxQJ`8{8VwJ4xaghdsTMPh}Vm*y=TdlV;^-l1SwozM?gh^rLnv5>I6YEQtD(^^Y+8 z?bm;&MEofYz=MDA;K{)yvwxi3#d@OrOy;U|N%@(y(#9H}@QU;N68LpAf(l63lQ{Y} znZe(rS+EomSnss<*>sG9odu3hIOz+n#YW`gFTGy@ZW-oUSn|Ro{Z&>}3L{*j8Fhn* zV-z$A8S*?{v-Yv;fO?p~g$S_hq338MYjFnZh;yOrM&fwI6=l+tX`IinonXZ?q%-0C zMMiJHy_h%#Yk!9`Ay%Kn>F_q-wvldk71vO;DE zESLN^;ngy&X`GO6RKcRau;T>(z)kVe>JEkfX%T-)1MuKqioA$vbvxsSRE!fYK+mJ? za{=u`TSr!nqY|NRi!r>SJ8Gt!hfhYfH8!m*{s=G*uPBNK&ig~F*{!?5%=lYekGPNS zT)%Z1EKAuP$&F9bP9p+9FfC8t3^@`iYzo?q|K0Hvwf-_zji+6FBH2(nO1hbZKWY6p zjnV2;XFG^HbDOQGG{xSL+H77>?9X}>1D>-#r7U^A;{!8kC z#^b2?dxmUJl{k{_jlGo;MRjs5t+ofN(eQhLWk0|o)cIN6tkR>_`c8d6%~~1M^}b|C zj#pM2vLIR5Dy;b!b?h`X>U{*o8lU;=T5VhDiu6MG^4Fn;*fHoFGAB=V7zbF1DZ-R* z47E`mB-{pzGO3jHI!8T*&UABnp0P(=PDY(8Q{zafawTaJu$Cl_J+M6)93^@Bj3_}1 zkCxu;OWxbD>_1gvG-&m zglSbt!Zg%+oJPQ(S58Calw??fUKC~un6+0ChcD(-;>^j5F!d}hFe+^!!V9NA5I(s2 z0$Gdg4QyRLklQm%>x@pTws@WK4{L$(H!B<7-==UTh*e@7X|N(09OLsu-ZyWgPp*Fr z_9RvcmOA()6Mgoat@qL(H(9TqyS#SO+A?@L(5;4ji8!P3==Ys=Hd&Zkh0E>E|_z*?vB@v*{1c zQ9UlVdu2R0M}>PROeErhEkWqHlh&3ByGPe?#L228mySU87*Jt|{-2H~>ordYhoWM1 zkuQ;s=ym6Q{#WJ&WiuZit7eyirKKU^(w!j{nTFk2#f#r`u|rV{*(sb z!GBc{xO@_@_~r#xNE-7(&eqGr&(>GM!R@`rr-88Wl)~ds$~em5nKC#&2Pb(u$tgoGtU_Iy9(^4&g_=3r55ou!!SfD6_c0cnU1;Q?4PUURJF3X*6N1!hRl-VV&`+ zwHLICU!Ya|gk#VWR2cULjCHn&ml6>P_08Y`sJ*~RSE(6o-c?3+)@3N^gDk;M!@g_q zeiQ%Cx}GV4lo<9y{AY;v=z)wP9RI#^jw~E(#%Q-6(u7q&bS?Esi=V%1=}`Dri}+I- zfCqmP-lrDz8X+&wy5dS`yV=u|;fepb25bu%si2;?KJK=wx(7QP)5S(xk2scNggdNi zyFEQGKEEPCcsqmEZu5cs(jZ^Jbv26MR)-kpl)Tmua!5&Z)@ztv*wVbyw(8}_8qo0ZuCHd*7R z#9-n~r(J;t1O5gRoJ}gPlf+f7E`+lmb_Ebdzl;7IxW!m!Q@i(UjxRwaYif1Ey3-p+ z4IK*q8WDd=1MuMgrH!*sZ}=*Qv!cZeT8=o%@`_!ZNzMUk4Z2V-38m~^`14sh8wXfU zW%{q{w3d{gO5=xgc1zar*UEEfWG~VAd;m+EFPN3SG7Hro&$>ofFn_1Y*E5cPxj5k& zePBg^GZ-te$UJ&CWQ!npYH82r)viNM)`v#tJX=F`iFko%eJy8Do$s)T>}TAu1h}tx z{H<0!&UT)}tU#ZM=jp^}(Tahs1ARXr8|l-MV3AC;we$-(PptyJMJFm!Vr+-PzgEPb(f~a8FU5K(P{=b%>r{=;s&>E{$n>i`PxW<;6)o*J zVgiCC6wPSruQxM}TNwH8S~+ljwb1WPgj(g*7caPY4WnnGsBIp0d02oo8fXoUA$dnl zs-pb;)JMm_7DMk7i93-JR2#p`38XJ^{w)vd%~JYI;+T@BEVRP%0FJR{sxT2=0abyb zDBt*sEfICS``SOmn&V}xIh4g4<1JL%J6>*@B|vJ#Lu!nD!pcMpz6e%lMWTz3JaJt) zdAHHani3yjJL2N>C$OqmXY5QplhJ4D*^nMsS9B=+&x!a`8h{7?2kp|OW|K>%Wd^c+ zcB8E{wu`QCEfcM@tLohQhl~3;asRM0^ytttHkDJ$;~wOQD;QRl!MI0H?b-vV=7<;) zt-jc(wqA7gO59@PvBvAA-(uvf#m3+YLlB;UDlDyfRT1(7^iF8=5TlPgE7^cN6z~z( zSUUk99@vk(k+<)nOHIW0f8R&@!^j&8v5&ZW&FeSP_Z_iwLb;vvH8?&t6P?1T=hZvB z!BkiKQXh35>z9$}(&=9?7+g9n6D5g&57;?E3UAOO{A#!U`$oi{(f~a8)3&K@*EVQD z>|dMtpKW%zUaj*+^k3`1;#l=s_|PIEt!hL9OoT?T3KE`b{S$7fjlS*`gc=q)#_{1p zl7HllrF-8gONEtSB60>02X`A4dG#Z22zyE27i^m_bJGk0BlohsZvINbZ8qPX^bXFy z++haJje`xsk0HHI*Grhft8ya$tg7A*nTQe%b-&ViOAkg1XT5+vhE?pXV|xkKHp>}b z3$;@F;`@@&mL^lHFFX&AF#PS;f8UDuQyPE=|G)|=gM({fFDFd5vPP@V>$l$9dlX(- zj79#h@_KPICuqv(46d+Y-1bFY4V~1k6+BrS=)RFRR_>)|jJ&aYujSVVHJDc*LQ~Ak zz&h2?zSL^T9ukHbrIKn0#1Y@jp!XzH$OO8k(#1ApP_Qp!Ff+5o}m3iM&Zo=bv+8AjuPTlLWQc(8pc^03}~Ha^BW5jjkj z8=tgxDE!Zh_){8y2Y(@6YMaoIz>~0D0(g^lIo9a>9?ZZ|(n1ekl7LSM=G8TM3}$5s z9Ya(Cumw8Ah&kqMgDr>3?3_CcdPjaRFA&=lVO4O5K&*?)eN9gX%OU%N6PF6|!m$GL zct-Fi?kF!B+c%kb;`Th;t$&uvEJRx%j0S?hOu1e_9LY#z^amczh<|)~8Kd<9l1T8biT0Lfk)oCkadL zSp3gA5r0Yp@Zj&^=`pir3KB4^yzUg1*C9SLCz!X^x`OS}qIZNIu%jtackgpIZV&i5 z9*?^RyVY3dD|bqfRrMQ0i+hj-Q;QPY<5HzJqwfwt>_6}7$OBU1fJ+BnOAK|hP((8gQpQ*w12Q0X~u$@MLWUGDY7Yh|VR*50H7^Ca}Cz`he?E zQkjN${`;|AlgT(c^-zztev7BB7N+#zELsz*53(hhmc)0d*=AA(u8sGvF2NPg1(w0* zKOR2+U2bN80qYIc5!X^0x8KbR=!M_2BP$#A0boJE%2AP>u9bJo;+okcyv#tEQce9IJ_YLEs8l zN6o!+^$fE=s}3j=vKA}=8cSj^?nshBS7bsddCtYzKR_Ly4;sCt+fje-VDs{u2bz~& zpQCtDL9_ZuH%G=!QUt|%S>?s>0qW?Ay}&rzJr|6qz&)S-`c~`TWksI5Gsy5oDj+$i z|Drdv68&eeF^ZC(P% zbW6EuTzohfXj)TL92a$$+MM8BrZ`0k$T+g0rRgSoP`}ucy6$Y0GOQ!)t_t-%FMDPW zIc1tEOukNu4^s!rp?wMFk|M+quSf&eFVu=v#=tlRF^;!x{$$FErHrz`GR|$E?oi|Z zI}v|M1MuMQI7+b(zzA#ApTf$yww~yJF%gWC7&>!qWDpx|&Nhdu>`1}*HUsKAhqt?7IYXPkMoSTCq-9svNH}bMWCcb}o1s}#087Ko! z0;DyRl{-m5hPjO`O?mh7%Uz~uSZP7q!P-9`xO2ABxbyMf*C1zveS(7}3Gg@mr|$XB zQZK~yRHd8XyU48DhRUL`&;tsEL--yutx`yW06~hXw9*2pa|j~^he=jI82}v$|L;Zo zDGk7be?-O@iS*ooELcsn7t@N3J#430P3<|v+|m`&Xo0clsofXaVGuZ023thN)eITN zwyYRBl*B&?Y)`U33wZ-{HEFC6k+L0g^m(-Wr@|>#U5hoAj+m&&e$CZRM2{GpmL|MOXJ6rDwJ_%}1=4DWg7PO5D`ALyanaTAV4RK4qtkE2L2Y9^@a)QyWTGwq+gY zBvi?k2wHFf2a!5gU#uE<_JZqG{VHe!zCsZ)16%+vu*x-poCY&65xjs7g}+_IpV9z4 z_@gc>^8SFQLr8yvV@sYE+(fHTBQ8*R-B~kF*OLfF0?x@|D^QgS2bB!gU#Av-uucOkY%4HyacJb&4 zeO20OqrveQJOT8svUBKNL?u+!do%t&5SubinNdQ)tnzq#?aeR$vBZK27v$~M_CeGuG4u$^@BL0*H z;KAQSyf#&)l{k5}m}XJX1qso1 z^b+F}wuE5sB1?0LgK{za3OF6pXr>$hg&*b%O`%T_Du}BvM<^17N$^6m8$<~~{R6SE z;B#C_{A86F2 z$`2u)j)Nbaj<-uTJ#u_%E!0LpKX-;EL0j6-PWO0&=fS~>L-)wV^I&zOpE0t*&Cp4Y zI5{8q_005XU8s#gPjfPh<9i_R8+jvm-*{Zv*DTva*(I7n=@w-%u9nCV$uHdksRb|O z2)(kHREV-fPpZ6%+dcWl@`d>K3zsN^P{H9w5dIK8o5(P!gN5D z;{Gafz&NPfiDrhf4HMawRPIEx4FxQfJH8Lgo#=@)2Mmj26Q>3#XdKwB9gtq!2GUD! zKPcX11T$3akzVvJ9KDO~;kyi+in~0*@VEE>{4C;6X#gJlB^-xVOmk<_aokWhJi{ah zwQuvOu}R4PLK^c(zaVY{9n-Qsz-$Pqcn{GQ`fgNuZ)|?gS?TOaklpuo0yMxpK~^}S zVI?Ci7DpYjFCu3nl`n5K^UVq;3HOfs-YT=p3b{?+B65#UB3l0>k9Oy=C6$$WTNb6~ zgA@8~y-YDQU1?dAh8&TlD$9_x9)g#}W!fnCSV#!bVr_}6kiKgb7R_3v;8k?i6%0=T z%`wL`5QTcJSApKma!iWX-?tFt#C0hAe-ZJgGyo6&=V=sG_cx4T)$rMq3pAdB^V`8% zybCvBRmM^~3FLlD(_pIoL)Y>v)a)XMa|{O93H&U$MuTh$1-kCO1@D1{(K_Nqp+?{# zLwt&uh=hxGuCgpM)X(BmU~Z5wT^ksmPuw{pyf)LU?P|oB`{!MD^|JWyscKaC#=CT8 zDRK;{wj8gQ#;#ea+>$GtT`J$A>h877XUo#7iM&@bzeSA-ABK|S^@_n>LcFW5598Dm z)G)J~uX1q;C!-+R@wduD_zmx2HtS`PQ=cy~m@2_sB)SF2bf+i+7dV1AE|{62$6+gc zbYJb{|F0tclm_6zpV24^z?Ekvp`N3yUQ%kSXMXju_Bct<0b|mnyezLy!1ssSvE(2ur(6v0m0FRj4=fTS@QZknUq= z9IscV9y5=v9C@<8kN=lXZd$8aYu}sBOsm{a-2Wm|b*yp?Y%( zkW{&mMAlc}_4W>tc(5G16)vdKRS|zm1MuKaW3ETQURsB|F1^9%PB4(e zh484zEV5lxFXWJA<;~kujvPe1mi#i^V?+)xF#K=xM}qC&m66`i;#Ewq^RU=X5+dT( zT$R9MLv#ZLYF#gO<&@KFP#*;MNxwa$oOw#>WTaPM%R!AW^1zzoneW#i=a)Il=Hg(} z0cVp@IRjX+`iLjupSeSB?v6L3qR+d|0Qi)ZJ2*Y{FKbXyh=hR`V&T`53YC*15r_wB zK}N7}*nZG|O8K}c&`XvIJFsV|up7L9)<+oq|6=^ti}+I-fCqnM#8k)Clw_f;^_4+O zT#`J zg)5N3b@L8zyK$HO?0VwxyG^fR;oUblwwn3Ph|Mt4Twg3g)KSw+>ePIxqlfoH;iv2KC@qL7z|@29JPO7Q`Tb1aVkfF*o?3 z`Wz~N%NRuw{T|?;g!1t7v^JH&hMi>VkChFFm5o{>>noe@Yq^l0&9RLP8w+kK30-JxTYP zF11W4r)wITZE0qL9@?ZTEPYE9K>Ay-a_YpaKzom-Z$Tdhu=#`FhUN; zDz+kmXfD~0m>!7)6a1bnm;PS7bq>kHq@X)r(I>h>lI9^2AVkk} ztoZ*wMEofYz=OY}&rP(B9<9^9ZRjzAdRoZag;;=zi06305Ca}IWnka1DQO%)RDP_| zLTdy?z_YvZ?x`cn!oYG>Az!X8Oe&+106y+W0Of8iEX@1vQq<&D{ShBXhSnyjJECx~ z+v=}P4mVYTwNKY0ovjgw{NV<$eSB-QkTwJEg+uEMW|X$+4OKZ(Ye^RRq}xk0_zFGW zV{N|r+C#Dalf-AtcR%widdkQfx%=v`fXU#_Z1NfA3RoRA9cujlDdJCQ03Q4eL6_?_ zemj4iW(WXX~(>_sv8Jt#c99zl58++zH$756JQlT=-A|#a2IG-g(v*YKy z^DfT)?)yBVWqNx#laLjZC`d0Zj9cf0IGjL2DyFz1h_Z1dgNPsKdJHoKD+?+g=xiXZUn#aAf-E6Ah=8SVTPG`|owHX^Y!8ACl)^80B7_<=yow^0)Bdm?;(ISl69(C0GpC zd*mgw-96!L~)X zQQvDyaX<4nvu~k)5$zRuU=%c%{R*)Ji}TrwG580%zm3DAWEAw_)jcDq;_vBvV&$%Xz)*@h$yVbkEn~W zqRNxuvT;`}+6PJ2Wxh_!y!WO^8&c zcM$u}BMg80@lT_)8A2!xz=MCl{T8I{cjC@7`iWLr{n=}?uRRz#w8{#!bYHr8xcqq{ zQ#Y23fP|=I;rm7Orp2%5kclf!Fldad)hft~e*9Hy8lHyC?fjxNpIy`{Ke5)Y$SQOO z3!`r()%Wrm)GSu)^MZ`t$p7^VU1MtL{Vm4AiWs0w?|$Kms^C1;H}QnpD^zP3Wb<}2 z3Mjh$QJc;x$m~jo!$6#l+;eTDkpV9z4_&>v-C2e+h8`oGx8%wt~8w<4mzQID#d_7`#O`26{ z$OU*ED=5}@WXv2?R~mMpanb}9S%XXF_q0oktL4Gg(`limfGxmn1c6kZij`kNCFPK| zHu>Il=W%6ZHou}y#Vdp8N^i7c+kA2FXBd|w-1%QR<5>nxhzS;Z8$1wNFprVvImDLW zAPGFie;jhXT(izV9=Sh}>*aTAvnjf)WEDLt4@?hU(3lTlc400XgiTl8cJD_t8IELQ zK3jVw5Lt|yO&oHZ4XN01(`>R|=}`FJ5b>up01y7aYRF}G&c_vqz#*pUdeSQo`ZcdU zlSZvLUQUhonyUc@7Fen)?=_V*FDmDXX|6!ninI#5bkhfj72S^faHzs#o#M^~BzsV4 z^XRft8R{_-(>L|ZXSg?=WqQ2}$=_Qb1q@=iD5Hz3Y-#%buA#itRN}s?$nqTmmaiv| zFSYiq$130AibBPZfwk*hBhg!Od?Kv0vLAFgrvW}*B2{BufzJbJwQBHtFe8mch0z}} zAa{(IU07cO%_D^TB+{6+YSbMH|C=KIlm_6zA2A(hHJQ8a#=9x^ntr`qcm&m2b+GZ= z>u>k8uDb^4f3&Xat^*Yrf>4zwM;bGyGOh1f62T!Nxbhl{>@?t(u7 zo6umXMZJ@AKj~i6{@Z+60Q!kGLwkduQv8O8>^X0hb~Y6wbF^%2w=&3kWN{%RJbfi9 zyCEhNNSe|qmWEqBpJs28Kx8LUDGCyjkRN2HYJ(n9=T_6n)IT^87geL zMg1cbwy?n8uY@d0UW9CtA;w$%lRFgtw?zCY4Zwr{D&tLSSRm6|X_0Rf+wQ$qStC(W zmfWqT5okTenpo~{FNR&H*u|hCAge>W%_uNRtju5~JitF)VV-QZDV?mW5^-AEMI;;y zOE>R^Af5zS-+O}Llk~is_dzv09(7`oUCN@`l5Y&KiWOPl$(IlXEd@~z3R zr7*lf@M)X(M``EwH620)0bQyOSke+8k()iSAmoJNVxC7A5p7 zBW9SErp`FayOu%K2nO+FQsjYq|6B27eBJ+dE7z|6}1Al|h%2L_d!zM)e_xYQZaz;m_Ri?F=CW1BE9XZ_H z-Y6BV8t7(>4rGQ(JY3I#;G(x@s=K+KB2Rsy$QZptZI-2@Iu!o5Mf@oZz=OZ}2+>h5 zTclM5`&yNgrC!>J;8FQaXvmi&3i3UYbu4TvgHgu=Rymq6r(&m3UM(-u($<3vW|&)6 zFS~q4qN{fzZBs;fsl+3Mu~})vj>p?Z^Ka#hqBR+e*WQ_id0R~?d|k|NW*FFk-rf!$ z$uw7}9=3vjr42p&C2gOVHE6UrPU>w(uUZW`qevePwHqFIrrt*8xD!s|O?s(blD@RX z*vs}#d=D$r$nm6+Qxv)weUXbn2BJWlcOxe|5UjBlx>)REvCq3>#s4;o_){8y2mkBH z^HAuLpgkmL51EY{^tSN=G<(svcQr`-PwOvn5z-n}&kM1B4z&+!3$n99FW3Nx8kOH& z+!=rD<*gEjnyrLB&-Ibo_@TUBX77qxTb!MQsD~~|QtMek9jT}xp{$@8dZL~TJW`nn$9N%E-~t=w*gCE#FMBIML@iL1;)iRGLcFv8@a^A*d?}tV9xFh09&w1i zpX}nE?oi|Zj)*^{0eJB5fwmcoc2FQcN^Fw1LoMMV$?U65>S0Th z)KO~vGC?IAbE0?uWd=Zr=+o6AjXevp(mHJcz#q{jKB)86=xZIn zh-L{Ca(LSt!7G9l_GN;)k(F$YH`HX>-(2)%@QR$z-F?Elh8w{>72x8g%dn*`nxFIT zqJufVEV`L9xce64HQU>byf?T9Tz|w6bSV7qiuh9+fCv8oheRf6WYtq`De;}Eb%K{E z*2TS;67N$zuI=4Z$p0?xlUAQKX`;mU4K>>Wz0rOm0)49?g}wb863*YM6jB907n8yC zmEy0Lb<85R?;BV-^suc8Ry$egF^pPiwZA=8P@*SEe7tLXd-mz+>*BImY~vR_m-FVL zjX7T}`X;Ay_pLz7%`@Tm`njcp&$fZb(#C92srS9Efku2#@_}>%pr!)W$ z{;BcEvMD7S=2Xu!GK~_2)Dg%?;rBsowB>l5d{duhRWs$y@&!z@DjD0$ZL8h;i_<_~3Ex()i4G}nl-GHiM z6Pae|ZD|p^MH3a@ppYiVBZfFJyjoTy-*OpGwYfAUe38PbQ7D_GH+9V_XGE-IOV=dL zU_4#YwR>`WX^jHk!yob-5r7Qxj1NQvT8Y{&D>^OkQF2uNMDy_mMpga#)32RUqeI)z(0kSv-$V`|h6iL$Rl;(gjlRKLcjRPO=@_%NjWXzMAkw*y_woWqdv68tx|?P0Np z#U6G}PgL*;bV=r<2on5_wrl!4_Lq6X>^Nx_XAUp-%z>)DW||A2(?fFyag>-nvxmX4 z(Yyxp$3}aKP!!am@NX6Ir!)W${zb-VHO=>D(n`lE^L4b#DM8XtQ?tX#$!;zJD$@?) zFFS2M{z|5Gc5zcBF7BnR@s66e8&bO@#_ta@67Y!dspv- z4S6@>IG9Eid`BwjHB-Ec>#J^5u*k$({UJW_V*`3_H;$}WfcNT5e%LyrvU;LRrTqZ9 zgJx*FOM|mjIQw!9U!=s010SWLD5wamgMXW;?k~<7N6NU zQfpV2q#wS0Kf0gljg^Qx+1=xBi#inkgme4*ra#`XE(!j#ncQ&9 z#d8Xbf4DWPvkz-lPjXLna&Z%&Sxv}Xl$-Oxq7QR^TXZ95Q1{KEX2n9Yl7^r^baF@( zl17<2!>w6F2x_WDJWVx=v2E|3s(7RAowWK(QM17DhMJvSkuU83f@a~ibUnfypq>Ap z5%H%q01y7;|3kCd(J19en0)Q7ZgwXYAL zeU);J3U6p%xjicSE_%~N4A8z*?=~tp`T7YBRUES(8dz>z#bB4p&>x#>Gjy;LetmHF znemtvII=#yy2?o;n6XQthj??)LpV_nv40LdB(hm~=R3C^B3Vy05zeiNs3fa}r=f}b zgm{pz&HN^4BKGfGygjs8d4p;q-Z(S#z9wRJd})?#{@KK@?~mi`dgvlCk1+i0{r{|p zKcxY9@MoI27U*J|HBoU5-du7#_@4$dW&vnpKuBYUHde|PdBY2+YUXa}nw3sntYkB^ zu|Yt1x^5=Un`6@~!Y+ z+WR*%Egu@jH*gHK4bW$GDEuWN{*(sb!GE-i4^DvYE!jHJrAB+o&_dFpUTD#n25+*Y34({6h<@mqjEIKDkizm7?zsZaGqh=q6^Mbq6cGm=RMRTzpS9xoO=Em=?q4h(i z#;p@(0snx??LsQFb?*n-dTBTN8v<9vY~3zw6r$oLLs!54knXOwgC`!$6eCw(sWQ&D zXRN5pm#V2Q->V$DB6L-Q+!Z}mc3+#P79%Be*7u#!(C%4pwW!e=s76~aXTdTh-YU0F z>+AB?h+1uQaEHR56Y-}s01y7q>S+s&XNn@5ncE4#To+3=L;7;t3^5G~rfbp@zfvr= z3rw+Z96wZEa2cyS@0}!UOjmi4_r{1gbsfh^im*kUbC|G|^0JMN&pt&M7Ru0-31HMMvlfdT3LGL(`vn0ou(`4J$s8(Z@K?38J8vUzn`!NFz zN{)rr(QTQ6c`9w0-VS_+v_^{4Yua@ZkR^U7InnfrZ8%9_uTovN8hG7q-_( zIWS=RQUs0%=LHixrv54>{T z)M7j(aH&!2`Oe;6)~+~{@uAwlzG7`E%@TMM`esXJU4%;uNVrdR> zO1x1)4dYef!&R&7E8J}>ui1-;TM}w;aU;3z>tTl<-A#wFsEJ!*)KrsD_y~qC!6+2} zkEjs;OWHpFS;L?g8UroHp4CtHfCqqcdjQnvhc4y}(-$6qzGfFwDY2m%9eN@40OX-h zN+O3;l+wPa!*hE|y061?OaHg_|JJ4vhdZSGUoPTLX#gJl|8Ls=TbsyXDkF|wH5*!+ zn#=!R@G5nv@z0C+QyPE=|NpsH?E!MiBek`fgUd?U4+vtrITu?j*~FD<-12`#=`w)@ ztJP+A{oyVHry!CPre)a&NhcF#HiU|!v*tdgbHA*BTlEcwy(g11gluSS-^$P>8w60WYaeR!wE$=vB7M8vM8QH4O*Y~J7KEt`j& zu&>lmln*uMQm$acm$ z^3@3qUAy)I!fM=|lgewU9{W+FH#;BMK-ubH_Rd0g{LW|aJ4bXZ|DRICpV9z4`0o#z z51bXXz(N|+FqHuwQrbRjby!=QZkEP3ESvuv@Ln$^{b*|zJ=B{1?$(^pa0$4_&D|fA z+E@$RKW@8U-TnKORs$_{WjzV5tY=e2Rsr2ZpY_+h`^BCTMvs!-e?8`9+kfY}6W*LV z{y5J3$Ndi6X}Npsrg^0LPLIJs)e#)&9n;_!Q+B5XtaWea*arWx#~b}(PBbudA1ajf z=xjvpgGcw(&i$xO@5%}kv&kM!?P=B1{Pxf!Hg zd$MF^axTe9ojWgWUT$huZrjaMW@OJLv(jc}6W{x{UywXEEjcS!`>B?g)0Bkx_SHT+ zI(CvaCNXi+glFPopYa^=?yJpAo|mhgn>sHwcbJx9CX9}oFg<#D)a};RRu{J9%!SE| z=RLb1Wp3)sakJ;-E=`voJX$RXb~L_8e{YtXY{kDcN&!W~R=VKUW)oRgZClAQ%p1973xDe#|8wCC|2 zIiIK(iZJ*tfZY9Ah4-Q&#t>h;_riX9MUVUYInoR7ecbzb@^lbK@DuRTkg?cL?^k&o zohS)<1zz+!(S1*UO-RA#bkBo*XR*)!iwFC}caP@ZcJkj_#GldtJowXginJ2)a$B3w z&vYA&eQ*88zW1^3_y5>;6Z?jrB4iG_O)SRVvkS&&=T3TgX6mAxBYeDk-%v|grFf%n{z=A0E`Kehca~J32re$Z*D+ocCgw&d!o3@aDwu7ILehzZwUYV# z216dN;O>7Y;48%@3&20xR|b5?kSmDlNWoTwjlMi%aNwoCe*PMtzrfb*KhAsqD~2@H zGlZW148G^X=gq|DIsaftGPaA@wqv8O|H<=T``BZqTVd!oXJ$sfnb}#hGgGI``tM)c7ftm)J+5*7?(;D* z%@{df(q@Z)X-%9HDT-E;fdv8ekqHo%?OW)j!`thC0mdROX zYaUP2&Hh!9zI^ZOBXh53jTm-w!n?0e@}BsHNxErw-O`?2&)Q!Ud&naS?Emm*wZq?6 z#GldtJox{|t=!G_KWV$E&i!HQH+|FiT-nkk#Q}Drw_X3^n)%JHSMGlQ+@(5MuhJ6l zF^_foP-X|K0sCHx*OBg4kzb5~H;V<6>g95clGznE1)`10f%GKhAk>5;pY4nV+;rzSA-f zKZV})(R#JR-%rG!(f~a8U!{EluZ?>7!oJDge;l5uDC&B0j{L0~={bYnO{w3$VdmE8 z{EOc29J;i)NBuc_eqHsyBFBEDIQnYYKji%mT`A~ZVVSAZ%FTn1H%WSxU;2KFv41_%)}r zS;POPNgMlfOwzfzFVBA4_OoQfs9Nsnd&|A5GY%@>ZQgNkaAx6t<2O}DE*frs^1)A; z=cDIO`#%0_uWv3*ebTo31ASfCF!J3*^TcmYbxyWc9K7+NF7)Jq=ZZEQ{@Ul=qldO0 zV#E1->Gb_|>d$-CtIGcQYW4u%v8E}zyC)xiv=IO6uW5(BzlcAj0eJ9#vfr$aEHRfB z$X>q4e4?!`?4vpN=gQ?}FZVq7k?h@{EB-yO_R!V0tK^FY-6lS7?oezDEcE{2h*$dS z{hpk||0{E50W&S-*BcWvGG-)a2A|ibE+0>3T>E{4Ec5U0GTn~f;Fmmq(&y&qb)~6^ z^&k5+96Gl8)%^0i-*>+}V|2d@ovy!H^G52}+B;K{_mBH(;=y6LW|dMy!-u_ zZ#SHOa?VNHJ9ln;Qh1hL zP1l$nEhl7YFFik_>CEg@^UIHCcD*9Y$Xd{?w#6P5|9R}q z*kd1eIrnC1($($XeDjZWwrwX*oF6jj+V>Njvya$jKmW;lmt_Y>KK=OqgbR^g=f`$a z?z=Tc@_5oKT+F9`CVl_x_p^8W`DRws;$vyT8wZll1TCHQNlA5f@5g^MP1>+f{iS4- z>PUHKHe^7U^x0#>4}TV}I=X-D3m-;u=?A90-}>!|sIRRDS8uKB`)DEl*I&~P|4t(Q zlm_6zzx&?rUMxK^b5q#0l;1XQPoJ+`HwQ&J6`Mys?%lY2wtTMt^F+F2OvQ$PR}THS zH?r*SL%MyW-t=bmTCZd0e);&%ORws_zo@FMu32IHvDWE2aM_f#^g_?GosZ?c7*>Ak zhlQot3rBq%`0ERNeonei>*?XLS<_UEZ|m07x6<~`aMiSCB*%Z9*?G~A%91~-y}o^B zDL4Ma0m;zhu-Wf7bxyL58>644UXaGpP0P&lbxS!J@Vb_ zU+*7P-+E9VeC_DbRVNOg)~`D-`MvEQ_L4qsJ-kl#?b(Ruzk8-)c3o)yS7seJG$#2Z z+s*XS`pE1)PaIQyxb02#r`^7nzVO!;d$c~a!@skLKcxY9@L%&M+mHV0B&b5zO(vIN zEr)g3oKl7?-p`N?vkCb(-aGd(1hoO&+i;xoE#7~RZ7Gf?Vi7^FtvD!N`zQ9(>$-o$ zkXGEI2phe&-vNfak8?cNdbBTU2B6o^K{Vz8*b?Z=vu|ECAxEmjeUz+4&wCyFj-CEhCG2S;v7R> z!sq94{Apaj5C4mBO&;EF$FU=LPhXyAO#YT3pW*yD`2Qld|Lz&{&jWC5jo2Q3#$sIO zc}8*_L%zoS%nOdKp0tL{Z`xJACi~r2=8SMZ_0j#)4*x(Ae@X-J;7`XXhvvsFvhQn# z`~*A9&0A>G|DRv~=cus%?F+d8+^_%h=ls8Whj#dP74fGu01y72cHrpip`X&fzkX42 z=Ir?k=FiPE%}Gw_2g~W))LhZuV}$$c>D0x!rnI>;6O-rWE>28dJO{oWTu=QkiF32D zBF~+_ASPwj?Bw~mrmVTKvu4jo%Z|^Qo1K}Nl9`5c6VtNXz9V|CdGi+-JxAf;8JCuo zIC}ip)U4ULCfI48T@ZtNJd>S4?YXHlacx?1CiU?o&P`pAmb!5MywthRrOr*8m6noB zjlB;Y%E}&>GAcPSbuLW3^KfY1^J%%JSkLo?(TS5E`pJ*n+jjWFZ$jlir2%;G?-x7n zxx{|a@TVnC7T*ti=zVm*#Du92eI7_Zdt7hR6DP$#8!b$KE;=VUB_nla)~uBI^JZkt zBs0_I!9}!qJX}H4ZJ3#s(hoM60q*wo$oQ#Wv*Zl6gHj1eSNuBr`X^QVk=c8fFFXDI z@DW+p=eDeOMZP=X=CJAAA9qglp7i>jUzgZ6NlkA=K9$+C=hC{}cVdoayl6k$)&C#5 z#eQ3+tGaXx=<($1YdSsu#K?fWZ|8P>wQ&IVj`^M&qogQhkj5y{JV+xQyPE=f7%A(=0kq3xfxs?xQ=Wbe5HH*(d*sE ziPQ2!chr!Oz2V;$4p?P8oBC&HLEIBB4;Vh~x3BM19{l9u%Di_k9;_d7FyZ=(C!QPH z)hhkS>Fb=jX+qb1?<^U)HZX6_g>!!k-fd(h+Y5Ke&mYUqiDzD1>i5R}pT{3t9@Xo| z4_nWD`kMOL?3I7NmiyANxn&zW4{s^^&OF%fi{9_cE^S&LmiBe7bJOwaG0v^W(>DG5 zQ|}2wR*X9K=fQJttp0q% zIN5jUh5XwKc7H$Xk4Y1sD%3=O*l*6~Q9B;`agW^FcK8R2_){8y2mg_}JB6nnla&7K z{pYbSUY}ZV;;kJ|URT*a@BO}V-Kc{1&t)%>*e9l(mgQu5D`!VU1l%1^Ei6}l{8(63 z*t8+KZvB7nbMl3|bNY_^{=kMU{$4{Sf0wdv^)vI7sXO*B9C1XMzTnrrzmMu)bs}&0 z;3Wae`_5fEQ{o)E?P|r_jNbUk)3bth6#UC&%~}2Q3H`BWWZNfZei1n7&u_Y3U2D_q zOntVOtmvCQ+LxbSKG^%lA={DYoRW0SDQoqi&d1;BI(c`@L_YJ09z~6Bem{0$!ecuU zHvMq$lhQ#cFI0VYKpi~v%&M55#_T#je%?3ZRpG(p8evD@E$3l&8^2Q^+%U{*O;03 zPN&76?{C_E`&i`Uxj$W7^z!GMlfxRmdg`&$@)MQ1FAlA+^=P!8{pPg`4U249f4n~7 zwVQ{tyUg7++aY_e@YLI%y_TZf>vj7WS2)tQ+o)jw!K#ALuCw=FI2Wrxk6DZ^^o{o7s-sxDU zDZ;?mX29EUg=n+<5}s~!G5 zMf~B;y^sI>CYb>pZhp@FCSgM3XRq9S_Rp3}hYJ@x6RmOlQ2lA%(iIi?%Pa*))-o*h zA-G=@47@16$D=NI-rs9!y~}`Xb`=xOA#4Moe~!eKh;>LWY%tn}Us~03+St;dmSldHb> zieIuw{^dV^iAZ;xyO})giNn){<+gIxO2U&-;o6+^Ck@MQZjz9Aa5cgs{PsONd8Eu`rxjo zZb+W;`?TxC!~Wy8yf{*C9Tk50@9({I?V54+hM1~_mxizVb2i^At5e{{i(lK{JNVoo{Hl(SN6^L;iSW?f6*Q=aQZv1Ed02~Pw_8(_50uVJr^{fEWen^ ziu_;Y+j}%rc>ut1@(N=l&xZA86T?`qr6h(*UT0=dnYEPHs7&OQ%`>S{>y^f2jnXiR zj6z-+qD;tmOx~hlFt*tklcbHwy6gC>(;xk_=WOmd_pf{Z`JM0moqK=xer}#mGQaD1 z;CA6@hm#VzahwTe0v0beonH+pOOr2JR141}`hTbC{~gvB{WUiF1D||1`|~nG_v2h| z=$}Z5g0!DVn7NfLtz+#^QB5tC0;SjKOlk>aW5kCHo&0oK=~8`XQ-Xucz%n;)dD!$* zsmE*asIurw;R%!A=1l!av#FPc5t+#mm=?5Jqo#jvETML`Blt@53R=XMT02ZV=M>NK zoY$fYg=QyBYe$&Oi;wn6z`>;~@782LH)P!b9pxfBceB7D!lA3tuZy|c7f5dG}<+hI;-JKd%X~ja=XVi4{7Iud$?&X zVXRE=wJ$j_L*B3{oGq(AFO#yWJtxGNPou5X<;HWYkeWLbudW{1QvEeI`U4DLv%e(= zo*`+yNTWhsGm;cadq3qi@8#vM#n@hGSZh6cZ6JR_N{QUXxP}yidy?lw(i4t~DZR**p0)U3vWh5SE}rMbU4MuZs*A2Sv%I0{NQ(TFN@IsRImT-_^qA^~s_>ft$D{%SQTpQH}$@l81 z9A~=_LvBm;uuDWx8V^g7j1(=8^;~%#IbL*^Zp3oBv_Ega{0#~sb27gB#hpdJg?@N@ z*67ZAQVTQDPoj(y;KT?1;5dX>PXlJ)RXq&zn6v^hDt_9^j!mqQ=bp-$-ctRwHu?h$ zV6#7!)0V}qsT@@1goHVvKkj0{f7jmgtML(E{+NQKwSJpWA76feS!?(HZ^`LBZrRYq zRP!LorDE8lCb?wS=U4*u-ER!u_^hhinGcrxEI62JlbD3d6}_l;ErAHRjF}69#pC!0 zSeBjVl$TV69r^H&%8nj;!go{!6cZ1&I757pKOEPyx#?DS8hv(l@{-SOTW)+)>Yc}l zIsF1V4NSO7YU`wX$=x-!xpSu86l^=G2(hB+*gL$1W$oH;m?@wb-=X)gM$7-a43-UT z!b2X(bwG8KYY@VXr=k!QXB$#XeJCC=oq?GuZf;_(_3f}hwW z)n9v~KfnMs`&abJkt9R{7!k~J?fqjj6W#GVyr;e9$S8626bC#AWmHns@>W2sEZA^i z=S0-w$c~tD?A4TZ9Qhp?V|?VwdotnAoQ1=22e>UC3}n&IP9unF{Fqi$mbCCBJZK?b z4F?uQfJ>0)C==p2611NSvFzH==-fCF%1`$@!#wR-YaCE6-NJicWD|3M^m&4g>BZN? z4!MkWS*YSfQ63FNG#t-98f3B{Yq~8ciJJOLvsPL4b(ufrHMJTNjV%hy6+mL!UN`nH zvZRO4n?1D>hkz;RI1poDM%1^4ge0esi2jz>yYa!ZquDXeg;tI^^x2Vcjy)oeVTx7# zt``7b-2Zhp`U4DLv%lX{vM{`eG@@Ts9S6$c8<;e@TgXepC2rEupa_SO5jAy$=VvA1 zRgKi~zsv<#rj}?y3sj*HGo#C`N8!E!Z;}lilVgVULgm{E`Sp#b;Z2475TpLRMhM*(97I5EI_0bU6(M}Qjw><{2q0D}TJ62O80o&hik zfGYrO!20{muWnmv{`;=~iLt&&0~o+&e@`crF|cj}_G#e4_{PnFtQ5>m7*=uw1r^gT zdR6Rh(^yt<-0fgvYxR*aH8V~rXmc4Jb#=a|P+R_-;TTZ)*`>Tu2>JwX-O?r-hZXv2 RnE&X&HxBoIbviKr{{eO?xl;fD delta 41113 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 diff --git a/firmware/boards/nrf52840-mdk-dongle/memory.x b/firmware/boards/nrf52840-mdk-dongle/memory.x index b7d6a13..5c12350 100644 --- a/firmware/boards/nrf52840-mdk-dongle/memory.x +++ b/firmware/boards/nrf52840-mdk-dongle/memory.x @@ -6,16 +6,32 @@ * 0x96000..0x97000 its signature slot, which the bootloader fork checks on every * boot (bootloader/src/signature.h) * 0x97000..0xD8000 the vault (VAULT_BASE in main.rs) - * 0xD8000..0xEC000 Trussed's filesystem, not used yet + * 0xD8000..0xEC000 Trussed's filesystem, the passkeys (FS_LEN in main.rs) * 0xEC000..0xF4000 free * 0xF4000..0x100000 the UF2 bootloader, its CF2 page, MBR parameters and settings * * The bootloader writes only 0x01000..0x97000 (BOARD_APP_FLASH_END in bootloader/board), - * so a firmware update cannot reach the vault. RAM starts 8 bytes in, the way Nordic's - * own images on the MBR are linked: the MBR keeps its forwarding address there. + * so a firmware update cannot reach the vault or the passkeys. RAM starts 8 bytes in, + * the way Nordic's own images on the MBR are linked: the MBR keeps its forwarding + * address there. + * + * The stack comes first in RAM and the statics after it. A stack that overflows runs off + * the bottom of RAM into unmapped addresses, and the fault it takes there cannot even be + * stacked: the core locks up and the chip resets, which `vkey info` reports as "lockup". + * Placed the usual way, at the top, it would run down into the vault's index and the + * working buffer without a sound. Statics that outgrow RAM fail the link. + * + * Nearly all of RAM is stack, because the two deepest things the key does take turns in + * it: a key derivation holds Argon2's 128 KiB there (about 166 KiB deep in all), and a + * passkey request goes through fido-authenticator and Trussed (at most about 154 KiB, + * counted over the call graph of the image). The statics, ~46 KiB, get 56 KiB. */ MEMORY { FLASH : ORIGIN = 0x00001000, LENGTH = 0x95000 - RAM : ORIGIN = 0x20000008, LENGTH = 0x3FFF8 + STACK : ORIGIN = 0x20000008, LENGTH = 0x31FF8 + RAM : ORIGIN = 0x20032000, LENGTH = 0x0E000 } + +_stack_start = ORIGIN(STACK) + LENGTH(STACK); +_stack_end = ORIGIN(STACK); diff --git a/firmware/boards/nrf52840-mdk-dongle/src/fido.rs b/firmware/boards/nrf52840-mdk-dongle/src/fido.rs new file mode 100644 index 0000000..c8f1d21 --- /dev/null +++ b/firmware/boards/nrf52840-mdk-dongle/src/fido.rs @@ -0,0 +1,393 @@ +//! Passkeys: Trussed and fido-authenticator (docs2/roadmap.md, phase 6), in the main loop +//! like everything else. A CTAP request reaches `Passkeys::call` through the CTAPHID +//! dispatch, fido-authenticator turns it into Trussed requests, and `Syscall` serves each +//! of those on the spot by running the Trussed service inline: no interrupt, no runtime, +//! no second context. +//! +//! The keys live in Trussed's own littlefs at 0xD8000..0xEC000, apart from the vault and +//! not sealed under the PIN; docs/threat-model.md says what that costs. + +use core::cell::RefCell; +use core::sync::atomic::{AtomicBool, Ordering}; +use core::time::Duration; + +use cortex_m::peripheral::SCB; +use ctaphid_dispatch::app::{self, App, Command}; +use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; +use fido_authenticator::{Authenticator, Config, TrussedRequirements, UserPresence}; +use heapless_bytes::BytesView; +use littlefs2::consts::{U1, U256, U512}; +use littlefs2::driver::Storage; +use littlefs2::fs::{Allocation, Filesystem}; +use littlefs2::object_safe::DynFilesystem; +use littlefs2::{const_ram_storage, io, path}; +use static_cell::{ConstStaticCell, StaticCell}; +use trussed::backend::BackendId; +use trussed::pipe::{ServiceEndpoint, TrussedChannel}; +use trussed::serde_extensions::{ExtensionDispatch, ExtensionId, ExtensionImpl}; +use trussed::service::ServiceResources; +use trussed::types::{Context, CoreContext}; +use trussed::{ClientImplementation, Platform, Service}; +use trussed_core::Error; +use trussed_core::api::{reply, request}; +use trussed_core::types::reboot; +use trussed_fs_info::FsInfoExtension; +use trussed_hkdf::HkdfExtension; +use trussed_staging::{StagingBackend, StagingContext}; +use vaultkey_core::hal::Clock; +use vaultkey_core::ui; + +use crate::{CTAP_MESSAGE, Entropy, FS_LEN, Panel, Region, Uptime, UsbStack}; + +/// authenticatorReset, the CTAP2 command that erases every passkey. +const AUTHENTICATOR_RESET: u8 = 0x07; + +/// How long the hold that approves authenticatorReset lasts: the same five seconds as +/// the vault's wipe, because it is one. +const RESET_HOLD_MS: u64 = 5_000; + +/// Trussed's flash: the 4 KiB sectors of `FS_LEN`, read and written in words. +struct Internal(Region); + +impl Storage for Internal { + const READ_SIZE: usize = 4; + const WRITE_SIZE: usize = 4; + const BLOCK_SIZE: usize = 4096; + const BLOCK_COUNT: usize = FS_LEN as usize / 4096; + /// A metadata block moves on after this many erases, so the files rewritten on every + /// login - the signature counter, the RNG seed - do not wear one sector out. + const BLOCK_CYCLES: isize = 500; + /// Files up to this size sit in their directory's metadata instead of a 4 KiB block + /// each: what lets a few dozen passkeys share 80 KiB. + type CACHE_SIZE = U512; + /// 8 bytes, a bit per block for 64 blocks: more than there are. + type LOOKAHEAD_SIZE = U1; + + fn read(&mut self, off: usize, buf: &mut [u8]) -> io::Result { + let off = u32::try_from(off).map_err(|_| io::Error::IO)?; + self.0.read(off, buf).map_err(|_| io::Error::IO)?; + Ok(buf.len()) + } + + fn write(&mut self, off: usize, data: &[u8]) -> io::Result { + let off = u32::try_from(off).map_err(|_| io::Error::IO)?; + self.0.write(off, data).map_err(|_| io::Error::IO)?; + Ok(data.len()) + } + + fn erase(&mut self, off: usize, len: usize) -> io::Result { + let from = u32::try_from(off).map_err(|_| io::Error::IO)?; + let to = u32::try_from(off + len).map_err(|_| io::Error::IO)?; + self.0.erase(from, to).map_err(|_| io::Error::IO)?; + Ok(len) + } +} + +// What Trussed keeps only until the next reset - key agreement keys, public keys on +// their way out - in 4 KiB of RAM. littlefs makes no assumption about erased bytes, and +// zero keeps it out of the image. +const_ram_storage!( + name = Volatile, + erase_value = 0x00, + read_size = 4, + write_size = 4, + cache_size_ty = U256, + block_size = 256, + block_count = 16, + lookahead_size_ty = U1, +); + +static INTERNAL: StaticCell = StaticCell::new(); +static INTERNAL_ALLOC: StaticCell> = StaticCell::new(); +static INTERNAL_FS: StaticCell> = StaticCell::new(); +static VOLATILE: ConstStaticCell = ConstStaticCell::new(Volatile::new()); +static VOLATILE_ALLOC: StaticCell> = StaticCell::new(); +static VOLATILE_FS: StaticCell> = StaticCell::new(); + +/// The filesystems Trussed asks for by location. +#[derive(Clone, Copy)] +struct Store { + internal: &'static Filesystem<'static, Internal>, + volatile: &'static Filesystem<'static, Volatile>, +} + +impl trussed::store::Store for Store { + fn ifs(&self) -> &dyn DynFilesystem { + self.internal + } + + // There is no external flash on this board. Nothing here asks for it, and whatever + // would is kept like the rest rather than lost at the next reset. + fn efs(&self) -> &dyn DynFilesystem { + self.internal + } + + fn vfs(&self) -> &dyn DynFilesystem { + self.volatile + } +} + +/// What Trussed needs from the board: the chip's RNG, the filesystems and a clock. +struct Board { + rng: Entropy, + store: Store, + ui: Clockwork, +} + +impl Platform for Board { + type R = Entropy; + type S = Store; + type UI = Clockwork; + + fn rng(&mut self) -> &mut Entropy { + &mut self.rng + } + + fn store(&self) -> Store { + self.store + } + + fn user_interface(&mut self) -> &mut Clockwork { + &mut self.ui + } +} + +/// Trussed's user interface, reduced to the clock and the reset. User presence does not +/// go through Trussed: fido-authenticator asks `Touch`, which keeps the vault's rules. +struct Clockwork; + +impl trussed::platform::UserInterface for Clockwork { + fn uptime(&mut self) -> Duration { + Duration::from_millis(Uptime.now_ms()) + } + + fn reboot(&mut self, _: reboot::To) -> ! { + SCB::sys_reset() + } +} + +/// The custom backend: trussed-staging, for the two extensions fido-authenticator asks +/// for on top of Trussed's core. +enum Backend { + Staging, +} + +/// Those two extensions, numbered for the trip from client to service. +enum Extension { + FsInfo, + Hkdf, +} + +impl From for u8 { + fn from(extension: Extension) -> u8 { + match extension { + Extension::FsInfo => 0, + Extension::Hkdf => 1, + } + } +} + +impl TryFrom for Extension { + type Error = Error; + + fn try_from(id: u8) -> Result { + match id { + 0 => Ok(Extension::FsInfo), + 1 => Ok(Extension::Hkdf), + _ => Err(Error::FunctionNotSupported), + } + } +} + +#[derive(Default)] +struct Extensions { + staging: StagingBackend, +} + +impl ExtensionId for Extensions { + type Id = Extension; + const ID: Extension = Extension::FsInfo; +} + +impl ExtensionId for Extensions { + type Id = Extension; + const ID: Extension = Extension::Hkdf; +} + +impl ExtensionDispatch for Extensions { + type BackendId = Backend; + type Context = StagingContext; + type ExtensionId = Extension; + + // Never inlined, like everything on the way to a Trussed request: inlined, its + // buffers join the frame of the service loop, which every request pays for. + #[inline(never)] + fn extension_request( + &mut self, + _: &Backend, + extension: &Extension, + ctx: &mut Context, + request: &request::SerdeExtension, + resources: &mut ServiceResources

l^7@dt#u) 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�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�hJf%-Yr+b^lt6>xnP_crvh4X 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 delta 55976 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 BYE|gMMM`BZ3+l@ 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

!&9M$E)L?j1!Ueq(u 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 CB#;jP diff --git a/firmware/boards/nrf52840-mdk-dongle/src/fido.rs b/firmware/boards/nrf52840-mdk-dongle/src/fido.rs index c8f1d21..c693127 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/fido.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/fido.rs @@ -28,14 +28,14 @@ use trussed::serde_extensions::{ExtensionDispatch, ExtensionId, ExtensionImpl}; use trussed::service::ServiceResources; use trussed::types::{Context, CoreContext}; use trussed::{ClientImplementation, Platform, Service}; -use trussed_core::Error; use trussed_core::api::{reply, request}; use trussed_core::types::reboot; +use trussed_core::{Error, InterruptFlag}; use trussed_fs_info::FsInfoExtension; use trussed_hkdf::HkdfExtension; use trussed_staging::{StagingBackend, StagingContext}; -use vaultkey_core::hal::Clock; -use vaultkey_core::ui; +use vaultkey_core::hal::{Clock, Ui}; +use vaultkey_core::ui::{self, State}; use crate::{CTAP_MESSAGE, Entropy, FS_LEN, Panel, Region, Uptime, UsbStack}; @@ -272,10 +272,14 @@ type Client = ClientImplementation<'static, Syscall, Extensions>; /// Set while the request being served is authenticatorReset. static RESET: AtomicBool = AtomicBool::new(false); +/// Raised by the CTAPHID pipe when the host cancels the request being served; the +/// dispatch sets it working before each call and idle after. +static CANCEL: InterruptFlag = InterruptFlag::new(); + /// User presence is the vault's own gesture on the same button and light: a fresh tap /// while the light is amber, through `vaultkey_core::ui`, so a button already held when /// the request arrives does not count. Erasing every passkey takes the wipe's hold -/// instead, because a tap never wipes. +/// instead, because a tap never wipes. A request the host cancels ends the wait refused. #[derive(Clone, Copy)] struct Touch { panel: Panel, @@ -288,7 +292,7 @@ impl UserPresence for Touch { _: &mut T, timeout_ms: u32, ) -> fido_authenticator::Result<()> { - let mut panel = self.panel; + let mut panel = Cancellable(self.panel); let timeout_ms = u64::from(timeout_ms); self.usb.borrow_mut().awaiting_touch = true; let confirmed = if RESET.load(Ordering::Relaxed) { @@ -299,12 +303,32 @@ impl UserPresence for Touch { self.usb.borrow_mut().awaiting_touch = false; if confirmed { Ok(()) + } else if CANCEL.is_interrupted() { + Err(fido_authenticator::Error::KeepaliveCancel) } else { Err(fido_authenticator::Error::UserActionTimeout) } } } +/// The panel as a passkey's wait sees it: the same button and light, and a request the +/// host can withdraw. +struct Cancellable(Panel); + +impl Ui for Cancellable { + fn set(&mut self, state: State) { + self.0.set(state); + } + + fn pressed(&self) -> bool { + self.0.pressed() + } + + fn withdrawn(&self) -> bool { + CANCEL.is_interrupted() + } +} + /// fido-authenticator as the CTAPHID dispatch sees it: CTAP2 only. U2F's MSG is not /// taken - it polls for presence every 250 ms, which a tap that must start after the /// request cannot answer - so the dispatch refuses it as an unknown command. @@ -315,6 +339,10 @@ impl App<'static> for Passkeys { &[Command::Cbor] } + fn interrupt(&self) -> Option<&'static InterruptFlag> { + Some(&CANCEL) + } + fn call( &mut self, command: Command, diff --git a/firmware/boards/nrf52840-mdk-dongle/src/main.rs b/firmware/boards/nrf52840-mdk-dongle/src/main.rs index 5569586..139da4d 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/main.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/main.rs @@ -29,7 +29,9 @@ use nrf52840_hal::nvmc::{Nvmc, NvmcError}; use nrf52840_hal::pac; use nrf52840_hal::rng::Rng; use nrf52840_hal::usbd::{UsbPeripheral, Usbd}; +use ref_swap::OptionRefSwap; use static_cell::{ConstStaticCell, StaticCell}; +use trussed_core::InterruptFlag; use usb_device::UsbError; use usb_device::bus::UsbBusAllocator; use usb_device::device::{StringDescriptors, UsbDevice, UsbDeviceBuilder, UsbVidPid}; @@ -197,6 +199,10 @@ const CTAP_MESSAGE: usize = 3072; /// way. static CTAP_CHANNEL: Channel = Channel::new(); +/// Where the pipe finds the flag of the request being served, to raise it when the host +/// sends `CTAPHID_CANCEL`: the dispatch puts the app's flag here for the length of a call. +static CTAP_CANCEL: OptionRefSwap<'static, InterruptFlag> = OptionRefSwap::new(None); + /// The protocol's side of the stack, and FIDO's: requests that come through CTAPHID are /// answered while vkey's line is quiet. struct Usb { @@ -620,7 +626,7 @@ fn main() -> ! { .split() .expect("the CTAPHID channel is split once, here"); // CBOR announced in INIT, or hosts never send CTAP2. - let ctaphid = CtapHid::new(bus, requester, 0).implements_ctap2(); + let ctaphid = CtapHid::with_interrupt(bus, requester, Some(&CTAP_CANCEL), 0).implements_ctap2(); let usb = UsbDeviceBuilder::new(bus, UsbVidPid(USB_VID, USB_PID)) .strings(&[StringDescriptors::default() .manufacturer("vaulttecdev") @@ -677,7 +683,7 @@ fn main() -> ! { let port = Usb { stack: usb, - fido: Dispatch::new(responder), + fido: Dispatch::with_interrupt(responder, Some(&CTAP_CANCEL)), passkeys: fido::start(passkeys, rng, panel, usb), last_rx: 0, }; diff --git a/firmware/core/Cargo.toml b/firmware/core/Cargo.toml index 1392f69..4812068 100644 --- a/firmware/core/Cargo.toml +++ b/firmware/core/Cargo.toml @@ -26,9 +26,5 @@ hmac = { version = "0.13", default-features = false, features = ["zeroize"] } sha1 = { version = "0.11", default-features = false, features = ["zeroize"] } sha2 = { version = "0.11", default-features = false, features = ["zeroize"] } subtle = { version = "2.6", default-features = false } -# `vkey auth`: a login is an Ed25519 signature, so the host keeps a public key and no -# secret. Built on RustCrypto's `signature` and `sha2`; no precomputed tables, which -# would cost flash for a speed a tap does not need. -ed25519-dalek = { version = "2.2", default-features = false, features = ["zeroize"] } zeroize = { version = "1.9", default-features = false } crc = "3.4" diff --git a/firmware/core/src/device.rs b/firmware/core/src/device.rs index 29f8e5a..2f12db5 100644 --- a/firmware/core/src/device.rs +++ b/firmware/core/src/device.rs @@ -6,32 +6,25 @@ //! that a backup needs - a whole secret leaving the key is one act with one gesture. //! Categories are labels; classes are the boundary. -use ed25519_dalek::{Signer, SigningKey}; use embedded_storage::nor_flash::NorFlash; use rand_core::{CryptoRng, RngCore}; use zeroize::{Zeroize, Zeroizing}; use crate::hal::{Clock, DeviceKey, Ui}; use crate::item::{Category, Class, Item, Writer}; -use crate::oath::{self, AUTH_SECRET_LEN, NAME_MAX, Name, Params, len_u8}; +use crate::oath::{self, NAME_MAX, Name, Params, len_u8}; use crate::store::{Header, ITEM_BUF_LEN, Index, MAX_ATTEMPTS, Slot, Store, StoredName}; use crate::ui; use crate::vault::{ self, BACKUP_AAD, Block, Cost, KDF_BLOCKS, KEY_LEN, Keys, NONCE_LEN, Passphrase, Pin, SALT_LEN, }; -use crate::wire::{ - AUTH_CHALLENGE_LEN, AUTH_SIGNATURE_LEN, AUTH_SIGNED_PREFIX, BackupHead, Fail, HAS_OPEN, - HAS_SECRET, HAS_SEED, PinStatus, -}; +use crate::wire::{BackupHead, Fail, HAS_OPEN, HAS_SECRET, HAS_SEED, PinStatus}; /// Unlocked and idle this long, the device forgets the key on its own. Two minutes: /// long enough to finish a login, short enough that a key left on the desk is a /// locked key. const AUTOLOCK_MS: u64 = 120_000; const TOUCH_TIMEOUT_MS: u64 = 30_000; -/// A login waits for the tap this long and no longer: the password prompt behind it is -/// the other way in, and nobody should wait half a minute to reach it. -const AUTH_TOUCH_TIMEOUT_MS: u64 = 10_000; /// A wipe after five seconds of red: no reflex reaches it. const WIPE_HOLD_MS: u64 = 5_000; @@ -317,8 +310,6 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> /// Verifies the old PIN, re-seals every item under the new one, writes all of it as /// a single image. A host that found the device unlocked still cannot take it over. - /// Auth items are sealed under the chip key, not the PIN: they are carried across - /// untouched. pub fn pin_change(&mut self, old: Pin<'_>, new: Pin<'_>) -> Result<(), Fail> { self.pin_unlock(old)?; // loads the index too let old_dek = self.dek()?; @@ -348,14 +339,6 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> .map_err(|_| Fail::Internal)?; for i in 0..self.index.len() { let slot = *self.index.get(i).ok_or(Fail::Internal)?; - // An auth item's key does not change with the PIN. - if slot.category == Category::Auth.wire() { - let (_, carry) = self.buf.split_at_mut(ITEM_BUF_LEN); - self.store - .save_keep(&slot, carry) - .map_err(|_| Fail::Internal)?; - continue; - } let n = { let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); self.store @@ -419,15 +402,6 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> vault::open_in_place(key, aad, buf) } - /// The key an item of this category is sealed under: the chip key alone for an auth - /// secret, the PIN's for everything else. The one place that decides. - fn item_key(&mut self, dek: &[u8; KEY_LEN], category: u8) -> Result { - if category == Category::Auth.wire() { - return vault::auth_key(&mut self.key).ok_or(Fail::Incompatible); - } - Ok(Zeroizing::new(*dek)) - } - /// Stores an item. The PIN is enough, like every write: nothing comes out. pub fn put( &mut self, @@ -453,8 +427,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> { return Err(Fail::Full); } - let key = self.item_key(&dek, category.wire())?; - let r = self.write_item(&key, name, category.wire(), plain, at); + let r = self.write_item(&dek, name, category.wire(), plain, at); self.buf.zeroize(); r?; self.touch(); @@ -535,15 +508,11 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> } /// The item called `name`, opened into the working half of the buffer: how many - /// plaintext bytes, sitting at `NONCE_LEN`. Never an auth item, which only - /// `respond` opens. + /// plaintext bytes, sitting at `NONCE_LEN`. fn open_named(&mut self, dek: &[u8; KEY_LEN], name: Name<'_>) -> Result<(usize, u8), Fail> { self.load()?; let i = self.index.find(name).ok_or(Fail::NotFound)?; let slot = *self.index.get(i).ok_or(Fail::Internal)?; - if slot.category == Category::Auth.wire() { - return Err(Fail::BadArg); - } let n = { let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); self.store @@ -648,73 +617,6 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> Ok((len, params.period.get())) } - /// The host's challenge signed with the auth item called `name`, after a tap - the - /// same gesture as a code. The one command that needs no PIN: the secret is sealed - /// under the chip key, it never comes out, and a login is proven by the finger on - /// this board. Leaves the PIN session as it was, and spends no attempt. - pub fn respond( - &mut self, - name: Name<'_>, - challenge: &[u8; AUTH_CHALLENGE_LEN], - out: &mut [u8; AUTH_SIGNATURE_LEN], - ) -> Result<(), Fail> { - self.load()?; - // Any other category reads as absent: without the PIN, which names exist is - // nobody's to learn, and a different answer for "exists, but not auth" would - // tell. - let i = self - .index - .find(name) - .filter(|&i| { - self.index - .get(i) - .is_some_and(|s| s.category == Category::Auth.wire()) - }) - .ok_or(Fail::NotFound)?; - let slot = *self.index.get(i).ok_or(Fail::Internal)?; - let key = vault::auth_key(&mut self.key).ok_or(Fail::Incompatible)?; - let r = self.sign_with(&key, &slot, name, challenge, out); - self.buf.zeroize(); - r - } - - fn sign_with( - &mut self, - key: &[u8; KEY_LEN], - slot: &Slot, - name: Name<'_>, - challenge: &[u8; AUTH_CHALLENGE_LEN], - out: &mut [u8; AUTH_SIGNATURE_LEN], - ) -> Result<(), Fail> { - let n = { - let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); - self.store - .read_item(slot, work) - .map_err(|_| Fail::Internal)? - }; - let opened = { - let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); - Self::open_in(key, name, slot.category, &mut work[..n]).ok_or(Fail::Internal)? - }; - if !ui::await_confirmation(&mut self.ui, &self.clock, AUTH_TOUCH_TIMEOUT_MS) { - return Err(Fail::Refused); - } - let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); - let item = Item::parse(&work[NONCE_LEN..NONCE_LEN + opened]).ok_or(Fail::Internal)?; - let seed: &[u8; AUTH_SECRET_LEN] = item - .first(Class::Secret) - .ok_or(Fail::Internal)? - .value() - .try_into() - .map_err(|_| Fail::Internal)?; - let signing = SigningKey::from_bytes(seed); - let mut msg = [0u8; AUTH_SIGNED_PREFIX.len() + AUTH_CHALLENGE_LEN]; - msg[..AUTH_SIGNED_PREFIX.len()].copy_from_slice(AUTH_SIGNED_PREFIX); - msg[AUTH_SIGNED_PREFIX.len()..].copy_from_slice(challenge); - *out = signing.sign(&msg).to_bytes(); - Ok(()) - } - /// An item, gone. pub fn delete(&mut self, name: Name<'_>) -> Result<(), Fail> { self.dek()?; @@ -745,8 +647,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> return Err(Fail::Exists); } let slot = *self.index.get(at).ok_or(Fail::Internal)?; - let key = self.item_key(&dek, slot.category)?; - let r = self.rename_into(&key, &slot, from, to, at); + let r = self.rename_into(&dek, &slot, from, to, at); self.buf.zeroize(); r?; self.touch(); @@ -849,7 +750,6 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> } let slot = *self.index.get(at).ok_or(Fail::Internal)?; let name = StoredName::of(slot.name()); - let item_key = self.item_key(&dek, slot.category)?; let n = { let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); @@ -859,8 +759,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> }; let opened = { let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); - Self::open_in(&item_key, name.get(), slot.category, &mut work[..n]) - .ok_or(Fail::Internal)? + Self::open_in(&dek, name.get(), slot.category, &mut work[..n]).ok_or(Fail::Internal)? }; // The plaintext moves back to make room for the prefix, which goes after the // nonce that `seal_in_place` writes over. @@ -967,19 +866,11 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> body.len(), ) }; - let item_key = self.item_key(dek, category)?; let resealed = { let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); work.copy_within(body_at..body_at + body_len, NONCE_LEN); - Self::seal_in( - &item_key, - &mut self.rng, - name.get(), - category, - work, - body_len, - ) - .ok_or(Fail::Internal)? + Self::seal_in(dek, &mut self.rng, name.get(), category, work, body_len) + .ok_or(Fail::Internal)? }; let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); self.store diff --git a/firmware/core/src/hal.rs b/firmware/core/src/hal.rs index 18f2424..2c92628 100644 --- a/firmware/core/src/hal.rs +++ b/firmware/core/src/hal.rs @@ -26,6 +26,12 @@ pub trait Ui { fn set(&mut self, state: crate::ui::State); /// True while the button is held. fn pressed(&self) -> bool; + /// True once whoever asked for the gesture has withdrawn the request: the wait ends + /// refused, as if its time were up, and never as a press. Only a board serving + /// requests that can be cancelled - passkeys - says anything but no. + fn withdrawn(&self) -> bool { + false + } } /// A secret only this chip has, mixed into the key derivation so that a copy of the diff --git a/firmware/core/src/item.rs b/firmware/core/src/item.rs index 8685b0a..3b5717f 100644 --- a/firmware/core/src/item.rs +++ b/firmware/core/src/item.rs @@ -143,9 +143,8 @@ pub enum Category { CryptoWallet = 115, /// A project's `.env`, which 1Password has no category for. Env = 200, - /// An Ed25519 seed for `vkey auth`. Sealed under the chip key, never the DEK, and - /// the one category whose item the device refuses to hand back at all. - Auth = 201, + // 201 was `vkey auth`'s Ed25519 seed, removed 2026-10-15 (restorable from 4bd49f3). + // Never reused: old backups and an old vault may still hold one. } impl Category { @@ -175,7 +174,6 @@ impl Category { 114 => Some(Self::SshKey), 115 => Some(Self::CryptoWallet), 200 => Some(Self::Env), - 201 => Some(Self::Auth), _ => None, } } diff --git a/firmware/core/src/oath.rs b/firmware/core/src/oath.rs index d03d1d6..7d2c092 100644 --- a/firmware/core/src/oath.rs +++ b/firmware/core/src/oath.rs @@ -15,9 +15,6 @@ use zeroize::Zeroizing; use crate::vault::OVERHEAD; pub const NAME_MAX: usize = 32; -/// An auth secret is an Ed25519 seed, exactly this long: the host draws it, keeps the -/// public key and forgets the seed. -pub const AUTH_SECRET_LEN: usize = 32; /// The HMAC hash, numbered as the wire and the flash spell it. #[derive(Clone, Copy, PartialEq, Eq, Debug)] diff --git a/firmware/core/src/proto.rs b/firmware/core/src/proto.rs index 134f816..22238af 100644 --- a/firmware/core/src/proto.rs +++ b/firmware/core/src/proto.rs @@ -18,9 +18,8 @@ use crate::oath::{NAME_MAX, Name, len_u8}; use crate::store::MAX_ENTRIES; use crate::vault::{Passphrase, Pin}; use crate::wire::{ - AUTH_CHALLENGE_LEN, AUTH_SIGNATURE_LEN, BAD_CMD, BAD_LEN, BackupHead, Cmd, FLAG_REPLACE, Fail, - MAGIC, MAX_PAYLOAD, OK, PinStatus, REACH_OPEN, REACH_SECRET, REACH_SEED, frame_head, - scan_magic, + BAD_CMD, BAD_LEN, BackupHead, Cmd, FLAG_REPLACE, Fail, MAGIC, MAX_PAYLOAD, OK, PinStatus, + REACH_OPEN, REACH_SECRET, REACH_SEED, frame_head, scan_magic, }; /// ~5 s of silence mid-frame resynchronises the framer instead of leaving it stuck. @@ -242,20 +241,6 @@ impl Proto { } } - Cmd::Respond => { - let Some((name, rest)) = take_name(p) else { - return self.reject(Malformed::Len); - }; - let Ok(challenge) = <&[u8; AUTH_CHALLENGE_LEN]>::try_from(rest) else { - return self.reject(Malformed::Len); - }; - let mut out = [0u8; AUTH_SIGNATURE_LEN]; - match dev.respond(name, challenge, &mut out) { - Ok(()) => self.respond(OK, &out), - Err(f) => self.fail(f), - } - } - Cmd::ItemGet => { let Some((name, rest)) = take_name(p) else { return self.reject(Malformed::Len); diff --git a/firmware/core/src/ui.rs b/firmware/core/src/ui.rs index 63dfbc7..b3765c7 100644 --- a/firmware/core/src/ui.rs +++ b/firmware/core/src/ui.rs @@ -11,6 +11,10 @@ //! hostile host: it would ask for a wipe while the owner expected a code request, and //! the reflex that approves a code would hand it over. A tap never wipes and never //! exports; a hold never exports either, and two taps never wipe. +//! +//! A request can be withdrawn while it waits (`Ui::withdrawn`, a passkey request the +//! host cancels). That ends the wait the way its deadline would - refused - and never +//! counts as a press or a hold. use crate::hal::{Clock, Ui}; @@ -70,22 +74,27 @@ pub fn await_double_tap(ui: &mut U, clock: &C, timeout_ms: u64) finish(ui, clock, true) } -/// Waits for a press that survives the debounce. False if the deadline passes first. +/// Waits for a press that survives the debounce. False if the wait is over first. fn await_press(ui: &U, clock: &C, deadline: u64) -> bool { loop { - if clock.now_ms() > deadline { + if over(ui, clock, deadline) { return false; } if ui.pressed() { let t = clock.now_ms(); while clock.now_ms() - t < DEBOUNCE_MS {} - if ui.pressed() { + if ui.pressed() && !ui.withdrawn() { return true; } } } } +/// Whether a wait is over: its deadline has passed, or the request was withdrawn. +fn over(ui: &U, clock: &C, deadline: u64) -> bool { + ui.withdrawn() || clock.now_ms() > deadline +} + /// Blocks until the button has been held down for `hold_ms` without letting go, or the /// timeout; the light shows red while the hold counts. Letting go early costs nothing /// but the hold: there is time to mean it, and time not to. @@ -95,13 +104,18 @@ pub fn await_hold(ui: &mut U, clock: &C, timeout_ms: u64, hold_ if !await_release(ui, clock, deadline) { return finish(ui, clock, false); } - while clock.now_ms() <= deadline { + while !over(ui, clock, deadline) { if !ui.pressed() { continue; } ui.set(State::Danger); let start = clock.now_ms(); while !released(ui, clock) { + // Asked before the time is counted: a request withdrawn mid-hold ends it, + // and must never be the moment that completes it. + if ui.withdrawn() { + break; + } if clock.now_ms() - start >= hold_ms { // The release too, so one hold cannot confirm twice. await_release(ui, clock, deadline); @@ -124,10 +138,12 @@ fn released(ui: &U, clock: &C) -> bool { !ui.pressed() } -/// Waits out a button that is already down. False if the deadline passes first. +/// Waits out a button that is down, until it has been up long enough to be really up: +/// a bounce in the middle of one press is not a release, or that press would count as +/// two taps, and two taps at blue let a backup out. False if the wait is over first. fn await_release(ui: &U, clock: &C, deadline: u64) -> bool { - while ui.pressed() { - if clock.now_ms() > deadline { + while !released(ui, clock) { + if over(ui, clock, deadline) { return false; } } diff --git a/firmware/core/src/vault.rs b/firmware/core/src/vault.rs index 7f366d8..b3bf7d6 100644 --- a/firmware/core/src/vault.rs +++ b/firmware/core/src/vault.rs @@ -4,7 +4,6 @@ //! kek = `DeviceKey::mac`(pre) - chip-bound when the board has a key //! dek = HMAC(kek, "vaultkey/dek/v1") - what actually encrypts //! verifier = HMAC(kek, "vaultkey/verify/v1") - stored, proves the PIN -//! auth = `DeviceKey::mac`("vaultkey/auth-key/v1") - auth secrets only, no PIN //! //! Only the dek stays resident while unlocked; the kek exists just long enough to //! check the verifier and derive it. Sealed blobs are AES-256-GCM with the entry name @@ -207,22 +206,6 @@ pub fn derive( Some(k) } -/// What the chip key is asked to MAC for the auth key: 32 bytes, as `DeviceKey::mac` -/// takes, and never an Argon2 output by any chance worth naming. -const AUTH_LABEL: &[u8; 32] = b"vaultkey/auth-key/v1\0\0\0\0\0\0\0\0\0\0\0\0"; - -/// The key auth secrets are sealed under: the chip key alone, no PIN, so a login -/// answers a tap on a locked device and a flash dump without the chip opens nothing. -/// None on a chip without a key - there it would be no key at all - or when the chip -/// cannot use it. -pub fn auth_key(key: &mut K) -> Option> { - if !key.bound() { - return None; - } - let mut out = Zeroizing::new([0u8; KEY_LEN]); - key.mac(AUTH_LABEL, &mut out).then_some(out) -} - #[must_use] pub fn verifier_of(kek: &[u8; KEY_LEN]) -> [u8; KEY_LEN] { let mut v = [0u8; KEY_LEN]; diff --git a/firmware/core/src/wire.rs b/firmware/core/src/wire.rs index a13facf..351ee7e 100644 --- a/firmware/core/src/wire.rs +++ b/firmware/core/src/wire.rs @@ -11,9 +11,7 @@ //! per item; `Code` sends `name | time u64le` and gets the ASCII code back; `ItemGet` //! sends `name | reach u8` and gets `category u8 | item` back, holding only the fields //! that reach allows - and taking the gesture that reach costs; `Rename` carries two -//! names, `old | new`; `Respond` sends `name | challenge(32)` and gets the Ed25519 -//! signature of `AUTH_SIGNED_PREFIX | challenge` back after a tap; `PinChange` is -//! `old_len u8 | old | new`; `PinStatus` answers +//! names, `old | new`; `PinChange` is `old_len u8 | old | new`; `PinStatus` answers //! `has_pin | unlocked | attempts_left | chip_bound`. //! //! An item's own bytes are `crate::item`'s: `category | count | field*`, where a field @@ -86,9 +84,8 @@ pub enum Cmd { ItemGet = 0x14, /// A new name for an item; the PIN is enough, nothing leaves the device. Rename = 0x16, - /// A challenge signed with an auth secret; the button must be tapped, the PIN is - /// not needed. - Respond = 0x19, + // 0x19 was `Respond`, `vkey auth`'s signed login, removed 2026-10-15 (restorable + // from 4bd49f3; docs/threat-model.md says why). Never reused: an older CLI means it. PinStatus = 0x20, PinSet = 0x21, PinUnlock = 0x22, @@ -120,7 +117,6 @@ impl Cmd { 0x13 => Self::Delete, 0x14 => Self::ItemGet, 0x16 => Self::Rename, - 0x19 => Self::Respond, 0x20 => Self::PinStatus, 0x21 => Self::PinSet, 0x22 => Self::PinUnlock, @@ -142,14 +138,6 @@ impl Cmd { } } -/// The host's challenge in a `Respond`. -pub const AUTH_CHALLENGE_LEN: usize = 32; -/// The answer: an Ed25519 signature. -pub const AUTH_SIGNATURE_LEN: usize = 64; -/// What a `Respond` signs in front of the challenge, so a login signature is never -/// valid as anything else. -pub const AUTH_SIGNED_PREFIX: &[u8; 16] = b"vaultkey/auth/v1"; - /// `ItemPut` flags. pub const FLAG_REPLACE: u8 = 0x01; diff --git a/firmware/core/tests/key.rs b/firmware/core/tests/key.rs index cd4dc64..eabbe3a 100644 --- a/firmware/core/tests/key.rs +++ b/firmware/core/tests/key.rs @@ -8,7 +8,6 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use ed25519_dalek::{Signer, SigningKey}; use embedded_storage::nor_flash::{ ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash, }; @@ -18,13 +17,12 @@ use sha2::Sha256; use vaultkey_core::device::{self, Device, Reach}; use vaultkey_core::hal::{Clock, DeviceKey, Ui}; use vaultkey_core::item::{Category, Class, Field, FieldKind, Item, Writer}; -use vaultkey_core::oath::{AUTH_SECRET_LEN, Algo, Digits, Name, Params}; +use vaultkey_core::oath::{Algo, Digits, Name, Params}; use vaultkey_core::store::{self, Layout, MAX_ATTEMPTS, Store}; -use vaultkey_core::ui::State; +use vaultkey_core::ui::{self, State}; use vaultkey_core::vault::{self, Block, Cost, KDF_BLOCKS, Passphrase, Pin}; use vaultkey_core::wire::{ - AUTH_CHALLENGE_LEN, AUTH_SIGNED_PREFIX, BackupHead, Cmd, Fail, HAS_OPEN, HAS_SECRET, HAS_SEED, - OK, REACH_OPEN, REACH_SECRET, REACH_SEED, + BackupHead, Cmd, Fail, HAS_OPEN, HAS_SECRET, HAS_SEED, OK, REACH_OPEN, REACH_SECRET, REACH_SEED, }; // --- the hardware, faked ------------------------------------------------------------- @@ -298,6 +296,8 @@ enum Finger { DoubleTap { gap: u64, }, + /// One tap whose contact opens for 15 ms in the middle: one press, bouncing. + BouncyTap, /// Down before the request arrives, and never let go. Taped, } @@ -309,6 +309,8 @@ struct Button { finger: Finger, down: Vec<(u64, u64)>, asked: u32, + /// When the request is withdrawn, if it ever is. + withdrawn_at: Option, } impl Button { @@ -318,6 +320,15 @@ impl Button { finger, down: Vec::new(), asked: 0, + withdrawn_at: None, + } + } + + /// The same finger, on a request withdrawn at `ms` on the clock. + fn withdrawn_at(self, ms: u64) -> Self { + Button { + withdrawn_at: Some(ms), + ..self } } } @@ -335,6 +346,7 @@ impl Ui for Button { Finger::DoubleTap { gap } => { vec![(from, from + 200), (from + 200 + gap, from + 400 + gap)] } + Finger::BouncyTap => vec![(from, from + 100), (from + 115, from + 300)], Finger::Away | Finger::Taped => Vec::new(), }; } @@ -346,6 +358,10 @@ impl Ui for Button { .iter() .any(|(a, b)| (*a..*b).contains(&self.clock.peek())) } + + fn withdrawn(&self) -> bool { + self.withdrawn_at.is_some_and(|t| self.clock.peek() >= t) + } } type Key = Device<'static, MemFlash, Repeatable, Button, Ticker, K>; @@ -629,6 +645,10 @@ fn only_valid_values_exist() { Category::from_wire(250).is_none(), "a category this firmware does not know is refused, not defaulted" ); + assert!( + Category::from_wire(201).is_none() && Cmd::from_wire(0x19).is_none(), + "vkey auth's category and command are gone, and nothing took their numbers" + ); } #[test] @@ -641,7 +661,6 @@ fn wire_codes_round_trip() { Cmd::Delete, Cmd::ItemGet, Cmd::Rename, - Cmd::Respond, Cmd::PinStatus, Cmd::PinSet, Cmd::PinUnlock, @@ -974,6 +993,59 @@ fn a_tap_never_wipes_and_never_exports_a_seed() { ); } +#[test] +fn a_bounce_in_one_press_is_not_two_taps() { + let flash = MemFlash::blank(); + let clock = Ticker::default(); + let mut dev = flash.key_with(Button::new(&clock, Finger::BouncyTap), clock, Unbound); + dev.pin_set(pin("12345678")).expect("sets the PIN"); + put( + &mut dev, + "rfc", + Category::Login, + &totp_item(b"12345678901234567890"), + false, + ) + .expect("stores"); + assert_eq!( + dev.export_begin(passphrase("correct horse battery staple")), + Err(Fail::Refused), + "the contact opening for 15 ms mid-press is not a release" + ); + code(&mut dev, "rfc", 59).expect("and the bouncing tap still approves a code"); +} + +#[test] +fn a_withdrawn_tap_wait_ends_refused_and_at_once() { + let clock = Ticker::default(); + let mut button = Button::new(&clock, Finger::Away).withdrawn_at(1_000); + assert!(!ui::await_confirmation(&mut button, &clock, 30_000)); + assert!( + clock.peek() < 2_000, + "the wait ends when the request goes, not at its deadline: {} ms", + clock.peek() + ); +} + +#[test] +fn a_withdrawn_hold_never_completes() { + // Down from 100 ms for ten seconds; withdrawn two seconds into the hold. + let clock = Ticker::default(); + let mut button = Button::new(&clock, Finger::Hold(10_000)).withdrawn_at(2_100); + assert!( + !ui::await_hold(&mut button, &clock, 30_000, 5_000), + "a hold that goes on past five seconds after the request was withdrawn is no wipe" + ); +} + +#[test] +fn a_withdrawn_second_tap_window_ends_refused() { + // First tap 100..300 ms, second 700..900 ms; withdrawn between them. + let clock = Ticker::default(); + let mut button = Button::new(&clock, Finger::DoubleTap { gap: 400 }).withdrawn_at(500); + assert!(!ui::await_double_tap(&mut button, &clock, 30_000)); +} + #[test] fn a_hold_wipes_and_nothing_else_does() { let flash = MemFlash::blank(); @@ -1353,120 +1425,6 @@ fn a_backup_refuses_the_wrong_passphrase_and_a_reordered_file() { ); } -// --- vkey auth ---------------------------------------------------------------------------- - -fn chip(flash: &MemFlash, finger: Finger, key: [u8; 32]) -> Key { - let clock = Ticker::default(); - flash.key_with(Button::new(&clock, finger), clock, ChipKey(key)) -} - -const SEED: [u8; AUTH_SECRET_LEN] = [4u8; AUTH_SECRET_LEN]; -const CHALLENGE: [u8; AUTH_CHALLENGE_LEN] = [5u8; AUTH_CHALLENGE_LEN]; - -fn auth_item() -> Vec { - pack( - Category::Auth, - &[(Class::Secret, FieldKind::Concealed, "seed", &SEED)], - ) -} - -fn respond(dev: &mut Key, n: &str) -> Result, Fail> { - let mut out = [0u8; 64]; - dev.respond(name(n), &CHALLENGE, &mut out)?; - Ok(out.to_vec()) -} - -fn expected_response() -> Vec { - let key = SigningKey::from_bytes(&SEED); - let mut msg = Vec::from(*AUTH_SIGNED_PREFIX); - msg.extend_from_slice(&CHALLENGE); - key.sign(&msg).to_bytes().to_vec() -} - -#[test] -fn an_auth_item_answers_a_tap_without_the_pin() { - let flash = MemFlash::blank(); - let mut dev = chip(&flash, Finger::Tap, [1u8; 32]); - dev.pin_set(pin("12345678")).expect("sets the PIN"); - put(&mut dev, "hifes", Category::Auth, &auth_item(), false).expect("stores the seed"); - dev.lock(); - - assert_eq!( - respond(&mut dev, "hifes").expect("signs while locked"), - expected_response(), - "a login is proven by the finger on the board, not by the PIN" - ); - assert_eq!( - get(&mut dev, "hifes", Reach::Seed), - Err(Fail::Locked), - "and the seed itself still never comes out, at any reach" - ); -} - -#[test] -fn a_locked_key_names_no_item_that_is_not_an_auth_secret() { - let flash = MemFlash::blank(); - let mut dev = chip(&flash, Finger::Tap, [1u8; 32]); - dev.pin_set(pin("12345678")).expect("sets the PIN"); - put( - &mut dev, - "github.com", - Category::Login, - &login_item("me", "pw"), - false, - ) - .expect("stores"); - dev.lock(); - - assert_eq!( - respond(&mut dev, "github.com"), - Err(Fail::NotFound), - "an item that is not an auth secret reads as absent while locked: a different \ - answer would tell a stranger which names exist" - ); -} - -#[test] -fn an_auth_item_needs_a_chip_key_to_exist() { - let flash = MemFlash::blank(); - let mut dev = tapping(&flash); // no chip key burned - dev.pin_set(pin("12345678")).expect("sets the PIN"); - assert_eq!( - put(&mut dev, "hifes", Category::Auth, &auth_item(), false), - Err(Fail::Incompatible), - "without the eFuse key there is nothing to seal an auth secret under" - ); -} - -#[test] -fn an_auth_item_is_not_re_sealed_by_a_pin_change() { - let flash = MemFlash::blank(); - let mut dev = chip(&flash, Finger::Tap, [1u8; 32]); - dev.pin_set(pin("12345678")).expect("sets the PIN"); - put(&mut dev, "hifes", Category::Auth, &auth_item(), false).expect("stores the seed"); - put( - &mut dev, - "github.com", - Category::Login, - &login_item("me", "hunter2"), - false, - ) - .expect("stores"); - - dev.pin_change(pin("12345678"), pin("87654321")) - .expect("changes the PIN"); - assert_eq!( - respond(&mut dev, "hifes").expect("still signs"), - expected_response(), - "its key is the chip's, not the PIN's: a PIN change must leave it alone" - ); - assert_eq!( - value(&mut dev, "github.com", Reach::Secret, "password"), - Some(b"hunter2".to_vec()), - "while everything else was re-sealed under the new PIN" - ); -} - // --- the shape of a reach on the wire ------------------------------------------------------- #[test] From b2d3eeb476dc7f775b5711d1d66319e2b3997d51 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 23:23:06 +0300 Subject: [PATCH 18/33] Carry the nRF52840's passkeys in the .vkb and add restore --only A backup now carries Trussed's flash as sealed 4 KiB sectors after the items, under REGION_AAD plus the position. The core takes a fifth board trait, hal::Attachment, and every backup session starts and ends in one place. The board freezes FIDO during a session and restarts after a restore that changed a sector. vkey restore --only adds named items from a .vkb beside the vault. Accepted on the board: check, restore, sync and selftest; backup, passkey reset, restore, then sudo and webauthn.io work again with nothing enrolled anew. --- CLAUDE.md | 9 + README.md | 3 +- cli/build.rs | 8 +- cli/src/backup.rs | 264 ++++++++++++++--- cli/src/boards.rs | 3 + cli/src/check.rs | 2 +- cli/src/main.rs | 45 ++- cli/src/shell.rs | 22 +- docs/threat-model.md | 20 +- docs2/roadmap.md | 39 ++- .../boards/esp32c6-zero/images/vaultkey.bin | Bin 186288 -> 185840 bytes firmware/boards/esp32c6-zero/src/main.rs | 3 +- .../boards/nrf52840-mdk-dongle/board.toml | 5 + .../nrf52840-mdk-dongle/images/vaultkey.bin | Bin 267620 -> 268476 bytes .../images/vaultkey.signed.uf2 | Bin 536064 -> 537600 bytes .../boards/nrf52840-mdk-dongle/src/fido.rs | 139 ++++++++- .../boards/nrf52840-mdk-dongle/src/main.rs | 13 +- firmware/core/src/device.rs | 262 ++++++++++++++--- firmware/core/src/hal.rs | 47 ++- firmware/core/src/proto.rs | 14 +- firmware/core/src/vault.rs | 8 + firmware/core/tests/key.rs | 275 +++++++++++++++++- 22 files changed, 1075 insertions(+), 106 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 782fe49..0ecb135 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -238,6 +238,15 @@ The boards: session is killed by any `load()`, by `lock`, and by the first error. An item's AAD is `BACKUP_AAD` plus its index in the file: a reordered or altered item does not open (`BadBackup`). + On the nRF52840 the backup also carries the passkeys (2026-10-15): the board's + `hal::Attachment`, Trussed's flash, as sealed 4 KiB sectors after the items under + `REGION_AAD` plus the same index, blank sectors left out, the region's geometry in each. + The session freezes Trussed (`start_session`/`end_session`, the one place every session + begins and ends), and the board lets the freeze go by itself after 10 s of a silent vkey + line. A restore rewrites only sectors that differ, and when it changed any the board + resets once the answer has left. A file with no sectors leaves the passkeys alone; a + board without them refuses sectors, and the CLI leaves them in the file and names them + (`passkeys` in `board.toml`). The second way is `vkey export` (2026-09-19): an item written back into 1Password through `op item create`, under the same double tap, with the seed in the clear. That ends the claim that a seed never leaves — `docs/threat-model.md` says what it costs. diff --git a/README.md b/README.md index ef8f39c..6754650 100644 --- a/README.md +++ b/README.md @@ -118,8 +118,9 @@ vkey get myapp > .env # better without a file: env $(vkey get m vkey list · rm · info · lock · pin set/change · totp selftest · wipe vkey op [query] # mirror 1Password (passwords, TOTP, notes, developer .env) vkey import passwords.csv # Google Password Manager or 1Password CSV export (skips unchanged) -vkey backup vault.vkb # everything in one file, sealed on the key; two taps +vkey backup vault.vkb # everything, the nRF's passkeys too, sealed on the key; two taps vkey restore [file] # restore from 1Password, CSV, or .vkb backup file +vkey restore --only NAME file.vkb # just that item out of a backup, nothing replaced vkey check --wipe-everything # lifecycle test on a board; ERASES EVERYTHING sudo vkey auth enable # sudo and the lock screen with a tap (below) ``` diff --git a/cli/build.rs b/cli/build.rs index a41ada6..1e4275b 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -84,9 +84,15 @@ fn main() { ) .expect("writing to a String cannot fail"); } + let passkeys = match t.get("passkeys") { + None => false, + Some(v) => v + .as_bool() + .unwrap_or_else(|| panic!("{}: `passkeys` is not a bool", toml_path.display())), + }; writeln!( out, - " Board {{ name: {:?}, chip: {:?}, button: {:?}, usb_vid: {:#x}, usb_pid: {:#x}, images: &[{images}] }},", + " Board {{ name: {:?}, chip: {:?}, button: {:?}, usb_vid: {:#x}, usb_pid: {:#x}, passkeys: {passkeys}, images: &[{images}] }},", string("name"), string("chip"), string("button"), diff --git a/cli/src/backup.rs b/cli/src/backup.rs index d08e2d8..4569f37 100644 --- a/cli/src/backup.rs +++ b/cli/src/backup.rs @@ -37,16 +37,59 @@ pub fn target(path: &Path) -> Result { Ok(file) } -/// Every item off the device into `path`; how many there were. Nothing is written -/// until the last item is in hand, so a refused tap or a pulled cable leaves no -/// half file behind. -pub fn export(dev: &mut Device, path: &Path, pass: Passphrase<'_>) -> Result { +/// What a backup holds: the items, and the sectors of the board's passkeys. +pub struct Exported { + pub items: usize, + pub sectors: usize, +} + +impl Exported { + /// "50 items" or "50 items and the passkeys", for the line that reports it. + pub fn describe(&self) -> String { + let items = format!( + "{} item{}", + self.items, + if self.items == 1 { "" } else { "s" } + ); + if self.sectors == 0 { + items + } else { + format!("{items} and the passkeys") + } + } +} + +/// Every item off the device into `path`, and the passkeys after them on a board that +/// keeps them. Nothing is written until the last one is in hand, so a refused tap or a +/// pulled cable leaves no half file behind; and before saying it is done, this side +/// opens every one with the passphrase it was given, so a file that would not open is +/// never reported as a backup. +pub fn export(dev: &mut Device, path: &Path, pass: Passphrase<'_>) -> Result { let path = &target(path)?; let head = dev.export_begin(pass)?; let mut items = Vec::new(); while let Some(item) = dev.export_next()? { items.push(item); } + let mut mem = vec![Block::new(); KDF_BLOCKS]; + let key = vault::backup_key(pass, &head.salt, head.cost, &mut mem) + .ok_or_else(|| Error::Value("the backup's key cannot be made here".into()))?; + let mut exported = Exported { + items: 0, + sectors: 0, + }; + for (i, sealed) in (0u32..).zip(&items) { + match open_item(&key, i, sealed) { + Some(Incoming::Region(_)) => exported.sectors += 1, + Some(_) => exported.items += 1, + None => { + return Err(Error::Value( + "the key's backup does not open with the passphrase; nothing was written" + .into(), + )); + } + } + } let count = u32::try_from(items.len()).map_err(|_| Error::BadArg)?; let mut file = Vec::with_capacity(FIXED + items.iter().map(|i| 2 + i.len()).sum::()); file.extend_from_slice(MAGIC); @@ -59,7 +102,7 @@ pub fn export(dev: &mut Device, path: &Path, pass: Passphrase<'_>) -> Result Result { use vaultkey_core::item::{Category, Class, FieldKind, Item as CoreItem}; use vaultkey_core::oath::{Name, Params}; use vaultkey_core::vault::{ - self, BACKUP_AAD, Block, CryptoRng, KDF_BLOCKS, NONCE_LEN, RngCore, TAG_LEN, + self, BACKUP_AAD, Block, CryptoRng, KDF_BLOCKS, NONCE_LEN, REGION_AAD, RngCore, TAG_LEN, }; use zeroize::Zeroizing; @@ -142,17 +185,19 @@ const RETIRED_AUTH: u8 = 201; const RETIRED_AUTH_KIND: [u8; 4] = [4, 0, 0, 0]; /// One backup item as this side reads it: what goes back on the key, as the plaintext -/// the device packed - `category | name_len | name | item` - or a retired item's name. +/// the device packed - `category | name_len | name | item` - a sector of the board's +/// passkeys, or a retired item's name. enum Incoming { Keep(Zeroizing>), + Region(Zeroizing>), Retired(String), } -/// Where item `item_idx` sits in the file, as its seal binds it. -fn item_aad(item_idx: u32) -> [u8; BACKUP_AAD.len() + 4] { - let mut aad = [0u8; BACKUP_AAD.len() + 4]; - aad[..BACKUP_AAD.len()].copy_from_slice(BACKUP_AAD); - aad[BACKUP_AAD.len()..].copy_from_slice(&item_idx.to_le_bytes()); +/// Where item `item_idx` sits in the file, as its seal binds it: after `BACKUP_AAD` for +/// an item, `REGION_AAD` for a sector. +fn aad(prefix: &[u8], item_idx: u32) -> Vec { + let mut aad = prefix.to_vec(); + aad.extend_from_slice(&item_idx.to_le_bytes()); aad } @@ -160,7 +205,14 @@ fn item_aad(item_idx: u32) -> [u8; BACKUP_AAD.len() + 4] { /// items existed. None when it does not open or parse. fn open_item(key: &[u8; vault::KEY_LEN], item_idx: u32, sealed: &[u8]) -> Option { let mut buf = Zeroizing::new(sealed.to_vec()); - let n = vault::open_in_place(key, &item_aad(item_idx), &mut buf)?; + let Some(n) = vault::open_in_place(key, &aad(BACKUP_AAD, item_idx), &mut buf) else { + // Not an item: a sector of the passkeys, or nothing this key opens. + let mut buf = Zeroizing::new(sealed.to_vec()); + let n = vault::open_in_place(key, &aad(REGION_AAD, item_idx), &mut buf)?; + return Some(Incoming::Region(Zeroizing::new( + buf[NONCE_LEN..NONCE_LEN + n].to_vec(), + ))); + }; let plain = &buf[NONCE_LEN..NONCE_LEN + n]; if let Some((&category, rest)) = plain.split_first() @@ -230,11 +282,15 @@ fn retired(name: Name<'_>) -> Incoming { /// `plain` sealed as backup item `item_idx`, as the device would have sealed it. fn seal_item(key: &[u8; vault::KEY_LEN], item_idx: u32, plain: &[u8]) -> Result, Error> { + seal_at(key, &aad(BACKUP_AAD, item_idx), plain) +} + +fn seal_at(key: &[u8; vault::KEY_LEN], aad: &[u8], plain: &[u8]) -> Result, Error> { let total = plain.len(); let mut out = vec![0u8; NONCE_LEN + total + TAG_LEN]; out[NONCE_LEN..NONCE_LEN + total].copy_from_slice(plain); let mut rng = BackupRng::new(); - let sealed = vault::seal_in_place(key, &mut rng, &item_aad(item_idx), &mut out, total); + let sealed = vault::seal_in_place(key, &mut rng, aad, &mut out, total); if rng.failed { return Err(Error::Value("no randomness from OS".into())); } @@ -250,54 +306,150 @@ fn seal_item(key: &[u8; vault::KEY_LEN], item_idx: u32, plain: &[u8]) -> Result< /// that does not open here goes as it is, for the device to refuse. pub fn import(dev: &mut Device, path: &Path, pass: Passphrase<'_>) -> Result { let (head, items) = read(&source(path)?)?; + let passkeys = keeps_passkeys(dev)?; let mut mem = vec![Block::new(); KDF_BLOCKS]; - let (items, skipped) = match vault::backup_key(pass, &head.salt, head.cost, &mut mem) { - Some(key) => prepare(&key, items)?, - None => (items, Vec::new()), + let prepared = match vault::backup_key(pass, &head.salt, head.cost, &mut mem) { + Some(key) => prepare(&key, items, passkeys)?, + None => Restored { + count: items.len(), + blobs: items, + skipped: Vec::new(), + passkeys: false, + }, }; dev.import_begin(pass, head)?; - for item in &items { - dev.import_item(item)?; + for blob in &prepared.blobs { + dev.import_item(blob)?; } dev.import_end()?; - Ok(Restored { - count: items.len(), - skipped, - }) + Ok(prepared) } -/// The items as the device takes them back, and the names of those left out. +/// The items called `names` out of the backup at `path`, put on the key beside what it +/// holds, under the PIN: a restore of a few things that replaces nothing. An item the +/// key already has under that name is refused, never overwritten. The names put on. +pub fn pick( + dev: &mut Device, + path: &Path, + pass: Passphrase<'_>, + names: &[String], +) -> Result, Error> { + let (head, blobs) = read(&source(path)?)?; + let mut mem = vec![Block::new(); KDF_BLOCKS]; + let key = vault::backup_key(pass, &head.salt, head.cost, &mut mem) + .ok_or_else(|| Error::Value("the backup's key cannot be made here".into()))?; + let mut found = Vec::new(); + for (i, sealed) in (0u32..).zip(&blobs) { + let Some(incoming) = open_item(&key, i, sealed) else { + return Err(Error::Value(format!( + "{} does not open with that passphrase", + path.display() + ))); + }; + let Incoming::Keep(plain) = incoming else { + continue; + }; + let Some((_, rest)) = plain.split_first() else { + continue; + }; + let Some((name, body)) = Name::take(rest) else { + continue; + }; + let name = String::from_utf8_lossy(name.as_bytes()).into_owned(); + if names.contains(&name) { + found.push((name, Item::unpack(body)?)); + } + } + let missing: Vec<&String> = names + .iter() + .filter(|n| !found.iter().any(|(f, _)| f == *n)) + .collect(); + if !missing.is_empty() { + return Err(Error::Value(format!( + "not in {}: {}; nothing was added", + path.display(), + missing + .iter() + .map(|n| n.as_str()) + .collect::>() + .join(", ") + ))); + } + for (name, item) in &found { + dev.put(name, item, false)?; + } + Ok(found.into_iter().map(|(name, _)| name).collect()) +} + +/// Whether the board on the other end keeps passkeys, as its folder says. +fn keeps_passkeys(dev: &mut Device) -> Result { + let version = dev.info()?; + Ok(version + .rsplit(' ') + .next() + .and_then(crate::boards::by_name) + .is_some_and(|b| b.passkeys)) +} + +/// The items and the passkeys as the device takes them back - the passkeys only on a +/// board that keeps them - and the names of what is left out. fn prepare( key: &[u8; vault::KEY_LEN], items: Vec>, -) -> Result<(Vec>, Vec), Error> { + passkeys: bool, +) -> Result { let opened = (0u32..) .zip(&items) .map(|(i, sealed)| open_item(key, i, sealed)) .collect::>>(); let Some(opened) = opened else { - return Ok((items, Vec::new())); + return Ok(Restored { + count: items.len(), + blobs: items, + skipped: Vec::new(), + passkeys: false, + }); }; - let mut kept = Vec::with_capacity(opened.len()); - let mut skipped = Vec::new(); + let mut out = Restored { + count: 0, + blobs: Vec::with_capacity(opened.len()), + skipped: Vec::new(), + passkeys: false, + }; + let mut sectors_left = 0; for item in opened { + let at = u32::try_from(out.blobs.len()).map_err(|_| Error::BadArg)?; match item { Incoming::Keep(plain) => { - let at = u32::try_from(kept.len()).map_err(|_| Error::BadArg)?; - kept.push(seal_item(key, at, &plain)?); + out.blobs.push(seal_item(key, at, &plain)?); + out.count += 1; + } + Incoming::Region(plain) if passkeys => { + out.blobs.push(seal_at(key, &aad(REGION_AAD, at), &plain)?); + out.passkeys = true; } - Incoming::Retired(name) => skipped.push(name), + Incoming::Region(_) => sectors_left += 1, + Incoming::Retired(name) => out.skipped.push(name), } } - Ok((kept, skipped)) + if sectors_left > 0 { + out.skipped + .push("the passkeys: this board does not keep passkeys".to_string()); + } + Ok(out) } -/// What a restore did: how many items are on the key, and what the file held that this -/// build could not store - a retired `vkey auth` secret from an older backup. +/// What a restore did: how many items are on the key, whether the passkeys went back +/// too - the key then restarts to load them - and what the file held that this board +/// could not take: the passkeys on one without them, a retired `vkey auth` secret from +/// an older backup. pub struct Restored { pub count: usize, + pub passkeys: bool, pub skipped: Vec, + /// The sealed items and sectors as they went to the device. + blobs: Vec>, } /// The file's head and items, checked for shape only: what is inside an item is the @@ -431,7 +583,11 @@ mod tests { .map(|(i, p)| seal_item(&key, i, p).expect("seals")) .collect(); - let (items, skipped) = prepare(&key, sealed).expect("prepares"); + let Restored { + blobs: items, + skipped, + .. + } = prepare(&key, sealed, true).expect("prepares"); assert_eq!(items.len(), 2, "the auth secret stays in the file"); assert_eq!(skipped.len(), 1, "and is named: {skipped:?}"); assert!(skipped[0].starts_with("hifes@pop-os:"), "{skipped:?}"); @@ -453,11 +609,43 @@ mod tests { let login = Category::Login.wire(); let sealed = vec![seal_item(&key, 0, &backup_plain(login, "github", login)).expect("seals")]; - let (items, skipped) = prepare(&[8u8; vault::KEY_LEN], sealed.clone()).expect("prepares"); + let out = prepare(&[8u8; vault::KEY_LEN], sealed.clone(), true).expect("prepares"); assert_eq!( - items, sealed, + out.blobs, sealed, "a wrong passphrase is the device's to refuse" ); - assert!(skipped.is_empty()); + assert!(out.skipped.is_empty()); + } + + #[test] + fn passkeys_move_up_behind_the_items_or_stay_in_the_file() { + let key = [7u8; vault::KEY_LEN]; + let login = Category::Login.wire(); + let sector = vec![0x5A; 16]; + let file = [ + seal_item( + &key, + 0, + &backup_plain(RETIRED_AUTH, "hifes@pop-os", RETIRED_AUTH), + ) + .expect("seals"), + seal_item(&key, 1, &backup_plain(login, "github", login)).expect("seals"), + seal_at(&key, &aad(REGION_AAD, 2), §or).expect("seals"), + ]; + + let out = prepare(&key, file.to_vec(), true).expect("prepares"); + assert_eq!((out.count, out.passkeys, out.blobs.len()), (1, true, 2)); + let Some(Incoming::Region(plain)) = open_item(&key, 1, &out.blobs[1]) else { + panic!("the sector opens one place up, under the sectors' associated data"); + }; + assert_eq!(plain.as_slice(), sector.as_slice()); + + let out = prepare(&key, file.to_vec(), false).expect("prepares"); + assert_eq!((out.count, out.passkeys, out.blobs.len()), (1, false, 1)); + assert!( + out.skipped.iter().any(|s| s.starts_with("the passkeys")), + "a board without passkeys takes the items and names what it leaves: {:?}", + out.skipped + ); } } diff --git a/cli/src/boards.rs b/cli/src/boards.rs index c0427f8..b3bebf4 100644 --- a/cli/src/boards.rs +++ b/cli/src/boards.rs @@ -9,6 +9,9 @@ pub struct Board { pub button: &'static str, pub usb_vid: u16, pub usb_pid: u16, + /// Whether it keeps passkeys, which a backup carries and only such a board takes + /// back. + pub passkeys: bool, /// Everything `setup` may write, in flash order. pub images: &'static [Image], } diff --git a/cli/src/check.rs b/cli/src/check.rs index 0308b99..4b7b7d4 100644 --- a/cli/src/check.rs +++ b/cli/src/check.rs @@ -368,7 +368,7 @@ fn backup( ); println!(" >>> tap {} twice when the light turns blue", rep.button); let n = backup::export(d, &dir, passphrase(PASS)?)?; - rep.check("backup written", n == 3, &format!("{n} items")); + rep.check("backup written", n.items == 3, &n.describe()); d.delete("t")?; d.delete("e")?; rep.expect( diff --git a/cli/src/main.rs b/cli/src/main.rs index 79add78..87e2744 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -179,6 +179,10 @@ enum Cmd { /// 1Password Developer Environment to import (name:id or name=id) #[arg(short = 'E', long = "environment")] environments: Vec, + /// Only these items out of a .vkb, added beside what the key holds; nothing + /// else is replaced + #[arg(long = "only", value_name = "NAME")] + only: Vec, }, /// Lifecycle test of a development board; ERASES everything #[command(long_about = "vkey check --wipe-everything\n\n\ @@ -398,7 +402,8 @@ fn run(cli: Cli) -> Result { file, op, environments, - } => run_restore(&mut dev, file.as_deref(), op, &environments), + only, + } => run_restore(&mut dev, file.as_deref(), op, &environments, &only), } } @@ -484,8 +489,8 @@ fn run_backup(dev: &mut Device, version: &str, file: &Path) -> Result backup::export(d, &file, passphrase(&pass)?) })?; println!( - "{n} item{} sealed into {} - it opens only with the passphrase, on any vkey", - if n == 1 { "" } else { "s" }, + "{} sealed into {} - it opens only with the passphrase, on any vkey", + n.describe(), file.display() ); Ok(0) @@ -498,12 +503,34 @@ enum RestoreSource { Backup, } +/// `vkey restore --only NAME file.vkb`: those items added, the rest of the key as it was. +fn run_pick(dev: &mut Device, file: &Path, names: &[String]) -> Result { + let file = backup::source(file)?; + let pass = prompt_secret("backup passphrase")?; + passphrase(&pass)?; + let added = with_unlock(dev, |d| backup::pick(d, &file, passphrase(&pass)?, names))?; + for name in &added { + println!("added '{name}' from {}", file.display()); + } + println!("nothing else on the key changed"); + Ok(0) +} + fn run_restore( dev: &mut Device, file: Option<&Path>, op: bool, environments: &[String], + only: &[String], ) -> Result { + if !only.is_empty() { + let Some(file) = file else { + return Err(Error::Value( + "--only takes items out of a .vkb: name the file".into(), + )); + }; + return run_pick(dev, file, only); + } if op { return run_op(dev, None, None, None, environments, false); } @@ -565,14 +592,24 @@ fn run_restore( passphrase(&pass)?; let done = with_unlock(dev, |d| backup::import(d, &file, passphrase(&pass)?))?; println!( - "{} item{} restored from {}", + "{} item{}{} restored from {}", done.count, if done.count == 1 { "" } else { "s" }, + if done.passkeys { + " and the passkeys" + } else { + "" + }, file.display() ); for line in &done.skipped { eprintln!(" left in the file: {line}"); } + if done.passkeys { + println!("the key restarts to load its passkeys..."); + // Past the reset, so a command run right after does not land in it. + std::thread::sleep(std::time::Duration::from_secs(3)); + } Ok(0) } diff --git a/cli/src/shell.rs b/cli/src/shell.rs index 3bb959e..1ba548a 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -2153,8 +2153,8 @@ impl Shell { self.line(Color::Blue, &hint); let n = backup::export(self.dev()?, &path, passphrase(&pass)?)?; let done = format!( - " {n} item{} sealed into {} - it opens only with the passphrase, on any vkey", - if n == 1 { "" } else { "s" }, + " {} sealed into {} - it opens only with the passphrase, on any vkey", + n.describe(), path.display() ); self.line(Color::Green, &done); @@ -2225,15 +2225,31 @@ impl Shell { self.ensure_unlocked()?; let restored = backup::import(self.dev()?, &path, passphrase(&pass)?)?; let done = format!( - " {} item{} restored from {}", + " {} item{}{} restored from {}", restored.count, if restored.count == 1 { "" } else { "s" }, + if restored.passkeys { + " and the passkeys" + } else { + "" + }, path.display() ); self.line(Color::Green, &done); for line in &restored.skipped { self.line(Color::Yellow, &format!(" left in the file: {line}")); } + if restored.passkeys { + // The key resets to load them; the port goes and comes back. + self.line(Color::Blue, " the key restarts to load its passkeys..."); + std::thread::sleep(Duration::from_secs(3)); + if !self.reconnect() { + self.line( + Color::Yellow, + " the key has not come back: plug it in again", + ); + } + } self.forget_logins(None); self.refresh(); Ok(()) diff --git a/docs/threat-model.md b/docs/threat-model.md index d28add4..ea77724 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -83,9 +83,23 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure - **Origin binding.** The browser binds a passkey to its site's origin, so a look-alike site gets nothing it can use: the property WebAuthn has and TOTP lacks. TOTP codes and passwords from the vault stay as phishable as anywhere. - - **No backup yet.** Milestone 5 puts the passkeys into the `.vkb`, a deliberate break - from FIDO's rule that they never leave. Until then, losing the key loses them, so - every site keeps a second way in. + - **They are in the backup, under its passphrase** (milestone 5): a deliberate break + from FIDO's rule that they never leave (maintainer's decision, 2026-10-15). `vkey + backup` carries Trussed's whole filesystem after the items, as sealed 4 KiB sectors: + every passkey, the key that wraps the non-resident credentials (`pam_u2f`'s among + them), the signature counters. They leave only after the double tap, like the items. + Passkeys are not served while the backup runs, so the copy is never torn. + - Whoever has the `.vkb` and its passphrase has the passkeys. Restored onto another + nRF52840, they make a clone that answers every site and this host's `sudo`. + - A restore replaces the passkeys with the PIN alone and no gesture, as it replaces + the vault. A file with no passkeys leaves them as they are. + - Restoring an older backup winds the signature counters back. A site that checks + them may take the key for a clone. + - A restore cut short leaves the region torn. The key formats it on its next start, + which also loses the `sudo` credential, until the restore runs again from the file. + - The C6 takes an nRF backup's items and leaves the passkeys in the file, named. + + Losing the key with no backup still loses them, so every site keeps a second way in. **Accepted, not fixed** (maintainer's decision, 2026-10-13): this revision-2 chip will hold everything once the steps below are done. The glitch above stays open after them. Someone diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 09b41d0..97ad72b 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -573,8 +573,13 @@ moves but the keys: 1. Put `vkey-signing`, the C6's Secure Boot key, on the nRF next to the bootloader key, back up to a `.vkb`, and write down where it lives. Losing it ends C6 updates forever. + `vkey restore --only vkey-signing ` (2026-10-15) adds one item from a backup + without replacing the vault. With the key on the nRF, `tools/sign-vaultkey.sh` signs the + C6's images again and its signed app returns to the repository, the C6 left alone. 2. C6 flashing moves out of the CLI into a script in its folder. `espflash` leaves, and the - audit exception goes. + audit exception goes. **Deferred** (2026-10-15): the script chooses between the plain + and the Secure Boot bootloader, and the wrong choice on a plain chip burns its eFuses. + It waits until the C6 may be touched to test it; until then `vkey setup` keeps doing it. Acceptance: the threat model's nRF section is rewritten to match; `selftest` green on the nRF; `check --wipe-everything` green on the C6. @@ -696,7 +701,37 @@ Milestones, one commit each, each leaving a key that works: - `check --wipe-everything` passed, then the restore from the `.vkb` through the new host-side reseal, the 1Password sync and `selftest`. 5. **The passkeys in the `.vkb`**: backup and restore carry the Trussed filesystem, sealed - under the passphrase like the items. + under the passphrase like the items. Built 2026-10-15: + - The core takes a fifth board trait, `hal::Attachment`: sectors to read and put, a + freeze and a thaw. The C6 passes `NoAttachment`. + - A backup carries the non-blank sectors after the items, each sealed under + `REGION_AAD` plus its position and holding the geometry. Every session begins and + ends in one place (`start_session`/`end_session`). + - The board freezes Trussed for the session, lets go by itself after 10 s of a silent + vkey line, and resets after a restore that changed a sector. + - The CLI opens the written backup to count items and sectors. It reseals sectors in + their new positions on restore, or leaves them in the file on a board without + passkeys. + - Host tests cover the exact copy, an identical restore that changes nothing, an older + file that leaves the passkeys alone, the refusal by a board without them or laid out + otherwise, and every way a session ends. + + Acceptance, still on the board: + 1. Take a fresh `.vkb`. + 2. authenticatorReset (the hold, within 10 s of plugging in). + 3. `sudo` asks for the password and the webauthn.io login fails. + 4. Restore the `.vkb`. The key restarts. + 5. `sudo` takes a tap and webauthn.io logs in again, with nothing enrolled anew. + 6. `check --wipe-everything`, the restore, the 1Password sync and `selftest`. + + **Accepted 2026-10-15**, all six in the order 6, 1-5: `check --wipe-everything` + green on the new image, the restore, the sync and `selftest` green; a backup of 48 + items "and the passkeys"; authenticatorReset erased them after the hold; `sudo` then + asked for the password and webauthn.io refused the login; the restore brought back 48 + items and the passkeys and the key restarted ("soft reset"); `sudo` took a tap and + webauthn.io logged in, nothing enrolled anew. Two `Broken pipe`s during the session + were the dongle's edge connector moving under a press (re-enumeration within a + second, the vault still unlocked), not the firmware. --- diff --git a/firmware/boards/esp32c6-zero/images/vaultkey.bin b/firmware/boards/esp32c6-zero/images/vaultkey.bin index 73d1d8ffd1341163e8cf847e4da1a515651c2cf5..83aba7294d696b8dcf0e178e2cba02b45a77ebd0 100644 GIT binary patch delta 18587 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 delta 18769 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 E0MyH7UjP6A diff --git a/firmware/boards/esp32c6-zero/src/main.rs b/firmware/boards/esp32c6-zero/src/main.rs index bbaa4cc..9dfcb3d 100644 --- a/firmware/boards/esp32c6-zero/src/main.rs +++ b/firmware/boards/esp32c6-zero/src/main.rs @@ -25,7 +25,7 @@ use esp_storage::FlashStorage; use smart_leds::{RGB8, SmartLedsWrite, brightness}; use static_cell::{ConstStaticCell, StaticCell}; use vaultkey_core::device::{self, Device}; -use vaultkey_core::hal::{Clock, DeviceKey, Port, Ui}; +use vaultkey_core::hal::{Clock, DeviceKey, NoAttachment, Port, Ui}; use vaultkey_core::proto::Proto; use vaultkey_core::store::{self, Layout, Store}; use vaultkey_core::ui::State; @@ -192,6 +192,7 @@ fn main() -> ! { trng, Uptime, ChipKey::detect(p.HMAC), + NoAttachment, KDF_COST, VAULT.init_with(store::Index::empty), BUF.take(), diff --git a/firmware/boards/nrf52840-mdk-dongle/board.toml b/firmware/boards/nrf52840-mdk-dongle/board.toml index 9476879..20da88b 100644 --- a/firmware/boards/nrf52840-mdk-dongle/board.toml +++ b/firmware/boards/nrf52840-mdk-dongle/board.toml @@ -17,6 +17,11 @@ usb_pid = 0x0001 # What is printed on the button the user is asked to press. button = "USER" +# It keeps passkeys (Trussed, src/fido.rs). A backup carries them, and `vkey restore` +# hands them only to a board that says this; another restores the items and names them +# as left in the file. +passkeys = true + # The radio peripheral's 4 KiB slot. Its driver ships inside the HAL crate, so the lock # file cannot show it is absent. tools/build-vaultkey.sh fails if anything in the image # reaches this address. diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin index c48a51a02b23ebd232054577e9610d7eb6f905b6..dc58fdc43738f96703afc562527c4d5cfc30233b 100755 GIT binary patch delta 46416 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⪙dtmBTQOd+hVZNQzF3a3*c23hVf47i^ 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 hTz0xYJSA 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 HlRWhwvndVgB$4%j_|7@;iRUzyJB) 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 HP<8(g^mE~D delta 86060 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 LrLOJm`}%(Y!kW-h diff --git a/firmware/boards/nrf52840-mdk-dongle/src/fido.rs b/firmware/boards/nrf52840-mdk-dongle/src/fido.rs index c693127..ee04b97 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/fido.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/fido.rs @@ -7,11 +7,12 @@ //! The keys live in Trussed's own littlefs at 0xD8000..0xEC000, apart from the vault and //! not sealed under the PIN; docs/threat-model.md says what that costs. -use core::cell::RefCell; +use core::cell::{Cell, RefCell}; use core::sync::atomic::{AtomicBool, Ordering}; use core::time::Duration; use cortex_m::peripheral::SCB; +use critical_section::Mutex; use ctaphid_dispatch::app::{self, App, Command}; use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; use fido_authenticator::{Authenticator, Config, TrussedRequirements, UserPresence}; @@ -34,7 +35,7 @@ use trussed_core::{Error, InterruptFlag}; use trussed_fs_info::FsInfoExtension; use trussed_hkdf::HkdfExtension; use trussed_staging::{StagingBackend, StagingContext}; -use vaultkey_core::hal::{Clock, Ui}; +use vaultkey_core::hal::{Attachment, Clock, Ui}; use vaultkey_core::ui::{self, State}; use crate::{CTAP_MESSAGE, Entropy, FS_LEN, Panel, Region, Uptime, UsbStack}; @@ -419,3 +420,137 @@ pub(crate) fn start( config, ))) } + +// --- the passkeys in a backup ---------------------------------------------------------- + +/// What a backup or a restore has done to Trussed's flash (`hal::Attachment`). +#[derive(Clone, Copy)] +enum Freeze { + /// Trussed's own: passkeys are served. + Thawed, + /// A backup or a restore has it; `dirty` once a sector was rewritten. + Frozen { dirty: bool }, + /// The host stopped talking mid-backup and the freeze was let go before anything + /// was written: passkeys are served again, and the session's next read fails. + Expired, + /// Rewritten: Trussed's mounted filesystem and fido's cached state are stale, so the + /// chip resets once the restore's answer has had time to leave. + Restart { at: u64 }, +} + +static FREEZE: Mutex> = Mutex::new(Cell::new(Freeze::Thawed)); + +fn freeze_state() -> Freeze { + critical_section::with(|cs| FREEZE.borrow(cs).get()) +} + +fn set_freeze(state: Freeze) { + critical_section::with(|cs| FREEZE.borrow(cs).set(state)); +} + +/// How long a backup or a restore may leave the vkey line silent before its freeze is +/// let go: a session runs frame after frame, and a host that died must not leave +/// passkeys and `sudo` dead until a replug. +const FREEZE_MS: u64 = 10_000; +/// How long the restore's last answer gets to reach the host before the reset. +const RESTART_MS: u64 = 300; + +/// Whether CTAP requests may be served now. +pub(crate) fn serving() -> bool { + matches!(freeze_state(), Freeze::Thawed | Freeze::Expired) +} + +/// Called on every look at the vkey line: lets a forgotten freeze go, and resets when +/// the region was rewritten. `last_rx` is when the last vkey byte came. +pub(crate) fn tend(now: u64, last_rx: u64) { + match freeze_state() { + Freeze::Frozen { dirty } if now - last_rx > FREEZE_MS => { + if dirty { + SCB::sys_reset(); + } + set_freeze(Freeze::Expired); + } + Freeze::Restart { at } if now - at > RESTART_MS => SCB::sys_reset(), + _ => {} + } +} + +/// Trussed's flash as a backup sees it: the same 4 KiB sectors littlefs uses, read and +/// written only while the freeze holds. +pub(crate) struct Backup(pub(crate) Region); + +const SECTOR: usize = 4096; + +impl Attachment for Backup { + fn sectors(&self) -> u32 { + FS_LEN / 4096 + } + + fn read(&mut self, i: u32, out: &mut [u8]) -> bool { + matches!(freeze_state(), Freeze::Frozen { .. }) + && out.len() == SECTOR + && i < self.sectors() + && self.0.read(i * 4096, out).is_ok() + } + + fn put(&mut self, i: u32, data: Option<&[u8]>) -> Option { + let Freeze::Frozen { .. } = freeze_state() else { + return None; + }; + if data.is_some_and(|d| d.len() != SECTOR) || i >= self.sectors() { + return None; + } + let at = i * 4096; + if self.holds(at, data)? { + return Some(false); + } + self.0.erase(at, at + 4096).ok()?; + // Dirty from the erase on: a sector half done is a rewritten one. + set_freeze(Freeze::Frozen { dirty: true }); + if let Some(data) = data { + self.0.write(at, data).ok()?; + } + Some(true) + } + + fn freeze(&mut self) { + // A restart still owed - a restore rewrote the region just before - is carried + // into this session, so its end resets rather than hand Trussed a stale region. + let owed = matches!( + freeze_state(), + Freeze::Restart { .. } | Freeze::Frozen { dirty: true } + ); + set_freeze(Freeze::Frozen { dirty: owed }); + } + + fn thaw(&mut self, changed: bool) { + let dirty = matches!(freeze_state(), Freeze::Frozen { dirty: true }); + set_freeze(if changed || dirty { + Freeze::Restart { + at: Uptime.now_ms(), + } + } else { + Freeze::Thawed + }); + } +} + +impl Backup { + /// Whether the sector at `at` already holds `data`, or is blank when `data` is + /// None: compared a little at a time, without a sector-sized buffer on the stack. + fn holds(&mut self, at: u32, data: Option<&[u8]>) -> Option { + let mut chunk = [0u8; 64]; + for (n, start) in (0..SECTOR).step_by(chunk.len()).enumerate() { + let offset = at + u32::try_from(n * chunk.len()).ok()?; + self.0.read(offset, &mut chunk).ok()?; + let same = match data { + Some(d) => chunk == d[start..start + chunk.len()], + None => chunk.iter().all(|&b| b == 0xFF), + }; + if !same { + return Some(false); + } + } + Some(true) + } +} diff --git a/firmware/boards/nrf52840-mdk-dongle/src/main.rs b/firmware/boards/nrf52840-mdk-dongle/src/main.rs index 139da4d..ecf1f47 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/main.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/main.rs @@ -233,7 +233,10 @@ impl Port for Usb { let now = Uptime.now_ms(); if byte.is_some() { self.last_rx = now; - } else if now - self.last_rx > Self::QUIET_MS { + } + fido::tend(now, self.last_rx); + // Not while a backup or a restore has the passkeys' flash: CTAP requests wait. + if byte.is_none() && now - self.last_rx > Self::QUIET_MS && fido::serving() { // Outside the stack's borrow: a passkey's tap wait polls the bus itself. let passkeys: &mut dyn App<'static> = &mut *self.passkeys; self.fido.poll(&mut [passkeys]); @@ -669,6 +672,13 @@ fn main() -> ! { base: VAULT_LEN, len: FS_LEN, }; + // The same flash again, for the backup to carry: never at once with Trussed, which + // the backup's freeze keeps off it. + let passkey_backup = Region { + flash, + base: VAULT_LEN, + len: FS_LEN, + }; let mut dev = Device::new( Store::new(vault, LAYOUT), @@ -676,6 +686,7 @@ fn main() -> ! { rng, Uptime, NoChipKey, + fido::Backup(passkey_backup), KDF_COST, VAULT.init_with(store::Index::empty), BUF.take(), diff --git a/firmware/core/src/device.rs b/firmware/core/src/device.rs index 2f12db5..b8afdcb 100644 --- a/firmware/core/src/device.rs +++ b/firmware/core/src/device.rs @@ -10,13 +10,14 @@ use embedded_storage::nor_flash::NorFlash; use rand_core::{CryptoRng, RngCore}; use zeroize::{Zeroize, Zeroizing}; -use crate::hal::{Clock, DeviceKey, Ui}; +use crate::hal::{Attachment, Clock, DeviceKey, Ui}; use crate::item::{Category, Class, Item, Writer}; use crate::oath::{self, NAME_MAX, Name, Params, len_u8}; -use crate::store::{Header, ITEM_BUF_LEN, Index, MAX_ATTEMPTS, Slot, Store, StoredName}; +use crate::store::{self, Header, ITEM_BUF_LEN, Index, MAX_ATTEMPTS, Slot, Store, StoredName}; use crate::ui; use crate::vault::{ - self, BACKUP_AAD, Block, Cost, KDF_BLOCKS, KEY_LEN, Keys, NONCE_LEN, Passphrase, Pin, SALT_LEN, + self, BACKUP_AAD, Block, Cost, KDF_BLOCKS, KEY_LEN, Keys, NONCE_LEN, Passphrase, Pin, + REGION_AAD, REGION_HEAD, SALT_LEN, }; use crate::wire::{BackupHead, Fail, HAS_OPEN, HAS_SECRET, HAS_SEED, PinStatus}; @@ -75,11 +76,13 @@ impl Reach { } /// A backup in flight: the passphrase key, and how far it got. Ended by the last item, -/// by a lock, or by any operation that reloads the index it walks. +/// by a lock, or by any operation that reloads the index it walks - always through +/// `end_session`, which lets the board's attachment go. enum Session { Export { key: Dek, - /// The index position to look at next. + /// What to look at next: an index position, and past the last item the + /// attachment's sectors, counted on from there. slot: usize, /// Items handed out so far: the next one's position in the file. item: u32, @@ -87,15 +90,33 @@ enum Session { Import { key: Dek, item: u32, + /// The first sector the next one may be, once a sector has come; None while + /// the file is still on items. + sector: Option, + /// Whether a sector was rewritten: the board restarts what uses them. + changed: bool, }, } -pub struct Device<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> { +/// A sector of the attachment, as `store` counts them. +const SECTOR_LEN: usize = store::SECTOR as usize; + +pub struct Device< + 'm, + F: NorFlash, + R: RngCore + CryptoRng, + U: Ui, + C: Clock, + K: DeviceKey, + A: Attachment, +> { store: Store, ui: U, rng: R, clock: C, key: K, + /// What a backup carries besides the items, on a board that has it. + attachment: A, /// What a new vault and a new backup are derived at: the board's measure of about a /// second. An existing vault opens at the cost its header records. cost: Cost, @@ -127,8 +148,22 @@ fn item_aad(item: u32) -> [u8; BACKUP_AAD.len() + 4] { aad } -impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> - Device<'m, F, R, U, C, K> +/// `REGION_AAD` followed by the sector's position in the file. +fn region_aad(item: u32) -> [u8; REGION_AAD.len() + 4] { + let mut aad = [0u8; REGION_AAD.len() + 4]; + aad[..REGION_AAD.len()].copy_from_slice(REGION_AAD); + aad[REGION_AAD.len()..].copy_from_slice(&item.to_le_bytes()); + aad +} + +/// A little-endian u32 at `at` in `bytes`. +fn le_u32(bytes: &[u8], at: usize) -> Option { + let word = bytes.get(at..at + 4)?; + Some(u32::from_le_bytes(word.try_into().ok()?)) +} + +impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey, A: Attachment> + Device<'m, F, R, U, C, K, A> { #[expect( clippy::too_many_arguments, @@ -140,6 +175,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> rng: R, clock: C, key: K, + attachment: A, cost: Cost, index: &'m mut Index, buf: &'m mut [u8; BUF_LEN], @@ -151,6 +187,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> rng, clock, key, + attachment, cost, index, buf, @@ -177,11 +214,30 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> pub fn lock(&mut self) { self.dek = None; // Zeroizing scrubs it on drop - self.backup = None; + self.end_session(); self.store.save_abort(); self.buf.zeroize(); } + /// A backup or a restore begins: the board keeps its own user of the attachment off + /// it until `end_session`. + fn start_session(&mut self, session: Session) { + self.end_session(); + self.attachment.freeze(); + self.backup = Some(session); + } + + /// The backup or restore in flight, if any, is over, however it ended, and the + /// board's attachment is let go - told whether a restore rewrote it. Every way a + /// session ends comes through here. + fn end_session(&mut self) { + match self.backup.take() { + Some(Session::Import { changed, .. }) => self.attachment.thaw(changed), + Some(Session::Export { .. }) => self.attachment.thaw(false), + None => {} + } + } + /// Factory reset: every secret and the PIN. Confirmed by the longest hold, never by /// the tap that approves a code. Whoever holds the key can empty it anyway (eight /// wrong PINs, or the flash tools); this protects the owner who did not mean to. @@ -205,7 +261,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> /// nothing gets written over it without `wipe`. A backup in flight walks the index /// as it was when it began; reloading ends it. fn load(&mut self) -> Result<(), Fail> { - self.backup = None; + self.end_session(); self.store.save_abort(); self.store.load(self.index).map_err(|_| Fail::Internal) } @@ -709,7 +765,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> let cost = self.cost; let key = with_kdf_memory(|mem| vault::backup_key(pass, &salt, cost, mem)) .ok_or(Fail::Internal)?; - self.backup = Some(Session::Export { + self.start_session(Session::Export { key, slot: 0, item: 0, @@ -732,7 +788,7 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> } self.buf.zeroize(); if !matches!(r, Ok(Some(_))) { - self.backup = None; + self.end_session(); } r.map(|_| self.touch()) } @@ -746,7 +802,8 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> }; let (key, at, item) = (Zeroizing::new(**key), *slot, *item); if at >= self.index.len() { - return Ok(None); + let first = u32::try_from(at - self.index.len()).map_err(|_| Fail::Internal)?; + return self.export_sector(&key, first, item); } let slot = *self.index.get(at).ok_or(Fail::Internal)?; let name = StoredName::of(slot.name()); @@ -781,14 +838,55 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> vault::seal_in_place(&key, &mut self.rng, &item_aad(item), work, total) .ok_or(Fail::Internal)? }; - self.backup = Some(Session::Export { - key, - slot: at + 1, - item: item + 1, - }); + self.advance_export(at + 1); Ok(Some(sealed)) } + /// The export moves on to `slot`, one more item handed out. + fn advance_export(&mut self, next: usize) { + if let Some(Session::Export { slot, item, .. }) = &mut self.backup { + *slot = next; + *item += 1; + } + } + + /// The first sector of the attachment from `first` on that is not blank, sealed into + /// the working half: its length, or None once there are no more. A blank sector is + /// not carried; a restore makes every sector the file leaves out blank. + fn export_sector( + &mut self, + key: &[u8; KEY_LEN], + first: u32, + item: u32, + ) -> Result, Fail> { + let count = self.attachment.sectors(); + for sector in first..count { + let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); + let data = &mut work[NONCE_LEN + REGION_HEAD..NONCE_LEN + REGION_HEAD + SECTOR_LEN]; + if !self.attachment.read(sector, data) { + return Err(Fail::Internal); + } + if data.iter().all(|&b| b == 0xFF) { + continue; + } + work[NONCE_LEN..NONCE_LEN + 4].copy_from_slice(&store::SECTOR.to_le_bytes()); + work[NONCE_LEN + 4..NONCE_LEN + 8].copy_from_slice(&count.to_le_bytes()); + work[NONCE_LEN + 8..NONCE_LEN + 12].copy_from_slice(§or.to_le_bytes()); + let sealed = vault::seal_in_place( + key, + &mut self.rng, + ®ion_aad(item), + work, + REGION_HEAD + SECTOR_LEN, + ) + .ok_or(Fail::Internal)?; + let next = usize::try_from(sector).map_err(|_| Fail::Internal)?; + self.advance_export(self.index.len() + next + 1); + return Ok(Some(sealed)); + } + Ok(None) + } + /// Starts a restore: the key for `pass` as the backup's head describes it, and a /// fresh image to write the items into. The PIN is enough, like `put`: nothing /// comes out. Everything already stored is replaced - a restore is a restore. @@ -800,7 +898,12 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> self.store .save_begin(self.index.header.as_ref()) .map_err(|_| Fail::Internal)?; - self.backup = Some(Session::Import { key, item: 0 }); + self.start_session(Session::Import { + key, + item: 0, + sector: None, + changed: false, + }); self.touch(); Ok(()) } @@ -809,38 +912,51 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> /// being written and become visible together at `import_end`; any failure ends the /// restore and leaves what was there before, because the new image never got its /// magic word. + /// + /// The attachment's sectors come after the items and are written in place as they + /// arrive - there is no second copy of them to switch to. A restore cut short leaves + /// that region torn, and the board formats it on its next start; the file still + /// holds it. A file with no sectors leaves the region as it was. pub fn import_item(&mut self, sealed: &[u8]) -> Result<(), Fail> { let dek = self.dek()?; - let Some(Session::Import { key, item }) = &self.backup else { + let Some(Session::Import { + key, item, sector, .. + }) = &self.backup + else { return Err(Fail::BadBackup); }; - let (key, item) = (Zeroizing::new(**key), *item); - let r = self.import_sealed(&dek, &key, item, sealed); + let (key, item, sector) = (Zeroizing::new(**key), *item, *sector); + let r = self.import_sealed(&dek, &key, item, sector, sealed); self.buf.zeroize(); match r { - Ok(()) => { - self.backup = Some(Session::Import { - key, - item: item + 1, - }); + Ok(next) => { + if let Some(Session::Import { item, sector, .. }) = &mut self.backup { + *item += 1; + if next.is_some() { + *sector = next; + } + } self.touch(); Ok(()) } Err(f) => { - self.backup = None; + self.end_session(); self.store.save_abort(); Err(f) } } } + /// An item, or a sector of the attachment: for a sector, the first sector the next + /// one may be. fn import_sealed( &mut self, dek: &[u8; KEY_LEN], key: &[u8; KEY_LEN], item: u32, + sector: Option, sealed: &[u8], - ) -> Result<(), Fail> { + ) -> Result, Fail> { if sealed.len() > ITEM_BUF_LEN { return Err(Fail::BadBackup); } @@ -848,8 +964,14 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); work[..sealed.len()].copy_from_slice(sealed); vault::open_in_place(key, &item_aad(item), &mut work[..sealed.len()]) - .ok_or(Fail::BadBackup)? }; + let Some(n) = n else { + return self.import_region(key, item, sector, sealed).map(Some); + }; + // Items come before sectors; one after them was never written by a backup. + if sector.is_some() { + return Err(Fail::BadBackup); + } // `category | name_len | name | item`, as `export_item` packed it. let (category, name, body_at, body_len) = { let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); @@ -876,17 +998,85 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> self.store .save_put(name.get(), category, &work[..resealed]) .map_err(|_| Fail::Full) + .map(|()| None) } - /// The restored items become the image, and the restore is over. + /// A sector of the attachment back in its place, every sector the file skipped + /// before it made blank: the sector after it. Refused by a board without the + /// attachment, or laid out differently from the one the file came from, and out + /// of order. + fn import_region( + &mut self, + key: &[u8; KEY_LEN], + item: u32, + sector: Option, + sealed: &[u8], + ) -> Result { + let count = self.attachment.sectors(); + if count == 0 { + return Err(Fail::BadBackup); + } + let at = { + let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); + work[..sealed.len()].copy_from_slice(sealed); + let n = vault::open_in_place(key, ®ion_aad(item), &mut work[..sealed.len()]) + .ok_or(Fail::BadBackup)?; + let plain = &work[NONCE_LEN..NONCE_LEN + n]; + if n != REGION_HEAD + SECTOR_LEN + || le_u32(plain, 0) != Some(store::SECTOR) + || le_u32(plain, 4) != Some(count) + { + return Err(Fail::BadBackup); + } + le_u32(plain, 8).ok_or(Fail::BadBackup)? + }; + let from = sector.unwrap_or(0); + if at < from || at >= count { + return Err(Fail::BadBackup); + } + for blank in from..at { + self.region_blank(blank)?; + } + let changed = { + let (work, _) = self.buf.split_at_mut(ITEM_BUF_LEN); + let data = &work[NONCE_LEN + REGION_HEAD..NONCE_LEN + REGION_HEAD + SECTOR_LEN]; + self.attachment.put(at, Some(data)).ok_or(Fail::Internal)? + }; + self.region_changed(changed); + Ok(at + 1) + } + + fn region_blank(&mut self, sector: u32) -> Result<(), Fail> { + let changed = self.attachment.put(sector, None).ok_or(Fail::Internal)?; + self.region_changed(changed); + Ok(()) + } + + /// Noted at once, so a restore that fails later still has the board restart. + fn region_changed(&mut self, now: bool) { + if let Some(Session::Import { changed, .. }) = &mut self.backup { + *changed |= now; + } + } + + /// The restored items become the image, the sectors after the last one the file + /// carried are made blank, and the restore is over. pub fn import_end(&mut self) -> Result<(), Fail> { - let Some(Session::Import { .. }) = &self.backup else { + let Some(Session::Import { sector, .. }) = &self.backup else { return Err(Fail::BadBackup); }; - self.backup = None; - self.store - .save_finish(self.index) - .map_err(|_| Fail::Internal)?; + if let Some(from) = *sector { + for blank in from..self.attachment.sectors() { + if let Err(f) = self.region_blank(blank) { + self.end_session(); + self.store.save_abort(); + return Err(f); + } + } + } + let r = self.store.save_finish(self.index); + self.end_session(); + r.map_err(|_| Fail::Internal)?; self.touch(); Ok(()) } diff --git a/firmware/core/src/hal.rs b/firmware/core/src/hal.rs index 2c92628..5d93646 100644 --- a/firmware/core/src/hal.rs +++ b/firmware/core/src/hal.rs @@ -1,4 +1,4 @@ -//! What a board must provide. Deliberately tiny: four traits with one job each, so a +//! What a board must provide. Deliberately tiny: five traits with one job each, so a //! new board is a page of glue, not a port of the firmware. //! //! Flash and entropy use the ecosystem traits directly @@ -34,6 +34,51 @@ pub trait Ui { } } +/// Flash the board keeps for something besides the vault - the nRF52840's passkeys - +/// which a backup carries sealed like the items and a restore puts back, sector by +/// 4 KiB sector (`store::SECTOR`). A board with nothing of the kind uses +/// [`NoAttachment`]. +/// +/// While a backup or a restore runs, the board keeps its own user of the region off it +/// (`freeze`), so the copy is never torn and a restore never writes under a live +/// filesystem; it lets go at `thaw`, and after a restore that changed the region it +/// restarts that user. A board may also let go on its own, when the host stops talking +/// mid-session; reads and writes then fail, which ends the session. +pub trait Attachment { + /// How many sectors it has. + fn sectors(&self) -> u32; + /// Sector `i` into `out`, `SECTOR` bytes. False when it cannot be read, or the + /// freeze is no longer held. + fn read(&mut self, i: u32, out: &mut [u8]) -> bool; + /// Sector `i` made to hold `data`, `SECTOR` bytes, or blank when `None`: whether it + /// changed, or None when it could not be written. + fn put(&mut self, i: u32, data: Option<&[u8]>) -> Option; + fn freeze(&mut self); + fn thaw(&mut self, changed: bool); +} + +/// The attachment of a board without one: no sectors, so a backup carries none and a +/// restore refuses any it is handed. +pub struct NoAttachment; + +impl Attachment for NoAttachment { + fn sectors(&self) -> u32 { + 0 + } + + fn read(&mut self, _: u32, _: &mut [u8]) -> bool { + false + } + + fn put(&mut self, _: u32, _: Option<&[u8]>) -> Option { + None + } + + fn freeze(&mut self) {} + + fn thaw(&mut self, _: bool) {} +} + /// A secret only this chip has, mixed into the key derivation so that a copy of the /// flash is worthless without the chip: HMAC-SHA256 under a key the chip can use but /// software never reads, such as one burned into its fuses. diff --git a/firmware/core/src/proto.rs b/firmware/core/src/proto.rs index 22238af..76566c1 100644 --- a/firmware/core/src/proto.rs +++ b/firmware/core/src/proto.rs @@ -12,7 +12,7 @@ use rand_core::{CryptoRng, RngCore}; use zeroize::Zeroizing; use crate::device::{Device, Reach}; -use crate::hal::{Clock, DeviceKey, Port, Ui}; +use crate::hal::{Attachment, Clock, DeviceKey, Port, Ui}; use crate::item::{Category, ITEM_MAX}; use crate::oath::{NAME_MAX, Name, len_u8}; use crate::store::MAX_ENTRIES; @@ -149,13 +149,14 @@ impl Proto { } /// Runs forever, one request at a time. - pub fn run(&mut self, dev: &mut Device<'_, F, R, U, DC, K>) -> ! + pub fn run(&mut self, dev: &mut Device<'_, F, R, U, DC, K, A>) -> ! where F: NorFlash, R: RngCore + CryptoRng, U: Ui, DC: Clock, K: DeviceKey, + A: Attachment, { loop { self.await_magic(); @@ -186,13 +187,18 @@ impl Proto { clippy::too_many_lines, reason = "one match over every wire command; splitting it would scatter the dispatch that is meant to be read in one place" )] - fn handle(&mut self, dev: &mut Device<'_, F, R, U, DC, K>, cmd: Cmd, p: &[u8]) - where + fn handle( + &mut self, + dev: &mut Device<'_, F, R, U, DC, K, A>, + cmd: Cmd, + p: &[u8], + ) where F: NorFlash, R: RngCore + CryptoRng, U: Ui, DC: Clock, K: DeviceKey, + A: Attachment, { match cmd { Cmd::Info => self.respond(OK, self.version.as_bytes()), diff --git a/firmware/core/src/vault.rs b/firmware/core/src/vault.rs index b3bf7d6..fa93e6a 100644 --- a/firmware/core/src/vault.rs +++ b/firmware/core/src/vault.rs @@ -51,6 +51,14 @@ pub const ENV_KEY_AAD: &[u8] = b"vaultkey/env-key/v1"; /// What a backup item is sealed under, followed by its position in the file: an item /// moved, repeated or dropped from the middle fails to open on the way back in. pub const BACKUP_AAD: &[u8] = b"vaultkey/backup/v1"; +/// What a sector of the board's attachment (`hal::Attachment`, the nRF52840's passkeys) +/// is sealed under in a backup, followed like an item by its position in the file: +/// never read as an item, never moved unnoticed. Sectors come after the items. +pub const REGION_AAD: &[u8] = b"vaultkey/backup-region/v1"; +/// A sealed sector's plaintext starts `sector_size u32le | sector_count u32le | index +/// u32le`, then the sector: a board laid out differently refuses it rather than write +/// a filesystem that would not mount. +pub const REGION_HEAD: usize = 12; /// Argon2id cost: memory in KiB and passes over it. Stored per vault and per backup, so /// a board can change its own without breaking either. diff --git a/firmware/core/tests/key.rs b/firmware/core/tests/key.rs index eabbe3a..74b457f 100644 --- a/firmware/core/tests/key.rs +++ b/firmware/core/tests/key.rs @@ -15,7 +15,7 @@ use hmac::{Hmac, KeyInit, Mac}; use rand_core::{CryptoRng, RngCore}; use sha2::Sha256; use vaultkey_core::device::{self, Device, Reach}; -use vaultkey_core::hal::{Clock, DeviceKey, Ui}; +use vaultkey_core::hal::{Attachment, Clock, DeviceKey, NoAttachment, Ui}; use vaultkey_core::item::{Category, Class, Field, FieldKind, Item, Writer}; use vaultkey_core::oath::{Algo, Digits, Name, Params}; use vaultkey_core::store::{self, Layout, MAX_ATTEMPTS, Store}; @@ -185,6 +185,23 @@ impl MemFlash { /// Power on with a finger on the button and, maybe, a chip key. fn key_with(&self, button: Button, clock: Ticker, key: K) -> Key { + self.key_full(button, clock, key, NoAttachment) + } + + /// Power on a board that keeps passkeys beside the vault, its finger tapping twice. + fn key_attached(&self, passkeys: &Passkeys) -> Key { + let clock = Ticker::default(); + let button = Button::new(&clock, Finger::DoubleTap { gap: 120 }); + self.key_full(button, clock, Unbound, passkeys.clone()) + } + + fn key_full( + &self, + button: Button, + clock: Ticker, + key: K, + attachment: A, + ) -> Key { // The index and the buffer outlive the device, as on the board. let index = Box::leak(Box::new(store::Index::empty())); let buf: Box<[u8; device::BUF_LEN]> = vec![0u8; device::BUF_LEN] @@ -198,6 +215,7 @@ impl MemFlash { Repeatable(7), clock, key, + attachment, COST, index, buf, @@ -205,6 +223,88 @@ impl MemFlash { } } +/// A board's passkey flash, faked: its sectors, and what the device did with the +/// freeze - whether it holds, and every thaw with whether it was told of a change. +#[derive(Clone)] +struct Passkeys(Rc>); + +struct PasskeyState { + sectors: Vec>, + frozen: bool, + /// The board let go on its own: reads and writes fail. + expired: bool, + thaws: Vec, +} + +const SECTOR: usize = store::SECTOR as usize; + +impl Passkeys { + fn blank(count: usize) -> Self { + Passkeys(Rc::new(RefCell::new(PasskeyState { + sectors: vec![vec![0xFF; SECTOR]; count], + frozen: false, + expired: false, + thaws: Vec::new(), + }))) + } + + fn fill(&self, sector: usize, byte: u8) -> &Self { + self.0.borrow_mut().sectors[sector] = vec![byte; SECTOR]; + self + } + + /// Each sector as the byte it is filled with, 0xFF for blank. + fn bytes(&self) -> Vec { + self.0.borrow().sectors.iter().map(|s| s[0]).collect() + } + + fn frozen(&self) -> bool { + self.0.borrow().frozen + } + + fn last_thaw(&self) -> Option { + self.0.borrow().thaws.last().copied() + } +} + +impl Attachment for Passkeys { + fn sectors(&self) -> u32 { + u32::try_from(self.0.borrow().sectors.len()).expect("a few") + } + + fn read(&mut self, i: u32, out: &mut [u8]) -> bool { + let s = self.0.borrow(); + if !s.frozen || s.expired { + return false; + } + out.copy_from_slice(&s.sectors[i as usize]); + true + } + + fn put(&mut self, i: u32, data: Option<&[u8]>) -> Option { + let mut s = self.0.borrow_mut(); + if !s.frozen || s.expired { + return None; + } + let want = data.map_or_else(|| vec![0xFF; SECTOR], <[u8]>::to_vec); + let changed = s.sectors[i as usize] != want; + s.sectors[i as usize] = want; + Some(changed) + } + + fn freeze(&mut self) { + let mut s = self.0.borrow_mut(); + s.frozen = true; + s.expired = false; + } + + fn thaw(&mut self, changed: bool) { + let mut s = self.0.borrow_mut(); + s.frozen = false; + s.thaws.push(changed); + } +} + /// Not random on purpose: a failing test must fail the same way twice. struct Repeatable(u64); @@ -364,7 +464,8 @@ impl Ui for Button { } } -type Key = Device<'static, MemFlash, Repeatable, Button, Ticker, K>; +type Key = + Device<'static, MemFlash, Repeatable, Button, Ticker, K, A>; // --- helpers --------------------------------------------------------------------------- @@ -436,8 +537,8 @@ fn totp_item(secret: &[u8]) -> Vec { ) } -fn put( - dev: &mut Key, +fn put( + dev: &mut Key, n: &str, category: Category, item: &[u8], @@ -487,7 +588,7 @@ fn code(dev: &mut Key, n: &str, t: u64) -> Result Ok(String::from_utf8_lossy(&out[..len]).into_owned()) } -fn names(dev: &mut Key) -> Result, Fail> { +fn names(dev: &mut Key) -> Result, Fail> { let mut out = Vec::new(); dev.list(|n, _| out.push(String::from_utf8_lossy(n.as_bytes()).into_owned()))?; Ok(out) @@ -517,7 +618,10 @@ fn passphrase(s: &str) -> Passphrase<'_> { Passphrase::new(s.as_bytes()).expect("a valid test passphrase") } -fn export(dev: &mut Key, pass: &str) -> Result<(BackupHead, Vec>), Fail> { +fn export( + dev: &mut Key, + pass: &str, +) -> Result<(BackupHead, Vec>), Fail> { let head = dev.export_begin(passphrase(pass))?; let mut items = Vec::new(); loop { @@ -530,8 +634,8 @@ fn export(dev: &mut Key, pass: &str) -> Result<(BackupHead, Vec } } -fn import( - dev: &mut Key, +fn import( + dev: &mut Key, pass: &str, head: BackupHead, items: &[Vec], @@ -1425,6 +1529,161 @@ fn a_backup_refuses_the_wrong_passphrase_and_a_reordered_file() { ); } +// --- passkeys in a backup ----------------------------------------------------------------- + +const PASS: &str = "correct horse battery staple"; + +/// A board with passkeys in sectors 1 and 3 of four, a PIN and one item. +fn board_with_passkeys() -> (MemFlash, Passkeys, Key) { + let flash = MemFlash::blank(); + let passkeys = Passkeys::blank(4); + passkeys.fill(1, 0x11).fill(3, 0x33); + let mut dev = flash.key_attached(&passkeys); + dev.pin_set(pin("12345678")).expect("sets the PIN"); + put( + &mut dev, + "github.com", + Category::Login, + &login_item("me", "pw"), + false, + ) + .expect("stores"); + (flash, passkeys, dev) +} + +#[test] +fn passkeys_go_into_a_backup_and_come_back_exactly() { + let (_, passkeys, mut dev) = board_with_passkeys(); + let (head, blobs) = export(&mut dev, PASS).expect("exports"); + assert_eq!( + blobs.len(), + 3, + "one item and the two sectors that are not blank" + ); + assert!(!passkeys.frozen(), "and the passkeys are served again"); + + let target = Passkeys::blank(4); + target.fill(0, 0x55).fill(2, 0x77); + let other_flash = MemFlash::blank(); + let mut other = other_flash.key_attached(&target); + other.pin_set(pin("87654321")).expect("sets the PIN"); + import(&mut other, PASS, head, &blobs).expect("restores"); + assert_eq!( + target.bytes(), + [0xFF, 0x11, 0xFF, 0x33], + "the copy exactly: what the file skipped is blank, whatever was there" + ); + assert_eq!( + target.last_thaw(), + Some(true), + "told it changed: the board restarts" + ); + assert_eq!(names(&mut other).expect("lists"), ["github.com"]); + + import(&mut other, PASS, head, &blobs).expect("restores again"); + assert_eq!( + target.last_thaw(), + Some(false), + "the same passkeys again change nothing, so nothing restarts" + ); +} + +#[test] +fn a_backup_without_passkeys_leaves_them_alone() { + let flash = MemFlash::blank(); + let mut plain = double_tapping(&flash); + plain.pin_set(pin("12345678")).expect("sets the PIN"); + put( + &mut plain, + "github.com", + Category::Login, + &login_item("me", "pw"), + false, + ) + .expect("stores"); + let (head, blobs) = export(&mut plain, PASS).expect("exports"); + + let (_, passkeys, mut dev) = board_with_passkeys(); + import(&mut dev, PASS, head, &blobs).expect("restores"); + assert_eq!( + passkeys.bytes(), + [0xFF, 0x11, 0xFF, 0x33], + "an older backup, or one from the C6, keeps the passkeys there are" + ); + assert_eq!(passkeys.last_thaw(), Some(false)); +} + +#[test] +fn a_board_without_passkeys_or_laid_out_otherwise_refuses_them() { + let (_, _, mut dev) = board_with_passkeys(); + let (head, blobs) = export(&mut dev, PASS).expect("exports"); + + let flash = MemFlash::blank(); + let mut plain = tapping(&flash); + plain.pin_set(pin("12345678")).expect("sets the PIN"); + assert_eq!( + import(&mut plain, PASS, head, &blobs), + Err(Fail::BadBackup), + "a board with nowhere to put passkeys says so rather than drop them" + ); + + let wider = Passkeys::blank(5); + wider.fill(4, 0x44); + let other_flash = MemFlash::blank(); + let mut other = other_flash.key_attached(&wider); + other.pin_set(pin("12345678")).expect("sets the PIN"); + assert_eq!(import(&mut other, PASS, head, &blobs), Err(Fail::BadBackup)); + assert_eq!( + wider.bytes(), + [0xFF, 0xFF, 0xFF, 0xFF, 0x44], + "a filesystem of another size would not mount: nothing of it is written" + ); + assert!(!wider.frozen()); +} + +#[test] +fn every_way_a_session_ends_lets_the_passkeys_go() { + let (_, passkeys, mut dev) = board_with_passkeys(); + + dev.export_begin(passphrase(PASS)).expect("begins"); + assert!(passkeys.frozen(), "held from the double tap on"); + dev.lock(); + assert!(!passkeys.frozen(), "a lock ends it"); + + dev.pin_unlock(pin("12345678")).expect("unlocks"); + dev.export_begin(passphrase(PASS)).expect("begins"); + names(&mut dev).expect("lists"); + assert!( + !passkeys.frozen(), + "anything that reloads the index ends it" + ); + + let (head, blobs) = export(&mut dev, PASS).expect("exports"); + dev.import_begin(passphrase(PASS), head).expect("begins"); + assert!(passkeys.frozen(), "a restore holds it too"); + assert_eq!( + dev.import_item(&blobs[2]), + Err(Fail::BadBackup), + "out of order" + ); + assert!(!passkeys.frozen(), "and a refused item ends it"); + + dev.import_begin(passphrase(PASS), head).expect("begins"); + dev.import_end().expect("an empty restore"); + assert!(!passkeys.frozen(), "as does the end"); + + dev.export_begin(passphrase(PASS)).expect("begins"); + let mut item = Vec::new(); + dev.export_next(|b| item = b.to_vec()).expect("the item"); + passkeys.0.borrow_mut().expired = true; + assert_eq!( + dev.export_next(|_| {}), + Err(Fail::Internal), + "a board that let go mid-backup gives no sector, so no copy is torn" + ); + assert!(!passkeys.frozen()); +} + // --- the shape of a reach on the wire ------------------------------------------------------- #[test] From ca39ca7c9c3b1217bd11b76fc9e913634c7a5164 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 23:25:08 +0300 Subject: [PATCH 19/33] Sign the C6's images again with its key restored onto the nRF52840 vkey-signing came onto the nRF from the C6's .vkb through restore --only, so the C6's app and Secure Boot bootloader are signed without touching the C6. The signed app returns to board.toml and vkey setup takes a Secure Boot chip again. --- CLAUDE.md | 6 +++--- docs/hardware.md | 10 +++++----- docs/threat-model.md | 4 ++++ docs2/roadmap.md | 5 ++++- firmware/boards/esp32c6-zero/board.toml | 13 ++++--------- .../images/bootloader-sb.signed.bin | Bin 45056 -> 45056 bytes .../esp32c6-zero/images/vaultkey.signed.bin | Bin 0 -> 192512 bytes 7 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 firmware/boards/esp32c6-zero/images/vaultkey.signed.bin diff --git a/CLAUDE.md b/CLAUDE.md index 0ecb135..b1fed33 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -160,9 +160,9 @@ The boards: info` prints the chip's build code, UICR `APPROTECT` and last reset cause. Notes, measurements and factory state: `docs2/makerdiary.md`; the plan: `docs2/roadmap.md`. - **`esp32c6-zero`**, the test board (2026-10-14): nothing is built for it, and it takes - `check --wipe-everything` for core changes. Its signed app image left the repository on - 2026-10-15, when the core changed while the C6 was left alone; `vkey setup` refuses a - Secure Boot chip until `tools/sign-vaultkey.sh` runs on it again. Secure Boot v2 is burned, so before its + `check --wipe-everything` for core changes. Its images are signed by + `tools/sign-vaultkey.sh` with `vkey-signing`, which also lives on the nRF since + 2026-10-15, so a core change is signed without touching the C6. Secure Boot v2 is burned, so before its first wipe a `.vkb` holding `vkey-signing` (its Secure Boot key) must exist: losing that key ends its updates for good. USB is a fixed Serial/JTAG (`303a:1001`), HID is impossible, so passkey will never exist here; one port carries both the protocol and logs — hence the `VTC2` magic word in diff --git a/docs/hardware.md b/docs/hardware.md index 541d20d..8e5e543 100644 --- a/docs/hardware.md +++ b/docs/hardware.md @@ -212,11 +212,11 @@ Signing costs a PIN and a tap (`tools/sign-vaultkey.sh`), which writes board that trusts it; leaking it removes Secure Boot. Public half and digest: `firmware/secure-boot/public.pem` and `digest.bin`, in the repository. `images/vaultkey.bin` stays unsigned and reproducible (a hook rebuilds and compares), with `vaultkey.signed.bin` -beside it, verified by the hook with the public key. Since 2026-10-15 it is not: the core -changed for the nRF52840's passkeys while this board was left alone, so the stale signed -app left the repository and its `board.toml` entry was commented out. `vkey setup` -refuses a Secure Boot chip until `tools/sign-vaultkey.sh` runs with this board plugged in -and the entry is restored. +beside it, verified by the hook with the public key. Since 2026-10-15 the key also lives +on the nRF52840 (added from a `.vkb` by `vkey restore --only vkey-signing`), so +`tools/sign-vaultkey.sh` signs this board's images with the nRF plugged in and this board +left alone. For one day the signed app was out of the repository, after a core change +this board was not there to sign. **A fork enables Secure Boot with its own key, never this one.** The private half exists only on the maintainer's device, so the committed `public.pem`, `digest.bin` and diff --git a/docs/threat-model.md b/docs/threat-model.md index ea77724..843c3b1 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -59,6 +59,10 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure Whoever has the key signs firmware the fork runs. By design, the fork moves to a new key only through a self-update signed with the old one. A leak is mended only while the owner still holds the key. +- **The C6's Secure Boot key lives here too** (since 2026-10-15): `vkey-signing`, added + from the C6's `.vkb` by `vkey restore --only`, so the C6's images are signed without + touching the C6. Whoever takes it off this board signs firmware the C6 boots; the C6 + holds no real secrets, and its own copy stays where it was. - **A backup made on this board uses its own cost** (20 passes). It is still guarded by the passphrase's entropy, at less than half the C6's work per guess. - **Passkeys (FIDO2) live outside the vault** (since 2026-10-15, roadmap phase 6). diff --git a/docs2/roadmap.md b/docs2/roadmap.md index 97ad72b..a3639b2 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -576,6 +576,8 @@ moves but the keys: `vkey restore --only vkey-signing ` (2026-10-15) adds one item from a backup without replacing the vault. With the key on the nRF, `tools/sign-vaultkey.sh` signs the C6's images again and its signed app returns to the repository, the C6 left alone. + **Done 2026-10-15**: added from the September `.vkb`, the C6's images signed and + verified, and the nRF backed up with it. 2. C6 flashing moves out of the CLI into a script in its folder. `espflash` leaves, and the audit exception goes. **Deferred** (2026-10-15): the script chooses between the plain and the Secure Boot bootloader, and the wrong choice on a plain chip burns its eFuses. @@ -666,7 +668,8 @@ Milestones, one commit each, each leaving a key that works: of corrupting the statics (`docs2/makerdiary.md`, "Passkeys on the board"). The C6's image changed with it. Its signed copy can only be made on the C6, which is left alone, so it left the repository, and `vkey setup` refuses a Secure Boot chip - until it is signed again (maintainer's decision, 2026-10-15). + until it is signed again (maintainer's decision, 2026-10-15). Signed again the same + day with `vkey-signing` restored onto the nRF, and back in the repository. - **The stack is bounded, not measured.** Its high-water mark cannot be read without a second `unsafe` or a probe. The bound comes from the image's call graph, and a lockup in `vkey info`'s reset cause would show an overflow. diff --git a/firmware/boards/esp32c6-zero/board.toml b/firmware/boards/esp32c6-zero/board.toml index 3524f9b..258cfda 100644 --- a/firmware/boards/esp32c6-zero/board.toml +++ b/firmware/boards/esp32c6-zero/board.toml @@ -40,12 +40,7 @@ offset = 0x10000 file = "images/vaultkey.bin" secure_boot = false -# The app signed for a Secure Boot chip is not here (2026-10-15): the core changed for -# the nRF52840's passkeys, and the key that signs this board's images lives on this -# board, which is left alone. Until tools/sign-vaultkey.sh runs with it plugged in and -# the entry below comes back, `vkey setup` refuses a Secure Boot chip: -# -# [[image]] -# offset = 0x10000 -# file = "images/vaultkey.signed.bin" -# secure_boot = true +[[image]] +offset = 0x10000 +file = "images/vaultkey.signed.bin" +secure_boot = true diff --git a/firmware/boards/esp32c6-zero/images/bootloader-sb.signed.bin b/firmware/boards/esp32c6-zero/images/bootloader-sb.signed.bin index 36478c1d864b14a120eb87adac2c4a3341626df3..6a137ccbe101b71f2b84e59deec8ce8e87df0890 100644 GIT binary patch delta 406 zcmV;H0crk#-~xc)0wT-@Z8E zarfn_deRRVAs>kVrBV%m&$eQcx4-*kO(`GH4_5`HDl@P62$iga*`~LJMB}`~WXFL4 zYPssm5;|HD5V8?o)+u`$Nx^^7YDw#!+~$l1tI4^u^Bi3|DMi7T1-hT=fe1eL9 zr9p}V`lL{v17+4&ax_)YJaXcc6dCOpd6#V!JFn`#kVG)YL3ksiW1{YC?l&@b8HgH2 z7kMb3L8`FFE0dpY+}nB#9*s<2WofZIGIJz?|JgpbL42TbQB_GxPj^cA2MXkN8Nu1-v#_L43+B?r A`~Uy| delta 406 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 J@E=m({{V#|-&z0w literal 0 HcmV?d00001 From 9a98dc8aaa21e78643a856f30d9cab1ffa2ea2ef Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 23:46:55 +0300 Subject: [PATCH 20/33] Sign git commits with a tap and switch auth and commits in /settings vkey commits enable makes an OpenSSH ecdsa-sk key on the nRF52840 and points git's global signing at it; disable unsets commit.gpgsign and keeps the key. The shell's /settings turns vkey auth and commit signing on and off, installing libpam-u2f with apt when it is missing. Linux only; macOS and Windows are #18 and #19. --- CLAUDE.md | 10 +- README.md | 21 +++- cli/src/auth.rs | 15 ++- cli/src/commits.rs | 256 +++++++++++++++++++++++++++++++++++++++++++ cli/src/main.rs | 56 +++++++--- cli/src/shell.rs | 105 +++++++++++++++++- docs/threat-model.md | 23 +++- 7 files changed, 465 insertions(+), 21 deletions(-) create mode 100644 cli/src/commits.rs diff --git a/CLAUDE.md b/CLAUDE.md index b1fed33..6d05572 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -120,8 +120,8 @@ This is a security device. The rules below are not recommendations. yields free attempts. In flash this is one word write without an erase. - **A claim in the protocol must hold in the code.** Advertising a guarantee only half the paths enforce is worse than not advertising it. -- **Irreversible actions get their own gesture.** Code, password, a `vkey auth` login and - a passkey on the nRF52840 — a tap (amber); wipe, and erasing every passkey +- **Irreversible actions get their own gesture.** Code, password, a `vkey auth` login, a + signed git commit and a passkey on the nRF52840 — a tap (amber); wipe, and erasing every passkey (authenticatorReset) — hold 5 s (red); backup — double tap (blue). A tap never wipes and never exports; a hold never exports; a double tap never wipes. Password on a tap is the maintainer's decision of 2026-09-08 — do not reintroduce a separate hold. A new command with consequences gets a @@ -228,6 +228,12 @@ The boards: it. That is the one place the CLI writes system files. The Ed25519 scheme before it (category 201 sealed under the chip key, command `Respond` 0x19) is gone, restorable from 4bd49f3; both numbers stay unused, and a restore leaves such an item in the file. +- `vkey commits enable` (2026-10-15, `cli/src/commits.rs`) signs every git commit with + a tap: an OpenSSH `ecdsa-sk` key on the nRF52840, its handle in `~/.ssh/id_vkey_sk`, + git's global signing settings pointed at it; `disable` unsets `commit.gpgsign` only. + The shell's `/settings` turns `auth` and `commits` on and off by running these same + commands outside raw mode (`sudo` for `auth`). Linux only; macOS and Windows are + issues #18 and #19. - A TOTP seed leaves the device two ways. The backup (`ExportBegin`/`ExportNext`, after a double tap; 2026-09-09) reseals every item under a key derived from a passphrase (Argon2id, `Passphrase` 12–128 bytes, without the chip key, so the file opens on another diff --git a/README.md b/README.md index 6754650..f7e9a54 100644 --- a/README.md +++ b/README.md @@ -160,11 +160,30 @@ recognise it leaves alone and prints the line to add by hand. Keep a root shell another terminal until `sudo` and the lock screen have both worked, with the tap and with the password. +In the shell, `/settings` → `auth` does the same in one step, and installs `libpam-u2f` +with apt first if it is missing. + +## Git commits signed with a tap + +```bash +vkey commits enable # a tap: an SSH key on the key, git signs every commit with it +vkey commits disable # git stops signing; the key stays for the next enable +``` + +`enable` makes an OpenSSH `ecdsa-sk` key on the nRF52840 (a tap) and keeps its handle in +`~/.ssh/id_vkey_sk`, which signs nothing without the key. It sets git's `gpg.format`, +`user.signingkey`, `gpg.ssh.allowedSignersFile` and `commit.gpgsign` globally, refuses +to overwrite a signing setup that is not its own, and offers to add the public half to +GitHub as a signing key (`gh`), so the commits show as verified there. From then on every +commit waits for a tap. In the shell it is `/settings` → `commits`, on or off. Linux only +for now; macOS and Windows are issues #18 and #19. What it costs is in +[the threat model](docs/threat-model.md#git-commits-signed-with-a-tap). + ## Gestures and capacity | Gesture | LED | What it releases | |---|---|---| -| Tap | amber | one TOTP code, the secret fields of one item, one `.env`, one passkey, or one `vkey auth` login | +| Tap | amber | one TOTP code, the secret fields of one item, one `.env`, one passkey, one `vkey auth` login, or one signed git commit | | Hold 5 s | red | factory wipe: every secret and the PIN; on the nRF52840, erasing every passkey (within 10 s of plugging in) | | Double tap | blue | the encrypted backup file, or an export / seed readout | diff --git a/cli/src/auth.rs b/cli/src/auth.rs index ed246dc..eeb7691 100644 --- a/cli/src/auth.rs +++ b/cli/src/auth.rs @@ -128,7 +128,7 @@ pub fn disable() -> Result { /// `pamu2fcfg` writes: `user:,,es256,+presence`. Nothing on /// this host changes until both taps have answered. fn enrol(user: &str) -> Result { - if !PAM_U2F.iter().any(|p| Path::new(p).exists()) { + if !module_present() { return Err(Error::Value( "pam_u2f is missing: sudo apt install libpam-u2f".into(), )); @@ -147,6 +147,19 @@ fn enrol(user: &str) -> Result { )) } +/// Whether `pam_u2f` is installed where this host's PAM looks for it. +pub fn module_present() -> bool { + PAM_U2F.iter().any(|p| Path::new(p).exists()) +} + +/// Whether a tap lets `user` in through `sudo`: the line in its PAM file and the user's +/// credential in the mapping. Both are world-readable, so no root is needed to ask. +pub fn enabled(user: &str) -> bool { + let mine = format!("{user}:"); + fs::read_to_string("/etc/pam.d/sudo").is_ok_and(|t| t.lines().any(|l| l.trim() == PAM_LINE)) + && fs::read_to_string(MAPPINGS).is_ok_and(|t| t.lines().any(|l| l.starts_with(&mine))) +} + fn hostname() -> Result { let name = fs::read_to_string("/proc/sys/kernel/hostname")?; Ok(name.trim().to_string()) diff --git a/cli/src/commits.rs b/cli/src/commits.rs new file mode 100644 index 0000000..d3d8efa --- /dev/null +++ b/cli/src/commits.rs @@ -0,0 +1,256 @@ +//! `vkey commits`: every git commit signed with a tap on the key. +//! +//! ```text +//! vkey commits enable an SSH key on the key, git told to sign with it +//! vkey commits disable git stops signing; the key stays for the next enable +//! ``` +//! +//! The key is a FIDO2 authenticator (the nRF52840's passkeys), and OpenSSH keeps a +//! private key on one as an `-sk` key: `ssh-keygen` makes the credential after a tap and +//! leaves on disk only its handle, which signs nothing without the key and a tap. git +//! signs with SSH keys since 2.34, so a commit is `ssh-keygen -Y sign` with that handle +//! and costs one tap. The credential is not resident: the handle in `~/.ssh` is the only +//! way back to it, and it is not in the `.vkb`. + +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use crate::device::Error; +use crate::{file, prompt}; + +/// The key handle, beside the user's other SSH keys; `.pub` next to it. +const KEY: &str = ".ssh/id_vkey_sk"; +/// Who signed what, for `git log --show-signature` and `git verify-commit`. +const SIGNERS: &str = ".config/git/allowed_signers"; + +/// `vkey commits enable`: the SSH key (made once, a tap), the user's line among the +/// allowed signers, git's four settings, and the public half offered to GitHub. +pub fn enable() -> Result { + let home = home()?; + let key = home.join(KEY); + let key_text = key.to_string_lossy().into_owned(); + refuse_foreign("gpg.format", "ssh")?; + refuse_foreign("user.signingkey", &key_text)?; + let Some(email) = git_get("user.email")? else { + return Err(Error::Value( + "git has no user.email to sign as: git config --global user.email you@example.com" + .into(), + )); + }; + + if !key.exists() { + make_key(&key)?; + } + let public = fs::read_to_string(pub_path(&key))?; + let signers = home.join(SIGNERS); + if let Some(dir) = signers.parent() { + fs::create_dir_all(dir)?; + } + let existing = match fs::read_to_string(&signers) { + Ok(text) => text, + Err(e) if e.kind() == std::io::ErrorKind::NotFound => String::new(), + Err(e) => return Err(e.into()), + }; + file::replace( + &signers, + with_signer(&existing, &email, public.trim()).as_bytes(), + 0o644, + )?; + + git_set("gpg.format", "ssh")?; + git_set("user.signingkey", &key_text)?; + git_set("gpg.ssh.allowedSignersFile", &signers.to_string_lossy())?; + git_set("commit.gpgsign", "true")?; + + println!("every git commit is now signed: tap the key when its light turns amber"); + offer_to_github(&key)?; + Ok(0) +} + +/// `vkey commits disable`: git stops signing. The key, its handle and the allowed +/// signers stay, so the next enable takes no tap and GitHub needs no new key. +pub fn disable() -> Result { + let status = Command::new("git") + .args(["config", "--global", "--unset", "commit.gpgsign"]) + .status()?; + // 5: the setting was not there, which is what was asked for. + if !status.success() && status.code() != Some(5) { + return Err(Error::Value( + "git config --unset commit.gpgsign failed".into(), + )); + } + println!("git commits are no longer signed; enable again to sign with the same key"); + Ok(0) +} + +/// Whether git signs every commit with this key. +pub fn enabled() -> bool { + let Ok(home) = home() else { + return false; + }; + let key = home.join(KEY).to_string_lossy().into_owned(); + matches!(git_get("commit.gpgsign"), Ok(Some(v)) if v == "true") + && matches!(git_get("user.signingkey"), Ok(Some(v)) if v == key) +} + +fn home() -> Result { + std::env::var_os("HOME") + .map(PathBuf::from) + .ok_or_else(|| Error::Value("HOME is not set".into())) +} + +fn pub_path(key: &Path) -> PathBuf { + let mut p = key.as_os_str().to_owned(); + p.push(".pub"); + PathBuf::from(p) +} + +/// The credential, after a tap. `-N ""`: the handle needs no passphrase, because it +/// signs nothing without the key and a tap on it. +fn make_key(key: &Path) -> Result<(), Error> { + if let Some(dir) = key.parent() { + fs::create_dir_all(dir)?; + } + eprintln!("tap the key when its light turns amber, to make the signing key"); + let status = Command::new("ssh-keygen") + .args([ + "-q", + "-t", + "ecdsa-sk", + "-N", + "", + "-C", + "vkey commit signing", + "-f", + ]) + .arg(key) + .status() + .map_err(|e| Error::Value(format!("ssh-keygen: {e}")))?; + if !status.success() { + return Err(Error::Value( + "ssh-keygen made no key: no tap in time, or no FIDO2 key it could reach".into(), + )); + } + Ok(()) +} + +/// GitHub shows a commit as verified only when it knows the key as a signing key. +/// Uploading publishes it, so it is asked, and needs `gh` with the scope for it. +fn offer_to_github(key: &Path) -> Result<(), Error> { + let public = pub_path(key); + let by_hand = format!( + " gh ssh-key add {} --type signing --title vkey", + public.display() + ); + let gh = Command::new("gh").args(["auth", "status"]).output(); + if !matches!(gh, Ok(ref o) if o.status.success()) { + println!( + "for GitHub to show the commits as verified, add the key as a signing key:\n{by_hand}" + ); + return Ok(()); + } + if !prompt::is_tty() || !prompt::yes_no("add the key to GitHub as a signing key?") { + println!("to add it later:\n{by_hand}"); + return Ok(()); + } + let out = Command::new("gh") + .args(["ssh-key", "add"]) + .arg(&public) + .args(["--type", "signing", "--title", "vkey"]) + .output()?; + if out.status.success() { + println!("added to GitHub: commits signed by this key show as verified"); + return Ok(()); + } + let why = String::from_utf8_lossy(&out.stderr); + if why.contains("admin:ssh_signing_key") { + println!( + "gh needs the scope to add signing keys first:\n gh auth refresh -h github.com -s admin:ssh_signing_key\nthen:\n{by_hand}" + ); + } else if why.contains("already") { + println!("GitHub already has this key"); + } else { + println!("GitHub refused the key: {}\n{by_hand}", why.trim()); + } + Ok(()) +} + +/// A global git setting, or None when it is not set. +fn git_get(name: &str) -> Result, Error> { + let out = Command::new("git") + .args(["config", "--global", "--get", name]) + .output() + .map_err(|e| Error::Value(format!("git: {e}")))?; + if out.status.success() { + return Ok(Some( + String::from_utf8_lossy(&out.stdout).trim().to_string(), + )); + } + // 1: not set. Anything else is git failing, which must not read as "not set". + if out.status.code() == Some(1) { + return Ok(None); + } + Err(Error::Value(format!("git config --get {name} failed"))) +} + +fn git_set(name: &str, value: &str) -> Result<(), Error> { + let status = Command::new("git") + .args(["config", "--global", name, value]) + .status()?; + if !status.success() { + return Err(Error::Value(format!("git config {name} failed"))); + } + Ok(()) +} + +/// A setting someone else made is not overwritten: signing with another key, or +/// through GPG, is a choice this command does not get to undo silently. +fn refuse_foreign(name: &str, ours: &str) -> Result<(), Error> { + match git_get(name)? { + Some(v) if v != ours => Err(Error::Value(format!( + "git already has {name} = {v}; unset it first if vkey should sign instead:\n git config --global --unset {name}" + ))), + _ => Ok(()), + } +} + +/// `existing` with `email`'s line replaced by one for `public`, every other line kept. +fn with_signer(existing: &str, email: &str, public: &str) -> String { + let mine = format!("{email} "); + let mut out = String::new(); + for line in existing.lines().filter(|l| !l.starts_with(&mine)) { + out.push_str(line); + out.push('\n'); + } + out + email + " namespaces=\"git\" " + public + "\n" +} + +#[cfg(test)] +mod tests { + use super::*; + + const KEY_A: &str = "sk-ecdsa-sha2-nistp256@openssh.com AAAA vkey commit signing"; + + #[test] + fn a_signer_is_added_beside_the_others() { + let out = with_signer("bob@x namespaces=\"git\" ssh-ed25519 BBBB\n", "me@x", KEY_A); + assert_eq!( + out, + format!("bob@x namespaces=\"git\" ssh-ed25519 BBBB\nme@x namespaces=\"git\" {KEY_A}\n") + ); + } + + #[test] + fn a_signer_already_there_is_replaced_not_doubled() { + let first = with_signer("", "me@x", "old-key"); + let out = with_signer(&first, "me@x", KEY_A); + assert_eq!(out, format!("me@x namespaces=\"git\" {KEY_A}\n")); + } + + #[test] + fn a_longer_address_sharing_the_prefix_is_not_mine() { + let out = with_signer("me@x.org namespaces=\"git\" k\n", "me@x", KEY_A); + assert!(out.starts_with("me@x.org namespaces=\"git\" k\n")); + } +} diff --git a/cli/src/main.rs b/cli/src/main.rs index 87e2744..8319e6f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -24,6 +24,7 @@ mod auth; mod backup; mod boards; mod check; +mod commits; mod device; mod fido; mod file; @@ -199,10 +200,24 @@ enum Cmd { #[command(subcommand)] cmd: AuthCmd, }, + /// Every git commit signed with a tap: an SSH key on the key, git told to use it + Commits { + #[command(subcommand)] + cmd: CommitsCmd, + }, /// Copy this binary to ~/.local/bin/vkey Install, } +#[derive(Subcommand, Clone, Copy)] +enum CommitsCmd { + /// An SSH key on the key (a tap, once), git set to sign every commit with it, and + /// its public half offered to GitHub as a signing key + Enable, + /// git stops signing; the key stays for the next enable + Disable, +} + #[derive(Subcommand, Clone, Copy)] enum AuthCmd { /// A credential on the key for this host's logins (a tap), its public half in @@ -295,22 +310,33 @@ fn main() -> ExitCode { } } -fn run(cli: Cli) -> Result { - match cli.cmd { - Some(Cmd::Install) => return install::install().map(|()| 0), - // pamu2fcfg talks to the key over FIDO itself; vkey's port is not needed. - Some(Cmd::Auth { +/// The commands that do not talk to vkey's port: installing, flashing, and what reaches +/// the key over FIDO. None for every other command. +fn run_off_port(cli: &Cli) -> Option> { + Some(match cli.cmd.as_ref()? { + Cmd::Install => install::install().map(|()| 0), + // The enrolment and ssh-keygen talk to the key over FIDO themselves. + Cmd::Auth { cmd: AuthCmd::Enable, - }) => return auth::enable(), - Some(Cmd::Auth { + } => auth::enable(), + Cmd::Auth { cmd: AuthCmd::Disable, - }) => return auth::disable(), - Some(Cmd::Setup { erase, board }) => { - return cmd_setup(cli.port.as_deref(), board.as_deref(), erase); - } - _ => {} - } + } => auth::disable(), + Cmd::Commits { + cmd: CommitsCmd::Enable, + } => commits::enable(), + Cmd::Commits { + cmd: CommitsCmd::Disable, + } => commits::disable(), + Cmd::Setup { erase, board } => cmd_setup(cli.port.as_deref(), board.as_deref(), *erase), + _ => return None, + }) +} +fn run(cli: Cli) -> Result { + if let Some(done) = run_off_port(&cli) { + return done; + } let mut dev = Device::open(cli.port.as_deref())?; let version = dev.probe(); let Some(cmd) = cli.cmd else { @@ -324,7 +350,9 @@ fn run(cli: Cli) -> Result { }; match cmd { - Cmd::Install | Cmd::Setup { .. } | Cmd::Auth { .. } => unreachable!("handled above"), + Cmd::Install | Cmd::Setup { .. } | Cmd::Auth { .. } | Cmd::Commits { .. } => { + unreachable!("handled above") + } Cmd::Info => run_info(&mut dev, &version), diff --git a/cli/src/shell.rs b/cli/src/shell.rs index 1ba548a..a515780 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -10,6 +10,7 @@ use std::collections::{BTreeMap, HashMap}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; +use std::process::Command; use std::time::{Duration, Instant}; use crossterm::cursor::{MoveDown, MoveToColumn, MoveUp}; @@ -29,7 +30,7 @@ use crate::device::{ }; use crate::item::{Item, category_name}; use crate::prompt::{ACCENT, DIM, PinPrompt, WARN_AT, copy_secret, copy_to_clipboard}; -use crate::{backup, import, op, prompt, setup, sources, totp}; +use crate::{auth, backup, commits, import, op, prompt, setup, sources, totp}; /// Commands live behind `/`; a bare word is the name of an entry to use. const COMMANDS: &[(&str, &str)] = &[ @@ -41,7 +42,7 @@ const COMMANDS: &[(&str, &str)] = &[ ("lock", "forget the key until the next PIN"), ( "settings", - "PIN, backup and restore, self-test, setup, factory reset", + "PIN, backup and restore, self-test, setup, factory reset, tap for sudo and commits", ), ]; /// Behind `/settings`: what is done to the key rather than with an entry. They still @@ -68,6 +69,14 @@ const SETTINGS: &[(&str, &str)] = &[ "restore", "restore entries from 1Password API, a CSV export, or a backup file", ), + ( + "auth", + "sudo and the lock screen with a tap - turn on or off", + ), + ( + "commits", + "sign every git commit with a tap - turn on or off", + ), ]; /// Reached from the list with a, e, d and i, never offered as commands: an entry has /// one place, and the list is it. They still resolve when typed, so the transcript's @@ -2275,6 +2284,86 @@ impl Shell { self.dispatch(&format!("/{}", SETTINGS[at].0)) } + /// `/auth`: `sudo vkey auth enable` or `disable`, whichever flips the current state, + /// with `libpam-u2f` installed first if it is missing and apt is there to do it. + fn cmd_auth(&mut self) -> Result<(), Error> { + let user = std::env::var("USER").unwrap_or_default(); + let on = auth::enabled(&user); + let question = if on { + "sudo and the lock screen take a tap now - turn that off?" + } else { + "let sudo and the lock screen take a tap on this key?" + }; + if !self.ask_yes(question) { + self.line(DIM, " nothing changed"); + return Ok(()); + } + let exe = std::env::current_exe()?; + if !on && !auth::module_present() { + if !Path::new("/usr/bin/apt-get").exists() { + return Err(Error::Value( + "pam_u2f is missing: install your distribution's pam-u2f package".into(), + )); + } + if !self.ask_yes("pam_u2f is missing - install libpam-u2f with apt first?") { + self.line(DIM, " nothing changed"); + return Ok(()); + } + self.line(DIM, " sudo asks for your password, or a tap"); + if !self.outside(Command::new("sudo").args([ + "apt-get", + "install", + "-y", + "libpam-u2f", + ]))? { + return Err(Error::Value("apt-get could not install libpam-u2f".into())); + } + } + // sudo's secure_path leaves out ~/.local/bin: the binary goes by its full path. + let verb = if on { "disable" } else { "enable" }; + self.line( + DIM, + " sudo asks for your password, or a tap if it already takes one", + ); + self.outside(Command::new("sudo").arg(&exe).args(["auth", verb]))?; + Ok(()) + } + + /// `/commits`: `vkey commits enable` or `disable`, whichever flips the current state. + fn cmd_commits(&mut self) -> Result<(), Error> { + let on = commits::enabled(); + let question = if on { + "every commit is signed with a tap now - turn that off?" + } else { + "sign every git commit with a tap on this key?" + }; + if !self.ask_yes(question) { + self.line(DIM, " nothing changed"); + return Ok(()); + } + let exe = std::env::current_exe()?; + let verb = if on { "disable" } else { "enable" }; + self.outside(Command::new(&exe).args(["commits", verb]))?; + Ok(()) + } + + /// `cmd` run in the plain terminal: the frame goes, raw mode is left for as long as + /// it runs - sudo reads a password and ssh-keygen prints its own lines - and both + /// come back after. Its output stays in the transcript. + fn outside(&mut self, cmd: &mut Command) -> Result { + let mut so = io::stdout(); + if self.frame_rows > 0 { + self.erase_frame(&mut so); + } + let _ = so.flush(); + let _ = terminal::disable_raw_mode(); + let status = cmd.status(); + let _ = terminal::enable_raw_mode(); + self.draw_frame(&mut so); + let _ = so.flush(); + Ok(status?.success()) + } + /// A `/command [arg]` runs the command; anything else is the name of an entry to /// use, and an empty line offers the list of them. Leaving is Ctrl-D, not a command. fn dispatch(&mut self, line: &str) -> Result<(), Error> { @@ -2299,6 +2388,18 @@ impl Shell { name => ("use", name), }, }; + // These reach the key over FIDO, not over this port, and touch no vault. + match cmd { + "auth" => { + let r = self.cmd_auth(); + return self.report(r); + } + "commits" => { + let r = self.cmd_commits(); + return self.report(r); + } + _ => {} + } if !self.connected() && !self.reconnect() { self.line(Color::Red, " board disconnected - plug it back in"); return Ok(()); diff --git a/docs/threat-model.md b/docs/threat-model.md index 843c3b1..a61cae1 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -303,7 +303,7 @@ mapping. The line is `sufficient`: what it adds is a way in, and the password st | Malware enrolling a key of its own | `/etc/u2f_mappings` is root's: adding a line needs root already | | Someone at the unlocked laptop while you are away, key in the port | Gets root with one tap where `sudo` used to want the password | | A copy of the board's flash (the revision-2 glitch) | The credential's key is wrapped by fido-authenticator's key, which sits unsealed in Trussed's filesystem: whoever reads the flash can answer this host's logins, given the host | -| A `.vkb` backup | Holds the login once milestone 5 puts the passkeys into it: with the passphrase, another board then answers this host's `sudo` too | +| A `.vkb` backup | Holds the login with the passkeys (since 2026-10-15): with the passphrase, another board then answers this host's `sudo` too | | The key in, nobody tapping | The password prompt comes when the key gives up, after 30 s; the old scheme gave up after 10 | | A FIDO PIN on the key | Its own, not vkey's; the credential is made without one, so a login does not ask for it | | The login screen after boot | COSMIC's greeter shares the `cosmic-greeter` service, so a tap may log in there too; the keyring, unlocked only by the password, then stays locked | @@ -325,6 +325,27 @@ Rejected: presence of the USB device as proof (any ESP32 shows `303a:1001`); PIN with a rotating expectation (state to write at every login); a PAM `cdylib`; keeping a scheme of our own beside `pam_u2f`. +### Git commits signed with a tap + +Since 2026-10-15 `vkey commits enable` (or `/settings` → `commits`) makes an OpenSSH +`ecdsa-sk` key on the nRF52840 after a tap and points git at it globally: `gpg.format +ssh`, `user.signingkey ~/.ssh/id_vkey_sk`, `commit.gpgsign true`, and an +`allowed_signers` line for `user.email`. It writes only the user's own files, never a +system one, and refuses when git already signs with something else. `disable` unsets +`commit.gpgsign` and keeps the key. `tag.gpgsign` is left alone. Uploading the public +half to GitHub is offered and asked, never done unasked. + +| | | +|---|---| +| Given | A signature needs this physical key, its handle file, and a tap after the request; no PIN and no user verification | +| What a signature proves | That someone touched this key while a process with the handle asked. Not who, and not what the commit contains: the tap does not show the commit | +| Malware running as the user | Can run `git commit` (or `ssh-keygen -Y sign` on anything) and wait for a reflex tap. The light is the same amber as a code or a login | +| Key and laptop stolen together | Signs as the user with a tap, until the key is removed from GitHub | +| The handle file `~/.ssh/id_vkey_sk` | Useless without the key. Not in the `.vkb`: losing it means a new key and a new upload to GitHub | +| A copy of the board's flash, or a `.vkb` with its passphrase | The credential is wrapped by fido-authenticator's key, which both carry: with the handle file, another board then signs too | +| authenticatorReset | Ends the key; a restore from a `.vkb` taken before brings it back | +| Every commit waits for a tap | A rebase or an amend signs each commit again, one tap each; a commit with no tap in 30 s fails | + ## What it does not protect against | Threat | Why not | From ebd4171669e32c26ea1ab809e3dc05ac604bfa97 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 23:51:18 +0300 Subject: [PATCH 21/33] Leave the frame to the main loop after a command run outside raw mode --- cli/src/shell.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cli/src/shell.rs b/cli/src/shell.rs index a515780..f963baa 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -2347,9 +2347,10 @@ impl Shell { Ok(()) } - /// `cmd` run in the plain terminal: the frame goes, raw mode is left for as long as - /// it runs - sudo reads a password and ssh-keygen prints its own lines - and both - /// come back after. Its output stays in the transcript. + /// `cmd` run in the plain terminal: the frame goes and raw mode is left for as long + /// as it runs - sudo reads a password and ssh-keygen prints its own lines. Raw mode + /// comes back after; the frame is left down, as `choose` leaves it, for the main + /// loop to draw once. Its output stays in the transcript. fn outside(&mut self, cmd: &mut Command) -> Result { let mut so = io::stdout(); if self.frame_rows > 0 { @@ -2359,8 +2360,6 @@ impl Shell { let _ = terminal::disable_raw_mode(); let status = cmd.status(); let _ = terminal::enable_raw_mode(); - self.draw_frame(&mut so); - let _ = so.flush(); Ok(status?.success()) } From c6fa7ef906cf354983a1af60f7e51f5e9cca50bc Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 23:58:32 +0300 Subject: [PATCH 22/33] Show the auth and commits state in /settings and flip them on a switch --- cli/src/prompt.rs | 105 ++++++++++++++++++++++++++++++++++++++++++++++ cli/src/shell.rs | 51 ++++++++++++++-------- 2 files changed, 138 insertions(+), 18 deletions(-) diff --git a/cli/src/prompt.rs b/cli/src/prompt.rs index 998e0af..0807675 100644 --- a/cli/src/prompt.rs +++ b/cli/src/prompt.rs @@ -197,6 +197,111 @@ fn pick(label: &str, options: &[(T, &str, &str)]) -> Option { chosen.map(|i| options[i].0) } +/// An off/on switch on one line, starting where the setting is now: ← → (or Tab, +/// Space, h, l) move it, Enter keeps what it shows, Esc or Ctrl-C leaves it. Only the +/// answer stays on screen. Works inside the shell's raw mode and on a plain terminal. +pub fn switch(label: &str, on: bool) -> Option { + // Columns before the label: " ▸ ", " off ", " ", " on ", " ", " ". + const SWITCH: usize = 16; + let was_raw = terminal::is_raw_mode_enabled().unwrap_or(false); + if !was_raw && terminal::enable_raw_mode().is_err() { + return None; + } + let mut so = io::stdout(); + // The switch first, then as much of the label as the width leaves: the line never + // wraps, so a redraw is always one line. + let draw = |so: &mut io::Stdout, sel: bool| -> usize { + let width = terminal::size() + .map_or(80, |(c, _)| usize::from(c)) + .saturating_sub(1); + let _ = queue!( + so, + MoveToColumn(0), + Clear(ClearType::CurrentLine), + SetForegroundColor(ACCENT), + Print(" ▸ "), + ResetColor + ); + for (value, name) in [(false, " off "), (true, " on ")] { + let picked = value == sel; + let _ = queue!( + so, + SetForegroundColor(if picked { ACCENT } else { DIM }), + SetAttribute(if picked { + Attribute::Reverse + } else { + Attribute::Reset + }), + Print(name), + SetAttribute(Attribute::Reset), + ResetColor, + Print(" ") + ); + } + let room = width.saturating_sub(SWITCH); + let shown: String = label.chars().take(room).collect(); + let len = SWITCH + shown.chars().count(); + let _ = queue!(so, Print(" "), Print(shown)); + let _ = so.flush(); + len + }; + let mut sel = on; + let mut drawn = draw(&mut so, sel); + let chosen = loop { + let Ok(event) = event::read() else { + continue; + }; + let key = match event { + Event::Key(key) if key.kind == KeyEventKind::Press => key, + // A narrower window rewraps the line already drawn into more rows, with the + // cursor on the last: up to the first of them, clear, draw to the new width. + Event::Resize(cols, _) => { + let up = drawn.saturating_sub(1) / usize::from(cols.max(1)); + if let Ok(up @ 1..) = u16::try_from(up) { + let _ = queue!(so, MoveUp(up)); + } + let _ = queue!(so, MoveToColumn(0), Clear(ClearType::FromCursorDown)); + drawn = draw(&mut so, sel); + continue; + } + _ => continue, + }; + match (key.code, key.modifiers) { + (KeyCode::Enter, _) => break Some(sel), + (KeyCode::Esc, _) | (KeyCode::Char('c' | 'd'), KeyModifiers::CONTROL) => break None, + (KeyCode::Left | KeyCode::Char('h'), _) => sel = false, + (KeyCode::Right | KeyCode::Char('l'), _) => sel = true, + (KeyCode::Tab | KeyCode::BackTab | KeyCode::Char(' '), _) => sel = !sel, + _ => {} + } + drawn = draw(&mut so, sel); + }; + let answer = match chosen { + Some(true) => "on", + Some(false) => "off", + None => "never mind", + }; + let _ = queue!( + so, + MoveToColumn(0), + Clear(ClearType::CurrentLine), + SetForegroundColor(ACCENT), + Print(" ▸ "), + ResetColor, + Print(label), + Print(" "), + SetForegroundColor(DIM), + Print(answer), + ResetColor, + Print("\r\n") + ); + let _ = so.flush(); + if !was_raw { + let _ = terminal::disable_raw_mode(); + } + chosen +} + /// A yes/no question that starts on "no": destructive answers take a keystroke. /// Without a terminal there is no asking; `--yes` says it up front. pub fn confirm(question: &str, assume_yes: bool) -> Result { diff --git a/cli/src/shell.rs b/cli/src/shell.rs index f963baa..9aa786f 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -2273,10 +2273,22 @@ impl Shell { /// `/settings`: one of the commands that act on the key itself. fn cmd_settings(&mut self) -> Result<(), Error> { + // The two switches say where they stand, so the list is also the status. + let state = |on: bool| if on { "on] " } else { "off]" }; + let user = std::env::var("USER").unwrap_or_default(); + let descs: Vec = SETTINGS + .iter() + .map(|(name, desc)| match *name { + "auth" => format!("[{} {desc}", state(auth::enabled(&user))), + "commits" => format!("[{} {desc}", state(commits::enabled())), + _ => (*desc).to_string(), + }) + .collect(); let options: Vec<(usize, &str, &str)> = SETTINGS .iter() + .zip(&descs) .enumerate() - .map(|(i, (name, desc))| (i, *name, *desc)) + .map(|(i, ((name, _), desc))| (i, *name, desc.as_str())) .collect(); let Some(at) = self.choose("settings:", &options) else { return Ok(()); @@ -2284,18 +2296,27 @@ impl Shell { self.dispatch(&format!("/{}", SETTINGS[at].0)) } - /// `/auth`: `sudo vkey auth enable` or `disable`, whichever flips the current state, - /// with `libpam-u2f` installed first if it is missing and apt is there to do it. + /// The off/on switch below the transcript, starting where the setting stands; true + /// only when it was moved and confirmed. + fn flipped(&mut self, label: &str, on: bool) -> bool { + if self.frame_rows > 0 { + let mut so = io::stdout(); + self.erase_frame(&mut so); + let _ = so.flush(); + } + if prompt::switch(label, on) == Some(!on) { + return true; + } + self.line(DIM, " nothing changed"); + false + } + + /// `/auth`: `sudo vkey auth enable` or `disable`, as the switch is moved, with + /// `libpam-u2f` installed first if it is missing and apt is there to do it. fn cmd_auth(&mut self) -> Result<(), Error> { let user = std::env::var("USER").unwrap_or_default(); let on = auth::enabled(&user); - let question = if on { - "sudo and the lock screen take a tap now - turn that off?" - } else { - "let sudo and the lock screen take a tap on this key?" - }; - if !self.ask_yes(question) { - self.line(DIM, " nothing changed"); + if !self.flipped("sudo and the lock screen with a tap", on) { return Ok(()); } let exe = std::env::current_exe()?; @@ -2329,16 +2350,10 @@ impl Shell { Ok(()) } - /// `/commits`: `vkey commits enable` or `disable`, whichever flips the current state. + /// `/commits`: `vkey commits enable` or `disable`, as the switch is moved. fn cmd_commits(&mut self) -> Result<(), Error> { let on = commits::enabled(); - let question = if on { - "every commit is signed with a tap now - turn that off?" - } else { - "sign every git commit with a tap on this key?" - }; - if !self.ask_yes(question) { - self.line(DIM, " nothing changed"); + if !self.flipped("sign every git commit with a tap", on) { return Ok(()); } let exe = std::env::current_exe()?; From 75882d3fa00b867a8151718440eb7cfeed42a923 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 00:11:23 +0300 Subject: [PATCH 23/33] Put wipe and setup last in /settings in red, list vaults with all first The vaults are a plain list of names and counts, led by 'all', every entry of every vault. The commit signing key moves out of ~/.ssh, where GNOME Keyring's agent takes it and then refuses to sign. --- CLAUDE.md | 3 ++- README.md | 3 ++- cli/src/commits.rs | 6 +++-- cli/src/prompt.rs | 21 +++++++++++++--- cli/src/shell.rs | 58 +++++++++++++++++++++++++++++++------------- docs/threat-model.md | 4 +-- 6 files changed, 69 insertions(+), 26 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 6d05572..2f9161d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -229,7 +229,8 @@ The boards: (category 201 sealed under the chip key, command `Respond` 0x19) is gone, restorable from 4bd49f3; both numbers stay unused, and a restore leaves such an item in the file. - `vkey commits enable` (2026-10-15, `cli/src/commits.rs`) signs every git commit with - a tap: an OpenSSH `ecdsa-sk` key on the nRF52840, its handle in `~/.ssh/id_vkey_sk`, + a tap: an OpenSSH `ecdsa-sk` key on the nRF52840, its handle in `~/.config/vkey/commit-signing-key` (not `~/.ssh`, whose keys GNOME + Keyring's agent takes and then refuses to sign with), git's global signing settings pointed at it; `disable` unsets `commit.gpgsign` only. The shell's `/settings` turns `auth` and `commits` on and off by running these same commands outside raw mode (`sudo` for `auth`). Linux only; macOS and Windows are diff --git a/README.md b/README.md index f7e9a54..43e638c 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,8 @@ vkey commits disable # git stops signing; the key stays for the next enable ``` `enable` makes an OpenSSH `ecdsa-sk` key on the nRF52840 (a tap) and keeps its handle in -`~/.ssh/id_vkey_sk`, which signs nothing without the key. It sets git's `gpg.format`, +`~/.config/vkey/commit-signing-key`, which signs nothing without the key (not in +`~/.ssh`, where GNOME Keyring's agent would take it and refuse to sign). It sets git's `gpg.format`, `user.signingkey`, `gpg.ssh.allowedSignersFile` and `commit.gpgsign` globally, refuses to overwrite a signing setup that is not its own, and offers to add the public half to GitHub as a signing key (`gh`), so the commits show as verified there. From then on every diff --git a/cli/src/commits.rs b/cli/src/commits.rs index d3d8efa..7b2dcfa 100644 --- a/cli/src/commits.rs +++ b/cli/src/commits.rs @@ -19,8 +19,10 @@ use std::process::Command; use crate::device::Error; use crate::{file, prompt}; -/// The key handle, beside the user's other SSH keys; `.pub` next to it. -const KEY: &str = ".ssh/id_vkey_sk"; +/// The key handle, `.pub` next to it. Not in `~/.ssh`: GNOME Keyring loads every key +/// there into its agent, which cannot sign with a FIDO2 key, and `ssh-keygen -Y sign` +/// asks the agent first - every commit then fails with "agent refused operation". +const KEY: &str = ".config/vkey/commit-signing-key"; /// Who signed what, for `git log --show-signature` and `git verify-commit`. const SIGNERS: &str = ".config/git/allowed_signers"; diff --git a/cli/src/prompt.rs b/cli/src/prompt.rs index 0807675..ca6da86 100644 --- a/cli/src/prompt.rs +++ b/cli/src/prompt.rs @@ -96,6 +96,16 @@ pub fn generate_password() -> Result, Error> { /// comes back - so a caller never maps an index. None on Esc or Ctrl-C. Only the /// answer stays on screen. Works inside the shell's raw mode and on a plain terminal. pub fn choose(label: &str, options: &[(T, &str, &str)]) -> Option { + choose_ending_in_danger(label, options, 0) +} + +/// `choose`, with the last `danger` options drawn in red: the ones that destroy what +/// cannot be brought back without a backup, kept together at the end of the list. +pub fn choose_ending_in_danger( + label: &str, + options: &[(T, &str, &str)], + danger: usize, +) -> Option { if options.is_empty() { return None; } @@ -103,14 +113,14 @@ pub fn choose(label: &str, options: &[(T, &str, &str)]) -> Option { if !was_raw && terminal::enable_raw_mode().is_err() { return None; } - let chosen = pick(label, options); + let chosen = pick(label, options, options.len().saturating_sub(danger)); if !was_raw { let _ = terminal::disable_raw_mode(); } chosen } -fn pick(label: &str, options: &[(T, &str, &str)]) -> Option { +fn pick(label: &str, options: &[(T, &str, &str)], danger_from: usize) -> Option { let count = options.len(); let mut so = io::stdout(); let _ = queue!( @@ -139,7 +149,12 @@ fn pick(label: &str, options: &[(T, &str, &str)]) -> Option { let _ = queue!( so, Clear(ClearType::CurrentLine), - SetForegroundColor(if i == sel { ACCENT } else { DIM }), + SetForegroundColor(match (i >= danger_from, i == sel) { + (true, true) => Color::Red, + (true, false) => Color::DarkRed, + (false, true) => ACCENT, + (false, false) => DIM, + }), SetAttribute(if i == sel { Attribute::Bold } else { diff --git a/cli/src/shell.rs b/cli/src/shell.rs index 9aa786f..c8bf53a 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -46,17 +46,10 @@ const COMMANDS: &[(&str, &str)] = &[ ), ]; /// Behind `/settings`: what is done to the key rather than with an entry. They still -/// resolve when typed, so `/pin` and `/backup` work as before. +/// resolve when typed, so `/pin` and `/backup` work as before. The last `DANGER` are +/// drawn red, together at the end: each can leave the key empty. const SETTINGS: &[(&str, &str)] = &[ ("pin", "set or change the PIN"), - ( - "wipe", - "factory reset - every secret and the PIN; the button is held, not tapped", - ), - ( - "setup", - "flash a new board with the built-in firmware, set its PIN, self-test", - ), ( "selftest", "one live code against an independent HMAC; one tap", @@ -77,7 +70,17 @@ const SETTINGS: &[(&str, &str)] = &[ "commits", "sign every git commit with a tap - turn on or off", ), + ( + "wipe", + "factory reset - every secret and the PIN; the button is held, not tapped", + ), + ( + "setup", + "flash a new board with the built-in firmware, set its PIN, self-test", + ), ]; +/// `wipe` and `setup`, the end of `SETTINGS`. +const DANGER: usize = 2; /// Reached from the list with a, e, d and i, never offered as commands: an entry has /// one place, and the list is it. They still resolve when typed, so the transcript's /// `❯ /rm name` is a line that would work. @@ -438,11 +441,15 @@ enum Tab { #[derive(Clone, PartialEq, Eq)] enum Shelf { Vaults, + /// Every entry, whichever vault it came from. + All, In(Option), } /// The row that stands for entries no vault owns. const NO_VAULT: &str = "(no vault)"; +/// The first row: every entry of every vault. +const ALL_VAULTS: &str = "all"; impl Tab { fn label(self) -> &'static str { @@ -664,11 +671,14 @@ impl Shell { /// selected item is always in it. fn menu_lines(&mut self, w: usize) -> Vec<(bool, String)> { let cap = Self::rows().saturating_sub(5 + usize::from(self.listing())); + // The vaults are places, not entries: a plain list of names and counts. + let at_vaults = self.at_vaults(); let Some(m) = self.menu.as_mut() else { return Vec::new(); }; match m.kind { MenuKind::Commands => command_lines(m, w, cap), + MenuKind::List if at_vaults => command_lines(m, w, cap), MenuKind::Names | MenuKind::List => table_lines(m, w, cap), } } @@ -718,6 +728,7 @@ impl Shell { let place = match &self.shelf { _ if self.vaults.is_empty() => None, Shelf::Vaults => Some((ACCENT, "vaults".to_string())), + Shelf::All => Some((DIM, format!("{ALL_VAULTS} ▸ "))), Shelf::In(v) => Some((DIM, format!("{} ▸ ", v.as_deref().unwrap_or(NO_VAULT)))), }; let at_vaults = self.at_vaults(); @@ -1260,6 +1271,7 @@ impl Shell { } self.shelf = match vault.trim() { "" => Shelf::Vaults, + ALL_VAULTS => Shelf::All, NO_VAULT => Shelf::In(None), v => Shelf::In(Some(v.to_string())), }; @@ -1273,13 +1285,18 @@ impl Shell { self.input.clear(); self.cursor = 0; let items = if self.at_vaults() { - self.vault_groups() - .into_iter() - .map(|(vault, n)| Row { + let count = |n: usize| format!("{n} item{}", if n == 1 { "" } else { "s" }); + let all = Row { + text: ALL_VAULTS.to_string(), + login: String::new(), + what: count(self.entries.len()), + }; + std::iter::once(all) + .chain(self.vault_groups().into_iter().map(|(vault, n)| Row { text: vault.unwrap_or_else(|| NO_VAULT.to_string()), login: String::new(), - what: format!("{n} item{}", if n == 1 { "" } else { "s" }), - }) + what: count(n), + })) .collect() } else { self.tab_entries() @@ -1323,7 +1340,7 @@ impl Shell { fn in_shelf(&self, e: &Stored) -> bool { match &self.shelf { - Shelf::Vaults => true, + Shelf::Vaults | Shelf::All => true, Shelf::In(v) => self.vault_of(e) == *v, } } @@ -2290,7 +2307,12 @@ impl Shell { .enumerate() .map(|(i, ((name, _), desc))| (i, *name, desc.as_str())) .collect(); - let Some(at) = self.choose("settings:", &options) else { + if self.frame_rows > 0 { + let mut so = io::stdout(); + self.erase_frame(&mut so); + let _ = so.flush(); + } + let Some(at) = prompt::choose_ending_in_danger("settings:", &options, DANGER) else { return Ok(()); }; self.dispatch(&format!("/{}", SETTINGS[at].0)) @@ -2715,7 +2737,9 @@ impl Shell { self.menu = None; Some(Key::Submit(format!("/list {vault}"))) } - KeyCode::Esc if matches!(self.shelf, Shelf::In(_)) && !self.vaults.is_empty() => { + KeyCode::Esc + if matches!(self.shelf, Shelf::In(_) | Shelf::All) && !self.vaults.is_empty() => + { self.shelf = Shelf::Vaults; self.open_list(); Some(Key::Redraw) diff --git a/docs/threat-model.md b/docs/threat-model.md index a61cae1..8d6eec9 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -329,7 +329,7 @@ scheme of our own beside `pam_u2f`. Since 2026-10-15 `vkey commits enable` (or `/settings` → `commits`) makes an OpenSSH `ecdsa-sk` key on the nRF52840 after a tap and points git at it globally: `gpg.format -ssh`, `user.signingkey ~/.ssh/id_vkey_sk`, `commit.gpgsign true`, and an +ssh`, `user.signingkey ~/.config/vkey/commit-signing-key`, `commit.gpgsign true`, and an `allowed_signers` line for `user.email`. It writes only the user's own files, never a system one, and refuses when git already signs with something else. `disable` unsets `commit.gpgsign` and keeps the key. `tag.gpgsign` is left alone. Uploading the public @@ -341,7 +341,7 @@ half to GitHub is offered and asked, never done unasked. | What a signature proves | That someone touched this key while a process with the handle asked. Not who, and not what the commit contains: the tap does not show the commit | | Malware running as the user | Can run `git commit` (or `ssh-keygen -Y sign` on anything) and wait for a reflex tap. The light is the same amber as a code or a login | | Key and laptop stolen together | Signs as the user with a tap, until the key is removed from GitHub | -| The handle file `~/.ssh/id_vkey_sk` | Useless without the key. Not in the `.vkb`: losing it means a new key and a new upload to GitHub | +| The handle file `~/.config/vkey/commit-signing-key` | Useless without the key. Not in the `.vkb`: losing it means a new key and a new upload to GitHub | | A copy of the board's flash, or a `.vkb` with its passphrase | The credential is wrapped by fido-authenticator's key, which both carry: with the handle file, another board then signs too | | authenticatorReset | Ends the key; a restore from a `.vkb` taken before brings it back | | Every commit waits for a tap | A rebase or an amend signs each commit again, one tap each; a commit with no tap in 30 s fails | From 404fa2633ad33499bcdd3fd637332f9609ca663c Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 00:21:31 +0300 Subject: [PATCH 24/33] Move the nRF52840 notes and the roadmap from docs2/ into docs/ --- CLAUDE.md | 10 +++++----- README.md | 6 +++--- cli/.cargo/audit.toml | 2 +- cli/src/fido.rs | 2 +- {docs2 => docs}/makerdiary.md | 8 ++++---- {docs2 => docs}/roadmap.md | 6 +++--- docs/threat-model.md | 2 +- firmware/boards/nrf52840-mdk-dongle/Cargo.toml | 2 +- firmware/boards/nrf52840-mdk-dongle/board.toml | 2 +- .../boards/nrf52840-mdk-dongle/bootloader/Dockerfile | 2 +- .../nrf52840-mdk-dongle/bootloader/signing-key.sh | 2 +- .../nrf52840-mdk-dongle/bootloader/test/app_test.c | 2 +- .../nrf52840-mdk-dongle/bootloader/test/board.sh | 2 +- firmware/boards/nrf52840-mdk-dongle/memory.x | 2 +- firmware/boards/nrf52840-mdk-dongle/src/fido.rs | 2 +- firmware/boards/nrf52840-mdk-dongle/src/main.rs | 10 +++++----- tools/build-bootloader.sh | 4 ++-- 17 files changed, 33 insertions(+), 33 deletions(-) rename {docs2 => docs}/makerdiary.md (99%) rename {docs2 => docs}/roadmap.md (99%) diff --git a/CLAUDE.md b/CLAUDE.md index 2f9161d..d895bdf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,14 +17,14 @@ Decision of 2026-09-07. The key is built for the maintainer's own accounts. Sale production runs, enclosures, provisioning, certifications and marketing are **not built and not proposed** unless the maintainer says otherwise. Passkey/WebAuthn was closed because the C6 has no USB HID; reopened 2026-10-03 for the nRF52840 board on Trussed + -`fido-authenticator`, not an own CTAP2 (maintainer's decision, `docs2/makerdiary.md`). It +`fido-authenticator`, not an own CTAP2 (maintainer's decision, `docs/makerdiary.md`). It never exists on the C6. **The nRF52840 board is the key; the C6 is a test board, not a fallback** (maintainer's decisions, 2026-10-13 and 2026-10-14). Every feature is built for the nRF. Nothing is kept only so the C6 works. A C6 need that remains is driven by its board folder or `board.toml`, not by shared code. Real secrets go onto the nRF when phases 3-5 of -`docs2/roadmap.md` are done, not when features are done. +`docs/roadmap.md` are done, not when features are done. Consequence for code: "convenience for a buyer" is not an argument; security of the maintainer's own secrets and minimal code are. @@ -158,7 +158,7 @@ The boards: runs only images signed with the key in `bootloader/signing-key.pem`; the app ends by its signature slot at 0x96000. No chip key, so it holds no real secrets yet. `vkey info` prints the chip's build code, UICR `APPROTECT` and last reset cause. Notes, - measurements and factory state: `docs2/makerdiary.md`; the plan: `docs2/roadmap.md`. + measurements and factory state: `docs/makerdiary.md`; the plan: `docs/roadmap.md`. - **`esp32c6-zero`**, the test board (2026-10-14): nothing is built for it, and it takes `check --wipe-everything` for core changes. Its images are signed by `tools/sign-vaultkey.sh` with `vkey-signing`, which also lives on the nRF since @@ -306,7 +306,7 @@ The boards: **On the nRF52840, without a probe, the bootloader and UICR are irreversible.** A broken bootloader is a board no USB tool reaches, and UICR `APPROTECT` once written stays. Each such step happens only while the board holds nothing a `.vkb` cannot restore, and only on -the maintainer's explicit go for that step (`docs2/roadmap.md`, phases 3 and 4). The +the maintainer's explicit go for that step (`docs/roadmap.md`, phases 3 and 4). The bootloader fork went in this way on 2026-10-14. **eFuses are irreversible.** Secure Boot, Flash Encryption and HMAC keys burn the chip @@ -364,7 +364,7 @@ at 0x1000 that runs under the factory bootloader and reports its verdicts in only on the drive it is meant for: a bootloader UF2 on the factory `UF2BOOT` would be installed. A real-key build writes `images/bootloader.bin`, which no `board.toml` names. A test build's outputs stay in a temporary directory. Installing the fork is never part -of a build (`docs2/roadmap.md`, phase 3). +of a build (`docs/roadmap.md`, phase 3). Compilation is the **only** exception to the check rule. Linters, formatters, tests and static analysers are not run without a direct request: git hooks in `.githooks/` diff --git a/README.md b/README.md index 43e638c..5f4d159 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ single-binary host CLI, and a press of the board's button for every secret that > only signed firmware and serves no flash back, and APPROTECT closes its debug port. This > revision-2 chip can still be glitched open, though, and it has no chip key > ([docs/threat-model.md](docs/threat-model.md)). So it is **not for real secrets** until the steps -> in [docs2/roadmap.md](docs2/roadmap.md) are done, and `vkey setup` does not flash it yet. +> in [docs/roadmap.md](docs/roadmap.md) are done, and `vkey setup` does not flash it yet. > Everything below still describes the ESP32-C6-Zero, which is now only a test board. ## In ten seconds @@ -267,8 +267,8 @@ that is not in it exists on neither side. The device has no clock — the host s |---|---| | [docs/threat-model.md](docs/threat-model.md) | what it protects against and what it does not. **Read first** | | [docs/hardware.md](docs/hardware.md) | the C6-Zero board: measured pins, traps, bringing up a new one | -| [docs2/roadmap.md](docs2/roadmap.md) | the nRF52840 board, from bring-up to daily use | -| [docs2/makerdiary.md](docs2/makerdiary.md) | the nRF52840 board: why this one, its factory state, what was measured | +| [docs/roadmap.md](docs/roadmap.md) | the nRF52840 board, from bring-up to daily use | +| [docs/makerdiary.md](docs/makerdiary.md) | the nRF52840 board: why this one, its factory state, what was measured | ## Security and licence diff --git a/cli/.cargo/audit.toml b/cli/.cargo/audit.toml index d03b6a7..b7ede7c 100644 --- a/cli/.cargo/audit.toml +++ b/cli/.cargo/audit.toml @@ -7,6 +7,6 @@ ignore = [ # section in an ELF. vkey never parses an ELF - it hands espflash finished images # through Connection, Flasher and Segment - so the decoder is linked but never fed. # Goes when `cargo tree -i ruzstd` shows 0.9.1 or later, or when espflash leaves - # the CLI (docs2/roadmap.md, phase 5). + # the CLI (docs/roadmap.md, phase 5). "RUSTSEC-2026-0344", ] diff --git a/cli/src/fido.rs b/cli/src/fido.rs index 3b4d0c7..2e252f5 100644 --- a/cli/src/fido.rs +++ b/cli/src/fido.rs @@ -1,7 +1,7 @@ //! The key's FIDO2 side, spoken directly: just enough CTAP2 over hidraw for `vkey auth` //! to make a credential and try it. `pamu2fcfg` would do the first half, but the 1.1.0 //! that distributions ship insists on an attestation certificate, and this key attests -//! with the credential's own key, as `WebAuthn` allows (docs2/roadmap.md, phase 6). +//! with the credential's own key, as `WebAuthn` allows (docs/roadmap.md, phase 6). use std::fs::{self, File, OpenOptions}; use std::io::{Read, Write}; diff --git a/docs2/makerdiary.md b/docs/makerdiary.md similarity index 99% rename from docs2/makerdiary.md rename to docs/makerdiary.md index 89e1069..9faa210 100644 --- a/docs2/makerdiary.md +++ b/docs/makerdiary.md @@ -352,7 +352,7 @@ No SoftDevice. The application starts at 0x1000, as `memory.x` assumes, and the (0x97000..0xD8000) misses the bootloader, so the board folder needs no change to run under it. A UF2 is made from `images/vaultkey.bin` with family `0xADA52840` and base 0x1000 (`uf2conv -f 0xADA52840 -c -b 0x1000`). Until our own fork of this bootloader replaces it -(`docs2/roadmap.md`, phase 3; Nordic's secure bootloader was dropped for want of a probe) +(`docs/roadmap.md`, phase 3; Nordic's secure bootloader was dropped for want of a probe) the board holds no real secrets, because UF2 flashes anything and its `CURRENT.UF2` reads the vault's ciphertext out. The fork replaced it on 2026-10-14. @@ -366,7 +366,7 @@ Open questions only the board answers: 2023-07-20, S132 5.1.0 plus the connectivity app in 0x1000..0x35000 and one page at 0x50000) is all 0xFF over 0x97000..0xD8000. Kept at `~/mdk-factory/`, sha256 `3022eb28...6aab`; it restores through the same drive. -- ~~Is the chip's bootloader the published 0.7.1?~~ Yes (2026-10-14, `docs2/roadmap.md` +- ~~Is the chip's bootloader the published 0.7.1?~~ Yes (2026-10-14, `docs/roadmap.md` phase 3 checklist). Its code equals the published `-nosd.hex` byte for byte, and the MBR page is Nordic's 2.4.1 with 0xFF8/0xFFC erased. Beside the settings page at 0xFF000, one thing differs: a Nordic FDS swap-page tag at 0xFD000 that an earlier @@ -386,7 +386,7 @@ Open questions only the board answers: ### Reading the `chip:` line of `vkey info` The firmware reads three things at boot and `vkey info` prints them (phase 1 of -`docs2/roadmap.md`), so the questions a probe would answer need none: +`docs/roadmap.md`), so the questions a probe would answer need none: - **Build code** (FICR `INFO.VARIANT`, ASCII): `AAC0` is revision 1, `AADx` revision 2, `AAF0` revision 3 (IN-141). Anything else: Nordic's IC revision overview. @@ -440,7 +440,7 @@ Both runs tripped on the same trap. The "no code from" steps for a password, an ## First steps when it arrives -> Superseded 2026-10-13 by `docs2/roadmap.md`. The board ran over UF2 without a probe, +> Superseded 2026-10-13 by `docs/roadmap.md`. The board ran over UF2 without a probe, > step 4's reset question is answered (P0.18 is a GPIO), and the order of everything after > step 5 is in the roadmap. Kept for the record. diff --git a/docs2/roadmap.md b/docs/roadmap.md similarity index 99% rename from docs2/roadmap.md rename to docs/roadmap.md index a3639b2..8a19c53 100644 --- a/docs2/roadmap.md +++ b/docs/roadmap.md @@ -5,7 +5,7 @@ dongle. Revised the same day for a constraint the maintainer set: **no SWD probe spare board, now or later.** Decided already, not reopened here: the nRF52840 is the key and the C6 a test board, not a fallback (2026-10-14); Trussed + `fido-authenticator` for passkeys. Board -notes, measurements and the factory state: `docs2/makerdiary.md`. +notes, measurements and the factory state: `docs/makerdiary.md`. ## What "no probe, no spare" changes @@ -84,7 +84,7 @@ and signed images only: APPROTECT means nothing while UF2 hands out the flash. T - the UICR `APPROTECT` word, raw; - the last reset cause from `RESETREAS`, cleared after reading. - How to read them: `docs2/makerdiary.md`, "Reading the `chip:` line". This answers the + How to read them: `docs/makerdiary.md`, "Reading the `chip:` line". This answers the revision question without a probe. It does **not** explain the first unexplained failure. A panic and the bootloader's post-flash restart both read as `soft reset`, and the replug that failure needed is a power-on reset, which clears the register. It @@ -665,7 +665,7 @@ Milestones, one commit each, each leaving a key that works: of stack and needed more than twice that; the first getInfo locked the core up. The core now takes the 128 KiB on the stack for one derivation (`with_kdf_memory`), and the stack is 200 KiB at the bottom of RAM, where an overflow resets the chip instead - of corrupting the statics (`docs2/makerdiary.md`, "Passkeys on the board"). The + of corrupting the statics (`docs/makerdiary.md`, "Passkeys on the board"). The C6's image changed with it. Its signed copy can only be made on the C6, which is left alone, so it left the repository, and `vkey setup` refuses a Secure Boot chip until it is signed again (maintainer's decision, 2026-10-15). Signed again the same diff --git a/docs/threat-model.md b/docs/threat-model.md index 8d6eec9..56018d5 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -118,7 +118,7 @@ Before this board holds a real secret, two things are required: A chip-bound key, a secret in a flash page locked by the ACL until reset, was the third. It was dropped on this revision (2026-10-15): it loads from flash at boot, so the glitch above reads it as well, and it would protect nothing the PIN does not already. On a -revision-3 chip it would be worth having. The plan is in `docs2/roadmap.md`. Nordic's secure bootloader was dropped from it: there is +revision-3 chip it would be worth having. The plan is in `docs/roadmap.md`. Nordic's secure bootloader was dropped from it: there is no SWD probe, and installing it moves the bootloader address in UICR, a one-shot change with no way back. diff --git a/firmware/boards/nrf52840-mdk-dongle/Cargo.toml b/firmware/boards/nrf52840-mdk-dongle/Cargo.toml index 07514ee..8ab1891 100644 --- a/firmware/boards/nrf52840-mdk-dongle/Cargo.toml +++ b/firmware/boards/nrf52840-mdk-dongle/Cargo.toml @@ -28,7 +28,7 @@ embedded-hal = "1.0" embedded-storage = "0.3" usb-device = "0.3" usbd-serial = "0.2" -# CTAPHID, the HID interface FIDO2 speaks (docs2/roadmap.md, phase 6), beside the CDC one. +# CTAPHID, the HID interface FIDO2 speaks (docs/roadmap.md, phase 6), beside the CDC one. usbd-ctaphid = { version = "0.5", default-features = false } ctaphid-dispatch = { version = "0.4", default-features = false } ctaphid-app = "0.2" diff --git a/firmware/boards/nrf52840-mdk-dongle/board.toml b/firmware/boards/nrf52840-mdk-dongle/board.toml index 20da88b..ff16423 100644 --- a/firmware/boards/nrf52840-mdk-dongle/board.toml +++ b/firmware/boards/nrf52840-mdk-dongle/board.toml @@ -28,7 +28,7 @@ passkeys = true radio_base = 0x40001000 # Flashed through its UF2 bootloader fork as images/vaultkey.signed.uf2 (bootloader/, -# docs2/roadmap.md phase 3). `vkey setup` talks only to the ESP ROM loader, so it never +# docs/roadmap.md phase 3). `vkey setup` talks only to the ESP ROM loader, so it never # picks this board. [[image]] offset = 0x1000 diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile b/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile index 06fecb6..851d7c7 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/Dockerfile @@ -2,7 +2,7 @@ # commit, with this folder's board definition and patches laid over it (build.sh), built # with a pinned Arm toolchain. tools/build-bootloader.sh runs it. Nothing here touches a # board: what comes out is installed, if ever, by hand and after its own checklist -# (docs2/roadmap.md, phase 3). +# (docs/roadmap.md, phase 3). FROM debian:bookworm-slim@sha256:7c7b2c966bc9ee8cedfeef67e0e279108992c77681fa595db4a9d65c06ccc587 ARG TOOLCHAIN=arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh index 9c57dff..93d8915 100755 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh @@ -12,7 +12,7 @@ # The public half lands in signing-key.pem and is committed: the bootloader build # compiles it in, and the git hooks verify signed UF2s with it. Neither is secret. Its # fingerprint, printed at the end and shown by the fork's INFO_UF2.TXT, goes into -# docs2/roadmap.md. +# docs/roadmap.md. # # Once a bootloader that trusts this key is installed, losing the private key freezes # the board - no firmware and no bootloader update ever again - so run `vkey backup` diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c index df80095..0860d51 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/app_test.c @@ -1,5 +1,5 @@ /* - * The on-board test of this bootloader fork (docs2/roadmap.md, phase 3, milestone 4). + * The on-board test of this bootloader fork (docs/roadmap.md, phase 3, milestone 4). * * Built with VKEY_AS_APP (patches/0007-as-app.patch), the bootloader runs as an * application from 0x1000 under the factory bootloader, which stays in place, so a diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.sh index b945ba1..33c99ba 100755 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.sh +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/test/board.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# The on-board test (test/app_test.c, docs2/roadmap.md phase 3, milestone 4): +# The on-board test (test/app_test.c, docs/roadmap.md phase 3, milestone 4): # # board.sh make TEST.pem OUTDIR sign with the test key and write the test's UF2s # into OUTDIR, the output of a test-key build: diff --git a/firmware/boards/nrf52840-mdk-dongle/memory.x b/firmware/boards/nrf52840-mdk-dongle/memory.x index 5c12350..d33836e 100644 --- a/firmware/boards/nrf52840-mdk-dongle/memory.x +++ b/firmware/boards/nrf52840-mdk-dongle/memory.x @@ -1,5 +1,5 @@ /* Makerdiary nRF52840 MDK USB Dongle: 1 MiB flash and 256 KiB RAM, all on the chip. - * FLASH below is only this firmware's part of the map (docs2/makerdiary.md): + * FLASH below is only this firmware's part of the map (docs/makerdiary.md): * * 0x00000..0x01000 MBR * 0x01000..0x96000 this firmware diff --git a/firmware/boards/nrf52840-mdk-dongle/src/fido.rs b/firmware/boards/nrf52840-mdk-dongle/src/fido.rs index ee04b97..0d5e06c 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/fido.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/fido.rs @@ -1,4 +1,4 @@ -//! Passkeys: Trussed and fido-authenticator (docs2/roadmap.md, phase 6), in the main loop +//! Passkeys: Trussed and fido-authenticator (docs/roadmap.md, phase 6), in the main loop //! like everything else. A CTAP request reaches `Passkeys::call` through the CTAPHID //! dispatch, fido-authenticator turns it into Trussed requests, and `Syscall` serves each //! of those on the spot by running the Trussed service inline: no interrupt, no runtime, diff --git a/firmware/boards/nrf52840-mdk-dongle/src/main.rs b/firmware/boards/nrf52840-mdk-dongle/src/main.rs index ecf1f47..e73b513 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/main.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/main.rs @@ -4,7 +4,7 @@ //! //! Runs on the board: `vkey check --wipe-everything` passed on 2026-10-13, flashed //! through the factory UF2 bootloader, which sits at 0xF4000 behind Nordic's MBR at 0x0 -//! (docs2/makerdiary.md). +//! (docs/makerdiary.md). #![no_std] #![no_main] @@ -80,7 +80,7 @@ const VAULT_LEN: u32 = 0x4_1000; const FS_LEN: u32 = 0x1_4000; /// One attempt sector and two copies of 128 KiB: the sizes decided in -/// docs2/makerdiary.md, smaller than the C6's because this chip has 1 MiB in all. +/// docs/makerdiary.md, smaller than the C6's because this chip has 1 MiB in all. const LAYOUT: Layout = Layout { attempts: 0x0_0000, state_a: 0x0_1000, @@ -147,7 +147,7 @@ impl Clock for Uptime { } /// The USB device with its two interfaces - CDC-ACM for vkey's protocol and CTAPHID for -/// FIDO (docs2/roadmap.md, phase 6) - polled from the main loop: nothing runs from an +/// FIDO (docs/roadmap.md, phase 6) - polled from the main loop: nothing runs from an /// interrupt. The bus is served wherever the key waits - for the next request (`Usb`) and /// for the button (`Panel`), which together cover all but Argon2 and flash writes, when /// the host's transfers simply wait. Shared by both through one `RefCell`, borrowed only @@ -442,7 +442,7 @@ impl rand_core_06::RngCore for Entropy { impl rand_core_06::CryptoRng for Entropy {} /// No chip key yet. This chip has no eFuse key, and its replacement - a secret in a -/// flash page locked by the ACL until reset - is not built (docs2/makerdiary.md). The +/// flash page locked by the ACL until reset - is not built (docs/makerdiary.md). The /// vault is protected by the PIN alone, and `vkey info` says so. struct NoChipKey; @@ -517,7 +517,7 @@ fn light(pin: &mut Pin>, on: bool) { /// What the chip says about itself, for a maintainer with no probe: the build code from /// FICR (`AAF0` - the third letter is the revision), the UICR `APPROTECT` word as stored, /// and why the chip last reset. The first two stay raw, because what an `APPROTECT` -/// value means depends on the revision; docs2/makerdiary.md reads them together. The +/// value means depends on the revision; docs/makerdiary.md reads them together. The /// factory bootloader leaves the reset cause for the application, and it is cleared /// here, so each boot reports only what happened since the last one. fn chip_report( diff --git a/tools/build-bootloader.sh b/tools/build-bootloader.sh index 211119e..59799a4 100755 --- a/tools/build-bootloader.sh +++ b/tools/build-bootloader.sh @@ -31,7 +31,7 @@ # INFO_UF2.TXT then names as a test key. Either must be a public key and nothing else. # A build with the real key copies bootloader.bin into images/, for bootloader/ # sign-vaultkey.sh to sign and the git hooks to check; a test build leaves its outputs -# in a temporary directory. Nothing is ever installed (docs2/roadmap.md, phase 3). +# in a temporary directory. Nothing is ever installed (docs/roadmap.md, phase 3). set -euo pipefail @@ -99,7 +99,7 @@ build_uf2() { key="$dir/bootloader/signing-key.pem" kind=real fi [[ -f "$key" ]] || { - echo "$name: no $key. The real key is not made yet (docs2/roadmap.md, phase 3);" >&2 + echo "$name: no $key. The real key is not made yet (docs/roadmap.md, phase 3);" >&2 echo " a test build: BOOTLOADER_TEST_KEY= $0" >&2 exit 1 } From 7bd76e172dc89602da22a2115debc111d340a13f Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 00:31:51 +0300 Subject: [PATCH 25/33] Add vkey commits github and /settings github: gh signed in, key added --- .github/workflows/audit.yml | 12 +++-- README.md | 7 ++- cli/src/commits.rs | 91 ++++++++++++++++++++++++++----------- cli/src/main.rs | 6 +++ cli/src/shell.rs | 11 +++++ 5 files changed, 94 insertions(+), 33 deletions(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index a6bc83c..f4145d0 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -5,9 +5,9 @@ name: audit on: push: - paths: ['**/Cargo.lock', '**/Cargo.toml', '.github/workflows/audit.yml'] + paths: ['**/Cargo.lock', '**/Cargo.toml', '**/.cargo/audit.toml', '.github/workflows/audit.yml'] pull_request: - paths: ['**/Cargo.lock', '**/Cargo.toml'] + paths: ['**/Cargo.lock', '**/Cargo.toml', '**/.cargo/audit.toml'] schedule: - cron: '17 6 * * 1' workflow_dispatch: @@ -24,5 +24,9 @@ jobs: persist-credentials: false # rust-toolchain.toml pins the version; rustup installs it on the first call. - run: cargo install cargo-audit --locked - - run: cargo audit --file firmware/Cargo.lock - - run: cargo audit --file cli/Cargo.lock + # From each folder, as tools/checks.sh does: cargo audit reads .cargo/audit.toml + # from the working directory, not from beside the lock file. + - run: cargo audit + working-directory: firmware + - run: cargo audit + working-directory: cli diff --git a/README.md b/README.md index 5f4d159..b285768 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,7 @@ with apt first if it is missing. ```bash vkey commits enable # a tap: an SSH key on the key, git signs every commit with it vkey commits disable # git stops signing; the key stays for the next enable +vkey commits github # the key on GitHub as a signing key: commits show as verified ``` `enable` makes an OpenSSH `ecdsa-sk` key on the nRF52840 (a tap) and keeps its handle in @@ -175,8 +176,10 @@ vkey commits disable # git stops signing; the key stays for the next enable `~/.ssh`, where GNOME Keyring's agent would take it and refuse to sign). It sets git's `gpg.format`, `user.signingkey`, `gpg.ssh.allowedSignersFile` and `commit.gpgsign` globally, refuses to overwrite a signing setup that is not its own, and offers to add the public half to -GitHub as a signing key (`gh`), so the commits show as verified there. From then on every -commit waits for a tap. In the shell it is `/settings` → `commits`, on or off. Linux only +GitHub as a signing key (`gh`), so the commits show as verified there. `github` does that +step alone: it signs `gh` in, or grants it the `admin:ssh_signing_key` permission, in the +browser when it has to, then adds the key. From then on every commit waits for a tap. In +the shell it is `/settings` → `commits`, on or off, and `/settings` → `github`. Linux only for now; macOS and Windows are issues #18 and #19. What it costs is in [the threat model](docs/threat-model.md#git-commits-signed-with-a-tap). diff --git a/cli/src/commits.rs b/cli/src/commits.rs index 7b2dcfa..791bb51 100644 --- a/cli/src/commits.rs +++ b/cli/src/commits.rs @@ -3,6 +3,7 @@ //! ```text //! vkey commits enable an SSH key on the key, git told to sign with it //! vkey commits disable git stops signing; the key stays for the next enable +//! vkey commits github the key on GitHub, so the commits show as verified //! ``` //! //! The key is a FIDO2 authenticator (the nRF52840's passkeys), and OpenSSH keeps a @@ -138,42 +139,78 @@ fn make_key(key: &Path) -> Result<(), Error> { } /// GitHub shows a commit as verified only when it knows the key as a signing key. -/// Uploading publishes it, so it is asked, and needs `gh` with the scope for it. +/// Uploading publishes it, so `enable` asks first. fn offer_to_github(key: &Path) -> Result<(), Error> { - let public = pub_path(key); - let by_hand = format!( - " gh ssh-key add {} --type signing --title vkey", - public.display() - ); - let gh = Command::new("gh").args(["auth", "status"]).output(); - if !matches!(gh, Ok(ref o) if o.status.success()) { + if !prompt::is_tty() + || !prompt::yes_no("add the key to GitHub, so the commits show as verified?") + { println!( - "for GitHub to show the commits as verified, add the key as a signing key:\n{by_hand}" + "to add it later: vkey commits github (or /settings → github)\n public key: {}", + pub_path(key).display() ); return Ok(()); } - if !prompt::is_tty() || !prompt::yes_no("add the key to GitHub as a signing key?") { - println!("to add it later:\n{by_hand}"); - return Ok(()); + github().map(drop) +} + +/// The scope `gh` needs to add a signing key; a plain `gh auth login` does not ask it. +const SCOPE: &str = "admin:ssh_signing_key"; + +/// `vkey commits github`: the signing key's public half on GitHub as a signing key, +/// signing `gh` in - or giving it the scope - in the browser first when it has to. +pub fn github() -> Result { + let public = pub_path(&home()?.join(KEY)); + if !public.exists() { + return Err(Error::Value( + "no signing key yet: vkey commits enable".into(), + )); } - let out = Command::new("gh") - .args(["ssh-key", "add"]) - .arg(&public) - .args(["--type", "signing", "--title", "vkey"]) - .output()?; - if out.status.success() { - println!("added to GitHub: commits signed by this key show as verified"); - return Ok(()); + let signed_in = match Command::new("gh").args(["auth", "status"]).output() { + Ok(out) => out.status.success(), + Err(_) => { + return Err(Error::Value( + "gh, GitHub's CLI, is missing: sudo apt install gh".into(), + )); + } + }; + if !signed_in { + println!("gh signs in to GitHub in the browser first"); + gh_interactive(&["auth", "login", "-h", "github.com", "-s", SCOPE])?; } + let mut out = add_key(&public)?; + if !out.status.success() && String::from_utf8_lossy(&out.stderr).contains(SCOPE) { + println!("gh needs one more permission, to add signing keys: grant it in the browser"); + gh_interactive(&["auth", "refresh", "-h", "github.com", "-s", SCOPE])?; + out = add_key(&public)?; + } + // gh answers success for a key GitHub already has, so both read the same. let why = String::from_utf8_lossy(&out.stderr); - if why.contains("admin:ssh_signing_key") { - println!( - "gh needs the scope to add signing keys first:\n gh auth refresh -h github.com -s admin:ssh_signing_key\nthen:\n{by_hand}" - ); - } else if why.contains("already") { - println!("GitHub already has this key"); + if out.status.success() || why.contains("already") { + println!("the key is on GitHub: commits signed with it show as verified"); } else { - println!("GitHub refused the key: {}\n{by_hand}", why.trim()); + return Err(Error::Value(format!( + "GitHub refused the key: {}", + why.trim() + ))); + } + Ok(0) +} + +fn add_key(public: &Path) -> Result { + Ok(Command::new("gh") + .args(["ssh-key", "add"]) + .arg(public) + .args(["--type", "signing", "--title", "vkey"]) + .output()?) +} + +/// `gh` with the terminal: it prints a one-time code and opens the browser. +fn gh_interactive(args: &[&str]) -> Result<(), Error> { + if !Command::new("gh").args(args).status()?.success() { + return Err(Error::Value(format!( + "gh {} did not finish", + args.join(" ") + ))); } Ok(()) } diff --git a/cli/src/main.rs b/cli/src/main.rs index 8319e6f..8ebf61a 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -216,6 +216,9 @@ enum CommitsCmd { Enable, /// git stops signing; the key stays for the next enable Disable, + /// The signing key on GitHub, so the commits show as verified; signs gh in, or + /// gives it the permission, in the browser when it has to + Github, } #[derive(Subcommand, Clone, Copy)] @@ -328,6 +331,9 @@ fn run_off_port(cli: &Cli) -> Option> { Cmd::Commits { cmd: CommitsCmd::Disable, } => commits::disable(), + Cmd::Commits { + cmd: CommitsCmd::Github, + } => commits::github(), Cmd::Setup { erase, board } => cmd_setup(cli.port.as_deref(), board.as_deref(), *erase), _ => return None, }) diff --git a/cli/src/shell.rs b/cli/src/shell.rs index c8bf53a..23cd804 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -70,6 +70,10 @@ const SETTINGS: &[(&str, &str)] = &[ "commits", "sign every git commit with a tap - turn on or off", ), + ( + "github", + "sign in to GitHub and add the signing key, so commits show as verified", + ), ( "wipe", "factory reset - every secret and the PIN; the button is held, not tapped", @@ -2434,6 +2438,13 @@ impl Shell { let r = self.cmd_commits(); return self.report(r); } + "github" => { + let r = std::env::current_exe() + .map_err(Error::from) + .and_then(|exe| self.outside(Command::new(exe).args(["commits", "github"]))) + .map(drop); + return self.report(r); + } _ => {} } if !self.connected() && !self.reconnect() { From 03cacbae27b4b47d6daa523ab59551fa761dc823 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 01:04:46 +0300 Subject: [PATCH 26/33] List and erase the key's passkeys under its FIDO PIN, a passkey tab vkey passkey list|rm|pin speak CTAP2 credentialManagement and clientPin (PIN protocol 1) over hidraw. The shell gets a passkey tab that asks the FIDO PIN once, and /settings gets passkey-pin. The FIDO PIN stays apart from vkey's: the key keeps it as a bare SHA-256. Also: github moves under the commits switch. --- CLAUDE.md | 5 + README.md | 19 +- cli/Cargo.lock | 210 +++++++++++++++++++++- cli/Cargo.toml | 7 + cli/src/commits.rs | 2 +- cli/src/fido.rs | 402 ++++++++++++++++++++++++++++++++++++++++++- cli/src/main.rs | 27 ++- cli/src/passkeys.rs | 106 ++++++++++++ cli/src/prompt.rs | 167 +++++++++++------- cli/src/shell.rs | 197 ++++++++++++++++++--- docs/threat-model.md | 19 ++ 11 files changed, 1073 insertions(+), 88 deletions(-) create mode 100644 cli/src/passkeys.rs diff --git a/CLAUDE.md b/CLAUDE.md index d895bdf..f095605 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -235,6 +235,11 @@ The boards: The shell's `/settings` turns `auth` and `commits` on and off by running these same commands outside raw mode (`sudo` for `auth`). Linux only; macOS and Windows are issues #18 and #19. +- `vkey passkey list|rm|pin` and the shell's `passkey` tab (2026-10-16, + `cli/src/passkeys.rs`) list and erase the discoverable passkeys through CTAP2 + credentialManagement under the key's FIDO PIN, which stays apart from vkey's PIN + (maintainer's decision): fido-authenticator keeps it as a bare SHA-256, so one PIN + for both would give a flash dump the vault's PIN. - A TOTP seed leaves the device two ways. The backup (`ExportBegin`/`ExportNext`, after a double tap; 2026-09-09) reseals every item under a key derived from a passphrase (Argon2id, `Passphrase` 12–128 bytes, without the chip key, so the file opens on another diff --git a/README.md b/README.md index b285768..1782f5b 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,23 @@ the password. In the shell, `/settings` → `auth` does the same in one step, and installs `libpam-u2f` with apt first if it is missing. +## Passkeys on the key + +```bash +vkey passkey list # site and account of every passkey the key keeps +vkey passkey rm # one erased from the key, picked from the list +vkey passkey pin # the FIDO PIN set, or changed +``` + +The nRF52840 keeps the passkeys sites make discoverable (webauthn.io's, a Google +account's). They sit behind the key's **FIDO PIN**, the one a browser asks for, which is +apart from vkey's PIN on purpose: the key stores it as a plain SHA-256, so the same PIN +for both would give a flash dump the vault's PIN too. In the shell the last tab of the +list is `passkey`: it asks the FIDO PIN once, lists them until the lock, and `d` erases +the highlighted one. Erasing it on the key does not remove it from the site. `/settings` +→ `passkey-pin` sets or changes the FIDO PIN. The `vkey auth` login and the commit +signing key are not kept on the key, so they are not in the list. + ## Git commits signed with a tap ```bash @@ -179,7 +196,7 @@ to overwrite a signing setup that is not its own, and offers to add the public h GitHub as a signing key (`gh`), so the commits show as verified there. `github` does that step alone: it signs `gh` in, or grants it the `admin:ssh_signing_key` permission, in the browser when it has to, then adds the key. From then on every commit waits for a tap. In -the shell it is `/settings` → `commits`, on or off, and `/settings` → `github`. Linux only +the shell it is `/settings` → `commits`: the switch, and `github` on the line under it. Linux only for now; macOS and Windows are issues #18 and #19. What it costs is in [the threat model](docs/threat-model.md#git-commits-signed-with-a-tap). diff --git a/cli/Cargo.lock b/cli/Cargo.lock index 19b09d5..54a2f57 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -122,6 +122,12 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.22.1" @@ -189,6 +195,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "block-padding" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bytemuck" version = "1.25.2" @@ -209,6 +224,15 @@ dependencies = [ "syn 3.0.5", ] +[[package]] +name = "cbc" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896" +dependencies = [ + "cipher", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -284,6 +308,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "const-oid" version = "0.10.2" @@ -381,6 +411,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -505,6 +547,16 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid 0.9.6", + "zeroize", +] + [[package]] name = "derive_more" version = "2.1.1" @@ -535,6 +587,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "crypto-common 0.1.7", + "subtle", ] [[package]] @@ -544,7 +597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer 0.12.1", - "const-oid", + "const-oid 0.10.2", "crypto-common 0.2.2", "ctutils", "zeroize", @@ -591,6 +644,38 @@ dependencies = [ "litrs", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "elliptic-curve", + "signature", + "spki", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "hkdf", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "embedded-storage" version = "0.3.1" @@ -666,6 +751,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "flate2" version = "1.1.10" @@ -706,6 +801,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -740,6 +836,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -752,6 +859,24 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "hmac" version = "0.13.0" @@ -894,6 +1019,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ + "block-padding", "hybrid-array", ] @@ -1130,6 +1256,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -1168,6 +1305,16 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.34" @@ -1195,6 +1342,15 @@ dependencies = [ "zerovec", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -1228,6 +1384,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "rand_core" version = "0.9.5" @@ -1359,6 +1524,20 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "1.0.28" @@ -1498,6 +1677,15 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "simd-adler32" version = "0.3.10" @@ -1516,6 +1704,16 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -1773,6 +1971,8 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" name = "vaultkey" version = "0.9.0" dependencies = [ + "aes", + "cbc", "clap", "crossterm", "csv-core", @@ -1780,13 +1980,15 @@ dependencies = [ "dirs", "espflash", "getrandom", - "hmac", + "hmac 0.13.0", + "p256", "percent-encoding", "rpassword", "serde", "serde_json", "serialport", "sha1", + "sha2", "toml", "url", "vaultkey-core", @@ -1801,8 +2003,8 @@ dependencies = [ "argon2", "crc", "embedded-storage", - "hmac", - "rand_core", + "hmac 0.13.0", + "rand_core 0.9.5", "sha1", "sha2", "subtle", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 27f08d1..21487ad 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -30,6 +30,13 @@ dirs = "6" # The self-test's second opinion: an HMAC that is not the firmware's. hmac = "0.13" sha1 = "0.11" +# The key's FIDO PIN, spoken as CTAP2 PIN protocol 1 asks: an ECDH agreement on P-256, +# its SHA-256 as the shared key, AES-256-CBC for the PIN and the token, HMAC-SHA-256 for +# every request that needs one (cli/src/fido.rs). +p256 = { version = "0.13", default-features = false, features = ["ecdh", "std"] } +sha2 = "0.11" +aes = "0.9" +cbc = "0.2" zeroize = "1" # Generated passwords: the OS random source, nothing seeded in userland. getrandom = "0.2" diff --git a/cli/src/commits.rs b/cli/src/commits.rs index 791bb51..4d81e28 100644 --- a/cli/src/commits.rs +++ b/cli/src/commits.rs @@ -145,7 +145,7 @@ fn offer_to_github(key: &Path) -> Result<(), Error> { || !prompt::yes_no("add the key to GitHub, so the commits show as verified?") { println!( - "to add it later: vkey commits github (or /settings → github)\n public key: {}", + "to add it later: vkey commits github (or /settings → commits → github)\n public key: {}", pub_path(key).display() ); return Ok(()); diff --git a/cli/src/fido.rs b/cli/src/fido.rs index 2e252f5..f5306ae 100644 --- a/cli/src/fido.rs +++ b/cli/src/fido.rs @@ -2,11 +2,25 @@ //! to make a credential and try it. `pamu2fcfg` would do the first half, but the 1.1.0 //! that distributions ship insists on an attestation certificate, and this key attests //! with the credential's own key, as `WebAuthn` allows (docs/roadmap.md, phase 6). +//! +//! And the passkeys the key keeps, through credentialManagement under the key's FIDO +//! PIN - its own, not vkey's: fido-authenticator keeps that PIN as a bare SHA-256, so +//! one PIN for both would hand a flash dump the vault's PIN in seconds. PIN protocol 1: +//! an ECDH agreement, its SHA-256 as the shared key, AES-256-CBC under a zero IV, and an +//! HMAC-SHA-256 cut to 16 bytes. use std::fs::{self, File, OpenOptions}; use std::io::{Read, Write}; use std::path::PathBuf; +use aes::cipher::block_padding::NoPadding; +use aes::cipher::{BlockModeDecrypt, BlockModeEncrypt, KeyIvInit}; +use hmac::{Hmac, KeyInit, Mac}; +use p256::elliptic_curve::sec1::ToEncodedPoint; +use p256::{PublicKey, SecretKey}; +use sha2::{Digest, Sha256}; +use zeroize::Zeroizing; + use crate::boards::BOARDS; use crate::device::Error; @@ -18,6 +32,30 @@ const CMD_KEEPALIVE: u8 = 0x3B; const CMD_ERROR: u8 = 0x3F; const MAKE_CREDENTIAL: u8 = 0x01; const GET_ASSERTION: u8 = 0x02; +const GET_INFO: u8 = 0x04; +const CLIENT_PIN: u8 = 0x06; +const CREDENTIAL_MANAGEMENT: u8 = 0x0A; +/// clientPin subcommands, and the one permission asked for. +const PIN_KEY_AGREEMENT: i64 = 0x02; +const PIN_SET: i64 = 0x03; +const PIN_CHANGE: i64 = 0x04; +const PIN_TOKEN_WITH_PERMISSIONS: i64 = 0x09; +const PERMISSION_CREDENTIAL_MANAGEMENT: i64 = 0x04; +const PIN_PROTOCOL: i64 = 1; +/// credentialManagement subcommands. +const RPS_BEGIN: u8 = 0x02; +const RPS_NEXT: u8 = 0x03; +const CREDENTIALS_BEGIN: u8 = 0x04; +const CREDENTIALS_NEXT: u8 = 0x05; +const DELETE_CREDENTIAL: u8 = 0x06; +/// The status for "nothing stored": an empty list, not a failure. +const NO_CREDENTIALS: u8 = 0x2E; +/// COSE: ECDH-ES with HKDF-256, what a key-agreement key is labelled. +const COSE_ECDH_ES_HKDF_256: i64 = -25; +/// A FIDO PIN is 4 to 63 bytes, sent padded with zeros to 64. +pub const FIDO_PIN_MIN: usize = 4; +pub const FIDO_PIN_MAX: usize = 63; +const PIN_PADDED: usize = 64; /// COSE: EC2 keys, P-256, ES256. const COSE_EC2: i64 = 2; const COSE_P256: i64 = 1; @@ -29,6 +67,19 @@ pub struct Credential { pub public: [u8; 64], } +/// A passkey the key keeps: the site it is for, the account on it, and its id, which is +/// what deleting it takes. +#[derive(Clone)] +pub struct Passkey { + pub site: String, + pub user: String, + pub id: Vec, +} + +/// What the FIDO PIN unlocked: a token that lets credentialManagement through until the +/// key forgets it (a replug, or another PIN). +pub struct Token(Zeroizing>); + /// The key's CTAPHID interface on a channel of its own. pub struct Key { hid: File, @@ -118,20 +169,256 @@ impl Key { Ok(()) } + /// Whether the key has a FIDO PIN, as getInfo's `clientPin` option says. + pub fn pin_is_set(&mut self) -> Result { + let info = self + .cbor_status(GET_INFO, None)? + .map_err(|CtapError(status)| Error::Value(ctap_error(status)))?; + let Some(Cbor::Map(options)) = field(&info, 4) else { + return Ok(false); + }; + Ok(options + .iter() + .any(|(k, v)| *k == text("clientPin") && *v == Cbor::Simple(21))) + } + + /// The FIDO PIN set where there is none yet. + pub fn set_pin(&mut self, new: &str) -> Result<(), Error> { + let (platform, shared) = self.agree()?; + let new_enc = encrypt(&shared, &padded_pin(new)?)?; + let auth = authenticate(&*shared, &new_enc)?; + self.cbor( + CLIENT_PIN, + &Cbor::Map(vec![ + (Cbor::Int(1), Cbor::Int(PIN_PROTOCOL)), + (Cbor::Int(2), Cbor::Int(PIN_SET)), + (Cbor::Int(3), platform), + (Cbor::Int(4), Cbor::Bytes(auth)), + (Cbor::Int(5), Cbor::Bytes(new_enc)), + ]), + ) + .map(drop) + } + + /// The FIDO PIN changed from `old` to `new`. A wrong `old` costs one of its retries. + pub fn change_pin(&mut self, old: &str, new: &str) -> Result<(), Error> { + let (platform, shared) = self.agree()?; + let new_enc = encrypt(&shared, &padded_pin(new)?)?; + let hash_enc = encrypt(&shared, &pin_hash(old))?; + let mut signed = new_enc.clone(); + signed.extend_from_slice(&hash_enc); + let auth = authenticate(&*shared, &signed)?; + self.cbor( + CLIENT_PIN, + &Cbor::Map(vec![ + (Cbor::Int(1), Cbor::Int(PIN_PROTOCOL)), + (Cbor::Int(2), Cbor::Int(PIN_CHANGE)), + (Cbor::Int(3), platform), + (Cbor::Int(4), Cbor::Bytes(auth)), + (Cbor::Int(5), Cbor::Bytes(new_enc)), + (Cbor::Int(6), Cbor::Bytes(hash_enc)), + ]), + ) + .map(drop) + } + + /// A token for credentialManagement and nothing else. A wrong PIN costs one of its + /// retries; three in a row want the key replugged. + pub fn token(&mut self, pin: &str) -> Result { + let (platform, shared) = self.agree()?; + let hash_enc = encrypt(&shared, &pin_hash(pin))?; + let answer = self.cbor( + CLIENT_PIN, + &Cbor::Map(vec![ + (Cbor::Int(1), Cbor::Int(PIN_PROTOCOL)), + (Cbor::Int(2), Cbor::Int(PIN_TOKEN_WITH_PERMISSIONS)), + (Cbor::Int(3), platform), + (Cbor::Int(6), Cbor::Bytes(hash_enc)), + (Cbor::Int(9), Cbor::Int(PERMISSION_CREDENTIAL_MANAGEMENT)), + ]), + )?; + let sealed = field(&answer, 2) + .and_then(Cbor::as_bytes) + .ok_or_else(|| Error::Value("the key's answer has no PIN token".into()))?; + Ok(Token(Zeroizing::new(decrypt(&shared, sealed)?))) + } + + /// Every passkey the key keeps, site by site. + pub fn passkeys(&mut self, token: &Token) -> Result, Error> { + let mut out = Vec::new(); + let Some(first) = self.manage(token, RPS_BEGIN, None)? else { + return Ok(out); + }; + let total = field(&first, 5).and_then(Cbor::as_int).unwrap_or(1); + let mut sites = vec![first]; + for _ in 1..total { + if let Some(next) = self.manage(token, RPS_NEXT, None)? { + sites.push(next); + } + } + for site in &sites { + let name = field(site, 3) + .and_then(|rp| text_field(rp, "id")) + .unwrap_or("?") + .to_string(); + let hash = field(site, 4) + .and_then(Cbor::as_bytes) + .ok_or_else(|| Error::Value("the key named a site without its hash".into()))?; + let params = Cbor::Map(vec![(Cbor::Int(1), Cbor::Bytes(hash.to_vec()))]); + let Some(first) = self.manage(token, CREDENTIALS_BEGIN, Some(params))? else { + continue; + }; + let total = field(&first, 9).and_then(Cbor::as_int).unwrap_or(1); + let mut creds = vec![first]; + for _ in 1..total { + if let Some(next) = self.manage(token, CREDENTIALS_NEXT, None)? { + creds.push(next); + } + } + for c in &creds { + let user = field(c, 6); + let shown = user + .and_then(|u| text_field(u, "name")) + .or_else(|| user.and_then(|u| text_field(u, "displayName"))) + .unwrap_or("") + .to_string(); + let id = field(c, 7) + .and_then(|d| bytes_field(d, "id")) + .ok_or_else(|| { + Error::Value("the key listed a passkey without its id".into()) + })?; + out.push(Passkey { + site: name.clone(), + user: shown, + id: id.to_vec(), + }); + } + } + Ok(out) + } + + /// The passkey with `id` erased from the key. What the site holds stays there: the + /// account still names this passkey until it is removed on the site too. + pub fn delete_passkey(&mut self, token: &Token, id: &[u8]) -> Result<(), Error> { + let params = Cbor::Map(vec![( + Cbor::Int(2), + Cbor::Map(vec![ + (text("id"), Cbor::Bytes(id.to_vec())), + (text("type"), text("public-key")), + ]), + )]); + self.manage(token, DELETE_CREDENTIAL, Some(params)) + .map(drop) + } + + /// One credentialManagement subcommand. The first of a listing and every change + /// carry the token's HMAC over the subcommand and its parameters; the "next" ones + /// continue what was already allowed. None when the key holds nothing to list. + fn manage( + &mut self, + token: &Token, + sub: u8, + params: Option, + ) -> Result, Error> { + let mut request = vec![(Cbor::Int(1), Cbor::Int(i64::from(sub)))]; + if !matches!(sub, RPS_NEXT | CREDENTIALS_NEXT) { + let mut signed = vec![sub]; + if let Some(p) = ¶ms { + p.encode(&mut signed); + } + if let Some(p) = params { + request.push((Cbor::Int(2), p)); + } + request.push((Cbor::Int(3), Cbor::Int(PIN_PROTOCOL))); + request.push((Cbor::Int(4), Cbor::Bytes(authenticate(&token.0, &signed)?))); + } + match self.cbor_status(CREDENTIAL_MANAGEMENT, Some(&Cbor::Map(request)))? { + Ok(answer) => Ok(Some(answer)), + Err(CtapError(NO_CREDENTIALS)) => Ok(None), + Err(CtapError(status)) => Err(Error::Value(ctap_error(status))), + } + } + + /// A fresh ECDH agreement with the key: the platform's public half as COSE, and the + /// shared key, SHA-256 of the shared point's x. + fn agree(&mut self) -> Result<(Cbor, Zeroizing<[u8; 32]>), Error> { + let answer = self.cbor( + CLIENT_PIN, + &Cbor::Map(vec![ + (Cbor::Int(1), Cbor::Int(PIN_PROTOCOL)), + (Cbor::Int(2), Cbor::Int(PIN_KEY_AGREEMENT)), + ]), + )?; + let key = field(&answer, 1) + .ok_or_else(|| Error::Value("the key sent no key-agreement key".into()))?; + let coord = |k: i64| { + field(key, k) + .and_then(Cbor::as_bytes) + .filter(|b| b.len() == 32) + }; + let (Some(x), Some(y)) = (coord(-2), coord(-3)) else { + return Err(Error::Value( + "the key's key-agreement key is malformed".into(), + )); + }; + let mut sec1 = vec![0x04]; + sec1.extend_from_slice(x); + sec1.extend_from_slice(y); + let peer = PublicKey::from_sec1_bytes(&sec1) + .map_err(|_| Error::Value("the key's key-agreement key is not on P-256".into()))?; + // The scalar from the OS random source; the odd value outside the group is drawn + // again rather than reduced. + let secret = loop { + if let Ok(s) = SecretKey::from_slice(&*Zeroizing::new(random32()?)) { + break s; + } + }; + let point = p256::ecdh::diffie_hellman(secret.to_nonzero_scalar(), peer.as_affine()); + let shared = Zeroizing::new(<[u8; 32]>::from(Sha256::digest(point.raw_secret_bytes()))); + let public = secret.public_key().to_encoded_point(false); + let (Some(px), Some(py)) = (public.x(), public.y()) else { + return Err(Error::Value("no public point".into())); + }; + let platform = Cbor::Map(vec![ + (Cbor::Int(1), Cbor::Int(COSE_EC2)), + (Cbor::Int(3), Cbor::Int(COSE_ECDH_ES_HKDF_256)), + (Cbor::Int(-1), Cbor::Int(COSE_P256)), + (Cbor::Int(-2), Cbor::Bytes(px.to_vec())), + (Cbor::Int(-3), Cbor::Bytes(py.to_vec())), + ]); + Ok((platform, shared)) + } + /// A CTAP2 command and its answer, the status byte checked. fn cbor(&mut self, command: u8, request: &Cbor) -> Result { + self.cbor_status(command, Some(request))? + .map_err(|CtapError(status)| Error::Value(ctap_error(status))) + } + + /// The answer, or the key's CTAP2 status when it refused: the transport failing is + /// the outer error, the key saying no the inner one. + fn cbor_status( + &mut self, + command: u8, + request: Option<&Cbor>, + ) -> Result, Error> { let mut payload = vec![command]; - request.encode(&mut payload); + if let Some(r) = request { + r.encode(&mut payload); + } let answer = self.transact(CMD_CBOR, &payload)?; let (&status, body) = answer .split_first() .ok_or_else(|| Error::Value("the key answered with nothing".into()))?; if status != 0 { - return Err(Error::Value(ctap_error(status))); + return Ok(Err(CtapError(status))); + } + if body.is_empty() { + return Ok(Ok(Cbor::Map(Vec::new()))); } Cbor::decode(body) .filter(|(_, rest)| rest.is_empty()) - .map(|(v, _)| v) + .map(|(v, _)| Ok(v)) .ok_or_else(|| Error::Value("the key's answer is not CBOR".into())) } @@ -264,12 +551,85 @@ fn ctap_error(status: u8) -> String { 0x2D => "the request was cancelled", 0x2E => "the key has no such credential", 0x2F => "nobody tapped the key in time", + 0x31 => "wrong FIDO PIN", + 0x32 => "the FIDO PIN is blocked: only a FIDO reset (every passkey gone) clears it", + 0x33 | 0x34 => "three wrong FIDO PINs in a row: replug the key and try again", + 0x35 => "the key has no FIDO PIN yet: set one in /settings → passkey PIN", 0x36 => "the key's FIDO PIN is needed", + 0x37 => "the key does not take that FIDO PIN (4 to 63 characters)", _ => "the key refused the request", }; format!("{why} (CTAP2 status {status:#04x})") } +/// A CTAP2 status other than success: the key answered, and said no. +struct CtapError(u8); + +/// AES-256-CBC under the zero IV, as PIN protocol 1 has it; `data` is whole blocks. +fn encrypt(key: &[u8; 32], data: &[u8]) -> Result, Error> { + let mut buf = data.to_vec(); + cbc::Encryptor::::new(key.into(), &[0u8; 16].into()) + .encrypt_padded::(&mut buf, data.len()) + .map_err(|_| Error::Value("not whole AES blocks".into()))?; + Ok(buf) +} + +fn decrypt(key: &[u8; 32], data: &[u8]) -> Result, Error> { + let mut buf = data.to_vec(); + let len = cbc::Decryptor::::new(key.into(), &[0u8; 16].into()) + .decrypt_padded::(&mut buf) + .map_err(|_| Error::Value("the key's ciphertext is not whole AES blocks".into()))? + .len(); + buf.truncate(len); + Ok(buf) +} + +/// HMAC-SHA-256 under `key`, its first 16 bytes: PIN protocol 1's `pinUvAuthParam`. +fn authenticate(key: &[u8], data: &[u8]) -> Result, Error> { + let mut mac = as KeyInit>::new_from_slice(key) + .map_err(|_| Error::Value("no HMAC key".into()))?; + mac.update(data); + Ok(mac.finalize().into_bytes()[..16].to_vec()) +} + +/// The first 16 bytes of the PIN's SHA-256: what the key compares with what it stored. +fn pin_hash(pin: &str) -> Zeroizing> { + Zeroizing::new(Sha256::digest(pin.as_bytes())[..16].to_vec()) +} + +/// A new PIN padded with zeros to 64 bytes; its length checked as the key will. +fn padded_pin(pin: &str) -> Result>, Error> { + if !(FIDO_PIN_MIN..=FIDO_PIN_MAX).contains(&pin.len()) { + return Err(Error::Value(format!( + "a FIDO PIN is {FIDO_PIN_MIN} to {FIDO_PIN_MAX} characters" + ))); + } + let mut out = Zeroizing::new(vec![0u8; PIN_PADDED]); + out[..pin.len()].copy_from_slice(pin.as_bytes()); + Ok(out) +} + +/// The text under key `k` of a CBOR map keyed by text. +fn text_field<'a>(map: &'a Cbor, k: &str) -> Option<&'a str> { + let Cbor::Map(entries) = map else { + return None; + }; + entries.iter().find_map(|(key, v)| match (key, v) { + (Cbor::Text(name), Cbor::Text(t)) if name == k => Some(t.as_str()), + _ => None, + }) +} + +fn bytes_field<'a>(map: &'a Cbor, k: &str) -> Option<&'a [u8]> { + let Cbor::Map(entries) = map else { + return None; + }; + entries.iter().find_map(|(key, v)| match (key, v) { + (Cbor::Text(name), Cbor::Bytes(b)) if name == k => Some(b.as_slice()), + _ => None, + }) +} + fn random32() -> Result<[u8; 32], Error> { let mut b = [0u8; 32]; getrandom::getrandom(&mut b).map_err(|e| Error::Value(format!("no randomness: {e}")))?; @@ -500,4 +860,40 @@ mod tests { let deep = [0x81u8; 64]; assert_eq!(Cbor::decode(&deep), None); } + + #[test] + fn a_new_fido_pin_is_padded_to_64_and_held_to_its_length() { + let p = padded_pin("1234").expect("four is the shortest"); + assert_eq!(p.len(), 64, "padded to 64"); + assert_eq!(&p[..5], b"1234\0", "zeros after the PIN"); + assert!(padded_pin("123").is_err(), "three is too short"); + assert!( + padded_pin(&"9".repeat(64)).is_err(), + "64 leaves no zero to end it" + ); + } + + #[test] + fn aes_cbc_under_the_zero_iv_round_trips_whole_blocks() { + let key = [7u8; 32]; + let data = [1u8; 32]; + let sealed = encrypt(&key, &data).expect("whole blocks"); + assert_ne!(sealed, data, "encrypted"); + assert_eq!(decrypt(&key, &sealed).expect("opens"), data, "back again"); + assert!( + encrypt(&key, &[0u8; 15]).is_err(), + "a partial block is refused" + ); + } + + #[test] + fn the_pin_auth_is_the_hmac_cut_to_16_bytes() { + let full = as KeyInit>::new_from_slice(b"k") + .expect("any key") + .chain_update(b"data") + .finalize() + .into_bytes(); + assert_eq!(authenticate(b"k", b"data").expect("hmac"), full[..16]); + assert_eq!(pin_hash("1234").len(), 16, "the PIN hash is cut to 16 too"); + } } diff --git a/cli/src/main.rs b/cli/src/main.rs index 8ebf61a..d2de627 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -32,6 +32,7 @@ mod import; mod install; mod item; mod op; +mod passkeys; mod prompt; mod setup; mod shell; @@ -205,10 +206,25 @@ enum Cmd { #[command(subcommand)] cmd: CommitsCmd, }, + /// The passkeys the key keeps, under its FIDO PIN (not vkey's PIN) + Passkey { + #[command(subcommand)] + cmd: PasskeyCmd, + }, /// Copy this binary to ~/.local/bin/vkey Install, } +#[derive(Subcommand, Clone, Copy)] +enum PasskeyCmd { + /// Site and account of every passkey on the key + List, + /// One passkey erased from the key, picked from the list + Rm, + /// The FIDO PIN set, or changed + Pin, +} + #[derive(Subcommand, Clone, Copy)] enum CommitsCmd { /// An SSH key on the key (a tap, once), git set to sign every commit with it, and @@ -334,6 +350,11 @@ fn run_off_port(cli: &Cli) -> Option> { Cmd::Commits { cmd: CommitsCmd::Github, } => commits::github(), + Cmd::Passkey { cmd } => match cmd { + PasskeyCmd::List => passkeys::list(), + PasskeyCmd::Rm => passkeys::rm(), + PasskeyCmd::Pin => passkeys::pin(), + }, Cmd::Setup { erase, board } => cmd_setup(cli.port.as_deref(), board.as_deref(), *erase), _ => return None, }) @@ -356,7 +377,11 @@ fn run(cli: Cli) -> Result { }; match cmd { - Cmd::Install | Cmd::Setup { .. } | Cmd::Auth { .. } | Cmd::Commits { .. } => { + Cmd::Install + | Cmd::Setup { .. } + | Cmd::Auth { .. } + | Cmd::Commits { .. } + | Cmd::Passkey { .. } => { unreachable!("handled above") } diff --git a/cli/src/passkeys.rs b/cli/src/passkeys.rs new file mode 100644 index 0000000..505c9ba --- /dev/null +++ b/cli/src/passkeys.rs @@ -0,0 +1,106 @@ +//! `vkey passkey`: the passkeys the nRF52840 keeps, under the key's FIDO PIN. +//! +//! ```text +//! vkey passkey list site and account of every passkey on the key +//! vkey passkey rm one of them erased, picked from the list +//! vkey passkey pin the FIDO PIN set, or changed +//! ``` +//! +//! The FIDO PIN is the passkeys' own and stays apart from vkey's (`crate::fido` says +//! why). Only passkeys a site made discoverable are kept on the key; the `vkey auth` +//! login and the commit signing key are not, so no list shows them. + +use zeroize::Zeroizing; + +use crate::device::Error; +use crate::fido::{FIDO_PIN_MAX, FIDO_PIN_MIN, Key, Passkey, Token}; +use crate::prompt; + +/// The key, and a token from its FIDO PIN. +pub fn unlocked() -> Result<(Key, Token), Error> { + let mut key = Key::open()?; + let pin = prompt::prompt_secret("FIDO PIN")?; + let token = key.token(&pin)?; + Ok((key, token)) +} + +pub fn list() -> Result { + let (mut key, token) = unlocked()?; + let all = key.passkeys(&token)?; + if all.is_empty() { + println!("no passkeys on the key"); + } + for p in &all { + println!("{}\t{}", p.site, p.user); + } + Ok(0) +} + +pub fn rm() -> Result { + let (mut key, token) = unlocked()?; + let all = key.passkeys(&token)?; + let labels: Vec = all.iter().map(label).collect(); + let options: Vec<(usize, &str, &str)> = labels + .iter() + .enumerate() + .map(|(i, l)| (i, l.as_str(), "")) + .collect(); + let Some(at) = prompt::choose("erase which passkey?", &options) else { + println!("nothing erased"); + return Ok(0); + }; + if !prompt::yes_no(&format!( + "erase {} from the key? the site still lists it until you remove it there", + labels[at] + )) { + println!("nothing erased"); + return Ok(0); + } + key.delete_passkey(&token, &all[at].id)?; + println!("erased {}", labels[at]); + Ok(0) +} + +/// `vkey passkey pin`: set where there is none, changed where there is. +pub fn pin() -> Result { + let mut key = Key::open()?; + let old = if key.pin_is_set()? { + Some(prompt::prompt_secret("current FIDO PIN")?) + } else { + None + }; + let new = new_pin()?; + match old { + Some(old) => key.change_pin(&old, &new)?, + None => key.set_pin(&new)?, + } + println!("the FIDO PIN is set: browsers and vkey ask for it before the passkeys"); + Ok(0) +} + +/// A new FIDO PIN, asked twice. +pub fn new_pin() -> Result, Error> { + let new = prompt::prompt_secret(&format!( + "new FIDO PIN ({FIDO_PIN_MIN}-{FIDO_PIN_MAX} characters, not vkey's PIN)" + ))?; + if !(FIDO_PIN_MIN..=FIDO_PIN_MAX).contains(&new.len()) { + return Err(Error::Value(format!( + "a FIDO PIN is {FIDO_PIN_MIN} to {FIDO_PIN_MAX} characters" + ))); + } + if prompt::prompt_secret("again")? != new { + return Err(Error::Value( + "the two did not match; nothing changed".into(), + )); + } + Ok(new) +} + +/// How a passkey is named to a person: the site and, when the site gave one, the account. +pub fn label(p: &Passkey) -> String { + if p.user.is_empty() { + p.site.clone() + } else { + format!("{} - {}", p.site, p.user) + } +} diff --git a/cli/src/prompt.rs b/cli/src/prompt.rs index ca6da86..5985084 100644 --- a/cli/src/prompt.rs +++ b/cli/src/prompt.rs @@ -212,94 +212,69 @@ fn pick(label: &str, options: &[(T, &str, &str)], danger_from: usize) - chosen.map(|i| options[i].0) } -/// An off/on switch on one line, starting where the setting is now: ← → (or Tab, -/// Space, h, l) move it, Enter keeps what it shows, Esc or Ctrl-C leaves it. Only the -/// answer stays on screen. Works inside the shell's raw mode and on a plain terminal. -pub fn switch(label: &str, on: bool) -> Option { - // Columns before the label: " ▸ ", " off ", " ", " on ", " ", " ". - const SWITCH: usize = 16; +/// What `switch` came back with: the switch set to a side, or one of the actions +/// listed under it, by its place in the list. +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum Flip { + To(bool), + Action(usize), +} + +/// An off/on switch, starting where the setting is now, with actions that belong to it +/// on the lines under it - each `(name, description)`. ← → (or Tab, Space, h, l) move +/// the switch, ↑ ↓ go between it and the actions, Enter takes what is highlighted, Esc +/// or Ctrl-C leaves it all. Only the answer stays on screen. Works inside the shell's +/// raw mode and on a plain terminal. +pub fn switch(label: &str, on: bool, actions: &[(&str, &str)]) -> Option { let was_raw = terminal::is_raw_mode_enabled().unwrap_or(false); if !was_raw && terminal::enable_raw_mode().is_err() { return None; } let mut so = io::stdout(); - // The switch first, then as much of the label as the width leaves: the line never - // wraps, so a redraw is always one line. - let draw = |so: &mut io::Stdout, sel: bool| -> usize { - let width = terminal::size() - .map_or(80, |(c, _)| usize::from(c)) - .saturating_sub(1); - let _ = queue!( - so, - MoveToColumn(0), - Clear(ClearType::CurrentLine), - SetForegroundColor(ACCENT), - Print(" ▸ "), - ResetColor - ); - for (value, name) in [(false, " off "), (true, " on ")] { - let picked = value == sel; - let _ = queue!( - so, - SetForegroundColor(if picked { ACCENT } else { DIM }), - SetAttribute(if picked { - Attribute::Reverse - } else { - Attribute::Reset - }), - Print(name), - SetAttribute(Attribute::Reset), - ResetColor, - Print(" ") - ); - } - let room = width.saturating_sub(SWITCH); - let shown: String = label.chars().take(room).collect(); - let len = SWITCH + shown.chars().count(); - let _ = queue!(so, Print(" "), Print(shown)); - let _ = so.flush(); - len - }; let mut sel = on; - let mut drawn = draw(&mut so, sel); + // 0 is the switch, 1.. the actions. + let mut row = 0; + let mut drawn = draw_switch(&mut so, label, sel, row, actions); let chosen = loop { let Ok(event) = event::read() else { continue; }; let key = match event { Event::Key(key) if key.kind == KeyEventKind::Press => key, - // A narrower window rewraps the line already drawn into more rows, with the - // cursor on the last: up to the first of them, clear, draw to the new width. + // A narrower window rewraps the lines already drawn into more rows, with + // the cursor at the end of the last: up to the first of them, then redraw. Event::Resize(cols, _) => { - let up = drawn.saturating_sub(1) / usize::from(cols.max(1)); - if let Ok(up @ 1..) = u16::try_from(up) { - let _ = queue!(so, MoveUp(up)); - } - let _ = queue!(so, MoveToColumn(0), Clear(ClearType::FromCursorDown)); - drawn = draw(&mut so, sel); + let cols = usize::from(cols.max(1)); + let rows: usize = drawn.iter().map(|n| n.saturating_sub(1) / cols + 1).sum(); + up_and_clear(&mut so, rows); + drawn = draw_switch(&mut so, label, sel, row, actions); continue; } _ => continue, }; match (key.code, key.modifiers) { - (KeyCode::Enter, _) => break Some(sel), + (KeyCode::Enter, _) if row == 0 => break Some(Flip::To(sel)), + (KeyCode::Enter, _) => break Some(Flip::Action(row - 1)), (KeyCode::Esc, _) | (KeyCode::Char('c' | 'd'), KeyModifiers::CONTROL) => break None, (KeyCode::Left | KeyCode::Char('h'), _) => sel = false, (KeyCode::Right | KeyCode::Char('l'), _) => sel = true, (KeyCode::Tab | KeyCode::BackTab | KeyCode::Char(' '), _) => sel = !sel, + (KeyCode::Up | KeyCode::Char('k'), _) => row = row.saturating_sub(1), + (KeyCode::Down | KeyCode::Char('j'), _) => row = (row + 1).min(actions.len()), _ => {} } - drawn = draw(&mut so, sel); + up_and_clear(&mut so, drawn.len()); + drawn = draw_switch(&mut so, label, sel, row, actions); }; let answer = match chosen { - Some(true) => "on", - Some(false) => "off", + Some(Flip::To(true)) => "on", + Some(Flip::To(false)) => "off", + Some(Flip::Action(i)) => actions[i].0, None => "never mind", }; + up_and_clear(&mut so, drawn.len()); let _ = queue!( so, - MoveToColumn(0), - Clear(ClearType::CurrentLine), SetForegroundColor(ACCENT), Print(" ▸ "), ResetColor, @@ -317,6 +292,82 @@ pub fn switch(label: &str, on: bool) -> Option { chosen } +/// From the last of `rows` rows up to the first, cleared downwards. +fn up_and_clear(so: &mut io::Stdout, rows: usize) { + if let Ok(up @ 1..) = u16::try_from(rows.saturating_sub(1)) { + let _ = queue!(so, MoveUp(up)); + } + let _ = queue!(so, MoveToColumn(0), Clear(ClearType::FromCursorDown)); +} + +/// The switch line and the action lines, each cut to the width so none wraps; the +/// cursor stays at the end of the last. Their lengths, for the next redraw. +fn draw_switch( + so: &mut io::Stdout, + label: &str, + sel: bool, + row: usize, + actions: &[(&str, &str)], +) -> Vec { + // Columns before the label: " ▸ ", " off ", " ", " on ", " ", " ". + const SWITCH: usize = 16; + let width = terminal::size() + .map_or(80, |(c, _)| usize::from(c)) + .saturating_sub(1); + let marker = if row == 0 { " ▸ " } else { " " }; + let _ = queue!(so, SetForegroundColor(ACCENT), Print(marker), ResetColor); + for (value, name) in [(false, " off "), (true, " on ")] { + let picked = value == sel; + let _ = queue!( + so, + SetForegroundColor(if picked { ACCENT } else { DIM }), + SetAttribute(if picked { + Attribute::Reverse + } else { + Attribute::Reset + }), + Print(name), + SetAttribute(Attribute::Reset), + ResetColor, + Print(" ") + ); + } + let shown: String = label.chars().take(width.saturating_sub(SWITCH)).collect(); + let mut lens = vec![SWITCH + shown.chars().count()]; + let _ = queue!(so, Print(" "), Print(shown)); + let name_w = actions + .iter() + .map(|(n, _)| n.chars().count()) + .max() + .unwrap_or(0); + for (i, (name, desc)) in actions.iter().enumerate() { + let here = row == i + 1; + let line: String = format!( + "{}{name: Result { diff --git a/cli/src/shell.rs b/cli/src/shell.rs index 23cd804..69c0809 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -30,7 +30,9 @@ use crate::device::{ }; use crate::item::{Item, category_name}; use crate::prompt::{ACCENT, DIM, PinPrompt, WARN_AT, copy_secret, copy_to_clipboard}; -use crate::{auth, backup, commits, import, op, prompt, setup, sources, totp}; +use crate::{ + auth, backup, boards, commits, fido, import, op, passkeys, prompt, setup, sources, totp, +}; /// Commands live behind `/`; a bare word is the name of an entry to use. const COMMANDS: &[(&str, &str)] = &[ @@ -71,8 +73,8 @@ const SETTINGS: &[(&str, &str)] = &[ "sign every git commit with a tap - turn on or off", ), ( - "github", - "sign in to GitHub and add the signing key, so commits show as verified", + "passkey-pin", + "set or change the passkeys' FIDO PIN - its own, not vkey's PIN", ), ( "wipe", @@ -88,7 +90,7 @@ const DANGER: usize = 2; /// Reached from the list with a, e, d and i, never offered as commands: an entry has /// one place, and the list is it. They still resolve when typed, so the transcript's /// `❯ /rm name` is a line that would work. -const LIST_COMMANDS: &[&str] = &["add", "edit", "rm", "import"]; +const LIST_COMMANDS: &[&str] = &["add", "edit", "rm", "import", "passkeys", "passkey-rm"]; const SETTLE: Duration = Duration::from_millis(120); // The palette Claude Code uses: one warm accent (ACCENT and DIM live in prompt.rs), @@ -437,6 +439,8 @@ enum Tab { All, Totp, Of(Category), + /// The passkeys the key's FIDO side keeps: not vault entries, and not in any vault. + Passkey, } /// The level above the tabs: the 1Password vaults the entries came from, then one of @@ -461,6 +465,7 @@ impl Tab { Tab::All => "all", Tab::Totp => "totp", Tab::Of(c) => category_name(c), + Tab::Passkey => "passkey", } } } @@ -532,6 +537,9 @@ pub struct Shell { /// Rows of the frame on screen, and the terminal width it was drawn for. frame_rows: u16, drawn_width: u16, + /// The passkeys, once the FIDO PIN opened them: its token and what it listed. + /// Forgotten with the vault's lock. + passkeys: Option<(fido::Token, Vec)>, } pub fn run(dev: Device, version: Option) -> Result { @@ -555,6 +563,7 @@ pub fn run(dev: Device, version: Option) -> Result { menu: None, frame_rows: 0, drawn_width: 0, + passkeys: None, }; shell.main_loop() } @@ -779,6 +788,7 @@ impl Shell { // width leaves. let legend = match (self.letters_act(), listing) { _ if listing && self.at_vaults() => " Enter open · type to search ", + _ if listing && self.tab == Tab::Passkey => " d erase · ← → tab ", (true, true) if !self.vaults.is_empty() => { " Enter use · type to search · a e d i · ← → tab · Esc vaults " } @@ -985,7 +995,7 @@ impl Shell { /// How to name the button on the board in front of the user; the board says what is /// printed on it. fn button(&self) -> String { - crate::boards::button(self.version.as_deref()) + boards::button(self.version.as_deref()) } /// After an unplug the port is gone and the board rebooted locked; come back on @@ -2325,16 +2335,74 @@ impl Shell { /// The off/on switch below the transcript, starting where the setting stands; true /// only when it was moved and confirmed. fn flipped(&mut self, label: &str, on: bool) -> bool { + self.switch(label, on, &[]) == Some(prompt::Flip::To(!on)) + } + + /// `prompt::switch` below the transcript; "nothing changed" when the answer leaves + /// the switch where it was and takes no action. + fn switch(&mut self, label: &str, on: bool, actions: &[(&str, &str)]) -> Option { if self.frame_rows > 0 { let mut so = io::stdout(); self.erase_frame(&mut so); let _ = so.flush(); } - if prompt::switch(label, on) == Some(!on) { - return true; + let flip = prompt::switch(label, on, actions); + if matches!(flip, None | Some(prompt::Flip::To(_))) && flip != Some(prompt::Flip::To(!on)) { + self.line(DIM, " nothing changed"); + } + flip + } + + /// The passkey tab, opened: the FIDO PIN asked, the passkeys listed and kept with + /// its token until the lock. + fn cmd_passkeys(&mut self) -> Result<(), Error> { + let Some(pin) = self.ask("FIDO PIN: ", Field::Hidden) else { + self.line(DIM, " never mind"); + return Ok(()); + }; + let mut key = fido::Key::open()?; + let token = key.token(&pin)?; + let all = key.passkeys(&token)?; + if all.is_empty() { + self.line(DIM, " no passkeys on the key"); + } + self.passkeys = Some((token, all)); + self.tab = Tab::Passkey; + if self.at_vaults() { + self.shelf = Shelf::All; + } + self.open_list(); + Ok(()) + } + + /// `/passkey-rm `: the n-th passkey of the tab erased, after a yes, and the tab + /// listed again from the key. + fn cmd_passkey_rm(&mut self, arg: &str) -> Result<(), Error> { + let at: usize = arg.parse().map_err(|_| Error::BadArg)?; + let Some((_, all)) = &self.passkeys else { + return Err(Error::Value("open the passkey tab first".into())); + }; + let Some(p) = all.get(at).cloned() else { + return Err(Error::NotFound); + }; + let label = passkeys::label(&p); + if !self.ask_yes(&format!( + "erase the passkey {label} from the key? The site still lists it until you remove it there." + )) { + self.line(DIM, " kept"); + self.open_list(); + return Ok(()); } - self.line(DIM, " nothing changed"); - false + let Some((token, _)) = self.passkeys.take() else { + return Err(Error::NotFound); + }; + let mut key = fido::Key::open()?; + key.delete_passkey(&token, &p.id)?; + let all = key.passkeys(&token)?; + self.passkeys = Some((token, all)); + self.line(Color::Green, &format!(" erased {label}")); + self.open_list(); + Ok(()) } /// `/auth`: `sudo vkey auth enable` or `disable`, as the switch is moved, with @@ -2379,11 +2447,22 @@ impl Shell { /// `/commits`: `vkey commits enable` or `disable`, as the switch is moved. fn cmd_commits(&mut self) -> Result<(), Error> { let on = commits::enabled(); - if !self.flipped("sign every git commit with a tap", on) { - return Ok(()); - } + let github = ( + "github", + "sign in to GitHub and add the signing key, so commits show as verified", + ); + let verb = match self.switch("sign every git commit with a tap", on, &[github]) { + Some(prompt::Flip::Action(_)) => "github", + Some(prompt::Flip::To(to)) if to != on => { + if to { + "enable" + } else { + "disable" + } + } + _ => return Ok(()), + }; let exe = std::env::current_exe()?; - let verb = if on { "disable" } else { "enable" }; self.outside(Command::new(&exe).args(["commits", verb]))?; Ok(()) } @@ -2438,10 +2517,18 @@ impl Shell { let r = self.cmd_commits(); return self.report(r); } - "github" => { + "passkeys" => { + let r = self.cmd_passkeys(); + return self.report(r); + } + "passkey-rm" => { + let r = self.cmd_passkey_rm(arg); + return self.report(r); + } + "passkey-pin" => { let r = std::env::current_exe() .map_err(Error::from) - .and_then(|exe| self.outside(Command::new(exe).args(["commits", "github"]))) + .and_then(|exe| self.outside(Command::new(exe).args(["passkey", "pin"]))) .map(drop); return self.report(r); } @@ -2472,7 +2559,10 @@ impl Shell { self.unlock().map(|()| self.refresh()) } } - "lock" => self.dev()?.lock().map(|()| self.refresh()), + "lock" => { + self.passkeys = None; + self.dev()?.lock().map(|()| self.refresh()) + } "settings" => self.cmd_settings(), "pin" => self.cmd_pin(), "wipe" => self.cmd_wipe(), @@ -2545,6 +2635,18 @@ impl Shell { /// The items the open tab shows, as table rows. fn tab_entries(&self) -> Vec { + if self.tab == Tab::Passkey { + return self + .passkeys + .iter() + .flat_map(|(_, all)| all) + .map(|p| Row { + text: p.site.clone(), + login: p.user.clone(), + what: "passkey".to_string(), + }) + .collect(); + } self.entries .iter() .filter(|e| self.in_tab(e)) @@ -2560,9 +2662,19 @@ impl Shell { Tab::All => true, Tab::Totp => self.known.get(&e.name).is_some_and(|k| k.has_seed), Tab::Of(c) => e.category == c, + Tab::Passkey => false, } } + /// Whether this board keeps passkeys, as its folder says. + fn has_passkeys(&self) -> bool { + self.version + .as_deref() + .and_then(|v| v.rsplit(' ').next()) + .and_then(boards::by_name) + .is_some_and(|b| b.passkeys) + } + /// The tabs to show: `all`, `totp` when anything has a seed, then every category /// the key holds, the most crowded first. Built from the vault each time it is /// drawn, so a tab never outlives what put it there. @@ -2581,6 +2693,9 @@ impl Shell { } counts.sort_by_key(|(c, n)| (std::cmp::Reverse(*n), category_name(*c))); tabs.extend(counts.into_iter().map(|(c, _)| Tab::Of(c))); + if self.has_passkeys() { + tabs.push(Tab::Passkey); + } tabs } @@ -2589,15 +2704,23 @@ impl Shell { } /// The neighbouring tab, wrapping at either end. - fn shift_tab(&mut self, dir: Dir) { + /// The next or previous tab. The passkey tab, the first time, is a command: it asks + /// the FIDO PIN before there is anything to show. + fn shift_tab(&mut self, dir: Dir) -> Key { let tabs = self.tabs(); let at = tabs.iter().position(|t| *t == self.tab).unwrap_or(0); let n = tabs.len(); - self.tab = match dir { + let to = match dir { Dir::Next => tabs[(at + 1) % n], Dir::Prev => tabs[(at + n - 1) % n], }; + if to == Tab::Passkey && self.passkeys.is_none() { + self.menu = None; + return Key::Submit("/passkeys".to_string()); + } + self.tab = to; self.open_list(); + Key::Redraw } fn update_menu(&mut self) { @@ -2759,11 +2882,41 @@ impl Shell { } } + /// The keys the passkey tab answers itself: d erases the highlighted one; Enter and + /// the other letters only say what a passkey is for, since one is made and used on + /// its site, and typing does not search entries that are not there. + fn passkey_key(&mut self, code: KeyCode, ctrl: bool) -> Option { + if ctrl || !self.listing() || self.tab != Tab::Passkey { + return None; + } + let selected = self.menu.as_ref().and_then(|m| m.selected); + match code { + KeyCode::Char('d') => Some(match selected { + Some(at) => { + self.menu = None; + Key::Submit(format!("/passkey-rm {at}")) + } + None => Key::Redraw, + }), + KeyCode::Enter | KeyCode::Char(_) => { + self.line( + DIM, + " a passkey is made and used on its site, in the browser; d erases it from the key", + ); + Some(Key::Redraw) + } + _ => None, + } + } + fn handle_key(&mut self, k: KeyEvent) -> Key { if let Some(key) = self.vault_key(k.code) { return key; } let ctrl = k.modifiers.contains(KeyModifiers::CONTROL); + if let Some(key) = self.passkey_key(k.code, ctrl) { + return key; + } match k.code { KeyCode::Enter => { // A highlighted menu item is already in the input: one Enter runs it. @@ -2809,8 +2962,12 @@ impl Shell { } // In the list the arrows turn the tab; a highlighted name there is not // something to edit in place. - KeyCode::Left if self.listing() && !self.at_vaults() => self.shift_tab(Dir::Prev), - KeyCode::Right if self.listing() && !self.at_vaults() => self.shift_tab(Dir::Next), + KeyCode::Left if self.listing() && !self.at_vaults() => { + return self.shift_tab(Dir::Prev); + } + KeyCode::Right if self.listing() && !self.at_vaults() => { + return self.shift_tab(Dir::Next); + } KeyCode::Left | KeyCode::Right if self.listing() => {} KeyCode::Left => self.cursor = self.prev_char(), KeyCode::Right => self.cursor = self.next_char(), diff --git a/docs/threat-model.md b/docs/threat-model.md index 56018d5..6f0978b 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -325,6 +325,25 @@ Rejected: presence of the USB device as proof (any ESP32 shows `303a:1001`); PIN with a rotating expectation (state to write at every login); a PAM `cdylib`; keeping a scheme of our own beside `pam_u2f`. +### The passkey list and the FIDO PIN + +Since 2026-10-16 `vkey passkey` and the shell's `passkey` tab list and erase the +discoverable passkeys through CTAP2 credentialManagement, and `vkey passkey pin` sets or +changes the FIDO PIN (`cli/src/fido.rs`, PIN protocol 1). Nothing in the firmware +changed: fido-authenticator enforces it all. + +| | | +|---|---| +| Given | Listing or erasing needs the FIDO PIN and gets a token for credential management only (permission `cm`), which the shell keeps in memory until the vault locks or it quits | +| The FIDO PIN apart from vkey's | Maintainer's decision, 2026-10-16. fido-authenticator stores the PIN as the first 16 bytes of its SHA-256 in Trussed's filesystem: a copy of the flash (the revision-2 glitch) finds an 8-digit PIN in under a second. One PIN for both would hand that copy the vault's PIN, which Argon2 otherwise makes cost years | +| Wrong FIDO PINs | Eight in all, then the FIDO side is blocked until authenticatorReset; three in a row want a replug. Separate from vkey's eight | +| Malware running as the user | With the FIDO PIN, it can list and erase passkeys - a denial of service, not a sign-in: using one still needs the tap | +| What the list does not show | Non-resident credentials: the `vkey auth` login and the commit signing key live as handles on the host, not on the key | + +Rejected: one PIN for vkey and FIDO (above); the firmware reading fido-authenticator's +files itself to list passkeys under vkey's PIN (a second path to the passkeys around the +authenticator, tied to its internal format, more code on the key). + ### Git commits signed with a tap Since 2026-10-15 `vkey commits enable` (or `/settings` → `commits`) makes an OpenSSH From b021954ab7ad0c91f59c4fc1017fea1656b82e6e Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 01:12:43 +0300 Subject: [PATCH 27/33] Ask to remove a passkey on its site before erasing it from the key --- cli/src/passkeys.rs | 14 ++++++++++---- cli/src/shell.rs | 4 +--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cli/src/passkeys.rs b/cli/src/passkeys.rs index 505c9ba..9e743a1 100644 --- a/cli/src/passkeys.rs +++ b/cli/src/passkeys.rs @@ -49,10 +49,7 @@ pub fn rm() -> Result { println!("nothing erased"); return Ok(0); }; - if !prompt::yes_no(&format!( - "erase {} from the key? the site still lists it until you remove it there", - labels[at] - )) { + if !prompt::yes_no(&erase_question(&labels[at])) { println!("nothing erased"); return Ok(0); } @@ -96,6 +93,15 @@ pub fn new_pin() -> Result, Error> { Ok(new) } +/// The question before a passkey is erased: the order that leaves nothing dead behind - +/// the site first, where the public half lives, then the key. +pub fn erase_question(label: &str) -> String { + format!( + "erase the passkey {label} from the key? Remove it on the site first: once erased \ + here it signs in nowhere, and the site keeps listing it until it is removed there too" + ) +} + /// How a passkey is named to a person: the site and, when the site gave one, the account. pub fn label(p: &Passkey) -> String { if p.user.is_empty() { diff --git a/cli/src/shell.rs b/cli/src/shell.rs index 69c0809..d7c06cb 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -2386,9 +2386,7 @@ impl Shell { return Err(Error::NotFound); }; let label = passkeys::label(&p); - if !self.ask_yes(&format!( - "erase the passkey {label} from the key? The site still lists it until you remove it there." - )) { + if !self.ask_yes(&passkeys::erase_question(&label)) { self.line(DIM, " kept"); self.open_list(); return Ok(()); From f4f99c614dbbf53d8d56721bd9565d17df90886b Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 01:39:18 +0300 Subject: [PATCH 28/33] Give the nRF52840's passkeys 44 blocks, taking a quarter of the vault littlefs moves to 0xC8000..0xF4000 (44 blocks, up to the bootloader) and the vault copies shrink to 24 sectors (0x97000..0xC8000). fido-authenticator refused GitHub's passkey: 20 blocks left no room for its six-block margin. A restore now leaves passkeys laid out for another count in the file instead of failing whole, and vkey passkey list reports the room fido-authenticator estimates. --- CLAUDE.md | 10 +- cli/build.rs | 26 ++++-- cli/src/backup.rs | 86 ++++++++++++++---- cli/src/boards.rs | 6 +- cli/src/fido.rs | 12 +++ cli/src/passkeys.rs | 5 +- cli/src/shell.rs | 10 +- docs/makerdiary.md | 17 ++-- docs/roadmap.md | 26 +++++- docs/threat-model.md | 6 +- .../boards/nrf52840-mdk-dongle/board.toml | 9 +- .../bootloader/board/board.h | 2 +- .../nrf52840-mdk-dongle/images/vaultkey.bin | Bin 268476 -> 268476 bytes .../images/vaultkey.signed.uf2 | Bin 537600 -> 537600 bytes firmware/boards/nrf52840-mdk-dongle/memory.x | 6 +- .../boards/nrf52840-mdk-dongle/src/fido.rs | 6 +- .../boards/nrf52840-mdk-dongle/src/main.rs | 35 ++++--- 17 files changed, 191 insertions(+), 71 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f095605..2448097 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -152,7 +152,8 @@ The boards: - **`nrf52840-mdk-dongle`**, the primary. USB from the firmware (`1209:0001`), polled: CDC-ACM for vkey and CTAPHID for passkeys (Trussed + `fido-authenticator` in - `src/fido.rs`, their littlefs at 0xD8000..0xEC000). The stack sits at the bottom of RAM, + `src/fido.rs`, their littlefs at 0xC8000..0xF4000, 44 blocks up to the bootloader, + `passkey_sectors` in its `board.toml`). The stack sits at the bottom of RAM, 200 KiB, so an overflow resets the chip ("lockup" in `vkey info`). Our UF2 bootloader fork (installed 2026-10-14, below) is how it is flashed: hold the button while plugging in, copy `images/vaultkey.signed.uf2` to `UF2BOOT`, replug. It runs only images signed with the key in `bootloader/signing-key.pem`; the app ends by @@ -257,8 +258,9 @@ The boards: begins and ends), and the board lets the freeze go by itself after 10 s of a silent vkey line. A restore rewrites only sectors that differ, and when it changed any the board resets once the answer has left. A file with no sectors leaves the passkeys alone; a - board without them refuses sectors, and the CLI leaves them in the file and names them - (`passkeys` in `board.toml`). + board without them, or with another count of them, refuses sectors, and the CLI leaves + them in the file and names them (`passkey_sectors` in `board.toml`), so the items still + go back. The second way is `vkey export` (2026-09-19): an item written back into 1Password through `op item create`, under the same double tap, with the seed in the clear. That ends the claim that a seed never leaves — `docs/threat-model.md` says what it costs. @@ -268,7 +270,7 @@ The boards: `main.rs`, checked by `Layout::fits` at compile time and again in `Store::new`; on C6-Zero 0x110000..0x17B000, raw flash past the `factory` partition, which the stock partition table does not describe). Three regions: one sector of attempt words and two - image copies of `state_sectors` each - 53 on C6-Zero, 32 on the nRF52840, whose 1 MiB + image copies of `state_sectors` each - 53 on C6-Zero, 24 on the nRF52840, whose 1 MiB also holds the firmware, Trussed and the bootloader - filling the region exactly. - The image is the PIN header and every item, **packed** - `name_len | category | sealed_len | name | pad | sealed | pad` - not fixed slots: a seed is twenty bytes and an diff --git a/cli/build.rs b/cli/build.rs index 1e4275b..1a77ea3 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -6,6 +6,23 @@ use std::fmt::Write as _; use std::path::{Path, PathBuf}; use std::{env, fs}; +/// `passkey_sectors` of a board.toml: how many 4 KiB sectors its passkeys take, 0 when +/// the board has none. +fn passkey_sectors(t: &toml::Table, path: &Path) -> u32 { + let Some(v) = t.get("passkey_sectors") else { + return 0; + }; + v.as_integer() + .and_then(|n| u32::try_from(n).ok()) + .filter(|n| *n > 0) + .unwrap_or_else(|| { + panic!( + "{}: `passkey_sectors` is not a positive count", + path.display() + ) + }) +} + fn main() { let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR")); let boards_dir = manifest.join("../firmware/boards"); @@ -84,15 +101,10 @@ fn main() { ) .expect("writing to a String cannot fail"); } - let passkeys = match t.get("passkeys") { - None => false, - Some(v) => v - .as_bool() - .unwrap_or_else(|| panic!("{}: `passkeys` is not a bool", toml_path.display())), - }; + let passkey_sectors = passkey_sectors(&t, &toml_path); writeln!( out, - " Board {{ name: {:?}, chip: {:?}, button: {:?}, usb_vid: {:#x}, usb_pid: {:#x}, passkeys: {passkeys}, images: &[{images}] }},", + " Board {{ name: {:?}, chip: {:?}, button: {:?}, usb_vid: {:#x}, usb_pid: {:#x}, passkey_sectors: {passkey_sectors}, images: &[{images}] }},", string("name"), string("chip"), string("button"), diff --git a/cli/src/backup.rs b/cli/src/backup.rs index 4569f37..79ed89d 100644 --- a/cli/src/backup.rs +++ b/cli/src/backup.rs @@ -306,10 +306,10 @@ fn seal_at(key: &[u8; vault::KEY_LEN], aad: &[u8], plain: &[u8]) -> Result) -> Result { let (head, items) = read(&source(path)?)?; - let passkeys = keeps_passkeys(dev)?; + let sectors = passkey_sectors(dev)?; let mut mem = vec![Block::new(); KDF_BLOCKS]; let prepared = match vault::backup_key(pass, &head.salt, head.cost, &mut mem) { - Some(key) => prepare(&key, items, passkeys)?, + Some(key) => prepare(&key, items, sectors)?, None => Restored { count: items.len(), blobs: items, @@ -382,22 +382,33 @@ pub fn pick( Ok(found.into_iter().map(|(name, _)| name).collect()) } -/// Whether the board on the other end keeps passkeys, as its folder says. -fn keeps_passkeys(dev: &mut Device) -> Result { +/// How many sectors the board on the other end keeps its passkeys in, as its folder +/// says; 0 for none. +fn passkey_sectors(dev: &mut Device) -> Result { let version = dev.info()?; Ok(version .rsplit(' ') .next() .and_then(crate::boards::by_name) - .is_some_and(|b| b.passkeys)) + .map_or(0, |b| b.passkey_sectors)) +} + +/// The sector count a passkey sector was laid out for: `sector_size | count | index` +/// lead its plaintext. +fn region_count(plain: &[u8]) -> Option { + plain + .get(4..8) + .map(|b| u32::from_le_bytes([b[0], b[1], b[2], b[3]])) } /// The items and the passkeys as the device takes them back - the passkeys only on a -/// board that keeps them - and the names of what is left out. +/// board that keeps them in as many sectors (`sectors`) as the file was made with, since +/// the device refuses any other and with it the whole restore - and the names of what is +/// left out. fn prepare( key: &[u8; vault::KEY_LEN], items: Vec>, - passkeys: bool, + sectors: u32, ) -> Result { let opened = (0u32..) .zip(&items) @@ -417,7 +428,8 @@ fn prepare( skipped: Vec::new(), passkeys: false, }; - let mut sectors_left = 0; + // The count the file's passkeys were laid out for, when they were left out. + let mut left_out: Option = None; for item in opened { let at = u32::try_from(out.blobs.len()).map_err(|_| Error::BadArg)?; match item { @@ -425,17 +437,22 @@ fn prepare( out.blobs.push(seal_item(key, at, &plain)?); out.count += 1; } - Incoming::Region(plain) if passkeys => { + Incoming::Region(plain) if sectors > 0 && region_count(&plain) == Some(sectors) => { out.blobs.push(seal_at(key, &aad(REGION_AAD, at), &plain)?); out.passkeys = true; } - Incoming::Region(_) => sectors_left += 1, + Incoming::Region(plain) => left_out = Some(region_count(&plain).unwrap_or(0)), Incoming::Retired(name) => out.skipped.push(name), } } - if sectors_left > 0 { - out.skipped - .push("the passkeys: this board does not keep passkeys".to_string()); + match left_out { + None => {} + Some(_) if sectors == 0 => out + .skipped + .push("the passkeys: this board does not keep passkeys".to_string()), + Some(theirs) => out.skipped.push(format!( + "the passkeys: laid out for {theirs} sectors, this board keeps {sectors}" + )), } Ok(out) } @@ -587,7 +604,7 @@ mod tests { blobs: items, skipped, .. - } = prepare(&key, sealed, true).expect("prepares"); + } = prepare(&key, sealed, 44).expect("prepares"); assert_eq!(items.len(), 2, "the auth secret stays in the file"); assert_eq!(skipped.len(), 1, "and is named: {skipped:?}"); assert!(skipped[0].starts_with("hifes@pop-os:"), "{skipped:?}"); @@ -609,7 +626,7 @@ mod tests { let login = Category::Login.wire(); let sealed = vec![seal_item(&key, 0, &backup_plain(login, "github", login)).expect("seals")]; - let out = prepare(&[8u8; vault::KEY_LEN], sealed.clone(), true).expect("prepares"); + let out = prepare(&[8u8; vault::KEY_LEN], sealed.clone(), 44).expect("prepares"); assert_eq!( out.blobs, sealed, "a wrong passphrase is the device's to refuse" @@ -617,11 +634,22 @@ mod tests { assert!(out.skipped.is_empty()); } + /// A passkey sector's plaintext as the device writes it: `sector_size | count | index` + /// and then the sector, here cut short. + fn region_plain(count: u32) -> Vec { + let mut plain = Vec::new(); + for word in [4096u32, count, 0] { + plain.extend_from_slice(&word.to_le_bytes()); + } + plain.extend_from_slice(&[0x5A; 16]); + plain + } + #[test] fn passkeys_move_up_behind_the_items_or_stay_in_the_file() { let key = [7u8; vault::KEY_LEN]; let login = Category::Login.wire(); - let sector = vec![0x5A; 16]; + let sector = region_plain(44); let file = [ seal_item( &key, @@ -633,14 +661,14 @@ mod tests { seal_at(&key, &aad(REGION_AAD, 2), §or).expect("seals"), ]; - let out = prepare(&key, file.to_vec(), true).expect("prepares"); + let out = prepare(&key, file.to_vec(), 44).expect("prepares"); assert_eq!((out.count, out.passkeys, out.blobs.len()), (1, true, 2)); let Some(Incoming::Region(plain)) = open_item(&key, 1, &out.blobs[1]) else { panic!("the sector opens one place up, under the sectors' associated data"); }; assert_eq!(plain.as_slice(), sector.as_slice()); - let out = prepare(&key, file.to_vec(), false).expect("prepares"); + let out = prepare(&key, file.to_vec(), 0).expect("prepares"); assert_eq!((out.count, out.passkeys, out.blobs.len()), (1, false, 1)); assert!( out.skipped.iter().any(|s| s.starts_with("the passkeys")), @@ -648,4 +676,26 @@ mod tests { out.skipped ); } + + #[test] + fn passkeys_laid_out_for_another_size_stay_in_the_file() { + let key = [7u8; vault::KEY_LEN]; + let login = Category::Login.wire(); + let file = [ + seal_item(&key, 0, &backup_plain(login, "github", login)).expect("seals"), + seal_at(&key, &aad(REGION_AAD, 1), ®ion_plain(20)).expect("seals"), + seal_at(&key, &aad(REGION_AAD, 2), ®ion_plain(20)).expect("seals"), + ]; + let out = prepare(&key, file.to_vec(), 44).expect("prepares"); + assert_eq!( + (out.count, out.passkeys, out.blobs.len()), + (1, false, 1), + "the items go back, the sectors the device would refuse do not" + ); + assert_eq!( + out.skipped, + ["the passkeys: laid out for 20 sectors, this board keeps 44"], + "and the restore says why" + ); + } } diff --git a/cli/src/boards.rs b/cli/src/boards.rs index b3bebf4..fbcc579 100644 --- a/cli/src/boards.rs +++ b/cli/src/boards.rs @@ -9,9 +9,9 @@ pub struct Board { pub button: &'static str, pub usb_vid: u16, pub usb_pid: u16, - /// Whether it keeps passkeys, which a backup carries and only such a board takes - /// back. - pub passkeys: bool, + /// The 4 KiB sectors its passkeys live in; 0 for a board without them. A backup's + /// passkeys go back only to a board with the same count. + pub passkey_sectors: u32, /// Everything `setup` may write, in flash order. pub images: &'static [Image], } diff --git a/cli/src/fido.rs b/cli/src/fido.rs index f5306ae..605b368 100644 --- a/cli/src/fido.rs +++ b/cli/src/fido.rs @@ -43,6 +43,7 @@ const PIN_TOKEN_WITH_PERMISSIONS: i64 = 0x09; const PERMISSION_CREDENTIAL_MANAGEMENT: i64 = 0x04; const PIN_PROTOCOL: i64 = 1; /// credentialManagement subcommands. +const CREDS_METADATA: u8 = 0x01; const RPS_BEGIN: u8 = 0x02; const RPS_NEXT: u8 = 0x03; const CREDENTIALS_BEGIN: u8 = 0x04; @@ -243,6 +244,17 @@ impl Key { Ok(Token(Zeroizing::new(decrypt(&shared, sealed)?))) } + /// How many passkeys the key keeps, and how many more fido-authenticator reckons + /// fit: its own estimate from the filesystem's free space, two blocks and 400 bytes + /// apiece after a margin of five, so it errs low. + pub fn room(&mut self, token: &Token) -> Result<(i64, i64), Error> { + let answer = self + .manage(token, CREDS_METADATA, None)? + .ok_or_else(|| Error::Value("the key did not say how full it is".into()))?; + let count = |k: i64| field(&answer, k).and_then(Cbor::as_int).unwrap_or(0); + Ok((count(1), count(2))) + } + /// Every passkey the key keeps, site by site. pub fn passkeys(&mut self, token: &Token) -> Result, Error> { let mut out = Vec::new(); diff --git a/cli/src/passkeys.rs b/cli/src/passkeys.rs index 9e743a1..511c1fe 100644 --- a/cli/src/passkeys.rs +++ b/cli/src/passkeys.rs @@ -27,12 +27,11 @@ pub fn unlocked() -> Result<(Key, Token), Error> { pub fn list() -> Result { let (mut key, token) = unlocked()?; let all = key.passkeys(&token)?; - if all.is_empty() { - println!("no passkeys on the key"); - } for p in &all { println!("{}\t{}", p.site, p.user); } + let (have, more) = key.room(&token)?; + eprintln!("{have} on the key, room for about {more} more"); Ok(0) } diff --git a/cli/src/shell.rs b/cli/src/shell.rs index d7c06cb..66e07a0 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -2363,9 +2363,11 @@ impl Shell { let mut key = fido::Key::open()?; let token = key.token(&pin)?; let all = key.passkeys(&token)?; - if all.is_empty() { - self.line(DIM, " no passkeys on the key"); - } + let (have, more) = key.room(&token)?; + self.line( + DIM, + &format!(" {have} passkeys on the key, room for about {more} more"), + ); self.passkeys = Some((token, all)); self.tab = Tab::Passkey; if self.at_vaults() { @@ -2670,7 +2672,7 @@ impl Shell { .as_deref() .and_then(|v| v.rsplit(' ').next()) .and_then(boards::by_name) - .is_some_and(|b| b.passkeys) + .is_some_and(|b| b.passkey_sectors > 0) } /// The tabs to show: `all`, `totp` when anything has a seed, then every category diff --git a/docs/makerdiary.md b/docs/makerdiary.md index 9faa210..720df92 100644 --- a/docs/makerdiary.md +++ b/docs/makerdiary.md @@ -89,12 +89,17 @@ filesystem and claims up to 100 passkeys; the FIDO-only Nitrokey Passkey firmwar | 0x00000..0x01000 | 4 KiB | MBR | | 0x01000..0x97000 | 600 KiB | firmware: vkey + Trussed + FIDO, ≈420 KiB by the fit check below | | 0x97000..0x98000 | 4 KiB | vkey attempt counter | -| 0x98000..0xB8000 | 128 KiB | vkey image copy A (32 sectors) | -| 0xB8000..0xD8000 | 128 KiB | vkey image copy B (32 sectors) | -| 0xD8000..0xEC000 | 80 KiB | Trussed littlefs (passkeys), as on NK3 Mini | -| 0xEC000..0x100000 | 80 KiB | Nordic secure bootloader, MBR params, bootloader settings | +| 0x98000..0xB0000 | 96 KiB | vkey image copy A (24 sectors) | +| 0xB0000..0xC8000 | 96 KiB | vkey image copy B (24 sectors) | +| 0xC8000..0xF4000 | 176 KiB | Trussed littlefs (passkeys), 44 blocks | +| 0xF4000..0x100000 | 48 KiB | the UF2 bootloader fork, its CF2 page, MBR params, bootloader settings | -- **Vault: 128 KiB per copy** (32 sectors, C6 has 53). The maintainer's backup of +The map as it stands since 2026-10-16 (roadmap phase 6, milestone 6). Until then the +copies were 32 sectors (0x98000..0xD8000) and littlefs had 20 blocks at 0xD8000..0xEC000, +as on NK3 Mini, with 0xEC000..0xF4000 left free; 20 blocks held two or three sites' +passkeys before fido-authenticator's margin refused the next. + +- **Vault: 96 KiB per copy** (24 sectors since 2026-10-16, 32 before; C6 has 53). The maintainer's backup of 2026-09-14 was 15 KB; 100–200 entries are expected. `STATE_SECTORS` stops being a core constant: the board gives the region size in `Layout`, because a second board with a different value now exists. @@ -275,7 +280,7 @@ vkey alone, no Trussed yet: the same core as the C6, behind the four HAL traits. | Port | USB CDC-ACM through `usb-device` + `usbd-serial`, polled from the main loop; VID/PID `1209:0001`, pid.codes' test pair | | Clock | SysTick exception, 1 ms. Not a counter read on demand: the auto-lock compares times only when the next request comes, so a counter that wraps between requests would keep an idle key unlocked | | Ui | button P0.18, LEDs P0.23/P0.22/P0.24, all active low, from the wiki; amber = red + green | -| Flash | `Nvmc` over 0x97000..0xEC000 behind a wrapper that fences after every erase and write, split into the vault's region and Trussed's (`Region`), each refusing access past its end | +| Flash | `Nvmc` over 0x97000..0xF4000 (0xEC000 until 2026-10-16) behind a wrapper that fences after every erase and write, split into the vault's region and Trussed's (`Region`), each refusing access past its end | | Entropy | the RNG peripheral, bias correction on | | DeviceKey | none: `bound() == false`, PIN only; `vkey auth` is `pam_u2f` since 2026-10-15 and needs none | diff --git a/docs/roadmap.md b/docs/roadmap.md index 8a19c53..126f7c5 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -594,8 +594,8 @@ nRF; `check --wipe-everything` green on the C6. runtime and no interrupt" below. It is also the fix for "USB unserviced during the tap wait". - ~~**Runtime: RTIC (Nitrokey's choice) or Embassy.**~~ Neither: see "No runtime" below. -- **Trussed + `fido-authenticator`**, with littlefs at 0xD8000..0xEC000 and P-256 from - `p256-cortex-m4`. Done 2026-10-15 (milestone 3). +- **Trussed + `fido-authenticator`**, with littlefs at 0xD8000..0xEC000 (0xC8000..0xF4000 + since milestone 6) and P-256 from `p256-cortex-m4`. Done 2026-10-15 (milestone 3). - **Then Linux login moves to `pam_u2f`**, and the old `vkey auth` is removed, recorded in `docs/` with the commit it can be restored from. - **This is done on the daily key** (no spare). Every update starts with a `.vkb` backup. @@ -735,6 +735,28 @@ Milestones, one commit each, each leaving a key that works: webauthn.io logged in, nothing enrolled anew. Two `Broken pipe`s during the session were the dongle's edge connector moving under a press (re-enumeration within a second, the vault still unlocked), not the firmware. +6. **Room for more passkeys** (maintainer's decision, 2026-10-16). GitHub's registration + failed with "Passkey registration failed": fido-authenticator 0.3 stores a resident + key only if six blocks and the key's size stay free after it (`can_fit`), and of + littlefs's 20 blocks the superblock and the directories of a few sites had taken the + rest. The vault gives up a quarter: copies of 24 sectors (96 KiB) instead of 32, the + region 0x97000..0xC8000. littlefs moves to 0xC8000..0xF4000, 44 blocks, up to the + bootloader, whose window ends at 0x97000; a const assert holds the data region to + 0xF4000. Expect roughly a dozen more sites rather than dozens: each site is a + directory, a metadata pair of two blocks. `vkey passkey list` reports + fido-authenticator's own estimate (getCredsMetadata). + - The old filesystem does not mount at the new place and is formatted: every + passkey, the FIDO PIN and the `vkey auth` and commit-signing credentials go. + - The vault moves too, so the order on the board is a `.vkb`, the flash, then the + restore. A `.vkb` made before carries passkeys laid out for 20 sectors; the CLI + now leaves sectors of another count in the file and says so, because the device + refuses them and with them the whole restore (`passkey_sectors` in board.toml). + + Acceptance, on the board: the restore of the `.vkb` taken before, `selftest`, the + FIDO PIN set again, `vkey passkey list` with the room it reports, the GitHub + registration that failed, then `sudo vkey auth enable` and `vkey commits enable` + with a new signing key on GitHub; a backup and a restore of it at 44 sectors that + changes nothing. --- diff --git a/docs/threat-model.md b/docs/threat-model.md index 6f0978b..354a0f1 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -67,7 +67,9 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure the passphrase's entropy, at less than half the C6's work per guess. - **Passkeys (FIDO2) live outside the vault** (since 2026-10-15, roadmap phase 6). Trussed and fido-authenticator keep them in a littlefs of their own at - 0xD8000..0xEC000: + 0xC8000..0xF4000 (0xD8000..0xEC000 until 2026-10-16; the new region covers the old + one, so blocks of the old filesystem, keys among them, stay readable to a flash dump + until littlefs reuses them, beside the tail of an old vault copy, which is sealed): - **They are not sealed under the PIN.** Trussed writes its keys as they are: the passkeys' private keys, and the key that wraps the credential IDs of the non-resident ones (`pam_u2f`'s among them). The glitch above reads them straight @@ -362,7 +364,7 @@ half to GitHub is offered and asked, never done unasked. | Key and laptop stolen together | Signs as the user with a tap, until the key is removed from GitHub | | The handle file `~/.config/vkey/commit-signing-key` | Useless without the key. Not in the `.vkb`: losing it means a new key and a new upload to GitHub | | A copy of the board's flash, or a `.vkb` with its passphrase | The credential is wrapped by fido-authenticator's key, which both carry: with the handle file, another board then signs too | -| authenticatorReset | Ends the key; a restore from a `.vkb` taken before brings it back | +| authenticatorReset | Ends the key; a restore from a `.vkb` taken before brings it back, if that `.vkb` was made at the current passkey layout (44 sectors since 2026-10-16) | | Every commit waits for a tap | A rebase or an amend signs each commit again, one tap each; a commit with no tap in 30 s fails | ## What it does not protect against diff --git a/firmware/boards/nrf52840-mdk-dongle/board.toml b/firmware/boards/nrf52840-mdk-dongle/board.toml index ff16423..3b0f594 100644 --- a/firmware/boards/nrf52840-mdk-dongle/board.toml +++ b/firmware/boards/nrf52840-mdk-dongle/board.toml @@ -17,10 +17,11 @@ usb_pid = 0x0001 # What is printed on the button the user is asked to press. button = "USER" -# It keeps passkeys (Trussed, src/fido.rs). A backup carries them, and `vkey restore` -# hands them only to a board that says this; another restores the items and names them -# as left in the file. -passkeys = true +# It keeps passkeys (Trussed, src/fido.rs) in this many 4 KiB sectors: FS_LEN in +# src/main.rs, and the two change together. A backup carries them, each sector naming +# the count it came from, and `vkey restore` hands them only to a board that names the +# same count; another restores the items and says the passkeys were left in the file. +passkey_sectors = 44 # The radio peripheral's 4 KiB slot. Its driver ships inside the HAL crate, so the lock # file cannot show it is absent. tools/build-vaultkey.sh fails if anything in the image diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h index 6d6cf72..c2a26e3 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/board/board.h @@ -65,7 +65,7 @@ /*------------------------------------------------------------------*/ /* Flash: the drive writes 0x1000..BOARD_APP_FLASH_END and nothing else. Above it lie - * the vault (0x97000..0xD8000) and the filesystem a firmware keeps (0xD8000..0xEC000). + * the vault (0x97000..0xC8000) and the filesystem a firmware keeps (0xC8000..0xF4000). * The same boundary as FLASH in the firmware's memory.x and VAULT_BASE in its main.rs. * * The on-board test build (VKEY_AS_APP, bootloader/test/) runs from 0x1000 under the diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin index dc58fdc43738f96703afc562527c4d5cfc30233b..f469afc9b2161f21caeb2d522af148bece7aa761 100755 GIT binary patch delta 266 zcmdn9QDDzTfelSUtU4-e89JNWgP#*ai)7T> ztW{-<*u2qoe>9LPT-dB(yGz0Ui@4&69~=z4U%LWMykuC&_~G3zw{HuA{J*#u9{R-0 zwEW`*7XL2>1}9%KD7ya;ky-vxhSB{cyO!gpip_?nq_uc;l$x9vKQb~VCLH*vvpMpM zYZ;@?^!ZspA)W0Lvl%yrGaDE*Oh0&(QFeOLVa5WW=;gzVn%s=q+y90=OzM$llH delta 266 zcmdn9QDDzTfelSUtRgCG86un8g9LPT-dB(yGp_Ti@4&69~=z4U%LWMykuC&_~G3zw{HuA{J%6Q9{R-0 zwEW`*7XL2`3{JjeP;~zxBD4IX45Rx?b}h$G7Ml%ENo(}!OgQjSWOL*f z*D^+t>GQLILL%EIW;1RKXI@~?F#X_BM%n2}hZzfiqL&XdYH~9QZ~uFaF?K3r#rEhF zrjLP)9@BldF&$)#*v`M5iO~coEclw~aS@RI8q4gwSbzZpK%@W@g94D6Zo$anu)Twk H#Y7wc;4xqb diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.signed.uf2 b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.signed.uf2 index 2f3671a086a00e9bb555cb3a3459e7a715a5da48..23d71d4868f4db8fa36ace7089000642d2b3a1ea 100644 GIT binary patch delta 382 zcmZp8q0sO`VZ$O7Rvi_#44uu(RbH|)>P()f6UnHv`L&K96Oj6=SIZ2fs*RTOGHP#D zc3A7h7_s?c*Z%E{5!)v^F*XPA>{9UmBCdGi2L}W1*U5^EwzNG<8m2$&VwRoW)W%!@6#d-BtSQE#trva+W@kI^ zJm&4Z^H_4V7&Eq4pJ4g8n9*W;ZVu}~Mn;eA`gyF389;HvYpjo-@MOq1Pcqu&Fu`Gk z(Zd#`BBghc2^4Xb~&#sxr3e O3ynDHr^_31JOlv2sgS|| delta 382 zcmZp8q0sO`VZ$O7RuL7p43W*tRbH|)icFrU6UivD`L&K96Oj6=SIZ2fs*RTOG74{2 zc3A7hn6dd{*Z%E{8QUj1F*XPAtWxm*BCdGi2L}W1*U5^Ew*ujDW&p(vudzOU!c!sRJjrO6!vu#F zPLmMY_poi}-NWwfCcpp!AX0#dK> io::Result { diff --git a/firmware/boards/nrf52840-mdk-dongle/src/main.rs b/firmware/boards/nrf52840-mdk-dongle/src/main.rs index e73b513..9f8d734 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/main.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/main.rs @@ -70,22 +70,34 @@ const RESET_CAUSES: [(u32, &str); 9] = [ const USB_VID: u16 = 0x1209; const USB_PID: u16 = 0x0001; -/// The vault's flash, 0x97000..0xD8000: past the end of FLASH in memory.x and the +/// The vault's flash, 0x97000..0xC8000: past the end of FLASH in memory.x and the /// signature slot after it, before Trussed's filesystem. `LAYOUT` counts from its start. const VAULT_BASE: u32 = 0x9_7000; -const VAULT_LEN: u32 = 0x4_1000; - -/// Trussed's filesystem, the passkeys, right after the vault: 0xD8000..0xEC000, twenty -/// sectors, below the bootloader at 0xF4000 and out of its reach like the vault. -const FS_LEN: u32 = 0x1_4000; +const VAULT_LEN: u32 = 0x3_1000; + +/// Trussed's filesystem, the passkeys, right after the vault: 0xC8000..0xF4000, 44 +/// sectors, up to the bootloader at 0xF4000 and out of its reach like the vault. It was +/// 20 sectors until 2026-10-16, and fido-authenticator refuses a resident key unless +/// six blocks and the key's size are free after it, which the directories of a few +/// sites had already used up. `passkey_sectors` in board.toml changes with it: the CLI +/// reads it to leave out a backup's passkeys laid out for another size. +const FS_LEN: u32 = 0x2_C000; + +/// Where the bootloader begins: the data region ends at it, and an access past the end +/// would erase the one thing on this board no USB tool can put back. +const BOOTLOADER: u32 = 0xF_4000; +const _: () = assert!( + VAULT_BASE + VAULT_LEN + FS_LEN <= BOOTLOADER, + "the vault and Trussed's filesystem end before the bootloader" +); -/// One attempt sector and two copies of 128 KiB: the sizes decided in +/// One attempt sector and two copies of 96 KiB: the sizes decided in /// docs/makerdiary.md, smaller than the C6's because this chip has 1 MiB in all. const LAYOUT: Layout = Layout { attempts: 0x0_0000, state_a: 0x0_1000, - state_b: 0x2_1000, - state_sectors: 32, + state_b: 0x1_9000, + state_sectors: 24, }; const _: () = assert!( LAYOUT.fits() && LAYOUT.state_b + store::SECTOR * LAYOUT.state_sectors == VAULT_LEN, @@ -293,8 +305,9 @@ fn data_region() -> &'static mut [u8] { "the data region is taken once" ); let base = core::ptr::with_exposed_provenance_mut::(VAULT_BASE as usize); - // SAFETY: 0x97000..0xEC000 is flash outside the image - memory.x ends FLASH at - // 0x96000, and the bootloader starts at 0xF4000 - so nothing the compiler knows of + // SAFETY: 0x97000..0xF4000 is flash outside the image - memory.x ends FLASH at + // 0x96000, and the bootloader starts at 0xF4000, which a const assert above holds + // the region to - so nothing the compiler knows of // lives there; it is page-aligned, as the driver asserts; and the flag above makes // this the only reference to it. The flash controller rewrites these bytes on // erase, which is why every access goes through `Flash` and its fences. From 240ae6433640c8183eccc6ddc696a7445887db92 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 02:11:52 +0300 Subject: [PATCH 29/33] Read an empty passkey list right; say a restart only might come fido-authenticator 0.3 answers an empty enumerateRPs with a total of none rather than NO_CREDENTIALS. A restore that carries passkeys says the key restarts only if one changed, since the CLI cannot tell. The roadmap records milestone 6's run. --- cli/src/fido.rs | 5 +++++ cli/src/main.rs | 2 +- cli/src/shell.rs | 5 ++++- docs/roadmap.md | 20 +++++++++++++++++--- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/cli/src/fido.rs b/cli/src/fido.rs index 605b368..7e86b02 100644 --- a/cli/src/fido.rs +++ b/cli/src/fido.rs @@ -261,7 +261,12 @@ impl Key { let Some(first) = self.manage(token, RPS_BEGIN, None)? else { return Ok(out); }; + // An empty key may say so with NO_CREDENTIALS or, as fido-authenticator 0.3 + // does, with a total of none and no site. let total = field(&first, 5).and_then(Cbor::as_int).unwrap_or(1); + if total == 0 { + return Ok(out); + } let mut sites = vec![first]; for _ in 1..total { if let Some(next) = self.manage(token, RPS_NEXT, None)? { diff --git a/cli/src/main.rs b/cli/src/main.rs index d2de627..a34c94a 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -665,7 +665,7 @@ fn run_restore( eprintln!(" left in the file: {line}"); } if done.passkeys { - println!("the key restarts to load its passkeys..."); + println!("if a passkey changed, the key restarts to load them..."); // Past the reset, so a command run right after does not land in it. std::thread::sleep(std::time::Duration::from_secs(3)); } diff --git a/cli/src/shell.rs b/cli/src/shell.rs index 66e07a0..68da75d 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -2281,7 +2281,10 @@ impl Shell { } if restored.passkeys { // The key resets to load them; the port goes and comes back. - self.line(Color::Blue, " the key restarts to load its passkeys..."); + self.line( + Color::Blue, + " if a passkey changed, the key restarts to load them...", + ); std::thread::sleep(Duration::from_secs(3)); if !self.reconnect() { self.line( diff --git a/docs/roadmap.md b/docs/roadmap.md index 126f7c5..c1d8872 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -742,9 +742,10 @@ Milestones, one commit each, each leaving a key that works: rest. The vault gives up a quarter: copies of 24 sectors (96 KiB) instead of 32, the region 0x97000..0xC8000. littlefs moves to 0xC8000..0xF4000, 44 blocks, up to the bootloader, whose window ends at 0x97000; a const assert holds the data region to - 0xF4000. Expect roughly a dozen more sites rather than dozens: each site is a - directory, a metadata pair of two blocks. `vkey passkey list` reports - fido-authenticator's own estimate (getCredsMetadata). + 0xF4000. fido-authenticator 0.3 keeps each resident key as a small file in one + directory, inline in its metadata, so the real room is wider than its own estimate, + which `vkey passkey list` reports (getCredsMetadata: two blocks and 400 bytes per + key after a margin of five): 13 on the empty filesystem. - The old filesystem does not mount at the new place and is formatted: every passkey, the FIDO PIN and the `vkey auth` and commit-signing credentials go. - The vault moves too, so the order on the board is a `.vkb`, the flash, then the @@ -758,6 +759,19 @@ Milestones, one commit each, each leaving a key that works: with a new signing key on GitHub; a backup and a restore of it at 44 sectors that changes nothing. + **Accepted 2026-10-16**: the restore brought back 48 items and left the passkeys in + the file ("laid out for 20 sectors, this board keeps 44"); `selftest` green; the + FIDO PIN set through `vkey passkey pin`; the list reported 0 and room for 13. The + first GitHub registration after the flash made a passkey on the key that GitHub's + server then refused - most likely a challenge left from a page opened before the + flash, not proven - and a fresh page registered it. The key holds one `github.com` + passkey after both: the second, for the same site and user handle, replaced the + first, as CTAP2 has it. `sudo vkey auth enable` and + `vkey commits enable` with a new key on GitHub; a backup of 48 items and the + passkeys and its restore, after which the key did not restart (reset cause still + power-on, vault still unlocked). The restore's "the key restarts" now reads "if a + passkey changed": the CLI cannot tell whether one did. + --- ## Decisions needed from the maintainer From 87c14a1dfd73a6ad1f9854018eadf96137eb78be Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 14:12:16 +0300 Subject: [PATCH 30/33] Make a restore take the wipe's hold; refuse sudo from a user's vkey --- CLAUDE.md | 13 ++-- README.md | 16 +++-- cli/src/auth.rs | 29 +++++++++ cli/src/check.rs | 10 +++ cli/src/main.rs | 49 +++++++++----- cli/src/shell.rs | 38 ++++++++--- docs/roadmap.md | 18 ++++++ docs/threat-model.md | 17 +++-- .../images/bootloader-sb.signed.bin | Bin 45056 -> 45056 bytes .../boards/esp32c6-zero/images/vaultkey.bin | Bin 185840 -> 186320 bytes .../esp32c6-zero/images/vaultkey.signed.bin | Bin 192512 -> 192512 bytes .../nrf52840-mdk-dongle/images/vaultkey.bin | Bin 268476 -> 268460 bytes .../images/vaultkey.signed.uf2 | Bin 537600 -> 537600 bytes firmware/core/src/device.rs | 15 +++-- firmware/core/src/ui.rs | 3 +- firmware/core/tests/key.rs | 61 ++++++++++++++++-- 16 files changed, 221 insertions(+), 48 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 2448097..97ea337 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -121,7 +121,8 @@ This is a security device. The rules below are not recommendations. - **A claim in the protocol must hold in the code.** Advertising a guarantee only half the paths enforce is worse than not advertising it. - **Irreversible actions get their own gesture.** Code, password, a `vkey auth` login, a - signed git commit and a passkey on the nRF52840 — a tap (amber); wipe, and erasing every passkey + signed git commit and a passkey on the nRF52840 — a tap (amber); wipe, a restore from a + `.vkb` (it replaces everything, passkeys included; 2026-10-16) and erasing every passkey (authenticatorReset) — hold 5 s (red); backup — double tap (blue). A tap never wipes and never exports; a hold never exports; a double tap never wipes. Password on a tap is the maintainer's decision of 2026-09-08 — do not reintroduce a separate hold. A new command with consequences gets a @@ -226,7 +227,10 @@ The boards: public half to `/etc/u2f_mappings` (root's) and one `sufficient` line in the PAM services of `SERVICES` (`cli/src/auth.rs`), each original kept as `*.before-vkey`; `disable` undoes - it. That is the one place the CLI writes system files. The Ed25519 scheme before it + it. That is the one place the CLI writes system files. Both refuse to run as root + from a binary anyone but root can change, and name `/usr/local/sbin/vkey` + (`auth::ROOT_COPY`, in sudo's `secure_path`); `/settings` installs that copy + through `/usr/bin/sudo` when it differs and runs it. The Ed25519 scheme before it (category 201 sealed under the chip key, command `Respond` 0x19) is gone, restorable from 4bd49f3; both numbers stay unused, and a restore leaves such an item in the file. - `vkey commits enable` (2026-10-15, `cli/src/commits.rs`) signs every git commit with @@ -245,8 +249,9 @@ The boards: double tap; 2026-09-09) reseals every item under a key derived from a passphrase (Argon2id, `Passphrase` 12–128 bytes, without the chip key, so the file opens on another board) and returns them one at a time; the host sees only ciphertext and assembles a - `.vkb`. `ImportBegin`/`ImportItem`/`ImportEnd` is the reverse, under the PIN with no - gesture: the items are appended to a fresh image as they arrive and become the vault at + `.vkb`. `ImportBegin`/`ImportItem`/`ImportEnd` is the reverse, under the PIN and the + wipe's hold (2026-10-16; the PIN alone before, which let a host that knew it swap in + passkeys without the hold authenticatorReset takes): the items are appended to a fresh image as they arrive and become the vault at `ImportEnd`, so a restore that stops half-way leaves what was there before. A backup session is killed by any `load()`, by `lock`, and by the first error. An item's AAD is `BACKUP_AAD` plus its index in the file: a reordered or altered item does not open diff --git a/README.md b/README.md index 1782f5b..ccefb36 100644 --- a/README.md +++ b/README.md @@ -148,10 +148,15 @@ first. ```bash sudo apt install libpam-u2f -sudo "$(command -v vkey)" auth enable # two taps: sudo and the lock screen are set up -sudo "$(command -v vkey)" auth disable # back to the password alone +sudo install -m 0755 "$(command -v vkey)" /usr/local/sbin/vkey # a copy only root can change +sudo vkey auth enable # two taps: sudo and the lock screen are set up +sudo vkey auth disable # back to the password alone ``` +`enable` and `disable` refuse to run as root from `~/.local/bin`: anything running as you +could rewrite that file and would then run as root. The copy in `/usr/local/sbin` is +root's, and `sudo` finds it by name. + `enable` makes a credential on the key (a tap), tries it the way a login will (another tap), writes it to `/etc/u2f_mappings` (root's), and adds one line to the PAM files of `sudo` and of the lock screens this host has — COSMIC, GNOME, @@ -160,8 +165,9 @@ recognise it leaves alone and prints the line to add by hand. Keep a root shell another terminal until `sudo` and the lock screen have both worked, with the tap and with the password. -In the shell, `/settings` → `auth` does the same in one step, and installs `libpam-u2f` -with apt first if it is missing. +In the shell, `/settings` → `auth` does the same in one step: it installs `libpam-u2f` +with apt first if it is missing, and brings `/usr/local/sbin/vkey` up to date when it +differs from the `vkey` you run. ## Passkeys on the key @@ -205,7 +211,7 @@ for now; macOS and Windows are issues #18 and #19. What it costs is in | Gesture | LED | What it releases | |---|---|---| | Tap | amber | one TOTP code, the secret fields of one item, one `.env`, one passkey, one `vkey auth` login, or one signed git commit | -| Hold 5 s | red | factory wipe: every secret and the PIN; on the nRF52840, erasing every passkey (within 10 s of plugging in) | +| Hold 5 s | red | factory wipe: every secret and the PIN; a restore from a `.vkb`, which replaces everything; on the nRF52840, erasing every passkey (within 10 s of plugging in) | | Double tap | blue | the encrypted backup file, or an export / seed readout | A tap never wipes and never exports, so a hostile host cannot swap a code request for a diff --git a/cli/src/auth.rs b/cli/src/auth.rs index eeb7691..691ed7c 100644 --- a/cli/src/auth.rs +++ b/cli/src/auth.rs @@ -50,6 +50,10 @@ const SERVICES: [&str; 6] = [ "swaylock", "hyprlock", ]; +/// Where root runs vkey from: a copy only root can change, in sudo's `secure_path`, so +/// `sudo vkey auth enable` finds it, and a program running as the user cannot swap +/// what root runs, as it could `~/.local/bin/vkey`. +pub const ROOT_COPY: &str = "/usr/local/sbin/vkey"; /// A copy of each PAM file as it was before `enable` first touched it. const BEFORE: &str = ".before-vkey"; /// What the scheme this replaced kept on the host: a public key per user. @@ -61,6 +65,7 @@ const OLD_BINARY: &str = "/usr/local/bin/vkey"; /// public half in the mapping, the line in PAM. pub fn enable() -> Result { let user = sudo_user()?; + root_only("enable")?; let mapping = enrol(&user)?; let existing = read_or_empty(Path::new(MAPPINGS))?; file::replace( @@ -103,6 +108,7 @@ pub fn enable() -> Result { /// mapping. The credential stays on the key, unused, until authenticatorReset. pub fn disable() -> Result { let user = sudo_user()?; + root_only("disable")?; for service in SERVICES { let path = Path::new("/etc/pam.d").join(service); if path.exists() { @@ -281,6 +287,29 @@ fn remove_line(path: &Path) -> Result<(), Error> { } /// The user who ran sudo: the one whose logins the key will answer. +/// Refuses to change PAM from a binary that anyone but root may rewrite, itself or +/// through a directory above it: whoever can would run as root the next time it is +/// called this way. It cannot stop a program running as the user from putting its +/// own `sudo` first in PATH; `docs/threat-model.md` says so. +fn root_only(verb: &str) -> Result<(), Error> { + let exe = std::env::current_exe()?; + for path in exe.ancestors() { + let meta = fs::metadata(path)?; + let writable = meta.mode() & 0o002 != 0 || (meta.mode() & 0o020 != 0 && meta.gid() != 0); + if meta.uid() != 0 || writable { + return Err(Error::Value(format!( + "this runs as root from {}, and {} can be changed by others than root, so \ + whoever changes it would run as root too. Run a copy only root can \ + change:\n sudo install -m 0755 {} {ROOT_COPY}\n sudo vkey auth {verb}", + exe.display(), + path.display(), + exe.display() + ))); + } + } + Ok(()) +} + fn sudo_user() -> Result { if fs::metadata("/proc/self")?.uid() != 0 { return Err(Error::Value("this changes PAM: run it with sudo".into())); diff --git a/cli/src/check.rs b/cli/src/check.rs index 4b7b7d4..9a18f45 100644 --- a/cli/src/check.rs +++ b/cli/src/check.rs @@ -371,11 +371,21 @@ fn backup( rep.check("backup written", n.items == 3, &n.describe()); d.delete("t")?; d.delete("e")?; + println!( + " >>> a restore replaces everything, so it takes the wipe's hold, and this one \ + must then refuse the wrong passphrase: hold {} down for five seconds when the \ + light turns red", + rep.button + ); rep.expect( "restore refused with the wrong passphrase", &backup::import(d, &dir, passphrase("correct horse battery")?), &Error::BadBackup, ); + println!( + " >>> hold {} down for five seconds again when the light turns red", + rep.button + ); let done = backup::import(d, &dir, passphrase(PASS)?)?; rep.check( "restore", diff --git a/cli/src/main.rs b/cli/src/main.rs index a34c94a..7dc5828 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -409,20 +409,7 @@ fn run(cli: Cli) -> Result { Ok(0) } - Cmd::Wipe { yes } => { - if !confirm("wipe every secret and the PIN from this key?", yes)? { - println!("kept"); - return Ok(0); - } - eprintln!( - "hold {} on the board down for five seconds - the light turns red...", - boards::button(Some(&version)) - ); - dev.wipe()?; - sources::forget_all(); - println!("wiped: no PIN, no credentials - run vkey pin set or /pin"); - Ok(0) - } + Cmd::Wipe { yes } => run_wipe(&mut dev, &version, yes), Cmd::Check { wipe_everything } => { if !wipe_everything { @@ -462,10 +449,32 @@ fn run(cli: Cli) -> Result { op, environments, only, - } => run_restore(&mut dev, file.as_deref(), op, &environments, &only), + } => run_restore( + &mut dev, + &version, + file.as_deref(), + op, + &environments, + &only, + ), } } +fn run_wipe(dev: &mut Device, version: &str, yes: bool) -> Result { + if !confirm("wipe every secret and the PIN from this key?", yes)? { + println!("kept"); + return Ok(0); + } + eprintln!( + "hold {} on the board down for five seconds - the light turns red...", + boards::button(Some(version)) + ); + dev.wipe()?; + sources::forget_all(); + println!("wiped: no PIN, no credentials - run vkey pin set or /pin"); + Ok(0) +} + fn run_list(dev: &mut Device, long: bool) -> Result { let entries = with_unlock(dev, Device::list)?; if entries.is_empty() && !long { @@ -577,6 +586,7 @@ fn run_pick(dev: &mut Device, file: &Path, names: &[String]) -> Result, op: bool, environments: &[String], @@ -649,7 +659,14 @@ fn run_restore( let file = backup::source(&file)?; let pass = prompt_secret("backup passphrase")?; passphrase(&pass)?; - let done = with_unlock(dev, |d| backup::import(d, &file, passphrase(&pass)?))?; + let button = boards::button(Some(version)); + let done = with_unlock(dev, |d| { + eprintln!( + "a restore replaces everything on the key: hold {button} on the board down for \ + five seconds - the light turns red..." + ); + backup::import(d, &file, passphrase(&pass)?) + })?; println!( "{} item{}{} restored from {}", done.count, diff --git a/cli/src/shell.rs b/cli/src/shell.rs index 68da75d..e506741 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -92,6 +92,8 @@ const DANGER: usize = 2; /// `❯ /rm name` is a line that would work. const LIST_COMMANDS: &[&str] = &["add", "edit", "rm", "import", "passkeys", "passkey-rm"]; const SETTLE: Duration = Duration::from_millis(120); +/// By its full path: a `sudo` earlier in the user's PATH is not the one meant. +const SUDO: &str = "/usr/bin/sudo"; // The palette Claude Code uses: one warm accent (ACCENT and DIM live in prompt.rs), // everything else grey or semantic. @@ -2263,6 +2265,7 @@ impl Shell { }; passphrase(&pass)?; self.ensure_unlocked()?; + self.hold_hint(" - a restore replaces everything on the key"); let restored = backup::import(self.dev()?, &path, passphrase(&pass)?)?; let done = format!( " {} item{}{} restored from {}", @@ -2428,22 +2431,41 @@ impl Shell { return Ok(()); } self.line(DIM, " sudo asks for your password, or a tap"); - if !self.outside(Command::new("sudo").args([ - "apt-get", - "install", - "-y", - "libpam-u2f", - ]))? { + if !self.outside(Command::new(SUDO).args(["apt-get", "install", "-y", "libpam-u2f"]))? { return Err(Error::Value("apt-get could not install libpam-u2f".into())); } } - // sudo's secure_path leaves out ~/.local/bin: the binary goes by its full path. + // Root runs its own copy, which only root can change; it is brought up to this + // binary first if it differs, so the switch never runs a stale one. let verb = if on { "disable" } else { "enable" }; self.line( DIM, " sudo asks for your password, or a tap if it already takes one", ); - self.outside(Command::new("sudo").arg(&exe).args(["auth", verb]))?; + if std::fs::read(auth::ROOT_COPY).ok() != Some(std::fs::read(&exe)?) { + self.line( + DIM, + &format!( + " root runs vkey from {}, a copy only root can change", + auth::ROOT_COPY + ), + ); + let copied = self.outside( + Command::new(SUDO) + .arg("install") + .arg("-m") + .arg("0755") + .arg(&exe) + .arg(auth::ROOT_COPY), + )?; + if !copied { + return Err(Error::Value(format!( + "could not copy vkey to {}", + auth::ROOT_COPY + ))); + } + } + self.outside(Command::new(SUDO).args([auth::ROOT_COPY, "auth", verb]))?; Ok(()) } diff --git a/docs/roadmap.md b/docs/roadmap.md index c1d8872..9254123 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -771,6 +771,24 @@ Milestones, one commit each, each leaving a key that works: passkeys and its restore, after which the key did not restart (reset cause still power-on, vault still unlocked). The restore's "the key restarts" now reads "if a passkey changed": the CLI cannot tell whether one did. +7. **A restore takes the wipe's hold** (maintainer's decision, 2026-10-16). A restore + replaced the vault and the passkeys under the PIN alone, so a host that learned the + PIN could swap in passkeys of its own and skip the 5 s hold that authenticatorReset + takes. `ImportBegin` now waits for that hold before it touches anything. A core + change: the C6's image is rebuilt with it, but the C6 is left alone, so + `check --wipe-everything` is not re-run on it. With it, `sudo vkey auth` refuses to + run as root from a binary anyone but root can change and names the root-owned copy + `/usr/local/sbin/vkey`, which `/settings` keeps current. + + Acceptance, on the board: a `.vkb` first, `selftest`, a restore refused by a tap + that leaves the vault and the passkeys as they were, then one that goes through + with the hold; `/settings` → `auth` through the root copy. + + **Accepted 2026-10-16**, but for `/settings` → `auth`: a `.vkb` of 48 items and the + passkeys; `selftest` green; the restore with the hold brought back 48 items and the + passkeys (`github.com` still listed), one with a tap was refused; `sudo + ~/.local/bin/vkey auth enable` refused and named `/usr/local/sbin/vkey`. The + switch through the root copy is not yet run on this host. --- diff --git a/docs/threat-model.md b/docs/threat-model.md index 354a0f1..f771efd 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -97,8 +97,10 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure Passkeys are not served while the backup runs, so the copy is never torn. - Whoever has the `.vkb` and its passphrase has the passkeys. Restored onto another nRF52840, they make a clone that answers every site and this host's `sudo`. - - A restore replaces the passkeys with the PIN alone and no gesture, as it replaces - the vault. A file with no passkeys leaves them as they are. + - A restore replaces the passkeys, as it replaces the vault, after the PIN and the + wipe's 5 s hold (since 2026-10-16; before, the PIN alone was enough, which let a + host that knew the PIN skip the hold authenticatorReset takes). A file with no + passkeys leaves them as they are. - Restoring an older backup winds the signature counters back. A site that checks them may take the key for a clone. - A restore cut short leaves the region torn. The key formats it on its next start, @@ -184,7 +186,7 @@ before the burn became `Incompatible` and was wiped. | Gesture | Action | LED | |---|---|---| | Tap | code, the secret fields of an item, a `.env`, a passkey, a `vkey auth` login | amber | -| Hold 5 s | wipe; on the nRF52840 also erasing every passkey | red | +| Hold 5 s | wipe; a restore from a `.vkb`, which replaces everything; on the nRF52840 also erasing every passkey | red | | Double tap, 800 ms window | encrypted backup, **and an export or seed readout** | blue | A tap never wipes and never exports; a hold never exports; a double tap never wipes. One @@ -277,8 +279,12 @@ its strength is the passphrase's — keep it where you keep other backups, and t passphrase elsewhere. Host malware during `backup` gets the same ciphertext the owner gets; it cannot swap a code request for an export, and it can substitute its own passphrase only if the owner happens to double tap, which is never needed otherwise. -`vkey restore` writes the file back under PIN with no gesture, like `add`: nothing comes -out, a duplicate name replaces, and entry versus blob the newer one from the file wins. +`vkey restore` writes the file back under the PIN and the wipe's 5 s hold (since +2026-10-16; before, the PIN alone): nothing comes out, but everything is replaced, the +passkeys too, so a host that learned the PIN cannot swap in a vault or passkeys of its +own. `vkey restore --only` adds items beside the vault under the PIN alone, like `add`; +`add` and `rm` of one item stay gesture-free, so such a host can still delete items one +by one, never the passkeys. Rejected: a flash-image copy as backup — PIN-encrypted, 8 digits fall offline in days, and it does not transfer while bound to the chip key. @@ -302,6 +308,7 @@ mapping. The line is `sufficient`: what it adds is a way in, and the password st | Given | A login needs this physical key and a fresh tap after the request; the host holds a public key only; no vkey PIN, locked or not, and no attempt spent | | Laptop and key stolen together | The lock screen opens with a tap. A powered-off laptop is protected by disk encryption, not by this. Carry the key separately, do not leave it in the port | | Malware running as the user | Can start `sudo` and wait for a reflex tap. The light is the same amber as a code or a passkey; a tap you did not ask for is the thing to refuse | +| Malware rewriting `vkey` | `~/.local/bin/vkey` is the user's to rewrite, so `enable` and `disable` refuse to run as root from a binary, or under a directory, that anyone but root can change, and name the copy to run instead: `/usr/local/sbin/vkey`, root's, in sudo's `secure_path`. `/settings` brings that copy up to date through `/usr/bin/sudo` before it calls it (since 2026-10-16). Not closed: malware running as the user can still put a `sudo` of its own first in PATH or alias it in the shell, and catch the password the next time `sudo` asks; no program of the user's can stop that | | Malware enrolling a key of its own | `/etc/u2f_mappings` is root's: adding a line needs root already | | Someone at the unlocked laptop while you are away, key in the port | Gets root with one tap where `sudo` used to want the password | | A copy of the board's flash (the revision-2 glitch) | The credential's key is wrapped by fido-authenticator's key, which sits unsealed in Trussed's filesystem: whoever reads the flash can answer this host's logins, given the host | diff --git a/firmware/boards/esp32c6-zero/images/bootloader-sb.signed.bin b/firmware/boards/esp32c6-zero/images/bootloader-sb.signed.bin index 6a137ccbe101b71f2b84e59deec8ce8e87df0890..fb7e08581b8f23dc026b6031b08d6597cbce60a1 100644 GIT binary patch delta 406 zcmV;H0crk#-~xc)0omJ+`_G#4XP~asp+{GUP9yDD9V29)J+`h2s6E}~dDHL~QVlb^LBI@C7)xfU zsrVJaOugEKV2e>*g#|=bp@@=|(8QrhQ8%3IV+JA-NNPF?Whtm5%f{TY$_rkSOi6o+@DQ^*AH@GA%?$sm)m_ENP^V)r!)mlOGMh_G44V`wpZS=Eq= za(S4W;44dHj+1V#f8-nmt=%e!!iLv@`@o*c*{Y5QKutqU#b0Qx2l5*k3Os3kfYoO^ zx-0e*LEU8I?|t;bUd?mP1g>Tt9%;{h*NcVnwKqX)$JACWFAd~6Q4Zj(ne+l(!^63; z5e~|LDtOcz4HG~rjM#f>JNbYX(mxS|QPNL?Md`Pb&Ld;Z2XK{e#mPlHv#_L43uUas AB>(^b delta 406 zcmV;H0crk#-~xc)0wT-@Z8E zarfn_deRRVAs>kVrBV%m&$eQcx4-*kO(`GH4_5`HDl@P62$iga*`~LJMB}`~WXFL4 zYPssm5;|HD5V8?o)+u`$Nx^^7YDw#!+~$l1tI4^u^Bi3|DMi7T1-hT=fe1eL9 zr9p}V`lL{v17+4&ax_)YJaXcc6dCOpd6#V!JFn`#kVG)YL3ksiW1{YC?l&@b8HgH2 z7kMb3L8`FFE0dpY+}nB#9*s<2WofZIGIJz?|JgpbL42TbQB_GxPj^cA2MXkN8Nu1-v#_L43+B?r A`~Uy| diff --git a/firmware/boards/esp32c6-zero/images/vaultkey.bin b/firmware/boards/esp32c6-zero/images/vaultkey.bin index 83aba7294d696b8dcf0e178e2cba02b45a77ebd0..2d003fc79cf5ee2284aafd9bea50a5c90a4155bb 100644 GIT binary patch delta 16316 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 delta 16168 zcmb_@4R{k(y6`zCnKVg%Xgh5wrNz*+rN)viEwsoYn}$v(Y+-4oRaekJ_>)Dz6T)5T& z%zyRHfM<4d2Zzl~T5O&hkIml#fCGuxylgHI1EU(oVir^7|USni1$oT zte*A5IASjPIWZ4|VSo_>V?2y982K<}z(|EL4TcIvA`CMO1S1Q^-vnUT0?%Q%VC2FW zHVOD9<8%SfZ0_!sYNa7QAzpz{DniH`jm(K~UF6xAw6q|7J~qPy;qdr&o;;7Now{v) zXXERpBu$*uEK@O;>S=bzrT|F1AF81TFW;K%gO z3($U8(DW}LJs`**Fy~=DcEEgdOU2L;m@IL(Je|HsNj81vxvb07mR-i?{LeutKW|AK zPBhx!WMVd{iMd1FGR%;vAe};sd1SRR(G>&ohJVV)c&KI9s5(qm{IX?SVFMu`mQ!PL zInp-8b7NeCT_+TeL1vy4vWtu0s&d`w;quiqxC;N(Vfw>2*}BoTP7V!Lti}tFa{>jR zuzuqbApW-u`@aj&|0f*#zlDqcBXXReI+=Mq=h&1Z)7mQ!8*1?6$327Yd3>1TH8ba_ z;xKLDf$4SHl?u3@zS!#$gg1(sFLXLab|xHl8w^E>31=HfExHX6>2f z@w9`T7+U6;Ynn-{A9)U$iV{&5S3B#3vF5h|HA%2O@@PxS6LqJ#+Sr5r%fS<#g(WkI z?vI}KlAILB12Rz62Oh3NDJue6?g4`*fk~ca=2Xuyb4*L6`H;f?9jM^#BWcP{*KXhQ zZ<=TP1bO}dS!lsJ9>9u6PCR;<|HAdTQcsGsg|bcy7L6IL?dneY-k%F6!Q0hj{THid`o)^LS2-Yl+>0H1j-~jVk|8 zhspEYb5|0k@G-jhipd`Bb*^(W7M$6?L>p_boOfnNqe9nf^a{a)?LyCRFUN%z2|aoq ztMp2&;H)sK~Uhh4^d4;e_a#=+O^{dke?xM30k2yn@F#1m$7dA+ zlU(h{PiqGv_$ExiUw73QYxy^0)1A?&h zSBK-t$WfUZ;chxxvwp*mx!$`nnV*-8WT^y)eY}Miul>Wr?fEXW#5Y4$4TXh69u*>? zd7btd9#wZ#2zSotN#?lEt~1@(2o~0sx3->FZB%uC+;lz^&CO7ho=UP*b%!jyhn zjJDpx^`yu;r~6#*SckScUIH@!gMeodZS(a;h(sGaPh20wtGWk;>f5GEM<}tO3j8V* z%T1&6Ic(54hAOgSW1ZPk>1Ga>#2~MtEd~wwbZLCxA$pm^!|b}Q2nJq-6do>CBU9i# ztJoHUda7(mK2V{2RjnZ3EmLk0V6M~%A(wK3!m?2nBB}{JNg;c~_~C*rVLKTvctBAZ z4xQTB&LNTWxKuqWlkc1qx_tTODtJ4n8ZLwyn#O_XCaSgwAqQt+^5ZyOrRwQP-f0Of z=)AcUb&R#Sm3hnpdXj9P*W?YfU!ycU>R5UYLht%8zNw!m& zY!g6!+2aSw)^SvEXRL;;x8;FcwPM^>t#8oYsVjlkoxrPZFnh*LXyL#K0oQEJk;2x* zGA*1SA|B2imQvs_lOCtsJJlXqRzCw<6xr^S?ZU49;Y(kLH- zebF4J&wE`P*2&l5K1OeRC&m-oJqT?SVQ5SOa3oJbjR5#*k+J775H1ie#8dMC-oG*C7{f4^Mn z6Sr!`#6Cl??yBKI-#lFRAe)luMDTZt?5Qco#3e3<%MK3q-0m6?d=7hvRbu2;+>_y-SR7k!@PZ36E~1I>qoPX?sBhM2dcEGDaKeUb0?b*3sCwUF~|vr ztSA$Z!cv8trSp)Y^ae#7nKuUM8)4MI*dBvI>$znG9hs+cPEY7GoE_IybnZ~# zHujAJ*|)x`U;7f;x^^8+&|u#FrFhjfWsU3zAeChr08w%aVm1_t<5noz(vh<*4{^Yf zBWYk1@t&4;OM$Fn@=}zql{8bqCG}gqB>k}i(R*J3W7R}_h2Fka)F#a5Rqc6&nu9=9 zy|z{eCHf>)M%$;KBQXGAT09AI0tauV3%UU~-oEFtybg^p6 z*(t8DCpQ>eyIpJt2SVQ`7P(GUXRe_E7ERF@&Js##Q_ZO|)_=c(cXi${GSu8vz!WS1Z&GSw+LrLfs#35xHLR;;ozXVvjoTCTy4IxHsr2a>oS~H| zfi%KRx5VJV>cAb6d%vFsVsMIGe9gJ79P!`w40TpL(1RgcDrGl4-#pn=_>i7MYrPME!Io&^j3Y<8M$2ZwBl z;9MnGEb`e}t0fjLD!pkTYktU&jW^8`Ht>vMI}JmRLF`Ss&mG9|$>3&bmCwdlb@ zaUJ4SNr>0f_UMrhdunPVE0mM#P?F|5nUfZXa#*5@Ts#9cWaSItdN&GK*gs04NE8eX~QJ6o_O$5|SMcqJmXFKe=RWp|X# zRg*;ngYdKX1f3j@ja7&xvi~&Okz^Az{>yAfI?+I9pS)^7Hu2VcdI5T7TJM+48`}t1 zL=6d8#|5%Lmh@K%SZ@bWOU9=A-O3puB$^}Mff=M>VP&;# z6GNcWYb^4eBhv}T6HyIs-L9I567;1^@(~Y}Qzm`xJ8E0B&z=hbe~>R{i|~50oPh6Y z=W3-|3*y3FR55wTry3!_n;};p5~+d7w^kNQgAacnjw|x>NlUvw_$FBhGgfl+y;V~y zCWFyODRN@f5wc_*)|gtDVtTG;P){PxhO>Ap5#MFE{^I)9`l(;NmOMFOS40`Tz5&7g z4qv6Lju1tJHYYHV?5lKU$Evyc#s=oTsfqc_z%lS1YM)gs9kta19$>g7BB8)?kY4nt z$&&LL#}sV#jy^|5`51gx0dpTvaY;NOu*2JvCfjH37+fmxBgN1yJE%4Wr`^R30NVdl z0uD~S|2P369hHRdh>6ue*(RNi?mId&38&ky4%o&8_$R)XQyR7Jl&7i|O$qBvK)1B} z?;nOEM=+9`E$x1zW1~mRT*x^lvy%lZPg z*oJDFxLTW6dte;DPqPid(5_uYvcr5?Y2h6V=dy6#qH zipNCil`2ZLEsFCRI*n)NR28bSOIo-r+0_EU1-0@XlR?pT9A%W+i1aViKo&9{E{8U{F7DGRq_nPP+-@R^P;0`g9U zp;^CxTBax&xu=2_J=aeRQt+dcu^K4iCEkK3WQP$G07FUzLsR=wwg|pP4+P1L>oSBb zme7XN`{~*gJkVw`Yd=G@WC7o~jBB^Chx)a+PV9Bmu`C49?w7Xo1XE30!Sx zFgO2B)>6b=`F^P?k*0(As^ISt=c zXuKe$%Em(FUc~OIMz+9R#pJKU-YV#O$}2PDeIo4D>5pl+IK6vNgmWo97`e6{@RLYNQCiZI@nq{(E@WInfI zvMoxS2@WpW_vd9vKttgmI=b_xSp~SI z+}G85ty{fS`?5MBwWlmR_ozlb0q?K$hFB;QW3{rT1%DpNQxfLUn>uh4x^kL69Pb~! zbZ0n&m3*6bFGxJu*BI8%yvSP~W%r=^H&+P>!qVU;FVgr-tkbhje8uD(@yc#_cVI+h zHxE%~Y4_5j$#lH|-!ZmPymODCGpA$KR3*^V;L>UXb8E2uGc>AeTi z!!lEDfq0;AY)+>ZJsvh9I9JhjI?2Ob?*$iqxed8l=s^iW%cDMg@V$a6J=%%3A`MN@ zaPT@?F?OD29kMr%e zr2TNHCM|oPwPY3BMc%oCOL8`fNiE`G)Z)4ywbpOu8mn#BT4AR*$|H_OE{pBb8JOvc zH_rFC+VfhXK7~E+ck#Go39dV zQfh+i`I%jonsJ>eXA8NvP^%a|$_)O@T;vgC?VNb;DE9uTs_^?mnAERB|27NB&ja~WHkqsWDwj+WIt=n_0&?zQ^aMt*m-mHV z4kpi;!6_3#$Ra9vXLXf6&X=||&Noz+ULklhUd%$CDiK|zf6l_W2HhV}XlNUl=PwcK zi|aFAlRVG1GPYMTJIQ;)b2>a5C)xkWe)eu`?W5;C98%_pwoCgVo+4!nw-Xs$PKyR{ znw2Sf-CxiXKPYkl%ls6;@+ZXZW7j@%A|)0??i(e`=HZ+}J)#0I(Fx<5?*c+0ItJ`Y*c*NU&++Uf~1%(z8OGC8&$x8Z3HuPn_ zJhLLELLods3};#Kr7ls7aDyP+DR0*ob%v9b9bnKYzU5BVsscS=-wVQ-uT0$6@+u2V zQ^c#HIh>|?JuK;!y&6k-x4R1N3pZz80U9#uml$j93@Gb;?G^S~a-_Z&B;d_7o+aSH z*nfu3`d|I%GDVjVK^IteJ37d)B{<$^09{J`LSyZr8B9Eprc9fYr_rPFAeQGysa9Yd zaEg3Z`J;?yZZf2Z9dns;lbW8{oWsy%({MUmDz(FI>8XT%XnWfB)&3hToY?nOg;zo2 zQ<72O6BcbCA|T%n(3#8deW&<1(zmqP=VyN}3m=XL_ctz&x#R;t8>CL!w>jq;1FV1Q zQO1+d6PxBR3yOR+fXq@tgg%aVC4HPIxkI)iQusjDAngivvR$mp%ly;`u`JwOl^*KO zL_jD?g@n-WH!Wj_w~-30NM;+E>oOjW$4k%4h;6?T$~{)Ri(UgU|*}UDs)F~ z{e^I}lT^l3$nx+Ui?N|U(}L5A_nl)Y!!WXU51o*Uhd$hziug7DUeD-MN$gHKV^m2_U3=l2!Pk~pnz{Rwn3|%Ml*!I0(MxZCQ0@$#Q>S`76|vks}aahtuFB?SCx5O z%h6LB&)4m}o)t%XLu)ybSw}PP!bQcut-12XlFkb0 zJA%(qYaSjlSRbJQ{Es4XcHU>{hCHkzUt8$DJe-rIZ*C^~-N(uQ3{JP2l94!*(+%0W zK8D^o65l&?-z>e3LkaL_3BH@~B}@r*iBduqUr4u%#DfX?9esNwPD^(@A#oe|wqSvF zsD*a0#6I{q?H-AdUHHhKp=yFZ17T-b)2!rG%M^^(E+1k%cPu>5>iuWh1tYxg^OWpo6 z16T=~{sk*{$P)hr7~kph?nm?L+Uc=&kOModn6mIzllpBA6zfdCiyeSA^ox7Isbmq z!v&ND>V}3wF{Q*V#HNO~BYFZJY6|KF_a z+yNGb^^Gqfa~0?~d=<|NcXb)gMdHOO_&(2YI!qt*HFunC#QDGWDF#GU`q@w%Pv01g zHAR8z1M^OI;$2B!|S{!vDu61EA$;aj4N z0Uh#)C#b#%XQx@;3xjz`Ms~4E-V%I=&MAV5)f6G-L1t|#sF%V-z7>A&L8e7ea=Ya9 zfWL2D+HVxU_uaYz7ACQ&i>%N7_#J1g*XSMO#uQEZzx=JuL8ep+bH^-y=3bVBw@l<#% zXjLb%mB^mp!_;enfQBBT@0ze9(OboH*m8ljGbI?o8FYFH^arh#^vM#upP)(9XvUqy zbT?H^#A}HopFTek&m=(u?VgC!NHCYil;Y#Wluo-!aUDUtf02MMV-mRLubhOF6vXyN z|H3JFA{i{fcf6ujGsOV6DbHV~hsyDt!=*{!MMbj~JDaCqkGK}g8^f$^rZH3TRC!y_ zqu14N`piun&($bnBzW>R)ARJ{src_vGApa;vT67s;(f;7F%91Ul4kl(PRC0yK^Fgn zN<0i!3jGh=i*qrt4yVt~z|RoJ5UQ%e4J0s#zEXwDi7wjzw<;VYByf(NydUQhYZv|Q ze(WHoQ~swPz^U+Nz`yC&*oBGs2~D4g{}Q!_9YtU>y*U#fl_$tePtL+$lfX)P=ppTLJ``NC{GgP>os$qr&Q(HG{x!8i*2^KJM^LV~ksa2{}A zdeE<(k1Ih6*XTnF@DZ|LBh6iipC-C7v}qxb3Wmq zJ%Y!R`K@%(BX|O_ZliJkNz(j>AHiOtb8LMU9b<}wm^E0V*(ZBs0#%pU*+Od;<110p z#QHpa@=-iWo&@XsdmhEcAtd;tKj^~GW8%F?mp_Z|C+Ivq`7EAK9G$eN7LrNpX?lMx zE{G3y?1*k;m>f({rVjdIEzT@QCv%53XGmg_*3k)`TV;W{8k9|1@&3sZUICvWtptwg z5gwNZt#?GojL53>C{?e;qX}xK6V~Fz_Tak=lC(=HzlYvs@9h{Ifft5nf%yM*NjNjwD4xHdj~t)KDk=g0pHS!yxaR6z2wI03ngHt)x37q z7=2d7M12nYrih7yB~9`($Bvk=SeLP*blBnYp&rA zE`7lfa78yRh`)AqhV|dnRJ?$|=iNy`|FR$OYNFbwV*sI?cT_~Ux;I&5GohkN`g z0eTZ|Gr6jioCqFOdD9O+Re@AO(@Mw=1raOhE{>Fu zd9D6y9GQ!?Yt;TI0JrAV^>j`Y`I?yCrqybqBW()$q?%Nd-{ko_)I>`Nw~?OHlDRS5 z#(1^NYrBG$N0WkESJp<88Mm%{8BL1v)EndD{nboD^IPu^qkLb1)Vb=#$b8z;S#Y+f zt2hOuq`KTf%VWs+TVZU9Avvi7F^^S0gNl=2zw%Ox|5Oag!=zTz8b{t%#?5QxRbOF0 z0E6R*_a8|lW0geF;wOX2!#JwDhxz1}=)zQDoAgaj&jO@qSnYV~G5Lo#962u(OFz9? zq4?BtKl0zlWV4{vaL9OgAu4DuI^yBJBIAxtIBqyOp`$pN9V-{_PaHyqDT%e!Uywnx z;E~VL3B$-VVjAbK8%Cal;PMAL{Sr>~>vUv}Dsg@*AN3VxAd9mZfVOh~rW^u47t^Ks z%ZkZzqP5h?j)C)oK9r;~Nwm3~boRZg{zdV_63hd1 z(^N8+ydUtNoJtleQoZd%4r+v0FVyI(n^+|kSa}ni#0gqi0Vo^?XG zQUBrx$ps4umeTS@lAeSn*6>JK0-a(=r>v61%=DQ?VoVE8;FVgeRPtJ!$(}ccpL_4| zA8sVW2=NZ}Uuq(b*hJIBh3dsDDI;_`gWxdJ>HA1hV$k&YE$ccHeQ6)5A%S9=*+L*C z94+lj(iKMb1=TVHQvrRtg_wxWNDs6SNagZqR||Qb1Ty_g_LD`Jm||$)VPd4}Rx&-^ zq%2V$RE7pG?_G%g#(cEWiexxm;$PlMz9Yo(5nb{Y*+7Cv8{Q_DLFxRTzfH#Bc7*Slm#qW3YD(=3iJu~3s_SIg+8_edqt{f2)29?2t)g){|zPM8~*o2$tKq8%ze zdX+}r>#*ghrnjY*z%K^;bZa zw4#d;H4So)p^U6BkyB~=K`@`d6#Df+I4iG(jy^;(7gYdppu9wQkCWfC znsd=f5q_*AQRyhzs;J;(5y1CCY0YHXk;d>uXhFa5Xja9_BGL7U#Cs1D$%<565p?k$ z5fr!biN?@reL*aHT7^^at3 ziZ!e2=!M&$SoL(_VF($4VRYYNQZU*yG$OUEFfZ1$-1KINn=to7B&iZeb>ve@^{2KG zH8_zde`Y&@Y+Ls&9sfQ=7jHM+^gdZaykAh|5n>^_&uIA(VkW^L-EahOn$FR#Bcwdt z`e*RFc8_>w5a%rvUqmIAt}yJt8EQUCrV#WYtz%cyaoTm1Sc$Hk&5d-?F)%IbLHg`5 zaLCpJ^z1P*Ay)?p8ZPf-S%^%aU+>bCKZ`xE3WuT&3#pY(_!G&StAnVEr^y5)SN1E1 zcW>VtVa0RoVQ?9Qh+uVZL||5j2{!F!xQ@iHW6mV}9(tXg{1f>kN+#wN|Ni3y0%?kX46Nfp7SIu7xn19?^*R5g6XX!Ynx%Bd2V^=iEuues0KDrK($o&pN`f=} z9UUYevZ%?FoFeN;&_p+!B2Xeupl_ZcM@V24UHuW6lW4jNFwW~@!pWCBoq>M)5y>ak z5j6KSX(!$^fA?vU1*fT|DV<>DUXGTsD}1&3Z6_EDLiCkRvYnW&Q_G*pBX>a^5&riQ pSNL;P?}UuMYF;%g{=+{emi|~@v?S)kquXEDdSUQ?jClLde*=*Xl;HpX diff --git a/firmware/boards/esp32c6-zero/images/vaultkey.signed.bin b/firmware/boards/esp32c6-zero/images/vaultkey.signed.bin index e401a2ee2c0ba291dbc78d1079fba0f0f18ec2b9..dbd17193d6f77352489dc7df7b5f9df46f1d907b 100644 GIT binary patch delta 16763 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 delta 16615 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 Gga03urGOa# diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.bin index f469afc9b2161f21caeb2d522af148bece7aa761..796cefb61eb281a5eec9ce562fb75bce61c78dfa 100755 GIT binary patch delta 20357 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 delta 20264 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 diff --git a/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.signed.uf2 b/firmware/boards/nrf52840-mdk-dongle/images/vaultkey.signed.uf2 index 23d71d4868f4db8fa36ace7089000642d2b3a1ea..65e30da8aaa96e9da10b7f0da4ec353c19472ca7 100644 GIT binary patch delta 68778 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 delta 67846 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, head: BackupHead) -> Result<(), Fail> { self.dek()?; self.load()?; + if !ui::await_hold(&mut self.ui, &self.clock, TOUCH_TIMEOUT_MS, WIPE_HOLD_MS) { + return Err(Fail::Refused); + } let key = with_kdf_memory(|mem| vault::backup_key(pass, &head.salt, head.cost, mem)) .ok_or(Fail::Internal)?; self.store diff --git a/firmware/core/src/ui.rs b/firmware/core/src/ui.rs index b3765c7..3351c18 100644 --- a/firmware/core/src/ui.rs +++ b/firmware/core/src/ui.rs @@ -5,7 +5,8 @@ //! exists to stop. //! //! There are three gestures, and the differences are the point. A code or a password -//! is approved by a tap while the light is amber. The wipe needs five seconds of red. +//! is approved by a tap while the light is amber. The wipe needs five seconds of red, +//! and so does a restore, which replaces everything as a wipe does. //! A backup - every secret leaving at once, sealed - needs two taps in a row while //! the light is blue. Without that split the button would guard nothing against a //! hostile host: it would ask for a wipe while the owner expected a code request, and diff --git a/firmware/core/tests/key.rs b/firmware/core/tests/key.rs index 74b457f..d365085 100644 --- a/firmware/core/tests/key.rs +++ b/firmware/core/tests/key.rs @@ -188,10 +188,10 @@ impl MemFlash { self.key_full(button, clock, key, NoAttachment) } - /// Power on a board that keeps passkeys beside the vault, its finger tapping twice. + /// Power on a board that keeps passkeys beside the vault, its owner at the button. fn key_attached(&self, passkeys: &Passkeys) -> Key { let clock = Ticker::default(); - let button = Button::new(&clock, Finger::DoubleTap { gap: 120 }); + let button = Button::new(&clock, Finger::Owner); self.key_full(button, clock, Unbound, passkeys.clone()) } @@ -398,6 +398,9 @@ enum Finger { }, /// One tap whose contact opens for 15 ms in the middle: one press, bouncing. BouncyTap, + /// The owner, doing what the light asks: two taps at blue, otherwise down for six + /// seconds, which a tap wait takes as a tap and a hold wait as the hold. + Owner, /// Down before the request arrives, and never let go. Taped, } @@ -447,6 +450,10 @@ impl Ui for Button { vec![(from, from + 200), (from + 200 + gap, from + 400 + gap)] } Finger::BouncyTap => vec![(from, from + 100), (from + 115, from + 300)], + Finger::Owner if state == State::Export => { + vec![(from, from + 200), (from + 320, from + 520)] + } + Finger::Owner => vec![(from, from + 6_000)], Finger::Away | Finger::Taped => Vec::new(), }; } @@ -614,6 +621,11 @@ fn double_tapping(flash: &MemFlash) -> Key { ) } +fn owned(flash: &MemFlash) -> Key { + let clock = Ticker::default(); + flash.key_with(Button::new(&clock, Finger::Owner), clock, Unbound) +} + fn passphrase(s: &str) -> Passphrase<'_> { Passphrase::new(s.as_bytes()).expect("a valid test passphrase") } @@ -1462,7 +1474,7 @@ fn a_backup_moves_every_item_to_another_board() { // A different board: a blank flash and a new PIN of its own. let target = MemFlash::blank(); - let mut other = double_tapping(&target); + let mut other = owned(&target); other.pin_set(pin("87654321")).expect("sets its own PIN"); import(&mut other, "correct horse battery staple", head, &items).expect("restores"); @@ -1513,7 +1525,7 @@ fn a_backup_refuses_the_wrong_passphrase_and_a_reordered_file() { let (head, items) = export(&mut dev, "correct horse battery staple").expect("exports"); let target = MemFlash::blank(); - let mut other = double_tapping(&target); + let mut other = owned(&target); other.pin_set(pin("87654321")).expect("sets a PIN"); assert_eq!( import(&mut other, "wrong passphrase here", head, &items), @@ -1619,7 +1631,7 @@ fn a_board_without_passkeys_or_laid_out_otherwise_refuses_them() { let (head, blobs) = export(&mut dev, PASS).expect("exports"); let flash = MemFlash::blank(); - let mut plain = tapping(&flash); + let mut plain = owned(&flash); plain.pin_set(pin("12345678")).expect("sets the PIN"); assert_eq!( import(&mut plain, PASS, head, &blobs), @@ -1641,6 +1653,45 @@ fn a_board_without_passkeys_or_laid_out_otherwise_refuses_them() { assert!(!wider.frozen()); } +#[test] +fn a_restore_takes_the_wipes_hold_and_nothing_less() { + let (_, _, mut dev) = board_with_passkeys(); + let (head, blobs) = export(&mut dev, PASS).expect("exports"); + + for finger in [ + Finger::Tap, + Finger::DoubleTap { gap: 120 }, + Finger::Hold(2_000), + ] { + let passkeys = Passkeys::blank(4); + passkeys.fill(0, 0x55); + let flash = MemFlash::blank(); + let clock = Ticker::default(); + let mut other = flash.key_full( + Button::new(&clock, finger), + clock, + Unbound, + passkeys.clone(), + ); + other.pin_set(pin("87654321")).expect("sets the PIN"); + put( + &mut other, + "mine", + Category::Login, + &login_item("me", "pw"), + false, + ) + .expect("stores"); + assert_eq!( + import(&mut other, PASS, head, &blobs), + Err(Fail::Refused), + "a host that knows the PIN must not swap in passkeys of its own" + ); + assert_eq!(passkeys.bytes(), [0x55, 0xFF, 0xFF, 0xFF], "untouched"); + assert_eq!(names(&mut other).expect("lists"), ["mine"]); + } +} + #[test] fn every_way_a_session_ends_lets_the_passkeys_go() { let (_, passkeys, mut dev) = board_with_passkeys(); From 5ae64b72dc613b9e5852d79486d0b94dab9b5606 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 15:37:05 +0300 Subject: [PATCH 31/33] Let typos pass COSE, upstream's bootloader names and commit hashes --- _typos.toml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/_typos.toml b/_typos.toml index f03a7f2..5c06fd2 100644 --- a/_typos.toml +++ b/_typos.toml @@ -1,14 +1,28 @@ # Words the spell checker flags that are correct here. Each one is a name from # somewhere else - an API, a package, a diagram node - not prose we chose. +[default] +extend-ignore-re = [ + "`[0-9a-f]{7,40}`", # a commit hash in backticks, docs/ +] + [default.extend-identifiers] nin = "nin" # csv-core read_record: bytes consumed nout = "nout" # csv-core read_record: bytes written +BOOTLOADER_ADDR_NEW_RECIEVED = "BOOTLOADER_ADDR_NEW_RECIEVED" # Adafruit_nRF52_Bootloader +CFG_TUD_ENDOINT0_SIZE = "CFG_TUD_ENDOINT0_SIZE" # Adafruit_nRF52_Bootloader [default.extend-words] BA = "BA" # mermaid node id, docs/threat-model.md BK = "BK" # mermaid node id, docs/threat-model.md +cose = "cose" # COSE, RFC 9052: how CTAP2 encodes a public key gir = "gir" # the Debian package gir1.2-vte-2.91 Unparented = "Unparented" # GTK term: a widget with no parent +# A patch's context and removed lines are upstream's text, not ours to spell; +# its added lines are checked like any other file. +[type.patch] +extend-glob = ["*.patch"] +extend-ignore-re = ["(?m)^[- ].*$"] + [files] extend-exclude = ["*.bin", "*.pem", "Cargo.lock"] From e5e6f2af6af459c324f38c8f3e7dd95c79570873 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 15:57:30 +0300 Subject: [PATCH 32/33] Answer PR #21's review: CTAPHID channels, idle lock, docs that drifted --- .githooks/pre-commit | 2 +- .github/workflows/ci.yml | 2 + CLAUDE.md | 6 +-- README.md | 8 ++-- cli/src/auth.rs | 3 +- cli/src/backup.rs | 15 ++++++- cli/src/check.rs | 6 ++- cli/src/commits.rs | 16 +++++--- cli/src/device.rs | 3 +- cli/src/fido.rs | 39 ++++++++++++++----- cli/src/file.rs | 3 +- cli/src/main.rs | 5 ++- cli/src/op.rs | 28 +++++++++---- cli/src/setup.rs | 6 ++- cli/src/shell.rs | 7 ++++ docs/hardware.md | 2 +- docs/makerdiary.md | 8 ++-- docs/roadmap.md | 16 ++++---- docs/threat-model.md | 2 +- .../nrf52840-mdk-dongle/bootloader/check.py | 28 ++++--------- .../bootloader/sign-vaultkey.sh | 3 +- .../bootloader/signing-key.sh | 3 +- firmware/core/src/vault.rs | 2 +- tools/build-bootloader.sh | 3 +- tools/build-vaultkey.sh | 8 +++- tools/checks.sh | 7 ++++ 26 files changed, 154 insertions(+), 77 deletions(-) diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 3e0422e..d71578a 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -19,7 +19,7 @@ unstaged=$(git -C "$ROOT" diff --name-only -- "${paths[@]}") [[ -z "$unstaged" ]] || fail "unstaged changes in files the checks read - stage or stash them: $unstaged" -untracked=$(git -C "$ROOT" ls-files --others --exclude-standard -- '*.rs' '*.py' '*.sh') +untracked=$(git -C "$ROOT" ls-files --others --exclude-standard -- '*.rs' '*.py' '*.sh' '*.pem') [[ -z "$untracked" ]] || fail "source files that are not in git would not be in the commit - add or delete them: $untracked" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56b6fe1..12f2fa2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,6 +134,8 @@ jobs: cmp -n "$(stat -c %s "$plain")" "$plain" "$s" espsecure verify-signature --version 2 --keyfile "$pub" "$s" done + - name: signed UF2s verify under each board's bootloader key + run: bash -c '. tools/checks.sh && check_signed_uf2' wording: name: no forbidden marketing claim diff --git a/CLAUDE.md b/CLAUDE.md index 97ea337..729913c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,7 +7,7 @@ real secrets yet. | Part | What it is | |---|---| -| `firmware/core` | Firmware as a chip-free library: `proto` (frames), `device` (PIN, entries), `vault` (KDF/AEAD), `store` (flash, A/B image), `oath` (entry kinds, HOTP/TOTP), `ui` (button rules), `hal` (four traits — port, clock, button+LED, chip key; flash and RNG arrive via `embedded-storage` and `rand_core`). Bare-metal Rust, `no_std`, no RTOS; crypto from RustCrypto. | +| `firmware/core` | Firmware as a chip-free library: `proto` (frames), `device` (PIN, entries), `vault` (KDF/AEAD), `store` (flash, A/B image), `oath` (entry kinds, HOTP/TOTP), `ui` (button rules), `hal` (five traits — port, clock, button+LED, chip key, attachment: flash a backup carries besides the vault; flash and RNG arrive via `embedded-storage` and `rand_core`). Bare-metal Rust, `no_std`, no RTOS; crypto from RustCrypto. | | `firmware/boards//` | One board = one folder: `Cargo.toml` with the chip crates, `.cargo/config.toml` with the target, `src/main.rs` with pins and trait impls, `board.toml`, `bootloader/`, `images/`. The chip name appears **nowhere** outside such a folder. | | `cli/` | The `vkey` command: one static binary. Subcommands for scripts (`clap`), an interactive shell (`crossterm`, draws itself), flashing through `espflash` as a library with images embedded via `include_bytes!`. All user work goes through this CLI. | @@ -122,7 +122,7 @@ This is a security device. The rules below are not recommendations. paths enforce is worse than not advertising it. - **Irreversible actions get their own gesture.** Code, password, a `vkey auth` login, a signed git commit and a passkey on the nRF52840 — a tap (amber); wipe, a restore from a - `.vkb` (it replaces everything, passkeys included; 2026-10-16) and erasing every passkey + `.vkb` (it replaces every item, and the passkeys when the file carries them; 2026-10-16) and erasing every passkey (authenticatorReset) — hold 5 s (red); backup — double tap (blue). A tap never wipes and never exports; a hold never exports; a double tap never wipes. Password on a tap is the maintainer's decision of 2026-09-08 — do not reintroduce a separate hold. A new command with consequences gets a @@ -161,7 +161,7 @@ The boards: its signature slot at 0x96000. No chip key, so it holds no real secrets yet. `vkey info` prints the chip's build code, UICR `APPROTECT` and last reset cause. Notes, measurements and factory state: `docs/makerdiary.md`; the plan: `docs/roadmap.md`. -- **`esp32c6-zero`**, the test board (2026-10-14): nothing is built for it, and it takes +- **`esp32c6-zero`**, the test board (2026-10-14): no feature is built for it, and it takes `check --wipe-everything` for core changes. Its images are signed by `tools/sign-vaultkey.sh` with `vkey-signing`, which also lives on the nRF since 2026-10-15, so a core change is signed without touching the C6. Secure Boot v2 is burned, so before its diff --git a/README.md b/README.md index ccefb36..6ec68fe 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,8 @@ single-binary host CLI, and a press of the board's button for every secret that > revision-2 chip can still be glitched open, though, and it has no chip key > ([docs/threat-model.md](docs/threat-model.md)). So it is **not for real secrets** until the steps > in [docs/roadmap.md](docs/roadmap.md) are done, and `vkey setup` does not flash it yet. -> Everything below still describes the ESP32-C6-Zero, which is now only a test board. +> Everything below still describes the ESP32-C6-Zero, which is now only a test board, except +> `sudo`, passkeys and signed commits, which need the nRF52840. ## In ten seconds @@ -57,7 +58,7 @@ the device under routine use — only an explicit export under a double tap read Routine use returns only codes. `vkey backup` reseals every item under a backup passphrase without revealing secrets. - Everything, `list` included, needs the PIN — except a passkey or a `vkey auth` login on the - nRF52840, a tap alone; the key re-locks after two idle minutes. Secrets and + nRF52840: a tap, plus the FIDO PIN when a site asks for it; the key re-locks after two idle minutes. Secrets and PINs are never arguments or environment variables — hidden prompt or stdin. ## What it does not do @@ -178,7 +179,8 @@ vkey passkey pin # the FIDO PIN set, or changed ``` The nRF52840 keeps the passkeys sites make discoverable (webauthn.io's, a Google -account's). They sit behind the key's **FIDO PIN**, the one a browser asks for, which is +account's). Making, listing and erasing them takes the key's **FIDO PIN** once it is set, +and a sign-in takes it when the site asks for it; that PIN is apart from vkey's PIN on purpose: the key stores it as a plain SHA-256, so the same PIN for both would give a flash dump the vault's PIN too. In the shell the last tab of the list is `passkey`: it asks the FIDO PIN once, lists them until the lock, and `d` erases diff --git a/cli/src/auth.rs b/cli/src/auth.rs index 691ed7c..c9fa90d 100644 --- a/cli/src/auth.rs +++ b/cli/src/auth.rs @@ -295,7 +295,8 @@ fn root_only(verb: &str) -> Result<(), Error> { let exe = std::env::current_exe()?; for path in exe.ancestors() { let meta = fs::metadata(path)?; - let writable = meta.mode() & 0o002 != 0 || (meta.mode() & 0o020 != 0 && meta.gid() != 0); + // Group root is not root: a member of it who can write here is "others". + let writable = meta.mode() & 0o022 != 0; if meta.uid() != 0 || writable { return Err(Error::Value(format!( "this runs as root from {}, and {} can be changed by others than root, so \ diff --git a/cli/src/backup.rs b/cli/src/backup.rs index 79ed89d..bce67e3 100644 --- a/cli/src/backup.rs +++ b/cli/src/backup.rs @@ -376,6 +376,19 @@ pub fn pick( .join(", ") ))); } + // Every name checked before the first is written, so a refusal adds nothing. + let on_key = dev.list()?; + let taken: Vec<&str> = found + .iter() + .map(|(n, _)| n.as_str()) + .filter(|n| on_key.iter().any(|e| e.name == *n)) + .collect(); + if !taken.is_empty() { + return Err(Error::Value(format!( + "already on the key: {}; nothing was added", + taken.join(", ") + ))); + } for (name, item) in &found { dev.put(name, item, false)?; } @@ -384,7 +397,7 @@ pub fn pick( /// How many sectors the board on the other end keeps its passkeys in, as its folder /// says; 0 for none. -fn passkey_sectors(dev: &mut Device) -> Result { +pub fn passkey_sectors(dev: &mut Device) -> Result { let version = dev.info()?; Ok(version .rsplit(' ') diff --git a/cli/src/check.rs b/cli/src/check.rs index 9a18f45..41fe5db 100644 --- a/cli/src/check.rs +++ b/cli/src/check.rs @@ -386,11 +386,13 @@ fn backup( " >>> hold {} down for five seconds again when the light turns red", rep.button ); + // A board that keeps passkeys must get them back, or the round trip lost them. + let keeps_passkeys = backup::passkey_sectors(d)? > 0; let done = backup::import(d, &dir, passphrase(PASS)?)?; rep.check( "restore", - done.count == 3 && done.skipped.is_empty(), - &format!("{} items", done.count), + done.count == 3 && done.skipped.is_empty() && done.passkeys == keeps_passkeys, + &format!("{} items, passkeys back: {}", done.count, done.passkeys), ); let _ = std::fs::remove_file(&dir); rep.tap(); diff --git a/cli/src/commits.rs b/cli/src/commits.rs index 4d81e28..16b5f55 100644 --- a/cli/src/commits.rs +++ b/cli/src/commits.rs @@ -35,6 +35,8 @@ pub fn enable() -> Result { let key_text = key.to_string_lossy().into_owned(); refuse_foreign("gpg.format", "ssh")?; refuse_foreign("user.signingkey", &key_text)?; + let signers = home.join(SIGNERS); + refuse_foreign("gpg.ssh.allowedSignersFile", &signers.to_string_lossy())?; let Some(email) = git_get("user.email")? else { return Err(Error::Value( "git has no user.email to sign as: git config --global user.email you@example.com" @@ -46,7 +48,6 @@ pub fn enable() -> Result { make_key(&key)?; } let public = fs::read_to_string(pub_path(&key))?; - let signers = home.join(SIGNERS); if let Some(dir) = signers.parent() { fs::create_dir_all(dir)?; } @@ -75,12 +76,13 @@ pub fn enable() -> Result { /// signers stay, so the next enable takes no tap and GitHub needs no new key. pub fn disable() -> Result { let status = Command::new("git") - .args(["config", "--global", "--unset", "commit.gpgsign"]) + .args(["config", "--global", "--unset-all", "commit.gpgsign"]) .status()?; - // 5: the setting was not there, which is what was asked for. + // 5: the setting was not there, which is what was asked for. With plain --unset it + // also means several lines, left in place. if !status.success() && status.code() != Some(5) { return Err(Error::Value( - "git config --unset commit.gpgsign failed".into(), + "git config --unset-all commit.gpgsign failed".into(), )); } println!("git commits are no longer signed; enable again to sign with the same key"); @@ -94,6 +96,7 @@ pub fn enabled() -> bool { }; let key = home.join(KEY).to_string_lossy().into_owned(); matches!(git_get("commit.gpgsign"), Ok(Some(v)) if v == "true") + && matches!(git_get("gpg.format"), Ok(Some(v)) if v == "ssh") && matches!(git_get("user.signingkey"), Ok(Some(v)) if v == key) } @@ -183,9 +186,10 @@ pub fn github() -> Result { gh_interactive(&["auth", "refresh", "-h", "github.com", "-s", SCOPE])?; out = add_key(&public)?; } - // gh answers success for a key GitHub already has, so both read the same. + // gh answers success for a key this account already has. A failure that says + // "already" is the key in use on another account, which is no verified commit here. let why = String::from_utf8_lossy(&out.stderr); - if out.status.success() || why.contains("already") { + if out.status.success() { println!("the key is on GitHub: commits signed with it show as verified"); } else { return Err(Error::Value(format!( diff --git a/cli/src/device.rs b/cli/src/device.rs index ee329ac..f23055c 100644 --- a/cli/src/device.rs +++ b/cli/src/device.rs @@ -278,8 +278,7 @@ pub struct Stored { /// the key. Two matches are an error, not a pick: the other one may be a key holding /// secrets, and `check` wipes whatever it reaches. pub fn find_port() -> Result { - let mut found: Vec = serialport::available_ports() - .unwrap_or_default() + let mut found: Vec = serialport::available_ports()? .into_iter() .filter(|p| { matches!(&p.port_type, SerialPortType::UsbPort(u) diff --git a/cli/src/fido.rs b/cli/src/fido.rs index 7e86b02..9857368 100644 --- a/cli/src/fido.rs +++ b/cli/src/fido.rs @@ -274,10 +274,11 @@ impl Key { } } for site in &sites { - let name = field(site, 3) - .and_then(|rp| text_field(rp, "id")) - .unwrap_or("?") - .to_string(); + let name = printable( + field(site, 3) + .and_then(|rp| text_field(rp, "id")) + .unwrap_or("?"), + ); let hash = field(site, 4) .and_then(Cbor::as_bytes) .ok_or_else(|| Error::Value("the key named a site without its hash".into()))?; @@ -294,11 +295,11 @@ impl Key { } for c in &creds { let user = field(c, 6); - let shown = user - .and_then(|u| text_field(u, "name")) - .or_else(|| user.and_then(|u| text_field(u, "displayName"))) - .unwrap_or("") - .to_string(); + let shown = printable( + user.and_then(|u| text_field(u, "name")) + .or_else(|| user.and_then(|u| text_field(u, "displayName"))) + .unwrap_or(""), + ); let id = field(c, 7) .and_then(|d| bytes_field(d, "id")) .ok_or_else(|| { @@ -477,8 +478,20 @@ impl Key { let total = usize::from(u16::from_be_bytes([packet[5], packet[6]])); let mut out = Vec::with_capacity(total); out.extend_from_slice(&packet[7..7 + total.min(PACKET - 7)]); + let mut next = 0u8; while out.len() < total { let more = self.packet()?; + // Another program's channel shares the hidraw node: not ours to read. + if more[..4] != packet[..4] { + continue; + } + if more[4] != next { + return Err(Error::Value(format!( + "the key sent packet {} of its answer where {next} was due", + more[4] + ))); + } + next = next.wrapping_add(1); let take = (total - out.len()).min(PACKET - 5); out.extend_from_slice(&more[5..5 + take]); } @@ -626,6 +639,14 @@ fn padded_pin(pin: &str) -> Result>, Error> { Ok(out) } +/// A name a site chose, with what a terminal would act on rather than show - escape +/// sequences, line breaks - turned into `?`: these names are printed. +fn printable(s: &str) -> String { + s.chars() + .map(|c| if c.is_control() { '?' } else { c }) + .collect() +} + /// The text under key `k` of a CBOR map keyed by text. fn text_field<'a>(map: &'a Cbor, k: &str) -> Option<&'a str> { let Cbor::Map(entries) = map else { diff --git a/cli/src/file.rs b/cli/src/file.rs index 37d2732..b47653e 100644 --- a/cli/src/file.rs +++ b/cli/src/file.rs @@ -12,7 +12,8 @@ use crate::device::Error; /// the source map or an `op` cache, never a file that no longer parses. pub fn replace(path: &Path, contents: &[u8], mode: u32) -> Result<(), Error> { let mut tmp = path.as_os_str().to_owned(); - tmp.push(".vkey-new"); + // Per process: two vkeys replacing the same file must not write into one another's. + tmp.push(format!(".vkey-new.{}", std::process::id())); let mut f = OpenOptions::new() .write(true) .create(true) diff --git a/cli/src/main.rs b/cli/src/main.rs index 7dc5828..382c4cc 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -750,8 +750,9 @@ fn run_op( } // `op` cannot list Developer Environments, so the saved ones are the whole known set: - // a run that names none takes all of them, and a new one is only ever added. - if item.is_none() && env_pairs.is_empty() { + // a run that names none takes all of them, and a new one is only ever added. One + // that names only unknown ones takes none, not all. + if item.is_none() && environments.is_empty() { env_pairs.extend(saved); env_pairs.sort_by(|a, b| a.0.cmp(&b.0)); if prompt::is_tty() { diff --git a/cli/src/op.rs b/cli/src/op.rs index f7f37e8..7f9c957 100644 --- a/cli/src/op.rs +++ b/cli/src/op.rs @@ -455,17 +455,31 @@ pub fn load_vault_map() -> BTreeMap { map.into_iter().filter(|(_, v)| !v.is_empty()).collect() } -/// Folds what a run learned into the vault map on disk, readable only by its owner. +/// Folds what a run learned into the vault map on disk. fn save_vault_map(learned: BTreeMap) { + let mut map = load_vault_map(); + map.extend(learned); + write_vault_map(&map); +} + +/// An entry renamed by hand stays in its vault under the new name. +pub fn vault_renamed(from: &str, to: &str) { + let mut map = load_vault_map(); + if let Some(vault) = map.remove(from) { + map.insert(to.to_string(), vault); + write_vault_map(&map); + } +} + +/// The vault map written whole, readable only by its owner. +fn write_vault_map(map: &BTreeMap) { let Some(path) = config_path("op_vaults.json") else { return; }; - let mut map = load_vault_map(); - map.extend(learned); if let Some(parent) = path.parent() { let _ = std::fs::create_dir_all(parent); } - if let Ok(json) = serde_json::to_vec_pretty(&map) { + if let Ok(json) = serde_json::to_vec_pretty(map) { let _ = file::replace(&path, &json, 0o600); } } @@ -1038,9 +1052,9 @@ pub fn sync( mirror.items( &items, item_blocked.or_else(|| { - items - .is_empty() - .then(|| "1Password listed no items at all".to_string()) + // The listing as it came, documents included: a vault of documents + // only is a listing, and what an earlier run took from it goes now. + (all == 0).then(|| "1Password listed no items at all".to_string()) }), )?, mirror.environments( diff --git a/cli/src/setup.rs b/cli/src/setup.rs index caf5de2..726a963 100644 --- a/cli/src/setup.rs +++ b/cli/src/setup.rs @@ -201,10 +201,14 @@ pub fn wait_for_firmware(port_hint: &str, timeout: Duration) -> Result p, Err(Error::NoBoard) => port_hint.to_string(), + Err(Error::ManyBoards(ports)) if ports.iter().any(|p| p == port_hint) => { + port_hint.to_string() + } Err(e) => return Err(e), }; let mut dev = match Device::open(Some(&port)) { diff --git a/cli/src/shell.rs b/cli/src/shell.rs index e506741..fe1beb5 100644 --- a/cli/src/shell.rs +++ b/cli/src/shell.rs @@ -904,6 +904,10 @@ impl Shell { return; }; let flipped = st.unlocked != self.unlocked; + // The passkeys' token goes with the lock, the idle one too. + if flipped && !st.unlocked { + self.passkeys = None; + } self.unlocked = st.unlocked; self.has_pin = st.has_pin; self.retries = st.retries_left; @@ -1716,6 +1720,7 @@ impl Shell { Some(new) if new != name => { self.dev()?.rename(&name, &new)?; sources::renamed(&name, &new); + op::vault_renamed(&name, &new); new } _ => name, @@ -2289,6 +2294,8 @@ impl Shell { " if a passkey changed, the key restarts to load them...", ); std::thread::sleep(Duration::from_secs(3)); + // A reset FIDO side has forgotten the token the passkey tab held. + self.passkeys = None; if !self.reconnect() { self.line( Color::Yellow, diff --git a/docs/hardware.md b/docs/hardware.md index 8e5e543..5c9cde2 100644 --- a/docs/hardware.md +++ b/docs/hardware.md @@ -213,7 +213,7 @@ board that trusts it; leaking it removes Secure Boot. Public half and digest: `firmware/secure-boot/public.pem` and `digest.bin`, in the repository. `images/vaultkey.bin` stays unsigned and reproducible (a hook rebuilds and compares), with `vaultkey.signed.bin` beside it, verified by the hook with the public key. Since 2026-10-15 the key also lives -on the nRF52840 (added from a `.vkb` by `vkey restore --only vkey-signing`), so +on the nRF52840 (added by `vkey restore --only vkey-signing `), so `tools/sign-vaultkey.sh` signs this board's images with the nRF plugged in and this board left alone. For one day the signed app was out of the repository, after a core change this board was not there to sign. diff --git a/docs/makerdiary.md b/docs/makerdiary.md index 720df92..ebe1d50 100644 --- a/docs/makerdiary.md +++ b/docs/makerdiary.md @@ -1,8 +1,8 @@ # Next board: Makerdiary nRF52840 MDK USB Dongle Research notes of 2026-10-03. The board was ordered on 2026-10-03. Decided: passkey is back, -on Trussed. Since 2026-10-04 the board folder builds vkey for the chip (no Trussed yet); it -has not run on a board. +on Trussed. Since 2026-10-04 the board folder builds vkey for the chip; it has run on the +board since 2026-10-13, with Trussed since 2026-10-15. ## Goal @@ -39,7 +39,7 @@ Why not our own, so it is not re-argued: Correctness and security rank above simplicity: a vetted stack beats fresh code of our own, even a bigger one. The price is accepted: a large dependency tree, littlefs in C, two -storages, two PINs, no passkey backup. +storages, two PINs, no passkey backup (since solved: the `.vkb` carries them, 2026-10-15). Plan: @@ -75,6 +75,8 @@ Open questions before code: in Trussed's store, the vault PIN in `store.rs`. Merging them means changing Trussed. - **Backup.** Passkeys in Trussed's store are not in the `.vkb` backup. Losing the key means re-enrolling passkeys on every site; keep a second factor registered everywhere. + Answered 2026-10-15: the `.vkb` carries Trussed's sectors, and a restore puts them back + on a board with the same `passkey_sectors`. ## Memory map (decided 2026-10-03) diff --git a/docs/roadmap.md b/docs/roadmap.md index 9254123..89e8f48 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -19,9 +19,10 @@ notes, measurements and the factory state: `docs/makerdiary.md`. `makerdiary.md`. Installing it moves the bootloader address in UICR, which without a probe is a one-shot operation with no way back. A fork of the bootloader already on the board installs through its own update path at the same address. -- **UF2 stays the transport for good.** `vkey setup` for the nRF copies a signed UF2 to - the bootloader's drive. That is no longer throwaway work. -- **Test without a spare.** Neither board holds real secrets (2026-10-14). The C6 takes +- **UF2 stays the transport for good.** `vkey setup` for the nRF is to copy a signed UF2 to + the bootloader's drive; until it does, the copy is by hand. That is no longer throwaway work. +- **Test without a spare.** Neither board holds real secrets (2026-10-14); the nRF holds + only the two signing keys, `vkey-signing` and `vkey-signing-nrf`, each also in a `.vkb`. The C6 takes the full `check --wipe-everything` for core changes, once a `.vkb` holds its Secure Boot key `vkey-signing`; the nRF takes it while it holds nothing a `.vkb` cannot restore. nRF-only changes get `selftest` and a `.vkb` @@ -33,14 +34,15 @@ notes, measurements and the factory state: `docs/makerdiary.md`. **Real secrets go onto the nRF when phases 3-5 are done, not when features are done.** No board holds real secrets today, and the C6 is a test board, not a fallback (2026-10-14), so every feature is built for the nRF alone. The nRF has no chip key, and -its debug port is open. Until 2026-10-14 its bootloader also flashed anything and served +APPROTECT closes its debug port (phase 4), though a boot-time glitch opens it on this +revision-2 chip. Until 2026-10-14 its bootloader also flashed anything and served the flash back (`CURRENT.UF2`); our fork has replaced it since (phase 3). A copy of its flash gives up the PIN offline in hours (`docs/threat-model.md`). `espflash` stays in the CLI while the C6 is flashed through it, and the audit exception with it. The order is fixed by what each step depends on. First the **bootloader** with no read-back and signed images only: APPROTECT means nothing while UF2 hands out the flash. Then -**APPROTECT**. Then the **chip key**. +**APPROTECT**. Then the **chip key**, skipped on this revision-2 chip (phase 5). --- @@ -60,8 +62,8 @@ and signed images only: APPROTECT means nothing while UF2 hands out the flash. T 3. **Re-sign and flash the C6.** Unplug the nRF. Then `./tools/sign-vaultkey.sh`, `cargo build --release` in `cli/`, `vkey install`, `vkey setup` **without** `--erase`, and `vkey totp selftest`. -4. **`auth enable` on the nRF.** `sudo vkey --port auth enable` must refuse at once - and write nothing to `/usr/local/bin/vkey`. +4. ~~**`auth enable` on the nRF.**~~ Obsolete since phase 6: `vkey auth` is `pam_u2f` + now, and `enable` works on the nRF. 5. **Commit.** `git add` the whole `firmware/boards/nrf52840-mdk-dongle/` folder with `images/`, then commit (the maintainer). diff --git a/docs/threat-model.md b/docs/threat-model.md index f771efd..66b74a1 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -305,7 +305,7 @@ mapping. The line is `sufficient`: what it adds is a way in, and the password st | | | |---|---| -| Given | A login needs this physical key and a fresh tap after the request; the host holds a public key only; no vkey PIN, locked or not, and no attempt spent | +| Given | A login needs this physical key and a fresh tap after the request; the host holds the public key and the credential ID, the private key wrapped by a key on the board; no vkey PIN, locked or not, and no attempt spent | | Laptop and key stolen together | The lock screen opens with a tap. A powered-off laptop is protected by disk encryption, not by this. Carry the key separately, do not leave it in the port | | Malware running as the user | Can start `sudo` and wait for a reflex tap. The light is the same amber as a code or a passkey; a tap you did not ask for is the thing to refuse | | Malware rewriting `vkey` | `~/.local/bin/vkey` is the user's to rewrite, so `enable` and `disable` refuse to run as root from a binary, or under a directory, that anyone but root can change, and name the copy to run instead: `/usr/local/sbin/vkey`, root's, in sudo's `secure_path`. `/settings` brings that copy up to date through `/usr/bin/sudo` before it calls it (since 2026-10-16). Not closed: malware running as the user can still put a `sudo` of its own first in PATH or alias it in the shell, and catch the password the next time `sudo` asks; no program of the user's can stop that | diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py b/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py index da8fe61..85df8b1 100644 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/check.py @@ -5,8 +5,7 @@ - No UICR address the code could write through: the bootloader must never write UICR. A write there (PSELRESET, NFCPINS, APPROTECT) is permanent without a probe. Searched three ways: as a word anywhere in the code, as an immediate in any instruction but a - comparison, and as a movw/movt pair or a movt of 0x1000 whose low half it cannot - see. Like the radio search in build-vaultkey.sh, it catches direct addressing, not an + comparison, and as any movt of 0x1000, whatever low half it meets. Like the radio search in build-vaultkey.sh, it catches direct addressing, not an address computed from another base plus an offset. - The CF2 block is the factory one, word for word. Its board ID is what the factory bootloader checks before it accepts this one as a self-update, and what a later @@ -43,23 +42,21 @@ # objdump --no-show-raw-insn: " f5f2a:\tcmp.w\tr3, #268439552\t@ 0x10001000" INSN = re.compile(r"^\s*([0-9a-f]+):\s+(\S+)\s*(.*)$") NUMBER = re.compile(r"(? list[str]: - # Halfword steps: Thumb literal pools are word-aligned, but a constant packed in - # data need not be. + # Every byte offset: Thumb literal pools are word-aligned, but a constant packed in + # data need not be aligned at all. return [ hex(base + i) - for i in range(0, len(code) - 3, 2) + for i in range(len(code) - 3) if struct.unpack_from(" list[str]: hits = [] - last_movw: dict[str, int] = {} for line in dis.splitlines(): m = INSN.match(line) if not m: @@ -71,19 +68,10 @@ def immediates_and_pairs(dis: str) -> list[str]: if int(n, 0) in UICR: hits.append(f"{addr}: {text}") break - if w := MOVW.match(text): - last_movw[w.group(1)] = int(w.group(2)) - elif t := MOVT.match(text): - # A high half of 0x1000 with a low half that did not come from a movw into - # the same register (a mov.w, a mov from another register) could still be - # UICR, so it counts as one. - low = last_movw.get(t.group(1)) - high = int(t.group(2)) << 16 - if (low is None and high == UICR.start & 0xFFFF0000) or ( - low is not None and (high | low) in UICR - ): - hits.append(f"{addr}: {text} (with movw #{low:#x})" if low is not None - else f"{addr}: {text} (low half unknown)") + if (t := MOVT.match(text)) and int(t.group(2)) << 16 == UICR.start & 0xFFFF0000: + # Any high half of 0x1000 counts: which low half meets it at run time is + # more than a line-by-line reading can tell. + hits.append(f"{addr}: {text}") return hits diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/sign-vaultkey.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/sign-vaultkey.sh index 48179fc..4065271 100755 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/sign-vaultkey.sh +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/sign-vaultkey.sh @@ -28,7 +28,8 @@ for tool in openssl vkey base64 python3; do command -v "$tool" >/dev/null || { echo "$tool is missing" >&2; exit 1; } done [[ -f "$PUBLIC" ]] || { echo "no $PUBLIC: run signing-key.sh first" >&2; exit 1; } -[[ -d /dev/shm ]] || { echo "no /dev/shm: the key would have to touch the disk" >&2; exit 1; } +[[ -d /dev/shm && "$(stat -f -c %T /dev/shm 2>/dev/null)" == tmpfs ]] \ + || { echo "/dev/shm is not tmpfs: the key would have to touch the disk" >&2; exit 1; } [[ -f "$images/vaultkey.bin" ]] || { echo "no images/vaultkey.bin - build first" >&2; exit 1; } grep -qE "^device:.* $board\$" <<<"$(vk info)" || { echo "$PORT is not $board" >&2; exit 1; } diff --git a/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh b/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh index 93d8915..d31ebbd 100755 --- a/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh +++ b/firmware/boards/nrf52840-mdk-dongle/bootloader/signing-key.sh @@ -32,7 +32,8 @@ vk() { vkey --port "$PORT" "$@"; } for tool in openssl vkey base64; do command -v "$tool" >/dev/null || { echo "$tool is missing" >&2; exit 1; } done -[[ -d /dev/shm ]] || { echo "no /dev/shm: the key would have to touch the disk" >&2; exit 1; } +[[ -d /dev/shm && "$(stat -f -c %T /dev/shm 2>/dev/null)" == tmpfs ]] \ + || { echo "/dev/shm is not tmpfs: the key would have to touch the disk" >&2; exit 1; } if [[ -e "$PUBLIC" ]]; then echo "$PUBLIC exists: the signing key was made already." >&2 echo "A second one would not be the key a built bootloader trusts." >&2 diff --git a/firmware/core/src/vault.rs b/firmware/core/src/vault.rs index fa93e6a..36ee805 100644 --- a/firmware/core/src/vault.rs +++ b/firmware/core/src/vault.rs @@ -33,7 +33,7 @@ pub const OVERHEAD: usize = NONCE_LEN + TAG_LEN; /// six digits fall in a fortnight, seven in five months, eight in four years. No key /// derivation rescues a shorter PIN - a second per unlock is already as slow as the /// device may be, so length is the only lever left. Without a chip key a copy of the -/// flash is guessed offline instead, and no length rescues that (docs/threat-model.md). +/// flash is guessed offline instead, and eight digits do not hold there (docs/threat-model.md). pub const PIN_LEN: usize = 8; /// A backup file has no attempt counter: whoever holds it guesses forever, at the speed /// of their own hardware, and 128 KiB of Argon2id is not much of a brake. Twelve is a diff --git a/tools/build-bootloader.sh b/tools/build-bootloader.sh index 59799a4..e93f54b 100755 --- a/tools/build-bootloader.sh +++ b/tools/build-bootloader.sh @@ -94,7 +94,8 @@ build_esp() { build_uf2() { local dir="$1" name="$2" out log key kind if [[ -n "${BOOTLOADER_TEST_KEY:-}" ]]; then - key="$BOOTLOADER_TEST_KEY" kind=test + # Absolute: docker -v reads a bare relative name as a named volume. + key="$(realpath -m -- "$BOOTLOADER_TEST_KEY")" kind=test else key="$dir/bootloader/signing-key.pem" kind=real fi diff --git a/tools/build-vaultkey.sh b/tools/build-vaultkey.sh index 16bfaee..27841ac 100755 --- a/tools/build-vaultkey.sh +++ b/tools/build-vaultkey.sh @@ -39,10 +39,14 @@ OBJCOPY="$LLVM/llvm-objcopy" # every slot this firmware does use (USB, flash controller, RNG). It does not rule out # an address computed from a neighbouring peripheral's base plus an offset. radio_refs() { # elf image base - local slot words pairs + local slot words pairs dis slot=$(printf '%x' $(($3 >> 12))) words=$(od -An -v -tx4 -w4 "$2" | grep -c "^ *0*${slot}[0-9a-f]\{3\}$" || true) - pairs=$("$LLVM/llvm-objdump" -d --no-show-raw-insn "$1" | grep -E $'\tmov[wt]\t' | { + # On its own: the `|| true` below is for grep finding no mov, not for a failed + # disassembly, which would read as no reference at all. + dis="$("$LLVM/llvm-objdump" -d --no-show-raw-insn "$1")" \ + || { echo "llvm-objdump could not disassemble $1" >&2; exit 1; } + pairs=$(grep -E $'\tmov[wt]\t' <<<"$dis" | { declare -A low n=0 while read -r _ op reg val; do diff --git a/tools/checks.sh b/tools/checks.sh index 41d99ed..d0caff1 100755 --- a/tools/checks.sh +++ b/tools/checks.sh @@ -146,6 +146,13 @@ check_signed_images() { check_signed_uf2() { step "signed UF2s match their unsigned twins and bootloader/signing-key.pem" local pem dir name signed plain kind tmp fp ok + # Driven by the UF2s too: a key taken away must not silently end their check. + for signed in "$ROOT"/firmware/boards/*/images/*.signed.uf2; do + [[ -f "$signed" ]] || continue + dir="$(dirname "$(dirname "$signed")")" + [[ -f "$dir/bootloader/signing-key.pem" ]] \ + || fail "$(basename "$dir"): $(basename "$signed") has no bootloader/signing-key.pem to verify it under" + done for pem in "$ROOT"/firmware/boards/*/bootloader/signing-key.pem; do [[ -f "$pem" ]] || continue dir="$(dirname "$(dirname "$pem")")" From c934feed42f612ea515a4100e227375173561217 Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Fri, 16 Oct 2026 17:16:54 +0300 Subject: [PATCH 33/33] Retry port discovery after a flash; list the nRF's passkeys too --- cli/src/setup.rs | 7 ++++++- docs/roadmap.md | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cli/src/setup.rs b/cli/src/setup.rs index 726a963..7dffd79 100644 --- a/cli/src/setup.rs +++ b/cli/src/setup.rs @@ -209,7 +209,12 @@ pub fn wait_for_firmware(port_hint: &str, timeout: Duration) -> Result { port_hint.to_string() } - Err(e) => return Err(e), + Err(e @ Error::ManyBoards(_)) => return Err(e), + // The ports could not be listed this second, mid-reset: try again. + Err(e) => { + last = e; + continue; + } }; let mut dev = match Device::open(Some(&port)) { Ok(d) => d, diff --git a/docs/roadmap.md b/docs/roadmap.md index 89e8f48..7aa2fb0 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -21,8 +21,9 @@ notes, measurements and the factory state: `docs/makerdiary.md`. board installs through its own update path at the same address. - **UF2 stays the transport for good.** `vkey setup` for the nRF is to copy a signed UF2 to the bootloader's drive; until it does, the copy is by hand. That is no longer throwaway work. -- **Test without a spare.** Neither board holds real secrets (2026-10-14); the nRF holds - only the two signing keys, `vkey-signing` and `vkey-signing-nrf`, each also in a `.vkb`. The C6 takes +- **Test without a spare.** Neither board holds real secrets (2026-10-14); the nRF's vault + holds only the two signing keys, `vkey-signing` and `vkey-signing-nrf`, each also in a `.vkb`, + and Trussed's storage beside it the passkeys of phase 6 (`github.com`'s among them). The C6 takes the full `check --wipe-everything` for core changes, once a `.vkb` holds its Secure Boot key `vkey-signing`; the nRF takes it while it holds nothing a `.vkb` cannot restore. nRF-only changes get `selftest` and a `.vkb`

, + ) -> Result { + let staging = &mut self.staging; + let (core, backend) = (&mut ctx.core, &mut ctx.backends); + match extension { + Extension::FsInfo => ExtensionImpl::::extension_request_serialized( + staging, core, backend, request, resources, + ), + Extension::Hkdf => ExtensionImpl::::extension_request_serialized( + staging, core, backend, request, resources, + ), + } + } +} + +/// Extensions first, then Trussed's core for everything else. +static BACKENDS: [BackendId; 2] = [BackendId::Custom(Backend::Staging), BackendId::Core]; + +/// The Trussed service and fido-authenticator's endpoint to it. +struct Runner { + service: Service, + endpoint: ServiceEndpoint<'static, Backend, StagingContext>, +} + +static RUNNER: StaticCell> = StaticCell::new(); +static TRUSSED: TrussedChannel = TrussedChannel::new(); + +/// A Trussed request is answered as soon as it is made: the service runs right here, +/// inside the client's call. +struct Syscall(&'static RefCell); + +impl trussed::platform::Syscall for Syscall { + fn syscall(&mut self) { + let mut runner = self.0.borrow_mut(); + let Runner { service, endpoint } = &mut *runner; + service.process(core::slice::from_mut(endpoint)); + } +} + +type Client = ClientImplementation<'static, Syscall, Extensions>; + +/// Set while the request being served is authenticatorReset. +static RESET: AtomicBool = AtomicBool::new(false); + +/// User presence is the vault's own gesture on the same button and light: a fresh tap +/// while the light is amber, through `vaultkey_core::ui`, so a button already held when +/// the request arrives does not count. Erasing every passkey takes the wipe's hold +/// instead, because a tap never wipes. +#[derive(Clone, Copy)] +struct Touch { + panel: Panel, + usb: &'static RefCell, +} + +impl UserPresence for Touch { + fn user_present( + self, + _: &mut T, + timeout_ms: u32, + ) -> fido_authenticator::Result<()> { + let mut panel = self.panel; + let timeout_ms = u64::from(timeout_ms); + self.usb.borrow_mut().awaiting_touch = true; + let confirmed = if RESET.load(Ordering::Relaxed) { + ui::await_hold(&mut panel, &Uptime, timeout_ms, RESET_HOLD_MS) + } else { + ui::await_confirmation(&mut panel, &Uptime, timeout_ms) + }; + self.usb.borrow_mut().awaiting_touch = false; + if confirmed { + Ok(()) + } else { + Err(fido_authenticator::Error::UserActionTimeout) + } + } +} + +/// fido-authenticator as the CTAPHID dispatch sees it: CTAP2 only. U2F's MSG is not +/// taken - it polls for presence every 250 ms, which a tap that must start after the +/// request cannot answer - so the dispatch refuses it as an unknown command. +pub(crate) struct Passkeys(Authenticator); + +impl App<'static> for Passkeys { + fn commands(&self) -> &'static [Command] { + &[Command::Cbor] + } + + fn call( + &mut self, + command: Command, + request: &[u8], + response: &mut BytesView, + ) -> Result<(), app::Error> { + RESET.store( + request.first() == Some(&AUTHENTICATOR_RESET), + Ordering::Relaxed, + ); + App::call(&mut self.0, command, request, response) + } +} + +static PASSKEYS: StaticCell = StaticCell::new(); + +/// Mounts Trussed's filesystems and builds the authenticator over them. A filesystem +/// that does not mount is formatted: the region held the factory's stale staging bytes +/// before the first boot, and a damaged one has nothing left to save. One that will not +/// mount even then is broken flash, and the key resets rather than run half-built. +/// +/// Never inlined: what it builds on the way would otherwise stay in `main`'s frame, and +/// so on the stack, for as long as the key runs. +#[inline(never)] +pub(crate) fn start( + region: Region, + rng: Entropy, + panel: Panel, + usb: &'static RefCell, +) -> &'static mut Passkeys { + let internal = Filesystem::mount_or_else( + INTERNAL_ALLOC.init(Allocation::new()), + INTERNAL.init(Internal(region)), + |_, storage, _| Filesystem::format(storage), + ) + .expect("Trussed's flash mounts once formatted"); + let volatile = Filesystem::mount_or_else( + VOLATILE_ALLOC.init(Allocation::new()), + VOLATILE.take(), + |_, storage, _| Filesystem::format(storage), + ) + .expect("RAM mounts once formatted"); + let board = Board { + rng, + store: Store { + internal: INTERNAL_FS.init(internal), + volatile: VOLATILE_FS.init(volatile), + }, + ui: Clockwork, + }; + + let (requester, responder) = TRUSSED + .split() + .expect("the Trussed channel is split once, here"); + let runner = RUNNER.init(RefCell::new(Runner { + service: Service::with_dispatch(board, Extensions::default()), + endpoint: ServiceEndpoint::new( + responder, + CoreContext::new(path!("fido").into()), + &BACKENDS, + ), + })); + let client = Client::new(requester, Syscall(runner), None); + let config = Config { + max_msg_size: CTAP_MESSAGE, + skip_up_timeout: None, + max_resident_credential_count: None, + large_blobs: None, + nfc_transport: false, + }; + PASSKEYS.init(Passkeys(Authenticator::new( + client, + Touch { panel, usb }, + config, + ))) +} diff --git a/firmware/boards/nrf52840-mdk-dongle/src/main.rs b/firmware/boards/nrf52840-mdk-dongle/src/main.rs index 638effb..5569586 100644 --- a/firmware/boards/nrf52840-mdk-dongle/src/main.rs +++ b/firmware/boards/nrf52840-mdk-dongle/src/main.rs @@ -9,6 +9,8 @@ #![no_std] #![no_main] +mod fido; + use core::cell::{Cell, RefCell}; use core::fmt::Write; use core::sync::atomic::{AtomicBool, Ordering, compiler_fence}; @@ -17,7 +19,8 @@ use cortex_m::peripheral::SCB; use cortex_m::peripheral::syst::SystClkSource; use cortex_m_rt::{entry, exception}; use critical_section::Mutex; -use ctaphid_dispatch::{Channel, DEFAULT_MESSAGE_SIZE as CTAP_MESSAGE, Dispatch}; +use ctaphid_dispatch::app::App; +use ctaphid_dispatch::{Channel, Dispatch}; use embedded_hal::digital::{InputPin, OutputPin}; use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; use nrf52840_hal::clocks::{Clocks, ExternalOscillator, Internal, LfOscStopped}; @@ -37,7 +40,7 @@ use vaultkey_core::hal::{Clock, DeviceKey, Port, Ui}; use vaultkey_core::proto::Proto; use vaultkey_core::store::{self, Layout, Store}; use vaultkey_core::ui::State; -use vaultkey_core::vault::{Block, Cost, KDF_BLOCKS}; +use vaultkey_core::vault::Cost; /// The first line of INFO; the version number lives in the core crate. const VERSION: &str = vaultkey_core::version!("nrf52840-mdk-dongle"); @@ -70,6 +73,10 @@ const USB_PID: u16 = 0x0001; const VAULT_BASE: u32 = 0x9_7000; const VAULT_LEN: u32 = 0x4_1000; +/// Trussed's filesystem, the passkeys, right after the vault: 0xD8000..0xEC000, twenty +/// sectors, below the bootloader at 0xF4000 and out of its reach like the vault. +const FS_LEN: u32 = 0x1_4000; + /// One attempt sector and two copies of 128 KiB: the sizes decided in /// docs2/makerdiary.md, smaller than the C6's because this chip has 1 MiB in all. const LAYOUT: Layout = Layout { @@ -93,18 +100,19 @@ const CYCLES_PER_MS: u32 = 64_000; const KDF_COST: Cost = Cost::from_wire(128, 20).expect("128 KiB and 20 passes is a cost Argon2 runs"); -/// Argon2 working memory, in RAM for the life of the program: the key derivation has -/// no allocator, and 128 KiB does not belong on the stack. -static KDF_MEM: ConstStaticCell<[Block; KDF_BLOCKS]> = - ConstStaticCell::new([Block::new(); KDF_BLOCKS]); - -/// Where every item sits in the image, ~10 KiB: same reason, same place. +/// Where every item sits in the image, ~10 KiB, in RAM for the life of the program: +/// the firmware has no allocator. Argon2's 128 KiB is not here: the core takes it on +/// the stack for each derivation, and passkeys use the same RAM between them. static VAULT: StaticCell = StaticCell::new(); /// Two item-sized halves, 16 KiB: one to open or build an item in, one for the items /// carried across while the image is rewritten. static BUF: ConstStaticCell<[u8; device::BUF_LEN]> = ConstStaticCell::new([0; device::BUF_LEN]); +/// The chip's RNG and its flash controller, each shared by the vault and Trussed. +static ENTROPY: StaticCell> = StaticCell::new(); +static FLASH: StaticCell> = StaticCell::new(); + /// The clock tree outlives everything: USB holds a reference to it. static CLOCKS: StaticCell> = StaticCell::new(); @@ -146,25 +154,47 @@ struct UsbStack { dev: UsbDevice<'static, Bus>, serial: SerialPort<'static, Bus>, ctaphid: CtapHid<'static, 'static, 'static, Bus, CTAP_MESSAGE>, + /// True while a passkey waits for its tap (`fido::Touch`). + awaiting_touch: bool, + /// When the last keepalive went out. + keepalive_ms: u64, } impl UsbStack { + /// CTAP2's keepalive interval: the host gives up on a request it hears nothing about. + const KEEPALIVE_MS: u64 = 100; + fn poll(&mut self) { + // usb-device polls the classes only when the bus has an event, and an answer the + // FIDO side has just finished is not one: it has to be picked up here. + self.ctaphid.check_for_app_response(); self.dev.poll(&mut [&mut self.serial, &mut self.ctaphid]); + let now = Uptime.now_ms(); // The pipe times out a request whose packets stop arriving; it compares wrapping // millisecond stamps, so the low half of the uptime is all it needs. #[expect( clippy::cast_possible_truncation, reason = "a wrapping stamp, on purpose" )] - self.ctaphid.check_timeout(Uptime.now_ms() as u32); + self.ctaphid.check_timeout(now as u32); + // A CTAP request the FIDO side holds - waiting for a tap, or for its turn behind a + // vkey request - is announced as such. With none pending the pipe sends nothing. + if now - self.keepalive_ms >= Self::KEEPALIVE_MS { + self.keepalive_ms = now; + self.ctaphid.send_keepalive(self.awaiting_touch); + } } } static USB_STACK: StaticCell> = StaticCell::new(); +/// The largest CTAP message either way, announced in getInfo. CTAPHID could carry 7609 +/// bytes, but every buffer of this size sits once in RAM and again on the stack, which +/// passkeys need more; CTAP2 asks for 1024, and no request here comes near 3072. +const CTAP_MESSAGE: usize = 3072; + /// CTAPHID requests on their way to the FIDO side, and its answers back: one message each -/// way, up to the 7609 bytes CTAPHID can carry. +/// way. static CTAP_CHANNEL: Channel = Channel::new(); /// The protocol's side of the stack, and FIDO's: requests that come through CTAPHID are @@ -172,6 +202,7 @@ static CTAP_CHANNEL: Channel = Channel::new(); struct Usb { stack: &'static RefCell, fido: Dispatch<'static, 'static, CTAP_MESSAGE>, + passkeys: &'static mut fido::Passkeys, /// When vkey's last byte arrived. last_rx: u64, } @@ -197,9 +228,9 @@ impl Port for Usb { if byte.is_some() { self.last_rx = now; } else if now - self.last_rx > Self::QUIET_MS { - // No FIDO application yet: the pipe answers INIT and PING itself, and - // anything that reaches the dispatch is refused as an unknown command. - self.fido.poll(&mut []); + // Outside the stack's borrow: a passkey's tap wait polls the bus itself. + let passkeys: &mut dyn App<'static> = &mut *self.passkeys; + self.fido.poll(&mut [passkeys]); } byte } @@ -239,25 +270,26 @@ impl Port for Usb { } } -/// The vault region as the slice the flash driver wants. Taken once: two slices over -/// the same flash would be two owners of it. +/// The flash the firmware keeps data in - the vault, then Trussed's filesystem - as the +/// slice the flash driver wants. Taken once: two slices over the same flash would be +/// two owners of it. #[expect( unsafe_code, reason = "the flash driver takes its region as a &'static mut slice, and memory-mapped flash cannot be named in safe code" )] -fn vault_region() -> &'static mut [u8] { +fn data_region() -> &'static mut [u8] { static TAKEN: AtomicBool = AtomicBool::new(false); assert!( !TAKEN.swap(true, Ordering::Relaxed), - "the vault region is taken once" + "the data region is taken once" ); let base = core::ptr::with_exposed_provenance_mut::(VAULT_BASE as usize); - // SAFETY: 0x97000..0xD8000 is flash outside the image - memory.x ends FLASH at - // 0x96000 - so nothing the compiler knows of lives there; it is page-aligned, as - // the driver asserts; and the flag above makes this the only reference to it. The - // flash controller rewrites these bytes on erase, which is why every access goes - // through `Flash` and its fences. - unsafe { core::slice::from_raw_parts_mut(base, VAULT_LEN as usize) } + // SAFETY: 0x97000..0xEC000 is flash outside the image - memory.x ends FLASH at + // 0x96000, and the bootloader starts at 0xF4000 - so nothing the compiler knows of + // lives there; it is page-aligned, as the driver asserts; and the flag above makes + // this the only reference to it. The flash controller rewrites these bytes on + // erase, which is why every access goes through `Flash` and its fences. + unsafe { core::slice::from_raw_parts_mut(base, (VAULT_LEN + FS_LEN) as usize) } } /// The flash controller over the vault region, with a compiler fence after every @@ -300,6 +332,106 @@ impl NorFlash for Flash { } } +/// One part of the data region - the vault's or Trussed's - over the one flash +/// controller. Each sees its own bytes from offset 0, and an access past its end is +/// refused, so neither can reach into the other. +struct Region { + flash: &'static RefCell, + base: u32, + len: u32, +} + +impl Region { + /// Where `len` bytes at `offset` sit in the data region, if they fit in this part. + fn at(&self, offset: u32, len: u32) -> Result { + match offset.checked_add(len) { + Some(end) if end <= self.len => Ok(self.base + offset), + _ => Err(NvmcError::OutOfBounds), + } + } +} + +/// A buffer's length as flash counts it; nothing here is anywhere near 4 GiB. +fn flash_len(bytes: &[u8]) -> Result { + u32::try_from(bytes.len()).map_err(|_| NvmcError::OutOfBounds) +} + +impl ErrorType for Region { + type Error = NvmcError; +} + +impl ReadNorFlash for Region { + const READ_SIZE: usize = Flash::READ_SIZE; + + fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), NvmcError> { + let at = self.at(offset, flash_len(bytes)?)?; + self.flash.borrow_mut().read(at, bytes) + } + + fn capacity(&self) -> usize { + self.len as usize + } +} + +impl NorFlash for Region { + const WRITE_SIZE: usize = Flash::WRITE_SIZE; + const ERASE_SIZE: usize = Flash::ERASE_SIZE; + + fn erase(&mut self, from: u32, to: u32) -> Result<(), NvmcError> { + let len = to.checked_sub(from).ok_or(NvmcError::OutOfBounds)?; + let at = self.at(from, len)?; + self.flash.borrow_mut().erase(at, at + len) + } + + fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), NvmcError> { + let at = self.at(offset, flash_len(bytes)?)?; + self.flash.borrow_mut().write(at, bytes) + } +} + +/// The chip's RNG, for the vault and for Trussed alike: two handles on one peripheral, +/// each borrowing it only for a draw. The core speaks `rand_core` 0.9, as the HAL does; +/// Trussed speaks 0.6. +#[derive(Clone, Copy)] +struct Entropy(&'static RefCell); + +impl rand_core::RngCore for Entropy { + fn next_u32(&mut self) -> u32 { + self.0.borrow_mut().random_u32() + } + + fn next_u64(&mut self) -> u64 { + self.0.borrow_mut().random_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.borrow_mut().random(dest); + } +} + +impl rand_core::CryptoRng for Entropy {} + +impl rand_core_06::RngCore for Entropy { + fn next_u32(&mut self) -> u32 { + self.0.borrow_mut().random_u32() + } + + fn next_u64(&mut self) -> u64 { + self.0.borrow_mut().random_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.borrow_mut().random(dest); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { + self.0.borrow_mut().random(dest); + Ok(()) + } +} + +impl rand_core_06::CryptoRng for Entropy {} + /// No chip key yet. This chip has no eFuse key, and its replacement - a secret in a /// flash page locked by the ACL until reset - is not built (docs2/makerdiary.md). The /// vault is protected by the PIN alone, and `vkey info` says so. @@ -320,9 +452,8 @@ impl DeviceKey for NoChipKey { /// all active low, from the Makerdiary wiki. Confirmed on the board: P0.18 is a plain /// input, not the chip's reset, and the tap (amber) and the double tap (blue) worked /// under `vkey check`. Red alone, the 5 s hold, has not been watched yet. -struct Panel { - // embedded-hal reads a pin through `&mut`, and `Ui::pressed` takes `&self`. - button: RefCell>>, +struct Controls { + button: Pin>, /// Served on every look at the button: a tap wait lasts seconds, and a host whose /// requests go unanswered that long resets the device. usb: &'static RefCell, @@ -331,30 +462,40 @@ struct Panel { blue: Pin>, } +static CONTROLS: StaticCell> = StaticCell::new(); + +/// The button and the light, for the vault and for passkeys alike: they take turns, as +/// a passkey is only served while the vault waits for its next request. +#[derive(Clone, Copy)] +struct Panel(&'static RefCell); + impl Ui for Panel { fn set(&mut self, state: State) { // Three plain LEDs and no PWM: amber is red and green together. let (r, g, b) = match state { State::Idle => (false, false, false), - State::Waiting => (true, true, false), // amber: a tap approves a code or a password + // amber: a tap approves a code, a password or a passkey + State::Waiting => (true, true, false), State::Export => (false, false, true), // blue: two taps let a backup out State::Ok => (false, true, false), // Red both ways, told apart by how long it stays: held while a wipe counts // down, a blink when nothing was confirmed. State::Danger | State::Refused => (true, false, false), }; - light(&mut self.red, r); - light(&mut self.green, g); - light(&mut self.blue, b); + let mut c = self.0.borrow_mut(); + light(&mut c.red, r); + light(&mut c.green, g); + light(&mut c.blue, b); } fn pressed(&self) -> bool { + let mut c = self.0.borrow_mut(); // The protocol never holds the stack while the key waits for the button; if it // ever did, this poll is skipped rather than borrowed twice. - if let Ok(mut usb) = self.usb.try_borrow_mut() { + if let Ok(mut usb) = c.usb.try_borrow_mut() { usb.poll(); } - let Ok(low) = self.button.borrow_mut().is_low(); + let Ok(low) = c.button.is_low(); low } } @@ -478,7 +619,8 @@ fn main() -> ! { let (requester, responder) = CTAP_CHANNEL .split() .expect("the CTAPHID channel is split once, here"); - let ctaphid = CtapHid::new(bus, requester, 0); + // CBOR announced in INIT, or hosts never send CTAP2. + let ctaphid = CtapHid::new(bus, requester, 0).implements_ctap2(); let usb = UsbDeviceBuilder::new(bus, UsbVidPid(USB_VID, USB_PID)) .strings(&[StringDescriptors::default() .manufacturer("vaulttecdev") @@ -494,26 +636,40 @@ fn main() -> ! { dev: usb, serial, ctaphid, + awaiting_touch: false, + keepalive_ms: 0, })); let port0 = p0::Parts::new(p.P0); - let mut panel = Panel { - button: RefCell::new(port0.p0_18.into_pullup_input().degrade()), + let mut panel = Panel(CONTROLS.init(RefCell::new(Controls { + button: port0.p0_18.into_pullup_input().degrade(), usb, red: port0.p0_23.into_push_pull_output(Level::High).degrade(), green: port0.p0_22.into_push_pull_output(Level::High).degrade(), blue: port0.p0_24.into_push_pull_output(Level::High).degrade(), - }; + }))); panel.set(State::Idle); - let store = Store::new(Flash(Nvmc::new(p.NVMC, vault_region())), LAYOUT); + let rng = Entropy(ENTROPY.init(RefCell::new(Rng::new(p.RNG)))); + let flash: &'static RefCell = + FLASH.init(RefCell::new(Flash(Nvmc::new(p.NVMC, data_region())))); + let vault = Region { + flash, + base: 0, + len: VAULT_LEN, + }; + let passkeys = Region { + flash, + base: VAULT_LEN, + len: FS_LEN, + }; + let mut dev = Device::new( - store, + Store::new(vault, LAYOUT), panel, - Rng::new(p.RNG), + rng, Uptime, NoChipKey, - KDF_MEM.take(), KDF_COST, VAULT.init_with(store::Index::empty), BUF.take(), @@ -522,6 +678,7 @@ fn main() -> ! { let port = Usb { stack: usb, fido: Dispatch::new(responder), + passkeys: fido::start(passkeys, rng, panel, usb), last_rx: 0, }; let mut proto = Proto::new(port, Uptime, info.as_str()); diff --git a/firmware/core/src/device.rs b/firmware/core/src/device.rs index d111ca9..29f8e5a 100644 --- a/firmware/core/src/device.rs +++ b/firmware/core/src/device.rs @@ -17,7 +17,7 @@ use crate::oath::{self, AUTH_SECRET_LEN, NAME_MAX, Name, Params, len_u8}; use crate::store::{Header, ITEM_BUF_LEN, Index, MAX_ATTEMPTS, Slot, Store, StoredName}; use crate::ui; use crate::vault::{ - self, BACKUP_AAD, Block, Cost, KEY_LEN, Keys, NONCE_LEN, Passphrase, Pin, SALT_LEN, + self, BACKUP_AAD, Block, Cost, KDF_BLOCKS, KEY_LEN, Keys, NONCE_LEN, Passphrase, Pin, SALT_LEN, }; use crate::wire::{ AUTH_CHALLENGE_LEN, AUTH_SIGNATURE_LEN, AUTH_SIGNED_PREFIX, BackupHead, Fail, HAS_OPEN, @@ -43,6 +43,21 @@ pub const BUF_LEN: usize = 2 * ITEM_BUF_LEN; /// A resident copy of the data key that scrubs itself when dropped. type Dek = Zeroizing<[u8; KEY_LEN]>; +/// Argon2's working memory, 128 KiB on the stack for one derivation: it exists only +/// while `f` runs, and `vault` scrubs it before handing the key back. Never inlined, so +/// the frame that holds it is gone before the key waits for its next request. A board +/// can then run other deep work in that same RAM between derivations - the nRF52840's +/// passkeys - where a static would hold it for the life of the program. +#[inline(never)] +#[expect( + clippy::large_stack_arrays, + reason = "on the stack on purpose: there is no heap, and a static would hold the 128 KiB for good" +)] +fn with_kdf_memory(f: impl FnOnce(&mut [Block]) -> T) -> T { + let mut mem = [Block::new(); KDF_BLOCKS]; + f(&mut mem) +} + /// Which classes a request may have. The device never returns a field outside it, and /// the gesture is decided by the highest class in it. #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -88,8 +103,6 @@ pub struct Device<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: D rng: R, clock: C, key: K, - /// The Argon2 working memory, owned by the board for the life of the program. - mem: &'m mut [Block], /// What a new vault and a new backup are derived at: the board's measure of about a /// second. An existing vault opens at the cost its header records. cost: Cost, @@ -134,15 +147,10 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> rng: R, clock: C, key: K, - mem: &'m mut [Block], cost: Cost, index: &'m mut Index, buf: &'m mut [u8; BUF_LEN], ) -> Self { - assert!( - mem.len() >= cost.m_kib as usize, - "the Argon2 memory holds the board's own cost" - ); let now = clock.now_ms(); Device { store, @@ -150,7 +158,6 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> rng, clock, key, - mem, cost, index, buf, @@ -230,7 +237,8 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> } fn derive(&mut self, pin: Pin<'_>, salt: &[u8; SALT_LEN], cost: Cost) -> Result { - vault::derive(pin, salt, cost, &mut self.key, self.mem).ok_or(Fail::Internal) + let key = &mut self.key; + with_kdf_memory(|mem| vault::derive(pin, salt, cost, key, mem)).ok_or(Fail::Internal) } /// A header for `pin`, and the resident key switched to match. The caller writes it; @@ -798,7 +806,8 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> let mut salt = [0u8; SALT_LEN]; self.rng.fill_bytes(&mut salt); let cost = self.cost; - let key = vault::backup_key(pass, &salt, cost, self.mem).ok_or(Fail::Internal)?; + let key = with_kdf_memory(|mem| vault::backup_key(pass, &salt, cost, mem)) + .ok_or(Fail::Internal)?; self.backup = Some(Session::Export { key, slot: 0, @@ -887,7 +896,8 @@ impl<'m, F: NorFlash, R: RngCore + CryptoRng, U: Ui, C: Clock, K: DeviceKey> pub fn import_begin(&mut self, pass: Passphrase<'_>, head: BackupHead) -> Result<(), Fail> { self.dek()?; self.load()?; - let key = vault::backup_key(pass, &head.salt, head.cost, self.mem).ok_or(Fail::Internal)?; + let key = with_kdf_memory(|mem| vault::backup_key(pass, &head.salt, head.cost, mem)) + .ok_or(Fail::Internal)?; self.store .save_begin(self.index.header.as_ref()) .map_err(|_| Fail::Internal)?; diff --git a/firmware/core/src/vault.rs b/firmware/core/src/vault.rs index acfd461..7f366d8 100644 --- a/firmware/core/src/vault.rs +++ b/firmware/core/src/vault.rs @@ -43,7 +43,8 @@ pub const PIN_LEN: usize = 8; pub const PASS_MIN: usize = 12; pub const PASS_MAX: usize = 128; -/// How many 1 KiB blocks the board must hand over for the key derivation. +/// Argon2's working memory in 1 KiB blocks: what the device takes on the stack for one +/// derivation (`device::with_kdf_memory`). pub const KDF_BLOCKS: usize = 128; /// What the env key is sealed under in the image header: a random key of its own, /// wrapped by the dek, so a PIN change re-seals sixty bytes instead of every blob. @@ -91,7 +92,7 @@ impl Cost { const _: () = assert!( KDF_BLOCKS == Cost::MAX.m_kib as usize, - "the board's buffer must hold the largest cost this firmware accepts" + "the derivation's memory must hold the largest cost this firmware accepts" ); /// `PIN_LEN` ASCII digits, checked once at the edge. Anything else is not a PIN and diff --git a/firmware/core/tests/key.rs b/firmware/core/tests/key.rs index 6b4d7b0..cd4dc64 100644 --- a/firmware/core/tests/key.rs +++ b/firmware/core/tests/key.rs @@ -187,9 +187,7 @@ impl MemFlash { /// Power on with a finger on the button and, maybe, a chip key. fn key_with(&self, button: Button, clock: Ticker, key: K) -> Key { - // The Argon2 memory, the index and the buffer outlive the device, as on the - // board. - let mem = Box::leak(vec![Block::new(); KDF_BLOCKS].into_boxed_slice()); + // The index and the buffer outlive the device, as on the board. let index = Box::leak(Box::new(store::Index::empty())); let buf: Box<[u8; device::BUF_LEN]> = vec![0u8; device::BUF_LEN] .into_boxed_slice() @@ -202,7 +200,6 @@ impl MemFlash { Repeatable(7), clock, key, - mem, COST, index, buf, From d6350ca93ec2c4c0a5276924e274b331bd7babde Mon Sep 17 00:00:00 2001 From: VaultTec-Dev Date: Thu, 15 Oct 2026 16:25:47 +0300 Subject: [PATCH 17/33] Move vkey auth to pam_u2f and drop the Ed25519 login Milestone 4 of phase 6. vkey auth enable now makes a pam:// credential on the key's FIDO2 side, tries it with an assertion, and writes /etc/u2f_mappings and one pam_u2f line per PAM service. It speaks CTAP2 itself: pamu2fcfg 1.1.0 demands an attestation certificate this key does not have. The Ed25519 scheme sealed under the chip key is gone (restorable from 4bd49f3); its category and command numbers stay unused, and a restore leaves such an item out and names it. Two core fixes ride along. A request withdrawn while it waits for the button ends refused and never counts as a press or a hold, which lets a CTAPHID_CANCEL end a passkey's touch wait. A release now needs the button up past the debounce, so a bounce mid-press is not two taps. Accepted on the board: sudo and the lock screen by tap, the password without the key, CANCEL answered in 0.2 s, check --wipe-everything with a restore, a 1Password sync and selftest. --- CLAUDE.md | 24 +- README.md | 44 +- cli/Cargo.lock | 97 +--- cli/Cargo.toml | 3 - cli/src/auth.rs | 416 +++++++-------- cli/src/backup.rs | 256 +++++---- cli/src/check.rs | 62 +-- cli/src/device.rs | 17 +- cli/src/fido.rs | 503 ++++++++++++++++++ cli/src/item.rs | 13 +- cli/src/main.rs | 41 +- cli/src/op.rs | 8 +- cli/src/shell.rs | 29 +- cli/src/sources.rs | 11 +- docs/threat-model.md | 85 ++- docs2/makerdiary.md | 14 +- docs2/roadmap.md | 15 + firmware/Cargo.lock | 48 +- .../boards/esp32c6-zero/images/vaultkey.bin | Bin 264128 -> 186288 bytes .../boards/nrf52840-mdk-dongle/Cargo.toml | 2 + .../nrf52840-mdk-dongle/images/vaultkey.bin | Bin 267748 -> 267620 bytes .../images/vaultkey.signed.uf2 | Bin 536064 -> 536064 bytes .../boards/nrf52840-mdk-dongle/src/fido.rs | 38 +- .../boards/nrf52840-mdk-dongle/src/main.rs | 10 +- firmware/core/Cargo.toml | 4 - firmware/core/src/device.rs | 125 +---- firmware/core/src/hal.rs | 6 + firmware/core/src/item.rs | 6 +- firmware/core/src/oath.rs | 3 - firmware/core/src/proto.rs | 19 +- firmware/core/src/ui.rs | 30 +- firmware/core/src/vault.rs | 17 - firmware/core/src/wire.rs | 18 +- firmware/core/tests/key.rs | 198 +++---- 34 files changed, 1188 insertions(+), 974 deletions(-) create mode 100644 cli/src/fido.rs diff --git a/CLAUDE.md b/CLAUDE.md index 24b5081..782fe49 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -171,8 +171,7 @@ The boards: ### Firmware design - Core crates: RustCrypto `aes-gcm`, `argon2`, `hmac`, `sha1`, `sha2`, `subtle`, - `zeroize`; `ed25519-dalek` (built on RustCrypto's `signature` and `sha2`) for `vkey - auth`; `crc`. Not own crypto. Toolchain: stable rustup, no compiler fork. + `zeroize`; `crc`. Not own crypto. Toolchain: stable rustup, no compiler fork. - nRF52840: `nrf52840-hal`, `cortex-m`, `cortex-m-rt` (`set-vtor`, `paint-stack`), `usb-device`, `usbd-serial`, `usbd-ctaphid`, `ctaphid-dispatch`, `static_cell`, `heapless`; for passkeys `trussed`, `trussed-staging`, `fido-authenticator`, @@ -219,17 +218,16 @@ The boards: because the device has nowhere else to keep them, and a code's shape is not a secret. The CLI turns an `otpauth://` URI into that on the way in and back into a URI on the way out (`totp::seed_field`, `totp::seed_uri`). -- The one exception is `Auth` (2026-09-14, maintainer's decision): a 32-byte Ed25519 seed - for `vkey auth` (`sudo` and the lock screen via `pam_exec`), sealed under - `DeviceKey::mac("vaultkey/auth-key/v1")` — the eFuse key alone, never the DEK — so - `Respond` signs `AUTH_SIGNED_PREFIX | challenge` after a tap while locked, spending no - attempt. Refused on an unbound chip. Which key an item is under is decided in one place, - `Device::item_key`; a PIN change carries `Auth` items across untouched. A login waits 10 s for the tap - (`AUTH_TOUCH_TIMEOUT_MS`), then PAM asks for the password. The host keeps only the public - key, `/etc/vkey/auth/`, and writes nothing at login. `sudo vkey auth enable` is the - one place the CLI writes system files: `/usr/local/bin/vkey`, the public key, and one - `sufficient` line in the PAM services of `SERVICES` (`cli/src/auth.rs`), each original - kept as `*.before-vkey`; `disable` undoes it. +- Every item is sealed under the DEK. `vkey auth` (`sudo` and the lock screen with a tap) + is `pam_u2f` over the nRF52840's FIDO2 since 2026-10-15: `sudo vkey auth enable` makes + a `pam://` credential and tries it, two taps, over its own CTAP2 + (`cli/src/fido.rs`, because `pamu2fcfg` 1.1.0 refuses a self-attesting key), writes its + public half to + `/etc/u2f_mappings` (root's) and one `sufficient` line in the PAM services of + `SERVICES` (`cli/src/auth.rs`), each original kept as `*.before-vkey`; `disable` undoes + it. That is the one place the CLI writes system files. The Ed25519 scheme before it + (category 201 sealed under the chip key, command `Respond` 0x19) is gone, restorable + from 4bd49f3; both numbers stay unused, and a restore leaves such an item in the file. - A TOTP seed leaves the device two ways. The backup (`ExportBegin`/`ExportNext`, after a double tap; 2026-09-09) reseals every item under a key derived from a passphrase (Argon2id, `Passphrase` 12–128 bytes, without the chip key, so the file opens on another diff --git a/README.md b/README.md index 4b3f474..ef8f39c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ single-binary host CLI, and a press of the board's button for every secret that > and keep the recovery codes your services give you. > **Two boards** (2026-10-13). Development now targets the Makerdiary nRF52840 MDK USB Dongle -> (`firmware/boards/nrf52840-mdk-dongle`), the board passkeys will come to. It runs the same +> (`firmware/boards/nrf52840-mdk-dongle`), which also holds passkeys (FIDO2, since +> 2026-10-15) and answers `sudo` through them. It runs the same > core and passes the full lifecycle test. Its bootloader is now our own fork, which runs > only signed firmware and serves no flash back, and APPROTECT closes its debug port. This > revision-2 chip can still be glitched open, though, and it has no chip key @@ -55,17 +56,17 @@ the device under routine use — only an explicit export under a double tap read - A TOTP secret leaves the key in the clear only under an explicit double tap (`vkey export `). Routine use returns only codes. `vkey backup` reseals every item under a backup passphrase without revealing secrets. -- Everything, `list` included, needs the PIN — except a `vkey auth` login, a tap alone; the key - re-locks after two idle minutes. Secrets and +- Everything, `list` included, needs the PIN — except a passkey or a `vkey auth` login on the + nRF52840, a tap alone; the key re-locks after two idle minutes. Secrets and PINs are never arguments or environment variables — hidden prompt or stdin. ## What it does not do Read [docs/threat-model.md](docs/threat-model.md) **before** you depend on this. -- **Nothing against phishing.** A TOTP code works on a fake site just as on the real one; that is a - property of TOTP. WebAuthn resists it, and this hardware cannot: the C6's USB is a fixed - Serial/JTAG port with no HID. +- **Phishing, for TOTP and passwords.** A TOTP code works on a fake site just as on the real one; + that is a property of TOTP. The browser binds a passkey to its site, and only the nRF52840 + board has passkeys: the C6's USB is a fixed Serial/JTAG port with no HID. - **Nothing for the code or password you just received** — it crosses the host: terminal, optionally the clipboard. The clipboard is cleared after 30 s, but a clipboard manager has already kept its own copy, and the reveal stays in the terminal's scrollback until the window closes. Details in the @@ -136,29 +137,34 @@ touches what a CSV brought, and an entry under a name no source offers is left a ## sudo and the lock screen with a tap -With the key plugged in, `sudo` and the lock screen take a tap instead of your password; -without it, or with no tap for ten seconds, they ask for the password as always. The key -signs a fresh challenge with a secret that never leaves it; the host keeps only its public -key. It needs no PIN, so a stolen laptop with the key still in it opens with a tap — read -[the trade-off](docs/threat-model.md#vkey-auth--sudo-and-the-lock-screen-with-a-tap-no-pin) +With the nRF52840 key plugged in, `sudo` and the lock screen take a tap instead of your +password; without it they ask for the password as always, and with it but no tap, once the +key gives up after 30 s. This is `pam_u2f`, the scheme every FIDO2 key uses: the key makes +a credential for this host, the host keeps only its public half. It needs no PIN, so a +stolen laptop with the key still in it opens with a tap — read +[the trade-off](docs/threat-model.md#vkey-auth--sudo-and-the-lock-screen-with-a-tap-through-pam_u2f) first. ```bash -sudo vkey auth enable # PIN, then a tap: sudo and the lock screen are set up -sudo vkey auth disable # back to the password alone +sudo apt install libpam-u2f +sudo "$(command -v vkey)" auth enable # two taps: sudo and the lock screen are set up +sudo "$(command -v vkey)" auth disable # back to the password alone ``` -`enable` copies `vkey` to `/usr/local/bin`, and adds one line to the PAM files of `sudo` and -of the lock screens this host has — COSMIC, GNOME, KDE, sway, Hyprland — keeping each -original as `*.before-vkey`. A file it does not recognise it leaves alone and prints the -line to add by hand. +`enable` makes a credential on the key (a tap), tries it the way a login will (another +tap), writes it to `/etc/u2f_mappings` (root's), and adds +one line to the PAM files of `sudo` and of the lock screens this host has — COSMIC, GNOME, +KDE, sway, Hyprland — keeping each original as `*.before-vkey`. A file it does not +recognise it leaves alone and prints the line to add by hand. Keep a root shell open in +another terminal until `sudo` and the lock screen have both worked, with the tap and with +the password. ## Gestures and capacity | Gesture | LED | What it releases | |---|---|---| -| Tap | amber | one TOTP code, the secret fields of one item, one `.env`, or one `vkey auth` login | -| Hold 5 s | red | factory wipe: every secret and the PIN | +| Tap | amber | one TOTP code, the secret fields of one item, one `.env`, one passkey, or one `vkey auth` login | +| Hold 5 s | red | factory wipe: every secret and the PIN; on the nRF52840, erasing every passkey (within 10 s of plugging in) | | Double tap | blue | the encrypted backup file, or an export / seed readout | A tap never wipes and never exports, so a hostile host cannot swap a code request for a diff --git a/cli/Cargo.lock b/cli/Cargo.lock index 1cf6e47..19b09d5 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -26,7 +26,7 @@ checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" dependencies = [ "cipher", "cpubits", - "cpufeatures 0.3.1", + "cpufeatures", "zeroize", ] @@ -112,7 +112,7 @@ checksum = "134c52ddac6d63c576bef8168db10c83c49c26444ecbc68060fef078925a901c" dependencies = [ "base64ct", "blake2", - "cpufeatures 0.3.1", + "cpufeatures", "zeroize", ] @@ -321,15 +321,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - [[package]] name = "cpufeatures" version = "0.3.1" @@ -448,33 +439,6 @@ dependencies = [ "cmov", ] -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "curve25519-dalek-derive", - "digest 0.10.7", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "darling" version = "0.20.11" @@ -627,28 +591,6 @@ dependencies = [ "litrs", ] -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" -dependencies = [ - "curve25519-dalek", - "ed25519", - "sha2 0.10.9", - "subtle", - "zeroize", -] - [[package]] name = "embedded-storage" version = "0.3.1" @@ -711,7 +653,7 @@ dependencies = [ "regex", "serde", "serialport", - "sha2 0.11.0", + "sha2", "slip-codec", "strum 0.28.0", "thiserror", @@ -724,12 +666,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - [[package]] name = "flate2" version = "1.1.10" @@ -1245,7 +1181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd" dependencies = [ "cpubits", - "cpufeatures 0.3.1", + "cpufeatures", "universal-hash", "zeroize", ] @@ -1516,21 +1452,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" dependencies = [ "cfg-if", - "cpufeatures 0.3.1", + "cpufeatures", "digest 0.11.3", ] -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - [[package]] name = "sha2" version = "0.11.0" @@ -1538,7 +1463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", - "cpufeatures 0.3.1", + "cpufeatures", "digest 0.11.3", ] @@ -1573,12 +1498,6 @@ dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" - [[package]] name = "simd-adler32" version = "0.3.10" @@ -1859,7 +1778,6 @@ dependencies = [ "csv-core", "data-encoding", "dirs", - "ed25519-dalek", "espflash", "getrandom", "hmac", @@ -1882,12 +1800,11 @@ dependencies = [ "aes-gcm", "argon2", "crc", - "ed25519-dalek", "embedded-storage", "hmac", "rand_core", "sha1", - "sha2 0.11.0", + "sha2", "subtle", "zeroize", ] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index da44545..27f08d1 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -31,9 +31,6 @@ dirs = "6" hmac = "0.13" sha1 = "0.11" zeroize = "1" -# `vkey auth`: the key's signature checked against the public key kept at enrolment. -# The same crate the firmware signs with. -ed25519-dalek = { version = "2.2", default-features = false, features = ["zeroize"] } # Generated passwords: the OS random source, nothing seeded in userland. getrandom = "0.2" serde = { version = "1.0", features = ["derive"] } diff --git a/cli/src/auth.rs b/cli/src/auth.rs index 0f43c98..ed246dc 100644 --- a/cli/src/auth.rs +++ b/cli/src/auth.rs @@ -1,47 +1,45 @@ -//! `vkey auth`: `sudo` and the lock screen with a tap on the key, through `pam_exec`. +//! `vkey auth`: `sudo` and the lock screen with a tap on the key, through `pam_u2f`. //! //! ```text -//! sudo vkey auth enable once: a secret on the key, its public key here, PAM told -//! vkey auth what PAM runs at every login +//! sudo vkey auth enable once: a credential for this host's logins, PAM told //! sudo vkey auth disable all of it undone //! ``` //! -//! The scheme of `pam_u2f`. The key holds an Ed25519 seed that never leaves it; this -//! host keeps only the public key, in `/etc/vkey/auth/`, readable by anyone and -//! writable by root. A login sends a fresh random challenge, the key signs it after a -//! tap, and the signature is checked here. Nothing is written at login, so `sudo`, -//! which runs this as root, and a lock screen running as the user read the same file. -//! The key answers without its PIN - the seed is sealed under the chip key alone - so -//! the tap on this board is the whole proof. Anything that goes wrong is a refusal, and -//! PAM asks for the password as it always did. +//! The key is a FIDO2 authenticator (the nRF52840's passkeys), so a login is the scheme +//! every other key uses, `pam_u2f`'s (maintainer's decision, 2026-10-03). `enable` makes +//! a credential for `pam://` after a tap and tries it after another, as +//! `pamu2fcfg` would if the 1.1.0 that distributions ship accepted a key that attests +//! with the credential's own key (`crate::fido`). Its public half goes into +//! `/etc/u2f_mappings`, which is root's: nothing running as the user can enrol a key of +//! its own. One `sufficient` line in each PAM service then lets a tap in. With no key, +//! or no tap before the key gives up (30 s), PAM asks for the password as it always did. +//! It replaced, 2026-10-15, an Ed25519 scheme of vkey's own over `pam_exec`, which +//! needed a chip key the nRF52840 does not have (restorable from 4bd49f3). -use std::fs::{self, DirBuilder}; -use std::os::unix::fs::{DirBuilderExt, MetadataExt}; -use std::path::{Path, PathBuf}; +use std::fs; +use std::os::unix::fs::MetadataExt; +use std::path::Path; -use data_encoding::HEXLOWER; -use ed25519_dalek::{Signature, SigningKey, VerifyingKey}; -use zeroize::Zeroizing; +use data_encoding::BASE64; -use crate::device::{ - AUTH_CHALLENGE_LEN, AUTH_SECRET_LEN, AUTH_SIGNATURE_LEN, AUTH_SIGNED_PREFIX, Category, Class, - Device, Error, FieldKind, -}; -use crate::file; -use crate::item::{Item, OwnedField}; -use crate::prompt::with_unlock; +use crate::device::Error; +use crate::{fido, file}; -/// What an auth entry says when someone tries to use it like the others. -pub const USED_BY_AUTH: &str = "this entry answers `vkey auth` logins; it has nothing to show"; +/// Where distributions install the module - Debian's and Ubuntu's multiarch directories, +/// Fedora's and Arch's. Without it the line would lock nobody out, but let nobody in. +const PAM_U2F: [&str; 4] = [ + "/usr/lib/x86_64-linux-gnu/security/pam_u2f.so", + "/usr/lib/aarch64-linux-gnu/security/pam_u2f.so", + "/usr/lib64/security/pam_u2f.so", + "/usr/lib/security/pam_u2f.so", +]; -const KEY_DIR: &str = "/etc/vkey/auth"; -/// Where PAM finds the binary: root's copy, never the user's `~/.local/bin`. -const INSTALLED: &str = "/usr/local/bin/vkey"; -/// The one line `enable` adds. `sufficient`: a good signature lets the user in, anything -/// else falls through to the password. `seteuid`: under `sudo` the check runs as root, -/// out of reach of whatever runs as the user; for a lock screen that is the user -/// already, it changes nothing. -const PAM_LINE: &str = "auth sufficient pam_exec.so quiet stdout seteuid /usr/local/bin/vkey auth"; +/// Who may log in with which credential: `user:keyHandle,publicKey,type,options`, one +/// line per user. +const MAPPINGS: &str = "/etc/u2f_mappings"; +/// The one line `enable` adds. `sufficient`: a good assertion lets the user in, anything +/// else falls through to the password. `cue`: PAM says to tap the key. +const PAM_LINE: &str = "auth sufficient pam_u2f.so authfile=/etc/u2f_mappings cue"; /// The PAM services that get the line, when this host has them: `sudo`, and the lock /// screens of COSMIC, GNOME, KDE, sway and Hyprland. const SERVICES: [&str; 6] = [ @@ -54,118 +52,23 @@ const SERVICES: [&str; 6] = [ ]; /// A copy of each PAM file as it was before `enable` first touched it. const BEFORE: &str = ".before-vkey"; +/// What the scheme this replaced kept on the host: a public key per user. +const OLD_KEYS: &str = "/etc/vkey/auth"; +/// And the copy of vkey its PAM line ran, which nothing runs any more. +const OLD_BINARY: &str = "/usr/local/bin/vkey"; -/// A user's enrolment: the entry on the key, and its public key. -struct Enrolled { - name: String, - key: VerifyingKey, -} - -impl Enrolled { - fn path(user: &str) -> PathBuf { - Path::new(KEY_DIR).join(user) - } - - fn read(user: &str) -> Result { - let path = Self::path(user); - for p in path.ancestors() { - root_owned(p)?; - } - let text = fs::read_to_string(&path)?; - let bad = || Error::Value(format!("{} is malformed", path.display())); - let mut lines = text.lines(); - let (Some(name), Some(key), None) = (lines.next(), lines.next(), lines.next()) else { - return Err(bad()); - }; - let key: [u8; 32] = HEXLOWER - .decode(key.as_bytes()) - .ok() - .and_then(|k| k.try_into().ok()) - .ok_or_else(bad)?; - Ok(Enrolled { - name: name.to_string(), - key: VerifyingKey::from_bytes(&key).map_err(|_| bad())?, - }) - } - - fn write(&self, user: &str) -> Result<(), Error> { - DirBuilder::new() - .recursive(true) - .mode(0o755) - .create(KEY_DIR)?; - let text = format!("{}\n{}\n", self.name, HEXLOWER.encode(self.key.as_bytes())); - file::replace(&Self::path(user), text.as_bytes(), 0o644) - } -} - -/// What `pam_exec` runs for `PAM_USER`: exit 0 lets the user in. -pub fn verify(port: Option<&str>) -> Result { - let user = user_from("PAM_USER", "PAM_USER is not set: this runs from pam_exec")?; - trusted(&std::env::current_exe()?)?; - let enrolled = Enrolled::read(&user)?; - let mut dev = Device::open(port)?; - let challenge = random()?; - println!("vkey: tap the key, or wait ten seconds for the password"); - let signature = dev.respond(&enrolled.name, &challenge)?; - if !verifies(&enrolled.key, &challenge, &signature) { - return Err(Error::Value("the key's signature does not verify".into())); - } - Ok(0) -} - -/// Whether `signature` is the key's answer to `challenge`. -pub fn verifies( - key: &VerifyingKey, - challenge: &[u8; AUTH_CHALLENGE_LEN], - signature: &[u8; AUTH_SIGNATURE_LEN], -) -> bool { - let mut msg = AUTH_SIGNED_PREFIX.to_vec(); - msg.extend_from_slice(challenge); - key.verify_strict(&msg, &Signature::from_bytes(signature)) - .is_ok() -} - -/// `sudo vkey auth enable`: everything a tap-login needs, for the user who ran sudo. -pub fn enable(dev: &mut Device) -> Result { +/// `sudo vkey auth enable`: a credential on the key for the user who ran sudo, its +/// public half in the mapping, the line in PAM. +pub fn enable() -> Result { let user = sudo_user()?; - let name = format!("{user}@{}", hostname()?); - crate::device::name(&name)?; - // The login secret is sealed under the chip key alone. A board without one refuses - // it as `Incompatible`, which reads as "wipe it" - asked first, before anything on - // this host is written. - if !dev.pin_status()?.chip_bound { - return Err(Error::Value( - "this key has no chip key, so it cannot hold a login secret; nothing was enabled" - .into(), - )); - } - - install_self()?; - - // A fresh seed every time: its public key is kept here and the seed forgotten, so - // one already on the key under this name could not be matched to a public key. - let seed = Zeroizing::new(random()?); - let key = SigningKey::from_bytes(&seed).verifying_key(); - // One secret field, and the category is what makes the device seal it under the - // chip key rather than the PIN's. - let item = Item::new(Category::Auth).with(OwnedField::new( - Class::Secret, - FieldKind::Concealed, - "seed", - &*seed, - )); - with_unlock(dev, |d| d.put(&name, &item, true))?; - drop(seed); - - let challenge = random()?; - eprintln!("tap the key to check it..."); - let signature = dev.respond(&name, &challenge)?; - if !verifies(&key, &challenge, &signature) { - return Err(Error::Value( - "the key's signature does not verify; nothing was enabled".into(), - )); - } - Enrolled { name, key }.write(&user)?; + let mapping = enrol(&user)?; + let existing = read_or_empty(Path::new(MAPPINGS))?; + file::replace( + Path::new(MAPPINGS), + with_mapping(&existing, &user, &mapping).as_bytes(), + 0o644, + )?; + forget_old(&user)?; let mut armed = Vec::new(); let mut manual = Vec::new(); @@ -189,34 +92,114 @@ pub fn enable(dev: &mut Device) -> Result { path.display() ); } - println!("without the key, or with no tap for ten seconds, the password works as before"); + println!( + "without the key the password works as before; with the key in and no tap, the\n\ + password prompt comes once the key gives up waiting, after 30 s" + ); Ok(0) } -/// `sudo vkey auth disable`: the line out of every PAM file, the public key off this host, -/// the secret off the key. -pub fn disable(dev: &mut Device) -> Result { +/// `sudo vkey auth disable`: the line out of every PAM file and the user out of the +/// mapping. The credential stays on the key, unused, until authenticatorReset. +pub fn disable() -> Result { let user = sudo_user()?; - let name = format!("{user}@{}", hostname()?); for service in SERVICES { let path = Path::new("/etc/pam.d").join(service); if path.exists() { remove_line(&path)?; } } - match fs::remove_file(Enrolled::path(&user)) { - Ok(()) => {} - Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} - Err(e) => return Err(e.into()), - } - match with_unlock(dev, |d| d.delete(&name)) { - Ok(()) | Err(Error::NotFound) => {} - Err(e) => return Err(e), + let path = Path::new(MAPPINGS); + if path.exists() { + let left = without_mapping(&read_or_empty(path)?, &user); + if left.is_empty() { + fs::remove_file(path)?; + } else { + file::replace(path, left.as_bytes(), 0o644)?; + } } - println!("disabled: {user} logs in with the password alone, and '{name}' is off the key"); + forget_old(&user)?; + println!("disabled: {user} logs in with the password alone"); Ok(0) } +/// A credential for `user` on the key, made and then tried with a login exactly as +/// `pam_u2f` will ask for it - a tap each - and its mapping line, in the shape +/// `pamu2fcfg` writes: `user:,,es256,+presence`. Nothing on +/// this host changes until both taps have answered. +fn enrol(user: &str) -> Result { + if !PAM_U2F.iter().any(|p| Path::new(p).exists()) { + return Err(Error::Value( + "pam_u2f is missing: sudo apt install libpam-u2f".into(), + )); + } + // What pam_u2f asserts with when no origin is given: pam:// and gethostname(). + let rp = format!("pam://{}", hostname()?); + let mut key = fido::Key::open()?; + eprintln!("tap the key when its light turns amber, to make the credential"); + let credential = key.make_credential(&rp, user)?; + eprintln!("and once more, to try it the way a login will"); + key.get_assertion(&rp, &credential.id)?; + Ok(format!( + "{user}:{},{},es256,+presence", + BASE64.encode(&credential.id), + BASE64.encode(&credential.public) + )) +} + +fn hostname() -> Result { + let name = fs::read_to_string("/proc/sys/kernel/hostname")?; + Ok(name.trim().to_string()) +} + +/// `existing` with `user`'s line replaced by `mapping`, every other user's kept. +fn with_mapping(existing: &str, user: &str, mapping: &str) -> String { + let mut out = without_mapping(existing, user); + out.push_str(mapping); + out.push('\n'); + out +} + +/// `existing` without `user`'s line. +fn without_mapping(existing: &str, user: &str) -> String { + let mine = format!("{user}:"); + let mut out = String::new(); + for line in existing.lines().filter(|l| !l.starts_with(&mine)) { + out.push_str(line); + out.push('\n'); + } + out +} + +/// What the scheme this replaced left for `user`: the public key goes, the directory +/// with it once empty. Its copy of vkey is pointed out rather than deleted - this run +/// cannot tell whether someone put a binary there for another reason. +fn forget_old(user: &str) -> Result<(), Error> { + let key = Path::new(OLD_KEYS).join(user); + if key.exists() { + fs::remove_file(&key)?; + for dir in [OLD_KEYS, "/etc/vkey"] { + // Only when empty: `remove_dir` refuses anything else, and that is fine. + fs::remove_dir(dir).ok(); + } + } + if Path::new(OLD_BINARY).exists() { + println!( + "{OLD_BINARY} was the old scheme's copy for PAM and nothing runs it now:\n \ + sudo rm {OLD_BINARY}" + ); + } + Ok(()) +} + +fn read_or_empty(path: &Path) -> Result { + match fs::read_to_string(path) { + Ok(text) => Ok(text), + Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(String::new()), + Err(e) => Err(e.into()), + } +} + /// Whether `line` is the one that brings in the password check: `vkey` goes right above /// it. Debian's `@include common-auth`, and the `include`/`substack` of Fedora and Arch. fn is_anchor(line: &str) -> bool { @@ -231,19 +214,16 @@ fn is_anchor(line: &str) -> bool { } } -/// A line `enable` put there, in this or an earlier form. +/// A line `enable` put there: this one, or the old scheme's `pam_exec` of `vkey auth`. fn is_ours(line: &str) -> bool { - line.contains("pam_exec.so") && line.contains("vkey auth") + line.trim() == PAM_LINE || (line.contains("pam_exec.so") && line.contains("vkey auth")) } -/// The line added above the anchor, replacing any earlier form of it; the file as it was -/// kept once beside it. False when there is no anchor, and then nothing is written. -fn add_line(path: &Path) -> Result { - let text = fs::read_to_string(path)?; +/// `text` with the line above the anchor, any earlier form of it gone. None when there +/// is no anchor. +fn with_line(text: &str) -> Option { let lines: Vec<&str> = text.lines().filter(|l| !is_ours(l)).collect(); - let Some(at) = lines.iter().position(|l| is_anchor(l)) else { - return Ok(false); - }; + let at = lines.iter().position(|l| is_anchor(l))?; let mut out = String::new(); for (i, line) in lines.iter().enumerate() { if i == at { @@ -253,6 +233,16 @@ fn add_line(path: &Path) -> Result { out.push_str(line); out.push('\n'); } + Some(out) +} + +/// The line added to the file at `path`, the file as it was kept once beside it. False +/// when there is no anchor, and then nothing is written. +fn add_line(path: &Path) -> Result { + let text = fs::read_to_string(path)?; + let Some(out) = with_line(&text) else { + return Ok(false); + }; if out != text { let mut before = path.as_os_str().to_owned(); before.push(BEFORE); @@ -277,29 +267,14 @@ fn remove_line(path: &Path) -> Result<(), Error> { file::replace(path, out.as_bytes(), 0o644) } -/// This binary copied to where PAM runs it, unless it already is that copy. -fn install_self() -> Result<(), Error> { - let me = std::env::current_exe()?; - if fs::canonicalize(&me)? == Path::new(INSTALLED) { - return Ok(()); - } - file::replace(Path::new(INSTALLED), &fs::read(&me)?, 0o755) -} - /// The user who ran sudo: the one whose logins the key will answer. fn sudo_user() -> Result { if fs::metadata("/proc/self")?.uid() != 0 { return Err(Error::Value("this changes PAM: run it with sudo".into())); } - user_from( - "SUDO_USER", - "run it through sudo as the user who logs in, not as root itself", - ) -} - -/// A login name out of the environment, safe as a file name: no path, no hidden file. -fn user_from(var: &str, missing: &str) -> Result { - let user = std::env::var(var).map_err(|_| Error::Value(missing.into()))?; + let user = std::env::var("SUDO_USER").map_err(|_| { + Error::Value("run it through sudo as the user who logs in, not as root itself".into()) + })?; let ok = !user.is_empty() && !user.starts_with('.') && user @@ -314,37 +289,52 @@ fn user_from(var: &str, missing: &str) -> Result { } } -fn hostname() -> Result { - Ok(fs::read_to_string("/proc/sys/kernel/hostname")? - .trim() - .to_string()) -} +#[cfg(test)] +mod tests { + use super::*; -/// A challenge, or a seed: one random draw of this size. -fn random() -> Result<[u8; AUTH_CHALLENGE_LEN], Error> { - const _: () = assert!(AUTH_SECRET_LEN == AUTH_CHALLENGE_LEN, "one draw fits both"); - let mut b = [0u8; AUTH_CHALLENGE_LEN]; - getrandom::getrandom(&mut b).map_err(|e| Error::Value(format!("no randomness: {e}")))?; - Ok(b) -} + const SUDO: &str = "#%PAM-1.0\n\ + session required pam_limits.so\n\ + auth sufficient pam_exec.so quiet stdout seteuid /usr/local/bin/vkey auth\n\ + @include common-auth\n\ + @include common-account\n"; -/// Owned by root and writable by nobody else. -fn root_owned(path: &Path) -> Result<(), Error> { - let m = fs::metadata(path)?; - if m.uid() != 0 || m.mode() & 0o022 != 0 { - return Err(Error::Value(format!( - "{} must belong to root and be writable by root alone", - path.display() - ))); + #[test] + fn the_line_replaces_the_old_scheme_above_the_password_check() { + let out = with_line(SUDO).expect("has an anchor"); + assert!(!out.contains("pam_exec.so"), "the old line is gone:\n{out}"); + assert!( + out.contains(&format!("{PAM_LINE}\n@include common-auth\n")), + "right above the password check:\n{out}" + ); + assert_eq!( + with_line(&out).as_deref(), + Some(out.as_str()), + "and twice is once" + ); } - Ok(()) -} -/// This binary and every directory above it root's alone: `sudo` runs it as root, and a -/// copy the user can replace would hand root to whatever runs as the user. -fn trusted(exe: &Path) -> Result<(), Error> { - for p in exe.ancestors() { - root_owned(p)?; + #[test] + fn a_file_without_the_password_check_is_left_alone() { + assert_eq!(with_line("auth required pam_unix.so\n"), None); + } + + #[test] + fn a_mapping_replaces_only_its_own_user() { + let existing = "alice:aaa,bbb,es256,+presence\nhifes:old,old,es256,+presence\n"; + let out = with_mapping(existing, "hifes", "hifes:new,new,es256,+presence"); + assert_eq!( + out, + "alice:aaa,bbb,es256,+presence\nhifes:new,new,es256,+presence\n" + ); + assert_eq!( + without_mapping(&out, "hifes"), + "alice:aaa,bbb,es256,+presence\n" + ); + assert_eq!( + without_mapping("hifesx:k,k\n", "hifes"), + "hifesx:k,k\n", + "a user whose name merely starts with another's is someone else" + ); } - Ok(()) } diff --git a/cli/src/backup.rs b/cli/src/backup.rs index 932e848..d08e2d8 100644 --- a/cli/src/backup.rs +++ b/cli/src/backup.rs @@ -1,7 +1,8 @@ //! A backup file: every entry and blob on the key, each sealed by the device itself //! under a key made from a passphrase, so the file opens on any key that is told the -//! passphrase - and on nothing else. This side never sees inside an item; it keeps -//! them in the order they came out, which is the order the device will take them. +//! passphrase - and on nothing else. Making one, this side never sees inside an item; +//! it keeps them in the order they came out, which is the order the device will take +//! them. Restoring, it has the passphrase, and opens them (`import`). //! //! ```text //! "VKB1" | salt(16) | m_kib u32le | t u32le | count u32le | (len u16le | item)* @@ -133,71 +134,72 @@ impl RngCore for BackupRng { impl CryptoRng for BackupRng {} -fn convert_legacy_item( - key: &[u8; vault::KEY_LEN], - item_idx: u32, - sealed: &[u8], -) -> Result>, Error> { +/// `vkey auth`'s category, and its kind in a backup older than items: the login secret +/// it served, removed 2026-10-15 (restorable from 4bd49f3). An older backup may still +/// hold one. Nothing here uses it any more and the device refuses its category, so a +/// restore leaves it in the file and says so. +const RETIRED_AUTH: u8 = 201; +const RETIRED_AUTH_KIND: [u8; 4] = [4, 0, 0, 0]; + +/// One backup item as this side reads it: what goes back on the key, as the plaintext +/// the device packed - `category | name_len | name | item` - or a retired item's name. +enum Incoming { + Keep(Zeroizing>), + Retired(String), +} + +/// Where item `item_idx` sits in the file, as its seal binds it. +fn item_aad(item_idx: u32) -> [u8; BACKUP_AAD.len() + 4] { let mut aad = [0u8; BACKUP_AAD.len() + 4]; aad[..BACKUP_AAD.len()].copy_from_slice(BACKUP_AAD); aad[BACKUP_AAD.len()..].copy_from_slice(&item_idx.to_le_bytes()); + aad +} +/// Item `item_idx` opened, and converted when it comes from a backup written before +/// items existed. None when it does not open or parse. +fn open_item(key: &[u8; vault::KEY_LEN], item_idx: u32, sealed: &[u8]) -> Option { let mut buf = Zeroizing::new(sealed.to_vec()); - let Some(n) = vault::open_in_place(key, &aad, &mut buf) else { - return Ok(None); - }; + let n = vault::open_in_place(key, &item_aad(item_idx), &mut buf)?; let plain = &buf[NONCE_LEN..NONCE_LEN + n]; - // Already v2? if let Some((&category, rest)) = plain.split_first() - && let Some((_, body)) = Name::take(rest) - && CoreItem::parse(body).is_some() - && Category::from_wire(category).is_some() + && let Some((name, body)) = Name::take(rest) { - return Ok(Some(sealed.to_vec())); + // Before the body is parsed: its own category byte is the retired one too, and + // the parser refuses a category it cannot name. No legacy kind is 201. + if category == RETIRED_AUTH { + return Some(retired(name)); + } + if CoreItem::parse(body).is_some() && Category::from_wire(category).is_some() { + return Some(Incoming::Keep(Zeroizing::new(plain.to_vec()))); + } } // Legacy format: Kind::WIRE_LEN (4) | name_len u8 | name | secret - let Some((kind_bytes, rest)) = plain.split_first_chunk::<4>() else { - return Ok(None); - }; - let Some((name, secret)) = Name::take(rest) else { - return Ok(None); - }; + let (kind_bytes, rest) = plain.split_first_chunk::<4>()?; + let (name, secret) = Name::take(rest)?; + if *kind_bytes == RETIRED_AUTH_KIND { + return Some(retired(name)); + } let item = match *kind_bytes { [1, algo, digits, period] => { - let Some(params) = Params::from_wire([algo, digits, period]) else { - return Ok(None); - }; - let Ok(sf) = crate::totp::seed_field(params, secret) else { - return Ok(None); - }; - Item::new(Category::Login).with(sf) + let params = Params::from_wire([algo, digits, period])?; + Item::new(Category::Login).with(crate::totp::seed_field(params, secret).ok()?) } [2, 0, 0, 0] => { - let Some((&login_len, rest)) = secret.split_first() else { - return Ok(None); - }; - let Some((login, rest)) = rest.split_at_checked(usize::from(login_len)) else { - return Ok(None); - }; - let Some((&pw_len, note)) = rest.split_first() else { - return Ok(None); - }; - let Some((password, note)) = note.split_at_checked(usize::from(pw_len)) else { - return Ok(None); - }; + let (&login_len, rest) = secret.split_first()?; + let (login, rest) = rest.split_at_checked(usize::from(login_len))?; + let (&pw_len, note) = rest.split_first()?; + let (password, note) = note.split_at_checked(usize::from(pw_len))?; let (Ok(login), Ok(password), Ok(note)) = ( std::str::from_utf8(login), std::str::from_utf8(password), std::str::from_utf8(note), ) else { - return Ok(None); - }; - let Ok(login_item) = crate::device::login_item(login, password, note) else { - return Ok(None); + return None; }; - login_item + crate::device::login_item(login, password, note).ok()? } [3, 0, 0, 0] => Item::new(Category::Env).with(OwnedField::new( Class::Secret, @@ -205,75 +207,94 @@ fn convert_legacy_item( ".env", secret, )), - [4, 0, 0, 0] => Item::new(Category::Auth).with(OwnedField::new( - Class::Secret, - FieldKind::Concealed, - "seed", - secret, - )), - _ => return Ok(None), + _ => return None, }; - let Ok(packed) = item.pack() else { - return Ok(None); - }; + let packed = item.pack().ok()?; let name_bytes = name.as_bytes(); - let Ok(name_len) = u8::try_from(name_bytes.len()) else { - return Ok(None); - }; + let name_len = u8::try_from(name_bytes.len()).ok()?; let mut new_plain = Zeroizing::new(Vec::with_capacity(2 + name_bytes.len() + packed.len())); new_plain.push(item.category.wire()); new_plain.push(name_len); new_plain.extend_from_slice(name_bytes); new_plain.extend_from_slice(&packed); + Some(Incoming::Keep(new_plain)) +} - let total = new_plain.len(); - let mut out_buf = vec![0u8; NONCE_LEN + total + TAG_LEN]; - out_buf[NONCE_LEN..NONCE_LEN + total].copy_from_slice(&new_plain); +fn retired(name: Name<'_>) -> Incoming { + Incoming::Retired(format!( + "{}: a `vkey auth` login secret, which vkey no longer has", + String::from_utf8_lossy(name.as_bytes()) + )) +} + +/// `plain` sealed as backup item `item_idx`, as the device would have sealed it. +fn seal_item(key: &[u8; vault::KEY_LEN], item_idx: u32, plain: &[u8]) -> Result, Error> { + let total = plain.len(); + let mut out = vec![0u8; NONCE_LEN + total + TAG_LEN]; + out[NONCE_LEN..NONCE_LEN + total].copy_from_slice(plain); let mut rng = BackupRng::new(); - let Some(sealed_len) = vault::seal_in_place(key, &mut rng, &aad, &mut out_buf, total) else { - return Ok(None); - }; + let sealed = vault::seal_in_place(key, &mut rng, &item_aad(item_idx), &mut out, total); if rng.failed { return Err(Error::Value("no randomness from OS".into())); } - out_buf.truncate(sealed_len); - Ok(Some(out_buf)) + out.truncate(sealed.ok_or(Error::BadArg)?); + Ok(out) } -/// Every item in `path` onto the device; how many there were. The items go back sealed, -/// and the device opens them - except for a backup written before items existed, which -/// this side converts first, because the device no longer speaks the old shape. +/// Every item in `path` onto the device; how many there were. This side holds the +/// passphrase too, so it opens each item on the way: an item from a backup written +/// before items existed is converted, because the device no longer speaks that shape, +/// and a retired one is left out. What remains is sealed again in its new position - +/// the position is in the seal, and an item left out moves every later one up. A file +/// that does not open here goes as it is, for the device to refuse. pub fn import(dev: &mut Device, path: &Path, pass: Passphrase<'_>) -> Result { let (head, items) = read(&source(path)?)?; let mut mem = vec![Block::new(); KDF_BLOCKS]; - let converted = match vault::backup_key(pass, &head.salt, head.cost, &mut mem) { - Some(k) => { - let mut res = Vec::with_capacity(items.len()); - for (i, item) in items.iter().enumerate() { - let idx = u32::try_from(i).unwrap_or(0); - let conv = convert_legacy_item(&k, idx, item)?.unwrap_or_else(|| item.clone()); - res.push(conv); - } - res - } - None => items, + let (items, skipped) = match vault::backup_key(pass, &head.salt, head.cost, &mut mem) { + Some(key) => prepare(&key, items)?, + None => (items, Vec::new()), }; dev.import_begin(pass, head)?; - for item in &converted { + for item in &items { dev.import_item(item)?; } dev.import_end()?; Ok(Restored { - count: converted.len(), - skipped: Vec::new(), + count: items.len(), + skipped, }) } +/// The items as the device takes them back, and the names of those left out. +fn prepare( + key: &[u8; vault::KEY_LEN], + items: Vec>, +) -> Result<(Vec>, Vec), Error> { + let opened = (0u32..) + .zip(&items) + .map(|(i, sealed)| open_item(key, i, sealed)) + .collect::>>(); + let Some(opened) = opened else { + return Ok((items, Vec::new())); + }; + let mut kept = Vec::with_capacity(opened.len()); + let mut skipped = Vec::new(); + for item in opened { + match item { + Incoming::Keep(plain) => { + let at = u32::try_from(kept.len()).map_err(|_| Error::BadArg)?; + kept.push(seal_item(key, at, &plain)?); + } + Incoming::Retired(name) => skipped.push(name), + } + } + Ok((kept, skipped)) +} + /// What a restore did: how many items are on the key, and what the file held that this -/// build could not store. Nothing is left behind by a backup this version wrote; the -/// field is what a caller prints when one is. +/// build could not store - a retired `vkey auth` secret from an older backup. pub struct Restored { pub count: usize, pub skipped: Vec, @@ -339,7 +360,7 @@ mod tests { vault::seal_in_place(&key, &mut rng, &aad, &mut sealed, total).expect("seals"); sealed.truncate(sealed_len); - let res = convert_legacy_item(&key, item_idx, &sealed).expect("no error"); + let res = open_item(&key, item_idx, &sealed); assert!(res.is_none(), "invalid UTF-8 in login must fail conversion"); // Invalid UTF-8 in note @@ -359,7 +380,7 @@ mod tests { vault::seal_in_place(&key, &mut rng, &aad, &mut sealed2, total2).expect("seals"); sealed2.truncate(sealed_len2); - let res2 = convert_legacy_item(&key, item_idx, &sealed2).expect("no error"); + let res2 = open_item(&key, item_idx, &sealed2); assert!(res2.is_none(), "invalid UTF-8 in note must fail conversion"); // Valid legacy login @@ -379,7 +400,64 @@ mod tests { vault::seal_in_place(&key, &mut rng, &aad, &mut sealed3, total3).expect("seals"); sealed3.truncate(sealed_len3); - let res3 = convert_legacy_item(&key, item_idx, &sealed3).expect("no error"); - assert!(res3.is_some(), "valid legacy login must convert"); + let res3 = open_item(&key, item_idx, &sealed3); + assert!( + matches!(res3, Some(Incoming::Keep(_))), + "valid legacy login must convert" + ); + } + + /// `category | name_len | name | item` for an item of `category` holding one field. + fn backup_plain(category: u8, name: &str, body_category: u8) -> Vec { + let mut plain = vec![category, u8::try_from(name.len()).expect("fits")]; + plain.extend_from_slice(name.as_bytes()); + // An item of no fields: `category | count`. + plain.extend_from_slice(&[body_category, 0]); + plain + } + + #[test] + fn a_retired_auth_item_is_left_out_and_the_rest_move_up() { + let key = [7u8; vault::KEY_LEN]; + let login = Category::Login.wire(); + let env = Category::Env.wire(); + let file = [ + backup_plain(login, "github", login), + backup_plain(RETIRED_AUTH, "hifes@pop-os", RETIRED_AUTH), + backup_plain(env, "app", env), + ]; + let sealed: Vec> = (0u32..) + .zip(&file) + .map(|(i, p)| seal_item(&key, i, p).expect("seals")) + .collect(); + + let (items, skipped) = prepare(&key, sealed).expect("prepares"); + assert_eq!(items.len(), 2, "the auth secret stays in the file"); + assert_eq!(skipped.len(), 1, "and is named: {skipped:?}"); + assert!(skipped[0].starts_with("hifes@pop-os:"), "{skipped:?}"); + for (i, (item, want)) in (0u32..).zip(items.iter().zip([&file[0], &file[2]])) { + let Some(Incoming::Keep(plain)) = open_item(&key, i, item) else { + panic!("item {i} opens at its new position"); + }; + assert_eq!( + plain.as_slice(), + want.as_slice(), + "item {i} unchanged inside" + ); + } + } + + #[test] + fn a_file_that_does_not_open_here_goes_as_it_is() { + let key = [7u8; vault::KEY_LEN]; + let login = Category::Login.wire(); + let sealed = + vec![seal_item(&key, 0, &backup_plain(login, "github", login)).expect("seals")]; + let (items, skipped) = prepare(&[8u8; vault::KEY_LEN], sealed.clone()).expect("prepares"); + assert_eq!( + items, sealed, + "a wrong passphrase is the device's to refuse" + ); + assert!(skipped.is_empty()); } } diff --git a/cli/src/check.rs b/cli/src/check.rs index e5d8a85..0308b99 100644 --- a/cli/src/check.rs +++ b/cli/src/check.rs @@ -13,16 +13,15 @@ use std::num::NonZeroU8; -use ed25519_dalek::SigningKey; use zeroize::Zeroizing; use crate::device::{ - AUTH_CHALLENGE_LEN, AUTH_SECRET_LEN, Category, Class, Device, EnvBlob, Error, FieldKind, - MAX_ATTEMPTS, Params, Reach, login_item, passphrase, pin, + Category, Class, Device, EnvBlob, Error, MAX_ATTEMPTS, Params, Reach, login_item, passphrase, + pin, }; -use crate::item::{Item, OwnedField}; +use crate::item::Item; use crate::totp::{TEST_SECRET, decode_base32, seed_field, selftest}; -use crate::{auth, backup, boards}; +use crate::{backup, boards}; const PIN: &str = "12345678"; const NEW_PIN: &str = "87654321"; @@ -105,8 +104,6 @@ pub fn run(d: &mut Device) -> Result { lock_unlock(d, &mut rep)?; println!("\n=== rekey ==="); rekey(d, &mut rep, &first_code, &env_blob)?; - println!("\n=== auth: a login answered while locked ==="); - auth(d, &mut rep)?; println!("\n=== live code against an independent HMAC ==="); let ok = selftest(d, &rep.button, |line| println!("{line}"))?; rep.check("selftest", ok, ""); @@ -460,57 +457,6 @@ fn rekey(d: &mut Device, rep: &mut Report, first_code: &str, env_blob: &[u8]) -> Ok(()) } -/// An auth secret signs a challenge after a tap with the device locked, and the -/// signature verifies under the seed's public key on this side; a chip without its -/// eFuse key refuses to hold one at all. -fn auth(d: &mut Device, rep: &mut Report) -> Result<(), Error> { - const SECRET: [u8; AUTH_SECRET_LEN] = [0x5A; AUTH_SECRET_LEN]; - let bound = d.pin_status()?.chip_bound; - let auth_item = Item::new(Category::Auth).with(OwnedField::new( - Class::Secret, - FieldKind::Concealed, - "seed", - &SECRET, - )); - let added = d.put("a", &auth_item, false); - if !bound { - rep.expect( - "no auth secret without a chip key", - &added, - &Error::Incompatible, - ); - return Ok(()); - } - added?; - rep.expect( - "no code from an auth secret", - &d.code("a", Some(59)), - &Error::BadArg, - ); - let challenge = [0x33; AUTH_CHALLENGE_LEN]; - d.lock()?; - rep.tap(); - let signature = d.respond("a", &challenge)?; - rep.check( - "the signature verifies under the public key", - auth::verifies( - &SigningKey::from_bytes(&SECRET).verifying_key(), - &challenge, - &signature, - ), - "", - ); - let st = d.pin_status()?; - rep.check( - "still locked, no attempt spent", - !st.unlocked && st.retries_left == MAX_ATTEMPTS, - &format!("{st:?}"), - ); - d.pin_unlock(pin(NEW_PIN)?)?; - d.delete("a")?; - Ok(()) -} - fn wipe(d: &mut Device, rep: &mut Report) -> Result<(), Error> { d.lock()?; let mut wiped = false; diff --git a/cli/src/device.rs b/cli/src/device.rs index d911702..ee329ac 100644 --- a/cli/src/device.rs +++ b/cli/src/device.rs @@ -13,10 +13,9 @@ use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use serialport::{SerialPort, SerialPortType}; pub use vaultkey_core::item::{Category, Class, FieldKind, VALUE_MAX}; -pub use vaultkey_core::oath::{AUTH_SECRET_LEN, Algo, Digits, NAME_MAX, Name, Params}; +pub use vaultkey_core::oath::{Algo, Digits, NAME_MAX, Name, Params}; pub use vaultkey_core::store::MAX_ATTEMPTS; pub use vaultkey_core::vault::{PASS_MIN, PIN_LEN, Passphrase, Pin}; -pub use vaultkey_core::wire::{AUTH_CHALLENGE_LEN, AUTH_SIGNATURE_LEN, AUTH_SIGNED_PREFIX}; use vaultkey_core::wire::{ BAD_LEN, Cmd, FLAG_REPLACE, Fail, HAS_SECRET, HAS_SEED, MAGIC, OK, REACH_OPEN, REACH_SECRET, REACH_SEED, frame_head, scan_magic, @@ -660,20 +659,6 @@ impl Device { Ok(Code { text, period }) } - /// `challenge` signed with the auth secret `name`, after a tap; no PIN needed. - pub fn respond( - &mut self, - name: &str, - challenge: &[u8; AUTH_CHALLENGE_LEN], - ) -> Result<[u8; AUTH_SIGNATURE_LEN], Error> { - let mut p = name_bytes(name)?; - p.extend_from_slice(challenge); - let body = self.request(Cmd::Respond, &p)?; - body.as_slice() - .try_into() - .map_err(|_| Error::Device(BAD_LEN)) - } - pub fn delete(&mut self, name: &str) -> Result<(), Error> { let p = name_bytes(name)?; self.request(Cmd::Delete, &p).map(drop) diff --git a/cli/src/fido.rs b/cli/src/fido.rs new file mode 100644 index 0000000..3b4d0c7 --- /dev/null +++ b/cli/src/fido.rs @@ -0,0 +1,503 @@ +//! The key's FIDO2 side, spoken directly: just enough CTAP2 over hidraw for `vkey auth` +//! to make a credential and try it. `pamu2fcfg` would do the first half, but the 1.1.0 +//! that distributions ship insists on an attestation certificate, and this key attests +//! with the credential's own key, as `WebAuthn` allows (docs2/roadmap.md, phase 6). + +use std::fs::{self, File, OpenOptions}; +use std::io::{Read, Write}; +use std::path::PathBuf; + +use crate::boards::BOARDS; +use crate::device::Error; + +const PACKET: usize = 64; +const BROADCAST: u32 = 0xFFFF_FFFF; +const CMD_INIT: u8 = 0x06; +const CMD_CBOR: u8 = 0x10; +const CMD_KEEPALIVE: u8 = 0x3B; +const CMD_ERROR: u8 = 0x3F; +const MAKE_CREDENTIAL: u8 = 0x01; +const GET_ASSERTION: u8 = 0x02; +/// COSE: EC2 keys, P-256, ES256. +const COSE_EC2: i64 = 2; +const COSE_P256: i64 = 1; +const COSE_ES256: i64 = -7; + +/// A credential as `pam_u2f` stores it: its id, and the public key as x and y. +pub struct Credential { + pub id: Vec, + pub public: [u8; 64], +} + +/// The key's CTAPHID interface on a channel of its own. +pub struct Key { + hid: File, + channel: u32, +} + +impl Key { + /// The one vkey on this machine with a FIDO interface. + pub fn open() -> Result { + let path = node()?; + let hid = OpenOptions::new() + .read(true) + .write(true) + .open(&path) + .map_err(|e| Error::Value(format!("cannot open {}: {e}", path.display())))?; + let mut key = Key { + hid, + channel: BROADCAST, + }; + let mut nonce = [0u8; 8]; + getrandom::getrandom(&mut nonce) + .map_err(|e| Error::Value(format!("no randomness: {e}")))?; + let answer = key.transact(CMD_INIT, &nonce)?; + let channel = answer + .strip_prefix(&nonce) + .and_then(|rest| rest.first_chunk::<4>()) + .ok_or_else(|| Error::Value("the key answered INIT with something else".into()))?; + key.channel = u32::from_be_bytes(*channel); + Ok(key) + } + + /// A non-resident credential for `rp` and `user`, after a tap. + pub fn make_credential(&mut self, rp: &str, user: &str) -> Result { + let request = Cbor::Map(vec![ + (Cbor::Int(1), Cbor::Bytes(random32()?.to_vec())), + ( + Cbor::Int(2), + Cbor::Map(vec![(text("id"), text(rp)), (text("name"), text(rp))]), + ), + ( + Cbor::Int(3), + Cbor::Map(vec![ + (text("id"), Cbor::Bytes(random32()?.to_vec())), + (text("name"), text(user)), + (text("displayName"), text(user)), + ]), + ), + ( + Cbor::Int(4), + Cbor::Array(vec![Cbor::Map(vec![ + (text("alg"), Cbor::Int(COSE_ES256)), + (text("type"), text("public-key")), + ])]), + ), + ]); + let answer = self.cbor(MAKE_CREDENTIAL, &request)?; + let auth_data = field(&answer, 2) + .and_then(Cbor::as_bytes) + .ok_or_else(|| Error::Value("the key's credential has no authenticator data".into()))?; + attested(auth_data) + } + + /// An assertion for `rp` with `credential`, after a tap: whether the key answers a + /// login the way `pam_u2f` will ask for it. + pub fn get_assertion(&mut self, rp: &str, credential: &[u8]) -> Result<(), Error> { + let request = Cbor::Map(vec![ + (Cbor::Int(1), text(rp)), + (Cbor::Int(2), Cbor::Bytes(random32()?.to_vec())), + ( + Cbor::Int(3), + Cbor::Array(vec![Cbor::Map(vec![ + (text("id"), Cbor::Bytes(credential.to_vec())), + (text("type"), text("public-key")), + ])]), + ), + ]); + let answer = self.cbor(GET_ASSERTION, &request)?; + let flags = field(&answer, 2) + .and_then(Cbor::as_bytes) + .and_then(|d| d.get(32)) + .ok_or_else(|| Error::Value("the key's assertion has no authenticator data".into()))?; + if flags & 0x01 == 0 { + return Err(Error::Value( + "the key answered without the tap it was asked for".into(), + )); + } + Ok(()) + } + + /// A CTAP2 command and its answer, the status byte checked. + fn cbor(&mut self, command: u8, request: &Cbor) -> Result { + let mut payload = vec![command]; + request.encode(&mut payload); + let answer = self.transact(CMD_CBOR, &payload)?; + let (&status, body) = answer + .split_first() + .ok_or_else(|| Error::Value("the key answered with nothing".into()))?; + if status != 0 { + return Err(Error::Value(ctap_error(status))); + } + Cbor::decode(body) + .filter(|(_, rest)| rest.is_empty()) + .map(|(v, _)| v) + .ok_or_else(|| Error::Value("the key's answer is not CBOR".into())) + } + + /// One CTAPHID message out and its answer back, keepalives skipped. + fn transact(&mut self, command: u8, data: &[u8]) -> Result, Error> { + let len = u16::try_from(data.len()).map_err(|_| Error::BadArg)?; + let mut report = [0u8; PACKET + 1]; + let mut head = Vec::with_capacity(PACKET); + head.extend_from_slice(&self.channel.to_be_bytes()); + head.push(0x80 | command); + head.extend_from_slice(&len.to_be_bytes()); + let first = data.len().min(PACKET - 7); + head.extend_from_slice(&data[..first]); + report[1..=head.len()].copy_from_slice(&head); + self.hid.write_all(&report)?; + for (seq, chunk) in (0u8..).zip(data[first..].chunks(PACKET - 5)) { + let mut report = [0u8; PACKET + 1]; + report[1..5].copy_from_slice(&self.channel.to_be_bytes()); + report[5] = seq; + report[6..6 + chunk.len()].copy_from_slice(chunk); + self.hid.write_all(&report)?; + } + + loop { + let packet = self.packet()?; + if packet[..4] != self.channel.to_be_bytes() && command != CMD_INIT { + continue; + } + let cmd = packet[4] & 0x7F; + if cmd == CMD_KEEPALIVE { + continue; + } + if cmd == CMD_ERROR { + return Err(Error::Value(format!( + "the key refused the request (CTAPHID error {:#04x})", + packet[7] + ))); + } + let total = usize::from(u16::from_be_bytes([packet[5], packet[6]])); + let mut out = Vec::with_capacity(total); + out.extend_from_slice(&packet[7..7 + total.min(PACKET - 7)]); + while out.len() < total { + let more = self.packet()?; + let take = (total - out.len()).min(PACKET - 5); + out.extend_from_slice(&more[5..5 + take]); + } + return Ok(out); + } + } + + fn packet(&mut self) -> Result<[u8; PACKET], Error> { + let mut packet = [0u8; PACKET]; + let n = self.hid.read(&mut packet)?; + if n != PACKET { + return Err(Error::Value(format!("the key sent a {n}-byte packet"))); + } + Ok(packet) + } +} + +/// The hidraw node of a vkey board: the one whose HID id names a board's USB pair. +fn node() -> Result { + let mut found = Vec::new(); + for entry in fs::read_dir("/sys/class/hidraw")? { + let entry = entry?; + let uevent = fs::read_to_string(entry.path().join("device/uevent")).unwrap_or_default(); + let ours = BOARDS.iter().any(|b| { + uevent.contains(&format!( + "HID_ID=0003:0000{:04X}:0000{:04X}", + b.usb_vid, b.usb_pid + )) + }); + if ours { + found.push(PathBuf::from("/dev").join(entry.file_name())); + } + } + match found.as_slice() { + [one] => Ok(one.clone()), + [] => Err(Error::Value( + "no key with passkeys is plugged in (the nRF52840 board)".into(), + )), + _ => Err(Error::Value( + "more than one key is plugged in: leave one".into(), + )), + } +} + +/// The credential in makeCredential's authenticator data: +/// `rpIdHash(32) | flags | counter(4) | aaguid(16) | idLen(2) | id | COSE key`. +fn attested(auth_data: &[u8]) -> Result { + let bad = |what: &str| Error::Value(format!("the key's credential {what}")); + let flags = *auth_data.get(32).ok_or_else(|| bad("is too short"))?; + if flags & 0x40 == 0 { + return Err(bad("carries no public key")); + } + let rest = auth_data + .get(37 + 16..) + .ok_or_else(|| bad("is too short"))?; + let (len, rest) = rest + .split_first_chunk::<2>() + .ok_or_else(|| bad("is too short"))?; + let (id, rest) = rest + .split_at_checked(usize::from(u16::from_be_bytes(*len))) + .ok_or_else(|| bad("is cut short"))?; + let (cose, _) = Cbor::decode(rest).ok_or_else(|| bad("has no COSE key"))?; + let int = |k: i64| field(&cose, k).and_then(Cbor::as_int); + if int(1) != Some(COSE_EC2) || int(3) != Some(COSE_ES256) || int(-1) != Some(COSE_P256) { + return Err(bad("is not a P-256 key")); + } + let coord = |k: i64| { + field(&cose, k) + .and_then(Cbor::as_bytes) + .and_then(|b| <[u8; 32]>::try_from(b).ok()) + }; + let (Some(x), Some(y)) = (coord(-2), coord(-3)) else { + return Err(bad("has a malformed public key")); + }; + let mut public = [0u8; 64]; + public[..32].copy_from_slice(&x); + public[32..].copy_from_slice(&y); + Ok(Credential { + id: id.to_vec(), + public, + }) +} + +fn ctap_error(status: u8) -> String { + let why = match status { + 0x27 => "the key refused", + 0x2D => "the request was cancelled", + 0x2E => "the key has no such credential", + 0x2F => "nobody tapped the key in time", + 0x36 => "the key's FIDO PIN is needed", + _ => "the key refused the request", + }; + format!("{why} (CTAP2 status {status:#04x})") +} + +fn random32() -> Result<[u8; 32], Error> { + let mut b = [0u8; 32]; + getrandom::getrandom(&mut b).map_err(|e| Error::Value(format!("no randomness: {e}")))?; + Ok(b) +} + +fn text(s: &str) -> Cbor { + Cbor::Text(s.to_string()) +} + +/// The value under integer key `k` of a CBOR map. +fn field(map: &Cbor, k: i64) -> Option<&Cbor> { + let Cbor::Map(entries) = map else { + return None; + }; + entries + .iter() + .find(|(key, _)| key.as_int() == Some(k)) + .map(|(_, v)| v) +} + +/// CBOR, the part CTAP2 uses here. Maps are written in the order given, which the +/// requests above give canonically: integers ascending, then shorter text first. +#[derive(Debug, PartialEq)] +enum Cbor { + Int(i64), + Bytes(Vec), + Text(String), + Array(Vec), + Map(Vec<(Cbor, Cbor)>), + Simple(u8), +} + +impl Cbor { + fn as_int(&self) -> Option { + match self { + Cbor::Int(n) => Some(*n), + _ => None, + } + } + + fn as_bytes(&self) -> Option<&[u8]> { + match self { + Cbor::Bytes(b) => Some(b), + _ => None, + } + } + + fn encode(&self, out: &mut Vec) { + match self { + Cbor::Int(n) if *n >= 0 => head(out, 0, n.unsigned_abs()), + Cbor::Int(n) => head(out, 1, (n + 1).unsigned_abs()), + Cbor::Bytes(b) => { + head(out, 2, b.len() as u64); + out.extend_from_slice(b); + } + Cbor::Text(t) => { + head(out, 3, t.len() as u64); + out.extend_from_slice(t.as_bytes()); + } + Cbor::Array(items) => { + head(out, 4, items.len() as u64); + for item in items { + item.encode(out); + } + } + Cbor::Map(entries) => { + head(out, 5, entries.len() as u64); + for (k, v) in entries { + k.encode(out); + v.encode(out); + } + } + Cbor::Simple(s) => out.push(0xE0 | s), + } + } + + fn decode(b: &[u8]) -> Option<(Cbor, &[u8])> { + Self::decode_at(b, 0) + } + + /// Nesting is bounded: a hostile answer must not run the stack out. + fn decode_at(input: &[u8], depth: u8) -> Option<(Cbor, &[u8])> { + if depth > 8 { + return None; + } + let (&first, mut rest) = input.split_first()?; + let (major, info) = (first >> 5, first & 0x1F); + let arg: u64 = match info { + 0..=23 => u64::from(info), + FOLLOWS_1 => { + let (byte, tail) = rest.split_first()?; + rest = tail; + u64::from(*byte) + } + FOLLOWS_2 => { + let (bytes, tail) = rest.split_first_chunk::<2>()?; + rest = tail; + u64::from(u16::from_be_bytes(*bytes)) + } + FOLLOWS_4 => { + let (bytes, tail) = rest.split_first_chunk::<4>()?; + rest = tail; + u64::from(u32::from_be_bytes(*bytes)) + } + FOLLOWS_8 => { + let (bytes, tail) = rest.split_first_chunk::<8>()?; + rest = tail; + u64::from_be_bytes(*bytes) + } + _ => return None, + }; + match major { + 0 => Some((Cbor::Int(i64::try_from(arg).ok()?), rest)), + 1 => Some((Cbor::Int(-1 - i64::try_from(arg).ok()?), rest)), + 2 | 3 => { + let (bytes, tail) = rest.split_at_checked(usize::try_from(arg).ok()?)?; + let value = if major == 2 { + Cbor::Bytes(bytes.to_vec()) + } else { + Cbor::Text(String::from_utf8(bytes.to_vec()).ok()?) + }; + Some((value, tail)) + } + 4 => { + let mut items = Vec::new(); + for _ in 0..arg { + let (item, tail) = Self::decode_at(rest, depth + 1)?; + items.push(item); + rest = tail; + } + Some((Cbor::Array(items), rest)) + } + 5 => { + let mut entries = Vec::new(); + for _ in 0..arg { + let (key, tail) = Self::decode_at(rest, depth + 1)?; + let (value, tail) = Self::decode_at(tail, depth + 1)?; + entries.push((key, value)); + rest = tail; + } + Some((Cbor::Map(entries), rest)) + } + 7 => Some((Cbor::Simple(u8::try_from(arg).ok()?), rest)), + _ => None, + } + } +} + +/// The additional-information values that say how many bytes of argument follow. +const FOLLOWS_1: u8 = 0x18; +const FOLLOWS_2: u8 = 0x19; +const FOLLOWS_4: u8 = 0x1A; +const FOLLOWS_8: u8 = 0x1B; + +fn head(out: &mut Vec, major: u8, arg: u64) { + let major = major << 5; + if let Ok(small) = u8::try_from(arg) + && small < FOLLOWS_1 + { + out.push(major | small); + } else if let Ok(byte) = u8::try_from(arg) { + out.extend_from_slice(&[major | FOLLOWS_1, byte]); + } else if let Ok(short) = u16::try_from(arg) { + out.push(major | FOLLOWS_2); + out.extend_from_slice(&short.to_be_bytes()); + } else if let Ok(word) = u32::try_from(arg) { + out.push(major | FOLLOWS_4); + out.extend_from_slice(&word.to_be_bytes()); + } else { + out.push(major | FOLLOWS_8); + out.extend_from_slice(&arg.to_be_bytes()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cbor_round_trips_what_ctap2_sends() { + let v = Cbor::Map(vec![ + (Cbor::Int(1), Cbor::Bytes(vec![7; 32])), + (Cbor::Int(-3), Cbor::Int(-7)), + ( + text("alg"), + Cbor::Array(vec![Cbor::Int(300), Cbor::Simple(21)]), + ), + ]); + let mut out = Vec::new(); + v.encode(&mut out); + assert_eq!( + out[..3], + [0xA3, 0x01, 0x58], + "a map of three, key 1, bytes(24..)" + ); + assert_eq!(Cbor::decode(&out), Some((v, &[][..]))); + } + + #[test] + fn a_credential_comes_out_of_authenticator_data() { + let mut cose = Vec::new(); + Cbor::Map(vec![ + (Cbor::Int(1), Cbor::Int(COSE_EC2)), + (Cbor::Int(3), Cbor::Int(COSE_ES256)), + (Cbor::Int(-1), Cbor::Int(COSE_P256)), + (Cbor::Int(-2), Cbor::Bytes(vec![1; 32])), + (Cbor::Int(-3), Cbor::Bytes(vec![2; 32])), + ]) + .encode(&mut cose); + let mut data = vec![0u8; 32]; + data.push(0x41); // UP and AT + data.extend_from_slice(&[0, 0, 0, 1]); + data.extend_from_slice(&[0; 16]); + data.extend_from_slice(&3u16.to_be_bytes()); + data.extend_from_slice(&[9, 9, 9]); + data.extend_from_slice(&cose); + let c = attested(&data).expect("parses"); + assert_eq!(c.id, [9, 9, 9]); + assert_eq!(c.public[..32], [1; 32]); + assert_eq!(c.public[32..], [2; 32]); + data[32] = 0x01; + assert!(attested(&data).is_err(), "no AT flag, no key"); + } + + #[test] + fn a_hostile_answer_nested_too_deep_is_refused() { + let deep = [0x81u8; 64]; + assert_eq!(Cbor::decode(&deep), None); + } +} diff --git a/cli/src/item.rs b/cli/src/item.rs index 482a314..99120c3 100644 --- a/cli/src/item.rs +++ b/cli/src/item.rs @@ -173,7 +173,6 @@ pub fn category_name(c: Category) -> &'static str { Category::SshKey => "ssh key", Category::CryptoWallet => "crypto wallet", Category::Env => "env", - Category::Auth => "auth", } } @@ -241,12 +240,11 @@ pub const fn field_kind_name(kind: FieldKind) -> &'static str { } } -/// The 1Password category name (`op --category`) for an item written back. `Env` and -/// `Auth` have no category there: an `.env` goes back as a secure note, and an auth -/// seed never goes back at all. +/// The 1Password category name (`op --category`) for an item written back. `Env` has +/// no category there: an `.env` goes back as a secure note. #[must_use] -pub const fn op_category(c: Category) -> Option<&'static str> { - Some(match c { +pub const fn op_category(c: Category) -> &'static str { + match c { Category::Login => "Login", Category::CreditCard => "Credit Card", Category::SecureNote | Category::Env => "Secure Note", @@ -269,8 +267,7 @@ pub const fn op_category(c: Category) -> Option<&'static str> { Category::MedicalRecord => "Medical Record", Category::SshKey => "SSH Key", Category::CryptoWallet => "Crypto Wallet", - Category::Auth => return None, - }) + } } #[cfg(test)] diff --git a/cli/src/main.rs b/cli/src/main.rs index a267404..79add78 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -11,7 +11,7 @@ //! vkey backup vault.vkb # everything into one file, sealed on the key; two taps //! vkey restore vault.vkb # everything back, onto this or another key //! vkey check --wipe-everything # lifecycle test; ERASES the device -//! sudo vkey auth enable # sudo and the lock screen with a tap +//! sudo vkey auth enable # sudo and the lock screen with a tap (pam_u2f) //! vkey install # copy this binary to ~/.local/bin //! ``` //! @@ -25,6 +25,7 @@ mod backup; mod boards; mod check; mod device; +mod fido; mod file; mod import; mod install; @@ -189,10 +190,10 @@ enum Cmd { #[arg(long)] wipe_everything: bool, }, - /// sudo and the lock screen with a tap: `sudo vkey auth enable`; bare, what PAM runs + /// sudo and the lock screen with a tap, through `pam_u2f`: `sudo vkey auth enable` Auth { #[command(subcommand)] - cmd: Option, + cmd: AuthCmd, }, /// Copy this binary to ~/.local/bin/vkey Install, @@ -200,10 +201,10 @@ enum Cmd { #[derive(Subcommand, Clone, Copy)] enum AuthCmd { - /// A login secret on the key, its public key here, and the PAM lines for sudo and - /// the lock screen; PIN and a tap + /// A credential on the key for this host's logins (a tap), its public half in + /// `/etc/u2f_mappings`, and the `pam_u2f` line for sudo and the lock screen Enable, - /// The PAM lines out, the public key and the login secret gone + /// The `pam_u2f` lines out and the user out of `/etc/u2f_mappings` Disable, } @@ -293,11 +294,16 @@ fn main() -> ExitCode { fn run(cli: Cli) -> Result { match cli.cmd { Some(Cmd::Install) => return install::install().map(|()| 0), + // pamu2fcfg talks to the key over FIDO itself; vkey's port is not needed. + Some(Cmd::Auth { + cmd: AuthCmd::Enable, + }) => return auth::enable(), + Some(Cmd::Auth { + cmd: AuthCmd::Disable, + }) => return auth::disable(), Some(Cmd::Setup { erase, board }) => { return cmd_setup(cli.port.as_deref(), board.as_deref(), erase); } - // What PAM runs: straight to the key, no probing, no shell on the way. - Some(Cmd::Auth { cmd: None }) => return auth::verify(cli.port.as_deref()), _ => {} } @@ -314,15 +320,7 @@ fn run(cli: Cli) -> Result { }; match cmd { - Cmd::Install | Cmd::Setup { .. } | Cmd::Auth { cmd: None } => { - unreachable!("handled above") - } - Cmd::Auth { - cmd: Some(AuthCmd::Enable), - } => auth::enable(&mut dev), - Cmd::Auth { - cmd: Some(AuthCmd::Disable), - } => auth::disable(&mut dev), + Cmd::Install | Cmd::Setup { .. } | Cmd::Auth { .. } => unreachable!("handled above"), Cmd::Info => run_info(&mut dev, &version), @@ -415,11 +413,7 @@ fn run_list(dev: &mut Device, long: bool) -> Result { continue; } // The open reach costs the PIN and no gesture, so a whole vault can be listed - // this way; an auth item refuses to be read at all and is reported as it lists. - if e.category == Category::Auth { - println!("{}\t{}\t\t", e.name, item::category_name(e.category)); - continue; - } + // this way. let (open, shape) = dev.get_with_shape(&e.name, Reach::Open)?; let login = open .by_label("username") @@ -807,9 +801,6 @@ fn run_get(dev: &mut Device, version: &str, name: &str, copy: bool) -> Result return Err(Error::Value(crate::auth::USED_BY_AUTH.into())), - Category::Env => return self.use_env(&name), - _ => {} + if stored.category == Category::Env { + return self.use_env(&name); } // The shape comes back with the open fields and costs no gesture, so the shell // knows whether a code is what this item is for before asking for a tap. @@ -1666,17 +1661,13 @@ impl Shell { .ask(&format!("name (Enter keeps '{name}'): "), Field::Plain) .map(|n| n.to_string()); - match category { - // Nothing to edit but the name: the seed was drawn at random and is never - // shown. - Category::Auth => {} - Category::Env => { - if let Some((text, blob)) = self.env_input()? { - self.after_prompt(|d| d.put(&name, &blob.item(), true))?; - self.env_preview(&text); - } + if category == Category::Env { + if let Some((text, blob)) = self.env_input()? { + self.after_prompt(|d| d.put(&name, &blob.item(), true))?; + self.env_preview(&text); } - _ => self.edit_fields(&name)?, + } else { + self.edit_fields(&name)?; } let name = match new_name { diff --git a/cli/src/sources.rs b/cli/src/sources.rs index f986927..79c02fc 100644 --- a/cli/src/sources.rs +++ b/cli/src/sources.rs @@ -19,7 +19,7 @@ use std::time::{Duration, Instant}; use serde::{Deserialize, Serialize}; -use crate::device::{Category, Device, Error, Reach, Stored}; +use crate::device::{Device, Error, Reach, Stored}; use crate::file; use crate::import::Summary; use crate::prompt::SyncUi; @@ -297,13 +297,10 @@ pub(crate) fn prune( Ok(()) } -/// An item worth pinging the device with to hold off its auto-lock: any but an auth -/// secret, which refuses to be read at all, out of a listing already in hand. +/// An item worth pinging the device with to hold off its auto-lock, out of a listing +/// already in hand. pub(crate) fn survivor(entries: &[Stored]) -> Option { - entries - .iter() - .find(|e| e.category != Category::Auth) - .map(|e| e.name.clone()) + entries.first().map(|e| e.name.clone()) } /// Every name the key holds. A listing that does not come back reads as empty, which diff --git a/docs/threat-model.md b/docs/threat-model.md index ab1d0c1..d28add4 100644 --- a/docs/threat-model.md +++ b/docs/threat-model.md @@ -43,8 +43,9 @@ and every guarantee below that rests on the eFuse key, JTAG being off or Secure an image signed with another key, and it ran the signed vkey. Whoever holds the button can still write the application region, so a bad copy leaves the board in the bootloader until a signed image is copied. -- **`vkey auth` does not exist here.** Its secret is sealed under the chip key, and the - CLI refuses to enable it. +- **`vkey auth` is a passkey here** (since 2026-10-15): `pam_u2f` over the board's FIDO2, + in place of the old scheme, which needed a chip key. Its section below says what that + costs. - **The bootloader fork's signing key lives on this board.** It is the `.env` `vkey-signing-nrf`, made by `bootloader/signing-key.sh` on 2026-10-14 (fingerprint `a1700ebd539b0bfc`), with a `.vkb` as its second copy. That copy was proven twice, each @@ -162,8 +163,8 @@ before the burn became `Incompatible` and was wiped. | Gesture | Action | LED | |---|---|---| -| Tap | code, the secret fields of an item, a `.env`, a `vkey auth` login | amber | -| Hold 5 s | wipe | red | +| Tap | code, the secret fields of an item, a `.env`, a passkey, a `vkey auth` login | amber | +| Hold 5 s | wipe; on the nRF52840 also erasing every passkey | red | | Double tap, 800 ms window | encrypted backup, **and an export or seed readout** | blue | A tap never wipes and never exports; a hold never exports; a double tap never wipes. One @@ -261,56 +262,50 @@ out, a duplicate name replaces, and entry versus blob the newer one from the fil Rejected: a flash-image copy as backup — PIN-encrypted, 8 digits fall offline in days, and it does not transfer while bound to the chip key. -### `vkey auth` — sudo and the lock screen with a tap, no PIN - -`vkey auth` (2026-09-14) lets `sudo` and the lock screen accept a tap on the key instead -of the Linux password, through `pam_exec`; with no key, or no tap within ten seconds (the -firmware's own timeout for a login, shorter than a code's 30 s), PAM asks for the password -as before. The scheme is `pam_u2f`'s. `sudo vkey auth enable` draws a 32-byte Ed25519 seed -on the host, stores it on the key as an `Auth` entry, keeps the public key in -`/etc/vkey/auth/` (root, 0644) and zeroizes the seed. A login sends a fresh random -challenge; the key signs `"vaultkey/auth/v1" | challenge` after a tap; the signature is -verified here. The host holds no secret and writes nothing at login, so `sudo` (checked as -root) and a lock screen running as the user (COSMIC's `cosmic-greeter`, `swaylock`) read the -same file. A recorded signature is worthless: the next challenge is a different one. - -`enable` also copies the binary to `/usr/local/bin/vkey` and adds one line to each PAM -service this host has among `sudo`, `cosmic-greeter`, `gdm-password`, `kde`, `swaylock`, -`hyprlock` — above the line that brings in the password check, a copy of the file kept once -as `*.before-vkey`, the new file renamed over the old. A file with no recognisable anchor is -left alone and the line printed for the owner to place. `disable` takes the lines out, -deletes the public key and the entry. This replaces the first version (same day), which -kept a rotating expectation on the host instead of a public key: two state files, one of -them in the user's home, and a user who had to edit PAM by hand. Writing `/etc/pam.d` from -the CLI is the price of a setup a person can do; the line is `sufficient`, so what it adds -is a way in, and the password stays one. - -**The deliberate exception to "everything needs the PIN".** An `Auth` record is sealed -under `DeviceKey::mac("vaultkey/auth-key/v1")` — the eFuse key alone — not under the DEK, so -`Respond` works while the device is locked and spends no attempt: `sudo` can never be what -wipes the vault. On a chip without a burned key it is refused (`Incompatible`), because -there it would be sealed under nothing. Adding, listing, renaming and deleting still need -the PIN; a PIN change does not touch the record; a wipe removes it; a backup reseals it -under the passphrase and a restore under the new chip, so the host's public key stays valid. +### `vkey auth` — sudo and the lock screen with a tap, through `pam_u2f` + +Since 2026-10-15 `vkey auth` is the scheme every other key uses: `pam_u2f` over FIDO2, on +the nRF52840's passkeys (maintainer's decision, 2026-10-03). `sudo vkey auth enable` makes +a non-resident credential for `pam://` after a tap, tries it with an assertion after +a second tap, and only then writes its public half to `/etc/u2f_mappings` (root's, 0644), +replacing only that user's line. It speaks CTAP2 itself (`cli/src/fido.rs`) rather than +run `pamu2fcfg`: the 1.1.0 that distributions ship demands an attestation certificate, and +this key attests with the credential's own key. Each PAM service this host has among `sudo`, `cosmic-greeter`, `gdm-password`, `kde`, +`swaylock`, `hyprlock` gets one line, `auth sufficient pam_u2f.so +authfile=/etc/u2f_mappings cue`, above the one that brings in the password check. A copy +of each file is kept once as `*.before-vkey`, and a file with no recognisable anchor is +left alone with the line printed. `disable` takes the lines out and the user out of the +mapping. The line is `sufficient`: what it adds is a way in, and the password stays one. | | | |---|---| -| Given | A login needs this physical board and a finger on it; no secret on the host; a fresh challenge every time; no PIN attempt spent | +| Given | A login needs this physical key and a fresh tap after the request; the host holds a public key only; no vkey PIN, locked or not, and no attempt spent | | Laptop and key stolen together | The lock screen opens with a tap. A powered-off laptop is protected by disk encryption, not by this. Carry the key separately, do not leave it in the port | -| Malware running as the user | Can start `sudo` and wait for a reflex tap. The LED is the same amber as a code; a tap you did not ask for is the thing to refuse | -| A locked key | Answers `NotFound` to every name that is not an auth entry, so it names no service without the PIN; whether `@` is enrolled is not secret | +| Malware running as the user | Can start `sudo` and wait for a reflex tap. The light is the same amber as a code or a passkey; a tap you did not ask for is the thing to refuse | +| Malware enrolling a key of its own | `/etc/u2f_mappings` is root's: adding a line needs root already | | Someone at the unlocked laptop while you are away, key in the port | Gets root with one tap where `sudo` used to want the password | -| A `.vkb` backup | Now also carries the login seed: with the passphrase and any chip-bound board it signs for your `sudo` too | -| A user-writable binary | PAM runs `vkey` as root; `vkey auth` refuses unless its executable and every directory above it are root's alone, hence `/usr/local/bin/vkey` | -| The public key file | Not secret. Replacing it needs root, and `vkey auth` refuses it unless it and every directory above it are root's alone | -| The port busy (the `vkey` shell open) | The login fails and PAM falls back to the password | -| A `vkey auth` killed mid-wait (Ctrl+C) | The key still signs the old challenge; the next login may read that signature, fail it once and fall back to the password. Nothing is left broken | +| A copy of the board's flash (the revision-2 glitch) | The credential's key is wrapped by fido-authenticator's key, which sits unsealed in Trussed's filesystem: whoever reads the flash can answer this host's logins, given the host | +| A `.vkb` backup | Holds the login once milestone 5 puts the passkeys into it: with the passphrase, another board then answers this host's `sudo` too | +| The key in, nobody tapping | The password prompt comes when the key gives up, after 30 s; the old scheme gave up after 10 | +| A FIDO PIN on the key | Its own, not vkey's; the credential is made without one, so a login does not ask for it | | The login screen after boot | COSMIC's greeter shares the `cosmic-greeter` service, so a tap may log in there too; the keyring, unlocked only by the password, then stays locked | +**The scheme before, removed 2026-10-15** (restorable from commit `4bd49f3`: +`cli/src/auth.rs`, `Respond`, `Category::Auth`, `vault::auth_key`). An Ed25519 seed on the +key, sealed under the chip key alone, answered a fresh challenge after a tap through +`pam_exec` of `/usr/local/bin/vkey auth`. It needed a burned chip key, which the nRF52840 +does not have, and `pam_u2f` does the same with a credential the key's FIDO side already +makes. What it leaves: +- an older `.vkb` may hold its seed; a restore leaves that item in the file and names it; +- a vault that still holds one (only the C6 ever did) cannot open it on newer firmware, + because it was sealed under the chip key: `vkey rm @` before a backup; +- `/usr/local/bin/vkey`, which `enable` points out and leaves for the owner to delete; +- category 201 and command byte 0x19 stay unused, so an older CLI never means something else. + Rejected: presence of the USB device as proof (any ESP32 shows `303a:1001`); PIN plus tap (a second password to type buys nothing over the one it replaces); HMAC challenge-response -with a rotating expectation (the first version: state to write at every login and two copies -of it); a PAM `cdylib` (`pam_exec` needs no C and no `unsafe`). +with a rotating expectation (state to write at every login); a PAM `cdylib`; keeping a +scheme of our own beside `pam_u2f`. ## What it does not protect against diff --git a/docs2/makerdiary.md b/docs2/makerdiary.md index 5954214..89e1069 100644 --- a/docs2/makerdiary.md +++ b/docs2/makerdiary.md @@ -163,8 +163,13 @@ nRF52840 lacks, so the firmware refuses it (`Incompatible`). pam_u2f needs no ch Other schemes, not chosen: `pam_yubico` (Yubico OTP or HMAC-SHA1 challenge-response, legacy), `pam_p11`/sssd smartcard (PIV certificates, enterprise setup). -The current Ed25519 `vkey auth` stays only while the C6 is in use, and is isolated so it can -be cut in one change. Its whole surface (2026-10-03): +**Done 2026-10-15** (roadmap phase 6, milestone 4): `sudo vkey auth enable` makes the +credential over its own CTAP2 (`pamu2fcfg` 1.1.0 refuses a key that attests with the +credential's own key) and writes `/etc/u2f_mappings` and the PAM lines; the Ed25519 scheme below was +cut in that change, restorable from 4bd49f3. + +The Ed25519 `vkey auth` was isolated so it could be cut in one change. Its whole surface +(2026-10-03): | Where | What | |---|---| @@ -237,7 +242,8 @@ Pins from the Makerdiary wiki (still to be **measured with a probe**, per projec YubiKey physically. Pot only after final flashing and APPROTECT, leaving the button and USB free. - **`vkey auth` does not migrate.** Its key is sealed under the C6 eFuse key; it must be - re-created and `vkey auth enable` repeated. Items move over a `.vkb` backup (passphrase + re-created and `vkey auth enable` repeated. (Done 2026-10-15 the other way: `vkey auth` + is now `pam_u2f` over this board's FIDO2.) Items move over a `.vkb` backup (passphrase only, no chip key). The Secure Boot signing key held in vkey needs a plan before the move. - **FIDO2 is the biggest piece of code in the project** (CTAP2.1, COSE, P-256, resident keys, PIN protocol). Every line is attack surface. @@ -271,7 +277,7 @@ vkey alone, no Trussed yet: the same core as the C6, behind the four HAL traits. | Ui | button P0.18, LEDs P0.23/P0.22/P0.24, all active low, from the wiki; amber = red + green | | Flash | `Nvmc` over 0x97000..0xEC000 behind a wrapper that fences after every erase and write, split into the vault's region and Trussed's (`Region`), each refusing access past its end | | Entropy | the RNG peripheral, bias correction on | -| DeviceKey | none: `bound() == false`, PIN only, `vkey auth` refused | +| DeviceKey | none: `bound() == false`, PIN only; `vkey auth` is `pam_u2f` since 2026-10-15 and needs none | Measured on the build: 72 KiB of code, 154 KiB of statics, ≈101 KiB left for the stack. diff --git a/docs2/roadmap.md b/docs2/roadmap.md index aabebeb..09b41d0 100644 --- a/docs2/roadmap.md +++ b/docs2/roadmap.md @@ -680,6 +680,21 @@ Milestones, one commit each, each leaving a key that works: - `ui::await_release`, which takes one "not pressed" sample for a release. A bounce in the middle of a press could then count as two taps, and two taps at blue let a backup out. It gets the same debounce `released` already has. + + **Accepted 2026-10-15**: + - `vkey auth` kept its name and became `pam_u2f`, as decided on 2026-10-03. The + Ed25519 scheme is gone, restorable from 4bd49f3 (`docs/threat-model.md`). + - `sudo` took a tap, the lock screen took a tap, and the password worked with the key + out. + - `enable` makes the credential over its own CTAP2: `pamu2fcfg` 1.1.0 calls + `fido_cred_verify`, which demands an attestation certificate this key does not have. + Its mapping line has `pamu2fcfg`'s shape, checked against the pam-u2f 1.1.0 source. + - A CTAPHID_CANCEL during a touch wait answers KEEPALIVE_CANCEL in 0.2 s, and the next + request goes through. + - The withdrawn-wait and bounce tests pass on the host. The bounce test fails against + the old `await_release`, so it catches what it is there for. + - `check --wipe-everything` passed, then the restore from the `.vkb` through the new + host-side reseal, the 1Password sync and `selftest`. 5. **The passkeys in the `.vkb`**: backup and restore carry the Trussed filesystem, sealed under the passphrase like the items. diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index 06bae75..4d28e92 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -572,33 +572,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "curve25519-dalek-derive", - "digest 0.10.7", - "fiat-crypto", - "rustc_version 0.4.1", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "darling" version = "0.21.3" @@ -802,19 +775,6 @@ dependencies = [ "signature 2.2.0", ] -[[package]] -name = "ed25519-dalek" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" -dependencies = [ - "curve25519-dalek", - "ed25519", - "sha2 0.10.9", - "subtle", - "zeroize", -] - [[package]] name = "either" version = "1.19.0" @@ -1381,12 +1341,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - [[package]] name = "fido-authenticator" version = "0.3.0" @@ -3081,7 +3035,6 @@ dependencies = [ "aes-gcm", "argon2", "crc", - "ed25519-dalek", "embedded-storage", "hmac 0.13.0", "rand_core 0.9.5", @@ -3125,6 +3078,7 @@ dependencies = [ "nrf52840-hal", "rand_core 0.6.4", "rand_core 0.9.5", + "ref-swap", "static_cell", "trussed", "trussed-core", diff --git a/firmware/boards/esp32c6-zero/images/vaultkey.bin b/firmware/boards/esp32c6-zero/images/vaultkey.bin index f7779c3883bfe56681ac306211da71fedd1fb2d5..73d1d8ffd1341163e8cf847e4da1a515651c2cf5 100644 GIT binary patch delta 33116 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 delta 111992 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