Exemplo n.º 1
0
def test_mode_stmt(input_text, throws_exception):
    parser = bd_parser.BDParser()

    try:
        retval = parser.parse(text=input_text)
        exception_thrown = False
        assert retval is not None
    except spsdk.SPSDKError:
        exception_thrown = True

    assert exception_thrown == throws_exception
Exemplo n.º 2
0
def test_extern(input_text, throws_exception, extern):
    """Test, that parser stops when extern() function is used and tries to
    reference a non-existing entry."""
    parser = bd_parser.BDParser()

    try:
        retval = parser.parse(text=input_text, extern=extern)
        exception_thrown = False
        assert retval is not None
    except spsdk.SPSDKError:
        exception_thrown = True

    assert exception_thrown == throws_exception
Exemplo n.º 3
0
def test_source_def_attr_list(input_text, throws_exception):
    """Test, that parser stops parsing when attribute lists in sources block
    are used, as these are not supported for now."""
    parser = bd_parser.BDParser()

    try:
        retval = parser.parse(text=input_text)
        exception_thrown = False
        assert retval is not None
    except spsdk.SPSDKError:
        exception_thrown = True

    assert exception_thrown == throws_exception
Exemplo n.º 4
0
def test_parser_return_none():
    """Test verifies, that on error an expection is raised."""
    text = r"""nonsense"""

    parser = bd_parser.BDParser()

    try:
        retval = parser.parse(text=text)
        exception_thrown = False
        assert retval is not None
    except spsdk.SPSDKError:
        exception_thrown = True

    assert exception_thrown == True
Exemplo n.º 5
0
def test_parser():
    """"""
    bd_file = r"""
# This BD configuration file serves as a minimal working example
# to test the python parser
    options {
        flags = 0x8; // bd file format: 0x8 encrypted + signed (always 0x8)
        buildNumber = 0x1;
        productVersion = "1.00.00";
        componentVersion = "1.00.00";
        secureBinaryVersion = "2.1";
    }
    sources {
        myImage = "data/sb_sources/output_images/application_signed.bin"; // Put location of Signed or UnSigned image input
        key_store = "data/sb_sources/key_store/key_store_rt5xx.bin";
        fcb_block = "data/sb_sources/input_images/rt500_oct_flash_fcb.bin";
    }
    keyblob (0) {
        (
            start = 0x08001000,
            end = 0x082013ff,
            key = "00112233445566778899001122334455",
            counter = "1122334455667788",
            byteSwap = false
        )
    }
    keyblob (1) {
        (
            start = 0x08201400,
            end = 0x082017FF,
            key = "aabbccddeeffaabbccddeeffaabbccdd",
            counter = "1122334455667788",
            byteSwap = false
        )
    }
    keyblob (2) {
        (
            start = 0x08201800,
            end = 0x08201BFF,
            key = "aabbccddeeffaabbccddeeffaabbcc11",
            counter = "1122334455667788",
            byteSwap = false
        )
    }
    keyblob (3) {
        (
            start = 0x08201C00,
            end = 0x08201FFF,
            key = "aabbccddeeffaabbccddeeffaabbcc22",
            counter = "1122334455667788",
            byteSwap = false
        )
    }

    constants {
        c1 = 1234;
        c2 = 0x80;
        c3 = 1 > 5;
    }

    section (0) {
        keystore_from_nv @9 0x08000800;
        load 0xc0403006 > 0x10C000; // Memory config word for Octal Flash
        enable @0x9 0x10C000;
        erase 0x8000000..0x8300000;  //0x8040000 Erase 3MB 0x300000 block at first ,
        keystore_to_nv @9 0x08000800;

        encrypt (0){
            load myImage > 0x08001000;
        }

        keywrap (0) {
            load {{00000000000000000000000000000000}} > 0x08000000;
        }

        keywrap (1) {
            load {{00000000000000000000000000000000}} > 0x08000100;
        }

        keywrap (2) {
            load {{00000000000000000000000000000000}} > 0x08000200;
        }

        keywrap (3) {
            load {{00000000000000000000000000000000}} > 0x08000300;
        }

        //load 0xf000000f > 0x10d000;
        //enable @0x9 0x10d000;       // Load new FCB by boot ROM code
        load fcb_block > 0x08000400;  // Load FCB block manually (workaround)

        load key_store > 0x08000800;  // Key Store will be copied to external Flash, offset 0x800

    }
    """

    expected_result = {
        "options": {
            "flags": 0x8,
            "buildNumber": 0x1,
            "productVersion": "1.00.00",
            "componentVersion": "1.00.00",
            "secureBinaryVersion": "2.1",
        },
        "keyblobs": [
            {
                "keyblob_id":
                0,
                "keyblob_content": [
                    {
                        "start": 0x08001000,
                        "end": 0x082013FF,
                        "key": "00112233445566778899001122334455",
                        "counter": "1122334455667788",
                        "byteSwap": 0,
                    },
                ],
            },
            {
                "keyblob_id":
                1,
                "keyblob_content": [{
                    "start": 0x08201400,
                    "end": 0x082017FF,
                    "key": "aabbccddeeffaabbccddeeffaabbccdd",
                    "counter": "1122334455667788",
                    "byteSwap": 0,
                }],
            },
            {
                "keyblob_id":
                2,
                "keyblob_content": [{
                    "start": 0x08201800,
                    "end": 0x08201BFF,
                    "key": "aabbccddeeffaabbccddeeffaabbcc11",
                    "counter": "1122334455667788",
                    "byteSwap": 0,
                }],
            },
            {
                "keyblob_id":
                3,
                "keyblob_content": [{
                    "start": 0x08201C00,
                    "end": 0x08201FFF,
                    "key": "aabbccddeeffaabbccddeeffaabbcc22",
                    "counter": "1122334455667788",
                    "byteSwap": 0,
                }],
            },
        ],
        "sections": [{
            "section_id":
            0,
            "options": {},
            "commands": [
                {
                    "keystore_from_nv": {
                        "mem_opt": 9,
                        "address": 0x08000800,
                        "length": 1
                    }
                },
                {
                    "fill": {
                        "pattern": 0xC0403006,
                        "address": 0x10C000,
                        "length": 1
                    }
                },
                {
                    "enable": {
                        "mem_opt": 0x9,
                        "address": 0x10C000
                    }
                },
                {
                    "erase": {
                        "address": 0x8000000,
                        "length": 0x300000
                    }
                },
                {
                    "keystore_to_nv": {
                        "mem_opt": 9,
                        "address": 0x08000800,
                        "length": 1
                    }
                },
                {
                    "encrypt": {
                        "keyblob_id": 0,
                        "load": {
                            "address": 0x08001000,
                            "file":
                            "data/sb_sources/output_images/application_signed.bin",
                            "length": 1,
                        },
                    }
                },
                {
                    "keywrap": {
                        "keyblob_id": 0,
                        "load": {
                            "address": 0x08000000,
                            "values": "00000000000000000000000000000000",
                        },
                    }
                },
                {
                    "keywrap": {
                        "keyblob_id": 1,
                        "load": {
                            "address": 0x08000100,
                            "values": "00000000000000000000000000000000",
                        },
                    }
                },
                {
                    "keywrap": {
                        "keyblob_id": 2,
                        "load": {
                            "address": 0x08000200,
                            "values": "00000000000000000000000000000000",
                        },
                    }
                },
                {
                    "keywrap": {
                        "keyblob_id": 3,
                        "load": {
                            "address": 0x08000300,
                            "values": "00000000000000000000000000000000",
                        },
                    }
                },
                {
                    "load": {
                        "file":
                        "data/sb_sources/input_images/rt500_oct_flash_fcb.bin",
                        "address": 0x08000400,
                        "length": 1,
                    }
                },
                {
                    "load": {
                        "file":
                        "data/sb_sources/key_store/key_store_rt5xx.bin",
                        "address": 0x08000800,
                        "length": 1,
                    }
                },
            ],
        }],
    }

    parser = bd_parser.BDParser()

    try:
        result = parser.parse(bd_file)
        exception_thrown = False
        assert expected_result == result
    except spsdk.SPSDKError:
        exception_thrown = True

    assert exception_thrown == False
Exemplo n.º 6
0
def generate_secure_binary_21(
    bd_file_path: click.Path,
    output_file_path: click.Path,
    key_file_path: click.Path,
    private_key_file_path: click.Path,
    signing_certificate_file_paths: List[click.Path],
    root_key_certificate_paths: List[click.Path],
    hoh_out_path: click.Path,
    external_files: List[click.Path],
) -> None:
    """Generate SecureBinary image from BD command file.

    :param bd_file_path: path to BD file.
    :param output_file_path: output path to generated secure binary file.
    :param key_file_path: path to key file.
    :param private_key_file_path: path to private key file for signing. This key
    relates to last certificate from signing certificate chain.
    :param signing_certificate_file_paths: signing certificate chain.
    :param root_key_certificate_paths: paths to root key certificate(s) for
    verifying other certificates. Only 4 root key certificates are allowed,
    others are ignored. One of the certificates must match the first certificate
    passed in signing_certificate_file_paths.
    :param hoh_out_path: output path to hash of hashes of root keys. If set to
    None, 'hash.bin' is created under working directory.
    :param external_files: external files referenced from BD file.

    :raises SPSDKError: If incorrect bf file is provided
    """
    # Create lexer and parser, load the BD file content and parse it for
    # further execution - the parsed BD file is a dictionary in JSON format
    with open(str(bd_file_path)) as bd_file:
        bd_file_content = bd_file.read()

    parser = bd_parser.BDParser()

    parsed_bd_file = parser.parse(text=bd_file_content, extern=external_files)
    if parsed_bd_file is None:
        raise SPSDKError(
            "Invalid bd file, secure binary file generation terminated")

    # The dictionary contains following content:
    # {
    #   options: {
    #       opt1: value,...
    #   },
    #   sections: [
    #       {section_id: value, options: {}, commands: {}},
    #       {section_id: value, options: {}, commands: {}}
    #   ]
    # }
    # TODO check, that section_ids differ in sections???

    # we need to encrypt and sign the image, let's check, whether we have
    # everything we need
    # It appears, that flags option in BD file are irrelevant for 2.1 secure
    # binary images regarding encryption/signing - SB 2.1 must be encrypted
    # and signed.
    # However, bit 15 represents, whether the final SB 2.1 must include a
    # SHA-256 of the botable section.
    flags = parsed_bd_file["options"].get(
        "flags", BootImageV21.FLAGS_SHA_PRESENT_BIT
        | BootImageV21.FLAGS_ENCRYPTED_SIGNED_BIT)
    if (private_key_file_path is None or signing_certificate_file_paths is None
            or root_key_certificate_paths is None):
        click.echo(
            "error: Signed image requires private key with -s option, "
            "one or more certificate(s) using -S option and one or more root key "
            "certificates using -R option")
        sys.exit(1)

    # Versions and build number are up to the user. If he doesn't provide any,
    # we set these to following values.
    product_version = parsed_bd_file["options"].get("productVersion", "")
    component_version = parsed_bd_file["options"].get("componentVersion", "")
    build_number = parsed_bd_file["options"].get("buildNumber", -1)

    if not product_version:
        product_version = "1.0.0"
        click.echo(
            "warning: production version not defined, defaults to '1.0.0'")

    if not component_version:
        component_version = "1.0.0"
        click.echo(
            "warning: component version not defined, defaults to '1.0.0'")

    if build_number == -1:
        build_number = 1
        click.echo("warning: build number not defined, defaults to '1.0.0'")

    if key_file_path is None:
        # Legacy elf2sb doesn't report no key provided, but this should
        # be definitely reported to tell the user, what kind of key is being
        # used
        click.echo("warning: no KEK key provided, using a zero KEK key")
        sb_kek = bytes.fromhex("0" * 64)
    else:
        with open(str(key_file_path)) as kek_key_file:
            # TODO maybe we should validate the key length and content, to make
            # sure the key provided in the file is valid??
            sb_kek = bytes.fromhex(kek_key_file.readline())

    # validate keyblobs and perform appropriate actions
    keyblobs = parsed_bd_file.get("keyblobs", [])

    # Based on content of parsed BD file, create a BootSectionV2 and assign
    # commands to them.
    # The content of section looks like this:
    # sections: [
    #   {
    #       section_id: <number>,
    #       options: {}, this is left empty for now...
    #       commands: [
    #           {<cmd1>: {<param1>: value, ...}},
    #           {<cmd2>: {<param1>: value, ...}},
    #           ...
    #       ]
    #   },
    #   {
    #       section_id: <number>,
    #       ...
    #   }
    # ]
    sb_sections = []
    bd_sections = parsed_bd_file["sections"]
    for bd_section in bd_sections:
        section_id = bd_section["section_id"]
        commands = []
        for cmd in bd_section["commands"]:
            for key, value in cmd.items():
                # we use a helper function, based on the key ('load', 'erase'
                # etc.) to create a command object. The helper function knows
                # how to handle the parameters of each command.
                # TODO Only load, fill, erase and enable commands are supported
                # for now. But there are few more to be supported...
                cmd_fce = elf2sb_helper21.get_command(key)
                if key in ("keywrap", "encrypt"):
                    keyblob = {"keyblobs": keyblobs}
                    value.update(keyblob)
                cmd = cmd_fce(value)
                commands.append(cmd)

        sb_sections.append(BootSectionV2(section_id, *commands))

    # We have a list of sections and their respective commands, lets create
    # a boot image v2.1 object
    secure_binary = BootImageV21(
        sb_kek,
        *sb_sections,
        product_version=product_version,
        component_version=component_version,
        build_number=build_number,
        flags=flags,
    )

    # create certificate block
    cert_block = CertBlockV2(build_number=build_number)
    for cert_path in signing_certificate_file_paths:
        cert_data = load_certificate_as_bytes(str(cert_path))
        cert_block.add_certificate(cert_data)
    for cert_idx, cert_path in enumerate(root_key_certificate_paths):
        cert_data = load_certificate_as_bytes(str(cert_path))
        cert_block.set_root_key_hash(cert_idx, Certificate(cert_data))

    # We have our secure binary, now we attach to it the certificate block and
    # the private key content
    # TODO legacy elf2sb doesn't require you to use certificates and private key,
    # so maybe we should make sure this is not necessary???
    # The -s/-R/-S are mandatory, 2.0 format not supported!!!
    secure_binary.cert_block = cert_block
    secure_binary.private_key_pem_data = load_binary(
        str(private_key_file_path))

    if hoh_out_path is None:
        hoh_out_path = os.path.join(os.getcwd(), "hash.bin")

    with open(str(hoh_out_path), "wb") as rkht_file:
        rkht_file.write(secure_binary.cert_block.rkht)

    with open(str(output_file_path), "wb") as sb_file_output:
        sb_file_output.write(secure_binary.export())

    click.echo(f"Success. (Secure binary 2.1: {output_file_path} created.)")