Beispiel #1
0
def test_ram_encrypted_keystore(data_dir: str, image_file_name: str, ram_addr: int) -> None:
    """Test encrypted load-to-RAM image with key stored in key-store

    :param data_dir: absolute path with data files
    :param image_file_name: name of the input image file (including extension)
    :param ram_addr: address in RAM, where the image should be located
    """
    path = os.path.join(data_dir, INPUT_IMAGES_SUBDIR, image_file_name)
    org_data = load_binary(path)

    # load keystore with HMAC user key
    key_store = get_keystore(data_dir)

    cert_block, priv_key_pem_data = create_cert_block(data_dir)

    with open(os.path.join(data_dir, KEYSTORE_SUBDIR, 'userkey.txt'), 'r') as f:
        hmac_user_key = f.readline()

    mbi = MasterBootImage(app=org_data,
                          image_type=MasterBootImageType.ENCRYPTED_RAM_IMAGE,
                          load_addr=ram_addr,
                          trust_zone=TrustZone.disabled(),
                          cert_block=cert_block,
                          priv_key_pem_data=priv_key_pem_data,
                          hmac_key=hmac_user_key,
                          key_store=key_store,
                          ctr_init_vector=ENCR_CTR_IV)

    out_image_file_name = image_file_name.replace('_unsigned.bin', '_encr_keystore.bin')
    write_image(data_dir, out_image_file_name, mbi.export())
Beispiel #2
0
def test_ram_signed_otp(data_dir: str, image_file_name: str, ram_addr: int) -> None:
    """Create signed load-to-RAM image with keys stored in OTP

    :param data_dir: absolute path with data files
    :param image_file_name: name of the input image file (including extension)
    :param ram_addr: address in RAM, where the image should be located
    """
    # read unsigned image (must be built without boot header)
    path = os.path.join(data_dir, INPUT_IMAGES_SUBDIR, image_file_name)
    unsigned_img = load_binary(path)

    keystore = KeyStore(KeySourceType.OTP)

    cert_block, priv_key_pem_data = create_cert_block(data_dir)

    mbi = MasterBootImage(app=unsigned_img,
                          image_type=MasterBootImageType.SIGNED_RAM_IMAGE,
                          load_addr=ram_addr,
                          key_store=keystore,
                          hmac_key=MASTER_KEY,
                          trust_zone=TrustZone.disabled(),
                          cert_block=cert_block,
                          priv_key_pem_data=priv_key_pem_data)

    out_image_file_name = image_file_name.replace('_unsigned.bin', '_signed_otp.bin')
    write_image(data_dir, out_image_file_name, mbi.export())
Beispiel #3
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()
Beispiel #4
0
def test_signed_xip_multiple_certificates_invalid_input(data_dir):
    """Test invalid input for multiple certificates"""
    # indexed certificate is not specified
    der_file_names = ['selfsign_4096_v3.der.crt', 'selfsign_3072_v3.der.crt', 'selfsign_2048_v3.der.crt']
    with pytest.raises(IndexError):
        certificate_block(data_dir, der_file_names, 3)

    # indexed certificate is not specified
    der_file_names = ['selfsign_4096_v3.der.crt', None, 'selfsign_3072_v3.der.crt', 'selfsign_2048_v3.der.crt']
    with pytest.raises(ValueError):
        certificate_block(data_dir, der_file_names, 1)

    # public key in certificate and private key does not match
    der_file_names = ['selfsign_4096_v3.der.crt']
    cert_block = certificate_block(data_dir, der_file_names, 0)
    priv_key_pem_data = _load_private_key(data_dir, 'selfsign_privatekey_rsa2048.pem')
    with pytest.raises(ValueError):
        MasterBootImage(app=bytes(range(128)), load_addr=0, image_type=MasterBootImageType.SIGNED_XIP_IMAGE,
                        trust_zone=TrustZone.disabled(),
                        cert_block=cert_block, priv_key_pem_data=priv_key_pem_data).export()

    # chain of certificates does not match
    der_file_names = ['selfsign_4096_v3.der.crt']
    chain_certificates = ['ch3_crt2_v3.der.crt']
    with pytest.raises(ValueError):
        certificate_block(data_dir, der_file_names, 0, chain_certificates)
Beispiel #5
0
def test_multiple_images_with_relocation_table(data_dir):
    """Test image that contains multiple binary images and relocation table
    :param data_dir: absolute path, where test data are located
    """
    with open(os.path.join(data_dir, 'multicore', "testfffffff.bin"),
              "rb") as f:
        img_data = f.read()
    with open(os.path.join(data_dir, 'multicore', "normal_boot.bin"),
              "rb") as f:
        img1_data = f.read()
    with open(os.path.join(data_dir, 'multicore', "special_boot.bin"),
              "rb") as f:
        img2_data = f.read()

    with open(os.path.join(data_dir, 'multicore', "rt5xxA0.json"), "rb") as f:
        trust_zone_data = json.loads(f.read())['trustZonePreset']

    table = MultipleImageTable()
    table.add_entry(MultipleImageEntry(img1_data, 0x80000))
    table.add_entry(MultipleImageEntry(img2_data, 0x80600))

    mbi = MasterBootImage(app=img_data,
                          app_table=table,
                          load_addr=0,
                          image_type=MasterBootImageType.CRC_RAM_IMAGE,
                          trust_zone=TrustZone.custom('rt5xx',
                                                      trust_zone_data))

    assert _compare_image(mbi, os.path.join(data_dir, 'multicore'),
                          'expected_output.bin')
Beispiel #6
0
def test_signed_xip_certificates_chain_no_tz(data_dir, der_certificates,
                                             chain_certificates, priv_key,
                                             expected_mbi):
    """Test signed image with multiple certificates, different key length
    :param data_dir: absolute path, where test data are located
    :param der_certificates: list of filenames of der root certificates
    :param chain_certificates: list of filenames of der cerificates
    :param priv_key: private key filename
    :param expected_mbi: filename of expected bootable image
    """
    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, der_certificates, 0,
                                   chain_certificates)
    priv_key_pem_data = _load_private_key(data_dir, priv_key)

    mbi = MasterBootImage(app=org_data,
                          load_addr=0,
                          image_type=MasterBootImageType.SIGNED_XIP_IMAGE,
                          trust_zone=TrustZone.disabled(),
                          cert_block=cert_block,
                          priv_key_pem_data=priv_key_pem_data)

    assert _compare_image(mbi, data_dir, expected_mbi)
Beispiel #7
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)
Beispiel #8
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)
Beispiel #9
0
def test_xip_crc(data_dir: str, image_file_name: str) -> None:
    """ Create image with CRC

    :param data_dir: absolute path with data files
    :param image_file_name: name of the input image file (including extension)
    """
    assert image_file_name.endswith('_unsigned.bin')
    path = os.path.join(data_dir, INPUT_IMAGES_SUBDIR, image_file_name)
    unsigned_image = load_binary(path)

    mbi = MasterBootImage(app=unsigned_image,
                          load_addr=0x8001000,
                          image_type=MasterBootImageType.CRC_XIP_IMAGE)

    out_image_file_name = image_file_name.replace('_unsigned.bin', '_crc.bin')
    write_image(data_dir, out_image_file_name, mbi.export())
Beispiel #10
0
def test_ram_crc(data_dir: str, image_file_name: str, ram_addr: int) -> None:
    """ Create image with CRC

    :param data_dir: absolute path with data files
    :param image_file_name: name of the input image file (including extension)
    :param ram_addr: address in RAM, where the image should be located
    """
    assert image_file_name.endswith('_unsigned.bin')
    path = os.path.join(data_dir, INPUT_IMAGES_SUBDIR, image_file_name)
    unsigned_image = load_binary(path)

    mbi = MasterBootImage(app=unsigned_image,
                          load_addr=ram_addr,
                          image_type=MasterBootImageType.CRC_RAM_IMAGE)

    out_image_file_name = image_file_name.replace('_unsigned.bin', '_crc.bin')
    write_image(data_dir, out_image_file_name, mbi.export())
Beispiel #11
0
def _compare_image(mbi: MasterBootImage, data_dir: str, expected_mbi_filename: str) -> bool:
    """Compare generated image with expected image

    :param mbi: master boot image instance configured to generate image data
    :param expected_mbi_filename: file name of expected image
    :return: True if data are same; False otherwise
    """
    generated_image = mbi.export()

    with open(os.path.join(data_dir, expected_mbi_filename), "rb") as f:
        expected_data = f.read()

    if generated_image != expected_data:
        with open(os.path.join(data_dir, expected_mbi_filename + ".created"), "wb") as f:
            f.write(generated_image)
        return False

    assert mbi.export() == expected_data  # check additional call still generates the same data
    return True
Beispiel #12
0
def test_xip_signed(data_dir: str, image_file_name: str) -> None:
    """Create signed XIP image

    :param data_dir: absolute path with data files
    :param image_file_name: name of the input image file (including extension)
    """
    # read unsigned image (must be built without boot header)
    path = os.path.join(data_dir, INPUT_IMAGES_SUBDIR, image_file_name)
    unsigned_img = load_binary(path)

    cert_block, priv_key_pem_data = create_cert_block(data_dir)

    mbi = MasterBootImage(app=unsigned_img,
                          image_type=MasterBootImageType.SIGNED_XIP_IMAGE,
                          load_addr=0x8001000,
                          cert_block=cert_block,
                          priv_key_pem_data=priv_key_pem_data)

    out_image_file_name = image_file_name.replace('_unsigned.bin', '_signed.bin')
    write_image(data_dir, out_image_file_name, mbi.export())
Beispiel #13
0
def test_plain_xip_crc_default_tz(data_dir, input_img, expected_mbi):
    """Test plain image with CRC and default TZ-M
    :param data_dir: absolute path, where test data are located
    :param input_img: file name of input image (binary)
    :param expected_mbi: file name of MBI image file with expected data
    """
    with open(os.path.join(data_dir, input_img), "rb") as f:
        org_data = f.read()

    mbi = MasterBootImage(app=org_data, load_addr=0, image_type=MasterBootImageType.CRC_XIP_IMAGE,
                          trust_zone=TrustZone.enabled())

    assert _compare_image(mbi, data_dir, expected_mbi)
Beispiel #14
0
def test_base_info(data_dir):
    """Basic test for MasterBootImage - information """
    # plain image
    mbi = MasterBootImage(app=bytes(range(64)),
                          load_addr=0,
                          enable_hw_user_mode_keys=True)
    output = mbi.info()
    repr_strings = [
        "Master Boot Image", "Image type", "Image length", "TrustZone",
        'HW user mode keys'
    ]
    for req_string in repr_strings:
        assert req_string in output, f'string {req_string} is not in the output: {output}'
    # CRC image
    mbi = MasterBootImage(app=bytes(range(64)),
                          image_type=MasterBootImageType.CRC_RAM_IMAGE,
                          load_addr=0x1000)
    output = mbi.info()
    repr_strings = [
        "Master Boot Image", "Image type", "Image length", "TrustZone"
    ]
    for req_string in repr_strings:
        assert req_string in output, f'string {req_string} is not in the output: {output}'
    # signed image
    priv_key_pem_data = _load_private_key(data_dir, 'private_rsa4096.pem')
    cert_block = certificate_block(
        data_dir, ['selfsign_4096_v3.der.crt', 'selfsign_3072_v3.der.crt'], 0)
    mbi = MasterBootImage(app=bytes(range(64)),
                          load_addr=0x12345678,
                          image_type=MasterBootImageType.SIGNED_XIP_IMAGE,
                          trust_zone=TrustZone.custom(
                              "lpc55xx",
                              {"MPU Control Register.(cm33_mpu_ctrl)": "0x0"}),
                          cert_block=cert_block,
                          priv_key_pem_data=priv_key_pem_data)
    output = mbi.info()
    repr_strings = [
        "Master Boot Image", "Image type", "Image length", "TrustZone"
    ]
    for req_string in repr_strings:
        assert req_string in output, f'string {req_string} is not in the output: {output}'
Beispiel #15
0
def test_signed_xip_single_certificate_no_tz(data_dir, priv_key, der_certificate, expected_mbi):
    """Test signed XIP image with single certificate, different key length
    :param data_dir: absolute path, where test data are located
    :param priv_key: filename of private key used for signing
    :param der_certificate: filename of corresponding certificate in DER format
    :param expected_mbi: filename of expected bootable image
    """
    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, [der_certificate])
    priv_key_pem_data = _load_private_key(data_dir, priv_key)

    mbi = MasterBootImage(app=org_data, load_addr=0, image_type=MasterBootImageType.SIGNED_XIP_IMAGE,
                          trust_zone=TrustZone.disabled(),
                          cert_block=cert_block, priv_key_pem_data=priv_key_pem_data)

    assert _compare_image(mbi, data_dir, expected_mbi)
Beispiel #16
0
def test_plain_xip_crc_custom_tz(data_dir, input_img, tz_config, family, expected_mbi):
    """Test plain image with CRC and custom TZ-M
    :param data_dir: absolute path, where test data are located
    :param input_img: file name of input image (binary)
    :param tz_config: file name of trust-zone configuration JSON file
    :param family: identification of the processor for conversion of trust-zone data
    :param expected_mbi: file name of MBI image file with expected data
    """
    with open(os.path.join(data_dir, input_img), "rb") as f:
        org_data = f.read()
    with open(os.path.join(data_dir, expected_mbi), "rb") as f:
        expected_data = f.read()
    with open(os.path.join(data_dir, tz_config)) as f:
        tz_presets = json.load(f)["trustZonePreset"]

    mbi = MasterBootImage(app=org_data, load_addr=0, image_type=MasterBootImageType.CRC_XIP_IMAGE,
                          trust_zone=TrustZone(family=family, customizations=tz_presets))

    assert _compare_image(mbi, data_dir, expected_mbi)
Beispiel #17
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()