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

Source Code for Module tlslite.extensions

   1  # Copyright (c) 2014, 2015 Hubert Kario 
   2  # 
   3  # See the LICENSE file for legal information regarding use of this file. 
   4   
   5  """ Helper package for handling TLS extensions encountered in ClientHello 
   6  and ServerHello messages. 
   7  """ 
   8   
   9  from __future__ import generators 
  10  from .utils.codec import Writer, Parser 
  11  from collections import namedtuple 
  12  from .constants import NameType, ExtensionType 
  13  from .errors import TLSInternalError 
14 15 -class TLSExtension(object):
16 """ 17 Base class for handling handshake protocol hello messages extensions. 18 19 This class handles the generic information about TLS extensions used by 20 both sides of connection in Client Hello and Server Hello messages. 21 See U{RFC 4366<https://tools.ietf.org/html/rfc4366>} for more info. 22 23 It is used as a base class for specific users and as a way to store 24 extensions that are not implemented in library. 25 26 To implement a new extension you will need to create a new class which 27 calls this class contructor (__init__), usually specifying just the 28 extType parameter. The other methods which need to be implemented are: 29 L{extData}, L{create}, L{parse} and L{__repr__}. If the parser can be used 30 for client and optionally server extensions, the extension constructor 31 should be added to L{_universalExtensions}. Otherwise, when the client and 32 server extensions have completely different forms, you should add client 33 form to the L{_universalExtensions} and the server form to 34 L{_serverExtensions}. Since the server MUST NOT send extensions not 35 advertised by client, there are no purely server-side extensions. But 36 if the client side extension is just marked by presence and has no payload, 37 the client side (thus the L{_universalExtensions} may be skipped, then 38 the L{TLSExtension} class will be used for implementing it. See 39 end of the file for type-to-constructor bindings. 40 41 Though please note that subclassing for the purpose of parsing extensions 42 is not an officially supported part of API (just as underscores in their 43 names would indicate. 44 45 @type extType: int 46 @ivar extType: a 2^16-1 limited integer specifying the type of the 47 extension that it contains, e.g. 0 indicates server name extension 48 49 @type extData: bytearray 50 @ivar extData: a byte array containing the value of the extension as 51 to be written on the wire 52 53 @type serverType: boolean 54 @ivar serverType: indicates that the extension was parsed with ServerHello 55 specific parser, otherwise it used universal or ClientHello specific 56 parser 57 58 @type _universalExtensions: dict 59 @cvar _universalExtensions: dictionary with concrete implementations of 60 specific TLS extensions where key is the numeric value of the extension 61 ID. Contains ClientHello version of extensions or universal 62 implementations 63 64 @type _serverExtensions: dict 65 @cvar _serverExtensions: dictionary with concrete implementations of 66 specific TLS extensions where key is the numeric value of the extension 67 ID. Includes only those extensions that require special handlers for 68 ServerHello versions. 69 """ 70 # actual definition at the end of file, after definitions of all classes 71 _universalExtensions = {} 72 _serverExtensions = {} 73
74 - def __init__(self, server=False, extType=None):
75 """ 76 Creates a generic TLS extension. 77 78 You'll need to use L{create} or L{parse} methods to create an extension 79 that is actually usable. 80 81 @type server: boolean 82 @param server: whether to select ClientHello or ServerHello version 83 for parsing 84 @type extType: int 85 @param extType: type of extension encoded as an integer, to be used 86 by subclasses 87 """ 88 self.extType = extType 89 self._extData = bytearray(0) 90 self.serverType = server
91 92 @property
93 - def extData(self):
94 """ 95 Return the on the wire encoding of extension 96 97 Child classes need to override this property so that it returns just 98 the payload of an extension, that is, without the 4 byte generic header 99 common to all extension. In other words, without the extension ID and 100 overall extension length. 101 102 @rtype: bytearray 103 """ 104 return self._extData
105
106 - def _oldCreate(self, extType, data):
107 """Legacy handling of create method""" 108 self.extType = extType 109 self._extData = data
110
111 - def _newCreate(self, data):
112 """New format for create method""" 113 self._extData = data
114
115 - def create(self, *args, **kwargs):
116 """ 117 Initializes a generic TLS extension. 118 119 The extension can carry arbitrary data and have arbitrary payload, can 120 be used in client hello or server hello messages. 121 122 The legacy calling method uses two arguments - the extType and data. 123 If the new calling method is used, only one argument is passed in - 124 data. 125 126 Child classes need to override this method so that it is possible 127 to set values for all fields used by the extension. 128 129 @type extType: int 130 @param extType: if int: type of the extension encoded as an integer 131 between M{0} and M{2^16-1} 132 @type data: bytearray 133 @param data: raw data representing extension on the wire 134 @rtype: L{TLSExtension} 135 """ 136 # old style 137 if len(args) + len(kwargs) == 2: 138 self._oldCreate(*args, **kwargs) 139 # new style 140 elif len(args) + len(kwargs) == 1: 141 self._newCreate(*args, **kwargs) 142 else: 143 raise TypeError("Invalid number of arguments") 144 145 return self
146
147 - def write(self):
148 """Returns encoded extension, as encoded on the wire 149 150 Note that child classes in general don't need to override this method. 151 152 @rtype: bytearray 153 @return: An array of bytes formatted as is supposed to be written on 154 the wire, including the extension_type, length and the extension 155 data 156 157 @raise AssertionError: when the object was not initialized 158 """ 159 assert self.extType is not None 160 161 w = Writer() 162 w.add(self.extType, 2) 163 w.add(len(self.extData), 2) 164 w.addFixSeq(self.extData, 1) 165 return w.bytes
166 167 @staticmethod
168 - def _parseExt(parser, extType, extLength, extList):
169 """Parse a extension using a predefined constructor""" 170 ext = extList[extType]() 171 extParser = Parser(parser.getFixBytes(extLength)) 172 ext = ext.parse(extParser) 173 return ext
174
175 - def parse(self, p):
176 """Parses extension from on the wire format 177 178 Child classes should override this method so that it parses the 179 extension from on the wire data. Note that child class parsers will 180 not receive the generic header of the extension, but just a parser 181 with the payload. In other words, the method should be the exact 182 reverse of the L{extData} property. 183 184 @type p: L{tlslite.util.codec.Parser} 185 @param p: data to be parsed 186 187 @raise SyntaxError: when the size of the passed element doesn't match 188 the internal representation 189 190 @rtype: L{TLSExtension} 191 """ 192 extType = p.get(2) 193 extLength = p.get(2) 194 195 # first check if we shouldn't use server side parser 196 if self.serverType and extType in self._serverExtensions: 197 return self._parseExt(p, extType, extLength, 198 self._serverExtensions) 199 200 # then fallback to universal/ClientHello-specific parsers 201 if extType in self._universalExtensions: 202 return self._parseExt(p, extType, extLength, 203 self._universalExtensions) 204 205 # finally, just save the extension data as there are extensions which 206 # don't require specific handlers and indicate option by mere presence 207 self.extType = extType 208 self._extData = p.getFixBytes(extLength) 209 assert len(self._extData) == extLength 210 return self
211
212 - def __eq__(self, that):
213 """Test if two TLS extensions are effectively the same 214 215 Will check if encoding them will result in the same on the wire 216 representation. 217 218 Will return False for every object that's not an extension. 219 """ 220 if hasattr(that, 'extType') and hasattr(that, 'extData'): 221 return self.extType == that.extType and \ 222 self.extData == that.extData 223 else: 224 return False
225
226 - def __repr__(self):
227 """Output human readable representation of object 228 229 Child classes should override this method to support more appropriate 230 string rendering of the extension. 231 232 @rtype: str 233 """ 234 return "TLSExtension(extType={0!r}, extData={1!r},"\ 235 " serverType={2!r})".format(self.extType, self.extData, 236 self.serverType)
237
238 -class VarListExtension(TLSExtension):
239 """ 240 Abstract extension for handling extensions comprised only of a value list 241 242 Extension for handling arbitrary extensions comprising of just a list 243 of same-sized elementes inside an array 244 """ 245
246 - def __init__(self, elemLength, lengthLength, fieldName, extType):
247 super(VarListExtension, self).__init__(extType=extType) 248 self._fieldName = fieldName 249 self._internalList = None 250 self._elemLength = elemLength 251 self._lengthLength = lengthLength
252 253 @property
254 - def extData(self):
255 """Return raw data encoding of the extension 256 257 @rtype: bytearray 258 """ 259 if self._internalList is None: 260 return bytearray(0) 261 262 writer = Writer() 263 writer.addVarSeq(self._internalList, 264 self._elemLength, 265 self._lengthLength) 266 return writer.bytes
267
268 - def create(self, values):
269 """Set the list to specified values 270 271 @type values: list of int 272 @param values: list of values to save 273 """ 274 self._internalList = values 275 return self
276
277 - def parse(self, parser):
278 """ 279 Deserialise extension from on-the-wire data 280 281 @type parser: L{Parser} 282 @rtype: Extension 283 """ 284 if parser.getRemainingLength() == 0: 285 self._internalList = None 286 return self 287 288 self._internalList = parser.getVarList(self._elemLength, 289 self._lengthLength) 290 return self
291
292 - def __getattr__(self, name):
293 """Return the special field name value""" 294 if name == '_fieldName': 295 raise AttributeError("type object '{0}' has no attribute '{1}'"\ 296 .format(self.__class__.__name__, name)) 297 if name == self._fieldName: 298 return self._internalList 299 raise AttributeError("type object '{0}' has no attribute '{1}'"\ 300 .format(self.__class__.__name__, name))
301
302 - def __setattr__(self, name, value):
303 """Set the special field value""" 304 if name == '_fieldName': 305 super(VarListExtension, self).__setattr__(name, value) 306 return 307 if hasattr(self, '_fieldName') and name == self._fieldName: 308 self._internalList = value 309 return 310 super(VarListExtension, self).__setattr__(name, value)
311
312 - def __repr__(self):
313 return "{0}({1}={2!r})".format(self.__class__.__name__, 314 self._fieldName, 315 self._internalList)
316
317 -class SNIExtension(TLSExtension):
318 """ 319 Class for handling Server Name Indication (server_name) extension from 320 RFC 4366. 321 322 Note that while usually the client does advertise just one name, it is 323 possible to provide a list of names, each of different type. 324 The type is a single byte value (represented by ints), the names are 325 opaque byte strings, in case of DNS host names (records of type 0) they 326 are UTF-8 encoded domain names (without the ending dot). 327 328 @type hostNames: tuple of bytearrays 329 @ivar hostNames: tuple of hostnames (server name records of type 0) 330 advertised in the extension. Note that it may not include all names 331 from client hello as the client can advertise other types. Also note 332 that while it's not possible to change the returned array in place, it 333 is possible to assign a new set of names. IOW, this won't work:: 334 335 sni_extension.hostNames[0] = bytearray(b'example.com') 336 337 while this will work:: 338 339 names = list(sni_extension.hostNames) 340 names[0] = bytearray(b'example.com') 341 sni_extension.hostNames = names 342 343 344 @type serverNames: list of L{ServerName} 345 @ivar serverNames: list of all names advertised in extension. 346 L{ServerName} is a namedtuple with two elements, the first 347 element (type) defines the type of the name (encoded as int) 348 while the other (name) is a bytearray that carries the value. 349 Known types are defined in L{tlslite.constants.NameType}. 350 The list will be empty if the on the wire extension had and empty 351 list while it will be None if the extension was empty. 352 353 @type extType: int 354 @ivar extType: numeric type of SNIExtension, i.e. 0 355 356 @type extData: bytearray 357 @ivar extData: raw representation of the extension 358 """ 359 360 ServerName = namedtuple('ServerName', 'name_type name') 361
362 - def __init__(self):
363 """ 364 Create an instance of SNIExtension. 365 366 See also: L{create} and L{parse}. 367 """ 368 super(SNIExtension, self).__init__(extType=ExtensionType.server_name) 369 self.serverNames = None
370
371 - def __repr__(self):
372 """ 373 Return programmer-readable representation of extension 374 375 @rtype: str 376 """ 377 return "SNIExtension(serverNames={0!r})".format(self.serverNames)
378
379 - def create(self, hostname=None, hostNames=None, serverNames=None):
380 """ 381 Initializes an instance with provided hostname, host names or 382 raw server names. 383 384 Any of the parameters may be None, in that case the list inside the 385 extension won't be defined, if either hostNames or serverNames is 386 an empty list, then the extension will define a list of lenght 0. 387 388 If multiple parameters are specified at the same time, then the 389 resulting list of names will be concatenated in order of hostname, 390 hostNames and serverNames last. 391 392 @type hostname: bytearray 393 @param hostname: raw UTF-8 encoding of the host name 394 395 @type hostNames: list of bytearrays 396 @param hostNames: list of raw UTF-8 encoded host names 397 398 @type serverNames: list of L{ServerName} 399 @param serverNames: pairs of name_type and name encoded as a namedtuple 400 401 @rtype: L{SNIExtension} 402 """ 403 if hostname is None and hostNames is None and serverNames is None: 404 self.serverNames = None 405 return self 406 else: 407 self.serverNames = [] 408 409 if hostname: 410 self.serverNames += [SNIExtension.ServerName(NameType.host_name,\ 411 hostname)] 412 413 if hostNames: 414 self.serverNames +=\ 415 [SNIExtension.ServerName(NameType.host_name, x) for x in\ 416 hostNames] 417 418 if serverNames: 419 self.serverNames += serverNames 420 421 return self
422 423 @property
424 - def hostNames(self):
425 """ Returns a simulated list of hostNames from the extension. 426 427 @rtype: tuple of bytearrays 428 """ 429 # because we can't simulate assignments to array elements we return 430 # an immutable type 431 if self.serverNames is None: 432 return tuple() 433 else: 434 return tuple([x.name for x in self.serverNames if \ 435 x.name_type == NameType.host_name])
436 437 @hostNames.setter
438 - def hostNames(self, hostNames):
439 """ Removes all host names from the extension and replaces them by 440 names in X{hostNames} parameter. 441 442 Newly added parameters will be added at the I{beginning} of the list 443 of extensions. 444 445 @type hostNames: iterable of bytearrays 446 @param hostNames: host names to replace the old server names of type 0 447 """ 448 449 self.serverNames = \ 450 [SNIExtension.ServerName(NameType.host_name, x) for x in \ 451 hostNames] + \ 452 [x for x in self.serverNames if \ 453 x.name_type != NameType.host_name]
454 455 @hostNames.deleter
456 - def hostNames(self):
457 """ Remove all host names from extension, leaves other name types 458 unmodified 459 """ 460 self.serverNames = [x for x in self.serverNames if \ 461 x.name_type != NameType.host_name]
462 463 @property
464 - def extData(self):
465 """ raw encoding of extension data, without type and length header 466 467 @rtype: bytearray 468 """ 469 if self.serverNames is None: 470 return bytearray(0) 471 472 w2 = Writer() 473 for server_name in self.serverNames: 474 w2.add(server_name.name_type, 1) 475 w2.add(len(server_name.name), 2) 476 w2.bytes += server_name.name 477 478 # note that when the array is empty we write it as array of length 0 479 w = Writer() 480 w.add(len(w2.bytes), 2) 481 w.bytes += w2.bytes 482 return w.bytes
483
484 - def write(self):
485 """ Returns encoded extension, as encoded on the wire 486 487 @rtype: bytearray 488 @return: an array of bytes formatted as they are supposed to be written 489 on the wire, including the type, length and extension data 490 """ 491 492 raw_data = self.extData 493 494 w = Writer() 495 w.add(self.extType, 2) 496 w.add(len(raw_data), 2) 497 w.bytes += raw_data 498 499 return w.bytes
500
501 - def parse(self, p):
502 """ 503 Deserialise the extension from on-the-wire data 504 505 The parser should not include the type or length of extension! 506 507 @type p: L{tlslite.util.codec.Parser} 508 @param p: data to be parsed 509 510 @rtype: L{SNIExtension} 511 @raise SyntaxError: when the internal sizes don't match the attached 512 data 513 """ 514 if p.getRemainingLength() == 0: 515 return self 516 517 self.serverNames = [] 518 519 p.startLengthCheck(2) 520 while not p.atLengthCheck(): 521 sn_type = p.get(1) 522 sn_name = p.getVarBytes(2) 523 self.serverNames += [SNIExtension.ServerName(sn_type, sn_name)] 524 p.stopLengthCheck() 525 526 return self
527
528 -class ClientCertTypeExtension(VarListExtension):
529 """ 530 This class handles the (client variant of) Certificate Type extension 531 532 See RFC 6091. 533 534 @type extType: int 535 @ivar extType: numeric type of Certificate Type extension, i.e. 9 536 537 @type extData: bytearray 538 @ivar extData: raw representation of the extension data 539 540 @type certTypes: list of int 541 @ivar certTypes: list of certificate type identifiers (each one byte long) 542 """ 543
544 - def __init__(self):
545 """ 546 Create an instance of ClientCertTypeExtension 547 548 See also: L{create} and L{parse} 549 """ 550 super(ClientCertTypeExtension, self).__init__(1, 1, 'certTypes', \ 551 ExtensionType.cert_type)
552
553 -class ServerCertTypeExtension(TLSExtension):
554 """ 555 This class handles the Certificate Type extension (variant sent by server) 556 defined in RFC 6091. 557 558 @type extType: int 559 @ivar extType: binary type of Certificate Type extension, i.e. 9 560 561 @type extData: bytearray 562 @ivar extData: raw representation of the extension data 563 564 @type cert_type: int 565 @ivar cert_type: the certificate type selected by server 566 """ 567
568 - def __init__(self):
569 """ 570 Create an instance of ServerCertTypeExtension 571 572 See also: L{create} and L{parse} 573 """ 574 super(ServerCertTypeExtension, self).__init__(server=True, \ 575 extType=ExtensionType.cert_type) 576 self.cert_type = None
577
578 - def __repr__(self):
579 """ Return programmer-centric description of object 580 581 @rtype: str 582 """ 583 return "ServerCertTypeExtension(cert_type={0!r})".format(self.cert_type)
584 585 @property
586 - def extData(self):
587 """ 588 Return the raw encoding of the extension data 589 590 @rtype: bytearray 591 """ 592 if self.cert_type is None: 593 return bytearray(0) 594 595 w = Writer() 596 w.add(self.cert_type, 1) 597 598 return w.bytes
599
600 - def create(self, val):
601 """Create an instance for sending the extension to client. 602 603 @type val: int 604 @param val: selected type of certificate 605 """ 606 self.cert_type = val 607 return self
608
609 - def parse(self, p):
610 """Parse the extension from on the wire format 611 612 @type p: L{Parser} 613 @param p: parser with data 614 """ 615 self.cert_type = p.get(1) 616 if p.getRemainingLength() > 0: 617 raise SyntaxError() 618 619 return self
620
621 -class SRPExtension(TLSExtension):
622 """ 623 This class handles the Secure Remote Password protocol TLS extension 624 defined in RFC 5054. 625 626 @type extType: int 627 @ivar extType: numeric type of SRPExtension, i.e. 12 628 629 @type extData: bytearray 630 @ivar extData: raw representation of extension data 631 632 @type identity: bytearray 633 @ivar identity: UTF-8 encoding of user name 634 """ 635
636 - def __init__(self):
637 """ 638 Create an instance of SRPExtension 639 640 See also: L{create} and L{parse} 641 """ 642 super(SRPExtension, self).__init__(extType=ExtensionType.srp) 643 644 self.identity = None
645
646 - def __repr__(self):
647 """ 648 Return programmer-centric description of extension 649 650 @rtype: str 651 """ 652 return "SRPExtension(identity={0!r})".format(self.identity)
653 654 @property
655 - def extData(self):
656 """ 657 Return raw data encoding of the extension 658 659 @rtype: bytearray 660 """ 661 662 if self.identity is None: 663 return bytearray(0) 664 665 w = Writer() 666 w.add(len(self.identity), 1) 667 w.addFixSeq(self.identity, 1) 668 669 return w.bytes
670
671 - def create(self, identity=None):
672 """ Create and instance of SRPExtension with specified protocols 673 674 @type identity: bytearray 675 @param identity: UTF-8 encoded identity (user name) to be provided 676 to user. MUST be shorter than 2^8-1. 677 678 @raise ValueError: when the identity lenght is longer than 2^8-1 679 """ 680 681 if identity is None: 682 return self 683 684 if len(identity) >= 2**8: 685 raise ValueError() 686 687 self.identity = identity 688 return self
689
690 - def parse(self, p):
691 """ 692 Parse the extension from on the wire format 693 694 @type p: L{tlslite.util.codec.Parser} 695 @param p: data to be parsed 696 697 @raise SyntaxError: when the data is internally inconsistent 698 699 @rtype: L{SRPExtension} 700 """ 701 702 self.identity = p.getVarBytes(1) 703 704 return self
705
706 -class NPNExtension(TLSExtension):
707 """ 708 This class handles the unofficial Next Protocol Negotiation TLS extension. 709 710 @type protocols: list of bytearrays 711 @ivar protocols: list of protocol names supported by the server 712 713 @type extType: int 714 @ivar extType: numeric type of NPNExtension, i.e. 13172 715 716 @type extData: bytearray 717 @ivar extData: raw representation of extension data 718 """ 719
720 - def __init__(self):
721 """ 722 Create an instance of NPNExtension 723 724 See also: L{create} and L{parse} 725 """ 726 super(NPNExtension, self).__init__(extType=ExtensionType.supports_npn) 727 728 self.protocols = None
729
730 - def __repr__(self):
731 """ 732 Create programmer-readable version of representation 733 734 @rtype: str 735 """ 736 return "NPNExtension(protocols={0!r})".format(self.protocols)
737 738 @property
739 - def extData(self):
740 """ Return the raw data encoding of the extension 741 742 @rtype: bytearray 743 """ 744 if self.protocols is None: 745 return bytearray(0) 746 747 w = Writer() 748 for prot in self.protocols: 749 w.add(len(prot), 1) 750 w.addFixSeq(prot, 1) 751 752 return w.bytes
753
754 - def create(self, protocols=None):
755 """ Create an instance of NPNExtension with specified protocols 756 757 @type protocols: list of bytearray 758 @param protocols: list of protocol names that are supported 759 """ 760 self.protocols = protocols 761 return self
762
763 - def parse(self, p):
764 """ Parse the extension from on the wire format 765 766 @type p: L{tlslite.util.codec.Parser} 767 @param p: data to be parsed 768 769 @raise SyntaxError: when the size of the passed element doesn't match 770 the internal representation 771 772 @rtype: L{NPNExtension} 773 """ 774 self.protocols = [] 775 776 while p.getRemainingLength() > 0: 777 self.protocols += [p.getVarBytes(1)] 778 779 return self
780
781 -class TACKExtension(TLSExtension):
782 """ 783 This class handles the server side TACK extension (see 784 draft-perrin-tls-tack-02). 785 786 @type tacks: list 787 @ivar tacks: list of L{TACK}'s supported by server 788 789 @type activation_flags: int 790 @ivar activation_flags: activation flags for the tacks 791 """ 792
793 - class TACK(object):
794 """ 795 Implementation of the single TACK 796 """
797 - def __init__(self):
798 """ 799 Create a single TACK object 800 """ 801 self.public_key = bytearray(64) 802 self.min_generation = 0 803 self.generation = 0 804 self.expiration = 0 805 self.target_hash = bytearray(32) 806 self.signature = bytearray(64)
807
808 - def __repr__(self):
809 """ 810 Return programmmer readable representation of TACK object 811 812 @rtype: str 813 """ 814 return "TACK(public_key={0!r}, min_generation={1!r}, "\ 815 "generation={2!r}, expiration={3!r}, target_hash={4!r}, "\ 816 "signature={5!r})".format( 817 self.public_key, self.min_generation, 818 self.generation, self.expiration, self.target_hash, 819 self.signature)
820
821 - def create(self, public_key, min_generation, generation, expiration, 822 target_hash, signature):
823 """ 824 Initialise the TACK with data 825 """ 826 self.public_key = public_key 827 self.min_generation = min_generation 828 self.generation = generation 829 self.expiration = expiration 830 self.target_hash = target_hash 831 self.signature = signature 832 return self
833
834 - def write(self):
835 """ 836 Convert the TACK into on the wire format 837 838 @rtype: bytearray 839 """ 840 w = Writer() 841 if len(self.public_key) != 64: 842 raise TLSInternalError("Public_key must be 64 bytes long") 843 w.bytes += self.public_key 844 w.add(self.min_generation, 1) 845 w.add(self.generation, 1) 846 w.add(self.expiration, 4) 847 if len(self.target_hash) != 32: 848 raise TLSInternalError("Target_hash must be 32 bytes long") 849 w.bytes += self.target_hash 850 if len(self.signature) != 64: 851 raise TLSInternalError("Signature must be 64 bytes long") 852 w.bytes += self.signature 853 return w.bytes
854
855 - def parse(self, p):
856 """ 857 Parse the TACK from on the wire format 858 859 @type p: L{tlslite.util.codec.Parser} 860 @param p: data to be parsed 861 862 @rtype: L{TACK} 863 @raise SyntaxError: when the internal sizes don't match the 864 provided data 865 """ 866 867 self.public_key = p.getFixBytes(64) 868 self.min_generation = p.get(1) 869 self.generation = p.get(1) 870 self.expiration = p.get(4) 871 self.target_hash = p.getFixBytes(32) 872 self.signature = p.getFixBytes(64) 873 return self
874
875 - def __eq__(self, other):
876 """ 877 Tests if the other object is equivalent to this TACK 878 879 Returns False for every object that's not a TACK 880 """ 881 if hasattr(other, 'public_key') and\ 882 hasattr(other, 'min_generation') and\ 883 hasattr(other, 'generation') and\ 884 hasattr(other, 'expiration') and\ 885 hasattr(other, 'target_hash') and\ 886 hasattr(other, 'signature'): 887 if self.public_key == other.public_key and\ 888 self.min_generation == other.min_generation and\ 889 self.generation == other.generation and\ 890 self.expiration == other.expiration and\ 891 self.target_hash == other.target_hash and\ 892 self.signature == other.signature: 893 return True 894 else: 895 return False 896 else: 897 return False
898
899 - def __init__(self):
900 """ 901 Create an instance of TACKExtension 902 903 See also: L{create} and L{parse} 904 """ 905 super(TACKExtension, self).__init__(extType=ExtensionType.tack) 906 907 self.tacks = [] 908 self.activation_flags = 0
909
910 - def __repr__(self):
911 """ 912 Create a programmer readable representation of TACK extension 913 914 @rtype: str 915 """ 916 return "TACKExtension(activation_flags={0!r}, tacks={1!r})".format( 917 self.activation_flags, self.tacks)
918 919 @property
920 - def extData(self):
921 """ 922 Return the raw data encoding of the extension 923 924 @rtype: bytearray 925 """ 926 w2 = Writer() 927 for t in self.tacks: 928 w2.bytes += t.write() 929 930 w = Writer() 931 w.add(len(w2.bytes), 2) 932 w.bytes += w2.bytes 933 w.add(self.activation_flags, 1) 934 return w.bytes
935
936 - def create(self, tacks, activation_flags):
937 """ 938 Initialize the instance of TACKExtension 939 940 @rtype: TACKExtension 941 """ 942 943 self.tacks = tacks 944 self.activation_flags = activation_flags 945 return self
946
947 - def parse(self, p):
948 """ 949 Parse the extension from on the wire format 950 951 @type p: L{tlslite.util.codec.Parser} 952 @param p: data to be parsed 953 954 @rtype: L{TACKExtension} 955 """ 956 self.tacks = [] 957 958 p.startLengthCheck(2) 959 while not p.atLengthCheck(): 960 tack = TACKExtension.TACK().parse(p) 961 self.tacks += [tack] 962 p.stopLengthCheck() 963 self.activation_flags = p.get(1) 964 965 return self
966
967 -class SupportedGroupsExtension(VarListExtension):
968 """ 969 Client side list of supported groups of (EC)DHE key exchage. 970 971 See RFC4492, RFC7027 and RFC-ietf-tls-negotiated-ff-dhe-10 972 973 @type groups: int 974 @ivar groups: list of groups that the client supports 975 """ 976
977 - def __init__(self):
978 """Create instance of class""" 979 super(SupportedGroupsExtension, self).__init__(2, 2, 'groups', \ 980 ExtensionType.supported_groups)
981
982 -class ECPointFormatsExtension(VarListExtension):
983 """ 984 Client side list of supported ECC point formats. 985 986 See RFC4492. 987 988 @type formats: list of int 989 @ivar formats: list of point formats supported by peer 990 """ 991
992 - def __init__(self):
993 """Create instance of class""" 994 super(ECPointFormatsExtension, self).__init__(1, 1, 'formats', \ 995 ExtensionType.ec_point_formats)
996
997 -class SignatureAlgorithmsExtension(TLSExtension):
998 999 """ 1000 Client side list of supported signature algorithms. 1001 1002 Should be used by server to select certificate and signing method for 1003 Server Key Exchange messages. In practice used only for the latter. 1004 1005 See RFC5246. 1006 """ 1007
1008 - def __init__(self):
1009 """Create instance of class""" 1010 super(SignatureAlgorithmsExtension, self).__init__(extType= 1011 ExtensionType. 1012 signature_algorithms) 1013 self.sigalgs = None
1014 1015 @property
1016 - def extData(self):
1017 """ 1018 Return raw encoding of the extension 1019 1020 @rtype: bytearray 1021 """ 1022 if self.sigalgs is None: 1023 return bytearray(0) 1024 1025 writer = Writer() 1026 # elements 1 byte each, overall length encoded in 2 bytes 1027 writer.addVarTupleSeq(self.sigalgs, 1, 2) 1028 return writer.bytes
1029
1030 - def create(self, sigalgs):
1031 """ 1032 Set the list of supported algorithm types 1033 1034 @type sigalgs: list of tuples 1035 @param sigalgs: list of pairs of a hash algorithm and signature 1036 algorithm 1037 """ 1038 self.sigalgs = sigalgs 1039 return self
1040
1041 - def parse(self, parser):
1042 """ 1043 Deserialise extension from on the wire data 1044 1045 @type parser: L{Parser} 1046 @rtype: SignatureAlgorithmsExtension 1047 """ 1048 if parser.getRemainingLength() == 0: 1049 self.sigalgs = None 1050 return self 1051 1052 self.sigalgs = parser.getVarTupleList(1, 2, 2) 1053 1054 if parser.getRemainingLength() != 0: 1055 raise SyntaxError() 1056 1057 return self
1058
1059 1060 -class PaddingExtension(TLSExtension):
1061 """ 1062 ClientHello message padding with a desired size. 1063 1064 Can be used to pad ClientHello messages to a desired size 1065 in order to avoid implementation bugs caused by certain 1066 ClientHello sizes. 1067 1068 See RFC7685. 1069 """ 1070
1071 - def __init__(self):
1072 """Create instance of class.""" 1073 extType = ExtensionType.client_hello_padding 1074 super(PaddingExtension, self).__init__(extType=extType) 1075 self.paddingData = bytearray(0)
1076 1077 @property
1078 - def extData(self):
1079 """ 1080 Return raw encoding of the extension. 1081 1082 @rtype: bytearray 1083 """ 1084 return self.paddingData
1085
1086 - def create(self, size):
1087 """ 1088 Set the padding size and create null byte padding of defined size. 1089 1090 @type size: int 1091 @param size: required padding size in bytes 1092 """ 1093 self.paddingData = bytearray(size) 1094 return self
1095
1096 - def parse(self, p):
1097 """ 1098 Deserialise extension from on the wire data. 1099 1100 @type p: L{tlslite.util.codec.Parser} 1101 @param p: data to be parsed 1102 1103 @raise SyntaxError: when the size of the passed element doesn't match 1104 the internal representation 1105 1106 @rtype: L{TLSExtension} 1107 """ 1108 self.paddingData = p.getFixBytes(p.getRemainingLength()) 1109 return self
1110
1111 -class RenegotiationInfoExtension(TLSExtension):
1112 """ 1113 Client and Server Hello secure renegotiation extension from RFC 5746 1114 1115 Should have an empty renegotiated_connection field in case of initial 1116 connection 1117 """ 1118
1119 - def __init__(self):
1120 """Create instance""" 1121 extType = ExtensionType.renegotiation_info 1122 super(RenegotiationInfoExtension, self).__init__(extType=extType) 1123 self.renegotiated_connection = None
1124 1125 @property
1126 - def extData(self):
1127 """ 1128 Return raw encoding of the extension. 1129 1130 @rtype: bytearray 1131 """ 1132 if self.renegotiated_connection is None: 1133 return bytearray(0) 1134 writer = Writer() 1135 writer.add(len(self.renegotiated_connection), 1) 1136 writer.bytes += self.renegotiated_connection 1137 return writer.bytes
1138
1139 - def create(self, renegotiated_connection):
1140 """ 1141 Set the finished message payload from previous connection. 1142 1143 @type renegotiated_connection: bytearray 1144 """ 1145 self.renegotiated_connection = renegotiated_connection 1146 return self
1147
1148 - def parse(self, parser):
1149 """ 1150 Deserialise extension from on the wire data. 1151 1152 @type parser: L{tlslite.util.codec.Parser} 1153 @param parser: data to be parsed 1154 1155 @rtype: L{RenegotiationInfoExtension} 1156 """ 1157 if parser.getRemainingLength() == 0: 1158 self.renegotiated_connection = None 1159 else: 1160 self.renegotiated_connection = parser.getVarBytes(1) 1161 1162 return self
1163
1164 1165 -class ALPNExtension(TLSExtension):
1166 """ 1167 Handling of Application Layer Protocol Negotiation extension from RFC 7301. 1168 1169 @type protocol_names: list of bytearrays 1170 @ivar protocol_names: list of protocol names acceptable or selected by peer 1171 1172 @type extType: int 1173 @ivar extType: numberic type of ALPNExtension, i.e. 16 1174 1175 @type extData: bytearray 1176 @ivar extData: raw encoding of the extension data 1177 """ 1178
1179 - def __init__(self):
1180 """ 1181 Create instance of ALPNExtension 1182 1183 See also: L{create} and L{parse} 1184 """ 1185 super(ALPNExtension, self).__init__(extType=ExtensionType.alpn) 1186 1187 self.protocol_names = None
1188
1189 - def __repr__(self):
1190 """ 1191 Create programmer-readable representation of object 1192 1193 @rtype: str 1194 """ 1195 return "ALPNExtension(protocol_names={0!r})".format(self.protocol_names)
1196 1197 @property
1198 - def extData(self):
1199 """ 1200 Return encoded payload of the extension 1201 1202 @rtype: bytearray 1203 """ 1204 if self.protocol_names is None: 1205 return bytearray(0) 1206 1207 writer = Writer() 1208 for prot in self.protocol_names: 1209 writer.add(len(prot), 1) 1210 writer.bytes += prot 1211 1212 writer2 = Writer() 1213 writer2.add(len(writer.bytes), 2) 1214 writer2.bytes += writer.bytes 1215 1216 return writer2.bytes
1217
1218 - def create(self, protocol_names=None):
1219 """ 1220 Create an instance of ALPNExtension with specified protocols 1221 1222 @type protocols: list of bytearray 1223 @param protocols: list of protocol names that are to be sent 1224 """ 1225 self.protocol_names = protocol_names 1226 return self
1227
1228 - def parse(self, parser):
1229 """ 1230 Parse the extension from on the wire format 1231 1232 @type parser: L{tlslite.util.codec.Parser} 1233 @param parser: data to be parsed as extension 1234 1235 @raise SyntaxError: when the encoding of the extension is self 1236 inconsistent 1237 1238 @rtype: L{ALPNExtension} 1239 """ 1240 self.protocol_names = [] 1241 parser.startLengthCheck(2) 1242 while not parser.atLengthCheck(): 1243 name_len = parser.get(1) 1244 self.protocol_names.append(parser.getFixBytes(name_len)) 1245 parser.stopLengthCheck() 1246 if parser.getRemainingLength() != 0: 1247 raise SyntaxError("Trailing data after protocol_name_list") 1248 return self
1249 1250 1251 TLSExtension._universalExtensions = \ 1252 { 1253 ExtensionType.server_name: SNIExtension, 1254 ExtensionType.cert_type: ClientCertTypeExtension, 1255 ExtensionType.supported_groups: SupportedGroupsExtension, 1256 ExtensionType.ec_point_formats: ECPointFormatsExtension, 1257 ExtensionType.srp: SRPExtension, 1258 ExtensionType.signature_algorithms: SignatureAlgorithmsExtension, 1259 ExtensionType.alpn: ALPNExtension, 1260 ExtensionType.supports_npn: NPNExtension, 1261 ExtensionType.client_hello_padding: PaddingExtension, 1262 ExtensionType.renegotiation_info: RenegotiationInfoExtension} 1263 1264 TLSExtension._serverExtensions = \ 1265 { 1266 ExtensionType.cert_type: ServerCertTypeExtension, 1267 ExtensionType.tack: TACKExtension} 1268