Skip to content

Commit

Permalink
Merge 8133a92 into 322f5ff
Browse files Browse the repository at this point in the history
  • Loading branch information
tomato42 committed Nov 25, 2019
2 parents 322f5ff + 8133a92 commit 43bcbfe
Show file tree
Hide file tree
Showing 9 changed files with 653 additions and 17 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,21 @@ endif
pylint --msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" tlslite > pylint_report.txt || :
diff-quality --violations=pylint --fail-under=90 pylint_report.txt
ifdef COVERAGE2
coverage2 combine --append
coverage2 combine --append .coverage .coverage.2.server .coverage.2.client
coverage2 report -m
coverage2 xml
diff-cover --fail-under=90 coverage.xml
endif
ifdef COVERAGE3
coverage2 combine --append .coverage .coverage.3.server .coverage.3.client
coverage3 report -m
coverage3 xml
diff-cover --fail-under=90 coverage.xml
endif
ifndef COVERAGE2
ifndef COVERAGE3
ifdef COVERAGE
coverage combine --append
coverage combine --append .coverage .coverage.server .coverage.client
coverage report -m
coverage xml
diff-cover --fail-under=90 coverage.xml
Expand Down
35 changes: 30 additions & 5 deletions scripts/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from tlslite.utils.compat import b2a_hex, a2b_hex, time_stamp
from tlslite.utils.dns_utils import is_valid_hostname
from tlslite.utils.cryptomath import getRandomBytes
from tlslite.constants import KeyUpdateMessageType

try:
from tack.structures.Tack import Tack
Expand Down Expand Up @@ -77,7 +78,7 @@ def printUsage(s=None):
server
[-c CERT] [-k KEY] [-t TACK] [-v VERIFIERDB] [-d DIR] [-l LABEL] [-L LENGTH]
[--reqcert] [--param DHFILE] [--psk PSK] [--psk-ident IDENTITY]
[--psk-sha384] [--ssl3] [--max-ver VER] [--tickets COUNT]
[--psk-sha384] [--ssl3] [--max-ver VER] [--tickets COUNT] [--request-pha]
HOST:PORT
client
Expand Down Expand Up @@ -155,6 +156,7 @@ def handleArgs(argv, argString, flagsList=[]):
ssl3 = False
max_ver = None
tickets = None
request_pha = False

for opt, arg in opts:
if opt == "-k":
Expand Down Expand Up @@ -226,6 +228,8 @@ def handleArgs(argv, argString, flagsList=[]):
max_ver = ver_to_tuple(arg)
elif opt == "--tickets":
tickets = int(arg)
elif opt == "--request-pha":
request_pha = True
else:
assert(False)

Expand Down Expand Up @@ -286,6 +290,8 @@ def handleArgs(argv, argString, flagsList=[]):
retList.append(max_ver)
if "tickets=" in flagsList:
retList.append(tickets)
if "request-pha" in flagsList:
retList.append(request_pha)
return retList


Expand Down Expand Up @@ -483,11 +489,11 @@ def serverCmd(argv):
(address, privateKey, cert_chain, virtual_hosts, tacks, verifierDB,
directory, reqCert,
expLabel, expLength, dhparam, psk, psk_ident, psk_hash, ssl3,
max_ver, tickets) = \
max_ver, tickets, request_pha) = \
handleArgs(argv, "kctbvdlL",
["reqcert", "param=", "psk=",
"psk-ident=", "psk-sha384", "ssl3", "max-ver=",
"tickets="])
"tickets=", "request-pha"])


if (cert_chain and not privateKey) or (not cert_chain and privateKey):
Expand Down Expand Up @@ -530,10 +536,22 @@ def serverCmd(argv):
settings.maxVersion = max_ver
settings.virtual_hosts = virtual_hosts

class MySimpleHTTPHandler(SimpleHTTPRequestHandler):
class MySimpleHTTPHandler(SimpleHTTPRequestHandler, object):
"""Buffer the header and body of HTTP message."""
wbufsize = -1

def do_GET(self):
"""Simple override to send KeyUpdate to client."""
if self.path.startswith('/keyupdate'):
for i in self.connection.send_keyupdate_request(
KeyUpdateMessageType.update_requested):
if i in (0, 1):
continue
else:
raise ValueError("Invalid return from "
"send_keyupdate_request")
return super(MySimpleHTTPHandler, self).do_GET()

class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn, HTTPServer):
def handshake(self, connection):
print("About to handshake...")
Expand Down Expand Up @@ -563,6 +581,13 @@ def handshake(self, connection):
sni=sni)
# As an example (does not work here):
#nextProtos=[b"spdy/3", b"spdy/2", b"http/1.1"])
try:
if request_pha:
for i in connection.request_post_handshake_auth():
pass
except ValueError:
# if we can't do PHA, we can't do it
pass
stop = time_stamp()
except TLSRemoteAlert as a:
if a.description == AlertDescription.user_canceled:
Expand All @@ -588,7 +613,7 @@ def handshake(self, connection):
return False
else:
raise

connection.ignoreAbruptClose = True
printGoodConnection(connection, stop-start)
printExporter(connection, expLabel, expLength)
Expand Down
145 changes: 140 additions & 5 deletions tests/tlstest.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from xmlrpc import client as xmlrpclib
import ssl
from tlslite import *
from tlslite.constants import KeyUpdateMessageType

try:
from tack.structures.Tack import Tack
Expand Down Expand Up @@ -76,11 +77,19 @@ def testConnClient(conn):
conn.write(b1)
conn.write(b10)
conn.write(b100)
r1 = conn.read(min=1, max=1)
assert len(r1) == 1
assert r1 == b1
r10 = conn.read(min=10, max=10)
assert len(r10) == 10
assert r10 == b10
r100 = conn.read(min=100, max=100)
assert len(r100) == 100
assert r100 == b100
conn.write(b1000)
assert(conn.read(min=1, max=1) == b1)
assert(conn.read(min=10, max=10) == b10)
assert(conn.read(min=100, max=100) == b100)
assert(conn.read(min=1000, max=1000) == b1000)
r1000 = conn.read(min=1000, max=1000)
assert len(r1000) == 1000
assert r1000 == b1000

def clientTestCmd(argv):

Expand Down Expand Up @@ -698,6 +707,20 @@ def connect():

test_no += 1

print("Test {0} - good mutual X.509, PHA, TLSv1.3".format(test_no))
synchro.recv(1)
connection = connect()
settings = HandshakeSettings()
settings.minVersion = (3, 4)
settings.maxVersion = (3, 4)
connection.handshakeClientCert(x509Chain, x509Key, settings=settings)
synchro.recv(1)
testConnClient(connection)
assert(isinstance(connection.session.serverCertChain, X509CertChain))
connection.close()

test_no += 1

print("Test {0} - good mutual X.509, TLSv1.1".format(test_no))
synchro.recv(1)
connection = connect()
Expand Down Expand Up @@ -1203,6 +1226,51 @@ def heartbeat_response_check(message):

test_no += 1

print("Test {0} - KeyUpdate from client in TLSv1.3".format(test_no))
assert synchro.recv(1) == b'R'
connection = connect()
settings = HandshakeSettings()
settings.maxVersion = (3, 4)
connection.handshakeClientCert(serverName=address[0], settings=settings)
assert synchro.recv(1) == b'K'
for i in connection.send_keyupdate_request(KeyUpdateMessageType.update_requested):
assert i in (0, 1)
assert synchro.recv(1) == b'K'
testConnClient(connection)
connection.close()

test_no += 1

print("Test {0} - mutual KeyUpdates in TLSv1.3".format(test_no))
assert synchro.recv(1) == b'R'
connection = connect()
settings = HandshakeSettings()
settings.maxVersion = (3, 4)
connection.handshakeClientCert(serverName=address[0], settings=settings)
for i in connection.send_keyupdate_request(KeyUpdateMessageType.update_requested):
assert i in (0, 1)
testConnClient(connection)
synchro.send(b'R')
connection.close()

test_no += 1

print("Test {0} - multiple mutual KeyUpdates in TLSv1.3".format(test_no))
assert synchro.recv(1) == b'R'
connection = connect()
settings = HandshakeSettings()
settings.maxVersion = (3, 4)
connection.handshakeClientCert(serverName=address[0], settings=settings)
for i in connection.send_keyupdate_request(KeyUpdateMessageType.update_requested):
assert i in (0, 1)
for i in connection.send_keyupdate_request(KeyUpdateMessageType.update_requested):
assert i in (0, 1)
testConnClient(connection)
synchro.send(b'R')
connection.close()

test_no += 1

print('Test {0} - good standard XMLRPC https client'.format(test_no))
address = address[0], address[1]+1
synchro.recv(1)
Expand Down Expand Up @@ -1847,6 +1915,27 @@ def connect():

test_no += 1

print("Test {0} - good mutual X.509, PHA, TLSv1.3".format(test_no))
synchro.send(b'R')
connection = connect()
settings = HandshakeSettings()
settings.minVersion = (3, 4)
settings.maxVersion = (3, 4)
connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
settings=settings)
assert connection.session.clientCertChain is None
for result in connection.request_post_handshake_auth(settings):
assert result in (0, 1)
synchro.send(b'R')
testConnServer(connection)

print(type(connection.session.clientCertChain))
assert connection.session.clientCertChain is not None
assert isinstance(connection.session.clientCertChain, X509CertChain)
connection.close()

test_no += 1

print("Test {0} - good mutual X.509, TLSv1.1".format(test_no))
synchro.send(b'R')
connection = connect()
Expand Down Expand Up @@ -2274,8 +2363,53 @@ def heartbeat_response_check(message):

test_no += 1

print("Test {0} - KeyUpdate from client in TLSv1.3".format(test_no))
synchro.send(b'R')
connection = connect()
settings = HandshakeSettings()
settings.maxVersion = (3, 4)
connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
settings=settings)
synchro.send(b'K')
synchro.send(b'K')
testConnServer(connection)
connection.close()

test_no += 1

print("Test {0} - mutual KeyUpdates in TLSv1.3".format(test_no))
synchro.send(b'R')
connection = connect()
settings = HandshakeSettings()
settings.maxVersion = (3, 4)
connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
settings=settings)
for i in connection.send_keyupdate_request(KeyUpdateMessageType.update_requested):
assert i in (0, 1)
testConnServer(connection)
assert synchro.recv(1) == b'R'
connection.close()

test_no += 1

print("Test {0} - multiple mutual KeyUpdates in TLSv1.3".format(test_no))
synchro.send(b'R')
connection = connect()
settings = HandshakeSettings()
settings.maxVersion = (3, 4)
connection.handshakeServer(certChain=x509Chain, privateKey=x509Key,
settings=settings)
for i in connection.send_keyupdate_request(KeyUpdateMessageType.update_requested):
assert i in (0, 1)
for i in connection.send_keyupdate_request(KeyUpdateMessageType.update_requested):
assert i in (0, 1)
testConnServer(connection)
assert synchro.recv(1) == b'R'
connection.close()

test_no += 1

print("Tests {0}-{1} - XMLRPXC server".format(test_no, test_no + 2))
test_no += 2

address = address[0], address[1]+1
class Server(TLSXMLRPCServer):
Expand Down Expand Up @@ -2306,6 +2440,7 @@ def add(self, x, y): return x + y

synchro.close()
synchroSocket.close()
test_no += 2

print("Test succeeded")

Expand Down
9 changes: 9 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 # TLS 1.3
next_protocol = 67
message_hash = 254 # TLS 1.3

Expand Down Expand Up @@ -170,6 +171,7 @@ class ExtensionType(TLSEnum):
supported_versions = 43 # TLS 1.3
cookie = 44 # TLS 1.3
psk_key_exchange_modes = 45 # TLS 1.3
post_handshake_auth = 49 # TLS 1.3
signature_algorithms_cert = 50 # TLS 1.3
key_share = 51 # TLS 1.3
supports_npn = 13172
Expand Down Expand Up @@ -409,6 +411,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 @@ -2329,3 +2329,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)
Loading

0 comments on commit 43bcbfe

Please sign in to comment.