コード例 #1
0
    def parse(
        cls,
        data: bytes,
        offset: int = 0,
        dek: bytes = b"",
        mac: bytes = b"",
        counter: Optional[Counter] = None,
    ) -> "CertSectionV2":
        """Parse Certificate Section from bytes array.

        :param data: Raw data of parsed image
        :param offset: The offset of input data
        :param dek: The DEK value in bytes (required)
        :param mac: The MAC value in bytes (required)
        :param counter: The counter object (required)
        :return: parsed cert section v2 object
        :raises SPSDKError: Raised when dek, mac, counter are not valid
        :raises SPSDKError: Raised when there is invalid header HMAC, TAG, FLAGS, Mark
        :raises SPSDKError: Raised when there is invalid certificate block HMAC
        """
        if not isinstance(dek, bytes):
            raise SPSDKError("DEK value has invalid format")
        if not isinstance(mac, bytes):
            raise SPSDKError("MAC value has invalid format")
        if not isinstance(counter, Counter):
            raise SPSDKError("Counter value has invalid format")
        index = offset
        header_encrypted = data[index:index + CmdHeader.SIZE]
        index += CmdHeader.SIZE
        header_hmac = data[index:index + cls.HMAC_SIZE]
        index += cls.HMAC_SIZE
        cert_block_hmac = data[index:index + cls.HMAC_SIZE]
        index += cls.HMAC_SIZE
        if header_hmac != crypto_backend().hmac(mac, header_encrypted):
            raise SPSDKError("Invalid Header HMAC")
        header_encrypted = crypto_backend().aes_ctr_decrypt(
            dek, header_encrypted, counter.value)
        header = CmdHeader.parse(header_encrypted)
        if header.tag != EnumCmdTag.TAG:
            raise SPSDKError(f"Invalid Header TAG: 0x{header.tag:02X}")
        if header.flags != (EnumSectionFlag.CLEARTEXT
                            | EnumSectionFlag.LAST_SECT):
            raise SPSDKError(f"Invalid Header FLAGS: 0x{header.flags:02X}")
        if header.address != cls.SECT_MARK:
            raise SPSDKError(f"Invalid Section Mark: 0x{header.address:08X}")
        # Parse Certificate Block
        cert_block = CertBlockV2.parse(data, index)
        if cert_block_hmac != crypto_backend().hmac(
                mac, data[index:index + cert_block.raw_size]):
            raise SPSDKError("Invalid Certificate Block HMAC")
        index += cert_block.raw_size
        cert_section_obj = cls(cert_block)
        counter.increment(calc_cypher_block_count(index - offset))
        return cert_section_obj
コード例 #2
0
    def parse(
        cls,
        data: bytes,
        offset: int = 0,
        kek: bytes = bytes(),
        plain_sections: bool = False,
    ) -> "BootImageV21":
        """Parse image from bytes.

        :param data: Raw data of parsed image
        :param offset: The offset of input data
        :param kek: The Key for unwrapping DEK and MAC keys (required)
        :param plain_sections: Sections are not encrypted; this is used only for debugging,
            not supported by ROM code
        :return: BootImageV21 parsed object
        :raises Exception: raised when header is in incorrect format
        :raises Exception: raised when signature is incorrect
        :raises SPSDKError: Raised when kek is empty
        :raises Exception: raised when header's nonce not present"
        """
        if not kek:
            raise SPSDKError("kek cannot be empty")
        index = offset
        header_raw_data = data[index:index + ImageHeaderV2.SIZE]
        index += ImageHeaderV2.SIZE
        # TODO not used right now: hmac_data = data[index: index + cls.HEADER_MAC_SIZE]
        index += cls.HEADER_MAC_SIZE
        key_blob = data[index:index + cls.KEY_BLOB_SIZE]
        index += cls.KEY_BLOB_SIZE
        key_blob_unwrap = crypto_backend().aes_key_unwrap(kek, key_blob[:-8])
        dek = key_blob_unwrap[:32]
        mac = key_blob_unwrap[32:]
        # Parse Header
        header = ImageHeaderV2.parse(header_raw_data)
        if header.offset_to_certificate_block != (index - offset):
            raise Exception()
        # Parse Certificate Block
        cert_block = CertBlockV2.parse(data, index)
        index += cert_block.raw_size

        # Verify Signature
        signature_index = index
        # The image may containt SHA, in such a case the signature is placed
        # after SHA. Thus we must shift the index by SHA size.
        if header.flags & BootImageV21.FLAGS_SHA_PRESENT_BIT:
            signature_index += BootImageV21.SHA_256_SIZE
        result = cert_block.verify_data(
            data[signature_index:signature_index + cert_block.signature_size],
            data[offset:signature_index],
        )

        if not result:
            raise Exception()
        # Check flags, if 0x8000 bit is set, the SB file contains SHA-256 between
        # certificate and signature.
        if header.flags & BootImageV21.FLAGS_SHA_PRESENT_BIT:
            bootable_section_sha256 = data[index:index +
                                           BootImageV21.SHA_256_SIZE]
            index += BootImageV21.SHA_256_SIZE
        index += cert_block.signature_size
        # Check first Boot Section HMAC
        # TODO: not implemented yet
        # hmac_data_calc = crypto_backend().hmac(mac, data[index + CmdHeader.SIZE: index + CmdHeader.SIZE + ((2) * 32)])
        # if hmac_data != hmac_data_calc:
        #    raise Exception()
        if not header.nonce:
            raise SPSDKError("Header's nonce not present")
        counter = Counter(header.nonce)
        counter.increment(calc_cypher_block_count(index - offset))
        boot_section = BootSectionV2.parse(data,
                                           index,
                                           dek=dek,
                                           mac=mac,
                                           counter=counter,
                                           plain_sect=plain_sections)
        if header.flags & BootImageV21.FLAGS_SHA_PRESENT_BIT:
            computed_bootable_section_sha256 = internal_backend.hash(
                data[index:], algorithm="sha256")

            if bootable_section_sha256 != computed_bootable_section_sha256:
                raise SPSDKError(desc=(
                    "Error: invalid Bootable section SHA."
                    f"Expected {bootable_section_sha256.decode('utf-8')},"
                    f"got {computed_bootable_section_sha256.decode('utf-8')}"))
        adv_params = SBV2xAdvancedParams(dek=dek,
                                         mac=mac,
                                         nonce=header.nonce,
                                         timestamp=header.timestamp)
        obj = cls(
            kek=kek,
            product_version=str(header.product_version),
            component_version=str(header.component_version),
            build_number=header.build_number,
            advanced_params=adv_params,
        )
        obj.cert_block = cert_block
        obj.add_boot_section(boot_section)
        return obj
コード例 #3
0
    def parse(cls,
              data: bytes,
              offset: int = 0,
              kek: bytes = bytes(),
              plain_sections: bool = False) -> 'BootImageV21':
        """Parse image from bytes.

        :param data: Raw data of parsed image
        :param offset: The offset of input data
        :param kek: The Key for unwrapping DEK and MAC keys (required)
        :param plain_sections: Sections are not encrypted; this is used only for debugging, not supported by ROM code
        :return: BootImageV21 parsed object
        :raise Exception: raised when header is in incorrect format
        :raise Exception: raised when signature is incorrect
        """
        assert kek, 'kek cannot be empty'
        index = offset
        header_raw_data = data[index:index + ImageHeaderV2.SIZE]
        index += ImageHeaderV2.SIZE
        # TODO not used right now: hmac_data = data[index: index + cls.HEADER_MAC_SIZE]
        index += cls.HEADER_MAC_SIZE
        key_blob = data[index:index + cls.KEY_BLOB_SIZE]
        index += cls.KEY_BLOB_SIZE
        key_blob_unwrap = crypto_backend().aes_key_unwrap(kek, key_blob[:-8])
        dek = key_blob_unwrap[:32]
        mac = key_blob_unwrap[32:]
        # Parse Header
        header = ImageHeaderV2.parse(header_raw_data)
        if header.offset_to_certificate_block != (index - offset):
            raise Exception()
        # Parse Certificate Block
        cert_block = CertBlockV2.parse(data, index)
        index += cert_block.raw_size
        # Verify Signature
        if not cert_block.verify_data(
                data[index:index + cert_block.signature_size],
                data[offset:index]):
            raise Exception()
        index += cert_block.signature_size
        # Check first Boot Section HMAC
        # TODO: not implemented yet
        # hmac_data_calc = crypto_backend().hmac(mac, data[index + CmdHeader.SIZE: index + CmdHeader.SIZE + ((2) * 32)])
        # if hmac_data != hmac_data_calc:
        #    raise Exception()
        assert header.nonce
        counter = Counter(header.nonce)
        counter.increment(calc_cypher_block_count(index - offset))
        boot_section = BootSectionV2.parse(data,
                                           index,
                                           dek=dek,
                                           mac=mac,
                                           counter=counter,
                                           plain_sect=plain_sections)
        adv_params = SBV2xAdvancedParams(dek=dek,
                                         mac=mac,
                                         nonce=header.nonce,
                                         timestamp=header.timestamp)
        obj = cls(kek=kek,
                  product_version=str(header.product_version),
                  component_version=str(header.component_version),
                  build_number=header.build_number,
                  advanced_params=adv_params)
        obj.cert_block = cert_block
        obj.add_boot_section(boot_section)
        return obj