blob: 194b18c83575e859dcff3fb1009ca926c4776678 [file] [log] [blame]
Paul Kehrer8cf26422015-03-21 09:50:24 -05001# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
4
5from __future__ import absolute_import, division, print_function
6
Paul Kehrer1eb82a62015-03-31 20:00:33 -05007import binascii
Paul Kehrerfbb7ac82015-03-16 19:26:29 -05008import os
9
Paul Kehrer8cf26422015-03-21 09:50:24 -050010import pytest
11
Paul Kehrercbfb1012015-04-10 20:57:20 -040012import six
13
Paul Kehrer8cf26422015-03-21 09:50:24 -050014from cryptography import x509
Paul Kehrerfbb7ac82015-03-16 19:26:29 -050015from cryptography.hazmat.backends.interfaces import RSABackend, X509Backend
16
17from .test_x509 import _load_cert
Paul Kehrer8cf26422015-03-21 09:50:24 -050018
19
Paul Kehrer85894662015-03-22 13:19:31 -050020class TestExtension(object):
21 def test_not_an_oid(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -050022 bc = x509.BasicConstraints(ca=False, path_length=None)
Paul Kehrer85894662015-03-22 13:19:31 -050023 with pytest.raises(TypeError):
24 x509.Extension("notanoid", True, bc)
25
26 def test_critical_not_a_bool(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -050027 bc = x509.BasicConstraints(ca=False, path_length=None)
Paul Kehrer85894662015-03-22 13:19:31 -050028 with pytest.raises(TypeError):
29 x509.Extension(x509.OID_BASIC_CONSTRAINTS, "notabool", bc)
30
31 def test_repr(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -050032 bc = x509.BasicConstraints(ca=False, path_length=None)
Paul Kehrer85894662015-03-22 13:19:31 -050033 ext = x509.Extension(x509.OID_BASIC_CONSTRAINTS, True, bc)
34 assert repr(ext) == (
35 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConst"
36 "raints)>, critical=True, value=<BasicConstraints(ca=False, path"
37 "_length=None)>)>"
38 )
39
40
Paul Kehrercecbbba2015-03-30 14:58:38 -050041class TestKeyUsage(object):
42 def test_key_agreement_false_encipher_decipher_true(self):
43 with pytest.raises(ValueError):
44 x509.KeyUsage(
45 digital_signature=False,
46 content_commitment=False,
47 key_encipherment=False,
48 data_encipherment=False,
49 key_agreement=False,
50 key_cert_sign=False,
51 crl_sign=False,
52 encipher_only=True,
53 decipher_only=False
54 )
55
56 with pytest.raises(ValueError):
57 x509.KeyUsage(
58 digital_signature=False,
59 content_commitment=False,
60 key_encipherment=False,
61 data_encipherment=False,
62 key_agreement=False,
63 key_cert_sign=False,
64 crl_sign=False,
65 encipher_only=True,
66 decipher_only=True
67 )
68
69 with pytest.raises(ValueError):
70 x509.KeyUsage(
71 digital_signature=False,
72 content_commitment=False,
73 key_encipherment=False,
74 data_encipherment=False,
75 key_agreement=False,
76 key_cert_sign=False,
77 crl_sign=False,
78 encipher_only=False,
79 decipher_only=True
80 )
81
82 def test_properties_key_agreement_true(self):
83 ku = x509.KeyUsage(
84 digital_signature=True,
85 content_commitment=True,
86 key_encipherment=False,
87 data_encipherment=False,
88 key_agreement=False,
89 key_cert_sign=True,
90 crl_sign=False,
91 encipher_only=False,
92 decipher_only=False
93 )
94 assert ku.digital_signature is True
95 assert ku.content_commitment is True
96 assert ku.key_encipherment is False
97 assert ku.data_encipherment is False
98 assert ku.key_agreement is False
99 assert ku.key_cert_sign is True
100 assert ku.crl_sign is False
101
102 def test_key_agreement_true_properties(self):
103 ku = x509.KeyUsage(
104 digital_signature=False,
105 content_commitment=False,
106 key_encipherment=False,
107 data_encipherment=False,
108 key_agreement=True,
109 key_cert_sign=False,
110 crl_sign=False,
111 encipher_only=False,
112 decipher_only=True
113 )
114 assert ku.key_agreement is True
115 assert ku.encipher_only is False
116 assert ku.decipher_only is True
117
118 def test_key_agreement_false_properties(self):
119 ku = x509.KeyUsage(
120 digital_signature=False,
121 content_commitment=False,
122 key_encipherment=False,
123 data_encipherment=False,
124 key_agreement=False,
125 key_cert_sign=False,
126 crl_sign=False,
127 encipher_only=False,
128 decipher_only=False
129 )
130 assert ku.key_agreement is False
131 with pytest.raises(ValueError):
132 ku.encipher_only
133
134 with pytest.raises(ValueError):
135 ku.decipher_only
136
137
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500138class TestSubjectKeyIdentifier(object):
139 def test_properties(self):
Paul Kehrercbfb1012015-04-10 20:57:20 -0400140 value = binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500141 ski = x509.SubjectKeyIdentifier(value)
142 assert ski.digest == value
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500143
144 def test_repr(self):
145 ski = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500146 binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500147 )
148 ext = x509.Extension(x509.OID_SUBJECT_KEY_IDENTIFIER, False, ski)
Paul Kehrercbfb1012015-04-10 20:57:20 -0400149 if six.PY3:
150 assert repr(ext) == (
151 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
152 "eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
153 "igest=b\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
154 "\\xf7\\xff:\\xc9\')>)>"
155 )
156 else:
157 assert repr(ext) == (
158 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
159 "eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
160 "igest=\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
161 "\\xf7\\xff:\\xc9\')>)>"
162 )
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500163
164 def test_eq(self):
165 ski = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500166 binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500167 )
168 ski2 = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500169 binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500170 )
171 assert ski == ski2
172
173 def test_ne(self):
174 ski = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500175 binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500176 )
177 ski2 = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500178 binascii.unhexlify(b"aa8098456f6ff7ff3ac9092384932230498bc980")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500179 )
180 assert ski != ski2
181 assert ski != object()
182
183
Paul Kehrer8cf26422015-03-21 09:50:24 -0500184class TestBasicConstraints(object):
185 def test_ca_not_boolean(self):
186 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500187 x509.BasicConstraints(ca="notbool", path_length=None)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500188
189 def test_path_length_not_ca(self):
190 with pytest.raises(ValueError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500191 x509.BasicConstraints(ca=False, path_length=0)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500192
193 def test_path_length_not_int(self):
194 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500195 x509.BasicConstraints(ca=True, path_length=1.1)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500196
197 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500198 x509.BasicConstraints(ca=True, path_length="notint")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500199
200 def test_path_length_negative(self):
201 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500202 x509.BasicConstraints(ca=True, path_length=-1)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500203
204 def test_repr(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500205 na = x509.BasicConstraints(ca=True, path_length=None)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500206 assert repr(na) == (
Paul Kehrer85894662015-03-22 13:19:31 -0500207 "<BasicConstraints(ca=True, path_length=None)>"
Paul Kehrer8cf26422015-03-21 09:50:24 -0500208 )
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500209
210
Paul Kehrerffa2a152015-03-31 08:18:25 -0500211class TestExtendedKeyUsage(object):
212 def test_not_all_oids(self):
213 with pytest.raises(TypeError):
214 x509.ExtendedKeyUsage(["notoid"])
215
216 def test_iter_len(self):
217 eku = x509.ExtendedKeyUsage([
218 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
219 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
220 ])
221 assert len(eku) == 2
222 assert list(eku) == [
223 x509.OID_SERVER_AUTH,
224 x509.OID_CLIENT_AUTH
225 ]
226
Paul Kehrer23d10c32015-04-02 23:12:32 -0500227 def test_repr(self):
228 eku = x509.ExtendedKeyUsage([
229 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
230 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
231 ])
232 assert repr(eku) == (
233 "<ExtendedKeyUsage([<ObjectIdentifier(oid=1.3.6.1.5.5.7.3.1, name="
234 "serverAuth)>, <ObjectIdentifier(oid=1.3.6.1.5.5.7.3.2, name=clien"
235 "tAuth)>])>"
236 )
237
Paul Kehrerffa2a152015-03-31 08:18:25 -0500238
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500239@pytest.mark.requires_backend_interface(interface=RSABackend)
240@pytest.mark.requires_backend_interface(interface=X509Backend)
241class TestExtensions(object):
242 def test_no_extensions(self, backend):
243 cert = _load_cert(
244 os.path.join("x509", "verisign_md2_root.pem"),
245 x509.load_pem_x509_certificate,
246 backend
247 )
248 ext = cert.extensions
249 assert len(ext) == 0
250 assert list(ext) == []
Paul Kehrerfa56a232015-03-17 13:14:03 -0500251 with pytest.raises(x509.ExtensionNotFound) as exc:
252 ext.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
253
254 assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS
255
256 def test_one_extension(self, backend):
257 cert = _load_cert(
258 os.path.join(
259 "x509", "custom", "basic_constraints_not_critical.pem"
260 ),
261 x509.load_pem_x509_certificate,
262 backend
263 )
264 extensions = cert.extensions
265 ext = extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
266 assert ext is not None
267 assert ext.value.ca is False
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500268
269 def test_duplicate_extension(self, backend):
270 cert = _load_cert(
271 os.path.join(
272 "x509", "custom", "two_basic_constraints.pem"
273 ),
274 x509.load_pem_x509_certificate,
275 backend
276 )
277 with pytest.raises(x509.DuplicateExtension) as exc:
278 cert.extensions
279
280 assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS
281
282 def test_unsupported_critical_extension(self, backend):
283 cert = _load_cert(
284 os.path.join(
285 "x509", "custom", "unsupported_extension_critical.pem"
286 ),
287 x509.load_pem_x509_certificate,
288 backend
289 )
290 with pytest.raises(x509.UnsupportedExtension) as exc:
291 cert.extensions
292
293 assert exc.value.oid == x509.ObjectIdentifier("1.2.3.4")
294
295 def test_unsupported_extension(self, backend):
296 # TODO: this will raise an exception when all extensions are complete
297 cert = _load_cert(
298 os.path.join(
299 "x509", "custom", "unsupported_extension.pem"
300 ),
301 x509.load_pem_x509_certificate,
302 backend
303 )
304 extensions = cert.extensions
305 assert len(extensions) == 0
Paul Kehrerfa56a232015-03-17 13:14:03 -0500306
307
308@pytest.mark.requires_backend_interface(interface=RSABackend)
309@pytest.mark.requires_backend_interface(interface=X509Backend)
Paul Kehrerde813ea2015-03-28 12:44:34 -0500310class TestBasicConstraintsExtension(object):
Paul Kehrerfa56a232015-03-17 13:14:03 -0500311 def test_ca_true_pathlen_6(self, backend):
312 cert = _load_cert(
313 os.path.join(
314 "x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
315 ),
316 x509.load_der_x509_certificate,
317 backend
318 )
319 ext = cert.extensions.get_extension_for_oid(
320 x509.OID_BASIC_CONSTRAINTS
321 )
322 assert ext is not None
323 assert ext.critical is True
324 assert ext.value.ca is True
325 assert ext.value.path_length == 6
326
327 def test_path_length_zero(self, backend):
328 cert = _load_cert(
329 os.path.join("x509", "custom", "bc_path_length_zero.pem"),
330 x509.load_pem_x509_certificate,
331 backend
332 )
333 ext = cert.extensions.get_extension_for_oid(
334 x509.OID_BASIC_CONSTRAINTS
335 )
336 assert ext is not None
337 assert ext.critical is True
338 assert ext.value.ca is True
339 assert ext.value.path_length == 0
340
341 def test_ca_true_no_pathlen(self, backend):
342 cert = _load_cert(
343 os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
344 x509.load_der_x509_certificate,
345 backend
346 )
347 ext = cert.extensions.get_extension_for_oid(
348 x509.OID_BASIC_CONSTRAINTS
349 )
350 assert ext is not None
351 assert ext.critical is True
352 assert ext.value.ca is True
353 assert ext.value.path_length is None
354
355 def test_ca_false(self, backend):
356 cert = _load_cert(
357 os.path.join("x509", "cryptography.io.pem"),
358 x509.load_pem_x509_certificate,
359 backend
360 )
361 ext = cert.extensions.get_extension_for_oid(
362 x509.OID_BASIC_CONSTRAINTS
363 )
364 assert ext is not None
365 assert ext.critical is True
366 assert ext.value.ca is False
367 assert ext.value.path_length is None
368
369 def test_no_basic_constraints(self, backend):
370 cert = _load_cert(
371 os.path.join(
372 "x509",
373 "PKITS_data",
374 "certs",
375 "ValidCertificatePathTest1EE.crt"
376 ),
377 x509.load_der_x509_certificate,
378 backend
379 )
380 with pytest.raises(x509.ExtensionNotFound):
381 cert.extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
382
383 def test_basic_constraint_not_critical(self, backend):
384 cert = _load_cert(
385 os.path.join(
386 "x509", "custom", "basic_constraints_not_critical.pem"
387 ),
388 x509.load_pem_x509_certificate,
389 backend
390 )
391 ext = cert.extensions.get_extension_for_oid(
392 x509.OID_BASIC_CONSTRAINTS
393 )
394 assert ext is not None
395 assert ext.critical is False
396 assert ext.value.ca is False
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500397
398
399@pytest.mark.requires_backend_interface(interface=RSABackend)
400@pytest.mark.requires_backend_interface(interface=X509Backend)
401class TestSubjectKeyIdentifierExtension(object):
402 def test_subject_key_identifier(self, backend):
403 cert = _load_cert(
404 os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
405 x509.load_der_x509_certificate,
406 backend
407 )
408 ext = cert.extensions.get_extension_for_oid(
409 x509.OID_SUBJECT_KEY_IDENTIFIER
410 )
411 ski = ext.value
412 assert ext is not None
413 assert ext.critical is False
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500414 assert ski.digest == binascii.unhexlify(
Paul Kehreree997262015-04-04 12:20:28 -0500415 b"580184241bbc2b52944a3da510721451f5af3ac9"
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500416 )
417
418 def test_no_subject_key_identifier(self, backend):
419 cert = _load_cert(
420 os.path.join("x509", "custom", "bc_path_length_zero.pem"),
421 x509.load_pem_x509_certificate,
422 backend
423 )
424 with pytest.raises(x509.ExtensionNotFound):
425 cert.extensions.get_extension_for_oid(
426 x509.OID_SUBJECT_KEY_IDENTIFIER
427 )