Skip to content

Commit

Permalink
TLS 1.3 padding support
Browse files Browse the repository at this point in the history
  • Loading branch information
ep69 committed Feb 23, 2018
1 parent 06bb34f commit 5deb128
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 1 deletion.
6 changes: 6 additions & 0 deletions tlslite/handshakesettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ class HandshakeSettings(object):
did not advertise support for any curves. It does not have to be the
first curve for eccCurves and may be distinct from curves from that
list.
:vartype padding_cb: func
:ivar padding_cb: Callback to function computing number of padding bytes
for TLS 1.3. Signature is cb_func(msg_size, content_type, max_size).
"""
def __init__(self):
self.minKeySize = 1023
Expand All @@ -185,6 +189,7 @@ def __init__(self):
self.dhParams = None
self.dhGroups = list(ALL_DH_GROUP_NAMES)
self.defaultCurve = "secp256r1"
self.padding_cb = None

@staticmethod
def _sanityCheckKeySizes(other):
Expand Down Expand Up @@ -315,6 +320,7 @@ def validate(self):
other.dhParams = self.dhParams
other.dhGroups = self.dhGroups
other.defaultCurve = self.defaultCurve
other.padding_cb = self.padding_cb
other.versions = self.versions

if not cipherfactory.tripleDESPresent:
Expand Down
9 changes: 8 additions & 1 deletion tlslite/recordlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ def __init__(self, sock):

self.handshake_finished = False

self.padding_cb = None

@property
def encryptThenMAC(self):
"""
Expand Down Expand Up @@ -518,8 +520,13 @@ def sendRecord(self, msg):

# TLS 1.3 hides the content type of messages
if self._is_tls13_plus() and self._writeState.encContext:
# TODO - add support for padding
data += bytearray([contentType])
if self.padding_cb:
max_padding = 2**14 - len(data) - 1
# add number of zero bytes specified by padding_cb()
data += bytearray(self.padding_cb(len(data),
contentType,
max_padding))
# in TLS 1.3 contentType is ignored by _encryptThenSeal
contentType = ContentType.application_data

Expand Down
2 changes: 2 additions & 0 deletions tlslite/tlsconnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams,
if not settings:
settings = HandshakeSettings()
settings = settings.validate()
self.sock.padding_cb = settings.padding_cb

if clientCertChain:
if not isinstance(clientCertChain, X509CertChain):
Expand Down Expand Up @@ -1252,6 +1253,7 @@ def _handshakeServerAsyncHelper(self, verifierDB,
if not settings:
settings = HandshakeSettings()
settings = settings.validate()
self.sock.padding_cb = settings.padding_cb

# OK Start exchanging messages
# ******************************
Expand Down
51 changes: 51 additions & 0 deletions unit_tests/test_tlslite_recordlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,57 @@ def test_sendRecord_with_encryption_tls1_3_chacha20(self):
b'o\x9fO\x16\x07\x878]GV\xa5l\x12\xb6\x85\xb5@\x83\x94\x06\xd6'
))

def test_sendRecord_with_padding_tls1_3(self):
patcher = mock.patch.object(os,
'urandom',
lambda x : bytearray(x))
mock_random = patcher.start()
self.addCleanup(patcher.stop)

sock = MockSocket(bytearray(0))

recordLayer = RecordLayer(sock)
recordLayer.version = (3, 4)
recordLayer.tls13record = True

def padding_cb(length, contenttype, max_padding):
return 100
recordLayer.padding_cb = padding_cb

ciph = CipherSuite.TLS_CHACHA20_POLY1305_SHA256
recordLayer.calcTLS1_3PendingState(ciph,
bytearray(48), # cl_traffic_sec
bytearray(48), # sr_traffic_sec
None) # implementations
recordLayer.changeWriteState()

app_data = ApplicationData().create(b'test')

for result in recordLayer.sendRecord(app_data):
# check if non-blocking socket
self.assertNotIn(result, (0, 1))
break
# we expect length 121 bytes (= 0x79)
# 4 B of application data
# 1 B of content type
# 100 B of padding
# 16 B of authentication tag
self.assertEqual(len(sock.sent), 1)
self.assertEqual(sock.sent[0][:5], bytearray(
b'\x17' + # application_data
b'\x03\x01' + # hidden protocol version - TLS 1.x
b'\x00\x79' # length
))
self.assertEqual(sock.sent[0][5:], bytearray(
b"o\x9fO\x16\x07\x96\xfdHGf\x8d\xe3\x03\x1a\x93p\xb9\xf6" +
b"\xf1\xafK\xbc\x92\xed\xdc\xa7\x02\xb0\x0e\x1e\x00\xd6\xc2" +
b"\xf6\x10\xe5}\xb1T\x85om\xa4\xfa\x1aS\x1f\xab\xc6b\'\xe6f" +
b"\xb3\xbe\xac\xfd\xed\x06\x93\xadbGMD\xd9\xb9\xca\xf6\x8b" +
b"\xac\x07\x96\xe8\xd13)r\xbcNJ\x9d#YP@\x9b\x8ez\x06\xfb" +
b"\x8f2\x8cz\xb7\xd6IP\xfa\xeezcQ\xf3\xe2n\x82\xd1\x9f\xd1x" +
b"\x01x\xea\xd4ht[)\x06"
))

def test_sendRecord_with_malformed_inner_plaintext(self):
# setup
patcher = mock.patch.object(os,
Expand Down

0 comments on commit 5deb128

Please sign in to comment.