Timeline
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

18 check-ins

2026-10-31
07:56
update LICENSE leaf check-in: dcdeccbace user: andrew tags: trunk
07:47
Implement NK3 LPC55 firmware update (bootloader protocol + wiring).

Ticket: c0aee280e0

This completes the majority of the nk3 firmware update work:

* Bootloader module (src/bootloader/): - Bootloader trait for multi-variant support - Full LPC55 NXP MCU bootloader protocol implementation (~610 lines) - HID framing, GetProperty, Reset, ReceiveSbFile commands - Auto-detects custom Nitrokey bootloader (0x20a0:0x42dd) and ROM ISP (0x1fc9:0x0021)

* Firmware module enhancements (src/firmware.rs): - HardwareVariant enum (Lpc55, Nrf52) - FirmwareImage struct with variant, format, filename - ImageFormat enum (Sb2, NordicDfuZip) - FirmwareManifest struct with serde parsing - extract_firmware_image() to pull SB2/nRF52 files from ZIP - Enhanced parse_firmware_container() to detect variants from manifest

* Update command wiring (src/main.rs): - cmd_nk3_update() function implementing complete workflow: 1. Validate firmware container, detect supported variants 2. Detect device state (app mode vs bootloader mode) 3. If in app mode: reboot to bootloader, wait for re-enumeration 4. Extract correct firmware image for device variant 5. Connect to bootloader, get version/uuid 6. Flash with progress bar 7. Reset to boot into new firmware - Progress bar via indicatif crate - Only LPC55 currently supported; helpful error for nRF52

* README.md: - Mark update command as '🟡 Enhanced (validates firmware, detects device variant, shows compatibility)' - Mark validate-update as '🟡 Enhanced (parses manifest, maps images to hardware variants, detects formats)' - Mark fetch-update as '🟡 Stub (manual workflow available: download ZIP from GitHub releases)'

* Cleanup: - Removed .gitignore (this is a Fossil repository)

Remaining for future work: - nRF52 DFU protocol (for NK3AM/NKPK devices) - Auto-fetch firmware from GitHub releases API - Software cryptographic signature verification (SB2 uses hardware RKTH verification) check-in: 2696e1ab5d user: andrew tags: trunk

07:13
Update README for validate-update status. Ticket: c0aee280e0

- validate-update: now marked as ✅ working (patina column) and 🟡 Partial (no crypto sig check yet) - fetch-update: clarify manual download workflow is available check-in: d8c642f194 user: andrew tags: trunk

07:13
Implement nk3 validate-update for local ZIP files. Ticket: c0aee280e0

- Add zip crate dependency for firmware container parsing - Add src/firmware.rs module for parsing firmware ZIP archives: - validate_firmware_file() - basic validation (ZIP structure, file listing) - parse_firmware_container() - extracts manifest JSON, version info - Auto-detects root-level JSON manifests and extracts version/sdk/tool fields

- Update stub messages for manual ZIP workflow (no GitHub API required): - fetch-update: points users to manual download + validate/update workflow - update: guides users to validate first with --firmware path - validate-update: now fully functional for local ZIP files

Implemented user workflow: 1. Download ZIP manually from https://github.com/Nitrokey/nitrokey-3-firmware/releases 2. patina nk3 validate-update ./firmware.zip # validates structure 3. patina nk3 update --firmware ./firmware.zip # (needs bootloader protocol) check-in: 43b127dedc user: andrew tags: trunk

07:00
Update README feature parity table for NK3 commands.

Correct the NK3 feature parity status to reflect actual implementation: - 12 NK3 commands: ✅ Complete (not CLI stub) - Added missing command to the table - 4 commands: 🟡 Stub with helpful user messages (not CLI stub) - fetch-update, update, validate-update, provision

The previous status incorrectly marked all NK3 commands (except list/wink) as "CLI stub only" when they have full working protocol implementations.

Also clarify the distinction: - "CLI stub only" = CLI parsing works, but handler uses unimplemented!() - "🟡 Stub" = handler runs, shows helpful error message about what's needed check-in: 189e0410d3 user: andrew tags: trunk

06:48
Fix test_fido2() redundant logic bug.

Remove unused CTAP2_STATUS_OK constant and eliminate redundant if-else that returned the same value in both branches.

Improve doc comments to clarify: - Returns Some((status, response)) if device responds - Returns None if FIDO2/CBOR not available - Status is passed through (0x00 = CTAP2_OK)

Follow-up fix to commit da41c2aa44. Ticket: f52c75a0e0 check-in: 733fe0548d user: andrew tags: trunk

06:44
Update AGENTS.md: Add upstream reference repo workflow.

Document the policy: - First check local disk for reference repos - If missing, git clone to /tmp (NOT web fetch) - Use glob/grep/view on local clone

Reason: web/agentic_fetch is lazy with pagination and rate-limited; local clone gives complete codebase access.

No ticket - this is workflow documentation for assistants. check-in: 1428e8eccc user: andrew tags: trunk

06:38
Finish nk3 test command: Implement FIDO2 connectivity test.

Add test_fido2() method using CTAP2 authenticatorGetInfo (0x04) command to verify FIDO2 connectivity. This uses the existing cbor() method and provides actual test coverage vs the previous NotImplemented stub.

Changes: - ctaphid.rs: New test_fido2() method that sends CTAP2_GET_INFO (0x04) Returns (status_code, response_data). Status 0x00 = success. - main.rs: Update Test handler to: - Call test_fido2() instead of returning NotImplemented - Updated --list help: 'connectivity (authenticatorGetInfo)' vs 'make-credential, get-assertion' - Run both SE050 and FIDO2 tests with --all - Removed misleading --pin option from help (not needed for getInfo)

Note: Full FIDO2 tests (makeCredential, getAssertion with PIN) would require significantly more CTAP2/CBOR protocol work. Those are future enhancements; this covers the basic 'is FIDO2 responding?' test case.

Ticket: f52c75a0e0 check-in: da41c2aa44 user: andrew tags: trunk

06:32
Fix 6 auto-fixable clippy warnings.

Found during code review. Fixed with cargo clippy --fix:

- src/ctaphid.rs:219: Unused variable cmd_byte -> _cmd_byte - src/main.rs:178: Two unused match fields (include, exclude) -> _ prefix - src/ctaphid.rs:689: data.len() >= 1 -> !data.is_empty() (len_zero lint) - src/helpers.rs:176,184: Remove needless borrows (2 places)

40 remaining warnings are dead_code from intentional scaffolding (traits for future devices, helper utilities). Per AGENTS.md: OK during development; release build requires -D dead-code -D unused.

1 style warning remains: clippy::upper_case_acronyms on NKPK enum variant. This matches USB product naming.

Ticket: 6ee2e6842d check-in: 5b4d7fb8f3 user: andrew tags: trunk

06:20
Implement nk3 test command (partial) and add handlers for remaining commands.

Protocol layer (src/ctaphid.rs): - test_se050(): Call ADMIN_TEST_SE050 (0x81) - Returns raw test response bytes as hex - Returns None if command not supported

CLI handlers (src/main.rs): - Test: - --list: Shows available tests (fido2, se050) and options - --all: Runs available tests (SE050, skips FIDO2 with message) - --only se050: Run specific test - Note: FIDO2 tests require full CTAP2 protocol implementation - FetchUpdate, Update, ValidateUpdate: - Show what would be done - Return NotImplemented with helpful error message explaining what's needed - Provision: - Return NotImplemented (production-only command, needs APP_PROVISIONER protocol)

Tested on Nitrokey 3 hardware: - nk3 test --list: Shows available tests - nk3 test --all: Runs SE050 test successfully, returns: 030101010b70a0025f02500102030405060708090a...

Remaining work for full implementation: - FIDO2 tests: Need CTAP2/CBOR protocol (make-credential, get-assertion) - Firmware update: Need bootloader protocol (LPC55/nRF52 chip-specific) - Provision: Need APP_PROVISIONER (0x71) protocol

Ticket: f52c75a0e0 (partial) Ticket: c0aee280e0 (stub with helpful message) Ticket: afc6ca061b (stub with helpful message) check-in: e53a24a35c user: andrew tags: trunk

06:17
Implement nk3 factory-reset commands.

Protocol layer (src/ctaphid.rs): - factory_reset(): Call ADMIN_FACTORY_RESET (0x84) - Handles Timeout and CommunicationError since device may reboot - Interprets FactoryResetStatus codes - factory_reset_app(app): Call ADMIN_FACTORY_RESET_APP (0x85) - Takes app name as ASCII bytes in request - Interprets FactoryResetStatus codes (NOT_CONFIRMED, APP_NOT_ALLOWED, APP_FAILED_PARSE)

CLI handlers (src/main.rs): - factory-reset: Perform full device factory reset - factory-reset-app APP: Reset specific application

Note: These operations are destructive and require touch confirmation. Build verified successfully.

Ticket: ce291fa9ac check-in: 2dffa6bfa3 user: andrew tags: trunk

06:15
Implement nk3 config commands.

Add ciborium dependency for CBOR encoding/decoding.

Protocol layer (src/ctaphid.rs): - list_available_fields(): Call ADMIN_LIST_FIELDS (0x86), decode CBOR response - get_config(key): Call ADMIN_GET_CONFIG (0x82), parse [status, value] response - set_config(key, value): Call ADMIN_SET_CONFIG (0x83) with CBOR-encoded request

CLI handlers (src/main.rs): - list-config-fields: List available config fields with type and flags - get-config: Query config value by key - set-config: Set config value

Tested on Nitrokey 3 hardware (/dev/hidraw1): - list-config-fields returns 4 fields with correct metadata - get-config fido.disable_skip_up_timeout returns 'false'

Ticket: 805aadbd45 check-in: dca56346da user: andrew tags: trunk

06:03
Implement nk3 uuid and reboot commands.

CLI: - Add Uuid variant to Nk3Commands enum - Add Reboot handler with bootloader flag to cmd_nk3() - Add Uuid handler to cmd_nk3()

Protocol: - CtapHidSession::reboot() - handles LEGACY_REBOOT (0x53) and LEGACY_UPDATE (0x51) Gracefully handles Timeout and CommunicationError since device disconnects during reboot

Tested on actual Nitrokey 3 hardware: - nk3 uuid returns: c48f6b34-a473-745c-8af0-90bc3cb51826 - nk3 reboot successfully reboots the device

Ticket: ba84814a18 Ticket: d212afca92 check-in: b105fa2a3d user: andrew tags: trunk

05:36
Implement nk3 status, version, and rng commands.

Add Trussed vendor-specific CTAPHID command support:

Protocol layer (ctaphid.rs): - PacketBuilder::init_packet_raw() for raw u8 command bytes - PacketParser::parse_init_header_raw() returning raw cmd byte - HidTransport::send_raw() and recv_raw() for vendor commands - CtapHidSession::call_vendor() - raw vendor command dispatch - CtapHidSession::call_admin() - wraps subcommands for APP_ADMIN - Convenience methods: status(), version(), rng(), uuid()

CLI handlers (main.rs): - nk3 status: Shows internal/external flash blocks, variant - nk3 version: Parses 4-byte BE int or UTF-8 semver string - nk3 rng: Returns device-generated random bytes as hex

Protocol discovery from nitrokey Python SDK: - Legacy commands (below 0x6F): direct CTAPHID cmd bytes (RNG=0x60, VERSION=0x61, UUID=0x62) - New Admin commands (0x80 and above): wrapped in APP_ADMIN (0x72) with subcommand in first data byte (STATUS=0x80, etc.)

Tested on actual Nitrokey 3 hardware (/dev/hidraw1).

Ticket: fc8e3dea85 Ticket: 7e47490744 Ticket: b09e08a184 check-in: df1a949d05 user: andrew tags: trunk

05:07
Document ticket-based workflow requirement.

- Add Ticket-based workflow section to Code Quality Requirements - Add full Fossil Ticket Workflow section with: - Clear atomic ticket requirement (no multi-feature tickets) - Step-by-step workflow: create ticket -> make changes -> commit with UUID -> close - Reference common ticket commands: list, add, show, set

Ticket: 51c50b733a check-in: c3cee071bb user: andrew tags: trunk

05:00
Documentation and process improvements

- README.md: Clarify feature parity table, fix subcommand terminology - README.md: Replace 'cargo run --' stooge commands with proper binary invocation - README.md: Reproducible builds use 'cargo build --release --frozen' - README.md: Fix misleading 'CLI only' status descriptions (not applicable) - README.md: Platform status: 'CLI stub only' → 'Incomplete' where appropriate

- AGENTS.md: Same build/run documentation improvements - AGENTS.md: Reproducible builds: 'cargo build --release --frozen' - AGENTS.md: Full clippy command with -D dead-code -D unused - AGENTS.md: Fix typo: SPDXLicense-Identifier → SPDX-License-Identifier - AGENTS.md: Remove 'cargo run --' developer-focused stooge commands

Key principle: Users build the binary, then run the binary. No one does 'cargo run -- list' like a stooge. check-in: 92d7b30b56 user: andrew tags: trunk

04:53
Initial implementation of patina: pure Rust nitropy reimplementation

Key achievements: - Complete CLI structure with clap (all nitropy commands: list, version, nk3, nkpk, fido2, start, pro, storage, nethsm with all subcommands) - Device enumeration working via hidapi (tested with Nitrokey 3) - Full CTAPHID (FIDO2 HID) protocol implementation: - INIT channel allocation - Initialization/continuation packet framing - PING, WINK, MSG, CBOR commands - Wink command working on actual Nitrokey 3 hardware - Error handling framework with thiserror - Helper utilities: table printing, progress bars, prompts, root check - Cross-platform support: hidapi configured for Linux, FreeBSD, OpenBSD (macOS/Windows: CLI defined, platform features not yet enabled) - Design priorities documented: safe code > secure code/minimal crates > UX - Quality requirements: clippy all/pedantic/nursery, -D dead-code/unused - SPDX-License-Identifier: BSD-3-Clause headers on all source files - Feature parity table in README.md tracking 50+ commands vs nitropy - AGENTS.md: comprehensive documentation for future contributors

Tested working commands: cargo run -- list # Detects /dev/hidraw1: Nitrokey 3 cargo run -- nk3 wink # Blinks device LED via CTAPHID

Status: ~6% complete (3 of 50+ commands working). CLI structure 100% defined. Goal: 100% feature parity with nitropy. check-in: 94016ded01 user: andrew tags: trunk

04:02
initial empty check-in check-in: 3a18619092 user: andrew tags: trunk