]>
git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_sae.py
2 # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
12 logger
= logging
.getLogger()
16 from utils
import HwsimSkip
17 from test_ap_psk
import find_wpas_process
, read_process_memory
, verify_not_present
, get_key_locations
19 def test_sae(dev
, apdev
):
20 """SAE with default group"""
21 if "SAE" not in dev
[0].get_capability("auth_alg"):
22 raise HwsimSkip("SAE not supported")
23 params
= hostapd
.wpa2_params(ssid
="test-sae",
24 passphrase
="12345678")
25 params
['wpa_key_mgmt'] = 'SAE'
26 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
27 key_mgmt
= hapd
.get_config()['key_mgmt']
28 if key_mgmt
.split(' ')[0] != "SAE":
29 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt
)
31 dev
[0].request("SET sae_groups ")
32 id = dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
34 if dev
[0].get_status_field('sae_group') != '19':
35 raise Exception("Expected default SAE group not used")
36 bss
= dev
[0].get_bss(apdev
[0]['bssid'])
37 if 'flags' not in bss
:
38 raise Exception("Could not get BSS flags from BSS table")
39 if "[WPA2-SAE-CCMP]" not in bss
['flags']:
40 raise Exception("Unexpected BSS flags: " + bss
['flags'])
42 def test_sae_pmksa_caching(dev
, apdev
):
43 """SAE and PMKSA caching"""
44 if "SAE" not in dev
[0].get_capability("auth_alg"):
45 raise HwsimSkip("SAE not supported")
46 params
= hostapd
.wpa2_params(ssid
="test-sae",
47 passphrase
="12345678")
48 params
['wpa_key_mgmt'] = 'SAE'
49 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
51 dev
[0].request("SET sae_groups ")
52 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
54 ev
= hapd
.wait_event([ "AP-STA-CONNECTED" ], timeout
=5)
56 raise Exception("No connection event received from hostapd")
57 dev
[0].request("DISCONNECT")
58 dev
[0].wait_disconnected()
59 dev
[0].request("RECONNECT")
60 dev
[0].wait_connected(timeout
=15, error
="Reconnect timed out")
61 if dev
[0].get_status_field('sae_group') is not None:
62 raise Exception("SAE group claimed to have been used")
64 def test_sae_pmksa_caching_disabled(dev
, apdev
):
65 """SAE and PMKSA caching disabled"""
66 if "SAE" not in dev
[0].get_capability("auth_alg"):
67 raise HwsimSkip("SAE not supported")
68 params
= hostapd
.wpa2_params(ssid
="test-sae",
69 passphrase
="12345678")
70 params
['wpa_key_mgmt'] = 'SAE'
71 params
['disable_pmksa_caching'] = '1'
72 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
74 dev
[0].request("SET sae_groups ")
75 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
77 ev
= hapd
.wait_event([ "AP-STA-CONNECTED" ], timeout
=5)
79 raise Exception("No connection event received from hostapd")
80 dev
[0].request("DISCONNECT")
81 dev
[0].wait_disconnected()
82 dev
[0].request("RECONNECT")
83 dev
[0].wait_connected(timeout
=15, error
="Reconnect timed out")
84 if dev
[0].get_status_field('sae_group') != '19':
85 raise Exception("Expected default SAE group not used")
87 def test_sae_groups(dev
, apdev
):
88 """SAE with all supported groups"""
89 if "SAE" not in dev
[0].get_capability("auth_alg"):
90 raise HwsimSkip("SAE not supported")
91 # This would be the full list of supported groups, but groups 14-16
92 # (2048-4096 bit MODP) are a bit too slow on some VMs and can result in
93 # hitting mac80211 authentication timeout, so skip them for now.
94 #sae_groups = [ 19, 25, 26, 20, 21, 2, 5, 14, 15, 16, 22, 23, 24 ]
95 sae_groups
= [ 19, 25, 26, 20, 21, 2, 5, 22, 23, 24 ]
96 groups
= [str(g
) for g
in sae_groups
]
97 params
= hostapd
.wpa2_params(ssid
="test-sae-groups",
98 passphrase
="12345678")
99 params
['wpa_key_mgmt'] = 'SAE'
100 params
['sae_groups'] = ' '.join(groups
)
101 hostapd
.add_ap(apdev
[0]['ifname'], params
)
104 logger
.info("Testing SAE group " + g
)
105 dev
[0].request("SET sae_groups " + g
)
106 id = dev
[0].connect("test-sae-groups", psk
="12345678", key_mgmt
="SAE",
108 if dev
[0].get_status_field('sae_group') != g
:
109 raise Exception("Expected SAE group not used")
110 dev
[0].remove_network(id)
112 def test_sae_group_nego(dev
, apdev
):
113 """SAE group negotiation"""
114 if "SAE" not in dev
[0].get_capability("auth_alg"):
115 raise HwsimSkip("SAE not supported")
116 params
= hostapd
.wpa2_params(ssid
="test-sae-group-nego",
117 passphrase
="12345678")
118 params
['wpa_key_mgmt'] = 'SAE'
119 params
['sae_groups'] = '19'
120 hostapd
.add_ap(apdev
[0]['ifname'], params
)
122 dev
[0].request("SET sae_groups 25 26 20 19")
123 dev
[0].connect("test-sae-group-nego", psk
="12345678", key_mgmt
="SAE",
125 if dev
[0].get_status_field('sae_group') != '19':
126 raise Exception("Expected SAE group not used")
128 def test_sae_anti_clogging(dev
, apdev
):
129 """SAE anti clogging"""
130 if "SAE" not in dev
[0].get_capability("auth_alg"):
131 raise HwsimSkip("SAE not supported")
132 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
133 params
['wpa_key_mgmt'] = 'SAE'
134 params
['sae_anti_clogging_threshold'] = '1'
135 hostapd
.add_ap(apdev
[0]['ifname'], params
)
137 dev
[0].request("SET sae_groups ")
138 dev
[1].request("SET sae_groups ")
140 for i
in range(0, 2):
141 dev
[i
].scan(freq
="2412")
142 id[i
] = dev
[i
].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
143 scan_freq
="2412", only_add_network
=True)
144 for i
in range(0, 2):
145 dev
[i
].select_network(id[i
])
146 for i
in range(0, 2):
147 dev
[i
].wait_connected(timeout
=10)
149 def test_sae_forced_anti_clogging(dev
, apdev
):
150 """SAE anti clogging (forced)"""
151 if "SAE" not in dev
[0].get_capability("auth_alg"):
152 raise HwsimSkip("SAE not supported")
153 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
154 params
['wpa_key_mgmt'] = 'SAE WPA-PSK'
155 params
['sae_anti_clogging_threshold'] = '0'
156 hostapd
.add_ap(apdev
[0]['ifname'], params
)
157 dev
[2].connect("test-sae", psk
="12345678", scan_freq
="2412")
158 for i
in range(0, 2):
159 dev
[i
].request("SET sae_groups ")
160 dev
[i
].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
163 def test_sae_mixed(dev
, apdev
):
164 """Mixed SAE and non-SAE network"""
165 if "SAE" not in dev
[0].get_capability("auth_alg"):
166 raise HwsimSkip("SAE not supported")
167 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
168 params
['wpa_key_mgmt'] = 'SAE WPA-PSK'
169 params
['sae_anti_clogging_threshold'] = '0'
170 hostapd
.add_ap(apdev
[0]['ifname'], params
)
172 dev
[2].connect("test-sae", psk
="12345678", scan_freq
="2412")
173 for i
in range(0, 2):
174 dev
[i
].request("SET sae_groups ")
175 dev
[i
].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
178 def test_sae_missing_password(dev
, apdev
):
179 """SAE and missing password"""
180 if "SAE" not in dev
[0].get_capability("auth_alg"):
181 raise HwsimSkip("SAE not supported")
182 params
= hostapd
.wpa2_params(ssid
="test-sae",
183 passphrase
="12345678")
184 params
['wpa_key_mgmt'] = 'SAE'
185 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
187 dev
[0].request("SET sae_groups ")
188 id = dev
[0].connect("test-sae",
189 raw_psk
="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858",
190 key_mgmt
="SAE", scan_freq
="2412", wait_connect
=False)
191 ev
= dev
[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout
=10)
193 raise Exception("Invalid network not temporarily disabled")
196 def test_sae_key_lifetime_in_memory(dev
, apdev
, params
):
197 """SAE and key lifetime in memory"""
198 if "SAE" not in dev
[0].get_capability("auth_alg"):
199 raise HwsimSkip("SAE not supported")
200 password
= "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
201 p
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
=password
)
202 p
['wpa_key_mgmt'] = 'SAE'
203 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], p
)
205 pid
= find_wpas_process(dev
[0])
207 dev
[0].request("SET sae_groups ")
208 id = dev
[0].connect("test-sae", psk
=password
, key_mgmt
="SAE",
212 buf
= read_process_memory(pid
, password
)
214 dev
[0].request("DISCONNECT")
215 dev
[0].wait_disconnected()
224 with
open(os
.path
.join(params
['logdir'], 'log0'), 'r') as f
:
225 for l
in f
.readlines():
226 if "SAE: k - hexdump" in l
:
227 val
= l
.strip().split(':')[3].replace(' ', '')
228 sae_k
= binascii
.unhexlify(val
)
229 if "SAE: keyseed - hexdump" in l
:
230 val
= l
.strip().split(':')[3].replace(' ', '')
231 sae_keyseed
= binascii
.unhexlify(val
)
232 if "SAE: KCK - hexdump" in l
:
233 val
= l
.strip().split(':')[3].replace(' ', '')
234 sae_kck
= binascii
.unhexlify(val
)
235 if "SAE: PMK - hexdump" in l
:
236 val
= l
.strip().split(':')[3].replace(' ', '')
237 pmk
= binascii
.unhexlify(val
)
238 if "WPA: PTK - hexdump" in l
:
239 val
= l
.strip().split(':')[3].replace(' ', '')
240 ptk
= binascii
.unhexlify(val
)
241 if "WPA: Group Key - hexdump" in l
:
242 val
= l
.strip().split(':')[3].replace(' ', '')
243 gtk
= binascii
.unhexlify(val
)
244 if not sae_k
or not sae_keyseed
or not sae_kck
or not pmk
or not ptk
or not gtk
:
245 raise Exception("Could not find keys from debug log")
247 raise Exception("Unexpected GTK length")
253 fname
= os
.path
.join(params
['logdir'],
254 'sae_key_lifetime_in_memory.memctx-')
256 logger
.info("Checking keys in memory while associated")
257 get_key_locations(buf
, password
, "Password")
258 get_key_locations(buf
, pmk
, "PMK")
259 if password
not in buf
:
260 raise HwsimSkip("Password not found while associated")
262 raise HwsimSkip("PMK not found while associated")
264 raise Exception("KCK not found while associated")
266 raise Exception("KEK not found while associated")
268 raise Exception("TK found from memory")
270 raise Exception("GTK found from memory")
271 verify_not_present(buf
, sae_k
, fname
, "SAE(k)")
272 verify_not_present(buf
, sae_keyseed
, fname
, "SAE(keyseed)")
273 verify_not_present(buf
, sae_kck
, fname
, "SAE(KCK)")
275 logger
.info("Checking keys in memory after disassociation")
276 buf
= read_process_memory(pid
, password
)
278 # Note: Password is still present in network configuration
279 # Note: PMK is in PMKSA cache
281 get_key_locations(buf
, password
, "Password")
282 get_key_locations(buf
, pmk
, "PMK")
283 verify_not_present(buf
, kck
, fname
, "KCK")
284 verify_not_present(buf
, kek
, fname
, "KEK")
285 verify_not_present(buf
, tk
, fname
, "TK")
286 verify_not_present(buf
, gtk
, fname
, "GTK")
287 verify_not_present(buf
, sae_k
, fname
, "SAE(k)")
288 verify_not_present(buf
, sae_keyseed
, fname
, "SAE(keyseed)")
289 verify_not_present(buf
, sae_kck
, fname
, "SAE(KCK)")
291 dev
[0].request("PMKSA_FLUSH")
292 logger
.info("Checking keys in memory after PMKSA cache flush")
293 buf
= read_process_memory(pid
, password
)
294 get_key_locations(buf
, password
, "Password")
295 get_key_locations(buf
, pmk
, "PMK")
296 verify_not_present(buf
, pmk
, fname
, "PMK")
298 dev
[0].request("REMOVE_NETWORK all")
300 logger
.info("Checking keys in memory after network profile removal")
301 buf
= read_process_memory(pid
, password
)
303 get_key_locations(buf
, password
, "Password")
304 get_key_locations(buf
, pmk
, "PMK")
305 verify_not_present(buf
, password
, fname
, "password")
306 verify_not_present(buf
, pmk
, fname
, "PMK")
307 verify_not_present(buf
, kck
, fname
, "KCK")
308 verify_not_present(buf
, kek
, fname
, "KEK")
309 verify_not_present(buf
, tk
, fname
, "TK")
310 verify_not_present(buf
, gtk
, fname
, "GTK")
311 verify_not_present(buf
, sae_k
, fname
, "SAE(k)")
312 verify_not_present(buf
, sae_keyseed
, fname
, "SAE(keyseed)")
313 verify_not_present(buf
, sae_kck
, fname
, "SAE(KCK)")