Ejemplo n.º 1
0
def gendc(
    protocol: str,
    plugin: click.Path,
    dc_file_path: str,
    config: click.File,
    elf2sb_config: click.File,
    force: bool,
) -> None:
    """Generate debug certificate (DC).

    \b
    PATH    - path to dc file
    """
    if plugin:
        # if a plugin is present simply load it
        # The SignatureProvider will automatically pick up any implementation(s)
        from importlib.util import (  # pylint: disable=import-outside-toplevel
            module_from_spec, spec_from_file_location,
        )

        spec = spec_from_file_location(name="plugin",
                                       location=plugin)  # type: ignore
        assert spec
        mod = module_from_spec(spec)
        spec.loader.exec_module(mod)  # type: ignore

    is_rsa = determine_protocol_version(protocol)
    check_destination_dir(dc_file_path, force)
    check_file_exists(dc_file_path, force)

    logger.info("Loading configuration from yml file...")
    yaml_content = load_configuration(config.name)
    if elf2sb_config:
        logger.info("Loading configuration from elf2sb config file...")
        rot_info = RootOfTrustInfo(load_configuration(
            elf2sb_config.name))  # type: ignore
        yaml_content["rot_meta"] = rot_info.public_keys
        yaml_content["rotk"] = rot_info.private_key
        yaml_content["rot_id"] = rot_info.public_key_index

    # enforcing rot_id presence in yaml config...
    assert "rot_id" in yaml_content, "Config file doesn't contain the 'rot_id' field"

    logger.info(
        f"Creating {'RSA' if is_rsa else 'ECC'} debug credential object...")
    dc = DebugCredential.create_from_yaml_config(version=protocol,
                                                 yaml_config=yaml_content)
    dc.sign()
    data = dc.export()
    logger.info("Saving the debug credential to a file...")
    with open(dc_file_path, "wb") as f:
        f.write(data)
    print_output(True, "Creating Debug credential file")
Ejemplo n.º 2
0
def test_invalid_image_base_address(data_dir):
    mbi = Mbi_PlainXip()
    with pytest.raises(SPSDKError):
        mbi.load_from_config(
            load_configuration(
                os.path.join(data_dir, "lpc55s6x_int_xip_plain.yml")))
    # test bad alignment
    mbi.app_ext_memory_align = 31
    with pytest.raises(SPSDKError):
        mbi.load_from_config(
            load_configuration(
                os.path.join(data_dir, "lpc55s6x_int_xip_plain.yml")))
Ejemplo n.º 3
0
 def _load_preset_file(self, preset_file: str, family: str) -> None:
     try:
         tz_config = load_configuration(preset_file)
         self.tz = TrustZone.from_config(tz_config)
     except SPSDKError:
         tz_bin = load_binary(preset_file)
         self.tz = TrustZone.from_binary(family=family, raw_data=tz_bin)
Ejemplo n.º 4
0
def generate(config: TextIO, output: BinaryIO, encoding: str,
             force: bool) -> None:
    """Generate certificate."""
    logger.info("Generating Certificate...")
    logger.info("Loading configuration from yml file...")

    check_destination_dir(output.name, force)
    check_file_exists(output.name, force)

    config_data = load_configuration(config.name)
    cert_config = CertificateParametersConfig(config_data)

    priv_key = load_private_key(cert_config.issuer_private_key)
    pub_key = load_public_key(cert_config.subject_public_key)

    certificate = generate_certificate(
        subject=cert_config.subject_name,
        issuer=cert_config.issuer_name,
        subject_public_key=pub_key,
        issuer_private_key=priv_key,
        serial_number=cert_config.serial_number,
        duration=cert_config.duration,
        if_ca=cert_config.BasicConstrains_ca,
        path_length=cert_config.BasicConstrains_path_length,
    )
    logger.info("Saving the generated certificate to the specified path...")
    encoding_type = Encoding.PEM if encoding.lower() == "pem" else Encoding.DER
    save_crypto_item(certificate, output.name, encoding_type=encoding_type)
    logger.info("Certificate generated successfully...")
    click.echo(
        f"The certificate file has been created: {os.path.abspath(output.name)}"
    )
Ejemplo n.º 5
0
def generate_trustzone_binary(tzm_conf: click.File) -> None:
    """Generate TrustZone binary from json configuration file."""
    config_data = load_configuration(tzm_conf.name)
    check_config(config_data, TrustZone.get_validation_schemas())
    trustzone = TrustZone.from_config(config_data)
    tz_data = trustzone.export()
    output_file = config_data["tzpOutputFile"]
    write_file(tz_data, output_file, mode="wb")
    click.echo(f"Success. (Trustzone binary: {output_file} created.)")
Ejemplo n.º 6
0
def load_rules(
        family: str,
        additional_rules_file: click.Path = None) -> List[Dict[str, str]]:
    """The function loads the rules for family and optionally add additional rules from user.

    :param family: Chip family
    :param additional_rules_file: Additional rules file, defaults to None
    :return: Loaded rules in list of dictionaries.
    """
    rules: List[Dict[str, str]] = []
    database = load_configuration(DATABASE_FILE)
    assert family in database.keys()
    rules_files = database[family]["rules"]
    for rules_file in rules_files:
        rules.extend(
            load_configuration(os.path.join(PFRC_DATA_FOLDER, rules_file)))

    if additional_rules_file:
        rules.extend(load_configuration(additional_rules_file))

    return rules
Ejemplo n.º 7
0
    def set_config(self, config: Union[str, CM, dict]) -> None:
        """Apply configuration from file.

        :param config: Name of configuration file or Commented map.
        :raises SPSDKPfrConfigReadError: The configuration file cannot be loaded.
        """
        if isinstance(config, (CM, dict)):
            self.set_config_dict(config)
        else:
            try:
                data = load_configuration(config)
            except SPSDKError as exc:
                raise SPSDKPfrConfigReadError(str(exc)) from exc
            self.set_config_dict(data)
Ejemplo n.º 8
0
    def __init__(
        self,
        mboot: McuBoot,
        user_pck: bytes,
        oem_share_input: bytes,
        info_print: Callable,
        container_conf: str = None,
        workspace: str = None,
    ) -> None:
        """Initialization of device HSM class. Its design to create provisioned SB3 file.

        :param mboot: mBoot communication interface.
        :param oem_share_input: OEM share input data.
        :param user_pck: USER PCK key.
        :param container_conf: Optional elftosb configuration file (to specify user list of SB commands).
        :param workspace: Optional folder to store middle results.
        :raises SPSDKError: In case of any vulnerability.
        """
        self.mboot = mboot
        self.user_pck = user_pck
        self.oem_share_input = oem_share_input
        self.info_print = info_print
        self.workspace = workspace
        if self.workspace and not os.path.isdir(self.workspace):
            os.mkdir(self.workspace)

        # store input of OEM_SHARE_INPUT to workspace in case that is generated randomly
        self.store_temp_res("OEM_SHARE_INPUT.BIN", self.oem_share_input)

        # Default value that could be given from SB3 configuration container
        self.timestamp = None
        self.sb3_descr = "SB3 SB_KEK"
        self.sb3_fw_ver = 0

        # Check the configuration file and options to update by user config
        self.config_data = None
        if container_conf:
            config_data = load_configuration(container_conf)
            # validate input configration
            check_config(config_data, DeviceHsm.get_validation_schemas())
            self.sb3_fw_ver = config_data.get("firmwareVersion") or self.sb3_fw_ver
            self.sb3_descr = config_data.get("description") or self.sb3_descr
            if "timestamp" in config_data:
                self.timestamp = value_to_int(str(config_data.get("timestamp")))

        self.wrapped_user_pck = bytes()
        self.final_sb = bytes()
Ejemplo n.º 9
0
def generate_master_boot_image(image_conf: click.File) -> None:
    """Generate MasterBootImage from json configuration file.

    :param image_conf: master boot image json configuration file.
    """
    config_data = load_configuration(image_conf.name)
    mbi_cls = get_mbi_class(config_data)
    check_config(config_data, mbi_cls.get_validation_schemas())
    mbi = mbi_cls()
    mbi.load_from_config(config_data)
    mbi_data = mbi.export()

    mbi_output_file_path = config_data["masterBootOutputFile"]
    write_file(mbi_data, mbi_output_file_path, mode="wb")

    click.echo(
        f"Success. (Master Boot Image: {mbi_output_file_path} created.)")
Ejemplo n.º 10
0
def generate_secure_binary_31(container_conf: click.File) -> None:
    """Geneate SecureBinary image from json configuration file.

    :param container_conf: configuration file
    :raises SPSDKError: Raised when there is no signing key
    """
    config_data = load_configuration(container_conf.name)
    schemas = SecureBinary31.get_validation_schemas(
        include_test_configuration=True)
    schemas.append(
        ValidationSchemas.get_schema_file(SB3_SCH_FILE)["sb3_output"])
    check_config(config_data, schemas)
    sb3 = SecureBinary31.load_from_config(config_data)
    sb3_data = sb3.export()

    sb3_output_file_path = config_data["containerOutputFile"]
    write_file(sb3_data, sb3_output_file_path, mode="wb")

    click.echo(
        f"Success. (Secure binary 3.1: {sb3_output_file_path} created.)")
Ejemplo n.º 11
0
    def get_validation_schemas(
            cls,
            family: str,
            revision: str = "latest") -> List[Dict[str, Any]]:
        """Create the validation schema.

        :param family: Family description.
        :param revision: Chip revision specification, as default, latest is used.
        :raises SPSDKError: Family or revision is not supported.
        :return: List of validation schemas.
        """
        config_file = cls.load_config_file()
        sch_cfg = ValidationSchemas.get_schema_file(TZ_SCH_FILE)
        preset_properties = {}

        try:
            real_rev = config_file[family][revision]

            presets = load_configuration(
                os.path.join(TrustZone.PRESET_DIR,
                             config_file[family]["revisions"][real_rev]))
            for key, value in presets.items():
                preset_properties[key] = {
                    "type": ["string", "number"],
                    "title": "TZ Preset",
                    "description": f"Preset for {key}",
                    "format": "number",
                    "template_value": f"{value}",
                }
            sch_cfg["tz"]["properties"]["trustZonePreset"].pop(
                "patternProperties")
            sch_cfg["tz"]["properties"]["trustZonePreset"][
                "properties"] = preset_properties

            return [sch_cfg["tz_family_rev"], sch_cfg["tz"]]
        except (KeyError, SPSDKError) as exc:
            raise SPSDKError(
                f"Family {family} or {revision} is not supported") from exc
Ejemplo n.º 12
0
    def generate_config_template(cls, family: str) -> Dict[str, str]:
        """Generate configuration for selected family.

        :param family: Family description.
        :return: Dictionary of individual templates (key is name of template, value is template itself).
        """
        ret: Dict[str, str] = {}

        config_file = cls.load_config_file()
        schemas = cls.get_validation_schemas()
        override = {}
        override["family"] = family
        override["revisions"] = config_file[family]["latest"]
        preset_properties = {}

        presets = load_configuration(
            os.path.join(
                TrustZone.PRESET_DIR,
                config_file[family]["revisions"][override["revisions"]]))
        for key, value in presets.items():
            preset_properties[key] = {
                "type": ["string", "number"],
                "title": "TZ Preset",
                "description": f"Preset for {key}",
                "format": "number",
                "template_value": f"{value}",
            }
        schemas[0]["properties"]["trustZonePreset"][
            "properties"] = preset_properties

        yaml_data = ConfigTemplate(
            f"Trust Zone Configuration template for {family}.",
            schemas,
            override,
        ).export_to_yaml()
        ret[f"{family}_tz"] = yaml_data

        return ret
Ejemplo n.º 13
0
def generate_binary(
    output: click.Path,
    user_config_file: click.Path,
    add_seal: bool,
    calc_inverse: bool,
    elf2sb_config: click.File,
    secret_file: Tuple[str],
    password: str,
) -> None:
    """Generate binary data."""
    pfr_config = pfr.PfrConfiguration(str(user_config_file))
    invalid_reason = pfr_config.is_invalid()
    if invalid_reason:
        raise SPSDKPfrConfigError(
            f"The configuration file is not valid. The reason is: {invalid_reason}"
        )
    assert pfr_config.type
    root_of_trust = None
    keys = None
    if elf2sb_config:
        public_keys = RootOfTrustInfo(load_configuration(
            elf2sb_config.name)).public_keys  # type: ignore
        root_of_trust = tuple(public_keys)
    if secret_file:
        root_of_trust = secret_file
    area = pfr_config.type
    if area.lower() == "cmpa" and root_of_trust:
        keys = extract_public_keys(root_of_trust, password)
    pfr_obj = _get_pfr_class(area)(device=pfr_config.device,
                                   revision=pfr_config.revision)
    if not pfr_config.revision:
        pfr_config.revision = pfr_obj.revision
    pfr_obj.set_config(pfr_config, raw=not calc_inverse)

    data = pfr_obj.export(add_seal=add_seal, keys=keys)
    _store_output(data, output, "wb")
Ejemplo n.º 14
0
import logging
import os
import sys
from typing import Dict, List

import click

from spsdk import __version__ as spsdk_version
from spsdk.apps.utils import catch_spsdk_error, load_configuration
from spsdk.pfr import PFR_DATA_FOLDER, Processor, Translator
from spsdk.pfr.pfr import PfrConfiguration

PFRC_DATA_FOLDER = os.path.join(PFR_DATA_FOLDER, "pfrc")
DATABASE_FILE = os.path.join(PFRC_DATA_FOLDER, "database.yaml")

SUPPORTED_FAMILIES = list(load_configuration(DATABASE_FILE).keys())


def load_rules(
        family: str,
        additional_rules_file: click.Path = None) -> List[Dict[str, str]]:
    """The function loads the rules for family and optionally add additional rules from user.

    :param family: Chip family
    :param additional_rules_file: Additional rules file, defaults to None
    :return: Loaded rules in list of dictionaries.
    """
    rules: List[Dict[str, str]] = []
    database = load_configuration(DATABASE_FILE)
    assert family in database.keys()
    rules_files = database[family]["rules"]
Ejemplo n.º 15
0
def test_load_configuration(data_dir, file_name):
    with use_working_directory(data_dir):
        result = load_configuration(file_name)
        assert isinstance(result, dict)
Ejemplo n.º 16
0
def test_load_configuration_invalid_file(data_dir, file_name):
    with use_working_directory(data_dir):
        with pytest.raises(SPSDKError):
            load_configuration(file_name)