Skip to content

Commit 67aafc2

Browse files
committed
Raise exception on wrong root hash
1 parent 45025b8 commit 67aafc2

2 files changed

Lines changed: 39 additions & 3 deletions

File tree

autograph_utils/__init__.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,19 @@ def detail(self):
128128
return f"Certificate expired on {self.not_after}"
129129

130130

131+
class CertificateHasWrongRoot(BadCertificate):
132+
def __init__(self, *, expected, actual):
133+
self.expected = binascii.hexlify(expected).decode()
134+
self.actual = binascii.hexlify(actual).decode()
135+
136+
@property
137+
def detail(self):
138+
return (
139+
"Certificate is not based on expected root hash. "
140+
f"Got '{self.actual}' expected '{self.expected}'"
141+
)
142+
143+
131144
class CertificateHasWrongSubject(BadCertificate):
132145
def __init__(self, actual, check_description):
133146
self.check_description = check_description
@@ -255,6 +268,12 @@ async def verify_x5u(self, url):
255268
if now > cert.not_valid_after:
256269
raise CertificateExpired(cert.not_valid_after)
257270

271+
# Verify chain of trust.
272+
chain = certs[::-1]
273+
root_hash = chain[0].fingerprint(SHA256())
274+
if root_hash != self.root_hash:
275+
raise CertificateHasWrongRoot(expected=self.root_hash, actual=root_hash)
276+
258277
leaf_subject_name = (
259278
certs[0].subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
260279
)
@@ -263,9 +282,6 @@ async def verify_x5u(self, url):
263282
leaf_subject_name, check_description=self.subject_name_check.describe()
264283
)
265284

266-
root_hash = certs[-1].fingerprint(SHA256())
267-
assert root_hash == self.root_hash
268-
269285
res = certs[0]
270286
self.cache.set(url, res)
271287
return res

tests/test_autograph_utils.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,26 @@ async def test_verify_x5u_name_exact_doesnt_match(
216216
)
217217

218218

219+
async def test_verify_wrong_root_hash(aiohttp_session, mock_with_x5u, cache, now_fixed):
220+
wrong_root_hash = DEV_ROOT_HASH[:-1] + b"\x03"
221+
s = SignatureVerifier(
222+
aiohttp_session,
223+
cache,
224+
wrong_root_hash,
225+
subject_name_check=ExactMatch("remote-settings.content-signature.mozilla.org"),
226+
)
227+
with pytest.raises(autograph_utils.CertificateHasWrongRoot) as excinfo:
228+
await s.verify_x5u(FAKE_CERT_URL)
229+
230+
actual = "4c35b1c3e312d955e778edd0a7e78a388304ef01bffa0329b2469f3cc5ec3604"
231+
expected = actual[:-1] + "3"
232+
233+
assert excinfo.value.detail == (
234+
"Certificate is not based on expected root hash. "
235+
f"Got '{actual}' expected '{expected}'"
236+
)
237+
238+
219239
def test_command_line_interface():
220240
"""Test the CLI."""
221241
runner = CliRunner()

0 commit comments

Comments
 (0)