blob: e0184777556038a77512df0beebc7cdc9c15af06 [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,
Alex Gaynor2a36dd12013-12-24 13:44:45 -080025 mode_factory, only_if, skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080026 all_params = _load_all_params(path, file_names, param_loader)
27
28 @pytest.mark.parametrize("params", all_params)
29 def test_encryption(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -080030 encrypt_test(
31 backend,
32 cipher_factory,
33 mode_factory,
34 params,
35 only_if,
36 skip_message
Alex Gaynore5c5eec2013-12-13 08:10:20 -080037 )
Alex Gaynore5c5eec2013-12-13 08:10:20 -080038
Alex Gaynorbd458ae2013-10-16 11:59:30 -070039 return test_encryption
40
41
Alex Gaynor21919e22013-12-13 08:56:32 -080042def encrypt_test(backend, cipher_factory, mode_factory, params, only_if,
43 skip_message):
44 if not only_if(backend):
45 pytest.skip(skip_message)
Paul Kehrera620b7d2013-12-20 22:59:02 -060046 plaintext = params["plaintext"]
47 ciphertext = params["ciphertext"]
Alex Gaynor21919e22013-12-13 08:56:32 -080048 cipher = Cipher(
49 cipher_factory(**params),
50 mode_factory(**params),
51 backend=backend
52 )
53 encryptor = cipher.encryptor()
54 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
55 actual_ciphertext += encryptor.finalize()
56 assert actual_ciphertext == binascii.unhexlify(ciphertext)
57 decryptor = cipher.decryptor()
58 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
59 actual_plaintext += decryptor.finalize()
60 assert actual_plaintext == binascii.unhexlify(plaintext)
61
62
Paul Kehrer22e80cb2013-11-20 21:27:00 -060063def generate_aead_test(param_loader, path, file_names, cipher_factory,
64 mode_factory, only_if, skip_message):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080065 all_params = _load_all_params(path, file_names, param_loader)
66
67 @pytest.mark.parametrize("params", all_params)
68 def test_aead(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -080069 aead_test(
70 backend,
71 cipher_factory,
72 mode_factory,
73 params,
74 only_if,
75 skip_message
76 )
Alex Gaynore5c5eec2013-12-13 08:10:20 -080077
Paul Kehrer22e80cb2013-11-20 21:27:00 -060078 return test_aead
79
80
Alex Gaynor21919e22013-12-13 08:56:32 -080081def aead_test(backend, cipher_factory, mode_factory, params, only_if,
82 skip_message):
83 if not only_if(backend):
84 pytest.skip(skip_message)
85 if params.get("pt") is not None:
Paul Kehrera620b7d2013-12-20 22:59:02 -060086 plaintext = params["pt"]
87 ciphertext = params["ct"]
88 aad = params["aad"]
Alex Gaynor21919e22013-12-13 08:56:32 -080089 if params.get("fail") is True:
90 cipher = Cipher(
91 cipher_factory(binascii.unhexlify(params["key"])),
92 mode_factory(binascii.unhexlify(params["iv"]),
93 binascii.unhexlify(params["tag"])),
94 backend
95 )
96 decryptor = cipher.decryptor()
97 decryptor.authenticate_additional_data(binascii.unhexlify(aad))
98 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
99 with pytest.raises(InvalidTag):
100 decryptor.finalize()
101 else:
102 cipher = Cipher(
103 cipher_factory(binascii.unhexlify(params["key"])),
104 mode_factory(binascii.unhexlify(params["iv"]), None),
105 backend
106 )
107 encryptor = cipher.encryptor()
108 encryptor.authenticate_additional_data(binascii.unhexlify(aad))
109 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
110 actual_ciphertext += encryptor.finalize()
111 tag_len = len(params["tag"])
112 assert binascii.hexlify(encryptor.tag)[:tag_len] == params["tag"]
113 cipher = Cipher(
114 cipher_factory(binascii.unhexlify(params["key"])),
115 mode_factory(binascii.unhexlify(params["iv"]),
116 binascii.unhexlify(params["tag"])),
117 backend
118 )
119 decryptor = cipher.decryptor()
120 decryptor.authenticate_additional_data(binascii.unhexlify(aad))
121 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
122 actual_plaintext += decryptor.finalize()
123 assert actual_plaintext == binascii.unhexlify(plaintext)
124
125
Paul Kehrer4da28c32013-11-07 07:50:17 +0800126def generate_stream_encryption_test(param_loader, path, file_names,
127 cipher_factory, only_if=None,
128 skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800129 all_params = _load_all_params(path, file_names, param_loader)
130
131 @pytest.mark.parametrize("params", all_params)
132 def test_stream_encryption(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -0800133 stream_encryption_test(
134 backend,
135 cipher_factory,
136 params,
137 only_if,
138 skip_message
139 )
Paul Kehrer4da28c32013-11-07 07:50:17 +0800140 return test_stream_encryption
141
142
Alex Gaynor21919e22013-12-13 08:56:32 -0800143def stream_encryption_test(backend, cipher_factory, params, only_if,
144 skip_message):
145 if not only_if(backend):
146 pytest.skip(skip_message)
Paul Kehrera620b7d2013-12-20 22:59:02 -0600147 plaintext = params["plaintext"]
148 ciphertext = params["ciphertext"]
149 offset = params["offset"]
Alex Gaynor21919e22013-12-13 08:56:32 -0800150 cipher = Cipher(cipher_factory(**params), None, backend=backend)
151 encryptor = cipher.encryptor()
152 # throw away offset bytes
153 encryptor.update(b"\x00" * int(offset))
154 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
155 actual_ciphertext += encryptor.finalize()
156 assert actual_ciphertext == binascii.unhexlify(ciphertext)
157 decryptor = cipher.decryptor()
158 decryptor.update(b"\x00" * int(offset))
159 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
160 actual_plaintext += decryptor.finalize()
161 assert actual_plaintext == binascii.unhexlify(plaintext)
162
163
164def generate_hash_test(param_loader, path, file_names, hash_cls,
165 only_if=None, skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800166 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800167
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800168 @pytest.mark.parametrize("params", all_params)
169 def test_hash(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -0800170 hash_test(
171 backend,
172 hash_cls,
173 params,
174 only_if,
175 skip_message
176 )
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500177 return test_hash
178
179
Alex Gaynor21919e22013-12-13 08:56:32 -0800180def hash_test(backend, algorithm, params, only_if, skip_message):
181 if only_if is not None and not only_if(backend):
182 pytest.skip(skip_message)
183 msg = params[0]
184 md = params[1]
185 m = hashes.Hash(algorithm, backend=backend)
186 m.update(binascii.unhexlify(msg))
187 expected_md = md.replace(" ", "").lower().encode("ascii")
188 assert m.finalize() == binascii.unhexlify(expected_md)
189
190
191def generate_base_hash_test(algorithm, digest_size, block_size,
192 only_if=None, skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800193 def test_base_hash(self, backend):
Alex Gaynor21919e22013-12-13 08:56:32 -0800194 base_hash_test(
195 backend,
196 algorithm,
197 digest_size,
198 block_size,
199 only_if,
200 skip_message,
201 )
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500202 return test_base_hash
203
204
Alex Gaynor21919e22013-12-13 08:56:32 -0800205def base_hash_test(backend, algorithm, digest_size, block_size, only_if,
206 skip_message):
207 if only_if is not None and not only_if(backend):
208 pytest.skip(skip_message)
209
210 m = hashes.Hash(algorithm, backend=backend)
211 assert m.algorithm.digest_size == digest_size
212 assert m.algorithm.block_size == block_size
213 m_copy = m.copy()
214 assert m != m_copy
215 assert m._ctx != m_copy._ctx
216
217 m.update(b"abc")
218 copy = m.copy()
219 copy.update(b"123")
220 m.update(b"123")
221 assert copy.finalize() == m.finalize()
222
223
224def generate_long_string_hash_test(hash_factory, md, only_if=None,
Paul Kehrerc1794072013-10-18 21:42:57 -0500225 skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800226 def test_long_string_hash(self, backend):
Alex Gaynor21919e22013-12-13 08:56:32 -0800227 long_string_hash_test(
228 backend,
229 hash_factory,
230 md,
231 only_if,
232 skip_message
233 )
Paul Kehrerc1794072013-10-18 21:42:57 -0500234 return test_long_string_hash
235
236
Alex Gaynor21919e22013-12-13 08:56:32 -0800237def long_string_hash_test(backend, algorithm, md, only_if, skip_message):
238 if only_if is not None and not only_if(backend):
239 pytest.skip(skip_message)
240 m = hashes.Hash(algorithm, backend=backend)
241 m.update(b"a" * 1000000)
242 assert m.finalize() == binascii.unhexlify(md.lower().encode("ascii"))
243
244
245def generate_hmac_test(param_loader, path, file_names, algorithm,
246 only_if=None, skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800247 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer0317b042013-10-28 17:34:27 -0500248
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800249 @pytest.mark.parametrize("params", all_params)
250 def test_hmac(self, backend, params):
Alex Gaynor21919e22013-12-13 08:56:32 -0800251 hmac_test(
252 backend,
253 algorithm,
254 params,
255 only_if,
256 skip_message
257 )
Paul Kehrer0317b042013-10-28 17:34:27 -0500258 return test_hmac
259
260
Alex Gaynor21919e22013-12-13 08:56:32 -0800261def hmac_test(backend, algorithm, params, only_if, skip_message):
262 if only_if is not None and not only_if(backend):
263 pytest.skip(skip_message)
264 msg = params[0]
265 md = params[1]
266 key = params[2]
267 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
268 h.update(binascii.unhexlify(msg))
269 assert h.finalize() == binascii.unhexlify(md.encode("ascii"))
Paul Kehrer0317b042013-10-28 17:34:27 -0500270
Alex Gaynor21919e22013-12-13 08:56:32 -0800271
272def generate_base_hmac_test(hash_cls, only_if=None, skip_message=None):
273 def test_base_hmac(self, backend):
274 base_hmac_test(
275 backend,
276 hash_cls,
277 only_if,
278 skip_message,
279 )
Paul Kehrer0317b042013-10-28 17:34:27 -0500280 return test_base_hmac
281
282
Alex Gaynor21919e22013-12-13 08:56:32 -0800283def base_hmac_test(backend, algorithm, only_if, skip_message):
284 if only_if is not None and not only_if(backend):
285 pytest.skip(skip_message)
286 key = b"ab"
287 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
288 h_copy = h.copy()
289 assert h != h_copy
290 assert h._ctx != h_copy._ctx
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600291
Alex Gaynor21919e22013-12-13 08:56:32 -0800292
293def generate_aead_exception_test(cipher_factory, mode_factory,
294 only_if, skip_message):
295 def test_aead_exception(self, backend):
296 aead_exception_test(
297 backend,
298 cipher_factory,
299 mode_factory,
300 only_if,
301 skip_message
302 )
Paul Kehrerce9c6112013-11-22 14:10:59 -0600303 return test_aead_exception
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600304
305
Alex Gaynor21919e22013-12-13 08:56:32 -0800306def aead_exception_test(backend, cipher_factory, mode_factory,
307 only_if, skip_message):
308 if not only_if(backend):
309 pytest.skip(skip_message)
310 cipher = Cipher(
311 cipher_factory(binascii.unhexlify(b"0" * 32)),
312 mode_factory(binascii.unhexlify(b"0" * 24)),
313 backend
314 )
315 encryptor = cipher.encryptor()
316 encryptor.update(b"a" * 16)
317 with pytest.raises(NotYetFinalized):
318 encryptor.tag
319 with pytest.raises(AlreadyUpdated):
320 encryptor.authenticate_additional_data(b"b" * 16)
321 encryptor.finalize()
322 with pytest.raises(AlreadyFinalized):
323 encryptor.authenticate_additional_data(b"b" * 16)
324 with pytest.raises(AlreadyFinalized):
325 encryptor.update(b"b" * 16)
326 with pytest.raises(AlreadyFinalized):
327 encryptor.finalize()
328 cipher = Cipher(
329 cipher_factory(binascii.unhexlify(b"0" * 32)),
330 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
331 backend
332 )
333 decryptor = cipher.decryptor()
334 decryptor.update(b"a" * 16)
335 with pytest.raises(AttributeError):
336 decryptor.tag
Paul Kehrerb91221d2013-12-04 17:56:40 -0600337
Alex Gaynor21919e22013-12-13 08:56:32 -0800338
339def generate_aead_tag_exception_test(cipher_factory, mode_factory,
340 only_if, skip_message):
341 def test_aead_tag_exception(self, backend):
342 aead_tag_exception_test(
343 backend,
344 cipher_factory,
345 mode_factory,
346 only_if,
347 skip_message
348 )
Paul Kehrerb91221d2013-12-04 17:56:40 -0600349 return test_aead_tag_exception
Alex Gaynor21919e22013-12-13 08:56:32 -0800350
351
352def aead_tag_exception_test(backend, cipher_factory, mode_factory,
353 only_if, skip_message):
354 if not only_if(backend):
355 pytest.skip(skip_message)
356 cipher = Cipher(
357 cipher_factory(binascii.unhexlify(b"0" * 32)),
358 mode_factory(binascii.unhexlify(b"0" * 24)),
359 backend
360 )
361 with pytest.raises(ValueError):
362 cipher.decryptor()
363 cipher = Cipher(
364 cipher_factory(binascii.unhexlify(b"0" * 32)),
Paul Kehrerf7b4ede2013-12-21 17:25:19 -0600365 mode_factory(binascii.unhexlify(b"0" * 24), b"000"),
366 backend
367 )
368 with pytest.raises(ValueError):
369 cipher.decryptor()
370 cipher = Cipher(
371 cipher_factory(binascii.unhexlify(b"0" * 32)),
Alex Gaynor21919e22013-12-13 08:56:32 -0800372 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
373 backend
374 )
375 with pytest.raises(ValueError):
376 cipher.encryptor()