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