@@ -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+
131144class 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
0 commit comments