test_ap_psk.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. # WPA2-Personal tests
  2. # Copyright (c) 2014, Qualcomm Atheros, Inc.
  3. #
  4. # This software may be distributed under the terms of the BSD license.
  5. # See README for more details.
  6. import binascii
  7. import hashlib
  8. import hmac
  9. import logging
  10. logger = logging.getLogger()
  11. import os
  12. import struct
  13. import subprocess
  14. import time
  15. import hostapd
  16. import hwsim_utils
  17. def check_mib(dev, vals):
  18. mib = dev.get_mib()
  19. for v in vals:
  20. if mib[v[0]] != v[1]:
  21. raise Exception("Unexpected {} = {} (expected {})".format(v[0], mib[v[0]], v[1]))
  22. def test_ap_wpa2_psk(dev, apdev):
  23. """WPA2-PSK AP with PSK instead of passphrase"""
  24. ssid = "test-wpa2-psk"
  25. passphrase = 'qwertyuiop'
  26. psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
  27. params = hostapd.wpa2_params(ssid=ssid)
  28. params['wpa_psk'] = psk
  29. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  30. key_mgmt = hapd.get_config()['key_mgmt']
  31. if key_mgmt.split(' ')[0] != "WPA-PSK":
  32. raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
  33. dev[0].connect(ssid, raw_psk=psk, scan_freq="2412")
  34. dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
  35. sig = dev[0].request("SIGNAL_POLL").splitlines()
  36. pkt = dev[0].request("PKTCNT_POLL").splitlines()
  37. if "FREQUENCY=2412" not in sig:
  38. raise Exception("Unexpected SIGNAL_POLL value: " + str(sig))
  39. if "TXBAD=0" not in pkt:
  40. raise Exception("Unexpected TXBAD value: " + str(pkt))
  41. def test_ap_wpa2_psk_file(dev, apdev):
  42. """WPA2-PSK AP with PSK from a file"""
  43. ssid = "test-wpa2-psk"
  44. passphrase = 'qwertyuiop'
  45. psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
  46. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  47. params['wpa_psk_file'] = 'hostapd.wpa_psk'
  48. hostapd.add_ap(apdev[0]['ifname'], params)
  49. dev[1].connect(ssid, psk="very secret", scan_freq="2412", wait_connect=False)
  50. dev[2].connect(ssid, raw_psk=psk, scan_freq="2412")
  51. dev[2].request("REMOVE_NETWORK all")
  52. dev[0].connect(ssid, psk="very secret", scan_freq="2412")
  53. dev[0].request("REMOVE_NETWORK all")
  54. dev[2].connect(ssid, psk="another passphrase for all STAs", scan_freq="2412")
  55. dev[0].connect(ssid, psk="another passphrase for all STAs", scan_freq="2412")
  56. ev = dev[1].wait_event(["WPA: 4-Way Handshake failed"], timeout=10)
  57. if ev is None:
  58. raise Exception("Timed out while waiting for failure report")
  59. dev[1].request("REMOVE_NETWORK all")
  60. def test_ap_wpa2_ptk_rekey(dev, apdev):
  61. """WPA2-PSK AP and PTK rekey enforced by station"""
  62. ssid = "test-wpa2-psk"
  63. passphrase = 'qwertyuiop'
  64. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  65. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  66. dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
  67. ev = dev[0].wait_event(["WPA: Key negotiation completed"])
  68. if ev is None:
  69. raise Exception("PTK rekey timed out")
  70. hwsim_utils.test_connectivity(dev[0], hapd)
  71. def test_ap_wpa2_ptk_rekey_ap(dev, apdev):
  72. """WPA2-PSK AP and PTK rekey enforced by AP"""
  73. ssid = "test-wpa2-psk"
  74. passphrase = 'qwertyuiop'
  75. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  76. params['wpa_ptk_rekey'] = '2'
  77. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  78. dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
  79. ev = dev[0].wait_event(["WPA: Key negotiation completed"])
  80. if ev is None:
  81. raise Exception("PTK rekey timed out")
  82. hwsim_utils.test_connectivity(dev[0], hapd)
  83. def test_ap_wpa2_sha256_ptk_rekey(dev, apdev):
  84. """WPA2-PSK/SHA256 AKM AP and PTK rekey enforced by station"""
  85. ssid = "test-wpa2-psk"
  86. passphrase = 'qwertyuiop'
  87. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  88. params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
  89. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  90. dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK-SHA256",
  91. wpa_ptk_rekey="1", scan_freq="2412")
  92. ev = dev[0].wait_event(["WPA: Key negotiation completed"])
  93. if ev is None:
  94. raise Exception("PTK rekey timed out")
  95. hwsim_utils.test_connectivity(dev[0], hapd)
  96. check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-6"),
  97. ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-6") ])
  98. def test_ap_wpa2_sha256_ptk_rekey_ap(dev, apdev):
  99. """WPA2-PSK/SHA256 AKM AP and PTK rekey enforced by AP"""
  100. ssid = "test-wpa2-psk"
  101. passphrase = 'qwertyuiop'
  102. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  103. params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
  104. params['wpa_ptk_rekey'] = '2'
  105. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  106. dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK-SHA256",
  107. scan_freq="2412")
  108. ev = dev[0].wait_event(["WPA: Key negotiation completed"])
  109. if ev is None:
  110. raise Exception("PTK rekey timed out")
  111. hwsim_utils.test_connectivity(dev[0], hapd)
  112. check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-6"),
  113. ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-6") ])
  114. def test_ap_wpa_ptk_rekey(dev, apdev):
  115. """WPA-PSK/TKIP AP and PTK rekey enforced by station"""
  116. ssid = "test-wpa-psk"
  117. passphrase = 'qwertyuiop'
  118. params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
  119. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  120. dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
  121. if "[WPA-PSK-TKIP]" not in dev[0].request("SCAN_RESULTS"):
  122. raise Exception("Scan results missing WPA element info")
  123. ev = dev[0].wait_event(["WPA: Key negotiation completed"])
  124. if ev is None:
  125. raise Exception("PTK rekey timed out")
  126. hwsim_utils.test_connectivity(dev[0], hapd)
  127. def test_ap_wpa_ptk_rekey_ap(dev, apdev):
  128. """WPA-PSK/TKIP AP and PTK rekey enforced by AP"""
  129. ssid = "test-wpa-psk"
  130. passphrase = 'qwertyuiop'
  131. params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
  132. params['wpa_ptk_rekey'] = '2'
  133. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  134. dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
  135. ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=10)
  136. if ev is None:
  137. raise Exception("PTK rekey timed out")
  138. hwsim_utils.test_connectivity(dev[0], hapd)
  139. def test_ap_wpa_ccmp(dev, apdev):
  140. """WPA-PSK/CCMP"""
  141. ssid = "test-wpa-psk"
  142. passphrase = 'qwertyuiop'
  143. params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
  144. params['wpa_pairwise'] = "CCMP"
  145. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  146. dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
  147. hwsim_utils.test_connectivity(dev[0], hapd)
  148. check_mib(dev[0], [ ("dot11RSNAConfigGroupCipherSize", "128"),
  149. ("dot11RSNAGroupCipherRequested", "00-50-f2-4"),
  150. ("dot11RSNAPairwiseCipherRequested", "00-50-f2-4"),
  151. ("dot11RSNAAuthenticationSuiteRequested", "00-50-f2-2"),
  152. ("dot11RSNAGroupCipherSelected", "00-50-f2-4"),
  153. ("dot11RSNAPairwiseCipherSelected", "00-50-f2-4"),
  154. ("dot11RSNAAuthenticationSuiteSelected", "00-50-f2-2"),
  155. ("dot1xSuppSuppControlledPortStatus", "Authorized") ])
  156. def test_ap_wpa2_psk_file(dev, apdev):
  157. """WPA2-PSK AP with various PSK file error and success cases"""
  158. addr0 = dev[0].p2p_dev_addr()
  159. addr1 = dev[1].p2p_dev_addr()
  160. addr2 = dev[2].p2p_dev_addr()
  161. ssid = "psk"
  162. pskfile = "/tmp/ap_wpa2_psk_file_errors.psk_file"
  163. try:
  164. os.remove(pskfile)
  165. except:
  166. pass
  167. params = { "ssid": ssid, "wpa": "2", "wpa_key_mgmt": "WPA-PSK",
  168. "rsn_pairwise": "CCMP", "wpa_psk_file": pskfile }
  169. try:
  170. # missing PSK file
  171. hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
  172. if "FAIL" not in hapd.request("ENABLE"):
  173. raise Exception("Unexpected ENABLE success")
  174. hapd.request("DISABLE")
  175. # invalid MAC address
  176. with open(pskfile, "w") as f:
  177. f.write("\n")
  178. f.write("foo\n")
  179. if "FAIL" not in hapd.request("ENABLE"):
  180. raise Exception("Unexpected ENABLE success")
  181. hapd.request("DISABLE")
  182. # no PSK on line
  183. with open(pskfile, "w") as f:
  184. f.write("00:11:22:33:44:55\n")
  185. if "FAIL" not in hapd.request("ENABLE"):
  186. raise Exception("Unexpected ENABLE success")
  187. hapd.request("DISABLE")
  188. # invalid PSK
  189. with open(pskfile, "w") as f:
  190. f.write("00:11:22:33:44:55 1234567\n")
  191. if "FAIL" not in hapd.request("ENABLE"):
  192. raise Exception("Unexpected ENABLE success")
  193. hapd.request("DISABLE")
  194. # valid PSK file
  195. with open(pskfile, "w") as f:
  196. f.write("00:11:22:33:44:55 12345678\n")
  197. f.write(addr0 + " 123456789\n")
  198. f.write(addr1 + " 123456789a\n")
  199. f.write(addr2 + " 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n")
  200. if "FAIL" in hapd.request("ENABLE"):
  201. raise Exception("Unexpected ENABLE failure")
  202. dev[0].connect(ssid, psk="123456789", scan_freq="2412")
  203. dev[1].connect(ssid, psk="123456789a", scan_freq="2412")
  204. dev[2].connect(ssid, raw_psk="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", scan_freq="2412")
  205. finally:
  206. try:
  207. os.remove(pskfile)
  208. except:
  209. pass
  210. def test_ap_wpa2_psk_wildcard_ssid(dev, apdev):
  211. """WPA2-PSK AP and wildcard SSID configuration"""
  212. ssid = "test-wpa2-psk"
  213. passphrase = 'qwertyuiop'
  214. psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
  215. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  216. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  217. dev[0].connect("", bssid=apdev[0]['bssid'], psk=passphrase,
  218. scan_freq="2412")
  219. dev[1].connect("", bssid=apdev[0]['bssid'], raw_psk=psk, scan_freq="2412")
  220. def test_ap_wpa2_gtk_rekey(dev, apdev):
  221. """WPA2-PSK AP and GTK rekey enforced by AP"""
  222. ssid = "test-wpa2-psk"
  223. passphrase = 'qwertyuiop'
  224. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  225. params['wpa_group_rekey'] = '1'
  226. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  227. dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
  228. ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
  229. if ev is None:
  230. raise Exception("GTK rekey timed out")
  231. hwsim_utils.test_connectivity(dev[0], hapd)
  232. def test_ap_wpa_gtk_rekey(dev, apdev):
  233. """WPA-PSK/TKIP AP and GTK rekey enforced by AP"""
  234. ssid = "test-wpa-psk"
  235. passphrase = 'qwertyuiop'
  236. params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
  237. params['wpa_group_rekey'] = '1'
  238. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  239. dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
  240. ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
  241. if ev is None:
  242. raise Exception("GTK rekey timed out")
  243. hwsim_utils.test_connectivity(dev[0], hapd)
  244. def test_ap_wpa2_gmk_rekey(dev, apdev):
  245. """WPA2-PSK AP and GMK and GTK rekey enforced by AP"""
  246. ssid = "test-wpa2-psk"
  247. passphrase = 'qwertyuiop'
  248. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  249. params['wpa_group_rekey'] = '1'
  250. params['wpa_gmk_rekey'] = '2'
  251. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  252. dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
  253. for i in range(0, 3):
  254. ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
  255. if ev is None:
  256. raise Exception("GTK rekey timed out")
  257. hwsim_utils.test_connectivity(dev[0], hapd)
  258. def test_ap_wpa2_strict_rekey(dev, apdev):
  259. """WPA2-PSK AP and strict GTK rekey enforced by AP"""
  260. ssid = "test-wpa2-psk"
  261. passphrase = 'qwertyuiop'
  262. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  263. params['wpa_strict_rekey'] = '1'
  264. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  265. dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
  266. dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
  267. dev[1].request("DISCONNECT")
  268. ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
  269. if ev is None:
  270. raise Exception("GTK rekey timed out")
  271. hwsim_utils.test_connectivity(dev[0], hapd)
  272. def test_ap_wpa2_bridge_fdb(dev, apdev):
  273. """Bridge FDB entry removal"""
  274. try:
  275. ssid = "test-wpa2-psk"
  276. passphrase = "12345678"
  277. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  278. params['bridge'] = 'ap-br0'
  279. hostapd.add_ap(apdev[0]['ifname'], params)
  280. subprocess.call(['sudo', 'brctl', 'setfd', 'ap-br0', '0'])
  281. subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
  282. dev[0].connect(ssid, psk=passphrase, scan_freq="2412",
  283. bssid=apdev[0]['bssid'])
  284. dev[1].connect(ssid, psk=passphrase, scan_freq="2412",
  285. bssid=apdev[0]['bssid'])
  286. addr0 = dev[0].p2p_interface_addr()
  287. hwsim_utils.test_connectivity_sta(dev[0], dev[1])
  288. cmd = subprocess.Popen(['brctl', 'showmacs', 'ap-br0'],
  289. stdout=subprocess.PIPE)
  290. macs1 = cmd.stdout.read()
  291. dev[0].request("DISCONNECT")
  292. dev[1].request("DISCONNECT")
  293. time.sleep(1)
  294. cmd = subprocess.Popen(['brctl', 'showmacs', 'ap-br0'],
  295. stdout=subprocess.PIPE)
  296. macs2 = cmd.stdout.read()
  297. addr1 = dev[1].p2p_interface_addr()
  298. if addr0 not in macs1 or addr1 not in macs1:
  299. raise Exception("Bridge FDB entry missing")
  300. if addr0 in macs2 or addr1 in macs2:
  301. raise Exception("Bridge FDB entry was not removed")
  302. finally:
  303. subprocess.call(['sudo', 'ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
  304. subprocess.call(['sudo', 'brctl', 'delbr', 'ap-br0'])
  305. def test_ap_wpa2_already_in_bridge(dev, apdev):
  306. """hostapd behavior with interface already in bridge"""
  307. ifname = apdev[0]['ifname']
  308. br_ifname = 'ext-ap-br0'
  309. try:
  310. ssid = "test-wpa2-psk"
  311. passphrase = "12345678"
  312. subprocess.call(['brctl', 'addbr', br_ifname])
  313. subprocess.call(['brctl', 'setfd', br_ifname, '0'])
  314. subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
  315. subprocess.call(['iw', ifname, 'set', 'type', '__ap'])
  316. subprocess.call(['brctl', 'addif', br_ifname, ifname])
  317. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  318. hapd = hostapd.add_ap(ifname, params)
  319. if hapd.get_driver_status_field('brname') != br_ifname:
  320. raise Exception("Bridge name not identified correctly")
  321. dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
  322. finally:
  323. subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'down'])
  324. subprocess.call(['brctl', 'delif', br_ifname, ifname])
  325. subprocess.call(['iw', ifname, 'set', 'type', 'station'])
  326. subprocess.call(['brctl', 'delbr', br_ifname])
  327. def test_ap_wpa2_ext_add_to_bridge(dev, apdev):
  328. """hostapd behavior with interface added to bridge externally"""
  329. ifname = apdev[0]['ifname']
  330. br_ifname = 'ext-ap-br0'
  331. try:
  332. ssid = "test-wpa2-psk"
  333. passphrase = "12345678"
  334. params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
  335. hapd = hostapd.add_ap(ifname, params)
  336. subprocess.call(['brctl', 'addbr', br_ifname])
  337. subprocess.call(['brctl', 'setfd', br_ifname, '0'])
  338. subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
  339. subprocess.call(['brctl', 'addif', br_ifname, ifname])
  340. dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
  341. if hapd.get_driver_status_field('brname') != br_ifname:
  342. raise Exception("Bridge name not identified correctly")
  343. finally:
  344. subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'down'])
  345. subprocess.call(['brctl', 'delif', br_ifname, ifname])
  346. subprocess.call(['brctl', 'delbr', br_ifname])
  347. def test_ap_wpa2_psk_ext(dev, apdev):
  348. """WPA2-PSK AP using external EAPOL I/O"""
  349. bssid = apdev[0]['bssid']
  350. ssid = "test-wpa2-psk"
  351. passphrase = 'qwertyuiop'
  352. psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
  353. params = hostapd.wpa2_params(ssid=ssid)
  354. params['wpa_psk'] = psk
  355. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  356. hapd.request("SET ext_eapol_frame_io 1")
  357. dev[0].request("SET ext_eapol_frame_io 1")
  358. dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False)
  359. addr = dev[0].p2p_interface_addr()
  360. while True:
  361. ev = hapd.wait_event(["EAPOL-TX", "AP-STA-CONNECTED"], timeout=15)
  362. if ev is None:
  363. raise Exception("Timeout on EAPOL-TX from hostapd")
  364. if "AP-STA-CONNECTED" in ev:
  365. dev[0].wait_connected(timeout=15)
  366. break
  367. res = dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2])
  368. if "OK" not in res:
  369. raise Exception("EAPOL_RX to wpa_supplicant failed")
  370. ev = dev[0].wait_event(["EAPOL-TX", "CTRL-EVENT-CONNECTED"], timeout=15)
  371. if ev is None:
  372. raise Exception("Timeout on EAPOL-TX from wpa_supplicant")
  373. if "CTRL-EVENT-CONNECTED" in ev:
  374. break
  375. res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2])
  376. if "OK" not in res:
  377. raise Exception("EAPOL_RX to hostapd failed")
  378. def parse_eapol(data):
  379. (version, type, length) = struct.unpack('>BBH', data[0:4])
  380. payload = data[4:]
  381. if length > len(payload):
  382. raise Exception("Invalid EAPOL length")
  383. if length < len(payload):
  384. payload = payload[0:length]
  385. eapol = {}
  386. eapol['version'] = version
  387. eapol['type'] = type
  388. eapol['length'] = length
  389. eapol['payload'] = payload
  390. if type == 3:
  391. # EAPOL-Key
  392. (eapol['descr_type'],) = struct.unpack('B', payload[0:1])
  393. payload = payload[1:]
  394. if eapol['descr_type'] == 2 or eapol['descr_type'] == 254:
  395. # RSN EAPOL-Key
  396. (key_info, key_len) = struct.unpack('>HH', payload[0:4])
  397. eapol['rsn_key_info'] = key_info
  398. eapol['rsn_key_len'] = key_len
  399. eapol['rsn_replay_counter'] = payload[4:12]
  400. eapol['rsn_key_nonce'] = payload[12:44]
  401. eapol['rsn_key_iv'] = payload[44:60]
  402. eapol['rsn_key_rsc'] = payload[60:68]
  403. eapol['rsn_key_id'] = payload[68:76]
  404. eapol['rsn_key_mic'] = payload[76:92]
  405. payload = payload[92:]
  406. (eapol['rsn_key_data_len'],) = struct.unpack('>H', payload[0:2])
  407. payload = payload[2:]
  408. eapol['rsn_key_data'] = payload
  409. return eapol
  410. def build_eapol(msg):
  411. data = struct.pack(">BBH", msg['version'], msg['type'], msg['length'])
  412. if msg['type'] == 3:
  413. data += struct.pack('>BHH', msg['descr_type'], msg['rsn_key_info'],
  414. msg['rsn_key_len'])
  415. data += msg['rsn_replay_counter']
  416. data += msg['rsn_key_nonce']
  417. data += msg['rsn_key_iv']
  418. data += msg['rsn_key_rsc']
  419. data += msg['rsn_key_id']
  420. data += msg['rsn_key_mic']
  421. data += struct.pack('>H', msg['rsn_key_data_len'])
  422. data += msg['rsn_key_data']
  423. else:
  424. data += msg['payload']
  425. return data
  426. def sha1_prf(key, label, data, outlen):
  427. res = ''
  428. counter = 0
  429. while outlen > 0:
  430. m = hmac.new(key, label, hashlib.sha1)
  431. m.update(struct.pack('B', 0))
  432. m.update(data)
  433. m.update(struct.pack('B', counter))
  434. counter += 1
  435. hash = m.digest()
  436. if outlen > len(hash):
  437. res += hash
  438. outlen -= len(hash)
  439. else:
  440. res += hash[0:outlen]
  441. outlen = 0
  442. return res
  443. def pmk_to_ptk(pmk, addr1, addr2, nonce1, nonce2):
  444. if addr1 < addr2:
  445. data = binascii.unhexlify(addr1.replace(':','')) + binascii.unhexlify(addr2.replace(':',''))
  446. else:
  447. data = binascii.unhexlify(addr2.replace(':','')) + binascii.unhexlify(addr1.replace(':',''))
  448. if nonce1 < nonce2:
  449. data += nonce1 + nonce2
  450. else:
  451. data += nonce2 + nonce1
  452. label = "Pairwise key expansion"
  453. ptk = sha1_prf(pmk, label, data, 48)
  454. kck = ptk[0:16]
  455. kek = ptk[16:32]
  456. return (ptk, kck, kek)
  457. def eapol_key_mic(kck, msg):
  458. msg['rsn_key_mic'] = binascii.unhexlify('00000000000000000000000000000000')
  459. data = build_eapol(msg)
  460. m = hmac.new(kck, data, hashlib.sha1)
  461. msg['rsn_key_mic'] = m.digest()[0:16]
  462. def rsn_eapol_key_set(msg, key_info, key_len, nonce, data):
  463. msg['rsn_key_info'] = key_info
  464. msg['rsn_key_len'] = key_len
  465. if nonce:
  466. msg['rsn_key_nonce'] = nonce
  467. else:
  468. msg['rsn_key_nonce'] = binascii.unhexlify('0000000000000000000000000000000000000000000000000000000000000000')
  469. if data:
  470. msg['rsn_key_data_len'] = len(data)
  471. msg['rsn_key_data'] = data
  472. msg['length'] = 95 + len(data)
  473. else:
  474. msg['rsn_key_data_len'] = 0
  475. msg['rsn_key_data'] = ''
  476. msg['length'] = 95
  477. def recv_eapol(hapd):
  478. ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
  479. if ev is None:
  480. raise Exception("Timeout on EAPOL-TX from hostapd")
  481. eapol = binascii.unhexlify(ev.split(' ')[2])
  482. return parse_eapol(eapol)
  483. def send_eapol(hapd, addr, data):
  484. res = hapd.request("EAPOL_RX " + addr + " " + binascii.hexlify(data))
  485. if "OK" not in res:
  486. raise Exception("EAPOL_RX to hostapd failed")
  487. def reply_eapol(info, hapd, addr, msg, key_info, nonce, data, kck):
  488. logger.info("Send EAPOL-Key msg " + info)
  489. rsn_eapol_key_set(msg, key_info, 0, nonce, data)
  490. eapol_key_mic(kck, msg)
  491. send_eapol(hapd, addr, build_eapol(msg))
  492. def hapd_connected(hapd):
  493. ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=15)
  494. if ev is None:
  495. raise Exception("Timeout on AP-STA-CONNECTED from hostapd")
  496. def eapol_test(apdev, dev, wpa2=True):
  497. bssid = apdev['bssid']
  498. if wpa2:
  499. ssid = "test-wpa2-psk"
  500. else:
  501. ssid = "test-wpa-psk"
  502. psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
  503. pmk = binascii.unhexlify(psk)
  504. if wpa2:
  505. params = hostapd.wpa2_params(ssid=ssid)
  506. else:
  507. params = hostapd.wpa_params(ssid=ssid)
  508. params['wpa_psk'] = psk
  509. hapd = hostapd.add_ap(apdev['ifname'], params)
  510. hapd.request("SET ext_eapol_frame_io 1")
  511. dev.request("SET ext_eapol_frame_io 1")
  512. dev.connect(ssid, psk="not used", scan_freq="2412", wait_connect=False)
  513. addr = dev.p2p_interface_addr()
  514. if wpa2:
  515. rsne = binascii.unhexlify('30140100000fac040100000fac040100000fac020000')
  516. else:
  517. rsne = binascii.unhexlify('dd160050f20101000050f20201000050f20201000050f202')
  518. snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111')
  519. return (bssid,ssid,hapd,snonce,pmk,addr,rsne)
  520. def test_ap_wpa2_psk_ext_eapol(dev, apdev):
  521. """WPA2-PSK AP using external EAPOL supplicant"""
  522. (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
  523. msg = recv_eapol(hapd)
  524. anonce = msg['rsn_key_nonce']
  525. logger.info("Replay same data back")
  526. send_eapol(hapd, addr, build_eapol(msg))
  527. (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
  528. logger.info("Truncated Key Data in EAPOL-Key msg 2/4")
  529. rsn_eapol_key_set(msg, 0x0101, 0, snonce, rsne)
  530. msg['length'] = 95 + 22 - 1
  531. send_eapol(hapd, addr, build_eapol(msg))
  532. reply_eapol("2/4", hapd, addr, msg, 0x010a, snonce, rsne, kck)
  533. msg = recv_eapol(hapd)
  534. if anonce != msg['rsn_key_nonce']:
  535. raise Exception("ANonce changed")
  536. logger.info("Replay same data back")
  537. send_eapol(hapd, addr, build_eapol(msg))
  538. reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
  539. hapd_connected(hapd)
  540. def test_ap_wpa2_psk_ext_eapol_retry1(dev, apdev):
  541. """WPA2 4-way handshake with EAPOL-Key 1/4 retransmitted"""
  542. (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
  543. msg1 = recv_eapol(hapd)
  544. anonce = msg1['rsn_key_nonce']
  545. msg2 = recv_eapol(hapd)
  546. if anonce != msg2['rsn_key_nonce']:
  547. raise Exception("ANonce changed")
  548. (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
  549. logger.info("Send EAPOL-Key msg 2/4")
  550. msg = msg2
  551. rsn_eapol_key_set(msg, 0x010a, 0, snonce, rsne)
  552. eapol_key_mic(kck, msg)
  553. send_eapol(hapd, addr, build_eapol(msg))
  554. msg = recv_eapol(hapd)
  555. if anonce != msg['rsn_key_nonce']:
  556. raise Exception("ANonce changed")
  557. reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
  558. hapd_connected(hapd)
  559. def test_ap_wpa2_psk_ext_eapol_retry1b(dev, apdev):
  560. """WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted"""
  561. (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
  562. msg1 = recv_eapol(hapd)
  563. anonce = msg1['rsn_key_nonce']
  564. msg2 = recv_eapol(hapd)
  565. if anonce != msg2['rsn_key_nonce']:
  566. raise Exception("ANonce changed")
  567. (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
  568. reply_eapol("2/4 (a)", hapd, addr, msg1, 0x010a, snonce, rsne, kck)
  569. reply_eapol("2/4 (b)", hapd, addr, msg2, 0x010a, snonce, rsne, kck)
  570. msg = recv_eapol(hapd)
  571. if anonce != msg['rsn_key_nonce']:
  572. raise Exception("ANonce changed")
  573. reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
  574. hapd_connected(hapd)
  575. def test_ap_wpa2_psk_ext_eapol_retry1c(dev, apdev):
  576. """WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted and SNonce changing"""
  577. (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
  578. msg1 = recv_eapol(hapd)
  579. anonce = msg1['rsn_key_nonce']
  580. msg2 = recv_eapol(hapd)
  581. if anonce != msg2['rsn_key_nonce']:
  582. raise Exception("ANonce changed")
  583. (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
  584. reply_eapol("2/4 (a)", hapd, addr, msg1, 0x010a, snonce, rsne, kck)
  585. snonce2 = binascii.unhexlify('2222222222222222222222222222222222222222222222222222222222222222')
  586. (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce2, anonce)
  587. reply_eapol("2/4 (b)", hapd, addr, msg2, 0x010a, snonce2, rsne, kck)
  588. msg = recv_eapol(hapd)
  589. if anonce != msg['rsn_key_nonce']:
  590. raise Exception("ANonce changed")
  591. reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
  592. hapd_connected(hapd)
  593. def test_ap_wpa2_psk_ext_eapol_retry1d(dev, apdev):
  594. """WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted and SNonce changing and older used"""
  595. (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
  596. msg1 = recv_eapol(hapd)
  597. anonce = msg1['rsn_key_nonce']
  598. msg2 = recv_eapol(hapd)
  599. if anonce != msg2['rsn_key_nonce']:
  600. raise Exception("ANonce changed")
  601. (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
  602. reply_eapol("2/4 (a)", hapd, addr, msg1, 0x010a, snonce, rsne, kck)
  603. snonce2 = binascii.unhexlify('2222222222222222222222222222222222222222222222222222222222222222')
  604. (ptk2, kck2, kek2) = pmk_to_ptk(pmk, addr, bssid, snonce2, anonce)
  605. reply_eapol("2/4 (b)", hapd, addr, msg2, 0x010a, snonce2, rsne, kck2)
  606. msg = recv_eapol(hapd)
  607. if anonce != msg['rsn_key_nonce']:
  608. raise Exception("ANonce changed")
  609. reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
  610. hapd_connected(hapd)
  611. def test_ap_wpa2_psk_ext_eapol_type_diff(dev, apdev):
  612. """WPA2 4-way handshake using external EAPOL supplicant"""
  613. (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
  614. msg = recv_eapol(hapd)
  615. anonce = msg['rsn_key_nonce']
  616. (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
  617. # Incorrect descriptor type (frame dropped)
  618. msg['descr_type'] = 253
  619. rsn_eapol_key_set(msg, 0x010a, 0, snonce, rsne)
  620. eapol_key_mic(kck, msg)
  621. send_eapol(hapd, addr, build_eapol(msg))
  622. # Incorrect descriptor type, but with a workaround (frame processed)
  623. msg['descr_type'] = 254
  624. rsn_eapol_key_set(msg, 0x010a, 0, snonce, rsne)
  625. eapol_key_mic(kck, msg)
  626. send_eapol(hapd, addr, build_eapol(msg))
  627. msg = recv_eapol(hapd)
  628. if anonce != msg['rsn_key_nonce']:
  629. raise Exception("ANonce changed")
  630. logger.info("Replay same data back")
  631. send_eapol(hapd, addr, build_eapol(msg))
  632. reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
  633. hapd_connected(hapd)
  634. def test_ap_wpa_psk_ext_eapol(dev, apdev):
  635. """WPA2-PSK AP using external EAPOL supplicant"""
  636. (bssid,ssid,hapd,snonce,pmk,addr,wpae) = eapol_test(apdev[0], dev[0],
  637. wpa2=False)
  638. msg = recv_eapol(hapd)
  639. anonce = msg['rsn_key_nonce']
  640. logger.info("Replay same data back")
  641. send_eapol(hapd, addr, build_eapol(msg))
  642. logger.info("Too short data")
  643. send_eapol(hapd, addr, build_eapol(msg)[0:98])
  644. (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
  645. msg['descr_type'] = 2
  646. reply_eapol("2/4(invalid type)", hapd, addr, msg, 0x010a, snonce, wpae, kck)
  647. msg['descr_type'] = 254
  648. reply_eapol("2/4", hapd, addr, msg, 0x010a, snonce, wpae, kck)
  649. msg = recv_eapol(hapd)
  650. if anonce != msg['rsn_key_nonce']:
  651. raise Exception("ANonce changed")
  652. logger.info("Replay same data back")
  653. send_eapol(hapd, addr, build_eapol(msg))
  654. reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
  655. hapd_connected(hapd)
  656. def test_ap_wpa2_psk_ext_eapol_key_info(dev, apdev):
  657. """WPA2-PSK 4-way handshake with strange key info values"""
  658. (bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
  659. msg = recv_eapol(hapd)
  660. anonce = msg['rsn_key_nonce']
  661. (ptk, kck, kek) = pmk_to_ptk(pmk, addr, bssid, snonce, anonce)
  662. rsn_eapol_key_set(msg, 0x0000, 0, snonce, rsne)
  663. send_eapol(hapd, addr, build_eapol(msg))
  664. rsn_eapol_key_set(msg, 0xffff, 0, snonce, rsne)
  665. send_eapol(hapd, addr, build_eapol(msg))
  666. # SMK M1
  667. rsn_eapol_key_set(msg, 0x2802, 0, snonce, rsne)
  668. send_eapol(hapd, addr, build_eapol(msg))
  669. # SMK M3
  670. rsn_eapol_key_set(msg, 0x2002, 0, snonce, rsne)
  671. send_eapol(hapd, addr, build_eapol(msg))
  672. # Request
  673. rsn_eapol_key_set(msg, 0x0902, 0, snonce, rsne)
  674. send_eapol(hapd, addr, build_eapol(msg))
  675. # Request
  676. rsn_eapol_key_set(msg, 0x0902, 0, snonce, rsne)
  677. tmp_kck = binascii.unhexlify('00000000000000000000000000000000')
  678. eapol_key_mic(tmp_kck, msg)
  679. send_eapol(hapd, addr, build_eapol(msg))
  680. reply_eapol("2/4", hapd, addr, msg, 0x010a, snonce, rsne, kck)
  681. msg = recv_eapol(hapd)
  682. if anonce != msg['rsn_key_nonce']:
  683. raise Exception("ANonce changed")
  684. # Request (valic MIC)
  685. rsn_eapol_key_set(msg, 0x0902, 0, snonce, rsne)
  686. eapol_key_mic(kck, msg)
  687. send_eapol(hapd, addr, build_eapol(msg))
  688. # Request (valid MIC, replayed counter)
  689. rsn_eapol_key_set(msg, 0x0902, 0, snonce, rsne)
  690. eapol_key_mic(kck, msg)
  691. send_eapol(hapd, addr, build_eapol(msg))
  692. reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
  693. hapd_connected(hapd)