def test_sb_unsigned_otp(data_dir: str, subdir: str, image_name: str) -> None: """Test creation of SB file for RT5xx with unsigned image. SBKEK Key for SB file is stored in KEYSTORE. :param data_dir: absolute path of the directory with data files for the test :param image_name: file name of the unsigned image WITHOUT file extension """ write_shadow_regs(data_dir, [ (0x40130194, 0x00000000), # BOOT_CFG[5]: USE_OTP = 0 # MASTER KEY - 000102030405060708090a0b0c0d0e0f00112233445566778899aabbccddeeff (0x401301C0, 0xccddeeff), (0x401301C4, 0x8899aabb), (0x401301C8, 0x44556677), (0x401301CC, 0x00112233), (0x401301D0, 0x0c0d0e0f), (0x401301D4, 0x08090a0b), (0x401301D8, 0x04050607), (0x401301DC, 0x00010203), ]) sbkek = KeyStore.derive_sb_kek_key(bytes.fromhex(MASTER_KEY)) adv_params = SBV2xAdvancedParams(dek=b'\xA0' * 32, mac=b'\x0B' * 32, nonce=bytes(16), timestamp=datetime(2020, month=1, day=31)) # create SB file boot image boot_image = BootImageV21( kek=sbkek, product_version='1.0.0', component_version='1.0.0', build_number=1, # parameters fixed for test only (to have always same output), do not use in production advanced_params=adv_params) # certificate + private key cert_block, priv_key_pem_data = create_cert_block(data_dir) boot_image.cert_block = cert_block boot_image.private_key_pem_data = priv_key_pem_data fcb_data = load_binary(data_dir, FCB_FILE_NAME) plain_image_data = load_binary(data_dir, subdir, image_name + '.bin') # images are aligned for test purposes only, otherwise export will align with random data fcb_data = align_block(fcb_data, 16) plain_image_data = align_block(plain_image_data, 16) # create boot section 0 boot_section = BootSectionV2( 0, CmdFill(address=0x10C000, pattern=bytes.fromhex('063040C0')), CmdMemEnable(0x10C000, 4, ExtMemId.FLEX_SPI_NOR), CmdErase(address=0x8000000, length=0x00800), CmdErase(address=0x8001000, length=0x10000), CmdLoad(address=0x8000400, data=fcb_data), CmdLoad(address=0x8001000, data=plain_image_data)) boot_image.add_boot_section(boot_section) dbg_info = list() # debug log for analysis of the binary output content sb_file = boot_image.export(padding=bytes(8), dbg_info=dbg_info) # padding for unit test only, to avoid random data write_dbg_log(data_dir, image_name + '_otp.sb', dbg_info, TEST_IMG_CONTENT) write_sb(data_dir, image_name + '_otp.sb', sb_file, KeyStore(KeySourceType.OTP))
def test_sb_unsigned_keystore(data_dir: str, subdir: str, image_name: str) -> None: """Test creation of SB file for RT5xx with unsigned image. SBKEK Key for SB file is stored in KEYSTORE. :param data_dir: absolute path of the directory with data files for the test :param image_name: file name of the unsigned image WITHOUT file extension """ if not TEST_IMG_CONTENT: write_shadow_regs( data_dir, [(0x40130194, 0x00000080)]) # BOOT_CFG[5]: USE_PUF = 1 with open(os.path.join(data_dir, KEYSTORE_SUBDIR, 'SBkek_PUF.txt'), 'r') as f: sbkek_str = f.readline() adv_params = SBV2xAdvancedParams(dek=b'\xA0' * 32, mac=b'\x0B' * 32, nonce=bytes(16), timestamp=datetime(2020, month=1, day=31)) # create boot image boot_image = BootImageV21( kek=bytes.fromhex(sbkek_str), product_version='1.0.0', component_version='1.0.0', build_number=1, # parameters fixed for test only (to have always same output), do not use in production advanced_params=adv_params) # certificate + private key cert_block, priv_key_pem_data = create_cert_block(data_dir) boot_image.cert_block = cert_block boot_image.private_key_pem_data = priv_key_pem_data fcb_data = load_binary(data_dir, FCB_FILE_NAME) plain_image_data = load_binary(data_dir, subdir, image_name + '.bin') # images are aligned for test purposes only, otherwise export will align with random data fcb_data = align_block(fcb_data, 16) plain_image_data = align_block(plain_image_data, 16) # create boot section 0 boot_section = BootSectionV2( 0, CmdFill(address=0x10C000, pattern=bytes.fromhex('063040C0')), CmdMemEnable(0x10C000, 4, ExtMemId.FLEX_SPI_NOR), CmdErase(address=0x8000000, length=0x10000), CmdLoad(address=0x8000400, data=fcb_data), CmdLoad(address=0x8001000, data=plain_image_data)) boot_image.add_boot_section(boot_section) dbg_info = list() # debug log for analysis of the binary output content sb_file = boot_image.export( padding=bytes(8), dbg_info=dbg_info) # padding for unit test only, to avoid random data write_dbg_log(data_dir, image_name + '_keystore.sb', dbg_info, TEST_IMG_CONTENT) write_sb(data_dir, image_name + '_keystore.sb', sb_file, get_keystore(data_dir))
def test_align_block_invalid_input(): """Test invalid inputs for misc.align_block()""" with pytest.raises(AssertionError): align_block(None) with pytest.raises(SPSDKError, match="Wrong alignment"): align_block(b"", -1) with pytest.raises(SPSDKError, match="Wrong alignment"): align_block(b"", 0) with pytest.raises(SPSDKError, match="Wrong padding"): align_block(b"", 1, -2) with pytest.raises(SPSDKError, match="Wrong padding"): align_block(b"", 1, 256)
def test_align_block_invalid_input(): """Test invalid inputs for misc.align_block()""" with pytest.raises(AssertionError): align_block(None) with pytest.raises(AssertionError): align_block(b'', -1) with pytest.raises(AssertionError): align_block(b'', 0) with pytest.raises(AssertionError): align_block(b'', 1, -2) with pytest.raises(AssertionError): align_block(b'', 1, 256)
def __init__( self, app: bytes = None, app_table: MultipleImageTable = None, trust_zone: TrustZone = None, load_addr: int = None, hmac_key: Union[bytes, str] = None, key_store: KeyStore = None, hwk: bool = False, ) -> None: """Constructor for Master Boot CRC RAM Image for RTxxx family. :param app: Application image data, defaults to None :param app_table: Application table for additional application binaries, defaults to None :param trust_zone: TrustZone object, defaults to None :param load_addr: Load/Execution address in RAM of image, defaults to 0 :param hmac_key: HMAC key of image, defaults to None :param key_store: Optional KeyStore object for image, defaults to None :param hwk: Enable HW user mode keys, defaults to false """ self.app = align_block(app) if app else None self.app_table = app_table self.tz = trust_zone or TrustZone.enabled() self.user_hw_key_enabled = hwk self.load_address = load_addr self.hmac_key = bytes.fromhex(hmac_key) if isinstance( hmac_key, str) else hmac_key self.key_store = key_store super().__init__()
def export(self) -> bytes: """Export command header as bytes array.""" result_data = pack(self.FORMAT, self.TAG, self.address, self.key_wrap_id, self.length, self.cmd_tag) result_data += self.data result_data = align_block(data=result_data, alignment=16, padding=0) return result_data
def export(self) -> bytes: """Serialize Certificate Block V2 object.""" # At least one certificate must be used if not self._cert: raise SPSDKError("At least one certificate must be used") # The hast of root key certificate must be in RKHT if self.rkh_index is None: raise SPSDKError("The HASH of used Root Key must be in RKHT") # CA: Using a single certificate is allowed. In this case, the sole certificate must be self-signed and must not # be a CA. If multiple certificates are used, the root must be self-signed and all but the last must be CAs. if self._cert[-1].ca: raise SPSDKError("The last chain certificate must not be CA") if not all(cert.ca for cert in self._cert[:-1]): raise SPSDKError("All certificates except the last chain certificate must be CA") # Export data = self.header.export() for cert in self._cert: data += pack("<I", cert.raw_size) data += cert.export() for key in self._root_key_hashes: data += bytes(key) data = misc.align_block(data, self.alignment) if len(data) != self.raw_size: raise SPSDKError("Invalid length of data") return data
def export(self) -> bytes: """Export command as bytes.""" data = super().export() if self.HAS_MEMORY_ID_BLOCK: data += pack("<4L", self.memory_id, 0, 0, 0) data += self.data data = align_block(data, alignment=16) return data
def __init__(self, app: Union[bytes, bytearray], load_addr: int, image_type: MasterBootImageType = MasterBootImageType.PLAIN_IMAGE, trust_zone: Optional[TrustZone] = None, app_table: Optional[MultipleImageTable] = None, cert_block: Optional[CertBlock] = None, priv_key_pem_data: Optional[bytes] = None, hmac_key: Union[bytes, str] = None, key_store: KeyStore = None, enable_hw_user_mode_keys: bool = False, ctr_init_vector: bytes = None) -> None: """Constructor. :param app: input image (binary) :param load_addr: address in RAM, where 'RAM' image will be copied; for XIP images address, where the image is located in FLASH memory :param image_type: type of the master boot image :param trust_zone: TrustZone instance; None to use default settings (TrustZone enabled) :param app_table: optional table with additional images; None if no additional images needed :param cert_block: block of certificates; None for unsigned image :param priv_key_pem_data: private key to sign the image, decrypted binary data in PEM format :param hmac_key: optional key for HMAC generation (either binary ot HEX string; 32 bytes); None if HMAC is not in the image If key_store.key_source == KeySourceType.KEYSTORE, this is a user-key from key-store If key_store.key_source == KeySourceType.OTP, this is a master-key burned in OTP :param key_store: optional key store binary content; None if key store is not in the image :param enable_hw_user_mode_keys: flag for controlling secure hardware key bus. If true, then it is possible to access keys on hardware secure bus from non-secure application, else non-secure application will read zeros. :param ctr_init_vector: optional initial vector for encryption counter; None to use random vector :raises TypeError: if type is not binary data :raises ValueError: if images are not loaded from RAM """ if not isinstance(app, (bytes, bytearray)): raise TypeError("app must be binary data (bytes, bytearray)") if app_table and not MasterBootImageType.is_copied_to_ram(image_type): raise ValueError('app_table can be used only for images loaded to RAM') assert load_addr >= 0 self.load_addr = load_addr self.image_type = image_type alignment = MasterBootImage._IMAGE_ALIGNMENT self.app = misc.align_block(bytes(app), alignment) self.app_table = app_table # hmac + key store self.hmac_key = bytes.fromhex(hmac_key) if isinstance(hmac_key, str) else hmac_key self.key_store = key_store # trust zone self.trust_zone = trust_zone or TrustZone.enabled() # security stuff self.cert_block = cert_block if self.cert_block: self.cert_block.alignment = 4 #type: ignore # this value is used by elf-to-sb-gui self.signature_len = self.cert_block.signature_size #type: ignore else: self.signature_len = 0 self._priv_key_pem_data = priv_key_pem_data self.enable_hw_user_mode_keys = enable_hw_user_mode_keys self.ctr_init_vector = ctr_init_vector if MasterBootImageType.is_encrypted(self.image_type) and not ctr_init_vector: self.ctr_init_vector = crypto_backend().random_bytes(self._CTR_INIT_VECTOR_SIZE) self._verify_private_key() # validate parameters self._validate_new_instance()
def __init__(self, app: bytes = None, trust_zone: TrustZone = None) -> None: """Constructor for Master Boot CRC XiP Image for LPC55xxx family. :param app: Application image data, defaults to None :param trust_zone: TrustZone object, defaults to None """ self.app = align_block(app) if app else None self.tz = trust_zone or TrustZone.enabled() super().__init__()
def test_align_block_fill_random(test_input: bytes, alignment: int, expected: Union[int, bytes]): """Test misc.align_block_fill_random()""" data1 = align_block_fill_random(test_input, alignment) data2 = align_block(test_input, alignment, -1) assert isinstance(data1, bytes) if isinstance(expected, int): assert len(data1) == expected assert len(data2) == expected else: assert data1 == expected assert data2 == expected
def load_binary_image_file(self, path: str) -> None: """Load binary image from file (S19,HEX,BIN). :param path: File path :raises SPSDKError: If invalid data file is detected. """ binfile = load_binary_image(path) if binfile.minimum_address != 0: raise SPSDKError( f"Invalid input binary file {path}. It MUST starts at 0 offset." ) self.app = align_block(binfile.as_binary())
def encrypt_key_blobs(self, kek: Union[bytes, str]) -> bytes: """Encrypt key blobs with specified key. :param kek: key to encode key blobs :return: encrypted binary key blobs joined together """ result = bytes() for key_blob in self._key_blobs: result += key_blob.export(kek) return align_block( result, 256 ) # this is for compatibility with elftosb, probably need FLASH sector size
def export(self, kek: Union[bytes, str], iv: bytes = bytes([0xa6] * 8)) -> bytes: """Creates key wrap for the key blob. :param kek: key to encode; 16 bytes long :param iv: counter initialization vector; 8 bytes; optional, OTFAD uses empty init value :return: Serialized key blob :raise ValueError: if any parameter is not valid """ if isinstance(kek, str): kek = bytes.fromhex(kek) assert len(kek) == 16 assert len(iv) == self._EXPORT_CTR_IV_SIZE n = self._EXPORT_NBLOCKS_5 plaintext = self.plain_data() # input data to be encrypted assert len(plaintext) >= n * 8 # step 1: initialize the byte - sized data variables # set a = iv # for i = 1 to n # r[i] = plain_data[i] a = iv # 64-bit integrity check register r = bytearray(8) + bytearray( plaintext[0:8 * n]) # 8-bit array of 64-bit registers # step 2: calculate intermediate values # for j = 0 to 5 # for i = 1 to n # encr = AES(K, A | R[i]) # a = MSB(64, encr) ^ (n*j)+i # r[i] = LSB(64, B) for j in range(0, 6): for i in range(1, n + 1): in_data = a + r[8 * i:8 * i + 8] # 128-bit temporary plaintext input vector aes = AES.new(kek, AES.MODE_ECB) encr = aes.encrypt(in_data) xor = encr[7] ^ ((n * j) + i) a = bytes(encr[:7]) + bytes([xor]) r[8 * i:8 * i + 8] = encr[8:] # step 3: output the results # set result[0] = A # for i = 1 to n # result[i] = r[i] result = a + r[8:8 * n + 8] return align_block(result, self._EXPORT_KEY_BLOB_SIZE, padding=0) # align to 64 bytes (0 padding)
def __init__(self, app: bytes = None, trust_zone: TrustZone = None, firmware_version: int = 0) -> None: """Constructor for Master Boot CRC XiP Image for LPC55s3x family. :param app: Application image data, defaults to None :param trust_zone: TrustZone object, defaults to None :param firmware_version: Firmware version of image, defaults to 0 """ self.app = align_block(app) if app else None self.tz = trust_zone or TrustZone.enabled() self.firmware_version = firmware_version super().__init__()
def __init__(self, app: bytes = None, trust_zone: TrustZone = None, hwk: bool = False) -> None: """Constructor for Master Boot CRC XiP Image for RTxxx family. :param app: Application image data, defaults to None :param trust_zone: TrustZone object, defaults to None :param hwk: Enable HW user mode keys, defaults to false """ self.app = align_block(app) if app else None self.tz = trust_zone or TrustZone.enabled() self.user_hw_key_enabled = hwk super().__init__()
def test_sb(cpu_params: CpuParams) -> None: """Test creation of SB file. :param cpu_params: processor specific parameters of the test """ # timestamp is fixed for the test, do not not for production timestamp = datetime(year=2020, month=4, day=24, hour=15, minute=33, second=32, tzinfo=timezone.utc) # load application to add into SB img_name = f"{cpu_params.board}_iled_blinky_ext_FLASH_unsigned_nopadding" app_data = load_binary(cpu_params.data_dir, OUTPUT_IMAGES_SUBDIR, img_name + ".bin") boot_img = BootImgRT.parse(app_data) # parse to retrieve IVT offset sb = SecureBootV1(version=SB_FILE_VERSION, timestamp=timestamp) sect = BootSectionV1(0, SecureBootFlagsV1.ROM_SECTION_BOOTABLE) # load 0xc0233007 > 0x2000; sect.append( CmdFill( INT_RAM_ADDR_DATA, int.from_bytes(pack("<I", cpu_params.ext_flash_cfg_word0), "little"))) # enable flexspinor 0x2000; sect.append(CmdMemEnable(INT_RAM_ADDR_DATA, 4, ExtMemId.FLEX_SPI_NOR)) # erase 0x60000000..0x60100000; sect.append( CmdErase(EXT_FLASH_ADDR, align(boot_img.ivt_offset + boot_img.size, 0x1000))) # load 0xf000000f > 0x3000; sect.append( CmdFill(INT_RAM_ADDR_DATA, int.from_bytes(pack("<I", FCB_FLASH_NOR_CFG_WORD), "little"))) # enable flexspinor 0x3000; sect.append(CmdMemEnable(INT_RAM_ADDR_DATA, 4, ExtMemId.FLEX_SPI_NOR)) # load myBinFile > kAbsAddr_Ivt; app_data = align_block( app_data, 0x10) # this is padding fixed for the test, not needed for production sect.append(CmdLoad(EXT_FLASH_ADDR + boot_img.ivt_offset, app_data)) # sb.append(sect) # write_sb(cpu_params, img_name + ".sb", sb)
def get_cmd_blocks_to_export(self) -> List[bytes]: """Export commands as bytes.""" commands_bytes = b"".join( [command.export() for command in self.commands]) section_header = CmdSectionHeader(length=len(commands_bytes)) total = section_header.export() + commands_bytes data_blocks = [ total[i:i + self.DATA_CHUNK_LENGTH] for i in range(0, len(total), self.DATA_CHUNK_LENGTH) ] data_blocks[-1] = align_block(data_blocks[-1], alignment=self.DATA_CHUNK_LENGTH) return data_blocks
def encrypt_image(self, base_address: int, data: bytes, byte_swap: bool) -> bytes: """Encrypt specified data. :param base_address: of the data in target memory; must be >= self.start_addr :param data: to be encrypted (e.g. plain image); base_address + len(data) must be <= self.end_addr :param byte_swap: this probably depends on the flash device, how bytes are organized there True should be used for FLASH on EVK RT6xx; False for FLASH on EVK RT5xx :return: encrypted data :raise ValueError: if start_addr or end_addr does not match with base_address (+ data length) """ assert base_address % 16 == 0 # Start address has to be 16 byte aligned data = align_block(data, self._IMAGE_ALIGNMENT) # align data length data_len = len(data) # check start and end addresses if not self.matches_range(base_address, base_address + data_len - 1): raise ValueError( f'Image address range is not within key blob: {hex(self.start_addr)}-{hex(self.end_addr)}' ) result = bytes() counter = Counter(self._get_ctr_nonce(), ctr_value=base_address, ctr_byteorder_encoding='big') for index in range(0, data_len, 16): # prepare data in byte order if byte_swap: # swap 8 bytes + swap 8 bytes data_2_encr = data[-data_len + index + 7: -data_len + index - 1: -1] + \ data[-data_len + index + 15: -data_len + index + 7: -1] else: data_2_encr = data[index:index + 16] # encrypt encr_data = crypto_backend().aes_ctr_encrypt( self.key, data_2_encr, counter.value) # fix byte order in result if byte_swap: result += encr_data[-9:-17:-1] + encr_data[ -1:-9:-1] # swap 8 bytes + swap 8 bytes else: result += encr_data # update counter for encryption counter.increment(16) assert len(result) == data_len return bytes(result)
def _burn_image_to_sd(cpu_params: CpuParams, img: BootImgRT, img_data: bytes) -> None: """Burn image into SD card. This function is called only in production mode. :param cpu_params: processor specific parameters of the test :param img: RT10xx image instance :param img_data: exported image data """ assert TEST_IMG_CONTENT is False # start FLASH loader mboot = init_flashloader(cpu_params) assert mboot.get_property(PropertyTag.CURRENT_VERSION) # verify SRK fuses are properly burned if VERIFY_SRK_FUSES: assert verify_srk_fuses(mboot, srk_table4(cpu_params)) # ### Configure external FLASH on EVK: flex-spi-nor using options on address 0x2000 ### # call "%blhost%" -u 0x15A2,0x0073 -j -- fill-memory 0x2000 4 0xD0000000 word assert mboot.fill_memory(INT_RAM_ADDR_DATA, 4, 0xD0000000) # call "%blhost%" -u 0x15A2,0x0073 -j -- fill-memory 0x2004 4 0x00000000 word assert mboot.fill_memory(INT_RAM_ADDR_DATA + 4, 4, 0x00000000) # call "%blhost%" -u 0x15A2,0x0073 -j -- configure-memory 288 0x2000 assert mboot.configure_memory(INT_RAM_ADDR_DATA, ExtMemId.SD_CARD) img_data = align_block(img_data, 0x1000) # ### Erase memory before writing image ### # call "%blhost%" -u 0x15A2,0x0073 -j -- flash-erase-region 0x400 16384 288 assert mboot.flash_erase_region(SD_CARD_ADDR + img.ivt_offset, len(img_data), ExtMemId.SD_CARD) # @echo ### Write image ### # call "%blhost%" -u 0x15A2,0x0073 -j -- write-memory 0x00000400 image.bin 288 assert mboot.write_memory(SD_CARD_ADDR + img.ivt_offset, img_data, ExtMemId.SD_CARD) # for HAB encrypted image write KEY BLOB if img.dek_key: # call "blhost" -u 0x15A2,0x0073 -j -- generate-key-blob {BOARD}_iled_blinky_int_ram_hab_dek.bin blob.bin blob = mboot.generate_key_blob(img.dek_key) tgt_address = EXT_FLASH_ADDR + img.dek_img_offset # call "blhost" -u 0x15A2,0x0073 -j -- write-memory 0x60008000 blob.bin 9 assert mboot.write_memory(tgt_address, blob, ExtMemId.FLEX_SPI_NOR) mboot.close()
def load_binary_image_file(self, path: str) -> None: """Load binary image from file (S19,HEX,BIN). :param path: File path :raises SPSDKError: If invalid data file is detected. """ app_align = self.app_ext_memory_align if hasattr( self, "app_ext_memory_align") else 0 binfile = load_binary_image(path) if app_align == 0 and binfile.minimum_address != 0: raise SPSDKError( f"Invalid input binary file {path}. It MUST begins at 0 address." ) if app_align and binfile.minimum_address % app_align != 0: raise SPSDKError( f"Invalid input binary file {path}. It has to be aligned to {hex(app_align)}." ) self.app = align_block(binfile.as_binary())
def __init__( self, app: bytes = None, trust_zone: TrustZone = None, cert_block: CertBlockV2 = None, priv_key_data: bytes = None, ) -> None: """Constructor for Master Boot Signed XiP Image for LPC55xxx family. :param app: Application image data, defaults to None :param trust_zone: TrustZone object, defaults to None :param cert_block: Certification block of image, defaults to None :param priv_key_data: Private key used to sign image, defaults to None """ self.app = align_block(app) if app else None self.tz = trust_zone or TrustZone.enabled() self.cert_block = cert_block self.priv_key_data = priv_key_data super().__init__()
def __init__( self, app: bytes = None, trust_zone: TrustZone = None, load_addr: int = None, hwk: bool = False, ) -> None: """Constructor for Master Boot Plain XiP Image for RTxxx family. :param app: Application image data, defaults to None :param trust_zone: TrustZone object, defaults to None :param load_addr: Load/Execution address in RAM of image, defaults to 0 :param hwk: Enable HW user mode keys, defaults to false """ self.app = align_block(app) if app else None self.tz = trust_zone or TrustZone.enabled() self.load_address = load_addr self.user_hw_key_enabled = hwk super().__init__()
def __init__( self, app: bytes = None, trust_zone: TrustZone = None, load_addr: int = 0, firmware_version: int = 0, ) -> None: """Constructor for Master Boot Signed RAM Image for LPC55s3x family. :param app: Application image data, defaults to None :param trust_zone: TrustZone object, defaults to None :param load_addr: Load/Execution address in RAM of image, defaults to 0 :param firmware_version: Firmware version of image, defaults to 0 """ self.app = align_block(app) if app else None self.tz = trust_zone or TrustZone.enabled() self.load_address = load_addr self.firmware_version = firmware_version super().__init__()
def __init__( self, app: bytes = None, trust_zone: TrustZone = None, cert_block: CertBlockV2 = None, priv_key_data: bytes = None, hwk: bool = False, ) -> None: """Constructor for Master Boot Plain Signed XiP Image for RTxxx family. :param app: Application image data, defaults to None :param trust_zone: TrustZone object, defaults to None :param cert_block: Certification block of image, defaults to None :param priv_key_data: Private key used to sign image, defaults to None :param hwk: Enable HW user mode keys, defaults to false """ self.app = align_block(app) if app else None self.tz = trust_zone or TrustZone.enabled() self.cert_block = cert_block self.priv_key_data = priv_key_data self.user_hw_key_enabled = hwk super().__init__()
def export(self) -> bytes: """Export commands as bytes.""" commands_bytes = b''.join( [command.export() for command in self.commands]) section_header = CmdSectionHeader(length=len(commands_bytes)) total = section_header.export() + commands_bytes data_blocks = [ total[i:i + self.DATA_CHUNK_LENGTH] for i in range(0, len(total), self.DATA_CHUNK_LENGTH) ] data_blocks[-1] = align_block(data_blocks[-1], alignment=self.DATA_CHUNK_LENGTH) self.block_count = len(data_blocks) processed_blocks = [ self._process_block(block_number, block_data) for block_number, block_data in reversed( list(enumerate(data_blocks, start=1))) ] final_data = b''.join(reversed(processed_blocks)) return final_data
def __init__( self, app: bytes = None, app_table: MultipleImageTable = None, trust_zone: TrustZone = None, load_addr: int = None, cert_block: CertBlockV2 = None, priv_key_data: bytes = None, hmac_key: Union[bytes, str] = None, key_store: KeyStore = None, ctr_init_vector: bytes = None, hwk: bool = False, ) -> None: """Constructor for Master Boot Encrypted RAM Image for RTxxx family.. :param app: Application image data, defaults to None :param app_table: Application table for additional application binaries, defaults to None :param trust_zone: TrustZone object, defaults to None :param load_addr: Load/Execution address in RAM of image, defaults to 0 :param cert_block: Certification block of image, defaults to None :param priv_key_data: Private key used to sign image, defaults to None :param hwk: Enable HW user mode keys, defaults to false :param key_store: Optional KeyStore object for image, defaults to None :param hmac_key: HMAC key of image, defaults to None :param ctr_init_vector: Counter initialization vector of image, defaults to None """ self.app = align_block(app) if app else None self.load_address = load_addr self.app_table = app_table self.tz = trust_zone or TrustZone.enabled() self.cert_block = cert_block self.priv_key_data = priv_key_data self.user_hw_key_enabled = hwk self.key_store = key_store self.hmac_key = bytes.fromhex(hmac_key) if isinstance( hmac_key, str) else hmac_key self.store_ctr_init_vector(ctr_init_vector) self.img_len = 0 super().__init__()
def __init__( self, app: bytes = None, firmware_version: int = 0, cert_block: CertBlockV31 = None, manifest: MasterBootImageManifest = None, signature_provider: SignatureProvider = None, ) -> None: """Constructor for Master Boot Signed XIP Image for LPC55s3x family. :param app: Application image data, defaults to None :param firmware_version: Firmware version of image, defaults to 0 :param cert_block: Certification block of image, defaults to None :param manifest: Manifest of image, defaults to None :param signature_provider: Signature provider to sign final image, defaults to None """ self.app = align_block(app) if app else None self.firmware_version = firmware_version self.cert_block = cert_block self.manifest = manifest self.signature_provider = signature_provider super().__init__()
def export_image(self) -> bytes: """Binary image aligned to the 4-bytes boundary.""" return misc.align_block(self.image, 4)
def test_align_block(test_input: bytes, alignment: int, padding: int, expected: bytes): """Test misc.align_block()""" data = align_block(test_input, alignment, padding) assert isinstance(data, bytes) assert data == expected