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 87 88 @type padding: int 89 @ivar padding: number of bytes added at end of message to make it multiple 90 of block cipher size 91 @type securityEscape: boolean 92 @ivar securityEscape: whether the record contains a security escape message 93 """ 94
95 - def __init__(self):
96 """Define a SSLv2 style class""" 97 super(RecordHeader2, self).__init__(ssl2=True) 98 self.padding = 0 99 self.securityEscape = False
100
101 - def parse(self, parser):
102 """Deserialise object from Parser""" 103 firstByte = parser.get(1) 104 secondByte = parser.get(1) 105 if firstByte & 0x80: 106 self.length = ((firstByte & 0x7f) << 8) | secondByte 107 else: 108 self.length = ((firstByte & 0x3f) << 8) | secondByte 109 self.securityEscape = firstByte & 0x40 != 0 110 self.padding = parser.get(1) 111 112 self.type = ContentType.handshake 113 self.version = (2, 0) 114 return self
115
116 - def create(self, length, padding=0, securityEscape=False):
117 """Set object's values""" 118 self.length = length 119 self.padding = padding 120 self.securityEscape = securityEscape 121 return self
122
123 - def write(self):
124 """Serialise object to bytearray""" 125 writer = Writer() 126 127 if not (self.padding or self.securityEscape): 128 shortHeader = True 129 else: 130 shortHeader = False 131 132 if ((shortHeader and self.length >= 0x8000) or 133 (not shortHeader and self.length >= 0x4000)): 134 raise ValueError("length too large") 135 136 firstByte = 0 137 if shortHeader: 138 firstByte |= 0x80 139 if self.securityEscape: 140 firstByte |= 0x40 141 firstByte |= self.length >> 8 142 secondByte = self.length & 0xff 143 144 writer.add(firstByte, 1) 145 writer.add(secondByte, 1) 146 if not shortHeader: 147 writer.add(self.padding, 1) 148 149 return writer.bytes
150
151 -class Message(object):
152 153 """Generic TLS message""" 154
155 - def __init__(self, contentType, data):
156 """ 157 Initialize object with specified contentType and data 158 159 @type contentType: int 160 @param contentType: TLS record layer content type of associated data 161 @type data: bytearray 162 @param data: data 163 """ 164 self.contentType = contentType 165 self.data = data
166
167 - def write(self):
168 """Return serialised object data""" 169 return self.data
170
171 -class Alert(object):
172 - def __init__(self):
173 self.contentType = ContentType.alert 174 self.level = 0 175 self.description = 0
176
177 - def create(self, description, level=AlertLevel.fatal):
178 self.level = level 179 self.description = description 180 return self
181
182 - def parse(self, p):
183 p.setLengthCheck(2) 184 self.level = p.get(1) 185 self.description = p.get(1) 186 p.stopLengthCheck() 187 return self
188
189 - def write(self):
190 w = Writer() 191 w.add(self.level, 1) 192 w.add(self.description, 1) 193 return w.bytes
194 195 @property
196 - def levelName(self):
197 matching = [x[0] for x in AlertLevel.__dict__.items() 198 if x[1] == self.level] 199 if len(matching) == 0: 200 return "unknown({0})".format(self.level) 201 else: 202 return str(matching[0])
203 204 @property
205 - def descriptionName(self):
206 matching = [x[0] for x in AlertDescription.__dict__.items() 207 if x[1] == self.description] 208 if len(matching) == 0: 209 return "unknown({0})".format(self.description) 210 else: 211 return str(matching[0])
212
213 - def __str__(self):
214 return "Alert, level:{0}, description:{1}".format(self.levelName, 215 self.descriptionName)
216
217 - def __repr__(self):
218 return "Alert(level={0}, description={1})".format(self.level, 219 self.description)
220
221 -class HandshakeMsg(object):
222 - def __init__(self, handshakeType):
223 self.contentType = ContentType.handshake 224 self.handshakeType = handshakeType
225
226 - def postWrite(self, w):
227 headerWriter = Writer() 228 headerWriter.add(self.handshakeType, 1) 229 headerWriter.add(len(w.bytes), 3) 230 return headerWriter.bytes + w.bytes
231
232 -class ClientHello(HandshakeMsg):
233 """ 234 Class for handling the ClientHello TLS message, supports both the SSLv2 235 and SSLv3 style messages. 236 237 @type certificate_types: list 238 @ivar certificate_types: list of supported certificate types (deprecated) 239 240 @type srp_username: bytearray 241 @ivar srp_username: name of the user in SRP extension (deprecated) 242 243 @type supports_npn: boolean 244 @ivar supports_npn: NPN extension presence (deprecated) 245 246 @type tack: boolean 247 @ivar tack: TACK extension presence (deprecated) 248 249 @type server_name: bytearray 250 @ivar server_name: first host_name (type 0) present in SNI extension 251 (deprecated) 252 253 @type extensions: list of L{TLSExtension} 254 @ivar extensions: list of TLS extensions parsed from wire or to send, see 255 L{TLSExtension} and child classes for exact examples 256 """
257 - def __init__(self, ssl2=False):
258 HandshakeMsg.__init__(self, HandshakeType.client_hello) 259 self.ssl2 = ssl2 260 self.client_version = (0,0) 261 self.random = bytearray(32) 262 self.session_id = bytearray(0) 263 self.cipher_suites = [] # a list of 16-bit values 264 self.compression_methods = [] # a list of 8-bit values 265 self.extensions = None
266
267 - def __str__(self):
268 """ 269 Return human readable representation of Client Hello 270 271 @rtype: str 272 """ 273 274 if self.session_id.count(bytearray(b'\x00')) == len(self.session_id)\ 275 and len(self.session_id) != 0: 276 session = "bytearray(b'\\x00'*{0})".format(len(self.session_id)) 277 else: 278 session = repr(self.session_id) 279 ret = "client_hello,version({0[0]}.{0[1]}),random(...),"\ 280 "session ID({1!s}),cipher suites({2!r}),"\ 281 "compression methods({3!r})".format( 282 self.client_version, session, 283 self.cipher_suites, self.compression_methods) 284 285 if self.extensions is not None: 286 ret += ",extensions({0!r})".format(self.extensions) 287 288 return ret
289
290 - def __repr__(self):
291 """ 292 Return machine readable representation of Client Hello 293 294 @rtype: str 295 """ 296 return "ClientHello(ssl2={0}, client_version=({1[0]}.{1[1]}), "\ 297 "random={2!r}, session_id={3!r}, cipher_suites={4!r}, "\ 298 "compression_methods={5}, extensions={6})".format(\ 299 self.ssl2, self.client_version, self.random, self.session_id, 300 self.cipher_suites, self.compression_methods, self.extensions)
301
302 - def getExtension(self, extType):
303 """ 304 Returns extension of given type if present, None otherwise 305 306 @rtype: L{tlslite.extensions.TLSExtension} 307 @raise TLSInternalError: when there are multiple extensions of the 308 same type 309 """ 310 if self.extensions is None: 311 return None 312 313 exts = [ext for ext in self.extensions if ext.extType == extType] 314 if len(exts) > 1: 315 raise TLSInternalError( 316 "Multiple extensions of the same type present") 317 elif len(exts) == 1: 318 return exts[0] 319 else: 320 return None
321
322 - def addExtension(self, ext):
323 """ 324 Adds extension to internal list of extensions 325 326 @type ext: TLSExtension 327 @param ext: extension object to add to list 328 """ 329 if self.extensions is None: 330 self.extensions = [] 331 332 self.extensions.append(ext)
333 334 @property
335 - def certificate_types(self):
336 """ 337 Returns the list of certificate types supported. 338 339 @deprecated: use extensions field to get the extension for inspection 340 """ 341 cert_type = self.getExtension(ExtensionType.cert_type) 342 if cert_type is None: 343 # XXX backwards compatibility: TLSConnection 344 # depends on a default value of this property 345 return [CertificateType.x509] 346 else: 347 return cert_type.certTypes
348 349 @certificate_types.setter
350 - def certificate_types(self, val):
351 """ 352 Sets the list of supported types to list given in L{val} if the 353 cert_type extension is present. Creates the extension and places it 354 last in the list otherwise. 355 356 @type val: list 357 @param val: list of supported certificate types by client encoded as 358 single byte integers 359 """ 360 cert_type = self.getExtension(ExtensionType.cert_type) 361 362 if cert_type is None: 363 ext = ClientCertTypeExtension().create(val) 364 self.addExtension(ext) 365 else: 366 cert_type.certTypes = val
367 368 @property
369 - def srp_username(self):
370 """ 371 Returns username for the SRP. 372 373 @deprecated: use extensions field to get the extension for inspection 374 """ 375 srp_ext = self.getExtension(ExtensionType.srp) 376 377 if srp_ext is None: 378 return None 379 else: 380 return srp_ext.identity
381 382 @srp_username.setter
383 - def srp_username(self, name):
384 """ 385 Sets the username for SRP. 386 387 @type name: bytearray 388 @param name: UTF-8 encoded username 389 """ 390 srp_ext = self.getExtension(ExtensionType.srp) 391 392 if srp_ext is None: 393 ext = SRPExtension().create(name) 394 self.addExtension(ext) 395 else: 396 srp_ext.identity = name
397 398 @property
399 - def tack(self):
400 """ 401 Returns whatever the client supports TACK 402 403 @rtype: boolean 404 @deprecated: use extensions field to get the extension for inspection 405 """ 406 tack_ext = self.getExtension(ExtensionType.tack) 407 408 if tack_ext is None: 409 return False 410 else: 411 return True
412 413 @tack.setter
414 - def tack(self, present):
415 """ 416 Creates or deletes the TACK extension. 417 418 @type present: boolean 419 @param present: True will create extension while False will remove 420 extension from client hello 421 """ 422 if present: 423 tack_ext = self.getExtension(ExtensionType.tack) 424 if tack_ext is None: 425 ext = TLSExtension().create(ExtensionType.tack, bytearray(0)) 426 self.addExtension(ext) 427 else: 428 return 429 else: 430 if self.extensions is None: 431 return 432 # remove all extensions of this type without changing reference 433 self.extensions[:] = [ext for ext in self.extensions if 434 ext.extType != ExtensionType.tack]
435 436 @property
437 - def supports_npn(self):
438 """ 439 Returns whatever client supports NPN extension 440 441 @rtype: boolean 442 @deprecated: use extensions field to get the extension for inspection 443 """ 444 npn_ext = self.getExtension(ExtensionType.supports_npn) 445 446 if npn_ext is None: 447 return False 448 else: 449 return True
450 451 @supports_npn.setter
452 - def supports_npn(self, present):
453 """ 454 Creates or deletes the NPN extension 455 456 @type present: boolean 457 @param present: selects whatever to create or remove the extension 458 from list of supported ones 459 """ 460 if present: 461 npn_ext = self.getExtension(ExtensionType.supports_npn) 462 if npn_ext is None: 463 ext = TLSExtension().create( 464 ExtensionType.supports_npn, 465 bytearray(0)) 466 self.addExtension(ext) 467 else: 468 return 469 else: 470 if self.extensions is None: 471 return 472 #remove all extension of this type without changing reference 473 self.extensions[:] = [ext for ext in self.extensions if 474 ext.extType != ExtensionType.supports_npn]
475 476 @property
477 - def server_name(self):
478 """ 479 Returns first host_name present in SNI extension 480 481 @rtype: bytearray 482 @deprecated: use extensions field to get the extension for inspection 483 """ 484 sni_ext = self.getExtension(ExtensionType.server_name) 485 if sni_ext is None: 486 return bytearray(0) 487 else: 488 if len(sni_ext.hostNames) > 0: 489 return sni_ext.hostNames[0] 490 else: 491 return bytearray(0)
492 493 @server_name.setter
494 - def server_name(self, hostname):
495 """ 496 Sets the first host_name present in SNI extension 497 498 @type hostname: bytearray 499 @param hostname: name of the host_name to set 500 """ 501 sni_ext = self.getExtension(ExtensionType.server_name) 502 if sni_ext is None: 503 sni_ext = SNIExtension().create(hostname) 504 self.addExtension(sni_ext) 505 else: 506 names = list(sni_ext.hostNames) 507 names[0] = hostname 508 sni_ext.hostNames = names
509
510 - def create(self, version, random, session_id, cipher_suites, 511 certificate_types=None, srpUsername=None, 512 tack=False, supports_npn=False, serverName=None, 513 extensions=None):
514 """ 515 Create a ClientHello message for sending. 516 517 @type version: tuple 518 @param version: the highest supported TLS version encoded as two int 519 tuple 520 521 @type random: bytearray 522 @param random: client provided random value, in old versions of TLS 523 (before 1.2) the first 32 bits should include system time, also 524 used as the "challenge" field in SSLv2 525 526 @type session_id: bytearray 527 @param session_id: ID of session, set when doing session resumption 528 529 @type cipher_suites: list 530 @param cipher_suites: list of ciphersuites advertised as supported 531 532 @type certificate_types: list 533 @param certificate_types: list of supported certificate types, uses 534 TLS extension for signalling, as such requires TLS1.0 to work 535 536 @type srpUsername: bytearray 537 @param srpUsername: utf-8 encoded username for SRP, TLS extension 538 539 @type tack: boolean 540 @param tack: whatever to advertise support for TACK, TLS extension 541 542 @type supports_npn: boolean 543 @param supports_npn: whatever to advertise support for NPN, TLS 544 extension 545 546 @type serverName: bytearray 547 @param serverName: the hostname to request in server name indication 548 extension, TLS extension. Note that SNI allows to set multiple 549 hostnames and values that are not hostnames, use L{SNIExtension} 550 together with L{extensions} to use it. 551 552 @type extensions: list of L{TLSExtension} 553 @param extensions: list of extensions to advertise 554 """ 555 self.client_version = version 556 self.random = random 557 self.session_id = session_id 558 self.cipher_suites = cipher_suites 559 self.compression_methods = [0] 560 if not extensions is None: 561 self.extensions = extensions 562 if not certificate_types is None: 563 self.certificate_types = certificate_types 564 if not srpUsername is None: 565 self.srp_username = bytearray(srpUsername, "utf-8") 566 self.tack = tack 567 self.supports_npn = supports_npn 568 if not serverName is None: 569 self.server_name = bytearray(serverName, "utf-8") 570 return self
571
572 - def parse(self, p):
573 """Deserialise object from on the wire data""" 574 if self.ssl2: 575 self.client_version = (p.get(1), p.get(1)) 576 cipherSpecsLength = p.get(2) 577 sessionIDLength = p.get(2) 578 randomLength = p.get(2) 579 p.setLengthCheck(cipherSpecsLength + 580 sessionIDLength + 581 randomLength) 582 self.cipher_suites = p.getFixList(3, cipherSpecsLength//3) 583 self.session_id = p.getFixBytes(sessionIDLength) 584 self.random = p.getFixBytes(randomLength) 585 if len(self.random) < 32: 586 zeroBytes = 32-len(self.random) 587 self.random = bytearray(zeroBytes) + self.random 588 self.compression_methods = [0] # Fake this value 589 p.stopLengthCheck() 590 else: 591 p.startLengthCheck(3) 592 self.client_version = (p.get(1), p.get(1)) 593 self.random = p.getFixBytes(32) 594 self.session_id = p.getVarBytes(1) 595 self.cipher_suites = p.getVarList(2, 2) 596 self.compression_methods = p.getVarList(1, 1) 597 if not p.atLengthCheck(): 598 self.extensions = [] 599 totalExtLength = p.get(2) 600 while not p.atLengthCheck(): 601 ext = TLSExtension().parse(p) 602 self.extensions += [ext] 603 p.stopLengthCheck() 604 return self
605
606 - def _writeSSL2(self):
607 """Serialise SSLv2 object to on the wire data""" 608 writer = Writer() 609 writer.add(self.handshakeType, 1) 610 writer.add(self.client_version[0], 1) 611 writer.add(self.client_version[1], 1) 612 613 ciphersWriter = Writer() 614 ciphersWriter.addFixSeq(self.cipher_suites, 3) 615 616 writer.add(len(ciphersWriter.bytes), 2) 617 writer.add(len(self.session_id), 2) 618 writer.add(len(self.random), 2) 619 620 writer.bytes += ciphersWriter.bytes 621 writer.bytes += self.session_id 622 writer.bytes += self.random 623 624 # postWrite() is necessary only for SSLv3/TLS 625 return writer.bytes
626
627 - def _write(self):
628 """Serialise SSLv3 or TLS object to on the wire data""" 629 w = Writer() 630 w.add(self.client_version[0], 1) 631 w.add(self.client_version[1], 1) 632 w.addFixSeq(self.random, 1) 633 w.addVarSeq(self.session_id, 1, 1) 634 w.addVarSeq(self.cipher_suites, 2, 2) 635 w.addVarSeq(self.compression_methods, 1, 1) 636 637 if not self.extensions is None: 638 w2 = Writer() 639 for ext in self.extensions: 640 w2.bytes += ext.write() 641 642 w.add(len(w2.bytes), 2) 643 w.bytes += w2.bytes 644 return self.postWrite(w)
645
646 - def write(self):
647 """Serialise object to on the wire data""" 648 if self.ssl2: 649 return self._writeSSL2() 650 else: 651 return self._write()
652
653 -class ServerHello(HandshakeMsg):
654 """server_hello message 655 656 @type server_version: tuple 657 @ivar server_version: protocol version encoded as two int tuple 658 659 @type random: bytearray 660 @ivar random: server random value 661 662 @type session_id: bytearray 663 @ivar session_id: session identifier for resumption 664 665 @type cipher_suite: int 666 @ivar cipher_suite: server selected cipher_suite 667 668 @type compression_method: int 669 @ivar compression_method: server selected compression method 670 671 @type next_protos: list of bytearray 672 @ivar next_protos: list of advertised protocols in NPN extension 673 674 @type next_protos_advertised: list of bytearray 675 @ivar next_protos_advertised: list of protocols advertised in NPN extension 676 677 @type certificate_type: int 678 @ivar certificate_type: certificate type selected by server 679 680 @type extensions: list 681 @ivar extensions: list of TLS extensions present in server_hello message, 682 see L{TLSExtension} and child classes for exact examples 683 """
684 - def __init__(self):
685 """Initialise ServerHello object""" 686 687 HandshakeMsg.__init__(self, HandshakeType.server_hello) 688 self.server_version = (0,0) 689 self.random = bytearray(32) 690 self.session_id = bytearray(0) 691 self.cipher_suite = 0 692 self.compression_method = 0 693 self._tack_ext = None 694 self.extensions = None
695
696 - def __str__(self):
697 base = "server_hello,length({0}),version({1[0]}.{1[1]}),random(...),"\ 698 "session ID({2!r}),cipher({3:#x}),compression method({4})"\ 699 .format(len(self.write())-4, self.server_version, 700 self.session_id, self.cipher_suite, 701 self.compression_method) 702 703 if self.extensions is None: 704 return base 705 706 ret = ",extensions[" 707 ret += ",".join(repr(x) for x in self.extensions) 708 ret += "]" 709 return base + ret
710
711 - def __repr__(self):
712 return "ServerHello(server_version=({0[0]}, {0[1]}), random={1!r}, "\ 713 "session_id={2!r}, cipher_suite={3}, compression_method={4}, "\ 714 "_tack_ext={5}, extensions={6!r})".format(\ 715 self.server_version, self.random, self.session_id, 716 self.cipher_suite, self.compression_method, self._tack_ext, 717 self.extensions)
718
719 - def getExtension(self, extType):
720 """Return extension of a given type, None if extension of given type 721 is not present 722 723 @rtype: L{TLSExtension} 724 @raise TLSInternalError: multiple extensions of the same type present 725 """ 726 if self.extensions is None: 727 return None 728 729 exts = [ext for ext in self.extensions if ext.extType == extType] 730 if len(exts) > 1: 731 raise TLSInternalError( 732 "Multiple extensions of the same type present") 733 elif len(exts) == 1: 734 return exts[0] 735 else: 736 return None
737
738 - def addExtension(self, ext):
739 """ 740 Add extension to internal list of extensions 741 742 @type ext: TLSExtension 743 @param ext: extension to add to list 744 """ 745 if self.extensions is None: 746 self.extensions = [] 747 self.extensions.append(ext)
748 749 @property
750 - def tackExt(self):
751 """ Returns the TACK extension 752 """ 753 if self._tack_ext is None: 754 ext = self.getExtension(ExtensionType.tack) 755 if ext is None or not tackpyLoaded: 756 return None 757 else: 758 self._tack_ext = TackExtension(ext.extData) 759 return self._tack_ext
760 761 @tackExt.setter
762 - def tackExt(self, val):
763 """ Set the TACK extension 764 """ 765 self._tack_ext = val 766 # makes sure that extensions are included in the on the wire encoding 767 if not val is None: 768 if self.extensions is None: 769 self.extensions = []
770 771 @property
772 - def certificate_type(self):
773 """Returns the certificate type selected by server 774 775 @rtype: int 776 """ 777 cert_type = self.getExtension(ExtensionType.cert_type) 778 if cert_type is None: 779 # XXX backwards compatibility, TLSConnection expects the default 780 # value to be that 781 return CertificateType.x509 782 return cert_type.cert_type
783 784 @certificate_type.setter
785 - def certificate_type(self, val):
786 """Sets the certificate type supported 787 788 @type val: int 789 @param val: type of certificate 790 """ 791 # XXX backwards compatibility, 0 means x.509 and should not be sent 792 if val == 0 or val is None: 793 return 794 795 cert_type = self.getExtension(ExtensionType.cert_type) 796 if cert_type is None: 797 ext = ServerCertTypeExtension().create(val) 798 self.addExtension(ext) 799 else: 800 cert_type.cert_type = val
801 802 @property
803 - def next_protos(self):
804 """Returns the advertised protocols in NPN extension 805 806 @rtype: list of bytearrays 807 """ 808 npn_ext = self.getExtension(ExtensionType.supports_npn) 809 810 if npn_ext is None: 811 return None 812 else: 813 return npn_ext.protocols
814 815 @next_protos.setter
816 - def next_protos(self, val):
817 """Sets the advertised protocols in NPN extension 818 819 @type val: list 820 @param val: list of protocols to advertise as UTF-8 encoded names 821 """ 822 if val is None: 823 return 824 else: 825 # convinience function, make sure the values are properly encoded 826 val = [ bytearray(x) for x in val ] 827 828 npn_ext = self.getExtension(ExtensionType.supports_npn) 829 830 if npn_ext is None: 831 ext = NPNExtension().create(val) 832 self.addExtension(ext) 833 else: 834 npn_ext.protocols = val
835 836 @property
837 - def next_protos_advertised(self):
838 """Returns the advertised protocols in NPN extension 839 840 @rtype: list of bytearrays 841 """ 842 return self.next_protos
843 844 @next_protos_advertised.setter
845 - def next_protos_advertised(self, val):
846 """Sets the advertised protocols in NPN extension 847 848 @type val: list 849 @param val: list of protocols to advertise as UTF-8 encoded names 850 """ 851 self.next_protos = val
852
853 - def create(self, version, random, session_id, cipher_suite, 854 certificate_type=None, tackExt=None, next_protos_advertised=None, 855 extensions=None):
856 """Initialize the object for deserialisation""" 857 self.extensions = extensions 858 self.server_version = version 859 self.random = random 860 self.session_id = session_id 861 self.cipher_suite = cipher_suite 862 self.certificate_type = certificate_type 863 self.compression_method = 0 864 if tackExt is not None: 865 self.tackExt = tackExt 866 self.next_protos_advertised = next_protos_advertised 867 return self
868
869 - def parse(self, p):
870 p.startLengthCheck(3) 871 self.server_version = (p.get(1), p.get(1)) 872 self.random = p.getFixBytes(32) 873 self.session_id = p.getVarBytes(1) 874 self.cipher_suite = p.get(2) 875 self.compression_method = p.get(1) 876 if not p.atLengthCheck(): 877 self.extensions = [] 878 totalExtLength = p.get(2) 879 p2 = Parser(p.getFixBytes(totalExtLength)) 880 while p2.getRemainingLength() > 0: 881 ext = TLSExtension(server=True).parse(p2) 882 self.extensions += [ext] 883 p.stopLengthCheck() 884 return self
885
886 - def write(self):
887 w = Writer() 888 w.add(self.server_version[0], 1) 889 w.add(self.server_version[1], 1) 890 w.addFixSeq(self.random, 1) 891 w.addVarSeq(self.session_id, 1, 1) 892 w.add(self.cipher_suite, 2) 893 w.add(self.compression_method, 1) 894 895 if not self.extensions is None: 896 w2 = Writer() 897 for ext in self.extensions: 898 w2.bytes += ext.write() 899 900 if self.tackExt: 901 b = self.tackExt.serialize() 902 w2.add(ExtensionType.tack, 2) 903 w2.add(len(b), 2) 904 w2.bytes += b 905 906 w.add(len(w2.bytes), 2) 907 w.bytes += w2.bytes 908 return self.postWrite(w)
909
910 -class ServerHello2(HandshakeMsg):
911 """ 912 SERVER-HELLO message from SSLv2 913 914 @type session_id_hit: int 915 @ivar session_id_hit: non zero if the client provided session ID was 916 matched in server's session cache 917 918 @type certificate_type: int 919 @ivar certificate_type: type of certificate sent 920 921 @type server_version: tuple of ints 922 @ivar server_version: protocol version selected by server 923 924 @type certificate: bytearray 925 @ivar certificate: certificate sent by server 926 927 @type ciphers: array of int 928 @ivar ciphers: list of ciphers supported by server 929 930 @type session_id: bytearray 931 @ivar session_id: idendifier of negotiated session 932 """ 933
934 - def __init__(self):
935 super(ServerHello2, self).__init__(SSL2HandshakeType.server_hello) 936 self.session_id_hit = 0 937 self.certificate_type = 0 938 self.server_version = (0, 0) 939 self.certificate = bytearray(0) 940 self.ciphers = [] 941 self.session_id = bytearray(0)
942
943 - def create(self, session_id_hit, certificate_type, server_version, 944 certificate, ciphers, session_id):
945 """Initialize fields of the SERVER-HELLO message""" 946 self.session_id_hit = session_id_hit 947 self.certificate_type = certificate_type 948 self.server_version = server_version 949 self.certificate = certificate 950 self.ciphers = ciphers 951 self.session_id = session_id 952 return self
953
954 - def write(self):
955 """Serialise object to on the wire data""" 956 writer = Writer() 957 writer.add(self.handshakeType, 1) 958 writer.add(self.session_id_hit, 1) 959 writer.add(self.certificate_type, 1) 960 if len(self.server_version) != 2: 961 raise ValueError("server version must be a 2-element tuple") 962 writer.addFixSeq(self.server_version, 1) 963 writer.add(len(self.certificate), 2) 964 965 ciphersWriter = Writer() 966 ciphersWriter.addFixSeq(self.ciphers, 3) 967 968 writer.add(len(ciphersWriter.bytes), 2) 969 writer.add(len(self.session_id), 2) 970 971 writer.bytes += self.certificate 972 writer.bytes += ciphersWriter.bytes 973 writer.bytes += self.session_id 974 975 # postWrite() is necessary only for SSLv3/TLS 976 return writer.bytes
977
978 - def parse(self, parser):
979 """Deserialise object from on the wire data""" 980 self.session_id_hit = parser.get(1) 981 self.certificate_type = parser.get(1) 982 self.server_version = (parser.get(1), parser.get(1)) 983 certificateLength = parser.get(2) 984 ciphersLength = parser.get(2) 985 sessionIDLength = parser.get(2) 986 parser.setLengthCheck(certificateLength + 987 ciphersLength + 988 sessionIDLength) 989 self.certificate = parser.getFixBytes(certificateLength) 990 self.ciphers = parser.getFixList(3, ciphersLength // 3) 991 self.session_id = parser.getFixBytes(sessionIDLength) 992 parser.stopLengthCheck() 993 return self
994
995 -class Certificate(HandshakeMsg):
996 - def __init__(self, certificateType):
997 HandshakeMsg.__init__(self, HandshakeType.certificate) 998 self.certificateType = certificateType 999 self.certChain = None
1000
1001 - def create(self, certChain):
1002 self.certChain = certChain 1003 return self
1004
1005 - def parse(self, p):
1006 p.startLengthCheck(3) 1007 if self.certificateType == CertificateType.x509: 1008 chainLength = p.get(3) 1009 index = 0 1010 certificate_list = [] 1011 while index != chainLength: 1012 certBytes = p.getVarBytes(3) 1013 x509 = X509() 1014 x509.parseBinary(certBytes) 1015 certificate_list.append(x509) 1016 index += len(certBytes)+3 1017 if certificate_list: 1018 self.certChain = X509CertChain(certificate_list) 1019 else: 1020 raise AssertionError() 1021 1022 p.stopLengthCheck() 1023 return self
1024
1025 - def write(self):
1026 w = Writer() 1027 if self.certificateType == CertificateType.x509: 1028 chainLength = 0 1029 if self.certChain: 1030 certificate_list = self.certChain.x509List 1031 else: 1032 certificate_list = [] 1033 #determine length 1034 for cert in certificate_list: 1035 bytes = cert.writeBytes() 1036 chainLength += len(bytes)+3 1037 #add bytes 1038 w.add(chainLength, 3) 1039 for cert in certificate_list: 1040 bytes = cert.writeBytes() 1041 w.addVarSeq(bytes, 1, 3) 1042 else: 1043 raise AssertionError() 1044 return self.postWrite(w)
1045
1046 -class CertificateRequest(HandshakeMsg):
1047 - def __init__(self, version):
1048 HandshakeMsg.__init__(self, HandshakeType.certificate_request) 1049 self.certificate_types = [] 1050 self.certificate_authorities = [] 1051 self.version = version 1052 self.supported_signature_algs = []
1053
1054 - def create(self, certificate_types, certificate_authorities, sig_algs=()):
1055 self.certificate_types = certificate_types 1056 self.certificate_authorities = certificate_authorities 1057 self.supported_signature_algs = sig_algs 1058 return self
1059
1060 - def parse(self, p):
1061 p.startLengthCheck(3) 1062 self.certificate_types = p.getVarList(1, 1) 1063 if self.version >= (3,3): 1064 self.supported_signature_algs = p.getVarTupleList(1, 2, 2) 1065 ca_list_length = p.get(2) 1066 index = 0 1067 self.certificate_authorities = [] 1068 while index != ca_list_length: 1069 ca_bytes = p.getVarBytes(2) 1070 self.certificate_authorities.append(ca_bytes) 1071 index += len(ca_bytes)+2 1072 p.stopLengthCheck() 1073 return self
1074
1075 - def write(self):
1076 w = Writer() 1077 w.addVarSeq(self.certificate_types, 1, 1) 1078 if self.version >= (3,3): 1079 w.addVarTupleSeq(self.supported_signature_algs, 1, 2) 1080 caLength = 0 1081 #determine length 1082 for ca_dn in self.certificate_authorities: 1083 caLength += len(ca_dn)+2 1084 w.add(caLength, 2) 1085 #add bytes 1086 for ca_dn in self.certificate_authorities: 1087 w.addVarSeq(ca_dn, 1, 2) 1088 return self.postWrite(w)
1089
1090 -class ServerKeyExchange(HandshakeMsg):
1091 1092 """ 1093 Handling TLS Handshake protocol Server Key Exchange messages 1094 1095 @type cipherSuite: int 1096 @cvar cipherSuite: id of ciphersuite selected in Server Hello message 1097 @type srp_N: int 1098 @cvar srp_N: SRP protocol prime 1099 @type srp_g: int 1100 @cvar srp_g: SRP protocol generator 1101 @type srp_s: bytearray 1102 @cvar srp_s: SRP protocol salt value 1103 @type srp_B: int 1104 @cvar srp_B: SRP protocol server public value 1105 @type dh_p: int 1106 @cvar dh_p: FFDHE protocol prime 1107 @type dh_g: int 1108 @cvar dh_g: FFDHE protocol generator 1109 @type dh_Ys: int 1110 @cvar dh_Ys: FFDH protocol server key share 1111 @type curve_type: int 1112 @cvar curve_type: Type of curve used (explicit, named, etc.) 1113 @type named_curve: int 1114 @cvar named_curve: TLS ID of named curve 1115 @type ecdh_Ys: bytearray 1116 @cvar ecdh_Ys: ECDH protocol encoded point key share 1117 @type signature: bytearray 1118 @cvar signature: signature performed over the parameters by server 1119 @type hashAlg: int 1120 @cvar hashAlg: id of hash algorithm used for signature 1121 @type signAlg: int 1122 @cvar signAlg: id of signature algorithm used for signature 1123 """ 1124
1125 - def __init__(self, cipherSuite, version):
1126 """ 1127 Initialise Server Key Exchange for reading or writing 1128 1129 @type cipherSuite: int 1130 @param cipherSuite: id of ciphersuite selected by server 1131 """ 1132 HandshakeMsg.__init__(self, HandshakeType.server_key_exchange) 1133 self.cipherSuite = cipherSuite 1134 self.version = version 1135 self.srp_N = 0 1136 self.srp_g = 0 1137 self.srp_s = bytearray(0) 1138 self.srp_B = 0 1139 # Anon DH params: 1140 self.dh_p = 0 1141 self.dh_g = 0 1142 self.dh_Ys = 0 1143 # EC settings 1144 self.curve_type = None 1145 self.named_curve = None 1146 self.ecdh_Ys = bytearray(0) 1147 # signature for certificate authenticated ciphersuites 1148 self.signature = bytearray(0) 1149 # signature hash algorithm and signing algorithm for TLSv1.2 1150 self.hashAlg = 0 1151 self.signAlg = 0
1152
1153 - def __repr__(self):
1154 1155 ret = "ServerKeyExchange(cipherSuite=CipherSuite.{0}, version={1}"\ 1156 "".format(CipherSuite.ietfNames[self.cipherSuite], self.version) 1157 1158 if self.srp_N != 0: 1159 ret += ", srp_N={0}, srp_g={1}, srp_s={2!r}, srp_B={3}".format(\ 1160 self.srp_N, self.srp_g, self.srp_s, self.srp_B) 1161 if self.dh_p != 0: 1162 ret += ", dh_p={0}, dh_g={1}, dh_Ys={2}".format(\ 1163 self.dh_p, self.dh_g, self.dh_Ys) 1164 if self.signAlg != 0: 1165 ret += ", hashAlg={0}, signAlg={1}".format(\ 1166 self.hashAlg, self.signAlg) 1167 if self.signature != bytearray(0): 1168 ret += ", signature={0!r}".format(self.signature) 1169 ret += ")" 1170 1171 return ret
1172 1173
1174 - def createSRP(self, srp_N, srp_g, srp_s, srp_B):
1175 """Set SRP protocol parameters""" 1176 self.srp_N = srp_N 1177 self.srp_g = srp_g 1178 self.srp_s = srp_s 1179 self.srp_B = srp_B 1180 return self
1181
1182 - def createDH(self, dh_p, dh_g, dh_Ys):
1183 """Set FFDH protocol parameters""" 1184 self.dh_p = dh_p 1185 self.dh_g = dh_g 1186 self.dh_Ys = dh_Ys 1187 return self
1188
1189 - def createECDH(self, curve_type, named_curve=None, point=None):
1190 """Set ECDH protocol parameters""" 1191 self.curve_type = curve_type 1192 self.named_curve = named_curve 1193 self.ecdh_Ys = point
1194
1195 - def parse(self, parser):
1196 """Deserialise message from L{Parser} 1197 1198 @type parser: L{Parser} 1199 @param parser: parser to read data from 1200 """ 1201 parser.startLengthCheck(3) 1202 if self.cipherSuite in CipherSuite.srpAllSuites: 1203 self.srp_N = bytesToNumber(parser.getVarBytes(2)) 1204 self.srp_g = bytesToNumber(parser.getVarBytes(2)) 1205 self.srp_s = parser.getVarBytes(1) 1206 self.srp_B = bytesToNumber(parser.getVarBytes(2)) 1207 elif self.cipherSuite in CipherSuite.dhAllSuites: 1208 self.dh_p = bytesToNumber(parser.getVarBytes(2)) 1209 self.dh_g = bytesToNumber(parser.getVarBytes(2)) 1210 self.dh_Ys = bytesToNumber(parser.getVarBytes(2)) 1211 elif self.cipherSuite in CipherSuite.ecdhAllSuites: 1212 self.curve_type = parser.get(1) 1213 # only named curves supported 1214 assert self.curve_type == 3 1215 self.named_curve = parser.get(2) 1216 self.ecdh_Ys = parser.getVarBytes(1) 1217 else: 1218 raise AssertionError() 1219 1220 if self.cipherSuite in CipherSuite.certAllSuites: 1221 if self.version == (3, 3): 1222 self.hashAlg = parser.get(1) 1223 self.signAlg = parser.get(1) 1224 self.signature = parser.getVarBytes(2) 1225 1226 parser.stopLengthCheck() 1227 return self
1228
1229 - def writeParams(self):
1230 """Serialise the key exchange parameters 1231 1232 @rtype: bytearray 1233 """ 1234 writer = Writer() 1235 if self.cipherSuite in CipherSuite.srpAllSuites: 1236 writer.addVarSeq(numberToByteArray(self.srp_N), 1, 2) 1237 writer.addVarSeq(numberToByteArray(self.srp_g), 1, 2) 1238 writer.addVarSeq(self.srp_s, 1, 1) 1239 writer.addVarSeq(numberToByteArray(self.srp_B), 1, 2) 1240 elif self.cipherSuite in CipherSuite.dhAllSuites: 1241 writer.addVarSeq(numberToByteArray(self.dh_p), 1, 2) 1242 writer.addVarSeq(numberToByteArray(self.dh_g), 1, 2) 1243 writer.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2) 1244 elif self.cipherSuite in CipherSuite.ecdhAllSuites: 1245 writer.add(self.curve_type, 1) 1246 assert self.curve_type == 3 1247 writer.add(self.named_curve, 2) 1248 writer.addVarSeq(self.ecdh_Ys, 1, 1) 1249 else: 1250 assert(False) 1251 return writer.bytes
1252
1253 - def write(self):
1254 """ 1255 Serialise complete message 1256 1257 @rtype: bytearray 1258 """ 1259 writer = Writer() 1260 writer.bytes += self.writeParams() 1261 if self.cipherSuite in CipherSuite.certAllSuites: 1262 if self.version >= (3, 3): 1263 assert self.hashAlg != 0 and self.signAlg != 0 1264 writer.add(self.hashAlg, 1) 1265 writer.add(self.signAlg, 1) 1266 writer.addVarSeq(self.signature, 1, 2) 1267 return self.postWrite(writer)
1268
1269 - def hash(self, clientRandom, serverRandom):
1270 """ 1271 Calculate hash of parameters to sign 1272 1273 @rtype: bytearray 1274 """ 1275 bytesToHash = clientRandom + serverRandom + self.writeParams() 1276 if self.version >= (3, 3): 1277 hashAlg = HashAlgorithm.toRepr(self.hashAlg) 1278 if hashAlg is None: 1279 raise AssertionError("Unknown hash algorithm: {0}".\ 1280 format(self.hashAlg)) 1281 return secureHash(bytesToHash, hashAlg) 1282 return MD5(bytesToHash) + SHA1(bytesToHash)
1283
1284 -class ServerHelloDone(HandshakeMsg):
1285 - def __init__(self):
1287
1288 - def create(self):
1289 return self
1290
1291 - def parse(self, p):
1292 p.startLengthCheck(3) 1293 p.stopLengthCheck() 1294 return self
1295
1296 - def write(self):
1297 w = Writer() 1298 return self.postWrite(w)
1299
1300 - def __repr__(self):
1301 """Human readable representation of object""" 1302 return "ServerHelloDone()"
1303
1304 -class ClientKeyExchange(HandshakeMsg):
1305 1306 """ 1307 Handling of TLS Handshake protocol ClientKeyExchange message 1308 1309 @type cipherSuite: int 1310 @ivar cipherSuite: the cipher suite id used for the connection 1311 @type version: tuple(int, int) 1312 @ivar version: TLS protocol version used for the connection 1313 @type srp_A: int 1314 @ivar srp_A: SRP protocol client answer value 1315 @type dh_Yc: int 1316 @ivar dh_Yc: client Finite Field Diffie-Hellman protocol key share 1317 @type ecdh_Yc: bytearray 1318 @ivar ecdh_Yc: encoded curve coordinates 1319 @type encryptedPreMasterSecret: bytearray 1320 @ivar encryptedPreMasterSecret: client selected PremMaster secret encrypted 1321 with server public key (from certificate) 1322 """ 1323
1324 - def __init__(self, cipherSuite, version=None):
1325 """ 1326 Initialise ClientKeyExchange for reading or writing 1327 1328 @type cipherSuite: int 1329 @param cipherSuite: id of the ciphersuite selected by server 1330 @type version: tuple(int, int) 1331 @param version: protocol version selected by server 1332 """ 1333 HandshakeMsg.__init__(self, HandshakeType.client_key_exchange) 1334 self.cipherSuite = cipherSuite 1335 self.version = version 1336 self.srp_A = 0 1337 self.dh_Yc = 0 1338 self.ecdh_Yc = bytearray(0) 1339 self.encryptedPreMasterSecret = bytearray(0)
1340
1341 - def createSRP(self, srp_A):
1342 """ 1343 Set the SRP client answer 1344 1345 returns self 1346 1347 @type srp_A: int 1348 @param srp_A: client SRP answer 1349 @rtype: L{ClientKeyExchange} 1350 """ 1351 self.srp_A = srp_A 1352 return self
1353
1354 - def createRSA(self, encryptedPreMasterSecret):
1355 """ 1356 Set the encrypted PreMaster Secret 1357 1358 returns self 1359 1360 @type encryptedPreMasterSecret: bytearray 1361 @rtype: L{ClientKeyExchange} 1362 """ 1363 self.encryptedPreMasterSecret = encryptedPreMasterSecret 1364 return self
1365
1366 - def createDH(self, dh_Yc):
1367 """ 1368 Set the client FFDH key share 1369 1370 returns self 1371 1372 @type dh_Yc: int 1373 @rtype: L{ClientKeyExchange} 1374 """ 1375 self.dh_Yc = dh_Yc 1376 return self
1377
1378 - def createECDH(self, ecdh_Yc):
1379 """ 1380 Set the client ECDH key share 1381 1382 returns self 1383 1384 @type ecdh_Yc: bytearray 1385 @rtype: L{ClientKeyExchange} 1386 """ 1387 self.ecdh_Yc = ecdh_Yc 1388 return self
1389
1390 - def parse(self, parser):
1391 """ 1392 Deserialise the message from L{Parser} 1393 1394 returns self 1395 1396 @type parser: L{Parser} 1397 @rtype: L{ClientKeyExchange} 1398 """ 1399 parser.startLengthCheck(3) 1400 if self.cipherSuite in CipherSuite.srpAllSuites: 1401 self.srp_A = bytesToNumber(parser.getVarBytes(2)) 1402 elif self.cipherSuite in CipherSuite.certSuites: 1403 if self.version in ((3,1), (3,2), (3,3)): 1404 self.encryptedPreMasterSecret = parser.getVarBytes(2) 1405 elif self.version == (3,0): 1406 self.encryptedPreMasterSecret = \ 1407 parser.getFixBytes(parser.getRemainingLength()) 1408 else: 1409 raise AssertionError() 1410 elif self.cipherSuite in CipherSuite.dhAllSuites: 1411 self.dh_Yc = bytesToNumber(parser.getVarBytes(2)) 1412 elif self.cipherSuite in CipherSuite.ecdhAllSuites: 1413 self.ecdh_Yc = parser.getVarBytes(1) 1414 else: 1415 raise AssertionError() 1416 parser.stopLengthCheck() 1417 return self
1418
1419 - def write(self):
1420 """ 1421 Serialise the object 1422 1423 @rtype: bytearray 1424 """ 1425 w = Writer() 1426 if self.cipherSuite in CipherSuite.srpAllSuites: 1427 w.addVarSeq(numberToByteArray(self.srp_A), 1, 2) 1428 elif self.cipherSuite in CipherSuite.certSuites: 1429 if self.version in ((3,1), (3,2), (3,3)): 1430 w.addVarSeq(self.encryptedPreMasterSecret, 1, 2) 1431 elif self.version == (3,0): 1432 w.addFixSeq(self.encryptedPreMasterSecret, 1) 1433 else: 1434 raise AssertionError() 1435 elif self.cipherSuite in CipherSuite.dhAllSuites: 1436 w.addVarSeq(numberToByteArray(self.dh_Yc), 1, 2) 1437 elif self.cipherSuite in CipherSuite.ecdhAllSuites: 1438 w.addVarSeq(self.ecdh_Yc, 1, 1) 1439 else: 1440 raise AssertionError() 1441 return self.postWrite(w)
1442
1443 -class ClientMasterKey(HandshakeMsg):
1444 """ 1445 Handling of SSLv2 CLIENT-MASTER-KEY message 1446 1447 @type cipher: int 1448 @ivar cipher: negotiated cipher 1449 1450 @type clear_key: bytearray 1451 @ivar clear_key: the part of master secret key that is sent in clear for 1452 export cipher suites 1453 1454 @type encrypted_key: bytearray 1455 @ivar encrypted_key: (part of) master secret encrypted using server key 1456 1457 @type key_argument: bytearray 1458 @ivar key_argument: additional key argument for block ciphers 1459 """ 1460
1461 - def __init__(self):
1462 super(ClientMasterKey, 1463 self).__init__(SSL2HandshakeType.client_master_key) 1464 self.cipher = 0 1465 self.clear_key = bytearray(0) 1466 self.encrypted_key = bytearray(0) 1467 self.key_argument = bytearray(0)
1468
1469 - def create(self, cipher, clear_key, encrypted_key, key_argument):
1470 """Set values of the CLIENT-MASTER-KEY object""" 1471 self.cipher = cipher 1472 self.clear_key = clear_key 1473 self.encrypted_key = encrypted_key 1474 self.key_argument = key_argument 1475 return self
1476
1477 - def write(self):
1478 """Serialise the object to on the wire data""" 1479 writer = Writer() 1480 writer.add(self.handshakeType, 1) 1481 writer.add(self.cipher, 3) 1482 writer.add(len(self.clear_key), 2) 1483 writer.add(len(self.encrypted_key), 2) 1484 writer.add(len(self.key_argument), 2) 1485 writer.bytes += self.clear_key 1486 writer.bytes += self.encrypted_key 1487 writer.bytes += self.key_argument 1488 return writer.bytes
1489
1490 - def parse(self, parser):
1491 """Deserialise object from on the wire data""" 1492 self.cipher = parser.get(3) 1493 clear_key_length = parser.get(2) 1494 encrypted_key_length = parser.get(2) 1495 key_argument_length = parser.get(2) 1496 parser.setLengthCheck(clear_key_length + 1497 encrypted_key_length + 1498 key_argument_length) 1499 self.clear_key = parser.getFixBytes(clear_key_length) 1500 self.encrypted_key = parser.getFixBytes(encrypted_key_length) 1501 self.key_argument = parser.getFixBytes(key_argument_length) 1502 parser.stopLengthCheck() 1503 return self
1504
1505 -class CertificateVerify(HandshakeMsg):
1506 1507 """Serializer for TLS handshake protocol Certificate Verify message""" 1508
1509 - def __init__(self, version):
1510 """Create message 1511 1512 @param version: TLS protocol version in use 1513 """ 1514 HandshakeMsg.__init__(self, HandshakeType.certificate_verify) 1515 self.version = version 1516 self.signatureAlgorithm = None 1517 self.signature = bytearray(0)
1518
1519 - def create(self, signature, signatureAlgorithm=None):
1520 """ 1521 Provide data for serialisation of message 1522 1523 @param signature: signature carried in the message 1524 @param signatureAlgorithm: signature algorithm used to make the 1525 signature (TLSv1.2 only) 1526 """ 1527 self.signatureAlgorithm = signatureAlgorithm 1528 self.signature = signature 1529 return self
1530
1531 - def parse(self, parser):
1532 """ 1533 Deserialize message from parser 1534 1535 @param parser: parser with data to read 1536 """ 1537 parser.startLengthCheck(3) 1538 if self.version >= (3, 3): 1539 self.signatureAlgorithm = (parser.get(1), parser.get(1)) 1540 self.signature = parser.getVarBytes(2) 1541 parser.stopLengthCheck() 1542 return self
1543
1544 - def write(self):
1545 """ 1546 Serialize the data to bytearray 1547 1548 @rtype: bytearray 1549 """ 1550 writer = Writer() 1551 if self.version >= (3, 3): 1552 writer.add(self.signatureAlgorithm[0], 1) 1553 writer.add(self.signatureAlgorithm[1], 1) 1554 writer.addVarSeq(self.signature, 1, 2) 1555 return self.postWrite(writer)
1556
1557 -class ChangeCipherSpec(object):
1558 - def __init__(self):
1559 self.contentType = ContentType.change_cipher_spec 1560 self.type = 1
1561
1562 - def create(self):
1563 self.type = 1 1564 return self
1565
1566 - def parse(self, p):
1567 p.setLengthCheck(1) 1568 self.type = p.get(1) 1569 p.stopLengthCheck() 1570 return self
1571
1572 - def write(self):
1573 w = Writer() 1574 w.add(self.type,1) 1575 return w.bytes
1576
1577 1578 -class NextProtocol(HandshakeMsg):
1579 - def __init__(self):
1580 HandshakeMsg.__init__(self, HandshakeType.next_protocol) 1581 self.next_proto = None
1582
1583 - def create(self, next_proto):
1584 self.next_proto = next_proto 1585 return self
1586
1587 - def parse(self, p):
1588 p.startLengthCheck(3) 1589 self.next_proto = p.getVarBytes(1) 1590 _ = p.getVarBytes(1) 1591 p.stopLengthCheck() 1592 return self
1593
1594 - def write(self, trial=False):
1595 w = Writer() 1596 w.addVarSeq(self.next_proto, 1, 1) 1597 paddingLen = 32 - ((len(self.next_proto) + 2) % 32) 1598 w.addVarSeq(bytearray(paddingLen), 1, 1) 1599 return self.postWrite(w)
1600
1601 -class Finished(HandshakeMsg):
1602 - def __init__(self, version):
1603 HandshakeMsg.__init__(self, HandshakeType.finished) 1604 self.version = version 1605 self.verify_data = bytearray(0)
1606
1607 - def create(self, verify_data):
1608 self.verify_data = verify_data 1609 return self
1610
1611 - def parse(self, p):
1612 p.startLengthCheck(3) 1613 if self.version == (3,0): 1614 self.verify_data = p.getFixBytes(36) 1615 elif self.version in ((3,1), (3,2), (3,3)): 1616 self.verify_data = p.getFixBytes(12) 1617 else: 1618 raise AssertionError() 1619 p.stopLengthCheck() 1620 return self
1621
1622 - def write(self):
1623 w = Writer() 1624 w.addFixSeq(self.verify_data, 1) 1625 return self.postWrite(w)
1626
1627 1628 -class SSL2Finished(HandshakeMsg):
1629 """Handling of the SSL2 FINISHED messages""" 1630
1631 - def __init__(self, msg_type):
1632 super(SSL2Finished, self).__init__(msg_type) 1633 self.verify_data = bytearray(0)
1634
1635 - def create(self, verify_data):
1636 """Set the message payload""" 1637 self.verify_data = verify_data 1638 return self
1639
1640 - def parse(self, parser):
1641 """Deserialise the message from on the wire data""" 1642 self.verify_data = parser.getFixBytes(parser.getRemainingLength()) 1643 return self
1644
1645 - def write(self):
1646 """Serialise the message to on the wire data""" 1647 writer = Writer() 1648 writer.add(self.handshakeType, 1) 1649 writer.addFixSeq(self.verify_data, 1) 1650 # does not use postWrite() as it's a SSLv2 message 1651 return writer.bytes
1652
1653 1654 -class ClientFinished(SSL2Finished):
1655 """ 1656 Handling of SSLv2 CLIENT-FINISHED message 1657 1658 @type verify_data: bytearray 1659 @ivar verify_data: payload of the message, should be the CONNECTION-ID 1660 """ 1661
1662 - def __init__(self):
1664
1665 1666 -class ServerFinished(SSL2Finished):
1667 """ 1668 Handling of SSLv2 SERVER-FINISHED message 1669 1670 @type verify_data: bytearray 1671 @ivar verify_data: payload of the message, should be SESSION-ID 1672 """ 1673
1674 - def __init__(self):
1676
1677 1678 -class ApplicationData(object):
1679 - def __init__(self):
1680 self.contentType = ContentType.application_data 1681 self.bytes = bytearray(0)
1682
1683 - def create(self, bytes):
1684 self.bytes = bytes 1685 return self
1686
1687 - def splitFirstByte(self):
1688 newMsg = ApplicationData().create(self.bytes[:1]) 1689 self.bytes = self.bytes[1:] 1690 return newMsg
1691
1692 - def parse(self, p):
1693 self.bytes = p.bytes 1694 return self
1695
1696 - def write(self):
1697 return self.bytes
1698