Example #1
0
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))
Example #2
0
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))
Example #3
0
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)
Example #4
0
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)
Example #5
0
    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__()
Example #6
0
    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
Example #7
0
 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
Example #8
0
 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
Example #9
0
    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()
Example #10
0
    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__()
Example #11
0
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
Example #12
0
    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())
Example #13
0
    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
Example #14
0
    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)
Example #15
0
    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__()
Example #16
0
    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__()
Example #17
0
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)
Example #18
0
    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
Example #19
0
    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)
Example #20
0
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()
Example #21
0
    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())
Example #22
0
    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__()
Example #23
0
    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__()
Example #24
0
    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__()
Example #25
0
    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__()
Example #26
0
    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
Example #27
0
    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__()
Example #28
0
    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__()
Example #29
0
 def export_image(self) -> bytes:
     """Binary image aligned to the 4-bytes boundary."""
     return misc.align_block(self.image, 4)
Example #30
0
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