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

Source Code for Module tlslite.extensions

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