blob: 7f67ad40d73275458383b101778d347c5cf79e16 [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
23
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):
31 if not only_if(backend):
32 pytest.skip(skip_message)
33 plaintext = params.pop("plaintext")
34 ciphertext = params.pop("ciphertext")
35 cipher = Cipher(
36 cipher_factory(**params),
37 mode_factory(**params),
38 backend=backend
39 )
40 encryptor = cipher.encryptor()
41 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
42 actual_ciphertext += encryptor.finalize()
43 assert actual_ciphertext == binascii.unhexlify(ciphertext)
44 decryptor = cipher.decryptor()
45 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
46 actual_plaintext += decryptor.finalize()
47 assert actual_plaintext == binascii.unhexlify(plaintext)
48
Alex Gaynorbd458ae2013-10-16 11:59:30 -070049 return test_encryption
50
51
Paul Kehrer22e80cb2013-11-20 21:27:00 -060052def generate_aead_test(param_loader, path, file_names, cipher_factory,
53 mode_factory, only_if, skip_message):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080054 all_params = _load_all_params(path, file_names, param_loader)
55
56 @pytest.mark.parametrize("params", all_params)
57 def test_aead(self, backend, params):
58 if not only_if(backend):
59 pytest.skip(skip_message)
60 if params.get("pt") is not None:
61 plaintext = params.pop("pt")
62 ciphertext = params.pop("ct")
63 aad = params.pop("aad")
64 if params.get("fail") is True:
65 cipher = Cipher(
66 cipher_factory(binascii.unhexlify(params["key"])),
67 mode_factory(binascii.unhexlify(params["iv"]),
68 binascii.unhexlify(params["tag"])),
69 backend
70 )
71 decryptor = cipher.decryptor()
72 decryptor.authenticate_additional_data(binascii.unhexlify(aad))
73 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
74 with pytest.raises(InvalidTag):
75 decryptor.finalize()
76 else:
77 cipher = Cipher(
78 cipher_factory(binascii.unhexlify(params["key"])),
79 mode_factory(binascii.unhexlify(params["iv"]), None),
80 backend
81 )
82 encryptor = cipher.encryptor()
83 encryptor.authenticate_additional_data(binascii.unhexlify(aad))
84 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
85 actual_ciphertext += encryptor.finalize()
86 tag_len = len(params["tag"])
87 assert binascii.hexlify(encryptor.tag)[:tag_len] == params["tag"]
88 cipher = Cipher(
89 cipher_factory(binascii.unhexlify(params["key"])),
90 mode_factory(binascii.unhexlify(params["iv"]),
91 binascii.unhexlify(params["tag"])),
92 backend
93 )
94 decryptor = cipher.decryptor()
95 decryptor.authenticate_additional_data(binascii.unhexlify(aad))
96 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
97 actual_plaintext += decryptor.finalize()
98 assert actual_plaintext == binascii.unhexlify(plaintext)
99
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600100 return test_aead
101
102
Paul Kehrer4da28c32013-11-07 07:50:17 +0800103def generate_stream_encryption_test(param_loader, path, file_names,
104 cipher_factory, only_if=None,
105 skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800106 all_params = _load_all_params(path, file_names, param_loader)
107
108 @pytest.mark.parametrize("params", all_params)
109 def test_stream_encryption(self, backend, params):
110 if not only_if(backend):
111 pytest.skip(skip_message)
112 plaintext = params.pop("plaintext")
113 ciphertext = params.pop("ciphertext")
114 offset = params.pop("offset")
115 cipher = Cipher(cipher_factory(**params), None, backend=backend)
116 encryptor = cipher.encryptor()
117 # throw away offset bytes
118 encryptor.update(b"\x00" * int(offset))
119 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
120 actual_ciphertext += encryptor.finalize()
121 assert actual_ciphertext == binascii.unhexlify(ciphertext)
122 decryptor = cipher.decryptor()
123 decryptor.update(b"\x00" * int(offset))
124 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
125 actual_plaintext += decryptor.finalize()
126 assert actual_plaintext == binascii.unhexlify(plaintext)
127
Paul Kehrer4da28c32013-11-07 07:50:17 +0800128 return test_stream_encryption
129
130
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800131def generate_hash_test(param_loader, path, file_names, algorithm, only_if=None,
132 skip_message=None):
133 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800134
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800135 @pytest.mark.parametrize("params", all_params)
136 def test_hash(self, backend, params):
137 if only_if is not None and not only_if(backend):
138 pytest.skip(skip_message)
139 msg, md = params
140 m = hashes.Hash(algorithm, backend=backend)
141 m.update(binascii.unhexlify(msg))
142 expected_md = md.replace(" ", "").lower().encode("ascii")
143 assert m.finalize() == binascii.unhexlify(expected_md)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800144
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500145 return test_hash
146
147
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800148def generate_base_hash_test(algorithm, digest_size, block_size, only_if=None,
149 skip_message=None):
150 def test_base_hash(self, backend):
151 if only_if is not None and not only_if(backend):
152 pytest.skip(skip_message)
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500153
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800154 m = hashes.Hash(algorithm, backend=backend)
155 assert m.algorithm.digest_size == digest_size
156 assert m.algorithm.block_size == block_size
157 m_copy = m.copy()
158 assert m != m_copy
159 assert m._ctx != m_copy._ctx
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500160
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800161 m.update(b"abc")
162 copy = m.copy()
163 copy.update(b"123")
164 m.update(b"123")
165 assert copy.finalize() == m.finalize()
166
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500167 return test_base_hash
168
169
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800170def generate_long_string_hash_test(algorithm, md, only_if=None,
Paul Kehrerc1794072013-10-18 21:42:57 -0500171 skip_message=None):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800172 def test_long_string_hash(self, backend):
173 if only_if is not None and not only_if(backend):
174 pytest.skip(skip_message)
175 m = hashes.Hash(algorithm, backend=backend)
176 m.update(b"a" * 1000000)
177 assert m.finalize() == binascii.unhexlify(md.lower().encode("ascii"))
178
Paul Kehrerc1794072013-10-18 21:42:57 -0500179 return test_long_string_hash
180
181
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800182def generate_hmac_test(param_loader, path, file_names, algorithm, only_if=None,
183 skip_message=None):
184 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer0317b042013-10-28 17:34:27 -0500185
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800186 @pytest.mark.parametrize("params", all_params)
187 def test_hmac(self, backend, params):
188 if only_if is not None and not only_if(backend):
189 pytest.skip(skip_message)
190 msg, md, key = params
191 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
192 h.update(binascii.unhexlify(msg))
193 assert h.finalize() == binascii.unhexlify(md.encode("ascii"))
Paul Kehrer0317b042013-10-28 17:34:27 -0500194
Paul Kehrer0317b042013-10-28 17:34:27 -0500195 return test_hmac
196
197
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800198def generate_base_hmac_test(algorithm, only_if=None, skip_message=None):
199 def test_base_hmac(self, backend):
200 if only_if is not None and not only_if(backend):
201 pytest.skip(skip_message)
202 key = b"ab"
203 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
204 h_copy = h.copy()
205 assert h != h_copy
206 assert h._ctx != h_copy._ctx
Paul Kehrer0317b042013-10-28 17:34:27 -0500207
Paul Kehrer0317b042013-10-28 17:34:27 -0500208 return test_base_hmac
209
210
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800211def generate_aead_exception_test(cipher_factory, mode_factory, only_if,
212 skip_message):
213 def test_aead_exception(self, backend):
214 if not only_if(backend):
215 pytest.skip(skip_message)
216 cipher = Cipher(
217 cipher_factory(binascii.unhexlify(b"0" * 32)),
218 mode_factory(binascii.unhexlify(b"0" * 24)),
219 backend
220 )
221 encryptor = cipher.encryptor()
222 encryptor.update(b"a" * 16)
223 with pytest.raises(NotYetFinalized):
224 encryptor.tag
225 with pytest.raises(AlreadyUpdated):
226 encryptor.authenticate_additional_data(b"b" * 16)
227 encryptor.finalize()
228 with pytest.raises(AlreadyFinalized):
229 encryptor.authenticate_additional_data(b"b" * 16)
230 with pytest.raises(AlreadyFinalized):
231 encryptor.update(b"b" * 16)
232 with pytest.raises(AlreadyFinalized):
233 encryptor.finalize()
234 cipher = Cipher(
235 cipher_factory(binascii.unhexlify(b"0" * 32)),
236 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
237 backend
238 )
239 decryptor = cipher.decryptor()
240 decryptor.update(b"a" * 16)
241 with pytest.raises(AttributeError):
242 decryptor.tag
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600243
Paul Kehrerce9c6112013-11-22 14:10:59 -0600244 return test_aead_exception
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600245
246
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800247def generate_aead_tag_exception_test(cipher_factory, mode_factory, only_if,
248 skip_message):
249 def test_aead_tag_exception(self, backend):
250 if not only_if(backend):
251 pytest.skip(skip_message)
252 cipher = Cipher(
253 cipher_factory(binascii.unhexlify(b"0" * 32)),
254 mode_factory(binascii.unhexlify(b"0" * 24)),
255 backend
256 )
257 with pytest.raises(ValueError):
258 cipher.decryptor()
259 cipher = Cipher(
260 cipher_factory(binascii.unhexlify(b"0" * 32)),
261 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
262 backend
263 )
264 with pytest.raises(ValueError):
265 cipher.encryptor()
Paul Kehrerb91221d2013-12-04 17:56:40 -0600266
Paul Kehrerb91221d2013-12-04 17:56:40 -0600267 return test_aead_tag_exception