def _calc_rotkh(self, keys: List[PublicKey]) -> bytes: """Calculate ROTKH (Root Of Trust Key Hash). :param keys: List of Keys to compute ROTKH. :return: Value of ROTKH with right width. :raises SPSDKPfrError: Algorithm width doesn't fit into ROTKH field. """ # the data structure use for computing final ROTKH is 4*32B long # 32B is a hash of individual keys # 4 is the max number of keys, if a key is not provided the slot is filled with '\x00' # The LPC55S3x has two options to compute ROTKH, so it's needed to be # detected the right algorithm and mandatory warn user about this selection because # it's MUST correspond to settings in eFuses! reg_rotkh = self.registers.find_reg("ROTKH") width = reg_rotkh.width if isinstance(keys[0], rsa.RSAPublicKey): algorithm_width = 256 else: algorithm_width = keys[0].key_size if algorithm_width > width: raise SPSDKPfrError("The ROTKH field is smaller than used algorithm width.") key_hashes = [calc_pub_key_hash(key, openssl_backend, algorithm_width) for key in keys] data = [ key_hashes[i] if i < len(key_hashes) else bytes(algorithm_width // 8) for i in range(4) ] return openssl_backend.hash(bytearray().join(data), f"sha{algorithm_width}").ljust( width // 8, b"\x00" )
def export(self, add_hash: bool = False, compute_inverses: bool = False) -> bytes: """Generate binary output.""" data = bytearray(self.BINARY_SIZE) for reg in self._get_registers(exclude_computed=False): name = reg.attrib["name"] width = parse_int(reg.attrib["width"]) offset = parse_int(reg.attrib["offset"]) assert width == 32, "Don't know how to handle non-32b registers" register = self._export_register(name, compute_inverses) # rewriting 4B at the time data[offset:offset + 4] = register # ROTKH may or may not be present, derived class defines its presense if self.HAS_ROTKH: rotkh_data = self.rotkh or self._calc_rotkh() rothk_start = self._get_rotkh_start_address() data[rothk_start:rothk_start + self.ROTKH_SIZE] = rotkh_data if add_hash: sha_start = self._get_sha_start_address() data[sha_start:sha_start + self.SHA_SIZE] = openssl_backend.hash( data[:sha_start]) return bytes(data)
def _calc_rotkh(self) -> bytes: """Calculate ROTKH (Root Of Trust Key Hash).""" # the data structure use for computing final ROTKH is 4*32B long # 32B is a hash of individual keys # 4 is the max number of keys, if a key is not provided the slot is filled with '\x00' assert self.keys, f"Key's were not set, can't compute ROTKH" key_hashes = [calc_pub_key_hash(key, openssl_backend) for key in self.keys] data = [key_hashes[i] if i < len(key_hashes) else bytes(32) for i in range(4)] return openssl_backend.hash(bytearray().join(data))
def test_hash(): plain_text = b'testestestestestestestestestestestestestestestestestestestest' text_sha256 = unhexlify( "41116FE4EFB90A050AABB83419E19BF2196A0E76AB8E3034C8D674042EE23621") calc_sha256 = openssl_backend.hash(plain_text, 'sha256') assert calc_sha256 == text_sha256