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