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 base fields, used for record parsing/building. As several operations depend 8upon the TLS version or ciphersuite, the packet has to provide a TLS context. 9""" 10 11from scapy.fields import * 12import scapy.modules.six as six 13 14_tls_type = { 20: "change_cipher_spec", 15 21: "alert", 16 22: "handshake", 17 23: "application_data" } 18 19_tls_version = { 0x0002: "SSLv2", 20 0x0200: "SSLv2", 21 0x0300: "SSLv3", 22 0x0301: "TLS 1.0", 23 0x0302: "TLS 1.1", 24 0x0303: "TLS 1.2", 25 0x7f12: "TLS 1.3-d18", 26 0x7f13: "TLS 1.3-d19", 27 0x0304: "TLS 1.3" } 28 29_tls_version_options = { "sslv2": 0x0002, 30 "sslv3": 0x0300, 31 "tls1" : 0x0301, 32 "tls10": 0x0301, 33 "tls11": 0x0302, 34 "tls12": 0x0303, 35 "tls13-d18": 0x7f12, 36 "tls13-d19": 0x7f13, 37 "tls13": 0x0304 } 38 39def _tls13_version_filter(version, legacy_version): 40 if version < 0x0304: 41 return version 42 else: 43 return legacy_version 44 45class _TLSClientVersionField(ShortEnumField): 46 """ 47 We use the advertised_tls_version if it has been defined, 48 and the legacy 0x0303 for TLS 1.3 packets. 49 """ 50 def i2h(self, pkt, x): 51 if x is None: 52 v = pkt.tls_session.advertised_tls_version 53 if v: 54 return _tls13_version_filter(v, 0x0303) 55 return "" 56 return x 57 58 def i2m(self, pkt, x): 59 if x is None: 60 v = pkt.tls_session.advertised_tls_version 61 if v: 62 return _tls13_version_filter(v, 0x0303) 63 return b"" 64 return x 65 66 67class _TLSVersionField(ShortEnumField): 68 """ 69 We use the tls_version if it has been defined, else the advertised version. 70 Also, the legacy 0x0301 is used for TLS 1.3 packets. 71 """ 72 def i2h(self, pkt, x): 73 if x is None: 74 v = pkt.tls_session.tls_version 75 if v: 76 return _tls13_version_filter(v, 0x0301) 77 else: 78 adv_v = pkt.tls_session.advertised_tls_version 79 return _tls13_version_filter(adv_v, 0x0301) 80 return x 81 82 def i2m(self, pkt, x): 83 if x is None: 84 v = pkt.tls_session.tls_version 85 if v: 86 return _tls13_version_filter(v, 0x0301) 87 else: 88 adv_v = pkt.tls_session.advertised_tls_version 89 return _tls13_version_filter(adv_v, 0x0301) 90 return x 91 92 93class _TLSLengthField(ShortField): 94 def i2repr(self, pkt, x): 95 s = super(_TLSLengthField, self).i2repr(pkt, x) 96 if pkt.deciphered_len is not None: 97 dx = pkt.deciphered_len 98 ds = super(_TLSLengthField, self).i2repr(pkt, dx) 99 s += " [deciphered_len= %s]" % ds 100 return s 101 102 103class _TLSIVField(StrField): 104 """ 105 As stated in Section 6.2.3.2. RFC 4346, TLS 1.1 implements an explicit IV 106 mechanism. For that reason, the behavior of the field is dependent on the 107 TLS version found in the packet if available or otherwise (on build, if 108 not overloaded, it is provided by the session). The size of the IV and 109 its value are obviously provided by the session. As a side note, for the 110 first packets exchanged by peers, NULL being the default enc alg, it is 111 empty (except if forced to a specific value). Also note that the field is 112 kept empty (unless forced to a specific value) when the cipher is a stream 113 cipher (and NULL is considered a stream cipher). 114 """ 115 def i2len(self, pkt, i): 116 if i is not None: 117 return len(i) 118 l = 0 119 cipher_type = pkt.tls_session.rcs.cipher.type 120 if cipher_type == "block": 121 if pkt.tls_session.tls_version >= 0x0302: 122 l = pkt.tls_session.rcs.cipher.block_size 123 elif cipher_type == "aead": 124 l = pkt.tls_session.rcs.cipher.nonce_explicit_len 125 return l 126 127 def i2m(self, pkt, x): 128 return x or b"" 129 130 def addfield(self, pkt, s, val): 131 return s + self.i2m(pkt, val) 132 133 def getfield(self, pkt, s): 134 l = 0 135 cipher_type = pkt.tls_session.rcs.cipher.type 136 if cipher_type == "block": 137 if pkt.tls_session.tls_version >= 0x0302: 138 l = pkt.tls_session.rcs.cipher.block_size 139 elif cipher_type == "aead": 140 l = pkt.tls_session.rcs.cipher.nonce_explicit_len 141 return s[l:], self.m2i(pkt, s[:l]) 142 143 def i2repr(self, pkt, x): 144 return repr(self.i2m(pkt, x)) 145 146 147class _TLSMACField(StrField): 148 def i2len(self, pkt, i): 149 if i is not None: 150 return len(i) 151 return pkt.tls_session.wcs.mac_len 152 153 def i2m(self, pkt, x): 154 if x is None: 155 return b"" 156 return x 157 158 def addfield(self, pkt, s, val): 159 # We add nothing here. This is done in .post_build() if needed. 160 return s 161 162 def getfield(self, pkt, s): 163 if (pkt.tls_session.rcs.cipher.type != "aead" and 164 False in six.itervalues(pkt.tls_session.rcs.cipher.ready)): 165 #XXX Find a more proper way to handle the still-encrypted case 166 return s, b"" 167 l = pkt.tls_session.rcs.mac_len 168 return s[l:], self.m2i(pkt, s[:l]) 169 170 def i2repr(self, pkt, x): 171 #XXX Provide status when dissection has been performed successfully? 172 return repr(self.i2m(pkt, x)) 173 174 175class _TLSPadField(StrField): 176 def i2len(self, pkt, i): 177 if i is not None: 178 return len(i) 179 return 0 180 181 def i2m(self, pkt, x): 182 if x is None: 183 return b"" 184 return x 185 186 def addfield(self, pkt, s, val): 187 # We add nothing here. This is done in .post_build() if needed. 188 return s 189 190 def getfield(self, pkt, s): 191 if pkt.tls_session.consider_read_padding(): 192 # This should work with SSLv3 and also TLS versions. 193 # Note that we need to retrieve pkt.padlen beforehand, 194 # because it's possible that the padding is followed by some data 195 # from another TLS record (hence the last byte from s would not be 196 # the last byte from the current record padding). 197 l = orb(s[pkt.padlen-1]) 198 return s[l:], self.m2i(pkt, s[:l]) 199 return s, None 200 201 def i2repr(self, pkt, x): 202 #XXX Provide status when dissection has been performed successfully? 203 return repr(self.i2m(pkt, x)) 204 205 206class _TLSPadLenField(ByteField): 207 def addfield(self, pkt, s, val): 208 # We add nothing here. This is done in .post_build() if needed. 209 return s 210 211 def getfield(self, pkt, s): 212 if pkt.tls_session.consider_read_padding(): 213 return ByteField.getfield(self, pkt, s) 214 return s, None 215 216 217### SSLv2 fields 218 219class _SSLv2LengthField(_TLSLengthField): 220 def i2repr(self, pkt, x): 221 s = super(_SSLv2LengthField, self).i2repr(pkt, x) 222 if pkt.with_padding: 223 x |= 0x8000 224 #elif pkt.with_escape: #XXX no complete support for 'escape' yet 225 # x |= 0x4000 226 s += " [with padding: %s]" % hex(x) 227 return s 228 229 def getfield(self, pkt, s): 230 msglen = struct.unpack('!H', s[:2])[0] 231 pkt.with_padding = (msglen & 0x8000) == 0 232 if pkt.with_padding: 233 msglen_clean = msglen & 0x3fff 234 else: 235 msglen_clean = msglen & 0x7fff 236 return s[2:], msglen_clean 237 238 239class _SSLv2MACField(_TLSMACField): 240 pass 241 242 243class _SSLv2PadField(_TLSPadField): 244 def getfield(self, pkt, s): 245 if pkt.padlen is not None: 246 l = pkt.padlen 247 return s[l:], self.m2i(pkt, s[:l]) 248 return s, None 249 250 251class _SSLv2PadLenField(_TLSPadLenField): 252 def getfield(self, pkt, s): 253 if pkt.with_padding: 254 return ByteField.getfield(self, pkt, s) 255 return s, None 256 257