예제 #1
0
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)))
예제 #2
0
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()
예제 #3
0
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()
예제 #4
0
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)
예제 #5
0
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)
예제 #6
0
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()
예제 #7
0
    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
예제 #8
0
    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
예제 #9
0
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()
예제 #10
0
    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
예제 #11
0
    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())
예제 #12
0
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()
예제 #13
0
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()
예제 #14
0
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))
예제 #15
0
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()