Example #1
0
def test_commands_validate():
    """Test of validation function for Secure Binary commands class."""
    with pytest.raises(KeyError):
        SecureBinary31Commands(curve_name=None)
    with pytest.raises(KeyError):
        SecureBinary31Commands(curve_name="Invalid")
    with pytest.raises(SPSDKError):
        SecureBinary31Commands(curve_name="secp256r1")

    SecureBinary31Commands(curve_name="secp256r1",
                           is_encrypted=False).validate()

    sb3c = SecureBinary31Commands(curve_name="secp256r1",
                                  pck=bytes(32),
                                  kdk_access_rights=1,
                                  timestamp=1)
    sb3c.key_derivator = None  # something broke key derivator
    with pytest.raises(SPSDKError):
        sb3c.validate()
Example #2
0
def test_sb31_commands_no_key_derivator():
    sc = SecureBinary31Commands(curve_name="secp256r1",
                                is_encrypted=True,
                                pck=bytes(16),
                                timestamp=5,
                                kdk_access_rights=3)
    sc.add_command(commands.CmdCall(0x100))
    sc.key_derivator = None
    with pytest.raises(SPSDKError, match="No key derivator"):
        sc.export()
Example #3
0
def test_sb31_commands_add():
    sc = SecureBinary31Commands(curve_name="secp256r1", is_encrypted=False)
    sc.add_command(commands.CmdCall(0x100))
    assert len(sc.commands) == 1
    info = sc.info()
    assert "CALL: Address=" in info
Example #4
0
def test_sb31_commands_errors():
    with pytest.raises(NotImplementedError):
        SecureBinary31Commands.parse(bytes(100))

    with pytest.raises(SPSDKError):
        SecureBinary31Commands(curve_name="secp384r1")
Example #5
0
def generate_secure_binary(container_conf: click.File) -> None:
    """Geneate SecureBinary image from json configuration file."""
    config_data = json.load(container_conf)
    config = elftosb_helper.SB31Config(config_data)
    timestamp = config.timestamp
    if timestamp is None:
        # in our case, timestamp is the number of seconds since "Jan 1, 2000"
        timestamp = int(
            (datetime.now() - datetime(2000, 1, 1)).total_seconds())
    if isinstance(timestamp, str):
        timestamp = int(timestamp, 0)

    final_data = bytes()
    assert isinstance(config.main_curve_name, str)
    # COMMANDS
    pck = None
    if config.is_encrypted:
        assert isinstance(config.container_keyblob_enc_key_path, str)
        pck = bytes.fromhex(load_text(config.container_keyblob_enc_key_path))
    sb_cmd_block = SecureBinary31Commands(
        curve_name=config.main_curve_name,
        is_encrypted=config.is_encrypted,
        kdk_access_rights=config.kdk_access_rights,
        pck=pck,
        timestamp=timestamp,
    )
    commands = elftosb_helper.get_cmd_from_json(config)
    sb_cmd_block.set_commands(commands)

    commands_data = sb_cmd_block.export()

    # CERTIFICATE BLOCK
    cert_block = _get_cert_block_v31(config)
    data_cb = cert_block.export()

    # SB FILE HEADER
    sb_header = SecureBinary31Header(firmware_version=config.firmware_version,
                                     description=config.description,
                                     curve_name=config.main_curve_name,
                                     timestamp=timestamp,
                                     is_nxp_container=config.is_nxp_container)
    sb_header.block_count = sb_cmd_block.block_count
    sb_header.image_total_length += len(sb_cmd_block.final_hash) + len(data_cb)
    # TODO: use proper signature len calculation
    sb_header.image_total_length += 2 * len(sb_cmd_block.final_hash)
    sb_header_data = sb_header.export()
    final_data += sb_header_data

    # HASH OF PREVIOUS BLOCK
    final_data += sb_cmd_block.final_hash
    final_data += data_cb

    # SIGNATURE
    assert isinstance(config.main_signing_key, str)
    private_key_data = load_binary(config.main_signing_key)
    data_to_sign = final_data
    signature = internal_backend.ecc_sign(private_key_data, data_to_sign)
    assert internal_backend.ecc_verify(private_key_data, signature,
                                       data_to_sign)
    final_data += signature
    final_data += commands_data

    write_file(final_data, config.container_output, mode='wb')
Example #6
0
    def create_sb3(self) -> None:
        """Do device hsm process to create SB_KEK provisioning SB file."""
        # 1: Call GEN_OEM_MASTER_SHARE to generate encOemShare.bin (ENC_OEM_SHARE will be later put in place of ISK)
        self.info_print(" 1: Generating OEM master share.")
        oem_enc_share, _, _ = self.oem_generate_master_share(self.oem_share_input)

        # 2: Call hsm_gen_key to generate 48 bytes FW signing key
        self.info_print(" 2: Generating 48 bytes FW signing keys.")
        cust_fw_auth_prk, cust_fw_auth_puk = self.generate_key(
            TrustProvOemKeyType.MFWISK, "CUST_FW_AUTH"
        )

        # 3: Call hsm_gen_key to generate 48 bytes FW encryption key
        self.info_print(" 3: Generating 48 bytes FW encryption keys.")
        cust_fw_enc_prk, _ = self.generate_key(TrustProvOemKeyType.MFWENCK, "CUST_FW_ENC_SK")

        # 4: Call hsm_store_key to generate user defined CUST_MK_SK (aka PCK).
        # Will be stored into PFR using loadKeyBlob SB3 command.
        # Use NXP_CUST_KEK_EXT_SK in SB json
        self.info_print(" 4: Wrapping user PCK key.")
        self.wrapped_user_pck = self.wrap_key(self.user_pck)

        # 5: Generate template sb3 fw, sb3ImageType=6
        self.info_print(" 5: Creating template un-encrypted SB3 header and data blobs.")
        # 5.1: Generate SB3.1 header template
        self.info_print(" 5.1: Creating template SB3 header.")
        sb3_header = SecureBinary31Header(
            firmware_version=self.sb3_fw_ver,
            curve_name="secp256r1",
            description=self.sb3_descr,
            timestamp=self.timestamp,
            flags=0x01,  # Bit0: PROV_MFW: when set, the SB3 file encrypts provisioning firmware
        )
        self.timestamp = sb3_header.timestamp
        sb3_header_exported = sb3_header.export()
        logger.debug(
            f" 5.1: The template SB3 header: \n{sb3_header.info()} \n Length:{len(sb3_header_exported)}"
        )

        # 5.2: Create SB3 file un-encrypted data part
        self.info_print(" 5.2: Creating un-encrypted SB3 data.")
        sb3_data = SecureBinary31Commands(
            curve_name="secp256r1", is_encrypted=False, timestamp=self.timestamp
        )
        sb3_data.add_command(
            CmdLoadKeyBlob(
                offset=0x04,
                data=self.wrapped_user_pck,
                key_wrap_id=CmdLoadKeyBlob.KeyWraps["NXP_CUST_KEK_EXT_SK"],
            )
        )
        sb3_data.load_from_config(self.get_cmd_from_config())

        logger.debug(f" 5.2: Created un-encrypted SB3 data: \n{sb3_data.info()}")
        # 5.3: Get SB3 file data part individual chunks
        data_cmd_blocks = sb3_data.get_cmd_blocks_to_export()

        # 6: Call hsm_enc_blk to encrypt all the data chunks from step 6. Use FW encryption key from step 3.
        self.info_print(" 6: Encrypting SB3 data on device")
        sb3_enc_data = self.encrypt_data_blocks(
            cust_fw_enc_prk, sb3_header_exported, data_cmd_blocks
        )
        # 6.1: Add to encrypted data parts SHA256 hashes
        self.info_print(" 6.1: Enriching encrypted SB3 data by mandatory hashes.")
        enc_final_data = sb3_data.process_cmd_blocks_to_export(sb3_enc_data)
        self.store_temp_res("Final_data.bin", enc_final_data, "to_merge")

        # 6.2: Create dummy certification part of SB3 manifest
        self.info_print(" 6.2: Creating dummy certificate block.")
        cb_header = CertificateBlockHeader()
        cb_header.cert_block_size = (
            cb_header.SIZE + 68 + self.DEVBUFF_GEN_MASTER_ENC_SHARE_OUTPUT_SIZE
        )
        logger.debug(f" 6.2: The dummy certificate block has been created:\n{cb_header.info()}.")

        # 6.3: Update the SB3 pre-prepared header by current data
        self.info_print(" 6.3: Updating SB3 header by valid values.")
        sb3_header.block_count = sb3_data.block_count
        sb3_header.image_total_length += (
            len(sb3_data.final_hash) + cb_header.cert_block_size + self.DEFBUFF_SB3_SIGNATURE_SIZE
        )
        logger.debug(
            f" 6.3: The SB3 header has been updated by valid values:\n{sb3_header.info()}."
        )

        # 6.4: Compose manifest that will be signed
        self.info_print(" 6.4: Preparing SB3 manifest to sign.")
        manifest_to_sign = bytes()
        manifest_to_sign += sb3_header.export()
        manifest_to_sign += sb3_data.final_hash
        manifest_to_sign += cb_header.export()
        manifest_to_sign += (
            b"\x11\x00\x00\x80"  # 0x80000011  Cert Flags: CA Flag, 1 certificate and NIST P-256
        )
        manifest_to_sign += cust_fw_auth_puk
        manifest_to_sign += oem_enc_share
        self.store_temp_res("manifest_to_sign.bin", manifest_to_sign, "to_merge")
        logger.debug(
            f" 6.4: The SB3 manifest data to sign:\n{format_raw_data(manifest_to_sign, use_hexdump=True)}."
        )

        # 7: Get sign of SB3 file manifest
        self.info_print(" 7: Creating SB3 manifest signature on device.")
        manifest_signature = self.sign_data_blob(manifest_to_sign, cust_fw_auth_prk)
        logger.debug(
            f" 7: The SB3 manifest signature data:\n{format_raw_data(manifest_signature, use_hexdump=True)}."
        )

        # 8: Merge all parts together
        self.info_print(" 8: Composing final SB3 file.")
        self.final_sb = bytes()
        self.final_sb += manifest_to_sign
        self.final_sb += manifest_signature
        self.final_sb += enc_final_data
        self.store_temp_res("Final_SB3.sb3", self.final_sb)
        logger.debug(
            f" 8: The final SB3 file data:\n{format_raw_data(self.final_sb, use_hexdump=True)}."
        )