test_sae.py 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171
  1. # Test cases for SAE
  2. # Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi>
  3. #
  4. # This software may be distributed under the terms of the BSD license.
  5. # See README for more details.
  6. from remotehost import remote_compatible
  7. import binascii
  8. import os
  9. import time
  10. import logging
  11. logger = logging.getLogger()
  12. import hwsim_utils
  13. import hostapd
  14. from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
  15. from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
  16. @remote_compatible
  17. def test_sae(dev, apdev):
  18. """SAE with default group"""
  19. if "SAE" not in dev[0].get_capability("auth_alg"):
  20. raise HwsimSkip("SAE not supported")
  21. params = hostapd.wpa2_params(ssid="test-sae",
  22. passphrase="12345678")
  23. params['wpa_key_mgmt'] = 'SAE'
  24. hapd = hostapd.add_ap(apdev[0], 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)
  28. dev[0].request("SET sae_groups ")
  29. id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  30. scan_freq="2412")
  31. if dev[0].get_status_field('sae_group') != '19':
  32. raise Exception("Expected default SAE group not used")
  33. bss = dev[0].get_bss(apdev[0]['bssid'])
  34. if 'flags' not in bss:
  35. raise Exception("Could not get BSS flags from BSS table")
  36. if "[WPA2-SAE-CCMP]" not in bss['flags']:
  37. raise Exception("Unexpected BSS flags: " + bss['flags'])
  38. res = hapd.request("STA-FIRST")
  39. if "sae_group=19" not in res.splitlines():
  40. raise Exception("hostapd STA output did not specify SAE group")
  41. @remote_compatible
  42. def test_sae_password_ecc(dev, apdev):
  43. """SAE with number of different passwords (ECC)"""
  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], params)
  50. dev[0].request("SET sae_groups 19")
  51. for i in range(10):
  52. password = "12345678-" + str(i)
  53. hapd.set("wpa_passphrase", password)
  54. dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
  55. scan_freq="2412")
  56. dev[0].request("REMOVE_NETWORK all")
  57. dev[0].wait_disconnected()
  58. @remote_compatible
  59. def test_sae_password_ffc(dev, apdev):
  60. """SAE with number of different passwords (FFC)"""
  61. if "SAE" not in dev[0].get_capability("auth_alg"):
  62. raise HwsimSkip("SAE not supported")
  63. params = hostapd.wpa2_params(ssid="test-sae",
  64. passphrase="12345678")
  65. params['wpa_key_mgmt'] = 'SAE'
  66. params['sae_groups'] = '22'
  67. hapd = hostapd.add_ap(apdev[0], params)
  68. dev[0].request("SET sae_groups 22")
  69. for i in range(10):
  70. password = "12345678-" + str(i)
  71. hapd.set("wpa_passphrase", password)
  72. dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
  73. scan_freq="2412")
  74. dev[0].request("REMOVE_NETWORK all")
  75. dev[0].wait_disconnected()
  76. @remote_compatible
  77. def test_sae_pmksa_caching(dev, apdev):
  78. """SAE and PMKSA caching"""
  79. if "SAE" not in dev[0].get_capability("auth_alg"):
  80. raise HwsimSkip("SAE not supported")
  81. params = hostapd.wpa2_params(ssid="test-sae",
  82. passphrase="12345678")
  83. params['wpa_key_mgmt'] = 'SAE'
  84. hapd = hostapd.add_ap(apdev[0], params)
  85. dev[0].request("SET sae_groups ")
  86. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  87. scan_freq="2412")
  88. ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
  89. if ev is None:
  90. raise Exception("No connection event received from hostapd")
  91. dev[0].request("DISCONNECT")
  92. dev[0].wait_disconnected()
  93. dev[0].request("RECONNECT")
  94. dev[0].wait_connected(timeout=15, error="Reconnect timed out")
  95. if dev[0].get_status_field('sae_group') is not None:
  96. raise Exception("SAE group claimed to have been used")
  97. @remote_compatible
  98. def test_sae_pmksa_caching_disabled(dev, apdev):
  99. """SAE and PMKSA caching disabled"""
  100. if "SAE" not in dev[0].get_capability("auth_alg"):
  101. raise HwsimSkip("SAE not supported")
  102. params = hostapd.wpa2_params(ssid="test-sae",
  103. passphrase="12345678")
  104. params['wpa_key_mgmt'] = 'SAE'
  105. params['disable_pmksa_caching'] = '1'
  106. hapd = hostapd.add_ap(apdev[0], params)
  107. dev[0].request("SET sae_groups ")
  108. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  109. scan_freq="2412")
  110. ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
  111. if ev is None:
  112. raise Exception("No connection event received from hostapd")
  113. dev[0].request("DISCONNECT")
  114. dev[0].wait_disconnected()
  115. dev[0].request("RECONNECT")
  116. dev[0].wait_connected(timeout=15, error="Reconnect timed out")
  117. if dev[0].get_status_field('sae_group') != '19':
  118. raise Exception("Expected default SAE group not used")
  119. def test_sae_groups(dev, apdev):
  120. """SAE with all supported groups"""
  121. if "SAE" not in dev[0].get_capability("auth_alg"):
  122. raise HwsimSkip("SAE not supported")
  123. # This is the full list of supported groups, but groups 14-16 (2048-4096 bit
  124. # MODP) and group 21 (521-bit random ECP group) are a bit too slow on some
  125. # VMs and can result in hitting the mac80211 authentication timeout, so
  126. # allow them to fail and just report such failures in the debug log.
  127. sae_groups = [ 19, 25, 26, 20, 21, 2, 5, 14, 15, 16, 22, 23, 24 ]
  128. tls = dev[0].request("GET tls_library")
  129. if tls.startswith("OpenSSL") and "build=OpenSSL 1.0.2" in tls and "run=OpenSSL 1.0.2" in tls:
  130. logger.info("Add Brainpool EC groups since OpenSSL is new enough")
  131. sae_groups += [ 27, 28, 29, 30 ]
  132. heavy_groups = [ 14, 15, 16 ]
  133. groups = [str(g) for g in sae_groups]
  134. params = hostapd.wpa2_params(ssid="test-sae-groups",
  135. passphrase="12345678")
  136. params['wpa_key_mgmt'] = 'SAE'
  137. params['sae_groups'] = ' '.join(groups)
  138. hostapd.add_ap(apdev[0], params)
  139. for g in groups:
  140. logger.info("Testing SAE group " + g)
  141. dev[0].request("SET sae_groups " + g)
  142. id = dev[0].connect("test-sae-groups", psk="12345678", key_mgmt="SAE",
  143. scan_freq="2412", wait_connect=False)
  144. if int(g) in heavy_groups:
  145. ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
  146. if ev is None:
  147. logger.info("No connection with heavy SAE group %s did not connect - likely hitting timeout in mac80211" % g)
  148. dev[0].remove_network(id)
  149. time.sleep(0.1)
  150. dev[0].dump_monitor()
  151. continue
  152. logger.info("Connection with heavy SAE group " + g)
  153. else:
  154. ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
  155. if ev is None:
  156. if "BoringSSL" in tls and int(g) in [ 25 ]:
  157. logger.info("Ignore connection failure with group " + g + " with BoringSSL")
  158. dev[0].remove_network(id)
  159. dev[0].dump_monitor()
  160. continue
  161. raise Exception("Connection timed out with group " + g)
  162. if dev[0].get_status_field('sae_group') != g:
  163. raise Exception("Expected SAE group not used")
  164. dev[0].remove_network(id)
  165. dev[0].wait_disconnected()
  166. dev[0].dump_monitor()
  167. @remote_compatible
  168. def test_sae_group_nego(dev, apdev):
  169. """SAE group negotiation"""
  170. if "SAE" not in dev[0].get_capability("auth_alg"):
  171. raise HwsimSkip("SAE not supported")
  172. params = hostapd.wpa2_params(ssid="test-sae-group-nego",
  173. passphrase="12345678")
  174. params['wpa_key_mgmt'] = 'SAE'
  175. params['sae_groups'] = '19'
  176. hostapd.add_ap(apdev[0], params)
  177. dev[0].request("SET sae_groups 25 26 20 19")
  178. dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE",
  179. scan_freq="2412")
  180. if dev[0].get_status_field('sae_group') != '19':
  181. raise Exception("Expected SAE group not used")
  182. @remote_compatible
  183. def test_sae_anti_clogging(dev, apdev):
  184. """SAE anti clogging"""
  185. if "SAE" not in dev[0].get_capability("auth_alg"):
  186. raise HwsimSkip("SAE not supported")
  187. params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
  188. params['wpa_key_mgmt'] = 'SAE'
  189. params['sae_anti_clogging_threshold'] = '1'
  190. hostapd.add_ap(apdev[0], params)
  191. dev[0].request("SET sae_groups ")
  192. dev[1].request("SET sae_groups ")
  193. id = {}
  194. for i in range(0, 2):
  195. dev[i].scan(freq="2412")
  196. id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
  197. scan_freq="2412", only_add_network=True)
  198. for i in range(0, 2):
  199. dev[i].select_network(id[i])
  200. for i in range(0, 2):
  201. dev[i].wait_connected(timeout=10)
  202. def test_sae_forced_anti_clogging(dev, apdev):
  203. """SAE anti clogging (forced)"""
  204. if "SAE" not in dev[0].get_capability("auth_alg"):
  205. raise HwsimSkip("SAE not supported")
  206. params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
  207. params['wpa_key_mgmt'] = 'SAE WPA-PSK'
  208. params['sae_anti_clogging_threshold'] = '0'
  209. hostapd.add_ap(apdev[0], params)
  210. dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
  211. for i in range(0, 2):
  212. dev[i].request("SET sae_groups ")
  213. dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
  214. scan_freq="2412")
  215. def test_sae_mixed(dev, apdev):
  216. """Mixed SAE and non-SAE network"""
  217. if "SAE" not in dev[0].get_capability("auth_alg"):
  218. raise HwsimSkip("SAE not supported")
  219. params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
  220. params['wpa_key_mgmt'] = 'SAE WPA-PSK'
  221. params['sae_anti_clogging_threshold'] = '0'
  222. hostapd.add_ap(apdev[0], params)
  223. dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
  224. for i in range(0, 2):
  225. dev[i].request("SET sae_groups ")
  226. dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
  227. scan_freq="2412")
  228. @remote_compatible
  229. def test_sae_missing_password(dev, apdev):
  230. """SAE and missing password"""
  231. if "SAE" not in dev[0].get_capability("auth_alg"):
  232. raise HwsimSkip("SAE not supported")
  233. params = hostapd.wpa2_params(ssid="test-sae",
  234. passphrase="12345678")
  235. params['wpa_key_mgmt'] = 'SAE'
  236. hapd = hostapd.add_ap(apdev[0], params)
  237. dev[0].request("SET sae_groups ")
  238. id = dev[0].connect("test-sae",
  239. raw_psk="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858",
  240. key_mgmt="SAE", scan_freq="2412", wait_connect=False)
  241. ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10)
  242. if ev is None:
  243. raise Exception("Invalid network not temporarily disabled")
  244. def test_sae_key_lifetime_in_memory(dev, apdev, params):
  245. """SAE and key lifetime in memory"""
  246. if "SAE" not in dev[0].get_capability("auth_alg"):
  247. raise HwsimSkip("SAE not supported")
  248. password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
  249. p = hostapd.wpa2_params(ssid="test-sae", passphrase=password)
  250. p['wpa_key_mgmt'] = 'SAE'
  251. hapd = hostapd.add_ap(apdev[0], p)
  252. pid = find_wpas_process(dev[0])
  253. dev[0].request("SET sae_groups ")
  254. id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
  255. scan_freq="2412")
  256. # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
  257. # event has been delivered, so verify that wpa_supplicant has returned to
  258. # eloop before reading process memory.
  259. time.sleep(1)
  260. dev[0].ping()
  261. buf = read_process_memory(pid, password)
  262. dev[0].request("DISCONNECT")
  263. dev[0].wait_disconnected()
  264. dev[0].relog()
  265. sae_k = None
  266. sae_keyseed = None
  267. sae_kck = None
  268. pmk = None
  269. ptk = None
  270. gtk = None
  271. with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
  272. for l in f.readlines():
  273. if "SAE: k - hexdump" in l:
  274. val = l.strip().split(':')[3].replace(' ', '')
  275. sae_k = binascii.unhexlify(val)
  276. if "SAE: keyseed - hexdump" in l:
  277. val = l.strip().split(':')[3].replace(' ', '')
  278. sae_keyseed = binascii.unhexlify(val)
  279. if "SAE: KCK - hexdump" in l:
  280. val = l.strip().split(':')[3].replace(' ', '')
  281. sae_kck = binascii.unhexlify(val)
  282. if "SAE: PMK - hexdump" in l:
  283. val = l.strip().split(':')[3].replace(' ', '')
  284. pmk = binascii.unhexlify(val)
  285. if "WPA: PTK - hexdump" in l:
  286. val = l.strip().split(':')[3].replace(' ', '')
  287. ptk = binascii.unhexlify(val)
  288. if "WPA: Group Key - hexdump" in l:
  289. val = l.strip().split(':')[3].replace(' ', '')
  290. gtk = binascii.unhexlify(val)
  291. if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk:
  292. raise Exception("Could not find keys from debug log")
  293. if len(gtk) != 16:
  294. raise Exception("Unexpected GTK length")
  295. kck = ptk[0:16]
  296. kek = ptk[16:32]
  297. tk = ptk[32:48]
  298. fname = os.path.join(params['logdir'],
  299. 'sae_key_lifetime_in_memory.memctx-')
  300. logger.info("Checking keys in memory while associated")
  301. get_key_locations(buf, password, "Password")
  302. get_key_locations(buf, pmk, "PMK")
  303. if password not in buf:
  304. raise HwsimSkip("Password not found while associated")
  305. if pmk not in buf:
  306. raise HwsimSkip("PMK not found while associated")
  307. if kck not in buf:
  308. raise Exception("KCK not found while associated")
  309. if kek not in buf:
  310. raise Exception("KEK not found while associated")
  311. #if tk in buf:
  312. # raise Exception("TK found from memory")
  313. verify_not_present(buf, sae_k, fname, "SAE(k)")
  314. verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
  315. verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
  316. logger.info("Checking keys in memory after disassociation")
  317. buf = read_process_memory(pid, password)
  318. # Note: Password is still present in network configuration
  319. # Note: PMK is in PMKSA cache
  320. get_key_locations(buf, password, "Password")
  321. get_key_locations(buf, pmk, "PMK")
  322. verify_not_present(buf, kck, fname, "KCK")
  323. verify_not_present(buf, kek, fname, "KEK")
  324. verify_not_present(buf, tk, fname, "TK")
  325. if gtk in buf:
  326. get_key_locations(buf, gtk, "GTK")
  327. verify_not_present(buf, gtk, fname, "GTK")
  328. verify_not_present(buf, sae_k, fname, "SAE(k)")
  329. verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
  330. verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
  331. dev[0].request("PMKSA_FLUSH")
  332. logger.info("Checking keys in memory after PMKSA cache flush")
  333. buf = read_process_memory(pid, password)
  334. get_key_locations(buf, password, "Password")
  335. get_key_locations(buf, pmk, "PMK")
  336. verify_not_present(buf, pmk, fname, "PMK")
  337. dev[0].request("REMOVE_NETWORK all")
  338. logger.info("Checking keys in memory after network profile removal")
  339. buf = read_process_memory(pid, password)
  340. get_key_locations(buf, password, "Password")
  341. get_key_locations(buf, pmk, "PMK")
  342. verify_not_present(buf, password, fname, "password")
  343. verify_not_present(buf, pmk, fname, "PMK")
  344. verify_not_present(buf, kck, fname, "KCK")
  345. verify_not_present(buf, kek, fname, "KEK")
  346. verify_not_present(buf, tk, fname, "TK")
  347. verify_not_present(buf, gtk, fname, "GTK")
  348. verify_not_present(buf, sae_k, fname, "SAE(k)")
  349. verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
  350. verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
  351. @remote_compatible
  352. def test_sae_oom_wpas(dev, apdev):
  353. """SAE and OOM in wpa_supplicant"""
  354. if "SAE" not in dev[0].get_capability("auth_alg"):
  355. raise HwsimSkip("SAE not supported")
  356. params = hostapd.wpa2_params(ssid="test-sae",
  357. passphrase="12345678")
  358. params['wpa_key_mgmt'] = 'SAE'
  359. hapd = hostapd.add_ap(apdev[0], params)
  360. dev[0].request("SET sae_groups 25")
  361. tls = dev[0].request("GET tls_library")
  362. if "BoringSSL" in tls:
  363. dev[0].request("SET sae_groups 26")
  364. with alloc_fail(dev[0], 1, "sae_set_group"):
  365. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  366. scan_freq="2412")
  367. dev[0].request("REMOVE_NETWORK all")
  368. dev[0].request("SET sae_groups ")
  369. with alloc_fail(dev[0], 2, "sae_set_group"):
  370. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  371. scan_freq="2412")
  372. dev[0].request("REMOVE_NETWORK all")
  373. with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_commit"):
  374. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  375. scan_freq="2412")
  376. dev[0].request("REMOVE_NETWORK all")
  377. with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_confirm"):
  378. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  379. scan_freq="2412", wait_connect=False)
  380. wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
  381. dev[0].request("REMOVE_NETWORK all")
  382. with alloc_fail(dev[0], 1, "=sme_authenticate"):
  383. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  384. scan_freq="2412", wait_connect=False)
  385. wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
  386. dev[0].request("REMOVE_NETWORK all")
  387. with alloc_fail(dev[0], 1, "radio_add_work;sme_authenticate"):
  388. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  389. scan_freq="2412", wait_connect=False)
  390. wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
  391. dev[0].request("REMOVE_NETWORK all")
  392. @remote_compatible
  393. def test_sae_proto_ecc(dev, apdev):
  394. """SAE protocol testing (ECC)"""
  395. if "SAE" not in dev[0].get_capability("auth_alg"):
  396. raise HwsimSkip("SAE not supported")
  397. params = hostapd.wpa2_params(ssid="test-sae",
  398. passphrase="12345678")
  399. params['wpa_key_mgmt'] = 'SAE'
  400. hapd = hostapd.add_ap(apdev[0], params)
  401. bssid = apdev[0]['bssid']
  402. dev[0].request("SET sae_groups 19")
  403. tests = [ ("Confirm mismatch",
  404. "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
  405. "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"),
  406. ("Commit without even full cyclic group field",
  407. "13",
  408. None),
  409. ("Too short commit",
  410. "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02",
  411. None),
  412. ("Invalid commit scalar (0)",
  413. "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
  414. None),
  415. ("Invalid commit scalar (1)",
  416. "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
  417. None),
  418. ("Invalid commit scalar (> r)",
  419. "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
  420. None),
  421. ("Commit element not on curve",
  422. "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000",
  423. None),
  424. ("Invalid commit element (y coordinate > P)",
  425. "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
  426. None),
  427. ("Invalid commit element (x coordinate > P)",
  428. "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
  429. None),
  430. ("Different group in commit",
  431. "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
  432. None),
  433. ("Too short confirm",
  434. "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
  435. "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")]
  436. for (note, commit, confirm) in tests:
  437. logger.info(note)
  438. dev[0].scan_for_bss(bssid, freq=2412)
  439. hapd.set("ext_mgmt_frame_handling", "1")
  440. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  441. scan_freq="2412", wait_connect=False)
  442. logger.info("Commit")
  443. for i in range(0, 10):
  444. req = hapd.mgmt_rx()
  445. if req is None:
  446. raise Exception("MGMT RX wait timed out (commit)")
  447. if req['subtype'] == 11:
  448. break
  449. req = None
  450. if not req:
  451. raise Exception("Authentication frame (commit) not received")
  452. hapd.dump_monitor()
  453. resp = {}
  454. resp['fc'] = req['fc']
  455. resp['da'] = req['sa']
  456. resp['sa'] = req['da']
  457. resp['bssid'] = req['bssid']
  458. resp['payload'] = binascii.unhexlify("030001000000" + commit)
  459. hapd.mgmt_tx(resp)
  460. if confirm:
  461. logger.info("Confirm")
  462. for i in range(0, 10):
  463. req = hapd.mgmt_rx()
  464. if req is None:
  465. raise Exception("MGMT RX wait timed out (confirm)")
  466. if req['subtype'] == 11:
  467. break
  468. req = None
  469. if not req:
  470. raise Exception("Authentication frame (confirm) not received")
  471. hapd.dump_monitor()
  472. resp = {}
  473. resp['fc'] = req['fc']
  474. resp['da'] = req['sa']
  475. resp['sa'] = req['da']
  476. resp['bssid'] = req['bssid']
  477. resp['payload'] = binascii.unhexlify("030002000000" + confirm)
  478. hapd.mgmt_tx(resp)
  479. time.sleep(0.1)
  480. dev[0].request("REMOVE_NETWORK all")
  481. hapd.set("ext_mgmt_frame_handling", "0")
  482. hapd.dump_monitor()
  483. @remote_compatible
  484. def test_sae_proto_ffc(dev, apdev):
  485. """SAE protocol testing (FFC)"""
  486. if "SAE" not in dev[0].get_capability("auth_alg"):
  487. raise HwsimSkip("SAE not supported")
  488. params = hostapd.wpa2_params(ssid="test-sae",
  489. passphrase="12345678")
  490. params['wpa_key_mgmt'] = 'SAE'
  491. hapd = hostapd.add_ap(apdev[0], params)
  492. bssid = apdev[0]['bssid']
  493. dev[0].request("SET sae_groups 2")
  494. tests = [ ("Confirm mismatch",
  495. "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486",
  496. "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"),
  497. ("Too short commit",
  498. "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174",
  499. None),
  500. ("Invalid element (0) in commit",
  501. "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  502. None),
  503. ("Invalid element (1) in commit",
  504. "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
  505. None),
  506. ("Invalid element (> P) in commit",
  507. "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
  508. None) ]
  509. for (note, commit, confirm) in tests:
  510. logger.info(note)
  511. dev[0].scan_for_bss(bssid, freq=2412)
  512. hapd.set("ext_mgmt_frame_handling", "1")
  513. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  514. scan_freq="2412", wait_connect=False)
  515. logger.info("Commit")
  516. for i in range(0, 10):
  517. req = hapd.mgmt_rx()
  518. if req is None:
  519. raise Exception("MGMT RX wait timed out (commit)")
  520. if req['subtype'] == 11:
  521. break
  522. req = None
  523. if not req:
  524. raise Exception("Authentication frame (commit) not received")
  525. hapd.dump_monitor()
  526. resp = {}
  527. resp['fc'] = req['fc']
  528. resp['da'] = req['sa']
  529. resp['sa'] = req['da']
  530. resp['bssid'] = req['bssid']
  531. resp['payload'] = binascii.unhexlify("030001000000" + commit)
  532. hapd.mgmt_tx(resp)
  533. if confirm:
  534. logger.info("Confirm")
  535. for i in range(0, 10):
  536. req = hapd.mgmt_rx()
  537. if req is None:
  538. raise Exception("MGMT RX wait timed out (confirm)")
  539. if req['subtype'] == 11:
  540. break
  541. req = None
  542. if not req:
  543. raise Exception("Authentication frame (confirm) not received")
  544. hapd.dump_monitor()
  545. resp = {}
  546. resp['fc'] = req['fc']
  547. resp['da'] = req['sa']
  548. resp['sa'] = req['da']
  549. resp['bssid'] = req['bssid']
  550. resp['payload'] = binascii.unhexlify("030002000000" + confirm)
  551. hapd.mgmt_tx(resp)
  552. time.sleep(0.1)
  553. dev[0].request("REMOVE_NETWORK all")
  554. hapd.set("ext_mgmt_frame_handling", "0")
  555. hapd.dump_monitor()
  556. def test_sae_proto_confirm_replay(dev, apdev):
  557. """SAE protocol testing - Confirm replay"""
  558. if "SAE" not in dev[0].get_capability("auth_alg"):
  559. raise HwsimSkip("SAE not supported")
  560. params = hostapd.wpa2_params(ssid="test-sae",
  561. passphrase="12345678")
  562. params['wpa_key_mgmt'] = 'SAE'
  563. hapd = hostapd.add_ap(apdev[0], params)
  564. bssid = apdev[0]['bssid']
  565. dev[0].request("SET sae_groups 19")
  566. dev[0].scan_for_bss(bssid, freq=2412)
  567. hapd.set("ext_mgmt_frame_handling", "1")
  568. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  569. scan_freq="2412", wait_connect=False)
  570. logger.info("Commit")
  571. for i in range(0, 10):
  572. req = hapd.mgmt_rx()
  573. if req is None:
  574. raise Exception("MGMT RX wait timed out (commit)")
  575. if req['subtype'] == 11:
  576. break
  577. req = None
  578. if not req:
  579. raise Exception("Authentication frame (commit) not received")
  580. bssid = hapd.own_addr().replace(':', '')
  581. addr = dev[0].own_addr().replace(':', '')
  582. hdr = "b0003a01" + bssid + addr + bssid + "1000"
  583. hapd.dump_monitor()
  584. hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + req['frame'].encode('hex'))
  585. logger.info("Confirm")
  586. for i in range(0, 10):
  587. req = hapd.mgmt_rx()
  588. if req is None:
  589. raise Exception("MGMT RX wait timed out (confirm)")
  590. if req['subtype'] == 11:
  591. break
  592. req = None
  593. if not req:
  594. raise Exception("Authentication frame (confirm) not received")
  595. hapd.dump_monitor()
  596. hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + req['frame'].encode('hex'))
  597. logger.info("Replay Confirm")
  598. hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + req['frame'].encode('hex'))
  599. logger.info("Association Request")
  600. for i in range(0, 10):
  601. req = hapd.mgmt_rx()
  602. if req is None:
  603. raise Exception("MGMT RX wait timed out (AssocReq)")
  604. if req['subtype'] == 0:
  605. break
  606. req = None
  607. if not req:
  608. raise Exception("Association Request frame not received")
  609. hapd.dump_monitor()
  610. hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + req['frame'].encode('hex'))
  611. ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
  612. if ev is None:
  613. raise Exception("Management frame TX status not reported (1)")
  614. if "stype=1 ok=1" not in ev:
  615. raise Exception("Unexpected management frame TX status (1): " + ev)
  616. cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
  617. if "OK" not in hapd.request(cmd):
  618. raise Exception("MGMT_TX_STATUS_PROCESS failed")
  619. hapd.set("ext_mgmt_frame_handling", "0")
  620. dev[0].wait_connected()
  621. def test_sae_proto_hostapd(dev, apdev):
  622. """SAE protocol testing with hostapd"""
  623. params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
  624. params['wpa_key_mgmt'] = 'SAE'
  625. params['sae_groups'] = "19 65535"
  626. hapd = hostapd.add_ap(apdev[0], params)
  627. hapd.set("ext_mgmt_frame_handling", "1")
  628. bssid = hapd.own_addr().replace(':', '')
  629. addr = "020000000000"
  630. addr2 = "020000000001"
  631. hdr = "b0003a01" + bssid + addr + bssid + "1000"
  632. hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000"
  633. group = "1300"
  634. scalar = "f7df19f4a7fef1d3b895ea1de150b7c5a7a705c8ebb31a52b623e0057908bd93"
  635. element_x = "21931572027f2e953e2a49fab3d992944102cc95aa19515fc068b394fb25ae3c"
  636. element_y = "cb4eeb94d7b0b789abfdb73a67ab9d6d5efa94dd553e0e724a6289821cbce530"
  637. hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y)
  638. # "SAE: Not enough data for scalar"
  639. hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar[:-2])
  640. # "SAE: Do not allow group to be changed"
  641. hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + "ffff" + scalar[:-2])
  642. # "SAE: Unsupported Finite Cyclic Group 65535"
  643. hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr2 + "030001000000" + "ffff" + scalar[:-2])
  644. @remote_compatible
  645. def test_sae_no_ffc_by_default(dev, apdev):
  646. """SAE and default groups rejecting FFC"""
  647. if "SAE" not in dev[0].get_capability("auth_alg"):
  648. raise HwsimSkip("SAE not supported")
  649. params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
  650. params['wpa_key_mgmt'] = 'SAE'
  651. hapd = hostapd.add_ap(apdev[0], params)
  652. dev[0].request("SET sae_groups 5")
  653. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
  654. wait_connect=False)
  655. ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
  656. if ev is None:
  657. raise Exception("Did not try to authenticate")
  658. ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
  659. if ev is None:
  660. raise Exception("Did not try to authenticate (2)")
  661. dev[0].request("REMOVE_NETWORK all")
  662. def sae_reflection_attack(apdev, dev, group):
  663. if "SAE" not in dev.get_capability("auth_alg"):
  664. raise HwsimSkip("SAE not supported")
  665. params = hostapd.wpa2_params(ssid="test-sae",
  666. passphrase="no-knowledge-of-passphrase")
  667. params['wpa_key_mgmt'] = 'SAE'
  668. hapd = hostapd.add_ap(apdev, params)
  669. bssid = apdev['bssid']
  670. dev.scan_for_bss(bssid, freq=2412)
  671. hapd.set("ext_mgmt_frame_handling", "1")
  672. dev.request("SET sae_groups %d" % group)
  673. dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
  674. scan_freq="2412", wait_connect=False)
  675. # Commit
  676. for i in range(0, 10):
  677. req = hapd.mgmt_rx()
  678. if req is None:
  679. raise Exception("MGMT RX wait timed out")
  680. if req['subtype'] == 11:
  681. break
  682. req = None
  683. if not req:
  684. raise Exception("Authentication frame not received")
  685. resp = {}
  686. resp['fc'] = req['fc']
  687. resp['da'] = req['sa']
  688. resp['sa'] = req['da']
  689. resp['bssid'] = req['bssid']
  690. resp['payload'] = req['payload']
  691. hapd.mgmt_tx(resp)
  692. # Confirm
  693. req = hapd.mgmt_rx(timeout=0.5)
  694. if req is not None:
  695. if req['subtype'] == 11:
  696. raise Exception("Unexpected Authentication frame seen")
  697. @remote_compatible
  698. def test_sae_reflection_attack_ecc(dev, apdev):
  699. """SAE reflection attack (ECC)"""
  700. sae_reflection_attack(apdev[0], dev[0], 19)
  701. @remote_compatible
  702. def test_sae_reflection_attack_ffc(dev, apdev):
  703. """SAE reflection attack (FFC)"""
  704. sae_reflection_attack(apdev[0], dev[0], 5)
  705. def sae_reflection_attack_internal(apdev, dev, group):
  706. if "SAE" not in dev.get_capability("auth_alg"):
  707. raise HwsimSkip("SAE not supported")
  708. params = hostapd.wpa2_params(ssid="test-sae",
  709. passphrase="no-knowledge-of-passphrase")
  710. params['wpa_key_mgmt'] = 'SAE'
  711. params['sae_reflection_attack'] = '1'
  712. hapd = hostapd.add_ap(apdev, params)
  713. bssid = apdev['bssid']
  714. dev.scan_for_bss(bssid, freq=2412)
  715. dev.request("SET sae_groups %d" % group)
  716. dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
  717. scan_freq="2412", wait_connect=False)
  718. ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
  719. if ev is not None:
  720. raise Exception("Unexpected connection")
  721. @remote_compatible
  722. def test_sae_reflection_attack_ecc_internal(dev, apdev):
  723. """SAE reflection attack (ECC) - internal"""
  724. sae_reflection_attack_internal(apdev[0], dev[0], 19)
  725. @remote_compatible
  726. def test_sae_reflection_attack_ffc_internal(dev, apdev):
  727. """SAE reflection attack (FFC) - internal"""
  728. sae_reflection_attack_internal(apdev[0], dev[0], 5)
  729. @remote_compatible
  730. def test_sae_commit_override(dev, apdev):
  731. """SAE commit override (hostapd)"""
  732. if "SAE" not in dev[0].get_capability("auth_alg"):
  733. raise HwsimSkip("SAE not supported")
  734. params = hostapd.wpa2_params(ssid="test-sae",
  735. passphrase="12345678")
  736. params['wpa_key_mgmt'] = 'SAE'
  737. params['sae_commit_override'] = '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514'
  738. hapd = hostapd.add_ap(apdev[0], params)
  739. dev[0].request("SET sae_groups ")
  740. dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE",
  741. scan_freq="2412", wait_connect=False)
  742. ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
  743. if ev is not None:
  744. raise Exception("Unexpected connection")
  745. @remote_compatible
  746. def test_sae_commit_override2(dev, apdev):
  747. """SAE commit override (wpa_supplicant)"""
  748. if "SAE" not in dev[0].get_capability("auth_alg"):
  749. raise HwsimSkip("SAE not supported")
  750. params = hostapd.wpa2_params(ssid="test-sae",
  751. passphrase="12345678")
  752. params['wpa_key_mgmt'] = 'SAE'
  753. hapd = hostapd.add_ap(apdev[0], params)
  754. dev[0].request("SET sae_groups ")
  755. dev[0].set('sae_commit_override', '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514')
  756. dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE",
  757. scan_freq="2412", wait_connect=False)
  758. ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
  759. if ev is not None:
  760. raise Exception("Unexpected connection")
  761. @remote_compatible
  762. def test_sae_anti_clogging_proto(dev, apdev):
  763. """SAE anti clogging protocol testing"""
  764. if "SAE" not in dev[0].get_capability("auth_alg"):
  765. raise HwsimSkip("SAE not supported")
  766. params = hostapd.wpa2_params(ssid="test-sae",
  767. passphrase="no-knowledge-of-passphrase")
  768. params['wpa_key_mgmt'] = 'SAE'
  769. hapd = hostapd.add_ap(apdev[0], params)
  770. bssid = apdev[0]['bssid']
  771. dev[0].scan_for_bss(bssid, freq=2412)
  772. hapd.set("ext_mgmt_frame_handling", "1")
  773. dev[0].request("SET sae_groups ")
  774. dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE",
  775. scan_freq="2412", wait_connect=False)
  776. # Commit
  777. for i in range(0, 10):
  778. req = hapd.mgmt_rx()
  779. if req is None:
  780. raise Exception("MGMT RX wait timed out")
  781. if req['subtype'] == 11:
  782. break
  783. req = None
  784. if not req:
  785. raise Exception("Authentication frame not received")
  786. resp = {}
  787. resp['fc'] = req['fc']
  788. resp['da'] = req['sa']
  789. resp['sa'] = req['da']
  790. resp['bssid'] = req['bssid']
  791. resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00")
  792. hapd.mgmt_tx(resp)
  793. # Confirm (not received due to DH group being rejected)
  794. req = hapd.mgmt_rx(timeout=0.5)
  795. if req is not None:
  796. if req['subtype'] == 11:
  797. raise Exception("Unexpected Authentication frame seen")
  798. @remote_compatible
  799. def test_sae_no_random(dev, apdev):
  800. """SAE and no random numbers available"""
  801. if "SAE" not in dev[0].get_capability("auth_alg"):
  802. raise HwsimSkip("SAE not supported")
  803. params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
  804. params['wpa_key_mgmt'] = 'SAE'
  805. hapd = hostapd.add_ap(apdev[0], params)
  806. dev[0].request("SET sae_groups ")
  807. tests = [ (1, "os_get_random;sae_get_rand"),
  808. (1, "os_get_random;get_rand_1_to_p_1"),
  809. (1, "os_get_random;get_random_qr_qnr"),
  810. (1, "os_get_random;sae_derive_pwe_ecc") ]
  811. for count, func in tests:
  812. with fail_test(dev[0], count, func):
  813. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  814. scan_freq="2412")
  815. dev[0].request("REMOVE_NETWORK all")
  816. dev[0].wait_disconnected()
  817. @remote_compatible
  818. def test_sae_pwe_failure(dev, apdev):
  819. """SAE and pwe failure"""
  820. if "SAE" not in dev[0].get_capability("auth_alg"):
  821. raise HwsimSkip("SAE not supported")
  822. params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
  823. params['wpa_key_mgmt'] = 'SAE'
  824. params['sae_groups'] = '19 5'
  825. hapd = hostapd.add_ap(apdev[0], params)
  826. dev[0].request("SET sae_groups 19")
  827. with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"):
  828. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  829. scan_freq="2412")
  830. dev[0].request("REMOVE_NETWORK all")
  831. dev[0].wait_disconnected()
  832. with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"):
  833. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  834. scan_freq="2412")
  835. dev[0].request("REMOVE_NETWORK all")
  836. dev[0].wait_disconnected()
  837. dev[0].request("SET sae_groups 5")
  838. with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"):
  839. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  840. scan_freq="2412")
  841. dev[0].request("REMOVE_NETWORK all")
  842. dev[0].wait_disconnected()
  843. dev[0].request("SET sae_groups 5")
  844. with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"):
  845. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  846. scan_freq="2412")
  847. dev[0].request("REMOVE_NETWORK all")
  848. dev[0].wait_disconnected()
  849. with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"):
  850. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  851. scan_freq="2412")
  852. dev[0].request("REMOVE_NETWORK all")
  853. dev[0].wait_disconnected()
  854. @remote_compatible
  855. def test_sae_bignum_failure(dev, apdev):
  856. """SAE and bignum failure"""
  857. if "SAE" not in dev[0].get_capability("auth_alg"):
  858. raise HwsimSkip("SAE not supported")
  859. params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
  860. params['wpa_key_mgmt'] = 'SAE'
  861. params['sae_groups'] = '19 5 22'
  862. hapd = hostapd.add_ap(apdev[0], params)
  863. dev[0].request("SET sae_groups 19")
  864. tests = [ (1, "crypto_bignum_init_set;get_rand_1_to_p_1"),
  865. (1, "crypto_bignum_init;is_quadratic_residue_blind"),
  866. (1, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
  867. (2, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
  868. (3, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
  869. (1, "crypto_bignum_legendre;is_quadratic_residue_blind"),
  870. (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"),
  871. (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"),
  872. (1, "crypto_bignum_init_set;get_random_qr_qnr"),
  873. (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"),
  874. (1, "crypto_ec_point_init;sae_derive_pwe_ecc"),
  875. (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"),
  876. (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"),
  877. (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"),
  878. (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"),
  879. (1, "crypto_bignum_init;=sae_derive_commit"),
  880. (1, "crypto_ec_point_init;sae_derive_k_ecc"),
  881. (1, "crypto_ec_point_mul;sae_derive_k_ecc"),
  882. (1, "crypto_ec_point_add;sae_derive_k_ecc"),
  883. (2, "crypto_ec_point_mul;sae_derive_k_ecc"),
  884. (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"),
  885. (1, "crypto_bignum_legendre;get_random_qr_qnr"),
  886. (1, "sha256_prf;sae_derive_keys"),
  887. (1, "crypto_bignum_init;sae_derive_keys"),
  888. (1, "crypto_bignum_init_set;sae_parse_commit_scalar"),
  889. (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"),
  890. (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc") ]
  891. for count, func in tests:
  892. with fail_test(dev[0], count, func):
  893. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  894. scan_freq="2412", wait_connect=False)
  895. wait_fail_trigger(dev[0], "GET_FAIL")
  896. dev[0].request("REMOVE_NETWORK all")
  897. dev[0].request("SET sae_groups 5")
  898. tests = [ (1, "crypto_bignum_init_set;sae_set_group"),
  899. (2, "crypto_bignum_init_set;sae_set_group"),
  900. (1, "crypto_bignum_init_set;sae_get_rand"),
  901. (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
  902. (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"),
  903. (1, "crypto_bignum_init;sae_derive_pwe_ffc"),
  904. (1, "crypto_bignum_init;sae_derive_commit_element_ffc"),
  905. (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"),
  906. (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"),
  907. (1, "crypto_bignum_init;sae_derive_k_ffc"),
  908. (1, "crypto_bignum_exptmod;sae_derive_k_ffc"),
  909. (1, "crypto_bignum_mulmod;sae_derive_k_ffc"),
  910. (2, "crypto_bignum_exptmod;sae_derive_k_ffc"),
  911. (1, "crypto_bignum_to_bin;sae_derive_k_ffc"),
  912. (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
  913. (1, "crypto_bignum_init;sae_parse_commit_element_ffc"),
  914. (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
  915. (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc") ]
  916. for count, func in tests:
  917. with fail_test(dev[0], count, func):
  918. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  919. scan_freq="2412", wait_connect=False)
  920. wait_fail_trigger(dev[0], "GET_FAIL")
  921. dev[0].request("REMOVE_NETWORK all")
  922. dev[0].request("SET sae_groups 22")
  923. tests = [ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
  924. (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"),
  925. (1, "crypto_bignum_div;sae_test_pwd_seed_ffc") ]
  926. for count, func in tests:
  927. with fail_test(dev[0], count, func):
  928. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  929. scan_freq="2412", wait_connect=False)
  930. wait_fail_trigger(dev[0], "GET_FAIL")
  931. dev[0].request("REMOVE_NETWORK all")
  932. def test_sae_invalid_anti_clogging_token_req(dev, apdev):
  933. """SAE and invalid anti-clogging token request"""
  934. if "SAE" not in dev[0].get_capability("auth_alg"):
  935. raise HwsimSkip("SAE not supported")
  936. params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
  937. params['wpa_key_mgmt'] = 'SAE'
  938. # Beacon more frequently since Probe Request frames are practically ignored
  939. # in this test setup (ext_mgmt_frame_handled=1 on hostapd side) and
  940. # wpa_supplicant scans may end up getting ignored if no new results are
  941. # available due to the missing Probe Response frames.
  942. params['beacon_int'] = '20'
  943. hapd = hostapd.add_ap(apdev[0], params)
  944. bssid = apdev[0]['bssid']
  945. dev[0].request("SET sae_groups 19")
  946. dev[0].scan_for_bss(bssid, freq=2412)
  947. hapd.set("ext_mgmt_frame_handling", "1")
  948. dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
  949. scan_freq="2412", wait_connect=False)
  950. ev = dev[0].wait_event(["SME: Trying to authenticate"])
  951. if ev is None:
  952. raise Exception("No authentication attempt seen (1)")
  953. dev[0].dump_monitor()
  954. for i in range(0, 10):
  955. req = hapd.mgmt_rx()
  956. if req is None:
  957. raise Exception("MGMT RX wait timed out (commit)")
  958. if req['subtype'] == 11:
  959. break
  960. req = None
  961. if not req:
  962. raise Exception("Authentication frame (commit) not received")
  963. hapd.dump_monitor()
  964. resp = {}
  965. resp['fc'] = req['fc']
  966. resp['da'] = req['sa']
  967. resp['sa'] = req['da']
  968. resp['bssid'] = req['bssid']
  969. resp['payload'] = binascii.unhexlify("030001004c0013")
  970. hapd.mgmt_tx(resp)
  971. ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
  972. if ev is None:
  973. raise Exception("Management frame TX status not reported (1)")
  974. if "stype=11 ok=1" not in ev:
  975. raise Exception("Unexpected management frame TX status (1): " + ev)
  976. ev = dev[0].wait_event(["SME: Trying to authenticate"])
  977. if ev is None:
  978. raise Exception("No authentication attempt seen (2)")
  979. dev[0].dump_monitor()
  980. for i in range(0, 10):
  981. req = hapd.mgmt_rx()
  982. if req is None:
  983. raise Exception("MGMT RX wait timed out (commit) (2)")
  984. if req['subtype'] == 11:
  985. break
  986. req = None
  987. if not req:
  988. raise Exception("Authentication frame (commit) not received (2)")
  989. hapd.dump_monitor()
  990. resp = {}
  991. resp['fc'] = req['fc']
  992. resp['da'] = req['sa']
  993. resp['sa'] = req['da']
  994. resp['bssid'] = req['bssid']
  995. resp['payload'] = binascii.unhexlify("030001000100")
  996. hapd.mgmt_tx(resp)
  997. ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
  998. if ev is None:
  999. raise Exception("Management frame TX status not reported (1)")
  1000. if "stype=11 ok=1" not in ev:
  1001. raise Exception("Unexpected management frame TX status (1): " + ev)
  1002. ev = dev[0].wait_event(["SME: Trying to authenticate"])
  1003. if ev is None:
  1004. raise Exception("No authentication attempt seen (3)")
  1005. dev[0].dump_monitor()
  1006. dev[0].request("DISCONNECT")
  1007. def test_sae_password(dev, apdev):
  1008. """SAE and sae_password in hostapd configuration"""
  1009. if "SAE" not in dev[0].get_capability("auth_alg"):
  1010. raise HwsimSkip("SAE not supported")
  1011. params = hostapd.wpa2_params(ssid="test-sae",
  1012. passphrase="12345678")
  1013. params['wpa_key_mgmt'] = 'SAE WPA-PSK'
  1014. params['sae_password'] = "sae-password"
  1015. hapd = hostapd.add_ap(apdev[0], params)
  1016. dev[0].request("SET sae_groups ")
  1017. dev[0].connect("test-sae", psk="sae-password", key_mgmt="SAE",
  1018. scan_freq="2412")
  1019. dev[1].connect("test-sae", psk="12345678", scan_freq="2412")
  1020. dev[2].request("SET sae_groups ")
  1021. dev[2].connect("test-sae", sae_password="sae-password", key_mgmt="SAE",
  1022. scan_freq="2412")
  1023. def test_sae_password_short(dev, apdev):
  1024. """SAE and short password"""
  1025. if "SAE" not in dev[0].get_capability("auth_alg"):
  1026. raise HwsimSkip("SAE not supported")
  1027. params = hostapd.wpa2_params(ssid="test-sae")
  1028. params['wpa_key_mgmt'] = 'SAE'
  1029. params['sae_password'] = "secret"
  1030. hapd = hostapd.add_ap(apdev[0], params)
  1031. dev[0].request("SET sae_groups ")
  1032. dev[0].connect("test-sae", sae_password="secret", key_mgmt="SAE",
  1033. scan_freq="2412")
  1034. def test_sae_password_long(dev, apdev):
  1035. """SAE and long password"""
  1036. if "SAE" not in dev[0].get_capability("auth_alg"):
  1037. raise HwsimSkip("SAE not supported")
  1038. params = hostapd.wpa2_params(ssid="test-sae")
  1039. params['wpa_key_mgmt'] = 'SAE'
  1040. params['sae_password'] = 100*"A"
  1041. hapd = hostapd.add_ap(apdev[0], params)
  1042. dev[0].request("SET sae_groups ")
  1043. dev[0].connect("test-sae", sae_password=100*"A", key_mgmt="SAE",
  1044. scan_freq="2412")