Home | History | Annotate | Download | only in tls
      1 ## This file is part of Scapy
      2 ## Copyright (C) 2017 Maxence Tury
      3 ## This program is published under a GPLv2 license
      4 
      5 """
      6 TLS handshake extensions.
      7 """
      8 
      9 from __future__ import print_function
     10 
     11 from scapy.fields import *
     12 from scapy.packet import Packet, Raw, Padding
     13 from scapy.layers.x509 import X509_Extensions
     14 from scapy.layers.tls.basefields import _tls_version
     15 from scapy.layers.tls.keyexchange import (SigAndHashAlgsLenField,
     16                                           SigAndHashAlgsField, _tls_hash_sig)
     17 from scapy.layers.tls.session import _GenericTLSSessionInheritance
     18 from scapy.layers.tls.crypto.groups import _tls_named_groups
     19 
     20 
     21 _tls_ext = {  0: "server_name",             # RFC 4366
     22               1: "max_fragment_length",     # RFC 4366
     23               2: "client_certificate_url",  # RFC 4366
     24               3: "trusted_ca_keys",         # RFC 4366
     25               4: "truncated_hmac",          # RFC 4366
     26               5: "status_request",          # RFC 4366
     27               6: "user_mapping",            # RFC 4681
     28               7: "client_authz",            # RFC 5878
     29               8: "server_authz",            # RFC 5878
     30               9: "cert_type",               # RFC 6091
     31             #10: "elliptic_curves",         # RFC 4492
     32              10: "supported_groups",
     33              11: "ec_point_formats",        # RFC 4492
     34              13: "signature_algorithms",    # RFC 5246
     35              0x0f: "heartbeat",             # RFC 6520
     36              0x10: "alpn",                  # RFC 7301
     37              0x12: "signed_certificate_timestamp",  # RFC 6962
     38              0x15: "padding",               # RFC 7685
     39              0x16: "encrypt_then_mac",      # RFC 7366
     40              0x17: "extended_master_secret",# RFC 7627
     41              0x23: "session_ticket",        # RFC 5077
     42              0x28: "key_share",
     43              0x29: "pre_shared_key",
     44              0x2a: "early_data",
     45              0x2b: "supported_versions",
     46              0x2c: "cookie",
     47              0x2d: "psk_key_exchange_modes",
     48              0x2e: "ticket_early_data_info",
     49              0x2f: "certificate_authorities",
     50              0x30: "oid_filters",
     51              0x3374: "next_protocol_negotiation",
     52                                             # RFC-draft-agl-tls-nextprotoneg-03
     53              0xff01: "renegotiation_info"   # RFC 5746
     54              }
     55 
     56 
     57 class TLS_Ext_Unknown(_GenericTLSSessionInheritance):
     58     """
     59     We put this here rather than in extensions.py in order to avoid
     60     circular imports...
     61     """
     62     name = "TLS Extension - Scapy Unknown"
     63     fields_desc = [ShortEnumField("type", None, _tls_ext),
     64                    FieldLenField("len", None, fmt="!H", length_of="val"),
     65                    StrLenField("val", "",
     66                                length_from=lambda pkt: pkt.len) ]
     67 
     68     def post_build(self, p, pay):
     69         if self.len is None:
     70             l = len(p) - 4
     71             p = p[:2] + struct.pack("!H", l) + p[4:]
     72         return p+pay
     73 
     74 
     75 ###############################################################################
     76 ### ClientHello/ServerHello extensions                                      ###
     77 ###############################################################################
     78 
     79 # We provide these extensions mostly for packet manipulation purposes.
     80 # For now, most of them are not considered by our automaton.
     81 
     82 class TLS_Ext_PrettyPacketList(TLS_Ext_Unknown):
     83     """
     84     Dummy extension used for server_name/ALPN/NPN for a lighter representation:
     85     the final field is showed as a 1-line list rather than as lots of packets.
     86     XXX Define a new condition for packet lists in Packet._show_or_dump?
     87     """
     88     def _show_or_dump(self, dump=False, indent=3,
     89                       lvl="", label_lvl="", first_call=True):
     90         """ Reproduced from packet.py """
     91         ct = AnsiColorTheme() if dump else conf.color_theme
     92         s = "%s%s %s %s \n" % (label_lvl, ct.punct("###["),
     93                                ct.layer_name(self.name), ct.punct("]###"))
     94         for f in self.fields_desc[:-1]:
     95             ncol = ct.field_name
     96             vcol = ct.field_value
     97             fvalue = self.getfieldval(f.name)
     98             begn = "%s  %-10s%s " % (label_lvl+lvl, ncol(f.name),
     99                                      ct.punct("="),)
    100             reprval = f.i2repr(self,fvalue)
    101             if isinstance(reprval, str):
    102                 reprval = reprval.replace("\n", "\n"+" "*(len(label_lvl)
    103                                                           +len(lvl)
    104                                                           +len(f.name)
    105                                                           +4))
    106             s += "%s%s\n" % (begn,vcol(reprval))
    107         f = self.fields_desc[-1]
    108         ncol = ct.field_name
    109         vcol = ct.field_value
    110         fvalue = self.getfieldval(f.name)
    111         begn = "%s  %-10s%s " % (label_lvl+lvl, ncol(f.name), ct.punct("="),)
    112         reprval = f.i2repr(self,fvalue)
    113         if isinstance(reprval, str):
    114             reprval = reprval.replace("\n", "\n"+" "*(len(label_lvl)
    115                                                       +len(lvl)
    116                                                       +len(f.name)
    117                                                       +4))
    118         s += "%s%s\n" % (begn,vcol(reprval))
    119         if self.payload:
    120             s += self.payload._show_or_dump(dump=dump, indent=indent,
    121                                 lvl=lvl+(" "*indent*self.show_indent),
    122                                 label_lvl=label_lvl, first_call=False)
    123 
    124         if first_call and not dump:
    125             print(s)
    126         else:
    127             return s
    128 
    129 
    130 _tls_server_name_types = { 0: "host_name" }
    131 
    132 class ServerName(Packet):
    133     name = "HostName"
    134     fields_desc = [ ByteEnumField("nametype", 0, _tls_server_name_types),
    135                     FieldLenField("namelen", None, length_of="servername"),
    136                     StrLenField("servername", "",
    137                                 length_from=lambda pkt: pkt.namelen) ]
    138     def guess_payload_class(self, p):
    139         return Padding
    140 
    141 class ServerListField(PacketListField):
    142     def i2repr(self, pkt, x):
    143         res = [p.servername for p in x]
    144         return "[%s]" % b", ".join(res)
    145 
    146 class ServerLenField(FieldLenField):
    147     """
    148     There is no length when there are no servernames (as in a ServerHello).
    149     """
    150     def addfield(self, pkt, s, val):
    151         if not val:
    152             if not pkt.servernames:
    153                 return s
    154         return super(ServerLenField, self).addfield(pkt, s, val)
    155 
    156 class TLS_Ext_ServerName(TLS_Ext_PrettyPacketList):                 # RFC 4366
    157     name = "TLS Extension - Server Name"
    158     fields_desc = [ShortEnumField("type", 0, _tls_ext),
    159                    FieldLenField("len", None, length_of="servernames",
    160                                  adjust=lambda pkt,x: x+2),
    161                    ServerLenField("servernameslen", None,
    162                                  length_of="servernames"),
    163                    ServerListField("servernames", [], ServerName,
    164                                    length_from=lambda pkt: pkt.servernameslen)]
    165 
    166 
    167 class TLS_Ext_MaxFragLen(TLS_Ext_Unknown):                          # RFC 4366
    168     name = "TLS Extension - Max Fragment Length"
    169     fields_desc = [ShortEnumField("type", 1, _tls_ext),
    170                    ShortField("len", None),
    171                    ByteEnumField("maxfraglen", 4, { 1: "2^9",
    172                                                     2: "2^10",
    173                                                     3: "2^11",
    174                                                     4: "2^12" }) ]
    175 
    176 
    177 class TLS_Ext_ClientCertURL(TLS_Ext_Unknown):                       # RFC 4366
    178     name = "TLS Extension - Client Certificate URL"
    179     fields_desc = [ShortEnumField("type", 2, _tls_ext),
    180                    ShortField("len", None) ]
    181 
    182 
    183 _tls_trusted_authority_types = {0: "pre_agreed",
    184                                 1: "key_sha1_hash",
    185                                 2: "x509_name",
    186                                 3: "cert_sha1_hash" }
    187 
    188 class TAPreAgreed(Packet):
    189     name = "Trusted authority - pre_agreed"
    190     fields_desc = [ ByteEnumField("idtype", 0, _tls_trusted_authority_types) ]
    191     def guess_payload_class(self, p):
    192         return Padding
    193 
    194 class TAKeySHA1Hash(Packet):
    195     name = "Trusted authority - key_sha1_hash"
    196     fields_desc = [ ByteEnumField("idtype", 1, _tls_trusted_authority_types),
    197                     StrFixedLenField("id", None, 20) ]
    198     def guess_payload_class(self, p):
    199         return Padding
    200 
    201 class TAX509Name(Packet):
    202     """
    203     XXX Section 3.4 of RFC 4366. Implement a more specific DNField
    204     rather than current StrLenField.
    205     """
    206     name = "Trusted authority - x509_name"
    207     fields_desc = [ ByteEnumField("idtype", 2, _tls_trusted_authority_types),
    208                     FieldLenField("dnlen", None, length_of="dn"),
    209                     StrLenField("dn", "", length_from=lambda pkt: pkt.dnlen) ]
    210     def guess_payload_class(self, p):
    211         return Padding
    212 
    213 class TACertSHA1Hash(Packet):
    214     name = "Trusted authority - cert_sha1_hash"
    215     fields_desc = [ ByteEnumField("idtype", 3, _tls_trusted_authority_types),
    216                     StrFixedLenField("id", None, 20) ]
    217     def guess_payload_class(self, p):
    218         return Padding
    219 
    220 _tls_trusted_authority_cls = {0: TAPreAgreed,
    221                               1: TAKeySHA1Hash,
    222                               2: TAX509Name,
    223                               3: TACertSHA1Hash }
    224 
    225 class _TAListField(PacketListField):
    226     """
    227     Specific version that selects the right Trusted Authority (previous TA*)
    228     class to be used for dissection based on idtype.
    229     """
    230     def m2i(self, pkt, m):
    231         idtype = ord(m[0])
    232         cls = self.cls
    233         if idtype in _tls_trusted_authority_cls:
    234             cls = _tls_trusted_authority_cls[idtype]
    235         return cls(m)
    236 
    237 class TLS_Ext_TrustedCAInd(TLS_Ext_Unknown):                        # RFC 4366
    238     name = "TLS Extension - Trusted CA Indication"
    239     fields_desc = [ShortEnumField("type", 3, _tls_ext),
    240                    ShortField("len", None),
    241                    FieldLenField("talen", None, length_of="ta"),
    242                    _TAListField("ta", [], Raw,
    243                                 length_from=lambda pkt: pkt.talen) ]
    244 
    245 
    246 class TLS_Ext_TruncatedHMAC(TLS_Ext_Unknown):                       # RFC 4366
    247     name = "TLS Extension - Truncated HMAC"
    248     fields_desc = [ShortEnumField("type", 4, _tls_ext),
    249                    ShortField("len", None) ]
    250 
    251 
    252 class ResponderID(Packet):
    253     name = "Responder ID structure"
    254     fields_desc = [ FieldLenField("respidlen", None, length_of="respid"),
    255                     StrLenField("respid", "",
    256                                 length_from=lambda pkt: pkt.respidlen)]
    257     def guess_payload_class(self, p):
    258         return Padding
    259 
    260 class OCSPStatusRequest(Packet):
    261     """
    262     This is the structure defined in RFC 6066, not in RFC 6960!
    263     """
    264     name = "OCSPStatusRequest structure"
    265     fields_desc = [ FieldLenField("respidlen", None, length_of="respid"),
    266                     PacketListField("respid", [], ResponderID,
    267                                     length_from=lambda pkt: pkt.respidlen),
    268                     FieldLenField("reqextlen", None, length_of="reqext"),
    269                     PacketField("reqext", "", X509_Extensions) ]
    270     def guess_payload_class(self, p):
    271         return Padding
    272 
    273 _cert_status_type = { 1: "ocsp" }
    274 _cert_status_req_cls  = { 1: OCSPStatusRequest }
    275 
    276 class _StatusReqField(PacketListField):
    277     def m2i(self, pkt, m):
    278         idtype = pkt.stype
    279         cls = self.cls
    280         if idtype in _cert_status_req_cls:
    281             cls = _cert_status_req_cls[idtype]
    282         return cls(m)
    283 
    284 class TLS_Ext_CSR(TLS_Ext_Unknown):                                 # RFC 4366
    285     name = "TLS Extension - Certificate Status Request"
    286     fields_desc = [ShortEnumField("type", 5, _tls_ext),
    287                    ShortField("len", None),
    288                    ByteEnumField("stype", None, _cert_status_type),
    289                    _StatusReqField("req", [], Raw,
    290                                   length_from=lambda pkt: pkt.len - 1) ]
    291 
    292 
    293 class TLS_Ext_UserMapping(TLS_Ext_Unknown):                         # RFC 4681
    294     name = "TLS Extension - User Mapping"
    295     fields_desc = [ShortEnumField("type", 6, _tls_ext),
    296                    ShortField("len", None),
    297                    FieldLenField("umlen", None, fmt="B", length_of="um"),
    298                    FieldListField("um", [],
    299                                   ByteField("umtype", 0),
    300                                   length_from=lambda pkt: pkt.umlen) ]
    301 
    302 
    303 class TLS_Ext_ClientAuthz(TLS_Ext_Unknown):                         # RFC 5878
    304     """ XXX Unsupported """
    305     name = "TLS Extension - Client Authz"
    306     fields_desc = [ShortEnumField("type", 7, _tls_ext),
    307                    ShortField("len", None),
    308                    ]
    309 
    310 class TLS_Ext_ServerAuthz(TLS_Ext_Unknown):                         # RFC 5878
    311     """ XXX Unsupported """
    312     name = "TLS Extension - Server Authz"
    313     fields_desc = [ShortEnumField("type", 8, _tls_ext),
    314                    ShortField("len", None),
    315                    ]
    316 
    317 
    318 _tls_cert_types = { 0: "X.509", 1: "OpenPGP" }
    319 
    320 class TLS_Ext_ClientCertType(TLS_Ext_Unknown):                      # RFC 5081
    321     name = "TLS Extension - Certificate Type (client version)"
    322     fields_desc = [ShortEnumField("type", 9, _tls_ext),
    323                    ShortField("len", None),
    324                    FieldLenField("ctypeslen", None, length_of="ctypes"),
    325                    FieldListField("ctypes", [0, 1],
    326                                   ByteEnumField("certtypes", None,
    327                                                 _tls_cert_types),
    328                                   length_from=lambda pkt: pkt.ctypeslen) ]
    329 
    330 class TLS_Ext_ServerCertType(TLS_Ext_Unknown):                      # RFC 5081
    331     name = "TLS Extension - Certificate Type (server version)"
    332     fields_desc = [ShortEnumField("type", 9, _tls_ext),
    333                    ShortField("len", None),
    334                    ByteEnumField("ctype", None, _tls_cert_types) ]
    335 
    336 def _TLS_Ext_CertTypeDispatcher(m, *args, **kargs):
    337     """
    338     We need to select the correct one on dissection. We use the length for
    339     that, as 1 for client version would emply an empty list.
    340     """
    341     l = struct.unpack("!H", m[2:4])[0]
    342     if l == 1:
    343         cls = TLS_Ext_ServerCertType
    344     else:
    345         cls = TLS_Ext_ClientCertType
    346     return cls(m, *args, **kargs)
    347 
    348 
    349 class TLS_Ext_SupportedGroups(TLS_Ext_Unknown):
    350     """
    351     This extension was known as 'Supported Elliptic Curves' before TLS 1.3
    352     merged both group selection mechanisms for ECDH and FFDH.
    353     """
    354     name = "TLS Extension - Supported Groups"
    355     fields_desc = [ShortEnumField("type", 10, _tls_ext),
    356                    ShortField("len", None),
    357                    FieldLenField("groupslen", None, length_of="groups"),
    358                    FieldListField("groups", [],
    359                                   ShortEnumField("ng", None,
    360                                                  _tls_named_groups),
    361                                   length_from=lambda pkt: pkt.groupslen) ]
    362 
    363 class TLS_Ext_SupportedEllipticCurves(TLS_Ext_SupportedGroups):     # RFC 4492
    364     pass
    365 
    366 
    367 _tls_ecpoint_format = { 0: "uncompressed",
    368                         1: "ansiX962_compressed_prime",
    369                         2: "ansiX962_compressed_char2" }
    370 
    371 class TLS_Ext_SupportedPointFormat(TLS_Ext_Unknown):                # RFC 4492
    372     name = "TLS Extension - Supported Point Format"
    373     fields_desc = [ShortEnumField("type", 11, _tls_ext),
    374                    ShortField("len", None),
    375                    FieldLenField("ecpllen", None, fmt="B", length_of="ecpl"),
    376                    FieldListField("ecpl", [0],
    377                                     ByteEnumField("nc", None,
    378                                                   _tls_ecpoint_format),
    379                                     length_from=lambda pkt: pkt.ecpllen) ]
    380 
    381 
    382 class TLS_Ext_SignatureAlgorithms(TLS_Ext_Unknown):                 # RFC 5246
    383     name = "TLS Extension - Signature Algorithms"
    384     fields_desc = [ShortEnumField("type", 13, _tls_ext),
    385                    ShortField("len", None),
    386                    SigAndHashAlgsLenField("sig_algs_len", None,
    387                                           length_of="sig_algs"),
    388                    SigAndHashAlgsField("sig_algs", [],
    389                                        EnumField("hash_sig", None,
    390                                                     _tls_hash_sig),
    391                                        length_from=
    392                                            lambda pkt: pkt.sig_algs_len) ]
    393 
    394 
    395 class TLS_Ext_Heartbeat(TLS_Ext_Unknown):                           # RFC 6520
    396     name = "TLS Extension - Heartbeat"
    397     fields_desc = [ShortEnumField("type", 0x0f, _tls_ext),
    398                    ShortField("len", None),
    399                    ByteEnumField("heartbeat_mode", 2,
    400                        { 1: "peer_allowed_to_send",
    401                          2: "peer_not_allowed_to_send" }) ]
    402 
    403 
    404 class ProtocolName(Packet):
    405     name = "Protocol Name"
    406     fields_desc = [ FieldLenField("len", None, fmt='B', length_of="protocol"),
    407                     StrLenField("protocol", "",
    408                                 length_from=lambda pkt: pkt.len)]
    409     def guess_payload_class(self, p):
    410         return Padding
    411 
    412 class ProtocolListField(PacketListField):
    413     def i2repr(self, pkt, x):
    414         res = [p.protocol for p in x]
    415         return "[%s]" % b", ".join(res)
    416 
    417 class TLS_Ext_ALPN(TLS_Ext_PrettyPacketList):                       # RFC 7301
    418     name = "TLS Extension - Application Layer Protocol Negotiation"
    419     fields_desc = [ShortEnumField("type", 0x10, _tls_ext),
    420                    ShortField("len", None),
    421                    FieldLenField("protocolslen", None, length_of="protocols"),
    422                    ProtocolListField("protocols", [], ProtocolName,
    423                                      length_from=lambda pkt:pkt.protocolslen) ]
    424 
    425 
    426 class TLS_Ext_Padding(TLS_Ext_Unknown):                             # RFC 7685
    427     name = "TLS Extension - Padding"
    428     fields_desc = [ShortEnumField("type", 0x15, _tls_ext),
    429                    FieldLenField("len", None, length_of="padding"),
    430                    StrLenField("padding", "",
    431                                length_from=lambda pkt: pkt.len) ]
    432 
    433 
    434 class TLS_Ext_EncryptThenMAC(TLS_Ext_Unknown):                      # RFC 7366
    435     name = "TLS Extension - Encrypt-then-MAC"
    436     fields_desc = [ShortEnumField("type", 0x16, _tls_ext),
    437                    ShortField("len", None) ]
    438 
    439 
    440 class TLS_Ext_ExtendedMasterSecret(TLS_Ext_Unknown):                # RFC 7627
    441     name = "TLS Extension - Extended Master Secret"
    442     fields_desc = [ShortEnumField("type", 0x17, _tls_ext),
    443                    ShortField("len", None) ]
    444 
    445 
    446 class TLS_Ext_SessionTicket(TLS_Ext_Unknown):                       # RFC 5077
    447     """
    448     RFC 5077 updates RFC 4507 according to most implementations, which do not
    449     use another (useless) 'ticketlen' field after the global 'len' field.
    450     """
    451     name = "TLS Extension - Session Ticket"
    452     fields_desc = [ShortEnumField("type", 0x23, _tls_ext),
    453                    FieldLenField("len", None, length_of="ticket"),
    454                    StrLenField("ticket", "",
    455                                length_from=lambda pkt: pkt.len) ]
    456 
    457 
    458 class TLS_Ext_KeyShare(TLS_Ext_Unknown):
    459     name = "TLS Extension - Key Share (dummy class)"
    460     fields_desc = [ShortEnumField("type", 0x28, _tls_ext),
    461                    ShortField("len", None) ]
    462 
    463 
    464 class TLS_Ext_PreSharedKey(TLS_Ext_Unknown):
    465     name = "TLS Extension - Pre Shared Key (dummy class)"
    466     fields_desc = [ShortEnumField("type", 0x29, _tls_ext),
    467                    ShortField("len", None) ]
    468 
    469 
    470 class TLS_Ext_EarlyData(TLS_Ext_Unknown):
    471     name = "TLS Extension - Early Data"
    472     fields_desc = [ShortEnumField("type", 0x2a, _tls_ext),
    473                    ShortField("len", None) ]
    474 
    475 
    476 class TLS_Ext_SupportedVersions(TLS_Ext_Unknown):
    477     name = "TLS Extension - Supported Versions"
    478     fields_desc = [ShortEnumField("type", 0x2b, _tls_ext),
    479                    ShortField("len", None),
    480                    FieldLenField("versionslen", None, fmt='B',
    481                                  length_of="versions"),
    482                    FieldListField("versions", [],
    483                                   ShortEnumField("version", None,
    484                                                  _tls_version),
    485                                   length_from=lambda pkt: pkt.versionslen) ]
    486 
    487 
    488 class TLS_Ext_Cookie(TLS_Ext_Unknown):
    489     name = "TLS Extension - Cookie"
    490     fields_desc = [ShortEnumField("type", 0x2c, _tls_ext),
    491                    ShortField("len", None),
    492                    FieldLenField("cookielen", None, length_of="cookie"),
    493                    XStrLenField("cookie", "",
    494                                 length_from=lambda pkt: pkt.cookielen) ]
    495 
    496 
    497 _tls_psk_kx_modes = { 0: "psk_ke", 1: "psk_dhe_ke" }
    498 
    499 class TLS_Ext_PSKKeyExchangeModes(TLS_Ext_Unknown):
    500     name = "TLS Extension - PSK Key Exchange Modes"
    501     fields_desc = [ShortEnumField("type", 0x2d, _tls_ext),
    502                    ShortField("len", None),
    503                    FieldLenField("kxmodeslen", None, fmt='B',
    504                                  length_of="kxmodes"),
    505                    FieldListField("kxmodes", [],
    506                                   ByteEnumField("kxmode", None,
    507                                                  _tls_psk_kx_modes),
    508                                   length_from=lambda pkt: pkt.kxmodeslen) ]
    509 
    510 
    511 class TLS_Ext_TicketEarlyDataInfo(TLS_Ext_Unknown):
    512     name = "TLS Extension - Ticket Early Data Info"
    513     fields_desc = [ShortEnumField("type", 0x2e, _tls_ext),
    514                    ShortField("len", None),
    515                    IntField("max_early_data_size", 0) ]
    516 
    517 
    518 class TLS_Ext_NPN(TLS_Ext_PrettyPacketList):
    519     """
    520     Defined in RFC-draft-agl-tls-nextprotoneg-03. Deprecated in favour of ALPN.
    521     """
    522     name = "TLS Extension - Next Protocol Negotiation"
    523     fields_desc = [ShortEnumField("type", 0x3374, _tls_ext),
    524                    FieldLenField("len", None, length_of="protocols"),
    525                    ProtocolListField("protocols", [], ProtocolName,
    526                                      length_from=lambda pkt:pkt.len) ]
    527 
    528 
    529 class TLS_Ext_RenegotiationInfo(TLS_Ext_Unknown):                   # RFC 5746
    530     name = "TLS Extension - Renegotiation Indication"
    531     fields_desc = [ShortEnumField("type", 0xff01, _tls_ext),
    532                    ShortField("len", None),
    533                    FieldLenField("reneg_conn_len", None, fmt='B',
    534                                  length_of="renegotiated_connection"),
    535                    StrLenField("renegotiated_connection", "",
    536                                length_from=lambda pkt: pkt.reneg_conn_len) ]
    537 
    538 
    539 _tls_ext_cls = { 0: TLS_Ext_ServerName,
    540                  1: TLS_Ext_MaxFragLen,
    541                  2: TLS_Ext_ClientCertURL,
    542                  3: TLS_Ext_TrustedCAInd,
    543                  4: TLS_Ext_TruncatedHMAC,
    544                  5: TLS_Ext_CSR,
    545                  6: TLS_Ext_UserMapping,
    546                  7: TLS_Ext_ClientAuthz,
    547                  8: TLS_Ext_ServerAuthz,
    548                  9: _TLS_Ext_CertTypeDispatcher,
    549                #10: TLS_Ext_SupportedEllipticCurves,
    550                 10: TLS_Ext_SupportedGroups,
    551                 11: TLS_Ext_SupportedPointFormat,
    552                 13: TLS_Ext_SignatureAlgorithms,
    553                 0x0f: TLS_Ext_Heartbeat,
    554                 0x10: TLS_Ext_ALPN,
    555                 0x15: TLS_Ext_Padding,
    556                 0x16: TLS_Ext_EncryptThenMAC,
    557                 0x17: TLS_Ext_ExtendedMasterSecret,
    558                 0x23: TLS_Ext_SessionTicket,
    559                 0x28: TLS_Ext_KeyShare,
    560                 0x29: TLS_Ext_PreSharedKey,
    561                 0x2a: TLS_Ext_EarlyData,
    562                 0x2b: TLS_Ext_SupportedVersions,
    563                 0x2c: TLS_Ext_Cookie,
    564                 0x2d: TLS_Ext_PSKKeyExchangeModes,
    565                 0x2e: TLS_Ext_TicketEarlyDataInfo,
    566                #0x2f: TLS_Ext_CertificateAuthorities,       #XXX
    567                #0x30: TLS_Ext_OIDFilters,                   #XXX
    568                 0x3374: TLS_Ext_NPN,
    569                 0xff01: TLS_Ext_RenegotiationInfo
    570                 }
    571 
    572 
    573 class _ExtensionsLenField(FieldLenField):
    574     def getfield(self, pkt, s):
    575         """
    576         We try to compute a length, usually from a msglen parsed earlier.
    577         If this length is 0, we consider 'selection_present' (from RFC 5246)
    578         to be False. This means that there should not be any length field.
    579         However, with TLS 1.3, zero lengths are always explicit.
    580         """
    581         ext = pkt.get_field(self.length_of)
    582         l = ext.length_from(pkt)
    583         if l is None or l <= 0:
    584             v = pkt.tls_session.tls_version
    585             if v is None or v < 0x0304:
    586                 return s, None
    587         return super(_ExtensionsLenField, self).getfield(pkt, s)
    588 
    589     def addfield(self, pkt, s, i):
    590         """
    591         There is a hack with the _ExtensionsField.i2len. It works only because
    592         we expect _ExtensionsField.i2m to return a string of the same size (if
    593         not of the same value) upon successive calls (e.g. through i2len here,
    594         then i2m when directly building the _ExtensionsField).
    595 
    596         XXX A proper way to do this would be to keep the extensions built from
    597         the i2len call here, instead of rebuilding them later on.
    598         """
    599         if i is None:
    600             if self.length_of is not None:
    601                 fld,fval = pkt.getfield_and_val(self.length_of)
    602 
    603                 tmp = pkt.tls_session.frozen
    604                 pkt.tls_session.frozen = True
    605                 f = fld.i2len(pkt, fval)
    606                 pkt.tls_session.frozen = tmp
    607 
    608                 i = self.adjust(pkt, f)
    609                 if i == 0: # for correct build if no ext and not explicitly 0
    610                     return s
    611         return s + struct.pack(self.fmt, i)
    612 
    613 class _ExtensionsField(StrLenField):
    614     islist=1
    615     holds_packets=1
    616 
    617     def i2len(self, pkt, i):
    618         if i is None:
    619             return 0
    620         return len(self.i2m(pkt, i))
    621 
    622     def getfield(self, pkt, s):
    623         l = self.length_from(pkt)
    624         if l is None:
    625             return s, []
    626         return s[l:], self.m2i(pkt, s[:l])
    627 
    628     def i2m(self, pkt, i):
    629         if i is None:
    630             return b""
    631         if isinstance(pkt, _GenericTLSSessionInheritance):
    632             if not pkt.tls_session.frozen:
    633                 s = b""
    634                 for ext in i:
    635                     if isinstance(ext, _GenericTLSSessionInheritance):
    636                         ext.tls_session = pkt.tls_session
    637                         s += ext.raw_stateful()
    638                     else:
    639                         s += raw(ext)
    640                 return s
    641         return b"".join(map(raw, i))
    642 
    643     def m2i(self, pkt, m):
    644         res = []
    645         while m:
    646             t = struct.unpack("!H", m[:2])[0]
    647             l = struct.unpack("!H", m[2:4])[0]
    648             cls = _tls_ext_cls.get(t, TLS_Ext_Unknown)
    649             if cls is TLS_Ext_KeyShare:
    650                 from scapy.layers.tls.keyexchange_tls13 import _tls_ext_keyshare_cls
    651                 cls = _tls_ext_keyshare_cls.get(pkt.msgtype, TLS_Ext_Unknown)
    652             elif cls is TLS_Ext_PreSharedKey:
    653                 from scapy.layers.tls.keyexchange_tls13 import _tls_ext_presharedkey_cls
    654                 cls = _tls_ext_presharedkey_cls.get(pkt.msgtype, TLS_Ext_Unknown)
    655             res.append(cls(m[:l+4], tls_session=pkt.tls_session))
    656             m = m[l+4:]
    657         return res
    658 
    659 
    660