blob: c2d33d925a5c16c506e2c8202940fac2de07f48b [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
Paul Kehrerac3e5bb2015-04-02 23:07:10 -0500137 def test_repr_key_agreement_false(self):
138 ku = x509.KeyUsage(
139 digital_signature=True,
140 content_commitment=True,
141 key_encipherment=False,
142 data_encipherment=False,
143 key_agreement=False,
144 key_cert_sign=True,
145 crl_sign=False,
146 encipher_only=False,
147 decipher_only=False
148 )
149 assert repr(ku) == (
150 "<KeyUsage(digital_signature=True, content_commitment=True, key_en"
151 "cipherment=False, data_encipherment=False, key_agreement=False, k"
152 "ey_cert_sign=True, crl_sign=False, encipher_only=N/A, decipher_on"
153 "ly=N/A)>"
154 )
155
156 def test_repr_key_agreement_true(self):
157 ku = x509.KeyUsage(
158 digital_signature=True,
159 content_commitment=True,
160 key_encipherment=False,
161 data_encipherment=False,
162 key_agreement=True,
163 key_cert_sign=True,
164 crl_sign=False,
165 encipher_only=False,
166 decipher_only=False
167 )
168 assert repr(ku) == (
169 "<KeyUsage(digital_signature=True, content_commitment=True, key_en"
170 "cipherment=False, data_encipherment=False, key_agreement=True, k"
171 "ey_cert_sign=True, crl_sign=False, encipher_only=False, decipher_"
172 "only=False)>"
173 )
174
Paul Kehrercecbbba2015-03-30 14:58:38 -0500175
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500176class TestSubjectKeyIdentifier(object):
177 def test_properties(self):
Paul Kehrercbfb1012015-04-10 20:57:20 -0400178 value = binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500179 ski = x509.SubjectKeyIdentifier(value)
180 assert ski.digest == value
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500181
182 def test_repr(self):
183 ski = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500184 binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500185 )
186 ext = x509.Extension(x509.OID_SUBJECT_KEY_IDENTIFIER, False, ski)
Paul Kehrercbfb1012015-04-10 20:57:20 -0400187 if six.PY3:
188 assert repr(ext) == (
189 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
190 "eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
191 "igest=b\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
192 "\\xf7\\xff:\\xc9\')>)>"
193 )
194 else:
195 assert repr(ext) == (
196 "<Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectK"
197 "eyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(d"
198 "igest=\'\\t#\\x84\\x93\"0I\\x8b\\xc9\\x80\\xaa\\x80\\x98Eoo"
199 "\\xf7\\xff:\\xc9\')>)>"
200 )
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500201
202 def test_eq(self):
203 ski = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500204 binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500205 )
206 ski2 = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500207 binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500208 )
209 assert ski == ski2
210
211 def test_ne(self):
212 ski = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500213 binascii.unhexlify(b"092384932230498bc980aa8098456f6ff7ff3ac9")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500214 )
215 ski2 = x509.SubjectKeyIdentifier(
Paul Kehreree997262015-04-04 12:20:28 -0500216 binascii.unhexlify(b"aa8098456f6ff7ff3ac9092384932230498bc980")
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500217 )
218 assert ski != ski2
219 assert ski != object()
220
221
Paul Kehrer8cf26422015-03-21 09:50:24 -0500222class TestBasicConstraints(object):
223 def test_ca_not_boolean(self):
224 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500225 x509.BasicConstraints(ca="notbool", path_length=None)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500226
227 def test_path_length_not_ca(self):
228 with pytest.raises(ValueError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500229 x509.BasicConstraints(ca=False, path_length=0)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500230
231 def test_path_length_not_int(self):
232 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500233 x509.BasicConstraints(ca=True, path_length=1.1)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500234
235 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500236 x509.BasicConstraints(ca=True, path_length="notint")
Paul Kehrer8cf26422015-03-21 09:50:24 -0500237
238 def test_path_length_negative(self):
239 with pytest.raises(TypeError):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500240 x509.BasicConstraints(ca=True, path_length=-1)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500241
242 def test_repr(self):
Paul Kehrera5c6e9a2015-03-23 19:23:43 -0500243 na = x509.BasicConstraints(ca=True, path_length=None)
Paul Kehrer8cf26422015-03-21 09:50:24 -0500244 assert repr(na) == (
Paul Kehrer85894662015-03-22 13:19:31 -0500245 "<BasicConstraints(ca=True, path_length=None)>"
Paul Kehrer8cf26422015-03-21 09:50:24 -0500246 )
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500247
248
Paul Kehrerffa2a152015-03-31 08:18:25 -0500249class TestExtendedKeyUsage(object):
250 def test_not_all_oids(self):
251 with pytest.raises(TypeError):
252 x509.ExtendedKeyUsage(["notoid"])
253
254 def test_iter_len(self):
255 eku = x509.ExtendedKeyUsage([
256 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
257 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
258 ])
259 assert len(eku) == 2
260 assert list(eku) == [
261 x509.OID_SERVER_AUTH,
262 x509.OID_CLIENT_AUTH
263 ]
264
Paul Kehrer23d10c32015-04-02 23:12:32 -0500265 def test_repr(self):
266 eku = x509.ExtendedKeyUsage([
267 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.1"),
268 x509.ObjectIdentifier("1.3.6.1.5.5.7.3.2"),
269 ])
270 assert repr(eku) == (
271 "<ExtendedKeyUsage([<ObjectIdentifier(oid=1.3.6.1.5.5.7.3.1, name="
272 "serverAuth)>, <ObjectIdentifier(oid=1.3.6.1.5.5.7.3.2, name=clien"
273 "tAuth)>])>"
274 )
275
Paul Kehrerffa2a152015-03-31 08:18:25 -0500276
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500277@pytest.mark.requires_backend_interface(interface=RSABackend)
278@pytest.mark.requires_backend_interface(interface=X509Backend)
279class TestExtensions(object):
280 def test_no_extensions(self, backend):
281 cert = _load_cert(
282 os.path.join("x509", "verisign_md2_root.pem"),
283 x509.load_pem_x509_certificate,
284 backend
285 )
286 ext = cert.extensions
287 assert len(ext) == 0
288 assert list(ext) == []
Paul Kehrerfa56a232015-03-17 13:14:03 -0500289 with pytest.raises(x509.ExtensionNotFound) as exc:
290 ext.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
291
292 assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS
293
294 def test_one_extension(self, backend):
295 cert = _load_cert(
296 os.path.join(
297 "x509", "custom", "basic_constraints_not_critical.pem"
298 ),
299 x509.load_pem_x509_certificate,
300 backend
301 )
302 extensions = cert.extensions
303 ext = extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
304 assert ext is not None
305 assert ext.value.ca is False
Paul Kehrerfbb7ac82015-03-16 19:26:29 -0500306
307 def test_duplicate_extension(self, backend):
308 cert = _load_cert(
309 os.path.join(
310 "x509", "custom", "two_basic_constraints.pem"
311 ),
312 x509.load_pem_x509_certificate,
313 backend
314 )
315 with pytest.raises(x509.DuplicateExtension) as exc:
316 cert.extensions
317
318 assert exc.value.oid == x509.OID_BASIC_CONSTRAINTS
319
320 def test_unsupported_critical_extension(self, backend):
321 cert = _load_cert(
322 os.path.join(
323 "x509", "custom", "unsupported_extension_critical.pem"
324 ),
325 x509.load_pem_x509_certificate,
326 backend
327 )
328 with pytest.raises(x509.UnsupportedExtension) as exc:
329 cert.extensions
330
331 assert exc.value.oid == x509.ObjectIdentifier("1.2.3.4")
332
333 def test_unsupported_extension(self, backend):
334 # TODO: this will raise an exception when all extensions are complete
335 cert = _load_cert(
336 os.path.join(
337 "x509", "custom", "unsupported_extension.pem"
338 ),
339 x509.load_pem_x509_certificate,
340 backend
341 )
342 extensions = cert.extensions
343 assert len(extensions) == 0
Paul Kehrerfa56a232015-03-17 13:14:03 -0500344
345
346@pytest.mark.requires_backend_interface(interface=RSABackend)
347@pytest.mark.requires_backend_interface(interface=X509Backend)
Paul Kehrerde813ea2015-03-28 12:44:34 -0500348class TestBasicConstraintsExtension(object):
Paul Kehrerfa56a232015-03-17 13:14:03 -0500349 def test_ca_true_pathlen_6(self, backend):
350 cert = _load_cert(
351 os.path.join(
352 "x509", "PKITS_data", "certs", "pathLenConstraint6CACert.crt"
353 ),
354 x509.load_der_x509_certificate,
355 backend
356 )
357 ext = cert.extensions.get_extension_for_oid(
358 x509.OID_BASIC_CONSTRAINTS
359 )
360 assert ext is not None
361 assert ext.critical is True
362 assert ext.value.ca is True
363 assert ext.value.path_length == 6
364
365 def test_path_length_zero(self, backend):
366 cert = _load_cert(
367 os.path.join("x509", "custom", "bc_path_length_zero.pem"),
368 x509.load_pem_x509_certificate,
369 backend
370 )
371 ext = cert.extensions.get_extension_for_oid(
372 x509.OID_BASIC_CONSTRAINTS
373 )
374 assert ext is not None
375 assert ext.critical is True
376 assert ext.value.ca is True
377 assert ext.value.path_length == 0
378
379 def test_ca_true_no_pathlen(self, backend):
380 cert = _load_cert(
381 os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
382 x509.load_der_x509_certificate,
383 backend
384 )
385 ext = cert.extensions.get_extension_for_oid(
386 x509.OID_BASIC_CONSTRAINTS
387 )
388 assert ext is not None
389 assert ext.critical is True
390 assert ext.value.ca is True
391 assert ext.value.path_length is None
392
393 def test_ca_false(self, backend):
394 cert = _load_cert(
395 os.path.join("x509", "cryptography.io.pem"),
396 x509.load_pem_x509_certificate,
397 backend
398 )
399 ext = cert.extensions.get_extension_for_oid(
400 x509.OID_BASIC_CONSTRAINTS
401 )
402 assert ext is not None
403 assert ext.critical is True
404 assert ext.value.ca is False
405 assert ext.value.path_length is None
406
407 def test_no_basic_constraints(self, backend):
408 cert = _load_cert(
409 os.path.join(
410 "x509",
411 "PKITS_data",
412 "certs",
413 "ValidCertificatePathTest1EE.crt"
414 ),
415 x509.load_der_x509_certificate,
416 backend
417 )
418 with pytest.raises(x509.ExtensionNotFound):
419 cert.extensions.get_extension_for_oid(x509.OID_BASIC_CONSTRAINTS)
420
421 def test_basic_constraint_not_critical(self, backend):
422 cert = _load_cert(
423 os.path.join(
424 "x509", "custom", "basic_constraints_not_critical.pem"
425 ),
426 x509.load_pem_x509_certificate,
427 backend
428 )
429 ext = cert.extensions.get_extension_for_oid(
430 x509.OID_BASIC_CONSTRAINTS
431 )
432 assert ext is not None
433 assert ext.critical is False
434 assert ext.value.ca is False
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500435
436
437@pytest.mark.requires_backend_interface(interface=RSABackend)
438@pytest.mark.requires_backend_interface(interface=X509Backend)
439class TestSubjectKeyIdentifierExtension(object):
440 def test_subject_key_identifier(self, backend):
441 cert = _load_cert(
442 os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
443 x509.load_der_x509_certificate,
444 backend
445 )
446 ext = cert.extensions.get_extension_for_oid(
447 x509.OID_SUBJECT_KEY_IDENTIFIER
448 )
449 ski = ext.value
450 assert ext is not None
451 assert ext.critical is False
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500452 assert ski.digest == binascii.unhexlify(
Paul Kehreree997262015-04-04 12:20:28 -0500453 b"580184241bbc2b52944a3da510721451f5af3ac9"
Paul Kehrer1eb82a62015-03-31 20:00:33 -0500454 )
455
456 def test_no_subject_key_identifier(self, backend):
457 cert = _load_cert(
458 os.path.join("x509", "custom", "bc_path_length_zero.pem"),
459 x509.load_pem_x509_certificate,
460 backend
461 )
462 with pytest.raises(x509.ExtensionNotFound):
463 cert.extensions.get_extension_for_oid(
464 x509.OID_SUBJECT_KEY_IDENTIFIER
465 )