Package tlslite :: Module messages
[hide private]
[frames] | no frames]

Source Code for Module tlslite.messages

   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  #   Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 
   7  #   Hubert Kario - 'extensions' cleanup 
   8  # 
   9  # See the LICENSE file for legal information regarding use of this file. 
  10   
  11  """Classes representing TLS messages.""" 
  12   
  13  from .utils.compat import * 
  14  from .utils.cryptomath import * 
  15  from .errors import * 
  16  from .utils.codec import * 
  17  from .constants import * 
  18  from .x509 import X509 
  19  from .x509certchain import X509CertChain 
  20  from .utils.tackwrapper import * 
  21  from .extensions import * 
22 23 -class RecordHeader(object):
24 25 """Generic interface to SSLv2 and SSLv3 (and later) record headers""" 26
27 - def __init__(self, ssl2):
28 """define instance variables""" 29 self.type = 0 30 self.version = (0, 0) 31 self.length = 0 32 self.ssl2 = ssl2
33
34 -class RecordHeader3(RecordHeader):
35 36 """SSLv3 (and later) TLS record header""" 37
38 - def __init__(self):
39 """Define a SSLv3 style class""" 40 super(RecordHeader3, self).__init__(ssl2=False)
41
42 - def create(self, version, type, length):
43 """Set object values for writing (serialisation)""" 44 self.type = type 45 self.version = version 46 self.length = length 47 return self
48
49 - def write(self):
50 """Serialise object to bytearray""" 51 writer = Writer() 52 writer.add(self.type, 1) 53 writer.add(self.version[0], 1) 54 writer.add(self.version[1], 1) 55 writer.add(self.length, 2) 56 return writer.bytes
57
58 - def parse(self, parser):
59 """Deserialise object from Parser""" 60 self.type = parser.get(1) 61 self.version = (parser.get(1), parser.get(1)) 62 self.length = parser.get(2) 63 self.ssl2 = False 64 return self
65 66 @property
67 - def typeName(self):
68 matching = [x[0] for x in ContentType.__dict__.items() 69 if x[1] == self.type] 70 if len(matching) == 0: 71 return "unknown(" + str(self.type) + ")" 72 else: 73 return str(matching[0])
74
75 - def __str__(self):
76 return "SSLv3 record,version({0[0]}.{0[1]}),"\ 77 "content type({1}),length({2})".format(self.version, 78 self.typeName, self.length)
79
80 - def __repr__(self):
81 return "RecordHeader3(type={0}, version=({1[0]}.{1[1]}), length={2})".\ 82 format(self.type, self.version, self.length)
83
84 -class RecordHeader2(RecordHeader):
85 86 """SSLv2 record header (just reading)""" 87
88 - def __init__(self):
89 """Define a SSLv2 style class""" 90 super(RecordHeader2, self).__init__(ssl2=True)
91
92 - def parse(self, parser):
93 """Deserialise object from Parser""" 94 if parser.get(1) != 128: 95 raise SyntaxError() 96 self.type = ContentType.handshake 97 self.version = (2, 0) 98 #XXX We don't support 2-byte-length-headers; could be a problem 99 self.length = parser.get(1) 100 return self
101
102 -class Message(object):
103 104 """Generic TLS message""" 105
106 - def __init__(self, contentType, data):
107 """ 108 Initialize object with specified contentType and data 109 110 @type contentType: int 111 @param contentType: TLS record layer content type of associated data 112 @type data: bytearray 113 @param data: data 114 """ 115 self.contentType = contentType 116 self.data = data
117
118 - def write(self):
119 """Return serialised object data""" 120 return self.data
121
122 -class Alert(object):
123 - def __init__(self):
124 self.contentType = ContentType.alert 125 self.level = 0 126 self.description = 0
127
128 - def create(self, description, level=AlertLevel.fatal):
129 self.level = level 130 self.description = description 131 return self
132
133 - def parse(self, p):
134 p.setLengthCheck(2) 135 self.level = p.get(1) 136 self.description = p.get(1) 137 p.stopLengthCheck() 138 return self
139
140 - def write(self):
141 w = Writer() 142 w.add(self.level, 1) 143 w.add(self.description, 1) 144 return w.bytes
145 146 @property
147 - def levelName(self):
148 matching = [x[0] for x in AlertLevel.__dict__.items() 149 if x[1] == self.level] 150 if len(matching) == 0: 151 return "unknown({0})".format(self.level) 152 else: 153 return str(matching[0])
154 155 @property
156 - def descriptionName(self):
157 matching = [x[0] for x in AlertDescription.__dict__.items() 158 if x[1] == self.description] 159 if len(matching) == 0: 160 return "unknown({0})".format(self.description) 161 else: 162 return str(matching[0])
163
164 - def __str__(self):
165 return "Alert, level:{0}, description:{1}".format(self.levelName, 166 self.descriptionName)
167
168 - def __repr__(self):
169 return "Alert(level={0}, description={1})".format(self.level, 170 self.description)
171
172 -class HandshakeMsg(object):
173 - def __init__(self, handshakeType):
174 self.contentType = ContentType.handshake 175 self.handshakeType = handshakeType
176
177 - def postWrite(self, w):
178 headerWriter = Writer() 179 headerWriter.add(self.handshakeType, 1) 180 headerWriter.add(len(w.bytes), 3) 181 return headerWriter.bytes + w.bytes
182
183 -class ClientHello(HandshakeMsg):
184 """ 185 Class for handling the ClientHello TLS message, supports both the SSLv2 186 and SSLv3 style messages. 187 188 @type certificate_types: list 189 @ivar certificate_types: list of supported certificate types (deprecated) 190 191 @type srp_username: bytearray 192 @ivar srp_username: name of the user in SRP extension (deprecated) 193 194 @type supports_npn: boolean 195 @ivar supports_npn: NPN extension presence (deprecated) 196 197 @type tack: boolean 198 @ivar tack: TACK extension presence (deprecated) 199 200 @type server_name: bytearray 201 @ivar server_name: first host_name (type 0) present in SNI extension 202 (deprecated) 203 204 @type extensions: list of L{TLSExtension} 205 @ivar extensions: list of TLS extensions parsed from wire or to send, see 206 L{TLSExtension} and child classes for exact examples 207 """
208 - def __init__(self, ssl2=False):
209 HandshakeMsg.__init__(self, HandshakeType.client_hello) 210 self.ssl2 = ssl2 211 self.client_version = (0,0) 212 self.random = bytearray(32) 213 self.session_id = bytearray(0) 214 self.cipher_suites = [] # a list of 16-bit values 215 self.compression_methods = [] # a list of 8-bit values 216 self.extensions = None
217
218 - def __str__(self):
219 """ 220 Return human readable representation of Client Hello 221 222 @rtype: str 223 """ 224 225 if self.session_id.count(bytearray(b'\x00')) == len(self.session_id)\ 226 and len(self.session_id) != 0: 227 session = "bytearray(b'\\x00'*{0})".format(len(self.session_id)) 228 else: 229 session = repr(self.session_id) 230 ret = "client_hello,version({0[0]}.{0[1]}),random(...),"\ 231 "session ID({1!s}),cipher suites({2!r}),"\ 232 "compression methods({3!r})".format( 233 self.client_version, session, 234 self.cipher_suites, self.compression_methods) 235 236 if self.extensions is not None: 237 ret += ",extensions({0!r})".format(self.extensions) 238 239 return ret
240
241 - def __repr__(self):
242 """ 243 Return machine readable representation of Client Hello 244 245 @rtype: str 246 """ 247 return "ClientHello(ssl2={0}, client_version=({1[0]}.{1[1]}), "\ 248 "random={2!r}, session_id={3!r}, cipher_suites={4!r}, "\ 249 "compression_methods={5}, extensions={6})".format(\ 250 self.ssl2, self.client_version, self.random, self.session_id, 251 self.cipher_suites, self.compression_methods, self.extensions)
252
253 - def getExtension(self, extType):
254 """ 255 Returns extension of given type if present, None otherwise 256 257 @rtype: L{tlslite.extensions.TLSExtension} 258 @raise TLSInternalError: when there are multiple extensions of the 259 same type 260 """ 261 if self.extensions is None: 262 return None 263 264 exts = [ext for ext in self.extensions if ext.extType == extType] 265 if len(exts) > 1: 266 raise TLSInternalError( 267 "Multiple extensions of the same type present") 268 elif len(exts) == 1: 269 return exts[0] 270 else: 271 return None
272
273 - def addExtension(self, ext):
274 """ 275 Adds extension to internal list of extensions 276 277 @type ext: TLSExtension 278 @param ext: extension object to add to list 279 """ 280 if self.extensions is None: 281 self.extensions = [] 282 283 self.extensions.append(ext)
284 285 @property
286 - def certificate_types(self):
287 """ 288 Returns the list of certificate types supported. 289 290 @deprecated: use extensions field to get the extension for inspection 291 """ 292 cert_type = self.getExtension(ExtensionType.cert_type) 293 if cert_type is None: 294 # XXX backwards compatibility: TLSConnection 295 # depends on a default value of this property 296 return [CertificateType.x509] 297 else: 298 return cert_type.certTypes
299 300 @certificate_types.setter
301 - def certificate_types(self, val):
302 """ 303 Sets the list of supported types to list given in L{val} if the 304 cert_type extension is present. Creates the extension and places it 305 last in the list otherwise. 306 307 @type val: list 308 @param val: list of supported certificate types by client encoded as 309 single byte integers 310 """ 311 cert_type = self.getExtension(ExtensionType.cert_type) 312 313 if cert_type is None: 314 ext = ClientCertTypeExtension().create(val) 315 self.addExtension(ext) 316 else: 317 cert_type.certTypes = val
318 319 @property
320 - def srp_username(self):
321 """ 322 Returns username for the SRP. 323 324 @deprecated: use extensions field to get the extension for inspection 325 """ 326 srp_ext = self.getExtension(ExtensionType.srp) 327 328 if srp_ext is None: 329 return None 330 else: 331 return srp_ext.identity
332 333 @srp_username.setter
334 - def srp_username(self, name):
335 """ 336 Sets the username for SRP. 337 338 @type name: bytearray 339 @param name: UTF-8 encoded username 340 """ 341 srp_ext = self.getExtension(ExtensionType.srp) 342 343 if srp_ext is None: 344 ext = SRPExtension().create(name) 345 self.addExtension(ext) 346 else: 347 srp_ext.identity = name
348 349 @property
350 - def tack(self):
351 """ 352 Returns whatever the client supports TACK 353 354 @rtype: boolean 355 @deprecated: use extensions field to get the extension for inspection 356 """ 357 tack_ext = self.getExtension(ExtensionType.tack) 358 359 if tack_ext is None: 360 return False 361 else: 362 return True
363 364 @tack.setter
365 - def tack(self, present):
366 """ 367 Creates or deletes the TACK extension. 368 369 @type present: boolean 370 @param present: True will create extension while False will remove 371 extension from client hello 372 """ 373 if present: 374 tack_ext = self.getExtension(ExtensionType.tack) 375 if tack_ext is None: 376 ext = TLSExtension().create(ExtensionType.tack, bytearray(0)) 377 self.addExtension(ext) 378 else: 379 return 380 else: 381 if self.extensions is None: 382 return 383 # remove all extensions of this type without changing reference 384 self.extensions[:] = [ext for ext in self.extensions if 385 ext.extType != ExtensionType.tack]
386 387 @property
388 - def supports_npn(self):
389 """ 390 Returns whatever client supports NPN extension 391 392 @rtype: boolean 393 @deprecated: use extensions field to get the extension for inspection 394 """ 395 npn_ext = self.getExtension(ExtensionType.supports_npn) 396 397 if npn_ext is None: 398 return False 399 else: 400 return True
401 402 @supports_npn.setter
403 - def supports_npn(self, present):
404 """ 405 Creates or deletes the NPN extension 406 407 @type present: boolean 408 @param present: selects whatever to create or remove the extension 409 from list of supported ones 410 """ 411 if present: 412 npn_ext = self.getExtension(ExtensionType.supports_npn) 413 if npn_ext is None: 414 ext = TLSExtension().create( 415 ExtensionType.supports_npn, 416 bytearray(0)) 417 self.addExtension(ext) 418 else: 419 return 420 else: 421 if self.extensions is None: 422 return 423 #remove all extension of this type without changing reference 424 self.extensions[:] = [ext for ext in self.extensions if 425 ext.extType != ExtensionType.supports_npn]
426 427 @property
428 - def server_name(self):
429 """ 430 Returns first host_name present in SNI extension 431 432 @rtype: bytearray 433 @deprecated: use extensions field to get the extension for inspection 434 """ 435 sni_ext = self.getExtension(ExtensionType.server_name) 436 if sni_ext is None: 437 return bytearray(0) 438 else: 439 if len(sni_ext.hostNames) > 0: 440 return sni_ext.hostNames[0] 441 else: 442 return bytearray(0)
443 444 @server_name.setter
445 - def server_name(self, hostname):
446 """ 447 Sets the first host_name present in SNI extension 448 449 @type hostname: bytearray 450 @param hostname: name of the host_name to set 451 """ 452 sni_ext = self.getExtension(ExtensionType.server_name) 453 if sni_ext is None: 454 sni_ext = SNIExtension().create(hostname) 455 self.addExtension(sni_ext) 456 else: 457 names = list(sni_ext.hostNames) 458 names[0] = hostname 459 sni_ext.hostNames = names
460
461 - def create(self, version, random, session_id, cipher_suites, 462 certificate_types=None, srpUsername=None, 463 tack=False, supports_npn=False, serverName=None, 464 extensions=None):
465 """ 466 Create a ClientHello message for sending. 467 468 @type version: tuple 469 @param version: the highest supported TLS version encoded as two int 470 tuple 471 472 @type random: bytearray 473 @param random: client provided random value, in old versions of TLS 474 (before 1.2) the first 32 bits should include system time 475 476 @type session_id: bytearray 477 @param session_id: ID of session, set when doing session resumption 478 479 @type cipher_suites: list 480 @param cipher_suites: list of ciphersuites advertised as supported 481 482 @type certificate_types: list 483 @param certificate_types: list of supported certificate types, uses 484 TLS extension for signalling, as such requires TLS1.0 to work 485 486 @type srpUsername: bytearray 487 @param srpUsername: utf-8 encoded username for SRP, TLS extension 488 489 @type tack: boolean 490 @param tack: whatever to advertise support for TACK, TLS extension 491 492 @type supports_npn: boolean 493 @param supports_npn: whatever to advertise support for NPN, TLS 494 extension 495 496 @type serverName: bytearray 497 @param serverName: the hostname to request in server name indication 498 extension, TLS extension. Note that SNI allows to set multiple 499 hostnames and values that are not hostnames, use L{SNIExtension} 500 together with L{extensions} to use it. 501 502 @type extensions: list of L{TLSExtension} 503 @param extensions: list of extensions to advertise 504 """ 505 self.client_version = version 506 self.random = random 507 self.session_id = session_id 508 self.cipher_suites = cipher_suites 509 self.compression_methods = [0] 510 if not extensions is None: 511 self.extensions = extensions 512 if not certificate_types is None: 513 self.certificate_types = certificate_types 514 if not srpUsername is None: 515 self.srp_username = bytearray(srpUsername, "utf-8") 516 self.tack = tack 517 self.supports_npn = supports_npn 518 if not serverName is None: 519 self.server_name = bytearray(serverName, "utf-8") 520 return self
521
522 - def parse(self, p):
523 if self.ssl2: 524 self.client_version = (p.get(1), p.get(1)) 525 cipherSpecsLength = p.get(2) 526 sessionIDLength = p.get(2) 527 randomLength = p.get(2) 528 self.cipher_suites = p.getFixList(3, cipherSpecsLength//3) 529 self.session_id = p.getFixBytes(sessionIDLength) 530 self.random = p.getFixBytes(randomLength) 531 if len(self.random) < 32: 532 zeroBytes = 32-len(self.random) 533 self.random = bytearray(zeroBytes) + self.random 534 self.compression_methods = [0]#Fake this value 535 536 #We're not doing a stopLengthCheck() for SSLv2, oh well.. 537 else: 538 p.startLengthCheck(3) 539 self.client_version = (p.get(1), p.get(1)) 540 self.random = p.getFixBytes(32) 541 self.session_id = p.getVarBytes(1) 542 self.cipher_suites = p.getVarList(2, 2) 543 self.compression_methods = p.getVarList(1, 1) 544 if not p.atLengthCheck(): 545 self.extensions = [] 546 totalExtLength = p.get(2) 547 while not p.atLengthCheck(): 548 ext = TLSExtension().parse(p) 549 self.extensions += [ext] 550 p.stopLengthCheck() 551 return self
552
553 - def write(self):
554 w = Writer() 555 w.add(self.client_version[0], 1) 556 w.add(self.client_version[1], 1) 557 w.addFixSeq(self.random, 1) 558 w.addVarSeq(self.session_id, 1, 1) 559 w.addVarSeq(self.cipher_suites, 2, 2) 560 w.addVarSeq(self.compression_methods, 1, 1) 561 562 if not self.extensions is None: 563 w2 = Writer() 564 for ext in self.extensions: 565 w2.bytes += ext.write() 566 567 w.add(len(w2.bytes), 2) 568 w.bytes += w2.bytes 569 return self.postWrite(w)
570
571 -class ServerHello(HandshakeMsg):
572 """server_hello message 573 574 @type server_version: tuple 575 @ivar server_version: protocol version encoded as two int tuple 576 577 @type random: bytearray 578 @ivar random: server random value 579 580 @type session_id: bytearray 581 @ivar session_id: session identifier for resumption 582 583 @type cipher_suite: int 584 @ivar cipher_suite: server selected cipher_suite 585 586 @type compression_method: int 587 @ivar compression_method: server selected compression method 588 589 @type next_protos: list of bytearray 590 @ivar next_protos: list of advertised protocols in NPN extension 591 592 @type next_protos_advertised: list of bytearray 593 @ivar next_protos_advertised: list of protocols advertised in NPN extension 594 595 @type certificate_type: int 596 @ivar certificate_type: certificate type selected by server 597 598 @type extensions: list 599 @ivar extensions: list of TLS extensions present in server_hello message, 600 see L{TLSExtension} and child classes for exact examples 601 """
602 - def __init__(self):
603 """Initialise ServerHello object""" 604 605 HandshakeMsg.__init__(self, HandshakeType.server_hello) 606 self.server_version = (0,0) 607 self.random = bytearray(32) 608 self.session_id = bytearray(0) 609 self.cipher_suite = 0 610 self.compression_method = 0 611 self._tack_ext = None 612 self.extensions = None
613
614 - def __str__(self):
615 base = "server_hello,length({0}),version({1[0]}.{1[1]}),random(...),"\ 616 "session ID({2!r}),cipher({3:#x}),compression method({4})"\ 617 .format(len(self.write())-4, self.server_version, 618 self.session_id, self.cipher_suite, 619 self.compression_method) 620 621 if self.extensions is None: 622 return base 623 624 ret = ",extensions[" 625 ret += ",".join(repr(x) for x in self.extensions) 626 ret += "]" 627 return base + ret
628
629 - def __repr__(self):
630 return "ServerHello(server_version=({0[0]}.{0[1]}), random={1!r}, "\ 631 "session_id={2!r}, cipher_suite={3}, compression_method={4}, "\ 632 "_tack_ext={5}, extensions={6!r})".format(\ 633 self.server_version, self.random, self.session_id, 634 self.cipher_suite, self.compression_method, self._tack_ext, 635 self.extensions)
636
637 - def getExtension(self, extType):
638 """Return extension of a given type, None if extension of given type 639 is not present 640 641 @rtype: L{TLSExtension} 642 @raise TLSInternalError: multiple extensions of the same type present 643 """ 644 if self.extensions is None: 645 return None 646 647 exts = [ext for ext in self.extensions if ext.extType == extType] 648 if len(exts) > 1: 649 raise TLSInternalError( 650 "Multiple extensions of the same type present") 651 elif len(exts) == 1: 652 return exts[0] 653 else: 654 return None
655
656 - def addExtension(self, ext):
657 """ 658 Add extension to internal list of extensions 659 660 @type ext: TLSExtension 661 @param ext: extension to add to list 662 """ 663 if self.extensions is None: 664 self.extensions = [] 665 self.extensions.append(ext)
666 667 @property
668 - def tackExt(self):
669 """ Returns the TACK extension 670 """ 671 if self._tack_ext is None: 672 ext = self.getExtension(ExtensionType.tack) 673 if ext is None or not tackpyLoaded: 674 return None 675 else: 676 self._tack_ext = TackExtension(ext.extData) 677 return self._tack_ext
678 679 @tackExt.setter
680 - def tackExt(self, val):
681 """ Set the TACK extension 682 """ 683 self._tack_ext = val 684 # makes sure that extensions are included in the on the wire encoding 685 if not val is None: 686 if self.extensions is None: 687 self.extensions = []
688 689 @property
690 - def certificate_type(self):
691 """Returns the certificate type selected by server 692 693 @rtype: int 694 """ 695 cert_type = self.getExtension(ExtensionType.cert_type) 696 if cert_type is None: 697 # XXX backwards compatibility, TLSConnection expects the default 698 # value to be that 699 return CertificateType.x509 700 return cert_type.cert_type
701 702 @certificate_type.setter
703 - def certificate_type(self, val):
704 """Sets the certificate type supported 705 706 @type val: int 707 @param val: type of certificate 708 """ 709 # XXX backwards compatibility, 0 means x.509 and should not be sent 710 if val == 0 or val is None: 711 return 712 713 cert_type = self.getExtension(ExtensionType.cert_type) 714 if cert_type is None: 715 ext = ServerCertTypeExtension().create(val) 716 self.addExtension(ext) 717 else: 718 cert_type.cert_type = val
719 720 @property
721 - def next_protos(self):
722 """Returns the advertised protocols in NPN extension 723 724 @rtype: list of bytearrays 725 """ 726 npn_ext = self.getExtension(ExtensionType.supports_npn) 727 728 if npn_ext is None: 729 return None 730 else: 731 return npn_ext.protocols
732 733 @next_protos.setter
734 - def next_protos(self, val):
735 """Sets the advertised protocols in NPN extension 736 737 @type val: list 738 @param val: list of protocols to advertise as UTF-8 encoded names 739 """ 740 if val is None: 741 return 742 else: 743 # convinience function, make sure the values are properly encoded 744 val = [ bytearray(x) for x in val ] 745 746 npn_ext = self.getExtension(ExtensionType.supports_npn) 747 748 if npn_ext is None: 749 ext = NPNExtension().create(val) 750 self.addExtension(ext) 751 else: 752 npn_ext.protocols = val
753 754 @property
755 - def next_protos_advertised(self):
756 """Returns the advertised protocols in NPN extension 757 758 @rtype: list of bytearrays 759 """ 760 return self.next_protos
761 762 @next_protos_advertised.setter
763 - def next_protos_advertised(self, val):
764 """Sets the advertised protocols in NPN extension 765 766 @type val: list 767 @param val: list of protocols to advertise as UTF-8 encoded names 768 """ 769 self.next_protos = val
770
771 - def create(self, version, random, session_id, cipher_suite, 772 certificate_type=None, tackExt=None, next_protos_advertised=None, 773 extensions=None):
774 """Initialize the object for deserialisation""" 775 self.extensions = extensions 776 self.server_version = version 777 self.random = random 778 self.session_id = session_id 779 self.cipher_suite = cipher_suite 780 self.certificate_type = certificate_type 781 self.compression_method = 0 782 if tackExt is not None: 783 self.tackExt = tackExt 784 self.next_protos_advertised = next_protos_advertised 785 return self
786
787 - def parse(self, p):
788 p.startLengthCheck(3) 789 self.server_version = (p.get(1), p.get(1)) 790 self.random = p.getFixBytes(32) 791 self.session_id = p.getVarBytes(1) 792 self.cipher_suite = p.get(2) 793 self.compression_method = p.get(1) 794 if not p.atLengthCheck(): 795 self.extensions = [] 796 totalExtLength = p.get(2) 797 p2 = Parser(p.getFixBytes(totalExtLength)) 798 while p2.getRemainingLength() > 0: 799 ext = TLSExtension(server=True).parse(p2) 800 self.extensions += [ext] 801 p.stopLengthCheck() 802 return self
803
804 - def write(self):
805 w = Writer() 806 w.add(self.server_version[0], 1) 807 w.add(self.server_version[1], 1) 808 w.addFixSeq(self.random, 1) 809 w.addVarSeq(self.session_id, 1, 1) 810 w.add(self.cipher_suite, 2) 811 w.add(self.compression_method, 1) 812 813 if not self.extensions is None: 814 w2 = Writer() 815 for ext in self.extensions: 816 w2.bytes += ext.write() 817 818 if self.tackExt: 819 b = self.tackExt.serialize() 820 w2.add(ExtensionType.tack, 2) 821 w2.add(len(b), 2) 822 w2.bytes += b 823 824 w.add(len(w2.bytes), 2) 825 w.bytes += w2.bytes 826 return self.postWrite(w)
827
828 -class Certificate(HandshakeMsg):
829 - def __init__(self, certificateType):
830 HandshakeMsg.__init__(self, HandshakeType.certificate) 831 self.certificateType = certificateType 832 self.certChain = None
833
834 - def create(self, certChain):
835 self.certChain = certChain 836 return self
837
838 - def parse(self, p):
839 p.startLengthCheck(3) 840 if self.certificateType == CertificateType.x509: 841 chainLength = p.get(3) 842 index = 0 843 certificate_list = [] 844 while index != chainLength: 845 certBytes = p.getVarBytes(3) 846 x509 = X509() 847 x509.parseBinary(certBytes) 848 certificate_list.append(x509) 849 index += len(certBytes)+3 850 if certificate_list: 851 self.certChain = X509CertChain(certificate_list) 852 else: 853 raise AssertionError() 854 855 p.stopLengthCheck() 856 return self
857
858 - def write(self):
859 w = Writer() 860 if self.certificateType == CertificateType.x509: 861 chainLength = 0 862 if self.certChain: 863 certificate_list = self.certChain.x509List 864 else: 865 certificate_list = [] 866 #determine length 867 for cert in certificate_list: 868 bytes = cert.writeBytes() 869 chainLength += len(bytes)+3 870 #add bytes 871 w.add(chainLength, 3) 872 for cert in certificate_list: 873 bytes = cert.writeBytes() 874 w.addVarSeq(bytes, 1, 3) 875 else: 876 raise AssertionError() 877 return self.postWrite(w)
878
879 -class CertificateRequest(HandshakeMsg):
880 - def __init__(self, version):
881 HandshakeMsg.__init__(self, HandshakeType.certificate_request) 882 self.certificate_types = [] 883 self.certificate_authorities = [] 884 self.version = version 885 self.supported_signature_algs = []
886
887 - def create(self, certificate_types, certificate_authorities, sig_algs=()):
888 self.certificate_types = certificate_types 889 self.certificate_authorities = certificate_authorities 890 self.supported_signature_algs = sig_algs 891 return self
892
893 - def parse(self, p):
894 p.startLengthCheck(3) 895 self.certificate_types = p.getVarList(1, 1) 896 if self.version >= (3,3): 897 self.supported_signature_algs = p.getVarTupleList(1, 2, 2) 898 ca_list_length = p.get(2) 899 index = 0 900 self.certificate_authorities = [] 901 while index != ca_list_length: 902 ca_bytes = p.getVarBytes(2) 903 self.certificate_authorities.append(ca_bytes) 904 index += len(ca_bytes)+2 905 p.stopLengthCheck() 906 return self
907
908 - def write(self):
909 w = Writer() 910 w.addVarSeq(self.certificate_types, 1, 1) 911 if self.version >= (3,3): 912 w.addVarTupleSeq(self.supported_signature_algs, 1, 2) 913 caLength = 0 914 #determine length 915 for ca_dn in self.certificate_authorities: 916 caLength += len(ca_dn)+2 917 w.add(caLength, 2) 918 #add bytes 919 for ca_dn in self.certificate_authorities: 920 w.addVarSeq(ca_dn, 1, 2) 921 return self.postWrite(w)
922
923 -class ServerKeyExchange(HandshakeMsg):
924 925 """ 926 Handling TLS Handshake protocol Server Key Exchange messages 927 928 @type cipherSuite: int 929 @cvar cipherSuite: id of ciphersuite selected in Server Hello message 930 @type srp_N: int 931 @cvar srp_N: SRP protocol prime 932 @type srp_g: int 933 @cvar srp_g: SRP protocol generator 934 @type srp_s: bytearray 935 @cvar srp_s: SRP protocol salt value 936 @type srp_B: int 937 @cvar srp_B: SRP protocol server public value 938 @type dh_p: int 939 @cvar dh_p: FFDHE protocol prime 940 @type dh_g: int 941 @cvar dh_g: FFDHE protocol generator 942 @type dh_Ys: int 943 @cvar dh_Ys: FFDH protocol server key share 944 @type signature: bytearray 945 @cvar signature: signature performed over the parameters by server 946 @type hashAlg: int 947 @cvar hashAlg: id of hash algorithm used for signature 948 @type signAlg: int 949 @cvar signAlg: id of signature algorithm used for signature 950 """ 951
952 - def __init__(self, cipherSuite, version):
953 """ 954 Initialise Server Key Exchange for reading or writing 955 956 @type cipherSuite: int 957 @param cipherSuite: id of ciphersuite selected by server 958 """ 959 HandshakeMsg.__init__(self, HandshakeType.server_key_exchange) 960 self.cipherSuite = cipherSuite 961 self.version = version 962 self.srp_N = 0 963 self.srp_g = 0 964 self.srp_s = bytearray(0) 965 self.srp_B = 0 966 # Anon DH params: 967 self.dh_p = 0 968 self.dh_g = 0 969 self.dh_Ys = 0 970 # signature for certificate authenticated ciphersuites 971 self.signature = bytearray(0) 972 # signature hash algorithm and signing algorithm for TLSv1.2 973 self.hashAlg = 0 974 self.signAlg = 0
975
976 - def __repr__(self):
977 978 ret = "ServerKeyExchange(cipherSuite=CipherSuite.{0}, version={1}"\ 979 "".format(CipherSuite.ietfNames[self.cipherSuite], self.version) 980 981 if self.srp_N != 0: 982 ret += ", srp_N={0}, srp_g={1}, srp_s={2!r}, srp_B={3}".format(\ 983 self.srp_N, self.srp_g, self.srp_s, self.srp_B) 984 if self.dh_p != 0: 985 ret += ", dh_p={0}, dh_g={1}, dh_Ys={2}".format(\ 986 self.dh_p, self.dh_g, self.dh_Ys) 987 if self.signAlg != 0: 988 ret += ", hashAlg={0}, signAlg={1}".format(\ 989 self.hashAlg, self.signAlg) 990 if self.signature != bytearray(0): 991 ret += ", signature={0!r}".format(self.signature) 992 ret += ")" 993 994 return ret
995 996
997 - def createSRP(self, srp_N, srp_g, srp_s, srp_B):
998 """Set SRP protocol parameters""" 999 self.srp_N = srp_N 1000 self.srp_g = srp_g 1001 self.srp_s = srp_s 1002 self.srp_B = srp_B 1003 return self
1004
1005 - def createDH(self, dh_p, dh_g, dh_Ys):
1006 """Set FFDH protocol parameters""" 1007 self.dh_p = dh_p 1008 self.dh_g = dh_g 1009 self.dh_Ys = dh_Ys 1010 return self
1011
1012 - def parse(self, parser):
1013 """Deserialise message from L{Parser} 1014 1015 @type parser: L{Parser} 1016 @param parser: parser to read data from 1017 """ 1018 parser.startLengthCheck(3) 1019 if self.cipherSuite in CipherSuite.srpAllSuites: 1020 self.srp_N = bytesToNumber(parser.getVarBytes(2)) 1021 self.srp_g = bytesToNumber(parser.getVarBytes(2)) 1022 self.srp_s = parser.getVarBytes(1) 1023 self.srp_B = bytesToNumber(parser.getVarBytes(2)) 1024 elif self.cipherSuite in CipherSuite.dhAllSuites: 1025 self.dh_p = bytesToNumber(parser.getVarBytes(2)) 1026 self.dh_g = bytesToNumber(parser.getVarBytes(2)) 1027 self.dh_Ys = bytesToNumber(parser.getVarBytes(2)) 1028 else: 1029 raise AssertionError() 1030 1031 if self.cipherSuite in CipherSuite.certAllSuites: 1032 if self.version == (3, 3): 1033 self.hashAlg = parser.get(1) 1034 self.signAlg = parser.get(1) 1035 self.signature = parser.getVarBytes(2) 1036 1037 parser.stopLengthCheck() 1038 return self
1039
1040 - def writeParams(self):
1041 """Serialise the key exchange parameters 1042 1043 @rtype: bytearray 1044 """ 1045 writer = Writer() 1046 if self.cipherSuite in CipherSuite.srpAllSuites: 1047 writer.addVarSeq(numberToByteArray(self.srp_N), 1, 2) 1048 writer.addVarSeq(numberToByteArray(self.srp_g), 1, 2) 1049 writer.addVarSeq(self.srp_s, 1, 1) 1050 writer.addVarSeq(numberToByteArray(self.srp_B), 1, 2) 1051 elif self.cipherSuite in CipherSuite.dhAllSuites: 1052 writer.addVarSeq(numberToByteArray(self.dh_p), 1, 2) 1053 writer.addVarSeq(numberToByteArray(self.dh_g), 1, 2) 1054 writer.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2) 1055 else: 1056 assert(False) 1057 return writer.bytes
1058
1059 - def write(self):
1060 """ 1061 Serialise complete message 1062 1063 @rtype: bytearray 1064 """ 1065 writer = Writer() 1066 writer.bytes += self.writeParams() 1067 if self.cipherSuite in CipherSuite.certAllSuites: 1068 if self.version >= (3, 3): 1069 assert self.hashAlg != 0 and self.signAlg != 0 1070 writer.add(self.hashAlg, 1) 1071 writer.add(self.signAlg, 1) 1072 writer.addVarSeq(self.signature, 1, 2) 1073 return self.postWrite(writer)
1074
1075 - def hash(self, clientRandom, serverRandom):
1076 """ 1077 Calculate hash of paramters to sign 1078 1079 @rtype: bytearray 1080 """ 1081 bytesToHash = clientRandom + serverRandom + self.writeParams() 1082 if self.version >= (3, 3): 1083 # TODO: Signature algorithm negotiation not supported. 1084 return SHA1(bytesToHash) 1085 return MD5(bytesToHash) + SHA1(bytesToHash)
1086
1087 -class ServerHelloDone(HandshakeMsg):
1088 - def __init__(self):
1090
1091 - def create(self):
1092 return self
1093
1094 - def parse(self, p):
1095 p.startLengthCheck(3) 1096 p.stopLengthCheck() 1097 return self
1098
1099 - def write(self):
1100 w = Writer() 1101 return self.postWrite(w)
1102
1103 -class ClientKeyExchange(HandshakeMsg):
1104 1105 """ 1106 Handling of TLS Handshake protocol ClientKeyExchange message 1107 1108 @type cipherSuite: int 1109 @ivar cipherSuite: the cipher suite id used for the connection 1110 @type version: tuple(int, int) 1111 @ivar version: TLS protocol version used for the connection 1112 @type srp_A: int 1113 @ivar srp_A: SRP protocol client answer value 1114 @type dh_Yc: int 1115 @ivar dh_Yc: client Finite Field Diffie-Hellman protocol key share 1116 @type encryptedPreMasterSecret: bytearray 1117 @ivar encryptedPreMasterSecret: client selected PremMaster secret encrypted 1118 with server public key (from certificate) 1119 """ 1120
1121 - def __init__(self, cipherSuite, version=None):
1122 """ 1123 Initialise ClientKeyExchange for reading or writing 1124 1125 @type cipherSuite: int 1126 @param cipherSuite: id of the ciphersuite selected by server 1127 @type version: tuple(int, int) 1128 @param version: protocol version selected by server 1129 """ 1130 HandshakeMsg.__init__(self, HandshakeType.client_key_exchange) 1131 self.cipherSuite = cipherSuite 1132 self.version = version 1133 self.srp_A = 0 1134 self.dh_Yc = 0 1135 self.encryptedPreMasterSecret = bytearray(0)
1136
1137 - def createSRP(self, srp_A):
1138 """ 1139 Set the SRP client answer 1140 1141 returns self 1142 1143 @type srp_A: int 1144 @param srp_A: client SRP answer 1145 @rtype: L{ClientKeyExchange} 1146 """ 1147 self.srp_A = srp_A 1148 return self
1149
1150 - def createRSA(self, encryptedPreMasterSecret):
1151 """ 1152 Set the encrypted PreMaster Secret 1153 1154 returns self 1155 1156 @type encryptedPreMasterSecret: bytearray 1157 @rtype: L{ClientKeyExchange} 1158 """ 1159 self.encryptedPreMasterSecret = encryptedPreMasterSecret 1160 return self
1161
1162 - def createDH(self, dh_Yc):
1163 """ 1164 Set the client FFDH key share 1165 1166 returns self 1167 1168 @type dh_Yc: int 1169 @rtype: L{ClientKeyExchange} 1170 """ 1171 self.dh_Yc = dh_Yc 1172 return self
1173
1174 - def parse(self, parser):
1175 """ 1176 Deserialise the message from L{Parser} 1177 1178 returns self 1179 1180 @type parser: L{Parser} 1181 @rtype: L{ClientKeyExchange} 1182 """ 1183 parser.startLengthCheck(3) 1184 if self.cipherSuite in CipherSuite.srpAllSuites: 1185 self.srp_A = bytesToNumber(parser.getVarBytes(2)) 1186 elif self.cipherSuite in CipherSuite.certSuites: 1187 if self.version in ((3,1), (3,2), (3,3)): 1188 self.encryptedPreMasterSecret = parser.getVarBytes(2) 1189 elif self.version == (3,0): 1190 self.encryptedPreMasterSecret = \ 1191 parser.getFixBytes(parser.getRemainingLength()) 1192 else: 1193 raise AssertionError() 1194 elif self.cipherSuite in CipherSuite.dhAllSuites: 1195 self.dh_Yc = bytesToNumber(parser.getVarBytes(2)) 1196 else: 1197 raise AssertionError() 1198 parser.stopLengthCheck() 1199 return self
1200
1201 - def write(self):
1202 """ 1203 Serialise the object 1204 1205 @rtype: bytearray 1206 """ 1207 w = Writer() 1208 if self.cipherSuite in CipherSuite.srpAllSuites: 1209 w.addVarSeq(numberToByteArray(self.srp_A), 1, 2) 1210 elif self.cipherSuite in CipherSuite.certSuites: 1211 if self.version in ((3,1), (3,2), (3,3)): 1212 w.addVarSeq(self.encryptedPreMasterSecret, 1, 2) 1213 elif self.version == (3,0): 1214 w.addFixSeq(self.encryptedPreMasterSecret, 1) 1215 else: 1216 raise AssertionError() 1217 elif self.cipherSuite in CipherSuite.dhAllSuites: 1218 w.addVarSeq(numberToByteArray(self.dh_Yc), 1, 2) 1219 else: 1220 raise AssertionError() 1221 return self.postWrite(w)
1222
1223 -class CertificateVerify(HandshakeMsg):
1224 1225 """Serializer for TLS handshake protocol Certificate Verify message""" 1226
1227 - def __init__(self, version):
1228 """Create message 1229 1230 @param version: TLS protocol version in use 1231 """ 1232 HandshakeMsg.__init__(self, HandshakeType.certificate_verify) 1233 self.version = version 1234 self.signatureAlgorithm = None 1235 self.signature = bytearray(0)
1236
1237 - def create(self, signature, signatureAlgorithm=None):
1238 """ 1239 Provide data for serialisation of message 1240 1241 @param signature: signature carried in the message 1242 @param signatureAlgorithm: signature algorithm used to make the 1243 signature (TLSv1.2 only) 1244 """ 1245 self.signatureAlgorithm = signatureAlgorithm 1246 self.signature = signature 1247 return self
1248
1249 - def parse(self, parser):
1250 """ 1251 Deserialize message from parser 1252 1253 @param parser: parser with data to read 1254 """ 1255 parser.startLengthCheck(3) 1256 if self.version >= (3, 3): 1257 self.signatureAlgorithm = (parser.get(1), parser.get(1)) 1258 self.signature = parser.getVarBytes(2) 1259 parser.stopLengthCheck() 1260 return self
1261
1262 - def write(self):
1263 """ 1264 Serialize the data to bytearray 1265 1266 @rtype: bytearray 1267 """ 1268 writer = Writer() 1269 if self.version >= (3, 3): 1270 writer.add(self.signatureAlgorithm[0], 1) 1271 writer.add(self.signatureAlgorithm[1], 1) 1272 writer.addVarSeq(self.signature, 1, 2) 1273 return self.postWrite(writer)
1274
1275 -class ChangeCipherSpec(object):
1276 - def __init__(self):
1277 self.contentType = ContentType.change_cipher_spec 1278 self.type = 1
1279
1280 - def create(self):
1281 self.type = 1 1282 return self
1283
1284 - def parse(self, p):
1285 p.setLengthCheck(1) 1286 self.type = p.get(1) 1287 p.stopLengthCheck() 1288 return self
1289
1290 - def write(self):
1291 w = Writer() 1292 w.add(self.type,1) 1293 return w.bytes
1294
1295 1296 -class NextProtocol(HandshakeMsg):
1297 - def __init__(self):
1298 HandshakeMsg.__init__(self, HandshakeType.next_protocol) 1299 self.next_proto = None
1300
1301 - def create(self, next_proto):
1302 self.next_proto = next_proto 1303 return self
1304
1305 - def parse(self, p):
1306 p.startLengthCheck(3) 1307 self.next_proto = p.getVarBytes(1) 1308 _ = p.getVarBytes(1) 1309 p.stopLengthCheck() 1310 return self
1311
1312 - def write(self, trial=False):
1313 w = Writer() 1314 w.addVarSeq(self.next_proto, 1, 1) 1315 paddingLen = 32 - ((len(self.next_proto) + 2) % 32) 1316 w.addVarSeq(bytearray(paddingLen), 1, 1) 1317 return self.postWrite(w)
1318
1319 -class Finished(HandshakeMsg):
1320 - def __init__(self, version):
1321 HandshakeMsg.__init__(self, HandshakeType.finished) 1322 self.version = version 1323 self.verify_data = bytearray(0)
1324
1325 - def create(self, verify_data):
1326 self.verify_data = verify_data 1327 return self
1328
1329 - def parse(self, p):
1330 p.startLengthCheck(3) 1331 if self.version == (3,0): 1332 self.verify_data = p.getFixBytes(36) 1333 elif self.version in ((3,1), (3,2), (3,3)): 1334 self.verify_data = p.getFixBytes(12) 1335 else: 1336 raise AssertionError() 1337 p.stopLengthCheck() 1338 return self
1339
1340 - def write(self):
1341 w = Writer() 1342 w.addFixSeq(self.verify_data, 1) 1343 return self.postWrite(w)
1344
1345 -class ApplicationData(object):
1346 - def __init__(self):
1347 self.contentType = ContentType.application_data 1348 self.bytes = bytearray(0)
1349
1350 - def create(self, bytes):
1351 self.bytes = bytes 1352 return self
1353
1354 - def splitFirstByte(self):
1355 newMsg = ApplicationData().create(self.bytes[:1]) 1356 self.bytes = self.bytes[1:] 1357 return newMsg
1358
1359 - def parse(self, p):
1360 self.bytes = p.bytes 1361 return self
1362
1363 - def write(self):
1364 return self.bytes
1365