4 Commits

Author SHA1 Message Date
Jean-Michel Picod
7e5e2a665f Merge bugfix into stable (#324)
* Add Feitian OpenSK USB Dongle (#257)

Co-authored-by: superskybird <skybird.le@gmail.com>

* Fix `config.py` tool according to the new API of fido2 python package (#284)

* Fix fido2 API update.

Since fido2 0.8.1 the device descriptor moved to NamedTuple, breaking
our configuration tool.
Code is now updated accordingly and the setup script ensure we're
using the correct version for fido2 package.

* Make Yapf happy

* Fix missing update for fido2 0.9.1

Also split the comment into 2 lines so that the touch is not hidden
at the end of the screen.

* adds README changes, logo and certificate (#285)

* Fix broken parsing. (#317)

* Fix broken parsing.

By setting the default value before pre-parsing we ensure that the item
can't be None. As an extra safety the custom action also checks for
None.

Co-authored-by: Geoffrey <geoffrey@ftsafe.com>
Co-authored-by: superskybird <skybird.le@gmail.com>
Co-authored-by: kaczmarczyck <43844792+kaczmarczyck@users.noreply.github.com>
2021-06-09 16:50:00 +02:00
Jean-Michel Picod
5e682d9e17 Compare all timestamps in UTC timezone. (#309) 2021-04-15 17:22:54 +02:00
Jean-Michel Picod
748b7e7fb8 Bugfix (#304)
* Add Feitian OpenSK USB Dongle (#257)

Co-authored-by: superskybird <skybird.le@gmail.com>

* Fix `config.py` tool according to the new API of fido2 python package (#284)

* Fix fido2 API update.

Since fido2 0.8.1 the device descriptor moved to NamedTuple, breaking
our configuration tool.
Code is now updated accordingly and the setup script ensure we're
using the correct version for fido2 package.

* Make Yapf happy

* Fix missing update for fido2 0.9.1

Also split the comment into 2 lines so that the touch is not hidden
at the end of the screen.

* adds README changes, logo and certificate (#285)

Co-authored-by: Geoffrey <geoffrey@ftsafe.com>
Co-authored-by: superskybird <skybird.le@gmail.com>
Co-authored-by: kaczmarczyck <43844792+kaczmarczyck@users.noreply.github.com>
2021-04-13 14:59:47 +02:00
Jean-Michel Picod
b0c1b73897 Add Feitian OpenSK USB Dongle (#257) (#258)
Co-authored-by: superskybird <skybird.le@gmail.com>

Co-authored-by: Geoffrey <geoffrey@ftsafe.com>
Co-authored-by: superskybird <skybird.le@gmail.com>
2021-01-14 12:32:28 +01:00
241 changed files with 8682 additions and 31459 deletions

View File

@@ -2,10 +2,5 @@ Fixes #<issue_number_goes_here>
> It's a good idea to open an issue first for discussion.
- [ ] Local tests pass (running `run_desktop_tests.sh`)
- [ ] Tested against boards
- [ ] Nordic nRF52840 DK
- [ ] Nordic nRF52840 Dongle (JTAG programmed)
- [ ] Nordic nRF52840 Dongle (DFU programmed)
- [ ] Makerdiary nRF52840 MDK USB Dongle
- [ ] Tests pass
- [ ] Appropriate changes to README are included in PR

View File

@@ -1,46 +0,0 @@
#!/bin/bash
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cd "$(dirname "$0")"
# New output file is $1
# Old output file is $2
TMP=comment.md
WARNING="Note: numbers above are a result of guesswork. They are not 100% correct and never will be."
NEW_SIZE=$(cat "$1" | sed -nr 's/.*100.0% (.*)KiB .text.*/\1/p')
OLD_SIZE=$(cat "$2" | sed -nr 's/.*100.0% (.*)KiB .text.*/\1/p')
echo "
OLD $OLD_SIZE kiB
NEW $NEW_SIZE kiB" > "$TMP"
echo "
Output of cargo bloat
======================
" >> "$TMP"
echo "Including PR" >> "$TMP"
cat "$1" >> "$TMP"
echo "Base branch" >> "$TMP"
cat "$2" >> "$TMP"
COMMENT="$(cat $TMP | sed "s/$WARNING//g" | sed 's/%/%25/g' | sed -z 's/\n/%0A/g')"
# No output for equality is intentional.
if (( $(echo "$NEW_SIZE > $OLD_SIZE" | bc -l) )); then
echo "::warning file=.github/workflows/cargo_bloat.yml,title=Binary size::$COMMENT"
fi
if (( $(echo "$NEW_SIZE < $OLD_SIZE" | bc -l) )); then
echo "::notice file=.github/workflows/cargo_bloat.yml,title=Binary size::$COMMENT"
fi

View File

@@ -12,14 +12,15 @@ jobs:
build_boards:
strategy:
matrix:
os: [ubuntu-latest, macos-10.15]
os: [ubuntu-18.04, macos-10.15]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
- uses: actions/setup-python@v1
with:
python-version: 3.7
@@ -28,10 +29,10 @@ jobs:
- name: Set up OpenSK
run: ./setup.sh
- name: Building board nrf52840dk_opensk
run: ./deploy.py --board=nrf52840dk_opensk --no-app --programmer=none
- name: Building board nrf52840_dongle_opensk
run: ./deploy.py --board=nrf52840_dongle_opensk --no-app --programmer=none
- name: Building board nrf52840dk
run: ./deploy.py --board=nrf52840dk --no-app --programmer=none
- name: Building board nrf52840_dongle
run: ./deploy.py --board=nrf52840_dongle --no-app --programmer=none
- name: Building board nrf52840_dongle_dfu
run: ./deploy.py --board=nrf52840_dongle_dfu --no-app --programmer=none
- name: Building board nrf52840_mdk_dfu

View File

@@ -5,14 +5,15 @@ on:
jobs:
audit:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
if: github.repository == 'google/OpenSK'
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
- uses: actions/setup-python@v1
with:
python-version: 3.7

View File

@@ -1,47 +0,0 @@
name: Binary size report
on: pull_request
jobs:
cargo_bloat:
runs-on: ubuntu-latest
steps:
# Setup
- uses: actions/setup-python@v1
with:
python-version: 3.7
- name: Install Python dependencies
run: python -m pip install --upgrade pip setuptools wheel
- uses: actions-rs/cargo@v1
with:
command: install
args: cargo-bloat
# First run: PR
- uses: actions/checkout@v2
with:
submodules: true
- name: Install Rust toolchain
run: rustup show
- name: Set up OpenSK
run: ./setup.sh
- name: Run bloat on the PR
run: RUSTFLAGS="-C link-arg=-icf=all -C force-frame-pointers=no" cargo bloat --release --target=thumbv7em-none-eabi --features=with_ctap1,vendor_hid --crates >> .github/workflows/bloat_output_new.txt
# Second run: PR
- uses: actions/checkout@v2
with:
submodules: true
ref: ${{ github.base_ref }}
path: OpenSK_base
- name: Install old Rust toolchain
working-directory: ./OpenSK_base
run: rustup show
- name: Set up OpenSK
working-directory: ./OpenSK_base
run: ./setup.sh
- name: Run bloat on base
working-directory: ./OpenSK_base
run: RUSTFLAGS="-C link-arg=-icf=all -C force-frame-pointers=no" cargo bloat --release --target=thumbv7em-none-eabi --features=with_ctap1,vendor_hid --crates >> "$GITHUB_WORKSPACE/.github/workflows/bloat_output_old.txt"
- name: Run output formatter to echo workflow command
run: ./.github/workflows/bloat_formatter.sh bloat_output_new.txt bloat_output_old.txt bloat_comment.md

View File

@@ -14,13 +14,14 @@ on:
jobs:
cargo_check:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
- uses: actions/setup-python@v1
with:
python-version: 3.7
@@ -41,17 +42,11 @@ jobs:
command: check
args: --target thumbv7em-none-eabi --release --features with_ctap1
- name: Check OpenSK vendor_hid
- name: Check OpenSK with_ctap2_1
uses: actions-rs/cargo@v1
with:
command: check
args: --target thumbv7em-none-eabi --release --features vendor_hid
- name: Check OpenSK ed25519
uses: actions-rs/cargo@v1
with:
command: check
args: --target thumbv7em-none-eabi --release --features ed25519
args: --target thumbv7em-none-eabi --release --features with_ctap2_1
- name: Check OpenSK debug_ctap
uses: actions-rs/cargo@v1
@@ -83,20 +78,20 @@ jobs:
command: check
args: --target thumbv7em-none-eabi --release --features debug_ctap,with_ctap1
- name: Check OpenSK debug_ctap,with_ctap1,vendor_hid,ed25519,panic_console,debug_allocations,verbose
- name: Check OpenSK debug_ctap,with_ctap2_1
uses: actions-rs/cargo@v1
with:
command: check
args: --target thumbv7em-none-eabi --release --features debug_ctap,with_ctap1,vendor_hid,ed25519,panic_console,debug_allocations,verbose
args: --target thumbv7em-none-eabi --release --features debug_ctap,with_ctap2_1
- name: Check OpenSK debug_ctap,with_ctap1,with_ctap2_1,panic_console,debug_allocations,verbose
uses: actions-rs/cargo@v1
with:
command: check
args: --target thumbv7em-none-eabi --release --features debug_ctap,with_ctap1,with_ctap2_1,panic_console,debug_allocations,verbose
- name: Check examples
uses: actions-rs/cargo@v1
with:
command: check
args: --target thumbv7em-none-eabi --release --examples
- name: Check bootloader
uses: actions-rs/cargo@v1
with:
command: check
args: --manifest-path bootloader/Cargo.toml --target thumbv7em-none-eabi --release

View File

@@ -7,13 +7,15 @@ on:
jobs:
cargo_clippy:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
components: clippy
- uses: actions/setup-python@v1
with:
python-version: 3.7
@@ -26,9 +28,5 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-targets --features std
- name: Deny Clippy warnings (std)
- name: Deny Clippy warnings
run: cargo clippy --all-targets --features std -- -A clippy::new_without_default -D warnings
- name: Deny Clippy warnings (all)
run: cargo clippy --all-targets --features std,with_ctap1,ed25519,vendor_hid -- -A clippy::new_without_default -D warnings
- name: Deny Clippy warnings (all, nfc)
run: cargo clippy --all-targets --features std,with_ctap1,with_nfc,ed25519,vendor_hid -- -A clippy::new_without_default -D warnings

View File

@@ -15,13 +15,15 @@ on:
jobs:
cargo_format:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
components: rustfmt
- uses: actions/setup-python@v1
with:
python-version: 3.7
@@ -71,9 +73,3 @@ jobs:
with:
command: fmt
args: --manifest-path tools/heapviz/Cargo.toml --all -- --check
- name: Cargo format bootloader
uses: actions-rs/cargo@v1
with:
command: fmt
args: --manifest-path bootloader/Cargo.toml --all -- --check

View File

@@ -7,13 +7,14 @@ on:
jobs:
build_fuzzing:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
- uses: actions/setup-python@v1
with:
python-version: 3.7

View File

@@ -9,13 +9,14 @@ on:
jobs:
cbor_test:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
- uses: actions/setup-python@v1
with:
python-version: 3.7
@@ -28,10 +29,10 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path libraries/cbor/Cargo.toml --release
args: --manifest-path libraries/cbor/Cargo.toml --release --features std
- name: Unit testing of CBOR library (debug mode)
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path libraries/cbor/Cargo.toml
args: --manifest-path libraries/cbor/Cargo.toml --features std

View File

@@ -1,28 +0,0 @@
name: CIFuzz
on:
pull_request:
branches:
- develop
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'opensk'
dry-run: false
language: rust
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'opensk'
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v1
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

View File

@@ -1,48 +0,0 @@
---
name: OpenSK code coverage report
on:
push:
paths:
- 'src/**/*.rs'
- 'libraries/**/*.rs'
pull_request:
types: [opened, synchronize, reopened]
jobs:
coveralls:
name: OpenSK code coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions/setup-python@v1
with:
python-version: 3.7
- name: Install Python dependencies
run: python -m pip install --upgrade pip setuptools wheel
- name: Set up OpenSK
run: ./setup.sh
- name: Install llvm tools
run: rustup component add llvm-tools-preview
- name: Install grcov
run: if [[ ! -e ~/.cargo/bin/grcov ]]; then cargo +stable install grcov; fi
- uses: actions-rs/cargo@v1
with:
command: test
args: --features "with_ctap1,vendor_hid,ed25519,with_nfc,std" --no-fail-fast
env:
RUSTFLAGS: "-Zinstrument-coverage"
LLVM_PROFILE_FILE: "opensk-%p-%m.profraw"
- name: Run grcov
run: grcov . --binary-path ./target/debug/ --source-dir . --output-type lcov --ignore-not-existing ---output-path ./lcov.info --ignore "/*" --ignore "examples/*" --ignore "third_party/*"
- uses: coverallsapp/github-action@1.1.3
name: upload report to coveralls
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: "./lcov.info"

View File

@@ -11,13 +11,14 @@ on:
jobs:
crypto_test:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
- uses: actions/setup-python@v1
with:
python-version: 3.7
@@ -32,10 +33,10 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path libraries/crypto/Cargo.toml --release --features std
args: --manifest-path libraries/crypto/Cargo.toml --release --features std,derive_debug
- name: Unit testing of crypto library (debug mode)
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path libraries/crypto/Cargo.toml --features std
args: --manifest-path libraries/crypto/Cargo.toml --features std,derive_debug

View File

@@ -9,7 +9,7 @@ on:
jobs:
heapviz_test:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Install ncurses

View File

@@ -10,7 +10,7 @@ on:
jobs:
mdlint:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: markdownlint-cli

View File

@@ -9,14 +9,15 @@ jobs:
build_ctap2:
strategy:
matrix:
os: [ubuntu-latest, macos-10.15]
os: [ubuntu-18.04, macos-10.15]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
- uses: actions/setup-python@v1
with:
python-version: 3.7
@@ -35,6 +36,6 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: build
args: --release --target=thumbv7em-none-eabi --features with_ctap1,vendor_hid
args: --release --target=thumbv7em-none-eabi --features with_ctap1
- name: Compute SHA-256 sum
run: ./third_party/tock/tools/sha256sum/target/debug/sha256sum target/thumbv7em-none-eabi/release/ctap2

View File

@@ -10,14 +10,15 @@ on:
jobs:
ctap2_test:
name: CTAP2 unit tests
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
- uses: actions/setup-python@v1
with:
python-version: 3.7
@@ -50,3 +51,27 @@ jobs:
command: test
args: --features std,with_ctap1
- name: Unit testing of CTAP2 (release mode + CTAP2.1)
uses: actions-rs/cargo@v1
with:
command: test
args: --release --features std,with_ctap2_1
- name: Unit testing of CTAP2 (debug mode + CTAP2.1)
uses: actions-rs/cargo@v1
with:
command: test
args: --features std,with_ctap2_1
- name: Unit testing of CTAP2 (release mode + CTAP1 + CTAP2.1)
uses: actions-rs/cargo@v1
with:
command: test
args: --release --features std,with_ctap1,with_ctap2_1
- name: Unit testing of CTAP2 (debug mode + CTAP1 + CTAP2.1)
uses: actions-rs/cargo@v1
with:
command: test
args: --features std,with_ctap1,with_ctap2_1

View File

@@ -9,21 +9,18 @@ on:
jobs:
persistent_store_test:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Install Rust toolchain
run: rustup show
- name: Unit testing of Persistent store library (release mode)
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path libraries/persistent_store/Cargo.toml --release --features=std
args: --manifest-path libraries/persistent_store/Cargo.toml --release --features std
- name: Unit testing of Persistent store library (debug mode)
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path libraries/persistent_store/Cargo.toml --features=std
args: --manifest-path libraries/persistent_store/Cargo.toml --features std

View File

@@ -9,10 +9,10 @@ on:
types: [opened, synchronize, reopened]
jobs:
pylint:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: [3.6, 3.7, 3.8]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
@@ -29,7 +29,7 @@ jobs:
run: ./tools/run_pylint.sh
yapf:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.7

View File

@@ -9,15 +9,16 @@ jobs:
check_hashes:
strategy:
matrix:
os: [ubuntu-latest, macos-10.15]
os: [ubuntu-18.04, macos-10.15]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions-rs/toolchain@v1
with:
target: thumbv7em-none-eabi
- uses: actions/setup-python@v1
with:
python-version: 3.7
@@ -29,7 +30,7 @@ jobs:
- name: Use sample cryptographic material
run: rm -R crypto_data/ && cp -r reproducible/sample_crypto_data crypto_data
- name: Computing cryptographic hashes
run: ./maintainers/reproduce_hashes.sh
run: ./reproduce_hashes.sh
- name: Upload reproduced binaries
uses: actions/upload-artifact@v1

View File

@@ -1,39 +0,0 @@
---
name: RNG library tests
on:
push:
paths:
- 'libraries/rng256/**'
pull_request:
types: [opened, synchronize, reopened]
paths:
- 'libraries/rng256/**'
jobs:
rng256_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: "true"
- name: Install Rust toolchain
run: rustup show
- uses: actions/setup-python@v1
with:
python-version: 3.7
- name: Install Python dependencies
run: python -m pip install --upgrade pip setuptools wheel
- name: Set up OpenSK
run: ./setup.sh
- name: Unit testing of rng256library (release mode)
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path libraries/rng256/Cargo.toml --release --features std
- name: Unit testing of rng256 library (debug mode)
uses: actions-rs/cargo@v1
with:
command: test
args: --manifest-path libraries/rng256/Cargo.toml --features std

4
.gitignore vendored
View File

@@ -1,7 +1,5 @@
fuzz/artifacts
fuzz/corpus
fuzz/coverage
target/
Cargo.lock
# Local installation of elf2tab.
/elf2tab/

543
.pylintrc
View File

@@ -1,318 +1,135 @@
# This Pylint rcfile contains a best-effort configuration to uphold the
# best-practices and style described in the Google Python style guide:
# https://google.github.io/styleguide/pyguide.html
#
# Its canonical open-source location is:
# https://google.github.io/styleguide/pylintrc
# File taken from Tensor2Tensor project
# https://github.com/tensorflow/tensor2tensor/blob/master/pylintrc
[MAIN]
# Files or directories to be skipped. They should be base names, not paths.
ignore=third_party
# Files or directories matching the regex patterns are skipped. The regex
# matches against base names, not paths.
ignore-patterns=
[MASTER]
# Pickle collected data for later comparisons.
persistent=no
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
# Set the cache size for astng objects.
cache-size=500
# Ignore Py3 files
ignore=get_references_web.py,get_references_web_single_group.py
load-plugins=
# Use multiple processes to speed up Pylint.
jobs=4
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
#enable=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=abstract-method,
apply-builtin,
arguments-differ,
attribute-defined-outside-init,
backtick,
bad-option-value,
basestring-builtin,
buffer-builtin,
c-extension-no-member,
consider-using-enumerate,
cmp-builtin,
cmp-method,
coerce-builtin,
coerce-method,
delslice-method,
div-method,
duplicate-code,
eq-without-hash,
execfile-builtin,
file-builtin,
filter-builtin-not-iterating,
fixme,
getslice-method,
global-statement,
hex-method,
idiv-method,
implicit-str-concat-in-sequence,
import-error,
import-self,
import-star-module-level,
inconsistent-return-statements,
input-builtin,
intern-builtin,
invalid-str-codec,
locally-disabled,
long-builtin,
long-suffix,
map-builtin-not-iterating,
misplaced-comparison-constant,
missing-function-docstring,
metaclass-assignment,
next-method-called,
next-method-defined,
no-absolute-import,
no-else-break,
no-else-continue,
no-else-raise,
no-else-return,
no-init, # added
no-member,
no-name-in-module,
no-self-use,
nonzero-method,
oct-method,
old-division,
old-ne-operator,
old-octal-literal,
old-raise-syntax,
parameter-unpacking,
print-statement,
raising-string,
range-builtin-not-iterating,
raw_input-builtin,
rdiv-method,
reduce-builtin,
relative-import,
reload-builtin,
round-builtin,
setslice-method,
signature-differs,
standarderror-builtin,
suppressed-message,
sys-max-int,
too-few-public-methods,
too-many-ancestors,
too-many-arguments,
too-many-boolean-expressions,
too-many-branches,
too-many-instance-attributes,
too-many-locals,
too-many-nested-blocks,
too-many-public-methods,
too-many-return-statements,
too-many-statements,
trailing-newlines,
unichr-builtin,
unicode-builtin,
unnecessary-pass,
unpacking-in-except,
unrecognized-option,
useless-else-on-loop,
useless-object-inheritance,
useless-suppression,
using-cmp-argument,
wrong-import-order,
xrange-builtin,
zip-builtin-not-iterating,
pylint.extensions.bad_builtin,
pylint.extensions.docparams,
pylint.extensions.docstyle,
pylint.extensions.redefined_variable_type,
pylint.extensions.overlapping_exceptions,
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html. You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Set the output format.
# output-format=sorted-text
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]". This option is deprecated
# and it will be removed in Pylint 2.0.
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells whether to display a full report or only the messages
# Tells whether to display a full report or only the messages.
reports=no
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Disable the report(s) with the given id(s).
disable-report=R0001,R0002,R0003,R0004,R0101,R0102,R0201,R0202,R0220,R0401,R0402,R0701,R0801,R0901,R0902,R0903,R0904,R0911,R0912,R0913,R0914,R0915,R0921,R0922,R0923
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=
# Error message template (continued on second line)
msg-template={msg_id}:{line:3} {obj}: {msg} [{symbol}]
# We don't need evaluation score
score=no
[MESSAGES CONTROL]
# List of checkers and warnings to enable.
enable=indexing-exception,old-raise-syntax
# List of checkers and warnings to disable.
disable=design,similarities,no-self-use,attribute-defined-outside-init,locally-disabled,star-args,pointless-except,bad-option-value,global-statement,fixme,suppressed-message,useless-suppression,locally-enabled,file-ignored,multiple-imports,c-extension-no-member,trailing-newlines,unsubscriptable-object,misplaced-comparison-constant,no-member,abstract-method,no-else-return,missing-docstring,wrong-import-order,protected-access,inconsistent-return-statements,invalid-unary-operand-type,import-error,no-name-in-module,arguments-differ,not-context-manager,unused-argument
[BASIC]
# Required attributes for module, separated by a comma
required-attributes=
# Regular expression which should only match the name
# of functions or classes which do not require a docstring.
no-docstring-rgx=(__.*__|main)
# Min length in lines of a function that requires a docstring.
docstring-min-length=10
# Regular expression which should only match correct module names. The
# leading underscore is sanctioned for private modules by Google's style
# guide.
#
# There are exceptions to the basic rule (_?[a-z][a-z0-9_]*) to cover
# requirements of Python's module system.
module-rgx=^(_?[a-z][a-z0-9_]*)|__init__$
# Regular expression which should only match correct module level names
const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
# Regular expression which should only match correct class attribute
class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
# Regular expression which should only match correct class names
class-rgx=^_?[A-Z][a-zA-Z0-9]*$
# Regular expression which should only match correct function names.
# 'camel_case' and 'snake_case' group names are used for consistency of naming
# styles across functions and methods.
function-rgx=^(?:(?P<exempt>setUp|tearDown|setUpModule|tearDownModule)|(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$
# Regular expression which should only match correct method names.
# 'camel_case' and 'snake_case' group names are used for consistency of naming
# styles across functions and methods. 'exempt' indicates a name which is
# consistent with all naming styles.
method-rgx=(?x)
^(?:(?P<exempt>_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase
|tearDownTestCase|setupSelf|tearDownClass|setUpClass
|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)
|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9_]*)
|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$
# Regular expression which should only match correct instance attribute names
attr-rgx=^_{0,2}[a-z][a-z0-9_]*$
# Regular expression which should only match correct argument names
argument-rgx=^[a-z][a-z0-9_]*$
# Regular expression which should only match correct variable names
variable-rgx=^[a-z][a-z0-9_]*$
# Regular expression which should only match correct list comprehension /
# generator expression variable names
inlinevar-rgx=^[a-z][a-z0-9_]*$
# Good variable names which should always be accepted, separated by a comma
good-names=main,_
# Bad variable names which should always be refused, separated by a comma
bad-names=
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# List of builtins function names that should not be used, separated by a comma
bad-functions=input,apply,reduce
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl
# Regular expression matching correct function names
function-rgx=^(?:(?P<exempt>setUp|tearDown|setUpModule|tearDownModule)|(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$
# Regular expression matching correct variable names
variable-rgx=^[a-z][a-z0-9_]*$
# Regular expression matching correct constant names
const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
# Regular expression matching correct attribute names
attr-rgx=^_{0,2}[a-z][a-z0-9_]*$
# Regular expression matching correct argument names
argument-rgx=^[a-z][a-z0-9_]*$
# Regular expression matching correct class attribute names
class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
# Regular expression matching correct inline iteration names
inlinevar-rgx=^[a-z][a-z0-9_]*$
# Regular expression matching correct class names
class-rgx=^_?[A-Z][a-zA-Z0-9]*$
# Regular expression matching correct module names
module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$
# Regular expression matching correct method names
method-rgx=(?x)^(?:(?P<exempt>_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=10
# List of decorators that define properties, such as abc.abstractproperty.
property-classes=abc.abstractproperty
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=80
# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt
# lines made too long by directives to pytype.
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=(?x)(
^\s*(\#\ )?<?https?://\S+>?$|
^\s*(from\s+\S+\s+)?import\s+.+$)
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=yes
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=
# Maximum number of lines in a module
max-module-lines=99999
# String used as indentation unit. The internal Google style guide mandates 2
# spaces. Google's externaly-published style guide says 4, consistent with
# PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google
# projects (like TensorFlow).
indent-string=' '
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=TODO
[STRING]
# This flag controls whether inconsistent-quotes generates a warning when the
# character used as a quote delimiter is used inconsistently within a module.
check-quote-consistency=yes
# List of decorators that create context managers from functions, such as
# contextlib.contextmanager.
contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
[VARIABLES]
@@ -320,123 +137,99 @@ check-quote-consistency=yes
# Tells whether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
# A regular expression matching names used for dummy variables (i.e. not used).
dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,_cb
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp
# "class_" is also a valid for the first argument to a class method.
valid-classmethod-first-arg=cls,class_
[LOGGING]
[EXCEPTIONS]
# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging,absl.logging,tensorflow.io.logging
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=4
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
[SPELLING]
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
overgeneral-exceptions=StandardError,Exception,BaseException
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,
TERMIOS,
Bastion,
rexec,
sets
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant, absl
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
deprecated-modules=regsub,TERMIOS,Bastion,rexec,sets
[CLASSES]
[FORMAT]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
__new__,
setUp
# Maximum number of characters on a single line.
max-line-length=80
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,
_fields,
_replace,
_source,
_make
# Regexp for a line that is allowed to be longer than the limit.
# This "ignore" regex is today composed of several independent parts:
# (1) Long import lines
# (2) URLs in comments or pydocs. Detecting URLs by regex is a hard problem and
# no amount of tweaking will make a perfect regex AFAICT. This one is a good
# compromise.
# (3) Constant string literals at the start of files don't need to be broken
# across lines. Allowing long paths and urls to be on a single
# line. Also requires that the string not be a triplequoted string.
ignore-long-lines=(?x)
(^\s*(import|from)\s
|^\s*(\#\ )?<?(https?|ftp):\/\/[^\s\/$.?#].[^\s]*>?$
|^[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*("[^"]\S+"|'[^']\S+')
)
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls,
class_
# Maximum number of lines in a module
max-module-lines=99999
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
# String used as indentation unit. We differ from PEP8's normal 4 spaces.
indent-string=' '
# Do not warn about multiple statements on a single line for constructs like
# if test: stmt
single-line-if-stmt=y
# Make sure : in dicts and trailing commas are checked for whitespace.
no-space-check=
[EXCEPTIONS]
[LOGGING]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=StandardError,
Exception,
BaseException
# Add logging modules.
logging-modules=logging,absl.logging
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=
# Maximum line length for lambdas
short-func-length=1
# List of module members that should be marked as deprecated.
# All of the string functions are listed in 4.1.4 Deprecated string functions
# in the Python 2.4 docs.
deprecated-members=string.atof,string.atoi,string.atol,string.capitalize,string.expandtabs,string.find,string.rfind,string.index,string.rindex,string.count,string.lower,string.split,string.rsplit,string.splitfields,string.join,string.joinfields,string.lstrip,string.rstrip,string.strip,string.swapcase,string.translate,string.upper,string.ljust,string.rjust,string.center,string.zfill,string.replace,sys.exitfunc,sys.maxint
# List of exceptions that do not need to be mentioned in the Raises section of
# a docstring.
ignore-exceptions=AssertionError,NotImplementedError,StopIteration,TypeError
# Number of spaces of indent required when the last token on the preceding line
# is an open (, [, or {.
indent-after-paren=4
# Set the linting for string quotes
string-quote=double
triple-quote=double
docstring-quote=double

789
Cargo.lock generated
View File

@@ -1,789 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "autocfg"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "crypto"
version = "0.1.0"
dependencies = [
"arrayref",
"byteorder",
"hex",
"regex",
"ring",
"rng256",
"serde",
"serde_json",
"subtle",
"untrusted",
]
[[package]]
name = "ctap2"
version = "1.0.0"
dependencies = [
"arbitrary",
"arrayref",
"byteorder",
"crypto",
"ed25519-compact",
"embedded-time",
"enum-iterator",
"lang_items",
"libtock_core",
"libtock_drivers",
"openssl",
"persistent_store",
"rand 0.8.5",
"rng256",
"sk-cbor",
"subtle",
"uuid",
]
[[package]]
name = "derive_arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a012b5e473dc912f0db0546a1c9c6a194ce8494feb66fa0237160926f9e0e6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ed25519-compact"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bee9df587982575886a8682edcee11877894349a805f25629c27f63abe3e9ae8"
[[package]]
name = "embedded-time"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58"
dependencies = [
"num",
]
[[package]]
name = "enum-iterator"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c79a6321a1197d7730510c7e3f6cb80432dfefecb32426de8cea0aa19b4bb8d7"
dependencies = [
"enum-iterator-derive",
]
[[package]]
name = "enum-iterator-derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "getrandom"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lang_items"
version = "0.1.0"
dependencies = [
"libtock_core",
"libtock_drivers",
"linked_list_allocator",
]
[[package]]
name = "libc"
version = "0.2.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
[[package]]
name = "libtock_codegen"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "libtock_core"
version = "0.1.0"
dependencies = [
"libtock_codegen",
]
[[package]]
name = "libtock_drivers"
version = "0.1.0"
dependencies = [
"libtock_core",
]
[[package]]
name = "linked_list_allocator"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[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.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg 1.1.0",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg 1.1.0",
"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 1.1.0",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "once_cell"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "openssl"
version = "0.10.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-sys"
version = "0.9.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
dependencies = [
"autocfg 1.1.0",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "persistent_store"
version = "0.1.0"
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.3.1",
]
[[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.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[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_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]]
name = "rng256"
version = "0.1.0"
dependencies = [
"arrayref",
"libtock_drivers",
"rand 0.6.5",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "serde"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sk-cbor"
version = "0.1.2"
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "web-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@@ -13,37 +13,29 @@ edition = "2018"
libtock_core = { path = "third_party/libtock-rs/core" }
libtock_drivers = { path = "third_party/libtock-drivers" }
lang_items = { path = "third_party/lang-items" }
sk-cbor = { path = "libraries/cbor" }
cbor = { path = "libraries/cbor" }
crypto = { path = "libraries/crypto" }
rng256 = { path = "libraries/rng256" }
persistent_store = { path = "libraries/persistent_store" }
byteorder = { version = "1", default-features = false }
arrayref = "0.3.6"
subtle = { version = "2.2", default-features = false, features = ["nightly"] }
embedded-time = "0.12.1"
arbitrary = { version = "0.4.7", features = ["derive"], optional = true }
rand = { version = "0.8.4", optional = true }
ed25519-compact = { version = "1", default-features = false, optional = true }
[features]
debug_allocations = ["lang_items/debug_allocations"]
debug_ctap = ["libtock_drivers/debug_ctap"]
debug_ctap = ["crypto/derive_debug", "libtock_drivers/debug_ctap"]
panic_console = ["lang_items/panic_console"]
std = ["crypto/std", "lang_items/std", "persistent_store/std", "rng256/std", "rand"]
std = ["cbor/std", "crypto/std", "crypto/derive_debug", "lang_items/std", "persistent_store/std"]
verbose = ["debug_ctap", "libtock_drivers/verbose_usb"]
with_ctap1 = ["crypto/with_ctap1"]
with_ctap2_1 = []
with_nfc = ["libtock_drivers/with_nfc"]
vendor_hid = ["libtock_drivers/vendor_hid"]
fuzz = ["arbitrary", "std"]
ed25519 = ["ed25519-compact"]
[dev-dependencies]
elf2tab = "0.6.0"
enum-iterator = "0.6.0"
[build-dependencies]
sk-cbor = { path = "libraries/cbor" }
uuid = { version = "0.8", features = ["v4"] }
openssl = "0.10.36"
[profile.dev]
panic = "abort"
@@ -52,5 +44,3 @@ lto = true # Link Time Optimization usually reduces size of binaries and static
[profile.release]
panic = "abort"
lto = true # Link Time Optimization usually reduces size of binaries and static libraries
opt-level = "z"
codegen-units = 1

233
README.md
View File

@@ -1,84 +1,203 @@
# <img alt="OpenSK logo" src="docs/img/OpenSK.svg" width="200px">
![markdownlint](https://github.com/google/OpenSK/workflows/markdownlint/badge.svg?branch=develop)
![pylint](https://github.com/google/OpenSK/workflows/pylint/badge.svg?branch=develop)
![Cargo check](https://github.com/google/OpenSK/workflows/Cargo%20check/badge.svg?branch=develop)
![Cargo format](https://github.com/google/OpenSK/workflows/Cargo%20format/badge.svg?branch=develop)
[![Coverage Status](https://coveralls.io/repos/github/google/OpenSK/badge.svg?branch=develop)](https://coveralls.io/github/google/OpenSK?branch=develop)
![markdownlint](https://github.com/google/OpenSK/workflows/markdownlint/badge.svg?branch=master)
![pylint](https://github.com/google/OpenSK/workflows/pylint/badge.svg?branch=master)
![Cargo check](https://github.com/google/OpenSK/workflows/Cargo%20check/badge.svg?branch=master)
![Cargo format](https://github.com/google/OpenSK/workflows/Cargo%20format/badge.svg?branch=master)
## OpenSK
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 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)!
We developed this as a [Tock OS](https://tockos.org) application and it has been
successfully tested on the following boards:
You are viewing the branch for developers. New features are developed here
before they are stabilized. If you instead want to use the FIDO certified
firmware, please go back to the
[stable branch](https://github.com/google/OpenSK).
* [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:
### FIDO2
The develop branch implements the
[CTAP2.1 specification](https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html).
This branch is not FIDO certified. The implementation is backwards compatible
to CTAP2.0. Additionally, OpenSK supports U2F, and non-discoverable credentials
created with either protocol are compatible with the other.
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.
### :warning: Disclaimer
<img alt="FIDO2 certified L1" src="docs/img/FIDO2_Certified_L1.png" width="200px">
This project is **proof-of-concept and a research platform**. It is **NOT**
meant for a daily usage. It comes with a few limitations:
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.
* This branch is under development, and therefore less rigorously tested than the stable branch.
* The cryptography implementations are not resistent against side-channel attacks.
### Cryptography
We're still in the process of integrating the
We're currently still in the process on making the
[ARM&reg; 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)
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/).
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.
## Installation
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)
For a more detailed guide, please refer to our
[installation guide](docs/install.md).
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).
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
```
## Contributing
See [Contributing.md](docs/contributing.md).
## Reporting a Vulnerability
See [SECURITY.md](SECURITY.md).

View File

@@ -1,4 +0,0 @@
To report a security issue, please use http://g.co/vulnz. We use
http://g.co/vulnz for our intake, and do coordination and disclosure here on
GitHub (including using GitHub Security Advisory). The Google Security Team will
respond within 5 working days of your report on g.co/vulnz.

View File

@@ -6,7 +6,7 @@ build = "build.rs"
edition = "2018"
[[bin]]
path = "../nrf52840_dongle_opensk/src/main.rs"
path = "../nrf52840_dongle/src/main.rs"
name = "nrf52840_dongle_dfu"
[dependencies]
@@ -16,6 +16,3 @@ capsules = { path = "../../../capsules" }
kernel = { path = "../../../kernel" }
nrf52840 = { path = "../../../chips/nrf52840" }
nrf52_components = { path = "../nrf52_components" }
[features]
vendor_hid = ["capsules/vendor_hid"]

View File

@@ -1,17 +0,0 @@
[package]
name = "nrf52840_dongle_opensk"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
build = "build.rs"
edition = "2018"
[dependencies]
components = { path = "../../components" }
cortexm4 = { path = "../../../arch/cortex-m4" }
capsules = { path = "../../../capsules" }
kernel = { path = "../../../kernel" }
nrf52840 = { path = "../../../chips/nrf52840" }
nrf52_components = { path = "../nrf52_components" }
[features]
vendor_hid = ["capsules/vendor_hid"]

View File

@@ -1,28 +0,0 @@
# Makefile for building the tock kernel for the nRF development kit
TARGET=thumbv7em-none-eabi
PLATFORM=nrf52840_dongle_opensk
include ../../Makefile.common
TOCKLOADER=tockloader
# Where in the nrf52 flash to load the kernel with `tockloader`
KERNEL_ADDRESS=0x00000
# Upload programs over uart with tockloader
ifdef PORT
TOCKLOADER_GENERAL_FLAGS += --port $(PORT)
endif
TOCKLOADER_JTAG_FLAGS = --jlink --board nrf52dk
# Upload the kernel over JTAG
.PHONY: flash
flash: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin
$(TOCKLOADER) $(TOCKLOADER_GENERAL_FLAGS) flash --address $(KERNEL_ADDRESS) $(TOCKLOADER_JTAG_FLAGS) $<
# Upload the kernel over serial/bootloader
.PHONY: program
program: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).hex
$(error Cannot program nRF52840-Dongle over USB. Use \`make flash\` and JTAG)

View File

@@ -1,41 +0,0 @@
Platform-Specific Instructions: nRF52840-Dongle
===================================
This is an adapted nrf52840\_dongle made to work with OpenSK.
The [nRF52840 Dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle)
is a platform based around the nRF52840, an SoC with an ARM Cortex-M4 and a BLE radio.
The kit is uses a USB key form factor and includes 1 button, 1 red LED and 1 RGB LED.
## Getting Started
To program the nRF52840 Dongle with Tock, you will need a JLink JTAG device and the
appropriate cables. An example setup is:
- [JLink JTAG Device](https://www.digikey.com/product-detail/en/segger-microcontroller-systems/8.08.90-J-LINK-EDU/899-1008-ND/2263130)
- [ARM to TagConnect Adapter](https://www.digikey.com/product-detail/en/tag-connect-llc/TC2050-ARM2010/TC2050-ARM2010-ND/3528170)
- [10pin TagConnect Cable](https://www.digikey.com/product-detail/en/tag-connect-llc/TC2050-IDC-NL/TC2050-IDC-NL-ND/2605367)
Then, follow the [Tock Getting Started guide](../../../doc/Getting_Started.md)
JTAG is the preferred method to program. The development kit has the JTAG pins exposed either
through the half-moons pads or, below the PCB, on a Tag-Connect TC2050 connector footprint.
You need to [install JTAG software](../../../doc/Getting_Started.md#optional-requirements).
## Programming the kernel
Once you have all software installed, you should be able to simply run
make flash in this directory to install a fresh kernel.
## Programming user-level applications
You can program an application via JTAG using `tockloader`:
```shell
$ cd libtock-c/examples/<app>
$ make
$ tockloader install --jlink --board nrf52dk
```
## Debugging
See the [nrf52dk README](../nrf52dk/README.md) for information about debugging
the nRF52840 Dongle.

View File

@@ -1,4 +0,0 @@
fn main() {
println!("cargo:rerun-if-changed=layout.ld");
println!("cargo:rerun-if-changed=../../kernel_layout.ld");
}

View File

@@ -1,25 +0,0 @@
#
#
#
# J-LINK GDB SERVER initialization
#
# This connects to a GDB Server listening
# for commands on localhost at tcp port 2331
target remote localhost:2331
monitor speed 30
file ../../../../target/thumbv7em-none-eabi/release/nrf52840_dongle
monitor reset
#
# CPU core initialization (to be done by user)
#
# Set the processor mode
# monitor reg cpsr = 0xd3
# Set auto JTAG speed
monitor speed auto
# Setup GDB FOR FASTER DOWNLOADS
set remote memory-write-packet-size 1024
set remote memory-write-packet-size fixed
# tui enable
# layout split
# layout service_pending_interrupts
b reset_handler

View File

@@ -1 +0,0 @@
JLinkGDBServer -device nRF52840_xxAA -speed 1200 -if swd -AutoConnect 1 -port 2331

View File

@@ -1,2 +0,0 @@
INCLUDE ../nrf52840_chip_layout.ld
INCLUDE ../../kernel_layout.ld

View File

@@ -1,68 +0,0 @@
use core::fmt::Write;
use core::panic::PanicInfo;
use cortexm4;
use kernel::debug;
use kernel::debug::IoWrite;
use kernel::hil::led;
use kernel::hil::uart::{self, Configure};
use nrf52840::gpio::Pin;
use crate::CHIP;
use crate::PROCESSES;
struct Writer {
initialized: bool,
}
static mut WRITER: Writer = Writer { initialized: false };
impl Write for Writer {
fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
self.write(s.as_bytes());
Ok(())
}
}
impl IoWrite for Writer {
fn write(&mut self, buf: &[u8]) {
// Here, we create a second instance of the Uarte struct.
// This is okay because we only call this during a panic, and
// we will never actually process the interrupts
let uart = nrf52840::uart::Uarte::new();
if !self.initialized {
self.initialized = true;
uart.configure(uart::Parameters {
baud_rate: 115200,
stop_bits: uart::StopBits::One,
parity: uart::Parity::None,
hw_flow_control: false,
width: uart::Width::Eight,
});
}
for &c in buf {
unsafe {
uart.send_byte(c);
}
while !uart.tx_ready() {}
}
}
}
#[cfg(not(test))]
#[no_mangle]
#[panic_handler]
/// Panic handler
pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! {
// The nRF52840 Dongle LEDs (see back of board)
let led_kernel_pin = &nrf52840::gpio::GPIOPin::new(Pin::P0_06);
let led = &mut led::LedLow::new(led_kernel_pin);
let writer = &mut WRITER;
debug::panic(
&mut [led],
writer,
pi,
&cortexm4::support::nop,
&PROCESSES,
&CHIP,
)
}

View File

@@ -1,420 +0,0 @@
//! Tock kernel for the Nordic Semiconductor nRF52840 dongle.
//!
//! It is based on nRF52840 SoC (Cortex M4 core with a BLE transceiver) with
//! many exported I/O and peripherals.
#![no_std]
// Disable this attribute when documenting, as a workaround for
// https://github.com/rust-lang/rust/issues/62184.
#![cfg_attr(not(doc), no_main)]
#![feature(const_in_array_repeat_expressions)]
#![deny(missing_docs)]
use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
use kernel::component::Component;
use kernel::hil::led::LedLow;
use kernel::hil::time::Counter;
#[allow(unused_imports)]
use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
use nrf52840::gpio::Pin;
use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
use nrf52_components::{self, UartChannel, UartPins};
// The nRF52840 Dongle LEDs
const LED1_PIN: Pin = Pin::P0_06;
const LED2_R_PIN: Pin = Pin::P0_08;
const LED2_G_PIN: Pin = Pin::P1_09;
const LED2_B_PIN: Pin = Pin::P0_12;
// The nRF52840 Dongle button
const BUTTON_PIN: Pin = Pin::P1_06;
const BUTTON_RST_PIN: Pin = Pin::P0_18;
const UART_RTS: Option<Pin> = Some(Pin::P0_13);
const UART_TXD: Pin = Pin::P0_15;
const UART_CTS: Option<Pin> = Some(Pin::P0_17);
const UART_RXD: Pin = Pin::P0_20;
// SPI pins not currently in use, but left here for convenience
const _SPI_MOSI: Pin = Pin::P1_01;
const _SPI_MISO: Pin = Pin::P1_02;
const _SPI_CLK: Pin = Pin::P1_04;
/// UART Writer
pub mod io;
const VENDOR_ID: u16 = 0x1915; // Nordic Semiconductor
const PRODUCT_ID: u16 = 0x521f; // nRF52840 Dongle (PCA10059)
static STRINGS: &'static [&'static str] = &[
// Manufacturer
"Nordic Semiconductor ASA",
// Product
"OpenSK",
// Serial number
"v1.0",
];
// State for loading and holding applications.
// How should the kernel respond when a process faults.
const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic;
// Number of concurrent processes this platform supports.
const NUM_PROCS: usize = 8;
static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] =
[None; NUM_PROCS];
static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 2] = [
// We implement NUM_PAGES = 20 as 16 + 4 to satisfy the MPU.
kernel::StorageLocation {
address: 0xC0000,
size: 0x10000, // 16 pages
storage_type: kernel::StorageType::STORE,
},
kernel::StorageLocation {
address: 0xD0000,
size: 0x4000, // 4 pages
storage_type: kernel::StorageType::STORE,
},
];
// Static reference to chip for panic dumps
static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
/// Dummy buffer that causes the linker to reserve enough space for the stack.
#[no_mangle]
#[link_section = ".stack_buffer"]
pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
/// Supported drivers by the platform
pub struct Platform {
button: &'static capsules::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
pconsole: &'static capsules::process_console::ProcessConsole<
'static,
components::process_console::Capability,
>,
console: &'static capsules::console::Console<'static>,
gpio: &'static capsules::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>,
led: &'static capsules::led::LedDriver<
'static,
LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
>,
rng: &'static capsules::rng::RngDriver<'static>,
ipc: kernel::ipc::IPC<NUM_PROCS>,
analog_comparator: &'static capsules::analog_comparator::AnalogComparator<
'static,
nrf52840::acomp::Comparator<'static>,
>,
alarm: &'static capsules::alarm::AlarmDriver<
'static,
capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
>,
nvmc: &'static nrf52840::nvmc::SyscallDriver,
usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver<
'static,
'static,
nrf52840::usbd::Usbd<'static>,
>,
crp: &'static capsules::firmware_protection::FirmwareProtection<nrf52840::uicr::Uicr>,
}
impl kernel::Platform for Platform {
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
where
F: FnOnce(Option<&dyn kernel::Driver>) -> R,
{
match driver_num {
capsules::console::DRIVER_NUM => f(Some(self.console)),
capsules::gpio::DRIVER_NUM => f(Some(self.gpio)),
capsules::alarm::DRIVER_NUM => f(Some(self.alarm)),
capsules::led::DRIVER_NUM => f(Some(self.led)),
capsules::button::DRIVER_NUM => f(Some(self.button)),
capsules::rng::DRIVER_NUM => f(Some(self.rng)),
capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)),
capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)),
capsules::firmware_protection::DRIVER_NUM => f(Some(self.crp)),
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
_ => f(None),
}
}
fn filter_syscall(
&self,
process: &dyn kernel::procs::ProcessType,
syscall: &kernel::syscall::Syscall,
) -> Result<(), kernel::ReturnCode> {
use kernel::syscall::Syscall;
match *syscall {
Syscall::COMMAND {
driver_number: nrf52840::nvmc::DRIVER_NUM,
subdriver_number: cmd,
arg0: ptr,
arg1: len,
} if (cmd == 2 || cmd == 3) && !process.fits_in_storage_location(ptr, len) => {
Err(kernel::ReturnCode::EINVAL)
}
_ => Ok(()),
}
}
}
/// Entry point in the vector table called on hard reset.
#[no_mangle]
pub unsafe fn reset_handler() {
// Loads relocations and clears BSS
nrf52840::init();
let ppi = static_init!(nrf52840::ppi::Ppi, nrf52840::ppi::Ppi::new());
// Initialize chip peripheral drivers
let nrf52840_peripherals = static_init!(
Nrf52840DefaultPeripherals,
Nrf52840DefaultPeripherals::new(ppi)
);
// set up circular peripheral dependencies
nrf52840_peripherals.init();
let base_peripherals = &nrf52840_peripherals.nrf52;
let board_kernel = static_init!(
kernel::Kernel,
kernel::Kernel::new_with_storage(&PROCESSES, &STORAGE_LOCATIONS)
);
// GPIOs
let gpio = components::gpio::GpioComponent::new(
board_kernel,
components::gpio_component_helper!(
nrf52840::gpio::GPIOPin,
// left side of the USB plug
0 => &nrf52840_peripherals.gpio_port[Pin::P0_13],
1 => &nrf52840_peripherals.gpio_port[Pin::P0_15],
2 => &nrf52840_peripherals.gpio_port[Pin::P0_17],
3 => &nrf52840_peripherals.gpio_port[Pin::P0_20],
4 => &nrf52840_peripherals.gpio_port[Pin::P0_22],
5 => &nrf52840_peripherals.gpio_port[Pin::P0_24],
6 => &nrf52840_peripherals.gpio_port[Pin::P1_00],
7 => &nrf52840_peripherals.gpio_port[Pin::P0_09],
8 => &nrf52840_peripherals.gpio_port[Pin::P0_10],
// right side of the USB plug
9 => &nrf52840_peripherals.gpio_port[Pin::P0_31],
10 => &nrf52840_peripherals.gpio_port[Pin::P0_29],
11 => &nrf52840_peripherals.gpio_port[Pin::P0_02],
12 => &nrf52840_peripherals.gpio_port[Pin::P1_15],
13 => &nrf52840_peripherals.gpio_port[Pin::P1_13],
14 => &nrf52840_peripherals.gpio_port[Pin::P1_10],
// Below the PCB
15 => &nrf52840_peripherals.gpio_port[Pin::P0_26],
16 => &nrf52840_peripherals.gpio_port[Pin::P0_04],
17 => &nrf52840_peripherals.gpio_port[Pin::P0_11],
18 => &nrf52840_peripherals.gpio_port[Pin::P0_14],
19 => &nrf52840_peripherals.gpio_port[Pin::P1_11],
20 => &nrf52840_peripherals.gpio_port[Pin::P1_07],
21 => &nrf52840_peripherals.gpio_port[Pin::P1_01],
22 => &nrf52840_peripherals.gpio_port[Pin::P1_04],
23 => &nrf52840_peripherals.gpio_port[Pin::P1_02]
),
)
.finalize(components::gpio_component_buf!(nrf52840::gpio::GPIOPin));
let button = components::button::ButtonComponent::new(
board_kernel,
components::button_component_helper!(
nrf52840::gpio::GPIOPin,
(
&nrf52840_peripherals.gpio_port[BUTTON_PIN],
kernel::hil::gpio::ActivationMode::ActiveLow,
kernel::hil::gpio::FloatingState::PullUp
)
),
)
.finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin));
let led = components::led::LedsComponent::new(components::led_component_helper!(
LedLow<'static, nrf52840::gpio::GPIOPin>,
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_R_PIN]),
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_G_PIN]),
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_B_PIN]),
))
.finalize(components::led_component_buf!(
LedLow<'static, nrf52840::gpio::GPIOPin>
));
let chip = static_init!(
nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
nrf52840::chip::NRF52::new(nrf52840_peripherals)
);
CHIP = Some(chip);
nrf52_components::startup::NrfStartupComponent::new(
false,
BUTTON_RST_PIN,
nrf52840::uicr::Regulator0Output::V3_0,
&base_peripherals.nvmc,
)
.finalize(());
// Create capabilities that the board needs to call certain protected kernel
// functions.
let process_management_capability =
create_capability!(capabilities::ProcessManagementCapability);
let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
let gpio_port = &nrf52840_peripherals.gpio_port;
// Configure kernel debug gpios as early as possible
kernel::debug::assign_gpios(
Some(&gpio_port[LED2_R_PIN]),
Some(&gpio_port[LED2_G_PIN]),
Some(&gpio_port[LED2_B_PIN]),
);
let rtc = &base_peripherals.rtc;
rtc.start();
let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
.finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc));
let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm)
.finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc));
let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
let channel = nrf52_components::UartChannelComponent::new(
uart_channel,
mux_alarm,
&base_peripherals.uarte0,
)
.finalize(());
let dynamic_deferred_call_clients =
static_init!([DynamicDeferredCallClientState; 3], Default::default());
let dynamic_deferred_caller = static_init!(
DynamicDeferredCall,
DynamicDeferredCall::new(dynamic_deferred_call_clients)
);
DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);
// Create a shared UART channel for the console and for kernel debug.
let uart_mux =
components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller)
.finalize(());
let pconsole =
components::process_console::ProcessConsoleComponent::new(board_kernel, uart_mux)
.finalize(());
// Setup the console.
let console = components::console::ConsoleComponent::new(board_kernel, uart_mux).finalize(());
// Create the debugger object that handles calls to `debug!()`.
components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());
let rng = components::rng::RngComponent::new(board_kernel, &base_peripherals.trng).finalize(());
// Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02)
// These are hardcoded pin assignments specified in the driver
let analog_comparator = components::analog_comparator::AcComponent::new(
&base_peripherals.acomp,
components::acomp_component_helper!(
nrf52840::acomp::Channel,
&nrf52840::acomp::CHANNEL_AC0
),
)
.finalize(components::acomp_component_buf!(
nrf52840::acomp::Comparator
));
let nvmc = static_init!(
nrf52840::nvmc::SyscallDriver,
nrf52840::nvmc::SyscallDriver::new(
&base_peripherals.nvmc,
board_kernel.create_grant(&memory_allocation_capability),
dynamic_deferred_caller,
)
);
nvmc.set_deferred_handle(
dynamic_deferred_caller
.register(nvmc)
.expect("no deferred call slot available for nvmc"),
);
// Configure USB controller
let usb = components::usb_ctap::UsbCtapComponent::new(
board_kernel,
&nrf52840_peripherals.usbd,
capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840,
VENDOR_ID,
PRODUCT_ID,
STRINGS,
)
.finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd));
let crp = components::firmware_protection::FirmwareProtectionComponent::new(
board_kernel,
nrf52840::uicr::Uicr::new(),
)
.finalize(components::firmware_protection_component_helper!(
nrf52840::uicr::Uicr
));
nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
let platform = Platform {
button,
pconsole,
console,
led,
gpio,
rng,
alarm,
analog_comparator,
nvmc,
usb,
crp,
ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
};
platform.pconsole.start();
debug!("Initialization complete. Entering main loop\r");
debug!("{}", &nrf52840::ficr::FICR_INSTANCE);
/// These symbols are defined in the linker script.
extern "C" {
/// Beginning of the ROM region containing app images.
static _sapps: u8;
/// End of the ROM region containing app images.
static _eapps: u8;
/// Beginning of the RAM region for app memory.
static mut _sappmem: u8;
/// End of the RAM region for app memory.
static _eappmem: u8;
}
kernel::procs::load_processes(
board_kernel,
chip,
core::slice::from_raw_parts(
&_sapps as *const u8,
&_eapps as *const u8 as usize - &_sapps as *const u8 as usize,
),
core::slice::from_raw_parts_mut(
&mut _sappmem as *mut u8,
&_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize,
),
&mut PROCESSES,
FAULT_RESPONSE,
&process_management_capability,
)
.unwrap_or_else(|err| {
debug!("Error loading processes!");
debug!("{:?}", err);
});
let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES)
.finalize(components::rr_component_helper!(NUM_PROCS));
board_kernel.kernel_loop(
&platform,
chip,
Some(&platform.ipc),
scheduler,
&main_loop_capability,
);
}

View File

@@ -12,6 +12,3 @@ capsules = { path = "../../../capsules" }
kernel = { path = "../../../kernel" }
nrf52840 = { path = "../../../chips/nrf52840" }
nrf52_components = { path = "../nrf52_components" }
[features]
vendor_hid = ["capsules/vendor_hid"]

View File

@@ -25,10 +25,7 @@ impl Write for Writer {
impl IoWrite for Writer {
fn write(&mut self, buf: &[u8]) {
// Here, we create a second instance of the Uarte struct.
// This is okay because we only call this during a panic, and
// we will never actually process the interrupts
let uart = nrf52840::uart::Uarte::new();
let uart = unsafe { &mut nrf52840::uart::UARTE0 };
if !self.initialized {
self.initialized = true;
uart.configure(uart::Parameters {
@@ -54,8 +51,8 @@ impl IoWrite for Writer {
/// Panic handler
pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! {
// The nRF52840 Dongle LEDs (see back of board)
let led_kernel_pin = &nrf52840::gpio::GPIOPin::new(Pin::P0_23);
let led = &mut led::LedLow::new(led_kernel_pin);
const LED1_PIN: Pin = Pin::P0_23;
let led = &mut led::LedLow::new(&mut nrf52840::gpio::PORT[LED1_PIN]);
let writer = &mut WRITER;
debug::panic(
&mut [led],

View File

@@ -10,14 +10,13 @@
#![feature(const_in_array_repeat_expressions)]
#![deny(missing_docs)]
use capsules::virtual_alarm::VirtualMuxAlarm;
use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
use kernel::component::Component;
use kernel::hil::led::LedLow;
use kernel::hil::time::Counter;
#[allow(unused_imports)]
use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
use kernel::hil::usb::UsbController;
use nrf52840::gpio::Pin;
use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
use nrf52_components::{self, UartChannel, UartPins};
// The nRF52840 MDK USB Dongle LEDs
@@ -27,13 +26,17 @@ const LED1_B_PIN: Pin = Pin::P0_24;
// The nRF52840 Dongle button
const BUTTON_PIN: Pin = Pin::P0_18;
const _BUTTON_RST_PIN: Pin = Pin::P0_02;
const BUTTON_RST_PIN: Pin = Pin::P0_02;
const UART_RTS: Option<Pin> = Some(Pin::P0_21);
const UART_TXD: Pin = Pin::P0_20;
const UART_CTS: Option<Pin> = Some(Pin::P0_03);
const UART_RXD: Pin = Pin::P0_19;
// Constants related to the configuration of the 15.4 network stack
const SRC_MAC: u16 = 0xf00f;
const PAN_ID: u16 = 0xABCD;
/// UART Writer
pub mod io;
@@ -58,22 +61,13 @@ const NUM_PROCS: usize = 8;
static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] =
[None; NUM_PROCS];
static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 2] = [
// We implement NUM_PAGES = 20 as 16 + 4 to satisfy the MPU.
kernel::StorageLocation {
static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 1] = [kernel::StorageLocation {
address: 0xC0000,
size: 0x10000, // 16 pages
storage_type: kernel::StorageType::STORE,
},
kernel::StorageLocation {
address: 0xD0000,
size: 0x4000, // 4 pages
storage_type: kernel::StorageType::STORE,
},
];
size: 0x40000,
}];
// Static reference to chip for panic dumps
static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
static mut CHIP: Option<&'static nrf52840::chip::Chip> = None;
/// Dummy buffer that causes the linker to reserve enough space for the stack.
#[no_mangle]
@@ -82,6 +76,12 @@ pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
/// Supported drivers by the platform
pub struct Platform {
ble_radio: &'static capsules::ble_advertising_driver::BLE<
'static,
nrf52840::ble_radio::Radio<'static>,
VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
>,
ieee802154_radio: &'static capsules::ieee802154::RadioDriver<'static>,
button: &'static capsules::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
pconsole: &'static capsules::process_console::ProcessConsole<
'static,
@@ -89,12 +89,10 @@ pub struct Platform {
>,
console: &'static capsules::console::Console<'static>,
gpio: &'static capsules::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>,
led: &'static capsules::led::LedDriver<
'static,
LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
>,
led: &'static capsules::led::LED<'static, nrf52840::gpio::GPIOPin<'static>>,
rng: &'static capsules::rng::RngDriver<'static>,
ipc: kernel::ipc::IPC<NUM_PROCS>,
temp: &'static capsules::temperature::TemperatureSensor<'static>,
ipc: kernel::ipc::IPC,
analog_comparator: &'static capsules::analog_comparator::AnalogComparator<
'static,
nrf52840::acomp::Comparator<'static>,
@@ -123,6 +121,9 @@ impl kernel::Platform for Platform {
capsules::led::DRIVER_NUM => f(Some(self.led)),
capsules::button::DRIVER_NUM => f(Some(self.button)),
capsules::rng::DRIVER_NUM => f(Some(self.rng)),
capsules::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
capsules::ieee802154::DRIVER_NUM => f(Some(self.ieee802154_radio)),
capsules::temperature::DRIVER_NUM => f(Some(self.temp)),
capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)),
capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)),
@@ -157,17 +158,6 @@ pub unsafe fn reset_handler() {
// Loads relocations and clears BSS
nrf52840::init();
let ppi = static_init!(nrf52840::ppi::Ppi, nrf52840::ppi::Ppi::new());
// Initialize chip peripheral drivers
let nrf52840_peripherals = static_init!(
Nrf52840DefaultPeripherals,
Nrf52840DefaultPeripherals::new(ppi)
);
// set up circular peripheral dependencies
nrf52840_peripherals.init();
let base_peripherals = &nrf52840_peripherals.nrf52;
let board_kernel = static_init!(
kernel::Kernel,
kernel::Kernel::new_with_storage(&PROCESSES, &STORAGE_LOCATIONS)
@@ -178,21 +168,20 @@ pub unsafe fn reset_handler() {
components::gpio_component_helper!(
nrf52840::gpio::GPIOPin,
// left side of the USB plug. Right side is used for UART
0 => &nrf52840_peripherals.gpio_port[Pin::P0_04],
1 => &nrf52840_peripherals.gpio_port[Pin::P0_05],
2 => &nrf52840_peripherals.gpio_port[Pin::P0_06],
3 => &nrf52840_peripherals.gpio_port[Pin::P0_07],
4 => &nrf52840_peripherals.gpio_port[Pin::P0_08]
0 => &nrf52840::gpio::PORT[Pin::P0_04],
1 => &nrf52840::gpio::PORT[Pin::P0_05],
2 => &nrf52840::gpio::PORT[Pin::P0_06],
3 => &nrf52840::gpio::PORT[Pin::P0_07],
4 => &nrf52840::gpio::PORT[Pin::P0_08]
),
)
.finalize(components::gpio_component_buf!(nrf52840::gpio::GPIOPin));
).finalize(components::gpio_component_buf!(nrf52840::gpio::GPIOPin));
let button = components::button::ButtonComponent::new(
board_kernel,
components::button_component_helper!(
nrf52840::gpio::GPIOPin,
(
&nrf52840_peripherals.gpio_port[BUTTON_PIN],
&nrf52840::gpio::PORT[BUTTON_PIN],
kernel::hil::gpio::ActivationMode::ActiveLow,
kernel::hil::gpio::FloatingState::PullUp
)
@@ -201,21 +190,32 @@ pub unsafe fn reset_handler() {
.finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin));
let led = components::led::LedsComponent::new(components::led_component_helper!(
LedLow<'static, nrf52840::gpio::GPIOPin>,
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_R_PIN]),
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_G_PIN]),
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_B_PIN]),
nrf52840::gpio::GPIOPin,
(
&nrf52840::gpio::PORT[LED1_R_PIN],
kernel::hil::gpio::ActivationMode::ActiveLow
),
(
&nrf52840::gpio::PORT[LED1_G_PIN],
kernel::hil::gpio::ActivationMode::ActiveLow
),
(
&nrf52840::gpio::PORT[LED1_B_PIN],
kernel::hil::gpio::ActivationMode::ActiveLow
)
))
.finalize(components::led_component_buf!(
LedLow<'static, nrf52840::gpio::GPIOPin>
));
.finalize(components::led_component_buf!(nrf52840::gpio::GPIOPin));
let chip = static_init!(
nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
nrf52840::chip::NRF52::new(nrf52840_peripherals)
);
let chip = static_init!(nrf52840::chip::Chip, nrf52840::chip::new());
CHIP = Some(chip);
nrf52_components::startup::NrfStartupComponent::new(
false,
BUTTON_RST_PIN,
nrf52840::uicr::Regulator0Output::V3_0,
)
.finalize(());
// Create capabilities that the board needs to call certain protected kernel
// functions.
let process_management_capability =
@@ -223,7 +223,7 @@ pub unsafe fn reset_handler() {
let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
let gpio_port = &nrf52840_peripherals.gpio_port;
let gpio_port = &nrf52840::gpio::PORT;
// Configure kernel debug gpios as early as possible
kernel::debug::assign_gpios(
@@ -232,19 +232,14 @@ pub unsafe fn reset_handler() {
Some(&gpio_port[LED1_B_PIN]),
);
let rtc = &base_peripherals.rtc;
let rtc = &nrf52840::rtc::RTC;
rtc.start();
let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
.finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc));
let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm)
.finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc));
let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
let channel = nrf52_components::UartChannelComponent::new(
uart_channel,
mux_alarm,
&base_peripherals.uarte0,
)
.finalize(());
let channel = nrf52_components::UartChannelComponent::new(uart_channel, mux_alarm).finalize(());
let dynamic_deferred_call_clients =
static_init!([DynamicDeferredCallClientState; 2], Default::default());
@@ -268,12 +263,34 @@ pub unsafe fn reset_handler() {
// Create the debugger object that handles calls to `debug!()`.
components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());
let rng = components::rng::RngComponent::new(board_kernel, &base_peripherals.trng).finalize(());
let ble_radio =
nrf52_components::BLEComponent::new(board_kernel, &nrf52840::ble_radio::RADIO, mux_alarm)
.finalize(());
let (ieee802154_radio, _mux_mac) = components::ieee802154::Ieee802154Component::new(
board_kernel,
&nrf52840::ieee802154_radio::RADIO,
&nrf52840::aes::AESECB,
PAN_ID,
SRC_MAC,
)
.finalize(components::ieee802154_component_helper!(
nrf52840::ieee802154_radio::Radio,
nrf52840::aes::AesECB<'static>
));
let temp = components::temperature::TemperatureComponent::new(
board_kernel,
&nrf52840::temperature::TEMP,
)
.finalize(());
let rng = components::rng::RngComponent::new(board_kernel, &nrf52840::trng::TRNG).finalize(());
// Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02)
// These are hardcoded pin assignments specified in the driver
let analog_comparator = components::analog_comparator::AcComponent::new(
&base_peripherals.acomp,
&nrf52840::acomp::ACOMP,
components::acomp_component_helper!(
nrf52840::acomp::Channel,
&nrf52840::acomp::CHANNEL_AC0
@@ -286,37 +303,66 @@ pub unsafe fn reset_handler() {
let nvmc = static_init!(
nrf52840::nvmc::SyscallDriver,
nrf52840::nvmc::SyscallDriver::new(
&base_peripherals.nvmc,
&nrf52840::nvmc::NVMC,
board_kernel.create_grant(&memory_allocation_capability),
dynamic_deferred_caller,
)
);
nvmc.set_deferred_handle(
dynamic_deferred_caller
.register(nvmc)
.expect("no deferred call slot available for nvmc"),
);
// Configure USB controller
let usb = components::usb_ctap::UsbCtapComponent::new(
board_kernel,
&nrf52840_peripherals.usbd,
let usb:
&'static capsules::usb::usb_ctap::CtapUsbSyscallDriver<
'static,
'static,
nrf52840::usbd::Usbd<'static>,
> = {
let usb_ctap = static_init!(
capsules::usb::usbc_ctap_hid::ClientCtapHID<
'static,
'static,
nrf52840::usbd::Usbd<'static>,
>,
capsules::usb::usbc_ctap_hid::ClientCtapHID::new(
&nrf52840::usbd::USBD,
capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840,
VENDOR_ID,
PRODUCT_ID,
STRINGS,
)
.finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd));
);
nrf52840::usbd::USBD.set_client(usb_ctap);
nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
// Enable power events to be sent to USB controller
nrf52840::power::POWER.set_usb_client(&nrf52840::usbd::USBD);
nrf52840::power::POWER.enable_interrupts();
// Configure the USB userspace driver
let usb_driver = static_init!(
capsules::usb::usb_ctap::CtapUsbSyscallDriver<
'static,
'static,
nrf52840::usbd::Usbd<'static>,
>,
capsules::usb::usb_ctap::CtapUsbSyscallDriver::new(
usb_ctap,
board_kernel.create_grant(&memory_allocation_capability)
)
);
usb_ctap.set_client(usb_driver);
usb_driver as &'static _
};
nrf52_components::NrfClockComponent::new().finalize(());
let platform = Platform {
button,
ble_radio,
ieee802154_radio,
pconsole,
console,
led,
gpio,
rng,
temp,
alarm,
analog_comparator,
nvmc,

View File

@@ -1,17 +0,0 @@
[package]
name = "nrf52840dk_opensk"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
build = "build.rs"
edition = "2018"
[dependencies]
components = { path = "../../components" }
cortexm4 = { path = "../../../arch/cortex-m4" }
capsules = { path = "../../../capsules" }
kernel = { path = "../../../kernel" }
nrf52840 = { path = "../../../chips/nrf52840" }
nrf52_components = { path = "../nrf52_components" }
[features]
vendor_hid = ["capsules/vendor_hid"]

View File

@@ -1,31 +0,0 @@
# Makefile for building the tock kernel for the nRF development kit
TARGET=thumbv7em-none-eabi
PLATFORM=nrf52840dk_opensk
include ../../Makefile.common
TOCKLOADER=tockloader
# Where in the SAM4L flash to load the kernel with `tockloader`
KERNEL_ADDRESS=0x00000
# Upload programs over uart with tockloader
ifdef PORT
TOCKLOADER_GENERAL_FLAGS += --port $(PORT)
endif
# Upload the kernel over JTAG
.PHONY: flash
flash: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin
$(TOCKLOADER) $(TOCKLOADER_GENERAL_FLAGS) flash --address $(KERNEL_ADDRESS) --board nrf52dk --jlink $<
# Upload the kernel over JTAG using OpenOCD
.PHONY: flash-openocd
flash-openocd: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin
$(TOCKLOADER) $(TOCKLOADER_GENERAL_FLAGS) flash --address $(KERNEL_ADDRESS) --board nrf52dk --openocd $<
# Upload the kernel over serial/bootloader
.PHONY: program
program: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).hex
$(error Cannot program nRF52840DK over USB. Use \`make flash\` and JTAG)

View File

@@ -1,65 +0,0 @@
Platform-Specific Instructions: nRF52840-DK
===================================
This is an adapted nrf52840dk made to work with OpenSK.
The [nRF52840 Development
Kit](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) is a platform
based around the nRF52840, an SoC with an ARM Cortex-M4 and a BLE
radio. The kit is Arduino shield compatible and includes several
buttons.
## Getting Started
First, follow the [Tock Getting Started guide](../../../doc/Getting_Started.md)
JTAG is the preferred method to program. The development kit has an
integrated JTAG debugger, you simply need to [install JTAG
software](../../../doc/Getting_Started.md#loading-the-kernel-onto-a-board).
## Programming the kernel
Once you have all software installed, you should be able to simply run
make flash in this directory to install a fresh kernel.
## Programming user-level applications
You can program an application over USB using the integrated JTAG and `tockloader`:
```bash
$ cd libtock-c/examples/<app>
$ make
$ tockloader install --jlink --board nrf52dk
```
The same options (`--jlink --board nrf52dk`) must be passed for other tockloader commands
such as `erase-apps` or `list`.
Viewing console output on the nrf52840dk is slightly different from other boards. You must use
```bash
$ tockloader listen
```
**followed by a press of the reset button** in order to view console output starting from the boot
sequence. Notably, you should not
pass the `--jlink` option to `tockloader listen`.
## Console output
This board supports two methods for writing messages to a console interface
(console driver for applications as well as debug statements in the kernel).
By default, messages are written to a UART interface over the GPIO pins `P0.05`
to `P0.08` (see the [main.rs](src/main.rs) file).
If you don't have any UART cables or want to use a different interface, there is
also a console over the Segger RTT protocol. This only requires a micro-USB
cable on the USB debugging port (the same used to flash Tock on the board), and
is enabled by setting the `USB_DEBUGGING` constant to `true` in the
[main.rs](src/main.rs) file.
This disables the UART interface.
For instructions about how to receive RTT messages on the host, see the
[corresponding capsule](../../../capsules/src/segger_rtt.rs).
## Debugging
See the [nrf52dk README](../nrf52dk/README.md) for information about debugging
the nRF52840dk.

View File

@@ -1,29 +0,0 @@
use std::env;
use std::fs;
use std::path::Path;
fn main() {
println!("cargo:rerun-if-changed=layout.ld");
println!("cargo:rerun-if-changed=../../kernel_layout.ld");
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("locations.rs");
fs::write(
&dest_path,
"
static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 2] = [
// We implement NUM_PAGES = 20 as 16 + 4 to satisfy the MPU.
kernel::StorageLocation {
address: 0xC0000,
size: 0x10000, // 16 pages
storage_type: kernel::StorageType::STORE,
},
kernel::StorageLocation {
address: 0xD0000,
size: 0x4000, // 4 pages
storage_type: kernel::StorageType::STORE,
},
];
"
).unwrap();
}

View File

@@ -1,25 +0,0 @@
#
#
#
# J-LINK GDB SERVER initialization
#
# This connects to a GDB Server listening
# for commands on localhost at tcp port 2331
target remote localhost:2331
monitor speed 30
file ../../../../target/thumbv7em-none-eabi/release/nrf52dk
monitor reset
#
# CPU core initialization (to be done by user)
#
# Set the processor mode
# monitor reg cpsr = 0xd3
# Set auto JTAG speed
monitor speed auto
# Setup GDB FOR FASTER DOWNLOADS
set remote memory-write-packet-size 1024
set remote memory-write-packet-size fixed
# tui enable
# layout split
# layout service_pending_interrupts
b reset_handler

View File

@@ -1 +0,0 @@
JLinkGDBServer -device nrf52 -speed 1200 -if swd -AutoConnect 1 -port 2331

View File

@@ -1,2 +0,0 @@
INCLUDE ../nrf52840_chip_layout.ld
INCLUDE ../../kernel_layout.ld

View File

@@ -1,106 +0,0 @@
use core::fmt::Write;
use core::panic::PanicInfo;
use cortexm4;
use kernel::debug;
use kernel::debug::IoWrite;
use kernel::hil::led;
use kernel::hil::uart;
use kernel::hil::uart::Configure;
use nrf52840::gpio::Pin;
use crate::CHIP;
use crate::PROCESSES;
enum Writer {
WriterUart(/* initialized */ bool),
WriterRtt(&'static capsules::segger_rtt::SeggerRttMemory<'static>),
}
static mut WRITER: Writer = Writer::WriterUart(false);
fn wait() {
for _ in 0..100 {
cortexm4::support::nop();
}
}
/// Set the RTT memory buffer used to output panic messages.
pub unsafe fn set_rtt_memory(
rtt_memory: &'static mut capsules::segger_rtt::SeggerRttMemory<'static>,
) {
WRITER = Writer::WriterRtt(rtt_memory);
}
impl Write for Writer {
fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
self.write(s.as_bytes());
Ok(())
}
}
impl IoWrite for Writer {
fn write(&mut self, buf: &[u8]) {
match self {
Writer::WriterUart(ref mut initialized) => {
// Here, we create a second instance of the Uarte struct.
// This is okay because we only call this during a panic, and
// we will never actually process the interrupts
let uart = nrf52840::uart::Uarte::new();
if !*initialized {
*initialized = true;
uart.configure(uart::Parameters {
baud_rate: 115200,
stop_bits: uart::StopBits::One,
parity: uart::Parity::None,
hw_flow_control: false,
width: uart::Width::Eight,
});
}
for &c in buf {
unsafe {
uart.send_byte(c);
}
while !uart.tx_ready() {}
}
}
Writer::WriterRtt(rtt_memory) => {
let up_buffer = unsafe { &*rtt_memory.get_up_buffer_ptr() };
let buffer_len = up_buffer.length.get();
let buffer = unsafe {
core::slice::from_raw_parts_mut(
up_buffer.buffer.get() as *mut u8,
buffer_len as usize,
)
};
let mut write_position = up_buffer.write_position.get();
for &c in buf {
buffer[write_position as usize] = c;
write_position = (write_position + 1) % buffer_len;
up_buffer.write_position.set(write_position);
wait();
}
}
};
}
}
#[cfg(not(test))]
#[no_mangle]
#[panic_handler]
/// Panic handler
pub unsafe extern "C" fn panic_fmt(pi: &PanicInfo) -> ! {
// The nRF52840DK LEDs (see back of board)
let led_kernel_pin = &nrf52840::gpio::GPIOPin::new(Pin::P0_13);
let led = &mut led::LedLow::new(led_kernel_pin);
let writer = &mut WRITER;
debug::panic(
&mut [led],
writer,
pi,
&cortexm4::support::nop,
&PROCESSES,
&CHIP,
)
}

View File

@@ -1,493 +0,0 @@
//! Tock kernel for the Nordic Semiconductor nRF52840 development kit (DK).
//!
//! It is based on nRF52840 SoC (Cortex M4 core with a BLE transceiver) with
//! many exported I/O and peripherals.
//!
//! Pin Configuration
//! -------------------
//!
//! ### `GPIO`
//!
//! | # | Pin | Ix | Header | Arduino |
//! |----|-------|----|--------|---------|
//! | 0 | P1.01 | 33 | P3 1 | D0 |
//! | 1 | P1.02 | 34 | P3 2 | D1 |
//! | 2 | P1.03 | 35 | P3 3 | D2 |
//! | 3 | P1.04 | 36 | P3 4 | D3 |
//! | 4 | P1.05 | 37 | P3 5 | D4 |
//! | 5 | P1.06 | 38 | P3 6 | D5 |
//! | 6 | P1.07 | 39 | P3 7 | D6 |
//! | 7 | P1.08 | 40 | P3 8 | D7 |
//! | 8 | P1.10 | 42 | P4 1 | D8 |
//! | 9 | P1.11 | 43 | P4 2 | D9 |
//! | 10 | P1.12 | 44 | P4 3 | D10 |
//! | 11 | P1.13 | 45 | P4 4 | D11 |
//! | 12 | P1.14 | 46 | P4 5 | D12 |
//! | 13 | P1.15 | 47 | P4 6 | D13 |
//! | 14 | P0.26 | 26 | P4 9 | D14 |
//! | 15 | P0.27 | 27 | P4 10 | D15 |
//!
//! ### `GPIO` / Analog Inputs
//!
//! | # | Pin | Header | Arduino |
//! |----|------------|--------|---------|
//! | 16 | P0.03 AIN1 | P2 1 | A0 |
//! | 17 | P0.04 AIN2 | P2 2 | A1 |
//! | 18 | P0.28 AIN4 | P2 3 | A2 |
//! | 19 | P0.29 AIN5 | P2 4 | A3 |
//! | 20 | P0.30 AIN6 | P2 5 | A4 |
//! | 21 | P0.31 AIN7 | P2 6 | A5 |
//! | 22 | P0.02 AIN0 | P4 8 | AVDD |
//!
//! ### Onboard Functions
//!
//! | Pin | Header | Function |
//! |-------|--------|----------|
//! | P0.05 | P6 3 | UART RTS |
//! | P0.06 | P6 4 | UART TXD |
//! | P0.07 | P6 5 | UART CTS |
//! | P0.08 | P6 6 | UART RXT |
//! | P0.11 | P24 1 | Button 1 |
//! | P0.12 | P24 2 | Button 2 |
//! | P0.13 | P24 3 | LED 1 |
//! | P0.14 | P24 4 | LED 2 |
//! | P0.15 | P24 5 | LED 3 |
//! | P0.16 | P24 6 | LED 4 |
//! | P0.18 | P24 8 | Reset |
//! | P0.19 | P24 9 | SPI CLK |
//! | P0.20 | P24 10 | SPI MOSI |
//! | P0.21 | P24 11 | SPI MISO |
//! | P0.24 | P24 14 | Button 3 |
//! | P0.25 | P24 15 | Button 4 |
#![no_std]
// Disable this attribute when documenting, as a workaround for
// https://github.com/rust-lang/rust/issues/62184.
#![cfg_attr(not(doc), no_main)]
#![feature(const_in_array_repeat_expressions)]
#![deny(missing_docs)]
use core::env;
use kernel::common::dynamic_deferred_call::{DynamicDeferredCall, DynamicDeferredCallClientState};
use kernel::component::Component;
use kernel::hil::led::LedLow;
use kernel::hil::time::Counter;
#[allow(unused_imports)]
use kernel::{capabilities, create_capability, debug, debug_gpio, debug_verbose, static_init};
use nrf52840::gpio::Pin;
use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
use nrf52_components::{self, UartChannel, UartPins};
// The nRF52840DK LEDs (see back of board)
const LED1_PIN: Pin = Pin::P0_13;
const LED2_PIN: Pin = Pin::P0_14;
const LED3_PIN: Pin = Pin::P0_15;
const LED4_PIN: Pin = Pin::P0_16;
// The nRF52840DK buttons (see back of board)
const BUTTON1_PIN: Pin = Pin::P0_11;
const BUTTON2_PIN: Pin = Pin::P0_12;
const BUTTON3_PIN: Pin = Pin::P0_24;
const BUTTON4_PIN: Pin = Pin::P0_25;
const BUTTON_RST_PIN: Pin = Pin::P0_18;
const UART_RTS: Option<Pin> = Some(Pin::P0_05);
const UART_TXD: Pin = Pin::P0_06;
const UART_CTS: Option<Pin> = Some(Pin::P0_07);
const UART_RXD: Pin = Pin::P0_08;
const SPI_MOSI: Pin = Pin::P0_20;
const SPI_MISO: Pin = Pin::P0_21;
const SPI_CLK: Pin = Pin::P0_19;
/// Debug Writer
pub mod io;
// Whether to use UART debugging or Segger RTT (USB) debugging.
// - Set to false to use UART.
// - Set to true to use Segger RTT over USB.
const USB_DEBUGGING: bool = true;
const VENDOR_ID: u16 = 0x1915; // Nordic Semiconductor
const PRODUCT_ID: u16 = 0x521f; // nRF52840 Dongle (PCA10059)
static STRINGS: &'static [&'static str] = &[
// Manufacturer
"Nordic Semiconductor ASA",
// Product
"OpenSK",
// Serial number
"v1.0",
];
// State for loading and holding applications.
// How should the kernel respond when a process faults.
const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultResponse::Panic;
// Number of concurrent processes this platform supports.
const NUM_PROCS: usize = 8;
static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] =
[None; NUM_PROCS];
include!(concat!(env!("OUT_DIR"), "/locations.rs"));
static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
/// Dummy buffer that causes the linker to reserve enough space for the stack.
#[no_mangle]
#[link_section = ".stack_buffer"]
pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
/// Supported drivers by the platform
pub struct Platform {
button: &'static capsules::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
pconsole: &'static capsules::process_console::ProcessConsole<
'static,
components::process_console::Capability,
>,
console: &'static capsules::console::Console<'static>,
gpio: &'static capsules::gpio::GPIO<'static, nrf52840::gpio::GPIOPin<'static>>,
led: &'static capsules::led::LedDriver<
'static,
kernel::hil::led::LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
>,
rng: &'static capsules::rng::RngDriver<'static>,
ipc: kernel::ipc::IPC<NUM_PROCS>,
analog_comparator: &'static capsules::analog_comparator::AnalogComparator<
'static,
nrf52840::acomp::Comparator<'static>,
>,
alarm: &'static capsules::alarm::AlarmDriver<
'static,
capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52840::rtc::Rtc<'static>>,
>,
nvmc: &'static nrf52840::nvmc::SyscallDriver,
usb: &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver<
'static,
'static,
nrf52840::usbd::Usbd<'static>,
>,
crp: &'static capsules::firmware_protection::FirmwareProtection<nrf52840::uicr::Uicr>,
}
impl kernel::Platform for Platform {
fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
where
F: FnOnce(Option<&dyn kernel::Driver>) -> R,
{
match driver_num {
capsules::console::DRIVER_NUM => f(Some(self.console)),
capsules::gpio::DRIVER_NUM => f(Some(self.gpio)),
capsules::alarm::DRIVER_NUM => f(Some(self.alarm)),
capsules::led::DRIVER_NUM => f(Some(self.led)),
capsules::button::DRIVER_NUM => f(Some(self.button)),
capsules::rng::DRIVER_NUM => f(Some(self.rng)),
capsules::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
nrf52840::nvmc::DRIVER_NUM => f(Some(self.nvmc)),
capsules::usb::usb_ctap::DRIVER_NUM => f(Some(self.usb)),
capsules::firmware_protection::DRIVER_NUM => f(Some(self.crp)),
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
_ => f(None),
}
}
fn filter_syscall(
&self,
process: &dyn kernel::procs::ProcessType,
syscall: &kernel::syscall::Syscall,
) -> Result<(), kernel::ReturnCode> {
use kernel::syscall::Syscall;
match *syscall {
Syscall::COMMAND {
driver_number: nrf52840::nvmc::DRIVER_NUM,
subdriver_number: cmd,
arg0: ptr,
arg1: len,
} if (cmd == 2 || cmd == 3) && !process.fits_in_storage_location(ptr, len) => {
Err(kernel::ReturnCode::EINVAL)
}
_ => Ok(()),
}
}
}
/// Entry point in the vector table called on hard reset.
#[no_mangle]
pub unsafe fn reset_handler() {
// Loads relocations and clears BSS
nrf52840::init();
let ppi = static_init!(nrf52840::ppi::Ppi, nrf52840::ppi::Ppi::new());
// Initialize chip peripheral drivers
let nrf52840_peripherals = static_init!(
Nrf52840DefaultPeripherals,
Nrf52840DefaultPeripherals::new(ppi)
);
// set up circular peripheral dependencies
nrf52840_peripherals.init();
let base_peripherals = &nrf52840_peripherals.nrf52;
let uart_channel = if USB_DEBUGGING {
// Initialize early so any panic beyond this point can use the RTT memory object.
let mut rtt_memory_refs =
components::segger_rtt::SeggerRttMemoryComponent::new().finalize(());
// XXX: This is inherently unsafe as it aliases the mutable reference to rtt_memory. This
// aliases reference is only used inside a panic handler, which should be OK, but maybe we
// should use a const reference to rtt_memory and leverage interior mutability instead.
self::io::set_rtt_memory(&mut *rtt_memory_refs.get_rtt_memory_ptr());
UartChannel::Rtt(rtt_memory_refs)
} else {
UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD))
};
let board_kernel = static_init!(
kernel::Kernel,
kernel::Kernel::new_with_storage(&PROCESSES, &STORAGE_LOCATIONS)
);
let gpio = components::gpio::GpioComponent::new(
board_kernel,
components::gpio_component_helper!(
nrf52840::gpio::GPIOPin,
0 => &nrf52840_peripherals.gpio_port[Pin::P1_01],
1 => &nrf52840_peripherals.gpio_port[Pin::P1_02],
2 => &nrf52840_peripherals.gpio_port[Pin::P1_03],
3 => &nrf52840_peripherals.gpio_port[Pin::P1_04],
4 => &nrf52840_peripherals.gpio_port[Pin::P1_05],
5 => &nrf52840_peripherals.gpio_port[Pin::P1_06],
6 => &nrf52840_peripherals.gpio_port[Pin::P1_07],
7 => &nrf52840_peripherals.gpio_port[Pin::P1_08],
8 => &nrf52840_peripherals.gpio_port[Pin::P1_10],
9 => &nrf52840_peripherals.gpio_port[Pin::P1_11],
10 => &nrf52840_peripherals.gpio_port[Pin::P1_12],
11 => &nrf52840_peripherals.gpio_port[Pin::P1_13],
12 => &nrf52840_peripherals.gpio_port[Pin::P1_14],
13 => &nrf52840_peripherals.gpio_port[Pin::P1_15],
14 => &nrf52840_peripherals.gpio_port[Pin::P0_26],
15 => &nrf52840_peripherals.gpio_port[Pin::P0_27]
),
)
.finalize(components::gpio_component_buf!(nrf52840::gpio::GPIOPin));
let button = components::button::ButtonComponent::new(
board_kernel,
components::button_component_helper!(
nrf52840::gpio::GPIOPin,
(
&nrf52840_peripherals.gpio_port[BUTTON1_PIN],
kernel::hil::gpio::ActivationMode::ActiveLow,
kernel::hil::gpio::FloatingState::PullUp
), //13
(
&nrf52840_peripherals.gpio_port[BUTTON2_PIN],
kernel::hil::gpio::ActivationMode::ActiveLow,
kernel::hil::gpio::FloatingState::PullUp
), //14
(
&nrf52840_peripherals.gpio_port[BUTTON3_PIN],
kernel::hil::gpio::ActivationMode::ActiveLow,
kernel::hil::gpio::FloatingState::PullUp
), //15
(
&nrf52840_peripherals.gpio_port[BUTTON4_PIN],
kernel::hil::gpio::ActivationMode::ActiveLow,
kernel::hil::gpio::FloatingState::PullUp
) //16
),
)
.finalize(components::button_component_buf!(nrf52840::gpio::GPIOPin));
let led = components::led::LedsComponent::new(components::led_component_helper!(
LedLow<'static, nrf52840::gpio::GPIOPin>,
LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
LedLow::new(&nrf52840_peripherals.gpio_port[LED2_PIN]),
LedLow::new(&nrf52840_peripherals.gpio_port[LED3_PIN]),
LedLow::new(&nrf52840_peripherals.gpio_port[LED4_PIN]),
))
.finalize(components::led_component_buf!(
LedLow<'static, nrf52840::gpio::GPIOPin>
));
let chip = static_init!(
nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
nrf52840::chip::NRF52::new(nrf52840_peripherals)
);
CHIP = Some(chip);
nrf52_components::startup::NrfStartupComponent::new(
false,
BUTTON_RST_PIN,
nrf52840::uicr::Regulator0Output::DEFAULT,
&base_peripherals.nvmc,
)
.finalize(());
// Create capabilities that the board needs to call certain protected kernel
// functions.
let process_management_capability =
create_capability!(capabilities::ProcessManagementCapability);
let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
let gpio_port = &nrf52840_peripherals.gpio_port;
// Configure kernel debug gpios as early as possible
kernel::debug::assign_gpios(
Some(&gpio_port[LED1_PIN]),
Some(&gpio_port[LED2_PIN]),
Some(&gpio_port[LED3_PIN]),
);
let rtc = &base_peripherals.rtc;
rtc.start();
let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
.finalize(components::alarm_mux_component_helper!(nrf52840::rtc::Rtc));
let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm)
.finalize(components::alarm_component_helper!(nrf52840::rtc::Rtc));
let channel = nrf52_components::UartChannelComponent::new(
uart_channel,
mux_alarm,
&base_peripherals.uarte0,
)
.finalize(());
let dynamic_deferred_call_clients =
static_init!([DynamicDeferredCallClientState; 3], Default::default());
let dynamic_deferred_caller = static_init!(
DynamicDeferredCall,
DynamicDeferredCall::new(dynamic_deferred_call_clients)
);
DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);
// Create a shared UART channel for the console and for kernel debug.
let uart_mux =
components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller)
.finalize(());
let pconsole =
components::process_console::ProcessConsoleComponent::new(board_kernel, uart_mux)
.finalize(());
// Setup the console.
let console = components::console::ConsoleComponent::new(board_kernel, uart_mux).finalize(());
// Create the debugger object that handles calls to `debug!()`.
components::debug_writer::DebugWriterComponent::new(uart_mux).finalize(());
let rng = components::rng::RngComponent::new(board_kernel, &base_peripherals.trng).finalize(());
base_peripherals.spim0.configure(
nrf52840::pinmux::Pinmux::new(SPI_MOSI as u32),
nrf52840::pinmux::Pinmux::new(SPI_MISO as u32),
nrf52840::pinmux::Pinmux::new(SPI_CLK as u32),
);
// Initialize AC using AIN5 (P0.29) as VIN+ and VIN- as AIN0 (P0.02)
// These are hardcoded pin assignments specified in the driver
let analog_comparator = components::analog_comparator::AcComponent::new(
&base_peripherals.acomp,
components::acomp_component_helper!(
nrf52840::acomp::Channel,
&nrf52840::acomp::CHANNEL_AC0
),
)
.finalize(components::acomp_component_buf!(
nrf52840::acomp::Comparator
));
let nvmc = static_init!(
nrf52840::nvmc::SyscallDriver,
nrf52840::nvmc::SyscallDriver::new(
&base_peripherals.nvmc,
board_kernel.create_grant(&memory_allocation_capability),
dynamic_deferred_caller,
)
);
nvmc.set_deferred_handle(
dynamic_deferred_caller
.register(nvmc)
.expect("no deferred call slot available for nvmc"),
);
// Configure USB controller
let usb = components::usb_ctap::UsbCtapComponent::new(
board_kernel,
&nrf52840_peripherals.usbd,
capsules::usb::usbc_client::MAX_CTRL_PACKET_SIZE_NRF52840,
VENDOR_ID,
PRODUCT_ID,
STRINGS,
)
.finalize(components::usb_ctap_component_buf!(nrf52840::usbd::Usbd));
let crp = components::firmware_protection::FirmwareProtectionComponent::new(
board_kernel,
nrf52840::uicr::Uicr::new(),
)
.finalize(components::firmware_protection_component_helper!(
nrf52840::uicr::Uicr
));
nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
let platform = Platform {
button,
pconsole,
console,
led,
gpio,
rng,
alarm,
analog_comparator,
nvmc,
usb,
crp,
ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
};
platform.pconsole.start();
debug!("Initialization complete. Entering main loop\r");
debug!("{}", &nrf52840::ficr::FICR_INSTANCE);
/// These symbols are defined in the linker script.
extern "C" {
/// Beginning of the ROM region containing app images.
static _sapps: u8;
/// End of the ROM region containing app images.
static _eapps: u8;
/// Beginning of the RAM region for app memory.
static mut _sappmem: u8;
/// End of the RAM region for app memory.
static _eappmem: u8;
}
kernel::procs::load_processes(
board_kernel,
chip,
core::slice::from_raw_parts(
&_sapps as *const u8,
&_eapps as *const u8 as usize - &_sapps as *const u8 as usize,
),
core::slice::from_raw_parts_mut(
&mut _sappmem as *mut u8,
&_eappmem as *const u8 as usize - &_sappmem as *const u8 as usize,
),
&mut PROCESSES,
FAULT_RESPONSE,
&process_management_capability,
)
.unwrap_or_else(|err| {
debug!("Error loading processes!");
debug!("{:?}", err);
});
let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES)
.finalize(components::rr_component_helper!(NUM_PROCS));
board_kernel.kernel_loop(
&platform,
chip,
Some(&platform.ipc),
scheduler,
&main_loop_capability,
);
}

View File

@@ -1,21 +0,0 @@
[package]
name = "nrf52840dk_opensk_a"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
build = "build.rs"
edition = "2018"
[[bin]]
path = "../nrf52840dk_opensk/src/main.rs"
name = "nrf52840dk_opensk_a"
[dependencies]
components = { path = "../../components" }
cortexm4 = { path = "../../../arch/cortex-m4" }
capsules = { path = "../../../capsules" }
kernel = { path = "../../../kernel" }
nrf52840 = { path = "../../../chips/nrf52840" }
nrf52_components = { path = "../nrf52_components" }
[features]
vendor_hid = ["capsules/vendor_hid"]

View File

@@ -1,31 +0,0 @@
# Makefile for building the tock kernel for the nRF development kit
TARGET=thumbv7em-none-eabi
PLATFORM=nrf52840dk_opensk_a
include ../../Makefile.common
TOCKLOADER=tockloader
# Where in the SAM4L flash to load the kernel with `tockloader`
KERNEL_ADDRESS=0x20000
# Upload programs over uart with tockloader
ifdef PORT
TOCKLOADER_GENERAL_FLAGS += --port $(PORT)
endif
# Upload the kernel over JTAG
.PHONY: flash
flash: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin
$(TOCKLOADER) $(TOCKLOADER_GENERAL_FLAGS) flash --address $(KERNEL_ADDRESS) --board nrf52dk --jlink $<
# Upload the kernel over JTAG using OpenOCD
.PHONY: flash-openocd
flash-openocd: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin
$(TOCKLOADER) $(TOCKLOADER_GENERAL_FLAGS) flash --address $(KERNEL_ADDRESS) --board nrf52dk --openocd $<
# Upload the kernel over serial/bootloader
.PHONY: program
program: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).hex
$(error Cannot program nRF52840DK over USB. Use \`make flash\` and JTAG)

View File

@@ -1,11 +0,0 @@
Platform-Specific Instructions: nRF52840-DK, partition A
===================================
This is an upgrade partition for the adapted nrf52840dk in `../nrf52840dk_opensk`.
Compared to our regular board definition for the nrf52840dk, changes are:
- a `layout.ld` with 128 kB for kernel and app
- the matching kernel address in the `Makefile`
- different `StorageLocation`s in `build.rs`
For everything else, please check the README in `../nrf52840dk_opensk`.

View File

@@ -1,45 +0,0 @@
use std::env;
use std::fs;
use std::path::Path;
fn main() {
println!("cargo:rerun-if-changed=layout.ld");
println!("cargo:rerun-if-changed=../../kernel_layout.ld");
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("locations.rs");
fs::write(
&dest_path,
"
static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 5] = [
// We implement NUM_PAGES = 20 as 16 + 4 to satisfy the MPU.
kernel::StorageLocation {
address: 0xC0000,
size: 0x10000, // 16 pages
storage_type: kernel::StorageType::STORE,
},
kernel::StorageLocation {
address: 0xD0000,
size: 0x4000, // 4 pages
storage_type: kernel::StorageType::STORE,
},
// Partitions can also be split to maximize MPU happiness.
kernel::StorageLocation {
address: 0x60000,
size: 0x20000,
storage_type: kernel::StorageType::PARTITION,
},
kernel::StorageLocation {
address: 0x80000,
size: 0x20000,
storage_type: kernel::StorageType::PARTITION,
},
kernel::StorageLocation {
address: 0x5000,
size: 0x1000,
storage_type: kernel::StorageType::METADATA,
},
];
"
).unwrap();
}

View File

@@ -1,13 +0,0 @@
/* Memory Space Definitions, 1M flash, 256K ram */
MEMORY
{
rom (rx) : ORIGIN = 0x00020000, LENGTH = 128K
prog (rx) : ORIGIN = 0x00040000, LENGTH = 128K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
}
MPU_MIN_ALIGN = 8K;
PAGE_SIZE = 4K;
INCLUDE ../../kernel_layout.ld

View File

@@ -1,21 +0,0 @@
[package]
name = "nrf52840dk_opensk_b"
version = "0.1.0"
authors = ["Tock Project Developers <tock-dev@googlegroups.com>"]
build = "build.rs"
edition = "2018"
[[bin]]
path = "../nrf52840dk_opensk/src/main.rs"
name = "nrf52840dk_opensk_b"
[dependencies]
components = { path = "../../components" }
cortexm4 = { path = "../../../arch/cortex-m4" }
capsules = { path = "../../../capsules" }
kernel = { path = "../../../kernel" }
nrf52840 = { path = "../../../chips/nrf52840" }
nrf52_components = { path = "../nrf52_components" }
[features]
vendor_hid = ["capsules/vendor_hid"]

View File

@@ -1,31 +0,0 @@
# Makefile for building the tock kernel for the nRF development kit
TARGET=thumbv7em-none-eabi
PLATFORM=nrf52840dk_opensk_b
include ../../Makefile.common
TOCKLOADER=tockloader
# Where in the SAM4L flash to load the kernel with `tockloader`
KERNEL_ADDRESS=0x60000
# Upload programs over uart with tockloader
ifdef PORT
TOCKLOADER_GENERAL_FLAGS += --port $(PORT)
endif
# Upload the kernel over JTAG
.PHONY: flash
flash: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin
$(TOCKLOADER) $(TOCKLOADER_GENERAL_FLAGS) flash --address $(KERNEL_ADDRESS) --board nrf52dk --jlink $<
# Upload the kernel over JTAG using OpenOCD
.PHONY: flash-openocd
flash-openocd: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).bin
$(TOCKLOADER) $(TOCKLOADER_GENERAL_FLAGS) flash --address $(KERNEL_ADDRESS) --board nrf52dk --openocd $<
# Upload the kernel over serial/bootloader
.PHONY: program
program: $(TOCK_ROOT_DIRECTORY)target/$(TARGET)/release/$(PLATFORM).hex
$(error Cannot program nRF52840DK over USB. Use \`make flash\` and JTAG)

View File

@@ -1,11 +0,0 @@
Platform-Specific Instructions: nRF52840-DK, partition B
===================================
This is an upgrade partition for the adapted nrf52840dk in `../nrf52840dk_opensk`.
Compared to our regular board definition for the nrf52840dk, changes are:
- a `layout.ld` with 128 kB for kernel and app
- the matching kernel address in the `Makefile`
- different `StorageLocation`s in `build.rs`
For everything else, please check the README in `../nrf52840dk_opensk`.

View File

@@ -1,45 +0,0 @@
use std::env;
use std::fs;
use std::path::Path;
fn main() {
println!("cargo:rerun-if-changed=layout.ld");
println!("cargo:rerun-if-changed=../../kernel_layout.ld");
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("locations.rs");
fs::write(
&dest_path,
"
static mut STORAGE_LOCATIONS: [kernel::StorageLocation; 5] = [
// We implement NUM_PAGES = 20 as 16 + 4 to satisfy the MPU.
kernel::StorageLocation {
address: 0xC0000,
size: 0x10000, // 16 pages
storage_type: kernel::StorageType::STORE,
},
kernel::StorageLocation {
address: 0xD0000,
size: 0x4000, // 4 pages
storage_type: kernel::StorageType::STORE,
},
// Partitions can also be split to maximize MPU happiness.
kernel::StorageLocation {
address: 0x20000,
size: 0x20000,
storage_type: kernel::StorageType::PARTITION,
},
kernel::StorageLocation {
address: 0x40000,
size: 0x20000,
storage_type: kernel::StorageType::PARTITION,
},
kernel::StorageLocation {
address: 0x4000,
size: 0x1000,
storage_type: kernel::StorageType::METADATA,
},
];
"
).unwrap();
}

View File

@@ -1,13 +0,0 @@
/* Memory Space Definitions, 1M flash, 256K ram */
MEMORY
{
rom (rx) : ORIGIN = 0x00060000, LENGTH = 128K
prog (rx) : ORIGIN = 0x00080000, LENGTH = 128K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 256K
}
MPU_MIN_ALIGN = 8K;
PAGE_SIZE = 4K;
INCLUDE ../../kernel_layout.ld

View File

@@ -1,2 +0,0 @@
[target.thumbv7em-none-eabi]
linker = "arm-none-eabi-gcc"

282
bootloader/Cargo.lock generated
View File

@@ -1,282 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aligned"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a785a543aea40f5e4e2e93bb2655d31bc21bb391fff65697150973e383f16bb"
dependencies = [
"as-slice",
]
[[package]]
name = "as-slice"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
dependencies = [
"generic-array 0.12.4",
"generic-array 0.13.3",
"generic-array 0.14.6",
"stable_deref_trait",
]
[[package]]
name = "bare-metal"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
dependencies = [
"rustc_version",
]
[[package]]
name = "bitfield"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
[[package]]
name = "bootloader"
version = "0.1.0"
dependencies = [
"byteorder",
"cortex-m 0.6.7",
"cortex-m-rt",
"cortex-m-rt-macros",
"panic-abort",
"rtt-target",
"tock-registers",
]
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cortex-m"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9075300b07c6a56263b9b582c214d0ff037b00d45ec9fde1cc711490c56f1bb9"
dependencies = [
"aligned",
"bare-metal",
"bitfield",
"cortex-m 0.7.6",
"volatile-register",
]
[[package]]
name = "cortex-m"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0"
dependencies = [
"bare-metal",
"bitfield",
"embedded-hal",
"volatile-register",
]
[[package]]
name = "cortex-m-rt"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c433da385b720d5bb9f52362fa2782420798e68d40d67bfe4b0d992aba5dfe7"
dependencies = [
"cortex-m-rt-macros",
]
[[package]]
name = "cortex-m-rt-macros"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "embedded-hal"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
dependencies = [
"nb 0.1.3",
"void",
]
[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "nb"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
dependencies = [
"nb 1.0.0",
]
[[package]]
name = "nb"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
[[package]]
name = "panic-abort"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e20e6499bbbc412f280b04a42346b356c6fa0753d5fd22b7bd752ff34c778ee"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rtt-target"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065d6058bb1204f51a562a67209e1817cf714759d5cf845aa45c75fa7b0b9d9b"
dependencies = [
"cortex-m 0.7.6",
"ufmt-write",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[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-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tock-registers"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f521a79accce68c417c9c77ce22108056b626126da1932f7e2e9b5bbffee0cea"
[[package]]
name = "typenum"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "ufmt-write"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69"
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "vcell"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "volatile-register"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
dependencies = [
"vcell",
]

View File

@@ -1,29 +0,0 @@
[package]
name = "bootloader"
version = "0.1.0"
authors = [
"Fabian Kaczmarczyck <kaczmarczyck@google.com>",
]
build = "build.rs"
license = "Apache-2.0"
edition = "2018"
[dependencies]
byteorder = { version = "1", default-features = false }
cortex-m = "^0.6.0"
cortex-m-rt = "*"
cortex-m-rt-macros = "*"
panic-abort = "0.3.2"
rtt-target = { version = "*", features = ["cortex-m"] }
tock-registers = { version = "0.6.0", features = ["no_std_unit_tests"] }
[profile.dev]
panic = "abort"
lto = true
opt-level = 3
[profile.release]
panic = "abort"
lto = true
# Level "z" may decrease the binary size more of necessary.
opt-level = 3

View File

@@ -1,36 +0,0 @@
# OpenSK Bootloader
This bootloader supports upgradability for OpenSK. Its functionality is to
- check images on A/B partitions,
- boot the most recent valid partition.
## How to use
The bootloader is built and deployed by OpenSK's `deploy.py`. If your board
defines a metadata address, it is detected as an upgradable board and this
bootloader is flashed to memory address 0.
## How to debug
The bootloader prints debug message over RTT when compiled in debug mode. Using
`nrfjprog` for flashing and inspecting memory is recommended for debugging.
```shell
RUSTFLAGS="-C link-arg=-Wl,-Tlink.x -C link-arg=-nostartfiles" \
cargo build --target thumbv7em-none-eabi
llvm-objcopy -O ihex target/thumbv7em-none-eabi/debug/bootloader \
target/thumbv7em-none-eabi/debug/bootloader.hex
nrfjprog --program target/thumbv7em-none-eabi/debug/bootloader.hex \
--sectorerase -f nrf52 --reset
```
To read the debug messages, open two terminals for:
```shell
JLinkRTTLogger -device NRF52840_XXAA -if swd -speed 1000 -RTTchannel 0
JLinkRTTClient
```
The first command also logs the output to a file. The second shows all output in
real time.

View File

@@ -1,17 +0,0 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
fn main() {
println!("cargo:rerun-if-changed=memory.x");
}

View File

@@ -1,21 +0,0 @@
/* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 16K
RAM (rwx) : ORIGIN = 0x20020000, LENGTH = 128K
}

View File

@@ -1,4 +0,0 @@
[toolchain]
channel = "nightly-2021-03-25"
components = ["clippy", "rustfmt"]
targets = ["thumbv7em-none-eabi"]

View File

@@ -1,118 +0,0 @@
// Copyright 2020-2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use tock_registers::register_bitfields;
register_bitfields! [u32,
// Generic or shared bitfields
pub Task [
ENABLE OFFSET(0) NUMBITS(1)
],
pub Byte [
VALUE OFFSET(0) NUMBITS(8)
],
pub Busy [
/// Asserted when AES_BUSY or DES_BUSY or HASH_BUSY are asserted or when the DIN FIFO is not empty
BUSY OFFSET(0) NUMBITS(1) [
Ready = 0,
Busy = 1
]
],
// CC_CTL register bitfields
pub CryptoMode [
/// Determines the active cryptographic engine
MODE OFFSET(0) NUMBITS(5) [
Bypass = 0,
Aes = 1,
AesToHash = 2,
AesAndHash = 3,
Des = 4,
DesToHash = 5,
DesAndHash = 6,
Hash = 7,
AesMacAndBypass = 9,
AesToHashAndDout = 10
]
],
// HOST_RGF register bitfields
pub Interrupts [
/// This interrupt is asserted when all data was delivered to DIN buffer from SRAM
SRAM_TO_DIN OFFSET(4) NUMBITS(1),
/// This interrupt is asserted when all data was delivered to SRAM buffer from DOUT
DOUT_TO_SRAM OFFSET(5) NUMBITS(1),
/// This interrupt is asserted when all data was delivered to DIN buffer from memory
MEM_TO_DIN OFFSET(6) NUMBITS(1),
/// This interrupt is asserted when all data was delivered to memory buffer from DOUT
DOUT_TO_MEM OFFSET(7) NUMBITS(1),
AXI_ERROR OFFSET(8) NUMBITS(1),
/// The PKA end of operation interrupt status
PKA_EXP OFFSET(9) NUMBITS(1),
/// The RNG interrupt status
RNG OFFSET(10) NUMBITS(1),
/// The GPR interrupt status
SYM_DMA_COMPLETED OFFSET(11) NUMBITS(1)
],
pub RgfEndianness [
/// DOUT write endianness
DOUT_WR_BG OFFSET(3) NUMBITS(1) [
LittleEndian = 0,
BigEndian = 1
],
/// DIN write endianness
DIN_RD_BG OFFSET(7) NUMBITS(1) [
LittleEndian = 0,
BigEndian = 1
],
/// DOUT write word endianness
DOUT_WR_WBG OFFSET(11) NUMBITS(1) [
LittleEndian = 0,
BigEndian = 1
],
/// DIN write word endianness
DIN_RD_WBG OFFSET(15) NUMBITS(1) [
LittleEndian = 0,
BigEndian = 1
]
],
// DIN and DOUT register bitfields
pub LliWord1 [
/// Total number of bytes to read using DMA in this entry
BYTES_NUM OFFSET(0) NUMBITS(30),
/// Indicates the first LLI entry
FIRST OFFSET(30) NUMBITS(1),
/// Indicates the last LLI entry
LAST OFFSET(31) NUMBITS(1)
],
pub HashControl [
// bit 2 is reserved but to simplify the logic we include it in the bitfield.
MODE OFFSET(0) NUMBITS(4) [
MD5 = 0,
SHA1 = 1,
SHA256 = 2,
SHA224 = 10
]
],
pub PaddingConfig [
/// Enable Padding generation. must be reset upon completion of padding.
DO_PAD OFFSET(2) NUMBITS(1)
]
];

View File

@@ -1,283 +0,0 @@
// Copyright 2019-2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! CryptoCell 310
//!
//! Author
//! -------------------
//!
//! * Author: Jean-Michel Picod <jmichel@google.com>
//! * Date: October 1 2019
use super::bitfields;
use super::registers::{CryptoCellRegisters, NordicCC310Registers};
use super::static_ref::StaticRef;
use core::cell::Cell;
#[cfg(debug_assertions)]
use rtt_target::rprintln;
const SHA256_INIT_VALUE: [u32; 8] = [
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
];
#[derive(Copy, Clone)]
enum DigestAlgorithm {
Sha256 = 2,
}
#[derive(Copy, Clone)]
enum OperationMode {
Idle,
Hash,
}
pub struct CryptoCell310 {
registers: StaticRef<CryptoCellRegisters>,
power: StaticRef<NordicCC310Registers>,
current_op: Cell<OperationMode>,
hash_ctx: Cell<[u32; 8]>,
hash_total_size: Cell<u64>,
}
const CC310_BASE: StaticRef<CryptoCellRegisters> =
unsafe { StaticRef::new(0x5002B000 as *const CryptoCellRegisters) };
const CC310_POWER: StaticRef<NordicCC310Registers> =
unsafe { StaticRef::new(0x5002A500 as *const NordicCC310Registers) };
// Identification "signature" for CryptoCell. According to the documentation, the value
// held by this register is a fixed value, used by Host driver to verify CryptoCell presence
// at this address.
// This value was read from a CryptoCell-310 on a nRF52840-dongle kit.
const CC310_SIGNATURE: u32 = 0x20E00000;
impl CryptoCell310 {
/// Creates a new instance of cryptocell state.
pub const fn new() -> Self {
CryptoCell310 {
registers: CC310_BASE,
power: CC310_POWER,
current_op: Cell::new(OperationMode::Idle),
hash_ctx: Cell::new(SHA256_INIT_VALUE),
hash_total_size: Cell::new(0),
}
}
fn enable(&self) {
self.power.enable.write(bitfields::Task::ENABLE::SET);
for _i in 1..10 {
let read_signature = self.registers.host_rgf.signature.get();
if read_signature != CC310_SIGNATURE {
#[cfg(debug_assertions)]
rprintln!(
"[loop {}] Invalid CC310 signature. Expected {}, got {}\n",
_i,
CC310_SIGNATURE,
read_signature
);
} else {
break;
}
}
if self.registers.host_rgf.signature.get() != CC310_SIGNATURE {
panic!("Failed to initialize CC310");
}
// Make sure everything is set to little endian
self.registers.host_rgf.endian.write(
bitfields::RgfEndianness::DOUT_WR_BG::LittleEndian
+ bitfields::RgfEndianness::DIN_RD_BG::LittleEndian
+ bitfields::RgfEndianness::DOUT_WR_WBG::LittleEndian
+ bitfields::RgfEndianness::DIN_RD_WBG::LittleEndian,
);
// Always start the clock for DMA engine. It's too hard to keep
// track of which submodule needs DMA otherwise.
self.registers
.misc
.dma_clk_enable
.write(bitfields::Task::ENABLE::SET);
self.registers.host_rgf.interrupt_mask.write(
bitfields::Interrupts::SRAM_TO_DIN::CLEAR
+ bitfields::Interrupts::DOUT_TO_SRAM::CLEAR
+ bitfields::Interrupts::MEM_TO_DIN::CLEAR
+ bitfields::Interrupts::DOUT_TO_MEM::CLEAR
+ bitfields::Interrupts::AXI_ERROR::SET
+ bitfields::Interrupts::PKA_EXP::SET
+ bitfields::Interrupts::RNG::SET
+ bitfields::Interrupts::SYM_DMA_COMPLETED::CLEAR,
);
}
fn disable(&self) {
self.registers.host_rgf.interrupt_mask.set(0);
self.power.enable.write(bitfields::Task::ENABLE::CLEAR);
self.registers
.misc
.dma_clk_enable
.write(bitfields::Task::ENABLE::CLEAR);
}
fn clear_data(&self) {
let mut ctx = self.hash_ctx.get();
ctx.iter_mut().for_each(|b| *b = 0);
self.hash_ctx.set(ctx);
self.hash_total_size.set(0);
}
/// Adds data to the current hash computation.
///
/// You have to know in advance if is this is going to be the last block, and indicate that
/// correctly. Sizes of chunks before the last need to be multiples of 64.
pub fn update(&self, data: &[u8], is_last_block: bool) {
// Start CryptoCell
self.enable();
while self.registers.ctrl.hash_busy.is_set(bitfields::Busy::BUSY) {}
while self
.registers
.ctrl
.crypto_busy
.is_set(bitfields::Busy::BUSY)
{}
while self
.registers
.din
.mem_dma_busy
.is_set(bitfields::Busy::BUSY)
{}
// Start HASH module and configure it
self.current_op.set(OperationMode::Hash);
self.registers
.misc
.hash_clk_enable
.write(bitfields::Task::ENABLE::SET);
self.registers
.ctrl
.crypto_ctl
.write(bitfields::CryptoMode::MODE::Hash);
self.registers
.hash
.padding
.write(bitfields::Task::ENABLE::SET);
let size = self.hash_total_size.get();
self.registers.hash.hash_len_lsb.set(size as u32);
self.registers
.hash
.hash_len_msb
.set(size.wrapping_shr(32) as u32);
self.registers
.hash
.control
.set(DigestAlgorithm::Sha256 as u32);
// Digest must be set backwards because writing to HASH[0]
// starts computation
let mut digest = self.hash_ctx.get();
for i in (0..digest.len()).rev() {
self.registers.hash.hash[i].set(digest[i]);
}
while self.registers.ctrl.hash_busy.is_set(bitfields::Busy::BUSY) {}
// Process data
if !data.is_empty() {
if is_last_block {
self.registers
.hash
.auto_hw_padding
.write(bitfields::Task::ENABLE::SET);
}
self.registers.din.src_lli_word0.set(data.as_ptr() as u32);
self.registers
.din
.src_lli_word1
.write(bitfields::LliWord1::BYTES_NUM.val(data.len() as u32));
while !self
.registers
.host_rgf
.interrupts
.is_set(bitfields::Interrupts::MEM_TO_DIN)
{}
self.registers
.host_rgf
.interrupt_clear
.write(bitfields::Interrupts::MEM_TO_DIN::SET);
} else {
// use DO_PAD to complete padding of previous operation
self.registers
.hash
.pad_config
.write(bitfields::PaddingConfig::DO_PAD::SET);
}
while self
.registers
.ctrl
.crypto_busy
.is_set(bitfields::Busy::BUSY)
{}
while self
.registers
.din
.mem_dma_busy
.is_set(bitfields::Busy::BUSY)
{}
// Update context and total size
for i in (0..digest.len()).rev() {
digest[i] = self.registers.hash.hash[i].get();
}
self.hash_ctx.set(digest);
let new_size: u64 = ((self.registers.hash.hash_len_msb.get() as u64) << 32)
+ (self.registers.hash.hash_len_lsb.get() as u64);
self.hash_total_size.set(new_size);
// Disable HASH module
self.registers
.hash
.padding
.write(bitfields::Task::ENABLE::SET);
self.registers
.hash
.auto_hw_padding
.write(bitfields::Task::ENABLE::CLEAR);
self.registers
.hash
.pad_config
.write(bitfields::PaddingConfig::DO_PAD::CLEAR);
while self
.registers
.ctrl
.crypto_busy
.is_set(bitfields::Busy::BUSY)
{}
self.registers
.misc
.hash_clk_enable
.write(bitfields::Task::ENABLE::CLEAR);
self.disable();
}
/// Clears the data for potential reuse, and returns the result.
pub fn finalize_and_clear(&self) -> [u8; 32] {
use byteorder::{BigEndian, ByteOrder};
let words = self.hash_ctx.get();
let mut bytes = [0u8; 32];
for (i, word) in words.iter().enumerate() {
BigEndian::write_u32(&mut bytes[4 * i..4 * i + 4], *word);
}
self.clear_data();
bytes
}
}

View File

@@ -1,176 +0,0 @@
// Copyright 2021-2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_main]
#![no_std]
mod bitfields;
mod crypto_cell;
mod registers;
mod static_ref;
extern crate cortex_m;
extern crate cortex_m_rt as rt;
use byteorder::{ByteOrder, LittleEndian};
use core::convert::TryInto;
use core::ptr;
use cortex_m::asm;
use panic_abort as _;
use rt::entry;
#[cfg(debug_assertions)]
use rtt_target::{rprintln, rtt_init_print};
/// Size of a flash page in bytes.
const PAGE_SIZE: usize = 0x1000;
/// A flash page.
type Page = [u8; PAGE_SIZE];
/// Reads a page of memory.
unsafe fn read_page(address: usize) -> Page {
debug_assert!(address % PAGE_SIZE == 0);
let address_pointer = address as *const Page;
ptr::read(address_pointer)
}
/// Parsed metadata for a firmware partition.
struct Metadata {
checksum: [u8; 32],
timestamp: u32,
address: u32,
}
impl Metadata {
pub const DATA_LEN: usize = 40;
}
/// Reads the metadata from a flash page.
impl From<Page> for Metadata {
fn from(page: Page) -> Self {
Metadata {
checksum: page[0..32].try_into().unwrap(),
timestamp: LittleEndian::read_u32(&page[32..36]),
address: LittleEndian::read_u32(&page[36..Metadata::DATA_LEN]),
}
}
}
/// Location of a firmware partition's data.
struct BootPartition {
firmware_address: usize,
metadata_address: usize,
}
impl BootPartition {
const FIRMWARE_LENGTH: usize = 0x00040000;
/// Reads the metadata, returns the timestamp if all checks pass.
pub fn read_timestamp(&self) -> Result<u32, ()> {
let metadata_page = unsafe { read_page(self.metadata_address) };
let hash_value = self.compute_upgrade_hash(&metadata_page);
let metadata = Metadata::from(metadata_page);
if self.firmware_address != metadata.address as usize {
#[cfg(debug_assertions)]
rprintln!(
"Firmware address mismatch: expected 0x{:08X}, metadata 0x{:08X}",
self.firmware_address,
metadata.address as usize
);
return Err(());
}
if hash_value != metadata.checksum {
#[cfg(debug_assertions)]
rprintln!("Hash mismatch");
return Err(());
}
Ok(metadata.timestamp)
}
/// Computes the SHA256 of metadata information and partition data.
///
/// Assumes that firmware address and length are divisible by the page size.
/// This is the hardware implementation on the cryptocell.
#[allow(clippy::assertions_on_constants)]
fn compute_upgrade_hash(&self, metadata_page: &[u8]) -> [u8; 32] {
debug_assert!(self.firmware_address % PAGE_SIZE == 0);
debug_assert!(BootPartition::FIRMWARE_LENGTH % PAGE_SIZE == 0);
let cc310 = crypto_cell::CryptoCell310::new();
for page_offset in (0..BootPartition::FIRMWARE_LENGTH).step_by(PAGE_SIZE) {
let page = unsafe { read_page(self.firmware_address + page_offset) };
cc310.update(&page, false);
}
cc310.update(&metadata_page[32..Metadata::DATA_LEN], true);
cc310.finalize_and_clear()
}
/// Jump to the firmware.
pub fn boot(&self) -> ! {
let address = self.firmware_address;
// Clear any pending Cryptocell interrupt in NVIC
let peripherals = cortex_m::Peripherals::take().unwrap();
unsafe {
// We could only clear cryptocell interrupts, but let's clean up before booting.
// Example code to clear more specifically:
// const CC310_IRQ: u16 = 42;
// peripherals.NVIC.icpr[usize::from(CC310_IRQ / 32)].write(1 << (CC310_IRQ % 32));
peripherals.NVIC.icer[0].write(0xffff_ffff);
peripherals.NVIC.icpr[0].write(0xffff_ffff);
peripherals.NVIC.icer[1].write(0xffff_ffff);
peripherals.NVIC.icpr[1].write(0xffff_ffff);
}
#[cfg(debug_assertions)]
rprintln!("Boot jump to {:08X}", address);
let address_pointer = address as *const u32;
// https://docs.rs/cortex-m/0.7.2/cortex_m/asm/fn.bootload.html
unsafe { asm::bootload(address_pointer) };
}
}
#[entry]
fn main() -> ! {
#[cfg(debug_assertions)]
rtt_init_print!();
#[cfg(debug_assertions)]
rprintln!("Starting bootloader");
let partition_a = BootPartition {
firmware_address: 0x20000,
metadata_address: 0x4000,
};
let partition_b = BootPartition {
firmware_address: 0x60000,
metadata_address: 0x5000,
};
#[cfg(debug_assertions)]
rprintln!("Reading partition A");
let timestamp_a = partition_a.read_timestamp();
#[cfg(debug_assertions)]
rprintln!("Reading partition B");
let timestamp_b = partition_b.read_timestamp();
match (timestamp_a, timestamp_b) {
(Ok(t1), Ok(t2)) => {
if t1 >= t2 {
partition_a.boot()
} else {
partition_b.boot()
}
}
(Ok(_), Err(_)) => partition_a.boot(),
(Err(_), Ok(_)) => partition_b.boot(),
(Err(_), Err(_)) => panic!(),
}
}

View File

@@ -1,137 +0,0 @@
// Copyright 2020-2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::bitfields::{
Busy, CryptoMode, HashControl, Interrupts, LliWord1, PaddingConfig, RgfEndianness, Task,
};
use tock_registers::register_structs;
use tock_registers::registers::{ReadOnly, ReadWrite, WriteOnly};
register_structs! {
pub CryptoCellControlRegisters {
/// Defines the cryptographic flow
(0x0000 => pub crypto_ctl: WriteOnly<u32, CryptoMode::Register>),
(0x0004 => _reserved0),
/// This register is set whent the cryptographic core is busy
(0x0010 => pub crypto_busy: ReadOnly<u32, Busy::Register>),
(0x0014 => _reserved1),
/// This register is set when the Hash engine is busy
(0x001C => pub hash_busy: ReadOnly<u32, Busy::Register>),
(0x0020 => @END),
}
}
register_structs! {
pub CryptoCellDinRegisters {
(0x0000 => _reserved0),
/// Indicates whether memoty (AXI) source DMA (DIN) is busy
(0x0020 => pub mem_dma_busy: ReadOnly<u32, Busy::Register>),
(0x0024 => _reserved1),
/// This register is used in direct LLI mode - holds the location of the data source
/// in the memory (AXI)
(0x0028 => pub src_lli_word0: WriteOnly<u32>),
/// This register is used in direct LLI mode - holds the number of bytes to be read
/// from the memory (AXI).
/// Writing to this register triggers the DMA.
(0x002C => pub src_lli_word1: WriteOnly<u32, LliWord1::Register>),
(0x0030 => @END),
}
}
register_structs! {
pub CryptoCellHashRegisters {
/// Write initial hash value or read final hash value
(0x0000 => pub hash: [ReadWrite<u32>; 9]),
(0x0024 => _reserved0),
/// HW padding automatically activated by engine.
/// For the special case of ZERO bytes data vector this register should not be used! instead use HASH_PAD_CFG
(0x0044 => pub auto_hw_padding: WriteOnly<u32, Task::Register>),
(0x0048 => _reserved1),
/// Selects which HASH mode to run
(0x0180 => pub control: ReadWrite<u32, HashControl::Register>),
/// This register enables the hash hw padding.
(0x0184 => pub padding: ReadWrite<u32, Task::Register>),
/// HASH_PAD_CFG Register.
(0x0188 => pub pad_config: ReadWrite<u32, PaddingConfig::Register>),
/// This register hold the length of current hash operation
(0x018C => pub hash_len_lsb: ReadWrite<u32>),
/// This register hold the length of current hash operation
(0x0190 => pub hash_len_msb: ReadWrite<u32>),
(0x0194 => @END),
}
}
register_structs! {
pub CryptoCellHostRgfRegisters {
/// The Interrupt Request register.
/// Each bit of this register holds the interrupt status of a single interrupt source.
(0x0000 => pub interrupts: ReadOnly<u32, Interrupts::Register>),
/// The Interrupt Mask register. Each bit of this register holds the mask of a single
/// interrupt source.
(0x0004 => pub interrupt_mask: ReadWrite<u32, Interrupts::Register>),
/// Interrupt Clear Register
(0x0008 => pub interrupt_clear: WriteOnly<u32, Interrupts::Register>),
/// This register defines the endianness of the Host-accessible registers.
(0x000C => pub endian: ReadWrite<u32, RgfEndianness::Register>),
(0x0010 => _reserved0),
/// This register holds the CryptoCell product signature.
(0x0024 => pub signature: ReadOnly<u32>),
(0x0028 => @END),
}
}
register_structs! {
pub CryptoCellMiscRegisters {
(0x0000 => _reserved0),
/// The HASH clock enable register
(0x0018 => pub hash_clk_enable: ReadWrite<u32, Task::Register>),
/// The PKA clock enable register
(0x001C => _reserved1),
/// The DMA clock enable register
(0x0020 => pub dma_clk_enable: ReadWrite<u32, Task::Register>),
/// the CryptoCell clocks' status register
(0x0024 => @END),
}
}
register_structs! {
pub NordicCC310Registers {
(0x0000 => pub enable: ReadWrite<u32, Task::Register>),
(0x0004 => @END),
},
pub CryptoCellRegisters {
(0x0000 => _reserved0),
/// HASH registers
/// - Base address: 0x0640
(0x0640 => pub hash: CryptoCellHashRegisters),
(0x07D4 => _reserved1),
/// Misc registers
/// - Base address: 0x0800
(0x0800 => pub misc: CryptoCellMiscRegisters),
(0x0824 => _reserved2),
/// CryptoCell control registers
/// - Base address: 0x0900
(0x0900 => pub ctrl: CryptoCellControlRegisters),
(0x0920 => _reserved3),
/// HOST_RGF registers
/// - Base address: 0x0A00
(0x0A00 => pub host_rgf: CryptoCellHostRgfRegisters),
(0x0A28 => _reserved4),
/// DIN registers
/// - Base address: 0x0C00
(0x0C00 => pub din: CryptoCellDinRegisters),
(0x0C30 => @END),
}
}

View File

@@ -1,46 +0,0 @@
//! Wrapper type for safe pointers to static memory.
//!
//! Imported from:
//! https://github.com/tock/tock/blob/master/kernel/src/utilities/static_ref.rs
use core::ops::Deref;
/// A pointer to statically allocated mutable data such as memory mapped I/O
/// registers.
///
/// This is a simple wrapper around a raw pointer that encapsulates an unsafe
/// dereference in a safe manner. It serve the role of creating a `&'static T`
/// given a raw address and acts similarly to `extern` definitions, except
/// `StaticRef` is subject to module and crate boundaries, while `extern`
/// definitions can be imported anywhere.
#[derive(Debug)]
pub struct StaticRef<T> {
ptr: *const T,
}
impl<T> StaticRef<T> {
/// Create a new `StaticRef` from a raw pointer
///
/// ## Safety
///
/// Callers must pass in a reference to statically allocated memory which
/// does not overlap with other values.
pub const unsafe fn new(ptr: *const T) -> StaticRef<T> {
StaticRef { ptr }
}
}
impl<T> Clone for StaticRef<T> {
fn clone(&self) -> Self {
StaticRef { ptr: self.ptr }
}
}
impl<T> Copy for StaticRef<T> {}
impl<T> Deref for StaticRef<T> {
type Target = T;
fn deref(&self) -> &'static T {
unsafe { &*self.ptr }
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2019-2021 Google LLC
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,24 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
extern crate alloc;
use openssl::{bn, ec, nid};
use sk_cbor::cbor_map;
use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::io::Read;
use std::io::Write;
use std::path::Path;
use std::{env, fs};
use uuid::Uuid;
fn main() {
const UPGRADE_FILE: &str = "crypto_data/opensk_upgrade_pub.pem";
println!("cargo:rerun-if-changed=crypto_data/aaguid.txt");
println!("cargo:rerun-if-changed={}", UPGRADE_FILE);
println!("cargo:rerun-if-changed=layout.ld");
println!("cargo:rerun-if-changed=nrf52840_layout.ld");
println!("cargo:rerun-if-changed=nrf52840_layout_a.ld");
println!("cargo:rerun-if-changed=nrf52840_layout_b.ld");
let out_dir = env::var_os("OUT_DIR").unwrap();
let aaguid_bin_path = Path::new(&out_dir).join("opensk_aaguid.bin");
@@ -41,36 +32,4 @@ fn main() {
content.truncate(36);
let aaguid = Uuid::parse_str(&content).unwrap();
aaguid_bin_file.write_all(aaguid.as_bytes()).unwrap();
// COSE encoding the public key, then write it out.
let pem_bytes = fs::read(UPGRADE_FILE).unwrap();
let ec_key = ec::EcKey::public_key_from_pem(&pem_bytes).ok().unwrap();
let group = ec::EcGroup::from_curve_name(nid::Nid::X9_62_PRIME256V1).unwrap();
let conversion_form = ec::PointConversionForm::UNCOMPRESSED;
let mut ctx = bn::BigNumContext::new().unwrap();
let raw_bytes = ec_key
.public_key()
.to_bytes(&group, conversion_form, &mut ctx)
.unwrap();
const POINT_LEN: usize = 32;
assert_eq!(raw_bytes.len(), 1 + 2 * POINT_LEN);
assert_eq!(raw_bytes[0], 0x04);
let x_bytes = &raw_bytes[1..][..POINT_LEN];
let y_bytes = &raw_bytes[1 + POINT_LEN..][..POINT_LEN];
const EC2_KEY_TYPE: i64 = 2;
const P_256_CURVE: i64 = 1;
const ES256_ALGORITHM: i64 = -7;
let pub_key_cbor = sk_cbor::cbor_map! {
1 => EC2_KEY_TYPE,
3 => ES256_ALGORITHM,
-1 => P_256_CURVE,
-2 => x_bytes,
-3 => y_bytes,
};
let mut cbor_bytes = vec![];
sk_cbor::writer::write(pub_key_cbor, &mut cbor_bytes).unwrap();
let upgrade_pubkey_path = Path::new(&out_dir).join("opensk_upgrade_pubkey_cbor.bin");
let mut upgrade_pub_bin_file = File::create(&upgrade_pubkey_path).unwrap();
upgrade_pub_bin_file.write_all(&cbor_bytes).unwrap();
}

636
deploy.py

File diff suppressed because it is too large Load Diff

View File

@@ -1,119 +0,0 @@
# <img alt="OpenSK logo" src="../img/OpenSK.svg" width="200px">
## Nordic nRF52840 Dongle
![Nordic dongle](../img/dongle_front.jpg)
### 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.
![OpenSK Enclosure](../img/enclosure.jpg)
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:
![Nordic dongle pads](../img/dongle_pads.jpg)
1. You can use the retainer clip if you have one to avoid maintaining pressure
between the board and the cable:
![Nordic dongle retainer clip](../img/dongle_clip.jpg)
#### JLink
Run our script for compiling/flashing Tock OS on your device:
```shell
$ ./deploy.py --board=nrf52840_dongle --programmer=jlink
```
#### OpenOCD
1. Create your openocd config, named `nordic_nrf52840_dongle.cfg` in the
appropriate location:
```shell
mkdir -p ${HOME}/.openocd/board
touch ${HOME}/.openocd/board/nordic_nrf52840_dongle.cfg
```
Paste the following st-link example and edit the specific setup to your needs:
```
# Specific setup
source [find interface/stlink-dap.cfg]
transport select dapdirect_swd
# The rest should be kept the same
set CHIPNAME nrf52840
source [find target/nrf52.cfg]
```
1. Test your config:
```shell
openocd -f board/nordic_nrf52840_dongle.cfg
```
1. Run the deploy script with the appropriate options, i.e.:
```shell
./deploy.py --board=nrf52840_dongle --opensk --programmer=openocd
```
Finally, 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 |

View File

@@ -1,23 +0,0 @@
# <img alt="OpenSK logo" src="../img/OpenSK.svg" width="200px">
## 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.

View File

@@ -1,47 +0,0 @@
# <img alt="OpenSK logo" src="../img/OpenSK.svg" width="200px">
## 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 |

View File

@@ -1,80 +0,0 @@
# <img alt="OpenSK logo" src="../img/OpenSK.svg" width="200px">
## Nordic nRF52840-DK board
![Nordic development kit](../img/devkit_annotated.jpg)
### 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 --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
### Upgradability
There are variants of the board that introduce A/B partitions for upgrading the
firmware. You can bootstrap an upgradable board using one of the two commands:
```shell
./deploy.py --board=nrf52840dk_opensk_a --opensk
./deploy.py --board=nrf52840dk_opensk_b --opensk
```
Afterwards, you can upgrade the other partition with
```shell
./tools/perform_upgrade.sh nrf52840dk_opensk_b
./tools/perform_upgrade.sh nrf52840dk_opensk_a
```
respectively. You can only upgrade the partition that is not currently running,
so always alternate your calls to `perform_upgrade.sh`. Otherwise, this script
works like `deploy.py`. You can call it even after you locked down your device,
to deploy changes to your development board.
If you deploy with `--vendor-hid`, also add this flag to `perform_upgrade.sh`,
for example:
```shell
./deploy.py --board=nrf52840dk_opensk_a --opensk --vendor-hid
./tools/perform_upgrade.sh nrf52840dk_opensk_b --vendor-hid
```

View File

@@ -1,95 +0,0 @@
# <img alt="OpenSK logo" src="img/OpenSK.svg" width="200px">
## 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
`opensk_upgrade.key` | Private key for signing upgrades through CTAP
`opensk_upgrade_pub.pem` | Public key added to the firmware for verifying upgrades
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 `src/main.rs`.
1. If you have colored LEDs, like different blinking patterns and want to play
around with the code in `src/main.rs` more, take a look at e.g. `wink_leds`.
1. You find more options and documentation in `src/ctap/customization.rs`,
including:
* The default level for the credProtect extension.
* The default minimum PIN length, and what relying parties can set it.
* Whether you want to enforce alwaysUv.
* Settings for enterprise attestation.
* The maximum PIN retries.
* Whether you want to use batch attestation.
* Whether you want to use signature counters.
* Various constants to adapt to different hardware.
### Testing and Fuzzing
You might want to test your changes before deploying them. To run unit tests,
make sure that at least the `std` feature is included, e.g.:
```shell
cargo test --features=std,with_ctap1
```
Alternatively, you can simply call our test script to also test all libraries,
run clippy, check formatting and more:
```shell
./run_desktop_tests.sh
```
OpenSK is fuzzed with the [OSS-Fuzz](https://github.com/google/oss-fuzz)
project. You can also run fuzzing locally. First install:
```shell
cargo +stable install cargo-fuzz --version 0.10.2
```
Then choose a fuzz target from `fuzz/fuzz_targets/`, e.g.:
```shell
cargo fuzz run fuzz_target_process_ctap1
```

View File

@@ -1,137 +0,0 @@
# <img alt="OpenSK logo" src="img/OpenSK.svg" width="200px">
## 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 <class IORegistryEntry, id 0x100000100, retain 21>
...
+-o AppleUSBXHCI Root Hub Simulation@14000000 <class AppleUSBRootHubDevice, id 0x100000a00, registered, matched, active, busy 0 (0 ms), retain 9>
+-o OpenSK@14400000 <class AppleUSBDevice, id 0x100003c04, registered, matched, active, busy 0 (0 ms), retain 13>
```
### 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 --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
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 KiB

View File

@@ -1,172 +1,340 @@
# <img alt="OpenSK logo" src="img/OpenSK.svg" width="200px">
<img alt="OpenSK logo" src="img/OpenSK.svg" width="200px">
## Installation guide
# Installation guide
This document lists required steps to start build your own OpenSK.
This document describes in details how to turn a Nordic nRF52840 board into a
working FIDO2 security key.
### Programmers
## Pre-requisite
OpenSK supports different ways to flash your board:
### 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/).
In the case of the Nordic USB dongle, you may also need the following extra
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.
Additionnaly, OpenSK supports other ways to flash your board:
* [OpenOCD](http://openocd.org/).
* [Segger J-Link](https://www.segger.com/products/debug-probes/j-link/)
(default method).
* [OpenOCD](http://openocd.org/).
* [pyOCD](https://pypi.org/project/pyocd/).
* [nrfutil](https://pypi.org/project/nrfutil/) for the USB dongle boards that
support it, which allows you to directly flash a working board over USB
supports it, which allows you to directly flash a working board over USB
without additional hardware.
### Software requirements
This guide **does not** cover how to setup the JTAG probe and their related
tools on your system.
### Software
In order to compile and flash a working OpenSK firmware, you will need the
following:
* rustup (can be installed with [Rustup](https://rustup.rs/))
* python3 and pip (can be installed with the `python3-pip` package on Debian)
* the OpenSSL command line tool (can be installed and configured with the
`libssl-dev` and `pkg-config` packages on Debian)
* `nrfutil` (can be installed using `pip3 install nrfutil`) if you want to flash
a device with DFU
* `uuid-runtime` if you are missing the `uuidgen` command.
* `llvm` if you want to use the upgradability feature.
The proprietary software to use the default programmer can be found on the
[Segger website](https://www.segger.com/downloads/jlink). Please follow their
instructions to appropriate binaries for your system.
* the OpenSSL command line tool (can be installed with the `libssl-dev`
package on Debian)
The scripts provided in this project have been tested under Linux and OS X. We
haven't tested them on Windows and other platforms.
### Compiling the firmware
## Compiling the firmware
If this is your first time installing OpenSK, please skip directly to
[Initial setup](#Initial-setup). Else, see
[Updating your setup](#Updating-your-setup) below.
### Initial setup
#### Updating your setup
Depending on the difference to your last state, you may need some of the
following steps:
* If you are not just testing minor changes, reset and redo the setup. This
will delete all uncommited changes.
If you just cloned this repository, you need to run the following script
(_output may differ_):
```shell
./reset.sh
./setup.sh
$ ./setup.sh
[-] Applying patch "01-persistent-storage.patch"... DONE.
[-] Applying patch "02-usb.patch"... DONE.
[-] Applying patch "03-app-memory.patch"... DONE.
[-] Applying patch "04-rtt.patch"... DONE.
[-] Applying patch "01-linked_list_allocator.patch"... DONE.
[-] Applying patch "02-panic_console.patch"... DONE.
[-] Applying patch "03-timer.patch"... DONE.
[-] Applying patch "04-public_syscalls.patch"... DONE.
[-] Applying patch "05-bigger_heap.patch"... DONE.
[-] Applying patch "06-no_spin_allocator.patch"... DONE.
Signature ok
subject=CN = Google OpenSK CA
Getting Private key
Signature ok
subject=CN = Google OpenSK Hacker Edition
Getting CA Private Key
info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu'
nightly-2020-02-03-x86_64-unknown-linux-gnu unchanged - rustc 1.42.0-nightly (f43c34a13 2020-02-02)
Requirement already up-to-date: tockloader in /usr/lib/python3/dist-packages/tockloader-1.4.0.dev0-py3.7.egg (1.4.0.dev0)
Requirement already satisfied, skipping upgrade: argcomplete>=1.8.2 in /usr/lib/python3/dist-packages (from tockloader) (1.10.0)
Requirement already satisfied, skipping upgrade: colorama>=0.3.7 in /usr/lib/python3/dist-packages (from tockloader) (0.3.7)
Requirement already satisfied, skipping upgrade: crcmod>=1.7 in /usr/lib/python3/dist-packages (from tockloader) (1.7)
Requirement already satisfied, skipping upgrade: pyserial>=3.0.1 in /usr/lib/python3/dist-packages (from tockloader) (3.4)
Requirement already satisfied, skipping upgrade: pytoml>=0.1.11 in /usr/lib/python3/dist-packages (from tockloader) (0.1.21)
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
Updating crates.io index
Ignored package `elf2tab v0.4.0` is already installed, use --force to override
```
* Flash your board according to the
[flashing instructions below](#Flashing-a-firmware]. If you come from an
OpenSK version before the 2.0 certified one, your credential storage is not
backwards compatible and you have to reset it. :warning: You will lose
logins to all websites that you registered with OpenSK. To erase your
persistent storage, run the deploy script twice: Once with the application
parameter `--erase_storage`, and once with `--opensk` as usual.
The script performs the following steps:
This reset also clears the certificate. For a privacy discussion, see the
[certificate section in Customization](customization.md#Certificate-considerations).
If you want to reinstall it, you also need to rerun:
```shell
./tools/configure.py \
--certificate=crypto_data/opensk_cert.pem \
--private-key=crypto_data/opensk.key
```
#### Initial setup
To clone and setup the repository for the develop branch, run the following
commands:
```shell
git clone -b develop https://github.com/google/OpenSK.git
cd OpenSK
./setup.sh
```
The setup script performs the following steps:
1. Make sure that the git submodules are checked out.
1. Make sure that the git submodules are checked out
1. Apply our patches that haven't yet been merged upstream to both
[Tock](https://github.com/tock/tock) and
[libtock-rs](https://github.com/tock/libtock-rs).
[libtock-rs](https://github.com/tock/libtock-rs)
1. Generate crypto material, see [Customization](customization.md) for details.
1. Generate a self-signed certificate authority as well as a private key and a
corresponding certificate for your OpenSK key signed by this CA. You will be
able to replace them with your own certificate and private key.
1. Install the correct Rust toolchain for ARM devices.
1. Ensure that your Rust toolchain is using the same version that we tested
OpenSK with.
1. Install [tockloader](https://github.com/tock/tockloader).
Additionally on Linux, you need to install a `udev` rule file to allow non-root
users to interact with OpenSK devices. To install it, execute:
1. Ensure that the Rust toolchain can compile code for ARM devices.
### Replacing the certificates
All the generated certificates and private keys are stored in the directory
`crypto_data/`.
This is the expected content after running our `setup.sh` script:
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, simply
replace `opensk_cert.pem` and `opensk.key` files.
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`.
Our configuration script `tools/configure.py` is responsible for configuring
an OpenSK device with the correct certificate and private key.
### Flashing a firmware
#### Nordic nRF52840-DK board
![Nordic development kit](img/devkit_annotated.jpg)
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
(_output may differ_):
```shell
$ ./deploy.py --board=nrf52840dk --opensk
info: Updating rust toolchain to nightly-2020-02-03
info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu'
info: checking for self-updates
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
info: Rust toolchain up-to-date
info: Building Tock OS for board nrf52840dk
Compiling tock-registers v0.5.0 (./third_party/tock/libraries/tock-register-interface)
Compiling tock-cells v0.1.0 (./third_party/tock/libraries/tock-cells)
Compiling enum_primitive v0.1.0 (./third_party/tock/libraries/enum_primitive)
Compiling tock_rt0 v0.1.0 (./third_party/tock/libraries/tock-rt0)
Compiling nrf52840dk v0.1.0 (./third_party/tock/boards/nordic/nrf52840dk)
Compiling kernel v0.1.0 (./third_party/tock/kernel)
Compiling cortexm v0.1.0 (./third_party/tock/arch/cortex-m)
Compiling nrf5x v0.1.0 (./third_party/tock/chips/nrf5x)
Compiling capsules v0.1.0 (./third_party/tock/capsules)
Compiling cortexm4 v0.1.0 (./third_party/tock/arch/cortex-m4)
Compiling nrf52 v0.1.0 (./third_party/tock/chips/nrf52)
Compiling nrf52840 v0.1.0 (./third_party/tock/chips/nrf52840)
Compiling components v0.1.0 (./third_party/tock/boards/components)
Compiling nrf52dk_base v0.1.0 (./third_party/tock/boards/nordic/nrf52dk_base)
Finished release [optimized + debuginfo] target(s) in 13.15s
info: Converting Tock OS file into a binary
info: Building OpenSK application
Finished release [optimized] target(s) in 0.02s
info: Generating Tock TAB file for application/example ctap2
info: Erasing all installed applications
All apps have been erased.
info: Flashing file third_party/tock/boards/nordic/nrf52840dk/target/thumbv7em-none-eabi/release/nrf52840dk.bin.
info: Flashing padding application
info: Installing Tock application ctap2
info: You're all set!
```
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.
#### Nordic nRF52840 Dongle
##### Using external programmer (JLink, OpenOCD, etc.)
![Nordic dongle](img/dongle_front.jpg)
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:
![Nordic dongle pads](img/dongle_pads.jpg)
1. You can use the retainer clip if you have one to avoid maintaining pressure
between the board and the cable:
![Nordic dongle retainer clip](img/dongle_clip.jpg)
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
(_output may differ_):
```shell
$ ./deploy.py os --board=nrf52840_dongle --programmer=jlink
info: Updating rust toolchain to nightly-2020-02-03
info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu'
info: checking for self-updates
info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date
info: Rust toolchain up-to-date
info: Building Tock OS for board nrf52840_dongle
Compiling tock-cells v0.1.0 (./third_party/tock/libraries/tock-cells)
Compiling tock-registers v0.5.0 (./third_party/tock/libraries/tock-register-interface)
Compiling enum_primitive v0.1.0 (./third_party/tock/libraries/enum_primitive)
Compiling tock_rt0 v0.1.0 (./third_party/tock/libraries/tock-rt0)
Compiling nrf52840_dongle v0.1.0 (./third_party/tock/boards/nordic/nrf52840_dongle)
Compiling kernel v0.1.0 (./third_party/tock/kernel)
Compiling cortexm v0.1.0 (./third_party/tock/arch/cortex-m)
Compiling nrf5x v0.1.0 (./third_party/tock/chips/nrf5x)
Compiling capsules v0.1.0 (./third_party/tock/capsules)
Compiling cortexm4 v0.1.0 (./third_party/tock/arch/cortex-m4)
Compiling nrf52 v0.1.0 (./third_party/tock/chips/nrf52)
Compiling nrf52840 v0.1.0 (./third_party/tock/chips/nrf52840)
Compiling components v0.1.0 (./third_party/tock/boards/components)
Compiling nrf52dk_base v0.1.0 (./third_party/tock/boards/nordic/nrf52dk_base)
Finished release [optimized + debuginfo] target(s) in 11.72s
info: Converting Tock OS file into a binary
info: Building OpenSK application
Finished release [optimized] target(s) in 0.02s
info: Generating Tock TAB file for application/example ctap2
info: Erasing all installed applications
All apps have been erased.
info: Flashing file third_party/tock/boards/nordic/nrf52840_dongle/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin.
info: Flashing padding application
info: Installing Tock application ctap2
info: You're all set!
```
1. Remove the programming cable and the USB-A extension cable.
### Advanced installation
Although flashing using a Segger JLink probe is the officially supported way,
our tool, `deploy.py` also supports other methods:
* OpenOCD: `./deploy.py --board=nrf52840_dongle --opensk --programmer=openocd`
* pyOCD: `./deploy.py --board=nrf52840_dongle --opensk --programmer=pyocd`
* Nordic DFU: `./deploy.py --board=nrf52840_dongle --opensk
--programmer=nordicdfu`
* Custom: `./deploy.py --board=nrf52840_dongle --opensk --programmer=none`. In
this case, an IntelHex file will be created and how to program a board is
left to the user.
If your board is already flashed with Tock OS, you may skip installing it:
`./deploy.py --board=nrf52840dk --opensk --no-tockos`
For more options, we invite you to read the help of our `deploy.py` script by
running `./deploy.py --help`.
### Installing the udev rule (Linux only)
By default on Linux, a USB device will require root privilege in order interact
with it. As it is not recommended to run your web browser with such a high
privileged account, we made a `udev` rule file to allow regular users to
interact with OpenSK authenticators.
To install it, you need to execute the following commands:
```shell
sudo cp rules.d/55-opensk.rules /etc/udev/rules.d/
sudo udevadm control --reload
```
Then, you need and replug the device for the rule to trigger.
Then, you will need to unplug and replug the key for the rule to trigger.
Last, if you want to use U2F or attestation, configure the certificate. If your
client does not support FIDO2 yet, this step is mandatory for your OpenSK to
work. OpenSK is incompatible with some browsers without a certificate. Please
read the
[certificate section in Customization](customization.md#Certificate-considerations)
for understand privacy tradeoffs.
## Troubleshooting
To test whether the installation was successful, visit a
[demo website](https://webauthn.io/) and try to register and login.
### Linux
If you have issues with the demo website, the following commands should help you
understand whether OpenSK was installed properly.
When plugging in the USB key, the following line should appear in `lsusb`.
```shell
./tools/configure.py \
--certificate=crypto_data/opensk_cert.pem \
--private-key=crypto_data/opensk.key
$ lsusb
...
Bus XXX Device YYY: ID 1915:521f Nordic Semiconductor ASA OpenSK
```
### Flashing a firmware
You should also see lines similar to the following in `dmesg`.
From here on, please follow the instructions for your hardware:
```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
```
* [Nordic nRF52840-DK](boards/nrf52840dk.md)
* [Nordic nRF52840 Dongle](boards/nrf52840_dongle.md)
* [Makerdiary nRF52840-MDK USB dongle](boards/nrf52840_mdk.md)
* [Feitian OpenSK dongle](boards/nrf52840_feitian.md)
### Mac OS X
### Advanced installation
If you have issues with the demo website, the following commands should help you
understand whether OpenSK was installed properly.
We recommend that you flash your development board with JTAG and dongles with
DFU, as described in the [board documentation](#Flashing-a-firmware) linked
above. However, we support other programmers:
When plugging in the USB key, you should see a similar line by using the `ioreg`
tool:
* OpenOCD: `./deploy.py --board=nrf52840_dongle_opensk --opensk
--programmer=openocd`
* pyOCD: `./deploy.py --board=nrf52840_dongle_opensk --opensk
--programmer=pyocd`
* Custom: `./deploy.py --board=nrf52840_dongle_opensk --opensk
--programmer=none`. In this case, an IntelHex file will be created and how
to program a board is left to the user.
If your board is already flashed with Tock OS, you may skip installing it:
`./deploy.py --board=nrf52840dk_opensk --opensk --no-tockos`
For more options, we invite you to read the help of our `deploy.py` script by
running `./deploy.py --help`.
### Upgradability
We experiment with a new CTAP command to allow upgrading your device without
access to its debugging port. For that purpose, the flash storage is split into
4 parts:
* the bootloader to decide with partition to boot
* firmware partition A
* firmware partition B
* the persistent storage for credentials
The storage is backward compatible to non-upgradable boards. Deploying an
upgradable board automatically installs the bootloader. Please keep in mind that
you have to safely store your private signing key for upgrades if you want to
use this feature. For more information on the cryptographic material, see
[Customization](customization.md).
So far, upgradability is only supported for the development board. See the
instructions on the [board specific page](boards/nrf52840dk.md).
```shell
$ ioreg -p IOUSB
+-o Root <class IORegistryEntry, id 0x100000100, retain 21>
...
+-o AppleUSBXHCI Root Hub Simulation@14000000 <class AppleUSBRootHubDevice, id 0x100000a00, registered, matched, active, busy 0 (0 ms), retain 9>
+-o OpenSK@14400000 <class AppleUSBDevice, id 0x100003c04, registered, matched, active, busy 0 (0 ms), retain 13>
```

View File

@@ -18,8 +18,6 @@ extern crate lang_items;
use libtock_drivers::console::{Console, BUFFER_SIZE};
libtock_core::stack_size! {0x800}
fn main() {
// Write messages of length up to the console driver's buffer size.
let mut buf = [0; BUFFER_SIZE];

View File

@@ -20,14 +20,14 @@ extern crate lang_items;
use alloc::format;
use alloc::vec::Vec;
use core::fmt::Write;
use crypto::{aes256, cbc, ecdsa, sha256, Hash256};
use crypto::{
aes256, cbc, ecdsa, rng256, sha256, Decrypt16BytesBlock, Encrypt16BytesBlock, Hash256,
};
use libtock_drivers::console::Console;
use libtock_drivers::result::FlexUnwrap;
use libtock_drivers::timer;
use libtock_drivers::timer::{Timer, Timestamp};
use rng256::TockRng256;
libtock_core::stack_size! {0x800}
use libtock_drivers::timer::Timer;
use libtock_drivers::timer::Timestamp;
fn main() {
let mut console = Console::new();
@@ -36,7 +36,7 @@ fn main() {
let mut with_callback = timer::with_callback(|_, _| {});
let timer = with_callback.init().flex_unwrap();
let mut rng = TockRng256 {};
let mut rng = rng256::TockRng256 {};
writeln!(console, "****************************************").unwrap();
writeln!(
@@ -76,11 +76,11 @@ fn main() {
// CBC
let mut blocks = Vec::new();
for i in 0..8 {
blocks.resize(1 << (i + 4), 0);
blocks.resize(1 << i, [0; 16]);
bench(
&mut console,
&timer,
&format!("cbc::cbc_encrypt({} bytes)", blocks.len()),
&format!("cbc::cbc_encrypt({} bytes)", blocks.len() * 16),
|| {
cbc::cbc_encrypt(&ek, [0; 16], &mut blocks);
},
@@ -90,11 +90,11 @@ fn main() {
let mut blocks = Vec::new();
for i in 0..8 {
blocks.resize(1 << (i + 4), 0);
blocks.resize(1 << i, [0; 16]);
bench(
&mut console,
&timer,
&format!("cbc::cbc_decrypt({} bytes)", blocks.len()),
&format!("cbc::cbc_decrypt({} bytes)", blocks.len() * 16),
|| {
cbc::cbc_decrypt(&dk, [0; 16], &mut blocks);
},

View File

@@ -1,55 +0,0 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![no_std]
extern crate lang_items;
use core::fmt::Write;
use ctap2::env::tock::take_storage;
use libtock_drivers::console::Console;
use libtock_drivers::led;
use libtock_drivers::result::FlexUnwrap;
use persistent_store::{Storage, StorageIndex};
libtock_core::stack_size! {0x800}
fn is_page_erased(storage: &dyn Storage, page: usize) -> bool {
let index = StorageIndex { page, byte: 0 };
let length = storage.page_size();
storage
.read_slice(index, length)
.unwrap()
.iter()
.all(|&x| x == 0xff)
}
fn main() {
led::get(1).flex_unwrap().on().flex_unwrap(); // red on dongle
let mut storage = take_storage().unwrap();
let num_pages = storage.num_pages();
writeln!(Console::new(), "Erase {} pages of storage:", num_pages).unwrap();
for page in 0..num_pages {
write!(Console::new(), "- Page {} ", page).unwrap();
if is_page_erased(&storage, page) {
writeln!(Console::new(), "skipped (was already erased).").unwrap();
} else {
storage.erase_page(page).unwrap();
writeln!(Console::new(), "erased.").unwrap();
}
}
writeln!(Console::new(), "Done.").unwrap();
led::get(1).flex_unwrap().off().flex_unwrap();
led::get(0).flex_unwrap().on().flex_unwrap(); // green on dongle
}

View File

@@ -7,11 +7,10 @@ extern crate libtock_drivers;
use core::fmt::Write;
use libtock_drivers::console::Console;
libtock_core::stack_size! {0x4000}
#[cfg(not(feature = "with_nfc"))]
mod example {
use super::{Console, Write};
use super::Console;
use super::Write;
pub fn nfc(console: &mut Console) {
writeln!(console, "NFC feature flag is missing!").unwrap();
@@ -20,15 +19,18 @@ mod example {
#[cfg(feature = "with_nfc")]
mod example {
use super::{Console, Write};
use super::Console;
use super::Write;
use libtock_core::result::CommandError;
use libtock_drivers::nfc::{NfcTag, RecvOp};
use libtock_drivers::result::{FlexUnwrap, TockError};
use libtock_drivers::nfc::NfcTag;
use libtock_drivers::nfc::RecvOp;
use libtock_drivers::result::FlexUnwrap;
use libtock_drivers::result::TockError;
use libtock_drivers::timer;
use libtock_drivers::timer::{Timer, Timestamp};
use libtock_drivers::timer::Timer;
use libtock_drivers::timer::Timestamp;
#[derive(Copy, Clone, Debug, PartialEq)]
#[allow(clippy::upper_case_acronyms)]
enum ReturnCode {
/// Operation completed successfully
SUCCESS,

View File

@@ -17,8 +17,6 @@
extern crate alloc;
extern crate lang_items;
libtock_core::stack_size! {0x800}
use alloc::vec::Vec;
use core::fmt::Write;
use libtock_drivers::console::Console;

View File

@@ -16,8 +16,6 @@
extern crate lang_items;
libtock_core::stack_size! {0x800}
fn main() {
panic!("Bye world!")
}

View File

@@ -17,17 +17,13 @@
extern crate alloc;
extern crate lang_items;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use alloc::{format, vec};
use alloc::vec;
use core::fmt::Write;
use ctap2::env::tock::{take_storage, TockStorage};
use ctap2::embedded_flash::{new_storage, Storage};
use libtock_drivers::console::Console;
use libtock_drivers::timer::{self, Duration, Timer, Timestamp};
use persistent_store::Store;
libtock_core::stack_size! {0x2000}
fn timestamp(timer: &Timer) -> Timestamp<f64> {
Timestamp::<f64>::from_clock_value(timer.get_current_clock().ok().unwrap())
}
@@ -39,61 +35,28 @@ fn measure<T>(timer: &Timer, operation: impl FnOnce() -> T) -> (T, Duration<f64>
(result, after - before)
}
fn boot_store(mut storage: TockStorage, erase: bool) -> Store<TockStorage> {
use persistent_store::Storage;
let num_pages = storage.num_pages();
// Only use one store at a time.
unsafe fn boot_store(num_pages: usize, erase: bool) -> Store<Storage> {
let mut storage = new_storage(num_pages);
if erase {
for page in 0..num_pages {
use persistent_store::Storage;
storage.erase_page(page).unwrap();
}
}
Store::new(storage).ok().unwrap()
}
#[derive(Debug)]
struct StorageConfig {
num_pages: usize,
}
fn storage_config(storage: &TockStorage) -> StorageConfig {
use persistent_store::Storage;
StorageConfig {
num_pages: storage.num_pages(),
}
}
#[derive(Default)]
struct Stat {
key_increment: usize,
entry_length: usize, // words
boot_ms: f64,
compaction_ms: f64,
insert_ms: f64,
remove_ms: f64,
}
fn compute_latency(
storage: TockStorage,
timer: &Timer,
num_pages: usize,
key_increment: usize,
word_length: usize,
) -> (TockStorage, Stat) {
let mut stat = Stat {
key_increment,
entry_length: word_length,
..Default::default()
};
fn compute_latency(timer: &Timer, num_pages: usize, key_increment: usize, word_length: usize) {
let mut console = Console::new();
writeln!(
console,
"\nLatency for key_increment={} word_length={}.",
key_increment, word_length
"\nLatency for num_pages={} key_increment={} word_length={}.",
num_pages, key_increment, word_length
)
.unwrap();
let mut store = boot_store(storage, true);
let mut store = unsafe { boot_store(num_pages, true) };
let total_capacity = store.capacity().unwrap().total();
assert_eq!(store.capacity().unwrap().used(), 0);
assert_eq!(store.lifetime().unwrap().used(), 0);
@@ -109,33 +72,33 @@ fn compute_latency(
let ((), time) = measure(timer, || {
for i in 0..count {
let key = 1 + key_increment * i;
store.insert(key, &vec![0; 4 * word_length]).unwrap();
// For some reason the kernel sometimes fails.
while store.insert(key, &vec![0; 4 * word_length]).is_err() {
// We never enter this loop in practice, but we still need it for the kernel.
writeln!(console, "Retry insert.").unwrap();
}
}
});
writeln!(console, "Setup: {:.1}ms for {} entries.", time.ms(), count).unwrap();
// Measure latency of insert.
let key = 1 + key_increment * count;
let ((), time) = measure(timer, || {
let ((), time) = measure(&timer, || {
store.insert(key, &vec![0; 4 * word_length]).unwrap()
});
writeln!(console, "Insert: {:.1}ms.", time.ms()).unwrap();
stat.insert_ms = time.ms();
assert_eq!(
store.lifetime().unwrap().used(),
num_pages + (1 + count) * (1 + word_length)
);
// Measure latency of boot.
let storage = store.extract_storage();
let (mut store, time) = measure(timer, || boot_store(storage, false));
let (mut store, time) = measure(&timer, || unsafe { boot_store(num_pages, false) });
writeln!(console, "Boot: {:.1}ms.", time.ms()).unwrap();
stat.boot_ms = time.ms();
// Measure latency of remove.
let ((), time) = measure(timer, || store.remove(key).unwrap());
let ((), time) = measure(&timer, || store.remove(key).unwrap());
writeln!(console, "Remove: {:.1}ms.", time.ms()).unwrap();
stat.remove_ms = time.ms();
// Measure latency of compaction.
let length = total_capacity + num_pages - store.lifetime().unwrap().used();
@@ -148,81 +111,28 @@ fn compute_latency(
assert_eq!(store.lifetime().unwrap().used(), num_pages + total_capacity);
let ((), time) = measure(timer, || store.prepare(1).unwrap());
writeln!(console, "Compaction: {:.1}ms.", time.ms()).unwrap();
stat.compaction_ms = time.ms();
assert!(store.lifetime().unwrap().used() > total_capacity + num_pages);
(store.extract_storage(), stat)
}
fn main() {
let mut with_callback = timer::with_callback(|_, _| {});
let timer = with_callback.init().ok().unwrap();
let storage = take_storage().unwrap();
let config = storage_config(&storage);
let mut stats = Vec::new();
writeln!(Console::new(), "\nRunning 2 tests...").unwrap();
// Simulate a store full of credentials (of 50 words).
let (storage, stat) = compute_latency(storage, &timer, config.num_pages, 1, 50);
stats.push(stat);
// Simulate a store full of increments of a single counter.
let (_storage, stat) = compute_latency(storage, &timer, config.num_pages, 0, 1);
stats.push(stat);
writeln!(Console::new(), "\nDone.\n").unwrap();
writeln!(Console::new(), "\nRunning 4 tests...").unwrap();
// Those non-overwritten 50 words entries simulate credentials.
compute_latency(&timer, 3, 1, 50);
compute_latency(&timer, 20, 1, 50);
// Those overwritten 1 word entries simulate counters.
compute_latency(&timer, 3, 0, 1);
compute_latency(&timer, 6, 0, 1);
writeln!(Console::new(), "\nDone.").unwrap();
const HEADERS: &[&str] = &[
"Overwrite",
"Length",
"Boot",
"Compaction",
"Insert",
"Remove",
];
let mut matrix = vec![HEADERS.iter().map(|x| x.to_string()).collect()];
for stat in stats {
matrix.push(vec![
if stat.key_increment == 0 { "yes" } else { "no" }.to_string(),
format!("{} words", stat.entry_length),
format!("{:.1} ms", stat.boot_ms),
format!("{:.1} ms", stat.compaction_ms),
format!("{:.1} ms", stat.insert_ms),
format!("{:.1} ms", stat.remove_ms),
]);
}
writeln!(Console::new(), "Copy to examples/store_latency.rs:\n").unwrap();
writeln!(Console::new(), "{:?}", config).unwrap();
write_matrix(matrix);
// Results for nrf52840dk_opensk:
// StorageConfig { num_pages: 20 }
// Overwrite Length Boot Compaction Insert Remove
// no 50 words 18.6 ms 145.8 ms 21.0 ms 9.8 ms
// yes 1 words 335.8 ms 100.6 ms 11.7 ms 5.7 ms
}
fn align(x: &str, n: usize) {
for _ in 0..n.saturating_sub(x.len()) {
write!(Console::new(), " ").unwrap();
}
write!(Console::new(), "{}", x).unwrap();
}
fn write_matrix(mut m: Vec<Vec<String>>) {
if m.is_empty() {
return;
}
let num_cols = m.iter().map(|r| r.len()).max().unwrap();
let mut col_len = vec![0; num_cols];
for row in &mut m {
row.resize(num_cols, String::new());
for col in 0..num_cols {
col_len[col] = core::cmp::max(col_len[col], row[col].len());
}
}
for row in m {
for col in 0..num_cols {
align(&row[col], col_len[col] + 2 * (col > 0) as usize);
}
writeln!(Console::new()).unwrap();
}
// Results on nrf52840dk:
//
// | Pages | Overwrite | Length | Boot | Compaction | Insert | Remove |
// | ----- | --------- | --------- | ------- | ---------- | ------ | ------- |
// | 3 | no | 50 words | 2.0 ms | 132.5 ms | 4.8 ms | 1.2 ms |
// | 20 | no | 50 words | 7.4 ms | 135.5 ms | 10.2 ms | 3.9 ms |
// | 3 | yes | 1 word | 21.9 ms | 94.5 ms | 12.4 ms | 5.9 ms |
// | 6 | yes | 1 word | 55.2 ms | 100.8 ms | 24.8 ms | 12.1 ms |
}

794
fuzz/Cargo.lock generated
View File

@@ -1,794 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "autocfg"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "crypto"
version = "0.1.0"
dependencies = [
"arrayref",
"byteorder",
"hex",
"regex",
"ring",
"rng256",
"serde",
"serde_json",
"subtle",
"untrusted",
]
[[package]]
name = "ctap2"
version = "1.0.0"
dependencies = [
"arbitrary",
"arrayref",
"byteorder",
"crypto",
"embedded-time",
"lang_items",
"libtock_core",
"libtock_drivers",
"openssl",
"persistent_store",
"rand 0.8.5",
"rng256",
"sk-cbor",
"subtle",
"uuid",
]
[[package]]
name = "ctap2-fuzz"
version = "0.0.0"
dependencies = [
"fuzz_helper",
"libfuzzer-sys",
]
[[package]]
name = "derive_arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a012b5e473dc912f0db0546a1c9c6a194ce8494feb66fa0237160926f9e0e6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "embedded-time"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58"
dependencies = [
"num",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "fuzz_helper"
version = "0.1.0"
dependencies = [
"arbitrary",
"arrayref",
"crypto",
"ctap2",
"embedded-time",
"lang_items",
"libtock_drivers",
"rng256",
"sk-cbor",
]
[[package]]
name = "getrandom"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lang_items"
version = "0.1.0"
dependencies = [
"libtock_core",
"libtock_drivers",
"linked_list_allocator",
]
[[package]]
name = "libc"
version = "0.2.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
[[package]]
name = "libfuzzer-sys"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcf184a4b6b274f82a5df6b357da6055d3e82272327bba281c28bbba6f1664ef"
dependencies = [
"arbitrary",
"cc",
]
[[package]]
name = "libtock_codegen"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "libtock_core"
version = "0.1.0"
dependencies = [
"libtock_codegen",
]
[[package]]
name = "libtock_drivers"
version = "0.1.0"
dependencies = [
"libtock_core",
]
[[package]]
name = "linked_list_allocator"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[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.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg 1.1.0",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg 1.1.0",
"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 1.1.0",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "once_cell"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "openssl"
version = "0.10.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-sys"
version = "0.9.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
dependencies = [
"autocfg 1.1.0",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "persistent_store"
version = "0.1.0"
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.3.1",
]
[[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.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[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_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]]
name = "rng256"
version = "0.1.0"
dependencies = [
"arrayref",
"libtock_drivers",
"rand 0.6.5",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "serde"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sk-cbor"
version = "0.1.2"
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "web-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@@ -34,36 +34,18 @@ path = "fuzz_targets/fuzz_target_process_ctap2_client_pin.rs"
test = false
doc = false
[[bin]]
name = "fuzz_target_process_ctap2_client_pin_structured"
path = "fuzz_targets/fuzz_target_process_ctap2_client_pin_structured.rs"
test = false
doc = false
[[bin]]
name = "fuzz_target_process_ctap2_get_assertion"
path = "fuzz_targets/fuzz_target_process_ctap2_get_assertion.rs"
test = false
doc = false
[[bin]]
name = "fuzz_target_process_ctap2_get_assertion_structured"
path = "fuzz_targets/fuzz_target_process_ctap2_get_assertion_structured.rs"
test = false
doc = false
[[bin]]
name = "fuzz_target_process_ctap2_make_credential"
path = "fuzz_targets/fuzz_target_process_ctap2_make_credential.rs"
test = false
doc = false
[[bin]]
name = "fuzz_target_process_ctap2_make_credential_structured"
path = "fuzz_targets/fuzz_target_process_ctap2_make_credential_structured.rs"
test = false
doc = false
[[bin]]
name = "fuzz_target_split_assemble"
path = "fuzz_targets/fuzz_target_split_assemble.rs"

View File

@@ -7,11 +7,8 @@ edition = "2018"
[dependencies]
arrayref = "0.3.6"
embedded-time = "0.12.1"
libtock_drivers = { path = "../../third_party/libtock-drivers" }
crypto = { path = "../../libraries/crypto", features = ['std'] }
rng256 = { path = "../../libraries/rng256", features = ['std'] }
sk-cbor = { path = "../../libraries/cbor" }
ctap2 = { path = "../..", features = ["fuzz"] }
cbor = { path = "../../libraries/cbor", features = ['std'] }
ctap2 = { path = "../..", features = ['std'] }
lang_items = { path = "../../third_party/lang-items", features = ['std'] }
arbitrary = { version = "0.4.7", features = ["derive"] }

View File

@@ -16,25 +16,27 @@
// `libtock_alloc_init` symbol.
extern crate lang_items;
use arbitrary::{Arbitrary, Unstructured};
use arrayref::array_ref;
use core::convert::TryFrom;
use ctap2::api::customization::is_valid;
use ctap2::clock::CtapInstant;
use crypto::rng256::ThreadRng256;
use ctap2::ctap::command::{
AuthenticatorClientPinParameters, AuthenticatorGetAssertionParameters,
AuthenticatorMakeCredentialParameters, Command,
AuthenticatorMakeCredentialParameters,
};
use ctap2::ctap::data_formats::EnterpriseAttestationMode;
use ctap2::ctap::hid::{
ChannelID, CtapHidCommand, HidPacket, HidPacketIterator, Message, MessageAssembler,
};
use ctap2::ctap::{cbor_read, Channel, CtapState};
use ctap2::env::test::customization::TestCustomization;
use ctap2::env::test::TestEnv;
use ctap2::{test_helpers, Ctap, Transport};
use ctap2::ctap::hid::receive::MessageAssembler;
use ctap2::ctap::hid::send::HidPacketIterator;
use ctap2::ctap::hid::{ChannelID, CtapHid, HidPacket, Message};
use ctap2::ctap::status_code::Ctap2StatusCode;
use ctap2::ctap::CtapState;
use libtock_drivers::timer::{ClockValue, Timestamp};
const COMMAND_INIT: u8 = 0x06;
const CHANNEL_BROADCAST: ChannelID = [0xFF, 0xFF, 0xFF, 0xFF];
const PACKET_TYPE_MASK: u8 = 0x80;
const CLOCK_FREQUENCY_HZ: usize = 32768;
const DUMMY_TIMESTAMP: Timestamp<isize> = Timestamp::from_ms(0);
const DUMMY_CLOCK_VALUE: ClockValue = ClockValue::new(0, CLOCK_FREQUENCY_HZ);
#[derive(Clone, Copy, PartialEq)]
pub enum InputType {
@@ -44,17 +46,8 @@ pub enum InputType {
Ctap1,
}
pub enum FuzzError {
ArbitraryError(arbitrary::Error),
InvalidCustomization,
}
pub type FuzzResult<T> = Result<T, FuzzError>;
impl From<arbitrary::Error> for FuzzError {
fn from(err: arbitrary::Error) -> Self {
Self::ArbitraryError(err)
}
fn user_immediately_present(_: ChannelID) -> Result<(), Ctap2StatusCode> {
Ok(())
}
// Converts a byte slice into Message
@@ -64,14 +57,13 @@ fn raw_to_message(data: &[u8]) -> Message {
cid[..data.len()].copy_from_slice(data);
Message {
cid,
// Arbitrary command.
cmd: CtapHidCommand::Cbor,
cmd: 0,
payload: vec![],
}
} else {
Message {
cid: array_ref!(data, 0, 4).clone(),
cmd: CtapHidCommand::from(data[4]),
cmd: data[4],
payload: data[5..].to_vec(),
}
}
@@ -79,22 +71,24 @@ fn raw_to_message(data: &[u8]) -> Message {
// Returns an initialized ctap state, hid and the allocated cid
// after processing the init command.
fn initialize(ctap: &mut Ctap<TestEnv>) -> ChannelID {
fn initialize<CheckUserPresence>(
ctap_state: &mut CtapState<ThreadRng256, CheckUserPresence>,
ctap_hid: &mut CtapHid,
) -> ChannelID
where
CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>,
{
let nonce = vec![0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0];
let message = Message {
cid: CHANNEL_BROADCAST,
cmd: CtapHidCommand::Init,
cmd: COMMAND_INIT,
payload: nonce,
};
let mut assembler_reply = MessageAssembler::new();
let mut result_cid: ChannelID = Default::default();
for pkt_request in HidPacketIterator::new(message).unwrap() {
for pkt_reply in
ctap.process_hid_packet(&pkt_request, Transport::MainHid, CtapInstant::new(0))
{
if let Ok(Some(result)) =
assembler_reply.parse_packet(ctap.env(), &pkt_reply, CtapInstant::new(0))
{
for pkt_reply in ctap_hid.process_hid_packet(&pkt_request, DUMMY_CLOCK_VALUE, ctap_state) {
if let Ok(Some(result)) = assembler_reply.parse_packet(&pkt_reply, DUMMY_TIMESTAMP) {
result_cid.copy_from_slice(&result.payload[8..12]);
}
}
@@ -107,7 +101,7 @@ fn is_type(data: &[u8], input_type: InputType) -> bool {
if input_type == InputType::Ctap1 {
return true;
}
match cbor_read(data) {
match cbor::read(data) {
Err(_) => false,
Ok(decoded_cbor) => match input_type {
InputType::CborMakeCredentialParameter => {
@@ -126,16 +120,22 @@ fn is_type(data: &[u8], input_type: InputType) -> bool {
// Interprets the raw data as a complete message (with channel id, command type and payload) and
// invokes message splitting, packet processing at CTAP HID level and response assembling.
fn process_message(data: &[u8], ctap: &mut Ctap<TestEnv>) {
fn process_message<CheckUserPresence>(
data: &[u8],
ctap_state: &mut CtapState<ThreadRng256, CheckUserPresence>,
ctap_hid: &mut CtapHid,
) where
CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>,
{
let message = raw_to_message(data);
if let Some(hid_packet_iterator) = HidPacketIterator::new(message) {
let mut assembler_reply = MessageAssembler::new();
for pkt_request in hid_packet_iterator {
for pkt_reply in
ctap.process_hid_packet(&pkt_request, Transport::MainHid, CtapInstant::new(0))
ctap_hid.process_hid_packet(&pkt_request, DUMMY_CLOCK_VALUE, ctap_state)
{
// Only checks for assembling crashes, not for semantics.
let _ = assembler_reply.parse_packet(ctap.env(), &pkt_reply, CtapInstant::new(0));
let _ = assembler_reply.parse_packet(&pkt_reply, DUMMY_TIMESTAMP);
}
}
}
@@ -144,66 +144,30 @@ fn process_message(data: &[u8], ctap: &mut Ctap<TestEnv>) {
// Interprets the raw data as any ctap command (including the command byte) and
// invokes message splitting, packet processing at CTAP HID level and response assembling
// using an initialized and allocated channel.
pub fn process_ctap_any_type(data: &[u8]) -> arbitrary::Result<()> {
let mut unstructured = Unstructured::new(data);
let mut env = TestEnv::new();
env.rng().seed_from_u64(u64::arbitrary(&mut unstructured)?);
let data = unstructured.take_rest();
pub fn process_ctap_any_type(data: &[u8]) {
// Initialize ctap state and hid and get the allocated cid.
let mut ctap = Ctap::new(env, CtapInstant::new(0));
let cid = initialize(&mut ctap);
let mut rng = ThreadRng256 {};
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
let mut ctap_hid = CtapHid::new();
let cid = initialize(&mut ctap_state, &mut ctap_hid);
// Wrap input as message with the allocated cid.
let mut command = cid.to_vec();
command.extend(data);
process_message(&command, &mut ctap);
Ok(())
}
fn setup_customization(
unstructured: &mut Unstructured,
customization: &mut TestCustomization,
) -> FuzzResult<()> {
customization.setup_enterprise_attestation(
Option::<EnterpriseAttestationMode>::arbitrary(unstructured)?,
// TODO: Generate arbitrary rp_id_list (but with some dummies because content doesn't
// matter), and use the rp ids in commands.
None,
);
if !is_valid(customization) {
return Err(FuzzError::InvalidCustomization);
}
Ok(())
}
fn setup_state(
unstructured: &mut Unstructured,
state: &mut CtapState,
env: &mut TestEnv,
) -> FuzzResult<()> {
if bool::arbitrary(unstructured)? {
test_helpers::enable_enterprise_attestation(state, env).ok();
}
Ok(())
process_message(&command, &mut ctap_state, &mut ctap_hid);
}
// Interprets the raw data as of the given input type and
// invokes message splitting, packet processing at CTAP HID level and response assembling
// using an initialized and allocated channel.
pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) -> arbitrary::Result<()> {
let mut unstructured = Unstructured::new(data);
let mut env = TestEnv::new();
env.rng().seed_from_u64(u64::arbitrary(&mut unstructured)?);
let data = unstructured.take_rest();
pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) {
if !is_type(data, input_type) {
return Ok(());
return;
}
// Initialize ctap state and hid and get the allocated cid.
let mut ctap = Ctap::new(env, CtapInstant::new(0));
let cid = initialize(&mut ctap);
let mut rng = ThreadRng256 {};
let mut ctap_state = CtapState::new(&mut rng, user_immediately_present, DUMMY_CLOCK_VALUE);
let mut ctap_hid = CtapHid::new();
let cid = initialize(&mut ctap_state, &mut ctap_hid);
// Wrap input as message with allocated cid and command type.
let mut command = cid.to_vec();
match input_type {
@@ -221,71 +185,24 @@ pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) -> arbitra
}
}
command.extend(data);
process_message(&command, &mut ctap);
Ok(())
}
pub fn process_ctap_structured(data: &[u8], input_type: InputType) -> FuzzResult<()> {
let unstructured = &mut Unstructured::new(data);
let mut env = TestEnv::new();
env.rng().seed_from_u64(u64::arbitrary(unstructured)?);
setup_customization(unstructured, env.customization_mut())?;
let mut state = CtapState::new(&mut env, CtapInstant::new(0));
setup_state(unstructured, &mut state, &mut env)?;
let command = match input_type {
InputType::CborMakeCredentialParameter => Command::AuthenticatorMakeCredential(
AuthenticatorMakeCredentialParameters::arbitrary(unstructured)?,
),
InputType::CborGetAssertionParameter => Command::AuthenticatorGetAssertion(
AuthenticatorGetAssertionParameters::arbitrary(unstructured)?,
),
InputType::CborClientPinParameter => Command::AuthenticatorClientPin(
AuthenticatorClientPinParameters::arbitrary(unstructured)?,
),
InputType::Ctap1 => {
unimplemented!()
}
};
state
.process_parsed_command(
&mut env,
command,
Channel::MainHid(ChannelID::arbitrary(unstructured)?),
CtapInstant::new(0),
)
.ok();
Ok(())
process_message(&command, &mut ctap_state, &mut ctap_hid);
}
// Splits the given data as HID packets and reassembles it, verifying that the original input message is reconstructed.
pub fn split_assemble_hid_packets(data: &[u8]) -> arbitrary::Result<()> {
let mut unstructured = Unstructured::new(data);
let mut env = TestEnv::new();
env.rng().seed_from_u64(u64::arbitrary(&mut unstructured)?);
let data = unstructured.take_rest();
let message = raw_to_message(data);
pub fn split_assemble_hid_packets(data: &[u8]) {
let mut message = raw_to_message(data);
if let Some(hid_packet_iterator) = HidPacketIterator::new(message.clone()) {
let mut assembler = MessageAssembler::new();
let packets: Vec<HidPacket> = hid_packet_iterator.collect();
if let Some((last_packet, first_packets)) = packets.split_last() {
for packet in first_packets {
assert_eq!(
assembler.parse_packet(&mut env, packet, CtapInstant::new(0)),
Ok(None)
);
assert_eq!(assembler.parse_packet(packet, DUMMY_TIMESTAMP), Ok(None));
}
message.cmd &= !PACKET_TYPE_MASK;
assert_eq!(
assembler.parse_packet(&mut env, last_packet, CtapInstant::new(0)),
assembler.parse_packet(last_packet, DUMMY_TIMESTAMP),
Ok(Some(message))
);
}
}
Ok(())
}

View File

@@ -7,5 +7,5 @@ use libfuzzer_sys::fuzz_target;
// For a more generic fuzz target including all CTAP commands, you can use
// fuzz_target_process_ctap_command.
fuzz_target!(|data: &[u8]| {
process_ctap_specific_type(data, InputType::Ctap1).ok();
process_ctap_specific_type(data, InputType::Ctap1);
});

View File

@@ -7,5 +7,5 @@ use libfuzzer_sys::fuzz_target;
// For a more generic fuzz target including all CTAP commands, you can use
// fuzz_target_process_ctap_command.
fuzz_target!(|data: &[u8]| {
process_ctap_specific_type(data, InputType::CborClientPinParameter).ok();
process_ctap_specific_type(data, InputType::CborClientPinParameter);
});

View File

@@ -1,10 +0,0 @@
#![no_main]
use fuzz_helper::{process_ctap_structured, InputType};
use libfuzzer_sys::fuzz_target;
// Fuzz inputs as CTAP2 client pin command parameters.
// The inputs will used to construct arbitrary client pin parameters.
fuzz_target!(|data: &[u8]| {
process_ctap_structured(data, InputType::CborClientPinParameter).ok();
});

View File

@@ -7,5 +7,5 @@ use libfuzzer_sys::fuzz_target;
// For a more generic fuzz target including all CTAP commands, you can use
// fuzz_target_process_ctap_command.
fuzz_target!(|data: &[u8]| {
process_ctap_specific_type(data, InputType::CborGetAssertionParameter).ok();
process_ctap_specific_type(data, InputType::CborGetAssertionParameter);
});

View File

@@ -1,10 +0,0 @@
#![no_main]
use fuzz_helper::{process_ctap_structured, InputType};
use libfuzzer_sys::fuzz_target;
// Fuzz inputs as CTAP2 get assertion command parameters.
// The inputs will used to construct arbitrary get assertion parameters.
fuzz_target!(|data: &[u8]| {
process_ctap_structured(data, InputType::CborGetAssertionParameter).ok();
});

View File

@@ -7,5 +7,5 @@ use libfuzzer_sys::fuzz_target;
// For a more generic fuzz target including all CTAP commands, you can use
// fuzz_target_process_ctap_command.
fuzz_target!(|data: &[u8]| {
process_ctap_specific_type(data, InputType::CborMakeCredentialParameter).ok();
process_ctap_specific_type(data, InputType::CborMakeCredentialParameter);
});

View File

@@ -1,10 +0,0 @@
#![no_main]
use fuzz_helper::{process_ctap_structured, InputType};
use libfuzzer_sys::fuzz_target;
// Fuzz inputs as CTAP2 make credential command parameters.
// The inputs will used to construct arbitrary make credential parameters.
fuzz_target!(|data: &[u8]| {
process_ctap_structured(data, InputType::CborMakeCredentialParameter).ok();
});

View File

@@ -5,5 +5,5 @@ use libfuzzer_sys::fuzz_target;
// Generically fuzz inputs as CTAP commands.
fuzz_target!(|data: &[u8]| {
process_ctap_any_type(data).ok();
process_ctap_any_type(data);
});

Some files were not shown because too many files have changed in this diff Show More