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

Side by Side Diff: third_party/tlslite/tlslite/messages.py

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
OLDNEW
1 # Authors: 1 # Authors:
2 # Trevor Perrin 2 # Trevor Perrin
3 # Google - handling CertificateRequest.certificate_types 3 # Google - handling CertificateRequest.certificate_types
4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support 4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support
5 # Dimitris Moraitis - Anon ciphersuites 5 # Dimitris Moraitis - Anon ciphersuites
6 # Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 6 # Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2
7 # 7 #
8 # See the LICENSE file for legal information regarding use of this file. 8 # See the LICENSE file for legal information regarding use of this file.
9 9
10 """Classes representing TLS messages.""" 10 """Classes representing TLS messages."""
11 11
12 from .utils.compat import * 12 from .utils.compat import *
13 from .utils.cryptomath import * 13 from .utils.cryptomath import *
14 from .errors import * 14 from .errors import *
15 from .utils.codec import * 15 from .utils.codec import *
16 from .constants import * 16 from .constants import *
17 from .x509 import X509 17 from .x509 import X509
18 from .x509certchain import X509CertChain 18 from .x509certchain import X509CertChain
19 from .utils.tackwrapper import * 19 from .utils.tackwrapper import *
20 20
21 def parse_next_protos(b):
22 protos = []
23 while True:
24 if len(b) == 0:
25 break
26 l = b[0]
27 b = b[1:]
28 if len(b) < l:
29 raise BadNextProtos(len(b))
30 protos.append(b[:l])
31 b = b[l:]
32 return protos
33
34 def next_protos_encoded(protocol_list):
35 b = bytearray()
36 for e in protocol_list:
37 if len(e) > 255 or len(e) == 0:
38 raise BadNextProtos(len(e))
39 b += bytearray( [len(e)] ) + bytearray(e)
40 return b
41
21 class RecordHeader3(object): 42 class RecordHeader3(object):
22 def __init__(self): 43 def __init__(self):
23 self.type = 0 44 self.type = 0
24 self.version = (0,0) 45 self.version = (0,0)
25 self.length = 0 46 self.length = 0
26 self.ssl2 = False 47 self.ssl2 = False
27 48
28 def create(self, version, type, length): 49 def create(self, version, type, length):
29 self.type = type 50 self.type = type
30 self.version = version 51 self.version = version
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 HandshakeMsg.__init__(self, HandshakeType.client_hello) 125 HandshakeMsg.__init__(self, HandshakeType.client_hello)
105 self.ssl2 = ssl2 126 self.ssl2 = ssl2
106 self.client_version = (0,0) 127 self.client_version = (0,0)
107 self.random = bytearray(32) 128 self.random = bytearray(32)
108 self.session_id = bytearray(0) 129 self.session_id = bytearray(0)
109 self.cipher_suites = [] # a list of 16-bit values 130 self.cipher_suites = [] # a list of 16-bit values
110 self.certificate_types = [CertificateType.x509] 131 self.certificate_types = [CertificateType.x509]
111 self.compression_methods = [] # a list of 8-bit values 132 self.compression_methods = [] # a list of 8-bit values
112 self.srp_username = None # a string 133 self.srp_username = None # a string
113 self.tack = False 134 self.tack = False
135 self.alpn_protos_advertised = None
114 self.supports_npn = False 136 self.supports_npn = False
115 self.server_name = bytearray(0) 137 self.server_name = bytearray(0)
116 self.channel_id = False 138 self.channel_id = False
117 self.extended_master_secret = False 139 self.extended_master_secret = False
118 self.tb_client_params = [] 140 self.tb_client_params = []
119 self.support_signed_cert_timestamps = False 141 self.support_signed_cert_timestamps = False
120 self.status_request = False 142 self.status_request = False
121 143
122 def create(self, version, random, session_id, cipher_suites, 144 def create(self, version, random, session_id, cipher_suites,
123 certificate_types=None, srpUsername=None, 145 certificate_types=None, srpUsername=None,
124 tack=False, supports_npn=False, serverName=None): 146 tack=False, alpn_protos_advertised=None,
147 supports_npn=False, serverName=None):
125 self.client_version = version 148 self.client_version = version
126 self.random = random 149 self.random = random
127 self.session_id = session_id 150 self.session_id = session_id
128 self.cipher_suites = cipher_suites 151 self.cipher_suites = cipher_suites
129 self.certificate_types = certificate_types 152 self.certificate_types = certificate_types
130 self.compression_methods = [0] 153 self.compression_methods = [0]
131 if srpUsername: 154 if srpUsername:
132 self.srp_username = bytearray(srpUsername, "utf-8") 155 self.srp_username = bytearray(srpUsername, "utf-8")
133 self.tack = tack 156 self.tack = tack
157 self.alpn_protos_advertised = alpn_protos_advertised
134 self.supports_npn = supports_npn 158 self.supports_npn = supports_npn
135 if serverName: 159 if serverName:
136 self.server_name = bytearray(serverName, "utf-8") 160 self.server_name = bytearray(serverName, "utf-8")
137 return self 161 return self
138 162
139 def parse(self, p): 163 def parse(self, p):
140 if self.ssl2: 164 if self.ssl2:
141 self.client_version = (p.get(1), p.get(1)) 165 self.client_version = (p.get(1), p.get(1))
142 cipherSpecsLength = p.get(2) 166 cipherSpecsLength = p.get(2)
143 sessionIDLength = p.get(2) 167 sessionIDLength = p.get(2)
(...skipping 20 matching lines...) Expand all
164 while soFar != totalExtLength: 188 while soFar != totalExtLength:
165 extType = p.get(2) 189 extType = p.get(2)
166 extLength = p.get(2) 190 extLength = p.get(2)
167 index1 = p.index 191 index1 = p.index
168 if extType == ExtensionType.srp: 192 if extType == ExtensionType.srp:
169 self.srp_username = p.getVarBytes(1) 193 self.srp_username = p.getVarBytes(1)
170 elif extType == ExtensionType.cert_type: 194 elif extType == ExtensionType.cert_type:
171 self.certificate_types = p.getVarList(1, 1) 195 self.certificate_types = p.getVarList(1, 1)
172 elif extType == ExtensionType.tack: 196 elif extType == ExtensionType.tack:
173 self.tack = True 197 self.tack = True
198 elif extType == ExtensionType.alpn:
199 structLength = p.get(2)
200 if structLength + 2 != extLength:
201 raise SyntaxError()
202 self.alpn_protos_advertised = parse_next_protos(p.getFix Bytes(structLength))
174 elif extType == ExtensionType.supports_npn: 203 elif extType == ExtensionType.supports_npn:
175 self.supports_npn = True 204 self.supports_npn = True
176 elif extType == ExtensionType.server_name: 205 elif extType == ExtensionType.server_name:
177 serverNameListBytes = p.getFixBytes(extLength) 206 serverNameListBytes = p.getFixBytes(extLength)
178 p2 = Parser(serverNameListBytes) 207 p2 = Parser(serverNameListBytes)
179 p2.startLengthCheck(2) 208 p2.startLengthCheck(2)
180 while 1: 209 while 1:
181 if p2.atLengthCheck(): 210 if p2.atLengthCheck():
182 break # no host_name, oh well 211 break # no host_name, oh well
183 name_type = p2.get(1) 212 name_type = p2.get(1)
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 w2 = Writer() # For Extensions 265 w2 = Writer() # For Extensions
237 if self.certificate_types and self.certificate_types != \ 266 if self.certificate_types and self.certificate_types != \
238 [CertificateType.x509]: 267 [CertificateType.x509]:
239 w2.add(ExtensionType.cert_type, 2) 268 w2.add(ExtensionType.cert_type, 2)
240 w2.add(len(self.certificate_types)+1, 2) 269 w2.add(len(self.certificate_types)+1, 2)
241 w2.addVarSeq(self.certificate_types, 1, 1) 270 w2.addVarSeq(self.certificate_types, 1, 1)
242 if self.srp_username: 271 if self.srp_username:
243 w2.add(ExtensionType.srp, 2) 272 w2.add(ExtensionType.srp, 2)
244 w2.add(len(self.srp_username)+1, 2) 273 w2.add(len(self.srp_username)+1, 2)
245 w2.addVarSeq(self.srp_username, 1, 1) 274 w2.addVarSeq(self.srp_username, 1, 1)
275 if self.alpn_protos_advertised is not None:
276 encoded_alpn_protos_advertised = next_protos_encoded(self.alpn_proto s_advertised)
277 w2.add(ExtensionType.alpn, 2)
278 w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
279 w2.add(len(encoded_alpn_protos_advertised), 2)
280 w2.addFixSeq(encoded_alpn_protos_advertised, 1)
246 if self.supports_npn: 281 if self.supports_npn:
247 w2.add(ExtensionType.supports_npn, 2) 282 w2.add(ExtensionType.supports_npn, 2)
248 w2.add(0, 2) 283 w2.add(0, 2)
249 if self.server_name: 284 if self.server_name:
250 w2.add(ExtensionType.server_name, 2) 285 w2.add(ExtensionType.server_name, 2)
251 w2.add(len(self.server_name)+5, 2) 286 w2.add(len(self.server_name)+5, 2)
252 w2.add(len(self.server_name)+3, 2) 287 w2.add(len(self.server_name)+3, 2)
253 w2.add(NameType.host_name, 1) 288 w2.add(NameType.host_name, 1)
254 w2.addVarSeq(self.server_name, 1, 2) 289 w2.addVarSeq(self.server_name, 1, 2)
255 if self.tack: 290 if self.tack:
256 w2.add(ExtensionType.tack, 2) 291 w2.add(ExtensionType.tack, 2)
257 w2.add(0, 2) 292 w2.add(0, 2)
258 if len(w2.bytes): 293 if len(w2.bytes):
259 w.add(len(w2.bytes), 2) 294 w.add(len(w2.bytes), 2)
260 w.bytes += w2.bytes 295 w.bytes += w2.bytes
261 return self.postWrite(w) 296 return self.postWrite(w)
262 297
263 class BadNextProtos(Exception): 298 class BadNextProtos(Exception):
264 def __init__(self, l): 299 def __init__(self, l):
265 self.length = l 300 self.length = l
266 301
267 def __str__(self): 302 def __str__(self):
268 return 'Cannot encode a list of next protocols because it contains an el ement with invalid length %d. Element lengths must be 0 < x < 256' % self.length 303 return 'Cannot encode a list of next protocols because it contains an el ement with invalid length %d. Element lengths must be 0 < x < 256' % self.length
269 304
305 class InvalidALPNResponse(Exception):
306 def __init__(self, l):
307 self.length = l
308
309 def __str__(self):
310 return 'ALPN server response protocol list has invalid length %d. It mu st be of length one.' % self.length
311
270 class ServerHello(HandshakeMsg): 312 class ServerHello(HandshakeMsg):
271 def __init__(self): 313 def __init__(self):
272 HandshakeMsg.__init__(self, HandshakeType.server_hello) 314 HandshakeMsg.__init__(self, HandshakeType.server_hello)
273 self.server_version = (0,0) 315 self.server_version = (0,0)
274 self.random = bytearray(32) 316 self.random = bytearray(32)
275 self.session_id = bytearray(0) 317 self.session_id = bytearray(0)
276 self.cipher_suite = 0 318 self.cipher_suite = 0
277 self.certificate_type = CertificateType.x509 319 self.certificate_type = CertificateType.x509
278 self.compression_method = 0 320 self.compression_method = 0
279 self.tackExt = None 321 self.tackExt = None
322 self.alpn_proto_selected = None
280 self.next_protos_advertised = None 323 self.next_protos_advertised = None
281 self.next_protos = None 324 self.next_protos = None
282 self.channel_id = False 325 self.channel_id = False
283 self.extended_master_secret = False 326 self.extended_master_secret = False
284 self.tb_params = None 327 self.tb_params = None
285 self.signed_cert_timestamps = None 328 self.signed_cert_timestamps = None
286 self.status_request = False 329 self.status_request = False
287 330
288 def create(self, version, random, session_id, cipher_suite, 331 def create(self, version, random, session_id, cipher_suite,
289 certificate_type, tackExt, next_protos_advertised): 332 certificate_type, tackExt, alpn_proto_selected,
333 next_protos_advertised):
290 self.server_version = version 334 self.server_version = version
291 self.random = random 335 self.random = random
292 self.session_id = session_id 336 self.session_id = session_id
293 self.cipher_suite = cipher_suite 337 self.cipher_suite = cipher_suite
294 self.certificate_type = certificate_type 338 self.certificate_type = certificate_type
295 self.compression_method = 0 339 self.compression_method = 0
296 self.tackExt = tackExt 340 self.tackExt = tackExt
341 self.alpn_proto_selected = alpn_proto_selected
297 self.next_protos_advertised = next_protos_advertised 342 self.next_protos_advertised = next_protos_advertised
298 return self 343 return self
299 344
300 def parse(self, p): 345 def parse(self, p):
301 p.startLengthCheck(3) 346 p.startLengthCheck(3)
302 self.server_version = (p.get(1), p.get(1)) 347 self.server_version = (p.get(1), p.get(1))
303 self.random = p.getFixBytes(32) 348 self.random = p.getFixBytes(32)
304 self.session_id = p.getVarBytes(1) 349 self.session_id = p.getVarBytes(1)
305 self.cipher_suite = p.get(2) 350 self.cipher_suite = p.get(2)
306 self.compression_method = p.get(1) 351 self.compression_method = p.get(1)
307 if not p.atLengthCheck(): 352 if not p.atLengthCheck():
308 totalExtLength = p.get(2) 353 totalExtLength = p.get(2)
309 soFar = 0 354 soFar = 0
310 while soFar != totalExtLength: 355 while soFar != totalExtLength:
311 extType = p.get(2) 356 extType = p.get(2)
312 extLength = p.get(2) 357 extLength = p.get(2)
313 if extType == ExtensionType.cert_type: 358 if extType == ExtensionType.cert_type:
314 if extLength != 1: 359 if extLength != 1:
315 raise SyntaxError() 360 raise SyntaxError()
316 self.certificate_type = p.get(1) 361 self.certificate_type = p.get(1)
317 elif extType == ExtensionType.tack and tackpyLoaded: 362 elif extType == ExtensionType.tack and tackpyLoaded:
318 self.tackExt = TackExtension(p.getFixBytes(extLength)) 363 self.tackExt = TackExtension(p.getFixBytes(extLength))
364 elif extType == ExtensionType.alpn:
365 structLength = p.get(2)
366 if structLength + 2 != extLength:
367 raise SyntaxError()
368 alpn_protos = parse_next_protos(p.getFixBytes(structLength))
369 if len(alpn_protos) != 1:
370 raise InvalidALPNResponse(len(alpn_protos));
371 self.alpn_proto_selected = alpn_protos[0]
319 elif extType == ExtensionType.supports_npn: 372 elif extType == ExtensionType.supports_npn:
320 self.next_protos = self.__parse_next_protos(p.getFixBytes(ex tLength)) 373 self.next_protos = parse_next_protos(p.getFixBytes(extLength ))
321 else: 374 else:
322 p.getFixBytes(extLength) 375 p.getFixBytes(extLength)
323 soFar += 4 + extLength 376 soFar += 4 + extLength
324 p.stopLengthCheck() 377 p.stopLengthCheck()
325 return self 378 return self
326 379
327 def __parse_next_protos(self, b):
328 protos = []
329 while True:
330 if len(b) == 0:
331 break
332 l = b[0]
333 b = b[1:]
334 if len(b) < l:
335 raise BadNextProtos(len(b))
336 protos.append(b[:l])
337 b = b[l:]
338 return protos
339
340 def __next_protos_encoded(self):
341 b = bytearray()
342 for e in self.next_protos_advertised:
343 if len(e) > 255 or len(e) == 0:
344 raise BadNextProtos(len(e))
345 b += bytearray( [len(e)] ) + bytearray(e)
346 return b
347
348 def write(self): 380 def write(self):
349 w = Writer() 381 w = Writer()
350 w.add(self.server_version[0], 1) 382 w.add(self.server_version[0], 1)
351 w.add(self.server_version[1], 1) 383 w.add(self.server_version[1], 1)
352 w.addFixSeq(self.random, 1) 384 w.addFixSeq(self.random, 1)
353 w.addVarSeq(self.session_id, 1, 1) 385 w.addVarSeq(self.session_id, 1, 1)
354 w.add(self.cipher_suite, 2) 386 w.add(self.cipher_suite, 2)
355 w.add(self.compression_method, 1) 387 w.add(self.compression_method, 1)
356 388
357 w2 = Writer() # For Extensions 389 w2 = Writer() # For Extensions
358 if self.certificate_type and self.certificate_type != \ 390 if self.certificate_type and self.certificate_type != \
359 CertificateType.x509: 391 CertificateType.x509:
360 w2.add(ExtensionType.cert_type, 2) 392 w2.add(ExtensionType.cert_type, 2)
361 w2.add(1, 2) 393 w2.add(1, 2)
362 w2.add(self.certificate_type, 1) 394 w2.add(self.certificate_type, 1)
363 if self.tackExt: 395 if self.tackExt:
364 b = self.tackExt.serialize() 396 b = self.tackExt.serialize()
365 w2.add(ExtensionType.tack, 2) 397 w2.add(ExtensionType.tack, 2)
366 w2.add(len(b), 2) 398 w2.add(len(b), 2)
367 w2.bytes += b 399 w2.bytes += b
400 if self.alpn_proto_selected is not None:
401 alpn_protos_single_element_list = [self.alpn_proto_selected]
402 encoded_alpn_protos_advertised = next_protos_encoded(alpn_protos_sin gle_element_list)
403 w2.add(ExtensionType.alpn, 2)
404 w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
405 w2.add(len(encoded_alpn_protos_advertised), 2)
406 w2.addFixSeq(encoded_alpn_protos_advertised, 1)
368 if self.next_protos_advertised is not None: 407 if self.next_protos_advertised is not None:
369 encoded_next_protos_advertised = self.__next_protos_encoded() 408 encoded_next_protos_advertised = next_protos_encoded(self.next_proto s_advertised)
370 w2.add(ExtensionType.supports_npn, 2) 409 w2.add(ExtensionType.supports_npn, 2)
371 w2.add(len(encoded_next_protos_advertised), 2) 410 w2.add(len(encoded_next_protos_advertised), 2)
372 w2.addFixSeq(encoded_next_protos_advertised, 1) 411 w2.addFixSeq(encoded_next_protos_advertised, 1)
373 if self.channel_id: 412 if self.channel_id:
374 w2.add(ExtensionType.channel_id, 2) 413 w2.add(ExtensionType.channel_id, 2)
375 w2.add(0, 2) 414 w2.add(0, 2)
376 if self.extended_master_secret: 415 if self.extended_master_secret:
377 w2.add(ExtensionType.extended_master_secret, 2) 416 w2.add(ExtensionType.extended_master_secret, 2)
378 w2.add(0, 2) 417 w2.add(0, 2)
379 if self.tb_params: 418 if self.tb_params:
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 newMsg = ApplicationData().create(self.bytes[:1]) 864 newMsg = ApplicationData().create(self.bytes[:1])
826 self.bytes = self.bytes[1:] 865 self.bytes = self.bytes[1:]
827 return newMsg 866 return newMsg
828 867
829 def parse(self, p): 868 def parse(self, p):
830 self.bytes = p.bytes 869 self.bytes = p.bytes
831 return self 870 return self
832 871
833 def write(self): 872 def write(self):
834 return self.bytes 873 return self.bytes
OLDNEW
« no previous file with comments | « third_party/tlslite/tlslite/handshakesettings.py ('k') | third_party/tlslite/tlslite/tlsconnection.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698