1import hashlib 2import hmac 3from io import BytesIO 4from struct import unpack, pack 5from zlib import crc32 6 7from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes 8from cryptography.hazmat.backends import default_backend 9 10from scapy.compat import hex_bytes, orb 11from scapy.packet import Raw 12 13# ARC4 14 15def ARC4_encrypt(key, data, skip=0): 16 """Encrypt data @data with key @key, skipping @skip first bytes of the 17 keystream""" 18 19 algorithm = algorithms.ARC4(key) 20 cipher = Cipher(algorithm, mode=None, backend=default_backend()) 21 encryptor = cipher.encryptor() 22 if skip: 23 encryptor.update("\x00" * skip) 24 return encryptor.update(data) 25 26def ARC4_decrypt(key, data, skip=0): 27 """Decrypt data @data with key @key, skipping @skip first bytes of the 28 keystream""" 29 return ARC4_encrypt(key, data, skip) 30 31# Custom WPA PseudoRandomFunction 32 33def customPRF512(key, amac, smac, anonce, snonce): 34 """Source https://stackoverflow.com/questions/12018920/""" 35 A = "Pairwise key expansion" 36 B = "".join(sorted([amac, smac]) + sorted([anonce, snonce])) 37 38 blen = 64 39 i = 0 40 R = '' 41 while i<=((blen*8+159)/160): 42 hmacsha1 = hmac.new(key,A+chr(0x00)+B+chr(i), hashlib.sha1) 43 i+=1 44 R = R+hmacsha1.digest() 45 return R[:blen] 46 47# TKIP - WEPSeed generation 48# Tested against pyDot11: tkip.py 49 50# 802.11i p.53-54 51_SBOXS = [ 52 [ 53 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, 54 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, 55 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, 56 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, 57 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, 58 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, 59 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, 60 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, 61 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, 62 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, 63 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, 64 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, 65 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, 66 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, 67 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, 68 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, 69 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, 70 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, 71 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, 72 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, 73 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, 74 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, 75 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, 76 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, 77 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, 78 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, 79 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, 80 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, 81 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, 82 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, 83 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, 84 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A 85 ], 86 [ 87 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, 88 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, 89 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, 90 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, 91 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, 92 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, 93 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, 94 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, 95 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, 96 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, 97 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, 98 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, 99 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, 100 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, 101 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, 102 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, 103 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, 104 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, 105 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, 106 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, 107 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, 108 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, 109 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, 110 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, 111 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, 112 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, 113 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, 114 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, 115 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, 116 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, 117 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, 118 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C 119 ] 120] 121 122# 802.11i Annex H 123PHASE1_LOOP_CNT = 8 124 125def _MK16(b1, b2): 126 return (b1 << 8) | b2 127 128def _SBOX16(index): 129 return _SBOXS[0][index & 0xff] ^ _SBOXS[1][(index >> 8)] 130 131def _CAST16(value): 132 return value & 0xffff 133 134def _RotR1(value): 135 return ((value >> 1) & 0x7fff) | (value << 15) 136 137def gen_TKIP_RC4_key(TSC, TA, TK): 138 """Implement TKIP WEPSeed generation 139 TSC: packet IV 140 TA: target addr bytes 141 TK: temporal key 142 """ 143 144 assert len(TSC) == 6 145 assert len(TA) == 6 146 assert len(TK) == 16 147 assert all(isinstance(x, (int, long)) for x in TSC + TA + TK) 148 149 # Phase 1 150 # 802.11i p.54 151 152 # Phase 1 - Step 1 153 TTAK = [] 154 TTAK.append(_MK16(TSC[3], TSC[2])) 155 TTAK.append(_MK16(TSC[5], TSC[4])) 156 TTAK.append(_MK16(TA[1], TA[0])) 157 TTAK.append(_MK16(TA[3], TA[2])) 158 TTAK.append(_MK16(TA[5], TA[4])) 159 160 # Phase 1 - Step 2 161 for i in xrange(PHASE1_LOOP_CNT): 162 j = 2 * (i & 1) 163 TTAK[0] = _CAST16(TTAK[0] + _SBOX16(TTAK[4] ^ _MK16(TK[1 + j], TK[0 + j]))) 164 TTAK[1] = _CAST16(TTAK[1] + _SBOX16(TTAK[0] ^ _MK16(TK[5 + j], TK[4 + j]))) 165 TTAK[2] = _CAST16(TTAK[2] + _SBOX16(TTAK[1] ^ _MK16(TK[9 + j], TK[8 + j]))) 166 TTAK[3] = _CAST16(TTAK[3] + _SBOX16(TTAK[2] ^ _MK16(TK[13 + j], TK[12 + j]))) 167 TTAK[4] = _CAST16(TTAK[4] + _SBOX16(TTAK[3] ^ _MK16(TK[1 + j], TK[0 + j])) + i) 168 169 # Phase 2 170 # 802.11i p.56 171 172 # Phase 2 - Step 1 173 PPK = list(TTAK) 174 PPK.append(_CAST16(TTAK[4] + _MK16(TSC[1], TSC[0]))) 175 176 # Phase 2 - Step 2 177 PPK[0] = _CAST16(PPK[0] + _SBOX16(PPK[5] ^ _MK16(TK[1], TK[0]))) 178 PPK[1] = _CAST16(PPK[1] + _SBOX16(PPK[0] ^ _MK16(TK[3], TK[2]))) 179 PPK[2] = _CAST16(PPK[2] + _SBOX16(PPK[1] ^ _MK16(TK[5], TK[4]))) 180 PPK[3] = _CAST16(PPK[3] + _SBOX16(PPK[2] ^ _MK16(TK[7], TK[6]))) 181 PPK[4] = _CAST16(PPK[4] + _SBOX16(PPK[3] ^ _MK16(TK[9], TK[8]))) 182 PPK[5] = _CAST16(PPK[5] + _SBOX16(PPK[4] ^ _MK16(TK[11], TK[10]))) 183 184 PPK[0] = _CAST16(PPK[0] + _RotR1(PPK[5] ^ _MK16(TK[13], TK[12]))) 185 PPK[1] = _CAST16(PPK[1] + _RotR1(PPK[0] ^ _MK16(TK[15], TK[14]))) 186 PPK[2] = _CAST16(PPK[2] + _RotR1(PPK[1])) 187 PPK[3] = _CAST16(PPK[3] + _RotR1(PPK[2])) 188 PPK[4] = _CAST16(PPK[4] + _RotR1(PPK[3])) 189 PPK[5] = _CAST16(PPK[5] + _RotR1(PPK[4])) 190 191 # Phase 2 - Step 3 192 WEPSeed = [] 193 WEPSeed.append(TSC[1]) 194 WEPSeed.append((TSC[1] | 0x20) & 0x7f) 195 WEPSeed.append(TSC[0]) 196 WEPSeed.append(((PPK[5] ^ _MK16(TK[1], TK[0])) >> 1) & 0xFF) 197 for i in xrange(6): 198 WEPSeed.append(PPK[i] & 0xFF) 199 WEPSeed.append(PPK[i] >> 8) 200 201 assert len(WEPSeed) == 16 202 203 return "".join([chr(x) for x in WEPSeed]) 204 205# TKIP - Michael 206# Tested against cryptopy (crypto.keyedHash.michael: Michael) 207 208def _rotate_right32(value, shift): 209 return (value >> (shift % 32) | value << ((32 - shift) % 32)) & 0xFFFFFFFF 210 211def _rotate_left32(value, shift): 212 return (value << (shift % 32) | value >> ((32 - shift) % 32)) & 0xFFFFFFFF 213 214def _XSWAP(value): 215 """Swap 2 least significant bytes of @value""" 216 return ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8) 217 218def _michael_b(l, r): 219 """Defined in 802.11i p.49""" 220 r = r ^ _rotate_left32(l, 17) 221 l = (l + r) % 2**32 222 r = r ^ _XSWAP(l) 223 l = (l + r) % 2**32 224 r = r ^ _rotate_left32(l, 3) 225 l = (l + r) % 2**32 226 r = r ^ _rotate_right32(l, 2) 227 l = (l + r) % 2**32 228 return l, r 229 230def michael(key, to_hash): 231 """Defined in 802.11i p.48""" 232 233 # Block size: 4 234 nb_block, nb_extra_bytes = divmod(len(to_hash), 4) 235 # Add padding 236 data = to_hash + chr(0x5a) + "\x00" * (7 - nb_extra_bytes) 237 238 # Hash 239 l, r = unpack('<II', key) 240 for i in xrange(nb_block + 2): 241 # Convert i-th block to int 242 block_i = unpack('<I', data[i*4:i*4 + 4])[0] 243 l ^= block_i 244 l, r = _michael_b(l, r) 245 return pack('<II', l, r) 246 247# TKIP packet utils 248 249def parse_TKIP_hdr(pkt): 250 """Extract TSCs, TA and encoded-data from a packet @pkt""" 251 # Note: FCS bit is not handled 252 assert pkt.FCfield.wep 253 254 # 802.11i - 8.3.2.2 255 payload = BytesIO(pkt[Raw].load) 256 TSC1, WEPseed, TSC0, bitfield = (orb(x) for x in payload.read(4)) 257 if bitfield & (1 << 5): 258 # Extended IV 259 TSC2, TSC3, TSC4, TSC5 = (orb(x) for x in payload.read(4)) 260 else: 261 TSC2, TSC3, TSC4, TSC5 = None, None, None, None 262 # 802.11i p. 46 263 raise ValueError("Extended IV must be set for TKIP") 264 265 # 802.11i p. 46 266 assert (TSC1 | 0x20) & 0x7f == WEPseed 267 268 TA = [orb(e) for e in hex_bytes(pkt.addr2.replace(':', ''))] 269 TSC = [TSC0, TSC1, TSC2, TSC3, TSC4, TSC5] 270 271 return TSC, TA, payload.read() 272 273def build_TKIP_payload(data, iv, mac, tk): 274 """Build a TKIP header for IV @iv and mac @mac, and encrypt @data 275 based on temporal key @tk 276 """ 277 TSC5, TSC4, TSC3, TSC2, TSC1, TSC0 = ( 278 (iv >> 40) & 0xFF, 279 (iv >> 32) & 0xFF, 280 (iv >> 24) & 0xFF, 281 (iv >> 16) & 0xFF, 282 (iv >> 8) & 0xFF, 283 iv & 0xFF 284 ) 285 bitfield = 1 << 5 # Extended IV 286 TKIP_hdr = chr(TSC1) + chr((TSC1 | 0x20) & 0x7f) + chr(TSC0) + chr(bitfield) 287 TKIP_hdr += chr(TSC2) + chr(TSC3) + chr(TSC4) + chr(TSC5) 288 289 TA = [orb(e) for e in hex_bytes(mac.replace(':', ''))] 290 TSC = [TSC0, TSC1, TSC2, TSC3, TSC4, TSC5] 291 TK = [orb(x) for x in tk] 292 293 rc4_key = gen_TKIP_RC4_key(TSC, TA, TK) 294 return TKIP_hdr + ARC4_encrypt(rc4_key, data) 295 296def parse_data_pkt(pkt, tk): 297 """Extract data from a WPA packet @pkt with temporal key @tk""" 298 TSC, TA, data = parse_TKIP_hdr(pkt) 299 TK = [orb(x) for x in tk] 300 301 rc4_key = gen_TKIP_RC4_key(TSC, TA, TK) 302 return ARC4_decrypt(rc4_key, data) 303 304class ICVError(Exception): 305 """The expected ICV is not the computed one""" 306 pass 307 308class MICError(Exception): 309 """The expected MIC is not the computed one""" 310 pass 311 312def check_MIC_ICV(data, mic_key, source, dest): 313 """Check MIC, ICV & return the data from a decrypted TKIP packet""" 314 assert len(data) > 12 315 316 # DATA - MIC(DA - SA - Priority=0 - 0 - 0 - 0 - DATA) - ICV 317 # 802.11i p.47 318 319 ICV = data[-4:] 320 MIC = data[-12:-4] 321 data_clear = data[:-12] 322 323 expected_ICV = pack("<I", crc32(data_clear + MIC) & 0xFFFFFFFF) 324 if expected_ICV != ICV: 325 raise ICVError() 326 327 sa = hex_bytes(source.replace(":", "")) # Source MAC 328 da = hex_bytes(dest.replace(":", "")) # Dest MAC 329 330 expected_MIC = michael(mic_key, da + sa + "\x00" + "\x00" * 3 + data_clear) 331 if expected_MIC != MIC: 332 raise MICError() 333 334 return data_clear 335 336def build_MIC_ICV(data, mic_key, source, dest): 337 """Compute and return the data with its MIC and ICV""" 338 # DATA - MIC(DA - SA - Priority=0 - 0 - 0 - 0 - DATA) - ICV 339 # 802.11i p.47 340 341 sa = hex_bytes(source.replace(":", "")) # Source MAC 342 da = hex_bytes(dest.replace(":", "")) # Dest MAC 343 MIC = michael(mic_key, da + sa + "\x00" + "\x00" * 3 + data) 344 ICV = pack("<I", crc32(data + MIC) & 0xFFFFFFFF) 345 346 return data + MIC + ICV 347