blob: dcf3f8e733c18537dfb7581ce4f92a8fd8830944 [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 Kehrerbfac2d12015-12-19 23:32:08 -060099 @pytest.mark.requires_backend_interface(interface=RSABackend)
100 @pytest.mark.requires_backend_interface(interface=X509Backend)
101 def test_no_issuer_name(self, backend):
102 private_key = RSA_KEY_2048.private_key(backend)
103 builder = x509.CertificateRevocationListBuilder().last_update(
104 datetime.datetime(2002, 1, 1, 12, 1)
105 ).next_update(
106 datetime.datetime(2030, 1, 1, 12, 1)
107 )
108
109 with pytest.raises(ValueError):
110 builder.sign(private_key, hashes.SHA256(), backend)
111
112 @pytest.mark.requires_backend_interface(interface=RSABackend)
113 @pytest.mark.requires_backend_interface(interface=X509Backend)
114 def test_no_last_update(self, backend):
115 private_key = RSA_KEY_2048.private_key(backend)
116 builder = x509.CertificateRevocationListBuilder().issuer_name(
117 x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
118 ).next_update(
119 datetime.datetime(2030, 1, 1, 12, 1)
120 )
121
122 with pytest.raises(ValueError):
123 builder.sign(private_key, hashes.SHA256(), backend)
124
125 @pytest.mark.requires_backend_interface(interface=RSABackend)
126 @pytest.mark.requires_backend_interface(interface=X509Backend)
127 def test_no_next_update(self, backend):
128 private_key = RSA_KEY_2048.private_key(backend)
129 builder = x509.CertificateRevocationListBuilder().issuer_name(
130 x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
131 ).last_update(
132 datetime.datetime(2030, 1, 1, 12, 1)
133 )
134
135 with pytest.raises(ValueError):
136 builder.sign(private_key, hashes.SHA256(), backend)
137
138 @pytest.mark.requires_backend_interface(interface=RSABackend)
139 @pytest.mark.requires_backend_interface(interface=X509Backend)
140 def test_sign_empty_list(self, backend):
141 private_key = RSA_KEY_2048.private_key(backend)
142 last_update = datetime.datetime(2002, 1, 1, 12, 1)
143 next_update = datetime.datetime(2030, 1, 1, 12, 1)
144 builder = x509.CertificateRevocationListBuilder().issuer_name(
145 x509.Name([
146 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
147 ])
148 ).last_update(last_update).next_update(next_update)
149
150 crl = builder.sign(private_key, hashes.SHA256(), backend)
151 assert len(crl) == 0
152 assert crl.last_update == last_update
153 assert crl.next_update == next_update
154
Paul Kehrer426b48d2015-12-24 20:50:43 -0600155 @pytest.mark.parametrize(
156 "extension",
157 [
158 x509.CRLNumber(13),
159 x509.AuthorityKeyIdentifier(
160 b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
161 b"\xcbY",
162 None,
163 None
164 ),
165 x509.AuthorityInformationAccess([
166 x509.AccessDescription(
167 AuthorityInformationAccessOID.CA_ISSUERS,
168 x509.DNSName(u"cryptography.io")
169 )
170 ]),
171 x509.IssuerAlternativeName([
172 x509.UniformResourceIdentifier(u"https://cryptography.io"),
173 ])
174 ]
175 )
176 @pytest.mark.requires_backend_interface(interface=RSABackend)
177 @pytest.mark.requires_backend_interface(interface=X509Backend)
178 def test_sign_extensions(self, backend, extension):
179 private_key = RSA_KEY_2048.private_key(backend)
180 last_update = datetime.datetime(2002, 1, 1, 12, 1)
181 next_update = datetime.datetime(2030, 1, 1, 12, 1)
182 builder = x509.CertificateRevocationListBuilder().issuer_name(
183 x509.Name([
184 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
185 ])
186 ).last_update(
187 last_update
188 ).next_update(
189 next_update
190 ).add_extension(
191 extension, False
192 )
193
194 crl = builder.sign(private_key, hashes.SHA256(), backend)
195 assert len(crl) == 0
196 assert len(crl.extensions) == 1
197 ext = crl.extensions.get_extension_for_class(extension.__class__)
198 assert ext.critical is False
199 assert ext.value == extension
200
201 @pytest.mark.requires_backend_interface(interface=RSABackend)
202 @pytest.mark.requires_backend_interface(interface=X509Backend)
203 def test_sign_multiple_extensions_critical(self, backend):
204 private_key = RSA_KEY_2048.private_key(backend)
205 last_update = datetime.datetime(2002, 1, 1, 12, 1)
206 next_update = datetime.datetime(2030, 1, 1, 12, 1)
207 ian = x509.IssuerAlternativeName([
208 x509.UniformResourceIdentifier(u"https://cryptography.io"),
209 ])
210 crl_number = x509.CRLNumber(13)
211 builder = x509.CertificateRevocationListBuilder().issuer_name(
212 x509.Name([
213 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
214 ])
215 ).last_update(
216 last_update
217 ).next_update(
218 next_update
219 ).add_extension(
220 crl_number, False
221 ).add_extension(
222 ian, True
223 )
224
225 crl = builder.sign(private_key, hashes.SHA256(), backend)
226 assert len(crl) == 0
227 assert len(crl.extensions) == 2
228 ext1 = crl.extensions.get_extension_for_class(x509.CRLNumber)
229 assert ext1.critical is False
230 assert ext1.value == crl_number
231 ext2 = crl.extensions.get_extension_for_class(
232 x509.IssuerAlternativeName
233 )
234 assert ext2.critical is True
235 assert ext2.value == ian
236
237 @pytest.mark.requires_backend_interface(interface=RSABackend)
238 @pytest.mark.requires_backend_interface(interface=X509Backend)
239 def test_add_unsupported_extension(self, backend):
240 private_key = RSA_KEY_2048.private_key(backend)
241 last_update = datetime.datetime(2002, 1, 1, 12, 1)
242 next_update = datetime.datetime(2030, 1, 1, 12, 1)
243 builder = x509.CertificateRevocationListBuilder().issuer_name(
244 x509.Name([
245 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
246 ])
247 ).last_update(
248 last_update
249 ).next_update(
250 next_update
251 ).add_extension(
252 x509.OCSPNoCheck(), False
253 )
254 with pytest.raises(NotImplementedError):
255 builder.sign(private_key, hashes.SHA256(), backend)
256
Paul Kehrerbfac2d12015-12-19 23:32:08 -0600257 @pytest.mark.requires_backend_interface(interface=RSABackend)
258 @pytest.mark.requires_backend_interface(interface=X509Backend)
259 def test_sign_rsa_key_too_small(self, backend):
260 private_key = RSA_KEY_512.private_key(backend)
261 last_update = datetime.datetime(2002, 1, 1, 12, 1)
262 next_update = datetime.datetime(2030, 1, 1, 12, 1)
263 builder = x509.CertificateRevocationListBuilder().issuer_name(
264 x509.Name([
265 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
266 ])
267 ).last_update(
268 last_update
269 ).next_update(
270 next_update
271 )
272
273 with pytest.raises(ValueError):
274 builder.sign(private_key, hashes.SHA512(), backend)
275
276 @pytest.mark.requires_backend_interface(interface=RSABackend)
277 @pytest.mark.requires_backend_interface(interface=X509Backend)
278 def test_sign_with_invalid_hash(self, backend):
279 private_key = RSA_KEY_2048.private_key(backend)
280 last_update = datetime.datetime(2002, 1, 1, 12, 1)
281 next_update = datetime.datetime(2030, 1, 1, 12, 1)
282 builder = x509.CertificateRevocationListBuilder().issuer_name(
283 x509.Name([
284 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
285 ])
286 ).last_update(
287 last_update
288 ).next_update(
289 next_update
290 )
291
292 with pytest.raises(TypeError):
293 builder.sign(private_key, object(), backend)
294
295 @pytest.mark.requires_backend_interface(interface=DSABackend)
296 @pytest.mark.requires_backend_interface(interface=X509Backend)
297 def test_sign_dsa_key_unsupported(self, backend):
298 private_key = DSA_KEY_2048.private_key(backend)
299 last_update = datetime.datetime(2002, 1, 1, 12, 1)
300 next_update = datetime.datetime(2030, 1, 1, 12, 1)
301 builder = x509.CertificateRevocationListBuilder().issuer_name(
302 x509.Name([
303 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
304 ])
305 ).last_update(
306 last_update
307 ).next_update(
308 next_update
309 )
310
311 with pytest.raises(NotImplementedError):
312 builder.sign(private_key, hashes.SHA256(), backend)
313
314 @pytest.mark.requires_backend_interface(interface=EllipticCurveBackend)
315 @pytest.mark.requires_backend_interface(interface=X509Backend)
316 def test_sign_ec_key_unsupported(self, backend):
317 _skip_curve_unsupported(backend, ec.SECP256R1())
318 private_key = ec.generate_private_key(ec.SECP256R1(), backend)
319 last_update = datetime.datetime(2002, 1, 1, 12, 1)
320 next_update = datetime.datetime(2030, 1, 1, 12, 1)
321 builder = x509.CertificateRevocationListBuilder().issuer_name(
322 x509.Name([
323 x509.NameAttribute(NameOID.COMMON_NAME, u"cryptography.io CA")
324 ])
325 ).last_update(
326 last_update
327 ).next_update(
328 next_update
329 )
330
331 with pytest.raises(NotImplementedError):
332 builder.sign(private_key, hashes.SHA256(), backend)