Update mojo sdk to rev 1dc8a9a5db73d3718d99917fadf31f5fb2ebad4f
[chromium-blink-merge.git] / third_party / tlslite / patches / aes_gcm.patch
blob9d4768dd9919a7f642c97e59af9ef22063966851
1 diff --git a/third_party/tlslite/tests/tlstest.py b/third_party/tlslite/tests/tlstest.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):
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", "python"):
14 + continue
16 print("Test 23:", end=' ')
17 connection = connect()
18 @@ -678,9 +680,11 @@ def serverTestCmd(argv):
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", "python"):
27 + continue
29 print("Test 23:", end=' ')
30 connection = connect()
31 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/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
39 + TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C
40 + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E
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)
49 + aes128GcmSuites = []
50 + aes128GcmSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256)
51 + aes128GcmSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
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)
63 + aeadSuites = aes128GcmSuites
66 md5Suites = []
67 md5Suites.append(TLS_RSA_WITH_RC4_128_MD5)
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
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)
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, version)
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)
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, version)
114 srpAllSuites = srpSuites + srpCertSuites
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, version)
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)
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, version)
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)
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, version)
150 certAllSuites = srpCertSuites + certSuites + dheCertSuites
152 @@ -323,8 +342,8 @@ class CipherSuite:
153 anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
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, version)
161 dhAllSuites = dheCertSuites + anonSuites
163 diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/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
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.
185 @type cipherNames: list
186 - @ivar cipherNames: The allowed ciphers, in order of preference.
187 + @ivar cipherNames: The allowed ciphers.
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):
194 @type certificateTypes: list
195 - @ivar certificateTypes: The allowed certificate types, in order of
196 - preference.
197 + @ivar certificateTypes: The allowed certificate types.
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 certificate
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")
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"]
209 return other
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):
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)
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):
240 else:
241 #Set the version to the client's version
242 - self.version = clientHello.client_version
243 + self.version = clientHello.client_version
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)
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..c3bcd8c 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
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 @@ -592,10 +593,30 @@ class TLSRecordLayer(object):
277 if self.fault == Fault.badMAC:
278 macBytes[0] = (macBytes[0]+1) % 256
280 - #Encrypt for Block or Stream Cipher
281 + #Encrypt for non-NULL cipher.
282 if self._writeState.encContext:
283 + #Seal (for AEAD)
284 + if self._writeState.encContext.isAEAD:
285 + #Assemble the authenticated data.
286 + seqNumBytes = self._writeState.getSeqNumBytes()
287 + authData = seqNumBytes + bytearray([contentType,
288 + self.version[0],
289 + self.version[1],
290 + len(b)//256,
291 + len(b)%256])
293 + #The nonce is always the fixed nonce and the sequence number.
294 + nonce = self._writeState.fixedNonce + seqNumBytes
295 + assert len(nonce) == self._writeState.encContext.nonceLength
297 + b = self._writeState.encContext.seal(nonce, b, authData)
299 + #The only AEAD supported, AES-GCM, has an explicit variable
300 + #nonce.
301 + b = seqNumBytes + b
303 #Add padding and encrypt (for Block Cipher):
304 - if self._writeState.encContext.isBlockCipher:
305 + elif self._writeState.encContext.isBlockCipher:
307 #Add TLS 1.1 fixed block
308 if self.version >= (3,2):
309 @@ -967,6 +988,43 @@ class TLSRecordLayer(object):
311 def _decryptRecord(self, recordType, b):
312 if self._readState.encContext:
313 + #Open if it's an AEAD.
314 + if self._readState.encContext.isAEAD:
315 + #The only AEAD supported, AES-GCM, has an explicit variable
316 + #nonce.
317 + explicitNonceLength = 8
318 + if explicitNonceLength > len(b):
319 + #Publicly invalid.
320 + for result in self._sendError(
321 + AlertDescription.bad_record_mac,
322 + "MAC failure (or padding failure)"):
323 + yield result
324 + nonce = self._readState.fixedNonce + b[:explicitNonceLength]
325 + b = b[8:]
327 + if self._readState.encContext.tagLength > len(b):
328 + #Publicly invalid.
329 + for result in self._sendError(
330 + AlertDescription.bad_record_mac,
331 + "MAC failure (or padding failure)"):
332 + yield result
334 + #Assemble the authenticated data.
335 + seqnumBytes = self._readState.getSeqNumBytes()
336 + plaintextLen = len(b) - self._readState.encContext.tagLength
337 + authData = seqnumBytes + bytearray([recordType, self.version[0],
338 + self.version[1],
339 + plaintextLen//256,
340 + plaintextLen%256])
342 + b = self._readState.encContext.open(nonce, b, authData)
343 + if b is None:
344 + for result in self._sendError(
345 + AlertDescription.bad_record_mac,
346 + "MAC failure (or padding failure)"):
347 + yield result
348 + yield b
349 + return
351 #Decrypt if it's a block cipher
352 if self._readState.encContext.isBlockCipher:
353 @@ -1064,7 +1122,11 @@ class TLSRecordLayer(object):
355 def _calcPendingStates(self, cipherSuite, masterSecret,
356 clientRandom, serverRandom, implementations):
357 - if cipherSuite in CipherSuite.aes128Suites:
358 + if cipherSuite in CipherSuite.aes128GcmSuites:
359 + keyLength = 16
360 + ivLength = 4
361 + createCipherFunc = createAESGCM
362 + elif cipherSuite in CipherSuite.aes128Suites:
363 keyLength = 16
364 ivLength = 16
365 createCipherFunc = createAES
366 @@ -1083,7 +1145,10 @@ class TLSRecordLayer(object):
367 else:
368 raise AssertionError()
370 - if cipherSuite in CipherSuite.shaSuites:
371 + if cipherSuite in CipherSuite.aeadSuites:
372 + macLength = 0
373 + digestmod = None
374 + elif cipherSuite in CipherSuite.shaSuites:
375 macLength = 20
376 digestmod = hashlib.sha1
377 elif cipherSuite in CipherSuite.sha256Suites:
378 @@ -1092,8 +1157,12 @@ class TLSRecordLayer(object):
379 elif cipherSuite in CipherSuite.md5Suites:
380 macLength = 16
381 digestmod = hashlib.md5
382 + else:
383 + raise AssertionError()
385 - if self.version == (3,0):
386 + if not digestmod:
387 + createMACFunc = None
388 + elif self.version == (3,0):
389 createMACFunc = createMAC_SSL
390 elif self.version in ((3,1), (3,2), (3,3)):
391 createMACFunc = createHMAC
392 @@ -1128,16 +1197,28 @@ class TLSRecordLayer(object):
393 serverKeyBlock = p.getFixBytes(keyLength)
394 clientIVBlock = p.getFixBytes(ivLength)
395 serverIVBlock = p.getFixBytes(ivLength)
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 + if digestmod:
407 + # Legacy cipher.
408 + clientPendingState.macContext = createMACFunc(
409 + compatHMAC(clientMACBlock), digestmod=digestmod)
410 + serverPendingState.macContext = createMACFunc(
411 + compatHMAC(serverMACBlock), digestmod=digestmod)
412 + clientPendingState.encContext = createCipherFunc(clientKeyBlock,
413 + clientIVBlock,
414 + implementations)
415 + serverPendingState.encContext = createCipherFunc(serverKeyBlock,
416 + serverIVBlock,
417 + implementations)
418 + else:
419 + # AEAD.
420 + clientPendingState.macContext = None
421 + serverPendingState.macContext = None
422 + clientPendingState.encContext = createCipherFunc(clientKeyBlock,
423 + implementations)
424 + serverPendingState.encContext = createCipherFunc(serverKeyBlock,
425 + implementations)
426 + clientPendingState.fixedNonce = clientIVBlock
427 + serverPendingState.fixedNonce = serverIVBlock
429 #Assign new connection states to pending states
430 if self._client:
431 diff --git a/third_party/tlslite/tlslite/utils/aes.py b/third_party/tlslite/tlslite/utils/aes.py
432 index 95afaa3..5a038fb 100644
433 --- a/third_party/tlslite/tlslite/utils/aes.py
434 +++ b/third_party/tlslite/tlslite/utils/aes.py
435 @@ -12,6 +12,7 @@ class AES(object):
436 if len(IV) != 16:
437 raise AssertionError()
438 self.isBlockCipher = True
439 + self.isAEAD = False
440 self.block_size = 16
441 self.implementation = implementation
442 if len(key)==16:
443 @@ -31,4 +32,4 @@ class AES(object):
444 #CBC-Mode decryption, returns plaintext
445 #WARNING: *MAY* modify the input as well
446 def decrypt(self, ciphertext):
447 - assert(len(ciphertext) % 16 == 0)
448 \ No newline at end of file
449 + assert(len(ciphertext) % 16 == 0)
450 diff --git a/third_party/tlslite/tlslite/utils/aesgcm.py b/third_party/tlslite/tlslite/utils/aesgcm.py
451 new file mode 100644
452 index 0000000..7319c26
453 --- /dev/null
454 +++ b/third_party/tlslite/tlslite/utils/aesgcm.py
455 @@ -0,0 +1,193 @@
456 +# Author: Google
457 +# See the LICENSE file for legal information regarding use of this file.
459 +# GCM derived from Go's implementation in crypto/cipher.
461 +# https://golang.org/src/crypto/cipher/gcm.go
463 +# GCM works over elements of the field GF(2^128), each of which is a 128-bit
464 +# polynomial. Throughout this implementation, polynomials are represented as
465 +# Python integers with the low-order terms at the most significant bits. So a
466 +# 128-bit polynomial is an integer from 0 to 2^128-1 with the most significant
467 +# bit representing the x^0 term and the least significant bit representing the
468 +# x^127 term. This bit reversal also applies to polynomials used as indices in a
469 +# look-up table.
471 +from .cryptomath import bytesToNumber, numberToByteArray
473 +class AESGCM(object):
474 + """
475 + AES-GCM implementation. Note: this implementation does not attempt
476 + to be side-channel resistant. It's also rather slow.
477 + """
479 + def __init__(self, key, implementation, rawAesEncrypt):
480 + self.isBlockCipher = False
481 + self.isAEAD = True
482 + self.nonceLength = 12
483 + self.tagLength = 16
484 + self.implementation = implementation
485 + if len(key) == 16:
486 + self.name = "aes128gcm"
487 + elif len(key) == 32:
488 + self.name = "aes256gcm"
489 + else:
490 + raise AssertionError()
492 + self._rawAesEncrypt = rawAesEncrypt
494 + # The GCM key is AES(0).
495 + h = bytesToNumber(self._rawAesEncrypt(bytearray(16)))
497 + # Pre-compute all 4-bit multiples of h. Note that bits are reversed
498 + # because our polynomial representation places low-order terms at the
499 + # most significant bit. Thus x^0 * h = h is at index 0b1000 = 8 and
500 + # x^1 * h is at index 0b0100 = 4.
501 + self._productTable = [0] * 16
502 + self._productTable[_reverseBits(1)] = h
503 + for i in range(2, 16, 2):
504 + self._productTable[_reverseBits(i)] = \
505 + _gcmShift(self._productTable[_reverseBits(i/2)])
506 + self._productTable[_reverseBits(i+1)] = \
507 + _gcmAdd(self._productTable[_reverseBits(i)], h)
509 + def _rawAesCtrEncrypt(self, counter, inp):
510 + """
511 + Encrypts (or decrypts) plaintext with AES-CTR. counter is modified.
512 + """
513 + out = bytearray(len(inp))
514 + for i in range(0, len(out), 16):
515 + mask = self._rawAesEncrypt(counter)
516 + for j in range(i, min(len(out), i + 16)):
517 + out[j] = inp[j] ^ mask[j-i]
518 + _inc32(counter)
519 + return out
521 + def _auth(self, ciphertext, ad, tagMask):
522 + y = 0
523 + y = self._update(y, ad)
524 + y = self._update(y, ciphertext)
525 + y ^= (len(ad) << (3 + 64)) | (len(ciphertext) << 3)
526 + y = self._mul(y)
527 + y ^= bytesToNumber(tagMask)
528 + return numberToByteArray(y, 16)
530 + def _update(self, y, data):
531 + for i in range(0, len(data) // 16):
532 + y ^= bytesToNumber(data[16*i:16*i+16])
533 + y = self._mul(y)
534 + extra = len(data) % 16
535 + if extra != 0:
536 + block = bytearray(16)
537 + block[:extra] = data[-extra:]
538 + y ^= bytesToNumber(block)
539 + y = self._mul(y)
540 + return y
542 + def _mul(self, y):
543 + """ Returns y*H, where H is the GCM key. """
544 + ret = 0
545 + # Multiply H by y 4 bits at a time, starting with the highest power
546 + # terms.
547 + for i in range(0, 128, 4):
548 + # Multiply by x^4. The reduction for the top four terms is
549 + # precomputed.
550 + retHigh = ret & 0xf
551 + ret >>= 4
552 + ret ^= (_gcmReductionTable[retHigh] << (128-16))
554 + # Add in y' * H where y' are the next four terms of y, shifted down
555 + # to the x^0..x^4. This is one of the pre-computed multiples of
556 + # H. The multiplication by x^4 shifts them back into place.
557 + ret ^= self._productTable[y & 0xf]
558 + y >>= 4
559 + assert y == 0
560 + return ret
562 + def seal(self, nonce, plaintext, data):
563 + """
564 + Encrypts and authenticates plaintext using nonce and data. Returns the
565 + ciphertext, consisting of the encrypted plaintext and tag concatenated.
566 + """
568 + if len(nonce) != 12:
569 + raise ValueError("Bad nonce length")
571 + # The initial counter value is the nonce, followed by a 32-bit counter
572 + # that starts at 1. It's used to compute the tag mask.
573 + counter = bytearray(16)
574 + counter[:12] = nonce
575 + counter[-1] = 1
576 + tagMask = self._rawAesEncrypt(counter)
578 + # The counter starts at 2 for the actual encryption.
579 + counter[-1] = 2
580 + ciphertext = self._rawAesCtrEncrypt(counter, plaintext)
582 + tag = self._auth(ciphertext, data, tagMask)
584 + return ciphertext + tag
586 + def open(self, nonce, ciphertext, data):
587 + """
588 + Decrypts and authenticates ciphertext using nonce and data. If the
589 + tag is valid, the plaintext is returned. If the tag is invalid,
590 + returns None.
591 + """
593 + if len(nonce) != 12:
594 + raise ValueError("Bad nonce length")
595 + if len(ciphertext) < 16:
596 + return None
598 + tag = ciphertext[-16:]
599 + ciphertext = ciphertext[:-16]
601 + # The initial counter value is the nonce, followed by a 32-bit counter
602 + # that starts at 1. It's used to compute the tag mask.
603 + counter = bytearray(16)
604 + counter[:12] = nonce
605 + counter[-1] = 1
606 + tagMask = self._rawAesEncrypt(counter)
608 + if tag != self._auth(ciphertext, data, tagMask):
609 + return None
611 + # The counter starts at 2 for the actual decryption.
612 + counter[-1] = 2
613 + return self._rawAesCtrEncrypt(counter, ciphertext)
615 +def _reverseBits(i):
616 + assert i < 16
617 + i = ((i << 2) & 0xc) | ((i >> 2) & 0x3)
618 + i = ((i << 1) & 0xa) | ((i >> 1) & 0x5)
619 + return i
621 +def _gcmAdd(x, y):
622 + return x ^ y
624 +def _gcmShift(x):
625 + # Multiplying by x is a right shift, due to bit order.
626 + highTermSet = x & 1
627 + x >>= 1
628 + if highTermSet:
629 + # The x^127 term was shifted up to x^128, so subtract a 1+x+x^2+x^7
630 + # term. This is 0b11100001 or 0xe1 when represented as an 8-bit
631 + # polynomial.
632 + x ^= 0xe1 << (128-8)
633 + return x
635 +def _inc32(counter):
636 + for i in range(len(counter)-1, len(counter)-5, -1):
637 + counter[i] = (counter[i] + 1) % 256
638 + if counter[i] != 0:
639 + break
640 + return counter
642 +# _gcmReductionTable[i] is i * (1+x+x^2+x^7) for all 4-bit polynomials i. The
643 +# result is stored as a 16-bit polynomial. This is used in the reduction step to
644 +# multiply elements of GF(2^128) by x^4.
645 +_gcmReductionTable = [
646 + 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
647 + 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
649 diff --git a/third_party/tlslite/tlslite/utils/cipherfactory.py b/third_party/tlslite/tlslite/utils/cipherfactory.py
650 index 20e20f1..d525644 100644
651 --- a/third_party/tlslite/tlslite/utils/cipherfactory.py
652 +++ b/third_party/tlslite/tlslite/utils/cipherfactory.py
653 @@ -6,6 +6,7 @@
654 import os
656 from tlslite.utils import python_aes
657 +from tlslite.utils import python_aesgcm
658 from tlslite.utils import python_rc4
660 from tlslite.utils import cryptomath
661 @@ -20,6 +21,7 @@ if cryptomath.m2cryptoLoaded:
663 if cryptomath.pycryptoLoaded:
664 from tlslite.utils import pycrypto_aes
665 + from tlslite.utils import pycrypto_aesgcm
666 from tlslite.utils import pycrypto_rc4
667 from tlslite.utils import pycrypto_tripledes
668 tripleDESPresent = True
669 @@ -52,6 +54,25 @@ def createAES(key, IV, implList=None):
670 return python_aes.new(key, 2, IV)
671 raise NotImplementedError()
673 +def createAESGCM(key, implList=None):
674 + """Create a new AESGCM object.
676 + @type key: bytearray
677 + @param key: A 16 or 32 byte byte array.
679 + @rtype: L{tlslite.utils.AESGCM}
680 + @return: An AESGCM object.
681 + """
682 + if implList == None:
683 + implList = ["pycrypto", "python"]
685 + for impl in implList:
686 + if impl == "pycrypto" and cryptomath.pycryptoLoaded:
687 + return pycrypto_aesgcm.new(key)
688 + if impl == "python":
689 + return python_aesgcm.new(key)
690 + raise NotImplementedError()
692 def createRC4(key, IV, implList=None):
693 """Create a new RC4 object.
695 @@ -99,4 +120,4 @@ def createTripleDES(key, IV, implList=None):
696 return openssl_tripledes.new(key, 2, IV)
697 elif impl == "pycrypto" and cryptomath.pycryptoLoaded:
698 return pycrypto_tripledes.new(key, 2, IV)
699 - raise NotImplementedError()
700 \ No newline at end of file
701 + raise NotImplementedError()
702 diff --git a/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py b/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py
703 new file mode 100644
704 index 0000000..ee187ee
705 --- /dev/null
706 +++ b/third_party/tlslite/tlslite/utils/pycrypto_aesgcm.py
707 @@ -0,0 +1,16 @@
708 +# Author: Google
709 +# See the LICENSE file for legal information regarding use of this file.
711 +"""PyCrypto AES-GCM implementation."""
713 +from .cryptomath import *
714 +from .aesgcm import AESGCM
716 +if pycryptoLoaded:
717 + import Crypto.Cipher.AES
719 + def new(key):
720 + cipher = Crypto.Cipher.AES.new(bytes(key))
721 + def encrypt(plaintext):
722 + return bytearray(cipher.encrypt(bytes(plaintext)))
723 + return AESGCM(key, "pycrypto", encrypt)
724 diff --git a/third_party/tlslite/tlslite/utils/python_aesgcm.py b/third_party/tlslite/tlslite/utils/python_aesgcm.py
725 new file mode 100644
726 index 0000000..80a5fd5
727 --- /dev/null
728 +++ b/third_party/tlslite/tlslite/utils/python_aesgcm.py
729 @@ -0,0 +1,10 @@
730 +# Author: Google
731 +# See the LICENSE file for legal information regarding use of this file.
733 +"""Pure-Python AES-GCM implementation."""
735 +from .aesgcm import AESGCM
736 +from .rijndael import rijndael
738 +def new(key):
739 + return AESGCM(key, "python", rijndael(key, 16).encrypt)
740 diff --git a/third_party/tlslite/tlslite/utils/rc4.py b/third_party/tlslite/tlslite/utils/rc4.py
741 index 809026a..3853f5b 100644
742 --- a/third_party/tlslite/tlslite/utils/rc4.py
743 +++ b/third_party/tlslite/tlslite/utils/rc4.py
744 @@ -9,6 +9,7 @@ class RC4(object):
745 if len(keyBytes) < 16 or len(keyBytes) > 256:
746 raise ValueError()
747 self.isBlockCipher = False
748 + self.isAEAD = False
749 self.name = "rc4"
750 self.implementation = implementation
752 @@ -16,4 +17,4 @@ class RC4(object):
753 raise NotImplementedError()
755 def decrypt(self, ciphertext):
756 - raise NotImplementedError()
757 \ No newline at end of file
758 + raise NotImplementedError()
759 diff --git a/third_party/tlslite/tlslite/utils/tripledes.py b/third_party/tlslite/tlslite/utils/tripledes.py
760 index 0b4d075..ddcdcad 100644
761 --- a/third_party/tlslite/tlslite/utils/tripledes.py
762 +++ b/third_party/tlslite/tlslite/utils/tripledes.py
763 @@ -12,6 +12,7 @@ class TripleDES(object):
764 if len(IV) != 8:
765 raise ValueError()
766 self.isBlockCipher = True
767 + self.isAEAD = False
768 self.block_size = 8
769 self.implementation = implementation
770 self.name = "3des"