blob: 758e755c579e4d6d9b4f2601cc4c9ddefd8bc864 [file] [log] [blame]
Alex Gaynorbd458ae2013-10-16 11:59:30 -07001import binascii
2import os
3
4import pytest
5
Paul Kehrer22e80cb2013-11-20 21:27:00 -06006from cryptography.hazmat.primitives import hashes, hmac
Paul Kehrer21dde562013-11-06 12:22:09 +08007from cryptography.hazmat.primitives.ciphers import Cipher
Paul Kehrer22e80cb2013-11-20 21:27:00 -06008from cryptography.exceptions import (
Paul Kehrera4bfc082013-11-22 19:57:37 -06009 AlreadyFinalized, NotYetFinalized, AlreadyUpdated, InvalidTag,
Paul Kehrer22e80cb2013-11-20 21:27:00 -060010)
Alex Gaynorbd458ae2013-10-16 11:59:30 -070011
Paul Kehrerf7f6a9f2013-11-11 20:43:52 -060012from ...utils import load_vectors_from_file
13
Alex Gaynorbd458ae2013-10-16 11:59:30 -070014
Alex Gaynore5c5eec2013-12-13 08:10:20 -080015def _load_all_params(path, file_names, param_loader):
16 all_params = []
17 for file_name in file_names:
18 all_params.extend(
19 load_vectors_from_file(os.path.join(path, file_name), param_loader)
20 )
21 return all_params
22
Alex Gaynor4eec0bb2013-12-13 09:12:19 -080023
Alex Gaynor016eed12013-10-16 14:16:04 -070024def generate_encrypt_test(param_loader, path, file_names, cipher_factory,
Paul Kehrerdb37d0e2013-10-22 20:13:06 -050025 mode_factory, only_if=lambda backend: True,
Alex Gaynor512dd692013-10-16 14:27:52 -070026 skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080027 all_params = _load_all_params(path, file_names, param_loader)
28
29 @pytest.mark.parametrize("params", all_params)
30 def test_encryption(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -080031 encrypt_test(
32 backend,
33 cipher_factory,
34 mode_factory,
35 params,
36 only_if,
37 skip_message
Alex Gaynore5c5eec2013-12-13 08:10:20 -080038 )
Alex Gaynore5c5eec2013-12-13 08:10:20 -080039
Alex Gaynorbd458ae2013-10-16 11:59:30 -070040 return test_encryption
41
42
Alex Gaynor21919e22013-12-13 08:56:32 -080043def encrypt_test(backend, cipher_factory, mode_factory, params, only_if,
44 skip_message):
45 if not only_if(backend):
46 pytest.skip(skip_message)
47 plaintext = params.pop("plaintext")
48 ciphertext = params.pop("ciphertext")
49 cipher = Cipher(
50 cipher_factory(**params),
51 mode_factory(**params),
52 backend=backend
53 )
54 encryptor = cipher.encryptor()
55 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
56 actual_ciphertext += encryptor.finalize()
57 assert actual_ciphertext == binascii.unhexlify(ciphertext)
58 decryptor = cipher.decryptor()
59 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
60 actual_plaintext += decryptor.finalize()
61 assert actual_plaintext == binascii.unhexlify(plaintext)
62
63
Paul Kehrer22e80cb2013-11-20 21:27:00 -060064def generate_aead_test(param_loader, path, file_names, cipher_factory,
65 mode_factory, only_if, skip_message):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080066 all_params = _load_all_params(path, file_names, param_loader)
67
68 @pytest.mark.parametrize("params", all_params)
69 def test_aead(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -080070 aead_test(
71 backend,
72 cipher_factory,
73 mode_factory,
74 params,
75 only_if,
76 skip_message
77 )
Alex Gaynore5c5eec2013-12-13 08:10:20 -080078
Paul Kehrer22e80cb2013-11-20 21:27:00 -060079 return test_aead
80
81
Alex Gaynor21919e22013-12-13 08:56:32 -080082def aead_test(backend, cipher_factory, mode_factory, params, only_if,
83 skip_message):
84 if not only_if(backend):
85 pytest.skip(skip_message)
86 if params.get("pt") is not None:
87 plaintext = params.pop("pt")
88 ciphertext = params.pop("ct")
89 aad = params.pop("aad")
90 if params.get("fail") is True:
91 cipher = Cipher(
92 cipher_factory(binascii.unhexlify(params["key"])),
93 mode_factory(binascii.unhexlify(params["iv"]),
94 binascii.unhexlify(params["tag"])),
95 backend
96 )
97 decryptor = cipher.decryptor()
98 decryptor.authenticate_additional_data(binascii.unhexlify(aad))
99 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
100 with pytest.raises(InvalidTag):
101 decryptor.finalize()
102 else:
103 cipher = Cipher(
104 cipher_factory(binascii.unhexlify(params["key"])),
105 mode_factory(binascii.unhexlify(params["iv"]), None),
106 backend
107 )
108 encryptor = cipher.encryptor()
109 encryptor.authenticate_additional_data(binascii.unhexlify(aad))
110 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
111 actual_ciphertext += encryptor.finalize()
112 tag_len = len(params["tag"])
113 assert binascii.hexlify(encryptor.tag)[:tag_len] == params["tag"]
114 cipher = Cipher(
115 cipher_factory(binascii.unhexlify(params["key"])),
116 mode_factory(binascii.unhexlify(params["iv"]),
117 binascii.unhexlify(params["tag"])),
118 backend
119 )
120 decryptor = cipher.decryptor()
121 decryptor.authenticate_additional_data(binascii.unhexlify(aad))
122 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
123 actual_plaintext += decryptor.finalize()
124 assert actual_plaintext == binascii.unhexlify(plaintext)
125
126
Paul Kehrer4da28c32013-11-07 07:50:17 +0800127def generate_stream_encryption_test(param_loader, path, file_names,
128 cipher_factory, only_if=None,
129 skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800130 all_params = _load_all_params(path, file_names, param_loader)
131
132 @pytest.mark.parametrize("params", all_params)
133 def test_stream_encryption(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -0800134 stream_encryption_test(
135 backend,
136 cipher_factory,
137 params,
138 only_if,
139 skip_message
140 )
Paul Kehrer4da28c32013-11-07 07:50:17 +0800141 return test_stream_encryption
142
143
Alex Gaynor21919e22013-12-13 08:56:32 -0800144def stream_encryption_test(backend, cipher_factory, params, only_if,
145 skip_message):
146 if not only_if(backend):
147 pytest.skip(skip_message)
148 plaintext = params.pop("plaintext")
149 ciphertext = params.pop("ciphertext")
150 offset = params.pop("offset")
151 cipher = Cipher(cipher_factory(**params), None, backend=backend)
152 encryptor = cipher.encryptor()
153 # throw away offset bytes
154 encryptor.update(b"\x00" * int(offset))
155 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
156 actual_ciphertext += encryptor.finalize()
157 assert actual_ciphertext == binascii.unhexlify(ciphertext)
158 decryptor = cipher.decryptor()
159 decryptor.update(b"\x00" * int(offset))
160 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
161 actual_plaintext += decryptor.finalize()
162 assert actual_plaintext == binascii.unhexlify(plaintext)
163
164
165def generate_hash_test(param_loader, path, file_names, hash_cls,
166 only_if=None, skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800167 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800168
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800169 @pytest.mark.parametrize("params", all_params)
170 def test_hash(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -0800171 hash_test(
172 backend,
173 hash_cls,
174 params,
175 only_if,
176 skip_message
177 )
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500178 return test_hash
179
180
Alex Gaynor21919e22013-12-13 08:56:32 -0800181def hash_test(backend, algorithm, params, only_if, skip_message):
182 if only_if is not None and not only_if(backend):
183 pytest.skip(skip_message)
184 msg = params[0]
185 md = params[1]
186 m = hashes.Hash(algorithm, backend=backend)
187 m.update(binascii.unhexlify(msg))
188 expected_md = md.replace(" ", "").lower().encode("ascii")
189 assert m.finalize() == binascii.unhexlify(expected_md)
190
191
192def generate_base_hash_test(algorithm, digest_size, block_size,
193 only_if=None, skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800194 def test_base_hash(self, backend):
Alex Gaynor21919e22013-12-13 08:56:32 -0800195 base_hash_test(
196 backend,
197 algorithm,
198 digest_size,
199 block_size,
200 only_if,
201 skip_message,
202 )
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500203 return test_base_hash
204
205
Alex Gaynor21919e22013-12-13 08:56:32 -0800206def base_hash_test(backend, algorithm, digest_size, block_size, only_if,
207 skip_message):
208 if only_if is not None and not only_if(backend):
209 pytest.skip(skip_message)
210
211 m = hashes.Hash(algorithm, backend=backend)
212 assert m.algorithm.digest_size == digest_size
213 assert m.algorithm.block_size == block_size
214 m_copy = m.copy()
215 assert m != m_copy
216 assert m._ctx != m_copy._ctx
217
218 m.update(b"abc")
219 copy = m.copy()
220 copy.update(b"123")
221 m.update(b"123")
222 assert copy.finalize() == m.finalize()
223
224
225def generate_long_string_hash_test(hash_factory, md, only_if=None,
Paul Kehrerc1794072013-10-18 21:42:57 -0500226 skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800227 def test_long_string_hash(self, backend):
Alex Gaynor21919e22013-12-13 08:56:32 -0800228 long_string_hash_test(
229 backend,
230 hash_factory,
231 md,
232 only_if,
233 skip_message
234 )
Paul Kehrerc1794072013-10-18 21:42:57 -0500235 return test_long_string_hash
236
237
Alex Gaynor21919e22013-12-13 08:56:32 -0800238def long_string_hash_test(backend, algorithm, md, only_if, skip_message):
239 if only_if is not None and not only_if(backend):
240 pytest.skip(skip_message)
241 m = hashes.Hash(algorithm, backend=backend)
242 m.update(b"a" * 1000000)
243 assert m.finalize() == binascii.unhexlify(md.lower().encode("ascii"))
244
245
246def generate_hmac_test(param_loader, path, file_names, algorithm,
247 only_if=None, skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800248 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer0317b042013-10-28 17:34:27 -0500249
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800250 @pytest.mark.parametrize("params", all_params)
251 def test_hmac(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -0800252 hmac_test(
253 backend,
254 algorithm,
255 params,
256 only_if,
257 skip_message
258 )
Paul Kehrer0317b042013-10-28 17:34:27 -0500259 return test_hmac
260
261
Alex Gaynor21919e22013-12-13 08:56:32 -0800262def hmac_test(backend, algorithm, params, only_if, skip_message):
263 if only_if is not None and not only_if(backend):
264 pytest.skip(skip_message)
265 msg = params[0]
266 md = params[1]
267 key = params[2]
268 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
269 h.update(binascii.unhexlify(msg))
270 assert h.finalize() == binascii.unhexlify(md.encode("ascii"))
Paul Kehrer0317b042013-10-28 17:34:27 -0500271
Alex Gaynor21919e22013-12-13 08:56:32 -0800272
273def generate_base_hmac_test(hash_cls, only_if=None, skip_message=None):
274 def test_base_hmac(self, backend):
275 base_hmac_test(
276 backend,
277 hash_cls,
278 only_if,
279 skip_message,
280 )
Paul Kehrer0317b042013-10-28 17:34:27 -0500281 return test_base_hmac
282
283
Alex Gaynor21919e22013-12-13 08:56:32 -0800284def base_hmac_test(backend, algorithm, only_if, skip_message):
285 if only_if is not None and not only_if(backend):
286 pytest.skip(skip_message)
287 key = b"ab"
288 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
289 h_copy = h.copy()
290 assert h != h_copy
291 assert h._ctx != h_copy._ctx
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600292
Alex Gaynor21919e22013-12-13 08:56:32 -0800293
294def generate_aead_exception_test(cipher_factory, mode_factory,
295 only_if, skip_message):
296 def test_aead_exception(self, backend):
297 aead_exception_test(
298 backend,
299 cipher_factory,
300 mode_factory,
301 only_if,
302 skip_message
303 )
Paul Kehrerce9c6112013-11-22 14:10:59 -0600304 return test_aead_exception
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600305
306
Alex Gaynor21919e22013-12-13 08:56:32 -0800307def aead_exception_test(backend, cipher_factory, mode_factory,
308 only_if, skip_message):
309 if not only_if(backend):
310 pytest.skip(skip_message)
311 cipher = Cipher(
312 cipher_factory(binascii.unhexlify(b"0" * 32)),
313 mode_factory(binascii.unhexlify(b"0" * 24)),
314 backend
315 )
316 encryptor = cipher.encryptor()
317 encryptor.update(b"a" * 16)
318 with pytest.raises(NotYetFinalized):
319 encryptor.tag
320 with pytest.raises(AlreadyUpdated):
321 encryptor.authenticate_additional_data(b"b" * 16)
322 encryptor.finalize()
323 with pytest.raises(AlreadyFinalized):
324 encryptor.authenticate_additional_data(b"b" * 16)
325 with pytest.raises(AlreadyFinalized):
326 encryptor.update(b"b" * 16)
327 with pytest.raises(AlreadyFinalized):
328 encryptor.finalize()
329 cipher = Cipher(
330 cipher_factory(binascii.unhexlify(b"0" * 32)),
331 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
332 backend
333 )
334 decryptor = cipher.decryptor()
335 decryptor.update(b"a" * 16)
336 with pytest.raises(AttributeError):
337 decryptor.tag
Paul Kehrerb91221d2013-12-04 17:56:40 -0600338
Alex Gaynor21919e22013-12-13 08:56:32 -0800339
340def generate_aead_tag_exception_test(cipher_factory, mode_factory,
341 only_if, skip_message):
342 def test_aead_tag_exception(self, backend):
343 aead_tag_exception_test(
344 backend,
345 cipher_factory,
346 mode_factory,
347 only_if,
348 skip_message
349 )
Paul Kehrerb91221d2013-12-04 17:56:40 -0600350 return test_aead_tag_exception
Alex Gaynor21919e22013-12-13 08:56:32 -0800351
352
353def aead_tag_exception_test(backend, cipher_factory, mode_factory,
354 only_if, skip_message):
355 if not only_if(backend):
356 pytest.skip(skip_message)
357 cipher = Cipher(
358 cipher_factory(binascii.unhexlify(b"0" * 32)),
359 mode_factory(binascii.unhexlify(b"0" * 24)),
360 backend
361 )
362 with pytest.raises(ValueError):
363 cipher.decryptor()
364 cipher = Cipher(
365 cipher_factory(binascii.unhexlify(b"0" * 32)),
366 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
367 backend
368 )
369 with pytest.raises(ValueError):
370 cipher.encryptor()