Esempio n. 1
0
def test_otfad_keyblob(data_dir):
    """ Test generation of key blob for OTFAD """
    # generate key blob using random keys
    key_blob = KeyBlob(start_addr=0x08001000, end_addr=0x0800F3FF)
    gen_blob = key_blob.export(kek=bytes.fromhex('50F66BB4F23B855DCD8FEFC0DA59E963'))
    assert gen_blob is not None
    # generate key blob using fixed keys
    key = bytes.fromhex('B1A0C56AF31E98CD6936A79D9E6F829D')
    counter = bytes.fromhex("5689fab8b4bfb264")
    zeros = bytes(4)  # zero_fill and crc are '0' just for this test; in reality should be random
    key_blob = KeyBlob(start_addr=0x08001000, end_addr=0x0800F3FF, key=key, counter_iv=counter,
                       zero_fill=zeros, crc=zeros)
    gen_blob = key_blob.export(kek=bytes.fromhex('50F66BB4F23B855DCD8FEFC0DA59E963'))

    with open(os.path.join(data_dir, 'otfad_keyblob.bin'), "rb") as f:
        keyblob_bin = f.read()
    assert gen_blob == keyblob_bin

    # check that info produces non-empty text
    assert key_blob.info()

    # test image encryption
    with open(os.path.join(data_dir, 'boot_image.bin'), "rb") as f:
        plain_image = f.read()
    encr_image = key_blob.encrypt_image(0x08001000, plain_image, True)
    with open(os.path.join(data_dir, 'otfad_image.bin'), "rb") as f:
        otfad_image = f.read()
    assert encr_image == otfad_image

    # check key blob is created with random bytes for zero_fill and crc
    key_blob = KeyBlob(start_addr=0x08001000, end_addr=0x0800F3FF, key=key, counter_iv=counter)
    gen_blob = key_blob.export(kek=bytes.fromhex('50F66BB4F23B855DCD8FEFC0DA59E963'))
    assert gen_blob != keyblob_bin

    # start address not aligned
    with pytest.raises(ValueError):
        KeyBlob(start_addr=0x08001001, end_addr=0x0800F3FF, key=key, counter_iv=counter)

    # end address not aligned
    with pytest.raises(ValueError):
        KeyBlob(start_addr=0x08001000, end_addr=0x0800F000, key=key, counter_iv=counter)

    # address of the image is not within key blob
    key_blob = KeyBlob(start_addr=0x08001000, end_addr=0x0800F3FF, key=key, counter_iv=counter)
    with pytest.raises(ValueError):
        key_blob.encrypt_image(0x8000000, plain_image, True)
    with pytest.raises(ValueError):
        key_blob.encrypt_image(0x800F000, plain_image, True)
Esempio n. 2
0
def test_keyblob_invalid():
    with pytest.raises(SPSDKError, match="Invalid start/end address"):
        KeyBlob(start_addr=0x08001000, end_addr=0x08000000)
    key = bytes.fromhex("B1")
    counter_iv = bytes.fromhex("53")
    with pytest.raises(SPSDKError, match="Invalid key"):
        KeyBlob(key=key,
                counter_iv=counter_iv,
                start_addr=0x08001000,
                end_addr=0x0800F3FF)
    with pytest.raises(SPSDKError, match="key_flags exceeds mask "):
        KeyBlob(start_addr=0x08000000, end_addr=0x080003FF, key_flags=0x8)
    counter = bytes.fromhex("5689fab8b4bfb264")
    key = bytes.fromhex("B1A0C56AF31E98CD6936A79D9E6F829D")
    key_blob = KeyBlob(start_addr=0x08001000,
                       end_addr=0x0800F3FF,
                       key=key,
                       counter_iv=counter)
    with pytest.raises(SPSDKError, match="Invalid length of kek"):
        key_blob.export(kek=bytes(15))
    with pytest.raises(SPSDKError, match="Invalid value crc"):
        key_blob = KeyBlob(start_addr=0x08001000,
                           end_addr=0x080013FF,
                           crc=bytes(5))
        key_blob.export(kek=bytes(16))
    with pytest.raises(SPSDKError, match="Invalid value"):
        key_blob = KeyBlob(start_addr=0x08001000,
                           end_addr=0x080013FF,
                           zero_fill=bytes(5))
        key_blob.export(kek=bytes(16))
    with pytest.raises(SPSDKError,
                       match="Invalid length of initialization vector"):
        key_blob = KeyBlob(start_addr=0x08001000, end_addr=0x080013FF)
        key_blob.export(kek=bytes(16), iv=bytes(32))
    with pytest.raises(SPSDKError,
                       match="Invalid length of data to be encrypted"):
        key_blob = KeyBlob(start_addr=0x08001000, end_addr=0x080013FF)
        key_blob._EXPORT_NBLOCKS_5 = 90
        key_blob.export(kek=bytes(16))
    key_blob = KeyBlob(start_addr=0x08001000,
                       end_addr=0x080013FF,
                       counter_iv=bytes(8))
    key_blob.ctr_init_vector = bytes(99)
    with pytest.raises(SPSDKError, match="Invalid length of counter init"):
        key_blob._get_ctr_nonce()
Esempio n. 3
0
def _keywrap(cmd_args: dict) -> CmdLoad:
    """Returns a CmdLoad object initialized based on cmd_args.

    Keywrap holds keyblob ID to be encoded by a value stored in load command and
    stored to address defined in the load command.

    e.g.
    keywrap (0) {
        load {{ 00000000 }} > 0x08000000;
    }

    :param cmd_args: dictionary holding list of keyblobs, keyblob ID and load dict
    :raises SPSDKError: If keyblob to be used is not in the list or is invalid
    :return: CmdLoad object
    """
    # iterate over keyblobs
    keyblobs = cmd_args.get("keyblobs", None)
    keyblob_id = cmd_args.get("keyblob_id", None)
    load_info = cmd_args.get("load", None)

    address = load_info.get("address")
    otfad_key = load_info.get("values")

    try:
        valid_keyblob = _validate_keyblob(keyblobs, keyblob_id)
    except SPSDKError as exc:
        raise SPSDKError(f" Key blob validation failed: {str(exc)}") from exc
    if valid_keyblob is None:
        raise SPSDKError(f"Missing keyblob {keyblob_id} for given keywrap")

    start_addr = valid_keyblob["keyblob_content"][0]["start"]
    end_addr = valid_keyblob["keyblob_content"][0]["end"]
    key = bytes.fromhex(valid_keyblob["keyblob_content"][0]["key"])
    counter = bytes.fromhex(valid_keyblob["keyblob_content"][0]["counter"])

    blob = KeyBlob(start_addr=start_addr,
                   end_addr=end_addr,
                   key=key,
                   counter_iv=counter)

    encoded_keyblob = blob.export(kek=otfad_key)
    print("creating wrapped keyblob")

    return CmdLoad(address=address, data=encoded_keyblob)
Esempio n. 4
0
def get_boot_sections(data_dir: str, otfad: bool, sect_cont: SectionsContent, load_addr: int) -> List[BootSectionV2]:
    """Create list of boot sections for SB 2.x file

    :param data_dir: absolute path to load boot image
    :param otfad: True to encrypt section with OTFAD; False otherwise
    :param sect_cont: sections content to test
    :param load_addr: address where to load the image (for simple section)
    :return:
    """
    result = list()

    # load input image (binary)
    with open(os.path.join(data_dir, 'sb2_x', 'boot_image.bin'), 'rb') as f:
        plain_image = f.read()

    # OTFAD
    key_blobs_data = list()
    if otfad:
        otfad = Otfad()
        # key blob 0
        key = bytes.fromhex('B1A0C56AF31E98CD6936A79D9E6F829D')
        counter = bytes.fromhex("5689fab8b4bfb264")
        key_blob = KeyBlob(0x08001000, 0x0800F3FF, key, counter,
                           zero_fill=bytes(4), crc=bytes(4))  # zero_fill and crc should be used only for testing !
        otfad.add_key_blob(key_blob)
        key_blobs_data = list()
        key_blobs_data.append(key_blob.export(kek=bytes.fromhex('50F66BB4F23B855DCD8FEFC0DA59E963')))
        # verify `otfad.encrypt_key_blobs` returns the same
        assert key_blobs_data[0] == otfad.encrypt_key_blobs(kek=bytes.fromhex('50F66BB4F23B855DCD8FEFC0DA59E963'))[:64]
        # key blob 1
        if sect_cont == SectionsContent.ADVANCED:
            key = bytes.fromhex('12345678901234567890123456789012')
            counter = bytes.fromhex("0011223344556677")
            key_blob1 = KeyBlob(0x08010000, 0x0801F3FF, key, counter,
                                zero_fill=bytes(4), crc=bytes(4))  # zero_fill and crc should be used only for testing !
            otfad.add_key_blob(key_blob1)
            key_blobs_data.append(key_blob1.export(kek=bytes.fromhex('0123456789ABCDEF0123456789ABCDEF')))
        # encrypted image
        encr_image = otfad.encrypt_image(plain_image, load_addr, True)
    else:
        encr_image = plain_image

    if sect_cont == SectionsContent.ADVANCED:
        # add boot sections 1 - advanced
        boot_section2 = BootSectionV2(
            1,
            CmdErase(address=0, length=0x2800),
            CmdLoad(address=0x10000000, data=plain_image),
            CmdLoad(address=0x20000000, data=plain_image),
            CmdCall(0xffff0000),
            CmdJump(0x12345678),
            CmdReset(),
            hmac_count=5)
        assert boot_section2.uid == 1
        result.append(boot_section2)

    # create boot section 0
    if sect_cont == SectionsContent.NEW_CMDS:
        boot_section0 = BootSectionV2(
            0,
            CmdVersionCheck(VersionCheckType.SECURE_VERSION, 0x16),
            CmdVersionCheck(VersionCheckType.NON_SECURE_VERSION, 15263),
            CmdErase(address=0, length=0x2800),
            CmdLoad(address=load_addr, data=encr_image),
            CmdKeyStoreBackup(0x12345678, 3),
            CmdKeyStoreRestore(0x12345678, 3),
            hmac_count=1)
    else:
        boot_section0 = BootSectionV2(
            0,
            CmdErase(address=0, length=0x2800),
            CmdLoad(address=load_addr, data=encr_image),
            hmac_count=10)
    for index, key_blob_data in enumerate(key_blobs_data):
        key_blob_aligned = align_block(key_blob_data, 256)  # it seems key-blob from elf-to-sb is aligned to 256
        boot_section0.append(CmdLoad(address=0x8000000 + 0x100 * index, data=key_blob_aligned))
    boot_section0.append(CmdReset())
    result.append(boot_section0)

    return result