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