blob: 39f5ae829441c1896185130339a470d6d5e12118 [file] [log] [blame]
Alex Gaynorbd458ae2013-10-16 11:59:30 -07001import binascii
2import os
3
4import pytest
5
Donald Stufftce0d7812013-10-27 16:52:33 -04006from cryptography.hazmat.bindings import _ALL_BACKENDS
Paul Kehrer22e80cb2013-11-20 21:27:00 -06007from cryptography.hazmat.primitives import hashes, hmac
Paul Kehrer21dde562013-11-06 12:22:09 +08008from cryptography.hazmat.primitives.ciphers import Cipher
Paul Kehrer22e80cb2013-11-20 21:27:00 -06009from cryptography.exceptions import (
Paul Kehrera4bfc082013-11-22 19:57:37 -060010 AlreadyFinalized, NotYetFinalized, AlreadyUpdated, InvalidTag,
Paul Kehrer22e80cb2013-11-20 21:27:00 -060011)
Alex Gaynorbd458ae2013-10-16 11:59:30 -070012
Paul Kehrerf7f6a9f2013-11-11 20:43:52 -060013from ...utils import load_vectors_from_file
14
Alex Gaynorbd458ae2013-10-16 11:59:30 -070015
Alex Gaynor016eed12013-10-16 14:16:04 -070016def generate_encrypt_test(param_loader, path, file_names, cipher_factory,
Paul Kehrerdb37d0e2013-10-22 20:13:06 -050017 mode_factory, only_if=lambda backend: True,
Alex Gaynor512dd692013-10-16 14:27:52 -070018 skip_message=None):
Alex Gaynorbd458ae2013-10-16 11:59:30 -070019 def test_encryption(self):
Paul Kehrerdb37d0e2013-10-22 20:13:06 -050020 for backend in _ALL_BACKENDS:
Alex Gaynor512dd692013-10-16 14:27:52 -070021 for file_name in file_names:
Paul Kehrerf7f6a9f2013-11-11 20:43:52 -060022 for params in load_vectors_from_file(
23 os.path.join(path, file_name),
24 param_loader
25 ):
Alex Gaynor512dd692013-10-16 14:27:52 -070026 yield (
27 encrypt_test,
Paul Kehrerdb37d0e2013-10-22 20:13:06 -050028 backend,
Alex Gaynor512dd692013-10-16 14:27:52 -070029 cipher_factory,
30 mode_factory,
31 params,
32 only_if,
33 skip_message
34 )
Alex Gaynorbd458ae2013-10-16 11:59:30 -070035 return test_encryption
36
37
Paul Kehrerdb37d0e2013-10-22 20:13:06 -050038def encrypt_test(backend, cipher_factory, mode_factory, params, only_if,
Alex Gaynor512dd692013-10-16 14:27:52 -070039 skip_message):
Paul Kehrerdb37d0e2013-10-22 20:13:06 -050040 if not only_if(backend):
Alex Gaynor512dd692013-10-16 14:27:52 -070041 pytest.skip(skip_message)
Alex Gaynorbd458ae2013-10-16 11:59:30 -070042 plaintext = params.pop("plaintext")
43 ciphertext = params.pop("ciphertext")
Paul Kehrer21dde562013-11-06 12:22:09 +080044 cipher = Cipher(
Alex Gaynorbd458ae2013-10-16 11:59:30 -070045 cipher_factory(**params),
46 mode_factory(**params),
David Reid9a1b0c72013-11-25 09:14:02 -080047 backend=backend
Alex Gaynorbd458ae2013-10-16 11:59:30 -070048 )
Paul Kehrer620c2ae2013-10-19 14:12:04 -050049 encryptor = cipher.encryptor()
50 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
51 actual_ciphertext += encryptor.finalize()
Alex Gaynorfb39b3f2013-10-16 14:30:59 -070052 assert actual_ciphertext == binascii.unhexlify(ciphertext)
Paul Kehrer620c2ae2013-10-19 14:12:04 -050053 decryptor = cipher.decryptor()
54 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
55 actual_plaintext += decryptor.finalize()
56 assert actual_plaintext == binascii.unhexlify(plaintext)
Paul Kehrerbde6fb52013-10-18 18:08:49 -050057
58
Paul Kehrer22e80cb2013-11-20 21:27:00 -060059def generate_aead_test(param_loader, path, file_names, cipher_factory,
60 mode_factory, only_if, skip_message):
61 def test_aead(self):
62 for backend in _ALL_BACKENDS:
63 for file_name in file_names:
64 for params in load_vectors_from_file(
65 os.path.join(path, file_name),
66 param_loader
67 ):
68 yield (
69 aead_test,
70 backend,
71 cipher_factory,
72 mode_factory,
73 params,
74 only_if,
75 skip_message
76 )
77 return test_aead
78
79
80def aead_test(backend, cipher_factory, mode_factory, params, only_if,
81 skip_message):
82 if not only_if(backend):
83 pytest.skip(skip_message)
84 if params.get("pt") is not None:
85 plaintext = params.pop("pt")
86 ciphertext = params.pop("ct")
87 aad = params.pop("aad")
88 if params.get("fail") is True:
89 cipher = Cipher(
90 cipher_factory(binascii.unhexlify(params["key"])),
91 mode_factory(binascii.unhexlify(params["iv"]),
92 binascii.unhexlify(params["tag"])),
93 backend
94 )
95 decryptor = cipher.decryptor()
96 decryptor.add_data(binascii.unhexlify(aad))
97 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
Paul Kehrera4bfc082013-11-22 19:57:37 -060098 with pytest.raises(InvalidTag):
Paul Kehrer22e80cb2013-11-20 21:27:00 -060099 decryptor.finalize()
100 else:
101 cipher = Cipher(
102 cipher_factory(binascii.unhexlify(params["key"])),
103 mode_factory(binascii.unhexlify(params["iv"]), None),
104 backend
105 )
106 encryptor = cipher.encryptor()
107 encryptor.add_data(binascii.unhexlify(aad))
108 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
109 actual_ciphertext += encryptor.finalize()
110 tag_len = len(params["tag"])
111 assert binascii.hexlify(encryptor.tag)[:tag_len] == params["tag"]
112 cipher = Cipher(
113 cipher_factory(binascii.unhexlify(params["key"])),
114 mode_factory(binascii.unhexlify(params["iv"]),
115 binascii.unhexlify(params["tag"])),
116 backend
117 )
118 decryptor = cipher.decryptor()
119 decryptor.add_data(binascii.unhexlify(aad))
120 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
121 actual_plaintext += decryptor.finalize()
122 assert actual_plaintext == binascii.unhexlify(plaintext)
123
124
Paul Kehrer4da28c32013-11-07 07:50:17 +0800125def generate_stream_encryption_test(param_loader, path, file_names,
126 cipher_factory, only_if=None,
127 skip_message=None):
128 def test_stream_encryption(self):
129 for backend in _ALL_BACKENDS:
130 for file_name in file_names:
Paul Kehrerf7f6a9f2013-11-11 20:43:52 -0600131 for params in load_vectors_from_file(
132 os.path.join(path, file_name),
133 param_loader
134 ):
Paul Kehrer4da28c32013-11-07 07:50:17 +0800135 yield (
136 stream_encryption_test,
137 backend,
138 cipher_factory,
139 params,
140 only_if,
141 skip_message
142 )
143 return test_stream_encryption
144
145
146def stream_encryption_test(backend, cipher_factory, params, only_if,
147 skip_message):
148 if not only_if(backend):
149 pytest.skip(skip_message)
150 plaintext = params.pop("plaintext")
151 ciphertext = params.pop("ciphertext")
152 offset = params.pop("offset")
David Reid9a1b0c72013-11-25 09:14:02 -0800153 cipher = Cipher(cipher_factory(**params), None, backend=backend)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800154 encryptor = cipher.encryptor()
155 # throw away offset bytes
156 encryptor.update(b"\x00" * int(offset))
157 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
158 actual_ciphertext += encryptor.finalize()
159 assert actual_ciphertext == binascii.unhexlify(ciphertext)
160 decryptor = cipher.decryptor()
161 decryptor.update(b"\x00" * int(offset))
162 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
163 actual_plaintext += decryptor.finalize()
164 assert actual_plaintext == binascii.unhexlify(plaintext)
165
166
Paul Kehrerbb069c22013-10-18 19:51:01 -0500167def generate_hash_test(param_loader, path, file_names, hash_cls,
Donald Stufft2acd77a2013-10-19 19:49:30 -0400168 only_if=None, skip_message=None):
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500169 def test_hash(self):
Paul Kehrerdb37d0e2013-10-22 20:13:06 -0500170 for backend in _ALL_BACKENDS:
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500171 for file_name in file_names:
Paul Kehrerf7f6a9f2013-11-11 20:43:52 -0600172 for params in load_vectors_from_file(
173 os.path.join(path, file_name),
174 param_loader
175 ):
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500176 yield (
177 hash_test,
Paul Kehrerdb37d0e2013-10-22 20:13:06 -0500178 backend,
Paul Kehrerbb069c22013-10-18 19:51:01 -0500179 hash_cls,
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500180 params,
181 only_if,
182 skip_message
183 )
184 return test_hash
185
186
David Reidbb0d3f02013-10-31 15:22:49 -0700187def hash_test(backend, algorithm, params, only_if, skip_message):
Paul Kehrerdb37d0e2013-10-22 20:13:06 -0500188 if only_if is not None and not only_if(backend):
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500189 pytest.skip(skip_message)
190 msg = params[0]
191 md = params[1]
David Reid9a1b0c72013-11-25 09:14:02 -0800192 m = hashes.Hash(algorithm, backend=backend)
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500193 m.update(binascii.unhexlify(msg))
David Reidc3d029f2013-10-31 14:06:14 -0700194 expected_md = md.replace(" ", "").lower().encode("ascii")
195 assert m.finalize() == binascii.unhexlify(expected_md)
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500196
197
David Reid69aeb492013-10-30 11:35:37 -0700198def generate_base_hash_test(algorithm, digest_size, block_size,
Donald Stufft2acd77a2013-10-19 19:49:30 -0400199 only_if=None, skip_message=None):
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500200 def test_base_hash(self):
Paul Kehrerdb37d0e2013-10-22 20:13:06 -0500201 for backend in _ALL_BACKENDS:
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500202 yield (
203 base_hash_test,
Paul Kehrerdb37d0e2013-10-22 20:13:06 -0500204 backend,
David Reid69aeb492013-10-30 11:35:37 -0700205 algorithm,
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500206 digest_size,
207 block_size,
208 only_if,
209 skip_message,
210 )
211 return test_base_hash
212
213
David Reid69aeb492013-10-30 11:35:37 -0700214def base_hash_test(backend, algorithm, digest_size, block_size, only_if,
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500215 skip_message):
Paul Kehrerdb37d0e2013-10-22 20:13:06 -0500216 if only_if is not None and not only_if(backend):
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500217 pytest.skip(skip_message)
David Reid69aeb492013-10-30 11:35:37 -0700218
David Reid9a1b0c72013-11-25 09:14:02 -0800219 m = hashes.Hash(algorithm, backend=backend)
David Reid69aeb492013-10-30 11:35:37 -0700220 assert m.algorithm.digest_size == digest_size
221 assert m.algorithm.block_size == block_size
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500222 m_copy = m.copy()
223 assert m != m_copy
224 assert m._ctx != m_copy._ctx
Paul Kehrerc1794072013-10-18 21:42:57 -0500225
Alex Gaynor217e3b52013-11-12 10:27:49 -0800226 m.update(b"abc")
227 copy = m.copy()
228 copy.update(b"123")
229 m.update(b"123")
230 assert copy.finalize() == m.finalize()
231
Paul Kehrerc1794072013-10-18 21:42:57 -0500232
Donald Stufft2acd77a2013-10-19 19:49:30 -0400233def generate_long_string_hash_test(hash_factory, md, only_if=None,
Paul Kehrerc1794072013-10-18 21:42:57 -0500234 skip_message=None):
235 def test_long_string_hash(self):
Paul Kehrerdb37d0e2013-10-22 20:13:06 -0500236 for backend in _ALL_BACKENDS:
Paul Kehrerc1794072013-10-18 21:42:57 -0500237 yield(
238 long_string_hash_test,
Paul Kehrerdb37d0e2013-10-22 20:13:06 -0500239 backend,
Paul Kehrerc1794072013-10-18 21:42:57 -0500240 hash_factory,
241 md,
242 only_if,
243 skip_message
244 )
245 return test_long_string_hash
246
247
David Reid69aeb492013-10-30 11:35:37 -0700248def long_string_hash_test(backend, algorithm, md, only_if, skip_message):
Paul Kehrerdb37d0e2013-10-22 20:13:06 -0500249 if only_if is not None and not only_if(backend):
Paul Kehrerc1794072013-10-18 21:42:57 -0500250 pytest.skip(skip_message)
David Reid9a1b0c72013-11-25 09:14:02 -0800251 m = hashes.Hash(algorithm, backend=backend)
Paul Kehrerc1794072013-10-18 21:42:57 -0500252 m.update(b"a" * 1000000)
David Reidc3d029f2013-10-31 14:06:14 -0700253 assert m.finalize() == binascii.unhexlify(md.lower().encode("ascii"))
Paul Kehrer0317b042013-10-28 17:34:27 -0500254
255
David Reide3960f62013-11-01 14:52:16 -0700256def generate_hmac_test(param_loader, path, file_names, algorithm,
Paul Kehrer0317b042013-10-28 17:34:27 -0500257 only_if=None, skip_message=None):
258 def test_hmac(self):
259 for backend in _ALL_BACKENDS:
260 for file_name in file_names:
Paul Kehrerf7f6a9f2013-11-11 20:43:52 -0600261 for params in load_vectors_from_file(
262 os.path.join(path, file_name),
263 param_loader
264 ):
Paul Kehrer0317b042013-10-28 17:34:27 -0500265 yield (
266 hmac_test,
267 backend,
David Reide3960f62013-11-01 14:52:16 -0700268 algorithm,
Paul Kehrer0317b042013-10-28 17:34:27 -0500269 params,
270 only_if,
271 skip_message
272 )
273 return test_hmac
274
275
David Reide3960f62013-11-01 14:52:16 -0700276def hmac_test(backend, algorithm, params, only_if, skip_message):
Paul Kehrer0317b042013-10-28 17:34:27 -0500277 if only_if is not None and not only_if(backend):
278 pytest.skip(skip_message)
279 msg = params[0]
280 md = params[1]
281 key = params[2]
David Reid9a1b0c72013-11-25 09:14:02 -0800282 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
Paul Kehrer0317b042013-10-28 17:34:27 -0500283 h.update(binascii.unhexlify(msg))
David Reid753ae192013-11-01 16:28:41 -0700284 assert h.finalize() == binascii.unhexlify(md.encode("ascii"))
Paul Kehrer0317b042013-10-28 17:34:27 -0500285
286
287def generate_base_hmac_test(hash_cls, only_if=None, skip_message=None):
288 def test_base_hmac(self):
289 for backend in _ALL_BACKENDS:
290 yield (
291 base_hmac_test,
292 backend,
293 hash_cls,
294 only_if,
295 skip_message,
296 )
297 return test_base_hmac
298
299
David Reide3960f62013-11-01 14:52:16 -0700300def base_hmac_test(backend, algorithm, only_if, skip_message):
Paul Kehrer0317b042013-10-28 17:34:27 -0500301 if only_if is not None and not only_if(backend):
302 pytest.skip(skip_message)
303 key = b"ab"
David Reid9a1b0c72013-11-25 09:14:02 -0800304 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
Paul Kehrer0317b042013-10-28 17:34:27 -0500305 h_copy = h.copy()
306 assert h != h_copy
307 assert h._ctx != h_copy._ctx
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600308
309
Paul Kehrerce9c6112013-11-22 14:10:59 -0600310def generate_aead_exception_test(cipher_factory, mode_factory,
311 only_if, skip_message):
312 def test_aead_exception(self):
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600313 for backend in _ALL_BACKENDS:
314 yield (
Paul Kehrerce9c6112013-11-22 14:10:59 -0600315 aead_exception_test,
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600316 backend,
317 cipher_factory,
318 mode_factory,
319 only_if,
320 skip_message
321 )
Paul Kehrerce9c6112013-11-22 14:10:59 -0600322 return test_aead_exception
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600323
324
Paul Kehrerce9c6112013-11-22 14:10:59 -0600325def aead_exception_test(backend, cipher_factory, mode_factory,
326 only_if, skip_message):
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600327 if not only_if(backend):
328 pytest.skip(skip_message)
329 cipher = Cipher(
330 cipher_factory(binascii.unhexlify(b"0" * 32)),
331 mode_factory(binascii.unhexlify(b"0" * 24)),
332 backend
333 )
334 encryptor = cipher.encryptor()
335 encryptor.update(b"a" * 16)
Paul Kehrercc9ec982013-11-21 11:21:35 -0600336 with pytest.raises(NotYetFinalized):
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600337 encryptor.tag
Paul Kehrerce9c6112013-11-22 14:10:59 -0600338 with pytest.raises(AlreadyUpdated):
339 encryptor.add_data(b"b" * 16)
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600340 encryptor.finalize()
341 with pytest.raises(AlreadyFinalized):
342 encryptor.add_data(b"b" * 16)
Paul Kehrer24316fd2013-11-22 13:30:46 -0600343 with pytest.raises(AlreadyFinalized):
344 encryptor.update(b"b" * 16)
345 with pytest.raises(AlreadyFinalized):
346 encryptor.finalize()