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