def test_invalid_key_store(): # invalid key store length with pytest.raises(ValueError): KeyStore(KeySourceType.KEYSTORE, bytes(range(10))) # key-store specified in OTP mode with pytest.raises(ValueError): KeyStore(KeySourceType.OTP, bytes(range(10)))
def test_empty_key_store(): key_store = KeyStore(KeySourceType.KEYSTORE) assert key_store.key_source == KeySourceType.KEYSTORE assert key_store.export() == bytes() key_store.info() # OTP key_store = KeyStore(KeySourceType.OTP) assert key_store.key_source == KeySourceType.OTP assert key_store.export() == bytes() key_store.info()
def test_invalid_master_boot_image_params(data_dir): with pytest.raises(TypeError): # noinspection PyTypeChecker MasterBootImage(app=5) # load_addr must not be negative with pytest.raises(AssertionError): MasterBootImage(app=bytes(range(64)), load_addr=-1, image_type=MasterBootImageType.CRC_XIP_IMAGE) # certificate block is supported for signed images with pytest.raises(ValueError): MasterBootImage(app=bytes(range(64)), load_addr=0, image_type=MasterBootImageType.SIGNED_RAM_IMAGE) with pytest.raises(ValueError): MasterBootImage(app=bytes(range(64)), load_addr=0, image_type=MasterBootImageType.SIGNED_XIP_IMAGE) # hmac_key must be provided for load-to-ram image cert_block = certificate_block(data_dir, ['selfsign_2048_v3.der.crt']) priv_key_pem_data = _load_private_key(data_dir, 'selfsign_privatekey_rsa2048.pem') with pytest.raises(ValueError): MasterBootImage(app=bytes(range(64)), load_addr=0, image_type=MasterBootImageType.SIGNED_RAM_IMAGE, cert_block=cert_block, priv_key_pem_data=priv_key_pem_data) with pytest.raises(ValueError): MasterBootImage(app=bytes(range(64)), load_addr=0, image_type=MasterBootImageType.SIGNED_RAM_IMAGE, cert_block=cert_block, priv_key_pem_data=priv_key_pem_data, key_store=KeyStore(KeySourceType.OTP)) with pytest.raises(ValueError): MasterBootImage(app=bytes(range(64)), load_addr=0, image_type=MasterBootImageType.SIGNED_RAM_IMAGE, cert_block=cert_block, priv_key_pem_data=priv_key_pem_data, key_store=KeyStore(KeySourceType.KEYSTORE)) # hmac_key (or key_store) cannot be provided for XIP image with pytest.raises(ValueError): MasterBootImage(app=bytes(range(64)), load_addr=0, image_type=MasterBootImageType.SIGNED_XIP_IMAGE, cert_block=cert_block, priv_key_pem_data=priv_key_pem_data, hmac_key=bytes(range(32))) with pytest.raises(ValueError): MasterBootImage(app=bytes(range(64)), load_addr=0, image_type=MasterBootImageType.SIGNED_XIP_IMAGE, cert_block=cert_block, priv_key_pem_data=priv_key_pem_data, key_store=KeyStore(KeySourceType.KEYSTORE)) # app_table can be specified only for RAM images with pytest.raises(ValueError): app_table = MultipleImageTable() MasterBootImage(app=bytes(range(64)), load_addr=0, image_type=MasterBootImageType.CRC_XIP_IMAGE, app_table=app_table) # app_table is empty with pytest.raises(ValueError): app_table = MultipleImageTable() MasterBootImage(app=bytes(range(64)), load_addr=0, image_type=MasterBootImageType.CRC_RAM_IMAGE, app_table=app_table) # error if image len is not enough with pytest.raises(ValueError): MasterBootImage(app=bytes(range(32)), load_addr=0).export()
def test_encrypted_ram_single_certificate_no_tz(data_dir, keysource: KeySourceType, keystore_fn: Optional[str], ctr_iv: str, expected_mbi: str): """Test encrypted image with fixed counter init vector""" with open(os.path.join(data_dir, 'testfffffff.bin'), "rb") as f: org_data = f.read() user_key = 'E39FD7AB61AE6DDDA37158A0FC3008C6D61100A03C7516EA1BE55A39F546BAD5' key_store_bin = None if keystore_fn: with open(os.path.join(data_dir, keystore_fn), "rb") as f: key_store_bin = f.read() key_store = KeyStore(keysource, key_store_bin) ctr_init_vector = bytes.fromhex(ctr_iv) # create certification block cert_block = certificate_block(data_dir, ['selfsign_2048_v3.der.crt']) priv_key_pem_data = _load_private_key(data_dir, 'selfsign_privatekey_rsa2048.pem') mbi = MasterBootImage(app=org_data, image_type=MasterBootImageType.ENCRYPTED_RAM_IMAGE, load_addr=0x12345678, trust_zone=TrustZone.disabled(), cert_block=cert_block, priv_key_pem_data=priv_key_pem_data, hmac_key=user_key, key_store=key_store, ctr_init_vector=ctr_init_vector) assert _compare_image(mbi, data_dir, expected_mbi)
def test_signed_ram_single_certificate_no_tz(data_dir, user_key, key_store_filename, expected_mbi): """Test non-XIP signed image with single certificate :param data_dir: absolute path, where test data are located """ with open(os.path.join(data_dir, 'testfffffff.bin'), "rb") as f: org_data = f.read() # create certification block cert_block = certificate_block(data_dir, ['selfsign_2048_v3.der.crt']) priv_key_pem_data = _load_private_key(data_dir, 'selfsign_privatekey_rsa2048.pem') key_store = None if key_store_filename: with open(os.path.join(data_dir, key_store_filename), "rb") as f: key_store_bin = f.read() key_store = KeyStore(KeySourceType.KEYSTORE, key_store_bin) mbi = MasterBootImage(app=org_data, image_type=MasterBootImageType.SIGNED_RAM_IMAGE, load_addr=0x12345678, trust_zone=TrustZone.disabled(), cert_block=cert_block, priv_key_pem_data=priv_key_pem_data, hmac_key=user_key, key_store=key_store) assert _compare_image(mbi, data_dir, expected_mbi)
def test_invalid_export_mbi(data_dir): with open(os.path.join(data_dir, "testfffffff.bin"), "rb") as f: org_data = f.read() user_key = "E39FD7AB61AE6DDDA37158A0FC3008C6D61100A03C7516EA1BE55A39F546BAD5" key_store_bin = None key_store = KeyStore(KeySourceType.KEYSTORE, key_store_bin) cert_block = certificate_block(data_dir, ["selfsign_2048_v3.der.crt"]) priv_key_pem_data = _load_private_key(data_dir, "selfsign_privatekey_rsa2048.pem") mbi = Mbi_EncryptedRamRtxxx( app=org_data, load_addr=0x12345678, trust_zone=TrustZone.disabled(), cert_block=cert_block, priv_key_data=priv_key_pem_data, hmac_key=user_key, key_store=key_store, ctr_init_vector=bytes(16), ) mbi.priv_key_data = None with pytest.raises(SPSDKError): mbi.export() mbi.priv_key_data = priv_key_pem_data mbi.cert_block = None with pytest.raises(SPSDKError): mbi.export()
def compute_hmac(self, data: bytes) -> bytes: """Compute HMAC hash. :param data: Data to be hashed. :return: Result HMAC hash of input data. """ if not self.hmac_key: return bytes() key = KeyStore.derive_hmac_key(self.hmac_key) result = crypto_backend().hmac(key, data) assert len(result) == self.HMAC_SIZE return result
def mix_load_from_config(self, config: Dict[str, Any]) -> None: """Load configuration from dictionary. :param config: Dictionary with configuration fields. """ key_source = KeySourceType.get(config.get("deviceKeySource", "OTP")) use_key_store = config.get("useKeyStore", False) key_store_file = config.get("keyStoreFile", None) if use_key_store and key_source == KeySourceType.KEYSTORE: key_store_data = (load_binary(key_store_file) if key_store_file else bytes(KeyStore.KEY_STORE_SIZE)) self.key_store = KeyStore(key_source, key_store_data) # type: ignore
def test_encrypted_random_ctr_single_certificate_no_tz(data_dir): """Test encrypted image with random counter init vector""" with open(os.path.join(data_dir, 'testfffffff.bin'), "rb") as f: org_data = f.read() user_key = 'E39FD7AB61AE6DDDA37158A0FC3008C6D61100A03C7516EA1BE55A39F546BAD5' key_store = KeyStore(KeySourceType.KEYSTORE, None) cert_block = certificate_block(data_dir, ['selfsign_2048_v3.der.crt']) priv_key_pem_data = _load_private_key(data_dir, 'selfsign_privatekey_rsa2048.pem') mbi = MasterBootImage(app=org_data, image_type=MasterBootImageType.ENCRYPTED_RAM_IMAGE, load_addr=0x12345678, trust_zone=TrustZone.disabled(), cert_block=cert_block, priv_key_pem_data=priv_key_pem_data, hmac_key=user_key, key_store=key_store) assert mbi.export() assert mbi.info()
def _hmac(self, data: bytes) -> bytes: """Calculate HMAC for provided data. :param data: to calculate hmac :return: calculated hmac; empty bytes if the block does not contain any HMAC """ if not MasterBootImageType.has_hmac(self.image_type): return bytes() assert self.hmac_key and len(self.hmac_key) == self._HMAC_KEY_LENGTH key = KeyStore.derive_hmac_key(self.hmac_key) assert len(key) == self._HMAC_DERIVED_KEY_LEN result = crypto_backend().hmac(key, data) assert len(result) == self.HMAC_SIZE return result
def encrypt(self, raw_image: bytes) -> bytes: """Encrypt image if needed. :param raw_image: Input raw image to encrypt. :return: Encrypted image. """ assert self.hmac_key and self.ctr_init_vector key = self.hmac_key if not self.key_store or self.key_store.key_source == KeySourceType.OTP: key = KeyStore.derive_enc_image_key(key) aes = AES.new(key, AES.MODE_CTR, initial_value=self.ctr_init_vector, nonce=bytes()) return aes.encrypt(raw_image + self.tz.export())
def test_master_boot_image_invalid_hmac(data_dir): with open(os.path.join(data_dir, "testfffffff.bin"), "rb") as f: org_data = f.read() user_key = "E39FD7AB61AE6DDDA37158A0FC3008C6D61100A03C7516EA1BE55A39F546BAD5" key_store = KeyStore(KeySourceType.KEYSTORE, None) cert_block = certificate_block(data_dir, ["selfsign_2048_v3.der.crt"]) priv_key_pem_data = _load_private_key(data_dir, "selfsign_privatekey_rsa2048.pem") mbi = Mbi_EncryptedRamRtxxx( app=org_data, load_addr=0x12345678, trust_zone=TrustZone.disabled(), cert_block=cert_block, priv_key_data=priv_key_pem_data, hmac_key=user_key, key_store=key_store, ) mbi.hmac_key = None assert mbi.compute_hmac(data=bytes(16)) == bytes()
def test_encrypted_random_ctr_single_certificate_no_tz(data_dir): """Test encrypted image with random counter init vector""" with open(os.path.join(data_dir, "testfffffff.bin"), "rb") as f: org_data = f.read() user_key = "E39FD7AB61AE6DDDA37158A0FC3008C6D61100A03C7516EA1BE55A39F546BAD5" key_store = KeyStore(KeySourceType.KEYSTORE, None) cert_block = certificate_block(data_dir, ["selfsign_2048_v3.der.crt"]) priv_key_pem_data = _load_private_key(data_dir, "selfsign_privatekey_rsa2048.pem") mbi = Mbi_EncryptedRamRtxxx( app=org_data, load_addr=0x12345678, trust_zone=TrustZone.disabled(), cert_block=cert_block, priv_key_data=priv_key_pem_data, hmac_key=user_key, key_store=key_store, ) assert mbi.export()
def test_invalid_key_store(): # invalid key store length with pytest.raises(SPSDKError): KeyStore(KeySourceType.KEYSTORE, bytes(range(10))) # key-store specified in OTP mode with pytest.raises(SPSDKError): KeyStore(KeySourceType.OTP, bytes(range(10))) with pytest.raises( SPSDKError, match="KeyStore can be initialized only if key_source == KEYSTORE" ): KeyStore(KeySourceType.OTP, bytes(1424)) key_store = KeyStore(KeySourceType.KEYSTORE, bytes([0] * KeyStore.KEY_STORE_SIZE)) with pytest.raises(SPSDKError, match="Invalid length of hmac key"): key_store.derive_hmac_key(hmac_key=bytes(31)) with pytest.raises(SPSDKError, match="Invalid length of master key"): key_store.derive_enc_image_key(master_key=bytes(31)) with pytest.raises(SPSDKError, match="Invalid length of master key"): key_store.derive_sb_kek_key(master_key=bytes(31)) with pytest.raises(SPSDKError, match="Invalid length of master key"): key_store.derive_otfad_kek_key(master_key=bytes(31), otfad_input=bytes(16)) with pytest.raises(SPSDKError, match="Invalid length of input"): key_store.derive_otfad_kek_key(master_key=bytes(32), otfad_input=bytes(15))
def test_key_store(): key_store = KeyStore(KeySourceType.KEYSTORE, bytes([0] * KeyStore.KEY_STORE_SIZE)) assert key_store.key_source == KeySourceType.KEYSTORE assert key_store.export() == bytes([0] * KeyStore.KEY_STORE_SIZE) key_store.info()