• 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#               2019 Gabriel Potter
8
9"""
10Common TLS fields & bindings.
11
12This module covers the record layer, along with the ChangeCipherSpec, Alert and
13ApplicationData submessages. For the Handshake type, see tls_handshake.py.
14
15See the TLS class documentation for more information.
16"""
17
18import struct
19
20from scapy.config import conf
21from scapy.error import log_runtime
22from scapy.fields import ByteEnumField, PacketListField, StrField
23from scapy.compat import raw, chb, orb
24from scapy.utils import randstring
25from scapy.packet import Raw, Padding, bind_layers
26from scapy.layers.inet import TCP
27from scapy.layers.tls.session import _GenericTLSSessionInheritance
28from scapy.layers.tls.handshake import (_tls_handshake_cls, _TLSHandshake,
29                                        _tls13_handshake_cls, TLS13ServerHello,
30                                        TLS13ClientHello)
31from scapy.layers.tls.basefields import (_TLSVersionField, _tls_version,
32                                         _TLSIVField, _TLSMACField,
33                                         _TLSPadField, _TLSPadLenField,
34                                         _TLSLengthField, _tls_type)
35from scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp
36from scapy.layers.tls.crypto.cipher_aead import AEADTagError
37from scapy.layers.tls.crypto.cipher_stream import Cipher_NULL
38from scapy.layers.tls.crypto.common import CipherError
39from scapy.layers.tls.crypto.h_mac import HMACError
40if conf.crypto_valid_advanced:
41    from scapy.layers.tls.crypto.cipher_aead import Cipher_CHACHA20_POLY1305
42
43
44###############################################################################
45#   TLS Record Protocol                                                       #
46###############################################################################
47
48
49class _TLSEncryptedContent(Raw, _GenericTLSSessionInheritance):
50    """
51    When the content of a TLS record (more precisely, a TLSCiphertext) could
52    not be deciphered, we use this class to represent the encrypted data.
53    The MAC will still be parsed from the whole message, even though it could
54    not been verified. When present (depending on cipher type and protocol
55    version), the nonce_explicit, IV and/or padding will also be parsed.
56    """
57    name = "Encrypted Content"
58    match_subclass = True
59
60
61class _TLSMsgListField(PacketListField):
62    """
63    This is the actual content of the TLS record. As a TLS record may pack
64    multiple sublayer messages (notably, several handshake messages),
65    we inherit from PacketListField.
66    """
67
68    def __init__(self, name, default, length_from=None):
69        if not length_from:
70            length_from = self._get_length
71        super(_TLSMsgListField, self).__init__(name, default, None,
72                                               length_from=length_from)
73
74    def _get_length(self, pkt):
75        if pkt.deciphered_len is None:
76            return pkt.len
77        return pkt.deciphered_len
78
79    def m2i(self, pkt, m):
80        """
81        Try to parse one of the TLS subprotocols (ccs, alert, handshake or
82        application_data). This is used inside a loop managed by .getfield().
83        """
84        cls = Raw
85        if pkt.type == 22:
86            if len(m) >= 1:
87                msgtype = orb(m[0])
88                # If a version was agreed on by both client and server,
89                # we use it (tls_session.tls_version)
90                # Otherwise, if the client advertised for TLS 1.3, we try to
91                # dissect the following packets (most likely, server hello)
92                # using TLS 1.3. The serverhello is able to fallback on
93                # TLS 1.2 if necessary. In any case, this will set the agreed
94                # version so that all future packets are correct.
95                if ((pkt.tls_session.advertised_tls_version == 0x0304 and
96                        pkt.tls_session.tls_version is None) or
97                        pkt.tls_session.tls_version == 0x0304):
98                    cls = _tls13_handshake_cls.get(msgtype, Raw)
99                else:
100                    cls = _tls_handshake_cls.get(msgtype, Raw)
101
102        elif pkt.type == 20:
103            cls = TLSChangeCipherSpec
104        elif pkt.type == 21:
105            cls = TLSAlert
106        elif pkt.type == 23:
107            cls = TLSApplicationData
108
109        if cls is Raw:
110            return Raw(m)
111        else:
112            try:
113                return cls(m, tls_session=pkt.tls_session)
114            except Exception:
115                if conf.debug_dissector:
116                    raise
117                return Raw(m)
118
119    def getfield(self, pkt, s):
120        """
121        If the decryption of the content did not fail with a CipherError,
122        we begin a loop on the clear content in order to get as much messages
123        as possible, of the type advertised in the record header. This is
124        notably important for several TLS handshake implementations, which
125        may for instance pack a server_hello, a certificate, a
126        server_key_exchange and a server_hello_done, all in one record.
127        Each parsed message may update the TLS context through their method
128        .post_dissection_tls_session_update().
129
130        If the decryption failed with a CipherError, presumably because we
131        missed the session keys, we signal it by returning a
132        _TLSEncryptedContent packet which simply contains the ciphered data.
133        """
134        tmp_len = self.length_from(pkt)
135        lst = []
136        ret = b""
137        remain = s
138        if tmp_len is not None:
139            remain, ret = s[:tmp_len], s[tmp_len:]
140
141        if remain == b"":
142            if (((pkt.tls_session.tls_version or 0x0303) > 0x0200) and
143                    hasattr(pkt, "type") and pkt.type == 23):
144                return ret, [TLSApplicationData(data=b"")]
145            elif hasattr(pkt, "type") and pkt.type == 20:
146                return ret, [TLSChangeCipherSpec()]
147            else:
148                return ret, [Raw(load=b"")]
149
150        if False in pkt.tls_session.rcs.cipher.ready.values():
151            return ret, _TLSEncryptedContent(remain)
152        else:
153            while remain:
154                raw_msg = remain
155                p = self.m2i(pkt, remain)
156                if Padding in p:
157                    pad = p[Padding]
158                    remain = pad.load
159                    del pad.underlayer.payload
160                    if len(remain) != 0:
161                        raw_msg = raw_msg[:-len(remain)]
162                else:
163                    remain = b""
164
165                if isinstance(p, _GenericTLSSessionInheritance):
166                    if not p.tls_session.frozen:
167                        p.post_dissection_tls_session_update(raw_msg)
168
169                lst.append(p)
170            return remain + ret, lst
171
172    def i2m(self, pkt, p):
173        """
174        Update the context with information from the built packet.
175        If no type was given at the record layer, we try to infer it.
176        """
177        cur = b""
178        if isinstance(p, _GenericTLSSessionInheritance):
179            if pkt.type is None:
180                if isinstance(p, TLSChangeCipherSpec):
181                    pkt.type = 20
182                elif isinstance(p, TLSAlert):
183                    pkt.type = 21
184                elif isinstance(p, _TLSHandshake):
185                    pkt.type = 22
186                elif isinstance(p, TLSApplicationData):
187                    pkt.type = 23
188            p.tls_session = pkt.tls_session
189            if not pkt.tls_session.frozen:
190                cur = p.raw_stateful()
191                p.post_build_tls_session_update(cur)
192            else:
193                cur = raw(p)
194        else:
195            pkt.type = 23
196            cur = raw(p)
197        return cur
198
199    def addfield(self, pkt, s, val):
200        """
201        Reconstruct the header because the TLS type may have been updated.
202        Then, append the content.
203        """
204        res = b""
205        for p in val:
206            res += self.i2m(pkt, p)
207
208        # Add TLS13ClientHello in case of HelloRetryRequest
209        # Add ChangeCipherSpec for middlebox compatibility
210        if (isinstance(pkt, _GenericTLSSessionInheritance) and
211                pkt.tls_session.tls_version == 0x0304 and
212                not isinstance(pkt.msg[0], TLS13ServerHello) and
213                not isinstance(pkt.msg[0], TLS13ClientHello) and
214                not isinstance(pkt.msg[0], TLSChangeCipherSpec)):
215            return s + res
216
217        if not pkt.type:
218            pkt.type = 0
219
220        hdr = struct.pack("!B", pkt.type) + s[1:5]
221        return hdr + res
222
223
224def _ssl_looks_like_sslv2(dat):
225    """
226    This is a copycat of wireshark's `packet-tls.c` ssl_looks_like_sslv2
227    """
228    if len(dat) < 3:
229        return
230    from scapy.layers.tls.handshake_sslv2 import _sslv2_handshake_type
231    return ord(dat[:1]) >= 0x80 and ord(dat[2:3]) in _sslv2_handshake_type
232
233
234class TLS(_GenericTLSSessionInheritance):
235    """
236    The generic TLS Record message, based on section 6.2 of RFC 5246.
237
238    When reading a TLS message, we try to parse as much as we can.
239    In .pre_dissect(), according to the type of the current cipher algorithm
240    (self.tls_session.rcs.cipher.type), we extract the 'iv', 'mac', 'pad' and
241    'padlen'. Some of these fields may remain blank: for instance, when using
242    a stream cipher, there is no IV nor any padding. The 'len' should always
243    hold the length of the ciphered message; for the plaintext version, you
244    should rely on the additional 'deciphered_len' attribute.
245
246    XXX Fix 'deciphered_len' which should not be defined when failing with
247    AEAD decryption. This is related to the 'decryption_success' below.
248    Also, follow this behaviour in record_sslv2.py and record_tls13.py
249
250    Once we have isolated the ciphered message aggregate (which should be one
251    or several TLS messages of the same type), we try to decipher it. Either we
252    succeed and store the clear data in 'msg', or we graciously fail with a
253    CipherError and store the ciphered data in 'msg'.
254
255    Unless the user manually provides the session secrets through the passing
256    of a 'tls_session', obviously the ciphered messages will not be deciphered.
257    Indeed, the need for a proper context may also present itself when trying
258    to parse clear handshake messages.
259
260    For instance, suppose you sniffed the beginning of a DHE-RSA negotiation::
261
262        t1 = TLS(<client_hello>)
263        t2 = TLS(<server_hello | certificate | server_key_exchange>)
264        t3 = TLS(<server_hello | certificate | server_key_exchange>,
265                 tls_session=t1.tls_session)
266
267    (Note that to do things properly, here 't1.tls_session' should actually be
268    't1.tls_session.mirror()'. See session.py for explanations.)
269
270    As no context was passed to t2, neither was any client_random. Hence Scapy
271    will not be able to verify the signature of the server_key_exchange inside
272    t2. However, it should be able to do so for t3, thanks to the tls_session.
273    The consequence of not having a complete TLS context is even more obvious
274    when trying to parse ciphered content, as we described before.
275
276    Thus, in order to parse TLS-protected communications with Scapy:
277    _either Scapy reads every message from one side of the TLS connection and
278    builds every message from the other side (as such, it should know the
279    secrets needed for the generation of the pre_master_secret), while passing
280    the same tls_session context (this is how our automaton.py mostly works);
281    _or, if Scapy did not build any TLS message, it has to create a TLS context
282    and feed it with secrets retrieved by whatever technique. Note that the
283    knowing the private key of the server certificate will not be sufficient
284    if a PFS ciphersuite was used. However, if you got a master_secret somehow,
285    use it with tls_session.(w|r)cs.derive_keys() and leave the rest to Scapy.
286
287    When building a TLS message with raw_stateful, we expect the tls_session to
288    have the right parameters for ciphering. Else, .post_build() might fail.
289    """
290    __slots__ = ["deciphered_len"]
291    name = "TLS"
292    fields_desc = [ByteEnumField("type", None, _tls_type),
293                   _TLSVersionField("version", None, _tls_version),
294                   _TLSLengthField("len", None),
295                   _TLSIVField("iv", None),
296                   _TLSMsgListField("msg", []),
297                   _TLSMACField("mac", None),
298                   _TLSPadField("pad", None),
299                   _TLSPadLenField("padlen", None)]
300
301    def __init__(self, *args, **kargs):
302        self.deciphered_len = kargs.get("deciphered_len", None)
303        super(TLS, self).__init__(*args, **kargs)
304
305    @classmethod
306    def dispatch_hook(cls, _pkt=None, *args, **kargs):
307        """
308        If the TLS class was called on raw SSLv2 data, we want to return an
309        SSLv2 record instance. We acknowledge the risk of SSLv2 packets with a
310        msglen of 0x1403, 0x1503, 0x1603 or 0x1703 which will never be casted
311        as SSLv2 records but TLS ones instead, but hey, we can't be held
312        responsible for low-minded extensibility choices.
313        """
314        if _pkt is not None:
315            plen = len(_pkt)
316            if plen >= 2:
317                byte0, byte1 = struct.unpack("BB", _pkt[:2])
318                s = kargs.get("tls_session", None)
319                if byte0 not in _tls_type or byte1 != 3:  # Unknown type
320                    # Check SSLv2: either the session is already SSLv2,
321                    # either the packet looks like one. As said above, this
322                    # isn't 100% reliable, but Wireshark does the same
323                    if s and (s.tls_version == 0x0002 or
324                              s.advertised_tls_version == 0x0002) or \
325                             (_ssl_looks_like_sslv2(_pkt) and (not s or
326                              s.tls_version is None)):
327                        from scapy.layers.tls.record_sslv2 import SSLv2
328                        return SSLv2
329                    # Not SSLv2: continuation
330                    return _TLSEncryptedContent
331                if plen >= 5:
332                    # Check minimum length
333                    msglen = struct.unpack('!H', _pkt[3:5])[0] + 5
334                    if plen < msglen:
335                        # This is a fragment
336                        return conf.padding_layer
337                # Check TLS 1.3
338                if s and s.tls_version == 0x0304:
339                    _has_cipher = lambda x: (
340                        x and not isinstance(x.cipher, Cipher_NULL)
341                    )
342                    if (_has_cipher(s.rcs) or _has_cipher(s.prcs)) and \
343                            byte0 == 0x17:
344                        from scapy.layers.tls.record_tls13 import TLS13
345                        return TLS13
346            if plen < 5:
347                # Layer detected as TLS but too small to be a
348                # parsed. Scapy should not try to decode them
349                return _TLSEncryptedContent
350        return TLS
351
352    # Parsing methods
353
354    def _tls_auth_decrypt(self, hdr, s):
355        """
356        Provided with the record header and AEAD-ciphered data, return the
357        sliced and clear tuple (nonce, TLSCompressed.fragment, mac). Note that
358        we still return the slicing of the original input in case of decryption
359        failure. Also, if the integrity check fails, a warning will be issued,
360        but we still return the sliced (unauthenticated) plaintext.
361        """
362        try:
363            read_seq_num = struct.pack("!Q", self.tls_session.rcs.seq_num)
364            self.tls_session.rcs.seq_num += 1
365            # self.type and self.version have not been parsed yet,
366            # this is why we need to look into the provided hdr.
367            add_data = read_seq_num + hdr[:3]
368            # Last two bytes of add_data are appended by the return function
369            return self.tls_session.rcs.cipher.auth_decrypt(add_data, s,
370                                                            read_seq_num)
371        except CipherError as e:
372            return e.args
373        except AEADTagError as e:
374            pkt_info = self.firstlayer().summary()
375            log_runtime.info("TLS: record integrity check failed [%s]", pkt_info)  # noqa: E501
376            return e.args
377
378    def _tls_decrypt(self, s):
379        """
380        Provided with stream- or block-ciphered data, return the clear version.
381        The cipher should have been updated with the right IV early on,
382        which should not be at the beginning of the input.
383        In case of decryption failure, a CipherError will be raised with
384        the slicing of the original input as first argument.
385        """
386        return self.tls_session.rcs.cipher.decrypt(s)
387
388    def _tls_hmac_verify(self, hdr, msg, mac):
389        """
390        Provided with the record header, the TLSCompressed.fragment and the
391        HMAC, return True if the HMAC is correct. If we could not compute the
392        HMAC because the key was missing, there is no sense in verifying
393        anything, thus we also return True.
394
395        Meant to be used with a block cipher or a stream cipher.
396        It would fail with an AEAD cipher, because rcs.hmac would be None.
397        See RFC 5246, section 6.2.3.
398        """
399        read_seq_num = struct.pack("!Q", self.tls_session.rcs.seq_num)
400        self.tls_session.rcs.seq_num += 1
401
402        mac_len = self.tls_session.rcs.mac_len
403        if mac_len == 0:            # should be TLS_NULL_WITH_NULL_NULL
404            return True
405        if len(mac) != mac_len:
406            return False
407
408        alg = self.tls_session.rcs.hmac
409        version = struct.unpack("!H", hdr[1:3])[0]
410        try:
411            if version > 0x300:
412                h = alg.digest(read_seq_num + hdr + msg)
413            elif version == 0x300:
414                h = alg.digest_sslv3(read_seq_num + hdr[:1] + hdr[3:5] + msg)
415            else:
416                raise Exception("Unrecognized version.")
417        except HMACError:
418            h = mac
419        return h == mac
420
421    def _tls_decompress(self, s):
422        """
423        Provided with the TLSCompressed.fragment,
424        return the TLSPlaintext.fragment.
425        """
426        alg = self.tls_session.rcs.compression
427        return alg.decompress(s)
428
429    def pre_dissect(self, s):
430        """
431        Decrypt, verify and decompress the message,
432        i.e. apply the previous methods according to the reading cipher type.
433        If the decryption was successful, 'len' will be the length of the
434        TLSPlaintext.fragment. Else, it should be the length of the
435        _TLSEncryptedContent.
436        """
437        if len(s) < 5:
438            raise Exception("Invalid record: header is too short.")
439
440        msglen = struct.unpack('!H', s[3:5])[0]
441        hdr, efrag, r = s[:5], s[5:5 + msglen], s[msglen + 5:]
442
443        iv = mac = pad = b""
444        self.padlen = None
445        decryption_success = False
446
447        cipher_type = self.tls_session.rcs.cipher.type
448
449        def extract_mac(data):
450            """Extract MAC."""
451            tmp_len = self.tls_session.rcs.mac_len
452            if tmp_len != 0:
453                frag, mac = data[:-tmp_len], data[-tmp_len:]
454            else:
455                frag, mac = data, b""
456            return frag, mac
457
458        def verify_mac(hdr, cfrag, mac):
459            """Verify integrity."""
460            chdr = hdr[:3] + struct.pack('!H', len(cfrag))
461            is_mac_ok = self._tls_hmac_verify(chdr, cfrag, mac)
462            if not is_mac_ok:
463                pkt_info = self.firstlayer().summary()
464                log_runtime.info(
465                    "TLS: record integrity check failed [%s]", pkt_info,
466                )
467
468        if cipher_type == 'block':
469            version = struct.unpack("!H", s[1:3])[0]
470
471            if self.tls_session.encrypt_then_mac:
472                efrag, mac = extract_mac(efrag)
473                verify_mac(hdr, efrag, mac)
474
475            # Decrypt
476            try:
477                if version >= 0x0302:
478                    # Explicit IV for TLS 1.1 and 1.2
479                    block_size = self.tls_session.rcs.cipher.block_size
480                    iv, efrag = efrag[:block_size], efrag[block_size:]
481                    self.tls_session.rcs.cipher.iv = iv
482                    pfrag = self._tls_decrypt(efrag)
483                else:
484                    # Implicit IV for SSLv3 and TLS 1.0
485                    pfrag = self._tls_decrypt(efrag)
486            except CipherError as e:
487                # This will end up dissected as _TLSEncryptedContent.
488                cfrag = e.args[0]
489            else:
490                decryption_success = True
491                # Excerpt below better corresponds to TLS 1.1 IV definition,
492                # but the result is the same as with TLS 1.2 anyway.
493                # This leading *IV* has been decrypted by _tls_decrypt with a
494                # random IV, hence it does not correspond to anything.
495                # What actually matters is that we got the first encrypted block  # noqa: E501
496                # in order to decrypt the second block (first data block).
497                # if version >= 0x0302:
498                #    block_size = self.tls_session.rcs.cipher.block_size
499                #    iv, pfrag = pfrag[:block_size], pfrag[block_size:]
500                #    l = struct.unpack('!H', hdr[3:5])[0]
501                #    hdr = hdr[:3] + struct.pack('!H', l-block_size)
502
503                # Extract padding ('pad' actually includes the trailing padlen)
504                padlen = orb(pfrag[-1]) + 1
505                mfrag, pad = pfrag[:-padlen], pfrag[-padlen:]
506                self.padlen = padlen
507
508                if self.tls_session.encrypt_then_mac:
509                    cfrag = mfrag
510                else:
511                    cfrag, mac = extract_mac(mfrag)
512                    verify_mac(hdr, cfrag, mac)
513
514        elif cipher_type == 'stream':
515            # Decrypt
516            try:
517                pfrag = self._tls_decrypt(efrag)
518            except CipherError as e:
519                # This will end up dissected as _TLSEncryptedContent.
520                cfrag = e.args[0]
521            else:
522                decryption_success = True
523                cfrag, mac = extract_mac(pfrag)
524                verify_mac(hdr, cfrag, mac)
525
526        elif cipher_type == 'aead':
527            # Authenticated encryption
528            # crypto/cipher_aead.py prints a warning for integrity failure
529            if (conf.crypto_valid_advanced and
530                    isinstance(self.tls_session.rcs.cipher, Cipher_CHACHA20_POLY1305)):  # noqa: E501
531                iv = b""
532                cfrag, mac = self._tls_auth_decrypt(hdr, efrag)
533            else:
534                iv, cfrag, mac = self._tls_auth_decrypt(hdr, efrag)
535            decryption_success = True       # see XXX above
536
537        frag = self._tls_decompress(cfrag)
538
539        if decryption_success:
540            self.deciphered_len = len(frag)
541        else:
542            self.deciphered_len = None
543
544        reconstructed_body = iv + frag + mac + pad
545
546        return hdr + reconstructed_body + r
547
548    def post_dissect(self, s):
549        """
550        Commit the pending r/w state if it has been triggered (e.g. by an
551        underlying TLSChangeCipherSpec or a SSLv2ClientMasterKey). We update
552        nothing if the prcs was not set, as this probably means that we're
553        working out-of-context (and we need to keep the default rcs).
554        """
555        if (self.tls_session.tls_version and
556                self.tls_session.tls_version <= 0x0303):
557            if self.tls_session.triggered_prcs_commit:
558                if self.tls_session.prcs is not None:
559                    self.tls_session.rcs = self.tls_session.prcs
560                    self.tls_session.prcs = None
561                self.tls_session.triggered_prcs_commit = False
562            if self.tls_session.triggered_pwcs_commit:
563                if self.tls_session.pwcs is not None:
564                    self.tls_session.wcs = self.tls_session.pwcs
565                    self.tls_session.pwcs = None
566                self.tls_session.triggered_pwcs_commit = False
567        return s
568
569    def do_dissect_payload(self, s):
570        """
571        Try to dissect the following data as a TLS message.
572        Note that overloading .guess_payload_class() would not be enough,
573        as the TLS session to be used would get lost.
574        """
575        if s:
576            # Check minimum length
577            if len(s) < 5:
578                p = conf.raw_layer(s, _internal=1, _underlayer=self)
579                self.add_payload(p)
580                return
581            msglen = struct.unpack('!H', s[3:5])[0] + 5
582            if len(s) < msglen:
583                # This is a fragment
584                self.add_payload(conf.padding_layer(s))
585                return
586            try:
587                p = TLS(s, _internal=1, _underlayer=self,
588                        tls_session=self.tls_session)
589            except KeyboardInterrupt:
590                raise
591            except Exception:
592                if conf.debug_dissector:
593                    raise
594                p = conf.raw_layer(s, _internal=1, _underlayer=self)
595            self.add_payload(p)
596
597    # Building methods
598
599    def _tls_compress(self, s):
600        """
601        Provided with the TLSPlaintext.fragment,
602        return the TLSCompressed.fragment.
603        """
604        alg = self.tls_session.wcs.compression
605        return alg.compress(s)
606
607    def _tls_auth_encrypt(self, s):
608        """
609        Return the TLSCiphertext.fragment for AEAD ciphers, i.e. the whole
610        GenericAEADCipher. Also, the additional data is computed right here.
611        """
612        write_seq_num = struct.pack("!Q", self.tls_session.wcs.seq_num)
613        self.tls_session.wcs.seq_num += 1
614        add_data = (write_seq_num +
615                    pkcs_i2osp(self.type, 1) +
616                    pkcs_i2osp(self.version, 2) +
617                    pkcs_i2osp(len(s), 2))
618        return self.tls_session.wcs.cipher.auth_encrypt(s, add_data,
619                                                        write_seq_num)
620
621    def _tls_hmac_add(self, hdr, msg):
622        """
623        Provided with the record header (concatenation of the TLSCompressed
624        type, version and length fields) and the TLSCompressed.fragment,
625        return the concatenation of the TLSCompressed.fragment and the HMAC.
626
627        Meant to be used with a block cipher or a stream cipher.
628        It would fail with an AEAD cipher, because wcs.hmac would be None.
629        See RFC 5246, section 6.2.3.
630        """
631        write_seq_num = struct.pack("!Q", self.tls_session.wcs.seq_num)
632        self.tls_session.wcs.seq_num += 1
633
634        alg = self.tls_session.wcs.hmac
635        version = struct.unpack("!H", hdr[1:3])[0]
636        if version > 0x300:
637            h = alg.digest(write_seq_num + hdr + msg)
638        elif version == 0x300:
639            h = alg.digest_sslv3(write_seq_num + hdr[:1] + hdr[3:5] + msg)
640        else:
641            raise Exception("Unrecognized version.")
642        return msg + h
643
644    def _tls_pad(self, s):
645        """
646        Provided with the concatenation of the TLSCompressed.fragment and the
647        HMAC, append the right padding and return it as a whole.
648        This is the TLS-style padding: while SSL allowed for random padding,
649        TLS (misguidedly) specifies the repetition of the same byte all over,
650        and this byte must be equal to len(<entire padding>) - 1.
651
652        Meant to be used with a block cipher only.
653        """
654        padding = b""
655        block_size = self.tls_session.wcs.cipher.block_size
656        padlen = block_size - ((len(s) + 1) % block_size)
657        if padlen == block_size:
658            padlen = 0
659        pad_pattern = chb(padlen)
660        padding = pad_pattern * (padlen + 1)
661        return s + padding
662
663    def _tls_encrypt(self, s):
664        """
665        Return the stream- or block-ciphered version of the concatenated input.
666        In case of GenericBlockCipher, no IV has been specifically prepended to
667        the output, so this might not be the whole TLSCiphertext.fragment yet.
668        """
669        return self.tls_session.wcs.cipher.encrypt(s)
670
671    def post_build(self, pkt, pay):
672        """
673        Apply the previous methods according to the writing cipher type.
674        """
675        # Compute the length of TLSPlaintext fragment
676        hdr, frag = pkt[:5], pkt[5:]
677        tmp_len = len(frag)
678        hdr = hdr[:3] + struct.pack("!H", tmp_len)
679
680        # Compression
681        cfrag = self._tls_compress(frag)
682        tmp_len = len(cfrag)  # Update the length as a result of compression
683        hdr = hdr[:3] + struct.pack("!H", tmp_len)
684
685        cipher_type = self.tls_session.wcs.cipher.type
686
687        if cipher_type == 'block':
688            # Integrity
689            if not self.tls_session.encrypt_then_mac:
690                cfrag = self._tls_hmac_add(hdr, cfrag)
691
692            # Excerpt below better corresponds to TLS 1.1 IV definition,
693            # but the result is the same as with TLS 1.2 anyway.
694            # if self.version >= 0x0302:
695            #    l = self.tls_session.wcs.cipher.block_size
696            #    iv = randstring(l)
697            #    mfrag = iv + mfrag
698
699            # Add padding
700            pfrag = self._tls_pad(cfrag)
701
702            # Encryption
703            if self.version >= 0x0302:
704                # Explicit IV for TLS 1.1 and 1.2
705                tmp_len = self.tls_session.wcs.cipher.block_size
706                iv = randstring(tmp_len)
707                self.tls_session.wcs.cipher.iv = iv
708                efrag = self._tls_encrypt(pfrag)
709                efrag = iv + efrag
710            else:
711                # Implicit IV for SSLv3 and TLS 1.0
712                efrag = self._tls_encrypt(pfrag)
713
714            if self.tls_session.encrypt_then_mac:
715                efrag = self._tls_hmac_add(hdr, efrag)
716
717        elif cipher_type == "stream":
718            # Integrity
719            mfrag = self._tls_hmac_add(hdr, cfrag)
720            # Encryption
721            efrag = self._tls_encrypt(mfrag)
722
723        elif cipher_type == "aead":
724            # Authenticated encryption (with nonce_explicit as header)
725            efrag = self._tls_auth_encrypt(cfrag)
726
727        if self.len is not None:
728            # The user gave us a 'len', let's respect this ultimately
729            hdr = hdr[:3] + struct.pack("!H", self.len)
730        else:
731            # Update header with the length of TLSCiphertext.fragment
732            hdr = hdr[:3] + struct.pack("!H", len(efrag))
733
734        # Now we commit the pending write state if it has been triggered (e.g.
735        # by an underlying TLSChangeCipherSpec or a SSLv2ClientMasterKey). We
736        # update nothing if the pwcs was not set. This probably means that
737        # we're working out-of-context (and we need to keep the default wcs).
738        if self.tls_session.triggered_pwcs_commit:
739            if self.tls_session.pwcs is not None:
740                self.tls_session.wcs = self.tls_session.pwcs
741                self.tls_session.pwcs = None
742            self.tls_session.triggered_pwcs_commit = False
743
744        return hdr + efrag + pay
745
746    def mysummary(self):
747        s, n = super(TLS, self).mysummary()
748        if self.msg:
749            s += " / "
750            s += " / ".join(getattr(x, "_name", x.name) for x in self.msg)
751        return s, n
752
753###############################################################################
754#   TLS ChangeCipherSpec                                                      #
755###############################################################################
756
757
758_tls_changecipherspec_type = {1: "change_cipher_spec"}
759
760
761class TLSChangeCipherSpec(_GenericTLSSessionInheritance):
762    """
763    Note that, as they are not handshake messages, the ccs messages do not get
764    appended to the list of messages whose integrity gets verified through the
765    Finished messages.
766    """
767    name = "TLS ChangeCipherSpec"
768    fields_desc = [ByteEnumField("msgtype", 1, _tls_changecipherspec_type)]
769
770    def post_dissection_tls_session_update(self, msg_str):
771        self.tls_session.triggered_prcs_commit = True
772
773    def post_build_tls_session_update(self, msg_str):
774        # Unlike for dissection case, we cannot commit pending write
775        # state as current write state. We need to delay this after
776        # the ChangeCipherSpec message has indeed been sent
777        self.tls_session.triggered_pwcs_commit = True
778
779
780###############################################################################
781#   TLS Alert                                                                 #
782###############################################################################
783
784_tls_alert_level = {1: "warning", 2: "fatal"}
785
786_tls_alert_description = {
787    0: "close_notify", 10: "unexpected_message",
788    20: "bad_record_mac", 21: "decryption_failed",
789    22: "record_overflow", 30: "decompression_failure",
790    40: "handshake_failure", 41: "no_certificate_RESERVED",
791    42: "bad_certificate", 43: "unsupported_certificate",
792    44: "certificate_revoked", 45: "certificate_expired",
793    46: "certificate_unknown", 47: "illegal_parameter",
794    48: "unknown_ca", 49: "access_denied",
795    50: "decode_error", 51: "decrypt_error",
796    60: "export_restriction_RESERVED", 70: "protocol_version",
797    71: "insufficient_security", 80: "internal_error",
798    86: "inappropriate_fallback", 90: "user_canceled",
799    100: "no_renegotiation", 109: "missing_extension",
800    110: "unsupported_extension", 111: "certificate_unobtainable",
801    112: "unrecognized_name", 113: "bad_certificate_status_response",
802    114: "bad_certificate_hash_value", 115: "unknown_psk_identity",
803    116: "certificate_required", 120: "no_application_protocol"}
804
805
806class TLSAlert(_GenericTLSSessionInheritance):
807    name = "TLS Alert"
808    fields_desc = [ByteEnumField("level", None, _tls_alert_level),
809                   ByteEnumField("descr", None, _tls_alert_description)]
810
811    def mysummary(self):
812        return self.sprintf("Alert %level%: %descr%")
813
814    def post_dissection_tls_session_update(self, msg_str):
815        pass
816
817    def post_build_tls_session_update(self, msg_str):
818        pass
819
820
821###############################################################################
822#   TLS Application Data                                                      #
823###############################################################################
824
825class TLSApplicationData(_GenericTLSSessionInheritance):
826    name = "TLS Application Data"
827    fields_desc = [StrField("data", "")]
828
829    def post_dissection_tls_session_update(self, msg_str):
830        pass
831
832    def post_build_tls_session_update(self, msg_str):
833        pass
834
835
836###############################################################################
837#   Bindings                                                                  #
838###############################################################################
839
840bind_layers(TCP, TLS, sport=443)
841bind_layers(TCP, TLS, dport=443)
842