Skip to content

Commit

Permalink
Merge 22f1887 into 75dbe54
Browse files Browse the repository at this point in the history
  • Loading branch information
NoName115 committed Nov 6, 2019
2 parents 75dbe54 + 22f1887 commit bb4ec55
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 3 deletions.
11 changes: 9 additions & 2 deletions scripts/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

from tlslite.api import *
from tlslite.constants import CipherSuite, HashAlgorithm, SignatureAlgorithm, \
GroupName, SignatureScheme
GroupName, SignatureScheme, KeyUpdateMessageType
from tlslite import __version__
from tlslite.utils.compat import b2a_hex, a2b_hex, time_stamp
from tlslite.utils.dns_utils import is_valid_hostname
Expand Down Expand Up @@ -561,7 +561,14 @@ def handshake(self, connection):
return False
else:
raise

for result in connection.send_keyupdate_request(KeyUpdateMessageType.update_requested):
if result in (0, 1):
continue
else:
print("unexpected result from send_keyupdate_request: {0}"
.format(result))
return False

connection.ignoreAbruptClose = True
printGoodConnection(connection, stop-start)
printExporter(connection, expLabel, expLength)
Expand Down
8 changes: 8 additions & 0 deletions tlslite/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class HandshakeType(TLSEnum):
client_key_exchange = 16
finished = 20
certificate_status = 22
key_update = 24
next_protocol = 67
message_hash = 254 # TLS 1.3

Expand Down Expand Up @@ -409,6 +410,13 @@ class HeartbeatMessageType(TLSEnum):
heartbeat_response = 2


class KeyUpdateMessageType(TLSEnum):
"""Types of keyupdate messages from RFC 8446"""

update_not_requested = 0
update_requested = 1


class AlertLevel(TLSEnum):
"""Enumeration of TLS Alert protocol levels"""

Expand Down
32 changes: 32 additions & 0 deletions tlslite/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -2307,3 +2307,35 @@ def _message_type(self):
def __str__(self):
"""Return human readable representation of heartbeat message."""
return "heartbeat {0}".format(self._message_type)


class KeyUpdate(HandshakeMsg):
"""
Handling KeyUpdate message from RFC 8446
@type message_type: int
@ivar message_type: type of message (update_not_requested or
update_requested)
"""

def __init__(self):
super(KeyUpdate, self).__init__(HandshakeType.key_update)
self.message_type = 0

def create(self, message_type):
"""Create KeyUpdate message with selected parameter."""
self.message_type = message_type
return self

def parse(self, p):
"""Deserialize keyupdate message from parser."""
p.startLengthCheck(3)
self.message_type = p.get(1)
p.stopLengthCheck()
return self

def write(self):
"""Serialise keyupdate message."""
writer = Writer()
writer.add(self.message_type, 1)
return self.postWrite(writer)
52 changes: 52 additions & 0 deletions tlslite/recordlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1316,3 +1316,55 @@ def calcTLS1_3PendingState(self, cipherSuite, cl_traffic_secret,
else:
self._pendingWriteState = serverPendingState
self._pendingReadState = clientPendingState

def _calcTLS1_3KeyUpdate(self, cipherSuite, app_secret):
prf_name, prf_length = ('sha384', 48) if cipherSuite \
in CipherSuite.sha384PrfSuites \
else ('sha256', 32)
key_length, iv_length, cipher_func = \
self._getCipherSettings(cipherSuite)
iv_length = 12

new_app_secret = HKDF_expand_label(app_secret,
b"traffic upd", b"",
prf_length,
prf_name)
new_state = ConnectionState()
new_state.macContext = None
new_state.encContext = \
cipher_func(HKDF_expand_label(new_app_secret,
b"key", b"",
key_length,
prf_name),
None)
new_state.fixedNonce = HKDF_expand_label(new_app_secret,
b"iv", b"",
iv_length,
prf_name)
return new_app_secret, new_state

def calcTLS1_3KeyUpdate_sender(self, cipherSuite, cl_app_secret,
sr_app_secret):
if self.client:
new_sr_app_secret, server_state = self._calcTLS1_3KeyUpdate(
cipherSuite, sr_app_secret)
self._readState = server_state
return cl_app_secret, new_sr_app_secret
else:
new_cl_app_secret, client_state = self._calcTLS1_3KeyUpdate(
cipherSuite, cl_app_secret)
self._readState = client_state
return new_cl_app_secret, sr_app_secret

def calcTLS1_3KeyUpdate_reciever(self, cipherSuite, cl_app_secret,
sr_app_secret):
if self.client:
new_cl_app_secret, client_state = self._calcTLS1_3KeyUpdate(
cipherSuite, cl_app_secret)
self._writeState = client_state
return new_cl_app_secret, sr_app_secret
else:
new_sr_app_secret, server_state = self._calcTLS1_3KeyUpdate(
cipherSuite, sr_app_secret)
self._writeState = server_state
return cl_app_secret, new_sr_app_secret
62 changes: 61 additions & 1 deletion tlslite/tlsrecordlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ def readAsync(self, max=None, min=1):
if self.version > (3, 3):
allowedTypes = (ContentType.application_data,
ContentType.handshake)
allowedHsTypes = HandshakeType.new_session_ticket
allowedHsTypes = (HandshakeType.new_session_ticket,
HandshakeType.key_update)
else:
allowedTypes = ContentType.application_data
allowedHsTypes = None
Expand All @@ -315,6 +316,10 @@ def readAsync(self, max=None, min=1):
result.time = time.time()
self.tickets.append(result)
continue
if isinstance(result, KeyUpdate):
for result in self._handle_keyupdate_request(result):
yield result
continue
applicationData = result
self._readBuffer += applicationData.write()
except TLSRemoteAlert as alert:
Expand Down Expand Up @@ -947,6 +952,8 @@ def _getMsg(self, expectedType, secondaryType=None, constructorType=None):
yield EncryptedExtensions().parse(p)
elif subType == HandshakeType.new_session_ticket:
yield NewSessionTicket().parse(p)
elif subType == HandshakeType.key_update:
yield KeyUpdate().parse(p)
else:
raise AssertionError()

Expand Down Expand Up @@ -1128,3 +1135,56 @@ def send_heartbeat_request(self, payload, padding_length):
"""
for _ in self.write_heartbeat(payload, padding_length):
pass

def _handle_keyupdate_request(self, request):
"""Process the KeyUpdate request.
@type request: KeyUpdate
@param request: Recieved KeyUpdate message.
"""
if request.message_type == KeyUpdateMessageType.update_not_requested or\
request.message_type == KeyUpdateMessageType.update_requested:
self.session.cl_app_secret, self.session.sr_app_secret = self._recordLayer.\
calcTLS1_3KeyUpdate_sender(
self.session.cipherSuite,
self.session.cl_app_secret,
self.session.sr_app_secret)
if request.message_type == KeyUpdateMessageType.update_requested:
keyupdate_request = KeyUpdate().create(
KeyUpdateMessageType.update_not_requested)
for result in self._sendMsg(keyupdate_request):
yield result
self.session.cl_app_secret, self.session.sr_app_secret = self._recordLayer.\
calcTLS1_3KeyUpdate_reciever(
self.session.cipherSuite,
self.session.cl_app_secret,
self.session.sr_app_secret)
else:
for result in self._sendError(
AlertDescription.illegal_parameter,
"Received KeyUpdate request with unknown message_type"):
yield result

def send_keyupdate_request(self, message_type):
"""Send a KeyUpdate message.
@type payload: int
@param payload: Type of KeyUpdate message.
@raise socket.error: If a socket error occurs.
"""
if self.closed:
raise TLSClosedConnectionError(
"attempt to write to closed connection")
if self.version != (3, 4):
raise TLSIllegalParameterException("KeyUpdate is a TLS 1.3 specific"
" feature")

keyupdate_request = KeyUpdate().create(message_type)
for result in self._sendMsg(keyupdate_request):
yield result
self.session.cl_app_secret, self.session.sr_app_secret = \
self._recordLayer.calcTLS1_3KeyUpdate_reciever(
self.session.cipherSuite,
self.session.cl_app_secret,
self.session.sr_app_secret)

0 comments on commit bb4ec55

Please sign in to comment.