• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard
5#               2015, 2016, 2017 Maxence Tury
6#               2019 Romain Perez
7
8"""
9TLS handshake fields & logic.
10
11This module covers the handshake TLS subprotocol, except for the key exchange
12mechanisms which are addressed with keyexchange.py.
13"""
14
15import math
16import os
17import struct
18
19from scapy.error import log_runtime, warning
20from scapy.fields import (
21    ByteEnumField,
22    ByteField,
23    Field,
24    FieldLenField,
25    IntField,
26    PacketField,
27    PacketLenField,
28    PacketListField,
29    ShortEnumField,
30    ShortField,
31    StrFixedLenField,
32    StrLenField,
33    ThreeBytesField,
34    UTCTimeField,
35)
36
37from scapy.compat import hex_bytes, orb, raw
38from scapy.config import conf
39from scapy.packet import Packet, Raw, Padding
40from scapy.utils import randstring, repr_hex
41from scapy.layers.x509 import OCSP_Response
42from scapy.layers.tls.cert import Cert
43from scapy.layers.tls.basefields import (_tls_version, _TLSVersionField,
44                                         _TLSClientVersionField)
45from scapy.layers.tls.extensions import (_ExtensionsLenField, _ExtensionsField,
46                                         _cert_status_type,
47                                         TLS_Ext_PostHandshakeAuth,
48                                         TLS_Ext_SupportedVersion_CH,
49                                         TLS_Ext_SignatureAlgorithms,
50                                         TLS_Ext_SupportedVersion_SH,
51                                         TLS_Ext_EarlyDataIndication,
52                                         _tls_hello_retry_magic,
53                                         TLS_Ext_ExtendedMasterSecret,
54                                         TLS_Ext_EncryptThenMAC)
55from scapy.layers.tls.keyexchange import (_TLSSignature, _TLSServerParamsField,
56                                          _TLSSignatureField, ServerRSAParams,
57                                          SigAndHashAlgsField, _tls_hash_sig,
58                                          SigAndHashAlgsLenField)
59from scapy.layers.tls.session import (_GenericTLSSessionInheritance,
60                                      readConnState, writeConnState)
61from scapy.layers.tls.keyexchange_tls13 import TLS_Ext_PreSharedKey_CH
62from scapy.layers.tls.crypto.compression import (_tls_compression_algs,
63                                                 _tls_compression_algs_cls,
64                                                 Comp_NULL, _GenericComp,
65                                                 _GenericCompMetaclass)
66from scapy.layers.tls.crypto.suites import (_tls_cipher_suites,
67                                            _tls_cipher_suites_cls,
68                                            _GenericCipherSuite,
69                                            _GenericCipherSuiteMetaclass)
70from scapy.layers.tls.crypto.hkdf import TLS13_HKDF
71
72if conf.crypto_valid:
73    from cryptography.hazmat.backends import default_backend
74    from cryptography.hazmat.primitives import hashes
75
76
77###############################################################################
78#   Generic TLS Handshake message                                             #
79###############################################################################
80
81_tls_handshake_type = {0: "hello_request", 1: "client_hello",
82                       2: "server_hello", 3: "hello_verify_request",
83                       4: "session_ticket", 6: "hello_retry_request",
84                       8: "encrypted_extensions", 11: "certificate",
85                       12: "server_key_exchange", 13: "certificate_request",
86                       14: "server_hello_done", 15: "certificate_verify",
87                       16: "client_key_exchange", 20: "finished",
88                       21: "certificate_url", 22: "certificate_status",
89                       23: "supplemental_data", 24: "key_update"}
90
91
92class _TLSHandshake(_GenericTLSSessionInheritance):
93    """
94    Inherited by other Handshake classes to get post_build().
95    Also used as a fallback for unknown TLS Handshake packets.
96    """
97    name = "TLS Handshake Generic message"
98    fields_desc = [ByteEnumField("msgtype", None, _tls_handshake_type),
99                   ThreeBytesField("msglen", None),
100                   StrLenField("msg", "",
101                               length_from=lambda pkt: pkt.msglen)]
102
103    def post_build(self, p, pay):
104        tmp_len = len(p)
105        if self.msglen is None:
106            l2 = tmp_len - 4
107            p = struct.pack("!I", (orb(p[0]) << 24) | l2) + p[4:]
108        return p + pay
109
110    def guess_payload_class(self, p):
111        return conf.padding_layer
112
113    def tls_session_update(self, msg_str):
114        """
115        Covers both post_build- and post_dissection- context updates.
116        """
117        # RFC8446 sect 4.4.1
118        # "Note, however, that subsequent post-handshake authentications do not
119        # include each other, just the messages through the end of the main
120        # handshake."
121        if self.tls_session.post_handshake:
122            self.tls_session.post_handshake_messages.append(msg_str)
123        else:
124            self.tls_session.handshake_messages.append(msg_str)
125            self.tls_session.handshake_messages_parsed.append(self)
126
127
128###############################################################################
129#   HelloRequest                                                              #
130###############################################################################
131
132class TLSHelloRequest(_TLSHandshake):
133    name = "TLS Handshake - Hello Request"
134    fields_desc = [ByteEnumField("msgtype", 0, _tls_handshake_type),
135                   ThreeBytesField("msglen", None)]
136
137    def tls_session_update(self, msg_str):
138        """
139        Message should not be added to the list of handshake messages
140        that will be hashed in the finished and certificate verify messages.
141        """
142        return
143
144
145###############################################################################
146#   ClientHello fields                                                        #
147###############################################################################
148
149class _GMTUnixTimeField(UTCTimeField):
150    """
151    "The current time and date in standard UNIX 32-bit format (seconds since
152     the midnight starting Jan 1, 1970, GMT, ignoring leap seconds)."
153    """
154
155    def i2h(self, pkt, x):
156        if x is not None:
157            return x
158        return 0
159
160    def i2m(self, pkt, x):
161        return int(x) if x is not None else 0
162
163
164class _TLSRandomBytesField(StrFixedLenField):
165    def i2repr(self, pkt, x):
166        if x is None:
167            return repr(x)
168        return repr_hex(self.i2h(pkt, x))
169
170
171class _SessionIDField(StrLenField):
172    """
173    opaque SessionID<0..32>; section 7.4.1.2 of RFC 4346
174    """
175    pass
176
177
178class _CipherSuitesField(StrLenField):
179    __slots__ = ["itemfmt", "itemsize", "i2s", "s2i"]
180    islist = 1
181
182    def __init__(self, name, default, dico, length_from=None, itemfmt="!H"):
183        StrLenField.__init__(self, name, default, length_from=length_from)
184        self.itemfmt = itemfmt
185        self.itemsize = struct.calcsize(itemfmt)
186        i2s = self.i2s = {}
187        s2i = self.s2i = {}
188        for k in dico.keys():
189            i2s[k] = dico[k]
190            s2i[dico[k]] = k
191
192    def any2i_one(self, pkt, x):
193        if isinstance(x, (_GenericCipherSuite, _GenericCipherSuiteMetaclass)):
194            x = x.val
195        if isinstance(x, bytes):
196            x = self.s2i[x]
197        return x
198
199    def i2repr_one(self, pkt, x):
200        fmt = "0x%%0%dx" % self.itemsize
201        return self.i2s.get(x, fmt % x)
202
203    def any2i(self, pkt, x):
204        if x is None:
205            return None
206        if not isinstance(x, list):
207            x = [x]
208        return [self.any2i_one(pkt, z) for z in x]
209
210    def i2repr(self, pkt, x):
211        if x is None:
212            return "None"
213        tmp_len = [self.i2repr_one(pkt, z) for z in x]
214        if len(tmp_len) == 1:
215            tmp_len = tmp_len[0]
216        else:
217            tmp_len = "[%s]" % ", ".join(tmp_len)
218        return tmp_len
219
220    def i2m(self, pkt, val):
221        if val is None:
222            val = []
223        return b"".join(struct.pack(self.itemfmt, x) for x in val)
224
225    def m2i(self, pkt, m):
226        res = []
227        itemlen = struct.calcsize(self.itemfmt)
228        while m:
229            res.append(struct.unpack(self.itemfmt, m[:itemlen])[0])
230            m = m[itemlen:]
231        return res
232
233    def i2len(self, pkt, i):
234        if i is None:
235            return 0
236        return len(i) * self.itemsize
237
238
239class _CompressionMethodsField(_CipherSuitesField):
240
241    def any2i_one(self, pkt, x):
242        if isinstance(x, (_GenericComp, _GenericCompMetaclass)):
243            x = x.val
244        if isinstance(x, str):
245            x = self.s2i[x]
246        return x
247
248
249###############################################################################
250#   ClientHello                                                               #
251###############################################################################
252
253class TLSClientHello(_TLSHandshake):
254    """
255    TLS ClientHello, with abilities to handle extensions.
256
257    The Random structure follows the RFC 5246: while it is 32-byte long,
258    many implementations use the first 4 bytes as a gmt_unix_time, and then
259    the remaining 28 byts should be completely random. This was designed in
260    order to (sort of) mitigate broken RNGs. If you prefer to show the full
261    32 random bytes without any GMT time, just comment in/out the lines below.
262    """
263    name = "TLS Handshake - Client Hello"
264    fields_desc = [ByteEnumField("msgtype", 1, _tls_handshake_type),
265                   ThreeBytesField("msglen", None),
266                   _TLSClientVersionField("version", None, _tls_version),
267
268                   # _TLSRandomBytesField("random_bytes", None, 32),
269                   _GMTUnixTimeField("gmt_unix_time", None),
270                   _TLSRandomBytesField("random_bytes", None, 28),
271
272                   FieldLenField("sidlen", None, fmt="B", length_of="sid"),
273                   _SessionIDField("sid", "",
274                                   length_from=lambda pkt: pkt.sidlen),
275
276                   FieldLenField("cipherslen", None, fmt="!H",
277                                 length_of="ciphers"),
278                   _CipherSuitesField("ciphers", None,
279                                      _tls_cipher_suites, itemfmt="!H",
280                                      length_from=lambda pkt: pkt.cipherslen),
281
282                   FieldLenField("complen", None, fmt="B", length_of="comp"),
283                   _CompressionMethodsField("comp", [0],
284                                            _tls_compression_algs,
285                                            itemfmt="B",
286                                            length_from=lambda pkt: pkt.complen),  # noqa: E501
287
288                   _ExtensionsLenField("extlen", None, length_of="ext"),
289                   _ExtensionsField("ext", None,
290                                    length_from=lambda pkt: (pkt.msglen -
291                                                             (pkt.sidlen or 0) -  # noqa: E501
292                                                             (pkt.cipherslen or 0) -  # noqa: E501
293                                                             (pkt.complen or 0) -  # noqa: E501
294                                                             40))]
295
296    def post_build(self, p, pay):
297        if self.random_bytes is None:
298            p = p[:10] + randstring(28) + p[10 + 28:]
299
300        # if no ciphersuites were provided, we add a few usual, supported
301        # ciphersuites along with the appropriate extensions
302        if self.ciphers is None:
303            cipherstart = 39 + (self.sidlen or 0)
304            s = b"001ac02bc023c02fc027009e0067009c003cc009c0130033002f000a"
305            p = p[:cipherstart] + hex_bytes(s) + p[cipherstart + 2:]
306            if self.ext is None:
307                ext_len = b'\x00\x2c'
308                ext_reneg = b'\xff\x01\x00\x01\x00'
309                ext_sn = b'\x00\x00\x00\x0f\x00\r\x00\x00\nsecdev.org'
310                ext_sigalg = b'\x00\r\x00\x08\x00\x06\x04\x03\x04\x01\x02\x01'
311                ext_supgroups = b'\x00\n\x00\x04\x00\x02\x00\x17'
312                p += ext_len + ext_reneg + ext_sn + ext_sigalg + ext_supgroups
313
314        return super(TLSClientHello, self).post_build(p, pay)
315
316    def tls_session_update(self, msg_str):
317        """
318        Either for parsing or building, we store the client_random
319        along with the raw string representing this handshake message.
320        """
321        super(TLSClientHello, self).tls_session_update(msg_str)
322        s = self.tls_session
323        s.advertised_tls_version = self.version
324        # This ClientHello could be a 1.3 one. Let's store the sid
325        # in all cases
326        if self.sidlen and self.sidlen > 0:
327            s.sid = self.sid
328        self.random_bytes = msg_str[10:38]
329        s.client_random = (struct.pack('!I', self.gmt_unix_time) +
330                           self.random_bytes)
331
332        # No distinction between a TLS 1.2 ClientHello and a TLS
333        # 1.3 ClientHello when dissecting : TLS 1.3 CH will be
334        # parsed as TLSClientHello
335        if self.ext:
336            for e in self.ext:
337                if isinstance(e, TLS_Ext_SupportedVersion_CH):
338                    for ver in sorted(e.versions, reverse=True):
339                        # RFC 8701: GREASE of TLS will send unknown versions
340                        # here. We have to ignore them
341                        if ver in _tls_version:
342                            s.advertised_tls_version = ver
343                            break
344                    if s.sid:
345                        s.middlebox_compatibility = True
346                if isinstance(e, TLS_Ext_SignatureAlgorithms):
347                    s.advertised_sig_algs = e.sig_algs
348                if isinstance(e, TLS_Ext_PostHandshakeAuth):
349                    s.post_handshake_auth = True
350
351
352class TLS13ClientHello(_TLSHandshake):
353    """
354    TLS 1.3 ClientHello, with abilities to handle extensions.
355
356    The Random structure is 32 random bytes without any GMT time
357    """
358    name = "TLS 1.3 Handshake - Client Hello"
359    fields_desc = [ByteEnumField("msgtype", 1, _tls_handshake_type),
360                   ThreeBytesField("msglen", None),
361                   _TLSClientVersionField("version", None, _tls_version),
362
363                   _TLSRandomBytesField("random_bytes", None, 32),
364
365                   FieldLenField("sidlen", None, fmt="B", length_of="sid"),
366                   _SessionIDField("sid", "",
367                                   length_from=lambda pkt: pkt.sidlen),
368
369                   FieldLenField("cipherslen", None, fmt="!H",
370                                 length_of="ciphers"),
371                   _CipherSuitesField("ciphers", None,
372                                      _tls_cipher_suites, itemfmt="!H",
373                                      length_from=lambda pkt: pkt.cipherslen),
374
375                   FieldLenField("complen", None, fmt="B", length_of="comp"),
376                   _CompressionMethodsField("comp", [0],
377                                            _tls_compression_algs,
378                                            itemfmt="B",
379                                            length_from=lambda pkt: pkt.complen),  # noqa: E501
380
381                   _ExtensionsLenField("extlen", None, length_of="ext"),
382                   _ExtensionsField("ext", None,
383                                    length_from=lambda pkt: (pkt.msglen -
384                                                             (pkt.sidlen or 0) -  # noqa: E501
385                                                             (pkt.cipherslen or 0) -  # noqa: E501
386                                                             (pkt.complen or 0) -  # noqa: E501
387                                                             40))]
388
389    def post_build(self, p, pay):
390        if self.random_bytes is None:
391            p = p[:6] + randstring(32) + p[6 + 32:]
392        # We don't call the post_build function from class _TLSHandshake
393        # to compute the message length because we need that value now
394        # for the HMAC in binder
395        tmp_len = len(p)
396        if self.msglen is None:
397            sz = tmp_len - 4
398            p = struct.pack("!I", (orb(p[0]) << 24) | sz) + p[4:]
399        s = self.tls_session
400        if self.ext:
401            for e in self.ext:
402                if isinstance(e, TLS_Ext_PreSharedKey_CH):
403                    if s.client_session_ticket:
404                        # For a resumed PSK, the hash function use
405                        # to compute the binder must be the same
406                        # as the one used to establish the original
407                        # connection. For that, we assume that
408                        # the ciphersuite associate with the ticket
409                        # is given as argument to tlsSession
410                        # (see layers/tls/automaton_cli.py for an
411                        # example)
412                        res_suite = s.tls13_ticket_ciphersuite
413                        cs_cls = _tls_cipher_suites_cls[res_suite]
414                        hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower())
415                        hash_len = hkdf.hash.digest_size
416                        s.compute_tls13_early_secrets(external=False)
417                    else:
418                        # For out of band PSK, SHA-256 is used as default
419                        # hash functions for HKDF
420                        hkdf = TLS13_HKDF("sha256")
421                        hash_len = hkdf.hash.digest_size
422                        s.compute_tls13_early_secrets(external=True)
423
424                    # RFC8446 4.2.11.2
425                    # "Each entry in the binders list is computed as an HMAC
426                    # over a transcript hash (see Section 4.4.1) containing a
427                    # partial ClientHello up to and including the
428                    # PreSharedKeyExtension.identities field."
429                    # PSK Binders field is :
430                    #   - PSK Binders length (2 bytes)
431                    #   - First PSK Binder length (1 byte) +
432                    #         HMAC (hash_len bytes)
433                    # The PSK Binder is computed in the same way as the
434                    # Finished message with binder_key as BaseKey
435
436                    handshake_context = b""
437                    if s.tls13_retry:
438                        for m in s.handshake_messages:
439                            handshake_context += m
440                    handshake_context += p[:-hash_len - 3]
441
442                    binder_key = s.tls13_derived_secrets["binder_key"]
443                    psk_binder = hkdf.compute_verify_data(binder_key,
444                                                          handshake_context)
445
446                    # Here, we replaced the last 32 bytes of the packet by the
447                    # new HMAC values computed over the ClientHello (without
448                    # the binders)
449                    p = p[:-hash_len] + psk_binder
450
451        return p + pay
452
453    def tls_session_update(self, msg_str):
454        """
455        Either for parsing or building, we store the client_random
456        along with the raw string representing this handshake message.
457        """
458        super(TLS13ClientHello, self).tls_session_update(msg_str)
459        s = self.tls_session
460
461        if self.sidlen and self.sidlen > 0:
462            s.sid = self.sid
463            s.middlebox_compatibility = True
464
465        self.random_bytes = msg_str[6:38]
466        s.client_random = self.random_bytes
467        if self.ext:
468            for e in self.ext:
469                if isinstance(e, TLS_Ext_SupportedVersion_CH):
470                    for ver in sorted(e.versions, reverse=True):
471                        # RFC 8701: GREASE of TLS will send unknown versions
472                        # here. We have to ignore them
473                        if ver in _tls_version:
474                            s.advertised_tls_version = ver
475                            break
476                if isinstance(e, TLS_Ext_SignatureAlgorithms):
477                    s.advertised_sig_algs = e.sig_algs
478                if isinstance(e, TLS_Ext_PostHandshakeAuth):
479                    s.post_handshake_auth = True
480
481
482###############################################################################
483#   ServerHello                                                               #
484###############################################################################
485
486
487class TLSServerHello(_TLSHandshake):
488    """
489    TLS ServerHello, with abilities to handle extensions.
490
491    The Random structure follows the RFC 5246: while it is 32-byte long,
492    many implementations use the first 4 bytes as a gmt_unix_time, and then
493    the remaining 28 byts should be completely random. This was designed in
494    order to (sort of) mitigate broken RNGs. If you prefer to show the full
495    32 random bytes without any GMT time, just comment in/out the lines below.
496    """
497    name = "TLS Handshake - Server Hello"
498    fields_desc = [ByteEnumField("msgtype", 2, _tls_handshake_type),
499                   ThreeBytesField("msglen", None),
500                   _TLSVersionField("version", None, _tls_version),
501
502                   # _TLSRandomBytesField("random_bytes", None, 32),
503                   _GMTUnixTimeField("gmt_unix_time", None),
504                   _TLSRandomBytesField("random_bytes", None, 28),
505
506                   FieldLenField("sidlen", None, length_of="sid", fmt="B"),
507                   _SessionIDField("sid", "",
508                                   length_from=lambda pkt: pkt.sidlen),
509
510                   ShortEnumField("cipher", None, _tls_cipher_suites),
511                   _CompressionMethodsField("comp", [0],
512                                            _tls_compression_algs,
513                                            itemfmt="B",
514                                            length_from=lambda pkt: 1),
515
516                   _ExtensionsLenField("extlen", None, length_of="ext"),
517                   _ExtensionsField("ext", None,
518                                    length_from=lambda pkt: (
519                                        pkt.msglen - (pkt.sidlen or 0) - 40
520                                    ))]
521
522    @classmethod
523    def dispatch_hook(cls, _pkt=None, *args, **kargs):
524        if _pkt and len(_pkt) >= 6:
525            version = struct.unpack("!H", _pkt[4:6])[0]
526            if version == 0x0304 or version > 0x7f00:
527                return TLS13ServerHello
528        return TLSServerHello
529
530    def build(self, *args, **kargs):
531        if self.getfieldval("sid") == b"" and self.tls_session:
532            self.sid = self.tls_session.sid
533        return super(TLSServerHello, self).build(*args, **kargs)
534
535    def post_build(self, p, pay):
536        if self.random_bytes is None:
537            p = p[:10] + randstring(28) + p[10 + 28:]
538        return super(TLSServerHello, self).post_build(p, pay)
539
540    def tls_session_update(self, msg_str):
541        """
542        Either for parsing or building, we store the server_random
543        along with the raw string representing this handshake message.
544        We also store the session_id, the cipher suite (if recognized),
545        the compression method, and finally we instantiate the pending write
546        and read connection states. Usually they get updated later on in the
547        negotiation when we learn the session keys, and eventually they
548        are committed once a ChangeCipherSpec has been sent/received.
549        """
550        super(TLSServerHello, self).tls_session_update(msg_str)
551
552        s = self.tls_session
553        s.tls_version = self.version
554        if hasattr(self, 'gmt_unix_time'):
555            self.random_bytes = msg_str[10:38]
556            s.server_random = (struct.pack('!I', self.gmt_unix_time) +
557                               self.random_bytes)
558        else:
559            s.server_random = self.random_bytes
560        s.sid = self.sid
561
562        if self.ext:
563            for e in self.ext:
564                if isinstance(e, TLS_Ext_ExtendedMasterSecret):
565                    self.tls_session.extms = True
566                if isinstance(e, TLS_Ext_EncryptThenMAC):
567                    self.tls_session.encrypt_then_mac = True
568
569        cs_cls = None
570        if self.cipher:
571            cs_val = self.cipher
572            if cs_val not in _tls_cipher_suites_cls:
573                warning("Unknown cipher suite %d from ServerHello", cs_val)
574                # we do not try to set a default nor stop the execution
575            else:
576                cs_cls = _tls_cipher_suites_cls[cs_val]
577
578        comp_cls = Comp_NULL
579        if self.comp:
580            comp_val = self.comp[0]
581            if comp_val not in _tls_compression_algs_cls:
582                err = "Unknown compression alg %d from ServerHello"
583                warning(err, comp_val)
584                comp_val = 0
585            comp_cls = _tls_compression_algs_cls[comp_val]
586
587        connection_end = s.connection_end
588        s.pwcs = writeConnState(ciphersuite=cs_cls,
589                                compression_alg=comp_cls,
590                                connection_end=connection_end,
591                                tls_version=self.version)
592        s.prcs = readConnState(ciphersuite=cs_cls,
593                               compression_alg=comp_cls,
594                               connection_end=connection_end,
595                               tls_version=self.version)
596
597
598_tls_13_server_hello_fields = [
599    ByteEnumField("msgtype", 2, _tls_handshake_type),
600    ThreeBytesField("msglen", None),
601    _TLSVersionField("version", 0x0303, _tls_version),
602    _TLSRandomBytesField("random_bytes", None, 32),
603    FieldLenField("sidlen", None, length_of="sid", fmt="B"),
604    _SessionIDField("sid", "",
605                    length_from=lambda pkt: pkt.sidlen),
606    ShortEnumField("cipher", None, _tls_cipher_suites),
607    _CompressionMethodsField("comp", [0],
608                             _tls_compression_algs,
609                             itemfmt="B",
610                             length_from=lambda pkt: 1),
611    _ExtensionsLenField("extlen", None, length_of="ext"),
612    _ExtensionsField("ext", None,
613                     length_from=lambda pkt: (pkt.msglen -
614                                              38))
615]
616
617
618class TLS13ServerHello(TLSServerHello):
619    """ TLS 1.3 ServerHello """
620    name = "TLS 1.3 Handshake - Server Hello"
621    fields_desc = _tls_13_server_hello_fields
622
623    # ServerHello and HelloRetryRequest has the same structure and the same
624    # msgId. We need to check the server_random value to determine which it is.
625    @classmethod
626    def dispatch_hook(cls, _pkt=None, *args, **kargs):
627        if _pkt and len(_pkt) >= 38:
628            # If SHA-256("HelloRetryRequest") == server_random,
629            # this message is a HelloRetryRequest
630            random_bytes = _pkt[6:38]
631            if random_bytes == _tls_hello_retry_magic:
632                return TLS13HelloRetryRequest
633        return TLS13ServerHello
634
635    def post_build(self, p, pay):
636        if self.random_bytes is None:
637            p = p[:6] + randstring(32) + p[6 + 32:]
638        return super(TLS13ServerHello, self).post_build(p, pay)
639
640    def tls_session_update(self, msg_str):
641        """
642        Either for parsing or building, we store the server_random along with
643        the raw string representing this handshake message. We also store the
644        cipher suite (if recognized), and finally we instantiate the write and
645        read connection states.
646        """
647        s = self.tls_session
648        s.server_random = self.random_bytes
649        s.ciphersuite = self.cipher
650        s.tls_version = self.version
651        # Check extensions
652        if self.ext:
653            for e in self.ext:
654                if isinstance(e, TLS_Ext_SupportedVersion_SH):
655                    s.tls_version = e.version
656                    break
657
658        if s.tls_version < 0x304:
659            # This means that the server does not support TLS 1.3 and ignored
660            # the initial TLS 1.3 ClientHello. tls_version has been updated
661            return TLSServerHello.tls_session_update(self, msg_str)
662        else:
663            _TLSHandshake.tls_session_update(self, msg_str)
664
665        cs_cls = None
666        if self.cipher:
667            cs_val = self.cipher
668            if cs_val not in _tls_cipher_suites_cls:
669                warning("Unknown cipher suite %d from ServerHello", cs_val)
670                # we do not try to set a default nor stop the execution
671            else:
672                cs_cls = _tls_cipher_suites_cls[cs_val]
673
674        connection_end = s.connection_end
675        if connection_end == "server":
676            s.pwcs = writeConnState(ciphersuite=cs_cls,
677                                    connection_end=connection_end,
678                                    tls_version=s.tls_version)
679
680            if not s.middlebox_compatibility:
681                s.triggered_pwcs_commit = True
682        elif connection_end == "client":
683            s.prcs = readConnState(ciphersuite=cs_cls,
684                                   connection_end=connection_end,
685                                   tls_version=s.tls_version)
686            if not s.middlebox_compatibility:
687                s.triggered_prcs_commit = True
688
689        if s.tls13_early_secret is None:
690            # In case the connState was not pre-initialized, we could not
691            # compute the early secrets at the ClientHello, so we do it here.
692            s.compute_tls13_early_secrets()
693        s.compute_tls13_handshake_secrets()
694        if connection_end == "server":
695            shts = s.tls13_derived_secrets["server_handshake_traffic_secret"]
696            s.pwcs.tls13_derive_keys(shts)
697        elif connection_end == "client":
698            shts = s.tls13_derived_secrets["server_handshake_traffic_secret"]
699            s.prcs.tls13_derive_keys(shts)
700
701
702###############################################################################
703#   HelloRetryRequest                                                         #
704###############################################################################
705
706class TLS13HelloRetryRequest(_TLSHandshake):
707    name = "TLS 1.3 Handshake - Hello Retry Request"
708
709    fields_desc = _tls_13_server_hello_fields
710
711    def build(self):
712        fval = self.getfieldval("random_bytes")
713        if fval is None:
714            self.random_bytes = _tls_hello_retry_magic
715        if self.getfieldval("sid") == b"" and self.tls_session:
716            self.sid = self.tls_session.sid
717        return _TLSHandshake.build(self)
718
719    def tls_session_update(self, msg_str):
720        s = self.tls_session
721        s.tls13_retry = True
722        s.tls13_client_pubshares = {}
723        # RFC8446 sect 4.4.1
724        # If the server responds to a ClientHello with a HelloRetryRequest
725        # The value of the first ClientHello is replaced by a message_hash
726        if s.client_session_ticket:
727            cs_cls = _tls_cipher_suites_cls[s.tls13_ticket_ciphersuite]
728            hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower())
729            hash_len = hkdf.hash.digest_size
730        else:
731            cs_cls = _tls_cipher_suites_cls[self.cipher]
732            hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower())
733            hash_len = hkdf.hash.digest_size
734
735        handshake_context = struct.pack("B", 254)
736        handshake_context += struct.pack("B", 0)
737        handshake_context += struct.pack("B", 0)
738        handshake_context += struct.pack("B", hash_len)
739        digest = hashes.Hash(hkdf.hash, backend=default_backend())
740        digest.update(s.handshake_messages[0])
741        handshake_context += digest.finalize()
742        s.handshake_messages[0] = handshake_context
743        super(TLS13HelloRetryRequest, self).tls_session_update(msg_str)
744
745
746###############################################################################
747#   EncryptedExtensions                                                       #
748###############################################################################
749
750
751class TLSEncryptedExtensions(_TLSHandshake):
752    name = "TLS 1.3 Handshake - Encrypted Extensions"
753    fields_desc = [ByteEnumField("msgtype", 8, _tls_handshake_type),
754                   ThreeBytesField("msglen", None),
755                   _ExtensionsLenField("extlen", None, length_of="ext"),
756                   _ExtensionsField("ext", None,
757                                    length_from=lambda pkt: pkt.msglen - 2)]
758
759    def post_build_tls_session_update(self, msg_str):
760        self.tls_session_update(msg_str)
761
762        s = self.tls_session
763        connection_end = s.connection_end
764
765        # Check if the server early_data extension is present in
766        # EncryptedExtensions message (if so, early data was accepted by the
767        # server)
768        early_data_accepted = False
769        if self.ext:
770            for e in self.ext:
771                if isinstance(e, TLS_Ext_EarlyDataIndication):
772                    early_data_accepted = True
773
774        # If the serveur did not accept early_data, we change prcs traffic
775        # encryption keys. Otherwise, the the keys will be updated after the
776        # EndOfEarlyData message
777        if connection_end == "server":
778            if not early_data_accepted:
779                s.prcs = readConnState(ciphersuite=type(s.wcs.ciphersuite),
780                                       connection_end=connection_end,
781                                       tls_version=s.tls_version)
782
783                chts = s.tls13_derived_secrets["client_handshake_traffic_secret"]  # noqa: E501
784                s.prcs.tls13_derive_keys(chts)
785
786                if not s.middlebox_compatibility:
787                    s.rcs = self.tls_session.prcs
788                    s.triggered_prcs_commit = False
789                else:
790                    s.triggered_prcs_commit = True
791
792    def post_dissection_tls_session_update(self, msg_str):
793        self.tls_session_update(msg_str)
794        s = self.tls_session
795        connection_end = s.connection_end
796
797        # Check if the server early_data extension is present in
798        # EncryptedExtensions message (if so, early data was accepted by the
799        # server)
800        early_data_accepted = False
801        if self.ext:
802            for e in self.ext:
803                if isinstance(e, TLS_Ext_EarlyDataIndication):
804                    early_data_accepted = True
805
806        # If the serveur did not accept early_data, we change pwcs traffic
807        # encryption key. Otherwise, the the keys will be updated after the
808        # EndOfEarlyData message
809        if connection_end == "client":
810            if not early_data_accepted:
811                s.pwcs = writeConnState(ciphersuite=type(s.rcs.ciphersuite),
812                                        connection_end=connection_end,
813                                        tls_version=s.tls_version)
814                chts = s.tls13_derived_secrets["client_handshake_traffic_secret"]  # noqa: E501
815                s.pwcs.tls13_derive_keys(chts)
816                if not s.middlebox_compatibility:
817                    s.wcs = self.tls_session.pwcs
818                    s.triggered_pwcs_commit = False
819                else:
820                    s.triggered_pwcs_commit = True
821
822###############################################################################
823#   Certificate                                                               #
824###############################################################################
825
826# XXX It might be appropriate to rewrite this mess with basic 3-byte FieldLenField.  # noqa: E501
827
828
829class _ASN1CertLenField(FieldLenField):
830    """
831    This is mostly a 3-byte FieldLenField.
832    """
833    def __init__(self, name, default, length_of=None, adjust=lambda pkt, x: x):
834        self.length_of = length_of
835        self.adjust = adjust
836        Field.__init__(self, name, default, fmt="!I")
837
838    def i2m(self, pkt, x):
839        if x is None:
840            if self.length_of is not None:
841                fld, fval = pkt.getfield_and_val(self.length_of)
842                f = fld.i2len(pkt, fval)
843                x = self.adjust(pkt, f)
844        return x
845
846    def addfield(self, pkt, s, val):
847        return s + struct.pack(self.fmt, self.i2m(pkt, val))[1:4]
848
849    def getfield(self, pkt, s):
850        return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b"\x00" + s[:3])[0])  # noqa: E501
851
852
853class _ASN1CertListField(StrLenField):
854    islist = 1
855
856    def i2len(self, pkt, i):
857        if i is None:
858            return 0
859        return len(self.i2m(pkt, i))
860
861    def getfield(self, pkt, s):
862        """
863        Extract Certs in a loop.
864        XXX We should provide safeguards when trying to parse a Cert.
865        """
866        tmp_len = None
867        if self.length_from is not None:
868            tmp_len = self.length_from(pkt)
869
870        lst = []
871        ret = b""
872        m = s
873        if tmp_len is not None:
874            m, ret = s[:tmp_len], s[tmp_len:]
875        while m:
876            c_len = struct.unpack("!I", b'\x00' + m[:3])[0]
877            lst.append((c_len, Cert(m[3:3 + c_len])))
878            m = m[3 + c_len:]
879        return m + ret, lst
880
881    def i2m(self, pkt, i):
882        def i2m_one(i):
883            if isinstance(i, str):
884                return i
885            if isinstance(i, Cert):
886                s = i.der
887                tmp_len = struct.pack("!I", len(s))[1:4]
888                return tmp_len + s
889
890            (tmp_len, s) = i
891            if isinstance(s, Cert):
892                s = s.der
893            return struct.pack("!I", tmp_len)[1:4] + s
894
895        if i is None:
896            return b""
897        if isinstance(i, str):
898            return i
899        if isinstance(i, Cert):
900            i = [i]
901        return b"".join(i2m_one(x) for x in i)
902
903    def any2i(self, pkt, x):
904        return x
905
906
907class _ASN1CertField(StrLenField):
908    def i2len(self, pkt, i):
909        if i is None:
910            return 0
911        return len(self.i2m(pkt, i))
912
913    def getfield(self, pkt, s):
914        tmp_len = None
915        if self.length_from is not None:
916            tmp_len = self.length_from(pkt)
917        ret = b""
918        m = s
919        if tmp_len is not None:
920            m, ret = s[:tmp_len], s[tmp_len:]
921        c_len = struct.unpack("!I", b'\x00' + m[:3])[0]
922        len_cert = (c_len, Cert(m[3:3 + c_len]))
923        m = m[3 + c_len:]
924        return m + ret, len_cert
925
926    def i2m(self, pkt, i):
927        def i2m_one(i):
928            if isinstance(i, str):
929                return i
930            if isinstance(i, Cert):
931                s = i.der
932                tmp_len = struct.pack("!I", len(s))[1:4]
933                return tmp_len + s
934
935            (tmp_len, s) = i
936            if isinstance(s, Cert):
937                s = s.der
938            return struct.pack("!I", tmp_len)[1:4] + s
939
940        if i is None:
941            return b""
942        return i2m_one(i)
943
944    def any2i(self, pkt, x):
945        return x
946
947
948class TLSCertificate(_TLSHandshake):
949    """
950    XXX We do not support RFC 5081, i.e. OpenPGP certificates.
951    """
952    name = "TLS Handshake - Certificate"
953    fields_desc = [ByteEnumField("msgtype", 11, _tls_handshake_type),
954                   ThreeBytesField("msglen", None),
955                   _ASN1CertLenField("certslen", None, length_of="certs"),
956                   _ASN1CertListField("certs", [],
957                                      length_from=lambda pkt: pkt.certslen)]
958
959    @classmethod
960    def dispatch_hook(cls, _pkt=None, *args, **kargs):
961        if _pkt:
962            tls_session = kargs.get("tls_session", None)
963            if tls_session and (tls_session.tls_version or 0) >= 0x0304:
964                return TLS13Certificate
965        return TLSCertificate
966
967    def post_dissection_tls_session_update(self, msg_str):
968        self.tls_session_update(msg_str)
969        connection_end = self.tls_session.connection_end
970        if connection_end == "client":
971            self.tls_session.server_certs = [x[1] for x in self.certs]
972        else:
973            self.tls_session.client_certs = [x[1] for x in self.certs]
974
975
976class _ASN1CertAndExt(_GenericTLSSessionInheritance):
977    name = "Certificate and Extensions"
978    fields_desc = [_ASN1CertField("cert", ""),
979                   FieldLenField("extlen", None, length_of="ext"),
980                   _ExtensionsField("ext", [],
981                                    length_from=lambda pkt: pkt.extlen)]
982
983    def extract_padding(self, s):
984        return b"", s
985
986
987class _ASN1CertAndExtListField(PacketListField):
988    def m2i(self, pkt, m):
989        return self.cls(m, tls_session=pkt.tls_session)
990
991
992class TLS13Certificate(_TLSHandshake):
993    name = "TLS 1.3 Handshake - Certificate"
994    fields_desc = [ByteEnumField("msgtype", 11, _tls_handshake_type),
995                   ThreeBytesField("msglen", None),
996                   FieldLenField("cert_req_ctxt_len", None, fmt="B",
997                                 length_of="cert_req_ctxt"),
998                   StrLenField("cert_req_ctxt", "",
999                               length_from=lambda pkt: pkt.cert_req_ctxt_len),
1000                   _ASN1CertLenField("certslen", None, length_of="certs"),
1001                   _ASN1CertAndExtListField("certs", [], _ASN1CertAndExt,
1002                                            length_from=lambda pkt: pkt.certslen)]  # noqa: E501
1003
1004    def post_dissection_tls_session_update(self, msg_str):
1005        self.tls_session_update(msg_str)
1006        connection_end = self.tls_session.connection_end
1007        if connection_end == "client":
1008            if self.certs:
1009                sc = [x.cert[1] for x in self.certs if hasattr(x, 'cert')]
1010                self.tls_session.server_certs = sc
1011        else:
1012            if self.certs:
1013                cc = [x.cert[1] for x in self.certs if hasattr(x, 'cert')]
1014                self.tls_session.client_certs = cc
1015
1016
1017###############################################################################
1018#   ServerKeyExchange                                                         #
1019###############################################################################
1020
1021class TLSServerKeyExchange(_TLSHandshake):
1022    name = "TLS Handshake - Server Key Exchange"
1023    fields_desc = [ByteEnumField("msgtype", 12, _tls_handshake_type),
1024                   ThreeBytesField("msglen", None),
1025                   _TLSServerParamsField("params", None,
1026                                         length_from=lambda pkt: pkt.msglen),
1027                   _TLSSignatureField("sig", None,
1028                                      length_from=lambda pkt: pkt.msglen - len(pkt.params))]  # noqa: E501
1029
1030    def build(self, *args, **kargs):
1031        r"""
1032        We overload build() method in order to provide a valid default value
1033        for params based on TLS session if not provided. This cannot be done by
1034        overriding i2m() because the method is called on a copy of the packet.
1035
1036        The 'params' field is built according to key_exchange.server_kx_msg_cls
1037        which should have been set after receiving a cipher suite in a
1038        previous ServerHello. Usual cases are:
1039
1040        - None: for RSA encryption or fixed FF/ECDH. This should never happen,
1041          as no ServerKeyExchange should be generated in the first place.
1042        - ServerDHParams: for ephemeral FFDH. In that case, the parameter to
1043          server_kx_msg_cls does not matter.
1044        - ServerECDH\*Params: for ephemeral ECDH. There are actually three
1045          classes, which are dispatched by _tls_server_ecdh_cls_guess on
1046          the first byte retrieved. The default here is b"\03", which
1047          corresponds to ServerECDHNamedCurveParams (implicit curves).
1048
1049        When the Server\*DHParams are built via .fill_missing(), the session
1050        server_kx_privkey will be updated accordingly.
1051        """
1052        fval = self.getfieldval("params")
1053        if fval is None:
1054            s = self.tls_session
1055            if s.pwcs:
1056                if s.pwcs.key_exchange.export:
1057                    cls = ServerRSAParams(tls_session=s)
1058                else:
1059                    cls = s.pwcs.key_exchange.server_kx_msg_cls(b"\x03")
1060                    cls = cls(tls_session=s)
1061                try:
1062                    cls.fill_missing()
1063                except Exception:
1064                    if conf.debug_dissector:
1065                        raise
1066            else:
1067                cls = Raw()
1068            self.params = cls
1069
1070        fval = self.getfieldval("sig")
1071        if fval is None:
1072            s = self.tls_session
1073            if s.pwcs and s.client_random:
1074                if not s.pwcs.key_exchange.anonymous:
1075                    p = self.params
1076                    if p is None:
1077                        p = b""
1078                    m = s.client_random + s.server_random + raw(p)
1079                    cls = _TLSSignature(tls_session=s)
1080                    cls._update_sig(m, s.server_key)
1081                else:
1082                    cls = Raw()
1083            else:
1084                cls = Raw()
1085            self.sig = cls
1086
1087        return _TLSHandshake.build(self, *args, **kargs)
1088
1089    def post_dissection(self, pkt):
1090        """
1091        While previously dissecting Server*DHParams, the session
1092        server_kx_pubkey should have been updated.
1093
1094        XXX Add a 'fixed_dh' OR condition to the 'anonymous' test.
1095        """
1096        s = self.tls_session
1097        if s.prcs and s.prcs.key_exchange.no_ske:
1098            pkt_info = pkt.firstlayer().summary()
1099            log_runtime.info("TLS: useless ServerKeyExchange [%s]", pkt_info)
1100        if (s.prcs and
1101            not s.prcs.key_exchange.anonymous and
1102            s.client_random and s.server_random and
1103                s.server_certs and len(s.server_certs) > 0):
1104            m = s.client_random + s.server_random + raw(self.params)
1105            sig_test = self.sig._verify_sig(m, s.server_certs[0])
1106            if not sig_test:
1107                pkt_info = pkt.firstlayer().summary()
1108                log_runtime.info("TLS: invalid ServerKeyExchange signature [%s]", pkt_info)  # noqa: E501
1109
1110
1111###############################################################################
1112#   CertificateRequest                                                        #
1113###############################################################################
1114
1115_tls_client_certificate_types = {1: "rsa_sign",
1116                                 2: "dss_sign",
1117                                 3: "rsa_fixed_dh",
1118                                 4: "dss_fixed_dh",
1119                                 5: "rsa_ephemeral_dh_RESERVED",
1120                                 6: "dss_ephemeral_dh_RESERVED",
1121                                 20: "fortezza_dms_RESERVED",
1122                                 64: "ecdsa_sign",
1123                                 65: "rsa_fixed_ecdh",
1124                                 66: "ecdsa_fixed_ecdh"}
1125
1126
1127class _CertTypesField(_CipherSuitesField):
1128    pass
1129
1130
1131class _CertAuthoritiesField(StrLenField):
1132    """
1133    XXX Rework this with proper ASN.1 parsing.
1134    """
1135    islist = 1
1136
1137    def getfield(self, pkt, s):
1138        tmp_len = self.length_from(pkt)
1139        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])
1140
1141    def m2i(self, pkt, m):
1142        res = []
1143        while len(m) > 1:
1144            tmp_len = struct.unpack("!H", m[:2])[0]
1145            if len(m) < tmp_len + 2:
1146                res.append((tmp_len, m[2:]))
1147                break
1148            dn = m[2:2 + tmp_len]
1149            res.append((tmp_len, dn))
1150            m = m[2 + tmp_len:]
1151        return res
1152
1153    def i2m(self, pkt, i):
1154        return b"".join(map(lambda x_y: struct.pack("!H", x_y[0]) + x_y[1], i))
1155
1156    def addfield(self, pkt, s, val):
1157        return s + self.i2m(pkt, val)
1158
1159    def i2len(self, pkt, val):
1160        if val is None:
1161            return 0
1162        else:
1163            return len(self.i2m(pkt, val))
1164
1165
1166class TLSCertificateRequest(_TLSHandshake):
1167    name = "TLS Handshake - Certificate Request"
1168    fields_desc = [ByteEnumField("msgtype", 13, _tls_handshake_type),
1169                   ThreeBytesField("msglen", None),
1170                   FieldLenField("ctypeslen", None, fmt="B",
1171                                 length_of="ctypes"),
1172                   _CertTypesField("ctypes", [1, 64],
1173                                   _tls_client_certificate_types,
1174                                   itemfmt="!B",
1175                                   length_from=lambda pkt: pkt.ctypeslen),
1176                   SigAndHashAlgsLenField("sig_algs_len", None,
1177                                          length_of="sig_algs"),
1178                   SigAndHashAlgsField("sig_algs", [0x0403, 0x0401, 0x0201],
1179                                       ShortEnumField("hash_sig", None, _tls_hash_sig),  # noqa: E501
1180                                       length_from=lambda pkt: pkt.sig_algs_len),  # noqa: E501
1181                   FieldLenField("certauthlen", None, fmt="!H",
1182                                 length_of="certauth"),
1183                   _CertAuthoritiesField("certauth", [],
1184                                         length_from=lambda pkt: pkt.certauthlen)]  # noqa: E501
1185
1186
1187class TLS13CertificateRequest(_TLSHandshake):
1188    name = "TLS 1.3 Handshake - Certificate Request"
1189    fields_desc = [ByteEnumField("msgtype", 13, _tls_handshake_type),
1190                   ThreeBytesField("msglen", None),
1191                   FieldLenField("cert_req_ctxt_len", None, fmt="B",
1192                                 length_of="cert_req_ctxt"),
1193                   StrLenField("cert_req_ctxt", "",
1194                               length_from=lambda pkt: pkt.cert_req_ctxt_len),
1195                   _ExtensionsLenField("extlen", None, length_of="ext"),
1196                   _ExtensionsField("ext", None,
1197                                    length_from=lambda pkt: pkt.msglen -
1198                                    pkt.cert_req_ctxt_len - 3)]
1199
1200    def tls_session_update(self, msg_str):
1201        super(TLS13CertificateRequest, self).tls_session_update(msg_str)
1202        self.tls_session.tls13_cert_req_ctxt = self.cert_req_ctxt
1203
1204
1205###############################################################################
1206#   ServerHelloDone                                                           #
1207###############################################################################
1208
1209
1210class TLSServerHelloDone(_TLSHandshake):
1211    name = "TLS Handshake - Server Hello Done"
1212    fields_desc = [ByteEnumField("msgtype", 14, _tls_handshake_type),
1213                   ThreeBytesField("msglen", None)]
1214
1215
1216###############################################################################
1217#   CertificateVerify                                                         #
1218###############################################################################
1219
1220class TLSCertificateVerify(_TLSHandshake):
1221    name = "TLS Handshake - Certificate Verify"
1222    fields_desc = [ByteEnumField("msgtype", 15, _tls_handshake_type),
1223                   ThreeBytesField("msglen", None),
1224                   _TLSSignatureField("sig", None,
1225                                      length_from=lambda pkt: pkt.msglen)]
1226
1227    # See https://datatracker.ietf.org/doc/html/rfc8446#section-4.4 for how to compute
1228    # the signature.
1229
1230    def build(self, *args, **kargs):
1231        sig = self.getfieldval("sig")
1232        if sig is None:
1233            s = self.tls_session
1234            m = b"".join(s.handshake_messages)
1235            if s.post_handshake:
1236                m += b"".join(s.post_handshake_messages)
1237            tls_version = s.tls_version
1238            if tls_version is None:
1239                tls_version = s.advertised_tls_version
1240            if tls_version >= 0x0304:
1241                if s.connection_end == "client":
1242                    context_string = b"TLS 1.3, client CertificateVerify"
1243                elif s.connection_end == "server":
1244                    context_string = b"TLS 1.3, server CertificateVerify"
1245                m = b"\x20" * 64 + context_string + b"\x00" + s.wcs.hash.digest(m)  # noqa: E501
1246            self.sig = _TLSSignature(tls_session=s)
1247            if s.connection_end == "client":
1248                self.sig._update_sig(m, s.client_key)
1249            elif s.connection_end == "server":
1250                # should be TLS 1.3 only
1251                self.sig._update_sig(m, s.server_key)
1252        return _TLSHandshake.build(self, *args, **kargs)
1253
1254    def post_dissection(self, pkt):
1255        s = self.tls_session
1256        m = b"".join(s.handshake_messages)
1257        if s.post_handshake:
1258            m += b"".join(s.post_handshake_messages)
1259        tls_version = s.tls_version
1260        if tls_version is None:
1261            tls_version = s.advertised_tls_version
1262        if tls_version >= 0x0304:
1263            if s.connection_end == "client":
1264                context_string = b"TLS 1.3, server CertificateVerify"
1265            elif s.connection_end == "server":
1266                context_string = b"TLS 1.3, client CertificateVerify"
1267            m = b"\x20" * 64 + context_string + b"\x00" + s.rcs.hash.digest(m)
1268
1269        if s.connection_end == "server":
1270            if s.client_certs and len(s.client_certs) > 0:
1271                sig_test = self.sig._verify_sig(m, s.client_certs[0])
1272                if not sig_test:
1273                    pkt_info = pkt.firstlayer().summary()
1274                    log_runtime.info("TLS: invalid CertificateVerify signature [%s]", pkt_info)  # noqa: E501
1275        elif s.connection_end == "client":
1276            # should be TLS 1.3 only
1277            if s.server_certs and len(s.server_certs) > 0:
1278                sig_test = self.sig._verify_sig(m, s.server_certs[0])
1279                if not sig_test:
1280                    pkt_info = pkt.firstlayer().summary()
1281                    log_runtime.info("TLS: invalid CertificateVerify signature [%s]", pkt_info)  # noqa: E501
1282
1283
1284###############################################################################
1285#   ClientKeyExchange                                                         #
1286###############################################################################
1287
1288class _TLSCKExchKeysField(PacketField):
1289    __slots__ = ["length_from"]
1290    holds_packet = 1
1291
1292    def __init__(self, name, length_from=None):
1293        self.length_from = length_from
1294        PacketField.__init__(self, name, None, None)
1295
1296    def m2i(self, pkt, m):
1297        """
1298        The client_kx_msg may be either None, EncryptedPreMasterSecret
1299        (for RSA encryption key exchange), ClientDiffieHellmanPublic,
1300        or ClientECDiffieHellmanPublic. When either one of them gets
1301        dissected, the session context is updated accordingly.
1302        """
1303        tmp_len = self.length_from(pkt)
1304        tbd, rem = m[:tmp_len], m[tmp_len:]
1305
1306        s = pkt.tls_session
1307        cls = None
1308
1309        if s.prcs and s.prcs.key_exchange:
1310            cls = s.prcs.key_exchange.client_kx_msg_cls
1311
1312        if cls is None:
1313            return Raw(tbd) / Padding(rem)
1314
1315        return cls(tbd, tls_session=s) / Padding(rem)
1316
1317
1318class TLSClientKeyExchange(_TLSHandshake):
1319    """
1320    This class mostly works like TLSServerKeyExchange and its 'params' field.
1321    """
1322    name = "TLS Handshake - Client Key Exchange"
1323    fields_desc = [ByteEnumField("msgtype", 16, _tls_handshake_type),
1324                   ThreeBytesField("msglen", None),
1325                   _TLSCKExchKeysField("exchkeys",
1326                                       length_from=lambda pkt: pkt.msglen)]
1327
1328    def build(self, *args, **kargs):
1329        fval = self.getfieldval("exchkeys")
1330        if fval is None:
1331            s = self.tls_session
1332            if s.prcs:
1333                cls = s.prcs.key_exchange.client_kx_msg_cls
1334                cls = cls(tls_session=s)
1335            else:
1336                cls = Raw()
1337            self.exchkeys = cls
1338        return _TLSHandshake.build(self, *args, **kargs)
1339
1340    def tls_session_update(self, msg_str):
1341        """
1342        Finalize the EXTMS messages and compute the hash
1343        """
1344        super(TLSClientKeyExchange, self).tls_session_update(msg_str)
1345
1346        if self.tls_session.extms:
1347            to_hash = b''.join(self.tls_session.handshake_messages)
1348            # https://tools.ietf.org/html/rfc7627#section-3
1349            if self.tls_session.tls_version >= 0x303:
1350                # TLS 1.2 uses the same Hash as the PRF
1351                from scapy.layers.tls.crypto.hash import _tls_hash_algs
1352                hash_object = _tls_hash_algs.get(
1353                    self.tls_session.prcs.prf.hash_name
1354                )()
1355                self.tls_session.session_hash = hash_object.digest(to_hash)
1356            else:
1357                # Previous TLS version use concatenation of MD5 & SHA1
1358                from scapy.layers.tls.crypto.hash import Hash_MD5, Hash_SHA
1359                self.tls_session.session_hash = (
1360                    Hash_MD5().digest(to_hash) + Hash_SHA().digest(to_hash)
1361                )
1362            if self.tls_session.pre_master_secret:
1363                self.tls_session.compute_ms_and_derive_keys()
1364
1365        if not self.tls_session.master_secret:
1366            # There are still no master secret (we're just passive)
1367            if self.tls_session.use_nss_master_secret_if_present():
1368                # we have a NSS file
1369                self.tls_session.compute_ms_and_derive_keys()
1370
1371
1372###############################################################################
1373#   Finished                                                                  #
1374###############################################################################
1375
1376class _VerifyDataField(StrLenField):
1377    def getfield(self, pkt, s):
1378        if pkt.tls_session.tls_version == 0x0300:
1379            sep = 36
1380        elif pkt.tls_session.tls_version and pkt.tls_session.tls_version >= 0x0304:
1381            sep = pkt.tls_session.rcs.hash.hash_len
1382        else:
1383            sep = 12
1384        return s[sep:], s[:sep]
1385
1386
1387class TLSFinished(_TLSHandshake):
1388    name = "TLS Handshake - Finished"
1389    fields_desc = [ByteEnumField("msgtype", 20, _tls_handshake_type),
1390                   ThreeBytesField("msglen", None),
1391                   _VerifyDataField("vdata", None)]
1392
1393    def build(self, *args, **kargs):
1394        fval = self.getfieldval("vdata")
1395        if fval is None:
1396            s = self.tls_session
1397            handshake_msg = b"".join(s.handshake_messages)
1398            if s.post_handshake:
1399                handshake_msg += b"".join(s.post_handshake_messages)
1400            con_end = s.connection_end
1401            tls_version = s.tls_version
1402            if tls_version is None:
1403                tls_version = s.advertised_tls_version
1404            if tls_version < 0x0304:
1405                ms = s.master_secret
1406                self.vdata = s.wcs.prf.compute_verify_data(con_end, "write",
1407                                                           handshake_msg, ms)
1408            else:
1409                self.vdata = s.compute_tls13_verify_data(con_end, "write",
1410                                                         handshake_msg)
1411        return _TLSHandshake.build(self, *args, **kargs)
1412
1413    def post_dissection(self, pkt):
1414        s = self.tls_session
1415        if not s.frozen:
1416            handshake_msg = b"".join(s.handshake_messages)
1417            if s.post_handshake:
1418                handshake_msg += b"".join(s.post_handshake_messages)
1419            tls_version = s.tls_version
1420            if tls_version is None:
1421                tls_version = s.advertised_tls_version
1422            if tls_version < 0x0304 and s.master_secret is not None:
1423                ms = s.master_secret
1424                con_end = s.connection_end
1425                verify_data = s.rcs.prf.compute_verify_data(con_end, "read",
1426                                                            handshake_msg, ms)
1427                if self.vdata != verify_data:
1428                    pkt_info = pkt.firstlayer().summary()
1429                    log_runtime.info("TLS: invalid Finished received [%s]", pkt_info)  # noqa: E501
1430            elif tls_version >= 0x0304:
1431                con_end = s.connection_end
1432                verify_data = s.compute_tls13_verify_data(con_end, "read",
1433                                                          handshake_msg)
1434                if self.vdata != verify_data:
1435                    pkt_info = pkt.firstlayer().summary()
1436                    log_runtime.info("TLS: invalid Finished received [%s]", pkt_info)  # noqa: E501
1437
1438    def post_build_tls_session_update(self, msg_str):
1439        self.tls_session_update(msg_str)
1440        s = self.tls_session
1441        tls_version = s.tls_version
1442        if tls_version is None:
1443            tls_version = s.advertised_tls_version
1444        if tls_version >= 0x0304 and not s.post_handshake:
1445            s.pwcs = writeConnState(ciphersuite=type(s.wcs.ciphersuite),
1446                                    connection_end=s.connection_end,
1447                                    tls_version=s.tls_version)
1448            s.triggered_pwcs_commit = True
1449            if s.connection_end == "server":
1450                s.compute_tls13_traffic_secrets()
1451            elif s.connection_end == "client":
1452                s.compute_tls13_traffic_secrets_end()
1453                s.compute_tls13_resumption_secret()
1454        if s.connection_end == "client":
1455            s.post_handshake = True
1456            s.post_handshake_messages = []
1457
1458    def post_dissection_tls_session_update(self, msg_str):
1459        self.tls_session_update(msg_str)
1460        s = self.tls_session
1461        tls_version = s.tls_version
1462        if tls_version is None:
1463            tls_version = s.advertised_tls_version
1464        if tls_version >= 0x0304 and not s.post_handshake:
1465            s.prcs = readConnState(ciphersuite=type(s.rcs.ciphersuite),
1466                                   connection_end=s.connection_end,
1467                                   tls_version=s.tls_version)
1468            s.triggered_prcs_commit = True
1469            if s.connection_end == "client":
1470                s.compute_tls13_traffic_secrets()
1471            elif s.connection_end == "server":
1472                s.compute_tls13_traffic_secrets_end()
1473                s.compute_tls13_resumption_secret()
1474        if s.connection_end == "server":
1475            s.post_handshake = True
1476            s.post_handshake_messages = []
1477
1478
1479# Additional handshake messages
1480
1481###############################################################################
1482#   HelloVerifyRequest                                                        #
1483###############################################################################
1484
1485class TLSHelloVerifyRequest(_TLSHandshake):
1486    """
1487    Defined for DTLS, see RFC 6347.
1488    """
1489    name = "TLS Handshake - Hello Verify Request"
1490    fields_desc = [ByteEnumField("msgtype", 21, _tls_handshake_type),
1491                   ThreeBytesField("msglen", None),
1492                   FieldLenField("cookielen", None,
1493                                 fmt="B", length_of="cookie"),
1494                   StrLenField("cookie", "",
1495                               length_from=lambda pkt: pkt.cookielen)]
1496
1497
1498###############################################################################
1499#   CertificateURL                                                            #
1500###############################################################################
1501
1502_tls_cert_chain_types = {0: "individual_certs",
1503                         1: "pkipath"}
1504
1505
1506class URLAndOptionalHash(Packet):
1507    name = "URLAndOptionHash structure for TLSCertificateURL"
1508    fields_desc = [FieldLenField("urllen", None, length_of="url"),
1509                   StrLenField("url", "",
1510                               length_from=lambda pkt: pkt.urllen),
1511                   FieldLenField("hash_present", None,
1512                                 fmt="B", length_of="hash",
1513                                 adjust=lambda pkt, x: int(math.ceil(x / 20.))),  # noqa: E501
1514                   StrLenField("hash", "",
1515                               length_from=lambda pkt: 20 * pkt.hash_present)]
1516
1517    def guess_payload_class(self, p):
1518        return Padding
1519
1520
1521class TLSCertificateURL(_TLSHandshake):
1522    """
1523    Defined in RFC 4366. PkiPath structure of section 8 is not implemented yet.
1524    """
1525    name = "TLS Handshake - Certificate URL"
1526    fields_desc = [ByteEnumField("msgtype", 21, _tls_handshake_type),
1527                   ThreeBytesField("msglen", None),
1528                   ByteEnumField("certchaintype", None, _tls_cert_chain_types),
1529                   FieldLenField("uahlen", None, length_of="uah"),
1530                   PacketListField("uah", [], URLAndOptionalHash,
1531                                   length_from=lambda pkt: pkt.uahlen)]
1532
1533
1534###############################################################################
1535#   CertificateStatus                                                         #
1536###############################################################################
1537
1538class ThreeBytesLenField(FieldLenField):
1539    def __init__(self, name, default, length_of=None, adjust=lambda pkt, x: x):
1540        FieldLenField.__init__(self, name, default, length_of=length_of,
1541                               fmt='!I', adjust=adjust)
1542
1543    def i2repr(self, pkt, x):
1544        if x is None:
1545            return 0
1546        return repr(self.i2h(pkt, x))
1547
1548    def addfield(self, pkt, s, val):
1549        return s + struct.pack(self.fmt, self.i2m(pkt, val))[1:4]
1550
1551    def getfield(self, pkt, s):
1552        return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b"\x00" + s[:3])[0])  # noqa: E501
1553
1554
1555_cert_status_cls = {1: OCSP_Response}
1556
1557
1558class _StatusField(PacketLenField):
1559    def m2i(self, pkt, m):
1560        idtype = pkt.status_type
1561        cls = self.cls
1562        if idtype in _cert_status_cls:
1563            cls = _cert_status_cls[idtype]
1564        return cls(m)
1565
1566
1567class TLSCertificateStatus(_TLSHandshake):
1568    name = "TLS Handshake - Certificate Status"
1569    fields_desc = [ByteEnumField("msgtype", 22, _tls_handshake_type),
1570                   ThreeBytesField("msglen", None),
1571                   ByteEnumField("status_type", 1, _cert_status_type),
1572                   ThreeBytesLenField("responselen", None,
1573                                      length_of="response"),
1574                   _StatusField("response", None, Raw,
1575                                length_from=lambda pkt: pkt.responselen)]
1576
1577
1578###############################################################################
1579#   SupplementalData                                                          #
1580###############################################################################
1581
1582class SupDataEntry(Packet):
1583    name = "Supplemental Data Entry - Generic"
1584    fields_desc = [ShortField("sdtype", None),
1585                   FieldLenField("len", None, length_of="data"),
1586                   StrLenField("data", "",
1587                               length_from=lambda pkt:pkt.len)]
1588
1589    def guess_payload_class(self, p):
1590        return Padding
1591
1592
1593class UserMappingData(Packet):
1594    name = "User Mapping Data"
1595    fields_desc = [ByteField("version", None),
1596                   FieldLenField("len", None, length_of="data"),
1597                   StrLenField("data", "",
1598                               length_from=lambda pkt: pkt.len)]
1599
1600    def guess_payload_class(self, p):
1601        return Padding
1602
1603
1604class SupDataEntryUM(Packet):
1605    name = "Supplemental Data Entry - User Mapping"
1606    fields_desc = [ShortField("sdtype", None),
1607                   FieldLenField("len", None, length_of="data",
1608                                 adjust=lambda pkt, x: x + 2),
1609                   FieldLenField("dlen", None, length_of="data"),
1610                   PacketListField("data", [], UserMappingData,
1611                                   length_from=lambda pkt:pkt.dlen)]
1612
1613    def guess_payload_class(self, p):
1614        return Padding
1615
1616
1617class TLSSupplementalData(_TLSHandshake):
1618    name = "TLS Handshake - Supplemental Data"
1619    fields_desc = [ByteEnumField("msgtype", 23, _tls_handshake_type),
1620                   ThreeBytesField("msglen", None),
1621                   ThreeBytesLenField("sdatalen", None, length_of="sdata"),
1622                   PacketListField("sdata", [], SupDataEntry,
1623                                   length_from=lambda pkt: pkt.sdatalen)]
1624
1625
1626###############################################################################
1627#   NewSessionTicket                                                          #
1628###############################################################################
1629
1630class TLSNewSessionTicket(_TLSHandshake):
1631    """
1632    XXX When knowing the right secret, we should be able to read the ticket.
1633    """
1634    name = "TLS Handshake - New Session Ticket"
1635    fields_desc = [ByteEnumField("msgtype", 4, _tls_handshake_type),
1636                   ThreeBytesField("msglen", None),
1637                   IntField("lifetime", 0xffffffff),
1638                   FieldLenField("ticketlen", None, length_of="ticket"),
1639                   StrLenField("ticket", "",
1640                               length_from=lambda pkt: pkt.ticketlen)]
1641
1642    @classmethod
1643    def dispatch_hook(cls, _pkt=None, *args, **kargs):
1644        s = kargs.get("tls_session", None)
1645        if s and s.tls_version and s.tls_version >= 0x0304:
1646            return TLS13NewSessionTicket
1647        return TLSNewSessionTicket
1648
1649    def post_dissection_tls_session_update(self, msg_str):
1650        self.tls_session_update(msg_str)
1651        if self.tls_session.connection_end == "client":
1652            self.tls_session.client_session_ticket = self.ticket
1653
1654
1655class TLS13NewSessionTicket(_TLSHandshake):
1656    """
1657    Uncomment the TicketField line for parsing a RFC 5077 ticket.
1658    """
1659    name = "TLS 1.3 Handshake - New Session Ticket"
1660    fields_desc = [ByteEnumField("msgtype", 4, _tls_handshake_type),
1661                   ThreeBytesField("msglen", None),
1662                   IntField("ticket_lifetime", 0xffffffff),
1663                   IntField("ticket_age_add", 0),
1664                   FieldLenField("noncelen", None, fmt="B",
1665                                 length_of="ticket_nonce"),
1666                   StrLenField("ticket_nonce", "",
1667                               length_from=lambda pkt: pkt.noncelen),
1668                   FieldLenField("ticketlen", None, length_of="ticket"),
1669                   # TicketField("ticket", "",
1670                   StrLenField("ticket", "",
1671                               length_from=lambda pkt: pkt.ticketlen),
1672                   _ExtensionsLenField("extlen", None, length_of="ext"),
1673                   _ExtensionsField("ext", None,
1674                                    length_from=lambda pkt: (pkt.msglen -
1675                                                             (pkt.ticketlen or 0) -  # noqa: E501
1676                                                             pkt.noncelen or 0) - 13)]  # noqa: E501
1677
1678    def build(self):
1679        fval = self.getfieldval("ticket")
1680        if fval == b"":
1681            # Here, the ticket is just a random 48-byte label
1682            # The ticket may also be a self-encrypted and self-authenticated
1683            # value
1684            self.ticket = os.urandom(48)
1685
1686        fval = self.getfieldval("ticket_nonce")
1687        if fval == b"":
1688            # Nonce is randomly chosen
1689            self.ticket_nonce = os.urandom(32)
1690
1691        fval = self.getfieldval("ticket_lifetime")
1692        if fval == 0xffffffff:
1693            # ticket_lifetime is set to 12 hours
1694            self.ticket_lifetime = 43200
1695
1696        fval = self.getfieldval("ticket_age_add")
1697        if fval == 0:
1698            # ticket_age_add is a random 32-bit value
1699            self.ticket_age_add = struct.unpack("!I", os.urandom(4))[0]
1700
1701        return _TLSHandshake.build(self)
1702
1703    def post_dissection_tls_session_update(self, msg_str):
1704        if self.tls_session.connection_end == "client":
1705            self.tls_session.client_session_ticket = self.ticket
1706
1707
1708###############################################################################
1709#   EndOfEarlyData                                                            #
1710###############################################################################
1711
1712class TLS13EndOfEarlyData(_TLSHandshake):
1713    name = "TLS 1.3 Handshake - End Of Early Data"
1714
1715    fields_desc = [ByteEnumField("msgtype", 5, _tls_handshake_type),
1716                   ThreeBytesField("msglen", None)]
1717
1718
1719###############################################################################
1720#   KeyUpdate                                                                 #
1721###############################################################################
1722_key_update_request = {0: "update_not_requested", 1: "update_requested"}
1723
1724
1725class TLS13KeyUpdate(_TLSHandshake):
1726    name = "TLS 1.3 Handshake - Key Update"
1727    fields_desc = [ByteEnumField("msgtype", 24, _tls_handshake_type),
1728                   ThreeBytesField("msglen", None),
1729                   ByteEnumField("request_update", 0, _key_update_request)]
1730
1731    def post_build_tls_session_update(self, msg_str):
1732        s = self.tls_session
1733        s.pwcs = writeConnState(ciphersuite=type(s.wcs.ciphersuite),
1734                                connection_end=s.connection_end,
1735                                tls_version=s.tls_version)
1736        s.triggered_pwcs_commit = True
1737        s.compute_tls13_next_traffic_secrets(s.connection_end, "write")
1738
1739    def post_dissection_tls_session_update(self, msg_str):
1740        s = self.tls_session
1741        s.prcs = writeConnState(ciphersuite=type(s.rcs.ciphersuite),
1742                                connection_end=s.connection_end,
1743                                tls_version=s.tls_version)
1744        s.triggered_prcs_commit = True
1745        if s.connection_end == "server":
1746            s.compute_tls13_next_traffic_secrets("client", "read")
1747        elif s.connection_end == "client":
1748            s.compute_tls13_next_traffic_secrets("server", "read")
1749
1750
1751###############################################################################
1752#   All handshake messages defined in this module                             #
1753###############################################################################
1754
1755_tls_handshake_cls = {0: TLSHelloRequest, 1: TLSClientHello,
1756                      2: TLSServerHello, 3: TLSHelloVerifyRequest,
1757                      4: TLSNewSessionTicket,
1758                      8: TLSEncryptedExtensions, 11: TLSCertificate,
1759                      12: TLSServerKeyExchange, 13: TLSCertificateRequest,
1760                      14: TLSServerHelloDone, 15: TLSCertificateVerify,
1761                      16: TLSClientKeyExchange, 20: TLSFinished,
1762                      21: TLSCertificateURL, 22: TLSCertificateStatus,
1763                      23: TLSSupplementalData}
1764
1765_tls13_handshake_cls = {1: TLS13ClientHello, 2: TLS13ServerHello,
1766                        4: TLS13NewSessionTicket, 5: TLS13EndOfEarlyData,
1767                        8: TLSEncryptedExtensions, 11: TLS13Certificate,
1768                        13: TLS13CertificateRequest, 15: TLSCertificateVerify,
1769                        20: TLSFinished, 24: TLS13KeyUpdate}
1770