diff --git a/README.md b/README.md index ade3a63d4e80bbb83ab3d6c9914b732aa8608cf8..dfca6996a0572edc8a4a4991fbe222e6d9cc6b6f 100644 --- a/README.md +++ b/README.md @@ -49,23 +49,22 @@ For a more detailed guide, please refer to our ./setup.sh ``` -2. If you have a Nordic development board that doesn't already have Tock OS - installed, you can install both TockOS and the OpenSK application by running - the following command, depending on the board you have: +2. If Tock OS is already installed on your board, move to the next step. + Otherwise, just run one of the following commands, depending on the board + you have: ```shell # Nordic nRF52840-DK board - board=nrf52840dk ./deploy.sh os app + ./deploy.py os --board=nrf52840dk # Nordic nRF52840-Dongle - board=nrf52840_dongle ./deploy.sh os app + ./deploy.py os --board=nrf52840_dongle ``` -3. If Tock OS is already installed and you want to install/update the OpenSK - application on your board (**Warning**: it will erase the locally stored - credentials), run: +3. Next step is to install/update the OpenSK application on your board + (**Warning**: it will erase the locally stored credentials). Run: ```shell - ./deploy.sh app + ./deploy.py app --opensk ``` 4. On Linux, you may want to avoid the need for `root` privileges to interact @@ -83,7 +82,7 @@ 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. + 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 diff --git a/deploy.py b/deploy.py new file mode 100755 index 0000000000000000000000000000000000000000..d1488d95df927240c1a244c42363ef3e812b83f1 --- /dev/null +++ b/deploy.py @@ -0,0 +1,425 @@ +#!/usr/bin/env python3 +# 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. +# 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. +# Lint as: python3 + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import argparse +import colorama +import copy +import os +import shutil +import subprocess +import sys +from tockloader import tab, tbfh, tockloader + + +# This structure allows us in the future to also support out-of-tree boards. +SUPPORTED_BOARDS = { + "nrf52840_dk": "third_party/tock/boards/nordic/nrf52840dk", + "nrf52840_dongle": "third_party/tock/boards/nordic/nrf52840_dongle" +} + +# The STACK_SIZE value below must match the one used in the linker script +# used by the board. +# e.g. for Nordic nRF52840 boards the file is `nrf52840dk_layout.ld`. +STACK_SIZE = 0x4000 + +# The following value must match the one used in the file +# `src/entry_point.rs` +APP_HEAP_SIZE = 90000 + + +def get_supported_boards(): + boards = [] + for name, root in SUPPORTED_BOARDS.items(): + if all((os.path.exists(os.path.join(root, "Cargo.toml")), + os.path.exists(os.path.join(root, "Makefile")))): + boards.append(name) + return tuple(set(boards)) + + +def fatal(msg): + print("{style_begin}fatal:{style_end} {message}".format( + style_begin=colorama.Fore.RED + colorama.Style.BRIGHT, + style_end=colorama.Style.RESET_ALL, + message=msg)) + sys.exit(1) + + +def error(msg): + print("{style_begin}error:{style_end} {message}".format( + style_begin=colorama.Fore.RED, + style_end=colorama.Style.RESET_ALL, + message=msg)) + + +def info(msg): + print("{style_begin}info:{style_end} {message}".format( + style_begin=colorama.Fore.GREEN + colorama.Style.BRIGHT, + style_end=colorama.Style.RESET_ALL, + message=msg)) + + +class RemoveConstAction(argparse.Action): + def __init__(self, + option_strings, + dest, + const, + default=None, + required=False, + help=None, + metavar=None): + super(RemoveConstAction, self).__init__( + option_strings=option_strings, + dest=dest, + nargs=0, + const=const, + default=default, + required=required, + help=help, + metavar=metavar) + + def __call__(self, parser, namespace, values, option_string=None): + # Code is simply a modified version of the AppendConstAction from argparse + # https://github.com/python/cpython/blob/master/Lib/argparse.py#L138-L147 + # https://github.com/python/cpython/blob/master/Lib/argparse.py#L1028-L1052 + items = getattr(namespace, self.dest, []) + if type(items) is list: + items = items[:] + else: + items = copy.copy(items) + if self.const in items: + self.remove(self.const) + setattr(namespace, self.dest, items) + + +class OpenSKInstaller(object): + def __init__(self, args): + colorama.init() + self.args = args + # Where all the TAB files should go + self.tab_folder = os.path.join("target", "tab") + # This is the filename that elf2tab command expects in order + # to create a working TAB file. + self.target_elf_filename = os.path.join( + self.tab_folder, "cortex-m4.elf") + self.tockloader_default_args = argparse.Namespace( + arch="cortex-m4", + board=getattr(self.args, "board", "nrf52840"), + debug=False, + force=False, + jlink=True, + jlink_device="nrf52840_xxaa", + jlink_if="swd", + jlink_speed=1200, + jtag=False, + no_bootloader_entry=False, + page_size=4096, + port=None, + ) + + def checked_command_output(self, cmd): + cmd_output = "" + try: + cmd_output = subprocess.check_output(cmd) + except subprocess.CalledProcessError as e: + fatal("Failed to execute {}: {}".format(cmd[0], str(e))) + # Unreachable because fatal() will exit + return cmd_output.decode() + + def update_rustc_if_needed(self): + target_toolchain_fullstring = "stable" + with open("rust-toolchain", "r") as f: + target_toolchain_fullstring = f.readline().strip() + target_toolchain = target_toolchain_fullstring.split("-", maxsplit=1) + if len(target_toolchain) == 1: + # If we target the stable version of rust, we won't have a date + # associated to the version and split will only return 1 item. + # To avoid failing later when accessing the date, we insert an + # empty value. + target_toolchain.append('') + current_version = self.checked_command_output(["rustc", "--version"]) + if not all( + (target_toolchain[0] in current_version, + target_toolchain[1] in current_version)): + info("Updating rust toolchain to {}".format( + "-".join(target_toolchain))) + # Need to update + self.checked_command_output( + ["rustup", "install", target_toolchain_fullstring]) + self.checked_command_output( + ["rustup", "target", "add", "thumbv7em-none-eabi"]) + info("Rust toolchain up-to-date") + + def build_and_install_tockos(self): + self.checked_command_output( + ["make", "-C", SUPPORTED_BOARDS[self.args.board], "flash"] + ) + + def build_and_install_example(self): + assert(self.args.application) + self.checked_command_output([ + "cargo", + "build", + "--release", + "--target=thumbv7em-none-eabi", + "--features={}".format(",".join(self.args.features)), + "--example", + self.args.application + ]) + self.install_elf_file(os.path.join( + "target/thumbv7em-none-eabi/release/examples", + self.args.application)) + + def build_and_install_opensk(self): + assert(self.args.application) + info("Building OpenSK application") + self.checked_command_output([ + "cargo", + "build", + "--release", + "--target=thumbv7em-none-eabi", + "--features={}".format(",".join(self.args.features)), + ]) + self.install_elf_file(os.path.join( + "target/thumbv7em-none-eabi/release", self.args.application)) + + def generate_crypto_materials(self, force_regenerate): + has_error = subprocess.call([ + os.path.join("tools", "gen_key_materials.sh"), + "Y" if force_regenerate else "N", + ]) + if has_error: + error(( + "Something went wrong while trying to generate ECC " + "key and/or certificate for OpenSK")) + + def install_elf_file(self, elf_path): + assert(self.args.application) + package_parameter = "-n" + elf2tab_ver = self.checked_command_output( + ["elf2tab", "--version"]).split(' ', maxsplit=1)[1] + # Starting from v0.5.0-dev the parameter changed. + # Current pyblished crate is 0.4.0 but we don't want developers + # running the HEAD from github to be stuck + if "0.5.0-dev" in elf2tab_ver: + package_parameter = "--package-name" + os.makedirs(self.tab_folder, exist_ok=True) + tab_filename = os.path.join( + self.tab_folder, + "{}.tab".format(self.args.application)) + shutil.copyfile(elf_path, self.target_elf_filename) + self.checked_command_output([ + "elf2tab", + package_parameter, + self.args.application, + "-o", + tab_filename, + self.target_elf_filename, + "--stack={}".format(STACK_SIZE), + "--app-heap={}".format(APP_HEAP_SIZE), + "--kernel-heap=1024", + "--protected-region-size=64" + ]) + self.install_padding() + info("Installing Tock application {}".format(self.args.application)) + args = copy.copy(self.tockloader_default_args) + setattr(args, "app_address", 0x40000) + setattr(args, "erase", self.args.clear_apps) + setattr(args, "make", False) + setattr(args, "no_replace", False) + setattr(args, "sticky", False) + tock = tockloader.TockLoader(args) + tock.open(args) + tabs = [tab.TAB(tab_filename)] + try: + tock.install(tabs, replace="yes", + erase=args.erase, sticky=args.sticky) + except tockloader.exceptions.TockLoaderException as e: + fatal("Couldn't install Tock application {}: {}".format( + self.args.application, str(e))) + + def install_padding(self): + fake_header = tbfh.TBFHeader("") + fake_header.version = 2 + fake_header.fields["header_size"] = 0x10 + fake_header.fields["total_size"] = 0x10000 + fake_header.fields["flags"] = 0 + padding = fake_header.get_binary() + info("Flashing padding application") + args = copy.copy(self.tockloader_default_args) + setattr(args, "address", 0x30000) + tock = tockloader.TockLoader(args) + tock.open(args) + try: + tock.flash_binary(padding, args.address) + except tockloader.exceptions.TockLoaderException as e: + fatal("Couldn't install padding: {}".format(str(e))) + + def clear_apps(self): + args = copy.copy(self.tockloader_default_args) + setattr(args, "app_address", 0x40000) + info("Erasing all installed applications") + tock = tockloader.TockLoader(args) + tock.open(args) + try: + tock.erase_apps(False) + except tockloader.exceptions.TockLoaderException as e: + # Erasing apps is not critical + info(("A non-critical error occured while erasing " + "apps: {}".format(str(e)))) + + def run(self): + if self.args.action is None: + # Nothing to do + return + + self.update_rustc_if_needed() + + if self.args.action == "os": + info("Installing Tock on board {}".format(self.args.board)) + self.build_and_install_tockos() + + if self.args.action == "app": + if self.args.application is None: + fatal("Unspecified application") + if self.args.clear_apps: + self.clear_apps() + if self.args.application == "ctap2": + self.generate_crypto_materials(self.args.regenerate_keys) + self.build_and_install_opensk() + else: + self.build_and_install_example() + + +def main(args): + # Make sure the current working directory is the right one before running + os.chdir(os.path.realpath(os.path.dirname(__file__))) + OpenSKInstaller(args).run() + + +if __name__ == '__main__': + shared_parser = argparse.ArgumentParser(add_help=False) + shared_parser.add_argument( + "--dont-clear-apps", + action="store_false", + default=True, + dest="clear_apps", + help=( + "When installing an application, previously installed " + "applications won't be erased from the board." + ), + ) + + parser = argparse.ArgumentParser() + commands = parser.add_subparsers( + dest="action", + help=( + "Indicates which part of the firmware should be compiled and " + "flashed to the connected board." + ) + ) + + os_commands = commands.add_parser( + "os", + parents=[shared_parser], + help=( + "Compiles and installs Tock OS. The target board must be " + "specified by setting the --board argument." + ), + ) + os_commands.add_argument( + "--board", + metavar="BOARD_NAME", + dest="board", + choices=get_supported_boards(), + help="Indicates which board Tock OS will be compiled for.", + required=True + ) + + app_commands = commands.add_parser( + "app", + parents=[shared_parser], + help="compiles and installs an application." + ) + app_commands.add_argument( + "--panic-console", + action="append_const", + const="panic_console", + dest="features", + help=( + "In case of application panic, the console will be used to " + "output messages before starting blinking the LEDs on the " + "board." + ), + ) + app_commands.add_argument( + "--no-u2f", + action=RemoveConstAction, + const="with_ctap1", + dest="features", + help=( + "Compiles the OpenSK application without backward compatible " + "support for U2F/CTAP1 protocol." + ), + ) + app_commands.add_argument( + "--regen-keys", + action="store_true", + default=False, + dest="regenerate_keys", + help=( + "Forces the generation of files (certificates and private keys) " + "under the crypto_data/ directory. " + "This is useful to allow flashing multiple OpenSK authenticators " + "in a row without them being considered clones." + ), + ) + app_commands.add_argument( + "--debug", + action="append_const", + const="debug_ctap", + dest="features", + help=( + "Compiles and installs the OpenSK application in debug mode " + "(i.e. more debug messages will be sent over the console port " + "such as hexdumps of packets)." + ), + ) + apps = app_commands.add_mutually_exclusive_group() + apps.add_argument( + "--opensk", + dest="application", + action="store_const", + const="ctap2", + help="Compiles and installs the OpenSK application." + ) + apps.add_argument( + "--crypto_bench", + dest="application", + action="store_const", + const="crypto_bench", + help=( + "Compiles and installs the crypto_bench example that tests " + "the performance of the cryptographic algorithms on the board." + ) + ) + + app_commands.set_defaults(features=["with_ctap1"]) + + main(parser.parse_args()) diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index e86fcd303936d6fd08adef515bcce82a0ac0a9b7..0000000000000000000000000000000000000000 --- a/deploy.sh +++ /dev/null @@ -1,327 +0,0 @@ -#!/usr/bin/env bash -# 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. -# 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. - - -set -e - -if [ "x$VERBOSE" != "x" ] -then - set -x -fi - -info_text="$(tput bold)info:$(tput sgr0)" -error_text="$(tput bold)error:$(tput sgr0)" - -tab_folder="target/tab" -# elf2tab requires a file named "cortex-m4", so this path is used for all -# target applications. -elf_file_name="${tab_folder}/cortex-m4.elf" - -# elf2tab 0.4.0 and below uses "-n" flag but 0.5.0-dev changes that "-p" or -# "--package-name" -# We try to be compatible with both versions. -elf2tab_package_param="-n" -if which elf2tab > /dev/null 2>&1 -then - if [ "$(elf2tab --version | cut -d' ' -f2)" = "0.5.0-dev" ] - then - # Short parameter is "-p" but long parameter names should be prefered - # when they are used in scripts. - elf2tab_package_param="--package-name" - fi -else - echo "" - echo "Command elf2tab not found. Have you run the setup.sh script?" - exit 2 -fi - -# We need to specify the board explicitly to be able to flash after 0x80000. -tockloader_flags=( - --jlink - --board="${board:-nrf52840}" - --arch=cortex-m4 - --jlink-device=nrf52840_xxaa - --page-size=4096 -) - -declare -A supported_boards -supported_boards["nrf52840dk"]="Y" -supported_boards["nrf52840_dongle"]="Y" - -declare -A enabled_features=( [with_ctap1]=Y ) - -print_usage () { - cat <<EOH -Usage: $0 [options...] <actions...> - -Example: - In order to install TockOS and a debug version of OpenSK on a Nordic nRF52840-DK - board, you need to run the following command: - board=nrf52840dk $0 --panic-console os app_debug - -Actions: - os - Compiles and installs Tock OS on the selected board. - The target board must be indicated by setting the environment - variable \$board - - app - Compiles and installs OpenSK application. - - app_debug - Compiles and installs OpenSK application in debug mode (i.e. more debug messages - will be sent over the console port such as hexdumps of packets) - - crypto_bench - Compiles and installs the crypto_bench example that tests the performance - of the cryptographic algorithms on the board. - -Options: - --dont-clear-apps - When installing an application, previously installed applications won't - be erased from the board. - - --no-u2f - Compiles OpenSK application without backward compatible support for - U2F/CTAP1 protocol. - - - --regen-keys - Forces the generation of src/ctap/key_materials.rs file. - This won't force re-generate OpenSSL files under crypto_data/ directory. - If the OpenSSL files needs to be re-generated, simply delete them (or - the whole directory). - - --panic-console - In case of application panic, the console will be used to output messages - before starting blinking the LEDs on the board. - -EOH -} - -display_supported_boards () { - echo "$info_text Currently supported boards are:" - for b in ${!supported_boards[@]} - do - if [ -d "third_party/tock/boards/nordic/$b" -a \ - -e "third_party/tock/boards/nordic/$b/Cargo.toml" ] - then - echo " - $b" - fi - done -} - -# Import generate_crypto_materials function -source tools/gen_key_materials.sh - -build_app_padding () { - # On nRF52840, the MMU can have 8 sub-regions and the flash size is 0x1000000. - # By default, applications are flashed at 0x30000 which means the maximum size - # for an application is 0x40000 (an application of size 0x80000 would need 16 - # sub-regions of size 0x10000; sub-regions need to be aligned on their size). - # This padding permits to have the application start at 0x40000 and increase - # the maximum application size to 0x80000 (with 4 sub-regions of size - # 0x40000). - ( - # Version: 2 - echo -n "0200" - # Header size: 0x10 - echo -n "1000" - # Total size: 0x10000 - echo -n "00000100" - # Flags: 0 - echo -n "00000000" - # Checksum - echo -n "02001100" - ) | xxd -p -r > "${tab_folder}/padding.bin" -} - -comma_separated () { - # Flatten the array - # This is equivalent to the following python snippet: ' '.join(arr).replace(' ', ',') - local list=$(IFS=$'\n'; echo "$@") - if [ "X${list}" != "X" ] - then - feature_list="${list// /,}" - fi - echo ${list} -} - -build_app () { - local feature_list="$(comma_separated "$@")" - cargo build \ - --release \ - --target=thumbv7em-none-eabi \ - --features="${feature_list}" - - mkdir -p "target/tab" - cp "target/thumbv7em-none-eabi/release/ctap2" "$elf_file_name" - - elf2tab \ - "${elf2tab_package_param}" "ctap2" \ - -o "${tab_folder}/ctap2.tab" \ - "$elf_file_name" \ - --stack 16384 \ - --app-heap 90000 \ - --kernel-heap 1024 \ - --protected-region-size=64 -} - -build_crypto_bench () { - local feature_list="$(comma_separated "$@")" - cargo build \ - --release \ - --target=thumbv7em-none-eabi \ - --features="${feature_list}" \ - --example crypto_bench - - mkdir -p "target/tab" - cp "target/thumbv7em-none-eabi/release/examples/crypto_bench" "$elf_file_name" - - elf2tab \ - "${elf2tab_package_param}" "crypto_bench" \ - -o "${tab_folder}/crypto_bench.tab" \ - "$elf_file_name" \ - --stack 16384 \ - --app-heap 90000 \ - --kernel-heap 1024 \ - --protected-region-size=64 -} - -deploy_tock () { - if [ "x$board" = "x" ]; - then - echo "$error_text You must set the board in order to install Tock OS (example: \`board=nrf52840dk $0 os\`)" - display_supported_boards - return 1 - fi - if [ "${supported_boards[$board]+x}" = "x" -a -d "third_party/tock/boards/nordic/$board" ] - then - make -C third_party/tock/boards/nordic/$board flash - else - echo "$error_text The board '$board' doesn't seem to be supported" - display_supported_boards - return 1 - fi -} - -clear_apps=Y -install_os=N -install_app=none - -force_generate=N -has_errors=N - -if [ "$#" -eq "0" ] -then - print_usage - exit 1 -fi - -while [ "$#" -ge "1" ] -do - case "$1" in - --dont-clear-apps) - clear_apps=N - ;; - - --no-u2f) - unset enabled_features["with_ctap1"] - ;; - - --regen-keys) - force_generate=Y - ;; - - --panic-console) - enabled_features["panic_console"]="Y" - ;; - - os) - install_os=Y - ;; - - app) - install_app=ctap2 - ;; - - app_debug) - install_app=ctap2 - enabled_features["debug_ctap"]="Y" - ;; - - crypto_bench) - install_app=crypto_bench - ;; - - *) - echo "$error_text Unsupported option: '"$1"'" - has_errors=Y - ;; - esac - shift 1 -done - -if [ "$has_errors" = "Y" ] -then - echo "" - print_usage - exit 1 -fi - -# Test if we need to update Rust toolchain -# rustc --version outputs a version line such as: -# rustc 1.40.0-nightly (0e8a4b441 2019-10-16) -# The sed regexp turns it into: -# nightly-2019-10-16 -current_toolchain=$(rustc --version | sed -e 's/^rustc [0-9]*\.[0-9]*\.[0-9]*-\(nightly\) ([0-9a-f]* \([0-9]*-[0-9]*-[0-9]*\))$/\1-\2/') -target_toolchain=$(head -n 1 rust-toolchain) - -if [ "x${current_toolchain}" != "x${target_toolchain}" ] -then - rustup install "${target_toolchain}" - rustup target add thumbv7em-none-eabi -fi - -if [ "$install_os" = "Y" ] -then - deploy_tock -fi - -# Don't try to uninstall app if we don't plan to install after. -if [ "$install_app" != "none" -a "$clear_apps" = "Y" ] -then - # Uninstall can fail if there's no app already installed. - # This is fine and we don't want that to stop the script - tockloader uninstall "${tockloader_flags[@]}" -a 0x40000 || true -fi - -if [ "$install_app" = "ctap2" ] -then - generate_crypto_materials "${force_generate}" - build_app "${!enabled_features[@]}" -fi - -if [ "$install_app" = "crypto_bench" ] -then - build_crypto_bench "${!enabled_features[@]}" -fi - -if [ "$install_app" != "none" ] -then - build_app_padding - tockloader flash "${tockloader_flags[@]}" -a 0x30000 "${tab_folder}/padding.bin" - tockloader install "${tockloader_flags[@]}" -a 0x40000 "${tab_folder}/${install_app}.tab" -fi diff --git a/docs/install.md b/docs/install.md index 8b1b6fe4b169f9601843aef2459ee76920e3b127..745709d8ebc97e74b2343484257b3b6fa8ee54e5 100644 --- a/docs/install.md +++ b/docs/install.md @@ -63,19 +63,21 @@ $ ./setup.sh [-] Applying patch "02-usb.patch"... DONE. [-] Applying patch "03-app-memory.patch"... DONE. [-] Applying patch "04-rtt.patch"... DONE. -[-] Applying patch "01-panic_console.patch"... DONE. -[-] Applying patch "02-timer.patch"... DONE. -[-] Applying patch "03-public_syscalls.patch"... DONE. -[-] Applying patch "04-bigger_heap.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-01-16-x86_64-unknown-linux-gnu' +info: syncing channel updates for 'nightly-2020-02-03-x86_64-unknown-linux-gnu' - nightly-2020-01-16-x86_64-unknown-linux-gnu unchanged - rustc 1.42.0-nightly (3291ae339 2020-01-15) + 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) @@ -127,8 +129,9 @@ File | Purpose If you want to use your own attestation certificate and private key, simply replace `opensk_cert.pem` and `opensk.key` files. -Our build script is responsible for converting `opensk_cert.pem` and -`opensk.key` files into the following Rust file: `src/ctap/key_material.rs`. +Our build script `build.rs` is responsible for converting `opensk_cert.pem` and +`opensk.key` files into raw data that is then used by the Rust file: +`src/ctap/key_material.rs`. ### Flashing a firmware @@ -138,45 +141,72 @@ Our build script is responsible for converting `opensk_cert.pem` and 1. Connect a micro USB cable to the JTAG USB port. -1. Run our script for compiling/flashing your device (_output may differ_): +1. Run our script for compiling/flashing Tock OS on your device (_output may + differ_): ```shell - $ board=nrf52840dk ./deploy.sh app os - make: Entering directory './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) - Compiling nrf52840dk v0.1.0 (./third_party/tock/boards/nordic/nrf52840dk) - Finished release [optimized + debuginfo] target(s) in 11.28s - text data bss dec hex filename - 114688 1760 260384 376832 5c000 target/thumbv7em-none-eabi/release/nrf52840dk - tockloader flash --address 0x00000 --jlink --board nrf52dk target/thumbv7em-none-eabi/release/nrf52840dk.bin - [STATUS ] Flashing binar(y|ies) to board... - [INFO ] Using known arch and jtag-device for known board nrf52dk - [INFO ] Finished in 0.324 seconds - - make: Leaving directory './third_party/tock/boards/nordic/nrf52840dk' - [STATUS ] Preparing to uninstall apps... - [INFO ] Using known arch and jtag-device for known board nrf52dk - [ERROR ] No apps are installed on the board - - Compiling libtock v0.1.0 (./third_party/libtock-rs) - Compiling crypto v0.1.0 (./libraries/crypto) - Compiling ctap2 v0.1.0 (.) - Finished release [optimized] target(s) in 7.60s - [STATUS ] Flashing binar(y|ies) to board... - [INFO ] Using known arch and jtag-device for known board nrf52dk - [INFO ] Finished in 0.305 seconds - - [STATUS ] Installing app on the board... - [INFO ] Using known arch and jtag-device for known board nrf52dk - [INFO ] Finished in 0.975 seconds + $ ./deploy.py os --board=nrf52840_dongle + 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: Installing Tock on board nrf52840_dk + 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 11.97s + [STATUS ] Flashing binar(y|ies) to board... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [INFO ] Finished in 0.284 seconds + ``` + +1. Run our script for compiling/flashing the OpenSK application on your device + (_output may differ_): + + ```shell + $ ./deploy.py app --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: Erasing all installed applications + All apps have been erased. + info: Building OpenSK application + Compiling autocfg v1.0.0 + Compiling pkg-config v0.3.17 + Compiling cc v1.0.50 + Compiling libc v0.2.66 + Compiling bitflags v1.2.1 + Compiling foreign-types-shared v0.1.1 + Compiling openssl v0.10.28 + Compiling cfg-if v0.1.10 + Compiling lazy_static v1.4.0 + Compiling byteorder v1.3.2 + Compiling linked_list_allocator v0.6.6 + Compiling arrayref v0.3.6 + Compiling cbor v0.1.0 (./libraries/cbor) + Compiling subtle v2.2.2 + Compiling foreign-types v0.3.2 + Compiling libtock v0.1.0 (./third_party/libtock-rs) + Compiling crypto v0.1.0 (./libraries/crypto) + Compiling openssl-sys v0.9.54 + Compiling ctap2 v0.1.0 (.) + Finished release [optimized] target(s) in 15.34s + info: Flashing padding application + info: Installing Tock application ctap2 ``` 1. Connect a micro USB cable to the device USB port. @@ -202,45 +232,72 @@ the board in order to see your OpenSK device on your system.  -1. Run our script for compiling/flashing your device (_output may differ_): +1. Run our script for compiling/flashing Tock OS on your device (_output may + differ_): ```shell - $ board=nrf52840_dongle ./deploy.sh app os - make: Entering directory './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) - Compiling nrf52840_dongle v0.1.0 (./third_party/tock/boards/nordic/nrf52840_dongle) - Finished release [optimized + debuginfo] target(s) in 10.47s - text data bss dec hex filename - 110592 1688 252264 364544 59000 target/thumbv7em-none-eabi/release/nrf52840_dongle - tockloader flash --address 0x00000 --jlink --board nrf52dk target/thumbv7em-none-eabi/release/nrf52840_dongle.bin - [STATUS ] Flashing binar(y|ies) to board... - [INFO ] Using known arch and jtag-device for known board nrf52dk - [INFO ] Finished in 0.296 seconds - - make: Leaving directory './third_party/tock/boards/nordic/nrf52840_dongle' - [STATUS ] Preparing to uninstall apps... - [INFO ] Using known arch and jtag-device for known board nrf52dk - [ERROR ] No apps are installed on the board - - Compiling libtock v0.1.0 (./third_party/libtock-rs) - Compiling crypto v0.1.0 (./libraries/crypto) - Compiling ctap2 v0.1.0 (.) - Finished release [optimized] target(s) in 7.60s - [STATUS ] Flashing binar(y|ies) to board... - [INFO ] Using known arch and jtag-device for known board nrf52dk - [INFO ] Finished in 0.317 seconds - - [STATUS ] Installing app on the board... - [INFO ] Using known arch and jtag-device for known board nrf52dk - [INFO ] Finished in 0.902 seconds + $ ./deploy.py os --board=nrf52840_dongle + 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: Installing Tock on 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 + [STATUS ] Flashing binar(y|ies) to board... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [INFO ] Finished in 0.280 seconds + ``` + +1. Run our script for compiling/flashing the OpenSK application on your device + (_output may differ_): + + ```shell + $ ./deploy.py app --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: Erasing all installed applications + All apps have been erased. + info: Building OpenSK application + Compiling autocfg v1.0.0 + Compiling pkg-config v0.3.17 + Compiling cc v1.0.50 + Compiling libc v0.2.66 + Compiling bitflags v1.2.1 + Compiling foreign-types-shared v0.1.1 + Compiling openssl v0.10.28 + Compiling cfg-if v0.1.10 + Compiling lazy_static v1.4.0 + Compiling byteorder v1.3.2 + Compiling linked_list_allocator v0.6.6 + Compiling arrayref v0.3.6 + Compiling cbor v0.1.0 (./libraries/cbor) + Compiling subtle v2.2.2 + Compiling foreign-types v0.3.2 + Compiling libtock v0.1.0 (./third_party/libtock-rs) + Compiling crypto v0.1.0 (./libraries/crypto) + Compiling openssl-sys v0.9.54 + Compiling ctap2 v0.1.0 (.) + Finished release [optimized] target(s) in 15.34s + info: Flashing padding application + info: Installing Tock application ctap2 ``` 1. Remove the programming cable and the USB-A extension cable. @@ -261,5 +318,7 @@ sudo udevadm control --reload Then, you will need to unplug and replug the key for the rule to trigger. +## Testing the key + To test whether the installation was successful, visit a [demo website](https://webauthn.io/) and try to register and login. diff --git a/tools/gen_key_materials.sh b/tools/gen_key_materials.sh old mode 100644 new mode 100755 index 414626a3e5b297c645c53782c79a5feb9da649ae..f8a7bca85aacf8e16432e4d38594ed4b062bec08 --- a/tools/gen_key_materials.sh +++ b/tools/gen_key_materials.sh @@ -23,9 +23,6 @@ generate_crypto_materials () { local opensk_key=crypto_data/opensk.key local opensk_cert_name=crypto_data/opensk_cert - # Rust file that we will generate will all cryptographic data. - local rust_file=src/ctap/key_material.rs - # Allow invoker to override the command with a full path. local openssl=${OPENSSL:-$(which openssl)} @@ -36,6 +33,9 @@ generate_crypto_materials () { exit 1 fi + # Exit on first error + set -e + force_generate="$1" mkdir -p crypto_data if [ ! -f "${ca_priv_key}" ] @@ -85,3 +85,5 @@ generate_crypto_materials () { -sha256 fi } + +generate_crypto_materials "$1"