Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: third_party/tlslite/patches/aes_gcm.patch

Issue 875683002: Implement AES-GCM in tlslite. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 diff --git a/third_party/tlslite/tests/tlstest.py b/third_party/tlslite/tests/tl stest.py
2 index fa1b13f..7985d23 100755
3 --- a/third_party/tlslite/tests/tlstest.py
4 +++ b/third_party/tlslite/tests/tlstest.py
5 @@ -318,9 +318,11 @@ def clientTestCmd(argv):
6
7 print("Test 23 - throughput test")
8 for implementation in implementations:
9 - for cipher in ["aes128", "aes256", "3des", "rc4"]:
10 + for cipher in ["aes128gcm", "aes128", "aes256", "3des", "rc4"]:
11 if cipher == "3des" and implementation not in ("openssl", "pycrypto "):
12 continue
13 + if cipher == "aes128gcm" and implementation not in ("pycrypto", "py thon"):
14 + continue
15
16 print("Test 23:", end=' ')
17 connection = connect()
18 @@ -678,9 +680,11 @@ def serverTestCmd(argv):
19
20 print("Test 23 - throughput test")
21 for implementation in implementations:
22 - for cipher in ["aes128", "aes256", "3des", "rc4"]:
23 + for cipher in ["aes128gcm", "aes128", "aes256", "3des", "rc4"]:
24 if cipher == "3des" and implementation not in ("openssl", "pycrypto "):
25 continue
26 + if cipher == "aes128gcm" and implementation not in ("pycrypto", "py thon"):
27 + continue
28
29 print("Test 23:", end=' ')
30 connection = connect()
31 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlsl ite/constants.py
32 index 7ee70be..e5b88af 100644
33 --- a/third_party/tlslite/tlslite/constants.py
34 +++ b/third_party/tlslite/tlslite/constants.py
35 @@ -175,6 +175,9 @@ class CipherSuite:
36 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067
37 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B
38
39 + TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
40 + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
41 +
42 tripleDESSuites = []
43 tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
44 tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
45 @@ -199,6 +202,10 @@ class CipherSuite:
46 aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
47 aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
48
49 + aes128GcmSuites = []
50 + aes128GcmSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
51 + aes128GcmSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
52 +
53 rc4Suites = []
54 rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA)
55 rc4Suites.append(TLS_RSA_WITH_RC4_128_MD5)
56 @@ -225,25 +232,35 @@ class CipherSuite:
57 sha256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
58 sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
59 sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
60 + sha256Suites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
61 + sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
62 +
63 + aeadSuites = aes128GcmSuites
64
65
66 md5Suites = []
67 md5Suites.append(TLS_RSA_WITH_RC4_128_MD5)
68
69 @staticmethod
70 - def _filterSuites(suites, settings):
71 + def _filterSuites(suites, settings, version=None):
72 + if version is None:
73 + version = settings.maxVersion
74 macNames = settings.macNames
75 cipherNames = settings.cipherNames
76 keyExchangeNames = settings.keyExchangeNames
77 macSuites = []
78 if "sha" in macNames:
79 macSuites += CipherSuite.shaSuites
80 - if "sha256" in macNames:
81 + if "sha256" in macNames and version >= (3,3):
82 macSuites += CipherSuite.sha256Suites
83 if "md5" in macNames:
84 macSuites += CipherSuite.md5Suites
85 + if "aead" in macNames and version >= (3,3):
86 + macSuites += CipherSuite.aeadSuites
87
88 cipherSuites = []
89 + if "aes128gcm" in cipherNames and version >= (3,3):
90 + cipherSuites += CipherSuite.aes128GcmSuites
91 if "aes128" in cipherNames:
92 cipherSuites += CipherSuite.aes128Suites
93 if "aes256" in cipherNames:
94 @@ -274,8 +291,8 @@ class CipherSuite:
95 srpSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
96
97 @staticmethod
98 - def getSrpSuites(settings):
99 - return CipherSuite._filterSuites(CipherSuite.srpSuites, settings)
100 + def getSrpSuites(settings, version=None):
101 + return CipherSuite._filterSuites(CipherSuite.srpSuites, settings, versi on)
102
103 srpCertSuites = []
104 srpCertSuites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA)
105 @@ -283,16 +300,17 @@ class CipherSuite:
106 srpCertSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
107
108 @staticmethod
109 - def getSrpCertSuites(settings):
110 - return CipherSuite._filterSuites(CipherSuite.srpCertSuites, settings)
111 + def getSrpCertSuites(settings, version=None):
112 + return CipherSuite._filterSuites(CipherSuite.srpCertSuites, settings, v ersion)
113
114 srpAllSuites = srpSuites + srpCertSuites
115
116 @staticmethod
117 - def getSrpAllSuites(settings):
118 - return CipherSuite._filterSuites(CipherSuite.srpAllSuites, settings)
119 + def getSrpAllSuites(settings, version=None):
120 + return CipherSuite._filterSuites(CipherSuite.srpAllSuites, settings, ve rsion)
121
122 certSuites = []
123 + certSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
124 certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA256)
125 certSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA256)
126 certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
127 @@ -302,10 +320,11 @@ class CipherSuite:
128 certSuites.append(TLS_RSA_WITH_RC4_128_MD5)
129
130 @staticmethod
131 - def getCertSuites(settings):
132 - return CipherSuite._filterSuites(CipherSuite.certSuites, settings)
133 + def getCertSuites(settings, version=None):
134 + return CipherSuite._filterSuites(CipherSuite.certSuites, settings, vers ion)
135
136 dheCertSuites = []
137 + dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
138 dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256)
139 dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256)
140 dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
141 @@ -313,8 +332,8 @@ class CipherSuite:
142 dheCertSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
143
144 @staticmethod
145 - def getDheCertSuites(settings):
146 - return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings)
147 + def getDheCertSuites(settings, version=None):
148 + return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings, v ersion)
149
150 certAllSuites = srpCertSuites + certSuites + dheCertSuites
151
152 @@ -323,8 +342,8 @@ class CipherSuite:
153 anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
154
155 @staticmethod
156 - def getAnonSuites(settings):
157 - return CipherSuite._filterSuites(CipherSuite.anonSuites, settings)
158 + def getAnonSuites(settings, version=None):
159 + return CipherSuite._filterSuites(CipherSuite.anonSuites, settings, vers ion)
160
161 dhAllSuites = dheCertSuites + anonSuites
162
163 diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlsl ite/tlslite/handshakesettings.py
164 index 2e9e06d..2f11aaa 100644
165 --- a/third_party/tlslite/tlslite/handshakesettings.py
166 +++ b/third_party/tlslite/tlslite/handshakesettings.py
167 @@ -11,11 +11,9 @@ from .constants import CertificateType
168 from .utils import cryptomath
169 from .utils import cipherfactory
170
171 -# RC4 is preferred as faster in Python, works in SSL3, and immune to CBC
172 -# issues such as timing attacks
173 -CIPHER_NAMES = ["rc4", "aes256", "aes128", "3des"]
174 -MAC_NAMES = ["sha", "sha256"] # Don't allow "md5" by default.
175 -ALL_MAC_NAMES = ["sha", "sha256", "md5"]
176 +CIPHER_NAMES = ["aes128gcm", "rc4", "aes256", "aes128", "3des"]
177 +MAC_NAMES = ["sha", "sha256", "aead"] # Don't allow "md5" by default.
178 +ALL_MAC_NAMES = MAC_NAMES + ["md5"]
179 KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
180 CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
181 CERTIFICATE_TYPES = ["x509"]
182 @@ -42,7 +40,7 @@ class HandshakeSettings(object):
183 The default is 8193.
184
185 @type cipherNames: list
186 - @ivar cipherNames: The allowed ciphers, in order of preference.
187 + @ivar cipherNames: The allowed ciphers.
188
189 The allowed values in this list are 'aes256', 'aes128', '3des', and
190 'rc4'. If these settings are used with a client handshake, they
191 @@ -68,8 +66,7 @@ class HandshakeSettings(object):
192
193
194 @type certificateTypes: list
195 - @ivar certificateTypes: The allowed certificate types, in order of
196 - preference.
197 + @ivar certificateTypes: The allowed certificate types.
198
199 The only allowed certificate type is 'x509'. This list is only used with a
200 client handshake. The client will advertise to the server which certificat e
201 @@ -197,10 +194,6 @@ class HandshakeSettings(object):
202 if not other.maxVersion in ((3,0), (3,1), (3,2), (3,3)):
203 raise ValueError("maxVersion set incorrectly")
204
205 - if other.maxVersion < (3,3):
206 - # No sha256 pre TLS 1.2
207 - other.macNames = [e for e in self.macNames if e != "sha256"]
208 -
209 return other
210
211 def _getCertificateTypes(self):
212 diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/ tlslite/tlsconnection.py
213 index 3d97e97..0e13a78 100644
214 --- a/third_party/tlslite/tlslite/tlsconnection.py
215 +++ b/third_party/tlslite/tlslite/tlsconnection.py
216 @@ -1385,21 +1385,6 @@ class TLSConnection(TLSRecordLayer):
217
218 def _serverGetClientHello(self, settings, certChain, verifierDB,
219 sessionCache, anon, fallbackSCSV):
220 - #Initialize acceptable cipher suites
221 - cipherSuites = []
222 - if verifierDB:
223 - if certChain:
224 - cipherSuites += \
225 - CipherSuite.getSrpCertSuites(settings)
226 - cipherSuites += CipherSuite.getSrpSuites(settings)
227 - elif certChain:
228 - cipherSuites += CipherSuite.getDheCertSuites(settings)
229 - cipherSuites += CipherSuite.getCertSuites(settings)
230 - elif anon:
231 - cipherSuites += CipherSuite.getAnonSuites(settings)
232 - else:
233 - assert(False)
234 -
235 #Tentatively set version to most-desirable version, so if an error
236 #occurs parsing the ClientHello, this is what we'll use for the
237 #error alert
238 @@ -1451,7 +1436,22 @@ class TLSConnection(TLSRecordLayer):
239
240 else:
241 #Set the version to the client's version
242 - self.version = clientHello.client_version
243 + self.version = clientHello.client_version
244 +
245 + #Initialize acceptable cipher suites
246 + cipherSuites = []
247 + if verifierDB:
248 + if certChain:
249 + cipherSuites += \
250 + CipherSuite.getSrpCertSuites(settings, self.version)
251 + cipherSuites += CipherSuite.getSrpSuites(settings, self.version)
252 + elif certChain:
253 + cipherSuites += CipherSuite.getDheCertSuites(settings, self.version )
254 + cipherSuites += CipherSuite.getCertSuites(settings, self.version)
255 + elif anon:
256 + cipherSuites += CipherSuite.getAnonSuites(settings, self.version)
257 + else:
258 + assert(False)
259
260 #If resumption was requested and we have a session cache...
261 if clientHello.session_id and sessionCache:
262 diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite /tlslite/tlsrecordlayer.py
263 index a09499d..545ff63 100644
264 --- a/third_party/tlslite/tlslite/tlsrecordlayer.py
265 +++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
266 @@ -11,7 +11,8 @@ from __future__ import generators
267
268 from .utils.compat import *
269 from .utils.cryptomath import *
270 -from .utils.cipherfactory import createAES, createRC4, createTripleDES
271 +from .utils.cipherfactory import createAESGCM, createAES, createRC4, \
272 + createTripleDES
273 from .utils.codec import *
274 from .errors import *
275 from .messages import *
276 @@ -594,8 +595,26 @@ class TLSRecordLayer(object):
277
278 #Encrypt for Block or Stream Cipher
279 if self._writeState.encContext:
280 + #Seal (for AEAD)
281 + if self._writeState.encContext.isAEAD:
282 + #Assemble the AD.
283 + seqnumBytes = self._writeState.getSeqNumBytes()
284 + ad = seqnumBytes + bytearray([contentType, self.version[0],
285 + self.version[1], len(b)//256,
286 + len(b)%256])
287 +
288 + #The nonce is always the fixed nonce and the sequence number.
289 + nonce = self._writeState.fixedNonce + seqnumBytes
290 + assert len(nonce) == self._writeState.encContext.nonceLength
291 +
292 + b = self._writeState.encContext.seal(nonce, b, ad)
293 +
294 + #The only AEAD supported, AES-GCM, has an explicit variable
295 + #nonce.
296 + b = seqnumBytes + b
297 +
298 #Add padding and encrypt (for Block Cipher):
299 - if self._writeState.encContext.isBlockCipher:
300 + elif self._writeState.encContext.isBlockCipher:
301
302 #Add TLS 1.1 fixed block
303 if self.version >= (3,2):
304 @@ -967,6 +986,36 @@ class TLSRecordLayer(object):
305
306 def _decryptRecord(self, recordType, b):
307 if self._readState.encContext:
308 + #Open if it's an AEAD.
309 + if self._readState.encContext.isAEAD:
310 + #The only AEAD supported, AES-GCM, has an explicit variable
311 + #nonce.
312 + explicitNonceLength = 8
313 + if explicitNonceLength > len(b):
314 + #Publicly invalid.
315 + for result in self._sendError(
316 + AlertDescription.bad_record_mac,
317 + "MAC failure (or padding failure)"):
318 + yield result
319 + nonce = self._readState.fixedNonce + b[:explicitNonceLength]
320 + b = b[8:]
321 +
322 + #Assemble the AD.
323 + seqnumBytes = self._readState.getSeqNumBytes()
324 + plaintextLen = len(b) - self._readState.encContext.tagLength
325 + ad = seqnumBytes + bytearray([recordType, self.version[0],
326 + self.version[1],
327 + plaintextLen//256,
328 + plaintextLen%256])
329 +
330 + b = self._readState.encContext.open(nonce, b, ad)
331 + if b is None:
332 + for result in self._sendError(
333 + AlertDescription.bad_record_mac,
334 + "MAC failure (or padding failure)"):
335 + yield result
336 + yield b
337 + return
338
339 #Decrypt if it's a block cipher
340 if self._readState.encContext.isBlockCipher:
341 @@ -1064,7 +1113,11 @@ class TLSRecordLayer(object):
342
343 def _calcPendingStates(self, cipherSuite, masterSecret,
344 clientRandom, serverRandom, implementations):
345 - if cipherSuite in CipherSuite.aes128Suites:
346 + if cipherSuite in CipherSuite.aes128GcmSuites:
347 + keyLength = 16
348 + ivLength = 4
349 + createCipherFunc = createAESGCM
350 + elif cipherSuite in CipherSuite.aes128Suites:
351 keyLength = 16
352 ivLength = 16
353 createCipherFunc = createAES
354 @@ -1083,7 +1136,10 @@ class TLSRecordLayer(object):
355 else:
356 raise AssertionError()
357
358 - if cipherSuite in CipherSuite.shaSuites:
359 + if cipherSuite in CipherSuite.aeadSuites:
360 + macLength = 0
361 + digestmod = None
362 + elif cipherSuite in CipherSuite.shaSuites:
363 macLength = 20
364 digestmod = hashlib.sha1
365 elif cipherSuite in CipherSuite.sha256Suites:
366 @@ -1092,8 +1148,12 @@ class TLSRecordLayer(object):
367 elif cipherSuite in CipherSuite.md5Suites:
368 macLength = 16
369 digestmod = hashlib.md5
370 + else:
371 + raise AssertionError()
372
373 - if self.version == (3,0):
374 + if not digestmod:
375 + createMACFunc = None
376 + elif self.version == (3,0):
377 createMACFunc = createMAC_SSL
378 elif self.version in ((3,1), (3,2), (3,3)):
379 createMACFunc = createHMAC
380 @@ -1128,16 +1188,28 @@ class TLSRecordLayer(object):
381 serverKeyBlock = p.getFixBytes(keyLength)
382 clientIVBlock = p.getFixBytes(ivLength)
383 serverIVBlock = p.getFixBytes(ivLength)
384 - clientPendingState.macContext = createMACFunc(
385 - compatHMAC(clientMACBlock), digestmod=digestmod)
386 - serverPendingState.macContext = createMACFunc(
387 - compatHMAC(serverMACBlock), digestmod=digestmod)
388 - clientPendingState.encContext = createCipherFunc(clientKeyBlock,
389 - clientIVBlock,
390 - implementations)
391 - serverPendingState.encContext = createCipherFunc(serverKeyBlock,
392 - serverIVBlock,
393 - implementations)
394 + if digestmod:
395 + # Legacy cipher.
396 + clientPendingState.macContext = createMACFunc(
397 + compatHMAC(clientMACBlock), digestmod=digestmod)
398 + serverPendingState.macContext = createMACFunc(
399 + compatHMAC(serverMACBlock), digestmod=digestmod)
400 + clientPendingState.encContext = createCipherFunc(clientKeyBlock,
401 + clientIVBlock,
402 + implementations)
403 + serverPendingState.encContext = createCipherFunc(serverKeyBlock,
404 + serverIVBlock,
405 + implementations)
406 + else:
407 + # AEAD.
408 + clientPendingState.macContext = None
409 + serverPendingState.macContext = None
410 + clientPendingState.encContext = createCipherFunc(clientKeyBlock,
411 + implementations)
412 + serverPendingState.encContext = createCipherFunc(serverKeyBlock,
413 + implementations)
414 + clientPendingState.fixedNonce = clientIVBlock
415 + serverPendingState.fixedNonce = serverIVBlock
416
417 #Assign new connection states to pending states
418 if self._client:
419 diff --git a/third_party/tlslite/tlslite/utils/aes.py b/third_party/tlslite/tlsl ite/utils/aes.py
420 index 95afaa3..5a038fb 100644
421 --- a/third_party/tlslite/tlslite/utils/aes.py
422 +++ b/third_party/tlslite/tlslite/utils/aes.py
423 @@ -12,6 +12,7 @@ class AES(object):
424 if len(IV) != 16:
425 raise AssertionError()
426 self.isBlockCipher = True
427 + self.isAEAD = False
428 self.block_size = 16
429 self.implementation = implementation
430 if len(key)==16:
431 @@ -31,4 +32,4 @@ class AES(object):
432 #CBC-Mode decryption, returns plaintext
433 #WARNING: *MAY* modify the input as well
434 def decrypt(self, ciphertext):
435 - assert(len(ciphertext) % 16 == 0)
436 \ No newline at end of file
437 + assert(len(ciphertext) % 16 == 0)
438 diff --git a/third_party/tlslite/tlslite/utils/aesgcm.py b/third_party/tlslite/t lslite/utils/aesgcm.py
439 new file mode 100644
440 index 0000000..4cb7720
441 --- /dev/null
442 +++ b/third_party/tlslite/tlslite/utils/aesgcm.py
443 @@ -0,0 +1,193 @@
444 +# Author: Google
445 +# See the LICENSE file for legal information regarding use of this file.
446 +
447 +# GCM derived from Go's implementation in crypto/cipher.
448 +#
449 +# https://golang.org/src/crypto/cipher/gcm.go
450 +
451 +# GCM works over elements of the field GF(2^128), each of which is a 128-bit
452 +# polynomial. Throughout this implementation, polynomials are represented as
453 +# Python integers with the low-order terms at the most significant bits. So a
454 +# 128-bit polynomial is an integer from 0 to 2^128-1 with the most significant
455 +# bit representing the x^0 term and the least significant bit representing the
456 +# x^127 term. This bit reversal also applies to polynomials used as indices in a
457 +# look-up table.
458 +
459 +from .cryptomath import bytesToNumber, numberToByteArray
460 +
461 +class AESGCM(object):
462 + """
463 + AES-GCM implementation. Note: this implementation does not attempt
464 + to be side-channel resistant. It's also rather slow.
465 + """
466 +
467 + def __init__(self, key, implementation, rawAesEncrypt):
468 + self.isBlockCipher = False
469 + self.isAEAD = True
470 + self.nonceLength = 12
471 + self.tagLength = 16
472 + self.implementation = implementation
473 + if len(key) == 16:
474 + self.name = "aes128gcm"
475 + elif len(key) == 32:
476 + self.name = "aes256gcm"
477 + else:
478 + raise AssertionError()
479 +
480 + self._rawAesEncrypt = rawAesEncrypt
481 +
482 + # The GCM key is AES(0).
483 + h = bytesToNumber(self._rawAesEncrypt(bytearray(16)))
484 +
485 + # Pre-compute all 4-bit multiples of h. Note that bits are reversed
486 + # because our polynomial representation places low-order terms at the
487 + # most significant bit. Thus x^0 * h = h is at index 0b1000 = 8 and
488 + # x^1 * h is at index 0b0100 = 4.
489 + self._productTable = [0] * 16
490 + self._productTable[_reverseBits(1)] = h
491 + for i in range(2, 16, 2):
492 + self._productTable[_reverseBits(i)] = \
493 + _gcmShift(self._productTable[_reverseBits(i/2)])
494 + self._productTable[_reverseBits(i+1)] = \
495 + _gcmAdd(self._productTable[_reverseBits(i)], h)
496 +
497 + def _rawAesCtrEncrypt(self, counter, inp):
498 + """
499 + Encrypts (or decrypts) plaintext with AES-CTR. counter is modified.
500 + """
501 + out = bytearray(len(inp))
502 + for i in range(0, len(out), 16):
503 + mask = self._rawAesEncrypt(counter)
504 + for j in range(i, min(len(out), i + 16)):
505 + out[j] = inp[j] ^ mask[j-i]
506 + _inc32(counter)
507 + return out
508 +
509 + def _auth(self, ciphertext, ad, tagMask):
510 + y = 0
511 + y = self._update(y, ad)
512 + y = self._update(y, ciphertext)
513 + y ^= (len(ad) << (3 + 64)) | (len(ciphertext) << 3)
514 + y = self._mul(y)
515 + y ^= bytesToNumber(tagMask)
516 + return numberToByteArray(y, 16)
517 +
518 + def _update(self, y, data):
519 + for i in range(0, len(data) // 16):
520 + y ^= bytesToNumber(data[16*i:16*i+16])
521 + y = self._mul(y)
522 + extra = len(data) % 16
523 + if extra != 0:
524 + block = bytearray(16)
525 + block[:extra] = data[-extra:]
526 + y ^= bytesToNumber(block)
527 + y = self._mul(y)
528 + return y
529 +
530 + def _mul(self, y):
531 + """ Returns y*H, where H is the GCM key. """
532 + ret = 0
533 + # Multiply H by y 4 bits at a time, starting with the highest power
534 + # terms.
535 + for i in range(0, 128, 4):
536 + # Multiply by x^4. The reduction for the top four terms is
537 + # precomputed.
538 + retHigh = ret & 0xf
539 + ret >>= 4
540 + ret ^= (_gcmReductionTable[retHigh] << (128-16))
541 +
542 + # Add in y' * H where y' are the next four terms of y, shifted down
543 + # to the x^0..x^4. This is one of the pre-computed multiples of
544 + # H. The multiplication by x^4 shifts them back into place.
545 + ret ^= self._productTable[y & 0xf]
546 + y >>= 4
547 + assert y == 0
548 + return ret
549 +
550 + def seal(self, nonce, plaintext, data):
551 + """
552 + Encrypts and authenticates plaintext using nonce and data. Returns the
553 + ciphertext, consisting of the encrypted plaintext and tag concatenated.
554 + """
555 +
556 + if len(nonce) != 12:
557 + raise ValueError("Bad nonce length")
558 +
559 + # The initial counter value is the nonce, followed with a 32-bit counte r
560 + # that starts at 1. It's used to compute the tag mask.
561 + counter = bytearray(16)
562 + counter[:12] = nonce
563 + counter[-1] = 1
564 + tagMask = self._rawAesEncrypt(counter)
565 +
566 + # The counter starts at 2 for the actual encryption.
567 + counter[-1] = 2
568 + ciphertext = self._rawAesCtrEncrypt(counter, plaintext)
569 +
570 + tag = self._auth(ciphertext, data, tagMask)
571 +
572 + return ciphertext + tag
573 +
574 + def open(self, nonce, ciphertext, data):
575 + """
576 + Decrypts and authenticates ciphertext using nonce and data. If the
577 + tag is valid, the plaintext is returned. If the tag is invalid,
578 + returns None.
579 + """
580 +
581 + if len(nonce) != 12:
582 + raise ValueError("Bad nonce length")
583 + if len(ciphertext) < 16:
584 + return None
585 +
586 + tag = ciphertext[-16:]
587 + ciphertext = ciphertext[:-16]
588 +
589 + # The initial counter value is the nonce, followed with a 32-bit counte r
590 + # that starts at 1. It's used to compute the tag mask.
591 + counter = bytearray(16)
592 + counter[:12] = nonce
593 + counter[-1] = 1
594 + tagMask = self._rawAesEncrypt(counter)
595 +
596 + if tag != self._auth(ciphertext, data, tagMask):
597 + return None
598 +
599 + # The counter starts at 2 for the actual decryption.
600 + counter[-1] = 2
601 + return self._rawAesCtrEncrypt(counter, ciphertext)
602 +
603 +def _reverseBits(i):
604 + assert i < 16
605 + i = ((i << 2) & 0xc) | ((i >> 2) & 0x3)
606 + i = ((i << 1) & 0xa) | ((i >> 1) & 0x5)
607 + return i
608 +
609 +def _gcmAdd(x, y):
610 + return x ^ y
611 +
612 +def _gcmShift(x):
613 + # Multiplying by x is a right shift, due to bit order.
614 + highTermSet = x & 1
615 + x >>= 1
616 + if highTermSet:
617 + # The x^127 term was shifted up to x^128, so subtract a 1+x+x^2+x^7
618 + # term. This is 0b11100001 or 0xe1 when represented as an 8-bit
619 + # polynomial.
620 + x ^= 0xe1 << (128-8)
621 + return x
622 +
623 +def _inc32(counter):
624 + for i in range(len(counter)-1, len(counter)-5, -1):
625 + counter[i] = (counter[i] + 1) % 256
626 + if counter[i] != 0:
627 + break
628 + return counter
629 +
630 +# _gcmReductionTable[i] is i * (1+x+x^2+x^7) for all 4-bit polynomials i. The
631 +# result is stored as a 16-bit polynomial. This is used in the reduction step t o
632 +# multiply elements of GF(2^128) by x^4.
633 +_gcmReductionTable = [
634 + 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
635 + 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
636 +]
637 diff --git a/third_party/tlslite/tlslite/utils/cipherfactory.py b/third_party/tl slite/tlslite/utils/cipherfactory.py
638 index 20e20f1..d525644 100644
639 --- a/third_party/tlslite/tlslite/utils/cipherfactory.py
640 +++ b/third_party/tlslite/tlslite/utils/cipherfactory.py
641 @@ -6,6 +6,7 @@
642 import os
643
644 from tlslite.utils import python_aes
645 +from tlslite.utils import python_aesgcm
646 from tlslite.utils import python_rc4
647
648 from tlslite.utils import cryptomath
649 @@ -20,6 +21,7 @@ if cryptomath.m2cryptoLoaded:
650
651 if cryptomath.pycryptoLoaded:
652 from tlslite.utils import pycrypto_aes
653 + from tlslite.utils import pycrypto_aesgcm
654 from tlslite.utils import pycrypto_rc4
655 from tlslite.utils import pycrypto_tripledes
656 tripleDESPresent = True
657 @@ -52,6 +54,25 @@ def createAES(key, IV, implList=None):
658 return python_aes.new(key, 2, IV)
659 raise NotImplementedError()
660
661 +def createAESGCM(key, implList=None):
662 + """Create a new AESGCM object.
663 +
664 + @type key: bytearray
665 + @param key: A 16 or 32 byte byte array.
666 +
667 + @rtype: L{tlslite.utils.AESGCM}
668 + @return: An AESGCM object.
669 + """
670 + if implList == None:
671 + implList = ["pycrypto", "python"]
672 +
673 + for impl in implList:
674 + if impl == "pycrypto" and cryptomath.pycryptoLoaded:
675 + return pycrypto_aesgcm.new(key)
676 + if impl == "python":
677 + return python_aesgcm.new(key)
678 + raise NotImplementedError()
679 +
680 def createRC4(key, IV, implList=None):
681 """Create a new RC4 object.
682
683 @@ -99,4 +120,4 @@ def createTripleDES(key, IV, implList=None):
684 return openssl_tripledes.new(key, 2, IV)
685 elif impl == "pycrypto" and cryptomath.pycryptoLoaded:
686 return pycrypto_tripledes.new(key, 2, IV)
687 - raise NotImplementedError()
688 \ No newline at end of file
689 + raise NotImplementedError()
690 diff --git a/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py b/third_party/ tlslite/tlslite/utils/pycrypto_aesgcm.py
691 new file mode 100644
692 index 0000000..ee187ee
693 --- /dev/null
694 +++ b/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py
695 @@ -0,0 +1,16 @@
696 +# Author: Google
697 +# See the LICENSE file for legal information regarding use of this file.
698 +
699 +"""PyCrypto AES-GCM implementation."""
700 +
701 +from .cryptomath import *
702 +from .aesgcm import AESGCM
703 +
704 +if pycryptoLoaded:
705 + import Crypto.Cipher.AES
706 +
707 + def new(key):
708 + cipher = Crypto.Cipher.AES.new(bytes(key))
709 + def encrypt(plaintext):
710 + return bytearray(cipher.encrypt(bytes(plaintext)))
711 + return AESGCM(key, "pycrypto", encrypt)
712 diff --git a/third_party/tlslite/tlslite/utils/python_aesgcm.py b/third_party/tl slite/tlslite/utils/python_aesgcm.py
713 new file mode 100644
714 index 0000000..dc30cd2
715 --- /dev/null
716 +++ b/third_party/tlslite/tlslite/utils/python_aesgcm.py
717 @@ -0,0 +1,11 @@
718 +# Author: Google
719 +# See the LICENSE file for legal information regarding use of this file.
720 +
721 +"""Pure-Python AES-GCM implementation."""
722 +
723 +from .aesgcm import AESGCM
724 +from .rijndael import rijndael
725 +
726 +
727 +def new(key):
728 + return AESGCM(key, "python", rijndael(key, 16).encrypt)
729 diff --git a/third_party/tlslite/tlslite/utils/rc4.py b/third_party/tlslite/tlsl ite/utils/rc4.py
730 index 809026a..3853f5b 100644
731 --- a/third_party/tlslite/tlslite/utils/rc4.py
732 +++ b/third_party/tlslite/tlslite/utils/rc4.py
733 @@ -9,6 +9,7 @@ class RC4(object):
734 if len(keyBytes) < 16 or len(keyBytes) > 256:
735 raise ValueError()
736 self.isBlockCipher = False
737 + self.isAEAD = False
738 self.name = "rc4"
739 self.implementation = implementation
740
741 @@ -16,4 +17,4 @@ class RC4(object):
742 raise NotImplementedError()
743
744 def decrypt(self, ciphertext):
745 - raise NotImplementedError()
746 \ No newline at end of file
747 + raise NotImplementedError()
748 diff --git a/third_party/tlslite/tlslite/utils/tripledes.py b/third_party/tlslit e/tlslite/utils/tripledes.py
749 index 0b4d075..ddcdcad 100644
750 --- a/third_party/tlslite/tlslite/utils/tripledes.py
751 +++ b/third_party/tlslite/tlslite/utils/tripledes.py
752 @@ -12,6 +12,7 @@ class TripleDES(object):
753 if len(IV) != 8:
754 raise ValueError()
755 self.isBlockCipher = True
756 + self.isAEAD = False
757 self.block_size = 8
758 self.implementation = implementation
759 self.name = "3des"
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698