1# Authors: 2# Trevor Perrin 3# Google - handling CertificateRequest.certificate_types 4# Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support 5# Dimitris Moraitis - Anon ciphersuites 6# 7# See the LICENSE file for legal information regarding use of this file. 8 9"""Classes representing TLS messages.""" 10 11from .utils.compat import * 12from .utils.cryptomath import * 13from .errors import * 14from .utils.codec import * 15from .constants import * 16from .x509 import X509 17from .x509certchain import X509CertChain 18from .utils.tackwrapper import * 19 20class RecordHeader3(object): 21 def __init__(self): 22 self.type = 0 23 self.version = (0,0) 24 self.length = 0 25 self.ssl2 = False 26 27 def create(self, version, type, length): 28 self.type = type 29 self.version = version 30 self.length = length 31 return self 32 33 def write(self): 34 w = Writer() 35 w.add(self.type, 1) 36 w.add(self.version[0], 1) 37 w.add(self.version[1], 1) 38 w.add(self.length, 2) 39 return w.bytes 40 41 def parse(self, p): 42 self.type = p.get(1) 43 self.version = (p.get(1), p.get(1)) 44 self.length = p.get(2) 45 self.ssl2 = False 46 return self 47 48class RecordHeader2(object): 49 def __init__(self): 50 self.type = 0 51 self.version = (0,0) 52 self.length = 0 53 self.ssl2 = True 54 55 def parse(self, p): 56 if p.get(1)!=128: 57 raise SyntaxError() 58 self.type = ContentType.handshake 59 self.version = (2,0) 60 #We don't support 2-byte-length-headers; could be a problem 61 self.length = p.get(1) 62 return self 63 64 65class Alert(object): 66 def __init__(self): 67 self.contentType = ContentType.alert 68 self.level = 0 69 self.description = 0 70 71 def create(self, description, level=AlertLevel.fatal): 72 self.level = level 73 self.description = description 74 return self 75 76 def parse(self, p): 77 p.setLengthCheck(2) 78 self.level = p.get(1) 79 self.description = p.get(1) 80 p.stopLengthCheck() 81 return self 82 83 def write(self): 84 w = Writer() 85 w.add(self.level, 1) 86 w.add(self.description, 1) 87 return w.bytes 88 89 90class HandshakeMsg(object): 91 def __init__(self, handshakeType): 92 self.contentType = ContentType.handshake 93 self.handshakeType = handshakeType 94 95 def postWrite(self, w): 96 headerWriter = Writer() 97 headerWriter.add(self.handshakeType, 1) 98 headerWriter.add(len(w.bytes), 3) 99 return headerWriter.bytes + w.bytes 100 101class ClientHello(HandshakeMsg): 102 def __init__(self, ssl2=False): 103 HandshakeMsg.__init__(self, HandshakeType.client_hello) 104 self.ssl2 = ssl2 105 self.client_version = (0,0) 106 self.random = bytearray(32) 107 self.session_id = bytearray(0) 108 self.cipher_suites = [] # a list of 16-bit values 109 self.certificate_types = [CertificateType.x509] 110 self.compression_methods = [] # a list of 8-bit values 111 self.srp_username = None # a string 112 self.tack = False 113 self.supports_npn = False 114 self.server_name = bytearray(0) 115 self.channel_id = False 116 self.support_signed_cert_timestamps = False 117 self.status_request = False 118 119 def create(self, version, random, session_id, cipher_suites, 120 certificate_types=None, srpUsername=None, 121 tack=False, supports_npn=False, serverName=None): 122 self.client_version = version 123 self.random = random 124 self.session_id = session_id 125 self.cipher_suites = cipher_suites 126 self.certificate_types = certificate_types 127 self.compression_methods = [0] 128 if srpUsername: 129 self.srp_username = bytearray(srpUsername, "utf-8") 130 self.tack = tack 131 self.supports_npn = supports_npn 132 if serverName: 133 self.server_name = bytearray(serverName, "utf-8") 134 return self 135 136 def parse(self, p): 137 if self.ssl2: 138 self.client_version = (p.get(1), p.get(1)) 139 cipherSpecsLength = p.get(2) 140 sessionIDLength = p.get(2) 141 randomLength = p.get(2) 142 self.cipher_suites = p.getFixList(3, cipherSpecsLength//3) 143 self.session_id = p.getFixBytes(sessionIDLength) 144 self.random = p.getFixBytes(randomLength) 145 if len(self.random) < 32: 146 zeroBytes = 32-len(self.random) 147 self.random = bytearray(zeroBytes) + self.random 148 self.compression_methods = [0]#Fake this value 149 150 #We're not doing a stopLengthCheck() for SSLv2, oh well.. 151 else: 152 p.startLengthCheck(3) 153 self.client_version = (p.get(1), p.get(1)) 154 self.random = p.getFixBytes(32) 155 self.session_id = p.getVarBytes(1) 156 self.cipher_suites = p.getVarList(2, 2) 157 self.compression_methods = p.getVarList(1, 1) 158 if not p.atLengthCheck(): 159 totalExtLength = p.get(2) 160 soFar = 0 161 while soFar != totalExtLength: 162 extType = p.get(2) 163 extLength = p.get(2) 164 index1 = p.index 165 if extType == ExtensionType.srp: 166 self.srp_username = p.getVarBytes(1) 167 elif extType == ExtensionType.cert_type: 168 self.certificate_types = p.getVarList(1, 1) 169 elif extType == ExtensionType.tack: 170 self.tack = True 171 elif extType == ExtensionType.supports_npn: 172 self.supports_npn = True 173 elif extType == ExtensionType.server_name: 174 serverNameListBytes = p.getFixBytes(extLength) 175 p2 = Parser(serverNameListBytes) 176 p2.startLengthCheck(2) 177 while 1: 178 if p2.atLengthCheck(): 179 break # no host_name, oh well 180 name_type = p2.get(1) 181 hostNameBytes = p2.getVarBytes(2) 182 if name_type == NameType.host_name: 183 self.server_name = hostNameBytes 184 break 185 elif extType == ExtensionType.channel_id: 186 self.channel_id = True 187 elif extType == ExtensionType.signed_cert_timestamps: 188 if extLength: 189 raise SyntaxError() 190 self.support_signed_cert_timestamps = True 191 elif extType == ExtensionType.status_request: 192 # Extension contents are currently ignored. 193 # According to RFC 6066, this is not strictly forbidden 194 # (although it is suboptimal): 195 # Servers that receive a client hello containing the 196 # "status_request" extension MAY return a suitable 197 # certificate status response to the client along with 198 # their certificate. If OCSP is requested, they 199 # SHOULD use the information contained in the extension 200 # when selecting an OCSP responder and SHOULD include 201 # request_extensions in the OCSP request. 202 p.getFixBytes(extLength) 203 self.status_request = True 204 else: 205 _ = p.getFixBytes(extLength) 206 index2 = p.index 207 if index2 - index1 != extLength: 208 raise SyntaxError("Bad length for extension_data") 209 soFar += 4 + extLength 210 p.stopLengthCheck() 211 return self 212 213 def write(self): 214 w = Writer() 215 w.add(self.client_version[0], 1) 216 w.add(self.client_version[1], 1) 217 w.addFixSeq(self.random, 1) 218 w.addVarSeq(self.session_id, 1, 1) 219 w.addVarSeq(self.cipher_suites, 2, 2) 220 w.addVarSeq(self.compression_methods, 1, 1) 221 222 w2 = Writer() # For Extensions 223 if self.certificate_types and self.certificate_types != \ 224 [CertificateType.x509]: 225 w2.add(ExtensionType.cert_type, 2) 226 w2.add(len(self.certificate_types)+1, 2) 227 w2.addVarSeq(self.certificate_types, 1, 1) 228 if self.srp_username: 229 w2.add(ExtensionType.srp, 2) 230 w2.add(len(self.srp_username)+1, 2) 231 w2.addVarSeq(self.srp_username, 1, 1) 232 if self.supports_npn: 233 w2.add(ExtensionType.supports_npn, 2) 234 w2.add(0, 2) 235 if self.server_name: 236 w2.add(ExtensionType.server_name, 2) 237 w2.add(len(self.server_name)+5, 2) 238 w2.add(len(self.server_name)+3, 2) 239 w2.add(NameType.host_name, 1) 240 w2.addVarSeq(self.server_name, 1, 2) 241 if self.tack: 242 w2.add(ExtensionType.tack, 2) 243 w2.add(0, 2) 244 if len(w2.bytes): 245 w.add(len(w2.bytes), 2) 246 w.bytes += w2.bytes 247 return self.postWrite(w) 248 249class BadNextProtos(Exception): 250 def __init__(self, l): 251 self.length = l 252 253 def __str__(self): 254 return 'Cannot encode a list of next protocols because it contains an element with invalid length %d. Element lengths must be 0 < x < 256' % self.length 255 256class ServerHello(HandshakeMsg): 257 def __init__(self): 258 HandshakeMsg.__init__(self, HandshakeType.server_hello) 259 self.server_version = (0,0) 260 self.random = bytearray(32) 261 self.session_id = bytearray(0) 262 self.cipher_suite = 0 263 self.certificate_type = CertificateType.x509 264 self.compression_method = 0 265 self.tackExt = None 266 self.next_protos_advertised = None 267 self.next_protos = None 268 self.channel_id = False 269 self.signed_cert_timestamps = None 270 self.status_request = False 271 272 def create(self, version, random, session_id, cipher_suite, 273 certificate_type, tackExt, next_protos_advertised): 274 self.server_version = version 275 self.random = random 276 self.session_id = session_id 277 self.cipher_suite = cipher_suite 278 self.certificate_type = certificate_type 279 self.compression_method = 0 280 self.tackExt = tackExt 281 self.next_protos_advertised = next_protos_advertised 282 return self 283 284 def parse(self, p): 285 p.startLengthCheck(3) 286 self.server_version = (p.get(1), p.get(1)) 287 self.random = p.getFixBytes(32) 288 self.session_id = p.getVarBytes(1) 289 self.cipher_suite = p.get(2) 290 self.compression_method = p.get(1) 291 if not p.atLengthCheck(): 292 totalExtLength = p.get(2) 293 soFar = 0 294 while soFar != totalExtLength: 295 extType = p.get(2) 296 extLength = p.get(2) 297 if extType == ExtensionType.cert_type: 298 if extLength != 1: 299 raise SyntaxError() 300 self.certificate_type = p.get(1) 301 elif extType == ExtensionType.tack and tackpyLoaded: 302 self.tackExt = TackExtension(p.getFixBytes(extLength)) 303 elif extType == ExtensionType.supports_npn: 304 self.next_protos = self.__parse_next_protos(p.getFixBytes(extLength)) 305 else: 306 p.getFixBytes(extLength) 307 soFar += 4 + extLength 308 p.stopLengthCheck() 309 return self 310 311 def __parse_next_protos(self, b): 312 protos = [] 313 while True: 314 if len(b) == 0: 315 break 316 l = b[0] 317 b = b[1:] 318 if len(b) < l: 319 raise BadNextProtos(len(b)) 320 protos.append(b[:l]) 321 b = b[l:] 322 return protos 323 324 def __next_protos_encoded(self): 325 b = bytearray() 326 for e in self.next_protos_advertised: 327 if len(e) > 255 or len(e) == 0: 328 raise BadNextProtos(len(e)) 329 b += bytearray( [len(e)] ) + bytearray(e) 330 return b 331 332 def write(self): 333 w = Writer() 334 w.add(self.server_version[0], 1) 335 w.add(self.server_version[1], 1) 336 w.addFixSeq(self.random, 1) 337 w.addVarSeq(self.session_id, 1, 1) 338 w.add(self.cipher_suite, 2) 339 w.add(self.compression_method, 1) 340 341 w2 = Writer() # For Extensions 342 if self.certificate_type and self.certificate_type != \ 343 CertificateType.x509: 344 w2.add(ExtensionType.cert_type, 2) 345 w2.add(1, 2) 346 w2.add(self.certificate_type, 1) 347 if self.tackExt: 348 b = self.tackExt.serialize() 349 w2.add(ExtensionType.tack, 2) 350 w2.add(len(b), 2) 351 w2.bytes += b 352 if self.next_protos_advertised is not None: 353 encoded_next_protos_advertised = self.__next_protos_encoded() 354 w2.add(ExtensionType.supports_npn, 2) 355 w2.add(len(encoded_next_protos_advertised), 2) 356 w2.addFixSeq(encoded_next_protos_advertised, 1) 357 if self.channel_id: 358 w2.add(ExtensionType.channel_id, 2) 359 w2.add(0, 2) 360 if self.signed_cert_timestamps: 361 w2.add(ExtensionType.signed_cert_timestamps, 2) 362 w2.addVarSeq(bytearray(self.signed_cert_timestamps), 1, 2) 363 if self.status_request: 364 w2.add(ExtensionType.status_request, 2) 365 w2.add(0, 2) 366 if len(w2.bytes): 367 w.add(len(w2.bytes), 2) 368 w.bytes += w2.bytes 369 return self.postWrite(w) 370 371 372class Certificate(HandshakeMsg): 373 def __init__(self, certificateType): 374 HandshakeMsg.__init__(self, HandshakeType.certificate) 375 self.certificateType = certificateType 376 self.certChain = None 377 378 def create(self, certChain): 379 self.certChain = certChain 380 return self 381 382 def parse(self, p): 383 p.startLengthCheck(3) 384 if self.certificateType == CertificateType.x509: 385 chainLength = p.get(3) 386 index = 0 387 certificate_list = [] 388 while index != chainLength: 389 certBytes = p.getVarBytes(3) 390 x509 = X509() 391 x509.parseBinary(certBytes) 392 certificate_list.append(x509) 393 index += len(certBytes)+3 394 if certificate_list: 395 self.certChain = X509CertChain(certificate_list) 396 else: 397 raise AssertionError() 398 399 p.stopLengthCheck() 400 return self 401 402 def write(self): 403 w = Writer() 404 if self.certificateType == CertificateType.x509: 405 chainLength = 0 406 if self.certChain: 407 certificate_list = self.certChain.x509List 408 else: 409 certificate_list = [] 410 #determine length 411 for cert in certificate_list: 412 bytes = cert.writeBytes() 413 chainLength += len(bytes)+3 414 #add bytes 415 w.add(chainLength, 3) 416 for cert in certificate_list: 417 bytes = cert.writeBytes() 418 w.addVarSeq(bytes, 1, 3) 419 else: 420 raise AssertionError() 421 return self.postWrite(w) 422 423class CertificateStatus(HandshakeMsg): 424 def __init__(self): 425 HandshakeMsg.__init__(self, HandshakeType.certificate_status) 426 427 def create(self, ocsp_response): 428 self.ocsp_response = ocsp_response 429 return self 430 431 # Defined for the sake of completeness, even though we currently only 432 # support sending the status message (server-side), not requesting 433 # or receiving it (client-side). 434 def parse(self, p): 435 p.startLengthCheck(3) 436 status_type = p.get(1) 437 # Only one type is specified, so hardwire it. 438 if status_type != CertificateStatusType.ocsp: 439 raise SyntaxError() 440 ocsp_response = p.getVarBytes(3) 441 if not ocsp_response: 442 # Can't be empty 443 raise SyntaxError() 444 self.ocsp_response = ocsp_response 445 p.stopLengthCheck() 446 return self 447 448 def write(self): 449 w = Writer() 450 w.add(CertificateStatusType.ocsp, 1) 451 w.addVarSeq(bytearray(self.ocsp_response), 1, 3) 452 return self.postWrite(w) 453 454class CertificateRequest(HandshakeMsg): 455 def __init__(self): 456 HandshakeMsg.__init__(self, HandshakeType.certificate_request) 457 self.certificate_types = [] 458 self.certificate_authorities = [] 459 460 def create(self, certificate_types, certificate_authorities): 461 self.certificate_types = certificate_types 462 self.certificate_authorities = certificate_authorities 463 return self 464 465 def parse(self, p): 466 p.startLengthCheck(3) 467 self.certificate_types = p.getVarList(1, 1) 468 ca_list_length = p.get(2) 469 index = 0 470 self.certificate_authorities = [] 471 while index != ca_list_length: 472 ca_bytes = p.getVarBytes(2) 473 self.certificate_authorities.append(ca_bytes) 474 index += len(ca_bytes)+2 475 p.stopLengthCheck() 476 return self 477 478 def write(self): 479 w = Writer() 480 w.addVarSeq(self.certificate_types, 1, 1) 481 caLength = 0 482 #determine length 483 for ca_dn in self.certificate_authorities: 484 caLength += len(ca_dn)+2 485 w.add(caLength, 2) 486 #add bytes 487 for ca_dn in self.certificate_authorities: 488 w.addVarSeq(ca_dn, 1, 2) 489 return self.postWrite(w) 490 491class ServerKeyExchange(HandshakeMsg): 492 def __init__(self, cipherSuite): 493 HandshakeMsg.__init__(self, HandshakeType.server_key_exchange) 494 self.cipherSuite = cipherSuite 495 self.srp_N = 0 496 self.srp_g = 0 497 self.srp_s = bytearray(0) 498 self.srp_B = 0 499 # Anon DH params: 500 self.dh_p = 0 501 self.dh_g = 0 502 self.dh_Ys = 0 503 self.signature = bytearray(0) 504 505 def createSRP(self, srp_N, srp_g, srp_s, srp_B): 506 self.srp_N = srp_N 507 self.srp_g = srp_g 508 self.srp_s = srp_s 509 self.srp_B = srp_B 510 return self 511 512 def createDH(self, dh_p, dh_g, dh_Ys): 513 self.dh_p = dh_p 514 self.dh_g = dh_g 515 self.dh_Ys = dh_Ys 516 return self 517 518 def parse(self, p): 519 p.startLengthCheck(3) 520 if self.cipherSuite in CipherSuite.srpAllSuites: 521 self.srp_N = bytesToNumber(p.getVarBytes(2)) 522 self.srp_g = bytesToNumber(p.getVarBytes(2)) 523 self.srp_s = p.getVarBytes(1) 524 self.srp_B = bytesToNumber(p.getVarBytes(2)) 525 if self.cipherSuite in CipherSuite.srpCertSuites: 526 self.signature = p.getVarBytes(2) 527 elif self.cipherSuite in CipherSuite.anonSuites: 528 self.dh_p = bytesToNumber(p.getVarBytes(2)) 529 self.dh_g = bytesToNumber(p.getVarBytes(2)) 530 self.dh_Ys = bytesToNumber(p.getVarBytes(2)) 531 p.stopLengthCheck() 532 return self 533 534 def write_params(self): 535 w = Writer() 536 if self.cipherSuite in CipherSuite.srpAllSuites: 537 w.addVarSeq(numberToByteArray(self.srp_N), 1, 2) 538 w.addVarSeq(numberToByteArray(self.srp_g), 1, 2) 539 w.addVarSeq(self.srp_s, 1, 1) 540 w.addVarSeq(numberToByteArray(self.srp_B), 1, 2) 541 elif self.cipherSuite in CipherSuite.dhAllSuites: 542 w.addVarSeq(numberToByteArray(self.dh_p), 1, 2) 543 w.addVarSeq(numberToByteArray(self.dh_g), 1, 2) 544 w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2) 545 else: 546 assert(False) 547 return w.bytes 548 549 def write(self): 550 w = Writer() 551 w.bytes += self.write_params() 552 if self.cipherSuite in CipherSuite.certAllSuites: 553 w.addVarSeq(self.signature, 1, 2) 554 return self.postWrite(w) 555 556 def hash(self, clientRandom, serverRandom): 557 bytes = clientRandom + serverRandom + self.write_params() 558 return MD5(bytes) + SHA1(bytes) 559 560class ServerHelloDone(HandshakeMsg): 561 def __init__(self): 562 HandshakeMsg.__init__(self, HandshakeType.server_hello_done) 563 564 def create(self): 565 return self 566 567 def parse(self, p): 568 p.startLengthCheck(3) 569 p.stopLengthCheck() 570 return self 571 572 def write(self): 573 w = Writer() 574 return self.postWrite(w) 575 576class ClientKeyExchange(HandshakeMsg): 577 def __init__(self, cipherSuite, version=None): 578 HandshakeMsg.__init__(self, HandshakeType.client_key_exchange) 579 self.cipherSuite = cipherSuite 580 self.version = version 581 self.srp_A = 0 582 self.encryptedPreMasterSecret = bytearray(0) 583 584 def createSRP(self, srp_A): 585 self.srp_A = srp_A 586 return self 587 588 def createRSA(self, encryptedPreMasterSecret): 589 self.encryptedPreMasterSecret = encryptedPreMasterSecret 590 return self 591 592 def createDH(self, dh_Yc): 593 self.dh_Yc = dh_Yc 594 return self 595 596 def parse(self, p): 597 p.startLengthCheck(3) 598 if self.cipherSuite in CipherSuite.srpAllSuites: 599 self.srp_A = bytesToNumber(p.getVarBytes(2)) 600 elif self.cipherSuite in CipherSuite.certSuites: 601 if self.version in ((3,1), (3,2)): 602 self.encryptedPreMasterSecret = p.getVarBytes(2) 603 elif self.version == (3,0): 604 self.encryptedPreMasterSecret = \ 605 p.getFixBytes(len(p.bytes)-p.index) 606 else: 607 raise AssertionError() 608 elif self.cipherSuite in CipherSuite.dhAllSuites: 609 self.dh_Yc = bytesToNumber(p.getVarBytes(2)) 610 else: 611 raise AssertionError() 612 p.stopLengthCheck() 613 return self 614 615 def write(self): 616 w = Writer() 617 if self.cipherSuite in CipherSuite.srpAllSuites: 618 w.addVarSeq(numberToByteArray(self.srp_A), 1, 2) 619 elif self.cipherSuite in CipherSuite.certSuites: 620 if self.version in ((3,1), (3,2)): 621 w.addVarSeq(self.encryptedPreMasterSecret, 1, 2) 622 elif self.version == (3,0): 623 w.addFixSeq(self.encryptedPreMasterSecret, 1) 624 else: 625 raise AssertionError() 626 elif self.cipherSuite in CipherSuite.anonSuites: 627 w.addVarSeq(numberToByteArray(self.dh_Yc), 1, 2) 628 else: 629 raise AssertionError() 630 return self.postWrite(w) 631 632class CertificateVerify(HandshakeMsg): 633 def __init__(self): 634 HandshakeMsg.__init__(self, HandshakeType.certificate_verify) 635 self.signature = bytearray(0) 636 637 def create(self, signature): 638 self.signature = signature 639 return self 640 641 def parse(self, p): 642 p.startLengthCheck(3) 643 self.signature = p.getVarBytes(2) 644 p.stopLengthCheck() 645 return self 646 647 def write(self): 648 w = Writer() 649 w.addVarSeq(self.signature, 1, 2) 650 return self.postWrite(w) 651 652class ChangeCipherSpec(object): 653 def __init__(self): 654 self.contentType = ContentType.change_cipher_spec 655 self.type = 1 656 657 def create(self): 658 self.type = 1 659 return self 660 661 def parse(self, p): 662 p.setLengthCheck(1) 663 self.type = p.get(1) 664 p.stopLengthCheck() 665 return self 666 667 def write(self): 668 w = Writer() 669 w.add(self.type,1) 670 return w.bytes 671 672 673class NextProtocol(HandshakeMsg): 674 def __init__(self): 675 HandshakeMsg.__init__(self, HandshakeType.next_protocol) 676 self.next_proto = None 677 678 def create(self, next_proto): 679 self.next_proto = next_proto 680 return self 681 682 def parse(self, p): 683 p.startLengthCheck(3) 684 self.next_proto = p.getVarBytes(1) 685 _ = p.getVarBytes(1) 686 p.stopLengthCheck() 687 return self 688 689 def write(self, trial=False): 690 w = Writer() 691 w.addVarSeq(self.next_proto, 1, 1) 692 paddingLen = 32 - ((len(self.next_proto) + 2) % 32) 693 w.addVarSeq(bytearray(paddingLen), 1, 1) 694 return self.postWrite(w) 695 696class Finished(HandshakeMsg): 697 def __init__(self, version): 698 HandshakeMsg.__init__(self, HandshakeType.finished) 699 self.version = version 700 self.verify_data = bytearray(0) 701 702 def create(self, verify_data): 703 self.verify_data = verify_data 704 return self 705 706 def parse(self, p): 707 p.startLengthCheck(3) 708 if self.version == (3,0): 709 self.verify_data = p.getFixBytes(36) 710 elif self.version in ((3,1), (3,2)): 711 self.verify_data = p.getFixBytes(12) 712 else: 713 raise AssertionError() 714 p.stopLengthCheck() 715 return self 716 717 def write(self): 718 w = Writer() 719 w.addFixSeq(self.verify_data, 1) 720 return self.postWrite(w) 721 722class EncryptedExtensions(HandshakeMsg): 723 def __init__(self): 724 self.channel_id_key = None 725 self.channel_id_proof = None 726 727 def parse(self, p): 728 p.startLengthCheck(3) 729 soFar = 0 730 while soFar != p.lengthCheck: 731 extType = p.get(2) 732 extLength = p.get(2) 733 if extType == ExtensionType.channel_id: 734 if extLength != 32*4: 735 raise SyntaxError() 736 self.channel_id_key = p.getFixBytes(64) 737 self.channel_id_proof = p.getFixBytes(64) 738 else: 739 p.getFixBytes(extLength) 740 soFar += 4 + extLength 741 p.stopLengthCheck() 742 return self 743 744class ApplicationData(object): 745 def __init__(self): 746 self.contentType = ContentType.application_data 747 self.bytes = bytearray(0) 748 749 def create(self, bytes): 750 self.bytes = bytes 751 return self 752 753 def splitFirstByte(self): 754 newMsg = ApplicationData().create(self.bytes[:1]) 755 self.bytes = self.bytes[1:] 756 return newMsg 757 758 def parse(self, p): 759 self.bytes = p.bytes 760 return self 761 762 def write(self): 763 return self.bytes 764