├── .envrc
├── .gitignore
├── .gitlab-ci.yml
├── 70-nitrokey-3.rules
├── CHANGELOG.md
├── Cargo.lock
├── Cargo.toml
├── Dockerfile
├── Info.plist
├── LICENSE-APACHE
├── LICENSE-MIT
├── Makefile
├── README.md
├── components
├── apps
│ ├── Cargo.toml
│ └── src
│ │ ├── dispatch.rs
│ │ ├── lib.rs
│ │ └── migrations.rs
├── boards
│ ├── Cargo.toml
│ └── src
│ │ ├── flash.rs
│ │ ├── init.rs
│ │ ├── lib.rs
│ │ ├── nk3am.rs
│ │ ├── nk3am
│ │ ├── migrations
│ │ │ ├── ftl_journal
│ │ │ │ ├── backends.rs
│ │ │ │ ├── ifs_flash_old.rs
│ │ │ │ └── mod.rs
│ │ │ └── mod.rs
│ │ └── ui.rs
│ │ ├── nk3xn.rs
│ │ ├── nk3xn
│ │ ├── button.rs
│ │ ├── led.rs
│ │ ├── nfc.rs
│ │ ├── prince.rs
│ │ └── spi.rs
│ │ ├── nkpk.rs
│ │ ├── runtime.rs
│ │ ├── soc.rs
│ │ ├── soc
│ │ ├── lpc55.rs
│ │ ├── lpc55
│ │ │ ├── clock_controller.rs
│ │ │ └── monotonic.rs
│ │ ├── nrf52.rs
│ │ └── nrf52
│ │ │ ├── flash.rs
│ │ │ └── rtic_monotonic.rs
│ │ ├── store.rs
│ │ ├── ui.rs
│ │ └── ui
│ │ ├── buttons.rs
│ │ └── rgb_led.rs
├── fm11nc08
│ ├── Cargo.toml
│ └── src
│ │ ├── device.rs
│ │ └── lib.rs
├── lfs-backup
│ ├── Cargo.toml
│ └── src
│ │ ├── lfs_backup.rs
│ │ ├── lib.rs
│ │ └── tests.rs
├── memory-regions
│ ├── Cargo.toml
│ └── src
│ │ └── lib.rs
├── ndef-app
│ ├── Cargo.toml
│ └── src
│ │ ├── lib.rs
│ │ └── ndef.rs
├── nfc-device
│ ├── Cargo.toml
│ └── src
│ │ ├── iso14443.rs
│ │ ├── lib.rs
│ │ ├── traits.rs
│ │ └── types.rs
├── provisioner-app
│ ├── Cargo.toml
│ └── src
│ │ ├── apdu.rs
│ │ ├── ctaphid.rs
│ │ └── lib.rs
└── utils
│ ├── Cargo.toml
│ └── src
│ ├── build.rs
│ ├── lib.rs
│ ├── storage.rs
│ └── version.rs
├── docker-Makefile
├── docs
├── contributing.md
├── ctaphid-commands.md
├── hardware.md
├── identifiers.md
├── index.md
├── lpc55-quickstart.md
├── maintenance.md
├── storage.md
├── testing.md
├── troubleshooting.md
└── usbip.md
├── repometrics.toml
├── runners
├── .gitignore
├── arm-none-eabi-arch-symbols.txt
├── embedded
│ ├── .cargo
│ │ └── config.toml
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── Makefile
│ ├── build.rs
│ ├── data
│ │ └── fido-cert.der
│ ├── deny.toml
│ ├── profiles
│ │ ├── lpc55.toml
│ │ └── nrf52-bootloader.toml
│ └── src
│ │ ├── bin
│ │ ├── app-lpc.rs
│ │ └── app-nrf.rs
│ │ ├── lib.rs
│ │ ├── nk3xn.rs
│ │ └── nk3xn
│ │ └── init.rs
├── ld
│ ├── cortex-m-rt_0.6.15_link.x
│ ├── lpc55-memory-template.x
│ └── nrf52-memory-template.x
├── nkpk
│ ├── .cargo
│ │ └── config
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── Makefile
│ ├── build.rs
│ └── src
│ │ └── main.rs
└── usbip
│ ├── .gitignore
│ ├── Cargo.toml
│ ├── Makefile
│ ├── build.rs
│ ├── src
│ ├── main.rs
│ ├── store.rs
│ └── ui.rs
│ └── walk.sh
├── rust-toolchain.toml
├── rustfmt.toml
├── scripts
├── bump-jlink
├── defuse-bee
└── fuse-bee
├── ssh
└── troubles
│ ├── .gitignore
│ ├── Dockerfile
│ ├── Makefile
│ ├── README.md
│ ├── entrypoint
│ └── works
├── tests
├── basic.py
├── beep.py
├── ccid.py
├── test_ccid.py
└── totp.py
└── utils
├── collect-license-info
├── Cargo.toml
├── src
│ └── main.rs
└── templates
│ └── license.txt
├── compare-bloat.py
├── fido2-mds
├── .gitignore
├── Makefile
├── attestation
│ ├── nk3am.der
│ ├── nk3xn.der
│ └── test.der
├── generate-mds.py
├── metadata
│ ├── v1
│ │ ├── metadata-nk3am-v1.json
│ │ ├── metadata-nk3am-v1.test.json
│ │ ├── metadata-nk3xn-v1.json
│ │ └── metadata-nk3xn-v1.test.json
│ ├── v2
│ │ ├── metadata-nk3am-v2.json
│ │ ├── metadata-nk3am-v2.test.json
│ │ ├── metadata-nk3xn-v2.json
│ │ └── metadata-nk3xn-v2.test.json
│ ├── v3
│ │ ├── metadata-nk3am-v3.json
│ │ ├── metadata-nk3am-v3.test.json
│ │ ├── metadata-nk3xn-v3.json
│ │ └── metadata-nk3xn-v3.test.json
│ ├── v4
│ │ ├── metadata-nk3am-v4.json
│ │ ├── metadata-nk3am-v4.test.json
│ │ ├── metadata-nk3xn-v4.json
│ │ └── metadata-nk3xn-v4.test.json
│ └── v5
│ │ ├── metadata-nk3am-v5.json
│ │ ├── metadata-nk3am-v5.test.json
│ │ ├── metadata-nk3xn-v5.json
│ │ └── metadata-nk3xn-v5.test.json
├── nitrokey.svg
├── requirements.in
└── requirements.txt
├── gen-commands-bd
├── Cargo.toml
└── src
│ └── main.rs
├── lpc55-builder
├── .gitignore
├── 70-lpc55.rules
├── Makefile
├── README.md
├── config
│ ├── cfpa.toml
│ ├── cmpa-develop.toml
│ ├── cmpa-empty.toml
│ ├── cmpa-release.toml
│ ├── flash-erase-all.toml
│ ├── flash-erase-firmware.toml
│ └── keystore.toml
├── jlink.gdb
├── jlink.sh
├── jlink
│ ├── connect.txt
│ └── erase.txt
└── scripts
│ ├── boot-to-bootrom.sh
│ └── usbwait.sh
├── manifest.template.json
├── nix
├── .gitignore
├── Makefile
├── nrf-command-line-tools
│ └── default.nix
└── shell.nix
├── nrf-bootloader
├── .gitignore
├── Dockerfile
├── Makefile
├── Makefile.bootloader
├── Makefile.docker
├── config
│ ├── default_sdk_config.h
│ ├── nk3am_sdk_config.h
│ ├── nkpk_sdk_config.h
│ └── sdk_config.h
├── generate_key.sh
├── secure_bootloader_gcc_nrf52.ld
├── sha256sums.txt
├── sign-bootloader.sh
├── sign.sh
├── src
│ ├── main.c
│ └── nrf_crypto_allocator.h
└── upload.sh
├── nrf-builder
├── .gitignore
├── Makefile
├── Makefile.nkpk
├── Makefile.test-ftl-migration
├── README.md
└── wait_for_usb.sh
├── nrf-debugging
├── Makefile
├── README.md
├── binary
├── binary.elf
├── gdb-stack.cmds
├── gdb.cmds
├── gdb_bt.cmds
├── gdb_regs.cmds
├── graph_stack.py
├── ocd.conf.example
├── ocdtool.py
├── parse-memrd.py
├── symbols.txt
└── walk.py
└── test-certificates
├── fido
├── nk-fido-ca-cert.der
├── nk-fido-ca-cert.pem
├── nk-fido-ca-key.pem
├── nk-fido-ca-key.trussed
├── nk-fido-ee-cert.der
├── nk-fido-ee-cert.pem
├── nk-fido-ee-key.pem
└── nk-fido-ee-key.trussed
├── firmware-lpc55
├── nk-firmware-ee1-cert.der
├── nk-firmware-ee1-cert.pem
├── nk-firmware-ee1-cert.viewable.pem
├── nk-firmware-ee1-key.der
├── nk-firmware-ee1-key.pem
├── nk-firmware-ee2-cert.der
├── nk-firmware-ee2-cert.pem
├── nk-firmware-ee2-cert.viewable.pem
├── nk-firmware-ee2-key.der
├── nk-firmware-ee2-key.pem
├── nk-firmware-ee3-cert.der
├── nk-firmware-ee3-cert.pem
├── nk-firmware-ee3-cert.viewable.pem
├── nk-firmware-ee3-key.der
├── nk-firmware-ee3-key.pem
├── nk-firmware-ee4-cert.der
├── nk-firmware-ee4-cert.pem
├── nk-firmware-ee4-cert.viewable.pem
├── nk-firmware-ee4-key.der
├── nk-firmware-ee4-key.pem
├── nk-firmware-root-cert.der
├── nk-firmware-root-cert.pem
├── nk-firmware-root-cert.viewable.pem
└── nk-firmware-root-key.pem
├── firmware-nk3am
├── dfu_private.key
├── dfu_public.pem
└── dfu_public_key.c
├── firmware-nkpk
├── dfu_private.key
├── dfu_public_key.c
└── dfu_public_key.pem
├── index.md
└── root
├── nk-root-cert.pem
├── nk-root-cert.viewable.pem
└── nk-root-key.pem
/.envrc:
--------------------------------------------------------------------------------
1 | export RUNNER=$(pwd)/platforms/lpc55/runner
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | binaries
2 | target
3 | **/.gdb_history
4 | ctap-2-1-pre.pdf
5 | solo-bee.code-workspace
6 | ref/
7 | memory.x
8 | solo-state.bin
9 | bee.littlefs2
10 | Cargo.lock
11 | !runners/lpc55/Cargo.lock
12 | !Cargo.lock
13 | /license.txt
14 | /commands.bd
15 | /manifest.json
16 | metrics.toml
17 | utils/nrf-debugging/binary
18 | utils/nrf-debugging/symbols.txt
19 | utils/nrf-debugging/ocd.conf
20 | utils/nrf-bootloader/build
21 | utils/nrf-bootloader/bootloader.hex
22 | utils/nrf-bootloader/mbr.hex
23 | utils/nrf-bootloader/signing-key
24 | utils/nrf-builder/bootloader-nk3am-nrf52-.zip
25 | utils/nrf-builder/bootloader-nk3am-nrf52-1.2.2.zip
26 | utils/nrf-builder/bootloader.hex
27 | utils/nrf-builder/csr.pem
28 | utils/nrf-builder/develop-nk3am-nrf52-.bin
29 | utils/nrf-builder/develop-nk3am-nrf52-.hex
30 | utils/nrf-builder/develop-nk3am-nrf52-.zip
31 | utils/nrf-builder/develop-nk3am-nrf52-1.2.2.bin
32 | utils/nrf-builder/develop-nk3am-nrf52-1.2.2.hex
33 | utils/nrf-builder/develop-nk3am-nrf52-1.2.2.zip
34 | utils/nrf-builder/firmware-nk3am-nrf52-.bin
35 | utils/nrf-builder/firmware-nk3am-nrf52-.hex
36 | utils/nrf-builder/firmware-nk3am-nrf52-.zip
37 | utils/nrf-builder/firmware-nk3am-nrf52-1.2.2.bin
38 | utils/nrf-builder/firmware-nk3am-nrf52-1.2.2.hex
39 | utils/nrf-builder/firmware-nk3am-nrf52-1.2.2.zip
40 | utils/nrf-builder/log.log
41 | utils/nrf-builder/mbr.hex
42 | utils/nrf-builder/provisioner-nk3am-nrf52-.bin
43 | utils/nrf-builder/provisioner-nk3am-nrf52-.hex
44 | utils/nrf-builder/provisioner-nk3am-nrf52-.zip
45 | utils/nrf-builder/provisioner-nk3am-nrf52-1.2.2.bin
46 | utils/nrf-builder/provisioner-nk3am-nrf52-1.2.2.hex
47 | utils/nrf-builder/provisioner-nk3am-nrf52-1.2.2.zip
48 | utils/nrf-builder/test-certs/
49 |
--------------------------------------------------------------------------------
/70-nitrokey-3.rules:
--------------------------------------------------------------------------------
1 | # Nitrokey 3 firmware
2 | SUBSYSTEM=="hidraw", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="42b2", TAG+="uaccess"
3 | SUBSYSTEM=="tty", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="42b2", TAG+="uaccess"
4 | SUBSYSTEM=="usb", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="42b2", TAG+="uaccess"
5 |
6 | # Nitrokey 3 bootloader
7 | SUBSYSTEM=="hidraw", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="42dd", TAG+="uaccess"
8 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = [
3 | "components/*",
4 | "runners/embedded",
5 | "runners/nkpk",
6 | "runners/usbip",
7 | "utils/collect-license-info",
8 | "utils/gen-commands-bd",
9 | ]
10 | resolver = "2"
11 |
12 | [workspace.package]
13 | version = "1.8.2"
14 |
15 | [workspace.dependencies]
16 | littlefs2 = "0.6"
17 |
18 | [patch.crates-io]
19 | # components
20 | memory-regions = { path = "components/memory-regions" }
21 |
22 | # unreleased libraries
23 | p256-cortex-m4 = { git = "https://github.com/ycrypto/p256-cortex-m4.git", rev = "cdb31e12594b4dc1f045b860a885fdc94d96aee2" }
24 | trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "e107ed315a07dc6c992fac39d542e847cc3a1b6c" }
25 | trussed-usbip = { git = "https://github.com/trussed-dev/pc-usbip-runner.git", rev = "504674453c9573a30aa2f155101df49eb2af1ba7" }
26 |
27 | # applications
28 | admin-app = { git = "https://github.com/Nitrokey/admin-app.git", tag = "v0.1.0-nitrokey.20" }
29 | fido-authenticator = { git = "https://github.com/Nitrokey/fido-authenticator.git",tag = "v0.1.1-nitrokey.27" }
30 | opcard = { git = "https://github.com/Nitrokey/opcard-rs", rev = "39ec4c37f808c0cfeb84e0a8493bbee06f02c8e2" }
31 | piv-authenticator = { git = "https://github.com/trussed-dev/piv-authenticator.git", tag = "v0.5.1" }
32 | secrets-app = { git = "https://github.com/Nitrokey/trussed-secrets-app", rev = "700863bdfa90a3616cbb695d6638c7aea7730c03" }
33 |
34 | # backends
35 | trussed-auth-backend = { git = "https://github.com/trussed-dev/trussed-auth", tag = "v0.4.0" }
36 | trussed-rsa-alloc = { git = "https://github.com/trussed-dev/trussed-rsa-backend.git", rev = "743d9aaa3d8a17d7dbf492bd54dc18ab8fca3dc0" }
37 | trussed-se050-backend = { git = "https://github.com/Nitrokey/trussed-se050-backend.git", rev = "be89dc04fc6b06505d2eed484802107b4aa3fe71" }
38 | trussed-staging = { git = "https://github.com/trussed-dev/trussed-staging.git", tag = "v0.3.3" }
39 | cargo-license = { git = "https://github.com/Nitrokey/cargo-license.git", rev = "d38912dc4b7a10d3cf48f8cf86f49640ff3173ab" }
40 | littlefs2-sys = { git = "https://github.com/trussed-dev/littlefs2-sys.git", rev = "v0.3.1-nitrokey.1" }
41 | littlefs2 = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "v0.6.1-nitrokey.1" }
42 | littlefs2-core = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "v0.6.1-nitrokey.1" }
43 |
44 | [profile.release]
45 | codegen-units = 1
46 | lto = "fat"
47 | opt-level = "z"
48 | incremental = false
49 | debug = true
50 |
51 | [profile.release-thin-lto]
52 | lto = "thin"
53 | inherits = "release"
54 |
55 | [profile.release.package.salty]
56 | opt-level = 2
57 |
58 | [profile.release-thin-lto.package.salty]
59 | opt-level = 2
60 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM rust:1.82.0
2 | RUN apt-get update && \
3 | apt-get install -y python3 python3-toml git curl llvm clang libclang-dev gcc-arm-none-eabi libc6-dev-i386 make wget zip
4 | RUN cargo install flip-link cargo-binutils
5 | RUN rustup target add thumbv7em-none-eabihf thumbv8m.main-none-eabi
6 | RUN rustup component add llvm-tools-preview clippy rustfmt
7 | RUN cargo install --git https://github.com/Nitrokey/nitrokey-ci --rev ef155b0c34317fab71405fe5e914d4732f8c9396 --locked
8 | RUN cargo install --git https://github.com/Nitrokey/repometrics --rev 98ffa20ddded8f09c0ef252b4e93ec6a9792f9dc --locked
9 | RUN rustup install nightly-2024-08-30
10 | RUN rustup component add rust-src --toolchain nightly-2024-08-30
11 | WORKDIR /app
12 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020 SoloKeys
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: check
2 | check:
3 | $(MAKE) -C runners/embedded check-all
4 | $(MAKE) -C runners/nkpk check
5 | $(MAKE) -C runners/usbip check
6 |
7 | .PHONY: check-components
8 | check-components:
9 | cargo check --manifest-path components/fm11nc08/Cargo.toml
10 | cargo check --manifest-path components/lfs-backup/Cargo.toml
11 | cargo check --manifest-path components/memory-regions/Cargo.toml
12 | cargo check --manifest-path components/ndef-app/Cargo.toml
13 | cargo check --manifest-path components/nfc-device/Cargo.toml
14 | cargo check --manifest-path components/provisioner-app/Cargo.toml
15 |
16 | cargo check --manifest-path components/apps/Cargo.toml
17 | for feature in nk3 nk3-test nk3-provisioner nkpk nkpk-provisioner ; do \
18 | echo "apps: $$feature" ; \
19 | cargo check --manifest-path components/apps/Cargo.toml --features $$feature ; \
20 | done
21 | cargo check --manifest-path components/apps/Cargo.toml --all-features
22 |
23 | cargo check --manifest-path components/boards/Cargo.toml
24 | for feature in board-nk3am board-nk3xn board-nkpk ; do \
25 | echo "boards: $$feature" ; \
26 | cargo check --manifest-path components/boards/Cargo.toml --features $$feature ; \
27 | done
28 |
29 | cargo check --manifest-path components/utils/Cargo.toml
30 | cargo check --manifest-path components/utils/Cargo.toml --all-features
31 |
32 | .PHONY: doc
33 | doc:
34 | $(MAKE) -C runners/embedded doc-nk3am
35 |
36 | .PHONY: lint
37 | lint:
38 | cargo fmt -- --check
39 | $(MAKE) -C runners/embedded lint-all
40 | $(MAKE) -C runners/nkpk lint
41 | $(MAKE) -C runners/usbip lint
42 |
43 | .PHONY: binaries
44 | binaries:
45 | mkdir -p binaries
46 | $(MAKE) -C runners/embedded build-all FEATURES=
47 | cp runners/embedded/artifacts/runner-lpc55-nk3xn.bin binaries/firmware-nk3xn.bin
48 | cp runners/embedded/artifacts/runner-lpc55-nk3xn.elf binaries/firmware-nk3xn.elf
49 | cp runners/embedded/artifacts/runner-nrf52-bootloader-nk3am.bin.ihex binaries/firmware-nk3am.ihex
50 | $(MAKE) -C runners/embedded build-all FEATURES=provisioner
51 | cp runners/embedded/artifacts/runner-lpc55-nk3xn.bin binaries/provisioner-nk3xn.bin
52 | cp runners/embedded/artifacts/runner-lpc55-nk3xn.elf binaries/provisioner-nk3xn.elf
53 | cp runners/embedded/artifacts/runner-nrf52-bootloader-nk3am.bin.ihex binaries/provisioner-nk3am.ihex
54 | $(MAKE) -C runners/embedded build-all FEATURES=test
55 | cp runners/embedded/artifacts/runner-lpc55-nk3xn.bin binaries/firmware-nk3xn-test.bin
56 | cp runners/embedded/artifacts/runner-lpc55-nk3xn.elf binaries/firmware-nk3xn-test.elf
57 | cp runners/embedded/artifacts/runner-nrf52-bootloader-nk3am.bin.ihex binaries/firmware-nk3am-test.ihex
58 | $(MAKE) -C runners/nkpk build
59 | cp runners/nkpk/artifacts/runner-nkpk.elf binaries/firmware-nkpk.elf
60 | cp runners/nkpk/artifacts/runner-nkpk.bin.ihex binaries/firmware-nkpk.ihex
61 | $(MAKE) -C runners/nkpk build FEATURES=provisioner
62 | cp runners/nkpk/artifacts/runner-nkpk.elf binaries/provisioner-nkpk.elf
63 | cp runners/nkpk/artifacts/runner-nkpk.bin.ihex binaries/provisioner-nkpk.ihex
64 |
65 | .PHONY: metrics
66 | metrics: binaries
67 | repometrics generate > metrics.toml
68 |
69 | license.txt:
70 | cargo run --release --manifest-path utils/collect-license-info/Cargo.toml -- runners/embedded/Cargo.toml "Nitrokey 3" > license.txt
71 |
72 | commands.bd:
73 | cargo run --release --manifest-path utils/gen-commands-bd/Cargo.toml -- runners/embedded/Cargo.toml > $@
74 |
75 | manifest.json:
76 | sed "s/@VERSION@/`git describe --always`/g" utils/manifest.template.json > manifest.json
77 |
78 | .PHONY: software-tests
79 | software-tests:
80 | cd components/apps && cargo test
81 | cd components/boards && cargo test
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Nitrokey 3 Firmware
2 |
3 | This repository contains the firmware of Nitrokey 3 USB keys.
4 |
5 | ## About
6 |
7 | The Nitrokey 3 firmware is written in [Rust][]. It uses the [Trussed][] firmware framework and is developed in collaboration with [SoloKeys][] (see the [solo2][] repository).
8 |
9 | [Rust]: https://rust-lang.org
10 | [Trussed]: https://trussed.dev/
11 | [SoloKeys]: https://solokeys.com/
12 | [solo2]: https://github.com/solokeys/solo2
13 |
14 | ## Documentation
15 |
16 | Documentation for users is available in the [Nitrokey 3 section on docs.nitrokey.com][docs.nitrokey.com]. For developer documentation, see the [`docs`](./docs/index.md) directory.
17 |
18 | [docs.nitrokey.com]: https://docs.nitrokey.com/nitrokey3/index.html
19 |
20 | ## Dependencies
21 |
22 | To build the firmware from source, you need these dependencies:
23 |
24 | - Rust (current stable release for the `thumbv8m.main-none-eabi` target with the `llvm-tools-preview` component)
25 | - clang with development headers
26 | - [`flip-link`][]
27 | - [`cargo-binutils`][]
28 |
29 | [`flip-link`]: https://github.com/knurling-rs/flip-link
30 | [`cargo-binutils`]: https://github.com/rust-embedded/cargo-binutils
31 |
32 | To flash the firmware to the device, you need [`mboot`][] or [`lpc55`][].
33 |
34 | [`mboot`]: https://github.com/molejar/pyMBoot
35 | [`lpc55`]: https://github.com/lpc55/lpc55-host
36 |
37 | ## License
38 |
39 | This software is fully open source.
40 |
41 | All software, unless otherwise noted, is dual licensed under [Apache 2.0](LICENSE-APACHE) and [MIT](LICENSE-MIT).
42 | You may use the software under the terms of either the Apache 2.0 license or MIT license.
43 |
44 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
45 |
46 | ## Funding
47 |
48 | [
](https://nlnet.nl/)
49 | [
](https://nlnet.nl/NGI0/)
50 |
51 | This project was funded through the [NGI0 PET](https://nlnet.nl/PET) Fund, a fund established by [NLnet](https://nlnet.nl/) with financial support from the European Commission's [Next Generation Internet programme](https://ngi.eu/), under the aegis of DG Communications Networks, Content and Technology under grant agreement No 825310.
52 |
--------------------------------------------------------------------------------
/components/apps/src/migrations.rs:
--------------------------------------------------------------------------------
1 | #![allow(unused)]
2 |
3 | use admin_app::migrations::Migrator;
4 | use littlefs2_core::path;
5 |
6 | pub(crate) const MIGRATION_VERSION_SPACE_EFFICIENCY: u32 = 1;
7 | const MIGRATION_VERSION_FIDO_RK_DIR: u32 = 2;
8 |
9 | #[cfg(feature = "backend-auth")]
10 | pub(crate) const TRUSSED_AUTH_FS_LAYOUT: trussed_auth_backend::FilesystemLayout =
11 | trussed_auth_backend::FilesystemLayout::V1;
12 | #[cfg(feature = "se050")]
13 | pub(crate) const SE050_BACKEND_FS_LAYOUT: trussed_se050_backend::FilesystemLayout =
14 | trussed_se050_backend::FilesystemLayout::V1;
15 |
16 | pub(crate) const MIGRATORS: &[Migrator] = &[
17 | // We first migrate the SE050 since this migration deletes data to make sure that the other
18 | // migrations succeed even on low block availability
19 | #[cfg(feature = "se050")]
20 | Migrator {
21 | migrate: |ifs, _efs| {
22 | trussed_se050_backend::migrate::migrate_remove_all_dat(ifs, &[path!("/opcard")])
23 | },
24 | version: MIGRATION_VERSION_SPACE_EFFICIENCY,
25 | },
26 | #[cfg(feature = "backend-auth")]
27 | Migrator {
28 | migrate: |ifs, _efs| {
29 | trussed_auth_backend::migrate::migrate_remove_dat(
30 | ifs,
31 | &[
32 | path!("opcard"),
33 | path!("webcrypt"),
34 | path!("secrets"),
35 | path!("piv"),
36 | ],
37 | )
38 | },
39 | version: MIGRATION_VERSION_SPACE_EFFICIENCY,
40 | },
41 | #[cfg(feature = "fido-authenticator")]
42 | Migrator {
43 | migrate: |ifs, _efs| fido_authenticator::migrate::migrate_no_rp_dir(ifs, path!("fido/dat")),
44 | version: MIGRATION_VERSION_FIDO_RK_DIR,
45 | },
46 | ];
47 |
--------------------------------------------------------------------------------
/components/boards/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "boards"
3 | edition = "2021"
4 | version.workspace = true
5 |
6 | [dependencies]
7 | apdu-dispatch = "0.3"
8 | apps = { path = "../apps", features = ["fido-authenticator"] }
9 | cortex-m = "0.7"
10 | cortex-m-rtic = "1.0"
11 | cortex-m-rt = "0.6.15"
12 | ctaphid-dispatch = "0.3"
13 | delog = "0.1"
14 | embedded-hal = "0.2.3"
15 | embedded-time = "0.12"
16 | generic-array = "0.14"
17 | interchange = "0.3"
18 | littlefs2 = { workspace = true, features = ["c-stubs"] }
19 | memory-regions = { path = "../memory-regions" }
20 | nb = "1"
21 | nfc-device = { path = "../nfc-device" }
22 | rand = { version = "0.8.5", default-features = false }
23 | rand_chacha = { version = "0.3.1", default-features = false }
24 | ref-swap = "0.1.0"
25 | spi-memory = "0.2.0"
26 | trussed = { version = "0.1", default-features = false }
27 | usb-device = "0.2"
28 | usbd-ccid = "0.3"
29 | usbd-ctaphid = "0.3"
30 | utils = { path = "../utils" }
31 |
32 | # soc-lpc55
33 | lpc55-hal = { version = "0.4", optional = true }
34 | lpc55-pac = { version = "0.4", optional = true }
35 | systick-monotonic = { version = "1.0.0", optional = true }
36 |
37 | # soc-nrf52
38 | embedded-storage = { version = "0.3", optional = true }
39 | nrf52840-hal = { version = "0.15.1", optional = true }
40 | nrf52840-pac = { version = "0.11", optional = true }
41 |
42 | # board-nk3am
43 | lfs-backup = { path = "../lfs-backup", optional = true }
44 |
45 | # board-nk3xn
46 | fm11nc08 = { path = "../fm11nc08", optional = true }
47 |
48 | # logging
49 | cortex-m-semihosting = { version = "0.3.5", optional = true }
50 | rtt-target = { version = "0.3", features = ["cortex-m"], optional = true }
51 |
52 | # se050
53 | se05x = { version = "0.2.0", optional = true }
54 |
55 | trussed-manage = "0.2.0"
56 |
57 | [dev-dependencies]
58 | littlefs2-core = { version = "0.1", features = ["debug-error"] }
59 |
60 | [features]
61 | board-nk3am = ["soc-nrf52", "lfs-backup", "se05x/embedded-hal-v0.2.7"]
62 | board-nk3xn = ["soc-lpc55", "fm11nc08", "utils/storage", "se05x/embedded-hal-v0.2.7"]
63 | board-nkpk = ["board-nk3am", "utils/storage"]
64 |
65 | soc-lpc55 = ["lpc55-hal", "lpc55-pac", "se05x?/lpc55-v0.4", "systick-monotonic"]
66 | soc-nrf52 = ["embedded-storage", "nrf52840-hal", "nrf52840-pac", "se05x?/nrf"]
67 |
68 | log-all = []
69 | log-trace = []
70 | log-debug = []
71 | log-info = []
72 | log-warn = []
73 | log-error = []
74 | log-none = []
75 |
76 | log-rtt = ["rtt-target"]
77 | log-semihosting = ["cortex-m-semihosting"]
78 |
79 | no-buttons = []
80 | no-delog = []
81 | no-encrypted-storage = []
82 | format-filesystem = []
83 | provisioner = ["apps/provisioner-app"]
84 | se050 = ["se05x", "apps/se050"]
85 | trussed-auth = ["apps/backend-auth"]
86 |
--------------------------------------------------------------------------------
/components/boards/src/nk3am/migrations/ftl_journal/backends.rs:
--------------------------------------------------------------------------------
1 | use littlefs2::driver::Storage;
2 | use trussed::types::Bytes;
3 |
4 | use lfs_backup::{BackupBackend, FSBackupError, Result, MAX_DUMP_BLOB_LENGTH};
5 |
6 | use crate::nk3am::ExternalFlashStorage;
7 |
8 | pub struct EFSBackupBackend<'a> {
9 | extflash: &'a mut ExternalFlashStorage,
10 | initial_offset: usize,
11 | offset: usize,
12 | len: usize,
13 | }
14 |
15 | impl<'a> EFSBackupBackend<'a> {
16 | pub fn new(extflash: &'a mut ExternalFlashStorage, offset: usize, len: usize) -> Self {
17 | Self {
18 | extflash,
19 | initial_offset: offset,
20 | offset,
21 | len,
22 | }
23 | }
24 | }
25 |
26 | impl BackupBackend for EFSBackupBackend<'_> {
27 | // would be good to get this from ext-flash directly
28 | const RW_SIZE: usize = 256;
29 |
30 | fn write(&mut self, content: &[u8]) -> Result {
31 | let len =
32 | content.len() + ((Self::RW_SIZE - (content.len() % Self::RW_SIZE)) % Self::RW_SIZE);
33 | let mut data: Bytes = Bytes::from_slice(content).unwrap();
34 |
35 | data.resize(len, 0x00)
36 | .map_err(|_| FSBackupError::BackendWriteErr)?;
37 |
38 | let count = self
39 | .extflash
40 | .write(self.offset, &data)
41 | .map_err(|_| FSBackupError::BackendWriteErr)?;
42 | self.offset += data.len();
43 |
44 | //trace_now!("W-addr: {} len: {} datalen: {}", self.offset, content.len(), data.len());
45 | //trace_now!("W-data: {} = {:?}", data);
46 |
47 | Ok(count)
48 | }
49 |
50 | fn read(&mut self, len: usize) -> Result> {
51 | let mut output = Bytes::::default();
52 | output.resize_default(len).expect("assuming: N > len");
53 |
54 | self.extflash
55 | .read(self.offset, &mut output)
56 | .map_err(|_| FSBackupError::BackendReadErr)?;
57 |
58 | self.offset +=
59 | output.len() + ((Self::RW_SIZE - (output.len() % Self::RW_SIZE)) % Self::RW_SIZE);
60 |
61 | //trace_now!("R-addr: {} len {:}", self.offset, output.len());
62 | //trace_now!("R-data {:?}", output);
63 |
64 | Ok(output)
65 | }
66 |
67 | fn erase(&mut self) -> Result {
68 | self.extflash
69 | .erase(self.initial_offset, self.len)
70 | .map_err(|_| FSBackupError::BackendEraseErr)?;
71 | self.offset = self.initial_offset;
72 | Ok(self.len)
73 | }
74 |
75 | fn reset(&mut self) {
76 | self.offset = self.initial_offset;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/components/boards/src/nk3am/migrations/ftl_journal/ifs_flash_old.rs:
--------------------------------------------------------------------------------
1 | use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
2 |
3 | use crate::nk3am::MEMORY_REGIONS;
4 |
5 | const FS_BASE: usize = MEMORY_REGIONS.filesystem.start;
6 | const FS_CEIL: usize = MEMORY_REGIONS.filesystem.end;
7 |
8 | pub const FLASH_BASE: *mut u8 = FS_BASE as *mut u8;
9 | pub const FLASH_SIZE: usize = FS_CEIL - FS_BASE;
10 |
11 | pub struct FlashStorage {
12 | nvmc: nrf52840_hal::nvmc::Nvmc,
13 | }
14 |
15 | impl littlefs2::driver::Storage for FlashStorage {
16 | const BLOCK_SIZE: usize = 256;
17 | const READ_SIZE: usize = 4;
18 | const WRITE_SIZE: usize = 4;
19 | const BLOCK_COUNT: usize = FLASH_SIZE / Self::BLOCK_SIZE;
20 |
21 | type CACHE_SIZE = generic_array::typenum::U256;
22 | type LOOKAHEAD_SIZE = generic_array::typenum::U1;
23 |
24 | fn read(&mut self, off: usize, buf: &mut [u8]) -> Result {
25 | // w/o this too much spam is generated, thus writes/deletes traces get lost
26 | if buf.len() > 4 {
27 | trace!("IFr {:x} {:x}", off, buf.len());
28 | }
29 | let res = self.nvmc.read(off as u32, buf);
30 | nvmc_to_lfs_return(res, buf.len())
31 | }
32 |
33 | fn write(&mut self, off: usize, buf: &[u8]) -> Result {
34 | trace!("IFw {:x} {:x}", off, buf.len());
35 | let res = self.nvmc.write(off as u32, buf);
36 | nvmc_to_lfs_return(res, buf.len())
37 | }
38 |
39 | fn erase(&mut self, off: usize, len: usize) -> Result {
40 | trace!("EE {:x} {:x}", off, len);
41 |
42 | const REAL_BLOCK_SIZE: usize = 4 * 1024;
43 |
44 | let block_off: usize = off - (off % REAL_BLOCK_SIZE);
45 |
46 | let mut buf: [u8; REAL_BLOCK_SIZE] = [0x00; REAL_BLOCK_SIZE];
47 | self.nvmc
48 | .read(block_off as u32, &mut buf)
49 | .expect("EE - failed read");
50 | let erase_res = self
51 | .nvmc
52 | .erase(block_off as u32, (block_off + REAL_BLOCK_SIZE) as u32);
53 |
54 | let left_end: usize = off - block_off;
55 | if left_end > 0 {
56 | self.nvmc
57 | .write(block_off as u32, &buf[..left_end])
58 | .expect("EE - failed write 1");
59 | }
60 |
61 | let right_off: usize = left_end + len;
62 | if REAL_BLOCK_SIZE - right_off > 0 {
63 | self.nvmc
64 | .write((off + len) as u32, &buf[right_off..])
65 | .expect("EE - failed write 2");
66 | }
67 |
68 | nvmc_to_lfs_return(erase_res, len)
69 | }
70 | }
71 |
72 | /**
73 | * Source Result type does not provide a useful Ok value, and Destination Result type
74 | * does not contain a meaningful low-level error code we could return; so here goes
75 | * the most stupid result conversion routine ever
76 | */
77 | fn nvmc_to_lfs_return(
78 | r: Result<(), nrf52840_hal::nvmc::NvmcError>,
79 | len: usize,
80 | ) -> Result {
81 | r.map(|_| len).map_err(|_| littlefs2::io::Error::IO) // 'NVMC'
82 | }
83 |
84 | impl FlashStorage {
85 | pub fn new(nvmc_pac: nrf52840_hal::pac::NVMC) -> Self {
86 | let buf = unsafe { core::slice::from_raw_parts_mut(FLASH_BASE, FLASH_SIZE) };
87 | let nvmc = nrf52840_hal::nvmc::Nvmc::new(nvmc_pac, buf);
88 | Self { nvmc }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/components/boards/src/nk3am/migrations/ftl_journal/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod backends;
2 | pub mod ifs_flash_old;
3 |
4 | use littlefs2::fs::{Allocation, Filesystem};
5 |
6 | use backends::EFSBackupBackend;
7 | use ifs_flash_old::FlashStorage as OldFlashStorage;
8 | use lfs_backup::{BackupBackend, FSBackupError, Result};
9 |
10 | use crate::nk3am::{ExternalFlashStorage, InternalFlashStorage};
11 |
12 | pub fn migrate(
13 | old_ifs_storage: &mut OldFlashStorage,
14 | old_ifs_alloc: &mut Allocation,
15 | ifs_alloc: &mut Allocation,
16 | ifs_storage: &mut InternalFlashStorage,
17 | efs_storage: &mut ExternalFlashStorage,
18 | ) -> Result<()> {
19 | let old_mounted = Filesystem::mount(old_ifs_alloc, old_ifs_storage)
20 | .map_err(|_| FSBackupError::LittleFs2Err)?;
21 |
22 | trace!("old IFS mount success - migrating");
23 |
24 | // ext.flash = 2MB, spare for e.g., backup operations = 128kb (at end)
25 | let spare_len = 4096 * 32;
26 | let spare_offset = (2 * 1024 * 1024) - spare_len;
27 | let mut backend = EFSBackupBackend::new(efs_storage, spare_offset, spare_len);
28 |
29 | backend.erase()?;
30 |
31 | trace!("backing: old IFS -> backend");
32 | backend.backup(&old_mounted)?;
33 |
34 | // only format IFS on failed backup...
35 | trace!("backup done, format new IFS");
36 | let _fmt_ifs = Filesystem::format(ifs_storage);
37 | ifs_storage.format_journal_blocks();
38 |
39 | let new_mounted =
40 | Filesystem::mount(ifs_alloc, ifs_storage).map_err(|_| FSBackupError::LittleFs2Err)?;
41 |
42 | trace!("restore: backend -> new IFS");
43 | backend.reset();
44 | let _res = backend.restore(&new_mounted)?;
45 |
46 | // any outcome should erase the external flash contents
47 | backend.erase()?;
48 | Ok(())
49 | }
50 |
--------------------------------------------------------------------------------
/components/boards/src/nk3am/migrations/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod ftl_journal;
2 |
--------------------------------------------------------------------------------
/components/boards/src/nk3xn.rs:
--------------------------------------------------------------------------------
1 | #[cfg(feature = "se050")]
2 | use embedded_hal::{blocking::delay::DelayUs, timer::CountDown};
3 | #[cfg(feature = "se050")]
4 | use embedded_time::duration::Microseconds;
5 | #[cfg(feature = "se050")]
6 | use lpc55_hal::drivers::Timer;
7 | use lpc55_hal::{
8 | drivers::pins::{Pio0_9, Pio1_14},
9 | peripherals::{ctimer, flexcomm::I2c5},
10 | typestates::{
11 | init_state::Unknown,
12 | pin::{
13 | function::{FC5_CTS_SDA_SSEL0, FC5_TXD_SCL_MISO_WS},
14 | state::Special,
15 | },
16 | },
17 | I2cMaster, Pin,
18 | };
19 | #[cfg(feature = "se050")]
20 | use se05x::embedded_hal::Hal027;
21 |
22 | use memory_regions::MemoryRegions;
23 | use utils::OptionalStorage;
24 |
25 | use crate::{flash::ExtFlashStorage, soc::lpc55::Lpc55, Board};
26 |
27 | pub mod button;
28 | pub mod led;
29 | pub mod nfc;
30 | pub mod prince;
31 | pub mod spi;
32 |
33 | #[cfg(feature = "no-encrypted-storage")]
34 | use trussed::types::LfsResult;
35 |
36 | #[cfg(feature = "no-encrypted-storage")]
37 | lpc55_hal::littlefs2_filesystem!(InternalFilesystem: (prince::FS_START, prince::BLOCK_COUNT));
38 | #[cfg(not(feature = "no-encrypted-storage"))]
39 | use prince::InternalFilesystem;
40 |
41 | use nfc::NfcChip;
42 | use spi::{FlashCs, Spi};
43 |
44 | pub const MEMORY_REGIONS: &MemoryRegions = &MemoryRegions::NK3XN;
45 |
46 | pub type PwmTimer = ctimer::Ctimer3;
47 | pub type ButtonsTimer = ctimer::Ctimer1;
48 |
49 | pub type I2C = I2cMaster<
50 | Pio0_9,
51 | Pio1_14,
52 | I2c5,
53 | (
54 | Pin>,
55 | Pin>,
56 | ),
57 | >;
58 |
59 | pub struct NK3xN;
60 |
61 | impl Board for NK3xN {
62 | type Soc = Lpc55;
63 |
64 | type Resources = ();
65 |
66 | type NfcDevice = NfcChip;
67 | type Buttons = button::ThreeButtons;
68 | type Led = led::RgbLed;
69 |
70 | type InternalStorage = InternalFlashStorage;
71 | type ExternalStorage = ExternalFlashStorage;
72 |
73 | #[cfg(feature = "se050")]
74 | type Se050Timer = Hal027>>>;
75 | #[cfg(feature = "se050")]
76 | type Twi = Hal027;
77 | #[cfg(not(feature = "se050"))]
78 | type Twi = ();
79 | #[cfg(not(feature = "se050"))]
80 | type Se050Timer = ();
81 |
82 | const BOARD_NAME: &'static str = "nk3xn";
83 | const HAS_NFC: bool = true;
84 | }
85 |
86 | pub type InternalFlashStorage = InternalFilesystem;
87 | pub type ExternalFlashStorage = OptionalStorage>;
88 |
89 | #[cfg(feature = "se050")]
90 | pub struct TimerDelay(pub T);
91 |
92 | #[cfg(feature = "se050")]
93 | impl DelayUs for TimerDelay
94 | where
95 | T: CountDown