blob: 4f0ad13b2aa5dae539175e9afb47f62cd212048e [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
12from cryptography import x509
Paul Kehrerfbb7ac82015-03-16 19:26:29 -050013from cryptography.hazmat.backends.interfaces import RSABackend, X509Backend
14
15from .test_x509 import _load_cert
Paul Kehrer8cf26422015-03-21 09:50:24 -050016
17
Paul Kehrer85894662015-03-22 13:19:31 -050018class TestExtension(object):
19 def test_not_an_oid(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -050020 bc = x509.BasicConstraints(ca=False, path_length=None)
Paul Kehrer85894662015-03-22 13:19:31 -050021 with pytest.raises(TypeError):
22 x509.Extension("notanoid", True, bc)
23
24 def test_critical_not_a_bool(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -050025 bc = x509.BasicConstraints(ca=False, path_length=None)
Paul Kehrer85894662015-03-22 13:19:31 -050026 with pytest.raises(TypeError):
27 x509.Extension(x509.OID_BASIC_CONSTRAINTS, "notabool", bc)
28
29 def test_repr(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -050030 bc = x509.BasicConstraints(ca=False, path_length=None)
Paul Kehrer85894662015-03-22 13:19:31 -050031 ext = x509.Extension(x509.OID_BASIC_CONSTRAINTS, True, bc)
32 assert repr(ext) == (
33 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConst"
34 "raints)>, critical=True, value=<BasicConstraints(ca=False, path"
35 "_length=None)>)>"
36 )
37
38
Paul Kehrercecbbba2015-03-30 14:58:38 -050039class TestKeyUsage(object):
40 def test_key_agreement_false_encipher_decipher_true(self):
41 with pytest.raises(ValueError):
42 x509.KeyUsage(
43 digital_signature=False,
44 content_commitment=False,
45 key_encipherment=False,
46 data_encipherment=False,
47 key_agreement=False,
48 key_cert_sign=False,
49 crl_sign=False,
50 encipher_only=True,
51 decipher_only=False
52 )
53
54 with pytest.raises(ValueError):
55 x509.KeyUsage(
56 digital_signature=False,
57 content_commitment=False,
58 key_encipherment=False,
59 data_encipherment=False,
60 key_agreement=False,
61 key_cert_sign=False,
62 crl_sign=False,
63 encipher_only=True,
64 decipher_only=True
65 )
66
67 with pytest.raises(ValueError):
68 x509.KeyUsage(
69 digital_signature=False,
70 content_commitment=False,
71 key_encipherment=False,
72 data_encipherment=False,
73 key_agreement=False,
74 key_cert_sign=False,
75 crl_sign=False,
76 encipher_only=False,
77 decipher_only=True
78 )
79
80 def test_properties_key_agreement_true(self):
81 ku = x509.KeyUsage(
82 digital_signature=True,
83 content_commitment=True,
84 key_encipherment=False,
85 data_encipherment=False,
86 key_agreement=False,
87 key_cert_sign=True,
88 crl_sign=False,
89 encipher_only=False,
90 decipher_only=False
91 )
92 assert ku.digital_signature is True
93 assert ku.content_commitment is True
94 assert ku.key_encipherment is False
95 assert ku.data_encipherment is False
96 assert ku.key_agreement is False
97 assert ku.key_cert_sign is True
98 assert ku.crl_sign is False
99
100 def test_key_agreement_true_properties(self):
101 ku = x509.KeyUsage(
102 digital_signature=False,
103 content_commitment=False,
104 key_encipherment=False,
105 data_encipherment=False,
106 key_agreement=True,
107 key_cert_sign=False,
108 crl_sign=False,
109 encipher_only=False,
110 decipher_only=True
111 )
112 assert ku.key_agreement is True
113 assert ku.encipher_only is False
114 assert ku.decipher_only is True
115
116 def test_key_agreement_false_properties(self):
117 ku = x509.KeyUsage(
118 digital_signature=False,
119 content_commitment=False,
120 key_encipherment=False,
121 data_encipherment=False,
122 key_agreement=False,
123 key_cert_sign=False,
124 crl_sign=False,
125 encipher_only=False,
126 decipher_only=False
127 )
128 assert ku.key_agreement is False
129 with pytest.raises(ValueError):
130 ku.encipher_only
131
132 with pytest.raises(ValueError):
133 ku.decipher_only
134
135
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500136class TestSubjectKeyIdentifier(object):
137 def test_properties(self):
138 hexdigest = "092384932230498bc980aa8098456f6ff7ff3ac9"
139 value = binascii.unhexlify(hexdigest)
140 ski = x509.SubjectKeyIdentifier(value)
141 assert ski.digest == value
142 assert ski.hexdigest == hexdigest
143
144 def test_repr(self):
145 ski = x509.SubjectKeyIdentifier(
146 binascii.unhexlify("092384932230498bc980aa8098456f6ff7ff3ac9")
147 )
148 ext = x509.Extension(x509.OID_SUBJECT_KEY_IDENTIFIER, False, ski)
149 assert repr(ext) == (
150 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectKey"
151 "Identifier)>, critical=False, value=<SubjectKeyIdentifier("
152 "value=092384932230498bc980aa8098456f6ff7ff3ac9)>)>"
153 )
154
155 def test_eq(self):
156 ski = x509.SubjectKeyIdentifier(
157 binascii.unhexlify("092384932230498bc980aa8098456f6ff7ff3ac9")
158 )
159 ski2 = x509.SubjectKeyIdentifier(
160 binascii.unhexlify("092384932230498bc980aa8098456f6ff7ff3ac9")
161 )
162 assert ski == ski2
163
164 def test_ne(self):
165 ski = x509.SubjectKeyIdentifier(
166 binascii.unhexlify("092384932230498bc980aa8098456f6ff7ff3ac9")
167 )
168 ski2 = x509.SubjectKeyIdentifier(
169 binascii.unhexlify("aa8098456f6ff7ff3ac9092384932230498bc980")
170 )
171 assert ski != ski2
172 assert ski != object()
173
174
Paul Kehrer8cf26422015-03-21 09:50:24 -0500175class TestBasicConstraints(object):
176 def test_ca_not_boolean(self):
177 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500178 x509.BasicConstraints(ca="notbool", path_length=None)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500179
180 def test_path_length_not_ca(self):
181 with pytest.raises(ValueError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500182 x509.BasicConstraints(ca=False, path_length=0)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500183
184 def test_path_length_not_int(self):
185 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500186 x509.BasicConstraints(ca=True, path_length=1.1)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500187
188 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500189 x509.BasicConstraints(ca=True, path_length="notint")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500190
191 def test_path_length_negative(self):
192 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500193 x509.BasicConstraints(ca=True, path_length=-1)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500194
195 def test_repr(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500196 na = x509.BasicConstraints(ca=True, path_length=None)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500197 assert repr(na) == (
Paul Kehrer85894662015-03-22 13:19:31 -0500198 "<BasicConstraints(ca=True, path_length=None)>"
Paul Kehrer8cf26422015-03-21 09:50:24 -0500199 )
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500200
201
Paul Kehrerffa2a152015-03-31 08:18:25 -0500202class TestExtendedKeyUsage(object):
203 def test_not_all_oids(self):
204 with pytest.raises(TypeError):
205 x509.ExtendedKeyUsage(["notoid"])
206
207 def test_iter_len(self):
208 eku = x509.ExtendedKeyUsage([
209 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
210 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
211 ])
212 assert len(eku) == 2
213 assert list(eku) == [
214 x509.OID_SERVER_AUTH,
215 x509.OID_CLIENT_AUTH
216 ]
217
Paul Kehrer23d10c32015-04-02 23:12:32 -0500218 def test_repr(self):
219 eku = x509.ExtendedKeyUsage([
220 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
221 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
222 ])
223 assert repr(eku) == (
224 "<ExtendedKeyUsage([<ObjectIdentifier(oid=1.3.6.1.5.5.7.3.1, name="
225 "serverAuth)>, <ObjectIdentifier(oid=1.3.6.1.5.5.7.3.2, name=clien"
226 "tAuth)>])>"
227 )
228
Paul Kehrerffa2a152015-03-31 08:18:25 -0500229
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500230@pytest.mark.requires_backend_interface(interface=RSABackend)
231@pytest.mark.requires_backend_interface(interface=X509Backend)
232class TestExtensions(object):
233 def test_no_extensions(self, backend):
234 cert = _load_cert(
235 os.path.join("x509", "verisign_md2_root.pem"),
236 x509.load_pem_x509_certificate,
237 backend
238 )
239 ext = cert.extensions
240 assert len(ext) == 0
241 assert list(ext) == []
Paul Kehrerfa56a232015-03-17 13:14:03 -0500242 with pytest.raises(x509.ExtensionNotFound) as exc:
243 ext.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
244
245 assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS
246
247 def test_one_extension(self, backend):
248 cert = _load_cert(
249 os.path.join(
250 "x509", "custom", "basic_constraints_not_critical.pem"
251 ),
252 x509.load_pem_x509_certificate,
253 backend
254 )
255 extensions = cert.extensions
256 ext = extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
257 assert ext is not None
258 assert ext.value.ca is False
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500259
260 def test_duplicate_extension(self, backend):
261 cert = _load_cert(
262 os.path.join(
263 "x509", "custom", "two_basic_constraints.pem"
264 ),
265 x509.load_pem_x509_certificate,
266 backend
267 )
268 with pytest.raises(x509.DuplicateExtension) as exc:
269 cert.extensions
270
271 assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS
272
273 def test_unsupported_critical_extension(self, backend):
274 cert = _load_cert(
275 os.path.join(
276 "x509", "custom", "unsupported_extension_critical.pem"
277 ),
278 x509.load_pem_x509_certificate,
279 backend
280 )
281 with pytest.raises(x509.UnsupportedExtension) as exc:
282 cert.extensions
283
284 assert exc.value.oid == x509.ObjectIdentifier("1.2.3.4")
285
286 def test_unsupported_extension(self, backend):
287 # TODO: this will raise an exception when all extensions are complete
288 cert = _load_cert(
289 os.path.join(
290 "x509", "custom", "unsupported_extension.pem"
291 ),
292 x509.load_pem_x509_certificate,
293 backend
294 )
295 extensions = cert.extensions
296 assert len(extensions) == 0
Paul Kehrerfa56a232015-03-17 13:14:03 -0500297
298
299@pytest.mark.requires_backend_interface(interface=RSABackend)
300@pytest.mark.requires_backend_interface(interface=X509Backend)
Paul Kehrerde813ea2015-03-28 12:44:34 -0500301class TestBasicConstraintsExtension(object):
Paul Kehrerfa56a232015-03-17 13:14:03 -0500302 def test_ca_true_pathlen_6(self, backend):
303 cert = _load_cert(
304 os.path.join(
305 "x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
306 ),
307 x509.load_der_x509_certificate,
308 backend
309 )
310 ext = cert.extensions.get_extension_for_oid(
311 x509.OID_BASIC_CONSTRAINTS
312 )
313 assert ext is not None
314 assert ext.critical is True
315 assert ext.value.ca is True
316 assert ext.value.path_length == 6
317
318 def test_path_length_zero(self, backend):
319 cert = _load_cert(
320 os.path.join("x509", "custom", "bc_path_length_zero.pem"),
321 x509.load_pem_x509_certificate,
322 backend
323 )
324 ext = cert.extensions.get_extension_for_oid(
325 x509.OID_BASIC_CONSTRAINTS
326 )
327 assert ext is not None
328 assert ext.critical is True
329 assert ext.value.ca is True
330 assert ext.value.path_length == 0
331
332 def test_ca_true_no_pathlen(self, backend):
333 cert = _load_cert(
334 os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
335 x509.load_der_x509_certificate,
336 backend
337 )
338 ext = cert.extensions.get_extension_for_oid(
339 x509.OID_BASIC_CONSTRAINTS
340 )
341 assert ext is not None
342 assert ext.critical is True
343 assert ext.value.ca is True
344 assert ext.value.path_length is None
345
346 def test_ca_false(self, backend):
347 cert = _load_cert(
348 os.path.join("x509", "cryptography.io.pem"),
349 x509.load_pem_x509_certificate,
350 backend
351 )
352 ext = cert.extensions.get_extension_for_oid(
353 x509.OID_BASIC_CONSTRAINTS
354 )
355 assert ext is not None
356 assert ext.critical is True
357 assert ext.value.ca is False
358 assert ext.value.path_length is None
359
360 def test_no_basic_constraints(self, backend):
361 cert = _load_cert(
362 os.path.join(
363 "x509",
364 "PKITS_data",
365 "certs",
366 "ValidCertificatePathTest1EE.crt"
367 ),
368 x509.load_der_x509_certificate,
369 backend
370 )
371 with pytest.raises(x509.ExtensionNotFound):
372 cert.extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
373
374 def test_basic_constraint_not_critical(self, backend):
375 cert = _load_cert(
376 os.path.join(
377 "x509", "custom", "basic_constraints_not_critical.pem"
378 ),
379 x509.load_pem_x509_certificate,
380 backend
381 )
382 ext = cert.extensions.get_extension_for_oid(
383 x509.OID_BASIC_CONSTRAINTS
384 )
385 assert ext is not None
386 assert ext.critical is False
387 assert ext.value.ca is False
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500388
389
390@pytest.mark.requires_backend_interface(interface=RSABackend)
391@pytest.mark.requires_backend_interface(interface=X509Backend)
392class TestSubjectKeyIdentifierExtension(object):
393 def test_subject_key_identifier(self, backend):
394 cert = _load_cert(
395 os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
396 x509.load_der_x509_certificate,
397 backend
398 )
399 ext = cert.extensions.get_extension_for_oid(
400 x509.OID_SUBJECT_KEY_IDENTIFIER
401 )
402 ski = ext.value
403 assert ext is not None
404 assert ext.critical is False
405 assert ski.hexdigest == "580184241bbc2b52944a3da510721451f5af3ac9"
406 assert ski.digest == binascii.unhexlify(
407 "580184241bbc2b52944a3da510721451f5af3ac9"
408 )
409
410 def test_no_subject_key_identifier(self, backend):
411 cert = _load_cert(
412 os.path.join("x509", "custom", "bc_path_length_zero.pem"),
413 x509.load_pem_x509_certificate,
414 backend
415 )
416 with pytest.raises(x509.ExtensionNotFound):
417 cert.extensions.get_extension_for_oid(
418 x509.OID_SUBJECT_KEY_IDENTIFIER
419 )