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..545ff6347407e3af3c2d7d49d88c5ca0f2366f3e 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 * |
@@ -594,8 +595,26 @@ class TLSRecordLayer(object): |
#Encrypt for Block or Stream Cipher |
Ryan Sleevi
2015/01/29 20:50:48
comment update?
davidben
2015/01/29 21:40:59
Done.
|
if self._writeState.encContext: |
+ #Seal (for AEAD) |
+ if self._writeState.encContext.isAEAD: |
+ #Assemble the AD. |
Ryan Sleevi
2015/01/29 20:50:49
expand this acronym?
#Assemble the authenticated
davidben
2015/01/29 21:40:59
Done.
|
+ seqnumBytes = self._writeState.getSeqNumBytes() |
Ryan Sleevi
2015/01/29 20:50:48
nit: naming wise, should this be seqNumBytes?
davidben
2015/01/29 21:40:59
Copy-and-paste from MAC block above, but I agree.
|
+ ad = 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, ad) |
+ |
+ #The only AEAD supported, AES-GCM, has an explicit variable |
+ #nonce. |
Ryan Sleevi
2015/01/29 20:50:49
"explicit variable nonce" - this is just explicit
davidben
2015/01/29 21:40:59
As opposed to the fixed half of the nonce. (GCM no
|
+ 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 +986,36 @@ 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:] |
+ |
+ #Assemble the AD. |
+ seqnumBytes = self._readState.getSeqNumBytes() |
+ plaintextLen = len(b) - self._readState.encContext.tagLength |
agl
2015/01/29 19:38:17
This can end up negative, but that doesn't appear
davidben
2015/01/29 21:40:59
Added a check anyway for good measure. I think a n
|
+ ad = seqnumBytes + bytearray([recordType, self.version[0], |
+ self.version[1], |
+ plaintextLen//256, |
+ plaintextLen%256]) |
+ |
+ b = self._readState.encContext.open(nonce, b, ad) |
+ 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 +1113,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 +1136,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 +1148,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 +1188,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: |