tests/test_signer.py
2.8 KB · 85 lines · python Raw
1 """Tests for FirmwareSigner / FirmwareVerifier."""
2
3 from __future__ import annotations
4
5 import pytest
6
7 from pqc_bootloader.errors import FirmwareVerificationError
8 from pqc_bootloader.firmware import FirmwareImage
9 from pqc_bootloader.key_ring import KeyRing
10 from pqc_bootloader.signer import FirmwareSigner, FirmwareVerifier
11
12
13 def test_sign_populates_fields(
14 firmware_signer: FirmwareSigner, sample_firmware: FirmwareImage
15 ) -> None:
16 signed = firmware_signer.sign(sample_firmware)
17 assert signed.signature
18 assert signed.public_key
19 assert signed.signer_did.startswith("did:pqaid:")
20 assert signed.algorithm
21 assert signed.manufacturer_key_id == firmware_signer.key_id
22 assert signed.firmware.image_hash == sample_firmware.image_hash
23
24
25 def test_verify_valid(
26 firmware_signer: FirmwareSigner, sample_firmware: FirmwareImage
27 ) -> None:
28 signed = firmware_signer.sign(sample_firmware)
29 result = FirmwareVerifier.verify(signed)
30 assert result.valid is True
31 assert result.signature_valid is True
32 assert result.error is None
33
34
35 def test_hash_mismatch_detected_when_actual_bytes_supplied(
36 firmware_signer: FirmwareSigner, sample_firmware: FirmwareImage
37 ) -> None:
38 signed = firmware_signer.sign(sample_firmware)
39 tampered = sample_firmware.image_bytes + b"\xff"
40 result = FirmwareVerifier.verify(signed, actual_bytes=tampered)
41 assert result.valid is False
42 assert result.hash_consistent is False
43 assert "hash mismatch" in (result.error or "")
44
45
46 def test_signature_tamper_detected(
47 firmware_signer: FirmwareSigner, sample_firmware: FirmwareImage
48 ) -> None:
49 signed = firmware_signer.sign(sample_firmware)
50 # Flip a byte in the signature
51 sig_bytes = bytearray(bytes.fromhex(signed.signature))
52 sig_bytes[0] ^= 0xFF
53 signed.signature = sig_bytes.hex()
54 result = FirmwareVerifier.verify(signed)
55 assert result.valid is False
56 assert result.signature_valid is False
57
58
59 def test_key_ring_check_passes_for_trusted(
60 firmware_signer: FirmwareSigner,
61 sample_firmware: FirmwareImage,
62 trusted_key_ring: KeyRing,
63 ) -> None:
64 signed = firmware_signer.sign(sample_firmware)
65 result = FirmwareVerifier.verify(signed, key_ring=trusted_key_ring)
66 assert result.valid is True
67 assert result.key_trusted is True
68
69
70 def test_untrusted_signer_rejected_via_key_ring(
71 sample_firmware: FirmwareImage,
72 rogue_identity, # type: ignore[no-untyped-def]
73 trusted_key_ring: KeyRing,
74 ) -> None:
75 rogue_signer = FirmwareSigner(rogue_identity)
76 signed = rogue_signer.sign(sample_firmware)
77
78 result = FirmwareVerifier.verify(signed, key_ring=trusted_key_ring)
79 assert result.valid is False
80 assert result.key_trusted is False
81 assert "not trusted" in (result.error or "")
82
83 with pytest.raises(FirmwareVerificationError):
84 FirmwareVerifier.verify_or_raise(signed, key_ring=trusted_key_ring)
85