blob: f2db54164c338ea765685f23e12e64d3f95e446b [file] [log] [blame]
Paul Kehrerbfac2d12015-12-19 23:32:08 -06001# 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
7import datetime
8
9import pytest
10
11from cryptography import x509
12from cryptography.hazmat.backends.interfaces import (
13 DSABackend, EllipticCurveBackend, RSABackend, X509Backend
14)
15from cryptography.hazmat.primitives import hashes
16from cryptography.hazmat.primitives.asymmetric import ec
Paul Kehrer426b48d2015-12-24 20:50:43 -060017from cryptography.x509.oid import AuthorityInformationAccessOID, NameOID
Paul Kehrerbfac2d12015-12-19 23:32:08 -060018
19from .hazmat.primitives.fixtures_dsa import DSA_KEY_2048
20from .hazmat.primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512
21from .hazmat.primitives.test_ec import _skip_curve_unsupported
22
23
24class TestCertificateRevocationListBuilder(object):
25 def test_issuer_name_invalid(self):
26 builder = x509.CertificateRevocationListBuilder()
27 with pytest.raises(TypeError):
28 builder.issuer_name("notanx509name")
29
30 def test_set_issuer_name_twice(self):
31 builder = x509.CertificateRevocationListBuilder().issuer_name(
32 x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
33 )
34 with pytest.raises(ValueError):
35 builder.issuer_name(
36 x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
37 )
38
39 def test_last_update_invalid(self):
40 builder = x509.CertificateRevocationListBuilder()
41 with pytest.raises(TypeError):
42 builder.last_update("notadatetime")
43
44 def test_last_update_before_unix_epoch(self):
45 builder = x509.CertificateRevocationListBuilder()
46 with pytest.raises(ValueError):
47 builder.last_update(datetime.datetime(1960, 8, 10))
48
49 def test_set_last_update_twice(self):
50 builder = x509.CertificateRevocationListBuilder().last_update(
51 datetime.datetime(2002, 1, 1, 12, 1)
52 )
53 with pytest.raises(ValueError):
54 builder.last_update(datetime.datetime(2002, 1, 1, 12, 1))
55
56 def test_next_update_invalid(self):
57 builder = x509.CertificateRevocationListBuilder()
58 with pytest.raises(TypeError):
59 builder.next_update("notadatetime")
60
61 def test_next_update_before_unix_epoch(self):
62 builder = x509.CertificateRevocationListBuilder()
63 with pytest.raises(ValueError):
64 builder.next_update(datetime.datetime(1960, 8, 10))
65
66 def test_set_next_update_twice(self):
67 builder = x509.CertificateRevocationListBuilder().next_update(
68 datetime.datetime(2002, 1, 1, 12, 1)
69 )
70 with pytest.raises(ValueError):
71 builder.next_update(datetime.datetime(2002, 1, 1, 12, 1))
72
73 def test_last_update_after_next_update(self):
74 builder = x509.CertificateRevocationListBuilder()
75
76 builder = builder.next_update(
77 datetime.datetime(2002, 1, 1, 12, 1)
78 )
79 with pytest.raises(ValueError):
80 builder.last_update(datetime.datetime(2003, 1, 1, 12, 1))
81
82 def test_next_update_after_last_update(self):
83 builder = x509.CertificateRevocationListBuilder()
84
85 builder = builder.last_update(
86 datetime.datetime(2002, 1, 1, 12, 1)
87 )
88 with pytest.raises(ValueError):
89 builder.next_update(datetime.datetime(2001, 1, 1, 12, 1))
90
Paul Kehrer426b48d2015-12-24 20:50:43 -060091 def test_add_extension_checks_for_duplicates(self):
92 builder = x509.CertificateRevocationListBuilder().add_extension(
93 x509.CRLNumber(1), False
94 )
95
96 with pytest.raises(ValueError):
97 builder.add_extension(x509.CRLNumber(2), False)
98
Paul Kehrerd8359692015-12-24 22:48:38 -060099 def test_add_invalid_extension(self):
100 builder = x509.CertificateRevocationListBuilder()
101
102 with pytest.raises(TypeError):
103 builder.add_extension(
104 object(), False
105 )
106
Paul Kehrerbfac2d12015-12-19 23:32:08 -0600107 @pytest.mark.requires_backend_interface(interface=RSABackend)
108 @pytest.mark.requires_backend_interface(interface=X509Backend)
109 def test_no_issuer_name(self, backend):
110 private_key = RSA_KEY_2048.private_key(backend)
111 builder = x509.CertificateRevocationListBuilder().last_update(
112 datetime.datetime(2002, 1, 1, 12, 1)
113 ).next_update(
114 datetime.datetime(2030, 1, 1, 12, 1)
115 )
116
117 with pytest.raises(ValueError):
118 builder.sign(private_key, hashes.SHA256(), backend)
119
120 @pytest.mark.requires_backend_interface(interface=RSABackend)
121 @pytest.mark.requires_backend_interface(interface=X509Backend)
122 def test_no_last_update(self, backend):
123 private_key = RSA_KEY_2048.private_key(backend)
124 builder = x509.CertificateRevocationListBuilder().issuer_name(
125 x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
126 ).next_update(
127 datetime.datetime(2030, 1, 1, 12, 1)
128 )
129
130 with pytest.raises(ValueError):
131 builder.sign(private_key, hashes.SHA256(), backend)
132
133 @pytest.mark.requires_backend_interface(interface=RSABackend)
134 @pytest.mark.requires_backend_interface(interface=X509Backend)
135 def test_no_next_update(self, backend):
136 private_key = RSA_KEY_2048.private_key(backend)
137 builder = x509.CertificateRevocationListBuilder().issuer_name(
138 x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
139 ).last_update(
140 datetime.datetime(2030, 1, 1, 12, 1)
141 )
142
143 with pytest.raises(ValueError):
144 builder.sign(private_key, hashes.SHA256(), backend)
145
146 @pytest.mark.requires_backend_interface(interface=RSABackend)
147 @pytest.mark.requires_backend_interface(interface=X509Backend)
148 def test_sign_empty_list(self, backend):
149 private_key = RSA_KEY_2048.private_key(backend)
150 last_update = datetime.datetime(2002, 1, 1, 12, 1)
151 next_update = datetime.datetime(2030, 1, 1, 12, 1)
152 builder = x509.CertificateRevocationListBuilder().issuer_name(
153 x509.Name([
154 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
155 ])
156 ).last_update(last_update).next_update(next_update)
157
158 crl = builder.sign(private_key, hashes.SHA256(), backend)
159 assert len(crl) == 0
160 assert crl.last_update == last_update
161 assert crl.next_update == next_update
162
Paul Kehrer426b48d2015-12-24 20:50:43 -0600163 @pytest.mark.parametrize(
164 "extension",
165 [
166 x509.CRLNumber(13),
167 x509.AuthorityKeyIdentifier(
168 b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
169 b"\xcbY",
170 None,
171 None
172 ),
173 x509.AuthorityInformationAccess([
174 x509.AccessDescription(
175 AuthorityInformationAccessOID.CA_ISSUERS,
176 x509.DNSName(u"cryptography.io")
177 )
178 ]),
179 x509.IssuerAlternativeName([
180 x509.UniformResourceIdentifier(u"https://cryptography.io"),
181 ])
182 ]
183 )
184 @pytest.mark.requires_backend_interface(interface=RSABackend)
185 @pytest.mark.requires_backend_interface(interface=X509Backend)
186 def test_sign_extensions(self, backend, extension):
187 private_key = RSA_KEY_2048.private_key(backend)
188 last_update = datetime.datetime(2002, 1, 1, 12, 1)
189 next_update = datetime.datetime(2030, 1, 1, 12, 1)
190 builder = x509.CertificateRevocationListBuilder().issuer_name(
191 x509.Name([
192 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
193 ])
194 ).last_update(
195 last_update
196 ).next_update(
197 next_update
198 ).add_extension(
199 extension, False
200 )
201
202 crl = builder.sign(private_key, hashes.SHA256(), backend)
203 assert len(crl) == 0
204 assert len(crl.extensions) == 1
Paul Kehrerbbc1ba92015-12-25 10:05:46 -0600205 ext = crl.extensions.get_extension_for_class(type(extension))
Paul Kehrer426b48d2015-12-24 20:50:43 -0600206 assert ext.critical is False
207 assert ext.value == extension
208
209 @pytest.mark.requires_backend_interface(interface=RSABackend)
210 @pytest.mark.requires_backend_interface(interface=X509Backend)
211 def test_sign_multiple_extensions_critical(self, backend):
212 private_key = RSA_KEY_2048.private_key(backend)
213 last_update = datetime.datetime(2002, 1, 1, 12, 1)
214 next_update = datetime.datetime(2030, 1, 1, 12, 1)
215 ian = x509.IssuerAlternativeName([
216 x509.UniformResourceIdentifier(u"https://cryptography.io"),
217 ])
218 crl_number = x509.CRLNumber(13)
219 builder = x509.CertificateRevocationListBuilder().issuer_name(
220 x509.Name([
221 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
222 ])
223 ).last_update(
224 last_update
225 ).next_update(
226 next_update
227 ).add_extension(
228 crl_number, False
229 ).add_extension(
230 ian, True
231 )
232
233 crl = builder.sign(private_key, hashes.SHA256(), backend)
234 assert len(crl) == 0
235 assert len(crl.extensions) == 2
236 ext1 = crl.extensions.get_extension_for_class(x509.CRLNumber)
237 assert ext1.critical is False
238 assert ext1.value == crl_number
239 ext2 = crl.extensions.get_extension_for_class(
240 x509.IssuerAlternativeName
241 )
242 assert ext2.critical is True
243 assert ext2.value == ian
244
245 @pytest.mark.requires_backend_interface(interface=RSABackend)
246 @pytest.mark.requires_backend_interface(interface=X509Backend)
247 def test_add_unsupported_extension(self, backend):
248 private_key = RSA_KEY_2048.private_key(backend)
249 last_update = datetime.datetime(2002, 1, 1, 12, 1)
250 next_update = datetime.datetime(2030, 1, 1, 12, 1)
251 builder = x509.CertificateRevocationListBuilder().issuer_name(
252 x509.Name([
253 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
254 ])
255 ).last_update(
256 last_update
257 ).next_update(
258 next_update
259 ).add_extension(
260 x509.OCSPNoCheck(), False
261 )
262 with pytest.raises(NotImplementedError):
263 builder.sign(private_key, hashes.SHA256(), backend)
264
Paul Kehrerbfac2d12015-12-19 23:32:08 -0600265 @pytest.mark.requires_backend_interface(interface=RSABackend)
266 @pytest.mark.requires_backend_interface(interface=X509Backend)
267 def test_sign_rsa_key_too_small(self, backend):
268 private_key = RSA_KEY_512.private_key(backend)
269 last_update = datetime.datetime(2002, 1, 1, 12, 1)
270 next_update = datetime.datetime(2030, 1, 1, 12, 1)
271 builder = x509.CertificateRevocationListBuilder().issuer_name(
272 x509.Name([
273 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
274 ])
275 ).last_update(
276 last_update
277 ).next_update(
278 next_update
279 )
280
281 with pytest.raises(ValueError):
282 builder.sign(private_key, hashes.SHA512(), backend)
283
284 @pytest.mark.requires_backend_interface(interface=RSABackend)
285 @pytest.mark.requires_backend_interface(interface=X509Backend)
286 def test_sign_with_invalid_hash(self, backend):
287 private_key = RSA_KEY_2048.private_key(backend)
288 last_update = datetime.datetime(2002, 1, 1, 12, 1)
289 next_update = datetime.datetime(2030, 1, 1, 12, 1)
290 builder = x509.CertificateRevocationListBuilder().issuer_name(
291 x509.Name([
292 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
293 ])
294 ).last_update(
295 last_update
296 ).next_update(
297 next_update
298 )
299
300 with pytest.raises(TypeError):
301 builder.sign(private_key, object(), backend)
302
303 @pytest.mark.requires_backend_interface(interface=DSABackend)
304 @pytest.mark.requires_backend_interface(interface=X509Backend)
305 def test_sign_dsa_key_unsupported(self, backend):
306 private_key = DSA_KEY_2048.private_key(backend)
307 last_update = datetime.datetime(2002, 1, 1, 12, 1)
308 next_update = datetime.datetime(2030, 1, 1, 12, 1)
309 builder = x509.CertificateRevocationListBuilder().issuer_name(
310 x509.Name([
311 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
312 ])
313 ).last_update(
314 last_update
315 ).next_update(
316 next_update
317 )
318
319 with pytest.raises(NotImplementedError):
320 builder.sign(private_key, hashes.SHA256(), backend)
321
322 @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
323 @pytest.mark.requires_backend_interface(interface=X509Backend)
324 def test_sign_ec_key_unsupported(self, backend):
325 _skip_curve_unsupported(backend, ec.SECP256R1())
326 private_key = ec.generate_private_key(ec.SECP256R1(), backend)
327 last_update = datetime.datetime(2002, 1, 1, 12, 1)
328 next_update = datetime.datetime(2030, 1, 1, 12, 1)
329 builder = x509.CertificateRevocationListBuilder().issuer_name(
330 x509.Name([
331 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
332 ])
333 ).last_update(
334 last_update
335 ).next_update(
336 next_update
337 )
338
339 with pytest.raises(NotImplementedError):
340 builder.sign(private_key, hashes.SHA256(), backend)