@@ -92,6 +92,23 @@ async def aiohttp_session(loop):
9292 yield s
9393
9494
95+ def mock_cert (real_cert ):
96+ """Utility function to create a mock of a cert that has all the same
97+ data but can have fields overridden.
98+
99+ """
100+ mock_cert = mock .create_autospec (spec = real_cert )
101+ mock_cert .not_valid_before = real_cert .not_valid_before
102+ mock_cert .not_valid_after = real_cert .not_valid_after
103+ mock_cert .signature = real_cert .signature
104+ mock_cert .tbs_certificate_bytes = real_cert .tbs_certificate_bytes
105+ mock_cert .signature_hash_algorithm = real_cert .signature_hash_algorithm
106+ mock_cert .subject = real_cert .subject
107+ mock_cert .extensions = real_cert .extensions
108+
109+ return mock_cert
110+
111+
95112def test_decode_mozilla_hash ():
96113 assert decode_mozilla_hash ("4C:35:B1:C3" ) == b"\x4c \x35 \xb1 \xc3 "
97114
@@ -255,6 +272,48 @@ async def test_verify_broken_chain(
255272 )
256273
257274
275+ async def test_verify_leaf_code_signing (
276+ aiohttp_session , mock_with_x5u , cache , now_fixed
277+ ):
278+ certs = [
279+ cryptography .x509 .load_pem_x509_certificate (pem , backend = default_backend ())
280+ for pem in CERT_LIST
281+ ]
282+
283+ # Change extended_key_usage for leaf cert
284+ real_leaf = certs [0 ]
285+ mock_leaf = mock_cert (real_leaf )
286+
287+ fake_uses = mock .Mock ()
288+ fake_uses .value = [
289+ cryptography .x509 .oid .ExtendedKeyUsageOID .CODE_SIGNING ,
290+ cryptography .x509 .oid .ExtendedKeyUsageOID .TIME_STAMPING ,
291+ ]
292+
293+ def get_extensions (x509_cls ):
294+ if x509_cls == cryptography .x509 .ExtendedKeyUsage :
295+ return fake_uses
296+
297+ return real_leaf .extensions .get_extension_for_class (x509_cls )
298+
299+ mock_leaf .extensions = mock .Mock ()
300+ mock_leaf .extensions .get_extension_for_class .side_effect = get_extensions
301+ certs [0 ] = mock_leaf
302+
303+ with mock .patch ("cryptography.x509.load_pem_x509_certificate" ) as load_cert_mock :
304+ load_cert_mock .side_effect = lambda * args , ** kwargs : certs .pop (0 )
305+ s = SignatureVerifier (aiohttp_session , cache , DEV_ROOT_HASH )
306+ with pytest .raises (autograph_utils .CertificateLeafHasWrongKeyUsage ) as excinfo :
307+ await s .verify_x5u (FAKE_CERT_URL )
308+
309+ assert excinfo .value .detail .startswith (
310+ f"Leaf certificate { mock_leaf !r} should have extended key usage of just "
311+ "Code Signing. "
312+ )
313+ assert excinfo .value .cert == mock_leaf
314+ assert excinfo .value .key_usage == fake_uses .value
315+
316+
258317def test_command_line_interface ():
259318 """Test the CLI."""
260319 runner = CliRunner ()
0 commit comments