From f2496a8e6d71a4e838884996a1c9b62121f87df2 Mon Sep 17 00:00:00 2001
From: kaczmarczyck <43844792+kaczmarczyck@users.noreply.github.com>
Date: Fri, 19 Nov 2021 13:42:39 +0100
Subject: [PATCH] Ported documentation (#413)
* ported documentation from develop
* adapted instructions
* fix broken English
---
README.md | 219 +++++---------------
docs/boards/nrf52840_dongle.md | 85 ++++++++
docs/boards/nrf52840_feitian.md | 23 +++
docs/boards/nrf52840_mdk.md | 47 +++++
docs/boards/nrf52840dk.md | 50 +++++
docs/customization.md | 78 ++++++++
docs/debugging.md | 137 +++++++++++++
docs/img/enclosure.jpg | Bin 0 -> 557037 bytes
docs/install.md | 343 ++++++--------------------------
9 files changed, 526 insertions(+), 456 deletions(-)
create mode 100644 docs/boards/nrf52840_dongle.md
create mode 100644 docs/boards/nrf52840_feitian.md
create mode 100644 docs/boards/nrf52840_mdk.md
create mode 100644 docs/boards/nrf52840dk.md
create mode 100644 docs/customization.md
create mode 100644 docs/debugging.md
create mode 100644 docs/img/enclosure.jpg
diff --git a/README.md b/README.md
index 3a51ee2..2db816b 100644
--- a/README.md
+++ b/README.md
@@ -10,194 +10,67 @@
This repository contains a Rust implementation of a
[FIDO2](https://fidoalliance.org/fido2/) authenticator.
+We developed OpenSK as a [Tock OS](https://tockos.org) application.
-We developed this as a [Tock OS](https://tockos.org) application and it has been
-successfully tested on the following boards:
-
-* [Nordic nRF52840-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)
-* [Nordic nRF52840-dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle)
-
-## Disclaimer
-
-This project is **proof-of-concept and a research platform**. It is **NOT**
-meant for a daily usage. It's still under development and as such comes with a
-few limitations:
+We intend to bring a full open source experience to security keys, from
+application to operating system. You can even 3D print your own open source
+enclosure!
+You can see OpenSK in action in this
+[video on YouTube](https://www.youtube.com/watch?v=klEozvpw0xg)!
### FIDO2
-The stable branch implements the published
-[CTAP2.0 specifications](https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html)
-and is FIDO certified.
+The stable branch implements the
+[CTAP2.0 specification](https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html)
+and is FIDO certified. OpenSK supports U2F, and non-discoverable credentials
+created with either protocol are compatible with the other.
-
+If you want to use features of the newer FIDO 2.1, you can try our
+[develop branch](https://github.com/google/OpenSK/tree/develop). This version is
+NOT certified and less thoroughly tested though. If you plan to add features to
+OpenSK, you should switch to develop.
-It already contains some preview features of 2.1, that you can try by adding the
-flag `--ctap2.1` to the deploy command. The full
-[CTAP2.1 specification](https://fidoalliance.org/specs/fido-v2.1-rd-20201208/fido-client-to-authenticator-protocol-v2.1-rd-20201208.html)
-is work in progress in the develop branch and is tested less thoroughly.
+### :warning: Disclaimer
-### Cryptography
+This project is **proof-of-concept and a research platform**. It is **NOT**
+meant for a daily usage. The cryptography implementations are not resistent
+against side-channel attacks.
-We're currently still in the process on making the
+We're still in the process of integrating the
[ARM® CryptoCell-310](https://developer.arm.com/ip-products/security-ip/cryptocell-300-family)
embedded in the
[Nordic nRF52840 chip](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Fcryptocell.html)
-work to get hardware-accelerated cryptography. In the meantime we implemented
-the required cryptography algorithms (ECDSA, ECC secp256r1, HMAC-SHA256 and
-AES256) in Rust as a placeholder. Those implementations are research-quality
-code and haven't been reviewed. They don't provide constant-time guarantees and
-are not designed to be resistant against side-channel attacks.
+to enable hardware-accelerated cryptography. Our placeholder implementations of required
+cryptography algorithms (ECDSA, ECC secp256r1, HMAC-SHA256 and AES256) in Rust are research-quality
+code. They haven't been reviewed and don't provide constant-time guarantees.
+
+## Hardware
+
+You will need one the following supported boards:
+
+* [Nordic nRF52840-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)
+ development kit. This board is more convenient for development and debug
+ scenarios as the JTAG probe is already on the board.
+* [Nordic nRF52840 Dongle](https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF52840-Dongle)
+ to have a more practical form factor.
+* [Makerdiary nRF52840-MDK USB dongle](https://wiki.makerdiary.com/nrf52840-mdk/).
+* [Feitian OpenSK dongle](https://feitiantech.github.io/OpenSK_USB/).
## Installation
-For a more detailed guide, please refer to our
-[installation guide](docs/install.md).
+To install OpenSK,
+1. follow the [general setup steps](docs/install.md),
+1. then continue with the instructions for your specific hardware:
+ * [Nordic nRF52840-DK](docs/boards/nrf52840dk.md)
+ * [Nordic nRF52840 Dongle](docs/boards/nrf52840_dongle.md)
+ * [Makerdiary nRF52840-MDK USB dongle](docs/boards/nrf52840_mdk.md)
+ * [Feitian OpenSK dongle](docs/boards/nrf52840_feitian.md)
-1. If you just cloned this repository, run the following script (**Note**: you
- only need to do this once):
-
- ```shell
- ./setup.sh
- ```
-
-1. Next step is to install Tock OS as well as the OpenSK application on your
- board. Run:
-
- ```shell
- # Nordic nRF52840-DK board
- ./deploy.py --board=nrf52840dk --opensk
- # Nordic nRF52840-Dongle
- ./deploy.py --board=nrf52840_dongle --opensk
- ```
-
-1. Finally you need to inject the cryptographic material if you enabled
- batch attestation or CTAP1/U2F compatibility (which is the case by
- default):
-
- ```shell
- ./tools/configure.py \
- --certificate=crypto_data/opensk_cert.pem \
- --private-key=crypto_data/opensk.key
- ```
-
-1. On Linux, you may want to avoid the need for `root` privileges to interact
- with the key. For that purpose we provide a udev rule file that can be
- installed with the following command:
-
- ```shell
- sudo cp rules.d/55-opensk.rules /etc/udev/rules.d/ &&
- sudo udevadm control --reload
- ```
-
-### Customization
-
-If you build your own security key, depending on the hardware you use, there are
-a few things you can personalize:
-
-1. If you have multiple buttons, choose the buttons responsible for user
- presence in `main.rs`.
-2. Decide whether you want to use batch attestation. There is a boolean flag in
- `ctap/mod.rs`. It is mandatory for U2F, and you can create your own
- self-signed certificate. The flag is used for FIDO2 and has some privacy
- implications. Please check
- [WebAuthn](https://www.w3.org/TR/webauthn/#attestation) for more
- information.
-3. Decide whether you want to use signature counters. Currently, only global
- signature counters are implemented, as they are the default option for U2F.
- The flag in `ctap/mod.rs` only turns them off for FIDO2. The most privacy
- preserving solution is individual or no signature counters. Again, please
- check [WebAuthn](https://www.w3.org/TR/webauthn/#signature-counter) for
- documentation.
-4. Depending on your available flash storage, choose an appropriate maximum
- number of supported residential keys and number of pages in
- `ctap/storage.rs`.
-5. Change the default level for the credProtect extension in `ctap/mod.rs`.
- When changing the default, resident credentials become undiscoverable without
- user verification. This helps privacy, but can make usage less comfortable
- for credentials that need less protection.
-6. Increase the default minimum length for PINs in `ctap/storage.rs`.
- The current minimum is 4. Values from 4 to 63 are allowed. Requiring longer
- PINs can help establish trust between users and relying parties. It makes
- user verification harder to break, but less convenient.
- NIST recommends at least 6-digit PINs in section 5.1.9.1:
- https://pages.nist.gov/800-63-3/sp800-63b.html
- You can add relying parties to the list of readers of the minimum PIN length.
-
-### 3D printed enclosure
-
-To protect and carry your key, we partnered with a professional designer and we
-are providing a custom enclosure that can be printed on both professional 3D
-printers and hobbyist models.
-
-All the required files can be downloaded from
-[Thingiverse](https://www.thingiverse.com/thing:4132768) including the STEP
-file, allowing you to easily make the modifications you need to further
-customize it.
-
-## Development and testing
-
-### Printing panic messages to the console
-
-By default, libtock-rs blinks some LEDs when the userspace application panicks.
-This is not always convenient as the panic message is lost. In order to enable
-a custom panic handler that first writes the panic message via Tock's console
-driver, before faulting the app, you can use the `--panic-console` flag of the
-`deploy.py` script.
-
-```shell
-# Example on Nordic nRF52840-DK board
-./deploy.py --board=nrf52840dk --opensk --panic-console
-```
-
-### Debugging memory allocations
-
-You may want to track memory allocations to understand the heap usage of
-OpenSK. This can be useful if you plan to port it to a board with fewer
-available RAM for example. To do so, you can enable the `--debug-allocations`
-flag of the `deploy.py` script. This enables a custom (userspace) allocator
-that prints a message to the console for each allocation and deallocation
-operation.
-
-The additional output looks like the following.
-
-```text
-# Allocation of 256 byte(s), aligned on 1 byte(s). The allocated address is
-# 0x2002401c. After this operation, 2 pointers have been allocated, totalling
-# 384 bytes (the total heap usage may be larger, due to alignment and
-# fragmentation of allocations within the heap).
-alloc[256, 1] = 0x2002401c (2 ptrs, 384 bytes)
-# Deallocation of 64 byte(s), aligned on 1 byte(s), from address 0x2002410c.
-# After this operation, 1 pointers are allocated, totalling 512 bytes.
-dealloc[64, 1] = 0x2002410c (1 ptrs, 512 bytes)
-```
-
-A tool is provided to analyze such reports, in `tools/heapviz`. This tool
-parses the console output, identifies the lines corresponding to (de)allocation
-operations, and first computes some statistics:
-
-* Address range used by the heap over this run of the program,
-* Peak heap usage (how many useful bytes are allocated),
-* Peak heap consumption (how many bytes are used by the heap, including
- unavailable bytes between allocated blocks, due to alignment constraints and
- memory fragmentation),
-* Fragmentation overhead (difference between heap consumption and usage).
-
-Then, the `heapviz` tool displays an animated "movie" of the allocated bytes in
-heap memory. Each frame in this "movie" shows bytes that are currently
-allocated, that were allocated but are now freed, and that have never been
-allocated. A new frame is generated for each (de)allocation operation. This tool
-uses the `ncurses` library, that you may have to install beforehand.
-
-You can control the tool with the following parameters:
-
-* `--logfile` (required) to provide the file which contains the console output
- to parse,
-* `--fps` (optional) to customize the number of frames per second in the movie
- animation.
-
-```shell
-cargo run --manifest-path tools/heapviz/Cargo.toml -- --logfile console.log --fps 50
-```
+To test whether the installation was successful, visit a
+[demo website](https://webauthn.io/) and try to register and login.
+Please check our [Troubleshooting and Debugging](docs/debugging.md) section if you
+have problems with the installation process or during development. To find out what
+else you can do with your OpenSK, see [Customization](docs/customization.md).
## Contributing
diff --git a/docs/boards/nrf52840_dongle.md b/docs/boards/nrf52840_dongle.md
new file mode 100644
index 0000000..e7c3982
--- /dev/null
+++ b/docs/boards/nrf52840_dongle.md
@@ -0,0 +1,85 @@
+#
+
+## Nordic nRF52840 Dongle
+
+
+
+### 3D printed enclosure
+
+To protect and carry your key, we partnered with a professional designer and we
+are providing a custom enclosure that can be printed on both professional 3D
+printers and hobbyist models.
+
+
+
+All the required files can be downloaded from
+[Thingiverse](https://www.thingiverse.com/thing:4132768) including the STEP
+file, allowing you to easily make the modifications you need to further
+customize it.
+
+### Flashing using DFU (preferred method)
+
+To flash the firmware, run:
+
+```shell
+./deploy.py --board=nrf52840_dongle_dfu --opensk --programmer=nordicdfu
+```
+
+The script will ask you to switch to DFU mode. To activate that on your dongle,
+keep the button pressed while inserting the device into your USB port. You may
+additionally need to press the tiny, sideways facing reset button. The device
+indicates DFU mode with a slowly blinking red LED.
+
+### Flashing with an external programmer (JLink, OpenOCD, etc.)
+
+If you want to use JTAG with the dongle, you need additional hardware.
+
+* a [Segger J-Link](https://www.segger.com/products/debug-probes/j-link/) JTAG
+ probe.
+* a
+ [TC2050 Tag-Connect programming cable](https://www.tag-connect.com/product/tc2050-idc-nl-10-pin-no-legs-cable-with-ribbon-connector).
+* a [Tag-Connect TC2050 ARM2010](http://www.tag-connect.com/TC2050-ARM2010)
+ adaptor
+* optionally a
+ [Tag-Connect TC2050 retainer clip](http://www.tag-connect.com/TC2050-CLIP)
+ to keep the spring loaded connector pressed to the PCB.
+
+Follow these steps:
+
+1. The JTAG probe used for programming won't provide power to the board.
+ Therefore you will need to use a USB-A extension cable to power the dongle
+ through its USB port.
+
+1. Connect the TC2050 cable to the pads below the PCB:
+
+ 
+
+1. You can use the retainer clip if you have one to avoid maintaining pressure
+ between the board and the cable:
+
+ 
+
+1. Depending on the programmer you're using, you may have to adapt the next
+ command line. Run our script for compiling/flashing Tock OS on your device:
+
+ ```shell
+ $ ./deploy.py --board=nrf52840_dongle --programmer=jlink
+ ```
+
+1. Remove the programming cable and the USB-A extension cable.
+
+### Buttons and LEDs
+
+The bigger, white button conveys user presence to the application. Some actions
+like register and login will make the dongle blink, asking you to confirm the
+transaction with a button press. The small, sideways pointing buttong next to it
+restarts the dongle.
+
+The 2 LEDs show the state of the app. There are different patterns:
+
+| Pattern | Cause |
+|------------------------------------|------------------------|
+| all LEDs and colors | app panic |
+| green and blue blinking | asking for touch |
+| all LEDs and colors for 5s | wink (just saying Hi!) |
+| red slow blink | DFU mode |
diff --git a/docs/boards/nrf52840_feitian.md b/docs/boards/nrf52840_feitian.md
new file mode 100644
index 0000000..664df7b
--- /dev/null
+++ b/docs/boards/nrf52840_feitian.md
@@ -0,0 +1,23 @@
+#
+
+## Feitian OpenSK USB Dongle
+
+### Flashing using DFU
+
+This board is similar in hardware to the Nordic nRF52840 Dongle. You can use DFU
+to flash it, instructions to enter DFU mode depend on the version of your
+hardware. See
+[Feitian's instructions](https://feitiantech.github.io/OpenSK_USB/). In short:
+
+* In V1, use a paperclip to press the Reset button through the tiny hole.
+* In V2, push and hold the user button for more than 10 seconds after
+ connecting your device.
+
+Afterwards, you can flash your Feitian OpenSK using DFU following the
+[instructions for the Nordic nRF52840 Dongle](nrf52840_dongle.md#Flashing-using-DFU).
+
+### Buttons and LEDs
+
+For both hardware versions, the buttons and LEDs are described in detail in the
+[hardware section](https://feitiantech.github.io/OpenSK_USB/hardware/) of
+Feitian's website.
diff --git a/docs/boards/nrf52840_mdk.md b/docs/boards/nrf52840_mdk.md
new file mode 100644
index 0000000..30d74b5
--- /dev/null
+++ b/docs/boards/nrf52840_mdk.md
@@ -0,0 +1,47 @@
+#
+
+## Nordic nRF52840 MDK
+
+Makerdiary has instructions on their [website](https://wiki.makerdiary.com/nrf52840-mdk-usb-dongle/opensk/). They use a custom script to deploy via DFU.
+
+After general setup, you still need these steps:
+
+1. Create the hexfile with the firmware.
+
+ ```shell
+ ./deploy.py --board=nrf52840_mdk_dfu --opensk --programmer=none
+ ```
+
+1. Download the
+ [script](https://github.com/makerdiary/nrf52840-mdk-usb-dongle/blob/master/tools/uf2conv.py)
+ from Makerdiary's GitHub into the OpenSK repository.
+
+1. Run the script:
+
+ ```shell
+ python3 uf2conv.py -c -f 0xada52840 -o target/opensk.uf2 target/nrf52840_mdk_dfu_merged.hex
+ ```
+
+1. Boot into DFU mode. Keep the user button pressed on your hardware while
+ inserting it into a USB slot. You should see a bit of red blinking, and then
+ a constant green light.
+
+1. Your dongle should appear in your normal file browser like other USB sticks.
+ Copy the file `target/opensk.uf2` over.
+
+1. Replug to reboot.
+
+### Buttons and LEDs
+
+The big, white button conveys user presence to the application. Some actions
+like register and login will make the device blink, asking you to confirm the
+transaction with a button press.
+
+The LED shows the state of the app. There are different patterns:
+
+| Pattern | Cause |
+|------------------------------------|------------------------|
+| red glow | busy |
+| red and blue blinking | asking for touch |
+| red, green, white pattern for 5s | wink (just saying Hi!) |
+| constant green | DFU mode |
diff --git a/docs/boards/nrf52840dk.md b/docs/boards/nrf52840dk.md
new file mode 100644
index 0000000..5bf7d50
--- /dev/null
+++ b/docs/boards/nrf52840dk.md
@@ -0,0 +1,50 @@
+#
+
+## Nordic nRF52840-DK board
+
+
+
+### Flashing using JTAG
+
+The development board comes with its own JTAG port, so the default programmer
+is the easiest and most convenient. You can flash OpenSK with these steps:
+
+1. Connect a micro USB cable to the JTAG USB port.
+
+1. Run our script for compiling/flashing Tock OS and OpenSK on your device:
+
+ ```shell
+ ./deploy.py --board=nrf52840dk --opensk
+ ```
+
+1. Connect a micro USB cable to the device USB port.
+
+**Note**: Due to current limitations of our implementation and Tock, you may
+have to press the `BOOT/RESET` button, located next to the device USB port on
+the board in order to see your OpenSK device on your system.
+
+### Buttons and LEDs
+
+Out of the 5 buttons, the group of 4 behaves identically. They all convey user
+presence to the application. Some actions like register and login will make the
+board blink, asking you to confirm the transaction with a button press. The
+remaining fifth button restarts the board.
+
+The group of 4 LEDs on the right show the state of the app. There are different
+patterns:
+
+| Pattern | Cause |
+|------------------------------------|------------------------|
+| LED1 slow blink | kernel panic |
+| all LEDs blinking together | app panic |
+| LED1+4 and LED2+3 fast alternating | asking for touch |
+| fast swirling | wink (just saying Hi!) |
+| circle | allocator panic |
+
+The LEDs closer to the JTAG port indicates the power and debugging state.
+
+There are 3 switches that need to be in the correct position:
+
+* Power (bottom left): On
+* nRF power source (center left): VDD
+* SW6 (top right): DEFAULT
diff --git a/docs/customization.md b/docs/customization.md
new file mode 100644
index 0000000..ca29099
--- /dev/null
+++ b/docs/customization.md
@@ -0,0 +1,78 @@
+#
+
+## Customization
+
+### Cryptographic material
+
+All the generated certificates and private keys are stored in the directory
+`crypto_data/`. The expected content after running our `setup.sh` script is:
+
+File | Purpose
+------------------------ | --------------------------------------------------------
+`aaguid.txt` | Text file containaing the AAGUID value
+`opensk_ca.csr` | Certificate sign request for the Root CA
+`opensk_ca.key` | ECC secp256r1 private key used for the Root CA
+`opensk_ca.pem` | PEM encoded certificate of the Root CA
+`opensk_ca.srl` | File generated by OpenSSL
+`opensk_cert.csr` | Certificate sign request for the attestation certificate
+`opensk_cert.pem` | PEM encoded certificate used for the authenticator
+`opensk.key` | ECC secp256r1 private key used for the autenticator
+
+If you want to use your own attestation certificate and private key,
+replace the `opensk_cert.pem` and `opensk.key` files. The script at
+`tools/configure.py` customizes an OpenSK device with the correct certificate
+and private key.
+
+Our build script `build.rs` is responsible for converting the `aaguid.txt` file
+into raw data that is then used by the Rust file `src/ctap/key_material.rs`.
+
+Please make sure to safely store all private key material before calling
+`reset.sh`, or the files will be lost.
+
+#### Certificate considerations
+
+The certificate on OpenSK is used for attestation. That means, whenever you
+register OpenSK on a website, you attest the legitimacy of your hardware. For
+self-generated certificates, this claim is rather trivial. Still, it is required
+by some websites and to use U2F.
+
+Usually, the attestation private key is shared between a batch of at least
+100,000 security keys of the same model. If you build your own OpenSK, your
+private key is unique to you. This makes you identifiable across registrations:
+Two websites could collaborate to track if registrations were attested with the
+same key material. If you use OpenSK beyond experimentation, please consider
+carefully if you want to take this privacy risk.
+
+### Software personalization
+
+If you build your own security key, depending on the hardware you use, there are
+a few things you can personalize:
+
+1. If you have multiple buttons, choose the buttons responsible for user
+ presence in `main.rs`.
+2. Decide whether you want to use batch attestation. There is a boolean flag in
+ `ctap/mod.rs`. It is mandatory for U2F, and you can create your own
+ self-signed certificate. The flag is used for FIDO2 and has some privacy
+ implications. Please check
+ [WebAuthn](https://www.w3.org/TR/webauthn/#attestation) for more
+ information.
+3. Decide whether you want to use signature counters. Currently, only global
+ signature counters are implemented, as they are the default option for U2F.
+ The flag in `ctap/mod.rs` only turns them off for FIDO2. The most privacy
+ preserving solution is individual or no signature counters. Again, please
+ check [WebAuthn](https://www.w3.org/TR/webauthn/#signature-counter) for
+ documentation.
+4. Depending on your available flash storage, choose an appropriate maximum
+ number of supported resident keys and number of pages in
+ `ctap/storage.rs`.
+5. Change the default level for the credProtect extension in `ctap/mod.rs`.
+ When changing the default, resident credentials become undiscoverable without
+ user verification. This helps privacy, but can make usage less comfortable
+ for credentials that need less protection.
+6. Increase the default minimum length for PINs in `ctap/storage.rs`.
+ The current minimum is 4. Values from 4 to 63 are allowed. Requiring longer
+ PINs can help establish trust between users and relying parties. It makes
+ user verification harder to break, but less convenient.
+ NIST recommends at least 6-digit PINs in section 5.1.9.1 of their
+ [Digital Identity Guidelines](https://pages.nist.gov/800-63-3/sp800-63b.html).
+ You can add relying parties to the list of readers of the minimum PIN length.
diff --git a/docs/debugging.md b/docs/debugging.md
new file mode 100644
index 0000000..2584785
--- /dev/null
+++ b/docs/debugging.md
@@ -0,0 +1,137 @@
+#
+
+## Troubleshooting and Debugging
+
+### Inspecting USB
+
+The following commands should help you identify whether your operating system
+identifies OpenSK over USB.
+
+#### Linux
+
+When plugging in the USB key, the following line should appear in `lsusb`.
+
+```shell
+$ lsusb
+...
+Bus XXX Device YYY: ID 1915:521f Nordic Semiconductor ASA OpenSK
+```
+
+You should also see lines similar to the following in `dmesg`.
+
+```shell
+$ dmesg
+...
+[XXX] usb A-BB: new full-speed USB device number 00 using xhci_hcd
+[XXX] usb A-BB: New USB device found, idVendor=1915, idProduct=521f, bcdDevice= 0.01
+[XXX] usb A-BB: New USB device strings: Mfr=1, Product=2, SerialNumber=3
+[XXX] usb A-BB: Product: OpenSK
+[XXX] usb A-BB: Manufacturer: Nordic Semiconductor ASA
+[XXX] usb A-BB: SerialNumber: v0.1
+[XXX] hid-generic 0000:0000:0000.0000: hiddev0,hidraw0: USB HID v1.10 Device [Nordic Semiconductor ASA OpenSK] on usb-0000:00:00.0-00/input0
+```
+
+#### Mac OS X
+
+When plugging in the USB key, you should see a similar line by using the `ioreg`
+tool:
+
+```shell
+$ ioreg -p IOUSB
++-o Root
+...
+ +-o AppleUSBXHCI Root Hub Simulation@14000000
+ +-o OpenSK@14400000
+```
+
+### Debug console
+
+On the dev board, you can read the debug messages using JLink. Use one terminal
+for the server and one for the client:
+
+```shell
+# Terminal 1
+JLinkExe -device nrf52 -if swd -speed 1000 -autoconnect 1
+# Terminal 2
+JLinkRTTClient
+```
+
+You can enhance the debug output by adding flags to the deploy command (see
+below for details):
+
+* `--debug`: more debug messages
+* `--panic-console`: add panic messages
+* `--debug-allocations`: print information about the used heap
+
+Adding debugging to your firmware increases resource usage, including
+
+* USB communication speed
+* RAM usage
+* binary size
+
+Depending on your choice of board, you may have to increase the available stack
+for kernel or app, or disable features so that the binary fits the flash. Also
+expect more packet loss.
+
+### App panic messages
+
+By default, libtock-rs blinks some LEDs when the userspace application panics.
+This is not always convenient as the panic message is lost. In order to enable
+a custom panic handler that first writes the panic message via Tock's console
+driver, before faulting the app, you can use the `--panic-console` flag of the
+`deploy.py` script.
+
+```shell
+# Example on Nordic nRF52840-DK board
+./deploy.py --board=nrf52840dk --opensk --panic-console
+```
+
+### Memory allocations
+
+You may want to track memory allocations to understand the heap usage of
+OpenSK. This can be useful if you plan to port it to a board with fewer
+available RAM for example. To do so, you can enable the `--debug-allocations`
+flag of the `deploy.py` script. This enables a custom (userspace) allocator
+that prints a message to the console for each allocation and deallocation
+operation.
+
+The additional output looks like the following.
+
+```text
+# Allocation of 256 byte(s), aligned on 1 byte(s). The allocated address is
+# 0x2002401c. After this operation, 2 pointers have been allocated, totalling
+# 384 bytes (the total heap usage may be larger, due to alignment and
+# fragmentation of allocations within the heap).
+alloc[256, 1] = 0x2002401c (2 ptrs, 384 bytes)
+# Deallocation of 64 byte(s), aligned on 1 byte(s), from address 0x2002410c.
+# After this operation, 1 pointers are allocated, totalling 512 bytes.
+dealloc[64, 1] = 0x2002410c (1 ptrs, 512 bytes)
+```
+
+A tool is provided to analyze such reports, in `tools/heapviz`. This tool
+parses the console output, identifies the lines corresponding to (de)allocation
+operations, and first computes some statistics:
+
+* Address range used by the heap over this run of the program,
+* Peak heap usage (how many useful bytes are allocated),
+* Peak heap consumption (how many bytes are used by the heap, including
+ unavailable bytes between allocated blocks, due to alignment constraints and
+ memory fragmentation),
+* Fragmentation overhead (difference between heap consumption and usage).
+
+Then, the `heapviz` tool displays an animated "movie" of the allocated bytes in
+heap memory. Each frame in this "movie" shows bytes that are currently
+allocated, that were allocated but are now freed, and that have never been
+allocated. A new frame is generated for each (de)allocation operation. This tool
+uses the `ncurses` library, that you may have to install beforehand.
+
+You can control the tool with the following parameters:
+
+* `--logfile` (required) to provide the file which contains the console output
+ to parse,
+* `--fps` (optional) to customize the number of frames per second in the movie
+ animation.
+
+```shell
+cargo run --manifest-path tools/heapviz/Cargo.toml -- --logfile console.log --fps 50
+```
diff --git a/docs/img/enclosure.jpg b/docs/img/enclosure.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..ed5ef9537a6b21e9fc2823d61c20ebc9d83bdd95
GIT binary patch
literal 557037
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
z
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