]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_ap_psk.py
tests: WPA EAPOL 4-way handshake protocol testing
[thirdparty/hostap.git] / tests / hwsim / test_ap_psk.py
CommitLineData
c89d9ebb
JM
1# WPA2-Personal tests
2# Copyright (c) 2014, Qualcomm Atheros, Inc.
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
821490f5
JM
7import binascii
8import hashlib
9import hmac
c89d9ebb
JM
10import logging
11logger = logging.getLogger()
138ec97e 12import os
821490f5 13import struct
d1fc5736
JM
14import subprocess
15import time
c89d9ebb
JM
16
17import hostapd
fb5c8cea 18import hwsim_utils
c89d9ebb 19
eaf3f9b1
JM
20def check_mib(dev, vals):
21 mib = dev.get_mib()
22 for v in vals:
23 if mib[v[0]] != v[1]:
24 raise Exception("Unexpected {} = {} (expected {})".format(v[0], mib[v[0]], v[1]))
25
c89d9ebb
JM
26def test_ap_wpa2_psk(dev, apdev):
27 """WPA2-PSK AP with PSK instead of passphrase"""
28 ssid = "test-wpa2-psk"
29 passphrase = 'qwertyuiop'
30 psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
31 params = hostapd.wpa2_params(ssid=ssid)
32 params['wpa_psk'] = psk
65038313
JM
33 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
34 key_mgmt = hapd.get_config()['key_mgmt']
35 if key_mgmt.split(' ')[0] != "WPA-PSK":
36 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
c89d9ebb
JM
37 dev[0].connect(ssid, raw_psk=psk, scan_freq="2412")
38 dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
39
de748924
JM
40 sig = dev[0].request("SIGNAL_POLL").splitlines()
41 pkt = dev[0].request("PKTCNT_POLL").splitlines()
42 if "FREQUENCY=2412" not in sig:
43 raise Exception("Unexpected SIGNAL_POLL value: " + str(sig))
44 if "TXBAD=0" not in pkt:
45 raise Exception("Unexpected TXBAD value: " + str(pkt))
46
c89d9ebb
JM
47def test_ap_wpa2_psk_file(dev, apdev):
48 """WPA2-PSK AP with PSK from a file"""
49 ssid = "test-wpa2-psk"
50 passphrase = 'qwertyuiop'
51 psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
52 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
53 params['wpa_psk_file'] = 'hostapd.wpa_psk'
54 hostapd.add_ap(apdev[0]['ifname'], params)
55 dev[1].connect(ssid, psk="very secret", scan_freq="2412", wait_connect=False)
56 dev[2].connect(ssid, raw_psk=psk, scan_freq="2412")
57 dev[2].request("REMOVE_NETWORK all")
58 dev[0].connect(ssid, psk="very secret", scan_freq="2412")
59 dev[0].request("REMOVE_NETWORK all")
60 dev[2].connect(ssid, psk="another passphrase for all STAs", scan_freq="2412")
61 dev[0].connect(ssid, psk="another passphrase for all STAs", scan_freq="2412")
62 ev = dev[1].wait_event(["WPA: 4-Way Handshake failed"], timeout=10)
63 if ev is None:
64 raise Exception("Timed out while waiting for failure report")
65 dev[1].request("REMOVE_NETWORK all")
fb5c8cea 66
d1635d97
JM
67def test_ap_wpa2_ptk_rekey(dev, apdev):
68 """WPA2-PSK AP and PTK rekey enforced by station"""
69 ssid = "test-wpa2-psk"
70 passphrase = 'qwertyuiop'
71 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
a8375c94 72 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
d1635d97
JM
73 dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
74 ev = dev[0].wait_event(["WPA: Key negotiation completed"])
75 if ev is None:
76 raise Exception("PTK rekey timed out")
a8375c94 77 hwsim_utils.test_connectivity(dev[0], hapd)
d1635d97 78
6c87b4b8
JM
79def test_ap_wpa2_ptk_rekey_ap(dev, apdev):
80 """WPA2-PSK AP and PTK rekey enforced by AP"""
81 ssid = "test-wpa2-psk"
82 passphrase = 'qwertyuiop'
83 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
84 params['wpa_ptk_rekey'] = '2'
a8375c94 85 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
6c87b4b8
JM
86 dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
87 ev = dev[0].wait_event(["WPA: Key negotiation completed"])
88 if ev is None:
89 raise Exception("PTK rekey timed out")
a8375c94 90 hwsim_utils.test_connectivity(dev[0], hapd)
6c87b4b8 91
d1635d97
JM
92def test_ap_wpa2_sha256_ptk_rekey(dev, apdev):
93 """WPA2-PSK/SHA256 AKM AP and PTK rekey enforced by station"""
94 ssid = "test-wpa2-psk"
95 passphrase = 'qwertyuiop'
96 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
97 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
a8375c94 98 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
d1635d97
JM
99 dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK-SHA256",
100 wpa_ptk_rekey="1", scan_freq="2412")
101 ev = dev[0].wait_event(["WPA: Key negotiation completed"])
102 if ev is None:
103 raise Exception("PTK rekey timed out")
a8375c94 104 hwsim_utils.test_connectivity(dev[0], hapd)
eaf3f9b1
JM
105 check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-6"),
106 ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-6") ])
d1635d97 107
6c87b4b8
JM
108def test_ap_wpa2_sha256_ptk_rekey_ap(dev, apdev):
109 """WPA2-PSK/SHA256 AKM AP and PTK rekey enforced by AP"""
110 ssid = "test-wpa2-psk"
111 passphrase = 'qwertyuiop'
112 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
113 params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
114 params['wpa_ptk_rekey'] = '2'
a8375c94 115 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
6c87b4b8
JM
116 dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK-SHA256",
117 scan_freq="2412")
118 ev = dev[0].wait_event(["WPA: Key negotiation completed"])
119 if ev is None:
120 raise Exception("PTK rekey timed out")
a8375c94 121 hwsim_utils.test_connectivity(dev[0], hapd)
6c87b4b8
JM
122 check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-6"),
123 ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-6") ])
124
fb5c8cea
JM
125def test_ap_wpa_ptk_rekey(dev, apdev):
126 """WPA-PSK/TKIP AP and PTK rekey enforced by station"""
127 ssid = "test-wpa-psk"
128 passphrase = 'qwertyuiop'
129 params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
a8375c94 130 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
fb5c8cea 131 dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
91bc6c36
JM
132 if "[WPA-PSK-TKIP]" not in dev[0].request("SCAN_RESULTS"):
133 raise Exception("Scan results missing WPA element info")
fb5c8cea
JM
134 ev = dev[0].wait_event(["WPA: Key negotiation completed"])
135 if ev is None:
136 raise Exception("PTK rekey timed out")
a8375c94 137 hwsim_utils.test_connectivity(dev[0], hapd)
138ec97e 138
6c87b4b8
JM
139def test_ap_wpa_ptk_rekey_ap(dev, apdev):
140 """WPA-PSK/TKIP AP and PTK rekey enforced by AP"""
141 ssid = "test-wpa-psk"
142 passphrase = 'qwertyuiop'
143 params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
144 params['wpa_ptk_rekey'] = '2'
a8375c94 145 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
6c87b4b8
JM
146 dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
147 ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=10)
148 if ev is None:
149 raise Exception("PTK rekey timed out")
a8375c94 150 hwsim_utils.test_connectivity(dev[0], hapd)
6c87b4b8 151
12124240
JM
152def test_ap_wpa_ccmp(dev, apdev):
153 """WPA-PSK/CCMP"""
154 ssid = "test-wpa-psk"
155 passphrase = 'qwertyuiop'
156 params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
157 params['wpa_pairwise'] = "CCMP"
a8375c94 158 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
12124240 159 dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
a8375c94 160 hwsim_utils.test_connectivity(dev[0], hapd)
eaf3f9b1
JM
161 check_mib(dev[0], [ ("dot11RSNAConfigGroupCipherSize", "128"),
162 ("dot11RSNAGroupCipherRequested", "00-50-f2-4"),
163 ("dot11RSNAPairwiseCipherRequested", "00-50-f2-4"),
164 ("dot11RSNAAuthenticationSuiteRequested", "00-50-f2-2"),
165 ("dot11RSNAGroupCipherSelected", "00-50-f2-4"),
166 ("dot11RSNAPairwiseCipherSelected", "00-50-f2-4"),
167 ("dot11RSNAAuthenticationSuiteSelected", "00-50-f2-2"),
168 ("dot1xSuppSuppControlledPortStatus", "Authorized") ])
12124240 169
138ec97e
JM
170def test_ap_wpa2_psk_file(dev, apdev):
171 """WPA2-PSK AP with various PSK file error and success cases"""
172 addr0 = dev[0].p2p_dev_addr()
173 addr1 = dev[1].p2p_dev_addr()
174 addr2 = dev[2].p2p_dev_addr()
175 ssid = "psk"
176 pskfile = "/tmp/ap_wpa2_psk_file_errors.psk_file"
177 try:
178 os.remove(pskfile)
179 except:
180 pass
181
182 params = { "ssid": ssid, "wpa": "2", "wpa_key_mgmt": "WPA-PSK",
183 "rsn_pairwise": "CCMP", "wpa_psk_file": pskfile }
184
185 try:
186 # missing PSK file
187 hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
188 if "FAIL" not in hapd.request("ENABLE"):
189 raise Exception("Unexpected ENABLE success")
190 hapd.request("DISABLE")
191
192 # invalid MAC address
193 with open(pskfile, "w") as f:
194 f.write("\n")
195 f.write("foo\n")
196 if "FAIL" not in hapd.request("ENABLE"):
197 raise Exception("Unexpected ENABLE success")
198 hapd.request("DISABLE")
199
200 # no PSK on line
201 with open(pskfile, "w") as f:
202 f.write("00:11:22:33:44:55\n")
203 if "FAIL" not in hapd.request("ENABLE"):
204 raise Exception("Unexpected ENABLE success")
205 hapd.request("DISABLE")
206
207 # invalid PSK
208 with open(pskfile, "w") as f:
209 f.write("00:11:22:33:44:55 1234567\n")
210 if "FAIL" not in hapd.request("ENABLE"):
211 raise Exception("Unexpected ENABLE success")
212 hapd.request("DISABLE")
213
214 # valid PSK file
215 with open(pskfile, "w") as f:
216 f.write("00:11:22:33:44:55 12345678\n")
217 f.write(addr0 + " 123456789\n")
218 f.write(addr1 + " 123456789a\n")
219 f.write(addr2 + " 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n")
220 if "FAIL" in hapd.request("ENABLE"):
221 raise Exception("Unexpected ENABLE failure")
222
223 dev[0].connect(ssid, psk="123456789", scan_freq="2412")
224 dev[1].connect(ssid, psk="123456789a", scan_freq="2412")
225 dev[2].connect(ssid, raw_psk="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", scan_freq="2412")
226
227 finally:
228 try:
229 os.remove(pskfile)
230 except:
231 pass
6796e502
JM
232
233def test_ap_wpa2_psk_wildcard_ssid(dev, apdev):
234 """WPA2-PSK AP and wildcard SSID configuration"""
235 ssid = "test-wpa2-psk"
236 passphrase = 'qwertyuiop'
237 psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
238 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
239 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
240 dev[0].connect("", bssid=apdev[0]['bssid'], psk=passphrase,
241 scan_freq="2412")
242 dev[1].connect("", bssid=apdev[0]['bssid'], raw_psk=psk, scan_freq="2412")
3b25ad4c
JM
243
244def test_ap_wpa2_gtk_rekey(dev, apdev):
245 """WPA2-PSK AP and GTK rekey enforced by AP"""
246 ssid = "test-wpa2-psk"
247 passphrase = 'qwertyuiop'
248 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
249 params['wpa_group_rekey'] = '1'
a8375c94 250 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
3b25ad4c
JM
251 dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
252 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
253 if ev is None:
254 raise Exception("GTK rekey timed out")
a8375c94 255 hwsim_utils.test_connectivity(dev[0], hapd)
3b25ad4c
JM
256
257def test_ap_wpa_gtk_rekey(dev, apdev):
258 """WPA-PSK/TKIP AP and GTK rekey enforced by AP"""
259 ssid = "test-wpa-psk"
260 passphrase = 'qwertyuiop'
261 params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
262 params['wpa_group_rekey'] = '1'
a8375c94 263 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
3b25ad4c
JM
264 dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
265 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
266 if ev is None:
267 raise Exception("GTK rekey timed out")
a8375c94 268 hwsim_utils.test_connectivity(dev[0], hapd)
3b25ad4c
JM
269
270def test_ap_wpa2_gmk_rekey(dev, apdev):
271 """WPA2-PSK AP and GMK and GTK rekey enforced by AP"""
272 ssid = "test-wpa2-psk"
273 passphrase = 'qwertyuiop'
274 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
275 params['wpa_group_rekey'] = '1'
276 params['wpa_gmk_rekey'] = '2'
a8375c94 277 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
3b25ad4c
JM
278 dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
279 for i in range(0, 3):
280 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
281 if ev is None:
282 raise Exception("GTK rekey timed out")
a8375c94 283 hwsim_utils.test_connectivity(dev[0], hapd)
3b25ad4c
JM
284
285def test_ap_wpa2_strict_rekey(dev, apdev):
286 """WPA2-PSK AP and strict GTK rekey enforced by AP"""
287 ssid = "test-wpa2-psk"
288 passphrase = 'qwertyuiop'
289 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
290 params['wpa_strict_rekey'] = '1'
a8375c94 291 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
3b25ad4c
JM
292 dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
293 dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
294 dev[1].request("DISCONNECT")
295 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
296 if ev is None:
297 raise Exception("GTK rekey timed out")
a8375c94 298 hwsim_utils.test_connectivity(dev[0], hapd)
d1fc5736
JM
299
300def test_ap_wpa2_bridge_fdb(dev, apdev):
301 """Bridge FDB entry removal"""
302 try:
303 ssid = "test-wpa2-psk"
304 passphrase = "12345678"
305 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
306 params['bridge'] = 'ap-br0'
307 hostapd.add_ap(apdev[0]['ifname'], params)
308 subprocess.call(['sudo', 'brctl', 'setfd', 'ap-br0', '0'])
309 subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
310 dev[0].connect(ssid, psk=passphrase, scan_freq="2412",
311 bssid=apdev[0]['bssid'])
312 dev[1].connect(ssid, psk=passphrase, scan_freq="2412",
313 bssid=apdev[0]['bssid'])
314 addr0 = dev[0].p2p_interface_addr()
315 hwsim_utils.test_connectivity_sta(dev[0], dev[1])
316 cmd = subprocess.Popen(['brctl', 'showmacs', 'ap-br0'],
317 stdout=subprocess.PIPE)
318 macs1 = cmd.stdout.read()
319 dev[0].request("DISCONNECT")
320 dev[1].request("DISCONNECT")
321 time.sleep(1)
322 cmd = subprocess.Popen(['brctl', 'showmacs', 'ap-br0'],
323 stdout=subprocess.PIPE)
324 macs2 = cmd.stdout.read()
325
326 addr1 = dev[1].p2p_interface_addr()
327 if addr0 not in macs1 or addr1 not in macs1:
328 raise Exception("Bridge FDB entry missing")
329 if addr0 in macs2 or addr1 in macs2:
330 raise Exception("Bridge FDB entry was not removed")
331 finally:
332 subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
333 subprocess.call(['sudo', 'brctl', 'delbr', 'ap-br0'])
cf0b9c86 334
8619c334
JM
335def test_ap_wpa2_already_in_bridge(dev, apdev):
336 """hostapd behavior with interface already in bridge"""
337 ifname = apdev[0]['ifname']
338 br_ifname = 'ext-ap-br0'
339 try:
340 ssid = "test-wpa2-psk"
341 passphrase = "12345678"
342 subprocess.call(['brctl', 'addbr', br_ifname])
343 subprocess.call(['brctl', 'setfd', br_ifname, '0'])
344 subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
345 subprocess.call(['iw', ifname, 'set', 'type', '__ap'])
346 subprocess.call(['brctl', 'addif', br_ifname, ifname])
347 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
348 hapd = hostapd.add_ap(ifname, params)
349 if hapd.get_driver_status_field('brname') != br_ifname:
350 raise Exception("Bridge name not identified correctly")
351 dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
352 finally:
353 subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'down'])
354 subprocess.call(['brctl', 'delif', br_ifname, ifname])
355 subprocess.call(['iw', ifname, 'set', 'type', 'station'])
356 subprocess.call(['brctl', 'delbr', br_ifname])
357
358def test_ap_wpa2_ext_add_to_bridge(dev, apdev):
359 """hostapd behavior with interface added to bridge externally"""
360 ifname = apdev[0]['ifname']
361 br_ifname = 'ext-ap-br0'
362 try:
363 ssid = "test-wpa2-psk"
364 passphrase = "12345678"
365 params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
366 hapd = hostapd.add_ap(ifname, params)
367
368 subprocess.call(['brctl', 'addbr', br_ifname])
369 subprocess.call(['brctl', 'setfd', br_ifname, '0'])
370 subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
371 subprocess.call(['brctl', 'addif', br_ifname, ifname])
372 dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
373 if hapd.get_driver_status_field('brname') != br_ifname:
374 raise Exception("Bridge name not identified correctly")
375 finally:
376 subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'down'])
377 subprocess.call(['brctl', 'delif', br_ifname, ifname])
378 subprocess.call(['brctl', 'delbr', br_ifname])
379
cf0b9c86
JM
380def test_ap_wpa2_psk_ext(dev, apdev):
381 """WPA2-PSK AP using external EAPOL I/O"""
382 bssid = apdev[0]['bssid']
383 ssid = "test-wpa2-psk"
384 passphrase = 'qwertyuiop'
385 psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
386 params = hostapd.wpa2_params(ssid=ssid)
387 params['wpa_psk'] = psk
388 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
389 hapd.request("SET ext_eapol_frame_io 1")
390 dev[0].request("SET ext_eapol_frame_io 1")
391 dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False)
392 addr = dev[0].p2p_interface_addr()
393 while True:
394 ev = hapd.wait_event(["EAPOL-TX", "AP-STA-CONNECTED"], timeout=15)
395 if ev is None:
396 raise Exception("Timeout on EAPOL-TX from hostapd")
397 if "AP-STA-CONNECTED" in ev:
398 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=15)
399 if ev is None:
400 raise Exception("Timeout on connection event from wpa_supplicant")
401 break
402 res = dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2])
403 if "OK" not in res:
404 raise Exception("EAPOL_RX to wpa_supplicant failed")
405 ev = dev[0].wait_event(["EAPOL-TX", "CTRL-EVENT-CONNECTED"], timeout=15)
406 if ev is None:
407 raise Exception("Timeout on EAPOL-TX from wpa_supplicant")
408 if "CTRL-EVENT-CONNECTED" in ev:
409 break
410 res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2])
411 if "OK" not in res:
412 raise Exception("EAPOL_RX to hostapd failed")
821490f5
JM
413
414def parse_eapol(data):
415 (version, type, length) = struct.unpack('>BBH', data[0:4])
416 payload = data[4:]
417 if length > len(payload):
418 raise Exception("Invalid EAPOL length")
419 if length < len(payload):
420 payload = payload[0:length]
421 eapol = {}
422 eapol['version'] = version
423 eapol['type'] = type
424 eapol['length'] = length
425 eapol['payload'] = payload
426 if type == 3:
427 # EAPOL-Key
428 (eapol['descr_type'],) = struct.unpack('B', payload[0:1])
429 payload = payload[1:]
a52fd1c3 430 if eapol['descr_type'] == 2 or eapol['descr_type'] == 254:
821490f5
JM
431 # RSN EAPOL-Key
432 (key_info, key_len) = struct.unpack('>HH', payload[0:4])
433 eapol['rsn_key_info'] = key_info
434 eapol['rsn_key_len'] = key_len
435 eapol['rsn_replay_counter'] = payload[4:12]
436 eapol['rsn_key_nonce'] = payload[12:44]
437 eapol['rsn_key_iv'] = payload[44:60]
438 eapol['rsn_key_rsc'] = payload[60:68]
439 eapol['rsn_key_id'] = payload[68:76]
440 eapol['rsn_key_mic'] = payload[76:92]
441 payload = payload[92:]
442 (eapol['rsn_key_data_len'],) = struct.unpack('>H', payload[0:2])
443 payload = payload[2:]
444 eapol['rsn_key_data'] = payload
445 return eapol
446
447def build_eapol(msg):
448 data = struct.pack(">BBH", msg['version'], msg['type'], msg['length'])
449 if msg['type'] == 3:
450 data += struct.pack('>BHH', msg['descr_type'], msg['rsn_key_info'],
451 msg['rsn_key_len'])
452 data += msg['rsn_replay_counter']
453 data += msg['rsn_key_nonce']
454 data += msg['rsn_key_iv']
455 data += msg['rsn_key_rsc']
456 data += msg['rsn_key_id']
457 data += msg['rsn_key_mic']
458 data += struct.pack('>H', msg['rsn_key_data_len'])
459 data += msg['rsn_key_data']
460 else:
461 data += msg['payload']
462 return data
463
464def sha1_prf(key, label, data, outlen):
465 res = ''
466 counter = 0
467 while outlen > 0:
468 m = hmac.new(key, label, hashlib.sha1)
469 m.update(struct.pack('B', 0))
470 m.update(data)
471 m.update(struct.pack('B', counter))
472 counter += 1
473 hash = m.digest()
474 if outlen > len(hash):
475 res += hash
476 outlen -= len(hash)
477 else:
478 res += hash[0:outlen]
479 outlen = 0
480 return res
481
482def pmk_to_ptk(pmk, addr1, addr2, nonce1, nonce2):
483 if addr1 < addr2:
484 data = binascii.unhexlify(addr1.replace(':','')) + binascii.unhexlify(addr2.replace(':',''))
485 else:
486 data = binascii.unhexlify(addr2.replace(':','')) + binascii.unhexlify(addr1.replace(':',''))
487 if nonce1 < nonce2:
488 data += nonce1 + nonce2
489 else:
490 data += nonce2 + nonce1
491 label = "Pairwise key expansion"
492 ptk = sha1_prf(pmk, label, data, 48)
493 kck = ptk[0:16]
494 kek = ptk[16:32]
495 return (ptk, kck, kek)
496
497def eapol_key_mic(kck, msg):
498 msg['rsn_key_mic'] = binascii.unhexlify('00000000000000000000000000000000')
499 data = build_eapol(msg)
500 m = hmac.new(kck, data, hashlib.sha1)
501 msg['rsn_key_mic'] = m.digest()[0:16]
502
503def rsn_eapol_key_set(msg, key_info, key_len, nonce, data):
504 msg['rsn_key_info'] = key_info
505 msg['rsn_key_len'] = key_len
506 if nonce:
507 msg['rsn_key_nonce'] = nonce
508 else:
509 msg['rsn_key_nonce'] = binascii.unhexlify('0000000000000000000000000000000000000000000000000000000000000000')
510 if data:
511 msg['rsn_key_data_len'] = len(data)
512 msg['rsn_key_data'] = data
513 msg['length'] = 95 + len(data)
514 else:
515 msg['rsn_key_data_len'] = 0
516 msg['rsn_key_data'] = ''
517 msg['length'] = 95
518
519def recv_eapol(hapd):
520 ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
521 if ev is None:
522 raise Exception("Timeout on EAPOL-TX from hostapd")
523 eapol = binascii.unhexlify(ev.split(' ')[2])
524 return parse_eapol(eapol)
525
526def send_eapol(hapd, addr, data):
527 res = hapd.request("EAPOL_RX " + addr + " " + binascii.hexlify(data))
528 if "OK" not in res:
529 raise Exception("EAPOL_RX to hostapd failed")
530
531def reply_eapol(info, hapd, addr, msg, key_info, nonce, data, kck):
532 logger.info("Send EAPOL-Key msg " + info)
533 rsn_eapol_key_set(msg, key_info, 0, nonce, data)
534 eapol_key_mic(kck, msg)
535 send_eapol(hapd, addr, build_eapol(msg))
536
537def hapd_connected(hapd):
538 ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=15)
539 if ev is None:
540 raise Exception("Timeout on AP-STA-CONNECTED from hostapd")
541
a52fd1c3 542def eapol_test(apdev, dev, wpa2=True):
821490f5 543 bssid = apdev['bssid']
a52fd1c3
JM
544 if wpa2:
545 ssid = "test-wpa2-psk"
546 else:
547 ssid = "test-wpa-psk"
821490f5
JM
548 psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
549 pmk = binascii.unhexlify(psk)
a52fd1c3
JM
550 if wpa2:
551 params = hostapd.wpa2_params(ssid=ssid)
552 else:
553 params = hostapd.wpa_params(ssid=ssid)
821490f5
JM
554 params['wpa_psk'] = psk
555 hapd = hostapd.add_ap(apdev['ifname'], params)
556 hapd.request("SET ext_eapol_frame_io 1")
557 dev.request("SET ext_eapol_frame_io 1")
558 dev.connect(ssid, psk="not used", scan_freq="2412", wait_connect=False)
559 addr = dev.p2p_interface_addr()
a52fd1c3
JM
560 if wpa2:
561 rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac020000')
562 else:
563 rsne = binascii.unhexlify('dd160050f20101000050f20201000050f20201000050f202')
821490f5
JM
564 snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111')
565 return (bssid,ssid,hapd,snonce,pmk,addr,rsne)
566
567def test_ap_wpa2_psk_ext_eapol(dev, apdev):
568 """WPA2-PSK AP using external EAPOL supplicant"""
569 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
570
571 msg = recv_eapol(hapd)
572 anonce = msg['rsn_key_nonce']
573 logger.info("Replay same data back")
574 send_eapol(hapd, addr, build_eapol(msg))
575
576 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
577
578 logger.info("Truncated Key Data in EAPOL-Key msg 2/4")
579 rsn_eapol_key_set(msg, 0x0101, 0, snonce, rsne)
580 msg['length'] = 95 + 22 - 1
581 send_eapol(hapd, addr, build_eapol(msg))
582
583 reply_eapol("2/4", hapd, addr, msg, 0x010a, snonce, rsne, kck)
584
585 msg = recv_eapol(hapd)
586 if anonce != msg['rsn_key_nonce']:
587 raise Exception("ANonce changed")
588 logger.info("Replay same data back")
589 send_eapol(hapd, addr, build_eapol(msg))
590
591 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
592 hapd_connected(hapd)
593
594def test_ap_wpa2_psk_ext_eapol_retry1(dev, apdev):
595 """WPA2 4-way handshake with EAPOL-Key 1/4 retransmitted"""
596 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
597
598 msg1 = recv_eapol(hapd)
599 anonce = msg1['rsn_key_nonce']
600
601 msg2 = recv_eapol(hapd)
602 if anonce != msg2['rsn_key_nonce']:
603 raise Exception("ANonce changed")
604
605 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
606
607 logger.info("Send EAPOL-Key msg 2/4")
608 msg = msg2
609 rsn_eapol_key_set(msg, 0x010a, 0, snonce, rsne)
610 eapol_key_mic(kck, msg)
611 send_eapol(hapd, addr, build_eapol(msg))
612
613 msg = recv_eapol(hapd)
614 if anonce != msg['rsn_key_nonce']:
615 raise Exception("ANonce changed")
616
617 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
618 hapd_connected(hapd)
619
620def test_ap_wpa2_psk_ext_eapol_retry1b(dev, apdev):
621 """WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted"""
622 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
623
624 msg1 = recv_eapol(hapd)
625 anonce = msg1['rsn_key_nonce']
626 msg2 = recv_eapol(hapd)
627 if anonce != msg2['rsn_key_nonce']:
628 raise Exception("ANonce changed")
629
630 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
631 reply_eapol("2/4 (a)", hapd, addr, msg1, 0x010a, snonce, rsne, kck)
632 reply_eapol("2/4 (b)", hapd, addr, msg2, 0x010a, snonce, rsne, kck)
633
634 msg = recv_eapol(hapd)
635 if anonce != msg['rsn_key_nonce']:
636 raise Exception("ANonce changed")
637
638 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
639 hapd_connected(hapd)
640
641def test_ap_wpa2_psk_ext_eapol_retry1c(dev, apdev):
642 """WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted and SNonce changing"""
643 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
644
645 msg1 = recv_eapol(hapd)
646 anonce = msg1['rsn_key_nonce']
647
648 msg2 = recv_eapol(hapd)
649 if anonce != msg2['rsn_key_nonce']:
650 raise Exception("ANonce changed")
651 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
652 reply_eapol("2/4 (a)", hapd, addr, msg1, 0x010a, snonce, rsne, kck)
653
654 snonce2 = binascii.unhexlify('2222222222222222222222222222222222222222222222222222222222222222')
655 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce2, anonce)
656 reply_eapol("2/4 (b)", hapd, addr, msg2, 0x010a, snonce2, rsne, kck)
657
658 msg = recv_eapol(hapd)
659 if anonce != msg['rsn_key_nonce']:
660 raise Exception("ANonce changed")
661 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
662 hapd_connected(hapd)
663
664def test_ap_wpa2_psk_ext_eapol_retry1d(dev, apdev):
665 """WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted and SNonce changing and older used"""
666 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
667
668 msg1 = recv_eapol(hapd)
669 anonce = msg1['rsn_key_nonce']
670 msg2 = recv_eapol(hapd)
671 if anonce != msg2['rsn_key_nonce']:
672 raise Exception("ANonce changed")
673
674 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
675 reply_eapol("2/4 (a)", hapd, addr, msg1, 0x010a, snonce, rsne, kck)
676
677 snonce2 = binascii.unhexlify('2222222222222222222222222222222222222222222222222222222222222222')
678 (ptk2, kck2, kek2) = pmk_to_ptk(pmk, addr, bssid, snonce2, anonce)
679
680 reply_eapol("2/4 (b)", hapd, addr, msg2, 0x010a, snonce2, rsne, kck2)
681 msg = recv_eapol(hapd)
682 if anonce != msg['rsn_key_nonce']:
683 raise Exception("ANonce changed")
684 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
685 hapd_connected(hapd)
53b9bedb
JM
686
687def test_ap_wpa2_psk_ext_eapol_type_diff(dev, apdev):
688 """WPA2 4-way handshake using external EAPOL supplicant"""
689 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
690
691 msg = recv_eapol(hapd)
692 anonce = msg['rsn_key_nonce']
693
694 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
695
696 # Incorrect descriptor type (frame dropped)
697 msg['descr_type'] = 253
698 rsn_eapol_key_set(msg, 0x010a, 0, snonce, rsne)
699 eapol_key_mic(kck, msg)
700 send_eapol(hapd, addr, build_eapol(msg))
701
702 # Incorrect descriptor type, but with a workaround (frame processed)
703 msg['descr_type'] = 254
704 rsn_eapol_key_set(msg, 0x010a, 0, snonce, rsne)
705 eapol_key_mic(kck, msg)
706 send_eapol(hapd, addr, build_eapol(msg))
707
708 msg = recv_eapol(hapd)
709 if anonce != msg['rsn_key_nonce']:
710 raise Exception("ANonce changed")
711 logger.info("Replay same data back")
712 send_eapol(hapd, addr, build_eapol(msg))
713
714 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
715 hapd_connected(hapd)
a52fd1c3
JM
716
717def test_ap_wpa_psk_ext_eapol(dev, apdev):
718 """WPA2-PSK AP using external EAPOL supplicant"""
719 (bssid,ssid,hapd,snonce,pmk,addr,wpae) = eapol_test(apdev[0], dev[0],
720 wpa2=False)
721
722 msg = recv_eapol(hapd)
723 anonce = msg['rsn_key_nonce']
724 logger.info("Replay same data back")
725 send_eapol(hapd, addr, build_eapol(msg))
726 logger.info("Too short data")
727 send_eapol(hapd, addr, build_eapol(msg)[0:98])
728
729 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
730 msg['descr_type'] = 2
731 reply_eapol("2/4(invalid type)", hapd, addr, msg, 0x010a, snonce, wpae, kck)
732 msg['descr_type'] = 254
733 reply_eapol("2/4", hapd, addr, msg, 0x010a, snonce, wpae, kck)
734
735 msg = recv_eapol(hapd)
736 if anonce != msg['rsn_key_nonce']:
737 raise Exception("ANonce changed")
738 logger.info("Replay same data back")
739 send_eapol(hapd, addr, build_eapol(msg))
740
741 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
742 hapd_connected(hapd)