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

Side by Side Diff: third_party/tlslite/patches/alpn.patch

Issue 2205433002: Implement ALPN in tlslite. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moving nextProtos back to where it was. 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 unified diff | Download patch
« no previous file with comments | « third_party/tlslite/README.chromium ('k') | third_party/tlslite/tlslite/constants.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlsl ite/constants.py
2 index 715def9..e9743e4 100644
3 --- a/third_party/tlslite/tlslite/constants.py
4 +++ b/third_party/tlslite/tlslite/constants.py
5 @@ -54,6 +54,7 @@ class ExtensionType: # RFC 6066 / 4366
6 status_request = 5 # RFC 6066 / 4366
7 srp = 12 # RFC 5054
8 cert_type = 9 # RFC 6091
9 + alpn = 16 # RFC 7301
10 signed_cert_timestamps = 18 # RFC 6962
11 extended_master_secret = 23 # RFC 7627
12 token_binding = 24 # draft-ietf-tokbind-negotiation
13 diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlsl ite/tlslite/handshakesettings.py
14 index d7be5b3..69fc6f4 100644
15 --- a/third_party/tlslite/tlslite/handshakesettings.py
16 +++ b/third_party/tlslite/tlslite/handshakesettings.py
17 @@ -128,6 +128,12 @@ class HandshakeSettings(object):
18
19 Note that TACK support is not standardized by IETF and uses a temporary
20 TLS Extension number, so should NOT be used in production software.
21 +
22 + @type alpnProtos: list of strings.
23 + @param alpnProtos: A list of supported upper layer protocols to use in the
24 + Application-Layer Protocol Negotiation Extension (RFC 7301). For the
25 + client, the order does not matter. For the server, the list is in
26 + decreasing order of preference.
27 """
28 def __init__(self):
29 self.minKeySize = 1023
30 @@ -146,6 +152,7 @@ class HandshakeSettings(object):
31 self.enableChannelID = True
32 self.enableExtendedMasterSecret = True
33 self.supportedTokenBindingParams = []
34 + self.alpnProtos = None
35
36 # Validates the min/max fields, and certificateTypes
37 # Filters out unsupported cipherNames and cipherImplementations
38 @@ -166,6 +173,7 @@ class HandshakeSettings(object):
39 other.enableChannelID = self.enableChannelID
40 other.enableExtendedMasterSecret = self.enableExtendedMasterSecret
41 other.supportedTokenBindingParams = self.supportedTokenBindingParams
42 + other.alpnProtos = self.alpnProtos;
43
44 if not cipherfactory.tripleDESPresent:
45 other.cipherNames = [e for e in self.cipherNames if e != "3des"]
46 diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlsli te/messages.py
47 index 5762ac6..1ce9320 100644
48 --- a/third_party/tlslite/tlslite/messages.py
49 +++ b/third_party/tlslite/tlslite/messages.py
50 @@ -18,6 +18,27 @@ from .x509 import X509
51 from .x509certchain import X509CertChain
52 from .utils.tackwrapper import *
53
54 +def parse_next_protos(b):
55 + protos = []
56 + while True:
57 + if len(b) == 0:
58 + break
59 + l = b[0]
60 + b = b[1:]
61 + if len(b) < l:
62 + raise BadNextProtos(len(b))
63 + protos.append(b[:l])
64 + b = b[l:]
65 + return protos
66 +
67 +def next_protos_encoded(protocol_list):
68 + b = bytearray()
69 + for e in protocol_list:
70 + if len(e) > 255 or len(e) == 0:
71 + raise BadNextProtos(len(e))
72 + b += bytearray( [len(e)] ) + bytearray(e)
73 + return b
74 +
75 class RecordHeader3(object):
76 def __init__(self):
77 self.type = 0
78 @@ -111,6 +132,7 @@ class ClientHello(HandshakeMsg):
79 self.compression_methods = [] # a list of 8-bit values
80 self.srp_username = None # a string
81 self.tack = False
82 + self.alpn_protos_advertised = None
83 self.supports_npn = False
84 self.server_name = bytearray(0)
85 self.channel_id = False
86 @@ -121,7 +143,8 @@ class ClientHello(HandshakeMsg):
87
88 def create(self, version, random, session_id, cipher_suites,
89 certificate_types=None, srpUsername=None,
90 - tack=False, supports_npn=False, serverName=None):
91 + tack=False, alpn_protos_advertised=None,
92 + supports_npn=False, serverName=None):
93 self.client_version = version
94 self.random = random
95 self.session_id = session_id
96 @@ -131,6 +154,7 @@ class ClientHello(HandshakeMsg):
97 if srpUsername:
98 self.srp_username = bytearray(srpUsername, "utf-8")
99 self.tack = tack
100 + self.alpn_protos_advertised = alpn_protos_advertised
101 self.supports_npn = supports_npn
102 if serverName:
103 self.server_name = bytearray(serverName, "utf-8")
104 @@ -171,6 +195,11 @@ class ClientHello(HandshakeMsg):
105 self.certificate_types = p.getVarList(1, 1)
106 elif extType == ExtensionType.tack:
107 self.tack = True
108 + elif extType == ExtensionType.alpn:
109 + structLength = p.get(2)
110 + if structLength + 2 != extLength:
111 + raise SyntaxError()
112 + self.alpn_protos_advertised = parse_next_protos(p.getFi xBytes(structLength))
113 elif extType == ExtensionType.supports_npn:
114 self.supports_npn = True
115 elif extType == ExtensionType.server_name:
116 @@ -243,6 +272,12 @@ class ClientHello(HandshakeMsg):
117 w2.add(ExtensionType.srp, 2)
118 w2.add(len(self.srp_username)+1, 2)
119 w2.addVarSeq(self.srp_username, 1, 1)
120 + if self.alpn_protos_advertised is not None:
121 + encoded_alpn_protos_advertised = next_protos_encoded(self.alpn_prot os_advertised)
122 + w2.add(ExtensionType.alpn, 2)
123 + w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
124 + w2.add(len(encoded_alpn_protos_advertised), 2)
125 + w2.addFixSeq(encoded_alpn_protos_advertised, 1)
126 if self.supports_npn:
127 w2.add(ExtensionType.supports_npn, 2)
128 w2.add(0, 2)
129 @@ -267,6 +302,13 @@ class BadNextProtos(Exception):
130 def __str__(self):
131 return 'Cannot encode a list of next protocols because it contains an e lement with invalid length %d. Element lengths must be 0 < x < 256' % self.lengt h
132
133 +class InvalidALPNResponse(Exception):
134 + def __init__(self, l):
135 + self.length = l
136 +
137 + def __str__(self):
138 + return 'ALPN server response protocol list has invalid length %d. It m ust be of length one.' % self.length
139 +
140 class ServerHello(HandshakeMsg):
141 def __init__(self):
142 HandshakeMsg.__init__(self, HandshakeType.server_hello)
143 @@ -277,6 +319,7 @@ class ServerHello(HandshakeMsg):
144 self.certificate_type = CertificateType.x509
145 self.compression_method = 0
146 self.tackExt = None
147 + self.alpn_proto_selected = None
148 self.next_protos_advertised = None
149 self.next_protos = None
150 self.channel_id = False
151 @@ -286,7 +329,8 @@ class ServerHello(HandshakeMsg):
152 self.status_request = False
153
154 def create(self, version, random, session_id, cipher_suite,
155 - certificate_type, tackExt, next_protos_advertised):
156 + certificate_type, tackExt, alpn_proto_selected,
157 + next_protos_advertised):
158 self.server_version = version
159 self.random = random
160 self.session_id = session_id
161 @@ -294,6 +338,7 @@ class ServerHello(HandshakeMsg):
162 self.certificate_type = certificate_type
163 self.compression_method = 0
164 self.tackExt = tackExt
165 + self.alpn_proto_selected = alpn_proto_selected
166 self.next_protos_advertised = next_protos_advertised
167 return self
168
169 @@ -316,35 +361,22 @@ class ServerHello(HandshakeMsg):
170 self.certificate_type = p.get(1)
171 elif extType == ExtensionType.tack and tackpyLoaded:
172 self.tackExt = TackExtension(p.getFixBytes(extLength))
173 + elif extType == ExtensionType.alpn:
174 + structLength = p.get(2)
175 + if structLength + 2 != extLength:
176 + raise SyntaxError()
177 + alpn_protos = parse_next_protos(p.getFixBytes(structLength) )
178 + if len(alpn_protos) != 1:
179 + raise InvalidALPNResponse(len(alpn_protos));
180 + self.alpn_proto_selected = alpn_protos[0]
181 elif extType == ExtensionType.supports_npn:
182 - self.next_protos = self.__parse_next_protos(p.getFixBytes(e xtLength))
183 + self.next_protos = parse_next_protos(p.getFixBytes(extLengt h))
184 else:
185 p.getFixBytes(extLength)
186 soFar += 4 + extLength
187 p.stopLengthCheck()
188 return self
189
190 - def __parse_next_protos(self, b):
191 - protos = []
192 - while True:
193 - if len(b) == 0:
194 - break
195 - l = b[0]
196 - b = b[1:]
197 - if len(b) < l:
198 - raise BadNextProtos(len(b))
199 - protos.append(b[:l])
200 - b = b[l:]
201 - return protos
202 -
203 - def __next_protos_encoded(self):
204 - b = bytearray()
205 - for e in self.next_protos_advertised:
206 - if len(e) > 255 or len(e) == 0:
207 - raise BadNextProtos(len(e))
208 - b += bytearray( [len(e)] ) + bytearray(e)
209 - return b
210 -
211 def write(self):
212 w = Writer()
213 w.add(self.server_version[0], 1)
214 @@ -365,8 +397,15 @@ class ServerHello(HandshakeMsg):
215 w2.add(ExtensionType.tack, 2)
216 w2.add(len(b), 2)
217 w2.bytes += b
218 + if self.alpn_proto_selected is not None:
219 + alpn_protos_single_element_list = [self.alpn_proto_selected]
220 + encoded_alpn_protos_advertised = next_protos_encoded(alpn_protos_si ngle_element_list)
221 + w2.add(ExtensionType.alpn, 2)
222 + w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
223 + w2.add(len(encoded_alpn_protos_advertised), 2)
224 + w2.addFixSeq(encoded_alpn_protos_advertised, 1)
225 if self.next_protos_advertised is not None:
226 - encoded_next_protos_advertised = self.__next_protos_encoded()
227 + encoded_next_protos_advertised = next_protos_encoded(self.next_prot os_advertised)
228 w2.add(ExtensionType.supports_npn, 2)
229 w2.add(len(encoded_next_protos_advertised), 2)
230 w2.addFixSeq(encoded_next_protos_advertised, 1)
231 diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/ tlslite/tlsconnection.py
232 index 41aab85..de5d580 100644
233 --- a/third_party/tlslite/tlslite/tlsconnection.py
234 +++ b/third_party/tlslite/tlslite/tlsconnection.py
235 @@ -495,6 +495,10 @@ class TLSConnection(TLSRecordLayer):
236 settings = HandshakeSettings()
237 settings = settings._filter()
238
239 + if settings.alpnProtos is not None:
240 + if len(settings.alpnProtos) == 0:
241 + raise ValueError("Caller passed no alpnProtos")
242 +
243 if clientCertChain:
244 if not isinstance(clientCertChain, X509CertChain):
245 raise ValueError("Unrecognized certificate type")
246 @@ -651,7 +655,8 @@ class TLSConnection(TLSRecordLayer):
247 session.sessionID, cipherSuites,
248 certificateTypes,
249 session.srpUsername,
250 - reqTack, nextProtos is not None,
251 + reqTack, settings.alpnProtos,
252 + nextProtos is not None,
253 session.serverName)
254
255 #Or send ClientHello (without)
256 @@ -661,7 +666,8 @@ class TLSConnection(TLSRecordLayer):
257 bytearray(0), cipherSuites,
258 certificateTypes,
259 srpUsername,
260 - reqTack, nextProtos is not None,
261 + reqTack, settings.alpnProtos,
262 + nextProtos is not None,
263 serverName)
264 for result in self._sendMsg(clientHello):
265 yield result
266 @@ -714,6 +720,16 @@ class TLSConnection(TLSRecordLayer):
267 AlertDescription.illegal_parameter,
268 "Server responded with unrequested Tack Extension"):
269 yield result
270 + if serverHello.alpn_proto_selected and not clientHello.alpn_protos_adve rtised:
271 + for result in self._sendError(\
272 + AlertDescription.illegal_parameter,
273 + "Server responded with unrequested ALPN Extension"):
274 + yield result
275 + if serverHello.alpn_proto_selected and serverHello.next_protos:
276 + for result in self._sendError(\
277 + AlertDescription.illegal_parameter,
278 + "Server responded with both ALPN and NPN extension"):
279 + yield result
280 if serverHello.next_protos and not clientHello.supports_npn:
281 for result in self._sendError(\
282 AlertDescription.illegal_parameter,
283 @@ -1315,6 +1331,15 @@ class TLSConnection(TLSRecordLayer):
284 else:
285 sessionID = bytearray(0)
286
287 + alpn_proto_selected = None
288 + if (clientHello.alpn_protos_advertised is not None
289 + and settings.alpnProtos is not None):
290 + for proto in settings.alpnProtos:
291 + if proto in clientHello.alpn_protos_advertised:
292 + alpn_proto_selected = proto
293 + nextProtos = None
294 + break;
295 +
296 if not clientHello.supports_npn:
297 nextProtos = None
298
299 @@ -1330,6 +1355,7 @@ class TLSConnection(TLSRecordLayer):
300 serverHello = ServerHello()
301 serverHello.create(self.version, getRandomBytes(32), sessionID, \
302 cipherSuite, CertificateType.x509, tackExt,
303 + alpn_proto_selected,
304 nextProtos)
305 serverHello.channel_id = \
306 clientHello.channel_id and settings.enableChannelID
307 @@ -1500,6 +1526,14 @@ class TLSConnection(TLSRecordLayer):
308 else:
309 assert(False)
310
311 + alpn_proto_selected = None
312 + if (clientHello.alpn_protos_advertised is not None
313 + and settings.alpnProtos is not None):
314 + for proto in settings.alpnProtos:
315 + if proto in clientHello.alpn_protos_advertised:
316 + alpn_proto_selected = proto
317 + break;
318 +
319 #If resumption was requested and we have a session cache...
320 if clientHello.session_id and sessionCache:
321 session = None
322 @@ -1540,7 +1574,8 @@ class TLSConnection(TLSRecordLayer):
323 serverHello = ServerHello()
324 serverHello.create(self.version, getRandomBytes(32),
325 session.sessionID, session.cipherSuite,
326 - CertificateType.x509, None, None)
327 + CertificateType.x509, None,
328 + alpn_proto_selected, None)
329 serverHello.extended_master_secret = \
330 clientHello.extended_master_secret and \
331 settings.enableExtendedMasterSecret
OLDNEW
« no previous file with comments | « third_party/tlslite/README.chromium ('k') | third_party/tlslite/tlslite/constants.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698