Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Unified Diff: third_party/tlslite/tlslite/tlsconnection.py

Issue 2205433002: Implement ALPN in tlslite. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/tlslite/tlslite/tlsconnection.py
diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
index 41aab85a71b3726d8cafb6060c94c44000e999a8..1dc39e1de60ce9b38f75c2ab0b1ef37b7da06607 100644
--- a/third_party/tlslite/tlslite/tlsconnection.py
+++ b/third_party/tlslite/tlslite/tlsconnection.py
@@ -337,8 +337,8 @@ class TLSConnection(TLSRecordLayer):
def handshakeClientCert(self, certChain=None, privateKey=None,
session=None, settings=None, checker=None,
- nextProtos=None, reqTack=True, serverName="",
- async=False):
+ alpnProtos=None, nextProtos=None, reqTack=True,
davidben 2016/08/03 23:34:22 Please do move this to the settings object. You wo
Bence 2016/08/04 18:41:45 Done. Also moved nextProtos so that they are toge
+ serverName="", async=False):
"""Perform a certificate-based handshake in the role of client.
This function performs an SSL or TLS handshake. The server
@@ -383,6 +383,11 @@ class TLSConnection(TLSRecordLayer):
@param checker: A Checker instance. This instance will be
invoked to examine the other party's authentication
credentials, if the handshake completes succesfully.
+
+ @type alpnProtos: list of strings.
+ @param alpnProtos: A list of upper layer protocols ordered by
+ preference, to advertise in the Application-Layer Protocol Negotiation
+ Extension (RFC 7301).
@type nextProtos: list of strings.
@param nextProtos: A list of upper layer protocols ordered by
@@ -417,7 +422,8 @@ class TLSConnection(TLSRecordLayer):
handshaker = self._handshakeClientAsync(certParams=(certChain,
privateKey), session=session, settings=settings,
checker=checker, serverName=serverName,
- nextProtos=nextProtos, reqTack=reqTack)
+ alpnProtos=alpnProtos, nextProtos=nextProtos,
+ reqTack=reqTack)
# The handshaker is a Python Generator which executes the handshake.
# It allows the handshake to be run in a "piecewise", asynchronous
# fashion, returning 1 when it is waiting to able to write, 0 when
@@ -433,7 +439,8 @@ class TLSConnection(TLSRecordLayer):
def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
session=None, settings=None, checker=None,
- nextProtos=None, serverName="", reqTack=True):
+ alpnProtos=None, nextProtos=None, serverName="",
+ reqTack=True):
handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams,
certParams=certParams,
@@ -441,6 +448,7 @@ class TLSConnection(TLSRecordLayer):
session=session,
settings=settings,
serverName=serverName,
+ alpnProtos=alpnProtos,
nextProtos=nextProtos,
reqTack=reqTack)
for result in self._handshakeWrapperAsync(handshaker, checker):
@@ -448,7 +456,8 @@ class TLSConnection(TLSRecordLayer):
def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams,
- session, settings, serverName, nextProtos, reqTack):
+ session, settings, serverName, alpnProtos,
+ nextProtos, reqTack):
self._handshakeStart(client=True)
@@ -485,6 +494,9 @@ class TLSConnection(TLSRecordLayer):
reqTack = False
if not settings or not settings.useExperimentalTackExtension:
reqTack = False
+ if alpnProtos is not None:
+ if len(alpnProtos) == 0:
+ raise ValueError("Caller passed no alpnProtos")
if nextProtos is not None:
if len(nextProtos) == 0:
raise ValueError("Caller passed no nextProtos")
@@ -530,8 +542,8 @@ class TLSConnection(TLSRecordLayer):
# Send the ClientHello.
for result in self._clientSendClientHello(settings, session,
srpUsername, srpParams, certParams,
- anonParams, serverName, nextProtos,
- reqTack):
+ anonParams, serverName, alpnProtos,
+ nextProtos, reqTack):
if result in (0,1): yield result
else: break
clientHello = result
@@ -543,9 +555,11 @@ class TLSConnection(TLSRecordLayer):
serverHello = result
cipherSuite = serverHello.cipher_suite
- # Choose a matching Next Protocol from server list against ours
- # (string or None)
- nextProto = self._clientSelectNextProto(nextProtos, serverHello)
+ #Ignore NPN if server response has ALPN.
davidben 2016/08/03 23:34:22 This isn't right. If the ServerHello contains both
Bence 2016/08/04 18:41:45 Done.
+ if (serverHello.alpn_proto_selected):
+ nextProto = None
+ else:
+ nextProto = self._clientSelectNextProto(nextProtos, serverHello)
#If the server elected to resume the session, it is handled here.
for result in self._clientResume(session, serverHello,
@@ -621,7 +635,7 @@ class TLSConnection(TLSRecordLayer):
def _clientSendClientHello(self, settings, session, srpUsername,
srpParams, certParams, anonParams,
- serverName, nextProtos, reqTack):
+ serverName, alpnProtos, nextProtos, reqTack):
#Initialize acceptable ciphersuites
cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
if srpParams:
@@ -651,7 +665,7 @@ class TLSConnection(TLSRecordLayer):
session.sessionID, cipherSuites,
certificateTypes,
session.srpUsername,
- reqTack, nextProtos is not None,
+ reqTack, alpnProtos, nextProtos is not None,
session.serverName)
#Or send ClientHello (without)
@@ -661,7 +675,7 @@ class TLSConnection(TLSRecordLayer):
bytearray(0), cipherSuites,
certificateTypes,
srpUsername,
- reqTack, nextProtos is not None,
+ reqTack, alpnProtos, nextProtos is not None,
serverName)
for result in self._sendMsg(clientHello):
yield result
@@ -714,6 +728,11 @@ class TLSConnection(TLSRecordLayer):
AlertDescription.illegal_parameter,
"Server responded with unrequested Tack Extension"):
yield result
+ if serverHello.alpn_proto_selected and not clientHello.alpn_protos_advertised:
+ for result in self._sendError(\
+ AlertDescription.illegal_parameter,
+ "Server responded with unrequested ALPN Extension"):
+ yield result
davidben 2016/08/03 23:34:22 Add a check that ALPN + NPN in a ServerHello is il
Bence 2016/08/04 18:41:45 Done.
if serverHello.next_protos and not clientHello.supports_npn:
for result in self._sendError(\
AlertDescription.illegal_parameter,
@@ -1102,7 +1121,7 @@ class TLSConnection(TLSRecordLayer):
sessionCache=None, settings=None, checker=None,
reqCAs = None, reqCertTypes = None,
tacks=None, activationFlags=0,
- nextProtos=None, anon=False,
+ alpnProtos=None, nextProtos=None, anon=False,
signedCertTimestamps=None,
fallbackSCSV=False, ocspResponse=None):
"""Perform a handshake in the role of server.
@@ -1172,6 +1191,11 @@ class TLSConnection(TLSRecordLayer):
@param reqCertTypes: A list of certificate_type values to be sent
along with a certificate request. This does not affect verification.
+ @type alpnProtos: list of strings.
+ @param alpnProtos: A list of upper layer protocols with zero or one
+ elements. If not empty, its single element is the protocol negotiated
+ via the Application-Layer Protocol Negotiation Extension (RFC 7301).
+
@type nextProtos: list of strings.
@param nextProtos: A list of upper layer protocols to expose to the
clients through the Next-Protocol Negotiation Extension,
@@ -1208,7 +1232,7 @@ class TLSConnection(TLSRecordLayer):
certChain, privateKey, reqCert, sessionCache, settings,
checker, reqCAs, reqCertTypes,
tacks=tacks, activationFlags=activationFlags,
- nextProtos=nextProtos, anon=anon,
+ alpnProtos=alpnProtos, nextProtos=nextProtos, anon=anon,
signedCertTimestamps=signedCertTimestamps,
fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse):
pass
@@ -1218,7 +1242,7 @@ class TLSConnection(TLSRecordLayer):
certChain=None, privateKey=None, reqCert=False,
sessionCache=None, settings=None, checker=None,
reqCAs=None, reqCertTypes=None,
- tacks=None, activationFlags=0,
+ tacks=None, activationFlags=0, alpnProtos=None,
nextProtos=None, anon=False,
signedCertTimestamps=None,
fallbackSCSV=False,
@@ -1240,7 +1264,7 @@ class TLSConnection(TLSRecordLayer):
privateKey=privateKey, reqCert=reqCert,
sessionCache=sessionCache, settings=settings,
reqCAs=reqCAs, reqCertTypes=reqCertTypes,
- tacks=tacks, activationFlags=activationFlags,
+ tacks=tacks, activationFlags=activationFlags, alpnProtos=alpnProtos,
nextProtos=nextProtos, anon=anon,
signedCertTimestamps=signedCertTimestamps,
fallbackSCSV=fallbackSCSV,
@@ -1257,7 +1281,7 @@ class TLSConnection(TLSRecordLayer):
certChain, privateKey, reqCert, sessionCache,
settings, reqCAs, reqCertTypes,
tacks, activationFlags,
- nextProtos, anon,
+ alpnProtos, nextProtos, anon,
signedCertTimestamps, fallbackSCSV,
ocspResponse):
@@ -1314,7 +1338,16 @@ class TLSConnection(TLSRecordLayer):
sessionID = getRandomBytes(32)
else:
sessionID = bytearray(0)
-
+
+ alpn_proto_selected = None
+ if clientHello.alpn_protos_advertised is not None:
+ if alpnProtos is not None:
+ for proto in alpnProtos:
+ if proto in clientHello.alpn_protos_advertised:
+ alpn_proto_selected = proto
+ nextProtos = None
+ break;
+
if not clientHello.supports_npn:
nextProtos = None
@@ -1330,7 +1363,7 @@ class TLSConnection(TLSRecordLayer):
serverHello = ServerHello()
serverHello.create(self.version, getRandomBytes(32), sessionID, \
cipherSuite, CertificateType.x509, tackExt,
- nextProtos)
+ alpn_proto_selected, nextProtos)
serverHello.channel_id = \
clientHello.channel_id and settings.enableChannelID
serverHello.extended_master_secret = \
@@ -1397,7 +1430,7 @@ class TLSConnection(TLSRecordLayer):
for result in self._serverFinished(premasterSecret,
clientHello.random, serverHello.random,
cipherSuite, settings.cipherImplementations,
- nextProtos, serverHello.channel_id,
+ alpnProtos, nextProtos, serverHello.channel_id,
serverHello.extended_master_secret):
if result in (0,1): yield result
else: break
@@ -1540,7 +1573,7 @@ class TLSConnection(TLSRecordLayer):
serverHello = ServerHello()
serverHello.create(self.version, getRandomBytes(32),
session.sessionID, session.cipherSuite,
- CertificateType.x509, None, None)
+ CertificateType.x509, None, None, None)
davidben 2016/08/03 23:34:22 ALPN also should happen on session resumption.
Bence 2016/08/04 18:41:45 Done.
serverHello.extended_master_secret = \
clientHello.extended_master_secret and \
settings.enableExtendedMasterSecret
@@ -1854,8 +1887,8 @@ class TLSConnection(TLSRecordLayer):
def _serverFinished(self, premasterSecret, clientRandom, serverRandom,
- cipherSuite, cipherImplementations, nextProtos,
- doingChannelID, useExtendedMasterSecret):
+ cipherSuite, cipherImplementations, alpnProtos,
+ nextProtos, doingChannelID, useExtendedMasterSecret):
davidben 2016/08/03 23:34:22 (ALPN doesn't interact interestingly with the Fini
Bence 2016/08/04 18:41:44 Done.
masterSecret = calcMasterSecret(self.version, premasterSecret,
clientRandom, serverRandom,
self._ems_handshake_hash,
« third_party/tlslite/tlslite/messages.py ('K') | « third_party/tlslite/tlslite/messages.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698