def test_registers_corrupted_xml(data_dir, tmpdir): regs = Registers(TEST_DEVICE_NAME) with use_working_directory(data_dir): regs.load_registers_from_xml("registers_corr.xml") with use_working_directory(tmpdir): regs.write_xml("registers_corr.xml") assert not filecmp.cmp(os.path.join(data_dir, "registers_corr.xml"), os.path.join(tmpdir, "registers_corr.xml")) regs.clear() with use_working_directory(tmpdir): regs.load_registers_from_xml("registers_corr.xml") regs.write_xml("registers_corr1.xml") assert filecmp.cmp(os.path.join(tmpdir, "registers_corr.xml"), os.path.join(tmpdir, "registers_corr1.xml")) # Without clear - Cannot add register with same name as is already added with use_working_directory(tmpdir): regs.load_registers_from_xml("registers_corr.xml") regs.write_xml("registers_corr1.xml") assert filecmp.cmp(os.path.join(tmpdir, "registers_corr.xml"), os.path.join(tmpdir, "registers_corr1.xml"))
def test_registers_corrupted_xml(data_dir): """Test registers XML support with invalid data.""" regs = Registers(TEST_DEVICE_NAME) with pytest.raises(SPSDKError): with use_working_directory(data_dir): regs.load_registers_from_xml("registers_corr.xml") with pytest.raises(SPSDKError): with use_working_directory(data_dir): regs.load_registers_from_xml("registers_corr2.xml")
def test_registers_xml(data_dir, tmpdir): regs = Registers(TEST_DEVICE_NAME) with use_working_directory(data_dir): regs.load_registers_from_xml("registers.xml") with use_working_directory(tmpdir): regs.write_xml("registers.xml") regs2 = Registers(TEST_DEVICE_NAME) with use_working_directory(tmpdir): regs2.load_registers_from_xml("registers.xml") assert str(regs) == str(regs2)
def test_elftosb_trustzone_basic(data_dir, tmpdir): runner = CliRunner() with use_working_directory(tmpdir): cmd = f"--tzm-conf {data_dir}/lpc55xxA1.json" result = runner.invoke(elftosb.main, cmd.split()) assert os.path.isfile(f"{tmpdir}/lpc55xxA1_tzFile.bin") assert filecmp.cmp(f"{data_dir}/lpc55xxA1_tzFile.bin", f"{tmpdir}/lpc55xxA1_tzFile.bin")
def test_debugcredential_ecc_compare_with_reference(data_dir): """Loads the yaml file, creates the debug credential, saves to a file and compares with reference.""" with use_working_directory(data_dir): with open("new_dck_secp256.yml", 'r') as f: yaml_config = yaml.safe_load(f) dc = DebugCredential.create_from_yaml_config( version='2.0', yaml_config=yaml_config) dc.sign() data = dc.export() pub_key = load_private_key(yaml_config['rotk']).public_key() data_without_singature = data[:-132] signature_bytes = data[-132:] with open('new_dck_secp256r1.cert', 'rb') as f: data_loaded = f.read() ref_data_without_signature = data_loaded[:-132] ref_signature_bytes = data_loaded[-132:] assert data_without_singature == ref_data_without_signature, \ "The generated dc binary and the referenced one are not the same." signature = utils.reconstruct_signature(signature_bytes) ref_signature = utils.reconstruct_signature(ref_signature_bytes) try: pub_key.verify(signature, data_without_singature, ec.ECDSA(hashes.SHA256())) pub_key.verify(ref_signature, data_without_singature, ec.ECDSA(hashes.SHA256())) assert True except InvalidSignature: assert False
def test_parse(data_dir, dc_file_name, class_name): """Verifies the parse mechanisms on DC files.""" with use_working_directory(data_dir): with open(dc_file_name, "rb") as f: dc_file = f.read() dc = DebugCredential.parse(dc_file) assert dc.__class__.__name__ == class_name
def test_elftosb_mbi_legacy_signed(data_dir, tmpdir, config_file, device, skip_hmac_keystore): runner = CliRunner() with use_working_directory(data_dir): config_file = f"{data_dir}/workspace/cfgs/{device}/{config_file}" ref_binary, new_binary, new_config = process_config_file( config_file, tmpdir) cmd = f"--image-conf {new_config}" result = runner.invoke(elftosb.main, cmd.split()) assert result.exit_code == 0 assert os.path.isfile(new_binary) # validate file lengths with open(ref_binary, "rb") as f: ref_data = f.read() with open(new_binary, "rb") as f: new_data = f.read() assert len(ref_data) == len(new_data) # validate signatures with open(new_config, "r") as f: config_data = json.load(f) signing_certificate_file_path = config_data["mainCertPrivateKeyFile"] with open(signing_certificate_file_path, "rb") as f: cert = f.read() signing_key = RSA.import_key(cert) modulus = signing_key.n exponent = signing_key.e signature_length = int(len(f"{modulus:x}") / 2) hmac_start = 0 hmac_end = 0 # skip_hmac_keystore # 0 no hmac/keystore # 1 hmac present # 2 hmac & keystore present if skip_hmac_keystore: hmac_start = Mbi_MixinHmac.HMAC_OFFSET gap_len = Mbi_MixinHmac.HMAC_SIZE gap_len += KeyStore.KEY_STORE_SIZE if skip_hmac_keystore == 2 else 0 hmac_end = hmac_start + gap_len assert internal_backend.rsa_verify( modulus, exponent, new_data[-signature_length:], new_data[:hmac_start] + new_data[hmac_end:-signature_length], ) assert internal_backend.rsa_verify( modulus, exponent, ref_data[-signature_length:], ref_data[:hmac_start] + ref_data[hmac_end:-signature_length], ) # validate data before signature assert ref_data[:-signature_length] == new_data[:-signature_length]
def test_force_subdir(tmpdir): with use_working_directory(tmpdir): result = CliRunner().invoke(main, '-p 1.0 genkey tmp/key'.split()) # should fail due to non-existing subfolder assert result.exit_code == 1 result = CliRunner().invoke(main, '-p 1.0 genkey tmp/key --force'.split()) assert result.exit_code == 0 assert os.path.isfile('tmp/key')
def test_lpc55s3x_export_parse_invalid(data_dir): with use_working_directory(data_dir): with open("new_dck_secp256_lpc55s3x.yml", "r") as f: yaml_config = yaml.safe_load(f) dc = DebugCredential.create_from_yaml_config(version="2.0", yaml_config=yaml_config) dc.sign() with pytest.raises(SPSDKError, match="Invalid flag"): dc.parse(bytes(232))
def test_generate_ecc_dc_file(tmpdir, data_dir): """Test generate dc file with ecc protocol.""" out_file = f'{tmpdir}/dc_secp256r1.cert' cmd = f'-p 2.0 gendc -c new_dck_secp256.yml {out_file}' with use_working_directory(data_dir): runner = CliRunner() result = runner.invoke(main, cmd.split()) assert result.exit_code == 0, result.output assert os.path.isfile(out_file)
def test_generate_rsa_dc_file(tmpdir, data_dir): """Test generate dc file with rsa 2048 protocol.""" out_file = f"{tmpdir}/dc_2048.cert" cmd = f"gendc -c new_dck_rsa2048.yml -p 1.0 {out_file}" with use_working_directory(data_dir): runner = CliRunner() result = runner.invoke(main, cmd.split()) assert result.exit_code == 0, result.output assert os.path.isfile(out_file)
def test_generate_dc_file_lpc55s3x_384(tmpdir, data_dir): """Test generate dc file with ecc protocol for lpc55s3x""" out_file = f"{tmpdir}/dc_secp384r1_lpc55s3x.cert" cmd = f"gendc -p 2.1 -c new_dck_secp384_lpc55s3x.yml {out_file}" with use_working_directory(data_dir): runner = CliRunner() result = runner.invoke(main, cmd.split()) assert result.exit_code == 0, result.output assert os.path.isfile(out_file)
def test_elftosb_mbi_invalid_conf(data_dir, tmpdir, config_file, device): runner = CliRunner() with use_working_directory(data_dir): config_file = f"{data_dir}/workspace/cfgs/{device}/{config_file}" _, _, new_config = process_config_file(config_file, tmpdir) cmd = f"--image-conf {new_config}" result = runner.invoke(elftosb.main, cmd.split()) assert result.exit_code == 1
def test_nxpkeygen_plugin(tmpdir, data_dir): out_dc = f"{tmpdir}/file.dc" cmd = f"gendc -c plugin_dck_rsa_2048.yml --plugin signature_provider.py {out_dc}" with use_working_directory(data_dir): result = CliRunner().invoke(nxpdebugmbox.main, cmd.split()) assert result.exit_code == 0, result.output with open(out_dc, "rb") as f: dc_data = f.read() assert dc_data[-256:] == 256 * b"x"
def test_elftosb_mbi_signed(data_dir, tmpdir, config_file): runner = CliRunner() with use_working_directory(data_dir): config_file = f"{data_dir}/{config_file}" ref_binary, new_binary, new_config = process_config_file( config_file, tmpdir) cmd = f"--image-conf {new_config}" result = runner.invoke(elftosb.main, cmd.split()) assert os.path.isfile(new_binary)
def test_debugcredential_info(data_dir): """Verifies the info message for debug authentication.""" with use_working_directory(data_dir): with open("new_dck_secp256.yml", 'r') as f: yaml_config = yaml.safe_load(f) dc = DebugCredentialECC.from_yaml_config(version='2.0', yaml_config=yaml_config) output = dc.info() req_strings = ["Version", "SOCC", "UUID", "UUID", "CC_SOCC", "CC_VU", "BEACON"] for req_string in req_strings: assert req_string in output, f'string {req_string} is not in the output: {output}'
def test_lpc55s3x_export_parse(data_dir, yml_file_name, version): """Verifies the signature for lpc55s3x for different versions.""" with use_working_directory(data_dir): with open(yml_file_name, "r") as f: yaml_config = yaml.safe_load(f) dc = DebugCredential.create_from_yaml_config(version=version, yaml_config=yaml_config) dc.sign() data = dc.export() dc_parsed = dc.parse(data) assert dc == dc_parsed
def test_force_actual_dir(tmpdir): with use_working_directory(tmpdir): result = CliRunner().invoke(main, '-p 1.0 genkey key'.split()) assert result.exit_code == 0 # attempt to rewrite the key should fail result = CliRunner().invoke(main, '-p 1.0 genkey key'.split()) assert result.exit_code == 1 # attempt to rewrite should pass due to --forces result = CliRunner().invoke(main, '-p 1.0 genkey key --force'.split()) assert result.exit_code == 0
def test_debugcredential_invalid(data_dir): """Evoke exceptions.""" with use_working_directory(data_dir): with open("new_dck_rsa2048.yml", "r") as f: yaml_config = yaml.safe_load(f) dc = DebugCredential.create_from_yaml_config(version="1.0", yaml_config=yaml_config) with pytest.raises(SPSDKError, match="Debug Credential Signature is not set"): dc.export() with pytest.raises(SPSDKError, match="Debug Credential Signature provider is not set"): dc.signature_provider = None dc.sign()
def test_registers_xml_hidden(data_dir, tmpdir): """Test registers XML support.""" regs = Registers(TEST_DEVICE_NAME) with use_working_directory(data_dir): regs.load_registers_from_xml("registers_reserved.xml") assert len(regs.get_registers()[0].get_bitfields()) == 1 assert regs.get_registers()[0].get_bitfields()[0].get_value() == 0xA assert regs.get_registers()[0].get_value() == 0x550A00 with use_working_directory(tmpdir): regs.write_xml("registers_reserved.xml") regs2 = Registers(TEST_DEVICE_NAME) with use_working_directory(tmpdir): regs2.load_registers_from_xml("registers_reserved.xml") assert str(regs) == str(regs2)
def test_elftosb_mbi_signed(data_dir, tmpdir, config_file, device, sign_digest): runner = CliRunner() with use_working_directory(data_dir): config_file = f"{data_dir}/workspace/cfgs/{device}/{config_file}" ref_binary, new_binary, new_config = process_config_file( config_file, tmpdir) cmd = f"--image-conf {new_config}" result = runner.invoke(elftosb.main, cmd.split()) assert os.path.isfile(new_binary) # validate file lengths with open(ref_binary, "rb") as f: ref_data = f.read() with open(new_binary, "rb") as f: new_data = f.read() assert len(ref_data) == len(new_data) # validate signatures signing_key = get_signing_key(config_file=config_file) signature_length = 2 * signing_key.pointQ.size_in_bytes() if sign_digest: sign_offset = 32 if sign_digest and sign_digest == "sha256" else 48 assert internal_backend.ecc_verify( signing_key, new_data[-(signature_length + sign_offset):-sign_offset], new_data[:-(signature_length + sign_offset)], ) assert internal_backend.ecc_verify( signing_key, ref_data[-(signature_length + sign_offset):-sign_offset], ref_data[:-(signature_length + sign_offset)], ) # validate data before signature assert (ref_data[:-(signature_length + sign_offset)] == new_data[:-(signature_length + sign_offset)]) # validate signature digest assert (internal_backend.hash( new_data[:-sign_offset], sign_digest) == new_data[-sign_offset:]) assert (internal_backend.hash( ref_data[:-sign_offset], sign_digest) == ref_data[-sign_offset:]) else: assert internal_backend.ecc_verify(signing_key, new_data[-signature_length:], new_data[:-signature_length]) assert internal_backend.ecc_verify(signing_key, ref_data[-signature_length:], ref_data[:-signature_length]) # validate data before signature assert ref_data[:-signature_length] == new_data[:-signature_length]
def test_key_types(tmpdir, key, valid): with use_working_directory(tmpdir): if valid: result = CliRunner().invoke(main, f"-k {key} my_key_{key}.pem") assert result.exit_code == 0 assert os.path.isfile(f"my_key_{key}.pem") assert os.path.isfile(f"my_key_{key}.pub") else: result = CliRunner().invoke(main, f"-k {key} my_key_{key}.pem") assert result.exit_code != 0
def test_elftosb_sb31(data_dir, tmpdir, config_file, device): runner = CliRunner() with use_working_directory(data_dir): config_file = f"{data_dir}/workspace/cfgs/{device}/{config_file}" ref_binary, new_binary, new_config = process_config_file( config_file, tmpdir, "containerOutputFile") cmd = f"--container-conf {new_config}" result = runner.invoke(elftosb.main, cmd.split()) assert result.exit_code == 0 assert os.path.isfile(new_binary) assert filecmp.cmp(ref_binary, new_binary, shallow=False)
def test_debugcredential_rsa_compare_with_reference(data_dir): """Loads the yaml file, creates the debug credential, saves to a file and compares with reference.""" with use_working_directory(data_dir): with open("new_dck_rsa2048.yml", 'r') as f: yaml_config = yaml.safe_load(f) dc = DebugCredentialRSA.from_yaml_config(version='1.0', yaml_config=yaml_config) data = dc.export() with open('sample.cert', 'wb') as f: f.write(data) with open('new_dck_rsa2048.cert', 'rb') as f: data_loaded = f.read() assert data == data_loaded, "The generated dc binary and the referenced one are not the same."
def test_extract_public_key(data_dir): """Test extraction of public key""" public_key_data = read_file(data_dir, 'public.pem', 'rb') public_key = load_pem_public_key(public_key_data, default_backend()) public_nums = public_key.public_numbers() with use_working_directory(data_dir): numbers = _extract_public_key('public.pem', password=None).public_numbers() assert public_nums == numbers numbers = _extract_public_key('private.pem', password=None).public_numbers() assert public_nums == numbers numbers = _extract_public_key('cert.pem', password=None).public_numbers() assert public_nums == numbers
def test_debugcredential_rot_meta_as_cert(data_dir): """Verifies the info message for debug authentication.""" with use_working_directory(data_dir): with open("dck_rsa2048_rot_meta_cert.yml", "r") as f: yaml_config = yaml.safe_load(f) dc = DebugCredential.create_from_yaml_config(version="1.0", yaml_config=yaml_config) dc.sign() assert dc.VERSION == "1.0" assert dc.cc_beacon == 0 assert dc.cc_socu == 1023 assert dc.cc_vu == 22136 assert dc.socc == 1 assert dc.uuid == b"\xe0\x04\t\x0ek\xdd!U\xbb\xce\x9e\x06e\x80[\xe3"
def test_generate_rsa_with_elf2sb(tmpdir, data_dir): org_file = f"{tmpdir}/org.dc" new_file = f"{tmpdir}/new.dc" cmd1 = f"gendc -p 1.0 -c org_dck_rsa_2048.yml {org_file}" # keys were removed from yaml and suplied by elf2sb config cmd2 = f"gendc -p 1.0 -c no_key_dck_rsa_2048.yml -e elf2sb_config.json {new_file}" with use_working_directory(data_dir): result = CliRunner().invoke(main, cmd1.split()) assert result.exit_code == 0, result.output result = CliRunner().invoke(main, cmd2.split()) assert result.exit_code == 0, result.output assert filecmp.cmp(org_file, new_file)
def test_debugcredential_info_lpc55s3x(data_dir, yml_file_name, version, required_values): """Verifies the info message for debug authentication.""" with use_working_directory(data_dir): with open(yml_file_name, "r") as f: yaml_config = yaml.safe_load(f) dc = DebugCredential.create_from_yaml_config(version=version, yaml_config=yaml_config) dc.sign() output = dc.info() req_strings = ["Version", "SOCC", "UUID", "UUID", "CC_SOCC", "CC_VU", "BEACON"] req_values = required_values for req_string in req_strings: assert req_string in output, f"string {req_string} is not in the output: {output}" for req_value in req_values: assert req_value in output, f"string {req_value} is not in the output: {output}"
def test_elftosb_mbi_basic(data_dir, tmpdir, config_file, device): runner = CliRunner() with use_working_directory(data_dir): config_file = f"{data_dir}/workspace/cfgs/{device}/{config_file}" ref_binary, new_binary, new_config = process_config_file( config_file, tmpdir) cmd = f"--image-conf {new_config}" result = runner.invoke(elftosb.main, cmd.split()) if result.exit_code != 0: assert isinstance(result.exception, SPSDKUnsupportedImageType) else: assert os.path.isfile(new_binary) assert filecmp.cmp(new_binary, ref_binary)
def test_dar_packet_rsa(tmpdir, data_dir): with use_working_directory(data_dir): dac_bytes = load_binary(os.path.join(data_dir, 'sample_dac.bin')) with open(os.path.join(data_dir, "new_dck_rsa2048.yml"), 'r') as f: yaml_config = yaml.safe_load(f) dc = DebugCredentialRSA.from_yaml_config(version='1.0', yaml_config=yaml_config) dar = DebugAuthenticateResponseRSA(debug_credential=dc, auth_beacon=0, dac=dac_bytes, path_dck_private=os.path.join( data_dir, 'new_dck_2048.pem')) dar_bytes = dar.export() assert len(dar_bytes) == 1200 assert isinstance(dar_bytes, bytes) assert 'Authentication Beacon' in dar.info()