]>
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 params
= hostapd
.wpa2_params(ssid
="test-sae",
22 passphrase
="12345678")
23 params
['wpa_key_mgmt'] = 'SAE'
24 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
25 key_mgmt
= hapd
.get_config()['key_mgmt']
26 if key_mgmt
.split(' ')[0] != "SAE":
27 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt
)
29 dev
[0].request("SET sae_groups ")
30 id = dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
32 if dev
[0].get_status_field('sae_group') != '19':
33 raise Exception("Expected default SAE group not used")
34 bss
= dev
[0].get_bss(apdev
[0]['bssid'])
35 if 'flags' not in bss
:
36 raise Exception("Could not get BSS flags from BSS table")
37 if "[WPA2-SAE-CCMP]" not in bss
['flags']:
38 raise Exception("Unexpected BSS flags: " + bss
['flags'])
40 def test_sae_pmksa_caching(dev
, apdev
):
41 """SAE and PMKSA caching"""
42 params
= hostapd
.wpa2_params(ssid
="test-sae",
43 passphrase
="12345678")
44 params
['wpa_key_mgmt'] = 'SAE'
45 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
47 dev
[0].request("SET sae_groups ")
48 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
50 dev
[0].request("DISCONNECT")
51 dev
[0].request("RECONNECT")
52 dev
[0].wait_connected(timeout
=15, error
="Reconnect timed out")
53 if dev
[0].get_status_field('sae_group') is not None:
54 raise Exception("SAE group claimed to have been used")
56 def test_sae_pmksa_caching_disabled(dev
, apdev
):
57 """SAE and PMKSA caching disabled"""
58 params
= hostapd
.wpa2_params(ssid
="test-sae",
59 passphrase
="12345678")
60 params
['wpa_key_mgmt'] = 'SAE'
61 params
['disable_pmksa_caching'] = '1'
62 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
64 dev
[0].request("SET sae_groups ")
65 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
67 dev
[0].request("DISCONNECT")
68 dev
[0].request("RECONNECT")
69 dev
[0].wait_connected(timeout
=15, error
="Reconnect timed out")
70 if dev
[0].get_status_field('sae_group') != '19':
71 raise Exception("Expected default SAE group not used")
73 def test_sae_groups(dev
, apdev
):
74 """SAE with all supported groups"""
75 # This would be the full list of supported groups, but groups 14-16
76 # (2048-4096 bit MODP) are a bit too slow on some VMs and can result in
77 # hitting mac80211 authentication timeout, so skip them for now.
78 #sae_groups = [ 19, 25, 26, 20, 21, 2, 5, 14, 15, 16, 22, 23, 24 ]
79 sae_groups
= [ 19, 25, 26, 20, 21, 2, 5, 22, 23, 24 ]
80 groups
= [str(g
) for g
in sae_groups
]
81 params
= hostapd
.wpa2_params(ssid
="test-sae-groups",
82 passphrase
="12345678")
83 params
['wpa_key_mgmt'] = 'SAE'
84 params
['sae_groups'] = ' '.join(groups
)
85 hostapd
.add_ap(apdev
[0]['ifname'], params
)
88 logger
.info("Testing SAE group " + g
)
89 dev
[0].request("SET sae_groups " + g
)
90 id = dev
[0].connect("test-sae-groups", psk
="12345678", key_mgmt
="SAE",
92 if dev
[0].get_status_field('sae_group') != g
:
93 raise Exception("Expected SAE group not used")
94 dev
[0].remove_network(id)
96 def test_sae_group_nego(dev
, apdev
):
97 """SAE group negotiation"""
98 params
= hostapd
.wpa2_params(ssid
="test-sae-group-nego",
99 passphrase
="12345678")
100 params
['wpa_key_mgmt'] = 'SAE'
101 params
['sae_groups'] = '19'
102 hostapd
.add_ap(apdev
[0]['ifname'], params
)
104 dev
[0].request("SET sae_groups 25 26 20 19")
105 dev
[0].connect("test-sae-group-nego", psk
="12345678", key_mgmt
="SAE",
107 if dev
[0].get_status_field('sae_group') != '19':
108 raise Exception("Expected SAE group not used")
110 def test_sae_anti_clogging(dev
, apdev
):
111 """SAE anti clogging"""
112 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
113 params
['wpa_key_mgmt'] = 'SAE'
114 params
['sae_anti_clogging_threshold'] = '1'
115 hostapd
.add_ap(apdev
[0]['ifname'], params
)
117 dev
[0].request("SET sae_groups ")
118 dev
[1].request("SET sae_groups ")
120 for i
in range(0, 2):
121 dev
[i
].scan(freq
="2412")
122 id[i
] = dev
[i
].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
123 scan_freq
="2412", only_add_network
=True)
124 for i
in range(0, 2):
125 dev
[i
].select_network(id[i
])
126 for i
in range(0, 2):
127 dev
[i
].wait_connected(timeout
=10)
129 def test_sae_forced_anti_clogging(dev
, apdev
):
130 """SAE anti clogging (forced)"""
131 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
132 params
['wpa_key_mgmt'] = 'SAE WPA-PSK'
133 params
['sae_anti_clogging_threshold'] = '0'
134 hostapd
.add_ap(apdev
[0]['ifname'], params
)
135 dev
[2].connect("test-sae", psk
="12345678", scan_freq
="2412")
136 for i
in range(0, 2):
137 dev
[i
].request("SET sae_groups ")
138 dev
[i
].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
141 def test_sae_mixed(dev
, apdev
):
142 """Mixed SAE and non-SAE network"""
143 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
144 params
['wpa_key_mgmt'] = 'SAE WPA-PSK'
145 params
['sae_anti_clogging_threshold'] = '0'
146 hostapd
.add_ap(apdev
[0]['ifname'], params
)
148 dev
[2].connect("test-sae", psk
="12345678", scan_freq
="2412")
149 for i
in range(0, 2):
150 dev
[i
].request("SET sae_groups ")
151 dev
[i
].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
154 def test_sae_missing_password(dev
, apdev
):
155 """SAE and missing password"""
156 params
= hostapd
.wpa2_params(ssid
="test-sae",
157 passphrase
="12345678")
158 params
['wpa_key_mgmt'] = 'SAE'
159 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], params
)
161 dev
[0].request("SET sae_groups ")
162 id = dev
[0].connect("test-sae",
163 raw_psk
="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858",
164 key_mgmt
="SAE", scan_freq
="2412", wait_connect
=False)
165 ev
= dev
[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout
=10)
167 raise Exception("Invalid network not temporarily disabled")
170 def test_sae_key_lifetime_in_memory(dev
, apdev
, params
):
171 """SAE and key lifetime in memory"""
172 password
= "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
173 p
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
=password
)
174 p
['wpa_key_mgmt'] = 'SAE'
175 hapd
= hostapd
.add_ap(apdev
[0]['ifname'], p
)
177 pid
= find_wpas_process(dev
[0])
179 dev
[0].request("SET sae_groups ")
180 id = dev
[0].connect("test-sae", psk
=password
, key_mgmt
="SAE",
184 buf
= read_process_memory(pid
, password
)
186 dev
[0].request("DISCONNECT")
187 dev
[0].wait_disconnected()
196 with
open(os
.path
.join(params
['logdir'], 'log0'), 'r') as f
:
197 for l
in f
.readlines():
198 if "SAE: k - hexdump" in l
:
199 val
= l
.strip().split(':')[3].replace(' ', '')
200 sae_k
= binascii
.unhexlify(val
)
201 if "SAE: keyseed - hexdump" in l
:
202 val
= l
.strip().split(':')[3].replace(' ', '')
203 sae_keyseed
= binascii
.unhexlify(val
)
204 if "SAE: KCK - hexdump" in l
:
205 val
= l
.strip().split(':')[3].replace(' ', '')
206 sae_kck
= binascii
.unhexlify(val
)
207 if "SAE: PMK - hexdump" in l
:
208 val
= l
.strip().split(':')[3].replace(' ', '')
209 pmk
= binascii
.unhexlify(val
)
210 if "WPA: PTK - hexdump" in l
:
211 val
= l
.strip().split(':')[3].replace(' ', '')
212 ptk
= binascii
.unhexlify(val
)
213 if "WPA: Group Key - hexdump" in l
:
214 val
= l
.strip().split(':')[3].replace(' ', '')
215 gtk
= binascii
.unhexlify(val
)
216 if not sae_k
or not sae_keyseed
or not sae_kck
or not pmk
or not ptk
or not gtk
:
217 raise Exception("Could not find keys from debug log")
219 raise Exception("Unexpected GTK length")
225 fname
= os
.path
.join(params
['logdir'],
226 'sae_key_lifetime_in_memory.memctx-')
228 logger
.info("Checking keys in memory while associated")
229 get_key_locations(buf
, password
, "Password")
230 get_key_locations(buf
, pmk
, "PMK")
231 if password
not in buf
:
232 raise HwsimSkip("Password not found while associated")
234 raise HwsimSkip("PMK not found while associated")
236 raise Exception("KCK not found while associated")
238 raise Exception("KEK not found while associated")
240 raise Exception("TK found from memory")
242 raise Exception("GTK found from memory")
243 verify_not_present(buf
, sae_k
, fname
, "SAE(k)")
244 verify_not_present(buf
, sae_keyseed
, fname
, "SAE(keyseed)")
245 verify_not_present(buf
, sae_kck
, fname
, "SAE(KCK)")
247 logger
.info("Checking keys in memory after disassociation")
248 buf
= read_process_memory(pid
, password
)
250 # Note: Password is still present in network configuration
251 # Note: PMK is in PMKSA cache
253 get_key_locations(buf
, password
, "Password")
254 get_key_locations(buf
, pmk
, "PMK")
255 verify_not_present(buf
, kck
, fname
, "KCK")
256 verify_not_present(buf
, kek
, fname
, "KEK")
257 verify_not_present(buf
, tk
, fname
, "TK")
258 verify_not_present(buf
, gtk
, fname
, "GTK")
259 verify_not_present(buf
, sae_k
, fname
, "SAE(k)")
260 verify_not_present(buf
, sae_keyseed
, fname
, "SAE(keyseed)")
261 verify_not_present(buf
, sae_kck
, fname
, "SAE(KCK)")
263 dev
[0].request("PMKSA_FLUSH")
264 logger
.info("Checking keys in memory after PMKSA cache flush")
265 buf
= read_process_memory(pid
, password
)
266 get_key_locations(buf
, password
, "Password")
267 get_key_locations(buf
, pmk
, "PMK")
268 verify_not_present(buf
, pmk
, fname
, "PMK")
270 dev
[0].request("REMOVE_NETWORK all")
272 logger
.info("Checking keys in memory after network profile removal")
273 buf
= read_process_memory(pid
, password
)
275 get_key_locations(buf
, password
, "Password")
276 get_key_locations(buf
, pmk
, "PMK")
277 verify_not_present(buf
, password
, fname
, "password")
278 verify_not_present(buf
, pmk
, fname
, "PMK")
279 verify_not_present(buf
, kck
, fname
, "KCK")
280 verify_not_present(buf
, kek
, fname
, "KEK")
281 verify_not_present(buf
, tk
, fname
, "TK")
282 verify_not_present(buf
, gtk
, fname
, "GTK")
283 verify_not_present(buf
, sae_k
, fname
, "SAE(k)")
284 verify_not_present(buf
, sae_keyseed
, fname
, "SAE(keyseed)")
285 verify_not_present(buf
, sae_kck
, fname
, "SAE(KCK)")