1# WPS+NFC tests
2# Copyright (c) 2013, 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
7from remotehost import remote_compatible
8import binascii
9import time
10import subprocess
11import logging
12logger = logging.getLogger()
13
14import hwsim_utils
15import hostapd
16from utils import *
17
18def check_wpa2_connection(sta, ap, hapd, ssid, mixed=False):
19    status = sta.get_status()
20    if status['wpa_state'] != 'COMPLETED':
21        raise Exception("Not fully connected")
22    if status['bssid'] != ap['bssid']:
23        raise Exception("Unexpected BSSID")
24    if status['ssid'] != ssid:
25        raise Exception("Unexpected SSID")
26    if status['pairwise_cipher'] != 'CCMP':
27        raise Exception("Unexpected encryption configuration")
28    if status['group_cipher'] != 'CCMP' and not mixed:
29        raise Exception("Unexpected encryption configuration")
30    if status['key_mgmt'] != 'WPA2-PSK':
31        raise Exception("Unexpected key_mgmt")
32    hwsim_utils.test_connectivity(sta, hapd)
33
34def ap_wps_params(ssid):
35    return {"ssid": ssid, "eap_server": "1", "wps_state": "2",
36            "wpa_passphrase": "12345678", "wpa": "2",
37            "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
38
39@remote_compatible
40def test_nfc_wps_password_token_sta(dev, apdev):
41    """NFC tag with password token on the station/Enrollee"""
42    ssid = "test-wps-nfc-pw-token-conf"
43    params = ap_wps_params(ssid)
44    hapd = hostapd.add_ap(apdev[0], params)
45    logger.info("WPS provisioning step using password token from station")
46    wps = dev[0].request("WPS_NFC_TOKEN WPS").rstrip()
47    if "FAIL" in wps:
48        raise Exception("Failed to generate password token (WPS only)")
49    pw = dev[0].request("WPS_NFC_TOKEN NDEF").rstrip()
50    if "FAIL" in pw:
51        raise Exception("Failed to generate password token")
52    res = hapd.request("WPS_NFC_TAG_READ " + pw)
53    if "FAIL" in res:
54        raise Exception("Failed to provide NFC tag contents to hostapd")
55    dev[0].dump_monitor()
56    res = dev[0].request("WPS_NFC")
57    if "FAIL" in res:
58        raise Exception("Failed to start Enrollee using NFC password token")
59    dev[0].wait_connected(timeout=30)
60    hapd.wait_sta()
61    check_wpa2_connection(dev[0], apdev[0], hapd, ssid)
62
63    if "FAIL" not in hapd.request("WPS_NFC_TAG_READ 0"):
64        raise Exception("Invalid WPS_NFC_TAG_READ accepted")
65    if "FAIL" not in hapd.request("WPS_NFC_TAG_READ 0q"):
66        raise Exception("Invalid WPS_NFC_TAG_READ accepted")
67    with alloc_fail(hapd, 1,
68                    "wpabuf_alloc;hostapd_ctrl_iface_wps_nfc_tag_read"):
69        if "FAIL" not in hapd.request("WPS_NFC_TAG_READ 00"):
70            raise Exception("WPS_NFC_TAG_READ accepted during OOM")
71
72def test_nfc_wps_config_token(dev, apdev):
73    """NFC tag with configuration token from AP"""
74    ssid = "test-wps-nfc-conf-token"
75    params = ap_wps_params(ssid)
76    hapd = hostapd.add_ap(apdev[0], params)
77    logger.info("NFC configuration token from AP to station")
78    conf = hapd.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip()
79    if "FAIL" in conf:
80        raise Exception("Failed to generate configuration token")
81    ndef_conf = conf
82    dev[0].dump_monitor()
83    res = dev[0].request("WPS_NFC_TAG_READ " + conf)
84    if "FAIL" in res:
85        raise Exception("Failed to provide NFC tag contents to wpa_supplicant")
86    dev[0].wait_connected(timeout=15)
87    hapd.wait_sta()
88    check_wpa2_connection(dev[0], apdev[0], hapd, ssid)
89
90    with alloc_fail(hapd, 1, "wps_get_oob_cred"):
91        conf = hapd.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip()
92        if "FAIL" not in conf:
93            raise Exception("Unexpected configuration token received during OOM")
94
95    wps_conf = hapd.request("WPS_NFC_CONFIG_TOKEN WPS").rstrip()
96    if "FAIL" in wps_conf:
97        raise Exception("Failed to generate configuration token (WPS)")
98    if wps_conf not in ndef_conf:
99        raise Exception("WPS config token not within NDEF encapsulated one")
100
101    conf = hapd.request("WPS_NFC_CONFIG_TOKEN FOO").rstrip()
102    if "FAIL" not in conf:
103        raise Exception("Invalid WPS_NFC_CONFIG_TOKEN accepted")
104
105def test_nfc_wps_config_token_init(dev, apdev):
106    """NFC tag with configuration token from AP with auto configuration"""
107    skip_without_tkip(dev[0])
108    ssid = "test-wps-nfc-conf-token-init"
109    hapd = hostapd.add_ap(apdev[0],
110                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
111    logger.info("NFC configuration token from AP to station")
112    conf = hapd.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip()
113    if "FAIL" in conf:
114        raise Exception("Failed to generate configuration token")
115    dev[0].dump_monitor()
116    res = dev[0].request("WPS_NFC_TAG_READ " + conf)
117    if "FAIL" in res:
118        raise Exception("Failed to provide NFC tag contents to wpa_supplicant")
119    dev[0].wait_connected(timeout=15)
120    hapd.wait_sta()
121    check_wpa2_connection(dev[0], apdev[0], hapd, ssid, mixed=True)
122
123@remote_compatible
124def test_nfc_wps_password_token_sta_init(dev, apdev):
125    """Initial AP configuration with first WPS NFC Enrollee"""
126    skip_without_tkip(dev[0])
127    ssid = "test-wps-nfc-pw-token-init"
128    hapd = hostapd.add_ap(apdev[0],
129                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
130    logger.info("WPS provisioning step using password token from station")
131    pw = dev[0].request("WPS_NFC_TOKEN NDEF").rstrip()
132    if "FAIL" in pw:
133        raise Exception("Failed to generate password token")
134    res = hapd.request("WPS_NFC_TAG_READ " + pw)
135    if "FAIL" in res:
136        raise Exception("Failed to provide NFC tag contents to hostapd")
137    dev[0].dump_monitor()
138    res = dev[0].request("WPS_NFC")
139    if "FAIL" in res:
140        raise Exception("Failed to start Enrollee using NFC password token")
141    dev[0].wait_connected(timeout=30)
142    hapd.wait_sta()
143    check_wpa2_connection(dev[0], apdev[0], hapd, ssid, mixed=True)
144
145@remote_compatible
146def test_nfc_wps_password_token_ap(dev, apdev):
147    """WPS registrar configuring an AP using AP password token"""
148    ssid = "test-wps-nfc-pw-token-init"
149    hapd = hostapd.add_ap(apdev[0],
150                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
151    logger.info("WPS configuration step")
152    pw = hapd.request("WPS_NFC_TOKEN NDEF").rstrip()
153    if "FAIL" in pw:
154        raise Exception("Failed to generate password token")
155    res = hapd.request("WPS_NFC_TOKEN enable")
156    if "FAIL" in res:
157        raise Exception("Failed to enable AP password token")
158    res = dev[0].request("WPS_NFC_TAG_READ " + pw)
159    if "FAIL" in res:
160        raise Exception("Failed to provide NFC tag contents to wpa_supplicant")
161    dev[0].dump_monitor()
162    new_ssid = "test-wps-nfc-pw-token-new-ssid"
163    new_passphrase = "1234567890"
164    res = dev[0].request("WPS_REG " + apdev[0]['bssid'] + " nfc-pw " +
165                         binascii.hexlify(new_ssid.encode()).decode() +
166                         " WPA2PSK CCMP " +
167                         binascii.hexlify(new_passphrase.encode()).decode())
168    if "FAIL" in res:
169        raise Exception("Failed to start Registrar using NFC password token")
170    dev[0].wait_connected(timeout=30)
171    hapd.wait_sta()
172    check_wpa2_connection(dev[0], apdev[0], hapd, new_ssid, mixed=True)
173    if "FAIL" in hapd.request("WPS_NFC_TOKEN disable"):
174        raise Exception("Failed to disable AP password token")
175    if "FAIL" in hapd.request("WPS_NFC_TOKEN WPS"):
176        raise Exception("Unexpected WPS_NFC_TOKEN WPS failure")
177
178    with fail_test(hapd, 1, "os_get_random;wps_nfc_token_gen"):
179        if "FAIL" not in hapd.request("WPS_NFC_TOKEN WPS"):
180            raise Exception("Unexpected WPS_NFC_TOKEN success")
181    with fail_test(hapd, 2, "os_get_random;wps_nfc_token_gen"):
182        if "FAIL" not in hapd.request("WPS_NFC_TOKEN WPS"):
183            raise Exception("Unexpected WPS_NFC_TOKEN success")
184
185    if "FAIL" not in hapd.request("WPS_NFC_TOKEN foo"):
186        raise Exception("Invalid WPS_NFC_TOKEN accepted")
187
188def test_nfc_wps_password_token_ap_preconf(dev, apdev):
189    """WPS registrar configuring an AP using preconfigured AP password token"""
190    ssid = "test-wps-nfc-pw-token-init"
191    params = {"ssid": ssid, "eap_server": "1",
192              "wps_state": "1",
193              "wps_nfc_dev_pw_id": "49067",
194              "wps_nfc_dh_pubkey": "991B7F54406226505D56C6C701ED2C725E4F4866611357CA1C4D92219B2E91CFC9E4172EB0899421657534DB396A6A11361663ACDC48417541DB8610428773BC18AAA00387775F14EEE49335B574165EF915D055F818B82F99CEF4C5F176E0C5D9055CBAF055A5B20B73B26D74816BA42C1A911FF0B8EDF77C7CEA76F9F6EABBFBF12742AA3E67BE7597FB7321C3B258C57B9EA045B0A7472558F9AA8E810E2E0462FFD9001A7E21C38006529B9FEDAAF47612D3817922F2335A5D541BAA9B7F",
195              "wps_nfc_dh_privkey": "06F35FDA777F6EFF1F7F008AD68C49572C5F2913B1DC96E0AC3AB67D75329D40EEE850C79D83EEA82CE35FADCCB1F2AF08560268B9E9B67BE66C9B7B3E6F462CF91647830CB0A40184CCF8AA74261E0308AB8973FB799C9EA46011C70215AEA83293E0C89AA4EB6CA753A9E689FA3A0A3FB40D0A8D9AD258F3E4DA1625F63C4B347660D17504B25856DE9D18EB76C239EDFF090A0A1779BE848C0F23C20CF83022C91EA56B0375DED0A62DF0B8B91348F667F5A7EAD23F0F033E071DCE11B786",
196              "wps_nfc_dev_pw": "CB7FE7A25053F8F5BF822660C21E66D8A58D3393BB78494E239031D6AABCB90C"}
197    hapd = hostapd.add_ap(apdev[0], params)
198    logger.info("WPS configuration step")
199    res = hapd.request("WPS_NFC_TOKEN enable")
200    if "FAIL" in res:
201        raise Exception("Failed to enable AP password token")
202    pw = "D217446170706C69636174696F6E2F766E642E7766612E777363102C0036691F6C35AC5FF23180FFBF899BF3E563D047AA68BFABCB7FE7A25053F8F5BF822660C21E66D8A58D3393BB78494E239031D6AABCB90C1049000600372A000120"
203    res = dev[0].request("WPS_NFC_TAG_READ " + pw)
204    if "FAIL" in res:
205        raise Exception("Failed to provide NFC tag contents to wpa_supplicant")
206    dev[0].dump_monitor()
207    new_ssid = "test-wps-nfc-pw-token-new-ssid"
208    new_passphrase = "1234567890"
209    res = dev[0].request("WPS_REG " + apdev[0]['bssid'] + " nfc-pw " +
210                         binascii.hexlify(new_ssid.encode()).decode() +
211                         " WPA2PSK CCMP " +
212                         binascii.hexlify(new_passphrase.encode()).decode())
213    if "FAIL" in res:
214        raise Exception("Failed to start Registrar using NFC password token")
215    dev[0].wait_connected(timeout=30)
216    hapd.wait_sta()
217    check_wpa2_connection(dev[0], apdev[0], hapd, new_ssid, mixed=True)
218
219def test_nfc_wps_handover_init(dev, apdev):
220    """Connect to WPS AP with NFC connection handover and move to configured state"""
221    skip_without_tkip(dev[0])
222    dev[0].request("SET ignore_old_scan_res 1")
223    ssid = "test-wps-nfc-handover-init"
224    hapd = hostapd.add_ap(apdev[0],
225                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
226    logger.info("NFC connection handover")
227    req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
228    if "FAIL" in req:
229        raise Exception("Failed to generate NFC connection handover request")
230    sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
231    if "FAIL" in sel:
232        raise Exception("Failed to generate NFC connection handover select")
233    res = hapd.request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
234    if "FAIL" in res:
235        raise Exception("Failed to report NFC connection handover to to hostapd")
236    dev[0].dump_monitor()
237    res = dev[0].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
238    if "FAIL" in res:
239        raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
240    dev[0].wait_connected(timeout=15)
241    # WPS provisioning
242    hapd.wait_sta()
243    # data connection
244    hapd.wait_sta()
245    check_wpa2_connection(dev[0], apdev[0], hapd, ssid, mixed=True)
246
247    with alloc_fail(hapd, 1, "wps_build_nfc_handover_sel"):
248        if "FAIL" not in hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR"):
249            raise Exception("Unexpected NFC_GET_HANDOVER_SEL success during OOM")
250
251    if "FAIL" not in hapd.request("NFC_GET_HANDOVER_SEL NDEF").rstrip():
252        raise Exception("Invalid NFC_GET_HANDOVER_SEL accepted")
253    if "FAIL" not in hapd.request("NFC_GET_HANDOVER_SEL foo foo").rstrip():
254        raise Exception("Invalid NFC_GET_HANDOVER_SEL accepted")
255    if "FAIL" not in hapd.request("NFC_GET_HANDOVER_SEL NDEF foo").rstrip():
256        raise Exception("Invalid NFC_GET_HANDOVER_SEL accepted")
257    res_ndef = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
258    res_wps = hapd.request("NFC_GET_HANDOVER_SEL WPS WPS-CR").rstrip()
259    if res_wps not in res_ndef:
260        raise Exception("WPS handover select not in NDEF encapsulated version")
261
262@remote_compatible
263def test_nfc_wps_handover_errors(dev, apdev):
264    """WPS AP NFC handover report error cases"""
265    ssid = "test-wps-nfc-handover"
266    hapd = hostapd.add_ap(apdev[0],
267                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
268    sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
269    if "FAIL" in sel:
270        raise Exception("Failed to generate NFC connection handover select")
271    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER "):
272        raise Exception("Unexpected handover report success")
273    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP"):
274        raise Exception("Unexpected handover report success")
275    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP WPS"):
276        raise Exception("Unexpected handover report success")
277    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP WPS 001122"):
278        raise Exception("Unexpected handover report success")
279    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP WPS 001122 00"):
280        raise Exception("Unexpected handover report success")
281    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP WPS 0 00"):
282        raise Exception("Unexpected handover report success")
283    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP WPS 001122 0"):
284        raise Exception("Unexpected handover report success")
285    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP WPS 00q122 001122"):
286        raise Exception("Unexpected handover report success")
287    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP WPS 001122 001q22"):
288        raise Exception("Unexpected handover report success")
289    if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP FOO 001122 00"):
290        raise Exception("Unexpected handover report success")
291    for i in range(1, 3):
292        with alloc_fail(hapd, i,
293                        "wpabuf_alloc;hostapd_ctrl_iface_nfc_report_handover"):
294            if "FAIL" not in hapd.request("NFC_REPORT_HANDOVER RESP WPS 001122 001122"):
295                raise Exception("NFC_REPORT_HANDOVER RESP succeeded during OOM")
296
297def test_nfc_wps_handover(dev, apdev):
298    """Connect to WPS AP with NFC connection handover"""
299    ssid = "test-wps-nfc-handover"
300    params = ap_wps_params(ssid)
301    hapd = hostapd.add_ap(apdev[0], params)
302    logger.info("NFC connection handover")
303    req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
304    if "FAIL" in req:
305        raise Exception("Failed to generate NFC connection handover request")
306    sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
307    if "FAIL" in sel:
308        raise Exception("Failed to generate NFC connection handover select")
309    res = hapd.request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
310    if "FAIL" in res:
311        raise Exception("Failed to report NFC connection handover to to hostapd")
312    dev[0].dump_monitor()
313    res = dev[0].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
314    if "FAIL" in res:
315        raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
316    dev[0].wait_connected(timeout=30)
317    hapd.wait_sta()
318    check_wpa2_connection(dev[0], apdev[0], hapd, ssid)
319
320def test_nfc_wps_handover_5ghz(dev, apdev):
321    """Connect to WPS AP with NFC connection handover on 5 GHz band"""
322    hapd = None
323    try:
324        ssid = "test-wps-nfc-handover"
325        params = ap_wps_params(ssid)
326        params["country_code"] = "FI"
327        params["hw_mode"] = "a"
328        params["channel"] = "36"
329        hapd = hostapd.add_ap(apdev[0], params)
330        logger.info("NFC connection handover")
331        req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
332        if "FAIL" in req:
333            raise Exception("Failed to generate NFC connection handover request")
334        sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
335        if "FAIL" in sel:
336            raise Exception("Failed to generate NFC connection handover select")
337        res = hapd.request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
338        if "FAIL" in res:
339            raise Exception("Failed to report NFC connection handover to to hostapd")
340        dev[0].dump_monitor()
341        res = dev[0].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
342        if "FAIL" in res:
343            raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
344        dev[0].wait_connected(timeout=30)
345        hapd.wait_sta()
346        check_wpa2_connection(dev[0], apdev[0], hapd, ssid)
347    finally:
348        clear_regdom(hapd, dev)
349
350def test_nfc_wps_handover_chan14(dev, apdev):
351    """Connect to WPS AP with NFC connection handover on channel 14"""
352    hapd = None
353    try:
354        ssid = "test-wps-nfc-handover"
355        params = ap_wps_params(ssid)
356        params["country_code"] = "JP"
357        params["hw_mode"] = "b"
358        params["channel"] = "14"
359        hapd = hostapd.add_ap(apdev[0], params)
360        logger.info("NFC connection handover")
361        req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
362        if "FAIL" in req:
363            raise Exception("Failed to generate NFC connection handover request")
364        sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
365        if "FAIL" in sel:
366            raise Exception("Failed to generate NFC connection handover select")
367        res = hapd.request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
368        if "FAIL" in res:
369            raise Exception("Failed to report NFC connection handover to to hostapd")
370        dev[0].dump_monitor()
371        res = dev[0].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
372        if "FAIL" in res:
373            raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
374        dev[0].wait_connected(timeout=30)
375        hapd.wait_sta()
376        check_wpa2_connection(dev[0], apdev[0], hapd, ssid)
377    finally:
378        dev[0].request("DISCONNECT")
379        clear_regdom(hapd, dev)
380
381def test_nfc_wps_handover_with_pw_token_set(dev, apdev):
382    """Connect to WPS AP with NFC connection handover (wps_nfc_* set)"""
383    ssid = "test-wps-nfc-handover2"
384    params = ap_wps_params(ssid)
385    hapd = hostapd.add_ap(apdev[0], params)
386    # enable a password token (which won't be used in this test case)
387    pw = hapd.request("WPS_NFC_TOKEN NDEF").rstrip()
388    if "FAIL" in pw:
389        raise Exception("Failed to generate password token")
390    res = hapd.request("WPS_NFC_TOKEN enable")
391    if "FAIL" in pw:
392        raise Exception("Failed to enable AP password token")
393    logger.info("NFC connection handover")
394    req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
395    if "FAIL" in req:
396        raise Exception("Failed to generate NFC connection handover request")
397    sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
398    if "FAIL" in sel:
399        raise Exception("Failed to generate NFC connection handover select")
400    res = hapd.request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
401    if "FAIL" in res:
402        raise Exception("Failed to report NFC connection handover to to hostapd")
403    dev[0].dump_monitor()
404    res = dev[0].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
405    if "FAIL" in res:
406        raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
407    dev[0].wait_connected(timeout=15)
408    hapd.wait_sta()
409    check_wpa2_connection(dev[0], apdev[0], hapd, ssid)
410
411def test_nfc_wps_handover_pk_hash_mismatch_sta(dev, apdev):
412    """WPS NFC connection handover with invalid pkhash from station (negative)"""
413    ssid = "wps-nfc-handover-pkhash-sta"
414    if "FAIL" in dev[0].request("SET wps_corrupt_pkhash 1"):
415        raise Exception("Could not enable wps_corrupt_pkhash")
416    params = ap_wps_params(ssid)
417    hapd = hostapd.add_ap(apdev[0], params)
418    logger.info("NFC connection handover")
419    req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
420    if "FAIL" in req:
421        raise Exception("Failed to generate NFC connection handover request")
422    sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
423    if "FAIL" in sel:
424        raise Exception("Failed to generate NFC connection handover select")
425    res = hapd.request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
426    if "FAIL" in res:
427        raise Exception("Failed to report NFC connection handover to to hostapd")
428    dev[0].dump_monitor()
429    res = dev[0].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
430    if "FAIL" in res:
431        raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
432    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "WPS-FAIL"], timeout=15)
433    if ev is None:
434        raise Exception("Timed out")
435    if "WPS-FAIL" not in ev:
436        raise Exception("Public key hash mismatch not detected")
437
438def test_nfc_wps_handover_pk_hash_mismatch_ap(dev, apdev):
439    """WPS NFC connection handover with invalid pkhash from AP (negative)"""
440    ssid = "wps-nfc-handover-pkhash-ap"
441    params = ap_wps_params(ssid)
442    hapd = hostapd.add_ap(apdev[0], params)
443    if "FAIL" in hapd.request("SET wps_corrupt_pkhash 1"):
444        raise Exception("Could not enable wps_corrupt_pkhash")
445    logger.info("NFC connection handover")
446    req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
447    if "FAIL" in req:
448        raise Exception("Failed to generate NFC connection handover request")
449    sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
450    if "FAIL" in sel:
451        raise Exception("Failed to generate NFC connection handover select")
452    res = hapd.request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
453    if "FAIL" in res:
454        raise Exception("Failed to report NFC connection handover to to hostapd")
455    dev[0].dump_monitor()
456    res = dev[0].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
457    if "FAIL" in res:
458        raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
459    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "WPS-FAIL"], timeout=15)
460    if ev is None:
461        raise Exception("Timed out")
462    if "WPS-FAIL" not in ev:
463        raise Exception("Public key hash mismatch not detected")
464
465def start_ap_er(er, ap, ssid):
466    ap_pin = "12345670"
467    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
468    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
469              "wpa_passphrase": "12345678", "wpa": "2",
470              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
471              "device_name": "Wireless AP", "manufacturer": "Company",
472              "model_name": "WAP", "model_number": "123",
473              "serial_number": "12345", "device_type": "6-0050F204-1",
474              "os_version": "01020300",
475              "config_methods": "label push_button",
476              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
477    hapd = hostapd.add_ap(ap, params)
478    logger.info("Learn AP configuration")
479    er.dump_monitor()
480    er.request("SET ignore_old_scan_res 1")
481    er.wps_reg(ap['bssid'], ap_pin)
482    er.request("SET ignore_old_scan_res 0")
483
484    logger.info("Start ER")
485    er.request("WPS_ER_STOP")
486    time.sleep(1)
487    er.request("WPS_ER_START ifname=lo")
488    ev = er.wait_event(["WPS-ER-AP-ADD"], timeout=15)
489    if ev is None:
490        raise Exception("AP discovery timed out")
491    if ap_uuid not in ev:
492        raise Exception("Expected AP UUID not found")
493
494    logger.info("Use learned network configuration on ER")
495    er.request("WPS_ER_SET_CONFIG " + ap_uuid + " 0")
496    return hapd
497
498@remote_compatible
499def test_nfc_wps_er_pw_token(dev, apdev):
500    """WPS NFC password token from Enrollee to ER"""
501    try:
502        _test_nfc_wps_er_pw_token(dev, apdev)
503    finally:
504        dev[0].request("WPS_ER_STOP")
505
506def _test_nfc_wps_er_pw_token(dev, apdev):
507    ssid = "wps-nfc-er-pw-token"
508    hapd = start_ap_er(dev[0], apdev[0], ssid)
509    logger.info("WPS provisioning step using password token from station")
510    dev[1].request("SET ignore_old_scan_res 1")
511    pw = dev[1].request("WPS_NFC_TOKEN NDEF").rstrip()
512    if "FAIL" in pw:
513        raise Exception("Failed to generate password token")
514    res = dev[0].request("WPS_NFC_TAG_READ " + pw)
515    if "FAIL" in res:
516        raise Exception("Failed to provide NFC tag contents to WPS ER")
517    dev[0].dump_monitor()
518    res = dev[1].request("WPS_NFC")
519    if "FAIL" in res:
520        raise Exception("Failed to start Enrollee using NFC password token")
521    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
522    if ev is None:
523        raise Exception("WPS ER did not report success")
524    dev[1].wait_connected(timeout=15)
525    hapd.wait_sta()
526    check_wpa2_connection(dev[1], apdev[0], hapd, ssid)
527
528@remote_compatible
529def test_nfc_wps_er_config_token(dev, apdev):
530    """WPS NFC configuration token from ER to Enrollee"""
531    try:
532        _test_nfc_wps_er_config_token(dev, apdev)
533    finally:
534        dev[0].request("WPS_ER_STOP")
535
536def _test_nfc_wps_er_config_token(dev, apdev):
537    ssid = "wps-nfc-er-config-token"
538    hapd = start_ap_er(dev[0], apdev[0], ssid)
539    logger.info("WPS provisioning step using configuration token from ER")
540    wps = dev[0].request("WPS_ER_NFC_CONFIG_TOKEN WPS " + apdev[0]['bssid']).rstrip()
541    if "FAIL" in wps:
542        raise Exception("Failed to generate configuration token (WPS format)")
543    conf = dev[0].request("WPS_ER_NFC_CONFIG_TOKEN NDEF " + apdev[0]['bssid']).rstrip()
544    if "FAIL" in conf:
545        raise Exception("Failed to generate configuration token")
546    dev[1].request("SET ignore_old_scan_res 1")
547    res = dev[1].request("WPS_NFC_TAG_READ " + conf)
548    if "FAIL" in res:
549        raise Exception("Failed to provide NFC tag contents to wpa_supplicant")
550    dev[1].wait_connected(timeout=15)
551    hapd.wait_sta()
552    check_wpa2_connection(dev[1], apdev[0], hapd, ssid)
553
554def test_nfc_wps_er_handover(dev, apdev):
555    """WPS NFC connection handover between Enrollee and ER"""
556    try:
557        _test_nfc_wps_er_handover(dev, apdev)
558    finally:
559        dev[0].request("WPS_ER_STOP")
560
561def _test_nfc_wps_er_handover(dev, apdev):
562    ssid = "wps-nfc-er-handover"
563    hapd = start_ap_er(dev[0], apdev[0], ssid)
564    logger.info("WPS provisioning step using connection handover")
565    req = dev[1].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
566    if "FAIL" in req:
567        raise Exception("Failed to generate NFC connection handover request")
568    sel = dev[0].request("NFC_GET_HANDOVER_SEL NDEF WPS-CR " + apdev[0]['bssid']).rstrip()
569    if "FAIL" in sel:
570        raise Exception("Failed to generate NFC connection handover select")
571    res = dev[0].request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
572    if "FAIL" in res:
573        raise Exception("Failed to report NFC connection handover to to hostapd")
574    dev[1].dump_monitor()
575    res = dev[1].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
576    if "FAIL" in res:
577        raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
578    dev[1].wait_connected(timeout=15)
579    hapd.wait_sta()
580    check_wpa2_connection(dev[1], apdev[0], hapd, ssid)
581
582def test_nfc_wps_er_handover_pk_hash_mismatch_sta(dev, apdev):
583    """WPS NFC connection handover with invalid pkhash from station to ER (negative)"""
584    try:
585        _test_nfc_wps_er_handover_pk_hash_mismatch_sta(dev, apdev)
586    finally:
587        dev[0].request("WPS_ER_STOP")
588
589def _test_nfc_wps_er_handover_pk_hash_mismatch_sta(dev, apdev):
590    ssid = "wps-nfc-er-handover-pkhash-sta"
591    hapd = start_ap_er(dev[0], apdev[0], ssid)
592    logger.info("WPS provisioning step using connection handover")
593    if "FAIL" in dev[1].request("SET wps_corrupt_pkhash 1"):
594        raise Exception("Could not enable wps_corrupt_pkhash")
595    dev[1].request("SET ignore_old_scan_res 1")
596    req = dev[1].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
597    if "FAIL" in req:
598        raise Exception("Failed to generate NFC connection handover request")
599    sel = dev[0].request("NFC_GET_HANDOVER_SEL NDEF WPS-CR " + apdev[0]['bssid']).rstrip()
600    if "FAIL" in sel:
601        raise Exception("Failed to generate NFC connection handover select")
602    res = dev[0].request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
603    if "FAIL" in res:
604        raise Exception("Failed to report NFC connection handover to to hostapd")
605    dev[1].dump_monitor()
606    res = dev[1].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
607    if "FAIL" in res:
608        raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
609    ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED", "WPS-FAIL"], timeout=15)
610    if ev is None:
611        raise Exception("Timed out")
612    if "WPS-FAIL" not in ev:
613        raise Exception("Public key hash mismatch not detected")
614
615def test_nfc_wps_er_handover_pk_hash_mismatch_er(dev, apdev):
616    """WPS NFC connection handover with invalid pkhash from ER to station (negative)"""
617    try:
618        _test_nfc_wps_er_handover_pk_hash_mismatch_er(dev, apdev)
619    finally:
620        dev[0].request("WPS_ER_STOP")
621
622def _test_nfc_wps_er_handover_pk_hash_mismatch_er(dev, apdev):
623    ssid = "wps-nfc-er-handover-pkhash-er"
624    hapd = start_ap_er(dev[0], apdev[0], ssid)
625    logger.info("WPS provisioning step using connection handover")
626    if "FAIL" in dev[0].request("SET wps_corrupt_pkhash 1"):
627        raise Exception("Could not enable wps_corrupt_pkhash")
628    dev[1].request("SET ignore_old_scan_res 1")
629    req = dev[1].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
630    if "FAIL" in req:
631        raise Exception("Failed to generate NFC connection handover request")
632    sel = dev[0].request("NFC_GET_HANDOVER_SEL NDEF WPS-CR " + apdev[0]['bssid']).rstrip()
633    if "FAIL" in sel:
634        raise Exception("Failed to generate NFC connection handover select")
635    res = dev[0].request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
636    if "FAIL" in res:
637        raise Exception("Failed to report NFC connection handover to to hostapd")
638    dev[1].dump_monitor()
639    res = dev[1].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
640    if "FAIL" in res:
641        raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
642    ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED", "WPS-FAIL"], timeout=15)
643    if ev is None:
644        raise Exception("Timed out")
645    if "WPS-FAIL" not in ev:
646        raise Exception("Public key hash mismatch not detected")
647
648@remote_compatible
649def test_nfc_invalid_ndef_record(dev, apdev):
650    """Invalid NFC NDEF record handling"""
651    tests = ["11223344",
652             "00112233",
653             "0000112233445566",
654             "0800112233445566",
655             "080011223344",
656             "18000000",
657             "18010000",
658             "90000050",
659             "9000005000",
660             "9001013344",
661             "98010101334455",
662             "0017ffffffe3",
663             "0017ffffffe4",
664             "0017ffffffe9",
665             "0000fffffffa",
666             "0017ffffffe46170706c69636174696f6e2f766e642e7766612e777363",
667             "0017ffffffff6170706c69636174696f6e2f766e642e7766612e777363",
668             "0017000000006170706c69636174696f6e2f766e642e7766612e7773ff",
669             "080000000000"]
670    for test in tests:
671        if "FAIL" not in dev[0].request("WPS_NFC_TAG_READ " + test):
672            raise Exception("Invalid tag accepted: " + test)
673
674def test_nfc_wps_handover_failure(dev, apdev):
675    """Connect to WPS AP with NFC connection handover (local failure)"""
676    ssid = "test-wps-nfc-handover"
677    params = ap_wps_params(ssid)
678    hapd = hostapd.add_ap(apdev[0], params)
679    logger.info("NFC connection handover")
680    req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
681    if "FAIL" in req:
682        raise Exception("Failed to generate NFC connection handover request")
683    sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
684    if "FAIL" in sel:
685        raise Exception("Failed to generate NFC connection handover select")
686    res = hapd.request("NFC_REPORT_HANDOVER RESP WPS " + req + " " + sel)
687    if "FAIL" in res:
688        raise Exception("Failed to report NFC connection handover to to hostapd")
689    dev[0].dump_monitor()
690
691    with alloc_fail(hapd, 1, "wpabuf_dup;wps_build_public_key"):
692        res = dev[0].request("NFC_REPORT_HANDOVER INIT WPS " + req + " " + sel)
693        if "FAIL" in res:
694            raise Exception("Failed to report NFC connection handover to to wpa_supplicant")
695        ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
696        if ev is None:
697            raise Exception("WPS failure not reported")
698