示例#1
0
def main() -> None:
    """Main."""
    # parse simple SB2.1 file generated by elftosb.exe
    with open(f"{DATA_DIR}/test_output_sb_2_1_from_elftosb.sb2", "rb") as f:
        sb_file = f.read()
    img_obj21 = BootImageV21.parse(sb_file, kek=KEK_VALUE)
    print(img_obj21.info())

    # parse SB2.1 file with OTFAD generated by elftosb.exe
    with open(f"{DATA_DIR}/otfad/test_output_sb_2_1_from_elftosb_OTFAD.sb2",
              "rb") as f:
        sb_file = f.read()
    img_obj21 = BootImageV21.parse(sb_file, kek=KEK_VALUE)
    print(img_obj21.info())

    # Generate not signed SB2.0 raw image
    raw_data_sb20_base = gen_boot_image_20_base()

    # Parse raw image
    img_obj20 = BootImageV20.parse(raw_data_sb20_base, kek=KEK_VALUE)
    print(img_obj20.info())

    # Generate signed SB2.0 raw image
    raw_data_sb20_signed = gen_boot_image_20()

    # Parse signed SB2.0 raw image
    img_obj20 = BootImageV20.parse(raw_data_sb20_signed, kek=KEK_VALUE)
    print(img_obj20.info())

    # Generate SB21 raw image
    raw_data_sb21_signed = gen_boot_image_21()

    # Parse raw image
    img_obj21 = BootImageV21.parse(raw_data_sb21_signed, kek=KEK_VALUE)
    print(img_obj21.info())
示例#2
0
def test_sb2_0_builder_validation(data_dir):
    """Validate exception from SB2.0 builder, if any required fields are not defined"""
    # create boot image
    boot_image = BootImageV20(True,
                              kek=kek_value,
                              product_version="1.0.0",
                              component_version="1.0.0",
                              build_number=1)

    # missing boot section
    with pytest.raises(SPSDKError):
        boot_image.export()

    for boot_sect in get_boot_sections(data_dir, False, SectionsContent.SIMPLE,
                                       0):
        boot_image.add_boot_section(boot_sect)

    # missing certificate block
    with pytest.raises(SPSDKError):
        boot_image.export()

    boot_image.cert_block = gen_cert_block(data_dir, 2048)
    # missing private key
    with pytest.raises(SPSDKError):
        boot_image.export()
示例#3
0
def build_sb(app: str, kek: bytes, address: int = 0) -> bytes:
    """Build a Secure Boot image.

    :param app: The application data
    :param kek: Key Encryption Key value
    :param address: Entry address for application
    :return: Serialized SB2.0 image
    """
    with open(app, "rb") as f:
        boot_data = f.read()

    boot_section = BootSectionV2(
        0,
        CmdErase(address, len(boot_data)),
        CmdLoad(address, boot_data),
        CmdReset(),
        hmac_count=10,
    )

    boot_image = BootImageV20(signed=False, kek=kek)
    boot_image.add_boot_section(boot_section)

    print(boot_image.info())

    return boot_image.export()
示例#4
0
def test_sb20_parser(data_dir):
    """Test parser"""
    with open(os.path.join(data_dir, "SB2.0_Not_Signed.sb2"), "rb") as file:
        img_obj = BootImageV20.parse(file.read(), kek=kek_value)

    assert isinstance(img_obj, BootImageV20)

    # check info() produces something
    assert img_obj.info()
示例#5
0
def gen_boot_image_20_base() -> bytes:
    """Generate SB2.0 image without signature."""
    # create boot section
    boot_section = gen_boot_section()
    # create boot image
    boot_image = BootImageV20(signed=False, kek=KEK_VALUE)
    boot_image.add_boot_section(boot_section)
    # print image info
    # print(boot_image.info())

    return boot_image.export()
示例#6
0
def test_invalid_boot_image_v2():
    with pytest.raises(SPSDKError, match="Invalid dek or mac"):
        BootImageV20(True,
                     kek=kek_value,
                     advanced_params=SBV2xAdvancedParams(dek=bytes(33),
                                                         mac=bytes(33)))
    bimg = BootImageV20(False, kek=kek_value)

    with pytest.raises(
            SPSDKError,
            match="Certificate block cannot be used unless SB file is signed"):
        bimg.cert_block = CertBlockV2()
    bimg = BootImageV20(True, kek=bytes(31))
    bimg.cert_block = None
    with pytest.raises(SPSDKError, match="Certification block not present"):
        bimg.raw_size_without_signature

    bimg = BootImageV20(True, kek=bytes(31))
    with pytest.raises(SPSDKError, match="Certification block not present"):
        bimg.raw_size
示例#7
0
def gen_boot_image_20() -> bytes:
    """Generate SB2.0 image with signature."""
    # create boot section
    boot_section = gen_boot_section()
    adv_params = SBV2xAdvancedParams(dek=DEK_VALUE, mac=MAC_VALUE)
    # create boot image
    boot_image = BootImageV20(
        signed=True,
        kek=KEK_VALUE,
        product_version="1.0.0",
        component_version="1.0.0",
        build_number=1,
        advanced_params=adv_params,
    )

    # add certificate block
    boot_image.cert_block = gen_cert_block()
    boot_image.private_key_pem_data = PRIVATE_KEY_PEM_DATA
    # add boot sections
    boot_image.add_boot_section(boot_section)
    # print image info
    # print(boot_image.info())

    return boot_image.export()
示例#8
0
def test_invalid_boot_image_v2_invalid_export():
    bimg = BootImageV20(True, kek=bytes(31))
    bimg._dek = bytes()
    with pytest.raises(SPSDKError, match="Invalid dek or mac"):
        bimg.export()
示例#9
0
def test_invalid_boot_section_v2():
    boot_img = BootImageV20(kek=kek_value, signed=False)
    with pytest.raises(SPSDKError):
        boot_img.add_boot_section(section=5)
示例#10
0
def test_sb2x_builder(
    data_dir: str,
    sb_minor_ver: int,
    sign_bits: int,
    otfad: bool,
    sect_cont: SectionsContent,
    load_addr: int,
):
    """Test SB2.x builder in several use-cases

    :param data_dir: absolute path to load data
    :param sb_minor_ver: 0 or 1 to select SB2.0 or SB2.1
    :param sign_bits: size of the signature in bits: 0 for unsigned; 2048 or 4096
    :param sect_cont: content of the sections to test
    :param load_addr: load address for simple section
    """
    assert sb_minor_ver in [0, 1]
    assert sign_bits in [0, 2048, 4096]
    signed = sign_bits != 0
    if (sb_minor_ver == 1) or otfad:
        assert signed

    # this is hardcoded in the test; if not specified, random values will be used
    dek_value = b"\xA0" * 32
    mac_value = b"\x0B" * 32

    # this is hardcoded in the test; if not specified, current value will be used
    timestamp = datetime.fromtimestamp(
        int(
            datetime(2020, month=1, day=31, hour=0,
                     tzinfo=timezone.utc).timestamp()))
    adv_params = SBV2xAdvancedParams(dek=dek_value,
                                     mac=mac_value,
                                     nonce=bytes(16),
                                     timestamp=timestamp)

    # create boot image
    if sb_minor_ver == 0:
        boot_image = BootImageV20(
            signed,
            kek=kek_value,
            product_version="1.0.0",
            component_version="1.0.0",
            build_number=1,
            # parameters fixed for test only, do not use in production
            advanced_params=adv_params,
        )
    else:
        boot_image = BootImageV21(
            kek=kek_value,
            product_version="1.0.0",
            component_version="1.0.0",
            build_number=1,
            # parameters fixed for test only, do not use in production
            advanced_params=adv_params,
            flags=0x0008,
        )

    if signed:
        boot_image.cert_block = gen_cert_block(data_dir, sign_bits)
        with open(
                os.path.join(
                    data_dir, "sb2_x",
                    "selfsign_privatekey_rsa" + str(sign_bits) + ".pem"),
                "rb",
        ) as keyf:
            key_data = keyf.read()
        boot_image.private_key_pem_data = key_data

    for sect in get_boot_sections(data_dir, otfad, sect_cont, load_addr):
        boot_image.add_boot_section(sect)

    result = boot_image.export(padding=bytes(
        8))  # padding is added for tests only, do not use for production:

    # test raw_size
    assert len(result) == boot_image.raw_size

    # check that info() prints anything
    assert boot_image.info()

    sect_cont_str = SectionsContent.name(sect_cont)
    if otfad:
        mode = "otfad"
    elif signed:
        mode = "signed" + str(sign_bits)
    else:
        mode = "unsigned"
    extected_file_name = f"expected_sb2_{str(sb_minor_ver)}_{sect_cont_str}_{mode}.sb2"

    with open(os.path.join(data_dir, "sb2_x", extected_file_name), "rb") as f:
        expected = f.read()

    if result != expected:  # if result does not match, save it for debugging
        with open(
                os.path.join(
                    data_dir, "sb2_x",
                    extected_file_name.replace("expected_", "generated_")),
                "wb",
        ) as f:
            f.write(result)

    assert result == expected