1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,53 @@ |
0 |
+From d8f8f4d637ce43f8699ba94c9b7648beda0ca174 Mon Sep 17 00:00:00 2001 |
|
1 |
+From: Ondrej Holy <oholy@redhat.com> |
|
2 |
+Date: Thu, 23 May 2019 10:41:53 +0200 |
|
3 |
+Subject: [PATCH] gfile: Limit access to files when copying |
|
4 |
+ |
|
5 |
+file_copy_fallback creates new files with default permissions and |
|
6 |
+set the correct permissions after the operation is finished. This |
|
7 |
+might cause that the files can be accessible by more users during |
|
8 |
+the operation than expected. Use G_FILE_CREATE_PRIVATE for the new |
|
9 |
+files to limit access to those files. |
|
10 |
+--- |
|
11 |
+ gio/gfile.c | 11 ++++++----- |
|
12 |
+ 1 file changed, 6 insertions(+), 5 deletions(-) |
|
13 |
+ |
|
14 |
+diff --git a/gio/gfile.c b/gio/gfile.c |
|
15 |
+index 24b136d80..74b58047c 100644 |
|
16 |
+--- a/gio/gfile.c |
|
17 |
+@@ -3284,12 +3284,12 @@ file_copy_fallback (GFile *source, |
|
18 |
+ out = (GOutputStream*)_g_local_file_output_stream_replace (_g_local_file_get_filename (G_LOCAL_FILE (destination)), |
|
19 |
+ FALSE, NULL, |
|
20 |
+ flags & G_FILE_COPY_BACKUP, |
|
21 |
+- G_FILE_CREATE_REPLACE_DESTINATION, |
|
22 |
+- info, |
|
23 |
++ G_FILE_CREATE_REPLACE_DESTINATION | |
|
24 |
++ G_FILE_CREATE_PRIVATE, info, |
|
25 |
+ cancellable, error); |
|
26 |
+ else |
|
27 |
+ out = (GOutputStream*)_g_local_file_output_stream_create (_g_local_file_get_filename (G_LOCAL_FILE (destination)), |
|
28 |
+- FALSE, 0, info, |
|
29 |
++ FALSE, G_FILE_CREATE_PRIVATE, info, |
|
30 |
+ cancellable, error); |
|
31 |
+ } |
|
32 |
+ else if (flags & G_FILE_COPY_OVERWRITE) |
|
33 |
+@@ -3297,12 +3297,13 @@ file_copy_fallback (GFile *source, |
|
34 |
+ out = (GOutputStream *)g_file_replace (destination, |
|
35 |
+ NULL, |
|
36 |
+ flags & G_FILE_COPY_BACKUP, |
|
37 |
+- G_FILE_CREATE_REPLACE_DESTINATION, |
|
38 |
++ G_FILE_CREATE_REPLACE_DESTINATION | |
|
39 |
++ G_FILE_CREATE_PRIVATE, |
|
40 |
+ cancellable, error); |
|
41 |
+ } |
|
42 |
+ else |
|
43 |
+ { |
|
44 |
+- out = (GOutputStream *)g_file_create (destination, 0, cancellable, error); |
|
45 |
++ out = (GOutputStream *)g_file_create (destination, G_FILE_CREATE_PRIVATE, cancellable, error); |
|
46 |
+ } |
|
47 |
+ |
|
48 |
+ if (!out) |
|
49 |
+-- |
|
50 |
+2.21.0 |
|
51 |
+ |
... | ... |
@@ -1,7 +1,7 @@ |
1 | 1 |
Summary: Low-level libraries useful for providing data structure handling for C. |
2 | 2 |
Name: glib |
3 | 3 |
Version: 2.58.0 |
4 |
-Release: 2%{?dist} |
|
4 |
+Release: 3%{?dist} |
|
5 | 5 |
License: LGPLv2+ |
6 | 6 |
URL: https://developer.gnome.org/glib/ |
7 | 7 |
Group: Applications/System |
... | ... |
@@ -9,6 +9,7 @@ Vendor: VMware, Inc. |
9 | 9 |
Distribution: Photon |
10 | 10 |
Source0: http://ftp.gnome.org/pub/gnome/sources/glib/2.58/%{name}-%{version}.tar.xz |
11 | 11 |
%define sha1 glib=c00e433c56e0ba3541abc5222aeca4136de10fb8 |
12 |
+Patch0: glib-CVE-2019-12450.patch |
|
12 | 13 |
BuildRequires: pcre-devel |
13 | 14 |
BuildRequires: libffi-devel |
14 | 15 |
BuildRequires: pkg-config |
... | ... |
@@ -51,6 +52,8 @@ Gsettings schemas compiling tool |
51 | 51 |
|
52 | 52 |
%prep |
53 | 53 |
%setup -q |
54 |
+%patch0 -p1 |
|
55 |
+ |
|
54 | 56 |
%build |
55 | 57 |
./autogen.sh |
56 | 58 |
%configure --with-pcre=system |
... | ... |
@@ -90,6 +93,8 @@ make DESTDIR=%{buildroot} install |
90 | 90 |
%{_datadir}/glib-2.0/schemas/* |
91 | 91 |
|
92 | 92 |
%changelog |
93 |
+* Mon Jun 03 2019 Ankit Jain <ankitja@vmware.com> 2.58.0-3 |
|
94 |
+- Fix for CVE-2019-12450 |
|
93 | 95 |
* Mon Dec 10 2018 Alexey Makhalov <amakhalov@vmware.com> 2.58.0-2 |
94 | 96 |
- glib-devel requires python-xml. |
95 | 97 |
* Tue Sep 11 2018 Anish Swaminathan <anishs@vmware.com> 2.58.0-1 |
96 | 98 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,1271 @@ |
0 |
+From 57104488faa9fc386ea1aee249bafb6e2a529a57 Mon Sep 17 00:00:00 2001 |
|
1 |
+From: Legrandin <helderijs@gmail.com> |
|
2 |
+Date: Wed, 23 Jan 2013 22:37:53 +0100 |
|
3 |
+Subject: [PATCH] Add support for CCM mode (AES only). |
|
4 |
+ |
|
5 |
+[dlitz@dlitz.net: Included changes from the following commits from the author's pull request:] |
|
6 |
+- [5306cf3] Added support for CCM mode (AES cipher only) |
|
7 |
+- [9abe301] Added CCM tests |
|
8 |
+- [f0c1395] Add MacMismatchError and ApiUsageError |
|
9 |
+- [fb62fae] ApiUsageError becomes TypeError |
|
10 |
+- [9c13f9c] Rename 'IV' parameter to 'nonce' for AEAD modes. |
|
11 |
+- [4ec64d8] Removed last references to ApiUsageError |
|
12 |
+- [80bfd35] Corrected AES-CCM examples |
|
13 |
+[dlitz@dlitz.net: Removed unrelated documentation change] |
|
14 |
+[dlitz@dlitz.net: Renamed 'targs' back to 'args'] |
|
15 |
+[dlitz@dlitz.net: Whitespace fixed with "git rebase --whitespace=fix"] |
|
16 |
+ |
|
17 |
+ |
|
18 |
+--- a/lib/Crypto/Cipher/AES.py_org 2019-05-17 22:49:36.800225203 +0530 |
|
19 |
+@@ -31,15 +31,46 @@ encryption. |
|
20 |
+ As an example, encryption can be done as follows: |
|
21 |
+ |
|
22 |
+ >>> from Crypto.Cipher import AES |
|
23 |
+- >>> from Crypto import Random |
|
24 |
++ >>> from Crypto.Random import get_random_bytes |
|
25 |
+ >>> |
|
26 |
+ >>> key = b'Sixteen byte key' |
|
27 |
+- >>> iv = Random.new().read(AES.block_size) |
|
28 |
++ >>> iv = get_random_bytes(16) |
|
29 |
+ >>> cipher = AES.new(key, AES.MODE_CFB, iv) |
|
30 |
+ >>> msg = iv + cipher.encrypt(b'Attack at dawn') |
|
31 |
+ |
|
32 |
++A more complicated example is based on CCM, (see `MODE_CCM`) an `AEAD`_ mode |
|
33 |
++that provides both confidentiality and authentication for a message. |
|
34 |
++It also allows message for the header to remain in the clear, whilst still |
|
35 |
++being authenticated. The encryption is done as follows: |
|
36 |
++ |
|
37 |
++ >>> from Crypto.Cipher import AES |
|
38 |
++ >>> from Crypto.Random import get_random_bytes |
|
39 |
++ >>> |
|
40 |
++ >>> |
|
41 |
++ >>> hdr = b'To your eyes only' |
|
42 |
++ >>> plaintext = b'Attack at dawn' |
|
43 |
++ >>> key = b'Sixteen byte key' |
|
44 |
++ >>> nonce = get_random_bytes(11) |
|
45 |
++ >>> cipher = AES.new(key, AES.MODE_CCM, nonce) |
|
46 |
++ >>> cipher.update(hdr) |
|
47 |
++ >>> msg = nonce, hdr, cipher.encrypt(plaintext), cipher.digest() |
|
48 |
++ |
|
49 |
++We assume that the tuple ``msg`` is transmitted to the receiver: |
|
50 |
++ |
|
51 |
++ >>> nonce, hdr, ciphertext, mac = msg |
|
52 |
++ >>> key = b'Sixteen byte key' |
|
53 |
++ >>> cipher = AES.new(key, AES.MODE_CCM, nonce) |
|
54 |
++ >>> cipher.update(hdr) |
|
55 |
++ >>> plaintext = cipher.decrypt(ciphertext) |
|
56 |
++ >>> try: |
|
57 |
++ >>> cipher.verify(mac) |
|
58 |
++ >>> print "The message is authentic: hdr=%s, pt=%s" % (hdr, plaintext) |
|
59 |
++ >>> except ValueError: |
|
60 |
++ >>> print "Key incorrect or message corrupted" |
|
61 |
++ |
|
62 |
+ .. __: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard |
|
63 |
+ .. _NIST: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf |
|
64 |
++.. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html |
|
65 |
+ |
|
66 |
+ :undocumented: __revision__, __package__ |
|
67 |
+ """ |
|
68 |
+@@ -70,6 +101,7 @@ def new(key, *args, **kwargs): |
|
69 |
+ The chaining mode to use for encryption or decryption. |
|
70 |
+ Default is `MODE_ECB`. |
|
71 |
+ IV : byte string |
|
72 |
++ (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). |
|
73 |
+ The initialization vector to use for encryption or decryption. |
|
74 |
+ |
|
75 |
+ It is ignored for `MODE_ECB` and `MODE_CTR`. |
|
76 |
+@@ -78,9 +110,17 @@ def new(key, *args, **kwargs): |
|
77 |
+ and `block_size` +2 bytes for decryption (in the latter case, it is |
|
78 |
+ actually the *encrypted* IV which was prefixed to the ciphertext). |
|
79 |
+ It is mandatory. |
|
80 |
+- |
|
81 |
+- For all other modes, it must be `block_size` bytes longs. It is optional and |
|
82 |
+- when not present it will be given a default value of all zeroes. |
|
83 |
++ |
|
84 |
++ For all other modes, it must be 16 bytes long. |
|
85 |
++ nonce : byte string |
|
86 |
++ (*Only* `MODE_CCM`). |
|
87 |
++ |
|
88 |
++ A mandatory value that must never be reused for any other encryption. |
|
89 |
++ |
|
90 |
++ For `MODE_CCM`, its length must be in the range ``[7..13]``. |
|
91 |
++ 11 or 12 bytes are reasonable values in general. Bear in |
|
92 |
++ mind that with CCM there is a trade-off between nonce length and |
|
93 |
++ maximum message size. |
|
94 |
+ counter : callable |
|
95 |
+ (*Only* `MODE_CTR`). A stateful function that returns the next |
|
96 |
+ *counter block*, which is a byte string of `block_size` bytes. |
|
97 |
+@@ -89,7 +129,15 @@ def new(key, *args, **kwargs): |
|
98 |
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext |
|
99 |
+ are segmented in. |
|
100 |
+ It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. |
|
101 |
+- |
|
102 |
++ mac_len : integer |
|
103 |
++ (*Only* `MODE_CCM`). Length of the MAC, in bytes. It must be even and in |
|
104 |
++ the range ``[4..16]``. The default is 16. |
|
105 |
++ msg_len : integer |
|
106 |
++ (*Only* `MODE_CCM`). Length of the message to (de)cipher. |
|
107 |
++ If not specified, ``encrypt`` or ``decrypt`` may only be called once. |
|
108 |
++ assoc_len : integer |
|
109 |
++ (*Only* `MODE_CCM`). Length of the associated data. |
|
110 |
++ If not specified, all data is internally buffered. |
|
111 |
+ :Return: an `AESCipher` object |
|
112 |
+ """ |
|
113 |
+ return AESCipher(key, *args, **kwargs) |
|
114 |
+@@ -108,6 +156,8 @@ MODE_OFB = 5 |
|
115 |
+ MODE_CTR = 6 |
|
116 |
+ #: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. |
|
117 |
+ MODE_OPENPGP = 7 |
|
118 |
++#: Counter with CBC-MAC (CCM) Mode. See `blockalgo.MODE_CCM`. |
|
119 |
++MODE_CCM = 8 |
|
120 |
+ #: Size of a data block (in bytes) |
|
121 |
+ block_size = 16 |
|
122 |
+ #: Size of a key (in bytes) |
|
123 |
+--- a/lib/Crypto/SelfTest/Cipher/common.py_org 2019-05-17 23:22:17.148264361 +0530 |
|
124 |
+@@ -28,8 +28,9 @@ __revision__ = "$Id$" |
|
125 |
+ |
|
126 |
+ import sys |
|
127 |
+ import unittest |
|
128 |
+-from binascii import a2b_hex, b2a_hex |
|
129 |
++from binascii import a2b_hex, b2a_hex, hexlify |
|
130 |
+ from Crypto.Util.py3compat import * |
|
131 |
++from Crypto.Util.strxor import strxor_c |
|
132 |
+ |
|
133 |
+ # For compatibility with Python 2.1 and Python 2.2 |
|
134 |
+ if sys.hexversion < 0x02030000: |
|
135 |
+@@ -66,6 +67,12 @@ class CipherSelfTest(unittest.TestCase): |
|
136 |
+ self.plaintext = b(_extract(params, 'plaintext')) |
|
137 |
+ self.ciphertext = b(_extract(params, 'ciphertext')) |
|
138 |
+ self.module_name = _extract(params, 'module_name', None) |
|
139 |
++ self.assoc_data = _extract(params, 'assoc_data', None) |
|
140 |
++ if self.assoc_data: |
|
141 |
++ self.assoc_data = b(self.assoc_data) |
|
142 |
++ self.mac = _extract(params, 'mac', None) |
|
143 |
++ if self.assoc_data: |
|
144 |
++ self.mac = b(self.mac) |
|
145 |
+ |
|
146 |
+ mode = _extract(params, 'mode', None) |
|
147 |
+ self.mode_name = str(mode) |
|
148 |
+@@ -73,8 +80,10 @@ class CipherSelfTest(unittest.TestCase): |
|
149 |
+ # Block cipher |
|
150 |
+ self.mode = getattr(self.module, "MODE_" + mode) |
|
151 |
+ self.iv = _extract(params, 'iv', None) |
|
152 |
+- if self.iv is not None: self.iv = b(self.iv) |
|
153 |
+- |
|
154 |
++ if self.iv is None: |
|
155 |
++ self.iv = _extract(params, 'nonce', None) |
|
156 |
++ if self.iv is not None: |
|
157 |
++ self.iv = b(self.iv) |
|
158 |
+ # Only relevant for OPENPGP mode |
|
159 |
+ self.encrypted_iv = _extract(params, 'encrypted_iv', None) |
|
160 |
+ if self.encrypted_iv is not None: |
|
161 |
+@@ -121,25 +130,49 @@ class CipherSelfTest(unittest.TestCase): |
|
162 |
+ plaintext = a2b_hex(self.plaintext) |
|
163 |
+ ciphertext = a2b_hex(self.ciphertext) |
|
164 |
+ |
|
165 |
+- ct1 = b2a_hex(self._new().encrypt(plaintext)) |
|
166 |
+- pt1 = b2a_hex(self._new(1).decrypt(ciphertext)) |
|
167 |
+- ct2 = b2a_hex(self._new().encrypt(plaintext)) |
|
168 |
+- pt2 = b2a_hex(self._new(1).decrypt(ciphertext)) |
|
169 |
++ assoc_data = None |
|
170 |
++ if self.assoc_data: |
|
171 |
++ assoc_data = a2b_hex(self.assoc_data) |
|
172 |
++ |
|
173 |
++ ct = None |
|
174 |
++ pt = None |
|
175 |
++ |
|
176 |
++ # |
|
177 |
++ # Repeat the same encryption or decryption twice and verify |
|
178 |
++ # that the result is always the same |
|
179 |
++ # |
|
180 |
++ for i in xrange(2): |
|
181 |
++ cipher = self._new() |
|
182 |
++ decipher = self._new(1) |
|
183 |
++ |
|
184 |
++ # Only AEAD modes |
|
185 |
++ if self.assoc_data: |
|
186 |
++ cipher.update(assoc_data) |
|
187 |
++ decipher.update(assoc_data) |
|
188 |
++ |
|
189 |
++ ctX = b2a_hex(cipher.encrypt(plaintext)) |
|
190 |
++ ptX = b2a_hex(decipher.decrypt(ciphertext)) |
|
191 |
++ |
|
192 |
++ if ct: |
|
193 |
++ self.assertEqual(ct, ctX) |
|
194 |
++ self.assertEqual(pt, ptX) |
|
195 |
++ ct, pt = ctX, ptX |
|
196 |
+ |
|
197 |
+ if hasattr(self.module, "MODE_OPENPGP") and self.mode == self.module.MODE_OPENPGP: |
|
198 |
+ # In PGP mode, data returned by the first encrypt() |
|
199 |
+ # is prefixed with the encrypted IV. |
|
200 |
+ # Here we check it and then remove it from the ciphertexts. |
|
201 |
+ eilen = len(self.encrypted_iv) |
|
202 |
+- self.assertEqual(self.encrypted_iv, ct1[:eilen]) |
|
203 |
+- self.assertEqual(self.encrypted_iv, ct2[:eilen]) |
|
204 |
+- ct1 = ct1[eilen:] |
|
205 |
+- ct2 = ct2[eilen:] |
|
206 |
+- |
|
207 |
+- self.assertEqual(self.ciphertext, ct1) # encrypt |
|
208 |
+- self.assertEqual(self.ciphertext, ct2) # encrypt (second time) |
|
209 |
+- self.assertEqual(self.plaintext, pt1) # decrypt |
|
210 |
+- self.assertEqual(self.plaintext, pt2) # decrypt (second time) |
|
211 |
++ self.assertEqual(self.encrypted_iv, ct[:eilen]) |
|
212 |
++ ct = ct[eilen:] |
|
213 |
++ |
|
214 |
++ self.assertEqual(self.ciphertext, ct) # encrypt |
|
215 |
++ self.assertEqual(self.plaintext, pt) # decrypt |
|
216 |
++ |
|
217 |
++ if self.mac: |
|
218 |
++ mac = b2a_hex(cipher.digest()) |
|
219 |
++ self.assertEqual(self.mac, mac) |
|
220 |
++ decipher.verify(a2b_hex(self.mac)) |
|
221 |
+ |
|
222 |
+ class CipherStreamingSelfTest(CipherSelfTest): |
|
223 |
+ |
|
224 |
+@@ -225,6 +258,258 @@ class CFBSegmentSizeTest(unittest.TestCa |
|
225 |
+ self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), self.module.MODE_CFB, segment_size=i) |
|
226 |
+ self.module.new(a2b_hex(self.key), self.module.MODE_CFB, "\0"*self.module.block_size, segment_size=8) # should succeed |
|
227 |
+ |
|
228 |
++class CCMMACLengthTest(unittest.TestCase): |
|
229 |
++ """CCM specific tests about MAC""" |
|
230 |
++ |
|
231 |
++ def __init__(self, module): |
|
232 |
++ unittest.TestCase.__init__(self) |
|
233 |
++ self.module = module |
|
234 |
++ self.key = b('\xFF')*16 |
|
235 |
++ self.iv = b('\x00')*10 |
|
236 |
++ |
|
237 |
++ def shortDescription(self): |
|
238 |
++ return self.description |
|
239 |
++ |
|
240 |
++ def runTest(self): |
|
241 |
++ """Verify that MAC can only be 4,6,8,..,16 bytes long.""" |
|
242 |
++ for i in range(3,16,2): |
|
243 |
++ self.description = "CCM MAC length check (%d bytes)" % i |
|
244 |
++ self.assertRaises(ValueError, self.module.new, self.key, |
|
245 |
++ self.module.MODE_CCM, self.iv, msg_len=10, mac_len=i) |
|
246 |
++ |
|
247 |
++ """Verify that default MAC length is 16.""" |
|
248 |
++ self.description = "CCM default MAC length check" |
|
249 |
++ cipher = self.module.new(self.key, self.module.MODE_CCM, |
|
250 |
++ self.iv, msg_len=4) |
|
251 |
++ cipher.encrypt(b('z')*4) |
|
252 |
++ self.assertEqual(len(cipher.digest()), 16) |
|
253 |
++ |
|
254 |
++class CCMSplitEncryptionTest(unittest.TestCase): |
|
255 |
++ """CCM specific tests to validate how encrypt() |
|
256 |
++ decrypt() can be called multiple times on the |
|
257 |
++ same object.""" |
|
258 |
++ |
|
259 |
++ def __init__(self, module): |
|
260 |
++ unittest.TestCase.__init__(self) |
|
261 |
++ self.module = module |
|
262 |
++ self.key = b('\xFF')*16 |
|
263 |
++ self.iv = b('\x00')*10 |
|
264 |
++ self.description = "CCM Split Encryption Test" |
|
265 |
++ |
|
266 |
++ def shortDescription(self): |
|
267 |
++ return self.description |
|
268 |
++ |
|
269 |
++ def runTest(self): |
|
270 |
++ """Verify that CCM update()/encrypt() can be called multiple times, |
|
271 |
++ provided that lengths are declared beforehand""" |
|
272 |
++ |
|
273 |
++ data = b("AUTH DATA") |
|
274 |
++ pt1 = b("PLAINTEXT1") # Short |
|
275 |
++ pt2 = b("PLAINTEXT2") # Long |
|
276 |
++ pt_ref = pt1+pt2 |
|
277 |
++ |
|
278 |
++ # REFERENCE: Run with 1 update() and 1 encrypt() |
|
279 |
++ cipher = self.module.new(self.key, self.module.MODE_CCM, |
|
280 |
++ self.iv) |
|
281 |
++ cipher.update(data) |
|
282 |
++ ct_ref = cipher.encrypt(pt_ref) |
|
283 |
++ mac_ref = cipher.digest() |
|
284 |
++ |
|
285 |
++ # Verify that calling CCM encrypt()/decrypt() twice is not |
|
286 |
++ # possible without the 'msg_len' parameter and regardless |
|
287 |
++ # of the 'assoc_len' parameter |
|
288 |
++ for ad_len in None, len(data): |
|
289 |
++ cipher = self.module.new(self.key, self.module.MODE_CCM, |
|
290 |
++ self.iv, assoc_len=ad_len) |
|
291 |
++ cipher.update(data) |
|
292 |
++ cipher.encrypt(pt1) |
|
293 |
++ self.assertRaises(TypeError, cipher.encrypt, pt2) |
|
294 |
++ |
|
295 |
++ cipher = self.module.new(self.key, self.module.MODE_CCM, |
|
296 |
++ self.iv, assoc_len=ad_len) |
|
297 |
++ cipher.update(data) |
|
298 |
++ cipher.decrypt(ct_ref[:len(pt1)]) |
|
299 |
++ self.assertRaises(TypeError, cipher.decrypt, ct_ref[len(pt1):]) |
|
300 |
++ |
|
301 |
++ # Run with 2 encrypt()/decrypt(). Results must be the same |
|
302 |
++ # regardless of the 'assoc_len' parameter |
|
303 |
++ for ad_len in None, len(data): |
|
304 |
++ cipher = self.module.new(self.key, self.module.MODE_CCM, |
|
305 |
++ self.iv, assoc_len=ad_len, msg_len=len(pt_ref)) |
|
306 |
++ cipher.update(data) |
|
307 |
++ ct = cipher.encrypt(pt1) |
|
308 |
++ ct += cipher.encrypt(pt2) |
|
309 |
++ mac = cipher.digest() |
|
310 |
++ self.assertEqual(ct_ref, ct) |
|
311 |
++ self.assertEqual(mac_ref, mac) |
|
312 |
++ |
|
313 |
++ cipher = self.module.new(self.key, self.module.MODE_CCM, |
|
314 |
++ self.iv, msg_len=len(pt1+pt2)) |
|
315 |
++ cipher.update(data) |
|
316 |
++ pt = cipher.decrypt(ct[:len(pt1)]) |
|
317 |
++ pt += cipher.decrypt(ct[len(pt1):]) |
|
318 |
++ mac = cipher.verify(mac_ref) |
|
319 |
++ self.assertEqual(pt_ref, pt) |
|
320 |
++ |
|
321 |
++class AEADTests(unittest.TestCase): |
|
322 |
++ """Tests generic to all AEAD modes""" |
|
323 |
++ |
|
324 |
++ def __init__(self, module, mode_name): |
|
325 |
++ unittest.TestCase.__init__(self) |
|
326 |
++ self.module = module |
|
327 |
++ self.mode_name = mode_name |
|
328 |
++ self.mode = getattr(module, mode_name) |
|
329 |
++ self.key = b('\xFF')*16 |
|
330 |
++ self.iv = b('\x00')*10 |
|
331 |
++ self.description = "AEAD Test" |
|
332 |
++ |
|
333 |
++ def right_mac_test(self): |
|
334 |
++ """Positive tests for MAC""" |
|
335 |
++ |
|
336 |
++ self.description = "Test for right MAC in %s of %s" % \ |
|
337 |
++ (self.mode_name, self.module.__name__) |
|
338 |
++ |
|
339 |
++ ad_ref = b("Reference AD") |
|
340 |
++ pt_ref = b("Reference plaintext") |
|
341 |
++ |
|
342 |
++ # Encrypt and create the reference MAC |
|
343 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
344 |
++ cipher.update(ad_ref) |
|
345 |
++ ct_ref = cipher.encrypt(pt_ref) |
|
346 |
++ mac_ref = cipher.digest() |
|
347 |
++ |
|
348 |
++ # Decrypt and verify that MAC is accepted |
|
349 |
++ decipher = self.module.new(self.key, self.mode, self.iv) |
|
350 |
++ decipher.update(ad_ref) |
|
351 |
++ pt = decipher.decrypt(ct_ref) |
|
352 |
++ decipher.verify(mac_ref) |
|
353 |
++ self.assertEqual(pt, pt_ref) |
|
354 |
++ |
|
355 |
++ # Verify that hexverify work |
|
356 |
++ decipher.hexverify(hexlify(mac_ref)) |
|
357 |
++ |
|
358 |
++ def wrong_mac_test(self): |
|
359 |
++ """Negative tests for MAC""" |
|
360 |
++ |
|
361 |
++ self.description = "Test for wrong MAC in %s of %s" % \ |
|
362 |
++ (self.mode_name, self.module.__name__) |
|
363 |
++ |
|
364 |
++ ad_ref = b("Reference AD") |
|
365 |
++ pt_ref = b("Reference plaintext") |
|
366 |
++ |
|
367 |
++ # Encrypt and create the reference MAC |
|
368 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
369 |
++ cipher.update(ad_ref) |
|
370 |
++ ct_ref = cipher.encrypt(pt_ref) |
|
371 |
++ mac_ref = cipher.digest() |
|
372 |
++ |
|
373 |
++ # Modify the MAC and verify it is NOT ACCEPTED |
|
374 |
++ wrong_mac = strxor_c(mac_ref, 255) |
|
375 |
++ decipher = self.module.new(self.key, self.mode, self.iv) |
|
376 |
++ decipher.update(ad_ref) |
|
377 |
++ pt = decipher.decrypt(ct_ref) |
|
378 |
++ self.assertRaises(ValueError, decipher.verify, wrong_mac) |
|
379 |
++ |
|
380 |
++ def zero_data(self): |
|
381 |
++ """Verify transition from INITIALIZED to FINISHED""" |
|
382 |
++ |
|
383 |
++ self.description = "Test for zero data in %s of %s" % \ |
|
384 |
++ (self.mode_name, self.module.__name__) |
|
385 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
386 |
++ cipher.digest() |
|
387 |
++ |
|
388 |
++ def multiple_updates(self): |
|
389 |
++ """Verify that update() can be called multiple times""" |
|
390 |
++ |
|
391 |
++ self.description = "Test for multiple updates in %s of %s" % \ |
|
392 |
++ (self.mode_name, self.module.__name__) |
|
393 |
++ |
|
394 |
++ ad = b("").join([bchr(x) for x in xrange(0,128)]) |
|
395 |
++ |
|
396 |
++ mac1, mac2, mac3 = (None,)*3 |
|
397 |
++ for chunk_length in 1,10,40,80,128: |
|
398 |
++ chunks = [ad[i:i+chunk_length] for i in range(0, len(ad), chunk_length)] |
|
399 |
++ |
|
400 |
++ # No encryption/decryption |
|
401 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
402 |
++ for c in chunks: |
|
403 |
++ cipher.update(c) |
|
404 |
++ if mac1: |
|
405 |
++ cipher.verify(mac1) |
|
406 |
++ else: |
|
407 |
++ mac1 = cipher.digest() |
|
408 |
++ |
|
409 |
++ # Encryption |
|
410 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
411 |
++ for c in chunks: |
|
412 |
++ cipher.update(c) |
|
413 |
++ ct = cipher.encrypt(b("PT")) |
|
414 |
++ mac2 = cipher.digest() |
|
415 |
++ |
|
416 |
++ # Decryption |
|
417 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
418 |
++ for c in chunks: |
|
419 |
++ cipher.update(c) |
|
420 |
++ cipher.decrypt(ct) |
|
421 |
++ cipher.verify(mac2) |
|
422 |
++ |
|
423 |
++ def no_mix_encrypt_decrypt(self): |
|
424 |
++ """Verify that encrypt and decrypt cannot be mixed up""" |
|
425 |
++ |
|
426 |
++ self.description = "Test for mix of encrypt and decrypt in %s of %s" % \ |
|
427 |
++ (self.mode_name, self.module.__name__) |
|
428 |
++ |
|
429 |
++ # Calling decrypt after encrypt raises an exception |
|
430 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
431 |
++ cipher.encrypt(b("PT")) |
|
432 |
++ self.assertRaises(TypeError, cipher.decrypt, b("XYZ")) |
|
433 |
++ |
|
434 |
++ # Calling encrypt after decrypt raises an exception |
|
435 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
436 |
++ cipher.decrypt(b("CT")) |
|
437 |
++ self.assertRaises(TypeError, cipher.encrypt, b("XYZ")) |
|
438 |
++ |
|
439 |
++ # Calling verify after encrypt raises an exception |
|
440 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
441 |
++ cipher.encrypt(b("PT")) |
|
442 |
++ self.assertRaises(TypeError, cipher.verify, b("XYZ")) |
|
443 |
++ self.assertRaises(TypeError, cipher.hexverify, "12") |
|
444 |
++ |
|
445 |
++ # Calling digest after decrypt raises an exception |
|
446 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
447 |
++ cipher.decrypt(b("CT")) |
|
448 |
++ self.assertRaises(TypeError, cipher.digest) |
|
449 |
++ self.assertRaises(TypeError, cipher.hexdigest) |
|
450 |
++ |
|
451 |
++ def no_late_update(self): |
|
452 |
++ """Verify that update cannot be called after encrypt or decrypt""" |
|
453 |
++ |
|
454 |
++ self.description = "Test for late update in %s of %s" % \ |
|
455 |
++ (self.mode_name, self.module.__name__) |
|
456 |
++ |
|
457 |
++ # Calling update after encrypt raises an exception |
|
458 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
459 |
++ cipher.update(b("XX")) |
|
460 |
++ cipher.encrypt(b("PT")) |
|
461 |
++ self.assertRaises(TypeError, cipher.update, b("XYZ")) |
|
462 |
++ |
|
463 |
++ # Calling update after decrypt raises an exception |
|
464 |
++ cipher = self.module.new(self.key, self.mode, self.iv) |
|
465 |
++ cipher.update(b("XX")) |
|
466 |
++ cipher.decrypt(b("CT")) |
|
467 |
++ self.assertRaises(TypeError, cipher.update, b("XYZ")) |
|
468 |
++ |
|
469 |
++ def runTest(self): |
|
470 |
++ self.right_mac_test() |
|
471 |
++ self.wrong_mac_test() |
|
472 |
++ self.zero_data() |
|
473 |
++ self.multiple_updates() |
|
474 |
++ self.no_mix_encrypt_decrypt() |
|
475 |
++ self.no_late_update() |
|
476 |
++ |
|
477 |
++ def shortDescription(self): |
|
478 |
++ return self.description |
|
479 |
++ |
|
480 |
+ class RoundtripTest(unittest.TestCase): |
|
481 |
+ def __init__(self, module, params): |
|
482 |
+ from Crypto import Random |
|
483 |
+@@ -297,6 +582,10 @@ class IVLengthTest(unittest.TestCase): |
|
484 |
+ self.module.MODE_OFB, "") |
|
485 |
+ self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), |
|
486 |
+ self.module.MODE_OPENPGP, "") |
|
487 |
++ if hasattr(self.module, "MODE_CCM"): |
|
488 |
++ for ivlen in (0,6,14): |
|
489 |
++ self.assertRaises(ValueError, self.module.new, a2b_hex(self.key), |
|
490 |
++ self.module.MODE_CCM, bchr(0)*ivlen, msg_len=10) |
|
491 |
+ self.module.new(a2b_hex(self.key), self.module.MODE_ECB, "") |
|
492 |
+ self.module.new(a2b_hex(self.key), self.module.MODE_CTR, "", counter=self._dummy_counter) |
|
493 |
+ |
|
494 |
+@@ -352,7 +641,12 @@ def make_block_tests(module, module_name |
|
495 |
+ IVLengthTest(module, params), |
|
496 |
+ ] |
|
497 |
+ extra_tests_added = 1 |
|
498 |
+- |
|
499 |
++ # Extract associated data and MAC for AEAD modes |
|
500 |
++ if p_mode == 'CCM': |
|
501 |
++ assoc_data, params['plaintext'] = params['plaintext'].split('|') |
|
502 |
++ assoc_data2, params['ciphertext'], params['mac'] = params['ciphertext'].split('|') |
|
503 |
++ params['assoc_data'] = assoc_data |
|
504 |
++ params['mac_len'] = len(params['mac'])>>1 |
|
505 |
+ # Add the current test to the test suite |
|
506 |
+ tests.append(CipherSelfTest(module, params)) |
|
507 |
+ |
|
508 |
+@@ -369,6 +663,17 @@ def make_block_tests(module, module_name |
|
509 |
+ if not params2['ctr_params'].has_key('disable_shortcut'): |
|
510 |
+ params2['ctr_params']['disable_shortcut'] = 1 |
|
511 |
+ tests.append(CipherSelfTest(module, params2)) |
|
512 |
++ # Add tests that don't use test vectors |
|
513 |
++ if hasattr(module, "MODE_CCM"): |
|
514 |
++ tests += [ |
|
515 |
++ CCMMACLengthTest(module), |
|
516 |
++ CCMSplitEncryptionTest(module), |
|
517 |
++ ] |
|
518 |
++ for aead_mode in ("MODE_CCM",): |
|
519 |
++ if hasattr(module, aead_mode): |
|
520 |
++ tests += [ |
|
521 |
++ AEADTests(module, aead_mode), |
|
522 |
++ ] |
|
523 |
+ return tests |
|
524 |
+ |
|
525 |
+ def make_stream_tests(module, module_name, test_data): |
|
526 |
+--- a/lib/Crypto/SelfTest/Cipher/test_AES.py_org 2019-05-17 23:39:02.360284441 +0530 |
|
527 |
+@@ -1418,6 +1418,239 @@ test_data = [ |
|
528 |
+ '5baa61e4c9b93f3f0682250b6cf8331b', # Key (hash of 'password') |
|
529 |
+ 'GPG Test Vector #1', |
|
530 |
+ dict(mode='OPENPGP', iv='3d7d3e62282add7eb203eeba5c800733', encrypted_iv='fd934601ef49cb58b6d9aebca6056bdb96ef' ) ), |
|
531 |
++ # NIST SP 800-38C test vectors for CCM |
|
532 |
++ # This is a list of tuples with 5 items: |
|
533 |
++ # |
|
534 |
++ # 1. Associated data + '|' + plaintext |
|
535 |
++ # 2. Associated data + '|' + ciphertext + '|' + MAC |
|
536 |
++ # 3. AES-128 key |
|
537 |
++ # 4. Description |
|
538 |
++ # 5. Dictionary of parameters to be passed to AES.new(). |
|
539 |
++ # It must include the nonce. |
|
540 |
++ # |
|
541 |
++ ( '0001020304050607|20212223', |
|
542 |
++ '0001020304050607|7162015b|4dac255d', |
|
543 |
++ '404142434445464748494a4b4c4d4e4f', |
|
544 |
++ 'NIST SP 800-38C Appex C.1', |
|
545 |
++ dict(mode='CCM', nonce='10111213141516') |
|
546 |
++ ), |
|
547 |
++ ( '000102030405060708090a0b0c0d0e0f|202122232425262728292a2b2c2d2e2f', |
|
548 |
++ '000102030405060708090a0b0c0d0e0f|d2a1f0e051ea5f62081a7792073d593d|1fc64fbfaccd', |
|
549 |
++ '404142434445464748494a4b4c4d4e4f', |
|
550 |
++ 'NIST SP 800-38C Appex C.2', |
|
551 |
++ dict(mode='CCM', nonce='1011121314151617') |
|
552 |
++ ), |
|
553 |
++ ( '000102030405060708090a0b0c0d0e0f10111213|'+ |
|
554 |
++ '202122232425262728292a2b2c2d2e2f3031323334353637', |
|
555 |
++ '000102030405060708090a0b0c0d0e0f10111213|'+ |
|
556 |
++ 'e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5|484392fbc1b09951', |
|
557 |
++ '404142434445464748494a4b4c4d4e4f', |
|
558 |
++ 'NIST SP 800-38C Appex C.3', |
|
559 |
++ dict(mode='CCM', nonce='101112131415161718191a1b') |
|
560 |
++ ), |
|
561 |
++ ( |
|
562 |
++ (''.join(["%02X" % (x*16+y) for x in xrange(0,16) for y in xrange(0,16)]))*256+'|'+ |
|
563 |
++ '202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f', |
|
564 |
++ (''.join(["%02X" % (x*16+y) for x in xrange(0,16) for y in xrange(0,16)]))*256+'|'+ |
|
565 |
++ '69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72|'+ |
|
566 |
++ 'b4ac6bec93e8598e7f0dadbcea5b', |
|
567 |
++ '404142434445464748494a4b4c4d4e4f', |
|
568 |
++ 'NIST SP 800-38C Appex C.4', |
|
569 |
++ dict(mode='CCM', nonce='101112131415161718191a1b1c') |
|
570 |
++ ), |
|
571 |
++ # RFC3610 test vectors |
|
572 |
++ ( |
|
573 |
++ '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e', |
|
574 |
++ '0001020304050607|588c979a61c663d2f066d0c2c0f989806d5f6b61dac384|'+ |
|
575 |
++ '17e8d12cfdf926e0', |
|
576 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
577 |
++ 'RFC3610 Packet Vector #1', |
|
578 |
++ dict(mode='CCM', nonce='00000003020100a0a1a2a3a4a5') |
|
579 |
++ ), |
|
580 |
++ ( |
|
581 |
++ '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', |
|
582 |
++ '0001020304050607|72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b|'+ |
|
583 |
++ 'a091d56e10400916', |
|
584 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
585 |
++ 'RFC3610 Packet Vector #2', |
|
586 |
++ dict(mode='CCM', nonce='00000004030201a0a1a2a3a4a5') |
|
587 |
++ ), |
|
588 |
++ ( |
|
589 |
++ '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', |
|
590 |
++ '0001020304050607|51b1e5f44a197d1da46b0f8e2d282ae871e838bb64da859657|'+ |
|
591 |
++ '4adaa76fbd9fb0c5', |
|
592 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
593 |
++ 'RFC3610 Packet Vector #3', |
|
594 |
++ dict(mode='CCM', nonce='00000005040302A0A1A2A3A4A5') |
|
595 |
++ ), |
|
596 |
++ ( |
|
597 |
++ '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e', |
|
598 |
++ '000102030405060708090a0b|a28c6865939a9a79faaa5c4c2a9d4a91cdac8c|'+ |
|
599 |
++ '96c861b9c9e61ef1', |
|
600 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
601 |
++ 'RFC3610 Packet Vector #4', |
|
602 |
++ dict(mode='CCM', nonce='00000006050403a0a1a2a3a4a5') |
|
603 |
++ ), |
|
604 |
++ ( |
|
605 |
++ '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f', |
|
606 |
++ '000102030405060708090a0b|dcf1fb7b5d9e23fb9d4e131253658ad86ebdca3e|'+ |
|
607 |
++ '51e83f077d9c2d93', |
|
608 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
609 |
++ 'RFC3610 Packet Vector #5', |
|
610 |
++ dict(mode='CCM', nonce='00000007060504a0a1a2a3a4a5') |
|
611 |
++ ), |
|
612 |
++ ( |
|
613 |
++ '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f20', |
|
614 |
++ '000102030405060708090a0b|6fc1b011f006568b5171a42d953d469b2570a4bd87|'+ |
|
615 |
++ '405a0443ac91cb94', |
|
616 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
617 |
++ 'RFC3610 Packet Vector #6', |
|
618 |
++ dict(mode='CCM', nonce='00000008070605a0a1a2a3a4a5') |
|
619 |
++ ), |
|
620 |
++ ( |
|
621 |
++ '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e', |
|
622 |
++ '0001020304050607|0135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c|'+ |
|
623 |
++ '048c56602c97acbb7490', |
|
624 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
625 |
++ 'RFC3610 Packet Vector #7', |
|
626 |
++ dict(mode='CCM', nonce='00000009080706a0a1a2a3a4a5') |
|
627 |
++ ), |
|
628 |
++ ( |
|
629 |
++ '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', |
|
630 |
++ '0001020304050607|7b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24|'+ |
|
631 |
++ 'c17b4433f434963f34b4', |
|
632 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
633 |
++ 'RFC3610 Packet Vector #8', |
|
634 |
++ dict(mode='CCM', nonce='0000000a090807a0a1a2a3a4a5') |
|
635 |
++ ), |
|
636 |
++ ( |
|
637 |
++ '0001020304050607|08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20', |
|
638 |
++ '0001020304050607|82531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197|'+ |
|
639 |
++ 'ea9c07e56b5eb17e5f4e', |
|
640 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
641 |
++ 'RFC3610 Packet Vector #9', |
|
642 |
++ dict(mode='CCM', nonce='0000000b0a0908a0a1a2a3a4a5') |
|
643 |
++ ), |
|
644 |
++ ( |
|
645 |
++ '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e', |
|
646 |
++ '000102030405060708090a0b|07342594157785152b074098330abb141b947b|'+ |
|
647 |
++ '566aa9406b4d999988dd', |
|
648 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
649 |
++ 'RFC3610 Packet Vector #10', |
|
650 |
++ dict(mode='CCM', nonce='0000000c0b0a09a0a1a2a3a4a5') |
|
651 |
++ ), |
|
652 |
++ ( |
|
653 |
++ '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f', |
|
654 |
++ '000102030405060708090a0b|676bb20380b0e301e8ab79590a396da78b834934|'+ |
|
655 |
++ 'f53aa2e9107a8b6c022c', |
|
656 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
657 |
++ 'RFC3610 Packet Vector #11', |
|
658 |
++ dict(mode='CCM', nonce='0000000d0c0b0aa0a1a2a3a4a5') |
|
659 |
++ ), |
|
660 |
++ ( |
|
661 |
++ '000102030405060708090a0b|0c0d0e0f101112131415161718191a1b1c1d1e1f20', |
|
662 |
++ '000102030405060708090a0b|c0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43|'+ |
|
663 |
++ 'cd1aa31662e7ad65d6db', |
|
664 |
++ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf', |
|
665 |
++ 'RFC3610 Packet Vector #12', |
|
666 |
++ dict(mode='CCM', nonce='0000000e0d0c0ba0a1a2a3a4a5') |
|
667 |
++ ), |
|
668 |
++ ( |
|
669 |
++ '0be1a88bace018b1|08e8cf97d820ea258460e96ad9cf5289054d895ceac47c', |
|
670 |
++ '0be1a88bace018b1|4cb97f86a2a4689a877947ab8091ef5386a6ffbdd080f8|'+ |
|
671 |
++ 'e78cf7cb0cddd7b3', |
|
672 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
673 |
++ 'RFC3610 Packet Vector #13', |
|
674 |
++ dict(mode='CCM', nonce='00412b4ea9cdbe3c9696766cfa') |
|
675 |
++ ), |
|
676 |
++ ( |
|
677 |
++ '63018f76dc8a1bcb|9020ea6f91bdd85afa0039ba4baff9bfb79c7028949cd0ec', |
|
678 |
++ '63018f76dc8a1bcb|4ccb1e7ca981befaa0726c55d378061298c85c92814abc33|'+ |
|
679 |
++ 'c52ee81d7d77c08a', |
|
680 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
681 |
++ 'RFC3610 Packet Vector #14', |
|
682 |
++ dict(mode='CCM', nonce='0033568ef7b2633c9696766cfa') |
|
683 |
++ ), |
|
684 |
++ ( |
|
685 |
++ 'aa6cfa36cae86b40|b916e0eacc1c00d7dcec68ec0b3bbb1a02de8a2d1aa346132e', |
|
686 |
++ 'aa6cfa36cae86b40|b1d23a2220ddc0ac900d9aa03c61fcf4a559a4417767089708|'+ |
|
687 |
++ 'a776796edb723506', |
|
688 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
689 |
++ 'RFC3610 Packet Vector #15', |
|
690 |
++ dict(mode='CCM', nonce='00103fe41336713c9696766cfa') |
|
691 |
++ ), |
|
692 |
++ ( |
|
693 |
++ 'd0d0735c531e1becf049c244|12daac5630efa5396f770ce1a66b21f7b2101c', |
|
694 |
++ 'd0d0735c531e1becf049c244|14d253c3967b70609b7cbb7c49916028324526|'+ |
|
695 |
++ '9a6f49975bcadeaf', |
|
696 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
697 |
++ 'RFC3610 Packet Vector #16', |
|
698 |
++ dict(mode='CCM', nonce='00764c63b8058e3c9696766cfa') |
|
699 |
++ ), |
|
700 |
++ ( |
|
701 |
++ '77b60f011c03e1525899bcae|e88b6a46c78d63e52eb8c546efb5de6f75e9cc0d', |
|
702 |
++ '77b60f011c03e1525899bcae|5545ff1a085ee2efbf52b2e04bee1e2336c73e3f|'+ |
|
703 |
++ '762c0c7744fe7e3c', |
|
704 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
705 |
++ 'RFC3610 Packet Vector #17', |
|
706 |
++ dict(mode='CCM', nonce='00f8b678094e3b3c9696766cfa') |
|
707 |
++ ), |
|
708 |
++ ( |
|
709 |
++ 'cd9044d2b71fdb8120ea60c0|6435acbafb11a82e2f071d7ca4a5ebd93a803ba87f', |
|
710 |
++ 'cd9044d2b71fdb8120ea60c0|009769ecabdf48625594c59251e6035722675e04c8|'+ |
|
711 |
++ '47099e5ae0704551', |
|
712 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
713 |
++ 'RFC3610 Packet Vector #18', |
|
714 |
++ dict(mode='CCM', nonce='00d560912d3f703c9696766cfa') |
|
715 |
++ ), |
|
716 |
++ ( |
|
717 |
++ 'd85bc7e69f944fb8|8a19b950bcf71a018e5e6701c91787659809d67dbedd18', |
|
718 |
++ 'd85bc7e69f944fb8|bc218daa947427b6db386a99ac1aef23ade0b52939cb6a|'+ |
|
719 |
++ '637cf9bec2408897c6ba', |
|
720 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
721 |
++ 'RFC3610 Packet Vector #19', |
|
722 |
++ dict(mode='CCM', nonce='0042fff8f1951c3c9696766cfa') |
|
723 |
++ ), |
|
724 |
++ ( |
|
725 |
++ '74a0ebc9069f5b37|1761433c37c5a35fc1f39f406302eb907c6163be38c98437', |
|
726 |
++ '74a0ebc9069f5b37|5810e6fd25874022e80361a478e3e9cf484ab04f447efff6|'+ |
|
727 |
++ 'f0a477cc2fc9bf548944', |
|
728 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
729 |
++ 'RFC3610 Packet Vector #20', |
|
730 |
++ dict(mode='CCM', nonce='00920f40e56cdc3c9696766cfa') |
|
731 |
++ ), |
|
732 |
++ ( |
|
733 |
++ '44a3aa3aae6475ca|a434a8e58500c6e41530538862d686ea9e81301b5ae4226bfa', |
|
734 |
++ '44a3aa3aae6475ca|f2beed7bc5098e83feb5b31608f8e29c38819a89c8e776f154|'+ |
|
735 |
++ '4d4151a4ed3a8b87b9ce', |
|
736 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
737 |
++ 'RFC3610 Packet Vector #21', |
|
738 |
++ dict(mode='CCM', nonce='0027ca0c7120bc3c9696766cfa') |
|
739 |
++ ), |
|
740 |
++ ( |
|
741 |
++ 'ec46bb63b02520c33c49fd70|b96b49e21d621741632875db7f6c9243d2d7c2', |
|
742 |
++ 'ec46bb63b02520c33c49fd70|31d750a09da3ed7fddd49a2032aabf17ec8ebf|'+ |
|
743 |
++ '7d22c8088c666be5c197', |
|
744 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
745 |
++ 'RFC3610 Packet Vector #22', |
|
746 |
++ dict(mode='CCM', nonce='005b8ccbcd9af83c9696766cfa') |
|
747 |
++ ), |
|
748 |
++ ( |
|
749 |
++ '47a65ac78b3d594227e85e71|e2fcfbb880442c731bf95167c8ffd7895e337076', |
|
750 |
++ '47a65ac78b3d594227e85e71|e882f1dbd38ce3eda7c23f04dd65071eb41342ac|'+ |
|
751 |
++ 'df7e00dccec7ae52987d', |
|
752 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
753 |
++ 'RFC3610 Packet Vector #23', |
|
754 |
++ dict(mode='CCM', nonce='003ebe94044b9a3c9696766cfa') |
|
755 |
++ ), |
|
756 |
++ ( |
|
757 |
++ '6e37a6ef546d955d34ab6059|abf21c0b02feb88f856df4a37381bce3cc128517d4', |
|
758 |
++ '6e37a6ef546d955d34ab6059|f32905b88a641b04b9c9ffb58cc390900f3da12ab1|'+ |
|
759 |
++ '6dce9e82efa16da62059', |
|
760 |
++ 'd7828d13b2b0bdc325a76236df93cc6b', |
|
761 |
++ 'RFC3610 Packet Vector #24', |
|
762 |
++ dict(mode='CCM', nonce='008d493b30ae8b3c9696766cfa') |
|
763 |
++ ), |
|
764 |
+ ] |
|
765 |
+ |
|
766 |
+ def get_tests(config={}): |
|
767 |
+--- a/pct-speedtest.py_org 2019-05-17 23:42:34.532288679 +0530 |
|
768 |
+@@ -123,6 +123,8 @@ class Benchmark: |
|
769 |
+ cipher = module.new(key) |
|
770 |
+ elif mode==module.MODE_ECB: |
|
771 |
+ cipher = module.new(key, module.MODE_ECB) |
|
772 |
++ elif hasattr(module, 'MODE_CCM') and mode==module.MODE_CCM: |
|
773 |
++ cipher = module.new(key, mode, iv[:8], msg_len=len(rand)*len(blocks)) |
|
774 |
+ else: |
|
775 |
+ cipher = module.new(key, mode, iv) |
|
776 |
+ |
|
777 |
+@@ -208,7 +210,8 @@ class Benchmark: |
|
778 |
+ self.test_encryption("%s-OFB" % (cipher_name,), module, key_bytes, module.MODE_OFB) |
|
779 |
+ self.test_encryption("%s-ECB" % (cipher_name,), module, key_bytes, module.MODE_ECB) |
|
780 |
+ self.test_encryption("%s-OPENPGP" % (cipher_name,), module, key_bytes, module.MODE_OPENPGP) |
|
781 |
+- |
|
782 |
++ if hasattr(module, "MODE_CCM"): |
|
783 |
++ self.test_encryption("%s-CCM" % (cipher_name,), module, key_bytes, module.MODE_CCM) |
|
784 |
+ for cipher_name, module, key_bytes in stream_specs: |
|
785 |
+ self.test_key_setup(cipher_name, module, key_bytes, None) |
|
786 |
+ self.test_encryption(cipher_name, module, key_bytes, None) |
|
787 |
+--- a/lib/Crypto/Cipher/blockalgo.py_org 2019-05-17 23:00:46.608238583 +0530 |
|
788 |
+@@ -25,6 +25,11 @@ import sys |
|
789 |
+ if sys.version_info[0] == 2 and sys.version_info[1] == 1: |
|
790 |
+ from Crypto.Util.py21compat import * |
|
791 |
+ from Crypto.Util.py3compat import * |
|
792 |
++from binascii import unhexlify |
|
793 |
++ |
|
794 |
++from Crypto.Util import Counter |
|
795 |
++from Crypto.Util.strxor import strxor |
|
796 |
++from Crypto.Util.number import long_to_bytes |
|
797 |
+ |
|
798 |
+ #: *Electronic Code Book (ECB)*. |
|
799 |
+ #: This is the simplest encryption mode. Each of the plaintext blocks |
|
800 |
+@@ -120,6 +125,60 @@ MODE_CTR = 6 |
|
801 |
+ #: |
|
802 |
+ #: .. _OpenPGP: http://tools.ietf.org/html/rfc4880 |
|
803 |
+ MODE_OPENPGP = 7 |
|
804 |
++#: *Counter with CBC-MAC (CCM)*. This is an Authenticated Encryption with |
|
805 |
++#: Associated Data (`AEAD`_) mode. It provides both confidentiality and |
|
806 |
++#: authenticity. |
|
807 |
++#: The header of the message may be left in the clear, if needed, and it will |
|
808 |
++#: still be subject to authentication. The decryption step tells the receiver |
|
809 |
++#: if the message comes from a source that really knowns the secret key. |
|
810 |
++#: Additionally, decryption detects if any part of the message - including the |
|
811 |
++#: header - has been modified or corrupted. |
|
812 |
++#: |
|
813 |
++#: This mode requires a nonce. The nonce shall never repeat for two |
|
814 |
++#: different messages encrypted with the same key, but it does not need |
|
815 |
++#: to be random. |
|
816 |
++#: Note that there is a trade-off between the size of the nonce and the |
|
817 |
++#: maximum size of a single message you can encrypt. |
|
818 |
++#: |
|
819 |
++#: It is important to use a large nonce if the key is reused across several |
|
820 |
++#: messages and the nonce is chosen randomly. |
|
821 |
++#: |
|
822 |
++#: It is acceptable to us a short nonce if the key is only used a few times or |
|
823 |
++#: if the nonce is taken from a counter. |
|
824 |
++#: |
|
825 |
++#: The following table shows the trade-off when the nonce is chosen at |
|
826 |
++#: random. The column on the left shows how many messages it takes |
|
827 |
++#: for the keystream to repeat **on average**. In practice, you will want to |
|
828 |
++#: stop using the key way before that. |
|
829 |
++#: |
|
830 |
++#: +--------------------+---------------+-------------------+ |
|
831 |
++#: | Avg. # of messages | nonce | Max. message | |
|
832 |
++#: | before keystream | size | size | |
|
833 |
++#: | repeats | (bytes) | (bytes) | |
|
834 |
++#: +====================+===============+===================+ |
|
835 |
++#: | 2**52 | 13 | 64K | |
|
836 |
++#: +--------------------+---------------+-------------------+ |
|
837 |
++#: | 2**48 | 12 | 16M | |
|
838 |
++#: +--------------------+---------------+-------------------+ |
|
839 |
++#: | 2**44 | 11 | 4G | |
|
840 |
++#: +--------------------+---------------+-------------------+ |
|
841 |
++#: | 2**40 | 10 | 1T | |
|
842 |
++#: +--------------------+---------------+-------------------+ |
|
843 |
++#: | 2**36 | 9 | 64P | |
|
844 |
++#: +--------------------+---------------+-------------------+ |
|
845 |
++#: | 2**32 | 8 | 16E | |
|
846 |
++#: +--------------------+---------------+-------------------+ |
|
847 |
++#: |
|
848 |
++#: This mode is only available for ciphers that operate on 128 bits blocks |
|
849 |
++#: (e.g. AES but not TDES). |
|
850 |
++#: |
|
851 |
++#: See `NIST SP800-38C`_ or RFC3610_ . |
|
852 |
++#: |
|
853 |
++#: .. _`NIST SP800-38C`: http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C.pdf |
|
854 |
++#: .. _RFC3610: https://tools.ietf.org/html/rfc3610 |
|
855 |
++#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html |
|
856 |
++MODE_CCM = 8 |
|
857 |
++ |
|
858 |
+ |
|
859 |
+ def _getParameter(name, index, args, kwargs, default=None): |
|
860 |
+ """Find a parameter in tuple and dictionary arguments a function receives""" |
|
861 |
+@@ -137,52 +196,203 @@ class BlockAlgo: |
|
862 |
+ self.mode = _getParameter('mode', 0, args, kwargs, default=MODE_ECB) |
|
863 |
+ self.block_size = factory.block_size |
|
864 |
+ |
|
865 |
+- if self.mode != MODE_OPENPGP: |
|
866 |
++ self._factory = factory |
|
867 |
++ if self.mode == MODE_CCM: |
|
868 |
++ if self.block_size != 16: |
|
869 |
++ raise ValueError("CCM mode is only available for ciphers that operate on 128 bits blocks") |
|
870 |
++ |
|
871 |
++ self._mac_len = kwargs.get('mac_len', 16) # t |
|
872 |
++ if self._mac_len not in (4, 6, 8, 10, 12, 14, 16): |
|
873 |
++ raise ValueError("Parameter 'mac_len' must be even and in the range 4..16") |
|
874 |
++ |
|
875 |
++ self.nonce = _getParameter('nonce', 1, args, kwargs) # N |
|
876 |
++ if not (self.nonce and 7 <= len(self.nonce) <= 13): |
|
877 |
++ raise ValueError("Length of parameter 'nonce' must be" |
|
878 |
++ " in the range 7..13 bytes") |
|
879 |
++ |
|
880 |
++ self._key = key |
|
881 |
++ self._msg_len = kwargs.get('msg_len', None) # p |
|
882 |
++ self._assoc_len = kwargs.get('assoc_len', None) # a |
|
883 |
++ |
|
884 |
++ self._assoc_buffer = [] |
|
885 |
++ self._assoc_buffer_len = 0 |
|
886 |
++ self._cipherCBC = None # To be used for MAC |
|
887 |
++ self._done_assoc_data = False # True when all associated data |
|
888 |
++ # has been processed |
|
889 |
++ |
|
890 |
++ # Allowed transitions after initialization |
|
891 |
++ self._next = [self.update, self.encrypt, self.decrypt, |
|
892 |
++ self.digest, self.verify] |
|
893 |
++ |
|
894 |
++ # Try to start CCM |
|
895 |
++ self._start_ccm() |
|
896 |
++ |
|
897 |
++ elif self.mode == MODE_OPENPGP: |
|
898 |
++ self._start_PGP(factory, key, *args, **kwargs) |
|
899 |
++ else: |
|
900 |
+ self._cipher = factory.new(key, *args, **kwargs) |
|
901 |
+ self.IV = self._cipher.IV |
|
902 |
++ |
|
903 |
++ def _start_PGP(self, factory, key, *args, **kwargs): |
|
904 |
++ # OPENPGP mode. For details, see 13.9 in RCC4880. |
|
905 |
++ # |
|
906 |
++ # A few members are specifically created for this mode: |
|
907 |
++ # - _encrypted_iv, set in this constructor |
|
908 |
++ # - _done_first_block, set to True after the first encryption |
|
909 |
++ # - _done_last_block, set to True after a partial block is processed |
|
910 |
++ |
|
911 |
++ self._done_first_block = False |
|
912 |
++ self._done_last_block = False |
|
913 |
++ self.IV = _getParameter('iv', 1, args, kwargs) |
|
914 |
++ if not self.IV: |
|
915 |
++ raise ValueError("MODE_OPENPGP requires an IV") |
|
916 |
++ |
|
917 |
++ # Instantiate a temporary cipher to process the IV |
|
918 |
++ IV_cipher = factory.new( |
|
919 |
++ key, |
|
920 |
++ MODE_CFB, |
|
921 |
++ b('\x00') * self.block_size, # IV for CFB |
|
922 |
++ segment_size=self.block_size * 8) |
|
923 |
++ |
|
924 |
++ # The cipher will be used for... |
|
925 |
++ if len(self.IV) == self.block_size: |
|
926 |
++ # ... encryption |
|
927 |
++ self._encrypted_IV = IV_cipher.encrypt( |
|
928 |
++ self.IV + self.IV[-2:] + # Plaintext |
|
929 |
++ b('\x00') * (self.block_size - 2) # Padding |
|
930 |
++ )[:self.block_size + 2] |
|
931 |
++ elif len(self.IV) == self.block_size + 2: |
|
932 |
++ # ... decryption |
|
933 |
++ self._encrypted_IV = self.IV |
|
934 |
++ self.IV = IV_cipher.decrypt( |
|
935 |
++ self.IV + # Ciphertext |
|
936 |
++ b('\x00') * (self.block_size - 2) # Padding |
|
937 |
++ )[:self.block_size + 2] |
|
938 |
++ if self.IV[-2:] != self.IV[-4:-2]: |
|
939 |
++ raise ValueError("Failed integrity check for OPENPGP IV") |
|
940 |
++ self.IV = self.IV[:-2] |
|
941 |
+ else: |
|
942 |
+- # OPENPGP mode. For details, see 13.9 in RCC4880. |
|
943 |
+- # |
|
944 |
+- # A few members are specifically created for this mode: |
|
945 |
+- # - _encrypted_iv, set in this constructor |
|
946 |
+- # - _done_first_block, set to True after the first encryption |
|
947 |
+- # - _done_last_block, set to True after a partial block is processed |
|
948 |
+- |
|
949 |
+- self._done_first_block = False |
|
950 |
+- self._done_last_block = False |
|
951 |
+- self.IV = _getParameter('iv', 1, args, kwargs) |
|
952 |
+- if not self.IV: |
|
953 |
+- raise ValueError("MODE_OPENPGP requires an IV") |
|
954 |
+- |
|
955 |
+- # Instantiate a temporary cipher to process the IV |
|
956 |
+- IV_cipher = factory.new(key, MODE_CFB, |
|
957 |
+- b('\x00')*self.block_size, # IV for CFB |
|
958 |
+- segment_size=self.block_size*8) |
|
959 |
+- |
|
960 |
+- # The cipher will be used for... |
|
961 |
+- if len(self.IV) == self.block_size: |
|
962 |
+- # ... encryption |
|
963 |
+- self._encrypted_IV = IV_cipher.encrypt( |
|
964 |
+- self.IV + self.IV[-2:] + # Plaintext |
|
965 |
+- b('\x00')*(self.block_size-2) # Padding |
|
966 |
+- )[:self.block_size+2] |
|
967 |
+- elif len(self.IV) == self.block_size+2: |
|
968 |
+- # ... decryption |
|
969 |
+- self._encrypted_IV = self.IV |
|
970 |
+- self.IV = IV_cipher.decrypt(self.IV + # Ciphertext |
|
971 |
+- b('\x00')*(self.block_size-2) # Padding |
|
972 |
+- )[:self.block_size+2] |
|
973 |
+- if self.IV[-2:] != self.IV[-4:-2]: |
|
974 |
+- raise ValueError("Failed integrity check for OPENPGP IV") |
|
975 |
+- self.IV = self.IV[:-2] |
|
976 |
++ raise ValueError("Length of IV must be %d or %d bytes for MODE_OPENPGP" |
|
977 |
++ % (self.block_size, self.block_size+2)) |
|
978 |
++ |
|
979 |
++ # Instantiate the cipher for the real PGP data |
|
980 |
++ self._cipher = factory.new( |
|
981 |
++ key, |
|
982 |
++ MODE_CFB, |
|
983 |
++ self._encrypted_IV[-self.block_size:], |
|
984 |
++ segment_size=self.block_size * 8 |
|
985 |
++ ) |
|
986 |
++ |
|
987 |
++ def _start_ccm(self, assoc_len=None, msg_len=None): |
|
988 |
++ # CCM mode. This method creates the 2 ciphers used for the MAC |
|
989 |
++ # (self._cipherCBC) and for the encryption/decryption (self._cipher). |
|
990 |
++ # |
|
991 |
++ # Member _assoc_buffer may already contain user data that needs to be |
|
992 |
++ # authenticated. |
|
993 |
++ |
|
994 |
++ if self._cipherCBC: |
|
995 |
++ # Already started |
|
996 |
++ return |
|
997 |
++ if assoc_len is not None: |
|
998 |
++ self._assoc_len = assoc_len |
|
999 |
++ if msg_len is not None: |
|
1000 |
++ self._msg_len = msg_len |
|
1001 |
++ if None in (self._assoc_len, self._msg_len): |
|
1002 |
++ return |
|
1003 |
++ |
|
1004 |
++ # q is the length of Q, the encoding of the message length |
|
1005 |
++ q = 15 - len(self.nonce) |
|
1006 |
++ |
|
1007 |
++ ## Compute B_0 |
|
1008 |
++ flags = ( |
|
1009 |
++ 64 * (self._assoc_len > 0) + |
|
1010 |
++ 8 * divmod(self._mac_len - 2, 2)[0] + |
|
1011 |
++ (q - 1) |
|
1012 |
++ ) |
|
1013 |
++ b_0 = bchr(flags) + self.nonce + long_to_bytes(self._msg_len, q) |
|
1014 |
++ self._assoc_buffer.insert(0, b_0) |
|
1015 |
++ self._assoc_buffer_len += 16 |
|
1016 |
++ |
|
1017 |
++ # Start CBC MAC with zero IV |
|
1018 |
++ # Mind that self._assoc_buffer may already contain some data |
|
1019 |
++ self._cipherCBC = self._factory.new(self._key, MODE_CBC, bchr(0)*16) |
|
1020 |
++ assoc_len_encoded = b('') |
|
1021 |
++ if self._assoc_len > 0: |
|
1022 |
++ if self._assoc_len < (2 ** 16 - 2 ** 8): |
|
1023 |
++ enc_size = 2 |
|
1024 |
++ elif self._assoc_len < (2L ** 32): |
|
1025 |
++ assoc_len_encoded = b('\xFF\xFE') |
|
1026 |
++ enc_size = 4 |
|
1027 |
+ else: |
|
1028 |
+- raise ValueError("Length of IV must be %d or %d bytes for MODE_OPENPGP" |
|
1029 |
+- % (self.block_size, self.block_size+2)) |
|
1030 |
++ assoc_len_encoded = b('\xFF\xFF') |
|
1031 |
++ enc_size = 8 |
|
1032 |
++ assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size) |
|
1033 |
++ self._assoc_buffer.insert(1, assoc_len_encoded) |
|
1034 |
++ self._assoc_buffer_len += len(assoc_len_encoded) |
|
1035 |
++ |
|
1036 |
++ # Start CTR cipher |
|
1037 |
++ flags = q - 1 |
|
1038 |
++ prefix = bchr(flags) + self.nonce |
|
1039 |
++ ctr = Counter.new(128 - len(prefix) * 8, prefix, initial_value=0) |
|
1040 |
++ self._cipher = self._factory.new(self._key, MODE_CTR, counter=ctr) |
|
1041 |
++ # Will XOR against CBC MAC |
|
1042 |
++ self._s_0 = self._cipher.encrypt(bchr(0) * 16) |
|
1043 |
++ |
|
1044 |
++ def update(self, assoc_data): |
|
1045 |
++ """Protect associated data |
|
1046 |
++ |
|
1047 |
++ When using an AEAD mode like CCM, and if there is any associated data, |
|
1048 |
++ the caller has to invoke this function one or more times, before |
|
1049 |
++ using ``decrypt`` or ``encrypt``. |
|
1050 |
++ |
|
1051 |
++ By *associated data* it is meant any data (e.g. packet headers) that |
|
1052 |
++ will not be encrypted and will be transmitted in the clear. |
|
1053 |
++ However, the receiver is still able to detect any modification to it. |
|
1054 |
++ In CCM, the *associated data* is also called *additional authenticated |
|
1055 |
++ data*. |
|
1056 |
++ |
|
1057 |
++ If there is no associated data, this method must not be called. |
|
1058 |
++ |
|
1059 |
++ The caller may split associated data in segments of any size, and |
|
1060 |
++ invoke this method multiple times, each time with the next segment. |
|
1061 |
++ |
|
1062 |
++ :Parameters: |
|
1063 |
++ assoc_data : byte string |
|
1064 |
++ A piece of associated data. There are no restrictions on its size. |
|
1065 |
++ """ |
|
1066 |
+ |
|
1067 |
+- # Instantiate the cipher for the real PGP data |
|
1068 |
+- self._cipher = factory.new(key, MODE_CFB, |
|
1069 |
+- self._encrypted_IV[-self.block_size:], |
|
1070 |
+- segment_size=self.block_size*8) |
|
1071 |
++ if self.mode == MODE_CCM: |
|
1072 |
++ if self.update not in self._next: |
|
1073 |
++ raise TypeError("update() can only be called immediately after initialization") |
|
1074 |
++ self._next = [ self.update, self.encrypt, self.decrypt, |
|
1075 |
++ self.digest, self.verify ] |
|
1076 |
++ return self._update(assoc_data) |
|
1077 |
++ |
|
1078 |
++ def _update(self, assoc_data, do_zero_padding=False): |
|
1079 |
++ """Equivalent to update(), but without FSM checks.""" |
|
1080 |
++ |
|
1081 |
++ if self.mode == MODE_CCM: |
|
1082 |
++ self._assoc_buffer.append(assoc_data) |
|
1083 |
++ self._assoc_buffer_len += len(assoc_data) |
|
1084 |
++ |
|
1085 |
++ if not self._cipherCBC: |
|
1086 |
++ return |
|
1087 |
++ |
|
1088 |
++ if do_zero_padding and (self._assoc_buffer_len & 15): |
|
1089 |
++ npad = 16 - self._assoc_buffer_len & 15 |
|
1090 |
++ self._assoc_buffer.append(bchr(0) * npad) |
|
1091 |
++ self._assoc_buffer_len += npad |
|
1092 |
++ |
|
1093 |
++ # Feed data into CBC MAC |
|
1094 |
++ aligned_data = 16 * divmod(self._assoc_buffer_len, 16)[0] |
|
1095 |
++ if aligned_data > 0: |
|
1096 |
++ buf = b("").join(self._assoc_buffer) |
|
1097 |
++ self._t = self._cipherCBC.encrypt(buf[:aligned_data])[-16:] |
|
1098 |
++ self._assoc_buffer = [buf[aligned_data:]] |
|
1099 |
++ self._assoc_buffer_len -= aligned_data |
|
1100 |
++ return |
|
1101 |
++ raise ValueError("update() not supported by this mode of operation") |
|
1102 |
++ |
|
1103 |
+ |
|
1104 |
+ def encrypt(self, plaintext): |
|
1105 |
+ """Encrypt data with the key and the parameters set at initialization. |
|
1106 |
+@@ -208,7 +418,7 @@ class BlockAlgo: |
|
1107 |
+ - For `MODE_CFB`, *plaintext* length (in bytes) must be a multiple |
|
1108 |
+ of *segment_size*/8. |
|
1109 |
+ |
|
1110 |
+- - For `MODE_CTR`, *plaintext* can be of any length. |
|
1111 |
++ - For `MODE_CTR` and `MODE_CCM`, *plaintext* can be of any length. |
|
1112 |
+ |
|
1113 |
+ - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, |
|
1114 |
+ unless it is the last chunk of the message. |
|
1115 |
+@@ -241,6 +451,23 @@ class BlockAlgo: |
|
1116 |
+ self._done_first_block = True |
|
1117 |
+ return res |
|
1118 |
+ |
|
1119 |
++ if self.mode == MODE_CCM: |
|
1120 |
++ |
|
1121 |
++ if self.encrypt not in self._next: |
|
1122 |
++ raise TypeError("encrypt() can only be called after initialization or an update()") |
|
1123 |
++ self._next = [self.encrypt, self.digest] |
|
1124 |
++ |
|
1125 |
++ if self._assoc_len is None: |
|
1126 |
++ self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
1127 |
++ if self._msg_len is None: |
|
1128 |
++ self._start_ccm(msg_len=len(plaintext)) |
|
1129 |
++ self._next = [self.digest] |
|
1130 |
++ if not self._done_assoc_data: |
|
1131 |
++ self._update(b(""), do_zero_padding=True) |
|
1132 |
++ self._done_assoc_data = True |
|
1133 |
++ |
|
1134 |
++ self._update(plaintext) |
|
1135 |
++ |
|
1136 |
+ return self._cipher.encrypt(plaintext) |
|
1137 |
+ |
|
1138 |
+ def decrypt(self, ciphertext): |
|
1139 |
+@@ -267,7 +494,7 @@ class BlockAlgo: |
|
1140 |
+ - For `MODE_CFB`, *ciphertext* length (in bytes) must be a multiple |
|
1141 |
+ of *segment_size*/8. |
|
1142 |
+ |
|
1143 |
+- - For `MODE_CTR`, *ciphertext* can be of any length. |
|
1144 |
++ - For `MODE_CTR` and `MODE_CCM`, *ciphertext* can be of any length. |
|
1145 |
+ |
|
1146 |
+ - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, |
|
1147 |
+ unless it is the last chunk of the message. |
|
1148 |
+@@ -292,5 +519,116 @@ class BlockAlgo: |
|
1149 |
+ res = self._cipher.decrypt(ciphertext) |
|
1150 |
+ return res |
|
1151 |
+ |
|
1152 |
+- return self._cipher.decrypt(ciphertext) |
|
1153 |
++ if self.mode == MODE_CCM: |
|
1154 |
++ |
|
1155 |
++ if self.decrypt not in self._next: |
|
1156 |
++ raise TypeError("decrypt() can only be called after initialization or an update()") |
|
1157 |
++ self._next = [self.decrypt, self.verify] |
|
1158 |
++ |
|
1159 |
++ if self._assoc_len is None: |
|
1160 |
++ self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
1161 |
++ if self._msg_len is None: |
|
1162 |
++ self._start_ccm(msg_len=len(ciphertext)) |
|
1163 |
++ self._next = [self.verify] |
|
1164 |
++ if not self._done_assoc_data: |
|
1165 |
++ self._update(b(""), do_zero_padding=True) |
|
1166 |
++ self._done_assoc_data = True |
|
1167 |
++ |
|
1168 |
++ pt = self._cipher.decrypt(ciphertext) |
|
1169 |
++ |
|
1170 |
++ if self.mode == MODE_CCM: |
|
1171 |
++ self._update(pt) |
|
1172 |
++ |
|
1173 |
++ return pt |
|
1174 |
++ |
|
1175 |
++ def digest(self): |
|
1176 |
++ """Compute the *binary* MAC tag in an AEAD mode. |
|
1177 |
++ |
|
1178 |
++ When using an AEAD mode like CCM, the caller invokes this function |
|
1179 |
++ at the very end. |
|
1180 |
++ |
|
1181 |
++ This method returns the MAC that shall be sent to the receiver, |
|
1182 |
++ together with the ciphertext. |
|
1183 |
++ |
|
1184 |
++ :Return: the MAC, as a byte string. |
|
1185 |
++ """ |
|
1186 |
+ |
|
1187 |
++ if self.mode == MODE_CCM: |
|
1188 |
++ |
|
1189 |
++ if self.digest not in self._next: |
|
1190 |
++ raise TypeError("digest() cannot be called when decrypting or validating a message") |
|
1191 |
++ self._next = [self.digest] |
|
1192 |
++ |
|
1193 |
++ if self._assoc_len is None: |
|
1194 |
++ self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
1195 |
++ if self._msg_len is None: |
|
1196 |
++ self._start_ccm(msg_len=0) |
|
1197 |
++ self._update(b(""), do_zero_padding=True) |
|
1198 |
++ |
|
1199 |
++ return strxor(self._t, self._s_0)[:self._mac_len] |
|
1200 |
++ |
|
1201 |
++ raise TypeError("digest() not supported by this mode of operation") |
|
1202 |
++ |
|
1203 |
++ def hexdigest(self): |
|
1204 |
++ """Compute the *printable* MAC tag in an AEAD mode. |
|
1205 |
++ |
|
1206 |
++ This method is like `digest`. |
|
1207 |
++ |
|
1208 |
++ :Return: the MAC, as a hexadecimal string. |
|
1209 |
++ """ |
|
1210 |
++ return "".join(["%02x" % bord(x) for x in self.digest()]) |
|
1211 |
++ |
|
1212 |
++ def verify(self, mac_tag): |
|
1213 |
++ """Validate the *binary* MAC tag in an AEAD mode. |
|
1214 |
++ |
|
1215 |
++ When using an AEAD mode like CCM, the caller invokes this function |
|
1216 |
++ at the very end. |
|
1217 |
++ |
|
1218 |
++ This method checks if the decrypted message is indeed valid |
|
1219 |
++ (that is, if the key is correct) and it has not been |
|
1220 |
++ tampered with while in transit. |
|
1221 |
++ |
|
1222 |
++ :Parameters: |
|
1223 |
++ mac_tag : byte string |
|
1224 |
++ This is the *binary* MAC, as received from the sender. |
|
1225 |
++ :Raises ValueError: |
|
1226 |
++ if the MAC does not match. The message has been tampered with |
|
1227 |
++ or the key is incorrect. |
|
1228 |
++ """ |
|
1229 |
++ |
|
1230 |
++ if self.mode == MODE_CCM: |
|
1231 |
++ if self.verify not in self._next: |
|
1232 |
++ raise TypeError("verify() cannot be called when encrypting a message") |
|
1233 |
++ self._next = [self.verify] |
|
1234 |
++ |
|
1235 |
++ if self._assoc_len is None: |
|
1236 |
++ self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
1237 |
++ if self._msg_len is None: |
|
1238 |
++ self._start_ccm(msg_len=0) |
|
1239 |
++ self._update(b(""), do_zero_padding=True) |
|
1240 |
++ u = strxor(self._t, self._s_0)[:self._mac_len] |
|
1241 |
++ |
|
1242 |
++ res = 0 |
|
1243 |
++ # Constant-time comparison |
|
1244 |
++ for x,y in zip(u, mac_tag): |
|
1245 |
++ res |= bord(x) ^ bord(y) |
|
1246 |
++ if res or len(mac_tag)!=self._mac_len: |
|
1247 |
++ raise ValueError("MAC check failed") |
|
1248 |
++ return |
|
1249 |
++ |
|
1250 |
++ raise TypeError("verify() not supported by this mode of operation") |
|
1251 |
++ |
|
1252 |
++ def hexverify(self, hex_mac_tag): |
|
1253 |
++ """Validate the *printable* MAC tag in an AEAD mode. |
|
1254 |
++ |
|
1255 |
++ This method is like `verify`. |
|
1256 |
++ |
|
1257 |
++ :Parameters: |
|
1258 |
++ hex_mac_tag : string |
|
1259 |
++ This is the *printable* MAC, as received from the sender. |
|
1260 |
++ :Raises ValueError: |
|
1261 |
++ if the MAC does not match. The message has been tampered with |
|
1262 |
++ or the key is incorrect. |
|
1263 |
++ """ |
|
1264 |
++ |
|
1265 |
++ self.verify(unhexlify(hex_mac_tag)) |
0 | 1266 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,715 @@ |
0 |
+From 8bdbdb8168511018d44ef014ae21da619ae73c24 Mon Sep 17 00:00:00 2001 |
|
1 |
+From: Legrandin <helderijs@gmail.com> |
|
2 |
+Date: Mon, 20 May 2013 12:43:44 +0200 |
|
3 |
+Subject: [PATCH] Add EAX authenticated encryption mode |
|
4 |
+ |
|
5 |
+[dlitz@dlitz.net: Included changes from the following commits from the author's pull request:] |
|
6 |
+- [9c13f9c] Rename 'IV' parameter to 'nonce' for AEAD modes. |
|
7 |
+- [ca460a7] Made blockalgo.py more PEP-8 compliant; The second parameter |
|
8 |
+ of the _GHASH constructor is now the length of the block |
|
9 |
+ (block_size) and not the full module. |
|
10 |
+[dlitz@dlitz.net: Fixed unresolved conflict in lib/Crypto/Cipher/blockalgo.py] |
|
11 |
+ |
|
12 |
+ |
|
13 |
+--- a/lib/Crypto/Cipher/AES.py_org 2019-05-20 18:32:03.837094052 +0530 |
|
14 |
+@@ -113,14 +113,17 @@ def new(key, *args, **kwargs): |
|
15 |
+ |
|
16 |
+ For all other modes, it must be 16 bytes long. |
|
17 |
+ nonce : byte string |
|
18 |
+- (*Only* `MODE_CCM`). |
|
19 |
++ (*Only* `MODE_CCM`, `MODE_EAX`). |
|
20 |
+ |
|
21 |
+ A mandatory value that must never be reused for any other encryption. |
|
22 |
+ |
|
23 |
+ For `MODE_CCM`, its length must be in the range ``[7..13]``. |
|
24 |
+ 11 or 12 bytes are reasonable values in general. Bear in |
|
25 |
+ mind that with CCM there is a trade-off between nonce length and |
|
26 |
+- maximum message size. |
|
27 |
++ maximum message size. |
|
28 |
++ For the other modes, there are no restrictions on its length, |
|
29 |
++ but it is recommended to use at least 16 bytes. |
|
30 |
++ |
|
31 |
+ counter : callable |
|
32 |
+ (*Only* `MODE_CTR`). A stateful function that returns the next |
|
33 |
+ *counter block*, which is a byte string of `block_size` bytes. |
|
34 |
+@@ -129,6 +132,9 @@ def new(key, *args, **kwargs): |
|
35 |
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext |
|
36 |
+ are segmented in. |
|
37 |
+ It must be a multiple of 8. If 0 or not specified, it will be assumed to be 8. |
|
38 |
++ (*Only* `MODE_EAX`). Length of the MAC, in bytes. It must be no |
|
39 |
++ larger than 16 bytes (which is the default). |
|
40 |
++ |
|
41 |
+ mac_len : integer |
|
42 |
+ (*Only* `MODE_CCM`). Length of the MAC, in bytes. It must be even and in |
|
43 |
+ the range ``[4..16]``. The default is 16. |
|
44 |
+@@ -158,6 +164,8 @@ MODE_CTR = 6 |
|
45 |
+ MODE_OPENPGP = 7 |
|
46 |
+ #: Counter with CBC-MAC (CCM) Mode. See `blockalgo.MODE_CCM`. |
|
47 |
+ MODE_CCM = 8 |
|
48 |
++#: EAX Mode. See `blockalgo.MODE_EAX`. |
|
49 |
++MODE_EAX = 9 |
|
50 |
+ #: Size of a data block (in bytes) |
|
51 |
+ block_size = 16 |
|
52 |
+ #: Size of a key (in bytes) |
|
53 |
+--- a/lib/Crypto/Cipher/ARC2.py_org 2019-05-20 18:38:03.249101231 +0530 |
|
54 |
+@@ -82,6 +82,8 @@ def new(key, *args, **kwargs): |
|
55 |
+ The chaining mode to use for encryption or decryption. |
|
56 |
+ Default is `MODE_ECB`. |
|
57 |
+ IV : byte string |
|
58 |
++ *Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). |
|
59 |
++ |
|
60 |
+ The initialization vector to use for encryption or decryption. |
|
61 |
+ |
|
62 |
+ It is ignored for `MODE_ECB` and `MODE_CTR`. |
|
63 |
+@@ -91,12 +93,20 @@ def new(key, *args, **kwargs): |
|
64 |
+ actually the *encrypted* IV which was prefixed to the ciphertext). |
|
65 |
+ It is mandatory. |
|
66 |
+ |
|
67 |
+- For all other modes, it must be `block_size` bytes longs. It is optional and |
|
68 |
+- when not present it will be given a default value of all zeroes. |
|
69 |
++ For all other modes, it must be 8 bytes long. |
|
70 |
++ nonce : byte string |
|
71 |
++ (*Only* `MODE_EAX`). |
|
72 |
++ A mandatory value that must never be reused for any other encryption. |
|
73 |
++ There are no restrictions on its length, but it is recommended to |
|
74 |
++ use at least 16 bytes. |
|
75 |
++ |
|
76 |
+ counter : callable |
|
77 |
+ (*Only* `MODE_CTR`). A stateful function that returns the next |
|
78 |
+ *counter block*, which is a byte string of `block_size` bytes. |
|
79 |
+ For better performance, use `Crypto.Util.Counter`. |
|
80 |
++ mac_len : integer |
|
81 |
++ (*Only* `MODE_EAX`). Length of the MAC, in bytes. |
|
82 |
++ It must be no larger than 8 (which is the default). |
|
83 |
+ segment_size : integer |
|
84 |
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext |
|
85 |
+ are segmented in. |
|
86 |
+@@ -123,6 +133,8 @@ MODE_OFB = 5 |
|
87 |
+ MODE_CTR = 6 |
|
88 |
+ #: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. |
|
89 |
+ MODE_OPENPGP = 7 |
|
90 |
++#: EAX Mode. See `blockalgo.MODE_EAX`. |
|
91 |
++MODE_EAX = 9 |
|
92 |
+ #: Size of a data block (in bytes) |
|
93 |
+ block_size = 8 |
|
94 |
+ #: Size of a key (in bytes) |
|
95 |
+--- a/lib/Crypto/Cipher/Blowfish.py_org 2019-05-20 18:41:32.689105415 +0530 |
|
96 |
+@@ -76,6 +76,8 @@ def new(key, *args, **kwargs): |
|
97 |
+ The chaining mode to use for encryption or decryption. |
|
98 |
+ Default is `MODE_ECB`. |
|
99 |
+ IV : byte string |
|
100 |
++ (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). |
|
101 |
++ |
|
102 |
+ The initialization vector to use for encryption or decryption. |
|
103 |
+ |
|
104 |
+ It is ignored for `MODE_ECB` and `MODE_CTR`. |
|
105 |
+@@ -85,12 +87,21 @@ def new(key, *args, **kwargs): |
|
106 |
+ actually the *encrypted* IV which was prefixed to the ciphertext). |
|
107 |
+ It is mandatory. |
|
108 |
+ |
|
109 |
+- For all other modes, it must be `block_size` bytes longs. It is optional and |
|
110 |
+- when not present it will be given a default value of all zeroes. |
|
111 |
++ For all other modes, it must be 8 bytes long. |
|
112 |
++ nonce : byte string |
|
113 |
++ (*Only* `MODE_EAX`). |
|
114 |
++ A mandatory value that must never be reused for any other encryption. |
|
115 |
++ There are no restrictions on its length, but it is recommended to |
|
116 |
++ use at least 16 bytes. |
|
117 |
++ |
|
118 |
+ counter : callable |
|
119 |
+ (*Only* `MODE_CTR`). A stateful function that returns the next |
|
120 |
+ *counter block*, which is a byte string of `block_size` bytes. |
|
121 |
+ For better performance, use `Crypto.Util.Counter`. |
|
122 |
++ mac_len : integer |
|
123 |
++ (*Only* `MODE_EAX`). Length of the MAC, in bytes. |
|
124 |
++ It must be no larger than 8 (which is the default). |
|
125 |
++ |
|
126 |
+ segment_size : integer |
|
127 |
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext |
|
128 |
+ are segmented in. |
|
129 |
+@@ -114,6 +125,8 @@ MODE_OFB = 5 |
|
130 |
+ MODE_CTR = 6 |
|
131 |
+ #: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. |
|
132 |
+ MODE_OPENPGP = 7 |
|
133 |
++#: EAX Mode. See `blockalgo.MODE_EAX`. |
|
134 |
++MODE_EAX = 9 |
|
135 |
+ #: Size of a data block (in bytes) |
|
136 |
+ block_size = 8 |
|
137 |
+ #: Size of a key (in bytes) |
|
138 |
+--- a/lib/Crypto/Cipher/CAST.py_org 2019-05-20 18:44:27.617108909 +0530 |
|
139 |
+@@ -79,6 +79,7 @@ def new(key, *args, **kwargs): |
|
140 |
+ The chaining mode to use for encryption or decryption. |
|
141 |
+ Default is `MODE_ECB`. |
|
142 |
+ IV : byte string |
|
143 |
++ (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). |
|
144 |
+ The initialization vector to use for encryption or decryption. |
|
145 |
+ |
|
146 |
+ It is ignored for `MODE_ECB` and `MODE_CTR`. |
|
147 |
+@@ -88,12 +89,20 @@ def new(key, *args, **kwargs): |
|
148 |
+ actually the *encrypted* IV which was prefixed to the ciphertext). |
|
149 |
+ It is mandatory. |
|
150 |
+ |
|
151 |
+- For all other modes, it must be `block_size` bytes longs. It is optional and |
|
152 |
+- when not present it will be given a default value of all zeroes. |
|
153 |
++ For all other modes, it must be 8 bytes long. |
|
154 |
++ nonce : byte string |
|
155 |
++ (*Only* `MODE_EAX`). |
|
156 |
++ A mandatory value that must never be reused for any other encryption. |
|
157 |
++ There are no restrictions on its length, but it is recommended to |
|
158 |
++ use at least 16 bytes. |
|
159 |
+ counter : callable |
|
160 |
+ (*Only* `MODE_CTR`). A stateful function that returns the next |
|
161 |
+ *counter block*, which is a byte string of `block_size` bytes. |
|
162 |
+ For better performance, use `Crypto.Util.Counter`. |
|
163 |
++ mac_len : integer |
|
164 |
++ (*Only* `MODE_EAX`). Length of the MAC, in bytes. |
|
165 |
++ It must be no larger than 8 (which is the default). |
|
166 |
++ |
|
167 |
+ segment_size : integer |
|
168 |
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext |
|
169 |
+ are segmented in. |
|
170 |
+@@ -117,6 +126,8 @@ MODE_OFB = 5 |
|
171 |
+ MODE_CTR = 6 |
|
172 |
+ #: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. |
|
173 |
+ MODE_OPENPGP = 7 |
|
174 |
++#: EAX Mode. See `blockalgo.MODE_EAX`. |
|
175 |
++MODE_EAX = 9 |
|
176 |
+ #: Size of a data block (in bytes) |
|
177 |
+ block_size = 8 |
|
178 |
+ #: Size of a key (in bytes) |
|
179 |
+--- a/lib/Crypto/Cipher/DES.py_org 2019-05-20 18:46:52.333111800 +0530 |
|
180 |
+@@ -74,6 +74,7 @@ def new(key, *args, **kwargs): |
|
181 |
+ The chaining mode to use for encryption or decryption. |
|
182 |
+ Default is `MODE_ECB`. |
|
183 |
+ IV : byte string |
|
184 |
++ (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). |
|
185 |
+ The initialization vector to use for encryption or decryption. |
|
186 |
+ |
|
187 |
+ It is ignored for `MODE_ECB` and `MODE_CTR`. |
|
188 |
+@@ -83,12 +84,19 @@ def new(key, *args, **kwargs): |
|
189 |
+ actually the *encrypted* IV which was prefixed to the ciphertext). |
|
190 |
+ It is mandatory. |
|
191 |
+ |
|
192 |
+- For all other modes, it must be `block_size` bytes longs. It is optional and |
|
193 |
+- when not present it will be given a default value of all zeroes. |
|
194 |
++ For all other modes, it must be 8 bytes long. |
|
195 |
++ nonce : byte string |
|
196 |
++ (*Only* `MODE_EAX`). |
|
197 |
++ A mandatory value that must never be reused for any other encryption. |
|
198 |
++ There are no restrictions on its length, but it is recommended to |
|
199 |
++ use at least 16 bytes. |
|
200 |
+ counter : callable |
|
201 |
+ (*Only* `MODE_CTR`). A stateful function that returns the next |
|
202 |
+ *counter block*, which is a byte string of `block_size` bytes. |
|
203 |
+ For better performance, use `Crypto.Util.Counter`. |
|
204 |
++ mac_len : integer |
|
205 |
++ (*Only* `MODE_EAX`). Length of the MAC, in bytes. |
|
206 |
++ It must be no larger than 8 (which is the default). |
|
207 |
+ segment_size : integer |
|
208 |
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext |
|
209 |
+ are segmented in. |
|
210 |
+@@ -112,6 +120,8 @@ MODE_OFB = 5 |
|
211 |
+ MODE_CTR = 6 |
|
212 |
+ #: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. |
|
213 |
+ MODE_OPENPGP = 7 |
|
214 |
++#: EAX Mode. See `blockalgo.MODE_EAX`. |
|
215 |
++MODE_EAX = 9 |
|
216 |
+ #: Size of a data block (in bytes) |
|
217 |
+ block_size = 8 |
|
218 |
+ #: Size of a key (in bytes) |
|
219 |
+--- a/lib/Crypto/Cipher/DES3.py_org 2019-05-20 18:49:14.581114641 +0530 |
|
220 |
+@@ -87,6 +87,7 @@ def new(key, *args, **kwargs): |
|
221 |
+ The chaining mode to use for encryption or decryption. |
|
222 |
+ Default is `MODE_ECB`. |
|
223 |
+ IV : byte string |
|
224 |
++ (*Only* `MODE_CBC`, `MODE_CFB`, `MODE_OFB`, `MODE_OPENPGP`). |
|
225 |
+ The initialization vector to use for encryption or decryption. |
|
226 |
+ |
|
227 |
+ It is ignored for `MODE_ECB` and `MODE_CTR`. |
|
228 |
+@@ -96,12 +97,19 @@ def new(key, *args, **kwargs): |
|
229 |
+ actually the *encrypted* IV which was prefixed to the ciphertext). |
|
230 |
+ It is mandatory. |
|
231 |
+ |
|
232 |
+- For all other modes, it must be `block_size` bytes longs. It is optional and |
|
233 |
+- when not present it will be given a default value of all zeroes. |
|
234 |
++ For all other modes, it must be 8 bytes long. |
|
235 |
++ nonce : byte string |
|
236 |
++ (*Only* `MODE_EAX`). |
|
237 |
++ A mandatory value that must never be reused for any other encryption. |
|
238 |
++ There are no restrictions on its length, but it is recommended to |
|
239 |
++ use at least 16 bytes. |
|
240 |
+ counter : callable |
|
241 |
+ (*Only* `MODE_CTR`). A stateful function that returns the next |
|
242 |
+- *counter block*, which is a byte string of `block_size` bytes. |
|
243 |
++ *counter block*, which is a byte string of 8 bytes. |
|
244 |
+ For better performance, use `Crypto.Util.Counter`. |
|
245 |
++ mac_len : integer |
|
246 |
++ (*Only* `MODE_EAX`). Length of the MAC, in bytes. |
|
247 |
++ It must be no larger than 8 (which is the default). |
|
248 |
+ segment_size : integer |
|
249 |
+ (*Only* `MODE_CFB`).The number of bits the plaintext and ciphertext |
|
250 |
+ are segmented in. |
|
251 |
+@@ -127,6 +135,8 @@ MODE_OFB = 5 |
|
252 |
+ MODE_CTR = 6 |
|
253 |
+ #: OpenPGP Mode. See `blockalgo.MODE_OPENPGP`. |
|
254 |
+ MODE_OPENPGP = 7 |
|
255 |
++#: EAX Mode. See `blockalgo.MODE_EAX`. |
|
256 |
++MODE_EAX = 9 |
|
257 |
+ #: Size of a data block (in bytes) |
|
258 |
+ block_size = 8 |
|
259 |
+ #: Size of a key (in bytes) |
|
260 |
+--- a/lib/Crypto/Cipher/blockalgo.py_org 2019-05-20 18:51:54.965117845 +0530 |
|
261 |
+@@ -29,7 +29,9 @@ from binascii import unhexlify |
|
262 |
+ |
|
263 |
+ from Crypto.Util import Counter |
|
264 |
+ from Crypto.Util.strxor import strxor |
|
265 |
+-from Crypto.Util.number import long_to_bytes |
|
266 |
++from Crypto.Util.number import long_to_bytes, bytes_to_long |
|
267 |
++import Crypto.Util.Counter |
|
268 |
++from Crypto.Hash import CMAC |
|
269 |
+ |
|
270 |
+ #: *Electronic Code Book (ECB)*. |
|
271 |
+ #: This is the simplest encryption mode. Each of the plaintext blocks |
|
272 |
+@@ -179,6 +181,32 @@ MODE_OPENPGP = 7 |
|
273 |
+ #: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html |
|
274 |
+ MODE_CCM = 8 |
|
275 |
+ |
|
276 |
++#: *EAX*. This is an Authenticated Encryption with Associated Data |
|
277 |
++#: (`AEAD`_) mode. It provides both confidentiality and authenticity. |
|
278 |
++#: |
|
279 |
++#: The header of the message may be left in the clear, if needed, and it will |
|
280 |
++#: still be subject to authentication. |
|
281 |
++#: |
|
282 |
++#: The decryption step tells the receiver if the message comes from a source |
|
283 |
++#: that really knowns the secret key. |
|
284 |
++#: Additionally, decryption detects if any part of the message - including the |
|
285 |
++#: header - has been modified or corrupted. |
|
286 |
++#: |
|
287 |
++#: This mode requires a nonce. The nonce shall never repeat for two |
|
288 |
++#: different messages encrypted with the same key, but it does not need to |
|
289 |
++#: be random. |
|
290 |
++# |
|
291 |
++#: This mode is only available for ciphers that operate on 64 or |
|
292 |
++#: 128 bits blocks. |
|
293 |
++#: |
|
294 |
++#: There are no official standards defining EAX. The implementation is based on |
|
295 |
++#: `a proposal`__ that was presented to NIST. |
|
296 |
++#: |
|
297 |
++#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html |
|
298 |
++#: .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf |
|
299 |
++MODE_EAX = 9 |
|
300 |
++ |
|
301 |
++ |
|
302 |
+ |
|
303 |
+ def _getParameter(name, index, args, kwargs, default=None): |
|
304 |
+ """Find a parameter in tuple and dictionary arguments a function receives""" |
|
305 |
+@@ -229,10 +257,44 @@ class BlockAlgo: |
|
306 |
+ |
|
307 |
+ elif self.mode == MODE_OPENPGP: |
|
308 |
+ self._start_PGP(factory, key, *args, **kwargs) |
|
309 |
++ elif self.mode == MODE_EAX: |
|
310 |
++ self._start_eax(factory, key, *args, **kwargs) |
|
311 |
+ else: |
|
312 |
+ self._cipher = factory.new(key, *args, **kwargs) |
|
313 |
+ self.IV = self._cipher.IV |
|
314 |
+ |
|
315 |
++ def _start_eax(self, factory, key, *args, **kwargs): |
|
316 |
++ |
|
317 |
++ self.nonce = _getParameter('nonce', 1, args, kwargs) |
|
318 |
++ if not self.nonce: |
|
319 |
++ raise ValueError("MODE_EAX requires a nonce") |
|
320 |
++ |
|
321 |
++ # Allowed transitions after initialization |
|
322 |
++ self._next = [self.update, self.encrypt, self.decrypt, |
|
323 |
++ self.digest, self.verify] |
|
324 |
++ |
|
325 |
++ self._mac_len = kwargs.get('mac_len', self.block_size) |
|
326 |
++ if not (self._mac_len and 4 <= self._mac_len <= self.block_size): |
|
327 |
++ raise ValueError("Parameter 'mac_len' must not be larger than %d" |
|
328 |
++ % self.block_size) |
|
329 |
++ |
|
330 |
++ self._omac = [ |
|
331 |
++ CMAC.new(key, bchr(0) * (self.block_size - 1) + bchr(i), |
|
332 |
++ ciphermod=factory) |
|
333 |
++ for i in xrange(0, 3) |
|
334 |
++ ] |
|
335 |
++ |
|
336 |
++ # Compute MAC of nonce |
|
337 |
++ self._omac[0].update(self.nonce) |
|
338 |
++ |
|
339 |
++ # MAC of the nonce is also the initial counter for CTR encryption |
|
340 |
++ counter_int = bytes_to_long(self._omac[0].digest()) |
|
341 |
++ counter_obj = Crypto.Util.Counter.new( |
|
342 |
++ self.block_size * 8, |
|
343 |
++ initial_value=counter_int, |
|
344 |
++ allow_wraparound=True) |
|
345 |
++ self._cipher = factory.new(key, MODE_CTR, counter=counter_obj) |
|
346 |
++ |
|
347 |
+ def _start_PGP(self, factory, key, *args, **kwargs): |
|
348 |
+ # OPENPGP mode. For details, see 13.9 in RCC4880. |
|
349 |
+ # |
|
350 |
+@@ -341,7 +403,7 @@ class BlockAlgo: |
|
351 |
+ def update(self, assoc_data): |
|
352 |
+ """Protect associated data |
|
353 |
+ |
|
354 |
+- When using an AEAD mode like CCM, and if there is any associated data, |
|
355 |
++ When using an AEAD mode like CCM or EAX, and if there is any associated data, |
|
356 |
+ the caller has to invoke this function one or more times, before |
|
357 |
+ using ``decrypt`` or ``encrypt``. |
|
358 |
+ |
|
359 |
+@@ -349,7 +411,7 @@ class BlockAlgo: |
|
360 |
+ will not be encrypted and will be transmitted in the clear. |
|
361 |
+ However, the receiver is still able to detect any modification to it. |
|
362 |
+ In CCM, the *associated data* is also called *additional authenticated |
|
363 |
+- data*. |
|
364 |
++ data*. In EAX, the *associated data* is called *header*. |
|
365 |
+ |
|
366 |
+ If there is no associated data, this method must not be called. |
|
367 |
+ |
|
368 |
+@@ -361,11 +423,11 @@ class BlockAlgo: |
|
369 |
+ A piece of associated data. There are no restrictions on its size. |
|
370 |
+ """ |
|
371 |
+ |
|
372 |
+- if self.mode == MODE_CCM: |
|
373 |
++ if self.mode in (MODE_CCM, MODE_EAX): |
|
374 |
+ if self.update not in self._next: |
|
375 |
+ raise TypeError("update() can only be called immediately after initialization") |
|
376 |
+- self._next = [ self.update, self.encrypt, self.decrypt, |
|
377 |
+- self.digest, self.verify ] |
|
378 |
++ self._next = [self.update, self.encrypt, self.decrypt, |
|
379 |
++ self.digest, self.verify] |
|
380 |
+ return self._update(assoc_data) |
|
381 |
+ |
|
382 |
+ def _update(self, assoc_data, do_zero_padding=False): |
|
383 |
+@@ -391,6 +453,10 @@ class BlockAlgo: |
|
384 |
+ self._assoc_buffer = [buf[aligned_data:]] |
|
385 |
+ self._assoc_buffer_len -= aligned_data |
|
386 |
+ return |
|
387 |
++ if self.mode == MODE_EAX: |
|
388 |
++ self._omac[1].update(assoc_data) |
|
389 |
++ return |
|
390 |
++ |
|
391 |
+ raise ValueError("update() not supported by this mode of operation") |
|
392 |
+ |
|
393 |
+ |
|
394 |
+@@ -418,7 +484,7 @@ class BlockAlgo: |
|
395 |
+ - For `MODE_CFB`, *plaintext* length (in bytes) must be a multiple |
|
396 |
+ of *segment_size*/8. |
|
397 |
+ |
|
398 |
+- - For `MODE_CTR` and `MODE_CCM`, *plaintext* can be of any length. |
|
399 |
++ - For `MODE_CTR` and `MODE_CCM` and `MODE_EAX`, *plaintext* can be of any length. |
|
400 |
+ |
|
401 |
+ - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, |
|
402 |
+ unless it is the last chunk of the message. |
|
403 |
+@@ -451,12 +517,12 @@ class BlockAlgo: |
|
404 |
+ self._done_first_block = True |
|
405 |
+ return res |
|
406 |
+ |
|
407 |
+- if self.mode == MODE_CCM: |
|
408 |
++ if self.mode in (MODE_CCM, MODE_EAX): |
|
409 |
+ |
|
410 |
+ if self.encrypt not in self._next: |
|
411 |
+ raise TypeError("encrypt() can only be called after initialization or an update()") |
|
412 |
+ self._next = [self.encrypt, self.digest] |
|
413 |
+- |
|
414 |
++ if self.mode == MODE_CCM: |
|
415 |
+ if self._assoc_len is None: |
|
416 |
+ self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
417 |
+ if self._msg_len is None: |
|
418 |
+@@ -468,7 +534,12 @@ class BlockAlgo: |
|
419 |
+ |
|
420 |
+ self._update(plaintext) |
|
421 |
+ |
|
422 |
+- return self._cipher.encrypt(plaintext) |
|
423 |
++ ct = self._cipher.encrypt(plaintext) |
|
424 |
++ |
|
425 |
++ if self.mode == MODE_EAX: |
|
426 |
++ self._omac[2].update(ct) |
|
427 |
++ |
|
428 |
++ return ct |
|
429 |
+ |
|
430 |
+ def decrypt(self, ciphertext): |
|
431 |
+ """Decrypt data with the key and the parameters set at initialization. |
|
432 |
+@@ -494,7 +565,7 @@ class BlockAlgo: |
|
433 |
+ - For `MODE_CFB`, *ciphertext* length (in bytes) must be a multiple |
|
434 |
+ of *segment_size*/8. |
|
435 |
+ |
|
436 |
+- - For `MODE_CTR` and `MODE_CCM`, *ciphertext* can be of any length. |
|
437 |
++ - For `MODE_CTR` and `MODE_CCM` and `MODE_EAX`, *ciphertext* can be of any length. |
|
438 |
+ |
|
439 |
+ - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, |
|
440 |
+ unless it is the last chunk of the message. |
|
441 |
+@@ -519,21 +590,24 @@ class BlockAlgo: |
|
442 |
+ res = self._cipher.decrypt(ciphertext) |
|
443 |
+ return res |
|
444 |
+ |
|
445 |
+- if self.mode == MODE_CCM: |
|
446 |
++ if self.mode in (MODE_CCM, MODE_EAX): |
|
447 |
+ |
|
448 |
+ if self.decrypt not in self._next: |
|
449 |
+ raise TypeError("decrypt() can only be called after initialization or an update()") |
|
450 |
+ self._next = [self.decrypt, self.verify] |
|
451 |
+ |
|
452 |
+- if self._assoc_len is None: |
|
453 |
+- self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
454 |
+- if self._msg_len is None: |
|
455 |
+- self._start_ccm(msg_len=len(ciphertext)) |
|
456 |
+- self._next = [self.verify] |
|
457 |
+- if not self._done_assoc_data: |
|
458 |
+- self._update(b(""), do_zero_padding=True) |
|
459 |
+- self._done_assoc_data = True |
|
460 |
++ if self.mode == MODE_CCM: |
|
461 |
++ if self._assoc_len is None: |
|
462 |
++ self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
463 |
++ if self._msg_len is None: |
|
464 |
++ self._start_ccm(msg_len=len(ciphertext)) |
|
465 |
++ self._next = [self.verify] |
|
466 |
++ if not self._done_assoc_data: |
|
467 |
++ self._update(b(""), do_zero_padding=True) |
|
468 |
++ self._done_assoc_data = True |
|
469 |
+ |
|
470 |
++ if self.mode == MODE_EAX: |
|
471 |
++ self._omac[2].update(ciphertext) |
|
472 |
+ pt = self._cipher.decrypt(ciphertext) |
|
473 |
+ |
|
474 |
+ if self.mode == MODE_CCM: |
|
475 |
+@@ -544,7 +618,7 @@ class BlockAlgo: |
|
476 |
+ def digest(self): |
|
477 |
+ """Compute the *binary* MAC tag in an AEAD mode. |
|
478 |
+ |
|
479 |
+- When using an AEAD mode like CCM, the caller invokes this function |
|
480 |
++ When using an AEAD mode like CCM or EAX, the caller invokes this function |
|
481 |
+ at the very end. |
|
482 |
+ |
|
483 |
+ This method returns the MAC that shall be sent to the receiver, |
|
484 |
+@@ -553,19 +627,28 @@ class BlockAlgo: |
|
485 |
+ :Return: the MAC, as a byte string. |
|
486 |
+ """ |
|
487 |
+ |
|
488 |
+- if self.mode == MODE_CCM: |
|
489 |
++ if self.mode in (MODE_CCM, MODE_EAX): |
|
490 |
+ |
|
491 |
+ if self.digest not in self._next: |
|
492 |
+ raise TypeError("digest() cannot be called when decrypting or validating a message") |
|
493 |
+ self._next = [self.digest] |
|
494 |
+ |
|
495 |
+- if self._assoc_len is None: |
|
496 |
+- self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
497 |
+- if self._msg_len is None: |
|
498 |
+- self._start_ccm(msg_len=0) |
|
499 |
+- self._update(b(""), do_zero_padding=True) |
|
500 |
++ if self.mode == MODE_CCM: |
|
501 |
+ |
|
502 |
+- return strxor(self._t, self._s_0)[:self._mac_len] |
|
503 |
++ if self._assoc_len is None: |
|
504 |
++ self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
505 |
++ if self._msg_len is None: |
|
506 |
++ self._start_ccm(msg_len=0) |
|
507 |
++ self._update(b(""), do_zero_padding=True) |
|
508 |
++ tag = strxor(self._t, self._s_0)[:self._mac_len] |
|
509 |
++ |
|
510 |
++ if self.mode == MODE_EAX: |
|
511 |
++ |
|
512 |
++ tag = bchr(0) * self.block_size |
|
513 |
++ for i in xrange(3): |
|
514 |
++ tag = strxor(tag, self._omac[i].digest()) |
|
515 |
++ |
|
516 |
++ return tag |
|
517 |
+ |
|
518 |
+ raise TypeError("digest() not supported by this mode of operation") |
|
519 |
+ |
|
520 |
+@@ -581,7 +664,7 @@ class BlockAlgo: |
|
521 |
+ def verify(self, mac_tag): |
|
522 |
+ """Validate the *binary* MAC tag in an AEAD mode. |
|
523 |
+ |
|
524 |
+- When using an AEAD mode like CCM, the caller invokes this function |
|
525 |
++ When using an AEAD mode like CCM or EAX, the caller invokes this function |
|
526 |
+ at the very end. |
|
527 |
+ |
|
528 |
+ This method checks if the decrypted message is indeed valid |
|
529 |
+@@ -596,17 +679,26 @@ class BlockAlgo: |
|
530 |
+ or the key is incorrect. |
|
531 |
+ """ |
|
532 |
+ |
|
533 |
+- if self.mode == MODE_CCM: |
|
534 |
++ if self.mode in (MODE_CCM, MODE_EAX): |
|
535 |
+ if self.verify not in self._next: |
|
536 |
+ raise TypeError("verify() cannot be called when encrypting a message") |
|
537 |
+ self._next = [self.verify] |
|
538 |
+ |
|
539 |
+- if self._assoc_len is None: |
|
540 |
+- self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
541 |
+- if self._msg_len is None: |
|
542 |
+- self._start_ccm(msg_len=0) |
|
543 |
+- self._update(b(""), do_zero_padding=True) |
|
544 |
+- u = strxor(self._t, self._s_0)[:self._mac_len] |
|
545 |
++ if self.mode == MODE_CCM: |
|
546 |
++ |
|
547 |
++ if self._assoc_len is None: |
|
548 |
++ self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
549 |
++ if self._msg_len is None: |
|
550 |
++ self._start_ccm(msg_len=0) |
|
551 |
++ self._update(b(""), do_zero_padding=True) |
|
552 |
++ u = strxor(self._t, self._s_0)[:self._mac_len] |
|
553 |
++ |
|
554 |
++ if self.mode == MODE_EAX: |
|
555 |
++ |
|
556 |
++ u = bchr(0)*self.block_size |
|
557 |
++ for i in xrange(3): |
|
558 |
++ u = strxor(u, self._omac[i].digest()) |
|
559 |
++ u = u[:self._mac_len] |
|
560 |
+ |
|
561 |
+ res = 0 |
|
562 |
+ # Constant-time comparison |
|
563 |
+--- a/lib/Crypto/SelfTest/Cipher/common.py_org 2019-05-20 19:10:52.217140561 +0530 |
|
564 |
+@@ -354,12 +354,12 @@ class CCMSplitEncryptionTest(unittest.Te |
|
565 |
+ class AEADTests(unittest.TestCase): |
|
566 |
+ """Tests generic to all AEAD modes""" |
|
567 |
+ |
|
568 |
+- def __init__(self, module, mode_name): |
|
569 |
++ def __init__(self, module, mode_name, key_size): |
|
570 |
+ unittest.TestCase.__init__(self) |
|
571 |
+ self.module = module |
|
572 |
+ self.mode_name = mode_name |
|
573 |
+ self.mode = getattr(module, mode_name) |
|
574 |
+- self.key = b('\xFF')*16 |
|
575 |
++ self.key = b('\xFF')*key_size |
|
576 |
+ self.iv = b('\x00')*10 |
|
577 |
+ self.description = "AEAD Test" |
|
578 |
+ |
|
579 |
+@@ -642,7 +642,7 @@ def make_block_tests(module, module_name |
|
580 |
+ ] |
|
581 |
+ extra_tests_added = 1 |
|
582 |
+ # Extract associated data and MAC for AEAD modes |
|
583 |
+- if p_mode == 'CCM': |
|
584 |
++ if p_mode in ('CCM', 'EAX'): |
|
585 |
+ assoc_data, params['plaintext'] = params['plaintext'].split('|') |
|
586 |
+ assoc_data2, params['ciphertext'], params['mac'] = params['ciphertext'].split('|') |
|
587 |
+ params['assoc_data'] = assoc_data |
|
588 |
+@@ -669,10 +669,16 @@ def make_block_tests(module, module_name |
|
589 |
+ CCMMACLengthTest(module), |
|
590 |
+ CCMSplitEncryptionTest(module), |
|
591 |
+ ] |
|
592 |
+- for aead_mode in ("MODE_CCM",): |
|
593 |
++ for aead_mode in ("MODE_CCM","MODE_EAX"): |
|
594 |
+ if hasattr(module, aead_mode): |
|
595 |
+- tests += [ |
|
596 |
+- AEADTests(module, aead_mode), |
|
597 |
++ key_sizes = [] |
|
598 |
++ try: |
|
599 |
++ key_sizes += module.key_size |
|
600 |
++ except TypeError: |
|
601 |
++ key_sizes = [ module.key_size ] |
|
602 |
++ for ks in key_sizes: |
|
603 |
++ tests += [ |
|
604 |
++ AEADTests(module, aead_mode, ks), |
|
605 |
+ ] |
|
606 |
+ return tests |
|
607 |
+ |
|
608 |
+--- a/lib/Crypto/SelfTest/Cipher/test_AES.py_org 2019-05-20 19:14:15.181144616 +0530 |
|
609 |
+@@ -1651,6 +1651,85 @@ test_data = [ |
|
610 |
+ 'RFC3610 Packet Vector #24', |
|
611 |
+ dict(mode='CCM', nonce='008d493b30ae8b3c9696766cfa') |
|
612 |
+ ), |
|
613 |
++ # Test vectors for EAX taken from http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf |
|
614 |
++ # This is a list of tuples with 5 items: |
|
615 |
++ # |
|
616 |
++ # 1. Header + '|' + plaintext |
|
617 |
++ # 2. Header + '|' + ciphertext + '|' + MAC |
|
618 |
++ # 3. AES-128 key |
|
619 |
++ # 4. Description |
|
620 |
++ # 5. Dictionary of parameters to be passed to AES.new(). It must |
|
621 |
++ # include the nonce. |
|
622 |
++ # |
|
623 |
++ ( '6bfb914fd07eae6b|', |
|
624 |
++ '6bfb914fd07eae6b||e037830e8389f27b025a2d6527e79d01', |
|
625 |
++ '233952dee4d5ed5f9b9c6d6ff80ff478', |
|
626 |
++ 'EAX spec Appendix G', |
|
627 |
++ dict(mode='EAX', nonce='62EC67F9C3A4A407FCB2A8C49031A8B3') |
|
628 |
++ ), |
|
629 |
++ |
|
630 |
++ ( 'fa3bfd4806eb53fa|f7fb', |
|
631 |
++ 'fa3bfd4806eb53fa|19dd|5c4c9331049d0bdab0277408f67967e5', |
|
632 |
++ '91945d3f4dcbee0bf45ef52255f095a4', |
|
633 |
++ 'EAX spec Appendix G', |
|
634 |
++ dict(mode='EAX', nonce='BECAF043B0A23D843194BA972C66DEBD') |
|
635 |
++ ), |
|
636 |
++ |
|
637 |
++ ( '234a3463c1264ac6|1a47cb4933', |
|
638 |
++ '234a3463c1264ac6|d851d5bae0|3a59f238a23e39199dc9266626c40f80', |
|
639 |
++ '01f74ad64077f2e704c0f60ada3dd523', |
|
640 |
++ 'EAX spec Appendix G', |
|
641 |
++ dict(mode='EAX', nonce='70C3DB4F0D26368400A10ED05D2BFF5E') |
|
642 |
++ ), |
|
643 |
++ |
|
644 |
++ ( '33cce2eabff5a79d|481c9e39b1', |
|
645 |
++ '33cce2eabff5a79d|632a9d131a|d4c168a4225d8e1ff755939974a7bede', |
|
646 |
++ 'd07cf6cbb7f313bdde66b727afd3c5e8', |
|
647 |
++ 'EAX spec Appendix G', |
|
648 |
++ dict(mode='EAX', nonce='8408DFFF3C1A2B1292DC199E46B7D617') |
|
649 |
++ ), |
|
650 |
++ |
|
651 |
++ ( 'aeb96eaebe2970e9|40d0c07da5e4', |
|
652 |
++ 'aeb96eaebe2970e9|071dfe16c675|cb0677e536f73afe6a14b74ee49844dd', |
|
653 |
++ '35b6d0580005bbc12b0587124557d2c2', |
|
654 |
++ 'EAX spec Appendix G', |
|
655 |
++ dict(mode='EAX', nonce='FDB6B06676EEDC5C61D74276E1F8E816') |
|
656 |
++ ), |
|
657 |
++ |
|
658 |
++ ( 'd4482d1ca78dce0f|4de3b35c3fc039245bd1fb7d', |
|
659 |
++ 'd4482d1ca78dce0f|835bb4f15d743e350e728414|abb8644fd6ccb86947c5e10590210a4f', |
|
660 |
++ 'bd8e6e11475e60b268784c38c62feb22', |
|
661 |
++ 'EAX spec Appendix G', |
|
662 |
++ dict(mode='EAX', nonce='6EAC5C93072D8E8513F750935E46DA1B') |
|
663 |
++ ), |
|
664 |
++ |
|
665 |
++ ( '65d2017990d62528|8b0a79306c9ce7ed99dae4f87f8dd61636', |
|
666 |
++ '65d2017990d62528|02083e3979da014812f59f11d52630da30|137327d10649b0aa6e1c181db617d7f2', |
|
667 |
++ '7c77d6e813bed5ac98baa417477a2e7d', |
|
668 |
++ 'EAX spec Appendix G', |
|
669 |
++ dict(mode='EAX', nonce='1A8C98DCD73D38393B2BF1569DEEFC19') |
|
670 |
++ ), |
|
671 |
++ |
|
672 |
++ ( '54b9f04e6a09189a|1bda122bce8a8dbaf1877d962b8592dd2d56', |
|
673 |
++ '54b9f04e6a09189a|2ec47b2c4954a489afc7ba4897edcdae8cc3|3b60450599bd02c96382902aef7f832a', |
|
674 |
++ '5fff20cafab119ca2fc73549e20f5b0d', |
|
675 |
++ 'EAX spec Appendix G', |
|
676 |
++ dict(mode='EAX', nonce='DDE59B97D722156D4D9AFF2BC7559826') |
|
677 |
++ ), |
|
678 |
++ |
|
679 |
++ ( '899a175897561d7e|6cf36720872b8513f6eab1a8a44438d5ef11', |
|
680 |
++ '899a175897561d7e|0de18fd0fdd91e7af19f1d8ee8733938b1e8|e7f6d2231618102fdb7fe55ff1991700', |
|
681 |
++ 'a4a4782bcffd3ec5e7ef6d8c34a56123', |
|
682 |
++ 'EAX spec Appendix G', |
|
683 |
++ dict(mode='EAX', nonce='B781FCF2F75FA5A8DE97A9CA48E522EC') |
|
684 |
++ ), |
|
685 |
++ |
|
686 |
++ ( '126735fcc320d25a|ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7', |
|
687 |
++ '126735fcc320d25a|cb8920f87a6c75cff39627b56e3ed197c552d295a7|cfc46afc253b4652b1af3795b124ab6e', |
|
688 |
++ '8395fcf1e95bebd697bd010bc766aac3', |
|
689 |
++ 'EAX spec Appendix G', |
|
690 |
++ dict(mode='EAX', nonce='22E7ADD93CFC6393C57EC0B3C17D6B44') |
|
691 |
++ ), |
|
692 |
+ ] |
|
693 |
+ |
|
694 |
+ def get_tests(config={}): |
|
695 |
+--- a/pct-speedtest.py_org 2019-05-20 19:15:48.605146482 +0530 |
|
696 |
+@@ -212,6 +212,8 @@ class Benchmark: |
|
697 |
+ self.test_encryption("%s-OPENPGP" % (cipher_name,), module, key_bytes, module.MODE_OPENPGP) |
|
698 |
+ if hasattr(module, "MODE_CCM"): |
|
699 |
+ self.test_encryption("%s-CCM" % (cipher_name,), module, key_bytes, module.MODE_CCM) |
|
700 |
++ if hasattr(module, "MODE_EAX"): |
|
701 |
++ self.test_encryption("%s-EAX" % (cipher_name,), module, key_bytes, module.MODE_EAX) |
|
702 |
+ for cipher_name, module, key_bytes in stream_specs: |
|
703 |
+ self.test_key_setup(cipher_name, module, key_bytes, None) |
|
704 |
+ self.test_encryption(cipher_name, module, key_bytes, None) |
0 | 705 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,1779 @@ |
0 |
+From 5d7ab24c513fb43a604ad23b23d040a53069c4db Mon Sep 17 00:00:00 2001 |
|
1 |
+From: Legrandin <helderijs@gmail.com> |
|
2 |
+Date: Tue, 28 May 2013 23:57:56 +0200 |
|
3 |
+Subject: [PATCH] Add support for GCM mode (AES only). |
|
4 |
+ |
|
5 |
+The main change done by this commit is adding support |
|
6 |
+for MODE_GCM (NIST SP 800 38D). Test vectors are included. |
|
7 |
+ |
|
8 |
+The mode uses a C extension (Crypto.Util.galois._ghash) |
|
9 |
+to compute the GHASH step. The C implementation is the most |
|
10 |
+basic one and it is still significantly (5x times) slower than CTR. |
|
11 |
+Optimizations can be introduced using tables (CPU/memory trade-off) |
|
12 |
+or even AES NI instructions on newer x86 CPUs. |
|
13 |
+ |
|
14 |
+This patch also simplifies Crypto.Cipher.blockalgo.py by: |
|
15 |
+ * removing duplicated code previously shared by digest() and verify(). |
|
16 |
+ * removing duplicated code previously shared by Crypto.Hash.CMAC |
|
17 |
+ and Crypto.Cipher.block_algo (management of internal buffers |
|
18 |
+ for MACs that can only operate on block aligned data, like |
|
19 |
+ CMAC, CBCMAC, and now also GHASH). |
|
20 |
+ |
|
21 |
+[dlitz@dlitz.net: Included changes from the following commits from the author's pull request:] |
|
22 |
+- [9c13f9c] Rename 'IV' parameter to 'nonce' for AEAD modes. |
|
23 |
+- [ca460a7] Made blockalgo.py more PEP-8 compliant; |
|
24 |
+ The second parameter of the _GHASH constructor |
|
25 |
+ is now the length of the block (block_size) |
|
26 |
+ and not the full module. |
|
27 |
+[dlitz@dlitz.net: Replaced MacMismatchError with ValueError] |
|
28 |
+[dlitz@dlitz.net: Replaced ApiUsageError with TypeError] |
|
29 |
+[dlitz@dlitz.net: Replaced renamed variable `ht` with original `h`] |
|
30 |
+[dlitz@dlitz.net: Whitespace fixed with "git rebase --whitespace=fix"] |
|
31 |
+ |
|
32 |
+From da79b781af41ff815b812c49d9be434f5de52aa4 Mon Sep 17 00:00:00 2001 |
|
33 |
+From: Legrandin <helderijs@gmail.com> |
|
34 |
+Date: Mon, 13 May 2013 08:40:46 +0200 |
|
35 |
+Subject: [PATCH] Add support for CMAC |
|
36 |
+ |
|
37 |
+This patch adds support for CMAC (RFC4493, NIST SP800-38B). |
|
38 |
+ |
|
39 |
+[dlitz@dlitz.net: Replaced MacMismatchError with ValueError] |
|
40 |
+[dlitz@dlitz.net: Whitespace fixed with "git rebase --whitespace=fix"] |
|
41 |
+ |
|
42 |
+ |
|
43 |
+--- a/lib/Crypto/Cipher/AES.py_org 2019-05-20 20:54:14.993264462 +0530 |
|
44 |
+@@ -114,7 +114,7 @@ def new(key, *args, **kwargs): |
|
45 |
+ |
|
46 |
+ For all other modes, it must be 16 bytes long. |
|
47 |
+ nonce : byte string |
|
48 |
+- (*Only* `MODE_CCM`, `MODE_EAX`, `MODE_SIV`). |
|
49 |
++ (*Only* `MODE_CCM`, `MODE_EAX`, `MODE_SIV`, `MODE_GCM`). |
|
50 |
+ |
|
51 |
+ A mandatory value that must never be reused for any other encryption. |
|
52 |
+ |
|
53 |
+@@ -139,6 +139,8 @@ def new(key, *args, **kwargs): |
|
54 |
+ mac_len : integer |
|
55 |
+ (*Only* `MODE_CCM`). Length of the MAC, in bytes. It must be even and in |
|
56 |
+ the range ``[4..16]``. The default is 16. |
|
57 |
++ (*Only* `MODE_EAX` and `MODE_GCM`). Length of the MAC, in bytes. It must be no |
|
58 |
++ larger than 16 bytes (which is the default). |
|
59 |
+ msg_len : integer |
|
60 |
+ (*Only* `MODE_CCM`). Length of the message to (de)cipher. |
|
61 |
+ If not specified, ``encrypt`` or ``decrypt`` may only be called once. |
|
62 |
+@@ -169,6 +171,8 @@ MODE_CCM = 8 |
|
63 |
+ MODE_EAX = 9 |
|
64 |
+ #: Syntethic Initialization Vector (SIV). See `blockalgo.MODE_SIV`. |
|
65 |
+ MODE_SIV = 10 |
|
66 |
++#: Galois Counter Mode (GCM). See `blockalgo.MODE_GCM`. |
|
67 |
++MODE_GCM = 11 |
|
68 |
+ #: Size of a data block (in bytes) |
|
69 |
+ block_size = 16 |
|
70 |
+ #: Size of a key (in bytes) |
|
71 |
+--- a/lib/Crypto/Cipher/blockalgo.py_org 2019-05-20 20:57:12.201268002 +0530 |
|
72 |
+@@ -32,8 +32,11 @@ from Crypto.Util.strxor import strxor |
|
73 |
+ from Crypto.Util.number import long_to_bytes, bytes_to_long |
|
74 |
+ import Crypto.Util.Counter |
|
75 |
+ from Crypto.Hash import CMAC |
|
76 |
++from Crypto.Hash.CMAC import _SmoothMAC |
|
77 |
+ from Crypto.Protocol.KDF import S2V |
|
78 |
+ |
|
79 |
++from Crypto.Util.galois import _ghash |
|
80 |
++ |
|
81 |
+ #: *Electronic Code Book (ECB)*. |
|
82 |
+ #: This is the simplest encryption mode. Each of the plaintext blocks |
|
83 |
+ #: is directly encrypted into a ciphertext block, independently of |
|
84 |
+@@ -252,6 +255,28 @@ MODE_EAX = 9 |
|
85 |
+ #: .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf |
|
86 |
+ MODE_SIV = 10 |
|
87 |
+ |
|
88 |
++#: *Galois/Counter Mode (GCM)*. This is an Authenticated Encryption with |
|
89 |
++#: Associated Data (`AEAD`_) mode. It provides both confidentiality and |
|
90 |
++#: authenticity. |
|
91 |
++#: The header of the message may be left in the clear, if needed, and it will |
|
92 |
++#: still be subject to authentication. The decryption step tells the receiver |
|
93 |
++#: if the message comes from a source that really knowns the secret key. |
|
94 |
++#: Additionally, decryption detects if any part of the message - including the |
|
95 |
++#: header - has been modified or corrupted. |
|
96 |
++#: |
|
97 |
++#: This mode requires a nonce. The nonce shall never repeat for two |
|
98 |
++#: different messages encrypted with the same key, but it does not need to |
|
99 |
++#: be random. |
|
100 |
++#: |
|
101 |
++#: This mode is only available for ciphers that operate on 128 bits blocks |
|
102 |
++#: (e.g. AES but not TDES). |
|
103 |
++#: |
|
104 |
++#: See `NIST SP800-38D`_ . |
|
105 |
++#: |
|
106 |
++#: .. _`NIST SP800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf |
|
107 |
++#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html |
|
108 |
++MODE_GCM = 11 |
|
109 |
++ |
|
110 |
+ def _getParameter(name, index, args, kwargs, default=None): |
|
111 |
+ """Find a parameter in tuple and dictionary arguments a function receives""" |
|
112 |
+ param = kwargs.get(name) |
|
113 |
+@@ -260,6 +285,61 @@ def _getParameter(name, index, args, kwa |
|
114 |
+ raise ValueError("Parameter '%s' is specified twice" % name) |
|
115 |
+ param = args[index] |
|
116 |
+ return param or default |
|
117 |
++ |
|
118 |
++class _CBCMAC(_SmoothMAC): |
|
119 |
++ |
|
120 |
++ def __init__(self, key, ciphermod): |
|
121 |
++ _SmoothMAC.__init__(self, ciphermod.block_size, None, 0) |
|
122 |
++ self._key = key |
|
123 |
++ self._factory = ciphermod |
|
124 |
++ |
|
125 |
++ def ignite(self, data): |
|
126 |
++ if self._mac: |
|
127 |
++ raise TypeError("ignite() cannot be called twice") |
|
128 |
++ |
|
129 |
++ self._buffer.insert(0, data) |
|
130 |
++ self._buffer_len += len(data) |
|
131 |
++ self._mac = self._factory.new(self._key, MODE_CBC, bchr(0) * 16) |
|
132 |
++ self.update(b("")) |
|
133 |
++ |
|
134 |
++ def _update(self, block_data): |
|
135 |
++ self._t = self._mac.encrypt(block_data)[-16:] |
|
136 |
++ |
|
137 |
++ def _digest(self, left_data): |
|
138 |
++ return self._t |
|
139 |
++ |
|
140 |
++ |
|
141 |
++class _GHASH(_SmoothMAC): |
|
142 |
++ """GHASH function defined in NIST SP 800-38D, Algorithm 2. |
|
143 |
++ |
|
144 |
++ If X_1, X_2, .. X_m are the blocks of input data, the function |
|
145 |
++ computes: |
|
146 |
++ |
|
147 |
++ X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H |
|
148 |
++ |
|
149 |
++ in the Galois field GF(2^256) using the reducing polynomial |
|
150 |
++ (x^128 + x^7 + x^2 + x + 1). |
|
151 |
++ """ |
|
152 |
++ |
|
153 |
++ def __init__(self, hash_subkey, block_size): |
|
154 |
++ _SmoothMAC.__init__(self, block_size, None, 0) |
|
155 |
++ self._hash_subkey = hash_subkey |
|
156 |
++ self._last_y = bchr(0) * 16 |
|
157 |
++ self._mac = _ghash |
|
158 |
++ |
|
159 |
++ def copy(self): |
|
160 |
++ clone = _GHASH(self._hash_subkey, self._bs) |
|
161 |
++ _SmoothMAC._deep_copy(self, clone) |
|
162 |
++ clone._last_y = self._last_y |
|
163 |
++ return clone |
|
164 |
++ |
|
165 |
++ def _update(self, block_data): |
|
166 |
++ self._last_y = _ghash(block_data, self._last_y, self._hash_subkey) |
|
167 |
++ |
|
168 |
++ def _digest(self, left_data): |
|
169 |
++ return self._last_y |
|
170 |
++ |
|
171 |
++ |
|
172 |
+ |
|
173 |
+ class BlockAlgo: |
|
174 |
+ """Class modelling an abstract block cipher.""" |
|
175 |
+@@ -269,6 +349,7 @@ class BlockAlgo: |
|
176 |
+ self.block_size = factory.block_size |
|
177 |
+ |
|
178 |
+ self._factory = factory |
|
179 |
++ self._tag = None |
|
180 |
+ if self.mode == MODE_CCM: |
|
181 |
+ if self.block_size != 16: |
|
182 |
+ raise ValueError("CCM mode is only available for ciphers that operate on 128 bits blocks") |
|
183 |
+@@ -286,9 +367,7 @@ class BlockAlgo: |
|
184 |
+ self._msg_len = kwargs.get('msg_len', None) # p |
|
185 |
+ self._assoc_len = kwargs.get('assoc_len', None) # a |
|
186 |
+ |
|
187 |
+- self._assoc_buffer = [] |
|
188 |
+- self._assoc_buffer_len = 0 |
|
189 |
+- self._cipherCBC = None # To be used for MAC |
|
190 |
++ self._cipherMAC = _CBCMAC(key, factory) |
|
191 |
+ self._done_assoc_data = False # True when all associated data |
|
192 |
+ # has been processed |
|
193 |
+ |
|
194 |
+@@ -305,10 +384,63 @@ class BlockAlgo: |
|
195 |
+ self._start_eax(factory, key, *args, **kwargs) |
|
196 |
+ elif self.mode == MODE_SIV: |
|
197 |
+ self._start_siv(factory, key, *args, **kwargs) |
|
198 |
++ elif self.mode == MODE_GCM: |
|
199 |
++ self._start_gcm(factory, key, *args, **kwargs) |
|
200 |
+ else: |
|
201 |
+ self._cipher = factory.new(key, *args, **kwargs) |
|
202 |
+ self.IV = self._cipher.IV |
|
203 |
+ |
|
204 |
++ def _start_gcm(self, factory, key, *args, **kwargs): |
|
205 |
++ |
|
206 |
++ if self.block_size != 16: |
|
207 |
++ raise ValueError("GCM mode is only available for ciphers that operate on 128 bits blocks") |
|
208 |
++ |
|
209 |
++ self.nonce = _getParameter('nonce', 1, args, kwargs) |
|
210 |
++ if not self.nonce: |
|
211 |
++ raise ValueError("MODE_GCM requires a nonce") |
|
212 |
++ |
|
213 |
++ self._mac_len = kwargs.get('mac_len', 16) |
|
214 |
++ if not (self._mac_len and 4 <= self._mac_len <= 16): |
|
215 |
++ raise ValueError("Parameter 'mac_len' must not be larger than 16 bytes") |
|
216 |
++ |
|
217 |
++ # Allowed transitions after initialization |
|
218 |
++ self._next = [self.update, self.encrypt, self.decrypt, |
|
219 |
++ self.digest, self.verify] |
|
220 |
++ |
|
221 |
++ self._done_assoc_data = False |
|
222 |
++ |
|
223 |
++ # Length of the ciphertext or plaintext |
|
224 |
++ self._msg_len = 0 |
|
225 |
++ |
|
226 |
++ # Step 1 in SP800-38D, Algorithm 4 (encryption) - Compute H |
|
227 |
++ # See also Algorithm 5 (decryption) |
|
228 |
++ hash_subkey = factory.new(key).encrypt(bchr(0) * 16) |
|
229 |
++ |
|
230 |
++ # Step 2 - Compute J0 (integer, not byte string!) |
|
231 |
++ if len(self.nonce) == 12: |
|
232 |
++ self._j0 = bytes_to_long(self.nonce + b("\x00\x00\x00\x01")) |
|
233 |
++ else: |
|
234 |
++ fill = (16 - (len(self.nonce) % 16)) % 16 + 8 |
|
235 |
++ ghash_in = (self.nonce + |
|
236 |
++ bchr(0) * fill + |
|
237 |
++ long_to_bytes(8 * len(self.nonce), 8)) |
|
238 |
++ |
|
239 |
++ mac = _GHASH(hash_subkey, factory.block_size) |
|
240 |
++ mac.update(ghash_in) |
|
241 |
++ self._j0 = bytes_to_long(mac.digest()) |
|
242 |
++ |
|
243 |
++ # Step 3 - Prepare GCTR cipher for encryption/decryption |
|
244 |
++ ctr = Counter.new(128, initial_value=self._j0 + 1, |
|
245 |
++ allow_wraparound=True) |
|
246 |
++ self._cipher = self._factory.new(key, MODE_CTR, counter=ctr) |
|
247 |
++ |
|
248 |
++ # Step 5 - Bootstrat GHASH |
|
249 |
++ self._cipherMAC = _GHASH(hash_subkey, factory.block_size) |
|
250 |
++ |
|
251 |
++ # Step 6 - Prepare GCTR cipher for GMAC |
|
252 |
++ ctr = Counter.new(128, initial_value=self._j0, allow_wraparound=True) |
|
253 |
++ self._tag_cipher = self._factory.new(key, MODE_CTR, counter=ctr) |
|
254 |
++ |
|
255 |
+ def _start_siv(self, factory, key, *args, **kwargs): |
|
256 |
+ |
|
257 |
+ subkey_size, rem = divmod(len(key), 2) |
|
258 |
+@@ -318,10 +450,10 @@ class BlockAlgo: |
|
259 |
+ # IV is optional |
|
260 |
+ self.nonce = _getParameter('nonce', 1, args, kwargs) |
|
261 |
+ |
|
262 |
+- self._prf = S2V(key[:subkey_size], ciphermod=factory) |
|
263 |
++ self._cipherMAC = S2V(key[:subkey_size], ciphermod=factory) |
|
264 |
+ self._subkey_ctr = key[subkey_size:] |
|
265 |
+ self._mac_len = factory.block_size |
|
266 |
+- |
|
267 |
++ self._cipherMAC = self._cipherMAC |
|
268 |
+ # Allowed transitions after initialization |
|
269 |
+ self._next = [self.update, self.encrypt, self.decrypt, |
|
270 |
+ self.digest, self.verify] |
|
271 |
+@@ -360,6 +492,7 @@ class BlockAlgo: |
|
272 |
+ |
|
273 |
+ # Compute MAC of nonce |
|
274 |
+ self._omac[0].update(self.nonce) |
|
275 |
++ self._cipherMAC = self._omac[1] |
|
276 |
+ |
|
277 |
+ # MAC of the nonce is also the initial counter for CTR encryption |
|
278 |
+ counter_int = bytes_to_long(self._omac[0].digest()) |
|
279 |
+@@ -421,12 +554,12 @@ class BlockAlgo: |
|
280 |
+ |
|
281 |
+ def _start_ccm(self, assoc_len=None, msg_len=None): |
|
282 |
+ # CCM mode. This method creates the 2 ciphers used for the MAC |
|
283 |
+- # (self._cipherCBC) and for the encryption/decryption (self._cipher). |
|
284 |
++ # (self._cipherMAC) and for the encryption/decryption (self._cipher). |
|
285 |
+ # |
|
286 |
+ # Member _assoc_buffer may already contain user data that needs to be |
|
287 |
+ # authenticated. |
|
288 |
+ |
|
289 |
+- if self._cipherCBC: |
|
290 |
++ if self._cipherMAC.can_reduce(): |
|
291 |
+ # Already started |
|
292 |
+ return |
|
293 |
+ if assoc_len is not None: |
|
294 |
+@@ -446,12 +579,8 @@ class BlockAlgo: |
|
295 |
+ (q - 1) |
|
296 |
+ ) |
|
297 |
+ b_0 = bchr(flags) + self.nonce + long_to_bytes(self._msg_len, q) |
|
298 |
+- self._assoc_buffer.insert(0, b_0) |
|
299 |
+- self._assoc_buffer_len += 16 |
|
300 |
+ |
|
301 |
+ # Start CBC MAC with zero IV |
|
302 |
+- # Mind that self._assoc_buffer may already contain some data |
|
303 |
+- self._cipherCBC = self._factory.new(self._key, MODE_CBC, bchr(0)*16) |
|
304 |
+ assoc_len_encoded = b('') |
|
305 |
+ if self._assoc_len > 0: |
|
306 |
+ if self._assoc_len < (2 ** 16 - 2 ** 8): |
|
307 |
+@@ -463,12 +592,9 @@ class BlockAlgo: |
|
308 |
+ assoc_len_encoded = b('\xFF\xFF') |
|
309 |
+ enc_size = 8 |
|
310 |
+ assoc_len_encoded += long_to_bytes(self._assoc_len, enc_size) |
|
311 |
+- self._assoc_buffer.insert(1, assoc_len_encoded) |
|
312 |
+- self._assoc_buffer_len += len(assoc_len_encoded) |
|
313 |
+- |
|
314 |
++ self._cipherMAC.ignite(b_0 + assoc_len_encoded) |
|
315 |
+ # Start CTR cipher |
|
316 |
+- flags = q - 1 |
|
317 |
+- prefix = bchr(flags) + self.nonce |
|
318 |
++ prefix = bchr(q - 1) + self.nonce |
|
319 |
+ ctr = Counter.new(128 - len(prefix) * 8, prefix, initial_value=0) |
|
320 |
+ self._cipher = self._factory.new(self._key, MODE_CTR, counter=ctr) |
|
321 |
+ # Will XOR against CBC MAC |
|
322 |
+@@ -477,7 +603,7 @@ class BlockAlgo: |
|
323 |
+ def update(self, assoc_data): |
|
324 |
+ """Protect associated data |
|
325 |
+ |
|
326 |
+- When using an AEAD mode like CCM, EAX or SIV, and |
|
327 |
++ When using an AEAD mode like CCM, EAX, GCM or SIV, and |
|
328 |
+ if there is any associated data, the caller has to invoke |
|
329 |
+ this function one or more times, before using |
|
330 |
+ ``decrypt`` or ``encrypt``. |
|
331 |
+@@ -485,8 +611,9 @@ class BlockAlgo: |
|
332 |
+ By *associated data* it is meant any data (e.g. packet headers) that |
|
333 |
+ will not be encrypted and will be transmitted in the clear. |
|
334 |
+ However, the receiver is still able to detect any modification to it. |
|
335 |
+- In CCM, the *associated data* is also called *additional authenticated |
|
336 |
+- data*. In EAX, the *associated data* is called *header*. |
|
337 |
++ In CCM and GCM, the *associated data* is also called |
|
338 |
++ *additional authenticated data* (AAD). |
|
339 |
++ In EAX, the *associated data* is called *header*. |
|
340 |
+ |
|
341 |
+ If there is no associated data, this method must not be called. |
|
342 |
+ |
|
343 |
+@@ -498,44 +625,16 @@ class BlockAlgo: |
|
344 |
+ A piece of associated data. There are no restrictions on its size. |
|
345 |
+ """ |
|
346 |
+ |
|
347 |
+- if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
348 |
+- if self.update not in self._next: |
|
349 |
+- raise TypeError("update() can only be called immediately after initialization") |
|
350 |
+- self._next = [self.update, self.encrypt, self.decrypt, |
|
351 |
+- self.digest, self.verify] |
|
352 |
+- return self._update(assoc_data) |
|
353 |
++ if self.mode not in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM): |
|
354 |
++ raise ValueError("update() not supported by this mode of operation") |
|
355 |
+ |
|
356 |
+- def _update(self, assoc_data, do_zero_padding=False): |
|
357 |
+- """Equivalent to update(), but without FSM checks.""" |
|
358 |
++ if self.update not in self._next: |
|
359 |
++ raise TypeError("update() can only be called immediately after initialization") |
|
360 |
+ |
|
361 |
+- if self.mode == MODE_CCM: |
|
362 |
+- self._assoc_buffer.append(assoc_data) |
|
363 |
+- self._assoc_buffer_len += len(assoc_data) |
|
364 |
+- |
|
365 |
+- if not self._cipherCBC: |
|
366 |
+- return |
|
367 |
+- |
|
368 |
+- if do_zero_padding and (self._assoc_buffer_len & 15): |
|
369 |
+- npad = 16 - self._assoc_buffer_len & 15 |
|
370 |
+- self._assoc_buffer.append(bchr(0) * npad) |
|
371 |
+- self._assoc_buffer_len += npad |
|
372 |
+- |
|
373 |
+- # Feed data into CBC MAC |
|
374 |
+- aligned_data = 16 * divmod(self._assoc_buffer_len, 16)[0] |
|
375 |
+- if aligned_data > 0: |
|
376 |
+- buf = b("").join(self._assoc_buffer) |
|
377 |
+- self._t = self._cipherCBC.encrypt(buf[:aligned_data])[-16:] |
|
378 |
+- self._assoc_buffer = [buf[aligned_data:]] |
|
379 |
+- self._assoc_buffer_len -= aligned_data |
|
380 |
+- return |
|
381 |
+- if self.mode == MODE_EAX: |
|
382 |
+- self._omac[1].update(assoc_data) |
|
383 |
+- return |
|
384 |
+- if self.mode == MODE_SIV: |
|
385 |
+- self._prf.update(assoc_data) |
|
386 |
+- return |
|
387 |
++ self._next = [self.update, self.encrypt, self.decrypt, |
|
388 |
++ self.digest, self.verify] |
|
389 |
+ |
|
390 |
+- raise ValueError("update() not supported by this mode of operation") |
|
391 |
++ return self._cipherMAC.update(assoc_data) |
|
392 |
+ |
|
393 |
+ |
|
394 |
+ def encrypt(self, plaintext): |
|
395 |
+@@ -570,7 +669,7 @@ class BlockAlgo: |
|
396 |
+ - For `MODE_CFB`, *plaintext* length (in bytes) must be a multiple |
|
397 |
+ of *segment_size*/8. |
|
398 |
+ |
|
399 |
+- - For `MODE_CTR` and `MODE_CCM`, `MODE_EAX` and `MODE_SIV`, |
|
400 |
++ - For `MODE_CTR` and all AEAD modes, |
|
401 |
+ *plaintext* can be of any length. |
|
402 |
+ |
|
403 |
+ - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, |
|
404 |
+@@ -604,36 +703,42 @@ class BlockAlgo: |
|
405 |
+ self._done_first_block = True |
|
406 |
+ return res |
|
407 |
+ |
|
408 |
+- if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
409 |
++ if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM): |
|
410 |
+ |
|
411 |
+ if self.encrypt not in self._next: |
|
412 |
+ raise TypeError("encrypt() can only be called after initialization or an update()") |
|
413 |
+ self._next = [self.encrypt, self.digest] |
|
414 |
+ if self.mode == MODE_CCM: |
|
415 |
+ if self._assoc_len is None: |
|
416 |
+- self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
417 |
++ self._start_ccm(assoc_len=self._cipherMAC.get_len() |
|
418 |
+ if self._msg_len is None: |
|
419 |
+ self._start_ccm(msg_len=len(plaintext)) |
|
420 |
+ self._next = [self.digest] |
|
421 |
+ if not self._done_assoc_data: |
|
422 |
+- self._update(b(""), do_zero_padding=True) |
|
423 |
++ self._cipherMAC.zero_pad() |
|
424 |
+ self._done_assoc_data = True |
|
425 |
+ |
|
426 |
+- self._update(plaintext) |
|
427 |
++ self._cipherMAC.update(plaintext) |
|
428 |
+ |
|
429 |
+ if self.mode == MODE_SIV: |
|
430 |
+ self._next = [self.digest] |
|
431 |
+ |
|
432 |
+ if self.nonce: |
|
433 |
+- self._prf.update(self.nonce) |
|
434 |
++ self._cipherMAC.update(self.nonce) |
|
435 |
+ |
|
436 |
+- self._prf.update(plaintext) |
|
437 |
+- self._cipher = self._siv_ctr_cipher(self._prf.derive()) |
|
438 |
++ self._cipherMAC.update(plaintext) |
|
439 |
++ self._cipher = self._siv_ctr_cipher(self._cipherMAC.derive()) |
|
440 |
+ |
|
441 |
+ ct = self._cipher.encrypt(plaintext) |
|
442 |
+ |
|
443 |
+ if self.mode == MODE_EAX: |
|
444 |
+ self._omac[2].update(ct) |
|
445 |
++ if self.mode == MODE_GCM: |
|
446 |
++ if not self._done_assoc_data: |
|
447 |
++ self._cipherMAC.zero_pad() |
|
448 |
++ self._done_assoc_data = True |
|
449 |
++ self._cipherMAC.update(ct) |
|
450 |
++ self._msg_len += len(plaintext) |
|
451 |
+ |
|
452 |
+ return ct |
|
453 |
+ |
|
454 |
+@@ -663,8 +768,8 @@ class BlockAlgo: |
|
455 |
+ |
|
456 |
+ This function does not perform any padding. |
|
457 |
+ |
|
458 |
+- - For `MODE_ECB`, `MODE_CBC`, and `MODE_OFB`, *ciphertext* length |
|
459 |
+- (in bytes) must be a multiple of *block_size*. |
|
460 |
++ - For `MODE_ECB`, `MODE_CBC`, and all AEAD modes, *ciphertext* length |
|
461 |
++ can be of any length. |
|
462 |
+ |
|
463 |
+ - For `MODE_CFB`, *ciphertext* length (in bytes) must be a multiple |
|
464 |
+ of *segment_size*/8. |
|
465 |
+@@ -698,7 +803,7 @@ class BlockAlgo: |
|
466 |
+ res = self._cipher.decrypt(ciphertext) |
|
467 |
+ return res |
|
468 |
+ |
|
469 |
+- if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
470 |
++ if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM): |
|
471 |
+ |
|
472 |
+ if self.decrypt not in self._next: |
|
473 |
+ raise TypeError("decrypt() can only be called after initialization or an update()") |
|
474 |
+@@ -706,14 +811,22 @@ class BlockAlgo: |
|
475 |
+ |
|
476 |
+ if self.mode == MODE_CCM: |
|
477 |
+ if self._assoc_len is None: |
|
478 |
+- self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
479 |
++ self._start_ccm(assoc_len=self._cipherMAC.get_len()) |
|
480 |
+ if self._msg_len is None: |
|
481 |
+ self._start_ccm(msg_len=len(ciphertext)) |
|
482 |
+ self._next = [self.verify] |
|
483 |
+ if not self._done_assoc_data: |
|
484 |
+- self._update(b(""), do_zero_padding=True) |
|
485 |
++ self._cipherMAC.zero_pad() |
|
486 |
+ self._done_assoc_data = True |
|
487 |
+ |
|
488 |
++ if self.mode == MODE_GCM: |
|
489 |
++ if not self._done_assoc_data: |
|
490 |
++ self._cipherMAC.zero_pad() |
|
491 |
++ self._done_assoc_data = True |
|
492 |
++ |
|
493 |
++ self._cipherMAC.update(ciphertext) |
|
494 |
++ self._msg_len += len(ciphertext) |
|
495 |
++ |
|
496 |
+ if self.mode == MODE_EAX: |
|
497 |
+ self._omac[2].update(ciphertext) |
|
498 |
+ if self.mode == MODE_SIV: |
|
499 |
+@@ -729,12 +842,12 @@ class BlockAlgo: |
|
500 |
+ pt = self._cipher.decrypt(ciphertext) |
|
501 |
+ |
|
502 |
+ if self.mode == MODE_CCM: |
|
503 |
+- self._update(pt) |
|
504 |
++ self._cipherMAC.update(pt) |
|
505 |
+ if self.mode == MODE_SIV: |
|
506 |
+ if self.nonce: |
|
507 |
+- self._prf.update(self.nonce) |
|
508 |
++ self._cipherMAC.update(self.nonce) |
|
509 |
+ if pt: |
|
510 |
+- self._prf.update(pt) |
|
511 |
++ self._cipherMAC.update(pt) |
|
512 |
+ return pt |
|
513 |
+ |
|
514 |
+ def digest(self): |
|
515 |
+@@ -749,33 +862,55 @@ class BlockAlgo: |
|
516 |
+ :Return: the MAC, as a byte string. |
|
517 |
+ """ |
|
518 |
+ |
|
519 |
+- if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
520 |
++ if self.mode not in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM): |
|
521 |
++ raise TypeError("digest() not supported by this mode of operation") |
|
522 |
+ |
|
523 |
+- if self.digest not in self._next: |
|
524 |
+- raise TypeError("digest() cannot be called when decrypting or validating a message") |
|
525 |
+- self._next = [self.digest] |
|
526 |
++ if self.digest not in self._next: |
|
527 |
++ raise TypeError("digest() cannot be called when decrypting or validating a message") |
|
528 |
++ self._next = [self.digest] |
|
529 |
+ |
|
530 |
+- if self.mode == MODE_CCM: |
|
531 |
++ return self._compute_mac() |
|
532 |
+ |
|
533 |
+- if self._assoc_len is None: |
|
534 |
+- self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
535 |
+- if self._msg_len is None: |
|
536 |
+- self._start_ccm(msg_len=0) |
|
537 |
+- self._update(b(""), do_zero_padding=True) |
|
538 |
+- tag = strxor(self._t, self._s_0)[:self._mac_len] |
|
539 |
++ def _compute_mac(self): |
|
540 |
++ """Compute MAC without any FSM checks.""" |
|
541 |
+ |
|
542 |
+- if self.mode == MODE_EAX: |
|
543 |
++ if self._tag: |
|
544 |
++ return self._tag |
|
545 |
+ |
|
546 |
+- tag = bchr(0) * self.block_size |
|
547 |
+- for i in xrange(3): |
|
548 |
+- tag = strxor(tag, self._omac[i].digest()) |
|
549 |
+ |
|
550 |
+- if self.mode == MODE_SIV: |
|
551 |
+- tag = self._prf.derive() |
|
552 |
++ if self.mode == MODE_CCM: |
|
553 |
++ |
|
554 |
++ if self._assoc_len is None: |
|
555 |
++ self._start_ccm(assoc_len=self._cipherMAC.get_len()) |
|
556 |
++ if self._msg_len is None: |
|
557 |
++ self._start_ccm(msg_len=0) |
|
558 |
++ self._cipherMAC.zero_pad() |
|
559 |
++ self._tag = strxor(self._cipherMAC.digest(), |
|
560 |
++ self._s_0)[:self._mac_len] |
|
561 |
++ |
|
562 |
++ if self.mode == MODE_GCM: |
|
563 |
++ # Step 5 in NIST SP 800-38D, Algorithm 4 - Compute S |
|
564 |
++ self._cipherMAC.zero_pad() |
|
565 |
++ auth_len = self._cipherMAC.get_len() - self._msg_len |
|
566 |
++ for tlen in (auth_len, self._msg_len): |
|
567 |
++ self._cipherMAC.update(long_to_bytes(8 * tlen, 8)) |
|
568 |
++ s_tag = self._cipherMAC.digest() |
|
569 |
++ # Step 6 - Compute T |
|
570 |
++ self._tag = self._tag_cipher.encrypt(s_tag)[:self._mac_len] |
|
571 |
++ |
|
572 |
++ if self.mode == MODE_EAX: |
|
573 |
++ tag = bchr(0) * self.block_size |
|
574 |
++ for i in xrange(3): |
|
575 |
++ tag = strxor(tag, self._omac[i].digest()) |
|
576 |
++ self._tag = tag[:self._mac_len] |
|
577 |
++ |
|
578 |
++ if self.mode == MODE_SIV: |
|
579 |
++ self._tag = self._cipherMAC.derive() |
|
580 |
++ |
|
581 |
++ return self._tag |
|
582 |
++ |
|
583 |
+ |
|
584 |
+- return tag |
|
585 |
+ |
|
586 |
+- raise TypeError("digest() not supported by this mode of operation") |
|
587 |
+ |
|
588 |
+ def hexdigest(self): |
|
589 |
+ """Compute the *printable* MAC tag in an AEAD mode. |
|
590 |
+@@ -804,39 +939,19 @@ class BlockAlgo: |
|
591 |
+ or the key is incorrect. |
|
592 |
+ """ |
|
593 |
+ |
|
594 |
+- if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
595 |
+- if self.verify not in self._next: |
|
596 |
+- raise TypeError("verify() cannot be called when encrypting a message") |
|
597 |
+- self._next = [self.verify] |
|
598 |
+- |
|
599 |
+- if self.mode == MODE_CCM: |
|
600 |
+- |
|
601 |
+- if self._assoc_len is None: |
|
602 |
+- self._start_ccm(assoc_len=self._assoc_buffer_len) |
|
603 |
+- if self._msg_len is None: |
|
604 |
+- self._start_ccm(msg_len=0) |
|
605 |
+- self._update(b(""), do_zero_padding=True) |
|
606 |
+- u = strxor(self._t, self._s_0)[:self._mac_len] |
|
607 |
+- |
|
608 |
+- if self.mode == MODE_EAX: |
|
609 |
+- |
|
610 |
+- u = bchr(0)*self.block_size |
|
611 |
+- for i in xrange(3): |
|
612 |
+- u = strxor(u, self._omac[i].digest()) |
|
613 |
+- u = u[:self._mac_len] |
|
614 |
+- |
|
615 |
+- if self.mode == MODE_SIV: |
|
616 |
+- u = self._prf.derive() |
|
617 |
+- |
|
618 |
+- res = 0 |
|
619 |
+- # Constant-time comparison |
|
620 |
+- for x,y in zip(u, mac_tag): |
|
621 |
+- res |= bord(x) ^ bord(y) |
|
622 |
+- if res or len(mac_tag)!=self._mac_len: |
|
623 |
+- raise ValueError("MAC check failed") |
|
624 |
+- return |
|
625 |
++ if self.mode not in (MODE_CCM, MODE_EAX, MODE_SIV, MODE_GCM): |
|
626 |
++ raise TypeError("verify() not supported by this mode of operation") |
|
627 |
+ |
|
628 |
+- raise TypeError("verify() not supported by this mode of operation") |
|
629 |
++ if self.verify not in self._next: |
|
630 |
++ raise TypeError("verify() cannot be called when encrypting a message") |
|
631 |
++ self._next = [self.verify] |
|
632 |
++ |
|
633 |
++ res = 0 |
|
634 |
++ # Constant-time comparison |
|
635 |
++ for x, y in zip(self._compute_mac(), mac_tag): |
|
636 |
++ res |= bord(x) ^ bord(y) |
|
637 |
++ if res or len(mac_tag) != self._mac_len: |
|
638 |
++ raise ValueError("MAC check failed") |
|
639 |
+ |
|
640 |
+ def hexverify(self, hex_mac_tag): |
|
641 |
+ """Validate the *printable* MAC tag in an AEAD mode. |
|
642 |
+--- a/lib/Crypto/Hash/__init__.py_org 2019-05-20 22:35:48.113386172 +0530 |
|
643 |
+@@ -50,7 +50,7 @@ The hashing modules here all support the |
|
644 |
+ """ |
|
645 |
+ |
|
646 |
+ __all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD', 'SHA', |
|
647 |
+- 'SHA224', 'SHA256', 'SHA384', 'SHA512'] |
|
648 |
++ 'SHA224', 'SHA256', 'SHA384', 'SHA512', 'CMAC'] |
|
649 |
+ __revision__ = "$Id$" |
|
650 |
+ |
|
651 |
+ |
|
652 |
+--- a/lib/Crypto/SelfTest/Hash/__init__.py_org 2019-05-20 22:36:33.661387082 +0530 |
|
653 |
+@@ -29,6 +29,7 @@ __revision__ = "$Id$" |
|
654 |
+ def get_tests(config={}): |
|
655 |
+ tests = [] |
|
656 |
+ from Crypto.SelfTest.Hash import test_HMAC; tests += test_HMAC.get_tests(config=config) |
|
657 |
++ from Crypto.SelfTest.Hash import test_CMAC; tests += test_CMAC.get_tests(config=config) |
|
658 |
+ from Crypto.SelfTest.Hash import test_MD2; tests += test_MD2.get_tests(config=config) |
|
659 |
+ from Crypto.SelfTest.Hash import test_MD4; tests += test_MD4.get_tests(config=config) |
|
660 |
+ from Crypto.SelfTest.Hash import test_MD5; tests += test_MD5.get_tests(config=config) |
|
661 |
+--- a/lib/Crypto/SelfTest/Hash/test_CMAC.py_org 2019-05-20 22:37:14.077387889 +0530 |
|
662 |
+@@ -0,0 +1,248 @@ |
|
663 |
++# |
|
664 |
++# SelfTest/Hash/CMAC.py: Self-test for the CMAC module |
|
665 |
++# |
|
666 |
++# =================================================================== |
|
667 |
++# The contents of this file are dedicated to the public domain. To |
|
668 |
++# the extent that dedication to the public domain is not available, |
|
669 |
++# everyone is granted a worldwide, perpetual, royalty-free, |
|
670 |
++# non-exclusive license to exercise all rights associated with the |
|
671 |
++# contents of this file for any purpose whatsoever. |
|
672 |
++# No rights are reserved. |
|
673 |
++# |
|
674 |
++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
675 |
++# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
676 |
++# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
677 |
++# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|
678 |
++# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
679 |
++# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
680 |
++# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
681 |
++# SOFTWARE. |
|
682 |
++# =================================================================== |
|
683 |
++ |
|
684 |
++"""Self-test suite for Crypto.Hash.CMAC""" |
|
685 |
++ |
|
686 |
++import sys |
|
687 |
++if sys.version_info[0] == 2 and sys.version_info[1] == 1: |
|
688 |
++ from Crypto.Util.py21compat import * |
|
689 |
++from Crypto.Util.py3compat import * |
|
690 |
++ |
|
691 |
++from common import dict |
|
692 |
++ |
|
693 |
++from Crypto.Hash import CMAC |
|
694 |
++from Crypto.Cipher import AES, DES3 |
|
695 |
++ |
|
696 |
++# This is a list of (key, data, result, description, module) tuples. |
|
697 |
++test_data = [ |
|
698 |
++ |
|
699 |
++ ## Test vectors from RFC 4493 ## |
|
700 |
++ ## The are also in NIST SP 800 38B D.2 ## |
|
701 |
++ ( '2b7e151628aed2a6abf7158809cf4f3c', |
|
702 |
++ '', |
|
703 |
++ 'bb1d6929e95937287fa37d129b756746', |
|
704 |
++ 'RFC 4493 #1', |
|
705 |
++ AES |
|
706 |
++ ), |
|
707 |
++ |
|
708 |
++ ( '2b7e151628aed2a6abf7158809cf4f3c', |
|
709 |
++ '6bc1bee22e409f96e93d7e117393172a', |
|
710 |
++ '070a16b46b4d4144f79bdd9dd04a287c', |
|
711 |
++ 'RFC 4493 #2', |
|
712 |
++ AES |
|
713 |
++ ), |
|
714 |
++ |
|
715 |
++ ( '2b7e151628aed2a6abf7158809cf4f3c', |
|
716 |
++ '6bc1bee22e409f96e93d7e117393172a'+ |
|
717 |
++ 'ae2d8a571e03ac9c9eb76fac45af8e51'+ |
|
718 |
++ '30c81c46a35ce411', |
|
719 |
++ 'dfa66747de9ae63030ca32611497c827', |
|
720 |
++ 'RFC 4493 #3', |
|
721 |
++ AES |
|
722 |
++ ), |
|
723 |
++ |
|
724 |
++ ( '2b7e151628aed2a6abf7158809cf4f3c', |
|
725 |
++ '6bc1bee22e409f96e93d7e117393172a'+ |
|
726 |
++ 'ae2d8a571e03ac9c9eb76fac45af8e51'+ |
|
727 |
++ '30c81c46a35ce411e5fbc1191a0a52ef'+ |
|
728 |
++ 'f69f2445df4f9b17ad2b417be66c3710', |
|
729 |
++ '51f0bebf7e3b9d92fc49741779363cfe', |
|
730 |
++ 'RFC 4493 #4', |
|
731 |
++ AES |
|
732 |
++ ), |
|
733 |
++ |
|
734 |
++ ## The rest of Appendix D of NIST SP 800 38B |
|
735 |
++ ## was not totally correct. |
|
736 |
++ ## Values in Examples 14, 15, 18, and 19 were wrong. |
|
737 |
++ ## The updated test values are published in: |
|
738 |
++ ## http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf |
|
739 |
++ |
|
740 |
++ ( '8e73b0f7da0e6452c810f32b809079e5'+ |
|
741 |
++ '62f8ead2522c6b7b', |
|
742 |
++ '', |
|
743 |
++ 'd17ddf46adaacde531cac483de7a9367', |
|
744 |
++ 'NIST SP 800 38B D.2 Example 5', |
|
745 |
++ AES |
|
746 |
++ ), |
|
747 |
++ |
|
748 |
++ ( '8e73b0f7da0e6452c810f32b809079e5'+ |
|
749 |
++ '62f8ead2522c6b7b', |
|
750 |
++ '6bc1bee22e409f96e93d7e117393172a', |
|
751 |
++ '9e99a7bf31e710900662f65e617c5184', |
|
752 |
++ 'NIST SP 800 38B D.2 Example 6', |
|
753 |
++ AES |
|
754 |
++ ), |
|
755 |
++ |
|
756 |
++ ( '8e73b0f7da0e6452c810f32b809079e5'+ |
|
757 |
++ '62f8ead2522c6b7b', |
|
758 |
++ '6bc1bee22e409f96e93d7e117393172a'+ |
|
759 |
++ 'ae2d8a571e03ac9c9eb76fac45af8e51'+ |
|
760 |
++ '30c81c46a35ce411', |
|
761 |
++ '8a1de5be2eb31aad089a82e6ee908b0e', |
|
762 |
++ 'NIST SP 800 38B D.2 Example 7', |
|
763 |
++ AES |
|
764 |
++ ), |
|
765 |
++ |
|
766 |
++ ( '8e73b0f7da0e6452c810f32b809079e5'+ |
|
767 |
++ '62f8ead2522c6b7b', |
|
768 |
++ '6bc1bee22e409f96e93d7e117393172a'+ |
|
769 |
++ 'ae2d8a571e03ac9c9eb76fac45af8e51'+ |
|
770 |
++ '30c81c46a35ce411e5fbc1191a0a52ef'+ |
|
771 |
++ 'f69f2445df4f9b17ad2b417be66c3710', |
|
772 |
++ 'a1d5df0eed790f794d77589659f39a11', |
|
773 |
++ 'NIST SP 800 38B D.2 Example 8', |
|
774 |
++ AES |
|
775 |
++ ), |
|
776 |
++ |
|
777 |
++ ( '603deb1015ca71be2b73aef0857d7781'+ |
|
778 |
++ '1f352c073b6108d72d9810a30914dff4', |
|
779 |
++ '', |
|
780 |
++ '028962f61b7bf89efc6b551f4667d983', |
|
781 |
++ 'NIST SP 800 38B D.3 Example 9', |
|
782 |
++ AES |
|
783 |
++ ), |
|
784 |
++ |
|
785 |
++ ( '603deb1015ca71be2b73aef0857d7781'+ |
|
786 |
++ '1f352c073b6108d72d9810a30914dff4', |
|
787 |
++ '6bc1bee22e409f96e93d7e117393172a', |
|
788 |
++ '28a7023f452e8f82bd4bf28d8c37c35c', |
|
789 |
++ 'NIST SP 800 38B D.3 Example 10', |
|
790 |
++ AES |
|
791 |
++ ), |
|
792 |
++ |
|
793 |
++ ( '603deb1015ca71be2b73aef0857d7781'+ |
|
794 |
++ '1f352c073b6108d72d9810a30914dff4', |
|
795 |
++ '6bc1bee22e409f96e93d7e117393172a'+ |
|
796 |
++ 'ae2d8a571e03ac9c9eb76fac45af8e51'+ |
|
797 |
++ '30c81c46a35ce411', |
|
798 |
++ 'aaf3d8f1de5640c232f5b169b9c911e6', |
|
799 |
++ 'NIST SP 800 38B D.3 Example 11', |
|
800 |
++ AES |
|
801 |
++ ), |
|
802 |
++ |
|
803 |
++ ( '603deb1015ca71be2b73aef0857d7781'+ |
|
804 |
++ '1f352c073b6108d72d9810a30914dff4', |
|
805 |
++ '6bc1bee22e409f96e93d7e117393172a'+ |
|
806 |
++ 'ae2d8a571e03ac9c9eb76fac45af8e51'+ |
|
807 |
++ '30c81c46a35ce411e5fbc1191a0a52ef'+ |
|
808 |
++ 'f69f2445df4f9b17ad2b417be66c3710', |
|
809 |
++ 'e1992190549f6ed5696a2c056c315410', |
|
810 |
++ 'NIST SP 800 38B D.3 Example 12', |
|
811 |
++ AES |
|
812 |
++ ), |
|
813 |
++ |
|
814 |
++ ( '8aa83bf8cbda1062'+ |
|
815 |
++ '0bc1bf19fbb6cd58'+ |
|
816 |
++ 'bc313d4a371ca8b5', |
|
817 |
++ '', |
|
818 |
++ 'b7a688e122ffaf95', |
|
819 |
++ 'NIST SP 800 38B D.4 Example 13', |
|
820 |
++ DES3 |
|
821 |
++ ), |
|
822 |
++ |
|
823 |
++ ( '8aa83bf8cbda1062'+ |
|
824 |
++ '0bc1bf19fbb6cd58'+ |
|
825 |
++ 'bc313d4a371ca8b5', |
|
826 |
++ '6bc1bee22e409f96', |
|
827 |
++ '8e8f293136283797', |
|
828 |
++ 'NIST SP 800 38B D.4 Example 14', |
|
829 |
++ DES3 |
|
830 |
++ ), |
|
831 |
++ |
|
832 |
++ ( '8aa83bf8cbda1062'+ |
|
833 |
++ '0bc1bf19fbb6cd58'+ |
|
834 |
++ 'bc313d4a371ca8b5', |
|
835 |
++ '6bc1bee22e409f96'+ |
|
836 |
++ 'e93d7e117393172a'+ |
|
837 |
++ 'ae2d8a57', |
|
838 |
++ '743ddbe0ce2dc2ed', |
|
839 |
++ 'NIST SP 800 38B D.4 Example 15', |
|
840 |
++ DES3 |
|
841 |
++ ), |
|
842 |
++ |
|
843 |
++ ( '8aa83bf8cbda1062'+ |
|
844 |
++ '0bc1bf19fbb6cd58'+ |
|
845 |
++ 'bc313d4a371ca8b5', |
|
846 |
++ '6bc1bee22e409f96'+ |
|
847 |
++ 'e93d7e117393172a'+ |
|
848 |
++ 'ae2d8a571e03ac9c'+ |
|
849 |
++ '9eb76fac45af8e51', |
|
850 |
++ '33e6b1092400eae5', |
|
851 |
++ 'NIST SP 800 38B D.4 Example 16', |
|
852 |
++ DES3 |
|
853 |
++ ), |
|
854 |
++ |
|
855 |
++ ( '4cf15134a2850dd5'+ |
|
856 |
++ '8a3d10ba80570d38', |
|
857 |
++ '', |
|
858 |
++ 'bd2ebf9a3ba00361', |
|
859 |
++ 'NIST SP 800 38B D.7 Example 17', |
|
860 |
++ DES3 |
|
861 |
++ ), |
|
862 |
++ |
|
863 |
++ ( '4cf15134a2850dd5'+ |
|
864 |
++ '8a3d10ba80570d38', |
|
865 |
++ '6bc1bee22e409f96', |
|
866 |
++ '4ff2ab813c53ce83', |
|
867 |
++ 'NIST SP 800 38B D.7 Example 18', |
|
868 |
++ DES3 |
|
869 |
++ ), |
|
870 |
++ |
|
871 |
++ ( '4cf15134a2850dd5'+ |
|
872 |
++ '8a3d10ba80570d38', |
|
873 |
++ '6bc1bee22e409f96'+ |
|
874 |
++ 'e93d7e117393172a'+ |
|
875 |
++ 'ae2d8a57', |
|
876 |
++ '62dd1b471902bd4e', |
|
877 |
++ 'NIST SP 800 38B D.7 Example 19', |
|
878 |
++ DES3 |
|
879 |
++ ), |
|
880 |
++ |
|
881 |
++ ( '4cf15134a2850dd5'+ |
|
882 |
++ '8a3d10ba80570d38', |
|
883 |
++ '6bc1bee22e409f96'+ |
|
884 |
++ 'e93d7e117393172a'+ |
|
885 |
++ 'ae2d8a571e03ac9c'+ |
|
886 |
++ '9eb76fac45af8e51', |
|
887 |
++ '31b1e431dabc4eb8', |
|
888 |
++ 'NIST SP 800 38B D.7 Example 20', |
|
889 |
++ DES3 |
|
890 |
++ ), |
|
891 |
++ |
|
892 |
++] |
|
893 |
++ |
|
894 |
++def get_tests(config={}): |
|
895 |
++ global test_data |
|
896 |
++ from common import make_mac_tests |
|
897 |
++ |
|
898 |
++ # Add new() parameters to the back of each test vector |
|
899 |
++ params_test_data = [] |
|
900 |
++ for row in test_data: |
|
901 |
++ t = list(row) |
|
902 |
++ t[4] = dict(ciphermod=t[4]) |
|
903 |
++ params_test_data.append(t) |
|
904 |
++ |
|
905 |
++ return make_mac_tests(CMAC, "CMAC", params_test_data) |
|
906 |
++ |
|
907 |
++if __name__ == '__main__': |
|
908 |
++ import unittest |
|
909 |
++ suite = lambda: unittest.TestSuite(get_tests()) |
|
910 |
++ unittest.main(defaultTest='suite') |
|
911 |
+--- a/pct-speedtest.py_org 2019-05-20 22:39:52.053391045 +0530 |
|
912 |
+@@ -29,7 +29,7 @@ import sys |
|
913 |
+ |
|
914 |
+ from Crypto.PublicKey import RSA |
|
915 |
+ from Crypto.Cipher import AES, ARC2, ARC4, Blowfish, CAST, DES3, DES, XOR |
|
916 |
+-from Crypto.Hash import MD2, MD4, MD5, SHA256, SHA |
|
917 |
++from Crypto.Hash import MD2, MD4, MD5, SHA256, SHA, CMAC |
|
918 |
+ try: |
|
919 |
+ from Crypto.Hash import RIPEMD |
|
920 |
+ except ImportError: # Some builds of PyCrypto don't have the RIPEMD module |
|
921 |
+@@ -214,6 +214,8 @@ class Benchmark: |
|
922 |
+ self.test_encryption("%s-CCM" % (cipher_name,), module, key_bytes, module.MODE_CCM) |
|
923 |
+ if hasattr(module, "MODE_EAX"): |
|
924 |
+ self.test_encryption("%s-EAX" % (cipher_name,), module, key_bytes, module.MODE_EAX) |
|
925 |
++ if hasattr(module, "MODE_GCM"): |
|
926 |
++ self.test_encryption("%s-GCM" % (cipher_name,), module, key_bytes, module.MODE_GCM) |
|
927 |
+ for cipher_name, module, key_bytes in stream_specs: |
|
928 |
+ self.test_key_setup(cipher_name, module, key_bytes, None) |
|
929 |
+ self.test_encryption(cipher_name, module, key_bytes, None) |
|
930 |
+@@ -221,6 +223,24 @@ class Benchmark: |
|
931 |
+ for hash_name, module in hash_specs: |
|
932 |
+ self.test_hash_small(hash_name, module) |
|
933 |
+ self.test_hash_large(hash_name, module) |
|
934 |
++ # CMAC |
|
935 |
++ for cipher_name, module, key_size in (("AES128", AES, 16),): |
|
936 |
++ self.test_cmac_small(cipher_name+"-CMAC", CMAC.new, module, key_size) |
|
937 |
++ self.test_cmac_large(cipher_name+"-CMAC", CMAC.new, module, key_size) |
|
938 |
++ |
|
939 |
++ def test_cmac_small(self, mac_name, cmac_constructor, ciphermod, key_size): |
|
940 |
++ keys = iter(self.random_keys(key_size)) |
|
941 |
++ if sys.version_info[0] == 2: |
|
942 |
++ mac_constructor = lambda data=None: cmac_constructor(keys.next(), data, ciphermod) |
|
943 |
++ else: |
|
944 |
++ mac_constructor = lambda data=None: cmac_constructor(keys.__next__(), data, ciphermod) |
|
945 |
++ self.test_hash_small(mac_name, mac_constructor, ciphermod.block_size) |
|
946 |
++ |
|
947 |
++ def test_cmac_large(self, mac_name, cmac_constructor, ciphermod, key_size): |
|
948 |
++ key = self.random_keys(key_size)[0] |
|
949 |
++ mac_constructor = lambda data=None: cmac_constructor(key, data, ciphermod) |
|
950 |
++ self.test_hash_large(mac_name, mac_constructor, ciphermod.block_size) |
|
951 |
++ |
|
952 |
+ |
|
953 |
+ if __name__ == '__main__': |
|
954 |
+ Benchmark().run() |
|
955 |
+--- a/lib/Crypto/SelfTest/Cipher/common.py_org 2019-05-20 22:50:03.969403268 +0530 |
|
956 |
+@@ -671,7 +671,7 @@ def make_block_tests(module, module_name |
|
957 |
+ ] |
|
958 |
+ extra_tests_added = 1 |
|
959 |
+ # Extract associated data and MAC for AEAD modes |
|
960 |
+- if p_mode in ('CCM', 'EAX', 'SIV'): |
|
961 |
++ if p_mode in ('CCM', 'EAX', 'SIV', 'GCM'): |
|
962 |
+ assoc_data, params['plaintext'] = params['plaintext'].split('|') |
|
963 |
+ assoc_data2, params['ciphertext'], params['mac'] = params['ciphertext'].split('|') |
|
964 |
+ params['assoc_data'] = assoc_data.split("-") |
|
965 |
+@@ -698,7 +698,7 @@ def make_block_tests(module, module_name |
|
966 |
+ CCMMACLengthTest(module), |
|
967 |
+ CCMSplitEncryptionTest(module), |
|
968 |
+ ] |
|
969 |
+- for aead_mode in ("MODE_CCM","MODE_EAX", "MODE_SIV"): |
|
970 |
++ for aead_mode in ("MODE_CCM","MODE_EAX", "MODE_SIV", "MODE_GCM"): |
|
971 |
+ if hasattr(module, aead_mode): |
|
972 |
+ key_sizes = [] |
|
973 |
+ try: |
|
974 |
+--- a/lib/Crypto/SelfTest/Cipher/test_AES.py_org 2019-05-20 22:51:26.593404918 +0530 |
|
975 |
+@@ -1765,6 +1765,202 @@ test_data = [ |
|
976 |
+ 'RFC5297 A.2', |
|
977 |
+ dict(mode='SIV', nonce='09f911029d74e35bd84156c5635688c0') |
|
978 |
+ ), |
|
979 |
++ # Test vectors for GCM taken from |
|
980 |
++ # http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf |
|
981 |
++ # This is a list of tuples with 5 items: |
|
982 |
++ # |
|
983 |
++ # 1. Header + '|' + plaintext |
|
984 |
++ # 2. Header + '|' + ciphertext + '|' + MAC |
|
985 |
++ # 3. AES-128 key |
|
986 |
++ # 4. Description |
|
987 |
++ # 5. Dictionary of parameters to be passed to AES.new(). |
|
988 |
++ # It must include the nonce. |
|
989 |
++ # |
|
990 |
++ ( '|', |
|
991 |
++ '||58e2fccefa7e3061367f1d57a4e7455a', |
|
992 |
++ '00000000000000000000000000000000', |
|
993 |
++ 'GCM Test Case 1', |
|
994 |
++ dict(mode='GCM', nonce='000000000000000000000000') |
|
995 |
++ ), |
|
996 |
++ |
|
997 |
++ ( '|00000000000000000000000000000000', |
|
998 |
++ '|0388dace60b6a392f328c2b971b2fe78|ab6e47d42cec13bdf53a67b21257bddf', |
|
999 |
++ '00000000000000000000000000000000', |
|
1000 |
++ 'GCM Test Case 2', |
|
1001 |
++ dict(mode='GCM', nonce='000000000000000000000000') |
|
1002 |
++ ), |
|
1003 |
++ |
|
1004 |
++ ( '|d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1005 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', |
|
1006 |
++ '|42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' + |
|
1007 |
++ '21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985|' + |
|
1008 |
++ '4d5c2af327cd64a62cf35abd2ba6fab4', |
|
1009 |
++ 'feffe9928665731c6d6a8f9467308308', |
|
1010 |
++ 'GCM Test Case 3', |
|
1011 |
++ dict(mode='GCM', nonce='cafebabefacedbaddecaf888') |
|
1012 |
++ ), |
|
1013 |
++ |
|
1014 |
++ ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1015 |
++ 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1016 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', |
|
1017 |
++ 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1018 |
++ '42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e' + |
|
1019 |
++ '21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091|' + |
|
1020 |
++ '5bc94fbc3221a5db94fae95ae7121a47', |
|
1021 |
++ 'feffe9928665731c6d6a8f9467308308', |
|
1022 |
++ 'GCM Test Case 4', |
|
1023 |
++ dict(mode='GCM', nonce='cafebabefacedbaddecaf888') |
|
1024 |
++ ), |
|
1025 |
++ |
|
1026 |
++ ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1027 |
++ 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1028 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', |
|
1029 |
++ 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1030 |
++ '61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423' + |
|
1031 |
++ '73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598|' + |
|
1032 |
++ '3612d2e79e3b0785561be14aaca2fccb', |
|
1033 |
++ 'feffe9928665731c6d6a8f9467308308', |
|
1034 |
++ 'GCM Test Case 5', |
|
1035 |
++ dict(mode='GCM', nonce='cafebabefacedbad') |
|
1036 |
++ ), |
|
1037 |
++ |
|
1038 |
++ ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1039 |
++ 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1040 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', |
|
1041 |
++ 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1042 |
++ '8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7' + |
|
1043 |
++ '01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5|' + |
|
1044 |
++ '619cc5aefffe0bfa462af43c1699d050', |
|
1045 |
++ 'feffe9928665731c6d6a8f9467308308', |
|
1046 |
++ 'GCM Test Case 6', |
|
1047 |
++ dict(mode='GCM', nonce='9313225df88406e555909c5aff5269aa'+ |
|
1048 |
++ '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+ |
|
1049 |
++ '16aedbf5a0de6a57a637b39b' ) |
|
1050 |
++ ), |
|
1051 |
++ |
|
1052 |
++ ( '|', |
|
1053 |
++ '||cd33b28ac773f74ba00ed1f312572435', |
|
1054 |
++ '000000000000000000000000000000000000000000000000', |
|
1055 |
++ 'GCM Test Case 7', |
|
1056 |
++ dict(mode='GCM', nonce='000000000000000000000000') |
|
1057 |
++ ), |
|
1058 |
++ |
|
1059 |
++ ( '|00000000000000000000000000000000', |
|
1060 |
++ '|98e7247c07f0fe411c267e4384b0f600|2ff58d80033927ab8ef4d4587514f0fb', |
|
1061 |
++ '000000000000000000000000000000000000000000000000', |
|
1062 |
++ 'GCM Test Case 8', |
|
1063 |
++ dict(mode='GCM', nonce='000000000000000000000000') |
|
1064 |
++ ), |
|
1065 |
++ |
|
1066 |
++ ( '|d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1067 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', |
|
1068 |
++ '|3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' + |
|
1069 |
++ '7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256|' + |
|
1070 |
++ '9924a7c8587336bfb118024db8674a14', |
|
1071 |
++ 'feffe9928665731c6d6a8f9467308308feffe9928665731c', |
|
1072 |
++ 'GCM Test Case 9', |
|
1073 |
++ dict(mode='GCM', nonce='cafebabefacedbaddecaf888') |
|
1074 |
++ ), |
|
1075 |
++ |
|
1076 |
++ ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1077 |
++ 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1078 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', |
|
1079 |
++ 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1080 |
++ '3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c' + |
|
1081 |
++ '7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710|' + |
|
1082 |
++ '2519498e80f1478f37ba55bd6d27618c', |
|
1083 |
++ 'feffe9928665731c6d6a8f9467308308feffe9928665731c', |
|
1084 |
++ 'GCM Test Case 10', |
|
1085 |
++ dict(mode='GCM', nonce='cafebabefacedbaddecaf888') |
|
1086 |
++ ), |
|
1087 |
++ |
|
1088 |
++ ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1089 |
++ 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1090 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', |
|
1091 |
++ 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1092 |
++ '0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057' + |
|
1093 |
++ 'fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7|' + |
|
1094 |
++ '65dcc57fcf623a24094fcca40d3533f8', |
|
1095 |
++ 'feffe9928665731c6d6a8f9467308308feffe9928665731c', |
|
1096 |
++ 'GCM Test Case 11', |
|
1097 |
++ dict(mode='GCM', nonce='cafebabefacedbad') |
|
1098 |
++ ), |
|
1099 |
++ |
|
1100 |
++ ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1101 |
++ 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1102 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', |
|
1103 |
++ 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1104 |
++ 'd27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45' + |
|
1105 |
++ '81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b|' + |
|
1106 |
++ 'dcf566ff291c25bbb8568fc3d376a6d9', |
|
1107 |
++ 'feffe9928665731c6d6a8f9467308308feffe9928665731c', |
|
1108 |
++ 'GCM Test Case 12', |
|
1109 |
++ dict(mode='GCM', nonce='9313225df88406e555909c5aff5269aa'+ |
|
1110 |
++ '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+ |
|
1111 |
++ '16aedbf5a0de6a57a637b39b' ) |
|
1112 |
++ ), |
|
1113 |
++ |
|
1114 |
++ ( '|', |
|
1115 |
++ '||530f8afbc74536b9a963b4f1c4cb738b', |
|
1116 |
++ '0000000000000000000000000000000000000000000000000000000000000000', |
|
1117 |
++ 'GCM Test Case 13', |
|
1118 |
++ dict(mode='GCM', nonce='000000000000000000000000') |
|
1119 |
++ ), |
|
1120 |
++ |
|
1121 |
++ ( '|00000000000000000000000000000000', |
|
1122 |
++ '|cea7403d4d606b6e074ec5d3baf39d18|d0d1c8a799996bf0265b98b5d48ab919', |
|
1123 |
++ '0000000000000000000000000000000000000000000000000000000000000000', |
|
1124 |
++ 'GCM Test Case 14', |
|
1125 |
++ dict(mode='GCM', nonce='000000000000000000000000') |
|
1126 |
++ ), |
|
1127 |
++ |
|
1128 |
++ ( '|d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1129 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255', |
|
1130 |
++ '|522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' + |
|
1131 |
++ '8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad|' + |
|
1132 |
++ 'b094dac5d93471bdec1a502270e3cc6c', |
|
1133 |
++ 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', |
|
1134 |
++ 'GCM Test Case 15', |
|
1135 |
++ dict(mode='GCM', nonce='cafebabefacedbaddecaf888') |
|
1136 |
++ ), |
|
1137 |
++ |
|
1138 |
++ ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1139 |
++ 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1140 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', |
|
1141 |
++ 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1142 |
++ '522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa' + |
|
1143 |
++ '8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662|' + |
|
1144 |
++ '76fc6ece0f4e1768cddf8853bb2d551b', |
|
1145 |
++ 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', |
|
1146 |
++ 'GCM Test Case 16', |
|
1147 |
++ dict(mode='GCM', nonce='cafebabefacedbaddecaf888') |
|
1148 |
++ ), |
|
1149 |
++ |
|
1150 |
++ ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1151 |
++ 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1152 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', |
|
1153 |
++ 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1154 |
++ 'c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0' + |
|
1155 |
++ 'feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f|' + |
|
1156 |
++ '3a337dbf46a792c45e454913fe2ea8f2', |
|
1157 |
++ 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', |
|
1158 |
++ 'GCM Test Case 17', |
|
1159 |
++ dict(mode='GCM', nonce='cafebabefacedbad') |
|
1160 |
++ ), |
|
1161 |
++ |
|
1162 |
++ ( 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1163 |
++ 'd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72' + |
|
1164 |
++ '1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39', |
|
1165 |
++ 'feedfacedeadbeeffeedfacedeadbeefabaddad2|' + |
|
1166 |
++ '5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4' + |
|
1167 |
++ '0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f|' + |
|
1168 |
++ 'a44a8266ee1c8eb0c8b5d4cf5ae9f19a', |
|
1169 |
++ 'feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308', |
|
1170 |
++ 'GCM Test Case 18', |
|
1171 |
++ dict(mode='GCM', nonce='9313225df88406e555909c5aff5269aa'+ |
|
1172 |
++ '6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b5254'+ |
|
1173 |
++ '16aedbf5a0de6a57a637b39b' ) |
|
1174 |
++ ), |
|
1175 |
+ ] |
|
1176 |
+ |
|
1177 |
+ def get_tests(config={}): |
|
1178 |
+--- a/setup.py_org 2019-05-20 22:54:47.889408939 +0530 |
|
1179 |
+@@ -430,7 +430,9 @@ kw = {'name':"pycrypto", |
|
1180 |
+ Extension("Crypto.Util.strxor", |
|
1181 |
+ include_dirs=['src/'], |
|
1182 |
+ sources=['src/strxor.c']), |
|
1183 |
+- |
|
1184 |
++ Extension("Crypto.Util.galois", |
|
1185 |
++ include_dirs=['src/'], |
|
1186 |
++ sources=['src/galois.c']), |
|
1187 |
+ # Counter modules |
|
1188 |
+ Extension("Crypto.Util._counter", |
|
1189 |
+ include_dirs=['src/'], |
|
1190 |
+--- a/src/galois.c_org 2019-05-20 22:56:06.813410516 +0530 |
|
1191 |
+@@ -0,0 +1,234 @@ |
|
1192 |
++/* |
|
1193 |
++ * galois.c: arithmetic in Galois Fields |
|
1194 |
++ * |
|
1195 |
++ * =================================================================== |
|
1196 |
++ * The contents of this file are dedicated to the public domain. To |
|
1197 |
++ * the extent that dedication to the public domain is not available, |
|
1198 |
++ * everyone is granted a worldwide, perpetual, royalty-free, |
|
1199 |
++ * non-exclusive license to exercise all rights associated with the |
|
1200 |
++ * contents of this file for any purpose whatsoever. |
|
1201 |
++ * No rights are reserved. |
|
1202 |
++ * |
|
1203 |
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
1204 |
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
1205 |
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
1206 |
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|
1207 |
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
1208 |
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
1209 |
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
1210 |
++ * SOFTWARE. |
|
1211 |
++ * =================================================================== |
|
1212 |
++ */ |
|
1213 |
++ |
|
1214 |
++#include "pycrypto_common.h" |
|
1215 |
++#include <stddef.h> |
|
1216 |
++#include <assert.h> |
|
1217 |
++#include <string.h> |
|
1218 |
++ |
|
1219 |
++/** |
|
1220 |
++ * Big Endian to word conversions |
|
1221 |
++ */ |
|
1222 |
++static uint32_t be_to_word(const uint8_t fb[4]) |
|
1223 |
++{ |
|
1224 |
++ uint32_t tmp; |
|
1225 |
++ int i; |
|
1226 |
++ tmp = 0; |
|
1227 |
++ for (i=0; i<4; i++) |
|
1228 |
++ tmp = tmp<<8 ^ *fb++; |
|
1229 |
++ return tmp; |
|
1230 |
++} |
|
1231 |
++ |
|
1232 |
++static void block_to_words(uint32_t w[4], const uint8_t block[16]) |
|
1233 |
++{ |
|
1234 |
++ int i; |
|
1235 |
++ for (i=0; i<4; i++) { |
|
1236 |
++ w[i] = be_to_word(&block[i*4]); |
|
1237 |
++ } |
|
1238 |
++} |
|
1239 |
++ |
|
1240 |
++/** |
|
1241 |
++ * Word to Big Endian conversions |
|
1242 |
++ */ |
|
1243 |
++static void word_to_be(uint8_t fb[4], uint32_t w) |
|
1244 |
++{ |
|
1245 |
++ int i; |
|
1246 |
++ for (i=0; i<4; i++) { |
|
1247 |
++ fb[3-i] = (uint8_t) w; |
|
1248 |
++ w >>= 8; |
|
1249 |
++ } |
|
1250 |
++} |
|
1251 |
++ |
|
1252 |
++static void words_to_block(uint8_t block[16], const uint32_t w[4]) |
|
1253 |
++{ |
|
1254 |
++ int i; |
|
1255 |
++ for (i=0; i<4; i++) { |
|
1256 |
++ word_to_be(&block[i*4], w[i]); |
|
1257 |
++ } |
|
1258 |
++} |
|
1259 |
++ |
|
1260 |
++/** |
|
1261 |
++ * Multiply to elements of GF(2**128) using the reducing polynomial |
|
1262 |
++ * (x^128 + x^7 + x^2 + x + 1). |
|
1263 |
++ */ |
|
1264 |
++static void gcm_mult(uint32_t z[4], const uint32_t x[4], const uint32_t y[4]) |
|
1265 |
++{ |
|
1266 |
++ uint32_t v[4]; |
|
1267 |
++ int i; |
|
1268 |
++ |
|
1269 |
++ /** z, v = 0, y **/ |
|
1270 |
++ for (i=0; i<4; i++) { |
|
1271 |
++ z[i] = 0; |
|
1272 |
++ v[i] = y[i]; |
|
1273 |
++ } |
|
1274 |
++ for (i=0; i<128; i++) { |
|
1275 |
++ uint32_t c; |
|
1276 |
++ |
|
1277 |
++ /** z ^= (x>>i&1)*v **/ |
|
1278 |
++ if ((x[i>>5] >> (~i&31)) & 1) { |
|
1279 |
++ z[0] ^= v[0]; |
|
1280 |
++ z[1] ^= v[1]; |
|
1281 |
++ z[2] ^= v[2]; |
|
1282 |
++ z[3] ^= v[3]; |
|
1283 |
++ } |
|
1284 |
++ /** v = (v&1)*0xE1000000000000000000000000000000L ^ (v>>1) **/ |
|
1285 |
++ c = v[3]&1 ? 0xE1000000 : 0; |
|
1286 |
++ v[3] = v[3]>>1 | (v[2] << 31); |
|
1287 |
++ v[2] = v[2]>>1 | (v[1] << 31); |
|
1288 |
++ v[1] = v[1]>>1 | (v[0] << 31); |
|
1289 |
++ v[0] = v[0]>>1 ^ c; |
|
1290 |
++ } |
|
1291 |
++} |
|
1292 |
++ |
|
1293 |
++/** |
|
1294 |
++ * Compute the GHASH of a piece of an arbitrary data given an |
|
1295 |
++ * arbitrary Y_0, as specified in NIST SP 800 38D. |
|
1296 |
++ * |
|
1297 |
++ * \param y_out The resulting GHASH (16 bytes). |
|
1298 |
++ * \param block_data Pointer to the data to hash. |
|
1299 |
++ * \param len Length of the data to hash (multiple of 16). |
|
1300 |
++ * \param y_in The initial Y (Y_0, 16 bytes). |
|
1301 |
++ * \param h The hash key (16 bytes). |
|
1302 |
++ */ |
|
1303 |
++static void ghash( |
|
1304 |
++ uint8_t y_out[16], |
|
1305 |
++ const uint8_t block_data[], |
|
1306 |
++ int len, |
|
1307 |
++ const uint8_t y_in[16], |
|
1308 |
++ const uint8_t h[16] |
|
1309 |
++ ) |
|
1310 |
++{ |
|
1311 |
++ int i, j; |
|
1312 |
++ uint32_t result[4], hw[4], x[4]; |
|
1313 |
++ |
|
1314 |
++ block_to_words(result, y_in); |
|
1315 |
++ block_to_words(hw, h); |
|
1316 |
++ for (i=0; i<len; i+=16) { |
|
1317 |
++ for (j=0; j<4; j++) { |
|
1318 |
++ x[j] = result[j] ^ be_to_word(&block_data[i+j*4]); |
|
1319 |
++ } |
|
1320 |
++ gcm_mult(result, hw, x); |
|
1321 |
++ } |
|
1322 |
++ words_to_block(y_out, result); |
|
1323 |
++} |
|
1324 |
++ |
|
1325 |
++static char ghash__doc__[] = |
|
1326 |
++"_ghash(data:str, y:str, h:str) -> str\n" |
|
1327 |
++"\n" |
|
1328 |
++"Return a GHASH.\n"; |
|
1329 |
++ |
|
1330 |
++static PyObject * |
|
1331 |
++ghash_function(PyObject *self, PyObject *args) |
|
1332 |
++{ |
|
1333 |
++ PyObject *data, *y, *h; |
|
1334 |
++ PyObject *retval = NULL; |
|
1335 |
++ Py_ssize_t len_data, len_y, len_h; |
|
1336 |
++ |
|
1337 |
++ if (!PyArg_ParseTuple(args, "SSS", &data, &y, &h)) { |
|
1338 |
++ goto out; |
|
1339 |
++ } |
|
1340 |
++ |
|
1341 |
++ len_data = PyBytes_GET_SIZE(data); |
|
1342 |
++ len_y = PyBytes_GET_SIZE(y); |
|
1343 |
++ len_h = PyBytes_GET_SIZE(h); |
|
1344 |
++ |
|
1345 |
++ if (len_data%16!=0) { |
|
1346 |
++ PyErr_SetString(PyExc_ValueError, "Length of data must be a multiple of 16 bytes."); |
|
1347 |
++ goto out; |
|
1348 |
++ } |
|
1349 |
++ |
|
1350 |
++ if (len_y!=16) { |
|
1351 |
++ PyErr_SetString(PyExc_ValueError, "Length of y must be 16 bytes."); |
|
1352 |
++ goto out; |
|
1353 |
++ } |
|
1354 |
++ |
|
1355 |
++ if (len_h!=16) { |
|
1356 |
++ PyErr_SetString(PyExc_ValueError, "Length of h must be 16 bytes."); |
|
1357 |
++ goto out; |
|
1358 |
++ } |
|
1359 |
++ |
|
1360 |
++ /* Create return string */ |
|
1361 |
++ retval = PyBytes_FromStringAndSize(NULL, 16); |
|
1362 |
++ if (!retval) { |
|
1363 |
++ goto out; |
|
1364 |
++ } |
|
1365 |
++ |
|
1366 |
++#define PyBytes_Buffer(a) (uint8_t*)PyBytes_AS_STRING(a) |
|
1367 |
++ |
|
1368 |
++ ghash( PyBytes_Buffer(retval), PyBytes_Buffer(data), len_data, |
|
1369 |
++ PyBytes_Buffer(y), PyBytes_Buffer(h)); |
|
1370 |
++ |
|
1371 |
++#undef PyBytes_Buffer |
|
1372 |
++ |
|
1373 |
++out: |
|
1374 |
++ return retval; |
|
1375 |
++} |
|
1376 |
++ |
|
1377 |
++/* |
|
1378 |
++ * Module-level method table and module initialization function |
|
1379 |
++ */ |
|
1380 |
++ |
|
1381 |
++static PyMethodDef galois_methods[] = { |
|
1382 |
++ {"_ghash", ghash_function, METH_VARARGS, ghash__doc__}, |
|
1383 |
++ {NULL, NULL, 0, NULL} /* end-of-list sentinel value */ |
|
1384 |
++}; |
|
1385 |
++ |
|
1386 |
++#ifdef IS_PY3K |
|
1387 |
++ |
|
1388 |
++static struct PyModuleDef moduledef = { |
|
1389 |
++ PyModuleDef_HEAD_INIT, |
|
1390 |
++ "galois", |
|
1391 |
++ NULL, |
|
1392 |
++ -1, |
|
1393 |
++ galois_methods, |
|
1394 |
++ NULL, |
|
1395 |
++ NULL, |
|
1396 |
++ NULL, |
|
1397 |
++ NULL |
|
1398 |
++}; |
|
1399 |
++ |
|
1400 |
++PyMODINIT_FUNC |
|
1401 |
++PyInit_galois(void) |
|
1402 |
++{ |
|
1403 |
++ PyObject *m; |
|
1404 |
++ |
|
1405 |
++ /* Initialize the module */ |
|
1406 |
++ m = PyModule_Create(&moduledef); |
|
1407 |
++ if (m == NULL) |
|
1408 |
++ return NULL; |
|
1409 |
++ return m; |
|
1410 |
++} |
|
1411 |
++ |
|
1412 |
++#else |
|
1413 |
++ |
|
1414 |
++PyMODINIT_FUNC |
|
1415 |
++initgalois(void) |
|
1416 |
++{ |
|
1417 |
++ PyObject *m; |
|
1418 |
++ |
|
1419 |
++ /* Initialize the module */ |
|
1420 |
++ m = Py_InitModule("galois", galois_methods); |
|
1421 |
++ if (m == NULL) |
|
1422 |
++ return; |
|
1423 |
++} |
|
1424 |
++ |
|
1425 |
++#endif |
|
1426 |
+--- a/lib/Crypto/Hash/CMAC.py_org 2019-05-20 22:32:04.925381714 +0530 |
|
1427 |
+@@ -0,0 +1,340 @@ |
|
1428 |
++# |
|
1429 |
++# Hash/CMAC.py - Implements the CMAC algorithm |
|
1430 |
++# |
|
1431 |
++# =================================================================== |
|
1432 |
++# The contents of this file are dedicated to the public domain. To |
|
1433 |
++# the extent that dedication to the public domain is not available, |
|
1434 |
++# everyone is granted a worldwide, perpetual, royalty-free, |
|
1435 |
++# non-exclusive license to exercise all rights associated with the |
|
1436 |
++# contents of this file for any purpose whatsoever. |
|
1437 |
++# No rights are reserved. |
|
1438 |
++# |
|
1439 |
++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
1440 |
++# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
1441 |
++# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
1442 |
++# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|
1443 |
++# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
1444 |
++# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
1445 |
++# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
1446 |
++# SOFTWARE. |
|
1447 |
++# =================================================================== |
|
1448 |
++ |
|
1449 |
++"""CMAC (Cipher-based Message Authentication Code) algorithm |
|
1450 |
++ |
|
1451 |
++CMAC is a MAC defined in `NIST SP 800-38B`_ and in RFC4493_ (for AES only) |
|
1452 |
++and constructed using a block cipher. It was originally known as `OMAC1`_. |
|
1453 |
++ |
|
1454 |
++The algorithm is sometimes named *X-CMAC* where *X* is the name |
|
1455 |
++of the cipher (e.g. AES-CMAC). |
|
1456 |
++ |
|
1457 |
++This is an example showing how to *create* an AES-CMAC: |
|
1458 |
++ |
|
1459 |
++ >>> from Crypto.Hash import CMAC |
|
1460 |
++ >>> from Crypto.Cipher import AES |
|
1461 |
++ >>> |
|
1462 |
++ >>> secret = b'Sixteen byte key' |
|
1463 |
++ >>> cobj = CMAC.new(secret, ciphermod=AES) |
|
1464 |
++ >>> cobj.update(b'Hello') |
|
1465 |
++ >>> print cobj.hexdigest() |
|
1466 |
++ |
|
1467 |
++And this is an example showing how to *check* an AES-CMAC: |
|
1468 |
++ |
|
1469 |
++ >>> from Crypto.Hash import CMAC |
|
1470 |
++ >>> from Crypto.Cipher import AES |
|
1471 |
++ >>> |
|
1472 |
++ >>> # We have received a message 'msg' together |
|
1473 |
++ >>> # with its MAC 'mac' |
|
1474 |
++ >>> |
|
1475 |
++ >>> secret = b'Sixteen byte key' |
|
1476 |
++ >>> cobj = CMAC.new(secret, ciphermod=AES) |
|
1477 |
++ >>> cobj.update(msg) |
|
1478 |
++ >>> try: |
|
1479 |
++ >>> cobj.verify(mac) |
|
1480 |
++ >>> print "The message '%s' is authentic" % msg |
|
1481 |
++ >>> except ValueError: |
|
1482 |
++ >>> print "The message or the key is wrong" |
|
1483 |
++ |
|
1484 |
++.. _`NIST SP 800-38B`: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf |
|
1485 |
++.. _RFC4493: http://www.ietf.org/rfc/rfc4493.txt |
|
1486 |
++.. _OMAC1: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html |
|
1487 |
++""" |
|
1488 |
++ |
|
1489 |
++__all__ = ['new', 'digest_size', 'CMAC' ] |
|
1490 |
++ |
|
1491 |
++import sys |
|
1492 |
++if sys.version_info[0] == 2 and sys.version_info[1] == 1: |
|
1493 |
++ from Crypto.Util.py21compat import * |
|
1494 |
++from Crypto.Util.py3compat import * |
|
1495 |
++ |
|
1496 |
++from binascii import unhexlify |
|
1497 |
++ |
|
1498 |
++from Crypto.Util.strxor import strxor |
|
1499 |
++from Crypto.Util.number import long_to_bytes, bytes_to_long |
|
1500 |
++ |
|
1501 |
++#: The size of the authentication tag produced by the MAC. |
|
1502 |
++digest_size = None |
|
1503 |
++ |
|
1504 |
++def _shift_bytes(bs, xor_lsb=0): |
|
1505 |
++ num = (bytes_to_long(bs)<<1) ^ xor_lsb |
|
1506 |
++ return long_to_bytes(num, len(bs))[-len(bs):] |
|
1507 |
++ |
|
1508 |
++class _SmoothMAC(object): |
|
1509 |
++ """Turn a MAC that only operates on aligned blocks of data |
|
1510 |
++ into a MAC with granularity of 1 byte.""" |
|
1511 |
++ |
|
1512 |
++ def __init__(self, block_size, msg=b(""), min_digest=0): |
|
1513 |
++ self._bs = block_size |
|
1514 |
++ #: Data waiting to be MAC-ed |
|
1515 |
++ self._buffer = [] |
|
1516 |
++ self._buffer_len = 0 |
|
1517 |
++ #: Data received via update() |
|
1518 |
++ self._total_len = 0 |
|
1519 |
++ #: Minimum amount of bytes required by the final digest step |
|
1520 |
++ self._min_digest = min_digest |
|
1521 |
++ #: Block MAC object |
|
1522 |
++ self._mac = None |
|
1523 |
++ #: Cached digest |
|
1524 |
++ self._tag = None |
|
1525 |
++ if msg: |
|
1526 |
++ self.update(msg) |
|
1527 |
++ |
|
1528 |
++ def can_reduce(self): |
|
1529 |
++ return (self._mac is not None) |
|
1530 |
++ |
|
1531 |
++ def get_len(self): |
|
1532 |
++ return self._total_len |
|
1533 |
++ |
|
1534 |
++ def zero_pad(self): |
|
1535 |
++ if self._buffer_len & (self._bs-1): |
|
1536 |
++ npad = self._bs - self._buffer_len & (self._bs-1) |
|
1537 |
++ self._buffer.append(bchr(0)*npad) |
|
1538 |
++ self._buffer_len += npad |
|
1539 |
++ |
|
1540 |
++ def update(self, data): |
|
1541 |
++ # Optimization (try not to copy data if possible) |
|
1542 |
++ if self._buffer_len==0 and self.can_reduce() and\ |
|
1543 |
++ self._min_digest==0 and len(data)%self._bs==0: |
|
1544 |
++ self._update(data) |
|
1545 |
++ self._total_len += len(data) |
|
1546 |
++ return |
|
1547 |
++ |
|
1548 |
++ self._buffer.append(data) |
|
1549 |
++ self._buffer_len += len(data) |
|
1550 |
++ self._total_len += len(data) |
|
1551 |
++ |
|
1552 |
++ # Feed data into MAC |
|
1553 |
++ blocks, rem = divmod(self._buffer_len, self._bs) |
|
1554 |
++ if rem<self._min_digest: |
|
1555 |
++ blocks -= 1 |
|
1556 |
++ if blocks>0 and self.can_reduce(): |
|
1557 |
++ aligned_data = blocks*self._bs |
|
1558 |
++ buf = b("").join(self._buffer) |
|
1559 |
++ self._update(buf[:aligned_data]) |
|
1560 |
++ self._buffer = [ buf[aligned_data:] ] |
|
1561 |
++ self._buffer_len -= aligned_data |
|
1562 |
++ |
|
1563 |
++ def _deep_copy(self, target): |
|
1564 |
++ # Copy everything by self._mac, since we don't know how to |
|
1565 |
++ target._buffer = self._buffer[:] |
|
1566 |
++ for m in [ '_bs', '_buffer_len', '_total_len', '_min_digest', '_tag' ]: |
|
1567 |
++ setattr(target, m, getattr(self, m)) |
|
1568 |
++ |
|
1569 |
++ def _update(self, data_block): |
|
1570 |
++ """Delegate to the implementation the update |
|
1571 |
++ of the MAC state given some new *block aligned* data.""" |
|
1572 |
++ raise NotImplementedError("_update() must be still implemented") |
|
1573 |
++ |
|
1574 |
++ def _digest(self, left_data): |
|
1575 |
++ """Delegate to the implementation the computation |
|
1576 |
++ of the final MAC given the current MAC state |
|
1577 |
++ and the last piece of data (not block aligned).""" |
|
1578 |
++ raise NotImplementedError("_digest() must be still implemented") |
|
1579 |
++ |
|
1580 |
++ def digest(self): |
|
1581 |
++ if self._tag: |
|
1582 |
++ return self._tag |
|
1583 |
++ if self._buffer_len>0: |
|
1584 |
++ self.update(b("")) |
|
1585 |
++ left_data = b("").join(self._buffer) |
|
1586 |
++ self._tag = self._digest(left_data) |
|
1587 |
++ return self._tag |
|
1588 |
++ |
|
1589 |
++class CMAC(_SmoothMAC): |
|
1590 |
++ """Class that implements CMAC""" |
|
1591 |
++ |
|
1592 |
++ #: The size of the authentication tag produced by the MAC. |
|
1593 |
++ digest_size = None |
|
1594 |
++ |
|
1595 |
++ def __init__(self, key, msg = None, ciphermod = None): |
|
1596 |
++ """Create a new CMAC object. |
|
1597 |
++ |
|
1598 |
++ :Parameters: |
|
1599 |
++ key : byte string |
|
1600 |
++ secret key for the CMAC object. |
|
1601 |
++ The key must be valid for the underlying cipher algorithm. |
|
1602 |
++ For instance, it must be 16 bytes long for AES-128. |
|
1603 |
++ msg : byte string |
|
1604 |
++ The very first chunk of the message to authenticate. |
|
1605 |
++ It is equivalent to an early call to `update`. Optional. |
|
1606 |
++ ciphermod : module |
|
1607 |
++ A cipher module from `Crypto.Cipher`. |
|
1608 |
++ The cipher's block size must be 64 or 128 bits. |
|
1609 |
++ It is recommended to use `Crypto.Cipher.AES`. |
|
1610 |
++ """ |
|
1611 |
++ |
|
1612 |
++ if ciphermod is None: |
|
1613 |
++ raise ValueError("ciphermod must be specified (try AES)") |
|
1614 |
++ |
|
1615 |
++ _SmoothMAC.__init__(self, ciphermod.block_size, msg, 1) |
|
1616 |
++ self._key = key |
|
1617 |
++ self._factory = ciphermod |
|
1618 |
++ |
|
1619 |
++ # Section 5.3 of NIST SP 800 38B |
|
1620 |
++ if ciphermod.block_size==8: |
|
1621 |
++ const_Rb = 0x1B |
|
1622 |
++ elif ciphermod.block_size==16: |
|
1623 |
++ const_Rb = 0x87 |
|
1624 |
++ else: |
|
1625 |
++ raise ValueError("For CMAC, block length of the selected cipher must be 8 or 16 bytes") |
|
1626 |
++ self.digest_size = ciphermod.block_size |
|
1627 |
++ |
|
1628 |
++ |
|
1629 |
++ # Compute sub-keys |
|
1630 |
++ cipher = ciphermod.new(key, ciphermod.MODE_ECB) |
|
1631 |
++ l = cipher.encrypt(bchr(0)*ciphermod.block_size) |
|
1632 |
++ if bord(l[0]) & 0x80: |
|
1633 |
++ self._k1 = _shift_bytes(l, const_Rb) |
|
1634 |
++ else: |
|
1635 |
++ self._k1 = _shift_bytes(l) |
|
1636 |
++ if bord(self._k1[0]) & 0x80: |
|
1637 |
++ self._k2 = _shift_bytes(self._k1, const_Rb) |
|
1638 |
++ else: |
|
1639 |
++ self._k2 = _shift_bytes(self._k1) |
|
1640 |
++ |
|
1641 |
++ # Initialize CBC cipher with zero IV |
|
1642 |
++ self._IV = bchr(0)*ciphermod.block_size |
|
1643 |
++ self._mac = ciphermod.new(key, ciphermod.MODE_CBC, self._IV) |
|
1644 |
++ |
|
1645 |
++ def update(self, msg): |
|
1646 |
++ """Continue authentication of a message by consuming the next chunk of data. |
|
1647 |
++ |
|
1648 |
++ Repeated calls are equivalent to a single call with the concatenation |
|
1649 |
++ of all the arguments. In other words: |
|
1650 |
++ |
|
1651 |
++ >>> m.update(a); m.update(b) |
|
1652 |
++ |
|
1653 |
++ is equivalent to: |
|
1654 |
++ |
|
1655 |
++ >>> m.update(a+b) |
|
1656 |
++ |
|
1657 |
++ :Parameters: |
|
1658 |
++ msg : byte string |
|
1659 |
++ The next chunk of the message being authenticated |
|
1660 |
++ """ |
|
1661 |
++ |
|
1662 |
++ _SmoothMAC.update(self, msg) |
|
1663 |
++ |
|
1664 |
++ def _update(self, data_block): |
|
1665 |
++ self._IV = self._mac.encrypt(data_block)[-self._mac.block_size:] |
|
1666 |
++ |
|
1667 |
++ def copy(self): |
|
1668 |
++ """Return a copy ("clone") of the MAC object. |
|
1669 |
++ |
|
1670 |
++ The copy will have the same internal state as the original MAC |
|
1671 |
++ object. |
|
1672 |
++ This can be used to efficiently compute the MAC of strings that |
|
1673 |
++ share a common initial substring. |
|
1674 |
++ |
|
1675 |
++ :Returns: A `CMAC` object |
|
1676 |
++ """ |
|
1677 |
++ obj = CMAC(self._key, ciphermod=self._factory) |
|
1678 |
++ _SmoothMAC._deep_copy(self, obj) |
|
1679 |
++ obj._mac = self._factory.new(self._key, self._factory.MODE_CBC, self._IV) |
|
1680 |
++ for m in [ '_tag', '_k1', '_k2', '_IV']: |
|
1681 |
++ setattr(obj, m, getattr(self, m)) |
|
1682 |
++ return obj |
|
1683 |
++ |
|
1684 |
++ def digest(self): |
|
1685 |
++ """Return the **binary** (non-printable) MAC of the message that has |
|
1686 |
++ been authenticated so far. |
|
1687 |
++ |
|
1688 |
++ This method does not change the state of the MAC object. |
|
1689 |
++ You can continue updating the object after calling this function. |
|
1690 |
++ |
|
1691 |
++ :Return: A byte string of `digest_size` bytes. It may contain non-ASCII |
|
1692 |
++ characters, including null bytes. |
|
1693 |
++ """ |
|
1694 |
++ return _SmoothMAC.digest(self) |
|
1695 |
++ |
|
1696 |
++ def _digest(self, last_data): |
|
1697 |
++ if len(last_data)==self._bs: |
|
1698 |
++ last_block = strxor(last_data, self._k1) |
|
1699 |
++ else: |
|
1700 |
++ last_block = strxor(last_data+bchr(128)+ |
|
1701 |
++ bchr(0)*(self._bs-1-len(last_data)), self._k2) |
|
1702 |
++ tag = self._mac.encrypt(last_block) |
|
1703 |
++ return tag |
|
1704 |
++ |
|
1705 |
++ def hexdigest(self): |
|
1706 |
++ """Return the **printable** MAC of the message that has been |
|
1707 |
++ authenticated so far. |
|
1708 |
++ |
|
1709 |
++ This method does not change the state of the MAC object. |
|
1710 |
++ |
|
1711 |
++ :Return: A string of 2* `digest_size` bytes. It contains only |
|
1712 |
++ hexadecimal ASCII digits. |
|
1713 |
++ """ |
|
1714 |
++ return "".join(["%02x" % bord(x) |
|
1715 |
++ for x in tuple(self.digest())]) |
|
1716 |
++ |
|
1717 |
++ def verify(self, mac_tag): |
|
1718 |
++ """Verify that a given **binary** MAC (computed by another party) is valid. |
|
1719 |
++ |
|
1720 |
++ :Parameters: |
|
1721 |
++ mac_tag : byte string |
|
1722 |
++ The expected MAC of the message. |
|
1723 |
++ :Raises ValueError: |
|
1724 |
++ if the MAC does not match. It means that the message |
|
1725 |
++ has been tampered with or that the MAC key is incorrect. |
|
1726 |
++ """ |
|
1727 |
++ |
|
1728 |
++ mac = self.digest() |
|
1729 |
++ res = 0 |
|
1730 |
++ # Constant-time comparison |
|
1731 |
++ for x,y in zip(mac, mac_tag): |
|
1732 |
++ res |= bord(x) ^ bord(y) |
|
1733 |
++ if res or len(mac_tag)!=self.digest_size: |
|
1734 |
++ raise ValueError("MAC check failed") |
|
1735 |
++ |
|
1736 |
++ def hexverify(self, hex_mac_tag): |
|
1737 |
++ """Verify that a given **printable** MAC (computed by another party) is valid. |
|
1738 |
++ |
|
1739 |
++ :Parameters: |
|
1740 |
++ hex_mac_tag : string |
|
1741 |
++ The expected MAC of the message, as a hexadecimal string. |
|
1742 |
++ :Raises ValueError: |
|
1743 |
++ if the MAC does not match. It means that the message |
|
1744 |
++ has been tampered with or that the MAC key is incorrect. |
|
1745 |
++ """ |
|
1746 |
++ |
|
1747 |
++ self.verify(unhexlify(hex_mac_tag)) |
|
1748 |
++ |
|
1749 |
++def new(key, msg = None, ciphermod = None): |
|
1750 |
++ """Create a new CMAC object. |
|
1751 |
++ |
|
1752 |
++ :Parameters: |
|
1753 |
++ key : byte string |
|
1754 |
++ secret key for the CMAC object. |
|
1755 |
++ The key must be valid for the underlying cipher algorithm. |
|
1756 |
++ For instance, it must be 16 bytes long for AES-128. |
|
1757 |
++ msg : byte string |
|
1758 |
++ The very first chunk of the message to authenticate. |
|
1759 |
++ It is equivalent to an early call to `CMAC.update`. Optional. |
|
1760 |
++ ciphermod : module |
|
1761 |
++ A cipher module from `Crypto.Cipher`. |
|
1762 |
++ The cipher's block size must be 64 or 128 bits. |
|
1763 |
++ Default is `Crypto.Cipher.AES`. |
|
1764 |
++ |
|
1765 |
++ :Returns: A `CMAC` object |
|
1766 |
++ """ |
|
1767 |
++ return CMAC(key, msg, ciphermod) |
0 | 1768 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,814 @@ |
0 |
+From 199a9741a1849066d070b114333fcf90bc73c55a Mon Sep 17 00:00:00 2001 |
|
1 |
+From: Legrandin <helderijs@gmail.com> |
|
2 |
+Date: Wed, 22 May 2013 22:18:35 +0200 |
|
3 |
+Subject: [PATCH] Add support for SIV (Synthetic IV) mode |
|
4 |
+ |
|
5 |
+This patch add supports for SIV, an AEAD block cipher |
|
6 |
+mode defined in RFC5297. SIV is only valid for AES. |
|
7 |
+ |
|
8 |
+The PRF of SIV (S2V) is factored out in the Protocol.KDF module. |
|
9 |
+ |
|
10 |
+See the following example to get a feeling of the API (slightly |
|
11 |
+different than other AEAD mode, during decryption). |
|
12 |
+ |
|
13 |
+Encryption (Python 2): |
|
14 |
+ |
|
15 |
+ >>> from Crypto.Cipher import AES |
|
16 |
+ >>> key = b'0'*32 |
|
17 |
+ >>> siv = AES.new(key, AES.MODE_SIV) |
|
18 |
+ >>> ct = siv.encrypt(b'Message') |
|
19 |
+ >>> mac = siv.digest() |
|
20 |
+ |
|
21 |
+Decryption (Python 2): |
|
22 |
+ |
|
23 |
+ >>> from Crypto.Cipher import AES, MacMismatchError |
|
24 |
+ >>> key = b'0'*32 |
|
25 |
+ >>> siv = AES.new(key, AES.MODE_SIV) |
|
26 |
+ >>> pt = siv.decrypt(ct + mac) |
|
27 |
+ >>> try: |
|
28 |
+ >>> siv.verify(mac) |
|
29 |
+ >>> print "Plaintext", pt |
|
30 |
+ >>> except MacMismatchError: |
|
31 |
+ >>> print "Error" |
|
32 |
+ |
|
33 |
+This change also fixes the description/design of AEAD API. |
|
34 |
+ |
|
35 |
+With SIV (RFC5297), decryption can only start when the MAC is known. |
|
36 |
+The original AEAD API did not support that. |
|
37 |
+ |
|
38 |
+For SIV the MAC is now exceptionally passed together with the ciphertext |
|
39 |
+to the decrypt() method. |
|
40 |
+ |
|
41 |
+[dlitz@dlitz.net: Included changes from the following commits from the author's pull request:] |
|
42 |
+- [9c13f9c] Rename 'IV' parameter to 'nonce' for AEAD modes. |
|
43 |
+- [d7727fb] Fix description/design of AEAD API. |
|
44 |
+- [fb62fae] ApiUsageError becomes TypeError [whitespace] |
|
45 |
+- [4ec64d8] Removed last references to ApiUsageError [whitespace] |
|
46 |
+- [ee46922] Removed most 'import *' statements |
|
47 |
+- [ca460a7] Made blockalgo.py more PEP-8 compliant; |
|
48 |
+ The second parameter of the _GHASH constructor |
|
49 |
+ is now the length of the block (block_size) |
|
50 |
+ and not the full module. |
|
51 |
+[dlitz@dlitz.net: A conflict that was not resolved in the previous |
|
52 |
+ commit was originally resolved here. Moved the |
|
53 |
+ resolution to the previous commit.] |
|
54 |
+[dlitz@dlitz.net: Replaced MacMismatchError with ValueError] |
|
55 |
+[dlitz@dlitz.net: Replaced ApiUsageError with TypeError] |
|
56 |
+[dlitz@dlitz.net: Whitespace fixed with "git rebase --whitespace=fix"] |
|
57 |
+ |
|
58 |
+--- a/lib/Crypto/Cipher/AES.py_org 2019-05-20 19:44:51.577181298 +0530 |
|
59 |
+@@ -96,6 +96,7 @@ def new(key, *args, **kwargs): |
|
60 |
+ key : byte string |
|
61 |
+ The secret key to use in the symmetric cipher. |
|
62 |
+ It must be 16 (*AES-128*), 24 (*AES-192*), or 32 (*AES-256*) bytes long. |
|
63 |
++ Only in `MODE_SIV`, it needs to be 32, 48, or 64 bytes long. |
|
64 |
+ :Keywords: |
|
65 |
+ mode : a *MODE_** constant |
|
66 |
+ The chaining mode to use for encryption or decryption. |
|
67 |
+@@ -113,7 +114,7 @@ def new(key, *args, **kwargs): |
|
68 |
+ |
|
69 |
+ For all other modes, it must be 16 bytes long. |
|
70 |
+ nonce : byte string |
|
71 |
+- (*Only* `MODE_CCM`, `MODE_EAX`). |
|
72 |
++ (*Only* `MODE_CCM`, `MODE_EAX`, `MODE_SIV`). |
|
73 |
+ |
|
74 |
+ A mandatory value that must never be reused for any other encryption. |
|
75 |
+ |
|
76 |
+@@ -166,6 +167,8 @@ MODE_OPENPGP = 7 |
|
77 |
+ MODE_CCM = 8 |
|
78 |
+ #: EAX Mode. See `blockalgo.MODE_EAX`. |
|
79 |
+ MODE_EAX = 9 |
|
80 |
++#: Syntethic Initialization Vector (SIV). See `blockalgo.MODE_SIV`. |
|
81 |
++MODE_SIV = 10 |
|
82 |
+ #: Size of a data block (in bytes) |
|
83 |
+ block_size = 16 |
|
84 |
+ #: Size of a key (in bytes) |
|
85 |
+--- a/lib/Crypto/Cipher/blockalgo.py_org 2019-05-20 19:48:41.877185898 +0530 |
|
86 |
+@@ -32,6 +32,7 @@ from Crypto.Util.strxor import strxor |
|
87 |
+ from Crypto.Util.number import long_to_bytes, bytes_to_long |
|
88 |
+ import Crypto.Util.Counter |
|
89 |
+ from Crypto.Hash import CMAC |
|
90 |
++from Crypto.Protocol.KDF import S2V |
|
91 |
+ |
|
92 |
+ #: *Electronic Code Book (ECB)*. |
|
93 |
+ #: This is the simplest encryption mode. Each of the plaintext blocks |
|
94 |
+@@ -206,7 +207,50 @@ MODE_CCM = 8 |
|
95 |
+ #: .. __: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf |
|
96 |
+ MODE_EAX = 9 |
|
97 |
+ |
|
98 |
+- |
|
99 |
++#: *Synthetic Initialization Vector*. This is an Authenticated Encryption with |
|
100 |
++#: Associated Data (`AEAD`_) mode. It provides both confidentiality and |
|
101 |
++#: authenticity. |
|
102 |
++#: The header of the message may be left in the clear, if needed, and it will |
|
103 |
++#: still be subject to authentication. The decryption step tells the receiver |
|
104 |
++#: if the message comes from a source that really knowns the secret key. |
|
105 |
++#: Additionally, decryption detects if any part of the message - including the |
|
106 |
++#: header - has been modified or corrupted. |
|
107 |
++#: |
|
108 |
++#: If the data being encrypted is completely unpredictable to an adversary |
|
109 |
++#: (e.g. a secret key, for key wrapping purposes) a nonce is not strictly |
|
110 |
++#: required. |
|
111 |
++#: |
|
112 |
++#: Otherwise, a nonce has to be provided; the nonce shall never repeat |
|
113 |
++#: for two different messages encrypted with the same key, but it does not |
|
114 |
++#: need to be random. |
|
115 |
++#: |
|
116 |
++#: Unlike other AEAD modes such as CCM, EAX or GCM, accidental reuse of a |
|
117 |
++#: nonce is not catastrophic for the confidentiality of the message. The only |
|
118 |
++#: effect is that an attacker can tell when the same plaintext (and same |
|
119 |
++#: associated data) is protected with the same key. |
|
120 |
++#: |
|
121 |
++#: The length of the MAC is fixed to the block size of the underlying cipher. |
|
122 |
++#: The key size is twice the length of the key of the underlying cipher. |
|
123 |
++#: |
|
124 |
++#: This mode is only available for AES ciphers. |
|
125 |
++#: |
|
126 |
++#: +--------------------+---------------+-------------------+ |
|
127 |
++#: | Cipher | SIV MAC size | SIV key length | |
|
128 |
++#: | | (bytes) | (bytes) | |
|
129 |
++#: +====================+===============+===================+ |
|
130 |
++#: | AES-128 | 16 | 32 | |
|
131 |
++#: +--------------------+---------------+-------------------+ |
|
132 |
++#: | AES-192 | 16 | 48 | |
|
133 |
++#: +--------------------+---------------+-------------------+ |
|
134 |
++#: | AES-256 | 16 | 64 | |
|
135 |
++#: +--------------------+---------------+-------------------+ |
|
136 |
++#: |
|
137 |
++#: See `RFC5297`_ and the `original paper`__. |
|
138 |
++#: |
|
139 |
++#: .. _RFC5297: https://tools.ietf.org/html/rfc5297 |
|
140 |
++#: .. _AEAD: http://blog.cryptographyengineering.com/2012/05/how-to-choose-authenticated-encryption.html |
|
141 |
++#: .. __: http://www.cs.ucdavis.edu/~rogaway/papers/keywrap.pdf |
|
142 |
++MODE_SIV = 10 |
|
143 |
+ |
|
144 |
+ def _getParameter(name, index, args, kwargs, default=None): |
|
145 |
+ """Find a parameter in tuple and dictionary arguments a function receives""" |
|
146 |
+@@ -259,10 +303,40 @@ class BlockAlgo: |
|
147 |
+ self._start_PGP(factory, key, *args, **kwargs) |
|
148 |
+ elif self.mode == MODE_EAX: |
|
149 |
+ self._start_eax(factory, key, *args, **kwargs) |
|
150 |
++ elif self.mode == MODE_SIV: |
|
151 |
++ self._start_siv(factory, key, *args, **kwargs) |
|
152 |
+ else: |
|
153 |
+ self._cipher = factory.new(key, *args, **kwargs) |
|
154 |
+ self.IV = self._cipher.IV |
|
155 |
+ |
|
156 |
++ def _start_siv(self, factory, key, *args, **kwargs): |
|
157 |
++ |
|
158 |
++ subkey_size, rem = divmod(len(key), 2) |
|
159 |
++ if rem: |
|
160 |
++ raise ValueError("MODE_SIV requires a key twice as long as for the underlying cipher") |
|
161 |
++ |
|
162 |
++ # IV is optional |
|
163 |
++ self.nonce = _getParameter('nonce', 1, args, kwargs) |
|
164 |
++ |
|
165 |
++ self._prf = S2V(key[:subkey_size], ciphermod=factory) |
|
166 |
++ self._subkey_ctr = key[subkey_size:] |
|
167 |
++ self._mac_len = factory.block_size |
|
168 |
++ |
|
169 |
++ # Allowed transitions after initialization |
|
170 |
++ self._next = [self.update, self.encrypt, self.decrypt, |
|
171 |
++ self.digest, self.verify] |
|
172 |
++ |
|
173 |
++ def _siv_ctr_cipher(self, tag): |
|
174 |
++ """Create a new CTR cipher from the MAC in SIV mode""" |
|
175 |
++ |
|
176 |
++ tag_int = bytes_to_long(tag) |
|
177 |
++ init_counter = tag_int ^ (tag_int & 0x8000000080000000L) |
|
178 |
++ ctr = Counter.new(self._factory.block_size * 8, |
|
179 |
++ initial_value=init_counter, |
|
180 |
++ allow_wraparound=True) |
|
181 |
++ |
|
182 |
++ return self._factory.new(self._subkey_ctr, MODE_CTR, counter=ctr) |
|
183 |
++ |
|
184 |
+ def _start_eax(self, factory, key, *args, **kwargs): |
|
185 |
+ |
|
186 |
+ self.nonce = _getParameter('nonce', 1, args, kwargs) |
|
187 |
+@@ -403,9 +477,10 @@ class BlockAlgo: |
|
188 |
+ def update(self, assoc_data): |
|
189 |
+ """Protect associated data |
|
190 |
+ |
|
191 |
+- When using an AEAD mode like CCM or EAX, and if there is any associated data, |
|
192 |
+- the caller has to invoke this function one or more times, before |
|
193 |
+- using ``decrypt`` or ``encrypt``. |
|
194 |
++ When using an AEAD mode like CCM, EAX or SIV, and |
|
195 |
++ if there is any associated data, the caller has to invoke |
|
196 |
++ this function one or more times, before using |
|
197 |
++ ``decrypt`` or ``encrypt``. |
|
198 |
+ |
|
199 |
+ By *associated data* it is meant any data (e.g. packet headers) that |
|
200 |
+ will not be encrypted and will be transmitted in the clear. |
|
201 |
+@@ -423,7 +498,7 @@ class BlockAlgo: |
|
202 |
+ A piece of associated data. There are no restrictions on its size. |
|
203 |
+ """ |
|
204 |
+ |
|
205 |
+- if self.mode in (MODE_CCM, MODE_EAX): |
|
206 |
++ if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
207 |
+ if self.update not in self._next: |
|
208 |
+ raise TypeError("update() can only be called immediately after initialization") |
|
209 |
+ self._next = [self.update, self.encrypt, self.decrypt, |
|
210 |
+@@ -456,20 +531,31 @@ class BlockAlgo: |
|
211 |
+ if self.mode == MODE_EAX: |
|
212 |
+ self._omac[1].update(assoc_data) |
|
213 |
+ return |
|
214 |
++ if self.mode == MODE_SIV: |
|
215 |
++ self._prf.update(assoc_data) |
|
216 |
++ return |
|
217 |
+ |
|
218 |
+ raise ValueError("update() not supported by this mode of operation") |
|
219 |
+ |
|
220 |
+ |
|
221 |
+ def encrypt(self, plaintext): |
|
222 |
+ """Encrypt data with the key and the parameters set at initialization. |
|
223 |
+- |
|
224 |
+- The cipher object is stateful; encryption of a long block |
|
225 |
+- of data can be broken up in two or more calls to `encrypt()`. |
|
226 |
++ |
|
227 |
++ A cipher object is stateful: once you have encrypted a message |
|
228 |
++ you cannot encrypt (or decrypt) another message using the same |
|
229 |
++ object. |
|
230 |
++ |
|
231 |
++ For `MODE_SIV` (always) and `MODE_CCM` (when ``msg_len`` was not |
|
232 |
++ passed at initialization), this method can be called only **once**. |
|
233 |
++ |
|
234 |
++ For all other modes, the data to encrypt can be broken up in two or |
|
235 |
++ more pieces and `encrypt` can be called multiple times. |
|
236 |
++ |
|
237 |
+ That is, the statement: |
|
238 |
+ |
|
239 |
+ >>> c.encrypt(a) + c.encrypt(b) |
|
240 |
+ |
|
241 |
+- is always equivalent to: |
|
242 |
++ is equivalent to: |
|
243 |
+ |
|
244 |
+ >>> c.encrypt(a+b) |
|
245 |
+ |
|
246 |
+@@ -484,7 +570,8 @@ class BlockAlgo: |
|
247 |
+ - For `MODE_CFB`, *plaintext* length (in bytes) must be a multiple |
|
248 |
+ of *segment_size*/8. |
|
249 |
+ |
|
250 |
+- - For `MODE_CTR` and `MODE_CCM` and `MODE_EAX`, *plaintext* can be of any length. |
|
251 |
++ - For `MODE_CTR` and `MODE_CCM`, `MODE_EAX` and `MODE_SIV`, |
|
252 |
++ *plaintext* can be of any length. |
|
253 |
+ |
|
254 |
+ - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, |
|
255 |
+ unless it is the last chunk of the message. |
|
256 |
+@@ -517,7 +604,7 @@ class BlockAlgo: |
|
257 |
+ self._done_first_block = True |
|
258 |
+ return res |
|
259 |
+ |
|
260 |
+- if self.mode in (MODE_CCM, MODE_EAX): |
|
261 |
++ if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
262 |
+ |
|
263 |
+ if self.encrypt not in self._next: |
|
264 |
+ raise TypeError("encrypt() can only be called after initialization or an update()") |
|
265 |
+@@ -534,6 +621,15 @@ class BlockAlgo: |
|
266 |
+ |
|
267 |
+ self._update(plaintext) |
|
268 |
+ |
|
269 |
++ if self.mode == MODE_SIV: |
|
270 |
++ self._next = [self.digest] |
|
271 |
++ |
|
272 |
++ if self.nonce: |
|
273 |
++ self._prf.update(self.nonce) |
|
274 |
++ |
|
275 |
++ self._prf.update(plaintext) |
|
276 |
++ self._cipher = self._siv_ctr_cipher(self._prf.derive()) |
|
277 |
++ |
|
278 |
+ ct = self._cipher.encrypt(plaintext) |
|
279 |
+ |
|
280 |
+ if self.mode == MODE_EAX: |
|
281 |
+@@ -543,14 +639,22 @@ class BlockAlgo: |
|
282 |
+ |
|
283 |
+ def decrypt(self, ciphertext): |
|
284 |
+ """Decrypt data with the key and the parameters set at initialization. |
|
285 |
+- |
|
286 |
+- The cipher object is stateful; decryption of a long block |
|
287 |
+- of data can be broken up in two or more calls to `decrypt()`. |
|
288 |
++ |
|
289 |
++ A cipher object is stateful: once you have decrypted a message |
|
290 |
++ you cannot decrypt (or encrypt) another message with the same |
|
291 |
++ object. |
|
292 |
++ |
|
293 |
++ For `MODE_SIV` (always) and `MODE_CCM` (when ``msg_len`` was not |
|
294 |
++ passed at initialization), this method can be called only **once**. |
|
295 |
++ |
|
296 |
++ For all other modes, the data to decrypt can be broken up in two or |
|
297 |
++ more pieces and `decrypt` can be called multiple times. |
|
298 |
++ |
|
299 |
+ That is, the statement: |
|
300 |
+ |
|
301 |
+ >>> c.decrypt(a) + c.decrypt(b) |
|
302 |
+ |
|
303 |
+- is always equivalent to: |
|
304 |
++ is equivalent to: |
|
305 |
+ |
|
306 |
+ >>> c.decrypt(a+b) |
|
307 |
+ |
|
308 |
+@@ -570,10 +674,14 @@ class BlockAlgo: |
|
309 |
+ - For `MODE_OPENPGP`, *plaintext* must be a multiple of *block_size*, |
|
310 |
+ unless it is the last chunk of the message. |
|
311 |
+ |
|
312 |
++ - For `MODE_SIV`, *ciphertext* can be of any length, but it must also |
|
313 |
++ include the MAC (concatenated at the end). |
|
314 |
++ |
|
315 |
+ :Parameters: |
|
316 |
+ ciphertext : byte string |
|
317 |
+- The piece of data to decrypt. |
|
318 |
+- :Return: the decrypted data (byte string, as long as *ciphertext*). |
|
319 |
++ The piece of data to decrypt (plus the MAC, for `MODE_SIV` only). |
|
320 |
++ |
|
321 |
++ :Return: the decrypted data (byte string). |
|
322 |
+ """ |
|
323 |
+ if self.mode == MODE_OPENPGP: |
|
324 |
+ padding_length = (self.block_size - len(ciphertext) % self.block_size) % self.block_size |
|
325 |
+@@ -590,7 +698,7 @@ class BlockAlgo: |
|
326 |
+ res = self._cipher.decrypt(ciphertext) |
|
327 |
+ return res |
|
328 |
+ |
|
329 |
+- if self.mode in (MODE_CCM, MODE_EAX): |
|
330 |
++ if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
331 |
+ |
|
332 |
+ if self.decrypt not in self._next: |
|
333 |
+ raise TypeError("decrypt() can only be called after initialization or an update()") |
|
334 |
+@@ -608,11 +716,25 @@ class BlockAlgo: |
|
335 |
+ |
|
336 |
+ if self.mode == MODE_EAX: |
|
337 |
+ self._omac[2].update(ciphertext) |
|
338 |
++ if self.mode == MODE_SIV: |
|
339 |
++ self._next = [self.verify] |
|
340 |
++ |
|
341 |
++ # Take the MAC and start the cipher for decryption |
|
342 |
++ self._mac = ciphertext[-self._factory.block_size:] |
|
343 |
++ self._cipher = self._siv_ctr_cipher(self._mac) |
|
344 |
++ |
|
345 |
++ # Remove MAC from ciphertext |
|
346 |
++ ciphertext = ciphertext[:-self._factory.block_size] |
|
347 |
++ |
|
348 |
+ pt = self._cipher.decrypt(ciphertext) |
|
349 |
+ |
|
350 |
+ if self.mode == MODE_CCM: |
|
351 |
+ self._update(pt) |
|
352 |
+- |
|
353 |
++ if self.mode == MODE_SIV: |
|
354 |
++ if self.nonce: |
|
355 |
++ self._prf.update(self.nonce) |
|
356 |
++ if pt: |
|
357 |
++ self._prf.update(pt) |
|
358 |
+ return pt |
|
359 |
+ |
|
360 |
+ def digest(self): |
|
361 |
+@@ -627,7 +749,7 @@ class BlockAlgo: |
|
362 |
+ :Return: the MAC, as a byte string. |
|
363 |
+ """ |
|
364 |
+ |
|
365 |
+- if self.mode in (MODE_CCM, MODE_EAX): |
|
366 |
++ if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
367 |
+ |
|
368 |
+ if self.digest not in self._next: |
|
369 |
+ raise TypeError("digest() cannot be called when decrypting or validating a message") |
|
370 |
+@@ -648,6 +770,9 @@ class BlockAlgo: |
|
371 |
+ for i in xrange(3): |
|
372 |
+ tag = strxor(tag, self._omac[i].digest()) |
|
373 |
+ |
|
374 |
++ if self.mode == MODE_SIV: |
|
375 |
++ tag = self._prf.derive() |
|
376 |
++ |
|
377 |
+ return tag |
|
378 |
+ |
|
379 |
+ raise TypeError("digest() not supported by this mode of operation") |
|
380 |
+@@ -679,7 +804,7 @@ class BlockAlgo: |
|
381 |
+ or the key is incorrect. |
|
382 |
+ """ |
|
383 |
+ |
|
384 |
+- if self.mode in (MODE_CCM, MODE_EAX): |
|
385 |
++ if self.mode in (MODE_CCM, MODE_EAX, MODE_SIV): |
|
386 |
+ if self.verify not in self._next: |
|
387 |
+ raise TypeError("verify() cannot be called when encrypting a message") |
|
388 |
+ self._next = [self.verify] |
|
389 |
+@@ -700,6 +825,9 @@ class BlockAlgo: |
|
390 |
+ u = strxor(u, self._omac[i].digest()) |
|
391 |
+ u = u[:self._mac_len] |
|
392 |
+ |
|
393 |
++ if self.mode == MODE_SIV: |
|
394 |
++ u = self._prf.derive() |
|
395 |
++ |
|
396 |
+ res = 0 |
|
397 |
+ # Constant-time comparison |
|
398 |
+ for x,y in zip(u, mac_tag): |
|
399 |
+--- a/lib/Crypto/Protocol/KDF.py_org 2019-05-20 20:04:03.629204310 +0530 |
|
400 |
+@@ -38,9 +38,14 @@ __revision__ = "$Id$" |
|
401 |
+ import math |
|
402 |
+ import struct |
|
403 |
+ |
|
404 |
++import sys |
|
405 |
++if sys.version_info[0] == 2 and sys.version_info[1] == 1: |
|
406 |
++ from Crypto.Util.py21compat import * |
|
407 |
++ |
|
408 |
+ from Crypto.Util.py3compat import * |
|
409 |
+-from Crypto.Hash import SHA as SHA1, HMAC |
|
410 |
++from Crypto.Hash import SHA as SHA1, HMAC, CMAC |
|
411 |
+ from Crypto.Util.strxor import strxor |
|
412 |
++from Crypto.Util.number import long_to_bytes, bytes_to_long |
|
413 |
+ |
|
414 |
+ def PBKDF1(password, salt, dkLen, count=1000, hashAlgo=None): |
|
415 |
+ """Derive one key from a password (or passphrase). |
|
416 |
+@@ -121,3 +126,84 @@ def PBKDF2(password, salt, dkLen=16, cou |
|
417 |
+ i = i + 1 |
|
418 |
+ return key[:dkLen] |
|
419 |
+ |
|
420 |
++class S2V(object): |
|
421 |
++ """String-to-vector PRF as defined in `RFC5297`_. |
|
422 |
++ |
|
423 |
++ This class implements a pseudorandom function family |
|
424 |
++ based on CMAC that takes as input a vector of strings. |
|
425 |
++ |
|
426 |
++ .. _RFC5297: http://tools.ietf.org/html/rfc5297 |
|
427 |
++ """ |
|
428 |
++ |
|
429 |
++ def __init__(self, key, ciphermod): |
|
430 |
++ """Initialize the S2V PRF. |
|
431 |
++ |
|
432 |
++ :Parameters: |
|
433 |
++ key : byte string |
|
434 |
++ A secret that can be used as key for CMACs |
|
435 |
++ based on ciphers from ``ciphermod``. |
|
436 |
++ ciphermod : module |
|
437 |
++ A block cipher module from `Crypto.Cipher`. |
|
438 |
++ """ |
|
439 |
++ |
|
440 |
++ self._key = key |
|
441 |
++ self._ciphermod = ciphermod |
|
442 |
++ self._last_string = self._cache = bchr(0)*ciphermod.block_size |
|
443 |
++ self._n_updates = ciphermod.block_size*8-1 |
|
444 |
++ |
|
445 |
++ def new(key, ciphermod): |
|
446 |
++ """Create a new S2V PRF. |
|
447 |
++ |
|
448 |
++ :Parameters: |
|
449 |
++ key : byte string |
|
450 |
++ A secret that can be used as key for CMACs |
|
451 |
++ based on ciphers from ``ciphermod``. |
|
452 |
++ ciphermod : module |
|
453 |
++ A block cipher module from `Crypto.Cipher`. |
|
454 |
++ """ |
|
455 |
++ return S2V(key, ciphermod) |
|
456 |
++ new = staticmethod(new) |
|
457 |
++ |
|
458 |
++ def _double(self, bs): |
|
459 |
++ doubled = bytes_to_long(bs)<<1 |
|
460 |
++ if bord(bs[0]) & 0x80: |
|
461 |
++ doubled ^= 0x87 |
|
462 |
++ return long_to_bytes(doubled, len(bs))[-len(bs):] |
|
463 |
++ |
|
464 |
++ def update(self, item): |
|
465 |
++ """Pass the next component of the vector. |
|
466 |
++ |
|
467 |
++ The maximum number of components you can pass is equal to the block |
|
468 |
++ length of the cipher (in bits) minus 1. |
|
469 |
++ |
|
470 |
++ :Parameters: |
|
471 |
++ item : byte string |
|
472 |
++ The next component of the vector. |
|
473 |
++ :Raise TypeError: when the limit on the number of components has been reached. |
|
474 |
++ :Raise ValueError: when the component is empty |
|
475 |
++ """ |
|
476 |
++ |
|
477 |
++ if not item: |
|
478 |
++ raise ValueError("A component cannot be empty") |
|
479 |
++ |
|
480 |
++ if self._n_updates==0: |
|
481 |
++ raise TypeError("Too many components passed to S2V") |
|
482 |
++ self._n_updates -= 1 |
|
483 |
++ |
|
484 |
++ mac = CMAC.new(self._key, msg=self._last_string, ciphermod=self._ciphermod) |
|
485 |
++ self._cache = strxor(self._double(self._cache), mac.digest()) |
|
486 |
++ self._last_string = item |
|
487 |
++ |
|
488 |
++ def derive(self): |
|
489 |
++ """"Derive a secret from the vector of components. |
|
490 |
++ |
|
491 |
++ :Return: a byte string, as long as the block length of the cipher. |
|
492 |
++ """ |
|
493 |
++ |
|
494 |
++ if len(self._last_string)>=16: |
|
495 |
++ final = self._last_string[:-16] + strxor(self._last_string[-16:], self._cache) |
|
496 |
++ else: |
|
497 |
++ padded = (self._last_string + bchr(0x80)+ bchr(0)*15)[:16] |
|
498 |
++ final = strxor(padded, self._double(self._cache)) |
|
499 |
++ mac = CMAC.new(self._key, msg=final, ciphermod=self._ciphermod) |
|
500 |
++ return mac.digest() |
|
501 |
+--- a/lib/Crypto/SelfTest/Cipher/common.py_org 2019-05-20 20:09:46.369211156 +0530 |
|
502 |
+@@ -27,6 +27,9 @@ |
|
503 |
+ __revision__ = "$Id$" |
|
504 |
+ |
|
505 |
+ import sys |
|
506 |
++if sys.version_info[0] == 2 and sys.version_info[1] == 1: |
|
507 |
++ from Crypto.Util.py21compat import * |
|
508 |
++ |
|
509 |
+ import unittest |
|
510 |
+ from binascii import a2b_hex, b2a_hex, hexlify |
|
511 |
+ from Crypto.Util.py3compat import * |
|
512 |
+@@ -68,8 +71,6 @@ class CipherSelfTest(unittest.TestCase): |
|
513 |
+ self.ciphertext = b(_extract(params, 'ciphertext')) |
|
514 |
+ self.module_name = _extract(params, 'module_name', None) |
|
515 |
+ self.assoc_data = _extract(params, 'assoc_data', None) |
|
516 |
+- if self.assoc_data: |
|
517 |
+- self.assoc_data = b(self.assoc_data) |
|
518 |
+ self.mac = _extract(params, 'mac', None) |
|
519 |
+ if self.assoc_data: |
|
520 |
+ self.mac = b(self.mac) |
|
521 |
+@@ -125,14 +126,18 @@ class CipherSelfTest(unittest.TestCase): |
|
522 |
+ return self.module.new(a2b_hex(self.key), self.mode, a2b_hex(self.encrypted_iv), **params) |
|
523 |
+ else: |
|
524 |
+ return self.module.new(a2b_hex(self.key), self.mode, a2b_hex(self.iv), **params) |
|
525 |
++ def isMode(self, name): |
|
526 |
++ if not hasattr(self.module, "MODE_"+name): |
|
527 |
++ return False |
|
528 |
++ return self.mode == getattr(self.module, "MODE_"+name) |
|
529 |
+ |
|
530 |
+ def runTest(self): |
|
531 |
+ plaintext = a2b_hex(self.plaintext) |
|
532 |
+ ciphertext = a2b_hex(self.ciphertext) |
|
533 |
+ |
|
534 |
+- assoc_data = None |
|
535 |
++ assoc_data = [] |
|
536 |
+ if self.assoc_data: |
|
537 |
+- assoc_data = a2b_hex(self.assoc_data) |
|
538 |
++ assoc_data = [ a2b_hex(b(x)) for x in self.assoc_data] |
|
539 |
+ |
|
540 |
+ ct = None |
|
541 |
+ pt = None |
|
542 |
+@@ -146,19 +151,22 @@ class CipherSelfTest(unittest.TestCase): |
|
543 |
+ decipher = self._new(1) |
|
544 |
+ |
|
545 |
+ # Only AEAD modes |
|
546 |
+- if self.assoc_data: |
|
547 |
+- cipher.update(assoc_data) |
|
548 |
+- decipher.update(assoc_data) |
|
549 |
++ for comp in assoc_data: |
|
550 |
++ cipher.update(comp) |
|
551 |
++ decipher.update(comp) |
|
552 |
+ |
|
553 |
+ ctX = b2a_hex(cipher.encrypt(plaintext)) |
|
554 |
+- ptX = b2a_hex(decipher.decrypt(ciphertext)) |
|
555 |
++ if self.isMode("SIV"): |
|
556 |
++ ptX = b2a_hex(decipher.decrypt(ciphertext+a2b_hex(self.mac))) |
|
557 |
++ else: |
|
558 |
++ ptX = b2a_hex(decipher.decrypt(ciphertext)) |
|
559 |
+ |
|
560 |
+ if ct: |
|
561 |
+ self.assertEqual(ct, ctX) |
|
562 |
+ self.assertEqual(pt, ptX) |
|
563 |
+ ct, pt = ctX, ptX |
|
564 |
+ |
|
565 |
+- if hasattr(self.module, "MODE_OPENPGP") and self.mode == self.module.MODE_OPENPGP: |
|
566 |
++ if self.isMode("OPENPGP"): |
|
567 |
+ # In PGP mode, data returned by the first encrypt() |
|
568 |
+ # is prefixed with the encrypted IV. |
|
569 |
+ # Here we check it and then remove it from the ciphertexts. |
|
570 |
+@@ -359,10 +367,18 @@ class AEADTests(unittest.TestCase): |
|
571 |
+ self.module = module |
|
572 |
+ self.mode_name = mode_name |
|
573 |
+ self.mode = getattr(module, mode_name) |
|
574 |
+- self.key = b('\xFF')*key_size |
|
575 |
++ if not self.isMode("SIV"): |
|
576 |
++ self.key = b('\xFF')*key_size |
|
577 |
++ else: |
|
578 |
++ self.key = b('\xFF')*key_size*2 |
|
579 |
+ self.iv = b('\x00')*10 |
|
580 |
+ self.description = "AEAD Test" |
|
581 |
+ |
|
582 |
++ def isMode(self, name): |
|
583 |
++ if not hasattr(self.module, "MODE_"+name): |
|
584 |
++ return False |
|
585 |
++ return self.mode == getattr(self.module, "MODE_"+name) |
|
586 |
++ |
|
587 |
+ def right_mac_test(self): |
|
588 |
+ """Positive tests for MAC""" |
|
589 |
+ |
|
590 |
+@@ -381,7 +397,10 @@ class AEADTests(unittest.TestCase): |
|
591 |
+ # Decrypt and verify that MAC is accepted |
|
592 |
+ decipher = self.module.new(self.key, self.mode, self.iv) |
|
593 |
+ decipher.update(ad_ref) |
|
594 |
+- pt = decipher.decrypt(ct_ref) |
|
595 |
++ if not self.isMode("SIV"): |
|
596 |
++ pt = decipher.decrypt(ct_ref) |
|
597 |
++ else: |
|
598 |
++ pt = decipher.decrypt(ct_ref+mac_ref) |
|
599 |
+ decipher.verify(mac_ref) |
|
600 |
+ self.assertEqual(pt, pt_ref) |
|
601 |
+ |
|
602 |
+@@ -424,6 +443,16 @@ class AEADTests(unittest.TestCase): |
|
603 |
+ self.description = "Test for multiple updates in %s of %s" % \ |
|
604 |
+ (self.mode_name, self.module.__name__) |
|
605 |
+ |
|
606 |
++ # In all modes other than SIV, the associated data is a single |
|
607 |
++ # component that can be arbitrarilly split and submitted to update(). |
|
608 |
++ # |
|
609 |
++ # In SIV, associated data is instead organized in a vector or multiple |
|
610 |
++ # components. Each component is passed to update() as a whole. |
|
611 |
++ # This test is therefore not meaningful to SIV. |
|
612 |
++ if self.isMode("SIV"): |
|
613 |
++ return |
|
614 |
++ |
|
615 |
++ |
|
616 |
+ ad = b("").join([bchr(x) for x in xrange(0,128)]) |
|
617 |
+ |
|
618 |
+ mac1, mac2, mac3 = (None,)*3 |
|
619 |
+@@ -461,23 +490,23 @@ class AEADTests(unittest.TestCase): |
|
620 |
+ |
|
621 |
+ # Calling decrypt after encrypt raises an exception |
|
622 |
+ cipher = self.module.new(self.key, self.mode, self.iv) |
|
623 |
+- cipher.encrypt(b("PT")) |
|
624 |
+- self.assertRaises(TypeError, cipher.decrypt, b("XYZ")) |
|
625 |
++ cipher.encrypt(b("PT")*40) |
|
626 |
++ self.assertRaises(TypeError, cipher.decrypt, b("XYZ")*40) |
|
627 |
+ |
|
628 |
+ # Calling encrypt after decrypt raises an exception |
|
629 |
+ cipher = self.module.new(self.key, self.mode, self.iv) |
|
630 |
+- cipher.decrypt(b("CT")) |
|
631 |
+- self.assertRaises(TypeError, cipher.encrypt, b("XYZ")) |
|
632 |
++ cipher.decrypt(b("CT")*40) |
|
633 |
++ self.assertRaises(TypeError, cipher.encrypt, b("XYZ")*40) |
|
634 |
+ |
|
635 |
+ # Calling verify after encrypt raises an exception |
|
636 |
+ cipher = self.module.new(self.key, self.mode, self.iv) |
|
637 |
+- cipher.encrypt(b("PT")) |
|
638 |
++ cipher.encrypt(b("PT")*40) |
|
639 |
+ self.assertRaises(TypeError, cipher.verify, b("XYZ")) |
|
640 |
+ self.assertRaises(TypeError, cipher.hexverify, "12") |
|
641 |
+ |
|
642 |
+ # Calling digest after decrypt raises an exception |
|
643 |
+ cipher = self.module.new(self.key, self.mode, self.iv) |
|
644 |
+- cipher.decrypt(b("CT")) |
|
645 |
++ cipher.decrypt(b("CT")*40) |
|
646 |
+ self.assertRaises(TypeError, cipher.digest) |
|
647 |
+ self.assertRaises(TypeError, cipher.hexdigest) |
|
648 |
+ |
|
649 |
+@@ -490,13 +519,13 @@ class AEADTests(unittest.TestCase): |
|
650 |
+ # Calling update after encrypt raises an exception |
|
651 |
+ cipher = self.module.new(self.key, self.mode, self.iv) |
|
652 |
+ cipher.update(b("XX")) |
|
653 |
+- cipher.encrypt(b("PT")) |
|
654 |
++ cipher.encrypt(b("PT")*40) |
|
655 |
+ self.assertRaises(TypeError, cipher.update, b("XYZ")) |
|
656 |
+ |
|
657 |
+ # Calling update after decrypt raises an exception |
|
658 |
+ cipher = self.module.new(self.key, self.mode, self.iv) |
|
659 |
+ cipher.update(b("XX")) |
|
660 |
+- cipher.decrypt(b("CT")) |
|
661 |
++ cipher.decrypt(b("CT")*40) |
|
662 |
+ self.assertRaises(TypeError, cipher.update, b("XYZ")) |
|
663 |
+ |
|
664 |
+ def runTest(self): |
|
665 |
+@@ -642,10 +671,10 @@ def make_block_tests(module, module_name |
|
666 |
+ ] |
|
667 |
+ extra_tests_added = 1 |
|
668 |
+ # Extract associated data and MAC for AEAD modes |
|
669 |
+- if p_mode in ('CCM', 'EAX'): |
|
670 |
++ if p_mode in ('CCM', 'EAX', 'SIV'): |
|
671 |
+ assoc_data, params['plaintext'] = params['plaintext'].split('|') |
|
672 |
+ assoc_data2, params['ciphertext'], params['mac'] = params['ciphertext'].split('|') |
|
673 |
+- params['assoc_data'] = assoc_data |
|
674 |
++ params['assoc_data'] = assoc_data.split("-") |
|
675 |
+ params['mac_len'] = len(params['mac'])>>1 |
|
676 |
+ # Add the current test to the test suite |
|
677 |
+ tests.append(CipherSelfTest(module, params)) |
|
678 |
+@@ -669,7 +698,7 @@ def make_block_tests(module, module_name |
|
679 |
+ CCMMACLengthTest(module), |
|
680 |
+ CCMSplitEncryptionTest(module), |
|
681 |
+ ] |
|
682 |
+- for aead_mode in ("MODE_CCM","MODE_EAX"): |
|
683 |
++ for aead_mode in ("MODE_CCM","MODE_EAX", "MODE_SIV"): |
|
684 |
+ if hasattr(module, aead_mode): |
|
685 |
+ key_sizes = [] |
|
686 |
+ try: |
|
687 |
+--- a/lib/Crypto/SelfTest/Cipher/test_AES.py_org 2019-05-20 20:24:14.565228498 +0530 |
|
688 |
+@@ -1730,6 +1730,41 @@ test_data = [ |
|
689 |
+ 'EAX spec Appendix G', |
|
690 |
+ dict(mode='EAX', nonce='22E7ADD93CFC6393C57EC0B3C17D6B44') |
|
691 |
+ ), |
|
692 |
++ # Test vectors for SIV taken from RFC5297 |
|
693 |
++ # This is a list of tuples with 5 items: |
|
694 |
++ # |
|
695 |
++ # 1. Header + '|' + plaintext |
|
696 |
++ # 2. Header + '|' + ciphertext + '|' + MAC |
|
697 |
++ # 3. AES-128 key |
|
698 |
++ # 4. Description |
|
699 |
++ # 5. Dictionary of parameters to be passed to AES.new(). |
|
700 |
++ # It must include the nonce. |
|
701 |
++ # |
|
702 |
++ # A "Header" is a dash ('-') separated sequece of components. |
|
703 |
++ # |
|
704 |
++ ( '101112131415161718191a1b1c1d1e1f2021222324252627|112233445566778899aabbccddee', |
|
705 |
++ '101112131415161718191a1b1c1d1e1f2021222324252627|40c02b9690c4dc04daef7f6afe5c|' + |
|
706 |
++ '85632d07c6e8f37f950acd320a2ecc93', |
|
707 |
++ 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff', |
|
708 |
++ 'RFC5297 A.1', |
|
709 |
++ dict(mode='SIV', nonce=None) |
|
710 |
++ ), |
|
711 |
++ |
|
712 |
++ ( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988' + |
|
713 |
++ '7766554433221100-102030405060708090a0|' + |
|
714 |
++ '7468697320697320736f6d6520706c61696e7465787420746f20656e63727970' + |
|
715 |
++ '74207573696e67205349562d414553', |
|
716 |
++ |
|
717 |
++ '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddccbbaa9988' + |
|
718 |
++ '7766554433221100-102030405060708090a0|' + |
|
719 |
++ 'cb900f2fddbe404326601965c889bf17dba77ceb094fa663b7a3f748ba8af829' + |
|
720 |
++ 'ea64ad544a272e9c485b62a3fd5c0d|' + |
|
721 |
++ '7bdb6e3b432667eb06f4d14bff2fbd0f', |
|
722 |
++ |
|
723 |
++ '7f7e7d7c7b7a79787776757473727170404142434445464748494a4b4c4d4e4f', |
|
724 |
++ 'RFC5297 A.2', |
|
725 |
++ dict(mode='SIV', nonce='09f911029d74e35bd84156c5635688c0') |
|
726 |
++ ), |
|
727 |
+ ] |
|
728 |
+ |
|
729 |
+ def get_tests(config={}): |
|
730 |
+--- a/lib/Crypto/SelfTest/Protocol/test_KDF.py_org 2019-05-20 20:25:20.061229807 +0530 |
|
731 |
+@@ -27,7 +27,7 @@ from binascii import unhexlify |
|
732 |
+ |
|
733 |
+ from Crypto.SelfTest.st_common import list_test_cases |
|
734 |
+ from Crypto.Hash import SHA as SHA1,HMAC |
|
735 |
+- |
|
736 |
++from Crypto.Cipher import AES, DES3 |
|
737 |
+ from Crypto.Protocol.KDF import * |
|
738 |
+ |
|
739 |
+ def t2b(t): return unhexlify(b(t)) |
|
740 |
+@@ -84,11 +84,67 @@ class PBKDF2_Tests(unittest.TestCase): |
|
741 |
+ res2 = PBKDF2(v[0], t2b(v[1]), v[2], v[3], prf) |
|
742 |
+ self.assertEqual(res, t2b(v[4])) |
|
743 |
+ self.assertEqual(res, res2) |
|
744 |
++class S2V_Tests(unittest.TestCase): |
|
745 |
++ |
|
746 |
++ # Sequence of test vectors. |
|
747 |
++ # Each test vector is made up by: |
|
748 |
++ # Item #0: a tuple of strings |
|
749 |
++ # Item #1: an AES key |
|
750 |
++ # Item #2: the result |
|
751 |
++ # Item #3: the cipher module S2V is based on |
|
752 |
++ # Everything is hex encoded |
|
753 |
++ _testData = [ |
|
754 |
++ |
|
755 |
++ # RFC5297, A.1 |
|
756 |
++ ( |
|
757 |
++ ( '101112131415161718191a1b1c1d1e1f2021222324252627', |
|
758 |
++ '112233445566778899aabbccddee' ), |
|
759 |
++ 'fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0', |
|
760 |
++ '85632d07c6e8f37f950acd320a2ecc93', |
|
761 |
++ AES |
|
762 |
++ ), |
|
763 |
++ |
|
764 |
++ # RFC5297, A.2 |
|
765 |
++ ( |
|
766 |
++ ( '00112233445566778899aabbccddeeffdeaddadadeaddadaffeeddcc'+ |
|
767 |
++ 'bbaa99887766554433221100', |
|
768 |
++ '102030405060708090a0', |
|
769 |
++ '09f911029d74e35bd84156c5635688c0', |
|
770 |
++ '7468697320697320736f6d6520706c61'+ |
|
771 |
++ '696e7465787420746f20656e63727970'+ |
|
772 |
++ '74207573696e67205349562d414553'), |
|
773 |
++ '7f7e7d7c7b7a79787776757473727170', |
|
774 |
++ '7bdb6e3b432667eb06f4d14bff2fbd0f', |
|
775 |
++ AES |
|
776 |
++ ), |
|
777 |
++ |
|
778 |
++ ] |
|
779 |
++ |
|
780 |
++ def test1(self): |
|
781 |
++ """Verify correctness of test vector""" |
|
782 |
++ for tv in self._testData: |
|
783 |
++ s2v = S2V.new(t2b(tv[1]), tv[3]) |
|
784 |
++ for s in tv[0]: |
|
785 |
++ s2v.update(t2b(s)) |
|
786 |
++ result = s2v.derive() |
|
787 |
++ self.assertEqual(result, t2b(tv[2])) |
|
788 |
++ |
|
789 |
++ def test2(self): |
|
790 |
++ """Verify that no more than 127(AES) and 63(TDES) |
|
791 |
++ components are accepted.""" |
|
792 |
++ key = bchr(0)*16 |
|
793 |
++ for module in (AES, DES3): |
|
794 |
++ s2v = S2V.new(key, module) |
|
795 |
++ max_comps = module.block_size*8-1 |
|
796 |
++ for i in xrange(max_comps): |
|
797 |
++ s2v.update(b("XX")) |
|
798 |
++ self.assertRaises(TypeError, s2v.update, b("YY")) |
|
799 |
+ |
|
800 |
+ def get_tests(config={}): |
|
801 |
+ tests = [] |
|
802 |
+ tests += list_test_cases(PBKDF1_Tests) |
|
803 |
+ tests += list_test_cases(PBKDF2_Tests) |
|
804 |
++ tests += list_test_cases(S2V_Tests) |
|
805 |
+ return tests |
|
806 |
+ |
|
807 |
+ if __name__ == '__main__': |
0 | 808 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,80 @@ |
0 |
+This header file is taken from: |
|
1 |
+https://github.com/dlitz/pycrypto/commits/master/src/pycrypto_common.h |
|
2 |
+ |
|
3 |
+ |
|
4 |
+ |
|
5 |
+--- a/src/pycrypto_common.h_org 2019-05-20 23:37:40.605460329 +0530 |
|
6 |
+@@ -0,0 +1,41 @@ |
|
7 |
++/* |
|
8 |
++ * pycrypto_compat.h: Common header file for PyCrypto |
|
9 |
++ * |
|
10 |
++ * Written in 2013 by Dwayne C. Litzenberger <dlitz@dlitz.net> |
|
11 |
++ * |
|
12 |
++ * =================================================================== |
|
13 |
++ * The contents of this file are dedicated to the public domain. To |
|
14 |
++ * the extent that dedication to the public domain is not available, |
|
15 |
++ * everyone is granted a worldwide, perpetual, royalty-free, |
|
16 |
++ * non-exclusive license to exercise all rights associated with the |
|
17 |
++ * contents of this file for any purpose whatsoever. |
|
18 |
++ * No rights are reserved. |
|
19 |
++ * |
|
20 |
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
21 |
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
22 |
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
23 |
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|
24 |
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
25 |
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
26 |
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
27 |
++ * SOFTWARE. |
|
28 |
++ * =================================================================== |
|
29 |
++ */ |
|
30 |
++#ifndef PYCRYPTO_COMMON_H |
|
31 |
++#define PYCRYPTO_COMMON_H |
|
32 |
++ |
|
33 |
++#include "Python.h" |
|
34 |
++#include "pycrypto_compat.h" |
|
35 |
++#include "config.h" |
|
36 |
++#if HAVE_STDINT_H |
|
37 |
++# include <stdint.h> |
|
38 |
++#elif HAVE_INTTYPES_H |
|
39 |
++# include <inttypes.h> |
|
40 |
++#elif HAVE_SYS_INTTYPES_H |
|
41 |
++# include <sys/inttypes.h> |
|
42 |
++#else |
|
43 |
++# error "stdint.h and inttypes.h not found" |
|
44 |
++#endif |
|
45 |
++ |
|
46 |
++ |
|
47 |
++#endif /* PYCRYPTO_COMMON_H */ |
|
48 |
+--- a/lib/Crypto/Cipher/blockalgo.py_org 2019-05-21 04:13:23.009790764 +0530 |
|
49 |
+@@ -710,7 +710,7 @@ class BlockAlgo: |
|
50 |
+ self._next = [self.encrypt, self.digest] |
|
51 |
+ if self.mode == MODE_CCM: |
|
52 |
+ if self._assoc_len is None: |
|
53 |
+- self._start_ccm(assoc_len=self._cipherMAC.get_len() |
|
54 |
++ self._start_ccm(assoc_len=self._cipherMAC.get_len()) |
|
55 |
+ if self._msg_len is None: |
|
56 |
+ self._start_ccm(msg_len=len(plaintext)) |
|
57 |
+ self._next = [self.digest] |
|
58 |
+@@ -822,7 +822,7 @@ class BlockAlgo: |
|
59 |
+ if self.mode == MODE_GCM: |
|
60 |
+ if not self._done_assoc_data: |
|
61 |
+ self._cipherMAC.zero_pad() |
|
62 |
+- self._done_assoc_data = True |
|
63 |
++ self._done_assoc_data = True |
|
64 |
+ |
|
65 |
+ self._cipherMAC.update(ciphertext) |
|
66 |
+ self._msg_len += len(ciphertext) |
|
67 |
+--- a/lib/Crypto/Protocol/KDF.py_org 2019-05-21 06:31:03.381955765 +0530 |
|
68 |
+@@ -188,7 +188,7 @@ class S2V(object): |
|
69 |
+ |
|
70 |
+ if self._n_updates==0: |
|
71 |
+ raise TypeError("Too many components passed to S2V") |
|
72 |
+- self._n_updates -= 1 |
|
73 |
++ self._n_updates -= 1 |
|
74 |
+ |
|
75 |
+ mac = CMAC.new(self._key, msg=self._last_string, ciphermod=self._ciphermod) |
|
76 |
+ self._cache = strxor(self._double(self._cache), mac.digest()) |
... | ... |
@@ -4,27 +4,32 @@ |
4 | 4 |
Summary: The Python Cryptography Toolkit. |
5 | 5 |
Name: pycrypto |
6 | 6 |
Version: 2.6.1 |
7 |
-Release: 4%{?dist} |
|
7 |
+Release: 5%{?dist} |
|
8 | 8 |
License: Public Domain and Python |
9 | 9 |
URL: http://www.pycrypto.org/ |
10 | 10 |
Source0: https://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/%{name}-%{version}.tar.gz |
11 | 11 |
%define sha1 pycrypto=aeda3ed41caf1766409d4efc689b9ca30ad6aeb2 |
12 | 12 |
Patch0: pycrypto-2.6.1-CVE-2013-7459.patch |
13 | 13 |
Patch1: pycrypto-2.6.1-CVE-2018-6594.patch |
14 |
+Patch2: add_ccm_support_aes_only.patch |
|
15 |
+Patch3: add_eax_authenticated_encryption.patch |
|
16 |
+Patch4: add_support_for_siv.patch |
|
17 |
+Patch5: add_gsm_support_aes.patch |
|
18 |
+Patch6: fix_patch_errors.patch |
|
14 | 19 |
Group: Development/Tools |
15 | 20 |
Vendor: VMware, Inc. |
16 | 21 |
Distribution: Photon |
17 | 22 |
|
18 | 23 |
BuildRequires: python-setuptools |
19 | 24 |
BuildRequires: python2-devel |
25 |
+BuildRequires: python3-devel |
|
26 |
+BuildRequires: python3-libs |
|
20 | 27 |
Requires: python2 |
21 | 28 |
%description |
22 | 29 |
This is a collection of both secure hash functions (such as SHA256 and RIPEMD160), and various encryption algorithms (AES, DES, RSA, ElGamal, etc.). |
23 | 30 |
|
24 | 31 |
%package -n python3-pycrypto |
25 | 32 |
Summary: python3-pycrypto |
26 |
-BuildRequires: python3-devel |
|
27 |
-BuildRequires: python3-libs |
|
28 | 33 |
|
29 | 34 |
Requires: python3 |
30 | 35 |
%description -n python3-pycrypto |
... | ... |
@@ -35,6 +40,12 @@ Python 3 version. |
35 | 35 |
%setup -q |
36 | 36 |
%patch0 -p1 |
37 | 37 |
%patch1 -p1 |
38 |
+%patch2 -p1 |
|
39 |
+%patch3 -p1 |
|
40 |
+%patch4 -p1 |
|
41 |
+%patch5 -p1 |
|
42 |
+%patch6 -p1 |
|
43 |
+ |
|
38 | 44 |
|
39 | 45 |
%build |
40 | 46 |
python2 setup.py build |
... | ... |
@@ -57,6 +68,8 @@ python3 setup.py test |
57 | 57 |
%{python3_sitelib}/* |
58 | 58 |
|
59 | 59 |
%changelog |
60 |
+* Fri May 17 2019 Tapas Kundu <tkundu@vmware.com> 2.6.1-5 |
|
61 |
+- Add support for GCM mode (AES only). |
|
60 | 62 |
* Thu Nov 29 2018 Siju Maliakkal <smaliakkal@vmware.com> 2.6.1-4 |
61 | 63 |
- Apply patch for CVE-2018-6594 |
62 | 64 |
* Thu Jul 20 2017 Anish Swaminathan <anishs@vmware.com> 2.6.1-3 |
... | ... |
@@ -1,6 +1,6 @@ |
1 | 1 |
Summary: Highly reliable distributed coordination |
2 | 2 |
Name: zookeeper |
3 |
-Version: 3.4.13 |
|
3 |
+Version: 3.4.14 |
|
4 | 4 |
Release: 1%{?dist} |
5 | 5 |
URL: http://zookeeper.apache.org/ |
6 | 6 |
License: Apache License, Version 2.0 |
... | ... |
@@ -8,7 +8,7 @@ Group: Applications/System |
8 | 8 |
Vendor: VMware, Inc. |
9 | 9 |
Distribution: Photon |
10 | 10 |
Source: http://apache.claz.org/zookeeper/zookeeper/zookeeper-%{version}/%{name}-%{version}.tar.gz |
11 |
-%define sha1 zookeeper=a989b527f3f990d471e6d47ee410e57d8be7620b |
|
11 |
+%define sha1 zookeeper=285a0c85112d9f99d42cbbf8fb750c9aa5474716 |
|
12 | 12 |
Source1: zookeeper.service |
13 | 13 |
Source2: zkEnv.sh |
14 | 14 |
Patch0: zookeeper-3.4.8-server.patch |
... | ... |
@@ -64,7 +64,7 @@ getent passwd zookeeper >/dev/null || /usr/sbin/useradd --comment "ZooKeeper" -- |
64 | 64 |
%post |
65 | 65 |
%{_sbindir}/ldconfig |
66 | 66 |
%systemd_post zookeeper.service |
67 |
- |
|
67 |
+ |
|
68 | 68 |
%preun |
69 | 69 |
%systemd_preun zookeeper.service |
70 | 70 |
|
... | ... |
@@ -86,6 +86,9 @@ fi |
86 | 86 |
%{_prefix} |
87 | 87 |
|
88 | 88 |
%changelog |
89 |
+* Fri May 31 2019 Tapas Kundu <tkundu@vmware.com> 3.4.14-1 |
|
90 |
+- Updated to release 3.4.14 |
|
91 |
+- Fix for CVE-2019-0201 |
|
89 | 92 |
* Wed Sep 19 2018 Siju Maliakkal <smaliakkal@vmware.com> 3.4.13-1 |
90 | 93 |
- Update to latest version |
91 | 94 |
* Wed Sep 27 2017 Harish Udaiya Kumar <hudaiyakumar@vmware.com> 3.4.10-7 |