def get_mbi_class(config: Dict[str, Any]) -> Type["MasterBootImage"]: """Get Master Boot Image class. :raises SPSDKUnsupportedImageType: The invalid configuration. :return: MBI Class. """ schema_cfg = ValidationSchemas.get_schema_file(MBIMG_SCH_FILE) with open(DEVICE_FILE) as f: device_cfg = YAML(typ="safe").load(f) # Validate needed configuration to recognize MBI class check_config(config, [schema_cfg["image_type"], schema_cfg["family"]]) try: target = get_key_by_val(config["outputImageExecutionTarget"], device_cfg["map_tables"]["targets"]) authentication = get_key_by_val( config["outputImageAuthenticationType"], device_cfg["map_tables"]["authentication"]) family = config["family"] cls_name = device_cfg["devices"][family]["images"][target][ authentication] except (KeyError, SPSDKValueError) as exc: raise SPSDKUnsupportedImageType( "The type of requested Master boot image is not supported for that device." ) from exc return globals()[cls_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 test_schema_invalid_validator(): """Basic test of scheme validator.""" schema = { "type": "object", "properties": { "n1": {"type": "invalid_type"}, }, } with pytest.raises(SPSDKError): check_config({}, [schema])
def test_schema_validator_required(test_vector, result): """Basic test of scheme validator.""" schema = { "type": "object", "properties": { "n1": {"type": ["number", "string"], "format": "number"}, "n2": {"type": "string"}, }, "required": ["n1"], } if result: check_config(test_vector, [schema]) else: with pytest.raises(SPSDKError): check_config(test_vector, [schema])
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 __init__(self, data: dict) -> None: """Create object out of data loaded from elf2sb configuration file.""" # Validate input sch_cfg = ValidationSchemas.get_schema_file(MBIMG_SCH_FILE) sch_crypto_cfg = ValidationSchemas.get_schema_file(CRYPTO_SCH_FILE) val_schemas = [ sch_cfg[x] for x in ["cert_prv_key", "signing_root_prv_key"] ] val_schemas.extend([ sch_crypto_cfg[x] for x in ["certificate_v2_chain_id", "certificate_root_keys"] ]) check_config(data, val_schemas) self.config_data = data self.private_key = data.get("mainCertPrivateKeyFile") or data.get( "mainRootCertPrivateKeyFile") if not self.private_key: raise SPSDKError( "Private key not specified (mainCertPrivateKeyFile or mainRootCertPrivateKeyFile)" ) public_keys: List[Optional[str]] = [ data.get(f"rootCertificate{idx}File") for idx in range(4) ] # filter out None and empty values self.public_keys = list(filter(None, public_keys)) for org, filtered in zip(public_keys, self.public_keys): if org != filtered: raise SPSDKError( "There are gaps in rootCertificateXFile definition") # look for keyID; can't use "or" because 0 is a valid number although it's a "falsy" value data_main_cert_index = data.get("mainCertChainId") if data_main_cert_index is None: data_main_cert_index = data.get("mainRootCertId") if data_main_cert_index is None: raise SPSDKError( "Main Cert ID not specified (mainCertChainId or mainRootCertId)" ) root_cert_file = data.get(f"rootCertificate{data_main_cert_index}File") if not root_cert_file: raise SPSDKError( f"rootCertificate{data_main_cert_index}File doesn't exist") self.public_key_index = self.public_keys.index(root_cert_file)
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 test_schema_validator(tmpdir, test_vector, result): """Basic test of scheme validator.""" schema = { "type": "object", "properties": { "n1": { "type": ["number", "string"], "format": "number" }, "s1": { "type": "string" }, "f1": { "type": "string", "format": "file" }, "f2": { "type": "string", "format": "optional_file" }, "d1": { "type": "string", "format": "dir" }, }, } # Create temporary test file with open(os.path.join(tmpdir, "testfile.bin"), "wb") as f: f.write(bytes(16)) os.mkdir(os.path.join(tmpdir, "testdir")) with use_working_directory(tmpdir): if result: check_config(test_vector, [schema]) else: with pytest.raises(SPSDKError): check_config(test_vector, [schema])