Example #1
0
def write_sb(cpu_params: CpuParams, image_file_name: str, img: SecureBootV1) -> None:
    """Write SB image to the external flash
    The method behaviour depends on TEST_IMG_CONTENT:
    - if True (TEST MODE), the method generates the image and compare with previous version
    - if False (PRODUCTION), the method generates the image and burn into FLASH

    :param cpu_params: processor specific parameters of the test
    :param image_file_name: of the image to be written (including file extension)
    :param img: image instance to be written
    """
    path = os.path.join(cpu_params.data_dir, OUTPUT_IMAGES_SUBDIR, image_file_name)
    dbg_info = DebugInfo()
    img_data = img.export(dbg_info=dbg_info,
                          # use the following parameters only for unit test
                          header_padding8=b'\xdb\x00\x76\x7a\xf4\x81\x0b\x86',
                          auth_padding=b'\x36\x72\xf4\x99\x92\x05\x34\xd2\xd5\x17\xa0\xf7')
    write_dbg_log(cpu_params.data_dir, image_file_name, dbg_info.lines, TEST_IMG_CONTENT)
    if TEST_IMG_CONTENT:
        assert img.info()  # quick check info prints non-empty output
        compare_bin_files(path, img_data)
        img = SecureBootV1.parse(b'0' + img_data, 1)
        dbg_info2 = DebugInfo()
        img_data2 = img.export(dbg_info=dbg_info2, header_padding8=b'\xdb\x00\x76\x7a\xf4\x81\x0b\x86',
                               auth_padding=b'\x36\x72\xf4\x99\x92\x05\x34\xd2\xd5\x17\xa0\xf7')
        assert dbg_info.lines == dbg_info2.lines
        assert img_data == img_data2
    else:
        with open(path, 'wb') as f:
            f.write(img_data)

        mboot = init_flashloader(cpu_params)
        assert mboot.receive_sb_file(img_data)
        mboot.close()
Example #2
0
def test_sb_unsigned_otp(data_dir: str, subdir: str, image_name: str) -> None:
    """Test creation of SB file for RT5xx with unsigned image. SBKEK Key for SB file is stored in KEYSTORE.

    :param data_dir: absolute path of the directory with data files for the test
    :param image_name: file name of the unsigned image WITHOUT file extension
    """
    write_shadow_regs(data_dir,
                      [
                          (0x40130194, 0x00000000),  # BOOT_CFG[5]: USE_OTP = 0
                          # MASTER KEY - 000102030405060708090a0b0c0d0e0f00112233445566778899aabbccddeeff
                          (0x401301C0, 0xccddeeff),
                          (0x401301C4, 0x8899aabb),
                          (0x401301C8, 0x44556677),
                          (0x401301CC, 0x00112233),
                          (0x401301D0, 0x0c0d0e0f),
                          (0x401301D4, 0x08090a0b),
                          (0x401301D8, 0x04050607),
                          (0x401301DC, 0x00010203),
                      ])

    sbkek = KeyStore.derive_sb_kek_key(bytes.fromhex(MASTER_KEY))

    adv_params = SBV2xAdvancedParams(dek=b'\xA0' * 32, mac=b'\x0B' * 32, nonce=bytes(16),
                                     timestamp=datetime(2020, month=1, day=31))

    # create SB file boot image
    boot_image = BootImageV21(
        kek=sbkek,
        product_version='1.0.0', component_version='1.0.0', build_number=1,
        # parameters fixed for test only (to have always same output), do not use in production
        advanced_params=adv_params)

    # certificate + private key
    cert_block, priv_key_pem_data = create_cert_block(data_dir)
    boot_image.cert_block = cert_block
    boot_image.private_key_pem_data = priv_key_pem_data

    fcb_data = load_binary(data_dir, FCB_FILE_NAME)
    plain_image_data = load_binary(data_dir, subdir, image_name + '.bin')

    # images are aligned for test purposes only, otherwise export will align with random data
    fcb_data = align_block(fcb_data, 16)
    plain_image_data = align_block(plain_image_data, 16)

    # create boot section 0
    boot_section = BootSectionV2(
        0,
        CmdFill(address=0x10C000, pattern=bytes.fromhex('063040C0')),
        CmdMemEnable(0x10C000, 4, ExtMemId.FLEX_SPI_NOR),
        CmdErase(address=0x8000000, length=0x00800),
        CmdErase(address=0x8001000, length=0x10000),
        CmdLoad(address=0x8000400, data=fcb_data),
        CmdLoad(address=0x8001000, data=plain_image_data))
    boot_image.add_boot_section(boot_section)

    dbg_info = list()  # debug log for analysis of the binary output content
    sb_file = boot_image.export(padding=bytes(8), dbg_info=dbg_info)  # padding for unit test only, to avoid random data
    write_dbg_log(data_dir, image_name + '_otp.sb', dbg_info, TEST_IMG_CONTENT)
    write_sb(data_dir, image_name + '_otp.sb', sb_file, KeyStore(KeySourceType.OTP))
Example #3
0
def write_image(
        cpu_params: CpuParams,
        image_file_name: str,
        img: BootImgRT,
        otpmk_bee_regions: Tuple[BeeFacRegion, ...] = tuple(),
) -> None:
    """Write image to the external flash
    The method behaviour depends on TEST_IMG_CONTENT:
    - if True (TEST MODE), the method generates the image and compare with previous version
    - if False (PRODUCTION), the method generates the image and burn into FLASH

    :param cpu_params: processor specific parameters of the test
    :param image_file_name: of the image to be written (including file extension)
    :param img: image instance to be written
    :param otpmk_bee_regions: optional list of BEE regions for BEE OTPMK encryption
    """
    path = os.path.join(cpu_params.data_dir, OUTPUT_IMAGES_SUBDIR,
                        image_file_name)
    debug_info = DebugInfo()
    # use zulu datetime for test purposes only, to produce stable output; remove the parameter for production
    zulu = datetime(year=2020,
                    month=4,
                    day=8,
                    hour=5,
                    minute=54,
                    second=33,
                    tzinfo=timezone.utc)
    img_data = img.export(dbg_info=debug_info, zulu=zulu)
    assert len(img_data) == img.size
    write_dbg_log(cpu_params.data_dir, image_file_name, debug_info.lines,
                  TEST_IMG_CONTENT)
    if TEST_IMG_CONTENT:
        assert img.info()  # quick check info prints non-empty output
        compare_bin_files(path, img_data)
        # compare no-padding
        if (NO_PADDING and img.fcb.enabled and isinstance(img.fcb, PaddingFCB)
                and not img.bee_encrypted):
            img.fcb.enabled = False
            compare_bin_files(path.replace(".bin", "_nopadding.bin"),
                              img.export(zulu=zulu))
            img.fcb.enabled = False
        # test that parse image will return same content
        if img.fcb.enabled and not img.bee_encrypted:
            compare_bin_files(path, BootImgRT.parse(img_data).export())
            # test that size matches len of exported data
            assert img.size == len(img_data)
    else:
        with open(path, "wb") as f:
            f.write(img_data)
        if (NO_PADDING and img.fcb.enabled and isinstance(img.fcb, PaddingFCB)
                and not img.bee_encrypted):
            with open(path.replace(".bin", "_nopadding.bin"), "wb") as f:
                f.write(img_data[img.ivt_offset:])

        if img.ivt_offset == BootImgRT.IVT_OFFSET_NOR_FLASH:
            _burn_image_to_flash(cpu_params, img, img_data, otpmk_bee_regions)
        else:
            assert len(otpmk_bee_regions) == 0
            _burn_image_to_sd(cpu_params, img, img_data)
Example #4
0
def test_sb_unsigned_keystore(data_dir: str, subdir: str,
                              image_name: str) -> None:
    """Test creation of SB file for RT5xx with unsigned image. SBKEK Key for SB file is stored in KEYSTORE.

    :param data_dir: absolute path of the directory with data files for the test
    :param image_name: file name of the unsigned image WITHOUT file extension
    """
    if not TEST_IMG_CONTENT:
        write_shadow_regs(
            data_dir, [(0x40130194, 0x00000080)])  # BOOT_CFG[5]: USE_PUF = 1

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

    adv_params = SBV2xAdvancedParams(dek=b'\xA0' * 32,
                                     mac=b'\x0B' * 32,
                                     nonce=bytes(16),
                                     timestamp=datetime(2020, month=1, day=31))
    # create boot image
    boot_image = BootImageV21(
        kek=bytes.fromhex(sbkek_str),
        product_version='1.0.0',
        component_version='1.0.0',
        build_number=1,
        # parameters fixed for test only (to have always same output), do not use in production
        advanced_params=adv_params)

    # certificate + private key
    cert_block, priv_key_pem_data = create_cert_block(data_dir)
    boot_image.cert_block = cert_block
    boot_image.private_key_pem_data = priv_key_pem_data

    fcb_data = load_binary(data_dir, FCB_FILE_NAME)
    plain_image_data = load_binary(data_dir, subdir, image_name + '.bin')

    # images are aligned for test purposes only, otherwise export will align with random data
    fcb_data = align_block(fcb_data, 16)
    plain_image_data = align_block(plain_image_data, 16)

    # create boot section 0
    boot_section = BootSectionV2(
        0, CmdFill(address=0x10C000, pattern=bytes.fromhex('063040C0')),
        CmdMemEnable(0x10C000, 4, ExtMemId.FLEX_SPI_NOR),
        CmdErase(address=0x8000000, length=0x10000),
        CmdLoad(address=0x8000400, data=fcb_data),
        CmdLoad(address=0x8001000, data=plain_image_data))
    boot_image.add_boot_section(boot_section)

    dbg_info = list()  # debug log for analysis of the binary output content
    sb_file = boot_image.export(
        padding=bytes(8),
        dbg_info=dbg_info)  # padding for unit test only, to avoid random data
    write_dbg_log(data_dir, image_name + '_keystore.sb', dbg_info,
                  TEST_IMG_CONTENT)
    write_sb(data_dir, image_name + '_keystore.sb', sb_file,
             get_keystore(data_dir))
Example #5
0
def test_sb_otfad_keystore(data_dir: str, subdir: str, image_name: str,
                           secure: bool) -> None:
    """Test creation of SB file for RT5xx with OTFAD encrypted image. SBKEK Key for SB file is stored in KEYSTORE.

    :param data_dir: absolute path of the directory with data files for the test
    :param image_name: file name of the signed image WITHOUT file extension
    :param secure: whether security should be enabled
    """
    if not TEST_IMG_CONTENT:
        secure_boot_en = 0x900000 if secure else 0  # BOOT_CFG[0]: SECURE_BOOT_EN=?
        write_shadow_regis(
            data_dir,
            [
                (0x40130194, 0x00000080),  # BOOT_CFG[5]: USE_PUF = 1
                (0x401301A8, 0x00001000),  # OTFAD CFG
                (0x40130180, 0x00000010 +
                 secure_boot_en),  # BOOT_CFG[0]: DEFAULT_ISP = 1(USB)
            ],
        )

    with open(os.path.join(data_dir, KEYSTORE_SUBDIR, "SBkek_PUF.txt"),
              "r") as f:
        sbkek_str = f.readline()

    key_store = get_keystore(data_dir)

    adv_params = SBV2xAdvancedParams(
        dek=b"\xA0" * 32,
        mac=b"\x0B" * 32,
        nonce=bytes(16),
        timestamp=datetime(2020, month=1, day=31, hour=0, tzinfo=timezone.utc),
    )

    # create SB file boot image
    boot_image = BootImageV21(
        kek=bytes.fromhex(sbkek_str),
        product_version="1.0.0",
        component_version="1.0.0",
        build_number=1,
        # parameters fixed for test only (to have always same output), do not use in production
        advanced_params=adv_params,
        flags=0x0008,
    )

    # certificate + private key
    cert_block, priv_key_pem_data = create_cert_block(data_dir)
    boot_image.cert_block = cert_block
    boot_image.private_key_pem_data = priv_key_pem_data

    fcb_data = load_binary(data_dir, FCB_FILE_NAME)
    plain_image_data = load_binary(data_dir, subdir, image_name + ".bin")

    # images are aligned for test purposes only, otherwise export will align with random data
    fcb_data = align_block(fcb_data, 16)
    plain_image_data = align_block(plain_image_data, 16)

    otfad = Otfad()
    # keys used to encrypt image, for RT5xx always define 4 key blobs!!
    key = bytes.fromhex("B1A0C56AF31E98CD6936A79D9E6F829D")
    counter = bytes.fromhex("5689fab8b4bfb264")
    otfad.add_key_blob(
        KeyBlob(0x8001000,
                0x80FFFFF,
                key,
                counter,
                zero_fill=bytes(4),
                crc=bytes(
                    4)))  # zero_fill and crc should be used only for testing !
    # to use random keys: otfad.add_key_blob(KeyBlob(0x8001000, 0x80FFFFF))
    otfad.add_key_blob(
        KeyBlob(0x8FFD000,
                0x8FFDFFF,
                key,
                counter,
                zero_fill=bytes(4),
                crc=bytes(
                    4)))  # zero_fill and crc should be used only for testing !
    otfad.add_key_blob(
        KeyBlob(0x8FFE000,
                0x8FFEFFF,
                key,
                counter,
                zero_fill=bytes(4),
                crc=bytes(
                    4)))  # zero_fill and crc should be used only for testing !
    otfad.add_key_blob(
        KeyBlob(0x8FFF000,
                0x8FFFFFF,
                key,
                counter,
                zero_fill=bytes(4),
                crc=bytes(
                    4)))  # zero_fill and crc should be used only for testing !
    encr_image_data = otfad.encrypt_image(plain_image_data, 0x8001000, False)
    with open(os.path.join(data_dir, KEYSTORE_SUBDIR, "OTFADKek_PUF.txt"),
              "r") as f:
        otfad_kek = f.readline()

    # create boot section 0
    boot_section = BootSectionV2(
        0,
        # configure external FLASH
        CmdFill(address=0x10C000, pattern=int("063040C0", 16)),
        CmdMemEnable(0x10C000, 4, ExtMemId.FLEX_SPI_NOR),
        # erase the FLASH
        CmdErase(address=0x8000000, length=0x10000),
        # load key blobs allowing th decrypt the image
        CmdLoad(address=0x8000000,
                data=otfad.encrypt_key_blobs(kek=otfad_kek)),
        # load FCB data
        CmdLoad(address=0x8000400, data=fcb_data),
        # load key-store
        CmdLoad(address=0x8000800, data=key_store.export()),
        # load encrypted image
        CmdLoad(address=0x8001000, data=encr_image_data),
    )
    boot_image.add_boot_section(boot_section)

    dbg_info = list()  # debug log for analysis of the binary output content
    sb_file = boot_image.export(
        padding=bytes(8),
        dbg_info=dbg_info)  # padding for unit test only, to avoid random data
    write_dbg_log(data_dir, image_name + "_otfad_keystore.sb", dbg_info,
                  TEST_IMG_CONTENT)
    write_sb(data_dir, image_name + "_otfad_keystore.sb", sb_file, key_store)
Example #6
0
def test_sb_otfad_otp(data_dir: str, subdir: str, image_name: str,
                      secure: bool) -> None:
    """Test creation of SB file for RT5xx with OTFAD encrypted image.
    SBKEK Key for SB file is derived from master key in OTP.

    :param data_dir: absolute path of the directory with data files for the test
    :param image_name: file name of the signed image WITHOUT file extension
    :param secure: whether security should be enabled
    """
    if not TEST_IMG_CONTENT:
        secure_boot_en = 0x900000 if secure else 0  # BOOT_CFG[0]: SECURE_BOOT_EN=?
        write_shadow_regis(
            data_dir,
            [
                (0x401301A8, 0x00001000),  # OTFAD CFG
                # OTFAD KEY INPUT - 12aaaaaabb34bbbbcccc56ccdddddd78
                (0x401301B0, 0xAAAAAA12),
                (0x401301B4, 0xBBBB34BB),
                (0x401301B8, 0xCC56CCCC),
                (0x401301BC, 0x78DDDDDD),
            ],
        )
        write_shadow_regis(
            data_dir,
            [
                # MASTER KEY - 000102030405060708090a0b0c0d0e0f00112233445566778899aabbccddeeff
                (0x401301C0, 0xCCDDEEFF),
                (0x401301C4, 0x8899AABB),
                (0x401301C8, 0x44556677),
                (0x401301CC, 0x00112233),
                (0x401301D0, 0x0C0D0E0F),
                (0x401301D4, 0x08090A0B),
                (0x401301D8, 0x04050607),
                (0x401301DC, 0x00010203),
                # BOOT_CFG[0]: DEFAULT_ISP = 1(USB)
                (0x40130180, 0x00000010 + secure_boot_en),
            ],
        )

    sbkek = KeyStore.derive_sb_kek_key(bytes.fromhex(MASTER_KEY))
    otfad_kek = KeyStore.derive_otfad_kek_key(
        bytes.fromhex(MASTER_KEY),
        bytes.fromhex("12aaaaaabb34bbbbcccc56ccdddddd78"))

    key_store = get_keystore(data_dir)

    adv_params = SBV2xAdvancedParams(
        dek=b"\xA0" * 32,
        mac=b"\x0B" * 32,
        nonce=bytes(16),
        timestamp=datetime(2020, month=1, day=31, hour=0, tzinfo=timezone.utc),
    )

    # create SB file boot image
    boot_image = BootImageV21(
        kek=sbkek,
        product_version="1.0.0",
        component_version="1.0.0",
        build_number=1,
        # parameters fixed for test only (to have always same output), do not use in production
        advanced_params=adv_params,
        flags=0x0008,
    )

    # certificate + private key
    cert_block, priv_key_pem_data = create_cert_block(data_dir)
    boot_image.cert_block = cert_block
    boot_image.private_key_pem_data = priv_key_pem_data

    fcb_data = load_binary(data_dir, FCB_FILE_NAME)
    plain_image_data = load_binary(data_dir, subdir, image_name + ".bin")

    # images are aligned for test purposes only, otherwise export will align with random data
    fcb_data = align_block(fcb_data, 16)
    plain_image_data = align_block(plain_image_data, 16)

    otfad = Otfad()
    # keys used to encrypt image, for RT5xx always define 4 key blobs!!
    key = bytes.fromhex("B1A0C56AF31E98CD6936A79D9E6F829D")
    counter = bytes.fromhex("5689fab8b4bfb264")
    otfad.add_key_blob(
        KeyBlob(0x8001000,
                0x80FFFFF,
                key,
                counter,
                zero_fill=bytes(4),
                crc=bytes(
                    4)))  # zero_fill and crc should be used only for testing !
    # to use random keys: otfad.add_key_blob(KeyBlob(0x8001000, 0x80FFFFF))
    otfad.add_key_blob(
        KeyBlob(0x8FFD000,
                0x8FFDFFF,
                key,
                counter,
                zero_fill=bytes(4),
                crc=bytes(
                    4)))  # zero_fill and crc should be used only for testing !
    otfad.add_key_blob(
        KeyBlob(0x8FFE000,
                0x8FFEFFF,
                key,
                counter,
                zero_fill=bytes(4),
                crc=bytes(
                    4)))  # zero_fill and crc should be used only for testing !
    otfad.add_key_blob(
        KeyBlob(0x8FFF000,
                0x8FFFFFF,
                key,
                counter,
                zero_fill=bytes(4),
                crc=bytes(
                    4)))  # zero_fill and crc should be used only for testing !
    encr_image_data = otfad.encrypt_image(plain_image_data, 0x8001000, False)

    # create boot section 0
    boot_section = BootSectionV2(
        0,
        # configure external FLASH
        CmdFill(address=0x10C000, pattern=int("063040C0", 16)),
        CmdMemEnable(0x10C000, 4, ExtMemId.FLEX_SPI_NOR),
        # erase the FLASH
        CmdErase(address=0x8000000, length=0x10000),
        # load key blobs allowing th decrypt the image
        CmdLoad(address=0x8000000,
                data=otfad.encrypt_key_blobs(kek=otfad_kek)),
        # load FCB data
        CmdLoad(address=0x8000400, data=fcb_data),
        # load key-store
        CmdLoad(address=0x8000800, data=key_store.export()),
        # load encrypted image
        CmdLoad(address=0x8001000, data=encr_image_data),
    )
    boot_image.add_boot_section(boot_section)

    dbg_info = list()  # debug log for analysis of the binary output content
    sb_file = boot_image.export(
        padding=bytes(8),
        dbg_info=dbg_info)  # padding for unit test only, to avoid random data
    write_dbg_log(data_dir, image_name + "_otfad_otp.sb", dbg_info,
                  TEST_IMG_CONTENT)
    write_sb(data_dir, image_name + "_otfad_otp.sb", sb_file, key_store)