| Index: third_party/tlslite/tlslite/tlsrecordlayer.py
|
| diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py
|
| index a09499d26c50c9b696b2c34be391db4dae46a146..c3bcd8c40ca64a12e426bc1f23ff3eff3d0305b4 100644
|
| --- a/third_party/tlslite/tlslite/tlsrecordlayer.py
|
| +++ b/third_party/tlslite/tlslite/tlsrecordlayer.py
|
| @@ -11,7 +11,8 @@ from __future__ import generators
|
|
|
| from .utils.compat import *
|
| from .utils.cryptomath import *
|
| -from .utils.cipherfactory import createAES, createRC4, createTripleDES
|
| +from .utils.cipherfactory import createAESGCM, createAES, createRC4, \
|
| + createTripleDES
|
| from .utils.codec import *
|
| from .errors import *
|
| from .messages import *
|
| @@ -592,10 +593,30 @@ class TLSRecordLayer(object):
|
| if self.fault == Fault.badMAC:
|
| macBytes[0] = (macBytes[0]+1) % 256
|
|
|
| - #Encrypt for Block or Stream Cipher
|
| + #Encrypt for non-NULL cipher.
|
| if self._writeState.encContext:
|
| + #Seal (for AEAD)
|
| + if self._writeState.encContext.isAEAD:
|
| + #Assemble the authenticated data.
|
| + seqNumBytes = self._writeState.getSeqNumBytes()
|
| + authData = seqNumBytes + bytearray([contentType,
|
| + self.version[0],
|
| + self.version[1],
|
| + len(b)//256,
|
| + len(b)%256])
|
| +
|
| + #The nonce is always the fixed nonce and the sequence number.
|
| + nonce = self._writeState.fixedNonce + seqNumBytes
|
| + assert len(nonce) == self._writeState.encContext.nonceLength
|
| +
|
| + b = self._writeState.encContext.seal(nonce, b, authData)
|
| +
|
| + #The only AEAD supported, AES-GCM, has an explicit variable
|
| + #nonce.
|
| + b = seqNumBytes + b
|
| +
|
| #Add padding and encrypt (for Block Cipher):
|
| - if self._writeState.encContext.isBlockCipher:
|
| + elif self._writeState.encContext.isBlockCipher:
|
|
|
| #Add TLS 1.1 fixed block
|
| if self.version >= (3,2):
|
| @@ -967,6 +988,43 @@ class TLSRecordLayer(object):
|
|
|
| def _decryptRecord(self, recordType, b):
|
| if self._readState.encContext:
|
| + #Open if it's an AEAD.
|
| + if self._readState.encContext.isAEAD:
|
| + #The only AEAD supported, AES-GCM, has an explicit variable
|
| + #nonce.
|
| + explicitNonceLength = 8
|
| + if explicitNonceLength > len(b):
|
| + #Publicly invalid.
|
| + for result in self._sendError(
|
| + AlertDescription.bad_record_mac,
|
| + "MAC failure (or padding failure)"):
|
| + yield result
|
| + nonce = self._readState.fixedNonce + b[:explicitNonceLength]
|
| + b = b[8:]
|
| +
|
| + if self._readState.encContext.tagLength > len(b):
|
| + #Publicly invalid.
|
| + for result in self._sendError(
|
| + AlertDescription.bad_record_mac,
|
| + "MAC failure (or padding failure)"):
|
| + yield result
|
| +
|
| + #Assemble the authenticated data.
|
| + seqnumBytes = self._readState.getSeqNumBytes()
|
| + plaintextLen = len(b) - self._readState.encContext.tagLength
|
| + authData = seqnumBytes + bytearray([recordType, self.version[0],
|
| + self.version[1],
|
| + plaintextLen//256,
|
| + plaintextLen%256])
|
| +
|
| + b = self._readState.encContext.open(nonce, b, authData)
|
| + if b is None:
|
| + for result in self._sendError(
|
| + AlertDescription.bad_record_mac,
|
| + "MAC failure (or padding failure)"):
|
| + yield result
|
| + yield b
|
| + return
|
|
|
| #Decrypt if it's a block cipher
|
| if self._readState.encContext.isBlockCipher:
|
| @@ -1064,7 +1122,11 @@ class TLSRecordLayer(object):
|
|
|
| def _calcPendingStates(self, cipherSuite, masterSecret,
|
| clientRandom, serverRandom, implementations):
|
| - if cipherSuite in CipherSuite.aes128Suites:
|
| + if cipherSuite in CipherSuite.aes128GcmSuites:
|
| + keyLength = 16
|
| + ivLength = 4
|
| + createCipherFunc = createAESGCM
|
| + elif cipherSuite in CipherSuite.aes128Suites:
|
| keyLength = 16
|
| ivLength = 16
|
| createCipherFunc = createAES
|
| @@ -1083,7 +1145,10 @@ class TLSRecordLayer(object):
|
| else:
|
| raise AssertionError()
|
|
|
| - if cipherSuite in CipherSuite.shaSuites:
|
| + if cipherSuite in CipherSuite.aeadSuites:
|
| + macLength = 0
|
| + digestmod = None
|
| + elif cipherSuite in CipherSuite.shaSuites:
|
| macLength = 20
|
| digestmod = hashlib.sha1
|
| elif cipherSuite in CipherSuite.sha256Suites:
|
| @@ -1092,8 +1157,12 @@ class TLSRecordLayer(object):
|
| elif cipherSuite in CipherSuite.md5Suites:
|
| macLength = 16
|
| digestmod = hashlib.md5
|
| + else:
|
| + raise AssertionError()
|
|
|
| - if self.version == (3,0):
|
| + if not digestmod:
|
| + createMACFunc = None
|
| + elif self.version == (3,0):
|
| createMACFunc = createMAC_SSL
|
| elif self.version in ((3,1), (3,2), (3,3)):
|
| createMACFunc = createHMAC
|
| @@ -1128,16 +1197,28 @@ class TLSRecordLayer(object):
|
| serverKeyBlock = p.getFixBytes(keyLength)
|
| clientIVBlock = p.getFixBytes(ivLength)
|
| serverIVBlock = p.getFixBytes(ivLength)
|
| - clientPendingState.macContext = createMACFunc(
|
| - compatHMAC(clientMACBlock), digestmod=digestmod)
|
| - serverPendingState.macContext = createMACFunc(
|
| - compatHMAC(serverMACBlock), digestmod=digestmod)
|
| - clientPendingState.encContext = createCipherFunc(clientKeyBlock,
|
| - clientIVBlock,
|
| - implementations)
|
| - serverPendingState.encContext = createCipherFunc(serverKeyBlock,
|
| - serverIVBlock,
|
| - implementations)
|
| + if digestmod:
|
| + # Legacy cipher.
|
| + clientPendingState.macContext = createMACFunc(
|
| + compatHMAC(clientMACBlock), digestmod=digestmod)
|
| + serverPendingState.macContext = createMACFunc(
|
| + compatHMAC(serverMACBlock), digestmod=digestmod)
|
| + clientPendingState.encContext = createCipherFunc(clientKeyBlock,
|
| + clientIVBlock,
|
| + implementations)
|
| + serverPendingState.encContext = createCipherFunc(serverKeyBlock,
|
| + serverIVBlock,
|
| + implementations)
|
| + else:
|
| + # AEAD.
|
| + clientPendingState.macContext = None
|
| + serverPendingState.macContext = None
|
| + clientPendingState.encContext = createCipherFunc(clientKeyBlock,
|
| + implementations)
|
| + serverPendingState.encContext = createCipherFunc(serverKeyBlock,
|
| + implementations)
|
| + clientPendingState.fixedNonce = clientIVBlock
|
| + serverPendingState.fixedNonce = serverIVBlock
|
|
|
| #Assign new connection states to pending states
|
| if self._client:
|
|
|