blob: f0a0031923510ab446253fed85e35ab579f4c977 [file] [log] [blame]
Alex Gaynorc37feed2014-03-08 08:32:56 -08001# Licensed under the Apache License, Version 2.0 (the "License");
2# you may not use this file except in compliance with the License.
3# You may obtain a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS,
9# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10# implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14from __future__ import absolute_import, division, print_function
15
Alex Gaynorbd458ae2013-10-16 11:59:30 -070016import binascii
17import os
18
David Reid5443e9d2014-01-22 17:18:49 -080019import itertools
20
Alex Gaynorbd458ae2013-10-16 11:59:30 -070021import pytest
22
Paul Kehrer22e80cb2013-11-20 21:27:00 -060023from cryptography.hazmat.primitives import hashes, hmac
Paul Kehrer1277bc72014-01-28 17:09:59 -060024from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
Paul Kehrer21dde562013-11-06 12:22:09 +080025from cryptography.hazmat.primitives.ciphers import Cipher
David Reid0d492db2014-01-27 17:05:49 -080026from cryptography.hazmat.primitives.kdf.hkdf import HKDF
David Reid66c9cd92014-01-20 16:05:53 -080027
Paul Kehrer22e80cb2013-11-20 21:27:00 -060028from cryptography.exceptions import (
Paul Kehrera4bfc082013-11-22 19:57:37 -060029 AlreadyFinalized, NotYetFinalized, AlreadyUpdated, InvalidTag,
Paul Kehrer22e80cb2013-11-20 21:27:00 -060030)
Alex Gaynorbd458ae2013-10-16 11:59:30 -070031
Paul Kehrerf7f6a9f2013-11-11 20:43:52 -060032from ...utils import load_vectors_from_file
33
Alex Gaynorbd458ae2013-10-16 11:59:30 -070034
Alex Gaynore5c5eec2013-12-13 08:10:20 -080035def _load_all_params(path, file_names, param_loader):
36 all_params = []
37 for file_name in file_names:
38 all_params.extend(
39 load_vectors_from_file(os.path.join(path, file_name), param_loader)
40 )
41 return all_params
42
Alex Gaynor4eec0bb2013-12-13 09:12:19 -080043
Alex Gaynor016eed12013-10-16 14:16:04 -070044def generate_encrypt_test(param_loader, path, file_names, cipher_factory,
Paul Kehrer783479c2013-12-26 21:08:45 -060045 mode_factory):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080046 all_params = _load_all_params(path, file_names, param_loader)
47
48 @pytest.mark.parametrize("params", all_params)
49 def test_encryption(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -060050 encrypt_test(backend, cipher_factory, mode_factory, params)
Alex Gaynore5c5eec2013-12-13 08:10:20 -080051
Alex Gaynorbd458ae2013-10-16 11:59:30 -070052 return test_encryption
53
54
Paul Kehrer783479c2013-12-26 21:08:45 -060055def encrypt_test(backend, cipher_factory, mode_factory, params):
Paul Kehrera620b7d2013-12-20 22:59:02 -060056 plaintext = params["plaintext"]
57 ciphertext = params["ciphertext"]
Alex Gaynor21919e22013-12-13 08:56:32 -080058 cipher = Cipher(
59 cipher_factory(**params),
60 mode_factory(**params),
61 backend=backend
62 )
63 encryptor = cipher.encryptor()
64 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
65 actual_ciphertext += encryptor.finalize()
66 assert actual_ciphertext == binascii.unhexlify(ciphertext)
67 decryptor = cipher.decryptor()
68 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
69 actual_plaintext += decryptor.finalize()
70 assert actual_plaintext == binascii.unhexlify(plaintext)
71
72
Paul Kehrer22e80cb2013-11-20 21:27:00 -060073def generate_aead_test(param_loader, path, file_names, cipher_factory,
Paul Kehrer783479c2013-12-26 21:08:45 -060074 mode_factory):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080075 all_params = _load_all_params(path, file_names, param_loader)
76
77 @pytest.mark.parametrize("params", all_params)
78 def test_aead(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -060079 aead_test(backend, cipher_factory, mode_factory, params)
Alex Gaynore5c5eec2013-12-13 08:10:20 -080080
Paul Kehrer22e80cb2013-11-20 21:27:00 -060081 return test_aead
82
83
Paul Kehrer783479c2013-12-26 21:08:45 -060084def aead_test(backend, cipher_factory, mode_factory, params):
Alex Gaynor21919e22013-12-13 08:56:32 -080085 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,
Paul Kehrer783479c2013-12-26 21:08:45 -0600127 cipher_factory):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800128 all_params = _load_all_params(path, file_names, param_loader)
129
130 @pytest.mark.parametrize("params", all_params)
131 def test_stream_encryption(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -0600132 stream_encryption_test(backend, cipher_factory, params)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800133 return test_stream_encryption
134
135
Paul Kehrer783479c2013-12-26 21:08:45 -0600136def stream_encryption_test(backend, cipher_factory, params):
Paul Kehrera620b7d2013-12-20 22:59:02 -0600137 plaintext = params["plaintext"]
138 ciphertext = params["ciphertext"]
139 offset = params["offset"]
Alex Gaynor21919e22013-12-13 08:56:32 -0800140 cipher = Cipher(cipher_factory(**params), None, backend=backend)
141 encryptor = cipher.encryptor()
142 # throw away offset bytes
143 encryptor.update(b"\x00" * int(offset))
144 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
145 actual_ciphertext += encryptor.finalize()
146 assert actual_ciphertext == binascii.unhexlify(ciphertext)
147 decryptor = cipher.decryptor()
148 decryptor.update(b"\x00" * int(offset))
149 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
150 actual_plaintext += decryptor.finalize()
151 assert actual_plaintext == binascii.unhexlify(plaintext)
152
153
Paul Kehrer783479c2013-12-26 21:08:45 -0600154def generate_hash_test(param_loader, path, file_names, hash_cls):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800155 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800156
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800157 @pytest.mark.parametrize("params", all_params)
158 def test_hash(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -0600159 hash_test(backend, hash_cls, params)
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500160 return test_hash
161
162
Paul Kehrer783479c2013-12-26 21:08:45 -0600163def hash_test(backend, algorithm, params):
Alex Gaynor36e651c2014-01-27 10:08:35 -0800164 msg, md = params
Alex Gaynor21919e22013-12-13 08:56:32 -0800165 m = hashes.Hash(algorithm, backend=backend)
166 m.update(binascii.unhexlify(msg))
167 expected_md = md.replace(" ", "").lower().encode("ascii")
168 assert m.finalize() == binascii.unhexlify(expected_md)
169
170
Paul Kehrerb078d8e2013-12-27 16:33:14 -0600171def generate_base_hash_test(algorithm, digest_size, block_size):
172 def test_base_hash(self, backend):
173 base_hash_test(backend, algorithm, digest_size, block_size)
174 return test_base_hash
175
176
Paul Kehrer783479c2013-12-26 21:08:45 -0600177def base_hash_test(backend, algorithm, digest_size, block_size):
Alex Gaynor21919e22013-12-13 08:56:32 -0800178 m = hashes.Hash(algorithm, backend=backend)
179 assert m.algorithm.digest_size == digest_size
180 assert m.algorithm.block_size == block_size
181 m_copy = m.copy()
182 assert m != m_copy
183 assert m._ctx != m_copy._ctx
184
185 m.update(b"abc")
186 copy = m.copy()
187 copy.update(b"123")
188 m.update(b"123")
189 assert copy.finalize() == m.finalize()
190
191
Paul Kehrer783479c2013-12-26 21:08:45 -0600192def generate_long_string_hash_test(hash_factory, md):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800193 def test_long_string_hash(self, backend):
Paul Kehrer783479c2013-12-26 21:08:45 -0600194 long_string_hash_test(backend, hash_factory, md)
Paul Kehrerc1794072013-10-18 21:42:57 -0500195 return test_long_string_hash
196
197
Paul Kehrer783479c2013-12-26 21:08:45 -0600198def long_string_hash_test(backend, algorithm, md):
Alex Gaynor21919e22013-12-13 08:56:32 -0800199 m = hashes.Hash(algorithm, backend=backend)
200 m.update(b"a" * 1000000)
201 assert m.finalize() == binascii.unhexlify(md.lower().encode("ascii"))
202
203
Paul Kehrerb078d8e2013-12-27 16:33:14 -0600204def generate_base_hmac_test(hash_cls):
205 def test_base_hmac(self, backend):
206 base_hmac_test(backend, hash_cls)
207 return test_base_hmac
208
209
210def base_hmac_test(backend, algorithm):
211 key = b"ab"
212 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
213 h_copy = h.copy()
214 assert h != h_copy
215 assert h._ctx != h_copy._ctx
216
217
Paul Kehrer783479c2013-12-26 21:08:45 -0600218def generate_hmac_test(param_loader, path, file_names, algorithm):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800219 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer0317b042013-10-28 17:34:27 -0500220
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800221 @pytest.mark.parametrize("params", all_params)
222 def test_hmac(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -0600223 hmac_test(backend, algorithm, params)
Paul Kehrer0317b042013-10-28 17:34:27 -0500224 return test_hmac
225
226
Paul Kehrer783479c2013-12-26 21:08:45 -0600227def hmac_test(backend, algorithm, params):
Alex Gaynor36e651c2014-01-27 10:08:35 -0800228 msg, md, key = params
Alex Gaynor21919e22013-12-13 08:56:32 -0800229 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
230 h.update(binascii.unhexlify(msg))
231 assert h.finalize() == binascii.unhexlify(md.encode("ascii"))
Paul Kehrer0317b042013-10-28 17:34:27 -0500232
Alex Gaynor21919e22013-12-13 08:56:32 -0800233
Paul Kehrer1050ddf2014-01-27 21:04:03 -0600234def generate_pbkdf2_test(param_loader, path, file_names, algorithm):
235 all_params = _load_all_params(path, file_names, param_loader)
236
237 @pytest.mark.parametrize("params", all_params)
238 def test_pbkdf2(self, backend, params):
239 pbkdf2_test(backend, algorithm, params)
240 return test_pbkdf2
241
242
243def pbkdf2_test(backend, algorithm, params):
244 # Password and salt can contain \0, which should be loaded as a null char.
245 # The NIST loader loads them as literal strings so we replace with the
246 # proper value.
Paul Kehrer1277bc72014-01-28 17:09:59 -0600247 kdf = PBKDF2HMAC(
Paul Kehrer1050ddf2014-01-27 21:04:03 -0600248 algorithm,
249 int(params["length"]),
250 params["salt"],
251 int(params["iterations"]),
252 backend
253 )
254 derived_key = kdf.derive(params["password"])
255 assert binascii.hexlify(derived_key) == params["derived_key"]
256
257
Paul Kehrer783479c2013-12-26 21:08:45 -0600258def generate_aead_exception_test(cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800259 def test_aead_exception(self, backend):
Paul Kehrer783479c2013-12-26 21:08:45 -0600260 aead_exception_test(backend, cipher_factory, mode_factory)
Paul Kehrerce9c6112013-11-22 14:10:59 -0600261 return test_aead_exception
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600262
263
Paul Kehrer783479c2013-12-26 21:08:45 -0600264def aead_exception_test(backend, cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800265 cipher = Cipher(
266 cipher_factory(binascii.unhexlify(b"0" * 32)),
267 mode_factory(binascii.unhexlify(b"0" * 24)),
268 backend
269 )
270 encryptor = cipher.encryptor()
271 encryptor.update(b"a" * 16)
272 with pytest.raises(NotYetFinalized):
273 encryptor.tag
274 with pytest.raises(AlreadyUpdated):
275 encryptor.authenticate_additional_data(b"b" * 16)
276 encryptor.finalize()
277 with pytest.raises(AlreadyFinalized):
278 encryptor.authenticate_additional_data(b"b" * 16)
279 with pytest.raises(AlreadyFinalized):
280 encryptor.update(b"b" * 16)
281 with pytest.raises(AlreadyFinalized):
282 encryptor.finalize()
283 cipher = Cipher(
284 cipher_factory(binascii.unhexlify(b"0" * 32)),
285 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
286 backend
287 )
288 decryptor = cipher.decryptor()
289 decryptor.update(b"a" * 16)
290 with pytest.raises(AttributeError):
291 decryptor.tag
Paul Kehrerb91221d2013-12-04 17:56:40 -0600292
Alex Gaynor21919e22013-12-13 08:56:32 -0800293
Paul Kehrer783479c2013-12-26 21:08:45 -0600294def generate_aead_tag_exception_test(cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800295 def test_aead_tag_exception(self, backend):
Paul Kehrer783479c2013-12-26 21:08:45 -0600296 aead_tag_exception_test(backend, cipher_factory, mode_factory)
Paul Kehrerb91221d2013-12-04 17:56:40 -0600297 return test_aead_tag_exception
Alex Gaynor21919e22013-12-13 08:56:32 -0800298
299
Paul Kehrer783479c2013-12-26 21:08:45 -0600300def aead_tag_exception_test(backend, cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800301 cipher = Cipher(
302 cipher_factory(binascii.unhexlify(b"0" * 32)),
303 mode_factory(binascii.unhexlify(b"0" * 24)),
304 backend
305 )
306 with pytest.raises(ValueError):
307 cipher.decryptor()
Alex Gaynor516b1ad2014-01-01 12:28:37 -0800308
Paul Kehrerf7b4ede2013-12-21 17:25:19 -0600309 with pytest.raises(ValueError):
Alex Gaynor516b1ad2014-01-01 12:28:37 -0800310 mode_factory(binascii.unhexlify(b"0" * 24), b"000")
311
Paul Kehrerf7b4ede2013-12-21 17:25:19 -0600312 cipher = Cipher(
313 cipher_factory(binascii.unhexlify(b"0" * 32)),
Alex Gaynor21919e22013-12-13 08:56:32 -0800314 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
315 backend
316 )
317 with pytest.raises(ValueError):
318 cipher.encryptor()
David Reid66c9cd92014-01-20 16:05:53 -0800319
320
David Reid5443e9d2014-01-22 17:18:49 -0800321def hkdf_derive_test(backend, algorithm, params):
David Reid0d492db2014-01-27 17:05:49 -0800322 hkdf = HKDF(
David Reid66c9cd92014-01-20 16:05:53 -0800323 algorithm,
David Reid0d492db2014-01-27 17:05:49 -0800324 int(params["l"]),
325 salt=binascii.unhexlify(params["salt"]) or None,
326 info=binascii.unhexlify(params["info"]) or None,
David Reid66c9cd92014-01-20 16:05:53 -0800327 backend=backend
328 )
329
David Reid0d492db2014-01-27 17:05:49 -0800330 okm = hkdf.derive(binascii.unhexlify(params["ikm"]))
331
David Reid14367302014-01-27 16:33:31 -0800332 assert okm == binascii.unhexlify(params["okm"])
David Reid66c9cd92014-01-20 16:05:53 -0800333
334
David Reid5443e9d2014-01-22 17:18:49 -0800335def hkdf_extract_test(backend, algorithm, params):
David Reid0d492db2014-01-27 17:05:49 -0800336 hkdf = HKDF(
David Reid5443e9d2014-01-22 17:18:49 -0800337 algorithm,
David Reid0d492db2014-01-27 17:05:49 -0800338 int(params["l"]),
339 salt=binascii.unhexlify(params["salt"]) or None,
340 info=binascii.unhexlify(params["info"]) or None,
David Reid5443e9d2014-01-22 17:18:49 -0800341 backend=backend
342 )
343
David Reid15fd6432014-01-30 15:28:09 -0800344 prk = hkdf._extract(binascii.unhexlify(params["ikm"]))
David Reid0d492db2014-01-27 17:05:49 -0800345
David Reid14367302014-01-27 16:33:31 -0800346 assert prk == binascii.unhexlify(params["prk"])
David Reid5443e9d2014-01-22 17:18:49 -0800347
348
349def hkdf_expand_test(backend, algorithm, params):
David Reid0d492db2014-01-27 17:05:49 -0800350 hkdf = HKDF(
David Reid5443e9d2014-01-22 17:18:49 -0800351 algorithm,
David Reid14367302014-01-27 16:33:31 -0800352 int(params["l"]),
David Reid0d492db2014-01-27 17:05:49 -0800353 salt=binascii.unhexlify(params["salt"]) or None,
354 info=binascii.unhexlify(params["info"]) or None,
David Reid5443e9d2014-01-22 17:18:49 -0800355 backend=backend
356 )
357
David Reid15fd6432014-01-30 15:28:09 -0800358 okm = hkdf._expand(binascii.unhexlify(params["prk"]))
David Reid0d492db2014-01-27 17:05:49 -0800359
David Reid14367302014-01-27 16:33:31 -0800360 assert okm == binascii.unhexlify(params["okm"])
David Reid5443e9d2014-01-22 17:18:49 -0800361
362
David Reid66c9cd92014-01-20 16:05:53 -0800363def generate_hkdf_test(param_loader, path, file_names, algorithm):
364 all_params = _load_all_params(path, file_names, param_loader)
365
David Reid5443e9d2014-01-22 17:18:49 -0800366 all_tests = [hkdf_extract_test, hkdf_expand_test, hkdf_derive_test]
367
368 @pytest.mark.parametrize(
369 ("params", "hkdf_test"),
370 itertools.product(all_params, all_tests)
371 )
372 def test_hkdf(self, backend, params, hkdf_test):
David Reid66c9cd92014-01-20 16:05:53 -0800373 hkdf_test(backend, algorithm, params)
374
375 return test_hkdf