Home | History | Annotate | Download | only in tls
      1 ## This file is part of Scapy
      2 ## Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
      3 ##               2015, 2016, 2017 Maxence Tury
      4 ## This program is published under a GPLv2 license
      5 
      6 """
      7 TLS handshake fields & logic.
      8 
      9 This module covers the handshake TLS subprotocol, except for the key exchange
     10 mechanisms which are addressed with keyexchange.py.
     11 """
     12 
     13 from __future__ import absolute_import
     14 import math
     15 
     16 from scapy.error import log_runtime, warning
     17 from scapy.fields import *
     18 from scapy.compat import *
     19 from scapy.packet import Packet, Raw, Padding
     20 from scapy.utils import repr_hex
     21 from scapy.layers.x509 import OCSP_Response
     22 from scapy.layers.tls.cert import Cert, PrivKey, PubKey
     23 from scapy.layers.tls.basefields import (_tls_version, _TLSVersionField,
     24                                          _TLSClientVersionField)
     25 from scapy.layers.tls.extensions import (_ExtensionsLenField, _ExtensionsField,
     26                                          _cert_status_type, TLS_Ext_SupportedVersions)
     27 from scapy.layers.tls.keyexchange import (_TLSSignature, _TLSServerParamsField,
     28                                           _TLSSignatureField, ServerRSAParams,
     29                                           SigAndHashAlgsField, _tls_hash_sig,
     30                                           SigAndHashAlgsLenField)
     31 from scapy.layers.tls.keyexchange_tls13 import TicketField
     32 from scapy.layers.tls.session import (_GenericTLSSessionInheritance,
     33                                       readConnState, writeConnState)
     34 from scapy.layers.tls.crypto.compression import (_tls_compression_algs,
     35                                                  _tls_compression_algs_cls,
     36                                                  Comp_NULL, _GenericComp,
     37                                                  _GenericCompMetaclass)
     38 from scapy.layers.tls.crypto.suites import (_tls_cipher_suites,
     39                                             _tls_cipher_suites_cls,
     40                                             _GenericCipherSuite,
     41                                             _GenericCipherSuiteMetaclass)
     42 
     43 
     44 ###############################################################################
     45 ### Generic TLS Handshake message                                           ###
     46 ###############################################################################
     47 
     48 _tls_handshake_type = { 0: "hello_request",         1: "client_hello",
     49                         2: "server_hello",          3: "hello_verify_request",
     50                         4: "session_ticket",        6: "hello_retry_request",
     51                         8: "encrypted_extensions",  11: "certificate",
     52                         12: "server_key_exchange",  13: "certificate_request",
     53                         14: "server_hello_done",    15: "certificate_verify",
     54                         16: "client_key_exchange",  20: "finished",
     55                         21: "certificate_url",      22: "certificate_status",
     56                         23: "supplemental_data",    24: "key_update" }
     57 
     58 
     59 class _TLSHandshake(_GenericTLSSessionInheritance):
     60     """
     61     Inherited by other Handshake classes to get post_build().
     62     Also used as a fallback for unknown TLS Handshake packets.
     63     """
     64     name = "TLS Handshake Generic message"
     65     fields_desc = [ ByteEnumField("msgtype", None, _tls_handshake_type),
     66                     ThreeBytesField("msglen", None),
     67                     StrLenField("msg", "",
     68                                 length_from=lambda pkt: pkt.msglen) ]
     69 
     70     def post_build(self, p, pay):
     71         l = len(p)
     72         if self.msglen is None:
     73             l2 = l - 4
     74             p = struct.pack("!I", (orb(p[0]) << 24) | l2) + p[4:]
     75         return p + pay
     76 
     77     def guess_payload_class(self, p):
     78         return conf.padding_layer
     79 
     80     def tls_session_update(self, msg_str):
     81         """
     82         Covers both post_build- and post_dissection- context updates.
     83         """
     84         self.tls_session.handshake_messages.append(msg_str)
     85         self.tls_session.handshake_messages_parsed.append(self)
     86 
     87 
     88 ###############################################################################
     89 ### HelloRequest                                                            ###
     90 ###############################################################################
     91 
     92 class TLSHelloRequest(_TLSHandshake):
     93     name = "TLS Handshake - Hello Request"
     94     fields_desc = [ ByteEnumField("msgtype", 0, _tls_handshake_type),
     95                     ThreeBytesField("msglen", None) ]
     96 
     97     def tls_session_update(self, msg_str):
     98         """
     99         Message should not be added to the list of handshake messages
    100         that will be hashed in the finished and certificate verify messages.
    101         """
    102         return
    103 
    104 
    105 ###############################################################################
    106 ### ClientHello fields                                                      ###
    107 ###############################################################################
    108 
    109 class _GMTUnixTimeField(UTCTimeField):
    110     """
    111     "The current time and date in standard UNIX 32-bit format (seconds since
    112      the midnight starting Jan 1, 1970, GMT, ignoring leap seconds)."
    113     """
    114     def i2h(self, pkt, x):
    115         if x is not None:
    116             return x
    117         return 0
    118 
    119 class _TLSRandomBytesField(StrFixedLenField):
    120     def i2repr(self, pkt, x):
    121         if x is None:
    122             return repr(x)
    123         return repr_hex(self.i2h(pkt,x))
    124 
    125 
    126 class _SessionIDField(StrLenField):
    127     """
    128     opaque SessionID<0..32>; section 7.4.1.2 of RFC 4346
    129     """
    130     pass
    131 
    132 
    133 class _CipherSuitesField(StrLenField):
    134     __slots__ = ["itemfmt", "itemsize", "i2s", "s2i"]
    135     islist = 1
    136     def __init__(self, name, default, dico, length_from=None, itemfmt="!H"):
    137         StrLenField.__init__(self, name, default, length_from=length_from)
    138         self.itemfmt = itemfmt
    139         self.itemsize = struct.calcsize(itemfmt)
    140         i2s = self.i2s = {}
    141         s2i = self.s2i = {}
    142         for k in six.iterkeys(dico):
    143             i2s[k] = dico[k]
    144             s2i[dico[k]] = k
    145 
    146     def any2i_one(self, pkt, x):
    147         if (isinstance(x, _GenericCipherSuite) or
    148             isinstance(x, _GenericCipherSuiteMetaclass)):
    149             x = x.val
    150         if isinstance(x, bytes):
    151             x = self.s2i[x]
    152         return x
    153 
    154     def i2repr_one(self, pkt, x):
    155         fmt = "0x%%0%dx" % self.itemsize
    156         return self.i2s.get(x, fmt % x)
    157 
    158     def any2i(self, pkt, x):
    159         if x is None:
    160             return None
    161         if not isinstance(x, list):
    162             x = [x]
    163         return [self.any2i_one(pkt, z) for z in x]
    164 
    165     def i2repr(self, pkt, x):
    166         if x is None:
    167             return "None"
    168         l = [self.i2repr_one(pkt, z) for z in x]
    169         if len(l) == 1:
    170             l = l[0]
    171         else:
    172             l = "[%s]" % ", ".join(l)
    173         return l
    174 
    175     def i2m(self, pkt, val):
    176         if val is None:
    177             val = []
    178         return b"".join(struct.pack(self.itemfmt, x) for x in val)
    179 
    180     def m2i(self, pkt, m):
    181         res = []
    182         itemlen = struct.calcsize(self.itemfmt)
    183         while m:
    184             res.append(struct.unpack(self.itemfmt, m[:itemlen])[0])
    185             m = m[itemlen:]
    186         return res
    187 
    188     def i2len(self, pkt, i):
    189         if i is None:
    190             return 0
    191         return len(i)*self.itemsize
    192 
    193 
    194 class _CompressionMethodsField(_CipherSuitesField):
    195 
    196     def any2i_one(self, pkt, x):
    197         if (isinstance(x, _GenericComp) or
    198             isinstance(x, _GenericCompMetaclass)):
    199             x = x.val
    200         if isinstance(x, str):
    201             x = self.s2i[x]
    202         return x
    203 
    204 
    205 ###############################################################################
    206 ### ClientHello                                                             ###
    207 ###############################################################################
    208 
    209 class TLSClientHello(_TLSHandshake):
    210     """
    211     TLS ClientHello, with abilities to handle extensions.
    212 
    213     The Random structure follows the RFC 5246: while it is 32-byte long,
    214     many implementations use the first 4 bytes as a gmt_unix_time, and then
    215     the remaining 28 byts should be completely random. This was designed in
    216     order to (sort of) mitigate broken RNGs. If you prefer to show the full
    217     32 random bytes without any GMT time, just comment in/out the lines below.
    218     """
    219     name = "TLS Handshake - Client Hello"
    220     fields_desc = [ ByteEnumField("msgtype", 1, _tls_handshake_type),
    221                     ThreeBytesField("msglen", None),
    222                     _TLSClientVersionField("version", None, _tls_version),
    223 
    224                     #_TLSRandomBytesField("random_bytes", None, 32),
    225                     _GMTUnixTimeField("gmt_unix_time", None),
    226                     _TLSRandomBytesField("random_bytes", None, 28),
    227 
    228                     FieldLenField("sidlen", None, fmt="B", length_of="sid"),
    229                     _SessionIDField("sid", "",
    230                                     length_from=lambda pkt:pkt.sidlen),
    231 
    232                     FieldLenField("cipherslen", None, fmt="!H",
    233                                   length_of="ciphers"),
    234                     _CipherSuitesField("ciphers", None,
    235                                        _tls_cipher_suites, itemfmt="!H",
    236                                        length_from=lambda pkt: pkt.cipherslen),
    237 
    238                     FieldLenField("complen", None, fmt="B", length_of="comp"),
    239                     _CompressionMethodsField("comp", [0],
    240                                              _tls_compression_algs,
    241                                              itemfmt="B",
    242                                              length_from=
    243                                                  lambda pkt: pkt.complen),
    244 
    245                     _ExtensionsLenField("extlen", None, length_of="ext"),
    246                     _ExtensionsField("ext", None,
    247                                      length_from=lambda pkt: (pkt.msglen -
    248                                                               (pkt.sidlen or 0) -
    249                                                               (pkt.cipherslen or 0) -
    250                                                               (pkt.complen or 0) -
    251                                                               40)) ]
    252 
    253     def post_build(self, p, pay):
    254         if self.random_bytes is None:
    255             p = p[:10] + randstring(28) + p[10+28:]
    256 
    257         # if no ciphersuites were provided, we add a few usual, supported
    258         # ciphersuites along with the appropriate extensions
    259         if self.ciphers is None:
    260             cipherstart = 39 + (self.sidlen or 0)
    261             s = b"001ac02bc023c02fc027009e0067009c003cc009c0130033002f000a"
    262             p = p[:cipherstart] + bytes_hex(s) + p[cipherstart+2:]
    263             if self.ext is None:
    264                 ext_len = b'\x00\x2c'
    265                 ext_reneg = b'\xff\x01\x00\x01\x00'
    266                 ext_sn = b'\x00\x00\x00\x0f\x00\r\x00\x00\nsecdev.org'
    267                 ext_sigalg = b'\x00\r\x00\x08\x00\x06\x04\x03\x04\x01\x02\x01'
    268                 ext_supgroups = b'\x00\n\x00\x04\x00\x02\x00\x17'
    269                 p += ext_len + ext_reneg + ext_sn + ext_sigalg + ext_supgroups
    270 
    271         return super(TLSClientHello, self).post_build(p, pay)
    272 
    273     def tls_session_update(self, msg_str):
    274         """
    275         Either for parsing or building, we store the client_random
    276         along with the raw string representing this handshake message.
    277         """
    278         super(TLSClientHello, self).tls_session_update(msg_str)
    279 
    280         self.tls_session.advertised_tls_version = self.version
    281         self.random_bytes = msg_str[10:38]
    282         self.tls_session.client_random = (struct.pack('!I',
    283                                                       self.gmt_unix_time) +
    284                                           self.random_bytes)
    285         if self.ext:
    286             for e in self.ext:
    287                 if isinstance(e, TLS_Ext_SupportedVersions):
    288                     if self.tls_session.tls13_early_secret is None:
    289                         # this is not recomputed if there was a TLS 1.3 HRR
    290                         self.tls_session.compute_tls13_early_secrets()
    291                     break
    292 
    293 ###############################################################################
    294 ### ServerHello                                                             ###
    295 ###############################################################################
    296 
    297 class TLSServerHello(TLSClientHello):
    298     """
    299     TLS ServerHello, with abilities to handle extensions.
    300 
    301     The Random structure follows the RFC 5246: while it is 32-byte long,
    302     many implementations use the first 4 bytes as a gmt_unix_time, and then
    303     the remaining 28 byts should be completely random. This was designed in
    304     order to (sort of) mitigate broken RNGs. If you prefer to show the full
    305     32 random bytes without any GMT time, just comment in/out the lines below.
    306     """
    307     name = "TLS Handshake - Server Hello"
    308     fields_desc = [ ByteEnumField("msgtype", 2, _tls_handshake_type),
    309                     ThreeBytesField("msglen", None),
    310                     _TLSVersionField("version", None, _tls_version),
    311 
    312                     #_TLSRandomBytesField("random_bytes", None, 32),
    313                     _GMTUnixTimeField("gmt_unix_time", None),
    314                     _TLSRandomBytesField("random_bytes", None, 28),
    315 
    316                     FieldLenField("sidlen", None, length_of="sid", fmt="B"),
    317                     _SessionIDField("sid", "",
    318                                    length_from = lambda pkt: pkt.sidlen),
    319 
    320                     EnumField("cipher", None, _tls_cipher_suites),
    321                     _CompressionMethodsField("comp", [0],
    322                                              _tls_compression_algs,
    323                                              itemfmt="B",
    324                                              length_from=lambda pkt: 1),
    325 
    326                     _ExtensionsLenField("extlen", None, length_of="ext"),
    327                     _ExtensionsField("ext", None,
    328                                      length_from=lambda pkt: (pkt.msglen -
    329                                                               (pkt.sidlen or 0) -
    330                                                               38)) ]
    331                                                               #40)) ]
    332 
    333     @classmethod
    334     def dispatch_hook(cls, _pkt=None, *args, **kargs):
    335         if _pkt and len(_pkt) >= 6:
    336             version = struct.unpack("!H", _pkt[4:6])[0]
    337             if version == 0x0304 or version > 0x7f00:
    338                 return TLS13ServerHello
    339         return TLSServerHello
    340 
    341     def post_build(self, p, pay):
    342         if self.random_bytes is None:
    343             p = p[:10] + randstring(28) + p[10+28:]
    344         return super(TLSClientHello, self).post_build(p, pay)
    345 
    346     def tls_session_update(self, msg_str):
    347         """
    348         Either for parsing or building, we store the server_random
    349         along with the raw string representing this handshake message.
    350         We also store the session_id, the cipher suite (if recognized),
    351         the compression method, and finally we instantiate the pending write
    352         and read connection states. Usually they get updated later on in the
    353         negotiation when we learn the session keys, and eventually they
    354         are committed once a ChangeCipherSpec has been sent/received.
    355         """
    356         super(TLSClientHello, self).tls_session_update(msg_str)
    357 
    358         self.tls_session.tls_version = self.version
    359         self.random_bytes = msg_str[10:38]
    360         self.tls_session.server_random = (struct.pack('!I',
    361                                                       self.gmt_unix_time) +
    362                                           self.random_bytes)
    363         self.tls_session.sid = self.sid
    364 
    365         cs_cls = None
    366         if self.cipher:
    367             cs_val = self.cipher
    368             if cs_val not in _tls_cipher_suites_cls:
    369                 warning("Unknown cipher suite %d from ServerHello" % cs_val)
    370                 # we do not try to set a default nor stop the execution
    371             else:
    372                 cs_cls = _tls_cipher_suites_cls[cs_val]
    373 
    374         comp_cls = Comp_NULL
    375         if self.comp:
    376             comp_val = self.comp[0]
    377             if comp_val not in _tls_compression_algs_cls:
    378                 err = "Unknown compression alg %d from ServerHello" % comp_val
    379                 warning(err)
    380                 comp_val = 0
    381             comp_cls = _tls_compression_algs_cls[comp_val]
    382 
    383         connection_end = self.tls_session.connection_end
    384         self.tls_session.pwcs = writeConnState(ciphersuite=cs_cls,
    385                                                compression_alg=comp_cls,
    386                                                connection_end=connection_end,
    387                                                tls_version=self.version)
    388         self.tls_session.prcs = readConnState(ciphersuite=cs_cls,
    389                                               compression_alg=comp_cls,
    390                                               connection_end=connection_end,
    391                                               tls_version=self.version)
    392 
    393 
    394 class TLS13ServerHello(TLSClientHello):
    395     """ TLS 1.3 ServerHello """
    396     name = "TLS 1.3 Handshake - Server Hello"
    397     fields_desc = [ ByteEnumField("msgtype", 2, _tls_handshake_type),
    398                     ThreeBytesField("msglen", None),
    399                     _TLSVersionField("version", None, _tls_version),
    400                     _TLSRandomBytesField("random_bytes", None, 32),
    401                     EnumField("cipher", None, _tls_cipher_suites),
    402                     _ExtensionsLenField("extlen", None, length_of="ext"),
    403                     _ExtensionsField("ext", None,
    404                                      length_from=lambda pkt: (pkt.msglen -
    405                                                               38)) ]
    406 
    407     def tls_session_update(self, msg_str):
    408         """
    409         Either for parsing or building, we store the server_random along with
    410         the raw string representing this handshake message. We also store the
    411         cipher suite (if recognized), and finally we instantiate the write and
    412         read connection states.
    413         """
    414         super(TLSClientHello, self).tls_session_update(msg_str)
    415 
    416         s = self.tls_session
    417         s.tls_version = self.version
    418         s.server_random = self.random_bytes
    419 
    420         cs_cls = None
    421         if self.cipher:
    422             cs_val = self.cipher
    423             if cs_val not in _tls_cipher_suites_cls:
    424                 warning("Unknown cipher suite %d from ServerHello" % cs_val)
    425                 # we do not try to set a default nor stop the execution
    426             else:
    427                 cs_cls = _tls_cipher_suites_cls[cs_val]
    428 
    429         connection_end = s.connection_end
    430         s.pwcs = writeConnState(ciphersuite=cs_cls,
    431                                 connection_end=connection_end,
    432                                 tls_version=self.version)
    433         s.triggered_pwcs_commit = True
    434         s.prcs = readConnState(ciphersuite=cs_cls,
    435                                connection_end=connection_end,
    436                                tls_version=self.version)
    437         s.triggered_prcs_commit = True
    438 
    439         if self.tls_session.tls13_early_secret is None:
    440             # In case the connState was not pre-initialized, we could not
    441             # compute the early secrets at the ClientHello, so we do it here.
    442             self.tls_session.compute_tls13_early_secrets()
    443         s.compute_tls13_handshake_secrets()
    444 
    445 
    446 ###############################################################################
    447 ### HelloRetryRequest                                                       ###
    448 ###############################################################################
    449 
    450 class TLSHelloRetryRequest(_TLSHandshake):
    451     name = "TLS 1.3 Handshake - Hello Retry Request"
    452     fields_desc = [ ByteEnumField("msgtype", 6, _tls_handshake_type),
    453                     ThreeBytesField("msglen", None),
    454                     _TLSVersionField("version", None, _tls_version),
    455                     _ExtensionsLenField("extlen", None, length_of="ext"),
    456                     _ExtensionsField("ext", None,
    457                                      length_from=lambda pkt: pkt.msglen - 4) ]
    458 
    459 
    460 ###############################################################################
    461 ### EncryptedExtensions                                                     ###
    462 ###############################################################################
    463 
    464 class TLSEncryptedExtensions(_TLSHandshake):
    465     name = "TLS 1.3 Handshake - Encrypted Extensions"
    466     fields_desc = [ ByteEnumField("msgtype", 8, _tls_handshake_type),
    467                     ThreeBytesField("msglen", None),
    468                     _ExtensionsLenField("extlen", None, length_of="ext"),
    469                     _ExtensionsField("ext", None,
    470                                      length_from=lambda pkt: pkt.msglen - 2) ]
    471 
    472 
    473 ###############################################################################
    474 ### Certificate                                                             ###
    475 ###############################################################################
    476 
    477 #XXX It might be appropriate to rewrite this mess with basic 3-byte FieldLenField.
    478 
    479 class _ASN1CertLenField(FieldLenField):
    480     """
    481     This is mostly a 3-byte FieldLenField.
    482     """
    483     def __init__(self, name, default, length_of=None, adjust=lambda pkt, x: x):
    484         self.length_of = length_of
    485         self.adjust = adjust
    486         Field.__init__(self, name, default, fmt="!I")
    487 
    488     def i2m(self, pkt, x):
    489         if x is None:
    490             if self.length_of is not None:
    491                 fld,fval = pkt.getfield_and_val(self.length_of)
    492                 f = fld.i2len(pkt, fval)
    493                 x = self.adjust(pkt, f)
    494         return x
    495 
    496     def addfield(self, pkt, s, val):
    497         return s + struct.pack(self.fmt, self.i2m(pkt,val))[1:4]
    498 
    499     def getfield(self, pkt, s):
    500         return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b"\x00" + s[:3])[0])
    501 
    502 
    503 class _ASN1CertListField(StrLenField):
    504     islist = 1
    505     def i2len(self, pkt, i):
    506         if i is None:
    507             return 0
    508         return len(self.i2m(pkt, i))
    509 
    510     def getfield(self, pkt, s):
    511         """
    512         Extract Certs in a loop.
    513         XXX We should provide safeguards when trying to parse a Cert.
    514         """
    515         l = None
    516         if self.length_from is not None:
    517             l = self.length_from(pkt)
    518 
    519         lst = []
    520         ret = b""
    521         m = s
    522         if l is not None:
    523             m, ret = s[:l], s[l:]
    524         while m:
    525             clen = struct.unpack("!I", b'\x00' + m[:3])[0]
    526             lst.append((clen, Cert(m[3:3 + clen])))
    527             m = m[3 + clen:]
    528         return m + ret, lst
    529 
    530     def i2m(self, pkt, i):
    531         def i2m_one(i):
    532             if isinstance(i, str):
    533                 return i
    534             if isinstance(i, Cert):
    535                 s = i.der
    536                 l = struct.pack("!I", len(s))[1:4]
    537                 return l + s
    538 
    539             (l, s) = i
    540             if isinstance(s, Cert):
    541                 s = s.der
    542             return struct.pack("!I", l)[1:4] + s
    543 
    544         if i is None:
    545             return b""
    546         if isinstance(i, str):
    547             return i
    548         if isinstance(i, Cert):
    549             i = [i]
    550         return b"".join(i2m_one(x) for x in i)
    551 
    552     def any2i(self, pkt, x):
    553         return x
    554 
    555 class _ASN1CertField(StrLenField):
    556     def i2len(self, pkt, i):
    557         if i is None:
    558             return 0
    559         return len(self.i2m(pkt, i))
    560 
    561     def getfield(self, pkt, s):
    562         l = None
    563         if self.length_from is not None:
    564             l = self.length_from(pkt)
    565         ret = b""
    566         m = s
    567         if l is not None:
    568             m, ret = s[:l], s[l:]
    569         clen = struct.unpack("!I", b'\x00' + m[:3])[0]
    570         len_cert = (clen, Cert(m[3:3 + clen]))
    571         m = m[3 + clen:]
    572         return m + ret, len_cert
    573 
    574     def i2m(self, pkt, i):
    575         def i2m_one(i):
    576             if isinstance(i, str):
    577                 return i
    578             if isinstance(i, Cert):
    579                 s = i.der
    580                 l = struct.pack("!I", len(s))[1:4]
    581                 return l + s
    582 
    583             (l, s) = i
    584             if isinstance(s, Cert):
    585                 s = s.der
    586             return struct.pack("!I", l)[1:4] + s
    587 
    588         if i is None:
    589             return b""
    590         return i2m_one(i)
    591 
    592     def any2i(self, pkt, x):
    593         return x
    594 
    595 
    596 class TLSCertificate(_TLSHandshake):
    597     """
    598     XXX We do not support RFC 5081, i.e. OpenPGP certificates.
    599     """
    600     name = "TLS Handshake - Certificate"
    601     fields_desc = [ ByteEnumField("msgtype", 11, _tls_handshake_type),
    602                     ThreeBytesField("msglen", None),
    603                     _ASN1CertLenField("certslen", None, length_of="certs"),
    604                     _ASN1CertListField("certs", [],
    605                                       length_from = lambda pkt: pkt.certslen) ]
    606 
    607     @classmethod
    608     def dispatch_hook(cls, _pkt=None, *args, **kargs):
    609         if _pkt:
    610             tls_session = kargs.get("tls_session", None)
    611             if tls_session and (tls_session.tls_version or 0) >= 0x0304:
    612                 return TLS13Certificate
    613         return TLSCertificate
    614 
    615     def post_dissection_tls_session_update(self, msg_str):
    616         self.tls_session_update(msg_str)
    617         connection_end = self.tls_session.connection_end
    618         if connection_end == "client":
    619             self.tls_session.server_certs = [x[1] for x in self.certs]
    620         else:
    621             self.tls_session.client_certs = [x[1] for x in self.certs]
    622 
    623 
    624 class _ASN1CertAndExt(_GenericTLSSessionInheritance):
    625     name = "Certificate and Extensions"
    626     fields_desc = [ _ASN1CertField("cert", ""),
    627                     FieldLenField("extlen", None, length_of="ext"),
    628                     _ExtensionsField("ext", [],
    629                                      length_from=lambda pkt: pkt.extlen) ]
    630     def extract_padding(self, s):
    631         return b"", s
    632 
    633 class _ASN1CertAndExtListField(PacketListField):
    634     def m2i(self, pkt, m):
    635         return self.cls(m, tls_session=pkt.tls_session)
    636 
    637 class TLS13Certificate(_TLSHandshake):
    638     name = "TLS 1.3 Handshake - Certificate"
    639     fields_desc = [ ByteEnumField("msgtype", 11, _tls_handshake_type),
    640                     ThreeBytesField("msglen", None),
    641                     FieldLenField("cert_req_ctxt_len", None, fmt="B",
    642                                   length_of="cert_req_ctxt"),
    643                     StrLenField("cert_req_ctxt", "",
    644                                 length_from=lambda pkt: pkt.cert_req_ctxt_len),
    645                     _ASN1CertLenField("certslen", None, length_of="certs"),
    646                     _ASN1CertAndExtListField("certs", [], _ASN1CertAndExt,
    647                                       length_from=lambda pkt: pkt.certslen) ]
    648 
    649     def post_dissection_tls_session_update(self, msg_str):
    650         self.tls_session_update(msg_str)
    651         connection_end = self.tls_session.connection_end
    652         if connection_end == "client":
    653             if self.certs:
    654                 sc = [x.cert[1] for x in self.certs]
    655                 self.tls_session.server_certs = sc
    656         else:
    657             if self.certs:
    658                 cc = [x.cert[1] for x in self.certs]
    659                 self.tls_session.client_certs = cc
    660 
    661 
    662 ###############################################################################
    663 ### ServerKeyExchange                                                       ###
    664 ###############################################################################
    665 
    666 class TLSServerKeyExchange(_TLSHandshake):
    667     name = "TLS Handshake - Server Key Exchange"
    668     fields_desc = [ ByteEnumField("msgtype", 12, _tls_handshake_type),
    669                     ThreeBytesField("msglen", None),
    670                     _TLSServerParamsField("params", None,
    671                         length_from=lambda pkt: pkt.msglen),
    672                     _TLSSignatureField("sig", None,
    673                         length_from=lambda pkt: pkt.msglen - len(pkt.params)) ]
    674 
    675     def build(self, *args, **kargs):
    676         """
    677         We overload build() method in order to provide a valid default value
    678         for params based on TLS session if not provided. This cannot be done by
    679         overriding i2m() because the method is called on a copy of the packet.
    680 
    681         The 'params' field is built according to key_exchange.server_kx_msg_cls
    682         which should have been set after receiving a cipher suite in a
    683         previous ServerHello. Usual cases are:
    684         - None: for RSA encryption or fixed FF/ECDH. This should never happen,
    685           as no ServerKeyExchange should be generated in the first place.
    686         - ServerDHParams: for ephemeral FFDH. In that case, the parameter to
    687           server_kx_msg_cls does not matter.
    688         - ServerECDH*Params: for ephemeral ECDH. There are actually three
    689           classes, which are dispatched by _tls_server_ecdh_cls_guess on
    690           the first byte retrieved. The default here is b"\03", which
    691           corresponds to ServerECDHNamedCurveParams (implicit curves).
    692 
    693         When the Server*DHParams are built via .fill_missing(), the session
    694         server_kx_privkey will be updated accordingly.
    695         """
    696         fval = self.getfieldval("params")
    697         if fval is None:
    698             s = self.tls_session
    699             if s.pwcs:
    700                 if s.pwcs.key_exchange.export:
    701                     cls = ServerRSAParams(tls_session=s)
    702                 else:
    703                     cls = s.pwcs.key_exchange.server_kx_msg_cls(b"\x03")
    704                     cls = cls(tls_session=s)
    705                 try:
    706                     cls.fill_missing()
    707                 except:
    708                     pass
    709             else:
    710                 cls = Raw()
    711             self.params = cls
    712 
    713         fval = self.getfieldval("sig")
    714         if fval is None:
    715             s = self.tls_session
    716             if s.pwcs:
    717                 if not s.pwcs.key_exchange.anonymous:
    718                     p = self.params
    719                     if p is None:
    720                         p = b""
    721                     m = s.client_random + s.server_random + raw(p)
    722                     cls = _TLSSignature(tls_session=s)
    723                     cls._update_sig(m, s.server_key)
    724                 else:
    725                     cls = Raw()
    726             else:
    727                 cls = Raw()
    728             self.sig = cls
    729 
    730         return _TLSHandshake.build(self, *args, **kargs)
    731 
    732     def post_dissection(self, pkt):
    733         """
    734         While previously dissecting Server*DHParams, the session
    735         server_kx_pubkey should have been updated.
    736 
    737         XXX Add a 'fixed_dh' OR condition to the 'anonymous' test.
    738         """
    739         s = self.tls_session
    740         if s.prcs and s.prcs.key_exchange.no_ske:
    741             pkt_info = pkt.firstlayer().summary()
    742             log_runtime.info("TLS: useless ServerKeyExchange [%s]", pkt_info)
    743         if (s.prcs and
    744             not s.prcs.key_exchange.anonymous and
    745             s.client_random and s.server_random and
    746             s.server_certs and len(s.server_certs) > 0):
    747             m = s.client_random + s.server_random + raw(self.params)
    748             sig_test = self.sig._verify_sig(m, s.server_certs[0])
    749             if not sig_test:
    750                 pkt_info = pkt.firstlayer().summary()
    751                 log_runtime.info("TLS: invalid ServerKeyExchange signature [%s]", pkt_info)
    752 
    753 
    754 ###############################################################################
    755 ### CertificateRequest                                                      ###
    756 ###############################################################################
    757 
    758 _tls_client_certificate_types =  {  1: "rsa_sign",
    759                                     2: "dss_sign",
    760                                     3: "rsa_fixed_dh",
    761                                     4: "dss_fixed_dh",
    762                                     5: "rsa_ephemeral_dh_RESERVED",
    763                                     6: "dss_ephemeral_dh_RESERVED",
    764                                    20: "fortezza_dms_RESERVED",
    765                                    64: "ecdsa_sign",
    766                                    65: "rsa_fixed_ecdh",
    767                                    66: "ecdsa_fixed_ecdh" }
    768 
    769 
    770 class _CertTypesField(_CipherSuitesField):
    771     pass
    772 
    773 class _CertAuthoritiesField(StrLenField):
    774     """
    775     XXX Rework this with proper ASN.1 parsing.
    776     """
    777     islist = 1
    778 
    779     def getfield(self, pkt, s):
    780         l = self.length_from(pkt)
    781         return s[l:], self.m2i(pkt, s[:l])
    782 
    783     def m2i(self, pkt, m):
    784         res = []
    785         while len(m) > 1:
    786             l = struct.unpack("!H", m[:2])[0]
    787             if len(m) < l + 2:
    788                 res.append((l, m[2:]))
    789                 break
    790             dn = m[2:2+l]
    791             res.append((l, dn))
    792             m = m[2+l:]
    793         return res
    794 
    795     def i2m(self, pkt, i):
    796         return b"".join(map(lambda x_y: struct.pack("!H", x_y[0]) + x_y[1], i))
    797 
    798     def addfield(self, pkt, s, val):
    799         return s + self.i2m(pkt, val)
    800 
    801     def i2len(self, pkt, val):
    802         if val is None:
    803             return 0
    804         else:
    805             return len(self.i2m(pkt, val))
    806 
    807 
    808 class TLSCertificateRequest(_TLSHandshake):
    809     name = "TLS Handshake - Certificate Request"
    810     fields_desc = [ ByteEnumField("msgtype", 13, _tls_handshake_type),
    811                     ThreeBytesField("msglen", None),
    812                     FieldLenField("ctypeslen", None, fmt="B",
    813                                   length_of="ctypes"),
    814                     _CertTypesField("ctypes", [1, 64],
    815                                     _tls_client_certificate_types,
    816                                     itemfmt="!B",
    817                                     length_from=lambda pkt: pkt.ctypeslen),
    818                     SigAndHashAlgsLenField("sig_algs_len", None,
    819                                            length_of="sig_algs"),
    820                     SigAndHashAlgsField("sig_algs", [0x0403, 0x0401, 0x0201],
    821                                 EnumField("hash_sig", None, _tls_hash_sig),
    822                                 length_from=lambda pkt: pkt.sig_algs_len),
    823                     FieldLenField("certauthlen", None, fmt="!H",
    824                                   length_of="certauth"),
    825                     _CertAuthoritiesField("certauth", [],
    826                                 length_from=lambda pkt: pkt.certauthlen) ]
    827 
    828 
    829 ###############################################################################
    830 ### ServerHelloDone                                                         ###
    831 ###############################################################################
    832 
    833 class TLSServerHelloDone(_TLSHandshake):
    834     name = "TLS Handshake - Server Hello Done"
    835     fields_desc = [ ByteEnumField("msgtype", 14, _tls_handshake_type),
    836                     ThreeBytesField("msglen", None) ]
    837 
    838 
    839 ###############################################################################
    840 ### CertificateVerify                                                       ###
    841 ###############################################################################
    842 
    843 class TLSCertificateVerify(_TLSHandshake):
    844     name = "TLS Handshake - Certificate Verify"
    845     fields_desc = [ ByteEnumField("msgtype", 15, _tls_handshake_type),
    846                     ThreeBytesField("msglen", None),
    847                     _TLSSignatureField("sig", None,
    848                                  length_from=lambda pkt: pkt.msglen) ]
    849 
    850     def build(self, *args, **kargs):
    851         sig = self.getfieldval("sig")
    852         if sig is None:
    853             s = self.tls_session
    854             m = b"".join(s.handshake_messages)
    855             if s.tls_version >= 0x0304:
    856                 if s.connection_end == "client":
    857                     context_string = "TLS 1.3, client CertificateVerify"
    858                 elif s.connection_end == "server":
    859                     context_string = "TLS 1.3, server CertificateVerify"
    860                 m = b"\x20"*64 + context_string + b"\x00" + s.wcs.hash.digest(m)
    861             self.sig = _TLSSignature(tls_session=s)
    862             if s.connection_end == "client":
    863                 self.sig._update_sig(m, s.client_key)
    864             elif s.connection_end == "server":
    865                 # should be TLS 1.3 only
    866                 self.sig._update_sig(m, s.server_key)
    867         return _TLSHandshake.build(self, *args, **kargs)
    868 
    869     def post_dissection(self, pkt):
    870         s = self.tls_session
    871         m = b"".join(s.handshake_messages)
    872         if s.tls_version >= 0x0304:
    873             if s.connection_end == "client":
    874                 context_string = b"TLS 1.3, server CertificateVerify"
    875             elif s.connection_end == "server":
    876                 context_string = b"TLS 1.3, client CertificateVerify"
    877             m = b"\x20"*64 + context_string + b"\x00" + s.rcs.hash.digest(m)
    878 
    879         if s.connection_end == "server":
    880             if s.client_certs and len(s.client_certs) > 0:
    881                 sig_test = self.sig._verify_sig(m, s.client_certs[0])
    882                 if not sig_test:
    883                     pkt_info = pkt.firstlayer().summary()
    884                     log_runtime.info("TLS: invalid CertificateVerify signature [%s]", pkt_info)
    885         elif s.connection_end == "client":
    886             # should be TLS 1.3 only
    887             if s.server_certs and len(s.server_certs) > 0:
    888                 sig_test = self.sig._verify_sig(m, s.server_certs[0])
    889                 if not sig_test:
    890                     pkt_info = pkt.firstlayer().summary()
    891                     log_runtime.info("TLS: invalid CertificateVerify signature [%s]", pkt_info)
    892 
    893 
    894 ###############################################################################
    895 ### ClientKeyExchange                                                       ###
    896 ###############################################################################
    897 
    898 class _TLSCKExchKeysField(PacketField):
    899     __slots__ = ["length_from"]
    900     holds_packet = 1
    901     def __init__(self, name, length_from=None, remain=0):
    902         self.length_from = length_from
    903         PacketField.__init__(self, name, None, None, remain=remain)
    904 
    905     def m2i(self, pkt, m):
    906         """
    907         The client_kx_msg may be either None, EncryptedPreMasterSecret
    908         (for RSA encryption key exchange), ClientDiffieHellmanPublic,
    909         or ClientECDiffieHellmanPublic. When either one of them gets
    910         dissected, the session context is updated accordingly.
    911         """
    912         l = self.length_from(pkt)
    913         tbd, rem = m[:l], m[l:]
    914 
    915         s = pkt.tls_session
    916         cls = None
    917 
    918         if s.prcs and s.prcs.key_exchange:
    919             cls = s.prcs.key_exchange.client_kx_msg_cls
    920 
    921         if cls is None:
    922             return Raw(tbd)/Padding(rem)
    923 
    924         return cls(tbd, tls_session=s)/Padding(rem)
    925 
    926 
    927 class TLSClientKeyExchange(_TLSHandshake):
    928     """
    929     This class mostly works like TLSServerKeyExchange and its 'params' field.
    930     """
    931     name = "TLS Handshake - Client Key Exchange"
    932     fields_desc = [ ByteEnumField("msgtype", 16, _tls_handshake_type),
    933                     ThreeBytesField("msglen", None),
    934                     _TLSCKExchKeysField("exchkeys",
    935                                         length_from = lambda pkt: pkt.msglen) ]
    936 
    937     def build(self, *args, **kargs):
    938         fval = self.getfieldval("exchkeys")
    939         if fval is None:
    940             s = self.tls_session
    941             if s.prcs:
    942                 cls = s.prcs.key_exchange.client_kx_msg_cls
    943                 cls = cls(tls_session=s)
    944             else:
    945                 cls = Raw()
    946             self.exchkeys = cls
    947         return _TLSHandshake.build(self, *args, **kargs)
    948 
    949 
    950 ###############################################################################
    951 ### Finished                                                                ###
    952 ###############################################################################
    953 
    954 class _VerifyDataField(StrLenField):
    955     def getfield(self, pkt, s):
    956         if pkt.tls_session.tls_version == 0x0300:
    957             sep = 36
    958         elif pkt.tls_session.tls_version >= 0x0304:
    959             sep = pkt.tls_session.rcs.hash.hash_len
    960         else:
    961             sep = 12
    962         return s[sep:], s[:sep]
    963 
    964 class TLSFinished(_TLSHandshake):
    965     name = "TLS Handshake - Finished"
    966     fields_desc = [ ByteEnumField("msgtype", 20, _tls_handshake_type),
    967                     ThreeBytesField("msglen", None),
    968                     _VerifyDataField("vdata", None) ]
    969 
    970     def build(self, *args, **kargs):
    971         fval = self.getfieldval("vdata")
    972         if fval is None:
    973             s = self.tls_session
    974             handshake_msg = b"".join(s.handshake_messages)
    975             con_end = s.connection_end
    976             if s.tls_version < 0x0304:
    977                 ms = s.master_secret
    978                 self.vdata = s.wcs.prf.compute_verify_data(con_end, "write",
    979                                                            handshake_msg, ms)
    980             else:
    981                 self.vdata = s.compute_tls13_verify_data(con_end, "write")
    982         return _TLSHandshake.build(self, *args, **kargs)
    983 
    984     def post_dissection(self, pkt):
    985         s = self.tls_session
    986         if not s.frozen:
    987             handshake_msg = b"".join(s.handshake_messages)
    988             if s.tls_version < 0x0304 and s.master_secret is not None:
    989                 ms = s.master_secret
    990                 con_end = s.connection_end
    991                 verify_data = s.rcs.prf.compute_verify_data(con_end, "read",
    992                                                             handshake_msg, ms)
    993                 if self.vdata != verify_data:
    994                     pkt_info = pkt.firstlayer().summary()
    995                     log_runtime.info("TLS: invalid Finished received [%s]", pkt_info)
    996             elif s.tls_version >= 0x0304:
    997                 con_end = s.connection_end
    998                 verify_data = s.compute_tls13_verify_data(con_end, "read")
    999                 if self.vdata != verify_data:
   1000                     pkt_info = pkt.firstlayer().summary()
   1001                     log_runtime.info("TLS: invalid Finished received [%s]", pkt_info)
   1002 
   1003     def post_build_tls_session_update(self, msg_str):
   1004         self.tls_session_update(msg_str)
   1005         s = self.tls_session
   1006         if s.tls_version >= 0x0304:
   1007             s.pwcs = writeConnState(ciphersuite=type(s.wcs.ciphersuite),
   1008                                     connection_end=s.connection_end,
   1009                                     tls_version=s.tls_version)
   1010             s.triggered_pwcs_commit = True
   1011             if s.connection_end == "server":
   1012                 s.compute_tls13_traffic_secrets()
   1013             elif s.connection_end == "client":
   1014                 s.compute_tls13_traffic_secrets_end()
   1015                 s.compute_tls13_resumption_secret()
   1016 
   1017     def post_dissection_tls_session_update(self, msg_str):
   1018         self.tls_session_update(msg_str)
   1019         s = self.tls_session
   1020         if s.tls_version >= 0x0304:
   1021             s.prcs = readConnState(ciphersuite=type(s.rcs.ciphersuite),
   1022                                    connection_end=s.connection_end,
   1023                                    tls_version=s.tls_version)
   1024             s.triggered_prcs_commit = True
   1025             if s.connection_end == "client":
   1026                 s.compute_tls13_traffic_secrets()
   1027             elif s.connection_end == "server":
   1028                 s.compute_tls13_traffic_secrets_end()
   1029                 s.compute_tls13_resumption_secret()
   1030 
   1031 
   1032 ## Additional handshake messages
   1033 
   1034 ###############################################################################
   1035 ### HelloVerifyRequest                                                      ###
   1036 ###############################################################################
   1037 
   1038 class TLSHelloVerifyRequest(_TLSHandshake):
   1039     """
   1040     Defined for DTLS, see RFC 6347.
   1041     """
   1042     name = "TLS Handshake - Hello Verify Request"
   1043     fields_desc = [ ByteEnumField("msgtype", 21, _tls_handshake_type),
   1044                     ThreeBytesField("msglen", None),
   1045                     FieldLenField("cookielen", None,
   1046                                   fmt="B", length_of="cookie"),
   1047                     StrLenField("cookie", "",
   1048                                 length_from=lambda pkt: pkt.cookielen) ]
   1049 
   1050 
   1051 ###############################################################################
   1052 ### CertificateURL                                                          ###
   1053 ###############################################################################
   1054 
   1055 _tls_cert_chain_types = { 0: "individual_certs",
   1056                           1: "pkipath" }
   1057 
   1058 class URLAndOptionalHash(Packet):
   1059     name = "URLAndOptionHash structure for TLSCertificateURL"
   1060     fields_desc = [ FieldLenField("urllen", None, length_of="url"),
   1061                     StrLenField("url", "",
   1062                                 length_from=lambda pkt: pkt.urllen),
   1063                     FieldLenField("hash_present", None,
   1064                                   fmt="B", length_of="hash",
   1065                                   adjust=lambda pkt,x: int(math.ceil(x/20.))),
   1066                     StrLenField("hash", "",
   1067                                 length_from=lambda pkt: 20*pkt.hash_present) ]
   1068     def guess_payload_class(self, p):
   1069         return Padding
   1070 
   1071 class TLSCertificateURL(_TLSHandshake):
   1072     """
   1073     Defined in RFC 4366. PkiPath structure of section 8 is not implemented yet.
   1074     """
   1075     name = "TLS Handshake - Certificate URL"
   1076     fields_desc = [ ByteEnumField("msgtype", 21, _tls_handshake_type),
   1077                     ThreeBytesField("msglen", None),
   1078                     ByteEnumField("certchaintype", None, _tls_cert_chain_types),
   1079                     FieldLenField("uahlen", None, length_of="uah"),
   1080                     PacketListField("uah", [], URLAndOptionalHash,
   1081                                     length_from=lambda pkt: pkt.uahlen) ]
   1082 
   1083 
   1084 ###############################################################################
   1085 ### CertificateStatus                                                       ###
   1086 ###############################################################################
   1087 
   1088 class ThreeBytesLenField(FieldLenField):
   1089     def __init__(self, name, default,  length_of=None, adjust=lambda pkt, x:x):
   1090         FieldLenField.__init__(self, name, default, length_of=length_of,
   1091                                fmt='!I', adjust=adjust)
   1092     def i2repr(self, pkt, x):
   1093         if x is None:
   1094             return 0
   1095         return repr(self.i2h(pkt,x))
   1096     def addfield(self, pkt, s, val):
   1097         return s+struct.pack(self.fmt, self.i2m(pkt,val))[1:4]
   1098     def getfield(self, pkt, s):
   1099         return  s[3:], self.m2i(pkt, struct.unpack(self.fmt, b"\x00"+s[:3])[0])
   1100 
   1101 _cert_status_cls  = { 1: OCSP_Response }
   1102 
   1103 class _StatusField(PacketField):
   1104     def m2i(self, pkt, m):
   1105         idtype = pkt.status_type
   1106         cls = self.cls
   1107         if idtype in _cert_status_cls:
   1108             cls = _cert_status_cls[idtype]
   1109         return cls(m)
   1110 
   1111 class TLSCertificateStatus(_TLSHandshake):
   1112     name = "TLS Handshake - Certificate Status"
   1113     fields_desc = [ ByteEnumField("msgtype", 22, _tls_handshake_type),
   1114                     ThreeBytesField("msglen", None),
   1115                     ByteEnumField("status_type", 1, _cert_status_type),
   1116                     ThreeBytesLenField("responselen", None,
   1117                                        length_of="response"),
   1118                     _StatusField("response", None, Raw) ]
   1119 
   1120 
   1121 ###############################################################################
   1122 ### SupplementalData                                                        ###
   1123 ###############################################################################
   1124 
   1125 class SupDataEntry(Packet):
   1126     name = "Supplemental Data Entry - Generic"
   1127     fields_desc = [ ShortField("sdtype", None),
   1128                     FieldLenField("len", None, length_of="data"),
   1129                     StrLenField("data", "",
   1130                                 length_from=lambda pkt:pkt.len) ]
   1131     def guess_payload_class(self, p):
   1132         return Padding
   1133 
   1134 class UserMappingData(Packet):
   1135     name = "User Mapping Data"
   1136     fields_desc = [ ByteField("version", None),
   1137                     FieldLenField("len", None, length_of="data"),
   1138                     StrLenField("data", "",
   1139                                 length_from=lambda pkt: pkt.len)]
   1140     def guess_payload_class(self, p):
   1141         return Padding
   1142 
   1143 class SupDataEntryUM(Packet):
   1144     name = "Supplemental Data Entry - User Mapping"
   1145     fields_desc = [ ShortField("sdtype", None),
   1146                     FieldLenField("len", None, length_of="data",
   1147                                   adjust=lambda pkt, x: x+2),
   1148                     FieldLenField("dlen", None, length_of="data"),
   1149                     PacketListField("data", [], UserMappingData,
   1150                                     length_from=lambda pkt:pkt.dlen) ]
   1151     def guess_payload_class(self, p):
   1152         return Padding
   1153 
   1154 class TLSSupplementalData(_TLSHandshake):
   1155     name = "TLS Handshake - Supplemental Data"
   1156     fields_desc = [ ByteEnumField("msgtype", 23, _tls_handshake_type),
   1157                     ThreeBytesField("msglen", None),
   1158                     ThreeBytesLenField("sdatalen", None, length_of="sdata"),
   1159                     PacketListField("sdata", [], SupDataEntry,
   1160                                     length_from=lambda pkt: pkt.sdatalen) ]
   1161 
   1162 
   1163 ###############################################################################
   1164 ### NewSessionTicket                                                        ###
   1165 ###############################################################################
   1166 
   1167 class TLSNewSessionTicket(_TLSHandshake):
   1168     """
   1169     XXX When knowing the right secret, we should be able to read the ticket.
   1170     """
   1171     name = "TLS Handshake - New Session Ticket"
   1172     fields_desc = [ ByteEnumField("msgtype", 4, _tls_handshake_type),
   1173                     ThreeBytesField("msglen", None),
   1174                     IntField("lifetime", 0xffffffff),
   1175                     FieldLenField("ticketlen", None, length_of="ticket"),
   1176                     StrLenField("ticket", "",
   1177                                 length_from=lambda pkt: pkt.ticketlen) ]
   1178 
   1179     @classmethod
   1180     def dispatch_hook(cls, _pkt=None, *args, **kargs):
   1181         s = kargs.get("tls_session", None)
   1182         if s and s.tls_version >= 0x0304:
   1183             return TLS13NewSessionTicket
   1184         return TLSNewSessionTicket
   1185 
   1186     def post_dissection_tls_session_update(self, msg_str):
   1187         self.tls_session_update(msg_str)
   1188         if self.tls_session.connection_end == "client":
   1189             self.tls_session.client_session_ticket = self.ticket
   1190 
   1191 
   1192 class TLS13NewSessionTicket(_TLSHandshake):
   1193     """
   1194     Uncomment the TicketField line for parsing a RFC 5077 ticket.
   1195     """
   1196     name = "TLS Handshake - New Session Ticket"
   1197     fields_desc = [ ByteEnumField("msgtype", 4, _tls_handshake_type),
   1198                     ThreeBytesField("msglen", None),
   1199                     IntField("ticket_lifetime", 0xffffffff),
   1200                     IntField("ticket_age_add", 0),
   1201                     FieldLenField("ticketlen", None, length_of="ticket"),
   1202                     #TicketField("ticket", "",
   1203                     StrLenField("ticket", "",
   1204                                 length_from=lambda pkt: pkt.ticketlen),
   1205                     _ExtensionsLenField("extlen", None, length_of="ext"),
   1206                     _ExtensionsField("ext", None,
   1207                                  length_from=lambda pkt: (pkt.msglen -
   1208                                                           (pkt.ticketlen or 0) -
   1209                                                           12)) ]
   1210 
   1211     def post_dissection_tls_session_update(self, msg_str):
   1212         self.tls_session_update(msg_str)
   1213         if self.tls_session.connection_end == "client":
   1214             self.tls_session.client_session_ticket = self.ticket
   1215 
   1216 
   1217 ###############################################################################
   1218 ### All handshake messages defined in this module                           ###
   1219 ###############################################################################
   1220 
   1221 _tls_handshake_cls = { 0: TLSHelloRequest,          1: TLSClientHello,
   1222                        2: TLSServerHello,           3: TLSHelloVerifyRequest,
   1223                        4: TLSNewSessionTicket,      6: TLSHelloRetryRequest,
   1224                        8: TLSEncryptedExtensions,   11: TLSCertificate,
   1225                        12: TLSServerKeyExchange,    13: TLSCertificateRequest,
   1226                        14: TLSServerHelloDone,      15: TLSCertificateVerify,
   1227                        16: TLSClientKeyExchange,    20: TLSFinished,
   1228                        21: TLSCertificateURL,       22: TLSCertificateStatus,
   1229                        23: TLSSupplementalData }
   1230 
   1231