blob: a29ef70ec567f8a2bf74d504eae3d79b0ee29653 [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
David Reid5443e9d2014-01-22 17:18:49 -080017import itertools
Paul Kehrerafc1ccd2014-03-19 11:49:32 -040018import os
David Reid5443e9d2014-01-22 17:18:49 -080019
Alex Gaynorbd458ae2013-10-16 11:59:30 -070020import pytest
21
Paul Kehrerafc1ccd2014-03-19 11:49:32 -040022from cryptography.exceptions import (
23 AlreadyFinalized, AlreadyUpdated, InvalidTag, NotYetFinalized
24)
Paul Kehrer22e80cb2013-11-20 21:27:00 -060025from cryptography.hazmat.primitives import hashes, hmac
Paul Kehrerafc1ccd2014-03-19 11:49:32 -040026from cryptography.hazmat.primitives.asymmetric import padding, rsa
Paul Kehrer21dde562013-11-06 12:22:09 +080027from cryptography.hazmat.primitives.ciphers import Cipher
David Reid0d492db2014-01-27 17:05:49 -080028from cryptography.hazmat.primitives.kdf.hkdf import HKDF
Paul Kehrerafc1ccd2014-03-19 11:49:32 -040029from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
Alex Gaynorbd458ae2013-10-16 11:59:30 -070030
Paul Kehrerf7f6a9f2013-11-11 20:43:52 -060031from ...utils import load_vectors_from_file
32
Alex Gaynorbd458ae2013-10-16 11:59:30 -070033
Alex Gaynore5c5eec2013-12-13 08:10:20 -080034def _load_all_params(path, file_names, param_loader):
35 all_params = []
36 for file_name in file_names:
37 all_params.extend(
38 load_vectors_from_file(os.path.join(path, file_name), param_loader)
39 )
40 return all_params
41
Alex Gaynor4eec0bb2013-12-13 09:12:19 -080042
Alex Gaynor016eed12013-10-16 14:16:04 -070043def generate_encrypt_test(param_loader, path, file_names, cipher_factory,
Paul Kehrer783479c2013-12-26 21:08:45 -060044 mode_factory):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080045 all_params = _load_all_params(path, file_names, param_loader)
46
47 @pytest.mark.parametrize("params", all_params)
48 def test_encryption(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -060049 encrypt_test(backend, cipher_factory, mode_factory, params)
Alex Gaynore5c5eec2013-12-13 08:10:20 -080050
Alex Gaynorbd458ae2013-10-16 11:59:30 -070051 return test_encryption
52
53
Paul Kehrer783479c2013-12-26 21:08:45 -060054def encrypt_test(backend, cipher_factory, mode_factory, params):
Paul Kehrera620b7d2013-12-20 22:59:02 -060055 plaintext = params["plaintext"]
56 ciphertext = params["ciphertext"]
Alex Gaynor21919e22013-12-13 08:56:32 -080057 cipher = Cipher(
58 cipher_factory(**params),
59 mode_factory(**params),
60 backend=backend
61 )
62 encryptor = cipher.encryptor()
63 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
64 actual_ciphertext += encryptor.finalize()
65 assert actual_ciphertext == binascii.unhexlify(ciphertext)
66 decryptor = cipher.decryptor()
67 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
68 actual_plaintext += decryptor.finalize()
69 assert actual_plaintext == binascii.unhexlify(plaintext)
70
71
Paul Kehrer22e80cb2013-11-20 21:27:00 -060072def generate_aead_test(param_loader, path, file_names, cipher_factory,
Paul Kehrer783479c2013-12-26 21:08:45 -060073 mode_factory):
Alex Gaynore5c5eec2013-12-13 08:10:20 -080074 all_params = _load_all_params(path, file_names, param_loader)
75
76 @pytest.mark.parametrize("params", all_params)
77 def test_aead(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -060078 aead_test(backend, cipher_factory, mode_factory, params)
Alex Gaynore5c5eec2013-12-13 08:10:20 -080079
Paul Kehrer22e80cb2013-11-20 21:27:00 -060080 return test_aead
81
82
Paul Kehrer783479c2013-12-26 21:08:45 -060083def aead_test(backend, cipher_factory, mode_factory, params):
Alex Gaynor21919e22013-12-13 08:56:32 -080084 if params.get("pt") is not None:
Paul Kehrera620b7d2013-12-20 22:59:02 -060085 plaintext = params["pt"]
86 ciphertext = params["ct"]
87 aad = params["aad"]
Alex Gaynor21919e22013-12-13 08:56:32 -080088 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.authenticate_additional_data(binascii.unhexlify(aad))
97 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
98 with pytest.raises(InvalidTag):
99 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.authenticate_additional_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.authenticate_additional_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,
Paul Kehrer783479c2013-12-26 21:08:45 -0600126 cipher_factory):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800127 all_params = _load_all_params(path, file_names, param_loader)
128
129 @pytest.mark.parametrize("params", all_params)
130 def test_stream_encryption(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -0600131 stream_encryption_test(backend, cipher_factory, params)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800132 return test_stream_encryption
133
134
Paul Kehrer783479c2013-12-26 21:08:45 -0600135def stream_encryption_test(backend, cipher_factory, params):
Paul Kehrera620b7d2013-12-20 22:59:02 -0600136 plaintext = params["plaintext"]
137 ciphertext = params["ciphertext"]
138 offset = params["offset"]
Alex Gaynor21919e22013-12-13 08:56:32 -0800139 cipher = Cipher(cipher_factory(**params), None, backend=backend)
140 encryptor = cipher.encryptor()
141 # throw away offset bytes
142 encryptor.update(b"\x00" * int(offset))
143 actual_ciphertext = encryptor.update(binascii.unhexlify(plaintext))
144 actual_ciphertext += encryptor.finalize()
145 assert actual_ciphertext == binascii.unhexlify(ciphertext)
146 decryptor = cipher.decryptor()
147 decryptor.update(b"\x00" * int(offset))
148 actual_plaintext = decryptor.update(binascii.unhexlify(ciphertext))
149 actual_plaintext += decryptor.finalize()
150 assert actual_plaintext == binascii.unhexlify(plaintext)
151
152
Paul Kehrer783479c2013-12-26 21:08:45 -0600153def generate_hash_test(param_loader, path, file_names, hash_cls):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800154 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer4da28c32013-11-07 07:50:17 +0800155
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800156 @pytest.mark.parametrize("params", all_params)
157 def test_hash(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -0600158 hash_test(backend, hash_cls, params)
Paul Kehrerbde6fb52013-10-18 18:08:49 -0500159 return test_hash
160
161
Paul Kehrer783479c2013-12-26 21:08:45 -0600162def hash_test(backend, algorithm, params):
Alex Gaynor36e651c2014-01-27 10:08:35 -0800163 msg, md = params
Alex Gaynor21919e22013-12-13 08:56:32 -0800164 m = hashes.Hash(algorithm, backend=backend)
165 m.update(binascii.unhexlify(msg))
166 expected_md = md.replace(" ", "").lower().encode("ascii")
167 assert m.finalize() == binascii.unhexlify(expected_md)
168
169
Paul Kehrerb078d8e2013-12-27 16:33:14 -0600170def generate_base_hash_test(algorithm, digest_size, block_size):
171 def test_base_hash(self, backend):
172 base_hash_test(backend, algorithm, digest_size, block_size)
173 return test_base_hash
174
175
Paul Kehrer783479c2013-12-26 21:08:45 -0600176def base_hash_test(backend, algorithm, digest_size, block_size):
Alex Gaynor21919e22013-12-13 08:56:32 -0800177 m = hashes.Hash(algorithm, backend=backend)
178 assert m.algorithm.digest_size == digest_size
179 assert m.algorithm.block_size == block_size
180 m_copy = m.copy()
181 assert m != m_copy
182 assert m._ctx != m_copy._ctx
183
184 m.update(b"abc")
185 copy = m.copy()
186 copy.update(b"123")
187 m.update(b"123")
188 assert copy.finalize() == m.finalize()
189
190
Paul Kehrer783479c2013-12-26 21:08:45 -0600191def generate_long_string_hash_test(hash_factory, md):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800192 def test_long_string_hash(self, backend):
Paul Kehrer783479c2013-12-26 21:08:45 -0600193 long_string_hash_test(backend, hash_factory, md)
Paul Kehrerc1794072013-10-18 21:42:57 -0500194 return test_long_string_hash
195
196
Paul Kehrer783479c2013-12-26 21:08:45 -0600197def long_string_hash_test(backend, algorithm, md):
Alex Gaynor21919e22013-12-13 08:56:32 -0800198 m = hashes.Hash(algorithm, backend=backend)
199 m.update(b"a" * 1000000)
200 assert m.finalize() == binascii.unhexlify(md.lower().encode("ascii"))
201
202
Paul Kehrerb078d8e2013-12-27 16:33:14 -0600203def generate_base_hmac_test(hash_cls):
204 def test_base_hmac(self, backend):
205 base_hmac_test(backend, hash_cls)
206 return test_base_hmac
207
208
209def base_hmac_test(backend, algorithm):
210 key = b"ab"
211 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
212 h_copy = h.copy()
213 assert h != h_copy
214 assert h._ctx != h_copy._ctx
215
216
Paul Kehrer783479c2013-12-26 21:08:45 -0600217def generate_hmac_test(param_loader, path, file_names, algorithm):
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800218 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer0317b042013-10-28 17:34:27 -0500219
Alex Gaynore5c5eec2013-12-13 08:10:20 -0800220 @pytest.mark.parametrize("params", all_params)
221 def test_hmac(self, backend, params):
Paul Kehrer783479c2013-12-26 21:08:45 -0600222 hmac_test(backend, algorithm, params)
Paul Kehrer0317b042013-10-28 17:34:27 -0500223 return test_hmac
224
225
Paul Kehrer783479c2013-12-26 21:08:45 -0600226def hmac_test(backend, algorithm, params):
Alex Gaynor36e651c2014-01-27 10:08:35 -0800227 msg, md, key = params
Alex Gaynor21919e22013-12-13 08:56:32 -0800228 h = hmac.HMAC(binascii.unhexlify(key), algorithm, backend=backend)
229 h.update(binascii.unhexlify(msg))
230 assert h.finalize() == binascii.unhexlify(md.encode("ascii"))
Paul Kehrer0317b042013-10-28 17:34:27 -0500231
Alex Gaynor21919e22013-12-13 08:56:32 -0800232
Paul Kehrer1050ddf2014-01-27 21:04:03 -0600233def generate_pbkdf2_test(param_loader, path, file_names, algorithm):
234 all_params = _load_all_params(path, file_names, param_loader)
235
236 @pytest.mark.parametrize("params", all_params)
237 def test_pbkdf2(self, backend, params):
238 pbkdf2_test(backend, algorithm, params)
239 return test_pbkdf2
240
241
242def pbkdf2_test(backend, algorithm, params):
243 # Password and salt can contain \0, which should be loaded as a null char.
244 # The NIST loader loads them as literal strings so we replace with the
245 # proper value.
Paul Kehrer1277bc72014-01-28 17:09:59 -0600246 kdf = PBKDF2HMAC(
Paul Kehrer1050ddf2014-01-27 21:04:03 -0600247 algorithm,
248 int(params["length"]),
249 params["salt"],
250 int(params["iterations"]),
251 backend
252 )
253 derived_key = kdf.derive(params["password"])
254 assert binascii.hexlify(derived_key) == params["derived_key"]
255
256
Paul Kehrer783479c2013-12-26 21:08:45 -0600257def generate_aead_exception_test(cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800258 def test_aead_exception(self, backend):
Paul Kehrer783479c2013-12-26 21:08:45 -0600259 aead_exception_test(backend, cipher_factory, mode_factory)
Paul Kehrerce9c6112013-11-22 14:10:59 -0600260 return test_aead_exception
Paul Kehrer22e80cb2013-11-20 21:27:00 -0600261
262
Paul Kehrer783479c2013-12-26 21:08:45 -0600263def aead_exception_test(backend, cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800264 cipher = Cipher(
265 cipher_factory(binascii.unhexlify(b"0" * 32)),
266 mode_factory(binascii.unhexlify(b"0" * 24)),
267 backend
268 )
269 encryptor = cipher.encryptor()
270 encryptor.update(b"a" * 16)
271 with pytest.raises(NotYetFinalized):
272 encryptor.tag
273 with pytest.raises(AlreadyUpdated):
274 encryptor.authenticate_additional_data(b"b" * 16)
275 encryptor.finalize()
276 with pytest.raises(AlreadyFinalized):
277 encryptor.authenticate_additional_data(b"b" * 16)
278 with pytest.raises(AlreadyFinalized):
279 encryptor.update(b"b" * 16)
280 with pytest.raises(AlreadyFinalized):
281 encryptor.finalize()
282 cipher = Cipher(
283 cipher_factory(binascii.unhexlify(b"0" * 32)),
284 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
285 backend
286 )
287 decryptor = cipher.decryptor()
288 decryptor.update(b"a" * 16)
289 with pytest.raises(AttributeError):
290 decryptor.tag
Paul Kehrerb91221d2013-12-04 17:56:40 -0600291
Alex Gaynor21919e22013-12-13 08:56:32 -0800292
Paul Kehrer783479c2013-12-26 21:08:45 -0600293def generate_aead_tag_exception_test(cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800294 def test_aead_tag_exception(self, backend):
Paul Kehrer783479c2013-12-26 21:08:45 -0600295 aead_tag_exception_test(backend, cipher_factory, mode_factory)
Paul Kehrerb91221d2013-12-04 17:56:40 -0600296 return test_aead_tag_exception
Alex Gaynor21919e22013-12-13 08:56:32 -0800297
298
Paul Kehrer783479c2013-12-26 21:08:45 -0600299def aead_tag_exception_test(backend, cipher_factory, mode_factory):
Alex Gaynor21919e22013-12-13 08:56:32 -0800300 cipher = Cipher(
301 cipher_factory(binascii.unhexlify(b"0" * 32)),
302 mode_factory(binascii.unhexlify(b"0" * 24)),
303 backend
304 )
305 with pytest.raises(ValueError):
306 cipher.decryptor()
Alex Gaynor516b1ad2014-01-01 12:28:37 -0800307
Paul Kehrerf7b4ede2013-12-21 17:25:19 -0600308 with pytest.raises(ValueError):
Alex Gaynor516b1ad2014-01-01 12:28:37 -0800309 mode_factory(binascii.unhexlify(b"0" * 24), b"000")
310
Paul Kehrerf7b4ede2013-12-21 17:25:19 -0600311 cipher = Cipher(
312 cipher_factory(binascii.unhexlify(b"0" * 32)),
Alex Gaynor21919e22013-12-13 08:56:32 -0800313 mode_factory(binascii.unhexlify(b"0" * 24), b"0" * 16),
314 backend
315 )
316 with pytest.raises(ValueError):
317 cipher.encryptor()
David Reid66c9cd92014-01-20 16:05:53 -0800318
319
David Reid5443e9d2014-01-22 17:18:49 -0800320def hkdf_derive_test(backend, algorithm, params):
David Reid0d492db2014-01-27 17:05:49 -0800321 hkdf = HKDF(
David Reid66c9cd92014-01-20 16:05:53 -0800322 algorithm,
David Reid0d492db2014-01-27 17:05:49 -0800323 int(params["l"]),
324 salt=binascii.unhexlify(params["salt"]) or None,
325 info=binascii.unhexlify(params["info"]) or None,
David Reid66c9cd92014-01-20 16:05:53 -0800326 backend=backend
327 )
328
David Reid0d492db2014-01-27 17:05:49 -0800329 okm = hkdf.derive(binascii.unhexlify(params["ikm"]))
330
David Reid14367302014-01-27 16:33:31 -0800331 assert okm == binascii.unhexlify(params["okm"])
David Reid66c9cd92014-01-20 16:05:53 -0800332
333
David Reid5443e9d2014-01-22 17:18:49 -0800334def hkdf_extract_test(backend, algorithm, params):
David Reid0d492db2014-01-27 17:05:49 -0800335 hkdf = HKDF(
David Reid5443e9d2014-01-22 17:18:49 -0800336 algorithm,
David Reid0d492db2014-01-27 17:05:49 -0800337 int(params["l"]),
338 salt=binascii.unhexlify(params["salt"]) or None,
339 info=binascii.unhexlify(params["info"]) or None,
David Reid5443e9d2014-01-22 17:18:49 -0800340 backend=backend
341 )
342
David Reid15fd6432014-01-30 15:28:09 -0800343 prk = hkdf._extract(binascii.unhexlify(params["ikm"]))
David Reid0d492db2014-01-27 17:05:49 -0800344
David Reid14367302014-01-27 16:33:31 -0800345 assert prk == binascii.unhexlify(params["prk"])
David Reid5443e9d2014-01-22 17:18:49 -0800346
347
348def hkdf_expand_test(backend, algorithm, params):
David Reid0d492db2014-01-27 17:05:49 -0800349 hkdf = HKDF(
David Reid5443e9d2014-01-22 17:18:49 -0800350 algorithm,
David Reid14367302014-01-27 16:33:31 -0800351 int(params["l"]),
David Reid0d492db2014-01-27 17:05:49 -0800352 salt=binascii.unhexlify(params["salt"]) or None,
353 info=binascii.unhexlify(params["info"]) or None,
David Reid5443e9d2014-01-22 17:18:49 -0800354 backend=backend
355 )
356
David Reid15fd6432014-01-30 15:28:09 -0800357 okm = hkdf._expand(binascii.unhexlify(params["prk"]))
David Reid0d492db2014-01-27 17:05:49 -0800358
David Reid14367302014-01-27 16:33:31 -0800359 assert okm == binascii.unhexlify(params["okm"])
David Reid5443e9d2014-01-22 17:18:49 -0800360
361
David Reid66c9cd92014-01-20 16:05:53 -0800362def generate_hkdf_test(param_loader, path, file_names, algorithm):
363 all_params = _load_all_params(path, file_names, param_loader)
364
David Reid5443e9d2014-01-22 17:18:49 -0800365 all_tests = [hkdf_extract_test, hkdf_expand_test, hkdf_derive_test]
366
367 @pytest.mark.parametrize(
368 ("params", "hkdf_test"),
369 itertools.product(all_params, all_tests)
370 )
371 def test_hkdf(self, backend, params, hkdf_test):
David Reid66c9cd92014-01-20 16:05:53 -0800372 hkdf_test(backend, algorithm, params)
373
374 return test_hkdf
Paul Kehrerb5936a72014-03-13 21:03:00 -0400375
376
Paul Kehrer1cfdca22014-03-16 17:57:43 -0400377def generate_rsa_pss_test(param_loader, path, file_names, hash_alg):
Paul Kehrerb5936a72014-03-13 21:03:00 -0400378 all_params = _load_all_params(path, file_names, param_loader)
Paul Kehrer1cfdca22014-03-16 17:57:43 -0400379 all_params = [i for i in all_params
380 if i["algorithm"] == hash_alg.name.upper()]
Paul Kehrerb5936a72014-03-13 21:03:00 -0400381
382 @pytest.mark.parametrize("params", all_params)
383 def test_rsa_pss(self, backend, params):
Paul Kehrer1cfdca22014-03-16 17:57:43 -0400384 rsa_pss_test(backend, params, hash_alg)
Paul Kehrerb5936a72014-03-13 21:03:00 -0400385
386 return test_rsa_pss
387
388
Paul Kehrer1cfdca22014-03-16 17:57:43 -0400389def rsa_pss_test(backend, params, hash_alg):
Paul Kehrer762014e2014-03-16 17:47:22 -0400390 public_key = rsa.RSAPublicKey(
391 public_exponent=params["public_exponent"],
392 modulus=params["modulus"]
393 )
Paul Kehrer762014e2014-03-16 17:47:22 -0400394 verifier = public_key.verifier(
395 binascii.unhexlify(params["s"]),
396 padding.PSS(
397 mgf=padding.MGF1(
Paul Kehrer1cfdca22014-03-16 17:57:43 -0400398 algorithm=hash_alg,
Paul Kehrer762014e2014-03-16 17:47:22 -0400399 salt_length=params["salt_length"]
400 )
401 ),
Paul Kehrer1cfdca22014-03-16 17:57:43 -0400402 hash_alg,
Paul Kehrer762014e2014-03-16 17:47:22 -0400403 backend
404 )
405 verifier.update(binascii.unhexlify(params["msg"]))
406 verifier.verify()