allows silent certificate checks (#410)
This commit is contained in:
76
deploy.py
76
deploy.py
@@ -26,6 +26,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
from typing import Dict, List, Tuple
|
from typing import Dict, List, Tuple
|
||||||
|
|
||||||
import colorama
|
import colorama
|
||||||
@@ -36,6 +37,7 @@ from tockloader import tbfh
|
|||||||
from tockloader import tockloader as loader
|
from tockloader import tockloader as loader
|
||||||
from tockloader.exceptions import TockLoaderException
|
from tockloader.exceptions import TockLoaderException
|
||||||
|
|
||||||
|
import tools.configure
|
||||||
from tools.deploy_partition import create_metadata, pad_to
|
from tools.deploy_partition import create_metadata, pad_to
|
||||||
|
|
||||||
PROGRAMMERS = frozenset(("jlink", "openocd", "pyocd", "nordicdfu", "none"))
|
PROGRAMMERS = frozenset(("jlink", "openocd", "pyocd", "nordicdfu", "none"))
|
||||||
@@ -706,6 +708,19 @@ class OpenSKInstaller:
|
|||||||
if self.args.programmer == "none":
|
if self.args.programmer == "none":
|
||||||
assert_python_library("intelhex")
|
assert_python_library("intelhex")
|
||||||
|
|
||||||
|
def configure_device(self):
|
||||||
|
"""Checks the device configuration, and sets it according to args."""
|
||||||
|
configure_response = tools.configure.main(
|
||||||
|
argparse.Namespace(
|
||||||
|
batch=False,
|
||||||
|
certificate=self.args.config_cert,
|
||||||
|
priv_key=self.args.config_pkey,
|
||||||
|
lock=self.args.lock_device,
|
||||||
|
))
|
||||||
|
if not configure_response:
|
||||||
|
return None
|
||||||
|
return configure_response[0]
|
||||||
|
|
||||||
def run(self) -> int:
|
def run(self) -> int:
|
||||||
"""Reads args to decide and run all required tasks."""
|
"""Reads args to decide and run all required tasks."""
|
||||||
self.check_prerequisites()
|
self.check_prerequisites()
|
||||||
@@ -746,17 +761,13 @@ class OpenSKInstaller:
|
|||||||
self.install_padding()
|
self.install_padding()
|
||||||
self.install_tab_file(f"target/tab/{self.args.application}.tab")
|
self.install_tab_file(f"target/tab/{self.args.application}.tab")
|
||||||
self.install_metadata()
|
self.install_metadata()
|
||||||
if self.verify_flashed_app(self.args.application):
|
if not self.verify_flashed_app(self.args.application):
|
||||||
info("You're all set!")
|
error(("It seems that something went wrong. App/example not found "
|
||||||
return 0
|
"on your board. Ensure the connections between the programmer "
|
||||||
error(
|
"and the board are correct."))
|
||||||
("It seems that something went wrong. App/example not found "
|
|
||||||
"on your board. Ensure the connections between the programmer and "
|
|
||||||
"the board are correct."))
|
|
||||||
return 1
|
return 1
|
||||||
return 0
|
|
||||||
|
|
||||||
if self.args.programmer in ("pyocd", "nordicdfu", "none"):
|
elif self.args.programmer in ("pyocd", "nordicdfu", "none"):
|
||||||
dest_file = f"target/{self.args.board}_merged.hex"
|
dest_file = f"target/{self.args.board}_merged.hex"
|
||||||
os.makedirs("target", exist_ok=True)
|
os.makedirs("target", exist_ok=True)
|
||||||
self.create_hex_file(dest_file)
|
self.create_hex_file(dest_file)
|
||||||
@@ -793,7 +804,7 @@ class OpenSKInstaller:
|
|||||||
fatal("Multiple DFU devices are detected. Please only connect one.")
|
fatal("Multiple DFU devices are detected. Please only connect one.")
|
||||||
# Run the command without capturing stdout so that we show progress
|
# Run the command without capturing stdout so that we show progress
|
||||||
info("Flashing device using DFU...")
|
info("Flashing device using DFU...")
|
||||||
return subprocess.run(
|
dfu_return_code = subprocess.run(
|
||||||
[
|
[
|
||||||
"nrfutil", "dfu", "usb-serial", f"--package={dfu_pkg_file}",
|
"nrfutil", "dfu", "usb-serial", f"--package={dfu_pkg_file}",
|
||||||
f"--serial-number={serial_number[0]}"
|
f"--serial-number={serial_number[0]}"
|
||||||
@@ -801,22 +812,49 @@ class OpenSKInstaller:
|
|||||||
check=False,
|
check=False,
|
||||||
timeout=None,
|
timeout=None,
|
||||||
).returncode
|
).returncode
|
||||||
|
if dfu_return_code != 0:
|
||||||
|
return dfu_return_code
|
||||||
|
|
||||||
# Configure OpenSK through vendor specific command if needed
|
# Configure OpenSK through vendor specific command if needed
|
||||||
|
if self.args.programmer == "none":
|
||||||
if any([
|
if any([
|
||||||
self.args.lock_device,
|
self.args.lock_device,
|
||||||
self.args.config_cert,
|
self.args.config_cert,
|
||||||
self.args.config_pkey,
|
self.args.config_pkey,
|
||||||
]):
|
]):
|
||||||
# pylint: disable=g-import-not-at-top,import-outside-toplevel
|
fatal("Unexpected arguments to configure your device. Since you "
|
||||||
import tools.configure
|
"selected the programmer \"none\", the device is not ready to be "
|
||||||
tools.configure.main(
|
"configured yet.")
|
||||||
argparse.Namespace(
|
return 0
|
||||||
batch=False,
|
|
||||||
certificate=self.args.config_cert,
|
# Perform checks if OpenSK was flashed.
|
||||||
priv_key=self.args.config_pkey,
|
if self.args.application != "ctap2":
|
||||||
lock=self.args.lock_device,
|
return 0
|
||||||
))
|
|
||||||
|
# Trying to check or configure the device. Booting might take some time.
|
||||||
|
for i in range(5):
|
||||||
|
# Increasing wait time, total of 10 seconds.
|
||||||
|
time.sleep(i)
|
||||||
|
devices = tools.configure.get_opensk_devices(False)
|
||||||
|
if devices:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not devices:
|
||||||
|
fatal("No device to configure found.")
|
||||||
|
status = self.configure_device()
|
||||||
|
if not status:
|
||||||
|
fatal("Could not read device configuration.")
|
||||||
|
|
||||||
|
if status["cert"] and status["pkey"]:
|
||||||
|
info("You're all set!")
|
||||||
|
else:
|
||||||
|
info("Your device is not yet configured, and lacks some functionality. "
|
||||||
|
"If you run into issues, this command might help:\n\n"
|
||||||
|
"./tools/configure.py \\\n"
|
||||||
|
" --certificate=crypto_data/opensk_cert.pem \\\n"
|
||||||
|
" --private-key=crypto_data/opensk.key\n\n"
|
||||||
|
"Please read the Certificate considerations in docs/customization.md"
|
||||||
|
" to understand the privacy trade-off.")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1192,7 +1192,9 @@ where
|
|||||||
params: AuthenticatorVendorConfigureParameters,
|
params: AuthenticatorVendorConfigureParameters,
|
||||||
cid: ChannelID,
|
cid: ChannelID,
|
||||||
) -> Result<ResponseData, Ctap2StatusCode> {
|
) -> Result<ResponseData, Ctap2StatusCode> {
|
||||||
|
if params.attestation_material.is_some() || params.lockdown {
|
||||||
(self.check_user_presence)(cid)?;
|
(self.check_user_presence)(cid)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
let current_priv_key = self.persistent_store.attestation_private_key()?;
|
let current_priv_key = self.persistent_store.attestation_private_key()?;
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ def main(args):
|
|||||||
}
|
}
|
||||||
|
|
||||||
devices = get_opensk_devices(args.batch)
|
devices = get_opensk_devices(args.batch)
|
||||||
|
responses = []
|
||||||
if not devices:
|
if not devices:
|
||||||
fatal("No devices found.")
|
fatal("No devices found.")
|
||||||
for authenticator in tqdm(devices):
|
for authenticator in tqdm(devices):
|
||||||
@@ -134,12 +135,15 @@ def main(args):
|
|||||||
authenticator.device.wink()
|
authenticator.device.wink()
|
||||||
aaguid = uuid.UUID(bytes=authenticator.get_info().aaguid)
|
aaguid = uuid.UUID(bytes=authenticator.get_info().aaguid)
|
||||||
info(f"Programming OpenSK device AAGUID {aaguid} ({authenticator.device}).")
|
info(f"Programming OpenSK device AAGUID {aaguid} ({authenticator.device}).")
|
||||||
|
if args.lock or args.priv_key:
|
||||||
info("Please touch the device to confirm...")
|
info("Please touch the device to confirm...")
|
||||||
try:
|
try:
|
||||||
result = authenticator.send_cbor(
|
result = authenticator.send_cbor(
|
||||||
OPENSK_VENDOR_CONFIGURE,
|
OPENSK_VENDOR_CONFIGURE,
|
||||||
data=cbor_data,
|
data=cbor_data,
|
||||||
)
|
)
|
||||||
|
status = {"cert": result[1], "pkey": result[2]}
|
||||||
|
responses.append(status)
|
||||||
info(f"Certificate: {'Present' if result[1] else 'Missing'}")
|
info(f"Certificate: {'Present' if result[1] else 'Missing'}")
|
||||||
info(f"Private Key: {'Present' if result[2] else 'Missing'}")
|
info(f"Private Key: {'Present' if result[2] else 'Missing'}")
|
||||||
if args.lock:
|
if args.lock:
|
||||||
@@ -156,6 +160,7 @@ def main(args):
|
|||||||
"the given cert/key don't match the ones currently programmed)."))
|
"the given cert/key don't match the ones currently programmed)."))
|
||||||
else:
|
else:
|
||||||
error(f"Failed to configure OpenSK (unknown error: {ex}")
|
error(f"Failed to configure OpenSK (unknown error: {ex}")
|
||||||
|
return responses
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user