]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_ap_psk.py
nl80211: Fix interface-in-different-bridge case
[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:
5f35a5e2 398 dev[0].wait_connected(timeout=15)
cf0b9c86
JM
399 break
400 res = dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2])
401 if "OK" not in res:
402 raise Exception("EAPOL_RX to wpa_supplicant failed")
403 ev = dev[0].wait_event(["EAPOL-TX", "CTRL-EVENT-CONNECTED"], timeout=15)
404 if ev is None:
405 raise Exception("Timeout on EAPOL-TX from wpa_supplicant")
406 if "CTRL-EVENT-CONNECTED" in ev:
407 break
408 res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2])
409 if "OK" not in res:
410 raise Exception("EAPOL_RX to hostapd failed")
821490f5
JM
411
412def parse_eapol(data):
413 (version, type, length) = struct.unpack('>BBH', data[0:4])
414 payload = data[4:]
415 if length > len(payload):
416 raise Exception("Invalid EAPOL length")
417 if length < len(payload):
418 payload = payload[0:length]
419 eapol = {}
420 eapol['version'] = version
421 eapol['type'] = type
422 eapol['length'] = length
423 eapol['payload'] = payload
424 if type == 3:
425 # EAPOL-Key
426 (eapol['descr_type'],) = struct.unpack('B', payload[0:1])
427 payload = payload[1:]
a52fd1c3 428 if eapol['descr_type'] == 2 or eapol['descr_type'] == 254:
821490f5
JM
429 # RSN EAPOL-Key
430 (key_info, key_len) = struct.unpack('>HH', payload[0:4])
431 eapol['rsn_key_info'] = key_info
432 eapol['rsn_key_len'] = key_len
433 eapol['rsn_replay_counter'] = payload[4:12]
434 eapol['rsn_key_nonce'] = payload[12:44]
435 eapol['rsn_key_iv'] = payload[44:60]
436 eapol['rsn_key_rsc'] = payload[60:68]
437 eapol['rsn_key_id'] = payload[68:76]
438 eapol['rsn_key_mic'] = payload[76:92]
439 payload = payload[92:]
440 (eapol['rsn_key_data_len'],) = struct.unpack('>H', payload[0:2])
441 payload = payload[2:]
442 eapol['rsn_key_data'] = payload
443 return eapol
444
445def build_eapol(msg):
446 data = struct.pack(">BBH", msg['version'], msg['type'], msg['length'])
447 if msg['type'] == 3:
448 data += struct.pack('>BHH', msg['descr_type'], msg['rsn_key_info'],
449 msg['rsn_key_len'])
450 data += msg['rsn_replay_counter']
451 data += msg['rsn_key_nonce']
452 data += msg['rsn_key_iv']
453 data += msg['rsn_key_rsc']
454 data += msg['rsn_key_id']
455 data += msg['rsn_key_mic']
456 data += struct.pack('>H', msg['rsn_key_data_len'])
457 data += msg['rsn_key_data']
458 else:
459 data += msg['payload']
460 return data
461
462def sha1_prf(key, label, data, outlen):
463 res = ''
464 counter = 0
465 while outlen > 0:
466 m = hmac.new(key, label, hashlib.sha1)
467 m.update(struct.pack('B', 0))
468 m.update(data)
469 m.update(struct.pack('B', counter))
470 counter += 1
471 hash = m.digest()
472 if outlen > len(hash):
473 res += hash
474 outlen -= len(hash)
475 else:
476 res += hash[0:outlen]
477 outlen = 0
478 return res
479
480def pmk_to_ptk(pmk, addr1, addr2, nonce1, nonce2):
481 if addr1 < addr2:
482 data = binascii.unhexlify(addr1.replace(':','')) + binascii.unhexlify(addr2.replace(':',''))
483 else:
484 data = binascii.unhexlify(addr2.replace(':','')) + binascii.unhexlify(addr1.replace(':',''))
485 if nonce1 < nonce2:
486 data += nonce1 + nonce2
487 else:
488 data += nonce2 + nonce1
489 label = "Pairwise key expansion"
490 ptk = sha1_prf(pmk, label, data, 48)
491 kck = ptk[0:16]
492 kek = ptk[16:32]
493 return (ptk, kck, kek)
494
495def eapol_key_mic(kck, msg):
496 msg['rsn_key_mic'] = binascii.unhexlify('00000000000000000000000000000000')
497 data = build_eapol(msg)
498 m = hmac.new(kck, data, hashlib.sha1)
499 msg['rsn_key_mic'] = m.digest()[0:16]
500
501def rsn_eapol_key_set(msg, key_info, key_len, nonce, data):
502 msg['rsn_key_info'] = key_info
503 msg['rsn_key_len'] = key_len
504 if nonce:
505 msg['rsn_key_nonce'] = nonce
506 else:
507 msg['rsn_key_nonce'] = binascii.unhexlify('0000000000000000000000000000000000000000000000000000000000000000')
508 if data:
509 msg['rsn_key_data_len'] = len(data)
510 msg['rsn_key_data'] = data
511 msg['length'] = 95 + len(data)
512 else:
513 msg['rsn_key_data_len'] = 0
514 msg['rsn_key_data'] = ''
515 msg['length'] = 95
516
517def recv_eapol(hapd):
518 ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
519 if ev is None:
520 raise Exception("Timeout on EAPOL-TX from hostapd")
521 eapol = binascii.unhexlify(ev.split(' ')[2])
522 return parse_eapol(eapol)
523
524def send_eapol(hapd, addr, data):
525 res = hapd.request("EAPOL_RX " + addr + " " + binascii.hexlify(data))
526 if "OK" not in res:
527 raise Exception("EAPOL_RX to hostapd failed")
528
529def reply_eapol(info, hapd, addr, msg, key_info, nonce, data, kck):
530 logger.info("Send EAPOL-Key msg " + info)
531 rsn_eapol_key_set(msg, key_info, 0, nonce, data)
532 eapol_key_mic(kck, msg)
533 send_eapol(hapd, addr, build_eapol(msg))
534
535def hapd_connected(hapd):
536 ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=15)
537 if ev is None:
538 raise Exception("Timeout on AP-STA-CONNECTED from hostapd")
539
a52fd1c3 540def eapol_test(apdev, dev, wpa2=True):
821490f5 541 bssid = apdev['bssid']
a52fd1c3
JM
542 if wpa2:
543 ssid = "test-wpa2-psk"
544 else:
545 ssid = "test-wpa-psk"
821490f5
JM
546 psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
547 pmk = binascii.unhexlify(psk)
a52fd1c3
JM
548 if wpa2:
549 params = hostapd.wpa2_params(ssid=ssid)
550 else:
551 params = hostapd.wpa_params(ssid=ssid)
821490f5
JM
552 params['wpa_psk'] = psk
553 hapd = hostapd.add_ap(apdev['ifname'], params)
554 hapd.request("SET ext_eapol_frame_io 1")
555 dev.request("SET ext_eapol_frame_io 1")
556 dev.connect(ssid, psk="not used", scan_freq="2412", wait_connect=False)
557 addr = dev.p2p_interface_addr()
a52fd1c3
JM
558 if wpa2:
559 rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac020000')
560 else:
561 rsne = binascii.unhexlify('dd160050f20101000050f20201000050f20201000050f202')
821490f5
JM
562 snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111')
563 return (bssid,ssid,hapd,snonce,pmk,addr,rsne)
564
565def test_ap_wpa2_psk_ext_eapol(dev, apdev):
566 """WPA2-PSK AP using external EAPOL supplicant"""
567 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
568
569 msg = recv_eapol(hapd)
570 anonce = msg['rsn_key_nonce']
571 logger.info("Replay same data back")
572 send_eapol(hapd, addr, build_eapol(msg))
573
574 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
575
576 logger.info("Truncated Key Data in EAPOL-Key msg 2/4")
577 rsn_eapol_key_set(msg, 0x0101, 0, snonce, rsne)
578 msg['length'] = 95 + 22 - 1
579 send_eapol(hapd, addr, build_eapol(msg))
580
581 reply_eapol("2/4", hapd, addr, msg, 0x010a, snonce, rsne, kck)
582
583 msg = recv_eapol(hapd)
584 if anonce != msg['rsn_key_nonce']:
585 raise Exception("ANonce changed")
586 logger.info("Replay same data back")
587 send_eapol(hapd, addr, build_eapol(msg))
588
589 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
590 hapd_connected(hapd)
591
592def test_ap_wpa2_psk_ext_eapol_retry1(dev, apdev):
593 """WPA2 4-way handshake with EAPOL-Key 1/4 retransmitted"""
594 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
595
596 msg1 = recv_eapol(hapd)
597 anonce = msg1['rsn_key_nonce']
598
599 msg2 = recv_eapol(hapd)
600 if anonce != msg2['rsn_key_nonce']:
601 raise Exception("ANonce changed")
602
603 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
604
605 logger.info("Send EAPOL-Key msg 2/4")
606 msg = msg2
607 rsn_eapol_key_set(msg, 0x010a, 0, snonce, rsne)
608 eapol_key_mic(kck, msg)
609 send_eapol(hapd, addr, build_eapol(msg))
610
611 msg = recv_eapol(hapd)
612 if anonce != msg['rsn_key_nonce']:
613 raise Exception("ANonce changed")
614
615 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
616 hapd_connected(hapd)
617
618def test_ap_wpa2_psk_ext_eapol_retry1b(dev, apdev):
619 """WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted"""
620 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
621
622 msg1 = recv_eapol(hapd)
623 anonce = msg1['rsn_key_nonce']
624 msg2 = recv_eapol(hapd)
625 if anonce != msg2['rsn_key_nonce']:
626 raise Exception("ANonce changed")
627
628 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
629 reply_eapol("2/4 (a)", hapd, addr, msg1, 0x010a, snonce, rsne, kck)
630 reply_eapol("2/4 (b)", hapd, addr, msg2, 0x010a, snonce, rsne, kck)
631
632 msg = recv_eapol(hapd)
633 if anonce != msg['rsn_key_nonce']:
634 raise Exception("ANonce changed")
635
636 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
637 hapd_connected(hapd)
638
639def test_ap_wpa2_psk_ext_eapol_retry1c(dev, apdev):
640 """WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted and SNonce changing"""
641 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
642
643 msg1 = recv_eapol(hapd)
644 anonce = msg1['rsn_key_nonce']
645
646 msg2 = recv_eapol(hapd)
647 if anonce != msg2['rsn_key_nonce']:
648 raise Exception("ANonce changed")
649 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
650 reply_eapol("2/4 (a)", hapd, addr, msg1, 0x010a, snonce, rsne, kck)
651
652 snonce2 = binascii.unhexlify('2222222222222222222222222222222222222222222222222222222222222222')
653 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce2, anonce)
654 reply_eapol("2/4 (b)", hapd, addr, msg2, 0x010a, snonce2, rsne, kck)
655
656 msg = recv_eapol(hapd)
657 if anonce != msg['rsn_key_nonce']:
658 raise Exception("ANonce changed")
659 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
660 hapd_connected(hapd)
661
662def test_ap_wpa2_psk_ext_eapol_retry1d(dev, apdev):
663 """WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted and SNonce changing and older used"""
664 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
665
666 msg1 = recv_eapol(hapd)
667 anonce = msg1['rsn_key_nonce']
668 msg2 = recv_eapol(hapd)
669 if anonce != msg2['rsn_key_nonce']:
670 raise Exception("ANonce changed")
671
672 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
673 reply_eapol("2/4 (a)", hapd, addr, msg1, 0x010a, snonce, rsne, kck)
674
675 snonce2 = binascii.unhexlify('2222222222222222222222222222222222222222222222222222222222222222')
676 (ptk2, kck2, kek2) = pmk_to_ptk(pmk, addr, bssid, snonce2, anonce)
677
678 reply_eapol("2/4 (b)", hapd, addr, msg2, 0x010a, snonce2, rsne, kck2)
679 msg = recv_eapol(hapd)
680 if anonce != msg['rsn_key_nonce']:
681 raise Exception("ANonce changed")
682 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
683 hapd_connected(hapd)
53b9bedb
JM
684
685def test_ap_wpa2_psk_ext_eapol_type_diff(dev, apdev):
686 """WPA2 4-way handshake using external EAPOL supplicant"""
687 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
688
689 msg = recv_eapol(hapd)
690 anonce = msg['rsn_key_nonce']
691
692 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
693
694 # Incorrect descriptor type (frame dropped)
695 msg['descr_type'] = 253
696 rsn_eapol_key_set(msg, 0x010a, 0, snonce, rsne)
697 eapol_key_mic(kck, msg)
698 send_eapol(hapd, addr, build_eapol(msg))
699
700 # Incorrect descriptor type, but with a workaround (frame processed)
701 msg['descr_type'] = 254
702 rsn_eapol_key_set(msg, 0x010a, 0, snonce, rsne)
703 eapol_key_mic(kck, msg)
704 send_eapol(hapd, addr, build_eapol(msg))
705
706 msg = recv_eapol(hapd)
707 if anonce != msg['rsn_key_nonce']:
708 raise Exception("ANonce changed")
709 logger.info("Replay same data back")
710 send_eapol(hapd, addr, build_eapol(msg))
711
712 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
713 hapd_connected(hapd)
a52fd1c3
JM
714
715def test_ap_wpa_psk_ext_eapol(dev, apdev):
716 """WPA2-PSK AP using external EAPOL supplicant"""
717 (bssid,ssid,hapd,snonce,pmk,addr,wpae) = eapol_test(apdev[0], dev[0],
718 wpa2=False)
719
720 msg = recv_eapol(hapd)
721 anonce = msg['rsn_key_nonce']
722 logger.info("Replay same data back")
723 send_eapol(hapd, addr, build_eapol(msg))
724 logger.info("Too short data")
725 send_eapol(hapd, addr, build_eapol(msg)[0:98])
726
727 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
728 msg['descr_type'] = 2
729 reply_eapol("2/4(invalid type)", hapd, addr, msg, 0x010a, snonce, wpae, kck)
730 msg['descr_type'] = 254
731 reply_eapol("2/4", hapd, addr, msg, 0x010a, snonce, wpae, kck)
732
733 msg = recv_eapol(hapd)
734 if anonce != msg['rsn_key_nonce']:
735 raise Exception("ANonce changed")
736 logger.info("Replay same data back")
737 send_eapol(hapd, addr, build_eapol(msg))
738
739 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
740 hapd_connected(hapd)
64d04af5
JM
741
742def test_ap_wpa2_psk_ext_eapol_key_info(dev, apdev):
743 """WPA2-PSK 4-way handshake with strange key info values"""
744 (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
745
746 msg = recv_eapol(hapd)
747 anonce = msg['rsn_key_nonce']
748
749 (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
750 rsn_eapol_key_set(msg, 0x0000, 0, snonce, rsne)
751 send_eapol(hapd, addr, build_eapol(msg))
752 rsn_eapol_key_set(msg, 0xffff, 0, snonce, rsne)
753 send_eapol(hapd, addr, build_eapol(msg))
754 # SMK M1
755 rsn_eapol_key_set(msg, 0x2802, 0, snonce, rsne)
756 send_eapol(hapd, addr, build_eapol(msg))
757 # SMK M3
758 rsn_eapol_key_set(msg, 0x2002, 0, snonce, rsne)
759 send_eapol(hapd, addr, build_eapol(msg))
760 # Request
761 rsn_eapol_key_set(msg, 0x0902, 0, snonce, rsne)
762 send_eapol(hapd, addr, build_eapol(msg))
763 # Request
764 rsn_eapol_key_set(msg, 0x0902, 0, snonce, rsne)
765 tmp_kck = binascii.unhexlify('00000000000000000000000000000000')
766 eapol_key_mic(tmp_kck, msg)
767 send_eapol(hapd, addr, build_eapol(msg))
768
769 reply_eapol("2/4", hapd, addr, msg, 0x010a, snonce, rsne, kck)
770
771 msg = recv_eapol(hapd)
772 if anonce != msg['rsn_key_nonce']:
773 raise Exception("ANonce changed")
774
775 # Request (valic MIC)
776 rsn_eapol_key_set(msg, 0x0902, 0, snonce, rsne)
777 eapol_key_mic(kck, msg)
778 send_eapol(hapd, addr, build_eapol(msg))
779 # Request (valid MIC, replayed counter)
780 rsn_eapol_key_set(msg, 0x0902, 0, snonce, rsne)
781 eapol_key_mic(kck, msg)
782 send_eapol(hapd, addr, build_eapol(msg))
783
784 reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
785 hapd_connected(hapd)