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")
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")))
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)
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)}" )
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.)")
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
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)
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()
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.)")
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.)")
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
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
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")
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"]
def test_load_configuration(data_dir, file_name): with use_working_directory(data_dir): result = load_configuration(file_name) assert isinstance(result, dict)
def test_load_configuration_invalid_file(data_dir, file_name): with use_working_directory(data_dir): with pytest.raises(SPSDKError): load_configuration(file_name)