• 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"""
7TLS session handler.
8"""
9
10import random
11import socket
12import struct
13
14from scapy.config import conf
15from scapy.compat import *
16import scapy.modules.six as six
17from scapy.error import log_runtime, warning
18from scapy.packet import Packet
19from scapy.utils import repr_hex, strxor
20from scapy.layers.tls.crypto.compression import Comp_NULL
21from scapy.layers.tls.crypto.hkdf import TLS13_HKDF
22from scapy.layers.tls.crypto.prf import PRF
23
24# Note the following import may happen inside connState.__init__()
25# in order to avoid to avoid cyclical dependancies.
26# from scapy.layers.tls.crypto.suites import TLS_NULL_WITH_NULL_NULL
27
28
29###############################################################################
30### Connection states                                                       ###
31###############################################################################
32
33class connState(object):
34    """
35    From RFC 5246, section 6.1:
36    A TLS connection state is the operating environment of the TLS Record
37    Protocol.  It specifies a compression algorithm, an encryption
38    algorithm, and a MAC algorithm.  In addition, the parameters for
39    these algorithms are known: the MAC key and the bulk encryption keys
40    for the connection in both the read and the write directions.
41    Logically, there are always four connection states outstanding: the
42    current read and write states, and the pending read and write states.
43    All records are processed under the current read and write states.
44    The security parameters for the pending states can be set by the TLS
45    Handshake Protocol, and the ChangeCipherSpec can selectively make
46    either of the pending states current, in which case the appropriate
47    current state is disposed of and replaced with the pending state; the
48    pending state is then reinitialized to an empty state.  It is illegal
49    to make a state that has not been initialized with security
50    parameters a current state.  The initial current state always
51    specifies that no encryption, compression, or MAC will be used.
52
53    (For practical reasons, Scapy scraps these two last lines, through the
54    implementation of dummy ciphers and MAC with TLS_NULL_WITH_NULL_NULL.)
55
56    These attributes and behaviours are mostly mapped in this class.
57    Also, note that Scapy may make a current state out of a pending state
58    which has been initialized with dummy security parameters. We need
59    this in order to know when the content of a TLS message is encrypted,
60    whether we possess the right keys to decipher/verify it or not.
61    For instance, when Scapy parses a CKE without knowledge of any secret,
62    and then a CCS, it needs to know that the following Finished
63    is encrypted and signed according to a new cipher suite, even though
64    it cannot decipher the message nor verify its integrity.
65    """
66    def __init__(self,
67                 connection_end="server",
68                 read_or_write="read",
69                 seq_num=0,
70                 compression_alg=Comp_NULL,
71                 ciphersuite=None,
72                 tls_version=0x0303):
73
74        self.tls_version = tls_version
75
76        # It is the user's responsibility to keep the record seq_num
77        # under 2**64-1. If this value gets maxed out, the TLS class in
78        # record.py will crash when trying to encode it with struct.pack().
79        self.seq_num = seq_num
80
81        self.connection_end = connection_end
82        self.row = read_or_write
83
84        if ciphersuite is None:
85            from scapy.layers.tls.crypto.suites import TLS_NULL_WITH_NULL_NULL
86            ciphersuite = TLS_NULL_WITH_NULL_NULL
87        self.ciphersuite = ciphersuite(tls_version=tls_version)
88
89        if not self.ciphersuite.usable:
90            warning("TLS ciphersuite not useable. Is the cryptography Python module installed ?")
91            return
92
93        self.compression = compression_alg()
94        self.key_exchange = ciphersuite.kx_alg()
95        self.cipher = ciphersuite.cipher_alg()
96        self.hash = ciphersuite.hash_alg()
97
98        if tls_version > 0x0200:
99            if ciphersuite.cipher_alg.type == "aead":
100                self.hmac = None
101                self.mac_len = self.cipher.tag_len
102            else:
103                self.hmac = ciphersuite.hmac_alg()
104                self.mac_len = self.hmac.hmac_len
105        else:
106            self.hmac = ciphersuite.hmac_alg()          # should be Hmac_NULL
107            self.mac_len = self.hash.hash_len
108
109        if tls_version >= 0x0304:
110            self.hkdf = TLS13_HKDF(self.hash.name.lower())
111        else:
112            self.prf = PRF(ciphersuite.hash_alg.name, tls_version)
113
114
115    def debug_repr(self, name, secret):
116        if conf.debug_tls and secret:
117            log_runtime.debug("TLS: %s %s %s: %s",
118                              self.connection_end,
119                              self.row,
120                              name,
121                              repr_hex(secret))
122
123    def derive_keys(self,
124                    client_random=b"",
125                    server_random=b"",
126                    master_secret=b""):
127        #XXX Can this be called over a non-usable suite? What happens then?
128
129        cs = self.ciphersuite
130
131        # Derive the keys according to the cipher type and protocol version
132        key_block = self.prf.derive_key_block(master_secret,
133                                              server_random,
134                                              client_random,
135                                              cs.key_block_len)
136
137        # When slicing the key_block, keep the right half of the material
138        skip_first = False
139        if ((self.connection_end == "client" and self.row == "read") or
140            (self.connection_end == "server" and self.row == "write")):
141            skip_first = True
142
143        pos = 0
144        cipher_alg = cs.cipher_alg
145
146        ### MAC secret (for block and stream ciphers)
147        if (cipher_alg.type == "stream") or (cipher_alg.type == "block"):
148            start = pos
149            if skip_first:
150                start += cs.hmac_alg.key_len
151            end = start + cs.hmac_alg.key_len
152            mac_secret = key_block[start:end]
153            self.debug_repr("mac_secret", mac_secret)
154            pos += 2*cs.hmac_alg.key_len
155        else:
156            mac_secret = None
157
158        ### Cipher secret
159        start = pos
160        if skip_first:
161            start += cipher_alg.key_len
162        end = start + cipher_alg.key_len
163        cipher_secret = key_block[start:end]
164        if cs.kx_alg.export:
165            reqLen = cipher_alg.expanded_key_len
166            cipher_secret = self.prf.postprocess_key_for_export(cipher_secret,
167                                                      client_random,
168                                                      server_random,
169                                                      self.connection_end,
170                                                      self.row,
171                                                      reqLen)
172        self.debug_repr("cipher_secret", cipher_secret)
173        pos += 2*cipher_alg.key_len
174
175        ### Implicit IV (for block and AEAD ciphers)
176        start = pos
177        if cipher_alg.type == "block":
178            if skip_first:
179                start += cipher_alg.block_size
180            end = start + cipher_alg.block_size
181        elif cipher_alg.type == "aead":
182            if skip_first:
183                start += cipher_alg.fixed_iv_len
184            end = start + cipher_alg.fixed_iv_len
185
186        ### Now we have the secrets, we can instantiate the algorithms
187        if cs.hmac_alg is None:         # AEAD
188            self.hmac = None
189            self.mac_len = cipher_alg.tag_len
190        else:
191            self.hmac = cs.hmac_alg(mac_secret)
192            self.mac_len = self.hmac.hmac_len
193
194        if cipher_alg.type == "stream":
195            cipher = cipher_alg(cipher_secret)
196        elif cipher_alg.type == "block":
197            # We set an IV every time, even though it does not matter for
198            # TLS 1.1+ as it requires an explicit IV. Indeed the cipher.iv
199            # would get updated in TLS.post_build() or TLS.pre_dissect().
200            iv = key_block[start:end]
201            if cs.kx_alg.export:
202                reqLen = cipher_alg.block_size
203                iv = self.prf.generate_iv_for_export(client_random,
204                                                     server_random,
205                                                     self.connection_end,
206                                                     self.row,
207                                                     reqLen)
208            cipher = cipher_alg(cipher_secret, iv)
209            self.debug_repr("block iv", iv)
210        elif cipher_alg.type == "aead":
211            fixed_iv = key_block[start:end]
212            nonce_explicit_init = 0
213            # If you ever wanted to set a random nonce_explicit, use this:
214            #exp_bit_len = cipher_alg.nonce_explicit_len * 8
215            #nonce_explicit_init = random.randint(0, 2**exp_bit_len - 1)
216            cipher = cipher_alg(cipher_secret, fixed_iv, nonce_explicit_init)
217            self.debug_repr("aead fixed iv", fixed_iv)
218        self.cipher = cipher
219
220    def sslv2_derive_keys(self, key_material):
221        """
222        There is actually only one key, the CLIENT-READ-KEY or -WRITE-KEY.
223
224        Note that skip_first is opposite from the one with SSLv3 derivation.
225
226        Also, if needed, the IV should be set elsewhere.
227        """
228        skip_first = True
229        if ((self.connection_end == "client" and self.row == "read") or
230            (self.connection_end == "server" and self.row == "write")):
231            skip_first = False
232
233        cipher_alg = self.ciphersuite.cipher_alg
234
235        start = 0
236        if skip_first:
237            start += cipher_alg.key_len
238        end = start + cipher_alg.key_len
239        cipher_secret = key_material[start:end]
240        self.cipher = cipher_alg(cipher_secret)
241        self.debug_repr("cipher_secret", cipher_secret)
242
243    def tls13_derive_keys(self, key_material):
244        cipher_alg = self.ciphersuite.cipher_alg
245        key_len = cipher_alg.key_len
246        iv_len = cipher_alg.fixed_iv_len
247        write_key = self.hkdf.expand_label(key_material, b"key", b"", key_len)
248        write_iv = self.hkdf.expand_label(key_material, b"iv", b"", iv_len)
249        self.cipher = cipher_alg(write_key, write_iv)
250
251    def snapshot(self):
252        """
253        This is used mostly as a way to keep the cipher state and the seq_num.
254        """
255        snap = connState(connection_end=self.connection_end,
256                         read_or_write=self.row,
257                         seq_num=self.seq_num,
258                         compression_alg=type(self.compression),
259                         ciphersuite=type(self.ciphersuite),
260                         tls_version=self.tls_version)
261        snap.cipher = self.cipher.snapshot()
262        if self.hmac:
263            snap.hmac.key = self.hmac.key
264        return snap
265
266    def __repr__(self):
267        def indent(s):
268            if s and s[-1] == '\n':
269                s = s[:-1]
270            s = '\n'.join('\t' + x for x in s.split('\n')) + '\n'
271            return s
272
273        res =  "Connection end : %s\n" % self.connection_end.upper()
274        res += "Cipher suite   : %s (0x%04x)\n" % (self.ciphersuite.name,
275                                                   self.ciphersuite.val)
276        res += "Compression    : %s (0x%02x)\n" % (self.compression.name,
277                                                   self.compression.val)
278        tabsize = 4
279        return res.expandtabs(tabsize)
280
281
282class readConnState(connState):
283    def __init__(self, **kargs):
284        connState.__init__(self, read_or_write="read", **kargs)
285
286class writeConnState(connState):
287    def __init__(self, **kargs):
288        connState.__init__(self, read_or_write="write", **kargs)
289
290
291###############################################################################
292### TLS session                                                             ###
293###############################################################################
294
295class tlsSession(object):
296    """
297    This is our TLS context, which gathers information from both sides of the
298    TLS connection. These sides are represented by a readConnState instance and
299    a writeConnState instance. Along with overarching network attributes, a
300    tlsSession object also holds negotiated, shared information, such as the
301    key exchange parameters and the master secret (when available).
302
303    The default connection_end is "server". This corresponds to the expected
304    behaviour for static exchange analysis (with a ClientHello parsed first).
305    """
306    def __init__(self,
307                 ipsrc=None, ipdst=None,
308                 sport=None, dport=None, sid=None,
309                 connection_end="server",
310                 wcs=None, rcs=None):
311
312        # Use this switch to prevent additions to the 'handshake_messages'.
313        self.frozen = False
314
315        ### Network settings
316        self.ipsrc = ipsrc
317        self.ipdst = ipdst
318        self.sport = sport
319        self.dport = dport
320        self.sid = sid
321
322        # Our TCP socket. None until we send (or receive) a packet.
323        self.sock = None
324
325        ### Connection states
326        self.connection_end = connection_end
327
328        if wcs is None:
329            # Instantiate wcs with dummy values.
330            self.wcs = writeConnState(connection_end=connection_end)
331            self.wcs.derive_keys()
332        else:
333            self.wcs = wcs
334
335        if rcs is None:
336            # Instantiate rcs with dummy values.
337            self.rcs = readConnState(connection_end=connection_end)
338            self.rcs.derive_keys()
339        else:
340            self.rcs = rcs
341
342        # The pending write/read states are updated by the building/parsing
343        # of various TLS packets. They get committed to self.wcs/self.rcs
344        # once Scapy builds/parses a ChangeCipherSpec message, or for certain
345        # other messages in case of TLS 1.3.
346        self.pwcs = None
347        self.triggered_pwcs_commit = False
348        self.prcs = None
349        self.triggered_prcs_commit = False
350
351
352        ### Certificates and private keys
353
354        # The server certificate chain, as a list of Cert instances.
355        # Either we act as server and it has to be provided, or it is expected
356        # to be sent by the server through a Certificate message.
357        # The server certificate should be self.server_certs[0].
358        self.server_certs = []
359
360        # The server private key, as a PrivKey instance, when acting as server.
361        # XXX It would be nice to be able to provide both an RSA and an ECDSA
362        # key in order for the same Scapy server to support both families of
363        # cipher suites. See INIT_TLS_SESSION() in automaton_srv.py.
364        # (For now server_key holds either one of both types for DHE
365        # authentication, while server_rsa_key is used only for RSAkx.)
366        self.server_key = None
367        self.server_rsa_key = None
368        #self.server_ecdsa_key = None
369
370        # Back in the dreadful EXPORT days, US servers were forbidden to use
371        # RSA keys longer than 512 bits for RSAkx. When their usual RSA key
372        # was longer than this, they had to create a new key and send it via
373        # a ServerRSAParams message. When receiving such a message,
374        # Scapy stores this key in server_tmp_rsa_key as a PubKey instance.
375        self.server_tmp_rsa_key = None
376
377        # When client authentication is performed, we need at least a
378        # client certificate chain. If we act as client, we also have
379        # to provide the key associated with the first certificate.
380        self.client_certs = []
381        self.client_key = None
382
383
384        ### Ephemeral key exchange parameters
385
386        # These are the group/curve parameters, needed to hold the information
387        # e.g. from receiving an SKE to sending a CKE. Usually, only one of
388        # these attributes will be different from None.
389        self.client_kx_ffdh_params = None
390        self.client_kx_ecdh_params = None
391
392        # These are PrivateKeys and PublicKeys from the appropriate FFDH/ECDH
393        # cryptography module, i.e. these are not raw bytes. Usually, only one
394        # in two will be different from None, e.g. when being a TLS client you
395        # will need the client_kx_privkey (the serialized public key is not
396        # actually registered) and you will receive a server_kx_pubkey.
397        self.client_kx_privkey = None
398        self.client_kx_pubkey = None
399        self.server_kx_privkey = None
400        self.server_kx_pubkey = None
401
402        # When using TLS 1.3, the tls13_client_pubshares will contain every
403        # potential key share (equate the 'client_kx_pubkey' before) the client
404        # offered, indexed by the id of the FFDH/ECDH group. These dicts
405        # effectively replace the four previous attributes.
406        self.tls13_client_privshares = {}
407        self.tls13_client_pubshares = {}
408        self.tls13_server_privshare = {}
409        self.tls13_server_pubshare = {}
410
411
412        ### Negotiated session parameters
413
414        # The advertised TLS version found in the ClientHello (and
415        # EncryptedPreMasterSecret if used). If acting as server, it is set to
416        # the value advertised by the client in its ClientHello.
417        # The default value corresponds to TLS 1.2 (and TLS 1.3, incidentally).
418        self.advertised_tls_version = 0x0303
419
420        # The agreed-upon TLS version found in the ServerHello.
421        self.tls_version = None
422
423        # These attributes should eventually be known to both sides (SSLv3-TLS 1.2).
424        self.client_random = None
425        self.server_random = None
426        self.pre_master_secret = None
427        self.master_secret = None
428
429        # A session ticket received by the client.
430        self.client_session_ticket = None
431
432        # These attributes should only be used with SSLv2 connections.
433        # We need to keep the KEY-MATERIAL here because it may be reused.
434        self.sslv2_common_cs = []
435        self.sslv2_connection_id = None
436        self.sslv2_challenge = None
437        self.sslv2_challenge_clientcert = None
438        self.sslv2_key_material = None
439
440        # These attributes should only be used with TLS 1.3 connections.
441        self.tls13_psk_secret = None
442        self.tls13_early_secret = None
443        self.tls13_dhe_secret = None
444        self.tls13_handshake_secret = None
445        self.tls13_master_secret = None
446        self.tls13_derived_secrets = {}
447
448        # Handshake messages needed for Finished computation/validation.
449        # No record layer headers, no HelloRequests, no ChangeCipherSpecs.
450        self.handshake_messages = []
451        self.handshake_messages_parsed = []
452
453        # All exchanged TLS packets.
454        #XXX no support for now
455        #self.exchanged_pkts = []
456
457
458    def __setattr__(self, name, val):
459        if name == "connection_end":
460            if hasattr(self, "rcs") and self.rcs:
461                self.rcs.connection_end = val
462            if hasattr(self, "wcs") and self.wcs:
463                self.wcs.connection_end = val
464            if hasattr(self, "prcs") and self.prcs:
465                self.prcs.connection_end = val
466            if hasattr(self, "pwcs") and self.pwcs:
467                self.pwcs.connection_end = val
468        super(tlsSession, self).__setattr__(name, val)
469
470
471    ### Mirroring
472
473    def mirror(self):
474        """
475        This function takes a tlsSession object and swaps the IP addresses,
476        ports, connection ends and connection states. The triggered_commit are
477        also swapped (though it is probably overkill, it is cleaner this way).
478
479        It is useful for static analysis of a series of messages from both the
480        client and the server. In such a situation, it should be used every
481        time the message being read comes from a different side than the one
482        read right before, as the reading state becomes the writing state, and
483        vice versa. For instance you could do:
484
485        client_hello = open('client_hello.raw').read()
486        <read other messages>
487
488        m1 = TLS(client_hello)
489        m2 = TLS(server_hello, tls_session=m1.tls_session.mirror())
490        m3 = TLS(server_cert, tls_session=m2.tls_session)
491        m4 = TLS(client_keyexchange, tls_session=m3.tls_session.mirror())
492        """
493
494        self.ipdst, self.ipsrc = self.ipsrc, self.ipdst
495        self.dport, self.sport = self.sport, self.dport
496
497        self.rcs, self.wcs = self.wcs, self.rcs
498        if self.rcs:
499            self.rcs.row = "read"
500        if self.wcs:
501            self.wcs.row = "write"
502
503        self.prcs, self.pwcs = self.pwcs, self.prcs
504        if self.prcs:
505            self.prcs.row = "read"
506        if self.pwcs:
507            self.pwcs.row = "write"
508
509        self.triggered_prcs_commit, self.triggered_pwcs_commit = \
510                self.triggered_pwcs_commit, self.triggered_prcs_commit
511
512        if self.connection_end == "client":
513            self.connection_end = "server"
514        elif self.connection_end == "server":
515            self.connection_end = "client"
516
517        return self
518
519
520    ### Secrets management for SSLv3 to TLS 1.2
521
522    def compute_master_secret(self):
523        if self.pre_master_secret is None:
524            warning("Missing pre_master_secret while computing master_secret!")
525        if self.client_random is None:
526            warning("Missing client_random while computing master_secret!")
527        if self.server_random is None:
528            warning("Missing server_random while computing master_secret!")
529
530        ms = self.pwcs.prf.compute_master_secret(self.pre_master_secret,
531                                                 self.client_random,
532                                                 self.server_random)
533        self.master_secret = ms
534        if conf.debug_tls:
535            log_runtime.debug("TLS: master secret: %s", repr_hex(ms))
536
537    def compute_ms_and_derive_keys(self):
538        self.compute_master_secret()
539        self.prcs.derive_keys(client_random=self.client_random,
540                              server_random=self.server_random,
541                              master_secret=self.master_secret)
542        self.pwcs.derive_keys(client_random=self.client_random,
543                              server_random=self.server_random,
544                              master_secret=self.master_secret)
545
546
547    ### Secrets management for SSLv2
548
549    def compute_sslv2_key_material(self):
550        if self.master_secret is None:
551            warning("Missing master_secret while computing key_material!")
552        if self.sslv2_challenge is None:
553            warning("Missing challenge while computing key_material!")
554        if self.sslv2_connection_id is None:
555            warning("Missing connection_id while computing key_material!")
556
557        km = self.pwcs.prf.derive_key_block(self.master_secret,
558                                            self.sslv2_challenge,
559                                            self.sslv2_connection_id,
560                                            2*self.pwcs.cipher.key_len)
561        self.sslv2_key_material = km
562        if conf.debug_tls:
563            log_runtime.debug("TLS: master secret: %s", repr_hex(self.master_secret))
564            log_runtime.debug("TLS: key material: %s", repr_hex(km))
565
566    def compute_sslv2_km_and_derive_keys(self):
567        self.compute_sslv2_key_material()
568        self.prcs.sslv2_derive_keys(key_material=self.sslv2_key_material)
569        self.pwcs.sslv2_derive_keys(key_material=self.sslv2_key_material)
570
571
572    ### Secrets management for TLS 1.3
573
574    def compute_tls13_early_secrets(self):
575        """
576        Ciphers key and IV are updated accordingly for 0-RTT data.
577        self.handshake_messages should be ClientHello only.
578        """
579        # we use the prcs rather than the pwcs in a totally arbitrary way
580        if self.prcs is None:
581            # too soon
582            return
583
584        hkdf = self.prcs.hkdf
585
586        self.tls13_early_secret = hkdf.extract(None,
587                                               self.tls13_psk_secret)
588
589        bk = hkdf.derive_secret(self.tls13_early_secret,
590                                b"external psk binder key",
591                               #"resumption psk binder key",
592                                b"")
593        self.tls13_derived_secrets["binder_key"] = bk
594
595        if len(self.handshake_messages) > 1:
596            # these secrets are not defined in case of HRR
597            return
598
599        cets = hkdf.derive_secret(self.tls13_early_secret,
600                                  b"client early traffic secret",
601                                  b"".join(self.handshake_messages))
602        self.tls13_derived_secrets["client_early_traffic_secret"] = cets
603
604        ees = hkdf.derive_secret(self.tls13_early_secret,
605                                 b"early exporter master secret",
606                                 b"".join(self.handshake_messages))
607        self.tls13_derived_secrets["early_exporter_secret"] = ees
608
609        if self.connection_end == "server":
610            self.prcs.tls13_derive_keys(cets)
611        elif self.connection_end == "client":
612            self.pwcs.tls13_derive_keys(cets)
613
614    def compute_tls13_handshake_secrets(self):
615        """
616        Ciphers key and IV are updated accordingly for Handshake data.
617        self.handshake_messages should be ClientHello...ServerHello.
618        """
619        if self.tls13_early_secret is None:
620            warning("No early secret. This is abnormal.")
621
622        hkdf = self.prcs.hkdf
623
624        self.tls13_handshake_secret = hkdf.extract(self.tls13_early_secret,
625                                                   self.tls13_dhe_secret)
626
627        chts = hkdf.derive_secret(self.tls13_handshake_secret,
628                                  b"client handshake traffic secret",
629                                  b"".join(self.handshake_messages))
630        self.tls13_derived_secrets["client_handshake_traffic_secret"] = chts
631
632        shts = hkdf.derive_secret(self.tls13_handshake_secret,
633                                  b"server handshake traffic secret",
634                                  b"".join(self.handshake_messages))
635        self.tls13_derived_secrets["server_handshake_traffic_secret"] = shts
636
637        if self.connection_end == "server":
638            self.prcs.tls13_derive_keys(chts)
639            self.pwcs.tls13_derive_keys(shts)
640        elif self.connection_end == "client":
641            self.pwcs.tls13_derive_keys(chts)
642            self.prcs.tls13_derive_keys(shts)
643
644    def compute_tls13_traffic_secrets(self):
645        """
646        Ciphers key and IV are updated accordingly for Application data.
647        self.handshake_messages should be ClientHello...ServerFinished.
648        """
649        hkdf = self.prcs.hkdf
650
651        self.tls13_master_secret = hkdf.extract(self.tls13_handshake_secret,
652                                                None)
653
654        cts0 = hkdf.derive_secret(self.tls13_master_secret,
655                                  b"client application traffic secret",
656                                  b"".join(self.handshake_messages))
657        self.tls13_derived_secrets["client_traffic_secrets"] = [cts0]
658
659        sts0 = hkdf.derive_secret(self.tls13_master_secret,
660                                  b"server application traffic secret",
661                                  b"".join(self.handshake_messages))
662        self.tls13_derived_secrets["server_traffic_secrets"] = [sts0]
663
664        es = hkdf.derive_secret(self.tls13_master_secret,
665                                b"exporter master secret",
666                                b"".join(self.handshake_messages))
667        self.tls13_derived_secrets["exporter_secret"] = es
668
669        if self.connection_end == "server":
670            #self.prcs.tls13_derive_keys(cts0)
671            self.pwcs.tls13_derive_keys(sts0)
672        elif self.connection_end == "client":
673            #self.pwcs.tls13_derive_keys(cts0)
674            self.prcs.tls13_derive_keys(sts0)
675
676    def compute_tls13_traffic_secrets_end(self):
677        cts0 = self.tls13_derived_secrets["client_traffic_secrets"][0]
678        if self.connection_end == "server":
679            self.prcs.tls13_derive_keys(cts0)
680        elif self.connection_end == "client":
681            self.pwcs.tls13_derive_keys(cts0)
682
683    def compute_tls13_verify_data(self, connection_end, read_or_write):
684        shts = "server_handshake_traffic_secret"
685        chts = "client_handshake_traffic_secret"
686        if read_or_write == "read":
687            hkdf = self.rcs.hkdf
688            if connection_end == "client":
689                basekey = self.tls13_derived_secrets[shts]
690            elif connection_end == "server":
691                basekey = self.tls13_derived_secrets[chts]
692        elif read_or_write == "write":
693            hkdf = self.wcs.hkdf
694            if connection_end == "client":
695                basekey = self.tls13_derived_secrets[chts]
696            elif connection_end == "server":
697                basekey = self.tls13_derived_secrets[shts]
698
699        if not hkdf or not basekey:
700            warning("Missing arguments for verify_data computation!")
701            return None
702        #XXX this join() works in standard cases, but does it in all of them?
703        handshake_context = b"".join(self.handshake_messages)
704        return hkdf.compute_verify_data(basekey, handshake_context)
705
706    def compute_tls13_resumption_secret(self):
707        """
708        self.handshake_messages should be ClientHello...ClientFinished.
709        """
710        if self.connection_end == "server":
711            hkdf = self.prcs.hkdf
712        elif self.connection_end == "client":
713            hkdf = self.pwcs.hkdf
714        rs = hkdf.derive_secret(self.tls13_master_secret,
715                                b"resumption master secret",
716                                b"".join(self.handshake_messages))
717        self.tls13_derived_secrets["resumption_secret"] = rs
718
719    def compute_tls13_next_traffic_secrets(self):
720        """
721        Ciphers key and IV are updated accordingly.
722        """
723        hkdf = self.prcs.hkdf
724        hl = hkdf.hash.digest_size
725
726        cts = self.tls13_derived_secrets["client_traffic_secrets"]
727        ctsN = cts[-1]
728        ctsN_1 = hkdf.expand_label(ctsN, "application traffic secret", "", hl)
729        cts.append(ctsN_1)
730
731        sts = self.tls13_derived_secrets["server_traffic_secrets"]
732        stsN = sts[-1]
733        stsN_1 = hkdf.expand_label(ctsN, "application traffic secret", "", hl)
734        cts.append(stsN_1)
735
736        if self.connection_end == "server":
737            self.prcs.tls13_derive_keys(ctsN_1)
738            self.pwcs.tls13_derive_keys(stsN_1)
739        elif self.connection_end == "client":
740            self.pwcs.tls13_derive_keys(ctsN_1)
741            self.prcs.tls13_derive_keys(stsN_1)
742
743    ### Tests for record building/parsing
744
745    def consider_read_padding(self):
746        # Return True if padding is needed. Used by TLSPadField.
747        return (self.rcs.cipher.type == "block" and
748                not (False in six.itervalues(self.rcs.cipher.ready)))
749
750    def consider_write_padding(self):
751        # Return True if padding is needed. Used by TLSPadField.
752        return self.wcs.cipher.type == "block"
753
754    def use_explicit_iv(self, version, cipher_type):
755        # Return True if an explicit IV is needed. Required for TLS 1.1+
756        # when either a block or an AEAD cipher is used.
757        if cipher_type == "stream":
758            return False
759        return version >= 0x0302
760
761
762    ### Python object management
763
764    def hash(self):
765        s1 = struct.pack("!H", self.sport)
766        s2 = struct.pack("!H", self.dport)
767        family = socket.AF_INET
768        if ':' in self.ipsrc:
769            family = socket.AF_INET6
770        s1 += socket.inet_pton(family, self.ipsrc)
771        s2 += socket.inet_pton(family, self.ipdst)
772        return strxor(s1, s2)
773
774    def eq(self, other):
775        ok = False
776        if (self.sport == other.sport and self.dport == other.dport and
777            self.ipsrc == other.ipsrc and self.ipdst == other.ipdst):
778            ok = True
779
780        if (not ok and
781            self.dport == other.sport and self.sport == other.dport and
782            self.ipdst == other.ipsrc and self.ipsrc == other.ipdst):
783            ok = True
784
785        if ok:
786            if self.sid and other.sid:
787                return self.sid == other.sid
788            return True
789
790        return False
791
792    def __repr__(self):
793        sid = repr(self.sid)
794        if len(sid) > 12:
795            sid = sid[:11] + "..."
796        return "%s:%s > %s:%s" % (self.ipsrc, str(self.sport),
797                                  self.ipdst, str(self.dport))
798
799###############################################################################
800### Session singleton                                                       ###
801###############################################################################
802
803class _GenericTLSSessionInheritance(Packet):
804    """
805    Many classes inside the TLS module need to get access to session-related
806    information. For instance, an encrypted TLS record cannot be parsed without
807    some knowledge of the cipher suite being used and the secrets which have
808    been negotiated. Passing information is also essential to the handshake.
809    To this end, various TLS objects inherit from the present class.
810    """
811    __slots__ = ["tls_session", "rcs_snap_init", "wcs_snap_init"]
812    name = "Dummy Generic TLS Packet"
813    fields_desc = []
814
815    def __init__(self, _pkt="", post_transform=None, _internal=0,
816                 _underlayer=None, tls_session=None, **fields):
817        try:
818            setme = self.tls_session is None
819        except:
820            setme = True
821
822        if setme:
823            if tls_session is None:
824                self.tls_session = tlsSession()
825            else:
826                self.tls_session = tls_session
827
828        self.rcs_snap_init = self.tls_session.rcs.snapshot()
829        self.wcs_snap_init = self.tls_session.wcs.snapshot()
830
831        Packet.__init__(self, _pkt=_pkt, post_transform=post_transform,
832                        _internal=_internal, _underlayer=_underlayer,
833                        **fields)
834
835    def __getattr__(self, attr):
836        """
837        The tls_session should be found only through the normal mechanism.
838        """
839        if attr == "tls_session":
840            return None
841        return super(_GenericTLSSessionInheritance, self).__getattr__(attr)
842
843    def tls_session_update(self, msg_str):
844        """
845        post_{build, dissection}_tls_session_update() are used to update the
846        tlsSession context. The default definitions below, along with
847        tls_session_update(), may prevent code duplication in some cases.
848        """
849        pass
850
851    def post_build_tls_session_update(self, msg_str):
852        self.tls_session_update(msg_str)
853
854    def post_dissection_tls_session_update(self, msg_str):
855        self.tls_session_update(msg_str)
856
857    def copy(self):
858        pkt = Packet.copy(self)
859        pkt.tls_session = self.tls_session
860        return pkt
861
862    def clone_with(self, payload=None, **kargs):
863        pkt = Packet.clone_with(self, payload=payload, **kargs)
864        pkt.tls_session = self.tls_session
865        return pkt
866
867    def raw_stateful(self):
868        return super(_GenericTLSSessionInheritance, self).__bytes__()
869
870    def str_stateful(self):
871        return self.raw_stateful()
872
873    def __bytes__(self):
874        """
875        The __bytes__ call has to leave the connection states unchanged.
876        We also have to delete raw_packet_cache in order to access post_build.
877
878        For performance, the pending connStates are not snapshotted.
879        This should not be an issue, but maybe pay attention to this.
880
881        The previous_freeze_state prevents issues with calling a raw() calling
882        in turn another raw(), which would unfreeze the session too soon.
883        """
884        s = self.tls_session
885        rcs_snap = s.rcs.snapshot()
886        wcs_snap = s.wcs.snapshot()
887        rpc_snap = self.raw_packet_cache
888
889        s.wcs = self.rcs_snap_init
890
891        self.raw_packet_cache = None
892        previous_freeze_state = s.frozen
893        s.frozen = True
894        built_packet = super(_GenericTLSSessionInheritance, self).__bytes__()
895        s.frozen = previous_freeze_state
896
897        s.rcs = rcs_snap
898        s.wcs = wcs_snap
899        self.raw_packet_cache = rpc_snap
900
901        return built_packet
902    __str__ = __bytes__
903
904    def show2(self):
905        """
906        Rebuild the TLS packet with the same context, and then .show() it.
907        We need self.__class__ to call the subclass in a dynamic way.
908
909        Howether we do not want the tls_session.{r,w}cs.seq_num to be updated.
910        We have to bring back the init states (it's possible the cipher context
911        has been updated because of parsing) but also to keep the current state
912        and restore it afterwards (the raw() call may also update the states).
913        """
914        s = self.tls_session
915        rcs_snap = s.rcs.snapshot()
916        wcs_snap = s.wcs.snapshot()
917
918        s.rcs = self.rcs_snap_init
919
920        built_packet = raw(self)
921        s.frozen = True
922        self.__class__(built_packet, tls_session=s).show()
923        s.frozen = False
924
925        s.rcs = rcs_snap
926        s.wcs = wcs_snap
927
928    # Uncomment this when the automata update IPs and ports properly
929    #def mysummary(self):
930    #    return "TLS %s" % repr(self.tls_session)
931
932
933###############################################################################
934### Multiple TLS sessions                                                   ###
935###############################################################################
936
937class _tls_sessions(object):
938    def __init__(self):
939        self.sessions = {}
940
941    def add(self, session):
942        s = self.find(session)
943        if s:
944            log_runtime.info("TLS: previous session shall not be overwritten")
945            return
946
947        h = session.hash()
948        if h in self.sessions:
949            self.sessions[h].append(session)
950        else:
951            self.sessions[h] = [session]
952
953    def rem(self, session):
954        s = self.find(session)
955        if s:
956            log_runtime.info("TLS: previous session shall not be overwritten")
957            return
958
959        h = session.hash()
960        self.sessions[h].remove(session)
961
962    def find(self, session):
963        h = session.hash()
964        if h in self.sessions:
965            for k in self.sessions[h]:
966                if k.eq(session):
967                    if conf.tls_verbose:
968                        log_runtime.info("TLS: found session matching %s", k)
969                    return k
970        if conf.tls_verbose:
971            log_runtime.info("TLS: did not find session matching %s", session)
972        return None
973
974    def __repr__(self):
975        res = [("First endpoint", "Second endpoint", "Session ID")]
976        for l in self.sessions.values():
977            for s in l:
978                src = "%s[%d]" % (s.ipsrc, s.sport)
979                dst = "%s[%d]" % (s.ipdst, s.dport)
980                sid = repr(s.sid)
981                if len(sid) > 12:
982                    sid = sid[:11] + "..."
983                res.append((src, dst, sid))
984        colwidth = (max([len(y) for y in x]) for x in zip(*res))
985        fmt = "  ".join(map(lambda x: "%%-%ds"%x, colwidth))
986        return "\n".join(map(lambda x: fmt % x, res))
987
988
989conf.tls_sessions = _tls_sessions()
990conf.tls_verbose = False
991
992