blob: 7fccaba6d73a4f2d07dfa28ddbe29373bf48525e [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 Kehrerfbb7ac82015-03-16 19:26:29 -05007import os
8
Paul Kehrer8cf26422015-03-21 09:50:24 -05009import pytest
10
11from cryptography import x509
Paul Kehrerfbb7ac82015-03-16 19:26:29 -050012from cryptography.hazmat.backends.interfaces import RSABackend, X509Backend
13
14from .test_x509 import _load_cert
Paul Kehrer8cf26422015-03-21 09:50:24 -050015
16
Paul Kehrer85894662015-03-22 13:19:31 -050017class TestExtension(object):
18 def test_not_an_oid(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -050019 bc = x509.BasicConstraints(ca=False, path_length=None)
Paul Kehrer85894662015-03-22 13:19:31 -050020 with pytest.raises(TypeError):
21 x509.Extension("notanoid", True, bc)
22
23 def test_critical_not_a_bool(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -050024 bc = x509.BasicConstraints(ca=False, path_length=None)
Paul Kehrer85894662015-03-22 13:19:31 -050025 with pytest.raises(TypeError):
26 x509.Extension(x509.OID_BASIC_CONSTRAINTS, "notabool", bc)
27
28 def test_repr(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -050029 bc = x509.BasicConstraints(ca=False, path_length=None)
Paul Kehrer85894662015-03-22 13:19:31 -050030 ext = x509.Extension(x509.OID_BASIC_CONSTRAINTS, True, bc)
31 assert repr(ext) == (
32 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConst"
33 "raints)>, critical=True, value=<BasicConstraints(ca=False, path"
34 "_length=None)>)>"
35 )
36
37
Paul Kehrercecbbba2015-03-30 14:58:38 -050038class TestKeyUsage(object):
39 def test_key_agreement_false_encipher_decipher_true(self):
40 with pytest.raises(ValueError):
41 x509.KeyUsage(
42 digital_signature=False,
43 content_commitment=False,
44 key_encipherment=False,
45 data_encipherment=False,
46 key_agreement=False,
47 key_cert_sign=False,
48 crl_sign=False,
49 encipher_only=True,
50 decipher_only=False
51 )
52
53 with pytest.raises(ValueError):
54 x509.KeyUsage(
55 digital_signature=False,
56 content_commitment=False,
57 key_encipherment=False,
58 data_encipherment=False,
59 key_agreement=False,
60 key_cert_sign=False,
61 crl_sign=False,
62 encipher_only=True,
63 decipher_only=True
64 )
65
66 with pytest.raises(ValueError):
67 x509.KeyUsage(
68 digital_signature=False,
69 content_commitment=False,
70 key_encipherment=False,
71 data_encipherment=False,
72 key_agreement=False,
73 key_cert_sign=False,
74 crl_sign=False,
75 encipher_only=False,
76 decipher_only=True
77 )
78
79 def test_properties_key_agreement_true(self):
80 ku = x509.KeyUsage(
81 digital_signature=True,
82 content_commitment=True,
83 key_encipherment=False,
84 data_encipherment=False,
85 key_agreement=False,
86 key_cert_sign=True,
87 crl_sign=False,
88 encipher_only=False,
89 decipher_only=False
90 )
91 assert ku.digital_signature is True
92 assert ku.content_commitment is True
93 assert ku.key_encipherment is False
94 assert ku.data_encipherment is False
95 assert ku.key_agreement is False
96 assert ku.key_cert_sign is True
97 assert ku.crl_sign is False
98
99 def test_key_agreement_true_properties(self):
100 ku = x509.KeyUsage(
101 digital_signature=False,
102 content_commitment=False,
103 key_encipherment=False,
104 data_encipherment=False,
105 key_agreement=True,
106 key_cert_sign=False,
107 crl_sign=False,
108 encipher_only=False,
109 decipher_only=True
110 )
111 assert ku.key_agreement is True
112 assert ku.encipher_only is False
113 assert ku.decipher_only is True
114
115 def test_key_agreement_false_properties(self):
116 ku = x509.KeyUsage(
117 digital_signature=False,
118 content_commitment=False,
119 key_encipherment=False,
120 data_encipherment=False,
121 key_agreement=False,
122 key_cert_sign=False,
123 crl_sign=False,
124 encipher_only=False,
125 decipher_only=False
126 )
127 assert ku.key_agreement is False
128 with pytest.raises(ValueError):
129 ku.encipher_only
130
131 with pytest.raises(ValueError):
132 ku.decipher_only
133
Paul Kehrerac3e5bb2015-04-02 23:07:10 -0500134 def test_repr_key_agreement_false(self):
135 ku = x509.KeyUsage(
136 digital_signature=True,
137 content_commitment=True,
138 key_encipherment=False,
139 data_encipherment=False,
140 key_agreement=False,
141 key_cert_sign=True,
142 crl_sign=False,
143 encipher_only=False,
144 decipher_only=False
145 )
146 assert repr(ku) == (
147 "<KeyUsage(digital_signature=True, content_commitment=True, key_en"
148 "cipherment=False, data_encipherment=False, key_agreement=False, k"
149 "ey_cert_sign=True, crl_sign=False, encipher_only=N/A, decipher_on"
150 "ly=N/A)>"
151 )
152
153 def test_repr_key_agreement_true(self):
154 ku = x509.KeyUsage(
155 digital_signature=True,
156 content_commitment=True,
157 key_encipherment=False,
158 data_encipherment=False,
159 key_agreement=True,
160 key_cert_sign=True,
161 crl_sign=False,
162 encipher_only=False,
163 decipher_only=False
164 )
165 assert repr(ku) == (
166 "<KeyUsage(digital_signature=True, content_commitment=True, key_en"
167 "cipherment=False, data_encipherment=False, key_agreement=True, k"
168 "ey_cert_sign=True, crl_sign=False, encipher_only=False, decipher_"
169 "only=False)>"
170 )
171
Paul Kehrercecbbba2015-03-30 14:58:38 -0500172
Paul Kehrer8cf26422015-03-21 09:50:24 -0500173class TestBasicConstraints(object):
174 def test_ca_not_boolean(self):
175 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500176 x509.BasicConstraints(ca="notbool", path_length=None)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500177
178 def test_path_length_not_ca(self):
179 with pytest.raises(ValueError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500180 x509.BasicConstraints(ca=False, path_length=0)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500181
182 def test_path_length_not_int(self):
183 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500184 x509.BasicConstraints(ca=True, path_length=1.1)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500185
186 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500187 x509.BasicConstraints(ca=True, path_length="notint")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500188
189 def test_path_length_negative(self):
190 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500191 x509.BasicConstraints(ca=True, path_length=-1)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500192
193 def test_repr(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500194 na = x509.BasicConstraints(ca=True, path_length=None)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500195 assert repr(na) == (
Paul Kehrer85894662015-03-22 13:19:31 -0500196 "<BasicConstraints(ca=True, path_length=None)>"
Paul Kehrer8cf26422015-03-21 09:50:24 -0500197 )
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500198
199
Paul Kehrerffa2a152015-03-31 08:18:25 -0500200class TestExtendedKeyUsage(object):
201 def test_not_all_oids(self):
202 with pytest.raises(TypeError):
203 x509.ExtendedKeyUsage(["notoid"])
204
205 def test_iter_len(self):
206 eku = x509.ExtendedKeyUsage([
207 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
208 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
209 ])
210 assert len(eku) == 2
211 assert list(eku) == [
212 x509.OID_SERVER_AUTH,
213 x509.OID_CLIENT_AUTH
214 ]
215
216
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500217@pytest.mark.requires_backend_interface(interface=RSABackend)
218@pytest.mark.requires_backend_interface(interface=X509Backend)
219class TestExtensions(object):
220 def test_no_extensions(self, backend):
221 cert = _load_cert(
222 os.path.join("x509", "verisign_md2_root.pem"),
223 x509.load_pem_x509_certificate,
224 backend
225 )
226 ext = cert.extensions
227 assert len(ext) == 0
228 assert list(ext) == []
Paul Kehrerfa56a232015-03-17 13:14:03 -0500229 with pytest.raises(x509.ExtensionNotFound) as exc:
230 ext.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
231
232 assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS
233
234 def test_one_extension(self, backend):
235 cert = _load_cert(
236 os.path.join(
237 "x509", "custom", "basic_constraints_not_critical.pem"
238 ),
239 x509.load_pem_x509_certificate,
240 backend
241 )
242 extensions = cert.extensions
243 ext = extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
244 assert ext is not None
245 assert ext.value.ca is False
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500246
247 def test_duplicate_extension(self, backend):
248 cert = _load_cert(
249 os.path.join(
250 "x509", "custom", "two_basic_constraints.pem"
251 ),
252 x509.load_pem_x509_certificate,
253 backend
254 )
255 with pytest.raises(x509.DuplicateExtension) as exc:
256 cert.extensions
257
258 assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS
259
260 def test_unsupported_critical_extension(self, backend):
261 cert = _load_cert(
262 os.path.join(
263 "x509", "custom", "unsupported_extension_critical.pem"
264 ),
265 x509.load_pem_x509_certificate,
266 backend
267 )
268 with pytest.raises(x509.UnsupportedExtension) as exc:
269 cert.extensions
270
271 assert exc.value.oid == x509.ObjectIdentifier("1.2.3.4")
272
273 def test_unsupported_extension(self, backend):
274 # TODO: this will raise an exception when all extensions are complete
275 cert = _load_cert(
276 os.path.join(
277 "x509", "custom", "unsupported_extension.pem"
278 ),
279 x509.load_pem_x509_certificate,
280 backend
281 )
282 extensions = cert.extensions
283 assert len(extensions) == 0
Paul Kehrerfa56a232015-03-17 13:14:03 -0500284
285
286@pytest.mark.requires_backend_interface(interface=RSABackend)
287@pytest.mark.requires_backend_interface(interface=X509Backend)
Paul Kehrerde813ea2015-03-28 12:44:34 -0500288class TestBasicConstraintsExtension(object):
Paul Kehrerfa56a232015-03-17 13:14:03 -0500289 def test_ca_true_pathlen_6(self, backend):
290 cert = _load_cert(
291 os.path.join(
292 "x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
293 ),
294 x509.load_der_x509_certificate,
295 backend
296 )
297 ext = cert.extensions.get_extension_for_oid(
298 x509.OID_BASIC_CONSTRAINTS
299 )
300 assert ext is not None
301 assert ext.critical is True
302 assert ext.value.ca is True
303 assert ext.value.path_length == 6
304
305 def test_path_length_zero(self, backend):
306 cert = _load_cert(
307 os.path.join("x509", "custom", "bc_path_length_zero.pem"),
308 x509.load_pem_x509_certificate,
309 backend
310 )
311 ext = cert.extensions.get_extension_for_oid(
312 x509.OID_BASIC_CONSTRAINTS
313 )
314 assert ext is not None
315 assert ext.critical is True
316 assert ext.value.ca is True
317 assert ext.value.path_length == 0
318
319 def test_ca_true_no_pathlen(self, backend):
320 cert = _load_cert(
321 os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
322 x509.load_der_x509_certificate,
323 backend
324 )
325 ext = cert.extensions.get_extension_for_oid(
326 x509.OID_BASIC_CONSTRAINTS
327 )
328 assert ext is not None
329 assert ext.critical is True
330 assert ext.value.ca is True
331 assert ext.value.path_length is None
332
333 def test_ca_false(self, backend):
334 cert = _load_cert(
335 os.path.join("x509", "cryptography.io.pem"),
336 x509.load_pem_x509_certificate,
337 backend
338 )
339 ext = cert.extensions.get_extension_for_oid(
340 x509.OID_BASIC_CONSTRAINTS
341 )
342 assert ext is not None
343 assert ext.critical is True
344 assert ext.value.ca is False
345 assert ext.value.path_length is None
346
347 def test_no_basic_constraints(self, backend):
348 cert = _load_cert(
349 os.path.join(
350 "x509",
351 "PKITS_data",
352 "certs",
353 "ValidCertificatePathTest1EE.crt"
354 ),
355 x509.load_der_x509_certificate,
356 backend
357 )
358 with pytest.raises(x509.ExtensionNotFound):
359 cert.extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
360
361 def test_basic_constraint_not_critical(self, backend):
362 cert = _load_cert(
363 os.path.join(
364 "x509", "custom", "basic_constraints_not_critical.pem"
365 ),
366 x509.load_pem_x509_certificate,
367 backend
368 )
369 ext = cert.extensions.get_extension_for_oid(
370 x509.OID_BASIC_CONSTRAINTS
371 )
372 assert ext is not None
373 assert ext.critical is False
374 assert ext.value.ca is False