1 # EAP Re-authentication Protocol (ERP) tests
2 # Copyright (c) 2014-2015, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
9 logger = logging.getLogger()
14 from utils import HwsimSkip
15 from test_ap_eap import int_eap_server_params
16 from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
18 def check_erp_capa(dev):
19 capab = dev.get_capability("erp")
20 if not capab or 'ERP' not in capab:
21 raise HwsimSkip("ERP not supported in the build")
23 def test_erp_initiate_reauth_start(dev, apdev):
24 """Authenticator sending EAP-Initiate/Re-auth-Start, but ERP disabled on peer"""
25 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
26 params['erp_send_reauth_start'] = '1'
27 params['erp_domain'] = 'example.com'
28 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
30 dev[0].request("ERP_FLUSH")
31 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
32 eap="PAX", identity="pax.user@example.com",
33 password_hex="0123456789abcdef0123456789abcdef",
36 def test_erp_enabled_on_server(dev, apdev):
37 """ERP enabled on internal EAP server, but disabled on peer"""
38 params = int_eap_server_params()
39 params['erp_send_reauth_start'] = '1'
40 params['erp_domain'] = 'example.com'
41 params['eap_server_erp'] = '1'
42 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
44 dev[0].request("ERP_FLUSH")
45 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
46 eap="PAX", identity="pax.user@example.com",
47 password_hex="0123456789abcdef0123456789abcdef",
50 def test_erp(dev, apdev):
51 """ERP enabled on server and peer"""
52 check_erp_capa(dev[0])
53 params = int_eap_server_params()
54 params['erp_send_reauth_start'] = '1'
55 params['erp_domain'] = 'example.com'
56 params['eap_server_erp'] = '1'
57 params['disable_pmksa_caching'] = '1'
58 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
60 dev[0].request("ERP_FLUSH")
61 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
62 eap="PSK", identity="psk.user@example.com",
63 password_hex="0123456789abcdef0123456789abcdef",
64 erp="1", scan_freq="2412")
66 dev[0].request("DISCONNECT")
67 dev[0].wait_disconnected(timeout=15)
68 dev[0].request("RECONNECT")
69 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
71 raise Exception("EAP success timed out")
72 if "EAP re-authentication completed successfully" not in ev:
73 raise Exception("Did not use ERP")
74 dev[0].wait_connected(timeout=15, error="Reconnection timed out")
76 def test_erp_server_no_match(dev, apdev):
77 """ERP enabled on server and peer, but server has no key match"""
78 check_erp_capa(dev[0])
79 params = int_eap_server_params()
80 params['erp_send_reauth_start'] = '1'
81 params['erp_domain'] = 'example.com'
82 params['eap_server_erp'] = '1'
83 params['disable_pmksa_caching'] = '1'
84 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
86 dev[0].request("ERP_FLUSH")
87 id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
88 eap="PSK", identity="psk.user@example.com",
89 password_hex="0123456789abcdef0123456789abcdef",
90 erp="1", scan_freq="2412")
91 dev[0].request("DISCONNECT")
92 dev[0].wait_disconnected(timeout=15)
93 hapd.request("ERP_FLUSH")
94 dev[0].request("RECONNECT")
95 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS",
96 "CTRL-EVENT-EAP-FAILURE"], timeout=15)
98 raise Exception("EAP result timed out")
99 if "CTRL-EVENT-EAP-SUCCESS" in ev:
100 raise Exception("Unexpected EAP success")
101 dev[0].request("DISCONNECT")
102 dev[0].select_network(id)
103 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
105 raise Exception("EAP success timed out")
106 if "EAP re-authentication completed successfully" in ev:
107 raise Exception("Unexpected use of ERP")
108 dev[0].wait_connected(timeout=15, error="Reconnection timed out")
110 def start_erp_as(apdev):
111 params = { "ssid": "as", "beacon_int": "2000",
112 "radius_server_clients": "auth_serv/radius_clients.conf",
113 "radius_server_auth_port": '18128',
115 "eap_user_file": "auth_serv/eap_user.conf",
116 "ca_cert": "auth_serv/ca.pem",
117 "server_cert": "auth_serv/server.pem",
118 "private_key": "auth_serv/server.key",
119 "eap_sim_db": "unix:/tmp/hlr_auc_gw.sock",
120 "dh_file": "auth_serv/dh.conf",
121 "pac_opaque_encr_key": "000102030405060708090a0b0c0d0e0f",
122 "eap_fast_a_id": "101112131415161718191a1b1c1d1e1f",
123 "eap_fast_a_id_info": "test server",
124 "eap_server_erp": "1",
125 "erp_domain": "example.com" }
126 hostapd.add_ap(apdev['ifname'], params)
128 def test_erp_radius(dev, apdev):
129 """ERP enabled on RADIUS server and peer"""
130 check_erp_capa(dev[0])
131 start_erp_as(apdev[1])
132 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
133 params['auth_server_port'] = "18128"
134 params['erp_send_reauth_start'] = '1'
135 params['erp_domain'] = 'example.com'
136 params['disable_pmksa_caching'] = '1'
137 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
139 dev[0].request("ERP_FLUSH")
140 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
141 eap="PSK", identity="psk.user@example.com",
142 password_hex="0123456789abcdef0123456789abcdef",
143 erp="1", scan_freq="2412")
145 dev[0].request("DISCONNECT")
146 dev[0].wait_disconnected(timeout=15)
147 dev[0].request("RECONNECT")
148 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
150 raise Exception("EAP success timed out")
151 if "EAP re-authentication completed successfully" not in ev:
152 raise Exception("Did not use ERP")
153 dev[0].wait_connected(timeout=15, error="Reconnection timed out")
155 def erp_test(dev, hapd, **kwargs):
156 res = dev.get_capability("eap")
157 if kwargs['eap'] not in res:
158 logger.info("Skip ERP test with %s due to missing support" % kwargs['eap'])
162 dev.request("ERP_FLUSH")
163 id = dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", erp="1",
164 scan_freq="2412", **kwargs)
165 dev.request("DISCONNECT")
166 dev.wait_disconnected(timeout=15)
168 dev.request("RECONNECT")
169 ev = dev.wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
171 raise Exception("EAP success timed out")
172 if "EAP re-authentication completed successfully" not in ev:
173 raise Exception("Did not use ERP")
174 dev.wait_connected(timeout=15, error="Reconnection timed out")
175 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
177 raise Exception("No connection event received from hostapd")
178 dev.request("DISCONNECT")
180 def test_erp_radius_eap_methods(dev, apdev):
181 """ERP enabled on RADIUS server and peer"""
182 check_erp_capa(dev[0])
183 eap_methods = dev[0].get_capability("eap")
184 start_erp_as(apdev[1])
185 params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
186 params['auth_server_port'] = "18128"
187 params['erp_send_reauth_start'] = '1'
188 params['erp_domain'] = 'example.com'
189 params['disable_pmksa_caching'] = '1'
190 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
192 erp_test(dev[0], hapd, eap="AKA", identity="0232010000000000@example.com",
193 password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
194 erp_test(dev[0], hapd, eap="AKA'", identity="6555444333222111@example.com",
195 password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
196 erp_test(dev[0], hapd, eap="EKE", identity="erp-eke@example.com",
198 if "FAST" in eap_methods:
199 erp_test(dev[0], hapd, eap="FAST", identity="erp-fast@example.com",
200 password="password", ca_cert="auth_serv/ca.pem",
202 phase1="fast_provisioning=2",
203 pac_file="blob://fast_pac_auth_erp")
204 erp_test(dev[0], hapd, eap="GPSK", identity="erp-gpsk@example.com",
205 password="abcdefghijklmnop0123456789abcdef")
206 erp_test(dev[0], hapd, eap="IKEV2", identity="erp-ikev2@example.com",
208 erp_test(dev[0], hapd, eap="PAX", identity="erp-pax@example.com",
209 password_hex="0123456789abcdef0123456789abcdef")
211 #if "MSCHAPV2" in eap_methods:
212 # erp_test(dev[0], hapd, eap="PEAP", identity="erp-peap@example.com",
213 # password="password", ca_cert="auth_serv/ca.pem",
214 # phase2="auth=MSCHAPV2")
215 erp_test(dev[0], hapd, eap="PSK", identity="erp-psk@example.com",
216 password_hex="0123456789abcdef0123456789abcdef")
217 if "PWD" in eap_methods:
218 erp_test(dev[0], hapd, eap="PWD", identity="erp-pwd@example.com",
219 password="secret password")
220 erp_test(dev[0], hapd, eap="SAKE", identity="erp-sake@example.com",
221 password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
222 erp_test(dev[0], hapd, eap="SIM", identity="1232010000000000@example.com",
223 password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
224 erp_test(dev[0], hapd, eap="TLS", identity="erp-tls@example.com",
225 ca_cert="auth_serv/ca.pem", client_cert="auth_serv/user.pem",
226 private_key="auth_serv/user.key")
227 erp_test(dev[0], hapd, eap="TTLS", identity="erp-ttls@example.com",
228 password="password", ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
230 def test_erp_key_lifetime_in_memory(dev, apdev, params):
231 """ERP and key lifetime in memory"""
232 check_erp_capa(dev[0])
233 p = int_eap_server_params()
234 p['erp_send_reauth_start'] = '1'
235 p['erp_domain'] = 'example.com'
236 p['eap_server_erp'] = '1'
237 p['disable_pmksa_caching'] = '1'
238 hapd = hostapd.add_ap(apdev[0]['ifname'], p)
239 password = "63d2d21ac3c09ed567ee004a34490f1d16e7fa5835edf17ddba70a63f1a90a25"
241 pid = find_wpas_process(dev[0])
243 dev[0].request("ERP_FLUSH")
244 dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
245 identity="pap-secret@example.com", password=password,
246 ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
247 erp="1", scan_freq="2412")
250 buf = read_process_memory(pid, password)
252 dev[0].request("DISCONNECT")
253 dev[0].wait_disconnected(timeout=15)
263 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
264 for l in f.readlines():
265 if "EAP-TTLS: Derived key - hexdump" in l:
266 val = l.strip().split(':')[3].replace(' ', '')
267 msk = binascii.unhexlify(val)
268 if "EAP-TTLS: Derived EMSK - hexdump" in l:
269 val = l.strip().split(':')[3].replace(' ', '')
270 emsk = binascii.unhexlify(val)
271 if "EAP: ERP rRK - hexdump" in l:
272 val = l.strip().split(':')[3].replace(' ', '')
273 rRK = binascii.unhexlify(val)
274 if "EAP: ERP rIK - hexdump" in l:
275 val = l.strip().split(':')[3].replace(' ', '')
276 rIK = binascii.unhexlify(val)
277 if "WPA: PMK - hexdump" in l:
278 val = l.strip().split(':')[3].replace(' ', '')
279 pmk = binascii.unhexlify(val)
280 if "WPA: PTK - hexdump" in l:
281 val = l.strip().split(':')[3].replace(' ', '')
282 ptk = binascii.unhexlify(val)
283 if "WPA: Group Key - hexdump" in l:
284 val = l.strip().split(':')[3].replace(' ', '')
285 gtk = binascii.unhexlify(val)
286 if not msk or not emsk or not rIK or not rRK or not pmk or not ptk or not gtk:
287 raise Exception("Could not find keys from debug log")
289 raise Exception("Unexpected GTK length")
295 fname = os.path.join(params['logdir'],
296 'erp_key_lifetime_in_memory.memctx-')
298 logger.info("Checking keys in memory while associated")
299 get_key_locations(buf, password, "Password")
300 get_key_locations(buf, pmk, "PMK")
301 get_key_locations(buf, msk, "MSK")
302 get_key_locations(buf, emsk, "EMSK")
303 get_key_locations(buf, rRK, "rRK")
304 get_key_locations(buf, rIK, "rIK")
305 if password not in buf:
306 raise HwsimSkip("Password not found while associated")
308 raise HwsimSkip("PMK not found while associated")
310 raise Exception("KCK not found while associated")
312 raise Exception("KEK not found while associated")
314 raise Exception("TK found from memory")
316 raise Exception("GTK found from memory")
318 logger.info("Checking keys in memory after disassociation")
319 buf = read_process_memory(pid, password)
321 # Note: Password is still present in network configuration
322 # Note: PMK is in EAP fast re-auth data
324 get_key_locations(buf, password, "Password")
325 get_key_locations(buf, pmk, "PMK")
326 get_key_locations(buf, msk, "MSK")
327 get_key_locations(buf, emsk, "EMSK")
328 get_key_locations(buf, rRK, "rRK")
329 get_key_locations(buf, rIK, "rIK")
330 verify_not_present(buf, kck, fname, "KCK")
331 verify_not_present(buf, kek, fname, "KEK")
332 verify_not_present(buf, tk, fname, "TK")
333 verify_not_present(buf, gtk, fname, "GTK")
335 dev[0].request("RECONNECT")
336 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
338 raise Exception("EAP success timed out")
339 if "EAP re-authentication completed successfully" not in ev:
340 raise Exception("Did not use ERP")
341 dev[0].wait_connected(timeout=15, error="Reconnection timed out")
343 dev[0].request("DISCONNECT")
344 dev[0].wait_disconnected(timeout=15)
350 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
351 for l in f.readlines():
352 if "WPA: PMK - hexdump" in l:
353 val = l.strip().split(':')[3].replace(' ', '')
354 pmk = binascii.unhexlify(val)
355 if "WPA: PTK - hexdump" in l:
356 val = l.strip().split(':')[3].replace(' ', '')
357 ptk = binascii.unhexlify(val)
358 if "WPA: GTK in EAPOL-Key - hexdump" in l:
359 val = l.strip().split(':')[3].replace(' ', '')
360 gtk = binascii.unhexlify(val)
361 if not pmk or not ptk or not gtk:
362 raise Exception("Could not find keys from debug log")
368 logger.info("Checking keys in memory after ERP and disassociation")
369 buf = read_process_memory(pid, password)
371 # Note: Password is still present in network configuration
373 get_key_locations(buf, password, "Password")
374 get_key_locations(buf, pmk, "PMK")
375 get_key_locations(buf, msk, "MSK")
376 get_key_locations(buf, emsk, "EMSK")
377 get_key_locations(buf, rRK, "rRK")
378 get_key_locations(buf, rIK, "rIK")
379 verify_not_present(buf, kck, fname, "KCK")
380 verify_not_present(buf, kek, fname, "KEK")
381 verify_not_present(buf, tk, fname, "TK")
382 verify_not_present(buf, gtk, fname, "GTK")
384 dev[0].request("REMOVE_NETWORK all")
386 logger.info("Checking keys in memory after network profile removal")
387 buf = read_process_memory(pid, password)
389 # Note: rRK and rIK are still in memory
391 get_key_locations(buf, password, "Password")
392 get_key_locations(buf, pmk, "PMK")
393 get_key_locations(buf, msk, "MSK")
394 get_key_locations(buf, emsk, "EMSK")
395 get_key_locations(buf, rRK, "rRK")
396 get_key_locations(buf, rIK, "rIK")
397 verify_not_present(buf, password, fname, "password")
398 verify_not_present(buf, pmk, fname, "PMK")
399 verify_not_present(buf, kck, fname, "KCK")
400 verify_not_present(buf, kek, fname, "KEK")
401 verify_not_present(buf, tk, fname, "TK")
402 verify_not_present(buf, gtk, fname, "GTK")
403 verify_not_present(buf, msk, fname, "MSK")
404 verify_not_present(buf, emsk, fname, "EMSK")
406 dev[0].request("ERP_FLUSH")
407 logger.info("Checking keys in memory after ERP_FLUSH")
408 buf = read_process_memory(pid, password)
409 get_key_locations(buf, rRK, "rRK")
410 get_key_locations(buf, rIK, "rIK")
411 verify_not_present(buf, rRK, fname, "rRK")
412 verify_not_present(buf, rIK, fname, "rIK")