OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |