test_owe.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. # Test cases for Opportunistic Wireless Encryption (OWE)
  2. # Copyright (c) 2017, 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. import logging
  7. logger = logging.getLogger()
  8. import time
  9. import hostapd
  10. from wpasupplicant import WpaSupplicant
  11. import hwsim_utils
  12. from utils import HwsimSkip
  13. def test_owe(dev, apdev):
  14. """Opportunistic Wireless Encryption"""
  15. if "OWE" not in dev[0].get_capability("key_mgmt"):
  16. raise HwsimSkip("OWE not supported")
  17. params = { "ssid": "owe",
  18. "wpa": "2",
  19. "ieee80211w": "2",
  20. "wpa_key_mgmt": "OWE",
  21. "rsn_pairwise": "CCMP" }
  22. hapd = hostapd.add_ap(apdev[0], params)
  23. bssid = hapd.own_addr()
  24. dev[0].scan_for_bss(bssid, freq="2412")
  25. bss = dev[0].get_bss(bssid)
  26. if "[WPA2-OWE-CCMP]" not in bss['flags']:
  27. raise Exception("OWE AKM not recognized: " + bss['flags'])
  28. dev[0].connect("owe", key_mgmt="OWE", ieee80211w="2",
  29. scan_freq="2412")
  30. hwsim_utils.test_connectivity(dev[0], hapd)
  31. val = dev[0].get_status_field("key_mgmt")
  32. if val != "OWE":
  33. raise Exception("Unexpected key_mgmt: " + val)
  34. def test_owe_groups(dev, apdev):
  35. """Opportunistic Wireless Encryption - DH groups"""
  36. if "OWE" not in dev[0].get_capability("key_mgmt"):
  37. raise HwsimSkip("OWE not supported")
  38. params = { "ssid": "owe",
  39. "wpa": "2",
  40. "wpa_key_mgmt": "OWE",
  41. "rsn_pairwise": "CCMP" }
  42. hapd = hostapd.add_ap(apdev[0], params)
  43. bssid = hapd.own_addr()
  44. dev[0].scan_for_bss(bssid, freq="2412")
  45. for group in [ 19, 20, 21 ]:
  46. dev[0].connect("owe", key_mgmt="OWE", owe_group=str(group))
  47. hwsim_utils.test_connectivity(dev[0], hapd)
  48. dev[0].request("REMOVE_NETWORK all")
  49. dev[0].wait_disconnected()
  50. dev[0].dump_monitor()
  51. def test_owe_pmksa_caching(dev, apdev):
  52. """Opportunistic Wireless Encryption and PMKSA caching"""
  53. run_owe_pmksa_caching(dev, apdev)
  54. def test_owe_pmksa_caching_connect_cmd(dev, apdev):
  55. """Opportunistic Wireless Encryption and PMKSA caching using cfg80211 connect command"""
  56. wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
  57. wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
  58. run_owe_pmksa_caching([ wpas ], apdev)
  59. def run_owe_pmksa_caching(dev, apdev):
  60. if "OWE" not in dev[0].get_capability("key_mgmt"):
  61. raise HwsimSkip("OWE not supported")
  62. params = { "ssid": "owe",
  63. "wpa": "2",
  64. "wpa_key_mgmt": "OWE",
  65. "rsn_pairwise": "CCMP" }
  66. hapd = hostapd.add_ap(apdev[0], params)
  67. bssid = hapd.own_addr()
  68. dev[0].scan_for_bss(bssid, freq="2412")
  69. id = dev[0].connect("owe", key_mgmt="OWE")
  70. hwsim_utils.test_connectivity(dev[0], hapd)
  71. pmksa = dev[0].get_pmksa(bssid)
  72. dev[0].request("DISCONNECT")
  73. dev[0].wait_disconnected()
  74. dev[0].dump_monitor()
  75. dev[0].select_network(id, 2412)
  76. dev[0].wait_connected()
  77. hwsim_utils.test_connectivity(dev[0], hapd)
  78. pmksa2 = dev[0].get_pmksa(bssid)
  79. dev[0].request("DISCONNECT")
  80. dev[0].wait_disconnected()
  81. dev[0].dump_monitor()
  82. if "OK" not in hapd.request("PMKSA_FLUSH"):
  83. raise Exception("PMKSA_FLUSH failed")
  84. dev[0].select_network(id, 2412)
  85. dev[0].wait_connected()
  86. hwsim_utils.test_connectivity(dev[0], hapd)
  87. pmksa3 = dev[0].get_pmksa(bssid)
  88. dev[0].request("DISCONNECT")
  89. dev[0].wait_disconnected()
  90. dev[0].dump_monitor()
  91. if pmksa is None or pmksa2 is None or pmksa3 is None:
  92. raise Exception("PMKSA entry missing")
  93. if pmksa['pmkid'] != pmksa2['pmkid']:
  94. raise Exception("Unexpected PMKID change when using PMKSA caching")
  95. if pmksa['pmkid'] == pmksa3['pmkid']:
  96. raise Exception("PMKID did not change after PMKSA cache flush")
  97. def test_owe_and_psk(dev, apdev):
  98. """Opportunistic Wireless Encryption and WPA2-PSK enabled"""
  99. if "OWE" not in dev[0].get_capability("key_mgmt"):
  100. raise HwsimSkip("OWE not supported")
  101. params = { "ssid": "owe+psk",
  102. "wpa": "2",
  103. "wpa_key_mgmt": "OWE WPA-PSK",
  104. "rsn_pairwise": "CCMP",
  105. "wpa_passphrase": "12345678" }
  106. hapd = hostapd.add_ap(apdev[0], params)
  107. bssid = hapd.own_addr()
  108. dev[0].scan_for_bss(bssid, freq="2412")
  109. dev[0].connect("owe+psk", psk="12345678")
  110. hwsim_utils.test_connectivity(dev[0], hapd)
  111. dev[1].scan_for_bss(bssid, freq="2412")
  112. dev[1].connect("owe+psk", key_mgmt="OWE")
  113. hwsim_utils.test_connectivity(dev[1], hapd)
  114. def test_owe_transition_mode(dev, apdev):
  115. """Opportunistic Wireless Encryption transition mode"""
  116. run_owe_transition_mode(dev, apdev)
  117. def test_owe_transition_mode_connect_cmd(dev, apdev):
  118. """Opportunistic Wireless Encryption transition mode using cfg80211 connect command"""
  119. wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
  120. wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
  121. run_owe_transition_mode([ wpas ], apdev)
  122. def run_owe_transition_mode(dev, apdev):
  123. if "OWE" not in dev[0].get_capability("key_mgmt"):
  124. raise HwsimSkip("OWE not supported")
  125. dev[0].flush_scan_cache()
  126. params = { "ssid": "owe-random",
  127. "wpa": "2",
  128. "wpa_key_mgmt": "OWE",
  129. "rsn_pairwise": "CCMP",
  130. "ieee80211w": "2",
  131. "owe_transition_bssid": apdev[1]['bssid'],
  132. "owe_transition_ssid": '"owe-test"',
  133. "ignore_broadcast_ssid": "1" }
  134. hapd = hostapd.add_ap(apdev[0], params)
  135. bssid = hapd.own_addr()
  136. params = { "ssid": "owe-test",
  137. "owe_transition_bssid": apdev[0]['bssid'],
  138. "owe_transition_ssid": '"owe-random"' }
  139. hapd2 = hostapd.add_ap(apdev[1], params)
  140. bssid2 = hapd2.own_addr()
  141. dev[0].scan_for_bss(bssid, freq="2412")
  142. dev[0].scan_for_bss(bssid2, freq="2412")
  143. bss = dev[0].get_bss(bssid)
  144. if "[WPA2-OWE-CCMP]" not in bss['flags']:
  145. raise Exception("OWE AKM not recognized: " + bss['flags'])
  146. if "[OWE-TRANS]" not in bss['flags']:
  147. raise Exception("OWE transition not recognized: " + bss['flags'])
  148. bss = dev[0].get_bss(bssid2)
  149. if "[OWE-TRANS-OPEN]" not in bss['flags']:
  150. raise Exception("OWE transition (open) not recognized: " + bss['flags'])
  151. id = dev[0].connect("owe-test", key_mgmt="OWE", ieee80211w="2",
  152. scan_freq="2412")
  153. hwsim_utils.test_connectivity(dev[0], hapd)
  154. val = dev[0].get_status_field("key_mgmt")
  155. if val != "OWE":
  156. raise Exception("Unexpected key_mgmt: " + val)
  157. logger.info("Move to OWE only mode (disable transition mode)")
  158. dev[0].request("DISCONNECT")
  159. dev[0].wait_disconnected()
  160. dev[0].dump_monitor()
  161. hapd2.disable()
  162. hapd.disable()
  163. dev[0].flush_scan_cache()
  164. hapd.set("owe_transition_bssid", "00:00:00:00:00:00")
  165. hapd.set("ignore_broadcast_ssid", '0')
  166. hapd.set("ssid", 'owe-test')
  167. hapd.enable()
  168. dev[0].scan_for_bss(bssid, freq="2412")
  169. dev[0].select_network(id, 2412)
  170. dev[0].wait_connected()
  171. hwsim_utils.test_connectivity(dev[0], hapd)
  172. def test_owe_transition_mode_open_only_ap(dev, apdev):
  173. """Opportunistic Wireless Encryption transition mode connect to open-only AP"""
  174. if "OWE" not in dev[0].get_capability("key_mgmt"):
  175. raise HwsimSkip("OWE not supported")
  176. dev[0].flush_scan_cache()
  177. params = { "ssid": "owe-test-open" }
  178. hapd = hostapd.add_ap(apdev[0], params)
  179. bssid = hapd.own_addr()
  180. dev[0].scan_for_bss(bssid, freq="2412")
  181. bss = dev[0].get_bss(bssid)
  182. id = dev[0].connect("owe-test-open", key_mgmt="OWE", ieee80211w="2",
  183. scan_freq="2412")
  184. hwsim_utils.test_connectivity(dev[0], hapd)
  185. val = dev[0].get_status_field("key_mgmt")
  186. if val != "NONE":
  187. raise Exception("Unexpected key_mgmt: " + val)
  188. def test_owe_transition_mode_multi_bss(dev, apdev):
  189. """Opportunistic Wireless Encryption transition mode (multi BSS)"""
  190. try:
  191. run_owe_transition_mode_multi_bss(dev, apdev)
  192. finally:
  193. dev[0].request("SCAN_INTERVAL 5")
  194. def run_owe_transition_mode_multi_bss(dev, apdev):
  195. if "OWE" not in dev[0].get_capability("key_mgmt"):
  196. raise HwsimSkip("OWE not supported")
  197. ifname1 = apdev[0]['ifname']
  198. ifname2 = apdev[0]['ifname'] + '-2'
  199. hapd1 = hostapd.add_bss(apdev[0], ifname1, 'owe-bss-1.conf')
  200. hapd2 = hostapd.add_bss(apdev[0], ifname2, 'owe-bss-2.conf')
  201. hapd2.bssidx = 1
  202. bssid = hapd1.own_addr()
  203. bssid2 = hapd2.own_addr()
  204. # Beaconing with the OWE Transition Mode element can start only once both
  205. # BSSs are enabled, so the very first Beacon frame may go out without this
  206. # element. Wait a bit to avoid getting incomplete scan results.
  207. time.sleep(0.1)
  208. dev[0].request("SCAN_INTERVAL 1")
  209. dev[0].scan_for_bss(bssid2, freq="2412")
  210. dev[0].scan_for_bss(bssid, freq="2412")
  211. dev[0].connect("transition-mode-open", key_mgmt="OWE")
  212. val = dev[0].get_status_field("bssid")
  213. if val != bssid2:
  214. raise Exception("Unexpected bssid: " + val)
  215. val = dev[0].get_status_field("key_mgmt")
  216. if val != "OWE":
  217. raise Exception("Unexpected key_mgmt: " + val)
  218. hwsim_utils.test_connectivity(dev[0], hapd2)
  219. def test_owe_unsupported_group(dev, apdev):
  220. """Opportunistic Wireless Encryption and unsupported group"""
  221. try:
  222. run_owe_unsupported_group(dev, apdev)
  223. finally:
  224. dev[0].request("VENDOR_ELEM_REMOVE 13 *")
  225. def test_owe_unsupported_group_connect_cmd(dev, apdev):
  226. """Opportunistic Wireless Encryption and unsupported group using cfg80211 connect command"""
  227. try:
  228. wpas = None
  229. wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
  230. wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
  231. run_owe_unsupported_group([ wpas ], apdev)
  232. finally:
  233. if wpas:
  234. wpas.request("VENDOR_ELEM_REMOVE 13 *")
  235. def run_owe_unsupported_group(dev, apdev):
  236. if "OWE" not in dev[0].get_capability("key_mgmt"):
  237. raise HwsimSkip("OWE not supported")
  238. # Override OWE Dh Parameters element with a payload that uses invalid group
  239. # 0 (and actual group 19 data) to make the AP reject this with the specific
  240. # status code 77.
  241. dev[0].request("VENDOR_ELEM_ADD 13 ff23200000783590fb7440e03d5b3b33911f86affdcc6b4411b707846ac4ff08ddc8831ccd")
  242. params = { "ssid": "owe",
  243. "wpa": "2",
  244. "wpa_key_mgmt": "OWE",
  245. "rsn_pairwise": "CCMP" }
  246. hapd = hostapd.add_ap(apdev[0], params)
  247. bssid = hapd.own_addr()
  248. dev[0].scan_for_bss(bssid, freq="2412")
  249. dev[0].connect("owe", key_mgmt="OWE", wait_connect=False)
  250. ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
  251. dev[0].request("DISCONNECT")
  252. if ev is None:
  253. raise Exception("Association not rejected")
  254. if "status_code=77" not in ev:
  255. raise Exception("Unexpected rejection reason: " + ev)
  256. def test_owe_limited_group_set(dev, apdev):
  257. """Opportunistic Wireless Encryption and limited group set"""
  258. if "OWE" not in dev[0].get_capability("key_mgmt"):
  259. raise HwsimSkip("OWE not supported")
  260. params = { "ssid": "owe",
  261. "wpa": "2",
  262. "wpa_key_mgmt": "OWE",
  263. "rsn_pairwise": "CCMP",
  264. "owe_groups": "20 21" }
  265. hapd = hostapd.add_ap(apdev[0], params)
  266. bssid = hapd.own_addr()
  267. dev[0].scan_for_bss(bssid, freq="2412")
  268. dev[0].connect("owe", key_mgmt="OWE", owe_group="19", wait_connect=False)
  269. ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
  270. dev[0].request("DISCONNECT")
  271. if ev is None:
  272. raise Exception("Association not rejected")
  273. if "status_code=77" not in ev:
  274. raise Exception("Unexpected rejection reason: " + ev)
  275. dev[0].dump_monitor()
  276. for group in [ 20, 21 ]:
  277. dev[0].connect("owe", key_mgmt="OWE", owe_group=str(group))
  278. dev[0].request("REMOVE_NETWORK all")
  279. dev[0].wait_disconnected()
  280. dev[0].dump_monitor()
  281. def test_owe_group_negotiation(dev, apdev):
  282. """Opportunistic Wireless Encryption and group negotiation"""
  283. run_owe_group_negotiation(dev[0], apdev)
  284. def test_owe_group_negotiation_connect_cmd(dev, apdev):
  285. """Opportunistic Wireless Encryption and group negotiation (connect command)"""
  286. wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
  287. wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
  288. run_owe_group_negotiation(wpas, apdev)
  289. def run_owe_group_negotiation(dev, apdev):
  290. if "OWE" not in dev.get_capability("key_mgmt"):
  291. raise HwsimSkip("OWE not supported")
  292. params = { "ssid": "owe",
  293. "wpa": "2",
  294. "wpa_key_mgmt": "OWE",
  295. "rsn_pairwise": "CCMP",
  296. "owe_groups": "21" }
  297. hapd = hostapd.add_ap(apdev[0], params)
  298. bssid = hapd.own_addr()
  299. dev.scan_for_bss(bssid, freq="2412")
  300. dev.connect("owe", key_mgmt="OWE")