• 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 Pseudorandom Function.
8"""
9
10from __future__ import absolute_import
11from scapy.error import warning
12from scapy.utils import strxor
13
14from scapy.layers.tls.crypto.hash import _tls_hash_algs
15from scapy.layers.tls.crypto.h_mac import _tls_hmac_algs
16from scapy.modules.six.moves import range
17from scapy.compat import *
18
19
20### Data expansion functions
21
22def _tls_P_hash(secret, seed, req_len, hm):
23    """
24    Provides the implementation of P_hash function defined in
25    section 5 of RFC 4346 (and section 5 of RFC 5246). Two
26    parameters have been added (hm and req_len):
27
28    - secret : the key to be used. If RFC 4868 is to be believed,
29               the length must match hm.key_len. Actually,
30               python hmac takes care of formatting every key.
31    - seed : the seed to be used.
32    - req_len : the length of data to be generated by iterating
33               the specific HMAC function (hm). This prevents
34               multiple calls to the function.
35    - hm : the hmac function class to use for iteration (either
36           Hmac_MD5 or Hmac_SHA1 in TLS <= 1.1 or
37           Hmac_SHA256 or Hmac_SHA384 in TLS 1.2)
38    """
39    hash_len = hm.hash_alg.hash_len
40    n = (req_len + hash_len - 1) // hash_len
41
42    res = b""
43    a = hm(secret).digest(seed)  # A(1)
44
45    while n > 0:
46        res += hm(secret).digest(a + raw(seed))
47        a = hm(secret).digest(a)
48        n -= 1
49
50    return res[:req_len]
51
52
53def _tls_P_MD5(secret, seed, req_len):
54    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs["HMAC-MD5"])
55
56def _tls_P_SHA1(secret, seed, req_len):
57    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs["HMAC-SHA"])
58
59def _tls_P_SHA256(secret, seed, req_len):
60    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs["HMAC-SHA256"])
61
62def _tls_P_SHA384(secret, seed, req_len):
63    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs["HMAC-SHA384"])
64
65def _tls_P_SHA512(secret, seed, req_len):
66    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs["HMAC-SHA512"])
67
68
69### PRF functions, according to the protocol version
70
71def _sslv2_PRF(secret, seed, req_len):
72    hash_md5 = _tls_hash_algs["MD5"]()
73    rounds = (req_len + hash_md5.hash_len - 1) // hash_md5.hash_len
74
75    res = b""
76    if rounds == 1:
77        res += hash_md5.digest(secret + seed)
78    else:
79        r = 0
80        while r < rounds:
81            label = str(r).encode("utf8")
82            res += hash_md5.digest(secret + label + seed)
83            r += 1
84
85    return res[:req_len]
86
87def _ssl_PRF(secret, seed, req_len):
88    """
89    Provides the implementation of SSLv3 PRF function:
90
91     SSLv3-PRF(secret, seed) =
92        MD5(secret || SHA-1("A" || secret || seed)) ||
93        MD5(secret || SHA-1("BB" || secret || seed)) ||
94        MD5(secret || SHA-1("CCC" || secret || seed)) || ...
95
96    req_len should not be more than  26 x 16 = 416.
97    """
98    if req_len > 416:
99        warning("_ssl_PRF() is not expected to provide more than 416 bytes")
100        return ""
101
102    d = [b"A", b"B", b"C", b"D", b"E", b"F", b"G", b"H", b"I", b"J", b"K", b"L",
103         b"M", b"N", b"O", b"P", b"Q", b"R", b"S", b"T", b"U", b"V", b"W", b"X",
104         b"Y", b"Z"]
105    res = b""
106    hash_sha1 = _tls_hash_algs["SHA"]()
107    hash_md5 = _tls_hash_algs["MD5"]()
108    rounds = (req_len + hash_md5.hash_len - 1) // hash_md5.hash_len
109
110    for i in range(rounds):
111        label = d[i] * (i+1)
112        tmp = hash_sha1.digest(label + secret + seed)
113        res += hash_md5.digest(secret + tmp)
114
115    return res[:req_len]
116
117def _tls_PRF(secret, label, seed, req_len):
118    """
119    Provides the implementation of TLS PRF function as defined in
120    section 5 of RFC 4346:
121
122    PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
123                               P_SHA-1(S2, label + seed)
124
125    Parameters are:
126
127    - secret: the secret used by the HMAC in the 2 expansion
128              functions (S1 and S2 are the halves of this secret).
129    - label: specific label as defined in various sections of the RFC
130             depending on the use of the generated PRF keystream
131    - seed: the seed used by the expansion functions.
132    - req_len: amount of keystream to be generated
133    """
134    l = (len(secret) + 1) // 2
135    S1 = secret[:l]
136    S2 = secret[-l:]
137
138    a1 = _tls_P_MD5(S1, label+seed, req_len)
139    a2 = _tls_P_SHA1(S2, label+seed, req_len)
140
141    return strxor(a1, a2)
142
143def _tls12_SHA256PRF(secret, label, seed, req_len):
144    """
145    Provides the implementation of TLS 1.2 PRF function as
146    defined in section 5 of RFC 5246:
147
148    PRF(secret, label, seed) = P_SHA256(secret, label + seed)
149
150    Parameters are:
151
152    - secret: the secret used by the HMAC in the 2 expansion
153              functions (S1 and S2 are the halves of this secret).
154    - label: specific label as defined in various sections of the RFC
155             depending on the use of the generated PRF keystream
156    - seed: the seed used by the expansion functions.
157    - req_len: amount of keystream to be generated
158    """
159    return _tls_P_SHA256(secret, label+seed, req_len)
160
161def _tls12_SHA384PRF(secret, label, seed, req_len):
162    return _tls_P_SHA384(secret, label+seed, req_len)
163
164def _tls12_SHA512PRF(secret, label, seed, req_len):
165    return _tls_P_SHA512(secret, label+seed, req_len)
166
167
168class PRF(object):
169    """
170    The PRF used by SSL/TLS varies based on the version of the protocol and
171    (for TLS 1.2) possibly the Hash algorithm of the negotiated cipher suite.
172    The various uses of the PRF (key derivation, computation of verify_data,
173    computation of pre_master_secret values) for the different versions of the
174    protocol also changes. In order to abstract those elements, the common
175    _tls_PRF() object is provided. It is expected to be initialised in the
176    context of the connection state using the tls_version and the cipher suite.
177    """
178    def __init__(self, hash_name="SHA256", tls_version=0x0303):
179        self.tls_version = tls_version
180        self.hash_name = hash_name
181
182        if tls_version < 0x0300:            # SSLv2
183            self.prf = _sslv2_PRF
184        elif tls_version == 0x0300:         # SSLv3
185            self.prf = _ssl_PRF
186        elif (tls_version == 0x0301 or      # TLS 1.0
187              tls_version == 0x0302):       # TLS 1.1
188            self.prf = _tls_PRF
189        elif tls_version == 0x0303:         # TLS 1.2
190            if hash_name == "SHA384":
191                self.prf = _tls12_SHA384PRF
192            elif hash_name == "SHA512":
193                self.prf = _tls12_SHA512PRF
194            else:
195                self.prf = _tls12_SHA256PRF
196        else:
197            warning("Unknown TLS version")
198
199    def compute_master_secret(self, pre_master_secret,
200                              client_random, server_random):
201        """
202        Return the 48-byte master_secret, computed from pre_master_secret,
203        client_random and server_random. See RFC 5246, section 6.3.
204        """
205        seed = client_random + server_random
206        if self.tls_version < 0x0300:
207            return None
208        elif self.tls_version == 0x0300:
209            return self.prf(pre_master_secret, seed, 48)
210        else:
211            return self.prf(pre_master_secret, b"master secret", seed, 48)
212
213    def derive_key_block(self, master_secret, server_random,
214                         client_random, req_len):
215        """
216        Perform the derivation of master_secret into a key_block of req_len
217        requested length. See RFC 5246, section 6.3.
218        """
219        seed = server_random + client_random
220        if self.tls_version <= 0x0300:
221            return self.prf(master_secret, seed, req_len)
222        else:
223            return self.prf(master_secret, b"key expansion", seed, req_len)
224
225    def compute_verify_data(self, con_end, read_or_write,
226                            handshake_msg, master_secret):
227        """
228        Return verify_data based on handshake messages, connection end,
229        master secret, and read_or_write position. See RFC 5246, section 7.4.9.
230
231        Every TLS 1.2 cipher suite has a verify_data of length 12. Note also:
232        "This PRF with the SHA-256 hash function is used for all cipher
233         suites defined in this document and in TLS documents published
234         prior to this document when TLS 1.2 is negotiated."
235        Cipher suites using SHA-384 were defined later on.
236        """
237        if self.tls_version < 0x0300:
238            return None
239        elif self.tls_version == 0x0300:
240
241            if read_or_write == "write":
242                d = {"client": b"CLNT", "server": b"SRVR"}
243            else:
244                d = {"client": b"SRVR", "server": b"CLNT"}
245            label = d[con_end]
246
247            sslv3_md5_pad1 = b"\x36"*48
248            sslv3_md5_pad2 = b"\x5c"*48
249            sslv3_sha1_pad1 = b"\x36"*40
250            sslv3_sha1_pad2 = b"\x5c"*40
251
252            md5 = _tls_hash_algs["MD5"]()
253            sha1 = _tls_hash_algs["SHA"]()
254
255            md5_hash = md5.digest(master_secret + sslv3_md5_pad2 +
256                                  md5.digest(handshake_msg + label +
257                                             master_secret + sslv3_md5_pad1))
258            sha1_hash = sha1.digest(master_secret + sslv3_sha1_pad2 +
259                                    sha1.digest(handshake_msg + label +
260                                                master_secret + sslv3_sha1_pad1))
261            verify_data = md5_hash + sha1_hash
262
263        else:
264
265            if read_or_write == "write":
266                d = {"client": "client", "server": "server"}
267            else:
268                d = {"client": "server", "server": "client"}
269            label = ("%s finished" % d[con_end]).encode()
270
271            if self.tls_version <= 0x0302:
272                s1 = _tls_hash_algs["MD5"]().digest(handshake_msg)
273                s2 = _tls_hash_algs["SHA"]().digest(handshake_msg)
274                verify_data = self.prf(master_secret, label, s1 + s2, 12)
275            else:
276                if self.hash_name in ["MD5", "SHA"]:
277                    h = _tls_hash_algs["SHA256"]()
278                else:
279                    h = _tls_hash_algs[self.hash_name]()
280                s = h.digest(handshake_msg)
281                verify_data = self.prf(master_secret, label, s, 12)
282
283        return verify_data
284
285    def postprocess_key_for_export(self, key, client_random, server_random,
286                                   con_end, read_or_write, req_len):
287        """
288        Postprocess cipher key for EXPORT ciphersuite, i.e. weakens it.
289        An export key generation example is given in section 6.3.1 of RFC 2246.
290        See also page 86 of EKR's book.
291        """
292        s = con_end + read_or_write
293        s = (s == "clientwrite" or s == "serverread")
294
295        if self.tls_version < 0x0300:
296            return None
297        elif self.tls_version == 0x0300:
298            if s:
299                tbh = key + client_random + server_random
300            else:
301                tbh = key + server_random + client_random
302            export_key = _tls_hash_algs["MD5"]().digest(tbh)[:req_len]
303        else:
304            if s:
305                tag = b"client write key"
306            else:
307                tag = b"server write key"
308            export_key = self.prf(key,
309                                  tag,
310                                  client_random + server_random,
311                                  req_len)
312        return export_key
313
314    def generate_iv_for_export(self, client_random, server_random,
315                               con_end, read_or_write, req_len):
316        """
317        Generate IV for EXPORT ciphersuite, i.e. weakens it.
318        An export IV generation example is given in section 6.3.1 of RFC 2246.
319        See also page 86 of EKR's book.
320        """
321        s = con_end + read_or_write
322        s = (s == "clientwrite" or s == "serverread")
323
324        if self.tls_version < 0x0300:
325            return None
326        elif self.tls_version == 0x0300:
327            if s:
328                tbh = client_random + server_random
329            else:
330                tbh = server_random + client_random
331            iv = _tls_hash_algs["MD5"]().digest(tbh)[:req_len]
332        else:
333            iv_block = self.prf("",
334                                b"IV block",
335                                client_random + server_random,
336                                2*req_len)
337            if s:
338                iv = iv_block[:req_len]
339            else:
340                iv = iv_block[req_len:]
341        return iv
342
343