Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get rid of libusbio #523

Closed
wants to merge 14 commits into from
Closed
2 changes: 1 addition & 1 deletion pynitrokey/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def nitropy():
"ecdsa",
"fido2",
"pyusb",
"spsdk",
# "spsdk",
]
for x in pymodules:
logger.info(f"{x} version: {package_version(x)}")
Expand Down
2 changes: 1 addition & 1 deletion pynitrokey/cli/fido2.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ def version(serial: Optional[str], udp: bool) -> None:
locked = ""
# @todo:
if len(res) > 3:
if res[3]: # type: ignore
if res[3]:
locked = "locked"
else:
locked = "unlocked"
Expand Down
4 changes: 2 additions & 2 deletions pynitrokey/nk3/updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
from io import BytesIO
from typing import Any, Callable, Iterator, List, Optional

from spsdk.mboot.exceptions import McuBootConnectionError

import pynitrokey
from pynitrokey.helpers import Retries
from pynitrokey.nk3 import NK3_DATA
Expand All @@ -35,6 +33,8 @@
from pynitrokey.trussed.utils import Version
from pynitrokey.updates import Asset, Release

from ..trussed.bootloader.lpc55_upload.mboot.exceptions import McuBootConnectionError

logger = logging.getLogger(__name__)


Expand Down
28 changes: 17 additions & 11 deletions pynitrokey/trussed/bootloader/lpc55.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@
import sys
from typing import List, Optional, Tuple, TypeVar

from spsdk.mboot.error_codes import StatusCode
from spsdk.mboot.interfaces.usb import MbootUSBInterface
from spsdk.mboot.mcuboot import McuBoot
from spsdk.mboot.properties import PropertyTag
from spsdk.sbfile.sb2.images import BootImageV21
from spsdk.utils.interfaces.device.usb_device import UsbDevice
from spsdk.utils.usbfilter import USBDeviceFilter

from pynitrokey.trussed.utils import Uuid, Version

from . import FirmwareMetadata, NitrokeyTrussedBootloader, ProgressCallback, Variant
from .lpc55_upload.mboot.error_codes import StatusCode
from .lpc55_upload.mboot.interfaces.usb import MbootUSBInterface
from .lpc55_upload.mboot.mcuboot import McuBoot
from .lpc55_upload.mboot.properties import PropertyTag
from .lpc55_upload.sbfile.misc import BcdVersion3
from .lpc55_upload.sbfile.sb2.images import BootImageV21
from .lpc55_upload.utils.interfaces.device.usb_device import UsbDevice
from .lpc55_upload.utils.usbfilter import USBDeviceFilter

RKTH = bytes.fromhex("050aad3e77791a81e59c5b2ba5a158937e9460ee325d8ccba09734b8fdebb171")
KEK = bytes([0xAA] * 32)
Expand Down Expand Up @@ -58,8 +58,10 @@ def path(self) -> str:
return self._path

@property
def status(self) -> str:
return self.device.status_string
def status(self) -> Tuple[int, str]:
code = self.device.status_code
message = StatusCode.get_label(code)
return (code, message)

def close(self) -> None:
self.device.close()
Expand Down Expand Up @@ -136,9 +138,13 @@ def open(cls: type[T], path: str) -> Optional[T]:
return None


def parse_bcd_version(version: BcdVersion3) -> Version:
return Version(major=version.major, minor=version.minor, patch=version.service)


def parse_firmware_image(data: bytes) -> FirmwareMetadata:
image = BootImageV21.parse(data, kek=KEK)
version = Version.from_bcd_version(image.header.product_version)
version = parse_bcd_version(image.header.product_version)
metadata = FirmwareMetadata(version=version)
if image.cert_block:
if image.cert_block.rkth == RKTH:
Expand Down
6 changes: 6 additions & 0 deletions pynitrokey/trussed/bootloader/lpc55_upload/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# LPC55 Bootloader Firmware Upload Module

Anything inside this directory is originally extracted from: https://github.com/nxp-mcuxpresso/spsdk/tree/master.
In detail anything that is needed to upload a signed firmware image to a Nitrokey 3 xN with an LPC55 MCU.


42 changes: 42 additions & 0 deletions pynitrokey/trussed/bootloader/lpc55_upload/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# Copyright 2019-2024 NXP
#
# SPDX-License-Identifier: BSD-3-Clause


version = "2.1.0"

import os

__author__ = "NXP"
__license__ = "BSD-3-Clause"
__version__ = version
__release__ = "beta"

# The SPSDK behavior settings
# SPSDK_DATA_FOLDER might be redefined by SPSDK_DATA_FOLDER_{version}
# or SPSDK_DATA_FOLDER env variable
SPSDK_DATA_FOLDER_ENV_VERSION = "SPSDK_DATA_FOLDER_" + version.replace(".", "_")
SPSDK_DATA_FOLDER = (
os.environ.get(SPSDK_DATA_FOLDER_ENV_VERSION)
or os.environ.get("SPSDK_DATA_FOLDER")
or os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")
)
SPSDK_DATA_FOLDER_COMMON = os.path.join(SPSDK_DATA_FOLDER, "common")
SPSDK_DATA_FOLDER_SCHEMAS = os.path.join(SPSDK_DATA_FOLDER, "jsonschemas")

# SPSDK_CACHE_DISABLED might be redefined by SPSDK_CACHE_DISABLED_{version} env variable, default is False
SPSDK_ENV_CACHE_DISABLED = "SPSDK_CACHE_DISABLED_" + version.replace(".", "_")
SPSDK_CACHE_DISABLED = bool(
os.environ.get(SPSDK_ENV_CACHE_DISABLED)
or os.environ.get("SPSDK_CACHE_DISABLED")
or False
)

SPSDK_YML_INDENT = 2


ROOT_DIR = os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))
SPSDK_EXAMPLES_FOLDER = os.path.relpath(os.path.join(ROOT_DIR, "examples"))
42 changes: 42 additions & 0 deletions pynitrokey/trussed/bootloader/lpc55_upload/apps/utils/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# Copyright 2020-2024 NXP
#
# SPDX-License-Identifier: BSD-3-Clause

import os
from typing import Dict

from ...utils.misc import get_abs_path, write_file


def filepath_from_config(
config: Dict,
key: str,
default_value: str,
base_dir: str,
output_folder: str = "",
file_extension: str = ".bin",
) -> str:
"""Get file path from configuration dictionary and append .bin if the value is not blank.

Function returns the output_folder + filename if the filename does not contain path.
In case filename contains path, return filename and append ".bin".
The empty string "" indicates that the user doesn't want the output.
:param config: Configuration dictionary
:param key: Name of the key
:param default_value: default value in case key value is not present
:param base_dir: base directory for path expansion
:param output_folder: Output folder, if blank file path from config will be used
:param file_extension: File extension that will be appended
:return: filename with appended ".bin" or blank filename ""
"""
filename = config.get(key, default_value)
if filename == "":
return filename
if not os.path.dirname(filename):
filename = os.path.join(output_folder, filename)
if not filename.endswith(file_extension):
filename += file_extension
return get_abs_path(filename, base_dir)
7 changes: 7 additions & 0 deletions pynitrokey/trussed/bootloader/lpc55_upload/crypto/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# Copyright 2020-2024 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
"""Module for crypto operations (certificate and key management)."""
Loading
Loading