blob: 38f6704613a987585ffe2dcd43e2e7bbf9d4c015 [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 Kehrerb5936a72014-03-13 21:03:00 -040024from cryptography.hazmat.primitives.asymmetric import rsa, padding
Paul Kehrer1277bc72014-01-28 17:09:59 -060025from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
Paul Kehrer21dde562013-11-06 12:22:09 +080026from cryptography.hazmat.primitives.ciphers import Cipher
David Reid0d492db2014-01-27 17:05:49 -080027from cryptography.hazmat.primitives.kdf.hkdf import HKDF
David Reid66c9cd92014-01-20 16:05:53 -080028
Paul Kehrer22e80cb2013-11-20 21:27:00 -060029from cryptography.exceptions import (
Paul Kehrera4bfc082013-11-22 19:57:37 -060030 AlreadyFinalized, NotYetFinalized, AlreadyUpdated, InvalidTag,
Paul Kehrer22e80cb2013-11-20 21:27:00 -060031)
Alex Gaynorbd458ae2013-10-16 11:59:30 -070032
Paul Kehrerf7f6a9f2013-11-11 20:43:52 -060033from ...utils import load_vectors_from_file
34
Alex Gaynorbd458ae2013-10-16 11:59:30 -070035
Alex Gaynore5c5eec2013-12-13 08:10:20 -080036def _load_all_params(path, file_names, param_loader):
37 all_params = []
38 for file_name in file_names:
39 all_params.extend(
40 load_vectors_from_file(os.path.join(path, file_name), param_loader)
41 )
42 return all_params
43
Alex Gaynor4eec0bb2013-12-13 09:12:19 -080044
Alex Gaynor016eed12013-10-16 14:16:04 -070045def generate_encrypt_test(param_loader, path, file_names, cipher_factory,
Paul Kehrer783479c2013-12-26 21:08:45 -060046 mode_factory):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080047 all_params = _load_all_params(path, file_names, param_loader)
48
49 @pytest.mark.parametrize("params", all_params)
50 def test_encryption(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -060051 encrypt_test(backend, cipher_factory, mode_factory, params)
Alex Gaynore5c5eec2013-12-13 08:10:20 -080052
Alex Gaynorbd458ae2013-10-16 11:59:30 -070053 return test_encryption
54
55
Paul Kehrer783479c2013-12-26 21:08:45 -060056def encrypt_test(backend, cipher_factory, mode_factory, params):
Paul Kehrera620b7d2013-12-20 22:59:02 -060057 plaintext = params["plaintext"]
58 ciphertext = params["ciphertext"]
Alex Gaynor21919e22013-12-13 08:56:32 -080059 cipher = Cipher(
60 cipher_factory(**params),
61 mode_factory(**params),
62 backend=backend
63 )
64 encryptor = cipher.encryptor()
65 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
66 actual_ciphertext += encryptor.finalize()
67 assert actual_ciphertext == binascii.unhexlify(ciphertext)
68 decryptor = cipher.decryptor()
69 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
70 actual_plaintext += decryptor.finalize()
71 assert actual_plaintext == binascii.unhexlify(plaintext)
72
73
Paul Kehrer22e80cb2013-11-20 21:27:00 -060074def generate_aead_test(param_loader, path, file_names, cipher_factory,
Paul Kehrer783479c2013-12-26 21:08:45 -060075 mode_factory):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080076 all_params = _load_all_params(path, file_names, param_loader)
77
78 @pytest.mark.parametrize("params", all_params)
79 def test_aead(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -060080 aead_test(backend, cipher_factory, mode_factory, params)
Alex Gaynore5c5eec2013-12-13 08:10:20 -080081
Paul Kehrer22e80cb2013-11-20 21:27:00 -060082 return test_aead
83
84
Paul Kehrer783479c2013-12-26 21:08:45 -060085def aead_test(backend, cipher_factory, mode_factory, params):
Alex Gaynor21919e22013-12-13 08:56:32 -080086 if params.get("pt") is not None:
Paul Kehrera620b7d2013-12-20 22:59:02 -060087 plaintext = params["pt"]
88 ciphertext = params["ct"]
89 aad = params["aad"]
Alex Gaynor21919e22013-12-13 08:56:32 -080090 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,
Paul Kehrer783479c2013-12-26 21:08:45 -0600128 cipher_factory):
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):
Paul Kehrer783479c2013-12-26 21:08:45 -0600133 stream_encryption_test(backend, cipher_factory, params)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800134 return test_stream_encryption
135
136
Paul Kehrer783479c2013-12-26 21:08:45 -0600137def stream_encryption_test(backend, cipher_factory, params):
Paul Kehrera620b7d2013-12-20 22:59:02 -0600138 plaintext = params["plaintext"]
139 ciphertext = params["ciphertext"]
140 offset = params["offset"]
Alex Gaynor21919e22013-12-13 08:56:32 -0800141 cipher = Cipher(cipher_factory(**params), None, backend=backend)
142 encryptor = cipher.encryptor()
143 # throw away offset bytes
144 encryptor.update(b"\x00" * int(offset))
145 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
146 actual_ciphertext += encryptor.finalize()
147 assert actual_ciphertext == binascii.unhexlify(ciphertext)
148 decryptor = cipher.decryptor()
149 decryptor.update(b"\x00" * int(offset))
150 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
151 actual_plaintext += decryptor.finalize()
152 assert actual_plaintext == binascii.unhexlify(plaintext)
153
154
Paul Kehrer783479c2013-12-26 21:08:45 -0600155def generate_hash_test(param_loader, path, file_names, hash_cls):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800156 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800157
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800158 @pytest.mark.parametrize("params", all_params)
159 def test_hash(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -0600160 hash_test(backend, hash_cls, params)
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500161 return test_hash
162
163
Paul Kehrer783479c2013-12-26 21:08:45 -0600164def hash_test(backend, algorithm, params):
Alex Gaynor36e651c2014-01-27 10:08:35 -0800165 msg, md = params
Alex Gaynor21919e22013-12-13 08:56:32 -0800166 m = hashes.Hash(algorithm, backend=backend)
167 m.update(binascii.unhexlify(msg))
168 expected_md = md.replace(" ", "").lower().encode("ascii")
169 assert m.finalize() == binascii.unhexlify(expected_md)
170
171
Paul Kehrerb078d8e2013-12-27 16:33:14 -0600172def generate_base_hash_test(algorithm, digest_size, block_size):
173 def test_base_hash(self, backend):
174 base_hash_test(backend, algorithm, digest_size, block_size)
175 return test_base_hash
176
177
Paul Kehrer783479c2013-12-26 21:08:45 -0600178def base_hash_test(backend, algorithm, digest_size, block_size):
Alex Gaynor21919e22013-12-13 08:56:32 -0800179 m = hashes.Hash(algorithm, backend=backend)
180 assert m.algorithm.digest_size == digest_size
181 assert m.algorithm.block_size == block_size
182 m_copy = m.copy()
183 assert m != m_copy
184 assert m._ctx != m_copy._ctx
185
186 m.update(b"abc")
187 copy = m.copy()
188 copy.update(b"123")
189 m.update(b"123")
190 assert copy.finalize() == m.finalize()
191
192
Paul Kehrer783479c2013-12-26 21:08:45 -0600193def generate_long_string_hash_test(hash_factory, md):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800194 def test_long_string_hash(self, backend):
Paul Kehrer783479c2013-12-26 21:08:45 -0600195 long_string_hash_test(backend, hash_factory, md)
Paul Kehrerc1794072013-10-18 21:42:57 -0500196 return test_long_string_hash
197
198
Paul Kehrer783479c2013-12-26 21:08:45 -0600199def long_string_hash_test(backend, algorithm, md):
Alex Gaynor21919e22013-12-13 08:56:32 -0800200 m = hashes.Hash(algorithm, backend=backend)
201 m.update(b"a" * 1000000)
202 assert m.finalize() == binascii.unhexlify(md.lower().encode("ascii"))
203
204
Paul Kehrerb078d8e2013-12-27 16:33:14 -0600205def generate_base_hmac_test(hash_cls):
206 def test_base_hmac(self, backend):
207 base_hmac_test(backend, hash_cls)
208 return test_base_hmac
209
210
211def base_hmac_test(backend, algorithm):
212 key = b"ab"
213 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
214 h_copy = h.copy()
215 assert h != h_copy
216 assert h._ctx != h_copy._ctx
217
218
Paul Kehrer783479c2013-12-26 21:08:45 -0600219def generate_hmac_test(param_loader, path, file_names, algorithm):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800220 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer0317b042013-10-28 17:34:27 -0500221
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800222 @pytest.mark.parametrize("params", all_params)
223 def test_hmac(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -0600224 hmac_test(backend, algorithm, params)
Paul Kehrer0317b042013-10-28 17:34:27 -0500225 return test_hmac
226
227
Paul Kehrer783479c2013-12-26 21:08:45 -0600228def hmac_test(backend, algorithm, params):
Alex Gaynor36e651c2014-01-27 10:08:35 -0800229 msg, md, key = params
Alex Gaynor21919e22013-12-13 08:56:32 -0800230 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
231 h.update(binascii.unhexlify(msg))
232 assert h.finalize() == binascii.unhexlify(md.encode("ascii"))
Paul Kehrer0317b042013-10-28 17:34:27 -0500233
Alex Gaynor21919e22013-12-13 08:56:32 -0800234
Paul Kehrer1050ddf2014-01-27 21:04:03 -0600235def generate_pbkdf2_test(param_loader, path, file_names, algorithm):
236 all_params = _load_all_params(path, file_names, param_loader)
237
238 @pytest.mark.parametrize("params", all_params)
239 def test_pbkdf2(self, backend, params):
240 pbkdf2_test(backend, algorithm, params)
241 return test_pbkdf2
242
243
244def pbkdf2_test(backend, algorithm, params):
245 # Password and salt can contain \0, which should be loaded as a null char.
246 # The NIST loader loads them as literal strings so we replace with the
247 # proper value.
Paul Kehrer1277bc72014-01-28 17:09:59 -0600248 kdf = PBKDF2HMAC(
Paul Kehrer1050ddf2014-01-27 21:04:03 -0600249 algorithm,
250 int(params["length"]),
251 params["salt"],
252 int(params["iterations"]),
253 backend
254 )
255 derived_key = kdf.derive(params["password"])
256 assert binascii.hexlify(derived_key) == params["derived_key"]
257
258
Paul Kehrer783479c2013-12-26 21:08:45 -0600259def generate_aead_exception_test(cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800260 def test_aead_exception(self, backend):
Paul Kehrer783479c2013-12-26 21:08:45 -0600261 aead_exception_test(backend, cipher_factory, mode_factory)
Paul Kehrerce9c6112013-11-22 14:10:59 -0600262 return test_aead_exception
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600263
264
Paul Kehrer783479c2013-12-26 21:08:45 -0600265def aead_exception_test(backend, cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800266 cipher = Cipher(
267 cipher_factory(binascii.unhexlify(b"0" * 32)),
268 mode_factory(binascii.unhexlify(b"0" * 24)),
269 backend
270 )
271 encryptor = cipher.encryptor()
272 encryptor.update(b"a" * 16)
273 with pytest.raises(NotYetFinalized):
274 encryptor.tag
275 with pytest.raises(AlreadyUpdated):
276 encryptor.authenticate_additional_data(b"b" * 16)
277 encryptor.finalize()
278 with pytest.raises(AlreadyFinalized):
279 encryptor.authenticate_additional_data(b"b" * 16)
280 with pytest.raises(AlreadyFinalized):
281 encryptor.update(b"b" * 16)
282 with pytest.raises(AlreadyFinalized):
283 encryptor.finalize()
284 cipher = Cipher(
285 cipher_factory(binascii.unhexlify(b"0" * 32)),
286 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
287 backend
288 )
289 decryptor = cipher.decryptor()
290 decryptor.update(b"a" * 16)
291 with pytest.raises(AttributeError):
292 decryptor.tag
Paul Kehrerb91221d2013-12-04 17:56:40 -0600293
Alex Gaynor21919e22013-12-13 08:56:32 -0800294
Paul Kehrer783479c2013-12-26 21:08:45 -0600295def generate_aead_tag_exception_test(cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800296 def test_aead_tag_exception(self, backend):
Paul Kehrer783479c2013-12-26 21:08:45 -0600297 aead_tag_exception_test(backend, cipher_factory, mode_factory)
Paul Kehrerb91221d2013-12-04 17:56:40 -0600298 return test_aead_tag_exception
Alex Gaynor21919e22013-12-13 08:56:32 -0800299
300
Paul Kehrer783479c2013-12-26 21:08:45 -0600301def aead_tag_exception_test(backend, cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800302 cipher = Cipher(
303 cipher_factory(binascii.unhexlify(b"0" * 32)),
304 mode_factory(binascii.unhexlify(b"0" * 24)),
305 backend
306 )
307 with pytest.raises(ValueError):
308 cipher.decryptor()
Alex Gaynor516b1ad2014-01-01 12:28:37 -0800309
Paul Kehrerf7b4ede2013-12-21 17:25:19 -0600310 with pytest.raises(ValueError):
Alex Gaynor516b1ad2014-01-01 12:28:37 -0800311 mode_factory(binascii.unhexlify(b"0" * 24), b"000")
312
Paul Kehrerf7b4ede2013-12-21 17:25:19 -0600313 cipher = Cipher(
314 cipher_factory(binascii.unhexlify(b"0" * 32)),
Alex Gaynor21919e22013-12-13 08:56:32 -0800315 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
316 backend
317 )
318 with pytest.raises(ValueError):
319 cipher.encryptor()
David Reid66c9cd92014-01-20 16:05:53 -0800320
321
David Reid5443e9d2014-01-22 17:18:49 -0800322def hkdf_derive_test(backend, algorithm, params):
David Reid0d492db2014-01-27 17:05:49 -0800323 hkdf = HKDF(
David Reid66c9cd92014-01-20 16:05:53 -0800324 algorithm,
David Reid0d492db2014-01-27 17:05:49 -0800325 int(params["l"]),
326 salt=binascii.unhexlify(params["salt"]) or None,
327 info=binascii.unhexlify(params["info"]) or None,
David Reid66c9cd92014-01-20 16:05:53 -0800328 backend=backend
329 )
330
David Reid0d492db2014-01-27 17:05:49 -0800331 okm = hkdf.derive(binascii.unhexlify(params["ikm"]))
332
David Reid14367302014-01-27 16:33:31 -0800333 assert okm == binascii.unhexlify(params["okm"])
David Reid66c9cd92014-01-20 16:05:53 -0800334
335
David Reid5443e9d2014-01-22 17:18:49 -0800336def hkdf_extract_test(backend, algorithm, params):
David Reid0d492db2014-01-27 17:05:49 -0800337 hkdf = HKDF(
David Reid5443e9d2014-01-22 17:18:49 -0800338 algorithm,
David Reid0d492db2014-01-27 17:05:49 -0800339 int(params["l"]),
340 salt=binascii.unhexlify(params["salt"]) or None,
341 info=binascii.unhexlify(params["info"]) or None,
David Reid5443e9d2014-01-22 17:18:49 -0800342 backend=backend
343 )
344
David Reid15fd6432014-01-30 15:28:09 -0800345 prk = hkdf._extract(binascii.unhexlify(params["ikm"]))
David Reid0d492db2014-01-27 17:05:49 -0800346
David Reid14367302014-01-27 16:33:31 -0800347 assert prk == binascii.unhexlify(params["prk"])
David Reid5443e9d2014-01-22 17:18:49 -0800348
349
350def hkdf_expand_test(backend, algorithm, params):
David Reid0d492db2014-01-27 17:05:49 -0800351 hkdf = HKDF(
David Reid5443e9d2014-01-22 17:18:49 -0800352 algorithm,
David Reid14367302014-01-27 16:33:31 -0800353 int(params["l"]),
David Reid0d492db2014-01-27 17:05:49 -0800354 salt=binascii.unhexlify(params["salt"]) or None,
355 info=binascii.unhexlify(params["info"]) or None,
David Reid5443e9d2014-01-22 17:18:49 -0800356 backend=backend
357 )
358
David Reid15fd6432014-01-30 15:28:09 -0800359 okm = hkdf._expand(binascii.unhexlify(params["prk"]))
David Reid0d492db2014-01-27 17:05:49 -0800360
David Reid14367302014-01-27 16:33:31 -0800361 assert okm == binascii.unhexlify(params["okm"])
David Reid5443e9d2014-01-22 17:18:49 -0800362
363
David Reid66c9cd92014-01-20 16:05:53 -0800364def generate_hkdf_test(param_loader, path, file_names, algorithm):
365 all_params = _load_all_params(path, file_names, param_loader)
366
David Reid5443e9d2014-01-22 17:18:49 -0800367 all_tests = [hkdf_extract_test, hkdf_expand_test, hkdf_derive_test]
368
369 @pytest.mark.parametrize(
370 ("params", "hkdf_test"),
371 itertools.product(all_params, all_tests)
372 )
373 def test_hkdf(self, backend, params, hkdf_test):
David Reid66c9cd92014-01-20 16:05:53 -0800374 hkdf_test(backend, algorithm, params)
375
376 return test_hkdf
Paul Kehrerb5936a72014-03-13 21:03:00 -0400377
378
379def generate_rsa_pss_test(param_loader, path, file_names, hash_name):
380 all_params = _load_all_params(path, file_names, param_loader)
381 all_params = [i for i in all_params if i["algorithm"] == hash_name]
382
383 @pytest.mark.parametrize("params", all_params)
384 def test_rsa_pss(self, backend, params):
385 rsa_pss_test(backend, params)
386
387 return test_rsa_pss
388
389
390def rsa_pss_test(backend, params):
391 public_key = rsa.RSAPublicKey(
392 public_exponent=params["public_exponent"],
393 modulus=params["modulus"]
394 )
395 hash_cls = getattr(hashes, params["algorithm"].decode("utf8"))
396 verifier = public_key.verifier(
397 binascii.unhexlify(params["s"]),
398 padding.PSS(
399 mgf=padding.MGF1(
400 algorithm=hash_cls(),
401 salt_length=params["salt_length"]
402 )
403 ),
404 hash_cls(),
405 backend
406 )
407 verifier.update(binascii.unhexlify(params["msg"]))
408 verifier.verify()